@Test
  public void shouldForceStagePlanWithModificationsSinceLast() throws Exception {
    Pipeline completedMingle = scheduleAndCompleteInitialPipelines();
    pipelineDao.loadPipeline(completedMingle.getId());
    TestingMaterial testingMaterial = new TestingMaterial();
    mingleConfig.setMaterialConfigs(new MaterialConfigs(testingMaterial.config()));

    MaterialRevisions revisions = new MaterialRevisions();
    revisions.addRevision(
        testingMaterial,
        testingMaterial.modificationsSince(null, null, subprocessExecutionContext));
    BuildCause buildCause = BuildCause.createManualForced(revisions, Username.ANONYMOUS);
    dbHelper.saveMaterials(buildCause.getMaterialRevisions());
    Pipeline forcedPipeline =
        instanceFactory.createPipelineInstance(
            mingleConfig,
            buildCause,
            new DefaultSchedulingContext(DEFAULT_APPROVED_BY),
            md5,
            new TimeProvider());

    pipelineService.save(forcedPipeline);

    verifyMingleScheduledWithModifications();
  }
  @Test
  public void shouldLockPipelineWhenSchedulingIt() throws Exception {
    scheduleAndCompleteInitialPipelines();

    configHelper.lockPipeline("mingle");

    Material stubMaterial = new TestingMaterial();
    mingleConfig.setMaterialConfigs(new MaterialConfigs(stubMaterial.config()));

    assertThat(pipelineLockService.isLocked("mingle"), is(false));

    MaterialRevisions revisions = new MaterialRevisions();
    revisions.addRevision(
        stubMaterial,
        ((TestingMaterial) stubMaterial)
            .modificationsSince(null, null, subprocessExecutionContext));
    BuildCause buildCause = BuildCause.createWithModifications(revisions, "");
    dbHelper.saveMaterials(buildCause.getMaterialRevisions());
    Pipeline pipeline =
        instanceFactory.createPipelineInstance(
            mingleConfig,
            buildCause,
            new DefaultSchedulingContext(DEFAULT_APPROVED_BY),
            md5,
            new TimeProvider());
    pipelineService.save(pipeline);

    assertThat(pipelineLockService.isLocked("mingle"), is(true));
  }
  @Test
  public void shouldUnderstandChangedMaterial_forManual_triggerWithOptions_DoneWithANewRevision()
      throws Exception {
    SvnMaterial svn = SvnMaterial.createSvnMaterialWithMock(repository);

    MaterialRevisions revsAfterFoo = checkinFile(svn, "foo.c", svnRepository);

    String revisionForFingerPrint =
        revsAfterFoo.findRevisionForFingerPrint(svn.getFingerprint()).getRevision().getRevision();
    scheduleHelper.manuallySchedulePipelineWithRealMaterials(
        MINGLE_PIPELINE_NAME,
        new Username(new CaseInsensitiveString("loser")),
        m(
            MaterialsMother.createMaterialFromMaterialConfig(mingleConfig.materialConfigs().get(0))
                .getPipelineUniqueFingerprint(),
            revisionForFingerPrint));

    assertThat(pipelineScheduleQueue.toBeScheduled().keySet(), hasItem(MINGLE_PIPELINE_NAME));
    BuildCause bisectAfterBisectBuildCause =
        pipelineScheduleQueue.toBeScheduled().get(MINGLE_PIPELINE_NAME);
    for (MaterialRevision materialRevision : bisectAfterBisectBuildCause.getMaterialRevisions()) {
      assertThat(
          "material revision " + materialRevision + " should have been considered changed.",
          materialRevision.isChanged(),
          is(true));
    }
    assertThat(bisectAfterBisectBuildCause.getMaterialRevisions().getRevisions().size(), is(1));
  }
 private MaterialRevisions materialRevisions(String userWithHtmlCharacters) {
   MaterialRevisions revisions = new MaterialRevisions();
   revisions.addRevision(
       MaterialsMother.svnMaterial(),
       new Modification(userWithHtmlCharacters, "comment", "email", new Date(), "r1"));
   return revisions;
 }
  @Before
  public void setup() throws Exception {
    diskSpaceSimulator = new DiskSpaceSimulator();
    new HgTestRepo("testHgRepo");

    svnRepository = new SvnTestRepo("testSvnRepo");

    dbHelper.onSetUp();
    configHelper.onSetUp();
    configHelper.usingCruiseConfigDao(goConfigDao).initializeConfigFile();

    repository = new SvnCommand(null, svnRepository.projectRepositoryUrl());

    goParentPipelineConfig =
        configHelper.addPipeline(
            GO_PIPELINE_UPSTREAM,
            STAGE_NAME,
            new MaterialConfigs(new GitMaterialConfig("foo-bar")),
            "unit");

    goPipelineConfig = configHelper.addPipeline(GO_PIPELINE_NAME, STAGE_NAME, repository, "unit");

    svnMaterialRevs = new MaterialRevisions();
    SvnMaterial svnMaterial = SvnMaterial.createSvnMaterialWithMock(repository);
    svnMaterialRevs.addRevision(
        svnMaterial,
        svnMaterial.latestModification(
            null, new ServerSubprocessExecutionContext(goConfigService, new SystemEnvironment())));

    final MaterialRevisions materialRevisions = new MaterialRevisions();
    SvnMaterial anotherSvnMaterial = SvnMaterial.createSvnMaterialWithMock(repository);
    materialRevisions.addRevision(
        anotherSvnMaterial,
        anotherSvnMaterial.latestModification(null, subprocessExecutionContext));

    transactionTemplate.execute(
        new TransactionCallbackWithoutResult() {
          @Override
          protected void doInTransactionWithoutResult(TransactionStatus status) {
            materialRepository.save(svnMaterialRevs);
          }
        });

    BuildCause buildCause = BuildCause.createWithModifications(svnMaterialRevs, "");

    mingleConfig =
        configHelper.addPipeline(
            MINGLE_PIPELINE_NAME,
            STAGE_NAME,
            repository,
            new Filter(new IgnoredFiles("**/*.doc")),
            "unit",
            "functional");
    latestPipeline = PipelineMother.schedule(this.mingleConfig, buildCause);
    latestPipeline = pipelineDao.saveWithStages(latestPipeline);
    dbHelper.passStage(latestPipeline.getStages().first());
    pipelineScheduleQueue.clear();
  }
  private void prepareAPipelineWithHistory() throws SQLException {
    MaterialRevisions materialRevisions = new MaterialRevisions();
    List<Modification> modifications =
        this.hgMaterial.latestModification(workingFolder, subprocessExecutionContext);
    materialRevisions.addRevision(this.hgMaterial, modifications);
    BuildCause buildCause = BuildCause.createWithModifications(materialRevisions, "");

    latestPipeline = PipelineMother.schedule(mingleConfig, buildCause);
    latestPipeline = dbHelper.savePipelineWithStagesAndMaterials(latestPipeline);
    dbHelper.passStage(latestPipeline.getStages().first());
  }
  @Test
  public void shouldScheduleJobForAllAgentsWhenToBeRunOnAllAgents() throws Exception {
    configHelper.addAgent("localhost", "uuid1");
    configHelper.addAgent("localhost", "uuid2");
    configHelper.addAgent("localhost", "uuid3");
    configHelper.addAgentToEnvironment("dev", "uuid1");
    configHelper.setRunOnAllAgents(
        CaseInsensitiveString.str(evolveConfig.name()), STAGE_NAME, "unit", true);

    Material stubMaterial = new TestingMaterial();
    evolveConfig.setMaterialConfigs(new MaterialConfigs(stubMaterial.config()));
    MaterialRevisions revisions = new MaterialRevisions();
    revisions.addRevision(
        stubMaterial,
        ((TestingMaterial) stubMaterial)
            .modificationsSince(null, null, subprocessExecutionContext));
    BuildCause buildCause = BuildCause.createWithModifications(revisions, "");
    dbHelper.saveMaterials(buildCause.getMaterialRevisions());

    Pipeline pipeline =
        instanceFactory.createPipelineInstance(
            evolveConfig,
            buildCause,
            new DefaultSchedulingContext(
                DEFAULT_APPROVED_BY,
                environmentConfigService.agentsForPipeline(evolveConfig.name())),
            md5,
            new TimeProvider());
    pipelineService.save(pipeline);

    Stage instance =
        scheduleService.scheduleStage(
            pipeline,
            STAGE_NAME,
            "anyone",
            new ScheduleService.NewStageInstanceCreator(goConfigService),
            new ScheduleService.ExceptioningErrorHandler());
    JobInstances scheduledJobs = instance.getJobInstances();
    assertThat(
        scheduledJobs.toArray(),
        hasItemInArray(
            hasProperty(
                "name", is(RunOnAllAgents.CounterBasedJobNameGenerator.appendMarker("unit", 1)))));
    assertThat(scheduledJobs.toArray(), hasItemInArray(hasProperty("agentUuid", is("uuid2"))));
    assertThat(
        scheduledJobs.toArray(),
        hasItemInArray(
            hasProperty(
                "name", is(RunOnAllAgents.CounterBasedJobNameGenerator.appendMarker("unit", 2)))));
    assertThat(scheduledJobs.toArray(), hasItemInArray(hasProperty("agentUuid", is("uuid3"))));
    assertThat(scheduledJobs.size(), is(2));
  }
  @Test
  public void shouldUpdateScmConfigurationOfPluggableScmMaterialsOnPipeline() {
    String jobName = "job-one";
    PipelineConfig pipelineConfig =
        setupPipelineWithScmMaterial("pipeline_with_pluggable_scm_mat", "stage", jobName);
    final Pipeline previousSuccessfulBuildWithOlderScmConfig =
        simulateSuccessfulPipelineRun(pipelineConfig);
    PipelineConfig updatedPipelineConfig =
        configHelper.updatePipeline(
            pipelineConfig.name(),
            new GoConfigFileHelper.Updater<PipelineConfig>() {
              @Override
              public void update(PipelineConfig config) {
                PluggableSCMMaterialConfig materialConfig =
                    (PluggableSCMMaterialConfig) config.materialConfigs().first();
                materialConfig
                    .getSCMConfig()
                    .getConfiguration()
                    .getProperty("password")
                    .setConfigurationValue(new ConfigurationValue("new_value"));
              }
            });

    final long jobId = rerunJob(jobName, pipelineConfig, previousSuccessfulBuildWithOlderScmConfig);

    Pipeline loadedPipeline =
        (Pipeline)
            transactionTemplate.execute(
                new TransactionCallback() {
                  public Object doInTransaction(TransactionStatus status) {
                    return loader.pipelineWithPasswordAwareBuildCauseByBuildId(jobId);
                  }
                });

    MaterialRevisions revisions = loadedPipeline.getBuildCause().getMaterialRevisions();
    Configuration updatedConfiguration =
        ((PluggableSCMMaterial)
                revisions
                    .findRevisionFor(updatedPipelineConfig.materialConfigs().first())
                    .getMaterial())
            .getScmConfig()
            .getConfiguration();
    assertThat(updatedConfiguration.size(), is(2));
    assertThat(
        updatedConfiguration.getProperty("password").getConfigurationValue(),
        is(new ConfigurationValue("new_value")));
  }
  public void saveRevs(final MaterialRevisions materialRevisions) {
    final MaterialRevisions unsavedRevisions = new MaterialRevisions();
    for (MaterialRevision materialRevision : materialRevisions) {
      unsavedRevisions.addRevision(filterUnsaved(materialRevision));
    }
    if (unsavedRevisions.isEmpty()) {
      return;
    }

    transactionTemplate.execute(
        new TransactionCallbackWithoutResult() {
          @Override
          protected void doInTransactionWithoutResult(TransactionStatus status) {
            materialRepository.save(unsavedRevisions);
          }
        });
  }
  @Test
  public void shouldFindModificationForEachMaterial() throws Exception {
    SvnMaterial material1 = repo.createMaterial("multiple-materials/trunk/part1", "part1");
    SvnMaterial material2 = repo.createMaterial("multiple-materials/trunk/part2", "part2");

    Materials materials = new Materials(material1, material2);

    repo.checkInOneFile("filename.txt", material1);
    repo.checkInOneFile("filename2.txt", material2);

    MaterialRevisions materialRevisions =
        materials.latestModification(pipelineDir, new TestSubprocessExecutionContext());

    assertThat(materialRevisions.getRevisions().size(), is(2));
    assertThat(materialRevisions, containsModifiedFile("/trunk/part1/filename.txt"));
    assertThat(materialRevisions, containsModifiedFile("/trunk/part2/filename2.txt"));
  }
  @Test
  public void shouldDetectLatestModifications() throws Exception {

    SvnMaterial svnMaterial1 = repo.createMaterial("multiple-materials/trunk/part1", "part1");
    SvnMaterial svnMaterial2 = repo.createMaterial("multiple-materials/trunk/part2", "part2");
    Materials materials = new Materials(svnMaterial1, svnMaterial2);

    MaterialRevisions materialRevisions =
        materials.latestModification(pipelineDir, new TestSubprocessExecutionContext());

    MaterialRevision revision1 = materialRevisions.getMaterialRevision(0);
    assertThat(
        revision1.getRevision(),
        is(latestRevision(svnMaterial1, pipelineDir, new TestSubprocessExecutionContext())));

    MaterialRevision revision2 = materialRevisions.getMaterialRevision(1);
    assertThat(
        revision2.getRevision(),
        is(latestRevision(svnMaterial2, pipelineDir, new TestSubprocessExecutionContext())));
  }
  @Test
  public void shouldLoadPipelineAlongwithBuildCauseHavingMaterialPasswordsPopulated() {
    PipelineConfig pipelineConfig =
        PipelineConfigMother.pipelineConfig(
            "last",
            new StageConfig(
                new CaseInsensitiveString("stage"), new JobConfigs(new JobConfig("job-one"))));
    pipelineConfig.materialConfigs().clear();
    SvnMaterial onDirOne =
        MaterialsMother.svnMaterial("google.com", "dirOne", "loser", "boozer", false, "**/*.html");
    P4Material onDirTwo =
        MaterialsMother.p4Material(
            "host:987654321", "zoozer", "secret", "through-the-window", true);
    onDirTwo.setFolder("dirTwo");
    pipelineConfig.addMaterialConfig(onDirOne.config());
    pipelineConfig.addMaterialConfig(onDirTwo.config());

    configHelper.addPipeline(pipelineConfig);

    Pipeline building = PipelineMother.building(pipelineConfig);
    Pipeline pipeline = dbHelper.savePipelineWithMaterials(building);

    final long jobId = pipeline.getStages().get(0).getJobInstances().get(0).getId();
    Pipeline loadedPipeline =
        (Pipeline)
            transactionTemplate.execute(
                new TransactionCallback() {
                  public Object doInTransaction(TransactionStatus status) {
                    return loader.pipelineWithPasswordAwareBuildCauseByBuildId(jobId);
                  }
                });

    MaterialRevisions revisions = loadedPipeline.getBuildCause().getMaterialRevisions();
    assertThat(
        ((SvnMaterial) revisions.findRevisionFor(onDirOne).getMaterial()).getPassword(),
        is("boozer"));
    assertThat(
        ((P4Material) revisions.findRevisionFor(onDirTwo).getMaterial()).getPassword(),
        is("secret"));
  }
  @Test
  public void shouldLoadShallowCloneFlagForGitMaterialsBaseOnTheirOwnPipelineConfig()
      throws IOException {
    GitTestRepo testRepo = new GitTestRepo();

    PipelineConfig shallowPipeline =
        PipelineConfigMother.pipelineConfig(
            "shallowPipeline",
            new StageConfig(
                new CaseInsensitiveString("stage"), new JobConfigs(new JobConfig("job-one"))));
    shallowPipeline.materialConfigs().clear();
    shallowPipeline.addMaterialConfig(
        new GitMaterialConfig(testRepo.projectRepositoryUrl(), null, true));
    configHelper.addPipeline(shallowPipeline);

    PipelineConfig fullPipeline =
        PipelineConfigMother.pipelineConfig(
            "fullPipeline",
            new StageConfig(
                new CaseInsensitiveString("stage"), new JobConfigs(new JobConfig("job-one"))));
    fullPipeline.materialConfigs().clear();
    fullPipeline.addMaterialConfig(
        new GitMaterialConfig(testRepo.projectRepositoryUrl(), null, false));
    configHelper.addPipeline(fullPipeline);

    Pipeline shallowPipelineInstance = createAndLoadModifyOneFilePipeline(shallowPipeline);
    MaterialRevisions shallowRevisions =
        shallowPipelineInstance.getBuildCause().getMaterialRevisions();
    assertThat(
        ((GitMaterial) shallowRevisions.getRevisions().get(0).getMaterial()).isShallowClone(),
        is(true));

    Pipeline fullPipelineInstance = createAndLoadModifyOneFilePipeline(fullPipeline);
    MaterialRevisions fullRevisions = fullPipelineInstance.getBuildCause().getMaterialRevisions();
    assertThat(
        ((GitMaterial) fullRevisions.getRevisions().get(0).getMaterial()).isShallowClone(),
        is(false));
  }
  @Test // if other materials have expansion concept at some point, add more tests here
  public void shouldSetPasswordForExpandedSvnMaterial() {
    PipelineConfig pipelineConfig =
        PipelineConfigMother.pipelineConfig(
            "last",
            new StageConfig(
                new CaseInsensitiveString("stage"), new JobConfigs(new JobConfig("job-one"))));
    pipelineConfig.materialConfigs().clear();
    SvnMaterialConfig materialConfig = svnRepo.materialConfig();
    materialConfig.setConfigAttributes(
        Collections.singletonMap(SvnMaterialConfig.CHECK_EXTERNALS, String.valueOf(true)));
    materialConfig.setPassword("boozer");
    pipelineConfig.addMaterialConfig(materialConfig);
    configHelper.addPipeline(pipelineConfig);

    Pipeline loadedPipeline = createAndLoadModifyOneFilePipeline(pipelineConfig);

    MaterialRevisions revisions = loadedPipeline.getBuildCause().getMaterialRevisions();
    assertThat(revisions.getRevisions().size(), is(2));
    assertThat(
        ((SvnMaterial) revisions.getRevisions().get(0).getMaterial()).getPassword(), is("boozer"));
    assertThat(
        ((SvnMaterial) revisions.getRevisions().get(1).getMaterial()).getPassword(), is("boozer"));
  }
 private MaterialRevisions runAndPassWith(
     SvnMaterial svn,
     String checkinFile,
     MaterialRevisions revsAfterFoo,
     final SvnTestRepo svnRepository)
     throws Exception {
   MaterialRevisions newRevs = checkinFile(svn, checkinFile, svnRepository);
   if (revsAfterFoo != null) {
     for (MaterialRevision newRev : newRevs) {
       newRev.addModifications(revsAfterFoo.getModifications(newRev.getMaterial()));
     }
   }
   runAndPass(newRevs);
   return newRevs;
 }
 public void addNewMaterialWithModifications(Material material, File folder) {
   MaterialRevisions materialRevisions = materialRepository.findLatestModification(material);
   Modifications list = materialRevisions.getModifications(material);
   insertLatestOrNewModifications(
       material, materialRepository.findOrCreateFrom(material), folder, list);
 }