/*-
* -\-\-
* Helios Testing Library
* --
* Copyright (C) 2016 Spotify AB
* --
* 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.spotify.helios.testing;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.collect.Iterables.getOnlyElement;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import com.google.common.base.Optional;
import com.spotify.helios.common.Json;
import com.spotify.helios.common.descriptors.Deployment;
import com.spotify.helios.common.descriptors.Job;
import com.spotify.helios.common.descriptors.JobId;
import com.spotify.helios.common.descriptors.JobStatus;
import com.spotify.helios.testing.descriptors.TemporaryJobEvent;
import java.io.File;
import java.net.Socket;
import java.nio.file.Files;
import java.util.Map;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class SimpleTest extends TemporaryJobsTestBase {
@ClassRule
public static final TemporaryFolder REPORT_DIR = new TemporaryFolder();
@Test
public void simpleTest() throws Exception {
assertThat(testResult(SimpleTestImpl.class), isSuccessful());
assertTrue("jobs are running that should not be",
client.jobs().get(15, SECONDS).isEmpty());
// Ensure test reports were written and everything was successful
final File[] reportFiles = REPORT_DIR.getRoot().listFiles();
if (reportFiles == null) {
fail();
}
assertNotEquals(reportFiles.length, 0);
for (final File reportFile : reportFiles) {
final byte[] testReport = Files.readAllBytes(reportFile.toPath());
final TemporaryJobEvent[] events = Json.read(testReport, TemporaryJobEvent[].class);
for (final TemporaryJobEvent event : events) {
assertTrue(event.isSuccess());
}
}
}
public static class SimpleTestImpl {
@Rule
public final TemporaryJobs temporaryJobs = temporaryJobsBuilder()
.client(client)
.prober(new TestProber())
.jobDeployedMessageFormat(
"Logs Link: http://${host}:8150/${name}%3A${version}%3A${hash}?cid=${containerId}")
.jobPrefix(Optional.of(testTag).get())
.deployTimeoutMillis(MINUTES.toMillis(3))
.testReportDirectory(REPORT_DIR.getRoot().getAbsolutePath())
.build();
private TemporaryJob job1;
@Before
public void setup() {
job1 = temporaryJobs.job()
.command("nc", "-p", "4711", "-lle", "cat")
.port("echo", 4711)
.deploy(testHost1);
}
@Test
public void testDeployment() throws Exception {
// Verify that it is possible to deploy additional jobs during test
temporaryJobs.job()
.command(IDLE_COMMAND)
.host(testHost1)
.deploy();
final Map<JobId, Job> jobs = client.jobs().get(15, SECONDS);
assertEquals("wrong number of jobs running", 2, jobs.size());
for (final Job job : jobs.values()) {
assertEquals("wrong job running", BUSYBOX, job.getImage());
}
//verify address and addresses return valid HostAndPort objects
assertEquals("wrong host", testHost1, job1.address("echo").getHostText());
assertEquals("wrong host", testHost1, getOnlyElement(job1.addresses("echo")).getHostText());
ping(DOCKER_HOST.address(), job1.port(testHost1, "echo"));
}
@Test
public void testRandomHost() throws Exception {
temporaryJobs.job()
.command("sh", "-c", "while :; do sleep 5; done")
.deploy();
final Map<JobId, Job> jobs = client.jobs().get(15, SECONDS);
assertEquals("wrong number of jobs running", 2, jobs.size());
for (final Job job : jobs.values()) {
assertEquals("wrong job running", BUSYBOX, job.getImage());
}
ping(DOCKER_HOST.address(), job1.port(testHost1, "echo"));
}
@Test
public void testSpecificHost() throws Exception {
final TemporaryJob job = temporaryJobs.job()
.command(IDLE_COMMAND)
.hostFilter(testHost2)
.deploy();
final JobStatus status = client.jobStatus(job.job().getId()).get(15, SECONDS);
final Map<String, Deployment> deployments = status.getDeployments();
assertThat(deployments.keySet(), contains(testHost2));
}
@Test
public void testManualUndeploy() throws Exception {
final TemporaryJob job = temporaryJobs.job()
.command(IDLE_COMMAND)
.deploy();
job.undeploy();
final JobStatus status = client.jobStatus(job.job().getId()).get(15, SECONDS);
assertNull("job still exists", status);
}
@Test
public void testDefaultLocalHostFilter() throws Exception {
temporaryJobs.job()
.command("sh", "-c", "while :; do sleep 5; done")
.deploy();
}
@Test(expected = AssertionError.class)
public void testExceptionWithBadHostFilter() throws Exception {
// Shouldn't be able to deploy if filter doesn't match any hosts
temporaryJobs.job()
.command("sh", "-c", "while :; do sleep 5; done")
.hostFilter("THIS_FILTER_SHOULDNT_MATCH_ANY_HOST")
.deploy();
}
@Test
public void testImageFromBuild() {
temporaryJobs.job()
.image(BUSYBOX)
.command("sh", "-c", "while :; do sleep 5; done")
.deploy();
}
@Test
public void testVolume() {
temporaryJobs.job()
.volume(System.getProperty("user.dir") + "/helios-testing/src/test/resources/helios.conf",
"/helios.conf")
.command("sh", "-c", "while :; do sleep 5; done")
.deploy();
}
private void ping(final String host, final int port) throws Exception {
try (final Socket s = new Socket(host, port)) {
final byte[] ping = "ping".getBytes(UTF_8);
s.getOutputStream().write(ping);
final byte[] pong = new byte[4];
final int n = s.getInputStream().read(pong);
assertEquals(4, n);
assertArrayEquals(ping, pong);
}
}
}
}