package com.hubspot.blazar.visitor.repositorybuild; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.Before; import org.junit.Test; import com.google.common.base.Optional; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.hubspot.blazar.base.BuildConfig; import com.hubspot.blazar.base.BuildOptions; import com.hubspot.blazar.base.BuildTrigger; import com.hubspot.blazar.base.CommitInfo; import com.hubspot.blazar.base.DependencyGraph; import com.hubspot.blazar.base.GitInfo; import com.hubspot.blazar.base.MalformedFile; import com.hubspot.blazar.base.Module; import com.hubspot.blazar.base.RepositoryBuild; import com.hubspot.blazar.data.service.BranchService; import com.hubspot.blazar.data.service.DependenciesService; import com.hubspot.blazar.data.service.InterProjectBuildMappingService; import com.hubspot.blazar.data.service.InterProjectBuildService; import com.hubspot.blazar.data.service.MalformedFileService; import com.hubspot.blazar.data.service.ModuleBuildService; import com.hubspot.blazar.data.service.ModuleService; import com.hubspot.blazar.data.service.RepositoryBuildService; import com.hubspot.blazar.exception.NonRetryableBuildException; import com.hubspot.blazar.github.GitHubProtos; import com.hubspot.blazar.util.BuildConfigUtils; import com.hubspot.blazar.util.GitHubHelper; public class LaunchingRepositoryBuildVisitorTest { private static final BranchService branchService = mock(BranchService.class); private static final BuildConfigUtils buildConfigUtils = mock(BuildConfigUtils.class); private static final RepositoryBuildService repositoryBuildService = mock(RepositoryBuildService.class); private static final ModuleBuildService moduleBuildService = mock(ModuleBuildService.class); private static final MalformedFileService malformedFileService = mock(MalformedFileService.class); private static final InterProjectBuildService interProjectBuildService = mock(InterProjectBuildService.class); private static final InterProjectBuildMappingService interProjectBuildMappingService = mock(InterProjectBuildMappingService.class); private static final ModuleService moduleService = mock(ModuleService.class); private static final DependenciesService dependenciesService = mock(DependenciesService.class); private static final GitHubHelper gitHubHelper = mock(GitHubHelper.class); private static final GitInfo branch = new GitInfo(Optional.of(1), "git.example.com", "example", "test", 1337, "master", true, 100L, 100L); private static final BuildConfig defaultBuildConfig = BuildConfig.makeDefaultBuildConfig(); private static final Module activeModule = new Module(Optional.of(1), "activeModule", "config", "/activeModule", "/activeModule/*", true, 100L, 100L, Optional.absent(), Optional.of(defaultBuildConfig), Optional.of(defaultBuildConfig)); private static final Module inactiveModule = new Module(Optional.of(2), "inactiveModule", "config", "/inactiveModule", "/inactiveModule/*", false, 100L, 100L, Optional.absent(), Optional.of(defaultBuildConfig), Optional.of(defaultBuildConfig)); private static final Map<Integer, Set<Integer>> dependencyMap = ImmutableMap.of( 1, ImmutableSet.of(), 2, ImmutableSet.of()); private static final CommitInfo commitInfo = new CommitInfo(GitHubProtos.Commit.newBuilder().setId("0000000000000000000000000000000000000000").build(), Optional.absent(), Collections.emptyList(), false); private static final RepositoryBuild launchingBuild = RepositoryBuild.newBuilder(1, 1, RepositoryBuild.State.LAUNCHING, BuildTrigger.forUser("example"), new BuildOptions(ImmutableSet.of(1), BuildOptions.BuildDownstreams.WITHIN_REPOSITORY, false)) .setId(Optional.of(1L)) .setDependencyGraph(Optional.of(new DependencyGraph(dependencyMap, ImmutableList.of(1, 2)))) .setCommitInfo(Optional.of(commitInfo)) .build(); private static final LaunchingRepositoryBuildVisitor buildVisitor = new LaunchingRepositoryBuildVisitor( repositoryBuildService, moduleBuildService, malformedFileService, interProjectBuildService, interProjectBuildMappingService, moduleService, dependenciesService, gitHubHelper); @Before public void before() throws IOException, NonRetryableBuildException { when(branchService.get(anyInt())).thenReturn(Optional.of(branch)); when(buildConfigUtils.getConfigAtRef(anyObject(), anyString(), anyString())).thenReturn(BuildConfig.makeDefaultBuildConfig()); } @Test public void itFailsBuildOfBranchWhenItHasMalformedFiles() throws Exception { when(malformedFileService.getMalformedFiles(anyInt())) .thenReturn(ImmutableSet.of(new MalformedFile(1, "config", "/.blazar.yaml", "this is a test malformed file"))); when(moduleService.getByBranch(1)).thenReturn(ImmutableSet.of(activeModule, inactiveModule)); boolean[] moduleBuildFailed = {false}; doAnswer(invocation -> { RepositoryBuild build = (RepositoryBuild) invocation.getArguments()[0]; Module module = (Module) invocation.getArguments()[1]; assertThat(module.equals(activeModule)); assertThat(build.equals(launchingBuild)); moduleBuildFailed[0] = true; return null; }).when(moduleBuildService).createFailedBuild(any(), any()); boolean[] repoBuildFailed = {false}; doAnswer(invocation -> { RepositoryBuild build = (RepositoryBuild) invocation.getArguments()[0]; assertThat(build).isEqualTo(launchingBuild); repoBuildFailed[0] = true; return null; }).when(repositoryBuildService).fail(any()); buildVisitor.visitLaunching(launchingBuild); assertThat(repoBuildFailed[0]).isTrue(); assertThat(moduleBuildFailed[0]).isTrue(); } @Test public void itFailsBuildOfBranchWithNoActiveModules() throws Exception { // no malformed files no active modules when(malformedFileService.getMalformedFiles(anyInt())).thenReturn(ImmutableSet.of()); when(moduleService.getByBranch(1)).thenReturn(ImmutableSet.of(inactiveModule)); boolean[] repoBuildFailed = {false}; doAnswer(invocation -> { RepositoryBuild build = (RepositoryBuild) invocation.getArguments()[0]; assertThat(build).isEqualTo(launchingBuild); repoBuildFailed[0] = true; return null; }).when(repositoryBuildService).fail(any()); buildVisitor.visitLaunching(launchingBuild); assertThat(repoBuildFailed[0]).isTrue(); } @Test public void itEnqueuesModuleBuildsAndUpdatesRepositoryBuildToLaunching() throws Exception { when(malformedFileService.getMalformedFiles(anyInt())).thenReturn(ImmutableSet.of()); when(moduleService.getByBranch(1)).thenReturn(ImmutableSet.of(activeModule, inactiveModule)); doThrow(new RuntimeException("Build should not have been failed")).when(repositoryBuildService).fail(any()); RepositoryBuild[] savedRepositoryBuild = {null}; doAnswer(invocation -> { savedRepositoryBuild[0] = (RepositoryBuild) invocation.getArguments()[0]; return null; }).when(repositoryBuildService).update(anyObject()); List<Module> modulesThatWereEnqueued = new ArrayList<>(); doAnswer(invocation -> { modulesThatWereEnqueued.add((Module) invocation.getArguments()[1]); return null; }).when(moduleBuildService).enqueue(anyObject(), anyObject(), anyObject(), anyObject()); RepositoryBuild expectedRepositoryBuild = launchingBuild.toBuilder().setState(RepositoryBuild.State.IN_PROGRESS).build(); buildVisitor.visitLaunching(launchingBuild); assertThat(savedRepositoryBuild).isNotNull(); assertThat(savedRepositoryBuild[0]).isEqualTo(expectedRepositoryBuild); assertThat(modulesThatWereEnqueued).doesNotContain(inactiveModule); assertThat(modulesThatWereEnqueued).isEqualTo(ImmutableList.of(activeModule)); } }