/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program 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.
*
* This program 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.db.qualityprofile;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.core.util.UuidFactory;
import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import static java.util.Arrays.asList;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class QProfileChangeDaoTest {
private static final long A_DATE = 1_500_000_000_000L;
private System2 system2 = mock(System2.class);
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public DbTester dbTester = DbTester.create(system2);
private DbSession dbSession = dbTester.getSession();
private UuidFactory uuidFactory = mock(UuidFactory.class);
private QProfileChangeDao underTest = new QProfileChangeDao(system2, uuidFactory);
@Test
public void test_insert_without_null_fields() {
when(system2.now()).thenReturn(A_DATE);
when(uuidFactory.create()).thenReturn("C1");
String profileKey = "P1";
String login = "marcel";
String type = "ACTIVATED";
String data = "some_data";
insertChange(profileKey, type, login, data);
Map<String, Object> row = selectChangeByKey("C1");
assertThat(row.get("qprofileKey")).isEqualTo(profileKey);
assertThat(row.get("createdAt")).isEqualTo(A_DATE);
assertThat(row.get("login")).isEqualTo(login);
assertThat(row.get("changeType")).isEqualTo(type);
assertThat(row.get("changeData")).isEqualTo(data);
}
/**
* user_login and data can be null
*/
@Test
public void test_insert_with_nullable_fields() {
when(system2.now()).thenReturn(A_DATE);
when(uuidFactory.create()).thenReturn("C1");
insertChange("P1", "ACTIVATED", null, null);
Map<String, Object> row = selectChangeByKey("C1");
assertThat(row.get("qprofileKey")).isEqualTo("P1");
assertThat(row.get("createdAt")).isEqualTo(A_DATE);
assertThat(row.get("changeType")).isEqualTo("ACTIVATED");
assertThat(row.get("login")).isNull();
assertThat(row.get("changeData")).isNull();
}
@Test
public void insert_throws_ISE_if_key_is_already_set() {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Key of QProfileChangeDto must be set by DAO only. Got C1.");
underTest.insert(dbSession, new QProfileChangeDto().setKey("C1"));
}
@Test
public void insert_throws_ISE_if_date_is_already_set() {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Date of QProfileChangeDto must be set by DAO only. Got 123.");
underTest.insert(dbSession, new QProfileChangeDto().setCreatedAt(123L));
}
@Test
public void selectByQuery_returns_empty_list_if_no_profile_changes() {
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1"));
assertThat(changes).isEmpty();
}
@Test
public void selectByQuery_returns_changes_ordered_by_descending_date() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 1, A_DATE + 2);
when(uuidFactory.create()).thenReturn("C1", "C2", "C3");
// profile P1
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
// profile P2: C3
insertChange("P2", "ACTIVATED", null, null);// key: C3
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1"));
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2", "C1");
}
@Test
public void selectByQuery_supports_pagination_of_changes() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20, A_DATE + 30);
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
insertChange("P1", "ACTIVATED", null, null);// key: C3
insertChange("P1", "ACTIVATED", null, null);// key: C4
QProfileChangeQuery query = new QProfileChangeQuery("P1");
query.setOffset(2);
query.setLimit(1);
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query);
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2");
}
@Test
public void selectByQuery_returns_changes_after_given_date() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20);
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
insertChange("P1", "ACTIVATED", null, null);// key: C3
QProfileChangeQuery query = new QProfileChangeQuery("P1");
query.setFromIncluded(A_DATE + 10);
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query);
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C3", "C2");
}
@Test
public void selectByQuery_returns_changes_before_given_date() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20);
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
insertChange("P1", "ACTIVATED", null, null);// key: C3
QProfileChangeQuery query = new QProfileChangeQuery("P1");
query.setToExcluded(A_DATE + 12);
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query);
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C2", "C1");
}
@Test
public void selectByQuery_returns_changes_in_a_range_of_dates() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 10, A_DATE + 20, A_DATE + 30);
when(uuidFactory.create()).thenReturn("C1", "C2", "C3", "C4");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
insertChange("P1", "ACTIVATED", null, null);// key: C3
insertChange("P1", "ACTIVATED", null, null);// key: C4
QProfileChangeQuery query = new QProfileChangeQuery("P1");
query.setFromIncluded(A_DATE + 8);
query.setToExcluded(A_DATE + 22);
List<QProfileChangeDto> changes = underTest.selectByQuery(dbSession, query);
assertThat(changes).extracting(QProfileChangeDto::getKey).containsExactly("C3", "C2");
}
@Test
public void selectByQuery_mapping() {
when(system2.now()).thenReturn(A_DATE);
when(uuidFactory.create()).thenReturn("C1");
insertChange("P1", "ACTIVATED", "Oscar", "data");
List<QProfileChangeDto> result = underTest.selectByQuery(dbSession, new QProfileChangeQuery("P1"));
assertThat(result).hasSize(1);
QProfileChangeDto change = result.get(0);
assertThat(change.getProfileKey()).isEqualTo("P1");
assertThat(change.getLogin()).isEqualTo("Oscar");
assertThat(change.getData()).isEqualTo("data");
assertThat(change.getChangeType()).isEqualTo("ACTIVATED");
assertThat(change.getKey()).isEqualTo("C1");
assertThat(change.getCreatedAt()).isEqualTo(A_DATE);
}
@Test
public void test_countForProfileKey() {
when(system2.now()).thenReturn(A_DATE, A_DATE + 10);
when(uuidFactory.create()).thenReturn("C1", "C2");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
assertThat(underTest.countForProfileKey(dbSession, "P1")).isEqualTo(2);
assertThat(underTest.countForProfileKey(dbSession, "P2")).isEqualTo(0);
}
@Test
public void deleteByProfileKeys_deletes_rows_with_specified_keys() {
when(uuidFactory.create()).thenReturn("C1", "C2", "C3");
insertChange("P1", "ACTIVATED", null, null);// key: C1
insertChange("P1", "ACTIVATED", null, null);// key: C2
insertChange("P2", "ACTIVATED", null, null);// key: C3
underTest.deleteByProfileKeys(dbSession, asList("P1"));
assertThat(underTest.countForProfileKey(dbSession, "P1")).isEqualTo(0);
assertThat(underTest.countForProfileKey(dbSession, "P2")).isEqualTo(1);
}
@Test
public void deleteByProfileKeys_does_nothing_if_row_with_specified_key_does_not_exist() {
when(uuidFactory.create()).thenReturn("C1");
insertChange("P1", "ACTIVATED", null, null);
underTest.deleteByProfileKeys(dbSession, asList("does_not_exist"));
assertThat(underTest.countForProfileKey(dbSession, "P1")).isEqualTo(1);
}
private void insertChange(String profileKey, String type, @Nullable String login, @Nullable String data) {
QProfileChangeDto dto = new QProfileChangeDto()
.setProfileKey(profileKey)
.setLogin(login)
.setChangeType(type)
.setData(data);
underTest.insert(dbSession, dto);
}
private Map<String, Object> selectChangeByKey(String key) {
return dbTester.selectFirst(dbSession,
"select qprofile_key as \"qprofileKey\", created_at as \"createdAt\", user_login as \"login\", change_type as \"changeType\", change_data as \"changeData\" from qprofile_changes where kee='"
+ key + "'");
}
}