/* * Copyright 2017 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.remote.work; import com.thoughtworks.go.agent.testhelpers.FakeBuildRepositoryRemote; import com.thoughtworks.go.config.*; import com.thoughtworks.go.config.materials.svn.SvnMaterial; import com.thoughtworks.go.domain.*; import com.thoughtworks.go.domain.buildcause.BuildCause; import com.thoughtworks.go.domain.builder.Builder; import com.thoughtworks.go.domain.builder.NullBuilder; import com.thoughtworks.go.domain.materials.svn.SvnCommand; import com.thoughtworks.go.helper.ModificationsMother; import com.thoughtworks.go.helper.PipelineConfigMother; import com.thoughtworks.go.helper.TestRepo; import com.thoughtworks.go.matchers.UploadEntry; import com.thoughtworks.go.plugin.access.packagematerial.PackageRepositoryExtension; import com.thoughtworks.go.plugin.access.pluggabletask.TaskExtension; import com.thoughtworks.go.plugin.access.scm.SCMExtension; import com.thoughtworks.go.remote.AgentIdentifier; import com.thoughtworks.go.server.service.AgentRuntimeInfo; import com.thoughtworks.go.util.FileUtil; import com.thoughtworks.go.util.SystemEnvironment; import com.thoughtworks.go.util.URLService; import com.thoughtworks.go.util.ZipUtil; import com.thoughtworks.go.util.command.CruiseControlException; import com.thoughtworks.go.util.command.EnvironmentVariableContext; import com.thoughtworks.go.utils.SvnRepoFixture; import com.thoughtworks.go.work.DefaultGoPublisher; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import static com.thoughtworks.go.matchers.ConsoleOutMatcher.*; import static com.thoughtworks.go.util.SystemUtil.currentWorkingDirectory; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNot.not; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; import static org.mockito.MockitoAnnotations.initMocks; public class BuildWorkArtifactUploadingTest { private static final String JOB_NAME = "one"; private static final String STAGE_NAME = "first"; private static final String PIPELINE_NAME = "cruise"; private static final String AGENT_UUID = "uuid"; private EnvironmentVariableContext environmentVariableContext; private SvnMaterial svnMaterial; private SvnRepoFixture svnRepoFixture; File buildWorkingDirectory; @Mock private PackageRepositoryExtension packageRepositoryExtension; @Mock private SCMExtension scmExtension; @Mock private TaskExtension taskExtension; @Before public void setUp() throws IOException { initMocks(this); buildWorkingDirectory = new File("tmp" + UUID.randomUUID()); environmentVariableContext = new EnvironmentVariableContext(); svnRepoFixture = new SvnRepoFixture("../common/test-resources/unit/data/svnrepo"); svnRepoFixture.createRepository(); SvnCommand command = new SvnCommand(null, svnRepoFixture.getEnd2EndRepoUrl()); PipelineConfigMother.createPipelineConfig(PIPELINE_NAME, STAGE_NAME, JOB_NAME); svnMaterial = SvnMaterial.createSvnMaterialWithMock(command); new SystemEnvironment().setProperty("serviceUrl", "some_random_place"); } @After public void teardown() throws Exception { TestRepo.internalTearDown(); FileUtil.deleteFolder(buildWorkingDirectory); new SystemEnvironment().clearProperty("serviceUrl"); } @Test public void shouldUploadEachMatchedFile() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("**/*.png", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic/fail.png", "logs/pic/pass.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/pass.png"), "mypic/logs/pic")); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/fail.png"), "mypic/logs/pic")); } @Test public void shouldUploadMatchedFolder() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("**/*", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic/fail.png", "logs/pic/pass.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/fail.png"), "mypic/logs/pic"))); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/pass.png"), "mypic/logs/pic"))); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic"), "mypic/logs")); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/README"), "mypic")); } @Test public void shouldNotUploadFileContainingFolderAgain() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("logs/pic/*.png", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic/fail.png", "logs/pic/pass.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/pass.png"), "mypic")); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic/fail.png"), "mypic")); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic"), "mypic"))); } @Test public void shouldUploadFolderWhenMatchedWithWildCards() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("logs/pic-*", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic-1/fail.png", "logs/pic-1/pass.png", "logs/pic-2/cancel.png", "logs/pic-2/complete.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-1/pass.png"), "mypic"))); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-1/fail.png"), "mypic"))); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-2/cancel.png"), "mypic"))); assertThat(entries, not(uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-2/complete.png"), "mypic"))); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-1"), "mypic")); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-2"), "mypic")); } @Test public void shouldUploadFolderWhenDirectMatch() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("logs/pic-1", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic-1/fail.png", "logs/pic-1/pass.png", "logs/pic-2/cancel.png", "logs/pic-2/complete.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-1"), "mypic")); } @Test public void shouldUploadFolderWhenTrimedPathDirectMatch() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("logs/pic-1 ", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic-1/fail.png", "logs/pic-1/pass.png", "logs/pic-2/cancel.png", "logs/pic-2/complete.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries, uploadFileToDestination(new File(buildWorkingDirectory.getPath()+ "/logs/pic-1"), "mypic")); } @Test public void shouldFailBuildWhenNothingMatched() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("logs/picture", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic-1/fail.png", "logs/pic-1/pass.png", "logs/pic-2/cancel.png", "logs/pic-2/complete.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); BuildRepositoryRemoteStub repository = new BuildRepositoryRemoteStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, repository, manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries.size(), is(0)); assertThat(repository.states, containsResult(JobState.Building)); assertThat(repository.states, containsResult(JobState.Completing)); assertThat(repository.results, containsResult(JobResult.Failed)); assertThat(manipulator.consoleOut(), printedRuleDoesNotMatchFailure(buildWorkingDirectory.getPath(), "logs/picture")); } @Test public void shouldFailBuildWhenSourceDirectoryDoesNotExist() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("not-Exist-Folder", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic-1/fail.png", "logs/pic-1/pass.png", "logs/pic-2/cancel.png", "logs/pic-2/complete.png", "README"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); BuildRepositoryRemoteStub repository = new BuildRepositoryRemoteStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, repository, manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries.size(), is(0)); assertThat(repository.states, containsResult(JobState.Building)); assertThat(repository.states, containsResult(JobState.Completing)); assertThat(repository.results, containsResult(JobResult.Failed)); assertThat(manipulator.consoleOut(), printedRuleDoesNotMatchFailure(buildWorkingDirectory.getPath(), "not-Exist-Folder")); } @Test public void shouldFailBuildWhenNothingMatchedUsingMatcherStartDotStart() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("target/pkg/*.*", "MYDEST")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"target/pkg/"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(); BuildRepositoryRemoteStub repository = new BuildRepositoryRemoteStub(); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, repository, manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries.size(), is(0)); assertThat(repository.states, containsResult(JobState.Building)); assertThat(repository.states, containsResult(JobState.Completing)); assertThat(repository.results, containsResult(JobResult.Failed)); assertThat(manipulator.consoleOut(), printedRuleDoesNotMatchFailure(buildWorkingDirectory.getPath(), "target/pkg/*.*")); } @Test public void shouldReportUploadFailuresWhenTheyHappen() throws Exception { ArtifactPlans artifactPlans = new ArtifactPlans(); artifactPlans.add(new ArtifactPlan("**/*.png", "mypic")); BuildAssignment buildAssigment = createAssignment(artifactPlans, new String[]{"logs/pic/pass.png", "logs/pic-1/pass.png"}); BuildWork work = new BuildWork(buildAssigment); GoArtifactsManipulatorStub manipulator = new GoArtifactsManipulatorStub(new ArrayList<>(), new ArrayList<>(), new HttpServiceStub(), new URLService(), new ZipUtilThatRunsOutOfMemory()); AgentIdentifier agentIdentifier = new AgentIdentifier("somename", "127.0.0.1", AGENT_UUID); work.doWork(agentIdentifier, new FakeBuildRepositoryRemote(), manipulator, environmentVariableContext, new AgentRuntimeInfo(agentIdentifier, AgentRuntimeStatus.Idle, currentWorkingDirectory(), "cookie", false), packageRepositoryExtension, scmExtension, taskExtension); List<UploadEntry> entries = manipulator.uploadEntries(); assertThat(entries.isEmpty(), is(true)); assertThat(manipulator.consoleOut(), containsString("Failed to upload [**/*.png]")); } private class ZipUtilThatRunsOutOfMemory extends ZipUtil { public File zip(File source, File destFile, int level) { throw new OutOfMemoryError("#2824"); } } private BuildAssignment createAssignment(ArtifactPlans artifactPlans, String[] fileToCreate) { MaterialRevisions materialRevisions = materialRevisions(); BuildCause buildCause = BuildCause.createWithModifications(materialRevisions, ""); List<Builder> builders = new ArrayList<>(); builders.add(new CreateFileBuilder(fileToCreate)); DefaultJobPlan plan = new DefaultJobPlan(new Resources(), artifactPlans, new ArtifactPropertiesGenerators(), -1, new JobIdentifier(PIPELINE_NAME, -2, "1", STAGE_NAME, "1", JOB_NAME), null, new EnvironmentVariablesConfig(), new EnvironmentVariablesConfig(), null); return BuildAssignment.create(plan, buildCause, builders, buildWorkingDirectory); } private MaterialRevisions materialRevisions() { MaterialRevision svnRevision = new MaterialRevision(this.svnMaterial, ModificationsMother.oneModifiedFile( svnRepoFixture.getHeadRevision(svnRepoFixture.getEnd2EndRepoUrl()))); return new MaterialRevisions(svnRevision); } public class CreateFileBuilder extends Builder { private final String[] files; public CreateFileBuilder(String[] files) { super(new RunIfConfigs(), new NullBuilder(), ""); this.files = files; } public void build(BuildLogElement buildLogElement, DefaultGoPublisher publisher, EnvironmentVariableContext environmentVariableContext, TaskExtension taskExtension) throws CruiseControlException { try { FileUtil.createFilesByPath(buildWorkingDirectory, files); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } } }