blob: e6b8b7d40a45fb883e2b4b73dfd89acb5efa5150 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF 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.rest.internal;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.reflect.Reflection2.method;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.config.InvocationConfig;
import org.jclouds.rest.internal.InvokeHttpMethod.InvokeAndTransform;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.TimeLimiter;
@Test(groups = "unit", singleThreaded = true)
public class InvokeHttpMethodTest {
public interface ThingApi {
@Named("ns:get")
HttpResponse get();
}
private Invocation get;
private HttpRequest getRequest = HttpRequest.builder().method("GET").endpoint("http://get").build();
private HttpCommand getCommand = new HttpCommand(getRequest);
private Function<Invocation, HttpRequest> toRequest;
@BeforeClass
void setupInvocations() throws SecurityException, NoSuchMethodException {
get = Invocation.create(method(ThingApi.class, "get"), ImmutableList.of());
toRequest = Functions.forMap(ImmutableMap.of(get, getRequest));
}
@SuppressWarnings("unchecked")
private Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest = Function.class.cast(Functions
.constant(Functions.identity()));
private HttpResponse response = HttpResponse.builder().statusCode(200).payload("foo").build();
private HttpCommandExecutorService http;
private TimeLimiter timeLimiter;
@SuppressWarnings("rawtypes")
private org.jclouds.Fallback fallback;
private InvocationConfig config;
private InvokeHttpMethod invokeHttpMethod;
@SuppressWarnings("unchecked")
@BeforeMethod
void createMocks() {
http = createMock(HttpCommandExecutorService.class);
timeLimiter = createMock(TimeLimiter.class);
fallback = createMock(org.jclouds.Fallback.class);
config = createMock(InvocationConfig.class);
invokeHttpMethod = new InvokeHttpMethod(toRequest, http, transformerForRequest, timeLimiter, config);
expect(config.getCommandName(get)).andReturn("ns:get");
expect(config.getFallback(get)).andReturn(fallback);
}
@AfterMethod
void verifyMocks() {
verify(http, timeLimiter, fallback, config);
}
public void testMethodWithTimeoutRunsTimeLimiter() throws Exception {
expect(config.getTimeoutNanos(get)).andReturn(Optional.of(250000000L));
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS)).andReturn(response);
replay(http, timeLimiter, fallback, config);
invokeHttpMethod.apply(get);
}
public void testMethodWithNoTimeoutCallGetDirectly() throws Exception {
expect(config.getTimeoutNanos(get)).andReturn(Optional.<Long> absent());
expect(http.invoke(new HttpCommand(getRequest))).andReturn(response);
replay(http, timeLimiter, fallback, config);
invokeHttpMethod.apply(get);
}
private HttpResponse fallbackResponse = HttpResponse.builder().statusCode(200).payload("bar").build();
public void testDirectCallRunsFallbackCreateOrPropagate() throws Exception {
IllegalStateException exception = new IllegalStateException();
expect(config.getTimeoutNanos(get)).andReturn(Optional.<Long> absent());
expect(http.invoke(new HttpCommand(getRequest))).andThrow(exception);
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
replay(http, timeLimiter, fallback, config);
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
}
public void testTimeLimitedRunsFallbackCreateOrPropagate() throws Exception {
IllegalStateException exception = new IllegalStateException();
expect(config.getTimeoutNanos(get)).andReturn(Optional.of(250000000L));
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS)).andThrow(exception);
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
replay(http, timeLimiter, fallback, config);
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
}
}