@Test
  public void backup_with_disabled_rules() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                // Debt disabled
                new RuleDto()
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setSubCharacteristicId(RuleDto.DISABLED_CHARACTERISTIC_ID),

                // Not debt
                new RuleDto().setRepositoryKey("squid").setRuleKey("AvoidNPE")));

    debtModelBackup.backup();

    verify(debtModelXMLExporter).export(any(DebtModel.class), ruleDebtListCaptor.capture());

    assertThat(ruleDebtListCaptor.getValue()).isEmpty();
  }
  @Test
  public void
      restore_from_xml_disable_rule_debt_when_not_in_xml_and_rule_have_default_debt_values() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                new RuleDto()
                    .setId(1)
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setDefaultSubCharacteristicId(2)
                    .setDefaultRemediationFunction("LINEAR_OFFSET")
                    .setDefaultRemediationCoefficient("2h")
                    .setDefaultRemediationOffset("15min")
                //        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
                ));

    debtModelBackup.restoreFromXml("<xml/>");

    verify(ruleOperations)
        .updateRule(
            ruleCaptor.capture(),
            isNull(CharacteristicDto.class),
            isNull(String.class),
            isNull(String.class),
            isNull(String.class),
            eq(session));

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(session).commit();
  }
  @Test
  public void update_characteristics_when_restoring_characteristics() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                // Order and name have changed
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2)
                    .setCreatedAt(oldDate)
                    .setUpdatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)
                    .setCreatedAt(oldDate)
                    .setUpdatedAt(oldDate)));

    debtModelBackup.restoreCharacteristics(
        new DebtModel()
            .addRootCharacteristic(
                new DefaultDebtCharacteristic()
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1))
            .addSubCharacteristic(
                new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                "PORTABILITY"),
        now,
        session);

    verify(dao, times(2)).update(characteristicCaptor.capture(), eq(session));

    CharacteristicDto dto1 = characteristicCaptor.getAllValues().get(0);
    assertThat(dto1.getId()).isEqualTo(1);
    assertThat(dto1.getKey()).isEqualTo("PORTABILITY");
    assertThat(dto1.getName()).isEqualTo("Portability");
    assertThat(dto1.getParentId()).isNull();
    assertThat(dto1.getOrder()).isEqualTo(1);
    assertThat(dto1.getCreatedAt()).isEqualTo(oldDate);
    assertThat(dto1.getUpdatedAt()).isEqualTo(now);

    CharacteristicDto dto2 = characteristicCaptor.getAllValues().get(1);
    assertThat(dto2.getId()).isEqualTo(2);
    assertThat(dto2.getKey()).isEqualTo("COMPILER");
    assertThat(dto2.getName()).isEqualTo("Compiler");
    assertThat(dto2.getParentId()).isEqualTo(1);
    assertThat(dto2.getOrder()).isNull();
    assertThat(dto2.getCreatedAt()).isEqualTo(oldDate);
    assertThat(dto2.getUpdatedAt()).isEqualTo(now);
  }
  @Test
  public void backup_from_language() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                new RuleDto()
                    .setId(1)
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setLanguage("java")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.toString())
                    .setRemediationOffset("15min"),
                //        .setCreatedAt(oldDate).setUpdatedAt(oldDate),
                // Should be ignored
                new RuleDto()
                    .setId(2)
                    .setRepositoryKey("checkstyle")
                    .setLanguage("java2")
                    .setSubCharacteristicId(3)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString())
                    .setRemediationCoefficient("2h")
                //        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
                ));

    debtModelBackup.backup("java");

    verify(debtModelXMLExporter).export(any(DebtModel.class), ruleDebtListCaptor.capture());

    List<RuleDebt> rules = ruleDebtListCaptor.getValue();
    assertThat(rules).hasSize(1);

    RuleDebt rule = rules.get(0);
    assertThat(rule.ruleKey().repository()).isEqualTo("squid");
    assertThat(rule.ruleKey().rule()).isEqualTo("UselessImportCheck");
    assertThat(rule.subCharacteristicKey()).isEqualTo("COMPILER");
    assertThat(rule.function()).isEqualTo("CONSTANT_ISSUE");
    assertThat(rule.coefficient()).isNull();
    assertThat(rule.offset()).isEqualTo("15min");
  }
  @Test
  public void disable_no_more_existing_characteristics_when_restoring_characteristics() {
    CharacteristicDto dto1 =
        new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1);
    CharacteristicDto dto2 =
        new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1);

    when(dao.selectEnabledCharacteristics(session)).thenReturn(newArrayList(dto1, dto2));

    debtModelBackup.restoreCharacteristics(new DebtModel(), now, session);

    verify(debtModelOperations).delete(dto1, now, session);
    verify(debtModelOperations).delete(dto2, now, session);
  }
  @Test
  public void backup_with_rule_having_default_linear_and_overridden_offset() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                // Rule with default debt values : default value is linear (only coefficient is set)
                // and overridden value is constant per issue (only offset is set)
                // -> Ony offset should be set
                new RuleDto()
                    .setRepositoryKey("squid")
                    .setRuleKey("AvoidNPE")
                    .setDefaultSubCharacteristicId(2)
                    .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString())
                    .setDefaultRemediationCoefficient("2h")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.CONSTANT_ISSUE.toString())
                    .setRemediationOffset("15min")));

    debtModelBackup.backup();

    ArgumentCaptor<DebtModel> debtModelArgument = ArgumentCaptor.forClass(DebtModel.class);
    verify(debtModelXMLExporter).export(debtModelArgument.capture(), ruleDebtListCaptor.capture());
    assertThat(debtModelArgument.getValue().rootCharacteristics()).hasSize(1);
    assertThat(debtModelArgument.getValue().subCharacteristics("PORTABILITY")).hasSize(1);

    List<RuleDebt> rules = ruleDebtListCaptor.getValue();
    assertThat(rules).hasSize(1);

    RuleDebt rule = rules.get(0);
    assertThat(rule.ruleKey().repository()).isEqualTo("squid");
    assertThat(rule.ruleKey().rule()).isEqualTo("AvoidNPE");
    assertThat(rule.subCharacteristicKey()).isEqualTo("COMPILER");
    assertThat(rule.function()).isEqualTo("CONSTANT_ISSUE");
    assertThat(rule.offset()).isEqualTo("15min");
    assertThat(rule.coefficient()).isNull();
  }
  @Test
  public void restore_from_xml_add_warning_message_when_rule_from_xml_is_not_found() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class)))
        .thenReturn(
            newArrayList(
                new RuleDebt()
                    .setRuleKey(RuleKey.of("squid", "UselessImportCheck"))
                    .setSubCharacteristicKey("COMPILER")
                    .setFunction(DebtRemediationFunction.Type.LINEAR.name())
                    .setCoefficient("2h")));

    when(ruleDao.selectEnabledAndNonManual(session)).thenReturn(Collections.<RuleDto>emptyList());

    assertThat(debtModelBackup.restoreFromXml("<xml/>").getWarnings()).hasSize(1);

    verifyZeroInteractions(ruleOperations);

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(session).commit();
  }
  @Test
  public void reset_model_do_not_load_rule_definitions_if_no_rule() {
    when(characteristicsXMLImporter.importXML(any(Reader.class)))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(ruleDao.selectEnabledAndNonManual(session)).thenReturn(Collections.<RuleDto>emptyList());

    debtModelBackup.reset();

    verify(dao).selectEnabledCharacteristics(session);
    verify(dao, times(2)).update(any(CharacteristicDto.class), eq(session));
    verifyNoMoreInteractions(dao);

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(ruleDao, never()).update(eq(session), any(RuleDto.class));
    verifyZeroInteractions(defLoader);

    verify(session).commit();
  }
  @Test
  public void create_characteristics_when_restoring_characteristics() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(Collections.<CharacteristicDto>emptyList());

    debtModelBackup.restoreCharacteristics(
        new DebtModel()
            .addRootCharacteristic(
                new DefaultDebtCharacteristic()
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1))
            .addSubCharacteristic(
                new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                "PORTABILITY"),
        now,
        session);

    verify(dao, times(2)).insert(characteristicCaptor.capture(), eq(session));

    CharacteristicDto dto1 = characteristicCaptor.getAllValues().get(0);
    assertThat(dto1.getId()).isEqualTo(10);
    assertThat(dto1.getKey()).isEqualTo("PORTABILITY");
    assertThat(dto1.getName()).isEqualTo("Portability");
    assertThat(dto1.getParentId()).isNull();
    assertThat(dto1.getOrder()).isEqualTo(1);
    assertThat(dto1.getCreatedAt()).isEqualTo(now);
    assertThat(dto1.getUpdatedAt()).isNull();

    CharacteristicDto dto2 = characteristicCaptor.getAllValues().get(1);
    assertThat(dto2.getId()).isEqualTo(11);
    assertThat(dto2.getKey()).isEqualTo("COMPILER");
    assertThat(dto2.getName()).isEqualTo("Compiler");
    assertThat(dto2.getParentId()).isEqualTo(10);
    assertThat(dto2.getOrder()).isNull();
    assertThat(dto2.getCreatedAt()).isEqualTo(now);
    assertThat(dto2.getUpdatedAt()).isNull();
  }
  @Test
  public void restore_from_xml_and_language_disable_no_more_existing_characteristics() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1)));

    CharacteristicDto dto1 =
        new CharacteristicDto().setId(1).setKey("PORTABILITY").setName("Portability").setOrder(1);
    // No more existing characteristic
    CharacteristicDto dto2 =
        new CharacteristicDto().setId(2).setKey("COMPILER").setName("Compiler").setParentId(1);
    when(dao.selectEnabledCharacteristics(session)).thenReturn(newArrayList(dto1, dto2));

    debtModelBackup.restoreFromXml("<xml/>", "java");

    verify(debtModelOperations).delete(dto2, now, session);
    verify(session).commit();
  }
  @Test
  public void restore_from_xml_and_language() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    CharacteristicDto compiler =
        new CharacteristicDto()
            .setId(2)
            .setKey("COMPILER")
            .setName("Compiler")
            .setParentId(1)
            .setCreatedAt(oldDate);
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1)
                    .setCreatedAt(oldDate),
                compiler));

    when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class)))
        .thenReturn(
            newArrayList(
                new RuleDebt()
                    .setRuleKey(RuleKey.of("squid", "UselessImportCheck"))
                    .setSubCharacteristicKey("COMPILER")
                    .setFunction(DebtRemediationFunction.Type.LINEAR.name())
                    .setCoefficient("2h")));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                new RuleDto()
                    .setId(1)
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setLanguage("java")
                    .setDefaultSubCharacteristicId(10)
                    .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString())
                    .setDefaultRemediationCoefficient("2h"),
                // Should be ignored
                new RuleDto()
                    .setId(2)
                    .setRepositoryKey("checkstyle")
                    .setLanguage("java2")
                    .setSubCharacteristicId(3)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString())
                    .setRemediationCoefficient("2h")));

    debtModelBackup.restoreFromXml("<xml/>", "java");

    verify(ruleOperations)
        .updateRule(
            ruleCaptor.capture(),
            eq(compiler),
            eq("LINEAR"),
            eq("2h"),
            isNull(String.class),
            eq(session));

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(session).commit();
  }
  @Test
  public void reset_model_on_custom_rules() {
    when(characteristicsXMLImporter.importXML(any(Reader.class)))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                // Template rule
                new RuleDto()
                    .setId(5)
                    .setRepositoryKey("squid")
                    .setRuleKey("XPath")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
                    .setRemediationCoefficient("2h")
                    .setRemediationOffset("15min"),
                // Custom rule
                new RuleDto()
                    .setId(6)
                    .setRepositoryKey("squid")
                    .setRuleKey("XPath_1369910135")
                    .setTemplateId(5)
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
                    .setRemediationCoefficient("2h")
                    .setRemediationOffset("15min")));

    RulesDefinition.Context context = new RulesDefinition.Context();
    // Template rule
    RulesDefinition.NewRepository repo = context.createRepository("squid", "java").setName("XPath");
    RulesDefinition.NewRule newRule =
        repo.createRule("XPath")
            .setName("XPath")
            .setHtmlDescription("XPath")
            .setSeverity(Severity.BLOCKER)
            .setStatus(RuleStatus.BETA)
            .setDebtSubCharacteristic("COMPILER");
    newRule.setDebtRemediationFunction(
        newRule.debtRemediationFunctions().linearWithOffset("4h", "20min"));
    repo.done();
    when(defLoader.load()).thenReturn(context);

    debtModelBackup.reset();

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(ruleDao, times(2)).update(eq(session), ruleCaptor.capture());
    verifyNoMoreInteractions(ruleDao);
    verify(session).commit();

    RuleDto rule = ruleCaptor.getAllValues().get(1);

    assertThat(rule.getId()).isEqualTo(6);
    assertThat(rule.getDefaultSubCharacteristicId()).isEqualTo(2);
    assertThat(rule.getDefaultRemediationFunction()).isEqualTo("LINEAR_OFFSET");
    assertThat(rule.getDefaultRemediationCoefficient()).isEqualTo("4h");
    assertThat(rule.getDefaultRemediationOffset()).isEqualTo("20min");
    assertThat(rule.getUpdatedAt()).isEqualTo(now);

    assertThat(rule.getSubCharacteristicId()).isNull();
    assertThat(rule.getRemediationFunction()).isNull();
    assertThat(rule.getRemediationCoefficient()).isNull();
    assertThat(rule.getRemediationOffset()).isNull();
    assertThat(rule.getUpdatedAt()).isEqualTo(now);
  }
  @Test
  public void reset_model_when_no_default_value() {
    when(characteristicsXMLImporter.importXML(any(Reader.class)))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                new RuleDto()
                    .setRepositoryKey("squid")
                    .setRuleKey("NPE")
                    .setDefaultSubCharacteristicId(10)
                    .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR.toString())
                    .setDefaultRemediationCoefficient("2h")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
                    .setRemediationCoefficient("2h")
                    .setRemediationOffset("15min")));

    RulesDefinition.Context context = new RulesDefinition.Context();
    RulesDefinition.NewRepository repo = context.createRepository("squid", "java").setName("Squid");
    repo.createRule("NPE")
        .setName("Detect NPE")
        .setHtmlDescription("Detect <code>java.lang.NullPointerException</code>")
        .setSeverity(Severity.BLOCKER)
        .setStatus(RuleStatus.BETA);
    repo.done();
    when(defLoader.load()).thenReturn(context);

    debtModelBackup.reset();

    verify(dao).selectEnabledCharacteristics(session);
    verify(dao, times(2)).update(any(CharacteristicDto.class), eq(session));
    verifyNoMoreInteractions(dao);

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(ruleDao).update(eq(session), ruleCaptor.capture());
    verifyNoMoreInteractions(ruleDao);

    verify(session).commit();

    RuleDto rule = ruleCaptor.getValue();
    assertThat(rule.getDefaultSubCharacteristicId()).isNull();
    assertThat(rule.getDefaultRemediationFunction()).isNull();
    assertThat(rule.getDefaultRemediationCoefficient()).isNull();
    assertThat(rule.getDefaultRemediationOffset()).isNull();
    assertThat(rule.getUpdatedAt()).isEqualTo(now);
  }
  @Test
  public void backup() {
    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                // Rule with overridden debt values
                new RuleDto()
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
                    .setRemediationCoefficient("2h")
                    .setRemediationOffset("15min"),

                // Rule with default debt values
                new RuleDto()
                    .setRepositoryKey("squid")
                    .setRuleKey("AvoidNPE")
                    .setDefaultSubCharacteristicId(2)
                    .setDefaultRemediationFunction("LINEAR")
                    .setDefaultRemediationCoefficient("2h")));

    debtModelBackup.backup();

    ArgumentCaptor<DebtModel> debtModelArgument = ArgumentCaptor.forClass(DebtModel.class);
    verify(debtModelXMLExporter).export(debtModelArgument.capture(), ruleDebtListCaptor.capture());
    assertThat(debtModelArgument.getValue().rootCharacteristics()).hasSize(1);
    assertThat(debtModelArgument.getValue().subCharacteristics("PORTABILITY")).hasSize(1);

    List<RuleDebt> rules = ruleDebtListCaptor.getValue();
    assertThat(rules).hasSize(2);

    RuleDebt rule = rules.get(0);
    assertThat(rule.ruleKey().repository()).isEqualTo("squid");
    assertThat(rule.ruleKey().rule()).isEqualTo("UselessImportCheck");
    assertThat(rule.subCharacteristicKey()).isEqualTo("COMPILER");
    assertThat(rule.function()).isEqualTo("LINEAR_OFFSET");
    assertThat(rule.coefficient()).isEqualTo("2h");
    assertThat(rule.offset()).isEqualTo("15min");

    rule = rules.get(1);
    assertThat(rule.ruleKey().repository()).isEqualTo("squid");
    assertThat(rule.ruleKey().rule()).isEqualTo("AvoidNPE");
    assertThat(rule.subCharacteristicKey()).isEqualTo("COMPILER");
    assertThat(rule.function()).isEqualTo("LINEAR");
    assertThat(rule.coefficient()).isEqualTo("2h");
    assertThat(rule.offset()).isNull();
  }
  @Test
  public void restore_from_xml_add_error_message_when_illegal_argument_exception() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability")
                    .setOrder(1)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class)))
        .thenReturn(
            newArrayList(
                new RuleDebt()
                    .setRuleKey(RuleKey.of("squid", "UselessImportCheck"))
                    .setSubCharacteristicKey("COMPILER")
                    .setFunction(DebtRemediationFunction.Type.LINEAR.name())
                    .setCoefficient("2h")));

    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                new RuleDto()
                    .setId(1)
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setDefaultSubCharacteristicId(3)
                    .setDefaultRemediationFunction("LINEAR")
                    .setDefaultRemediationCoefficient("2h")
                //        .setCreatedAt(oldDate).setUpdatedAt(oldDate)
                ));

    when(ruleOperations.updateRule(
            any(RuleDto.class),
            any(CharacteristicDto.class),
            anyString(),
            anyString(),
            anyString(),
            eq(session)))
        .thenThrow(IllegalArgumentException.class);

    assertThat(debtModelBackup.restoreFromXml("<xml/>").getErrors()).hasSize(1);

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(session, never()).commit();
  }
  @Test
  public void restore_from_xml_and_language_with_rule_not_in_xml() {
    when(characteristicsXMLImporter.importXML(anyString()))
        .thenReturn(
            new DebtModel()
                .addRootCharacteristic(
                    new DefaultDebtCharacteristic()
                        .setKey("PORTABILITY")
                        .setName("Portability")
                        .setOrder(1))
                .addSubCharacteristic(
                    new DefaultDebtCharacteristic().setKey("COMPILER").setName("Compiler"),
                    "PORTABILITY"));

    when(dao.selectEnabledCharacteristics(session))
        .thenReturn(
            newArrayList(
                new CharacteristicDto()
                    .setId(1)
                    .setKey("PORTABILITY")
                    .setName("Portability updated")
                    .setOrder(2)
                    .setCreatedAt(oldDate),
                new CharacteristicDto()
                    .setId(2)
                    .setKey("COMPILER")
                    .setName("Compiler updated")
                    .setParentId(1)
                    .setCreatedAt(oldDate)));

    when(rulesXMLImporter.importXML(anyString(), any(ValidationMessages.class)))
        .thenReturn(Collections.<RuleDebt>emptyList());
    when(ruleDao.selectEnabledAndNonManual(session))
        .thenReturn(
            newArrayList(
                // Rule does not exits in XML -> debt will be disabled
                new RuleDto()
                    .setId(1)
                    .setRepositoryKey("squid")
                    .setRuleKey("UselessImportCheck")
                    .setLanguage("java")
                    .setDefaultSubCharacteristicId(2)
                    .setDefaultRemediationFunction("LINEAR")
                    .setDefaultRemediationCoefficient("2h")
                    .setSubCharacteristicId(2)
                    .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
                    .setRemediationCoefficient("2h")
                    .setRemediationOffset("15min")));

    debtModelBackup.restoreFromXml("<xml/>", "java");

    verify(ruleOperations)
        .updateRule(
            ruleCaptor.capture(),
            isNull(CharacteristicDto.class),
            isNull(String.class),
            isNull(String.class),
            isNull(String.class),
            eq(session));

    verify(ruleDao).selectEnabledAndNonManual(session);
    verify(session).commit();
  }