/*-
* -\-\-
* Helios Client
* --
* 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.client;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.spotify.helios.common.Json;
import com.spotify.helios.common.descriptors.Job;
import com.spotify.helios.common.descriptors.JobId;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hamcrest.FeatureMatcher;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.Test;
public class HeliosClientTest {
private final RequestDispatcher dispatcher = mock(RequestDispatcher.class);
private final HeliosClient client = new HeliosClient("test", dispatcher);
@Test(expected = IllegalStateException.class)
public void testBuildWithNoEndpoints() {
HeliosClient.newBuilder()
.setEndpoints(Collections.<URI>emptyList())
.build();
}
@Test
public void listHosts() throws Exception {
final List<String> hosts = ImmutableList.of("foo1", "foo2", "foo3");
mockResponse("GET", hasPath("/hosts/"), response("GET", 200, hosts));
assertThat(client.listHosts().get(), equalTo(hosts));
}
private static Response response(final String method, int statusCode, Object payload) {
// second param is request URI, which is not relevant here
return new Response(method, null, statusCode, Json.asBytesUnchecked(payload),
Collections.<String, List<String>>emptyMap());
}
@SuppressWarnings("unchecked")
private void mockResponse(final String method,
final Matcher<URI> uriMatcher,
final Response response) {
final byte[] emptyRequestPayload = new byte[0];
when(dispatcher.request(argThat(uriMatcher), eq(method), eq(emptyRequestPayload), anyMap()))
.thenReturn(Futures.immediateFuture(response));
}
/** A Matcher that tests that the URI has a path equal to the given path. */
private static Matcher<URI> hasPath(final String path) {
return new FeatureMatcher<URI, String>(Matchers.equalTo(path), "path", "path") {
@Override
protected String featureValueOf(final URI actual) {
return actual.getPath();
}
};
}
/**
* A Matcher that tests that the rawQuery of the URI (i.e. encoded) contains the given substring.
*/
private static Matcher<URI> containsQuery(final String rawQuerySubstring) {
return new FeatureMatcher<URI, String>(Matchers.containsString(rawQuerySubstring), "query",
"query") {
@Override
protected String featureValueOf(final URI actual) {
return actual.getRawQuery();
}
};
}
@Test
public void listHostsFilterByNamePattern() throws Exception {
final List<String> hosts = ImmutableList.of("foo1", "foo2", "foo3");
mockResponse("GET",
allOf(hasPath("/hosts/"), containsQuery("namePattern=foo")),
response("GET", 200, hosts));
assertThat(client.listHosts("foo").get(), equalTo(hosts));
}
@Test
public void listHostsFilterBySelectors() throws Exception {
final List<String> hosts = ImmutableList.of("foo1", "foo2", "foo3");
mockResponse("GET",
allOf(hasPath("/hosts/"),
containsQuery("selector=foo%3Dbar"),
containsQuery("selector=site%3Dabc")
),
response("GET", 200, hosts));
final Set<String> selectors = ImmutableSet.of("foo=bar", "site=abc");
assertThat(client.listHosts(selectors).get(), equalTo(hosts));
}
private static Map<JobId, Job> fakeJobs(JobId... jobIds) {
Map<JobId, Job> jobs = new HashMap<>();
for (JobId jobId : jobIds) {
final Job job = Job.newBuilder()
.setName(jobId.getName())
.setVersion(jobId.getVersion())
.setHash(jobId.getHash())
.build();
jobs.put(jobId, job);
}
return jobs;
}
@Test
public void listJobs() throws Exception {
final Map<JobId, Job> jobs = fakeJobs(JobId.parse("foobar:v1"));
mockResponse("GET",
hasPath("/jobs"),
response("GET", 200, jobs)
);
assertThat(client.jobs().get(), is(jobs));
}
@Test
public void listJobsWithJobFilter() throws Exception {
final Map<JobId, Job> jobs = fakeJobs(JobId.parse("foobar:v1"));
mockResponse("GET",
allOf(
hasPath("/jobs"),
containsQuery("q=foo")
),
response("GET", 200, jobs)
);
assertThat(client.jobs("foo").get(), is(jobs));
}
@Test
public void listJobsWithJobAndHostFilter() throws Exception {
final Map<JobId, Job> jobs = fakeJobs(JobId.parse("foobar:v1"));
mockResponse("GET",
allOf(
hasPath("/jobs"),
containsQuery("q=foo"),
containsQuery("hostPattern=bar")
),
response("GET", 200, jobs)
);
assertThat(client.jobs("foo", "bar").get(), is(jobs));
}
}