/*
* 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.
*/
package com.thoughtworks.go.agent.launcher;
import com.thoughtworks.go.agent.common.ssl.GoAgentServerHttpClientBuilder;
import com.thoughtworks.go.agent.common.util.Downloader;
import com.thoughtworks.go.agent.testhelper.FakeBootstrapperServer;
import com.thoughtworks.go.mothers.ServerUrlGeneratorMother;
import com.thoughtworks.go.util.SslVerificationMode;
import org.apache.commons.io.FileUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.UnknownHostException;
import static com.thoughtworks.go.util.FileDigester.md5DigestOfStream;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(FakeBootstrapperServer.class)
public class ServerBinaryDownloaderTest {
@Rule
public ExpectedException exception = ExpectedException.none();
@After
public void tearDown() throws Exception {
FileUtils.deleteQuietly(new File(Downloader.AGENT_BINARY));
FileUtils.deleteQuietly(DownloadableFile.AGENT.getLocalFile());
}
@Test
public void shouldSetMd5AndSSLPortHeaders() throws Exception {
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("localhost", 9090), null, SslVerificationMode.NONE);
downloader.downloadIfNecessary(DownloadableFile.AGENT);
try(BufferedInputStream stream = new BufferedInputStream(new FileInputStream(DownloadableFile.AGENT.getLocalFile()))) {
assertThat(downloader.getMd5(), is(md5DigestOfStream(stream)));
}
assertThat(downloader.getSslPort(), is("9091"));
}
@Test
public void shouldDownloadAgentJarFile() throws Exception {
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("localhost", 9090), null, SslVerificationMode.NONE);
assertThat(DownloadableFile.AGENT.doesNotExist(), is(true));
downloader.downloadIfNecessary(DownloadableFile.AGENT);
assertThat(DownloadableFile.AGENT.getLocalFile().exists(), is(true));
}
@Test
public void shouldReturnTrueIfTheFileIsDownloaded() throws Exception {
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("localhost", 9090), null, SslVerificationMode.NONE);
assertThat(downloader.downloadIfNecessary(DownloadableFile.AGENT), is(true));
}
@Test(expected = Exception.class)
public void shouldThrowExceptionIfTheServerIsDown() throws Exception {
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("locahost", 9090), null, SslVerificationMode.NONE);
downloader.download(DownloadableFile.AGENT);
}
@Test
public void shouldConnectToAnSSLServerWithSelfSignedCertWhenInsecureModeIsNoVerifyHost() throws Exception {
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("localhost", 9090), new File("testdata/test_cert.pem"),
SslVerificationMode.NO_VERIFY_HOST);
downloader.download(DownloadableFile.AGENT);
assertThat(DownloadableFile.AGENT.getLocalFile().exists(), is(true));
}
@Test
public void shouldRaiseExceptionWhenSelfSignedCertDoesNotMatchTheHostName() throws Exception {
exception.expect(Exception.class);
exception.expectMessage("Host name 'localhost' does not match the certificate subject provided by the peer");
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorFor("https://localhost:9091/go/hello"), new File("testdata/test_cert.pem"),
SslVerificationMode.FULL);
downloader.download(DownloadableFile.AGENT);
}
@Test
public void shouldFailIfMD5HeadersAreMissing() throws Exception {
exception.expect(Exception.class);
exception.expectMessage("Missing required headers 'Content-MD5' and 'Cruise-Server-Ssl-Port' in response.");
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorWithoutSubPathFor("https://localhost:9091/go/hello"), null,
SslVerificationMode.NONE);
downloader.fetchUpdateCheckHeaders(DownloadableFile.AGENT);
}
@Test
public void shouldFailIfServerIsNotAvailable() throws Exception {
exception.expect(UnknownHostException.class);
exception.expectMessage("invalidserver");
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorWithoutSubPathFor("https://invalidserver:9091/go/hello"), null,
SslVerificationMode.NONE);
downloader.fetchUpdateCheckHeaders(DownloadableFile.AGENT);
}
@Test
public void shouldThrowExceptionInCaseOf404() throws Exception {
exception.expect(Exception.class);
exception.expectMessage("This agent might be incompatible with your Go Server."
+ " Please fix the version mismatch between Go Server and Go Agent.");
ServerBinaryDownloader downloader = new ServerBinaryDownloader(ServerUrlGeneratorMother.generatorWithoutSubPathFor("https://localhost:9091/go/not-found"), null,
SslVerificationMode.NONE);
downloader.download(DownloadableFile.AGENT);
}
@Test
public void shouldReturnFalseIfTheServerDoesNotRespondWithEntity() throws Exception {
GoAgentServerHttpClientBuilder builder = mock(GoAgentServerHttpClientBuilder.class);
CloseableHttpClient closeableHttpClient = mock(CloseableHttpClient.class);
when(builder.build()).thenReturn(closeableHttpClient);
CloseableHttpResponse httpResponse = mock(CloseableHttpResponse.class);
when(closeableHttpClient.execute(any(HttpRequestBase.class))).thenReturn(httpResponse);
ServerBinaryDownloader downloader = new ServerBinaryDownloader(builder, ServerUrlGeneratorMother.generatorFor("localhost", 9090));
assertThat(downloader.download(DownloadableFile.AGENT), is(false));
}
}