package com.hubspot.blazar.util;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
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.BuildStep;
import com.hubspot.blazar.base.Dependency;
import com.hubspot.blazar.base.GitInfo;
import com.hubspot.blazar.base.StepActivationCriteria;
import com.hubspot.blazar.config.BlazarConfiguration;
import com.hubspot.blazar.config.ExecutorConfiguration;
import com.hubspot.blazar.exception.NonRetryableBuildException;
import com.hubspot.blazar.external.models.singularity.BuildCGroupResources;
public class BlazarConfigUtilsTest {
private static final String DEFAULT_BUILD_USER = "DefaultBuildUser";
private static final BuildCGroupResources DEFAULT_BUILD_BUILD_CGROUP_RESOURCES = new BuildCGroupResources(2, 2560);
private static final long DEFAULT_BUILD_TIMEOUT = 1000L;
private static final long DEFAULT_CONTAINER_LAUNCH_TIMEOUT = 1000L;
private static final GitInfo PRIMARY_BRANCH = GitInfo.fromString("git.example.com/TestOrg/repo.git#primary");
private static final GitInfo SECONDARY_BRANCH = GitInfo.fromString("git.example.com/TestOrg/repo.git#secondary");
private static final GitHubHelper gitHubHelper = mock(GitHubHelper.class);
private static final BlazarConfiguration blazarConfiguration = mock(BlazarConfiguration.class);
private static final ExecutorConfiguration exexutorConfiguration = new ExecutorConfiguration(Optional.of(DEFAULT_BUILD_USER), Optional.of(DEFAULT_BUILD_BUILD_CGROUP_RESOURCES), Optional.of(DEFAULT_BUILD_TIMEOUT), Optional.of(DEFAULT_CONTAINER_LAUNCH_TIMEOUT));
private static final BuildConfigUtils configUtils = new BuildConfigUtils(blazarConfiguration, gitHubHelper);
private static final BuildConfig primaryConfig = BuildConfig.newBuilder()
.setSteps(ImmutableList.of(BuildStep.fromString("echo hi")))
.setBefore(ImmutableList.of(BuildStep.fromString("echo before - primary")))
.setAfter(Optional.absent())
.setEnv(ImmutableMap.of("VAR", "primary"))
.setBuildDeps(ImmutableList.of("dep-1"))
.setCache(ImmutableList.of("primary"))
.setBuildpack(Optional.of(PRIMARY_BRANCH))
.setUser(Optional.of("primary-build-user"))
.setStepActivation(ImmutableMap.of("step-one", new StepActivationCriteria(ImmutableSet.of("master"))))
.setBuildResources(Optional.of(new BuildCGroupResources(100, 100L)))
.setDepends(ImmutableSet.of(Dependency.fromString("primary-dep")))
.setProvides(ImmutableSet.of(Dependency.fromString("primary")))
.build();
private static final BuildConfig secondaryConfig = BuildConfig.newBuilder()
.setSteps(ImmutableList.of(BuildStep.fromString("echo hi")))
.setBefore(ImmutableList.of(BuildStep.fromString("echo before - secondary")))
.setAfter(Optional.absent())
.setEnv(ImmutableMap.of("VAR", "secondary", "VAR2", "secondary"))
.setBuildDeps(ImmutableList.of("dep-2"))
.setCache(ImmutableList.of("secondary"))
.setBuildpack(Optional.of(SECONDARY_BRANCH))
.setUser(Optional.of("secondary-build-user"))
.setStepActivation(ImmutableMap.of("step-one", new StepActivationCriteria(ImmutableSet.of("not-master")), "step-two", new StepActivationCriteria(ImmutableSet.of("master"))))
.setBuildResources(Optional.of(new BuildCGroupResources(200, 200L)))
.setDepends(ImmutableSet.of(Dependency.fromString("secondary-dep")))
.setProvides(ImmutableSet.of(Dependency.fromString("secondary")))
.build();
private static final BuildConfig primaryConfigWithoutOptions = BuildConfig.makeDefaultBuildConfig();
@Before
public void before() {
when(blazarConfiguration.getExecutorConfiguration()).thenReturn(exexutorConfiguration);
}
@Test
public void itPrefersPrimaryConfigForNonMergableFieldsWhenMergingConfigs() {
BuildConfig mergedConfig = configUtils.mergeBuildConfigs(primaryConfig, secondaryConfig);
assertThat(mergedConfig.getSteps()).isEqualTo(primaryConfig.getSteps());
assertThat(mergedConfig.getBefore()).isEqualTo(primaryConfig.getBefore());
assertThat(mergedConfig.getAfter()).isEqualTo(primaryConfig.getAfter());
assertThat(mergedConfig.getBuildpack()).isEqualTo(primaryConfig.getBuildpack());
assertThat(mergedConfig.getUser()).isEqualTo(primaryConfig.getUser());
assertThat(mergedConfig.getBuildResources()).isEqualTo(primaryConfig.getBuildResources());
}
@Test
public void itFallsBackToSecondaryConfigWhenOptionNotPresentInPrimary() {
BuildConfig mergedConfig = configUtils.mergeBuildConfigs(primaryConfigWithoutOptions, secondaryConfig);
assertThat(mergedConfig).isEqualTo(secondaryConfig);
}
@Test
public void itMergesCollectionFieldsPresentInBothConfigs() {
// Caveat we don't merge `steps` or `before` and they are collections.
BuildConfig mergedConfig = configUtils.mergeBuildConfigs(primaryConfig, secondaryConfig);
// Union different keys, prefer primary for same keys
assertThat(mergedConfig.getEnv().get("VAR")).isEqualTo("primary"); // in both configs primary has precedence
assertThat(mergedConfig.getEnv().get("VAR2")).isEqualTo("secondary"); // only in 2nd config is present
// Union
assertThat(mergedConfig.getBuildDeps().containsAll(primaryConfig.getBuildDeps())).isTrue();
assertThat(mergedConfig.getBuildDeps().containsAll(secondaryConfig.getBuildDeps())).isTrue();
// Union
assertThat(mergedConfig.getCache().containsAll(primaryConfig.getCache())).isTrue();
assertThat(mergedConfig.getCache().containsAll(secondaryConfig.getCache())).isTrue();
// Union different keys, prefer primary for same keys
assertThat(mergedConfig.getStepActivation().get("step-one")).isEqualTo(new StepActivationCriteria(ImmutableSet.of("master")));
assertThat(mergedConfig.getStepActivation().get("step-two")).isEqualTo(new StepActivationCriteria(ImmutableSet.of("master")));
// Union
assertThat(mergedConfig.getDepends().containsAll(primaryConfig.getDepends())).isTrue();
assertThat(mergedConfig.getDepends().containsAll(secondaryConfig.getDepends())).isTrue();
// Union
assertThat(mergedConfig.getProvides().containsAll(primaryConfig.getProvides())).isTrue();
assertThat(mergedConfig.getProvides().containsAll(secondaryConfig.getProvides())).isTrue();
}
@Test
public void itReturnsDefaultConfigIfConfigNotFound() throws IOException, NonRetryableBuildException {
when(gitHubHelper.configAtSha(anyString(), any(), anyString())).thenReturn(Optional.absent());
BuildConfig config = configUtils.getConfigAtRef(PRIMARY_BRANCH, BuildConfigUtils.BUILDPACK_FILE, "master");
assertThat(config).isEqualTo(BuildConfig.makeDefaultBuildConfig());
}
}