com.thoughtworks.go.server.service.ScheduleTestUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.server.service.ScheduleTestUtil.java

Source

/*
 * Copyright 2019 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.thoughtworks.go.server.service;

import com.thoughtworks.go.config.CaseInsensitiveString;
import com.thoughtworks.go.config.PipelineConfig;
import com.thoughtworks.go.config.StageConfig;
import com.thoughtworks.go.config.TimerConfig;
import com.thoughtworks.go.config.materials.MaterialConfigs;
import com.thoughtworks.go.config.materials.PackageMaterialConfig;
import com.thoughtworks.go.config.materials.ScmMaterial;
import com.thoughtworks.go.config.materials.dependency.DependencyMaterial;
import com.thoughtworks.go.domain.*;
import com.thoughtworks.go.domain.buildcause.BuildCause;
import com.thoughtworks.go.domain.materials.Material;
import com.thoughtworks.go.domain.materials.MaterialConfig;
import com.thoughtworks.go.domain.materials.Modification;
import com.thoughtworks.go.domain.materials.ModifiedAction;
import com.thoughtworks.go.domain.scm.SCM;
import com.thoughtworks.go.helper.PipelineConfigMother;
import com.thoughtworks.go.helper.StageConfigMother;
import com.thoughtworks.go.server.dao.DatabaseAccessHelper;
import com.thoughtworks.go.server.persistence.MaterialRepository;
import com.thoughtworks.go.server.transaction.TransactionTemplate;
import com.thoughtworks.go.util.GoConfigFileHelper;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.joda.time.DateTime;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;

import java.io.File;
import java.sql.SQLException;
import java.util.*;

import static com.thoughtworks.go.domain.config.CaseInsensitiveStringMother.str;
import static com.thoughtworks.go.util.DataStructureUtils.a;

public class ScheduleTestUtil {

    public static final String DEFAULT_GROUP = "test-group";
    private final TransactionTemplate transactionTemplate;
    private final MaterialRepository materialRepository;
    private final DatabaseAccessHelper dbHelper;
    private final GoConfigFileHelper configHelper;
    private Date date;
    private Map<CaseInsensitiveString, Pipeline> triggeredPipelines;

    public ScheduleTestUtil(TransactionTemplate transactionTemplate, MaterialRepository materialRepository,
            DatabaseAccessHelper dbHelper, GoConfigFileHelper configHelper) {
        this.transactionTemplate = transactionTemplate;
        this.materialRepository = materialRepository;
        this.dbHelper = dbHelper;
        this.configHelper = configHelper;
        date = new Date();
        triggeredPipelines = new HashMap<>();
    }

    public Date d(int extraHours) {
        return new DateTime(date.getTime()).plusHours(extraHours).toDate();
    }

    private Material mw(Material material) {
        material = AutoTriggerDependencyResolutionTest.CLONER.deepClone(material);
        return material;
    }

    public Material mw(AddedPipeline pipeline) {
        return mw(pipeline.material);
    }

    public MaterialRevision mr(Material material, final boolean changed, final String... revs) {
        ArrayList<Modification> modifications = new ArrayList<>();
        for (String rev : revs) {
            Modification mod = modForRev(rev);
            modifications.add(0, mod);
        }
        MaterialRevision materialRevision = new MaterialRevision(material, modifications);
        if (changed) {
            materialRevision.markAsChanged();
        }
        return materialRevision;
    }

    public MaterialRevision mr(AddedPipeline pipeline, final boolean changed, final String endRev) {
        return mr(pipeline.material, changed, endRev);
    }

    public String runAndPassWithGivenMDUTimestampAndRevisionObjects(final AddedPipeline pipeline, final Date mduAt,
            final RevisionsForMaterial... revisions) {
        final Pipeline instance = scheduleWith(pipeline, revisions);
        return pass(pipeline, mduAt, instance);
    }

    public String runAndPass(final AddedPipeline pipeline, String... revisions) {
        return runAndPassWithGivenMDUTimestampAndRevisionStrings(pipeline, date, revisions);
    }

    public String runAndPassWithGivenMDUTimestampAndRevisionStrings(final AddedPipeline pipeline, final Date mduAt,
            final String... revisions) {
        final Pipeline instance = scheduleWith(pipeline, revisions);
        return pass(pipeline, mduAt, instance);
    }

    public Pipeline runAndPassAndReturnPipelineInstance(final AddedPipeline pipeline, final Date mduAt,
            final String... revisions) {
        final Pipeline instance = scheduleWith(pipeline, revisions);
        pass(pipeline, mduAt, instance);
        return instance;
    }

    public String runAndFail(final AddedPipeline pipeline, final Date mduAt, final String... revisions) {
        final Pipeline instance = scheduleWith(pipeline, revisions);
        return fail(pipeline, mduAt, instance);
    }

    public String rerunStageAndCancel(Pipeline pipeline, StageConfig stageConfig) {
        Stage stage = dbHelper.scheduleStage(pipeline, stageConfig);
        dbHelper.cancelStage(stage);
        return stage.getIdentifier().getStageLocator();
    }

    private String pass(final AddedPipeline pipeline, final Date mduAt, final Pipeline instance) {
        dbHelper.pass(instance);
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                for (Stage stage : instance.getStages()) {
                    final String dmrRevStr = new StageIdentifier(new PipelineIdentifier(instance.getName(),
                            instance.getCounter(), instance.getName() + instance.getCounter()), stage.getName(),
                            "1").getStageLocator();
                    Modification modification = new Modification(mduAt, dmrRevStr, instance.getLabel(),
                            instance.getId());
                    materialRepository.saveMaterialRevision(new MaterialRevision(pipeline.material, modification));
                }
            }
        });
        return new StageIdentifier(
                new PipelineIdentifier(instance.getName(), instance.getCounter(),
                        instance.getName() + instance.getCounter()),
                pipeline.material.getStageName().toString(), "1").getStageLocator();
    }

    private String fail(final AddedPipeline pipeline, final Date mduAt, final Pipeline instance) {
        dbHelper.failStage(instance.getFirstStage());
        final String dmrRevStr = new StageIdentifier(
                new PipelineIdentifier(instance.getName(), instance.getCounter(),
                        instance.getName() + instance.getCounter()),
                CaseInsensitiveString.str(pipeline.material.getStageName()), "1").getStageLocator();
        //should not add dmr to database because it failed.
        return dmrRevStr;
    }

    public MaterialRevisions mrs(MaterialRevision... revs) {
        MaterialRevisions revisions = new MaterialRevisions();
        for (MaterialRevision rev : revs) {
            revisions.addRevision(rev);
        }
        return revisions;
    }

    public <T extends ScmMaterial> T wf(T material, String folder) {
        material.setFolder(folder);
        return material;
    }

    public TimerConfig timer(String timerSpec, boolean shouldTriggerOnlyOnNewMaterials) {
        return new TimerConfig(timerSpec, shouldTriggerOnlyOnNewMaterials);
    }

    public RevisionsForMaterial[] getRevisionsForMaterials(List<String>... materialRevisions) {
        List<RevisionsForMaterial> revisionsForMaterials = new ArrayList<>();
        for (List<String> materialRevision : materialRevisions) {
            revisionsForMaterials.add(new RevisionsForMaterial(materialRevision));
        }
        return revisionsForMaterials.toArray(new RevisionsForMaterial[revisionsForMaterials.size()]);
    }

    public AddedPipeline renamePipelineAndFirstStage(AddedPipeline pipeline, String newPipelineName,
            String stageName) {
        PipelineConfig oldConfig = pipeline.config;
        configHelper.removePipeline(CaseInsensitiveString.str(oldConfig.name()));
        PipelineConfig newPipeline = PipelineConfigMother.renamePipeline(oldConfig, newPipelineName);
        StageConfigMother.renameStage(newPipeline.get(0), stageName);
        configHelper.addPipeline(newPipeline);
        return new AddedPipeline(newPipeline, pipeline.material);
    }

    protected static class RevisionsForMaterial {

        List<String> revs;

        private RevisionsForMaterial(List<String> revs) {
            this.revs = revs;
        }

        @Override
        public String toString() {
            return "RevisionsForMaterial{" + "revs=" + revs + '}';
        }

    }

    public RevisionsForMaterial[] rs(String... revs) {
        return new RevisionsForMaterial[] { new RevisionsForMaterial(Arrays.asList(revs)) };
    }

    public List<String> revisions(String... revs) {
        return Arrays.asList(revs);
    }

    private Pipeline scheduleWith(AddedPipeline pipeline, RevisionsForMaterial... revisions) {
        Pipeline oldInstance = triggeredPipelines.get(pipeline.config.name());

        Map<Material, List<Modification>> modMap = new HashMap<>();
        Map<Modification, Modification> identityMap = new HashMap<>();

        MaterialRevisions buildCause = new MaterialRevisions();
        int i = 0;
        for (Material material : new MaterialConfigConverter().toMaterials(pipeline.config.materialConfigs())) {
            List<Modification> modifications = new ArrayList<>();
            for (Modification modification : modForRev(revisions[i++])) {
                if (!identityMap.containsKey(modification)) {
                    identityMap.put(modification, modification);
                }
                modifications.add(identityMap.get(modification));
            }
            MaterialInstance modificationsMaterialInstance = modifications.get(0).getMaterialInstance();
            if (modMap.containsKey(material)) {
                modifications = modMap.get(material);
            } else {
                modMap.put(material, modifications);
            }
            MaterialInstance configuredMaterialInstance = materialRepository.findOrCreateFrom(material);
            if (!configuredMaterialInstance.equals(modificationsMaterialInstance)) {
                throw new RuntimeException(
                        "Please fix the revision order to match material configuration order. Revision given for: "
                                + modificationsMaterialInstance + " against configured material: "
                                + configuredMaterialInstance);
            }
            if (oldInstance == null) {
                buildCause.addRevision(new MaterialRevision(material, modifications));
            } else {
                MaterialRevision oldRev = oldInstance.getBuildCause().getMaterialRevisions()
                        .findRevisionFor(material);
                List<Modification> modificationsSince = materialRepository.findModificationsSince(material, oldRev);
                List<Modification> newRange = new ArrayList<>();
                for (Modification newMod : modificationsSince) {
                    newRange.add(0, newMod);
                    if (newMod.equals(modifications)) {
                        break;
                    }
                }
                buildCause.addRevision(new MaterialRevision(material, newRange));
            }
        }

        return dbHelper.schedulePipelineWithAllStages(pipeline.config,
                BuildCause.createWithModifications(buildCause, "loser"));
    }

    private List<Modification> modForRev(final RevisionsForMaterial revision) {
        return (List<Modification>) materialRepository.getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query q = session.createQuery("from Modification where revision in (:in) order by id desc");
                q.setParameterList("in", revision.revs);
                List list = q.list();
                if (list.isEmpty()) {
                    throw new RuntimeException(
                            "you are trying to load revision " + revision + " which doesn't exist");
                }
                return list;
            }
        });
    }

    public Pipeline scheduleWith(AddedPipeline pipeline, String... revisions) {
        RevisionsForMaterial[] revsForMat = new RevisionsForMaterial[revisions.length];
        for (int i = 0; i < revisions.length; i++) {
            revsForMat[i] = rs(revisions[i])[0];
        }
        return scheduleWith(pipeline, revsForMat);
    }

    public String runAndFail(final AddedPipeline pipeline, String... revisions) {
        return runAndFail(pipeline, date, revisions);
    }

    private Modification modForRev(final String revision) {
        return (Modification) materialRepository.getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query q = session.createQuery("from Modification where revision = ?");
                q.setParameter(0, revision);
                List list = q.list();
                if (list.isEmpty()) {
                    throw new RuntimeException(
                            "you are trying to load revision " + revision + " which doesn't exist");
                }
                return list.get(0);
            }
        });
    }

    public static final class AddedPipeline {
        public final PipelineConfig config;
        public final DependencyMaterial material;

        public AddedPipeline(PipelineConfig config, DependencyMaterial material) {
            this.config = config;
            this.material = material;
        }

        public MaterialConfig materialConfig() {
            return material.config();
        }
    }

    public static final class MaterialDeclaration {
        final Material material;
        final String dest;

        private MaterialDeclaration(Material material) {
            this(material, null);
        }

        public MaterialDeclaration(Material material, String dest) {
            this.material = material;
            this.dest = dest;
        }

        public MaterialConfig materialConfig() {
            return material.config();
        }
    }

    public MaterialDeclaration m(Material material, String dest) {
        return new MaterialDeclaration(material, dest);
    }

    public MaterialDeclaration m(Material material) {
        return new MaterialDeclaration(material);
    }

    public MaterialDeclaration m(AddedPipeline pipeline) {
        return m(pipeline.material);
    }

    public MaterialDeclaration m(AddedPipeline pipeline, String materialName) {
        return m(new DependencyMaterial(new CaseInsensitiveString(materialName),
                pipeline.material.getPipelineName(), pipeline.material.getStageName()));
    }

    public AddedPipeline saveConfigWithTimer(String pipelineName, TimerConfig timer,
            MaterialDeclaration... materialDeclaration) {
        String stageName = AutoTriggerDependencyResolutionTest.STAGE_NAME;
        MaterialConfigs materialConfigs = new MaterialConfigs();
        for (MaterialDeclaration mDecl : materialDeclaration) {
            MaterialConfig materialConfig = AutoTriggerDependencyResolutionTest.CLONER
                    .deepClone(mDecl.material.config());
            materialConfigs.add(materialConfig);
        }
        PipelineConfig cfg = configHelper.addPipelineWithGroupAndTimer(DEFAULT_GROUP, pipelineName, materialConfigs,
                stageName, timer, "job1");
        return new AddedPipeline(cfg, new DependencyMaterial(str(pipelineName), str(stageName)));
    }

    public AddedPipeline saveConfigWithGroup(String groupName, String pipelineName,
            MaterialDeclaration... materialDecls) {
        return saveConfigWith(groupName, pipelineName, AutoTriggerDependencyResolutionTest.STAGE_NAME,
                materialDecls);
    }

    public AddedPipeline saveConfigWith(String pipelineName, String stageName,
            MaterialDeclaration... materialDecls) {
        return saveConfigWith(DEFAULT_GROUP, pipelineName, stageName, materialDecls);
    }

    public AddedPipeline saveConfigWith(PipelineConfig pipelineConfig) {
        return new AddedPipeline(configHelper.addPipeline(DEFAULT_GROUP, pipelineConfig), null);
    }

    public AddedPipeline saveConfigWith(String pipelineName, String stageName,
            MaterialDeclaration materialDeclaration, String[] builds) {
        MaterialConfigs materialConfigs = new MaterialConfigs();
        MaterialConfig materialConfig = AutoTriggerDependencyResolutionTest.CLONER
                .deepClone(materialDeclaration.material.config());
        materialConfigs.add(materialConfig);
        PipelineConfig cfg = configHelper.addPipelineWithGroup(DEFAULT_GROUP, pipelineName, materialConfigs,
                stageName, builds);
        return new AddedPipeline(cfg, new DependencyMaterial(str(pipelineName), str(stageName)));
    }

    public void addPackageDefinition(PackageMaterialConfig pkgMaterialConfig) {
        configHelper.addPackageDefinition(pkgMaterialConfig);
    }

    public void addSCMConfig(SCM scmConfig) {
        configHelper.addSCMConfig(scmConfig);
    }

    public AddedPipeline saveConfigWith(String pipelineName, MaterialDeclaration... materialDecls) {
        return saveConfigWith(DEFAULT_GROUP, pipelineName, AutoTriggerDependencyResolutionTest.STAGE_NAME,
                materialDecls);
    }

    private AddedPipeline saveConfigWith(String groupName, String pipelineName, String stageName,
            MaterialDeclaration... materialDecls) {
        MaterialConfigs materialConfigs = new MaterialConfigs();
        for (MaterialDeclaration mDecl : materialDecls) {
            MaterialConfig materialConfig = AutoTriggerDependencyResolutionTest.CLONER
                    .deepClone(mDecl.material.config());
            materialConfigs.add(materialConfig);
        }
        PipelineConfig cfg = configHelper.addPipelineWithGroup(groupName, pipelineName, materialConfigs, stageName,
                "job1");
        return new AddedPipeline(cfg, new DependencyMaterial(str(pipelineName), str(stageName)));
    }

    public AddedPipeline changeStagenameForToPipeline(String pipelineName, String oldStageName,
            String newStageName) {
        PipelineConfig cfg = configHelper.changeStagenameForToPipeline(pipelineName, oldStageName, newStageName);
        return new AddedPipeline(cfg, new DependencyMaterial(str(pipelineName), str(newStageName)));
    }

    public AddedPipeline addStageToPipeline(CaseInsensitiveString pipelineName, String stageName) throws Exception {
        PipelineConfig config = configHelper.addStageToPipeline(pipelineName.toString(), stageName);
        return new AddedPipeline(config,
                new DependencyMaterial(pipelineName, new CaseInsensitiveString(stageName)));
    }

    public AddedPipeline addMaterialToPipeline(AddedPipeline pipeline, MaterialDeclaration mDecl) {
        MaterialConfig materialConfig = AutoTriggerDependencyResolutionTest.CLONER
                .deepClone(mDecl.materialConfig());
        PipelineConfig cfg = configHelper.addMaterialToPipeline(pipeline.config.name().toString(), materialConfig);
        return new AddedPipeline(cfg, pipeline.material);
    }

    public AddedPipeline removeMaterialFromPipeline(AddedPipeline pipeline, MaterialDeclaration mDecl) {
        MaterialConfig materialConfig = AutoTriggerDependencyResolutionTest.CLONER
                .deepClone(mDecl.materialConfig());
        PipelineConfig cfg = configHelper.removeMaterialFromPipeline(pipeline.config.name().toString(),
                materialConfig);
        return new AddedPipeline(cfg, pipeline.material);
    }

    public void checkinInOrder(final Material material, final String... revisions) {
        checkinInOrder(material, date, revisions);
    }

    public void checkinInOrder(final Material material, final Date dateOfCheckin, final String... revisions) {
        transactionTemplate.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                for (int i = 0; i < revisions.length; i++) {
                    String revision = revisions[i];
                    materialRepository.saveMaterialRevision(new MaterialRevision(material,
                            new Modification("loser number " + i, "commit " + i, "e" + i + "@mail",
                                    new DateTime(dateOfCheckin.getTime()).plusHours(i).toDate(), revision)));
                }
                return null;
            }
        });
    }

    public void checkinFile(final Material material, final String revision, final File file,
            final ModifiedAction modifiedAction) {
        checkinFiles(material, revision, a(file), modifiedAction);
    }

    public void checkinFiles(final Material material, final String revision, final List<File> files,
            final ModifiedAction modifiedAction) {
        transactionTemplate.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                Modification modification = new Modification("user", "comment", "a@b.com", date, revision);
                for (File file : files) {
                    modification.createModifiedFile(file.getName(), file.getParent(), modifiedAction);
                }
                materialRepository.saveMaterialRevision(new MaterialRevision(material, modification));
                return null;
            }
        });
    }

    public void checkinFiles(final Material material, final String revision, final List<File> files,
            final ModifiedAction modifiedAction, final Date date) {
        transactionTemplate.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                Modification modification = new Modification("user", "comment", "a@b.com", date, revision);
                for (File file : files) {
                    modification.createModifiedFile(file.getName(), file.getParent(), modifiedAction);
                }
                materialRepository.saveMaterialRevision(new MaterialRevision(material, modification));
                return null;
            }
        });
    }
}