Package org.sonar.server.debt

Source Code of org.sonar.server.debt.DebtModelOperationsTest

/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package org.sonar.server.debt;

import org.apache.ibatis.session.SqlSession;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.sonar.api.server.debt.DebtCharacteristic;
import org.sonar.api.server.debt.DebtRemediationFunction;
import org.sonar.api.server.debt.internal.DefaultDebtCharacteristic;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.technicaldebt.db.CharacteristicDao;
import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.user.MockUserSession;

import java.util.Date;

import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
* TODO this class should use ServerTester instead of mocking db
*/
@RunWith(MockitoJUnitRunner.class)
public class DebtModelOperationsTest {

  @Mock
  CharacteristicDao dao;

  @Mock
  RuleDao ruleDao;

  @Mock
  DbClient dbClient;

  @Mock
  DbSession session;

  @Mock
  System2 system2;

  @Captor
  ArgumentCaptor<CharacteristicDto> characteristicCaptor;

  @Captor
  ArgumentCaptor<RuleDto> ruleCaptor;

  Date now = DateUtils.parseDate("2014-03-19");

  CharacteristicDto characteristicDto = new CharacteristicDto()
    .setId(1)
    .setKey("MEMORY_EFFICIENCY")
    .setName("Memory use")
    .setOrder(2)
    .setEnabled(true);

  CharacteristicDto subCharacteristicDto = new CharacteristicDto()
    .setId(2)
    .setKey("EFFICIENCY")
    .setName("Efficiency")
    .setParentId(1)
    .setEnabled(true);

  int currentId;

  DebtModelOperations service;

  @Before
  public void setUp() throws Exception {
    when(system2.now()).thenReturn(now.getTime());

    MockUserSession.set().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);

    currentId = 10;
    // Associate an id when inserting an object to simulate the db id generator
    doAnswer(new Answer() {
      public Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        CharacteristicDto dto = (CharacteristicDto) args[0];
        dto.setId(++currentId);
        return null;
      }
    }).when(dao).insert(any(CharacteristicDto.class), any(SqlSession.class));

    when(dbClient.openSession(false)).thenReturn(session);
    when(dbClient.ruleDao()).thenReturn(ruleDao);
    when(dbClient.debtCharacteristicDao()).thenReturn(dao);
    service = new DebtModelOperations(dbClient, system2);
  }

  @Test
  public void create_sub_characteristic() {
    when(dao.selectById(1, session)).thenReturn(characteristicDto);

    DefaultDebtCharacteristic result = (DefaultDebtCharacteristic) service.create("Compilation name", 1);

    assertThat(result.id()).isEqualTo(currentId);
    assertThat(result.key()).isEqualTo("COMPILATION_NAME");
    assertThat(result.name()).isEqualTo("Compilation name");
    assertThat(result.parentId()).isEqualTo(1);
    assertThat(result.createdAt()).isEqualTo(now);
  }

  @Test
  public void fail_to_create_sub_characteristic_when_parent_id_is_not_a_root_characteristic() {
    when(dao.selectById(1, session)).thenReturn(subCharacteristicDto);

    try {
      service.create("Compilation", 1);
      fail();
    } catch (BadRequestException e) {
      assertThat(e.firstError().getKey()).isEqualTo("A sub characteristic can not have a sub characteristic as parent.");
    }
  }

  @Test
  public void fail_to_create_sub_characteristic_when_parent_does_not_exists() {
    when(dao.selectById(1, session)).thenReturn(null);

    try {
      service.create("Compilation", 1);
      fail();
    } catch (Exception e) {
      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Characteristic with id 1 does not exists.");
    }
  }

  @Test
  public void fail_to_create_sub_characteristic_when_name_already_used() {
    when(dao.selectByName("Compilation", session)).thenReturn(new CharacteristicDto());
    when(dao.selectById(1, session)).thenReturn(characteristicDto);

    try {
      service.create("Compilation", 1);
      fail();
    } catch (BadRequestException e) {
      assertThat(e.firstError().getKey()).isEqualTo("errors.is_already_used");
      assertThat(e.firstError().getParams()[0]).isEqualTo("Compilation");
    }
  }

  @Test
  public void fail_to_create_sub_characteristic_when_wrong_permission() {
    MockUserSession.set().setGlobalPermissions(GlobalPermissions.DASHBOARD_SHARING);

    try {
      service.create("Compilation", 1);
      fail();
    } catch (Exception e) {
      assertThat(e).isInstanceOf(ForbiddenException.class);
    }
  }

  @Test
  public void create_characteristic() {
    when(dao.selectMaxCharacteristicOrder(session)).thenReturn(2);

    DefaultDebtCharacteristic result = (DefaultDebtCharacteristic) service.create("Portability", null);

    assertThat(result.id()).isEqualTo(currentId);
    assertThat(result.key()).isEqualTo("PORTABILITY");
    assertThat(result.name()).isEqualTo("Portability");
    assertThat(result.order()).isEqualTo(3);
    assertThat(result.createdAt()).isEqualTo(now);
  }

  @Test
  public void create_first_characteristic() {
    when(dao.selectMaxCharacteristicOrder(session)).thenReturn(0);

    DefaultDebtCharacteristic result = (DefaultDebtCharacteristic) service.create("Portability", null);

    assertThat(result.id()).isEqualTo(currentId);
    assertThat(result.key()).isEqualTo("PORTABILITY");
    assertThat(result.name()).isEqualTo("Portability");
    assertThat(result.order()).isEqualTo(1);
    assertThat(result.createdAt()).isEqualTo(now);
  }

  @Test
  public void rename_characteristic() {
    when(dao.selectById(10, session)).thenReturn(subCharacteristicDto);

    DefaultDebtCharacteristic result = (DefaultDebtCharacteristic) service.rename(10, "New Efficiency");

    assertThat(result.key()).isEqualTo("EFFICIENCY");
    assertThat(result.name()).isEqualTo("New Efficiency");
    assertThat(result.updatedAt()).isEqualTo(now);
  }

  @Test
  public void not_rename_characteristic_when_renaming_with_same_name() {
    when(dao.selectById(10, session)).thenReturn(subCharacteristicDto);

    service.rename(10, "Efficiency");

    verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
  }

  @Test
  public void fail_to_rename_unknown_characteristic() {
    when(dao.selectById(10, session)).thenReturn(null);

    try {
      service.rename(10, "New Efficiency");
      fail();
    } catch (Exception e) {
      assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Characteristic with id 10 does not exists.");
    }
  }

  @Test
  public void move_up() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(1),
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2)
    ));

    DebtCharacteristic result = service.moveUp(10);

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

    assertThat(result.order()).isEqualTo(1);
    assertThat(characteristicCaptor.getAllValues().get(0).getOrder()).isEqualTo(2);
    assertThat(characteristicCaptor.getAllValues().get(0).getUpdatedAt()).isEqualTo(now);
    assertThat(characteristicCaptor.getAllValues().get(1).getOrder()).isEqualTo(1);
    assertThat(characteristicCaptor.getAllValues().get(1).getUpdatedAt()).isEqualTo(now);
  }

  @Test
  public void do_nothing_when_move_up_and_already_on_top() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(1));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(1),
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(2)
    ));

    service.moveUp(10);

    verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
  }

  @Test
  public void move_down() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2),
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(3)
    ));

    DebtCharacteristic result = service.moveDown(10);

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

    assertThat(result.order()).isEqualTo(3);
    assertThat(characteristicCaptor.getAllValues().get(0).getOrder()).isEqualTo(2);
    assertThat(characteristicCaptor.getAllValues().get(0).getUpdatedAt()).isEqualTo(now);
    assertThat(characteristicCaptor.getAllValues().get(1).getOrder()).isEqualTo(3);
    assertThat(characteristicCaptor.getAllValues().get(1).getUpdatedAt()).isEqualTo(now);
  }

  @Test
  public void do_nothing_when_move_down_and_already_on_bottom() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(1),
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2)
    ));

    service.moveDown(10);

    verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
  }

  @Test
  public void fail_to_move_sub_characteristic() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setParentId(1));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2),
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(3)
    ));

    try {
      service.moveDown(10);
      fail();
    } catch (BadRequestException e) {
      assertThat(e.firstError().getKey()).isEqualTo("Sub characteristics can not be moved.");
    }
    verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
  }

  @Test
  public void fail_to_move_characteristic_with_no_order() {
    when(dao.selectById(10, session)).thenReturn(new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(null));
    when(dao.selectEnabledRootCharacteristics(session)).thenReturn(newArrayList(
      new CharacteristicDto().setId(10).setKey("MEMORY_EFFICIENCY").setOrder(2),
      new CharacteristicDto().setId(2).setKey("PORTABILITY").setOrder(3)
    ));

    try {
      service.moveDown(10);
      fail();
    } catch (Exception e) {
      assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("The order of the characteristic 'MEMORY_EFFICIENCY' should not be null");
    }

    verify(dao, never()).update(any(CharacteristicDto.class), eq(session));
  }

  @Test
  public void delete_sub_characteristic() {
    DbSession batchSession = mock(DbSession.class);
    when(dbClient.openSession(true)).thenReturn(batchSession);

    when(ruleDao.findRulesByDebtSubCharacteristicId(batchSession, 2)).thenReturn(newArrayList(
      new RuleDto()
        .setSubCharacteristicId(2)
        .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
        .setRemediationCoefficient("2h").setRemediationOffset("5min")
        .setDefaultSubCharacteristicId(10)
        .setDefaultRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
        .setDefaultRemediationCoefficient("4h")
        .setDefaultRemediationOffset("15min")
    ));
    when(dao.selectById(2, batchSession)).thenReturn(subCharacteristicDto);

    service.delete(2);

    verify(ruleDao).update(eq(batchSession), ruleCaptor.capture());

    RuleDto ruleDto = ruleCaptor.getValue();
    assertThat(ruleDto.getUpdatedAt()).isEqualTo(now);

    // Overridden debt data are disabled
    assertThat(ruleDto.getSubCharacteristicId()).isEqualTo(-1);
    assertThat(ruleDto.getRemediationFunction()).isNull();
    assertThat(ruleDto.getRemediationCoefficient()).isNull();
    assertThat(ruleDto.getRemediationOffset()).isNull();

    // Default debt data should not be touched
    assertThat(ruleDto.getDefaultSubCharacteristicId()).isEqualTo(10);
    assertThat(ruleDto.getDefaultRemediationFunction()).isEqualTo("LINEAR_OFFSET");
    assertThat(ruleDto.getDefaultRemediationCoefficient()).isEqualTo("4h");
    assertThat(ruleDto.getDefaultRemediationOffset()).isEqualTo("15min");

    verify(dao).update(characteristicCaptor.capture(), eq(batchSession));
    CharacteristicDto characteristicDto = characteristicCaptor.getValue();

    // Sub characteristic is disable
    assertThat(characteristicDto.getId()).isEqualTo(2);
    assertThat(characteristicDto.isEnabled()).isFalse();
    assertThat(characteristicDto.getUpdatedAt()).isEqualTo(now);
  }

  @Test
  public void delete_sub_characteristic_disable_default_rules_debt_if_default_characteristic_is_deleted() {
    DbSession batchSession = mock(DbSession.class);
    when(dbClient.openSession(true)).thenReturn(batchSession);

    when(ruleDao.findRulesByDebtSubCharacteristicId(batchSession, 2)).thenReturn(newArrayList(
      new RuleDto()
        .setSubCharacteristicId(10).setRemediationFunction("LINEAR_OFFSET").setRemediationCoefficient("2h").setRemediationOffset("5min")
        .setDefaultSubCharacteristicId(2).setDefaultRemediationFunction("LINEAR_OFFSET").setDefaultRemediationCoefficient("4h").setDefaultRemediationOffset("15min")
    ));
    when(dao.selectById(2, batchSession)).thenReturn(subCharacteristicDto);

    service.delete(2);

    verify(ruleDao).update(eq(batchSession), ruleCaptor.capture());
    RuleDto ruleDto = ruleCaptor.getValue();

    // Default debt data are disabled
    assertThat(ruleDto.getDefaultSubCharacteristicId()).isNull();
    assertThat(ruleDto.getDefaultRemediationFunction()).isNull();
    assertThat(ruleDto.getDefaultRemediationCoefficient()).isNull();
    assertThat(ruleDto.getDefaultRemediationOffset()).isNull();

    // Overridden debt data should not be touched
    assertThat(ruleDto.getSubCharacteristicId()).isEqualTo(10);
    assertThat(ruleDto.getRemediationFunction()).isEqualTo("LINEAR_OFFSET");
    assertThat(ruleDto.getRemediationCoefficient()).isEqualTo("2h");
    assertThat(ruleDto.getRemediationOffset()).isEqualTo("5min");

    verify(dao).update(characteristicCaptor.capture(), eq(batchSession));
    CharacteristicDto characteristicDto = characteristicCaptor.getValue();

    // Sub characteristic is disable
    assertThat(characteristicDto.getId()).isEqualTo(2);
    assertThat(characteristicDto.isEnabled()).isFalse();
    assertThat(characteristicDto.getUpdatedAt()).isEqualTo(now);
  }

  @Test
  public void delete_characteristic() {
    DbSession batchSession = mock(DbSession.class);
    when(dbClient.openSession(true)).thenReturn(batchSession);

    when(ruleDao.findRulesByDebtSubCharacteristicId(batchSession, subCharacteristicDto.getId())).thenReturn(newArrayList(
      new RuleDto().setSubCharacteristicId(subCharacteristicDto.getId())
        .setRemediationFunction(DebtRemediationFunction.Type.LINEAR_OFFSET.toString())
        .setRemediationCoefficient("2h")
        .setRemediationOffset("5min")
    ));
    when(dao.selectCharacteristicsByParentId(1, batchSession)).thenReturn(newArrayList(
      subCharacteristicDto
    ));
    when(dao.selectById(1, batchSession)).thenReturn(characteristicDto);

    service.delete(1);

    verify(ruleDao).update(eq(batchSession), ruleCaptor.capture());

    verify(dao, times(2)).update(characteristicCaptor.capture(), eq(batchSession));
    CharacteristicDto subCharacteristicDto = characteristicCaptor.getAllValues().get(0);
    CharacteristicDto characteristicDto = characteristicCaptor.getAllValues().get(1);

    // Sub characteristic is disable
    assertThat(subCharacteristicDto.getId()).isEqualTo(2);
    assertThat(subCharacteristicDto.isEnabled()).isFalse();
    assertThat(subCharacteristicDto.getUpdatedAt()).isEqualTo(now);

    // Characteristic is disable
    assertThat(characteristicDto.getId()).isEqualTo(1);
    assertThat(characteristicDto.isEnabled()).isFalse();
    assertThat(characteristicDto.getUpdatedAt()).isEqualTo(now);
  }

  @Test
  public void not_delete_already_disabled_characteristic() {
    DbSession batchSession = mock(DbSession.class);
    when(dbClient.openSession(true)).thenReturn(batchSession);

    when(dao.selectById(1, batchSession)).thenReturn(new CharacteristicDto()
      .setId(1)
      .setKey("MEMORY_EFFICIENCY")
      .setName("Memory use")
      .setOrder(2)
      .setEnabled(false));

    service.delete(1);

    verify(dao, never()).update(any(CharacteristicDto.class), eq(batchSession));
  }

}
TOP

Related Classes of org.sonar.server.debt.DebtModelOperationsTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.