@Test
  public void shouldBeAbleToSerializeAndDeserializeBuildWork() throws Exception {
    Pipeline pipeline1 =
        instanceFactory.createPipelineInstance(
            evolveConfig,
            modifySomeFiles(evolveConfig),
            new DefaultSchedulingContext(DEFAULT_APPROVED_BY),
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(pipeline1);

    buildAssignmentService.onTimer();
    BuildWork work =
        (BuildWork) buildAssignmentService.assignWorkToAgent(agent(AgentMother.localAgent()));

    BuildWork deserialized = (BuildWork) SerializationTester.serializeAndDeserialize(work);

    assertThat(
        deserialized.getAssignment().materialRevisions(),
        is(work.getAssignment().materialRevisions()));

    assertThat(deserialized.getAssignment(), is(work.getAssignment()));
    assertThat(deserialized, is(work));
  }
  @Test
  public void shouldCreateWorkWithFetchMaterialsFlagFromStageConfig() throws Exception {
    evolveConfig.getFirstStageConfig().setFetchMaterials(true);
    Pipeline pipeline1 =
        instanceFactory.createPipelineInstance(
            evolveConfig,
            modifySomeFiles(evolveConfig),
            new DefaultSchedulingContext(DEFAULT_APPROVED_BY),
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(pipeline1);

    buildAssignmentService.onTimer();
    BuildWork work =
        (BuildWork) buildAssignmentService.assignWorkToAgent(agent(AgentMother.localAgent()));

    assertThat(
        "should have set fetchMaterials on assignment",
        work.getAssignment().getPlan().shouldFetchMaterials(),
        is(true));
  }
  /**
   * (uppest/2/uppest-stage/1) |------------------> upper-peer ------- |
   * ...................................|............................................... | . | . [
   * uppest-stage ............................|...................... {bar.zip
   * uppest/upper-peer/downer} V . uppest uppest-stage-2 ------> upper ------> downer ------>
   * downest {foo.zip uppest/upper/downer} (uppest/1/uppest-stage-2/1) uppest-stage-3 ]
   *
   * <p>.... :: fetch artifact call ---> :: material dependency
   */
  @Test
  public void shouldCreateWork_withAncestorFetchArtifactCalls_resolvedToRelevantStage()
      throws Exception {
    configHelper.addPipeline("uppest", "uppest-stage");
    configHelper.addStageToPipeline("uppest", "uppest-stage-2");
    PipelineConfig uppest = configHelper.addStageToPipeline("uppest", "uppest-stage-3");

    configHelper.addPipeline("upper", "upper-stage");
    DependencyMaterial upper_sMaterial =
        new DependencyMaterial(
            new CaseInsensitiveString("uppest"), new CaseInsensitiveString("uppest-stage-2"));
    PipelineConfig upper =
        configHelper.setMaterialConfigForPipeline("upper", upper_sMaterial.config());

    configHelper.addPipeline("upper-peer", "upper-peer-stage");
    DependencyMaterial upperPeer_sMaterial =
        new DependencyMaterial(
            new CaseInsensitiveString("uppest"), new CaseInsensitiveString("uppest-stage"));
    PipelineConfig upperPeer =
        configHelper.setMaterialConfigForPipeline("upper-peer", upperPeer_sMaterial.config());

    configHelper.addPipeline("downer", "downer-stage");
    DependencyMaterial downer_sUpperMaterial =
        new DependencyMaterial(
            new CaseInsensitiveString("upper"), new CaseInsensitiveString("upper-stage"));
    configHelper.setMaterialConfigForPipeline("downer", downer_sUpperMaterial.config());
    DependencyMaterial downer_sUpperPeerMaterial =
        new DependencyMaterial(
            new CaseInsensitiveString("upper-peer"), new CaseInsensitiveString("upper-peer-stage"));
    PipelineConfig downer =
        configHelper.addMaterialToPipeline("downer", downer_sUpperPeerMaterial.config());

    configHelper.addPipeline("downest", "downest-stage");
    DependencyMaterial downest_sMaterial =
        new DependencyMaterial(
            new CaseInsensitiveString("downer"), new CaseInsensitiveString("downer-stage"));
    configHelper.setMaterialConfigForPipeline("downest", downest_sMaterial.config());
    Tasks allFetchTasks = new Tasks();
    allFetchTasks.add(
        new FetchTask(
            new CaseInsensitiveString("uppest/upper/downer"),
            new CaseInsensitiveString("uppest-stage"),
            new CaseInsensitiveString("unit"),
            "foo.zip",
            "bar"));
    allFetchTasks.add(
        new FetchTask(
            new CaseInsensitiveString("uppest/upper-peer/downer"),
            new CaseInsensitiveString("uppest-stage"),
            new CaseInsensitiveString("unit"),
            "bar.zip",
            "baz"));
    configHelper.replaceAllJobsInStage(
        "downest",
        "downest-stage",
        new JobConfig(
            new CaseInsensitiveString("fetcher"),
            new Resources("fetcher"),
            new ArtifactPlans(),
            allFetchTasks));
    PipelineConfig downest =
        goConfigService
            .getCurrentConfig()
            .pipelineConfigByName(new CaseInsensitiveString("downest"));

    DefaultSchedulingContext defaultSchedulingCtx =
        new DefaultSchedulingContext(DEFAULT_APPROVED_BY);
    Pipeline uppestInstanceForUpper =
        instanceFactory.createPipelineInstance(
            uppest, modifySomeFiles(uppest), defaultSchedulingCtx, md5, new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(uppestInstanceForUpper);
    dbHelper.passStage(uppestInstanceForUpper.findStage("uppest-stage"));
    Stage upper_sMaterialStage =
        dbHelper.scheduleStage(
            uppestInstanceForUpper, uppest.getStage(new CaseInsensitiveString("uppest-stage-2")));
    dbHelper.passStage(upper_sMaterialStage);

    Pipeline uppestInstanceForUpperPeer =
        instanceFactory.createPipelineInstance(
            uppest,
            modifySomeFiles(uppest),
            new DefaultSchedulingContext("super-hero"),
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(uppestInstanceForUpperPeer);
    Stage upperPeer_sMaterialStage = uppestInstanceForUpperPeer.findStage("uppest-stage");
    dbHelper.passStage(upperPeer_sMaterialStage);

    Pipeline upperInstance =
        instanceFactory.createPipelineInstance(
            upper,
            buildCauseForDependency(upper_sMaterial, upper_sMaterialStage),
            defaultSchedulingCtx,
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(upperInstance);
    Stage downer_sUpperMaterialStage = upperInstance.findStage("upper-stage");
    dbHelper.passStage(downer_sUpperMaterialStage);

    Pipeline upperPeerInstance =
        instanceFactory.createPipelineInstance(
            upperPeer,
            buildCauseForDependency(upperPeer_sMaterial, upperPeer_sMaterialStage),
            defaultSchedulingCtx,
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(upperPeerInstance);
    Stage downer_sUpperPeerMaterialStage = upperPeerInstance.findStage("upper-peer-stage");
    dbHelper.passStage(downer_sUpperPeerMaterialStage);

    MaterialRevisions downer_sMaterialRevisions =
        new MaterialRevisions(
            materialRevisionForDownstream(downer_sUpperMaterial, downer_sUpperMaterialStage),
            materialRevisionForDownstream(
                downer_sUpperPeerMaterial, downer_sUpperPeerMaterialStage));

    Pipeline downerInstance =
        instanceFactory.createPipelineInstance(
            downer,
            BuildCause.createManualForced(downer_sMaterialRevisions, loserUser),
            defaultSchedulingCtx,
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(downerInstance);
    Stage downest_sMaterialStage = downerInstance.findStage("downer-stage");
    dbHelper.passStage(downest_sMaterialStage);

    Pipeline downestInstance =
        instanceFactory.createPipelineInstance(
            downest,
            buildCauseForDependency(downest_sMaterial, downest_sMaterialStage),
            defaultSchedulingCtx,
            md5,
            new TimeProvider());
    dbHelper.savePipelineWithStagesAndMaterials(downestInstance);

    buildAssignmentService.onTimer();
    AgentConfig agentConfig = AgentMother.localAgent();
    agentConfig.addResource(new Resource("fetcher"));
    BuildWork work = (BuildWork) buildAssignmentService.assignWorkToAgent(agent(agentConfig));

    List<Builder> builders = work.getAssignment().getBuilders();
    FetchArtifactBuilder fooZipFetch = (FetchArtifactBuilder) builders.get(0);
    assertThat(fooZipFetch.artifactLocator(), is("uppest/1/uppest-stage/latest/unit/foo.zip"));
    FetchArtifactBuilder barZipFetch = (FetchArtifactBuilder) builders.get(1);
    assertThat(barZipFetch.artifactLocator(), is("uppest/2/uppest-stage/1/unit/bar.zip"));
  }