com.thoughtworks.go.agent.UrlBasedArtifactsRepositoryTest.java Source code

Java tutorial

Introduction

Here is the source code for com.thoughtworks.go.agent.UrlBasedArtifactsRepositoryTest.java

Source

/*************************** GO-LICENSE-START*********************************
 * Copyright 2016 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.
 * ************************GO-LICENSE-END***********************************/
package com.thoughtworks.go.agent;

import com.thoughtworks.go.buildsession.ArtifactsRepository;
import com.thoughtworks.go.domain.Property;
import com.thoughtworks.go.helper.TestStreamConsumer;
import com.thoughtworks.go.util.CachedDigestUtils;
import com.thoughtworks.go.util.FileUtil;
import com.thoughtworks.go.util.HttpService;
import com.thoughtworks.go.util.TestFileUtil;
import com.thoughtworks.go.util.ZipUtil;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Properties;

import static com.thoughtworks.go.matchers.ConsoleOutMatcher.printedUploadingFailure;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class UrlBasedArtifactsRepositoryTest {

    @Mock
    private HttpService httpService;
    private File tempFile;
    private File artifactFolder;
    private ArtifactsRepository artifactsRepository;
    private TestStreamConsumer console;

    @Before
    public void setUp() throws Exception {
        artifactFolder = TestFileUtil.createTempFolder("artifact_folder");
        tempFile = TestFileUtil.createTestFile(artifactFolder, "file.txt");
        console = new TestStreamConsumer();
        artifactsRepository = new UrlBasedArtifactsRepository(httpService, "http://baseurl/artifacts/",
                "http://baseurl/properties/", new ZipUtil());
    }

    @After
    public void tearDown() throws IOException {
        FileUtil.tryDeleting(artifactFolder);
    }

    @Test
    public void shouldBombWithErrorWhenStatusCodeReturnedIsRequestEntityTooLarge()
            throws IOException, InterruptedException {
        long size = anyLong();
        when(httpService.upload(any(String.class), size, any(File.class), any(Properties.class)))
                .thenReturn(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);

        try {
            artifactsRepository.upload(console, tempFile, "some_dest", "build42");
            fail("should have thrown request entity too large error");
        } catch (RuntimeException e) {
            String expectedMessage = "Artifact upload for file " + tempFile.getAbsolutePath() + " (Size: " + size
                    + ") was denied by the server. This usually happens when server runs out of disk space.";
            assertThat(e.getMessage(),
                    is("java.lang.RuntimeException: " + expectedMessage + ".  HTTP return code is 413"));
            assertThat(console.output().contains(expectedMessage), is(true));
        }
    }

    @Test
    public void uploadShouldBeGivenFileSize() throws IOException {
        when(httpService.upload(any(String.class), eq(tempFile.length()), any(File.class), any(Properties.class)))
                .thenReturn(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
        try {
            artifactsRepository.upload(console, tempFile, "dest", "build42");
            fail("should have thrown request entity too large error");
        } catch (RuntimeException e) {
            verify(httpService).upload(eq("http://baseurl/artifacts/dest?attempt=1&buildId=build42"),
                    eq(tempFile.length()), any(File.class), any(Properties.class));
        }
    }

    @Test
    public void shouldRetryUponUploadFailure() throws IOException {
        String data = "Some text whose checksum can be asserted";
        final String md5 = CachedDigestUtils.md5Hex(data);
        FileUtils.writeStringToFile(tempFile, data);
        Properties properties = new Properties();
        properties.setProperty("dest/path/file.txt", md5);

        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=1&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties)))
                        .thenReturn(HttpServletResponse.SC_BAD_GATEWAY);
        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=2&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties)))
                        .thenReturn(HttpServletResponse.SC_BAD_GATEWAY);
        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=3&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties))).thenReturn(HttpServletResponse.SC_OK);
        artifactsRepository.upload(console, tempFile, "dest/path", "build42");
    }

    @Test
    public void shouldPrintFailureMessageToConsoleWhenUploadFailed() throws IOException {
        String data = "Some text whose checksum can be asserted";
        final String md5 = CachedDigestUtils.md5Hex(data);
        FileUtils.writeStringToFile(tempFile, data);
        Properties properties = new Properties();
        properties.setProperty("dest/path/file.txt", md5);

        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=1&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties)))
                        .thenReturn(HttpServletResponse.SC_BAD_GATEWAY);
        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=2&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties)))
                        .thenReturn(HttpServletResponse.SC_BAD_GATEWAY);
        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=3&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties)))
                        .thenReturn(HttpServletResponse.SC_BAD_GATEWAY);

        try {
            artifactsRepository.upload(console, tempFile, "dest/path", "build42");
            fail("should have thrown request entity too large error");
        } catch (RuntimeException e) {
            assertThat(console.output(), printedUploadingFailure(tempFile));
        }
    }

    @Test
    public void shouldUploadArtifactChecksumAlongWithArtifact() throws IOException {
        String data = "Some text whose checksum can be asserted";
        final String md5 = CachedDigestUtils.md5Hex(data);
        FileUtils.writeStringToFile(tempFile, data);
        Properties properties = new Properties();
        properties.setProperty("dest/path/file.txt", md5);

        when(httpService.upload(eq("http://baseurl/artifacts/dest/path?attempt=1&buildId=build42"),
                eq(tempFile.length()), any(File.class), eq(properties))).thenReturn(HttpServletResponse.SC_OK);

        artifactsRepository.upload(console, tempFile, "dest/path", "build42");
    }

    @Test
    public void shouldUploadArtifactChecksumWithRightPathWhenArtifactDestinationPathIsEmpty() throws IOException {
        String data = "Some text whose checksum can be asserted";
        final String md5 = CachedDigestUtils.md5Hex(data);
        FileUtils.writeStringToFile(tempFile, data);
        Properties properties = new Properties();
        properties.setProperty("file.txt", md5);

        when(httpService.upload(eq("http://baseurl/artifacts/?attempt=1&buildId=build42"), eq(tempFile.length()),
                any(File.class), eq(properties))).thenReturn(HttpServletResponse.SC_OK);

        artifactsRepository.upload(console, tempFile, "", "build42");
    }

    @Test
    public void shouldUploadArtifactChecksumForADirectory() throws IOException {
        String data = "Some text whose checksum can be asserted";
        String secondData = "some more";

        FileUtils.writeStringToFile(tempFile, data);

        File anotherFile = new File(artifactFolder, "bond/james_bond/another_file");
        FileUtils.writeStringToFile(anotherFile, secondData);

        when(httpService.upload(eq("http://baseurl/artifacts/dest?attempt=1&buildId=build42"),
                eq(FileUtils.sizeOfDirectory(artifactFolder)), any(File.class),
                eq(expectedProperties(data, secondData)))).thenReturn(HttpServletResponse.SC_OK);
        artifactsRepository.upload(console, artifactFolder, "dest", "build42");
    }

    @Test
    public void setRemoteBuildPropertyShouldEncodePropertyName() throws IOException {
        ArgumentCaptor<String> url = ArgumentCaptor.forClass(String.class);
        ArgumentCaptor<String> value = ArgumentCaptor.forClass(String.class);

        artifactsRepository.setProperty(new Property("fo,o", "bar"));
        verify(httpService).postProperty(url.capture(), value.capture());
        assertThat(value.getValue(), is("bar"));
        assertThat(url.getValue(), is("http://baseurl/properties/fo%2Co"));
    }

    private Properties expectedProperties(String data, String secondData) {
        Properties properties = new Properties();
        properties.setProperty("dest/artifact_folder/file.txt", CachedDigestUtils.md5Hex(data));
        properties.setProperty("dest/artifact_folder/bond/james_bond/another_file",
                CachedDigestUtils.md5Hex(secondData));
        return properties;
    }

}