import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.Optional;
import javax.annotation.Nullable;
+import org.assertj.core.api.ThrowableAssert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.utils.System2;
import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.ce.task.projectanalysis.analysis.Branch;
+import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
@RunWith(DataProviderRunner.class)
public class BranchPersisterImplTest {
- private final static Component MAIN = builder(PROJECT, 1).setUuid("PROJECT_UUID").setKey("PROJECT_KEY").build();
- private final static Component BRANCH1 = builder(PROJECT, 1).setUuid("BRANCH_UUID").setKey("BRANCH_KEY").build();
+ private final static Component MAIN = builder(PROJECT, 1, "PROJECT_KEY").setUuid("PROJECT_UUID").build();
+ private final static Component BRANCH1 = builder(PROJECT, 2, "BRANCH_KEY").setUuid("BRANCH_UUID").build();
+ private final static Component PR1 = builder(PROJECT, 3, "develop").setUuid("PR_UUID").build();
@Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
- @Rule
- public ExpectedException exception = ExpectedException.none();
-
- private Configuration configuration = mock(Configuration.class);
- private BranchPersister underTest = new BranchPersisterImpl(dbTester.getDbClient(), treeRootHolder, analysisMetadataHolder, configuration);
+ private final Configuration configuration = mock(Configuration.class);
+ private final BranchPersister underTest = new BranchPersisterImpl(dbTester.getDbClient(), treeRootHolder, analysisMetadataHolder, configuration);
@Test
public void persist_fails_with_ISE_if_no_component_for_main_branches() {
analysisMetadataHolder.setBranch(createBranch(BRANCH, true, "master"));
treeRootHolder.setRoot(MAIN);
+ DbSession dbSession = dbTester.getSession();
- expectMissingComponentISE();
-
- underTest.persist(dbTester.getSession());
+ expectMissingComponentISE(() -> underTest.persist(dbSession));
}
@Test
public void persist_fails_with_ISE_if_no_component_for_branches() {
analysisMetadataHolder.setBranch(createBranch(BRANCH, false, "foo"));
treeRootHolder.setRoot(BRANCH1);
+ DbSession dbSession = dbTester.getSession();
- expectMissingComponentISE();
-
- underTest.persist(dbTester.getSession());
+ expectMissingComponentISE(() -> underTest.persist(dbSession));
}
@Test
public void persist_fails_with_ISE_if_no_component_for_pull_request() {
analysisMetadataHolder.setBranch(createBranch(BranchType.PULL_REQUEST, false, "12"));
treeRootHolder.setRoot(BRANCH1);
+ DbSession dbSession = dbTester.getSession();
- expectMissingComponentISE();
-
- underTest.persist(dbTester.getSession());
+ expectMissingComponentISE(() -> underTest.persist(dbSession));
}
@Test
underTest.persist(dbTester.getSession());
Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), MAIN.getUuid());
+ assertThat(branchDto).isPresent();
assertThat(branchDto.get().isExcludeFromPurge()).isTrue();
}
underTest.persist(dbTester.getSession());
Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
+ assertThat(branchDto).isPresent();
assertThat(branchDto.get().isExcludeFromPurge()).isTrue();
}
+ @Test
+ public void pull_request_is_never_excluded_from_branch_purge_even_if_its_source_branch_name_matches_sonar_dbcleaner_keepFromPurge_property() {
+ when(configuration.getStringArray(BRANCHES_TO_KEEP_WHEN_INACTIVE)).thenReturn(new String[] {"develop"});
+
+ analysisMetadataHolder.setBranch(createPullRequest(PR1.getKey(), MAIN.getUuid()));
+ analysisMetadataHolder.setPullRequestKey(PR1.getKey());
+ treeRootHolder.setRoot(PR1);
+ ComponentDto mainComponent = dbTester.components().insertPublicProject(p -> p.setDbKey(MAIN.getDbKey()).setUuid(MAIN.getUuid()));
+ ComponentDto component = ComponentTesting.newBranchComponent(mainComponent, new BranchDto()
+ .setUuid(PR1.getUuid())
+ .setKey(PR1.getKey())
+ .setProjectUuid(MAIN.getUuid())
+ .setBranchType(PULL_REQUEST)
+ .setMergeBranchUuid(MAIN.getUuid()));
+ dbTester.getDbClient().componentDao().insert(dbTester.getSession(), component);
+ dbTester.commit();
+
+ underTest.persist(dbTester.getSession());
+
+ Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), PR1.getUuid());
+ assertThat(branchDto).isPresent();
+ assertThat(branchDto.get().isExcludeFromPurge()).isFalse();
+ }
+
@Test
public void non_main_branch_is_included_in_branch_purge_if_branch_name_does_not_match_sonar_dbcleaner_keepFromPurge_property() {
when(configuration.getStringArray(BRANCHES_TO_KEEP_WHEN_INACTIVE)).thenReturn(new String[] {"foobar-.*"});
underTest.persist(dbTester.getSession());
Optional<BranchDto> branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), BRANCH1.getUuid());
+ assertThat(branchDto).isPresent();
assertThat(branchDto.get().isExcludeFromPurge()).isFalse();
}
return createBranch(type, isMain, name, null);
}
+ private static Branch createPullRequest(String key, String mergeBranchUuid) {
+ Branch branch = createBranch(PULL_REQUEST, false, key, mergeBranchUuid);
+ when(branch.getPullRequestKey()).thenReturn(key);
+ return branch;
+ }
+
private static Branch createBranch(BranchType type, boolean isMain, String name, @Nullable String mergeBranchUuid) {
Branch branch = mock(Branch.class);
when(branch.getType()).thenReturn(type);
return branch;
}
- private void expectMissingComponentISE() {
- exception.expect(IllegalStateException.class);
- exception.expectMessage("Component has been deleted by end-user during analysis");
+ private void expectMissingComponentISE(ThrowableAssert.ThrowingCallable callable) {
+ assertThatThrownBy(callable)
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage("Component has been deleted by end-user during analysis");
}
}
ComponentDto project = db.components().insertPublicProject();
ComponentDto branch1 = db.components().insertProjectBranch(project);
ComponentDto branch2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
+ ComponentDto pr1 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
+
db.components().insertSnapshot(branch1);
db.components().insertSnapshot(branch2);
+ db.components().insertSnapshot(pr1);
// branch with other components and issues, last analysed 31 days ago
- ComponentDto branch3 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
- db.components().insertSnapshot(branch3, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -31).getTime()));
-
- ComponentDto module = db.components().insertComponent(newModuleDto(branch3));
- ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
- ComponentDto file = db.components().insertComponent(newFileDto(subModule));
- db.issues().insert(rule, branch3, file);
- db.issues().insert(rule, branch3, subModule);
- db.issues().insert(rule, branch3, module);
+ ComponentDto branch3 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH).setExcludeFromPurge(false));
+ addComponentsSnapshotsAndIssuesToBranch(branch3, rule, 31);
// branch with no analysis
ComponentDto branch4 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
+ // branch last analysed 31 days ago but protected from purge
+ ComponentDto branch5 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH).setExcludeFromPurge(true));
+ db.components().insertSnapshot(branch5, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -31).getTime()));
+
+ // pull request last analysed 100 days ago
+ ComponentDto pr2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST).setExcludeFromPurge(false));
+ addComponentsSnapshotsAndIssuesToBranch(pr2, rule, 100);
+
+ // pull request last analysed 100 days ago but marked as "excluded from purge" which should not work for pull requests
+ ComponentDto pr3 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST).setExcludeFromPurge(true));
+ addComponentsSnapshotsAndIssuesToBranch(pr3, rule, 100);
+
underTest.purge(dbSession, newConfigurationWith30Days(System2.INSTANCE, project.uuid(), project.uuid()), PurgeListener.EMPTY, new PurgeProfiler());
dbSession.commit();
- assertThat(uuidsIn("components")).containsOnly(project.uuid(), branch1.uuid(), branch2.uuid());
+ assertThat(uuidsIn("components")).containsOnly(
+ project.uuid(), branch1.uuid(), branch2.uuid(), branch5.uuid(), pr1.uuid());
assertThat(uuidsIn("projects")).containsOnly(project.uuid());
}
.map(t -> (String) t.get("UUID"));
}
+ private void addComponentsSnapshotsAndIssuesToBranch(ComponentDto branch, RuleDefinitionDto rule, int branchAge) {
+ db.components().insertSnapshot(branch, dto -> dto.setCreatedAt(DateUtils.addDays(new Date(), -branchAge).getTime()));
+ ComponentDto module = db.components().insertComponent(newModuleDto(branch));
+ ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
+ ComponentDto file = db.components().insertComponent(newFileDto(subModule));
+ db.issues().insert(rule, branch, file);
+ db.issues().insert(rule, branch, subModule);
+ db.issues().insert(rule, branch, module);
+ }
+
}