mirror of https://github.com/apache/jclouds.git
Issue 799:simplify http test creation: take 1
This commit is contained in:
parent
9c97f2b6a3
commit
08355a92a1
|
@ -22,6 +22,7 @@ import java.util.concurrent.Future;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
/**
|
||||
* Executor which will invoke and transform the response of an {@code EndpointCommand} into generic
|
||||
|
@ -29,6 +30,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@ImplementedBy(TransformingHttpCommandExecutorServiceImpl.class)
|
||||
public interface TransformingHttpCommandExecutorService {
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.jclouds.logging.Logger;
|
|||
import org.jclouds.rest.internal.GeneratedHttpRequest;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
|
@ -144,6 +145,20 @@ public class TransformingHttpCommandImpl<T> implements TransformingHttpCommand<T
|
|||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null)
|
||||
return false;
|
||||
if (!(that instanceof HttpCommand))
|
||||
return false;
|
||||
return Objects.equal(this.request, HttpCommand.class.cast(that).getCurrentRequest());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (request instanceof GeneratedHttpRequest<?>)
|
||||
|
|
|
@ -71,20 +71,13 @@ public class RestContextSpec<S, A> {
|
|||
(Class) RestContextBuilder.class, EMPTY_LIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* this uses the inefficient {@link Objects} implementation as the object count will be
|
||||
* relatively small and therefore efficiency is not a concern.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(provider, endpoint, apiVersion, iso3166Codes, identity, credential, sync, async,
|
||||
propertiesBuilderClass, contextBuilderClass, modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* this uses the inefficient {@link Objects} implementation as the object count will be
|
||||
* relatively small and therefore efficiency is not a concern.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null)
|
||||
|
@ -92,10 +85,6 @@ public class RestContextSpec<S, A> {
|
|||
return Objects.equal(this.toString(), that.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* this uses the inefficient {@link Objects} implementation as the object count will be
|
||||
* relatively small and therefore efficiency is not a concern.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toStringHelper(this).add("provider", provider).add("endpoint", endpoint).add("apiVersion",
|
||||
|
|
|
@ -80,12 +80,15 @@ public class Throwables2 {
|
|||
return (Exception) throwable;
|
||||
}
|
||||
}
|
||||
for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class,
|
||||
for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class, AssertionError.class,
|
||||
UnsupportedOperationException.class, IllegalArgumentException.class, AuthorizationException.class,
|
||||
ResourceNotFoundException.class, InsufficientResourcesException.class, HttpResponseException.class }) {
|
||||
Throwable throwable = getFirstThrowableOfType(exception, propagatableExceptionType);
|
||||
if (throwable != null) {
|
||||
throw (Exception) throwable;
|
||||
if (throwable instanceof AssertionError)
|
||||
throw (AssertionError) throwable;
|
||||
else
|
||||
throw (Exception) throwable;
|
||||
}
|
||||
}
|
||||
Throwables.propagateIfPossible(exception.getCause(), Exception.class);
|
||||
|
|
|
@ -48,6 +48,7 @@ import org.jclouds.rest.annotations.XMLResponseParser;
|
|||
import org.jclouds.rest.binders.BindMapToMatrixParams;
|
||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||
import org.jclouds.rest.binders.BindToStringPayload;
|
||||
import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404;
|
||||
import org.jclouds.util.Strings2;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
@ -73,6 +74,7 @@ public interface IntegrationTestAsyncClient {
|
|||
|
||||
@HEAD
|
||||
@Path("/objects/{id}")
|
||||
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
|
||||
ListenableFuture<Boolean> exists(@PathParam("id") String path);
|
||||
|
||||
@GET
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you 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 org.jclouds.http;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||
import org.jclouds.rest.BaseRestClientExpectTest.RegisterContext;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* Allows us to test a client via its side effects.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "IntegrationTestClientExpectTest")
|
||||
// only needed as IntegrationTestClient is not registered in rest.properties
|
||||
@RegisterContext(sync = IntegrationTestClient.class, async = IntegrationTestAsyncClient.class)
|
||||
public class IntegrationTestClientExpectTest extends BaseRestClientExpectTest<IntegrationTestClient> {
|
||||
|
||||
public void testWhenResponseIs2xxExistsReturnsTrue() {
|
||||
|
||||
IntegrationTestClient client = requestSendsResponse(HttpRequest.builder().method("HEAD").endpoint(
|
||||
URI.create("http://mock/objects/rabbit")).build(), HttpResponse.builder().statusCode(200).build());
|
||||
|
||||
assertEquals(client.exists("rabbit"), true);
|
||||
|
||||
}
|
||||
|
||||
public void testWhenResponseIs404ExistsReturnsFalse() {
|
||||
|
||||
IntegrationTestClient client = requestSendsResponse(HttpRequest.builder().method("HEAD").endpoint(
|
||||
URI.create("http://mock/objects/rabbit")).build(), HttpResponse.builder().statusCode(404).build());
|
||||
|
||||
assertEquals(client.exists("rabbit"), false);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except fn 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 fn 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 org.jclouds.rest;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
import static org.jclouds.rest.RestContextFactory.contextSpec;
|
||||
import static org.jclouds.rest.RestContextFactory.createContext;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.Constants;
|
||||
import org.jclouds.concurrent.MoreExecutors;
|
||||
import org.jclouds.concurrent.SingleThreaded;
|
||||
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.HttpUtils;
|
||||
import org.jclouds.http.IOExceptionRetryHandler;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
import org.jclouds.http.handlers.DelegatingErrorHandler;
|
||||
import org.jclouds.http.handlers.DelegatingRetryHandler;
|
||||
import org.jclouds.http.internal.BaseHttpCommandExecutorService;
|
||||
import org.jclouds.http.internal.HttpWire;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.io.Payloads;
|
||||
import org.jclouds.logging.config.NullLoggingModule;
|
||||
import org.jclouds.util.Strings2;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
/**
|
||||
*
|
||||
* Allows us to test a client via its side effects.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
@Beta
|
||||
public abstract class BaseRestClientExpectTest<S> {
|
||||
/**
|
||||
* only needed when the client is simple and not registered fn rest.properties
|
||||
*/
|
||||
@Target(TYPE)
|
||||
@Retention(RUNTIME)
|
||||
public static @interface RegisterContext {
|
||||
Class<?> sync();
|
||||
|
||||
Class<?> async();
|
||||
}
|
||||
|
||||
protected String provider = "mock";
|
||||
|
||||
protected Module createModule() {
|
||||
return new Module() {
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
protected Payload payloadFromResource(String resource) {
|
||||
return Payloads.newInputStreamPayload(getClass().getResourceAsStream(resource));
|
||||
}
|
||||
|
||||
@SingleThreaded
|
||||
@Singleton
|
||||
public static class ExpectHttpCommandExecutorService extends BaseHttpCommandExecutorService<HttpRequest> {
|
||||
|
||||
private final Function<HttpRequest, HttpResponse> fn;
|
||||
|
||||
@Inject
|
||||
public ExpectHttpCommandExecutorService(Function<HttpRequest, HttpResponse> fn, HttpUtils utils,
|
||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor,
|
||||
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
|
||||
DelegatingErrorHandler errorHandler, HttpWire wire) {
|
||||
super(utils, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
|
||||
this.fn = checkNotNull(fn, "fn");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanup(HttpRequest nativeResponse) {
|
||||
if (nativeResponse.getPayload() != null)
|
||||
nativeResponse.getPayload().release();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpRequest convert(HttpRequest request) throws IOException, InterruptedException {
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpResponse invoke(HttpRequest nativeRequest) throws IOException, InterruptedException {
|
||||
return fn.apply(nativeRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@ConfiguresHttpCommandExecutorService
|
||||
@ConfiguresExecutorService
|
||||
public static class ExpectModule extends AbstractModule {
|
||||
private final Function<HttpRequest, HttpResponse> fn;
|
||||
|
||||
public ExpectModule(Function<HttpRequest, HttpResponse> fn) {
|
||||
this.fn = checkNotNull(fn, "fn");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).toInstance(
|
||||
MoreExecutors.sameThreadExecutor());
|
||||
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(
|
||||
MoreExecutors.sameThreadExecutor());
|
||||
bind(new TypeLiteral<Function<HttpRequest, HttpResponse>>() {
|
||||
}).toInstance(fn);
|
||||
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);
|
||||
}
|
||||
}
|
||||
|
||||
protected S requestSendsResponse(final HttpRequest fn, final HttpResponse out) {
|
||||
return createClient(new Function<HttpRequest, HttpResponse>() {
|
||||
|
||||
@Override
|
||||
public HttpResponse apply(HttpRequest command) {
|
||||
assertEquals(renderRequest(command), renderRequest(fn));
|
||||
return out;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String renderRequest(HttpRequest request) {
|
||||
StringBuilder builder = new StringBuilder().append(request.getRequestLine()).append('\n');
|
||||
for (Entry<String, String> header : request.getHeaders().entries()) {
|
||||
builder.append(header.getKey()).append(": ").append(header.getValue()).append('\n');
|
||||
}
|
||||
if (request.getPayload() != null) {
|
||||
for (Entry<String, String> header : HttpUtils.getContentHeadersFromMetadata(
|
||||
request.getPayload().getContentMetadata()).entries()) {
|
||||
builder.append(header.getKey()).append(": ").append(header.getValue()).append('\n');
|
||||
}
|
||||
try {
|
||||
builder.append('\n').append(Strings2.toStringAndClose(request.getPayload().getInput()));
|
||||
} catch (IOException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
protected S createClient(Function<HttpRequest, HttpResponse> fn) {
|
||||
return createClient(fn, createModule(), setupProperties());
|
||||
}
|
||||
|
||||
protected S createClient(Function<HttpRequest, HttpResponse> fn, Module module) {
|
||||
return createClient(fn, module, setupProperties());
|
||||
|
||||
}
|
||||
|
||||
protected S createClient(Function<HttpRequest, HttpResponse> fn, Properties props) {
|
||||
return createClient(fn, createModule(), props);
|
||||
|
||||
}
|
||||
|
||||
protected S createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
|
||||
RestContextSpec<S, ?> contextSpec = makeContextSpec();
|
||||
|
||||
return createContext(contextSpec,
|
||||
ImmutableSet.<Module> of(new ExpectModule(fn), new NullLoggingModule(), module), props).getApi();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private RestContextSpec<S, ?> makeContextSpec() {
|
||||
if (getClass().isAnnotationPresent(RegisterContext.class))
|
||||
return (RestContextSpec<S, ?>) contextSpec(provider, "http://mock", "1", "", "userfoo", null, getClass()
|
||||
.getAnnotation(RegisterContext.class).sync(),
|
||||
getClass().getAnnotation(RegisterContext.class).async(), ImmutableSet.<Module> of());
|
||||
else
|
||||
return new RestContextFactory(setupRestProperties()).createContextSpec(provider, "identity", "credential",
|
||||
new Properties());
|
||||
}
|
||||
|
||||
|
||||
protected Properties setupRestProperties() {
|
||||
return RestContextFactory.getPropertiesFromResource("/rest.properties");
|
||||
}
|
||||
|
||||
protected Properties setupProperties() {
|
||||
return new Properties();
|
||||
}
|
||||
}
|
|
@ -35,8 +35,8 @@ import org.jclouds.concurrent.MoreExecutors;
|
|||
import org.jclouds.concurrent.config.ConfiguresExecutorService;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.crypto.CryptoStreams;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.io.MutableContentMetadata;
|
||||
|
@ -65,13 +65,13 @@ public abstract class BaseRestClientTest {
|
|||
@ConfiguresHttpCommandExecutorService
|
||||
@ConfiguresExecutorService
|
||||
public static class MockModule extends AbstractModule {
|
||||
private final TransformingHttpCommandExecutorService mock;
|
||||
private final HttpCommandExecutorService mock;
|
||||
|
||||
public MockModule() {
|
||||
this(createMock(TransformingHttpCommandExecutorService.class));
|
||||
this(createMock(HttpCommandExecutorService.class));
|
||||
}
|
||||
|
||||
public MockModule(TransformingHttpCommandExecutorService mock) {
|
||||
public MockModule(HttpCommandExecutorService mock) {
|
||||
this.mock = mock;
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public abstract class BaseRestClientTest {
|
|||
MoreExecutors.sameThreadExecutor());
|
||||
bind(ExecutorService.class).annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).toInstance(
|
||||
MoreExecutors.sameThreadExecutor());
|
||||
bind(TransformingHttpCommandExecutorService.class).toInstance(mock);
|
||||
bind(HttpCommandExecutorService.class).toInstance(mock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ public abstract class RestClientTest<T> extends BaseRestClientTest {
|
|||
@BeforeClass
|
||||
protected void setupFactory() throws IOException {
|
||||
RestContextSpec<?, ?> contextSpec = createContextSpec();
|
||||
|
||||
injector = createContextBuilder(contextSpec,
|
||||
ImmutableSet.of(new MockModule(), new NullLoggingModule(), createModule()), getProperties())
|
||||
.buildInjector();
|
||||
|
|
|
@ -20,12 +20,6 @@ package org.jclouds.rest.internal;
|
|||
|
||||
import static com.google.common.base.Charsets.UTF_8;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.easymock.EasyMock.eq;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.reportMatcher;
|
||||
import static org.easymock.classextension.EasyMock.createNiceMock;
|
||||
import static org.easymock.classextension.EasyMock.replay;
|
||||
import static org.easymock.classextension.EasyMock.verify;
|
||||
import static org.jclouds.io.Payloads.calculateMD5;
|
||||
import static org.jclouds.io.Payloads.newInputStreamPayload;
|
||||
import static org.jclouds.io.Payloads.newStringPayload;
|
||||
|
@ -53,6 +47,7 @@ import java.util.Date;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
@ -75,26 +70,24 @@ import javax.ws.rs.core.MediaType;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.easymock.IArgumentMatcher;
|
||||
import org.eclipse.jetty.http.HttpHeaders;
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.crypto.Crypto;
|
||||
import org.jclouds.date.DateService;
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.http.HttpCommand;
|
||||
import org.jclouds.http.HttpCommandExecutorService;
|
||||
import org.jclouds.http.HttpException;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpRequestFilter;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.http.IOExceptionRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.TransformingHttpCommandExecutorService;
|
||||
import org.jclouds.http.functions.ParseFirstJsonValueNamed;
|
||||
import org.jclouds.http.functions.ParseJson;
|
||||
import org.jclouds.http.functions.ParseSax;
|
||||
import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
|
||||
import org.jclouds.http.functions.ParseXMLWithJAXB;
|
||||
import org.jclouds.http.functions.ReleasePayloadAndReturn;
|
||||
import org.jclouds.http.functions.ReturnInputStream;
|
||||
import org.jclouds.http.functions.ReturnStringIf2xx;
|
||||
import org.jclouds.http.functions.ReturnTrueIf2xx;
|
||||
|
@ -180,8 +173,8 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
protected static class CallerCalleeModule extends RestClientModule<Caller, AsyncCaller> {
|
||||
CallerCalleeModule() {
|
||||
protected static class CallerModule extends RestClientModule<Caller, AsyncCaller> {
|
||||
CallerModule() {
|
||||
super(Caller.class, AsyncCaller.class, ImmutableMap.<Class<?>, Class<?>> of(Callee.class, AsyncCallee.class));
|
||||
}
|
||||
|
||||
|
@ -227,13 +220,17 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
public AsyncCallee getCallee(@EndpointParam URI endpoint);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testDelegateAsyncIncludesVersion() throws SecurityException, NoSuchMethodException,
|
||||
InterruptedException, ExecutionException {
|
||||
Injector child = injectorForClient();
|
||||
TransformingHttpCommandExecutorService mock = child.getInstance(TransformingHttpCommandExecutorService.class);
|
||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException, ExecutionException {
|
||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||
|
||||
ReleasePayloadAndReturn function = child.getInstance(ReleasePayloadAndReturn.class);
|
||||
@Override
|
||||
public Future<HttpResponse> submit(HttpCommand command) {
|
||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||
"GET http://localhost:9999/client/1/foo HTTP/1.1");
|
||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
try {
|
||||
child.getInstance(AsyncCallee.class);
|
||||
|
@ -242,42 +239,21 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
}
|
||||
|
||||
AsyncCaller caller = child.getInstance(AsyncCaller.class);
|
||||
expect(mock.submit(requestLineEquals("GET http://localhost:9999/client/1/foo HTTP/1.1"), eq(function)))
|
||||
.andReturn(createNiceMock(ListenableFuture.class)).atLeastOnce();
|
||||
replay(mock);
|
||||
|
||||
caller.getCallee().onePath("foo");
|
||||
|
||||
verify(mock);
|
||||
child.getInstance(AsyncCaller.class).getCallee().onePath("foo").get();
|
||||
|
||||
}
|
||||
|
||||
public static HttpCommand requestLineEquals(final String requestLine) {
|
||||
reportMatcher(new IArgumentMatcher() {
|
||||
public void testDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException, ExecutionException {
|
||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuffer buffer) {
|
||||
buffer.append("requestLineEquals(");
|
||||
buffer.append(requestLine);
|
||||
buffer.append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object arg) {
|
||||
return ((HttpCommand) arg).getCurrentRequest().getRequestLine().equals(requestLine);
|
||||
public Future<HttpResponse> submit(HttpCommand command) {
|
||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||
"GET http://localhost:1111/client/1/foo HTTP/1.1");
|
||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
||||
}
|
||||
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
public void testDelegateWithOverridingEndpoint() throws SecurityException, NoSuchMethodException,
|
||||
InterruptedException, ExecutionException {
|
||||
Injector child = injectorForClient();
|
||||
TransformingHttpCommandExecutorService mock = child.getInstance(TransformingHttpCommandExecutorService.class);
|
||||
|
||||
ReleasePayloadAndReturn function = child.getInstance(ReleasePayloadAndReturn.class);
|
||||
|
||||
try {
|
||||
child.getInstance(Callee.class);
|
||||
|
@ -286,23 +262,45 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
}
|
||||
|
||||
Caller caller = child.getInstance(Caller.class);
|
||||
expect(mock.submit(requestLineEquals("GET http://localhost:1111/client/1/foo HTTP/1.1"), eq(function)))
|
||||
.andReturn(Futures.<Void> immediateFuture(null)).atLeastOnce();
|
||||
replay(mock);
|
||||
child.getInstance(Caller.class).getCallee().onePath("foo");
|
||||
|
||||
caller.getCallee().onePath("foo");
|
||||
}
|
||||
|
||||
|
||||
verify(mock);
|
||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException {
|
||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||
|
||||
@Override
|
||||
public Future<HttpResponse> submit(HttpCommand command) {
|
||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||
"GET http://howdyboys/client/1/foo HTTP/1.1");
|
||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
try {
|
||||
child.getInstance(AsyncCallee.class);
|
||||
assert false : "Callee shouldn't be bound yet";
|
||||
} catch (ConfigurationException e) {
|
||||
|
||||
}
|
||||
|
||||
child.getInstance(AsyncCaller.class).getCallee(URI.create("http://howdyboys")).onePath("foo").get();
|
||||
|
||||
}
|
||||
|
||||
public void testDelegateWithOverridingEndpointOnMethod() throws SecurityException, NoSuchMethodException,
|
||||
InterruptedException, ExecutionException {
|
||||
Injector child = injectorForClient();
|
||||
TransformingHttpCommandExecutorService mock = child.getInstance(TransformingHttpCommandExecutorService.class);
|
||||
public void testDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException {
|
||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||
|
||||
ReleasePayloadAndReturn function = child.getInstance(ReleasePayloadAndReturn.class);
|
||||
@Override
|
||||
public Future<HttpResponse> submit(HttpCommand command) {
|
||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
||||
"GET http://howdyboys/client/1/foo HTTP/1.1");
|
||||
return Futures.immediateFuture(HttpResponse.builder().build());
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
try {
|
||||
child.getInstance(Callee.class);
|
||||
|
@ -311,22 +309,15 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
}
|
||||
|
||||
Caller caller = child.getInstance(Caller.class);
|
||||
expect(mock.submit(requestLineEquals("GET http://howdyboys/client/1/foo HTTP/1.1"), eq(function))).andReturn(
|
||||
Futures.<Void> immediateFuture(null)).atLeastOnce();
|
||||
replay(mock);
|
||||
|
||||
caller.getCallee(URI.create("http://howdyboys")).onePath("foo");
|
||||
|
||||
verify(mock);
|
||||
child.getInstance(Caller.class).getCallee(URI.create("http://howdyboys")).onePath("foo");
|
||||
|
||||
}
|
||||
|
||||
private Injector injectorForClient() {
|
||||
|
||||
private Injector injectorForCaller(HttpCommandExecutorService service) {
|
||||
|
||||
RestContextSpec<Caller, AsyncCaller> contextSpec = contextSpec("test", "http://localhost:9999", "1", "",
|
||||
"userfoo", null, Caller.class, AsyncCaller.class,
|
||||
ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new CallerCalleeModule()));
|
||||
ImmutableSet.<Module> of(new MockModule(service), new NullLoggingModule(), new CallerModule()));
|
||||
|
||||
return createContextBuilder(contextSpec).buildInjector();
|
||||
|
||||
|
|
|
@ -116,6 +116,12 @@ public class Throwables2Test {
|
|||
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(new Class[] {}, new RuntimeException(e));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AssertionError.class)
|
||||
public void testPropagateStandardExceptionAssertionError() throws Exception {
|
||||
AssertionError e = new AssertionError();
|
||||
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(new Class[] {}, new RuntimeException(e));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testPropagateStandardExceptionAuthorizationException() throws Exception {
|
||||
Exception e = new AuthorizationException();
|
||||
|
|
Loading…
Reference in New Issue