/*
* Copyright (C) 2012 Google 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.google.inject.servlet;
import com.google.common.collect.ImmutableMap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provides;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import junit.framework.TestCase;
// TODO: Add test for HTTP transferring.
/** Tests transferring of entire request scope. */
public class TransferRequestIntegrationTest extends TestCase {
private final Callable<Boolean> FALSE_CALLABLE =
new Callable<Boolean>() {
@Override
public Boolean call() {
return false;
}
};
public void testTransferHttp_outOfScope() {
try {
ServletScopes.transferRequest(FALSE_CALLABLE);
fail();
} catch (OutOfScopeException expected) {
}
}
public void testTransferNonHttp_outOfScope() {
try {
ServletScopes.transferRequest(FALSE_CALLABLE);
fail();
} catch (OutOfScopeException expected) {
}
}
public void testTransferNonHttp_outOfScope_closeable() {
try {
ServletScopes.transferRequest();
fail();
} catch (OutOfScopeException expected) {
}
}
public void testTransferNonHttpRequest() throws Exception {
final Injector injector =
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bindScope(RequestScoped.class, ServletScopes.REQUEST);
}
@Provides
@RequestScoped
Object provideObject() {
return new Object();
}
});
Callable<Callable<Boolean>> callable =
new Callable<Callable<Boolean>>() {
@Override
public Callable<Boolean> call() {
final Object original = injector.getInstance(Object.class);
return ServletScopes.transferRequest(
new Callable<Boolean>() {
@Override
public Boolean call() {
return original == injector.getInstance(Object.class);
}
});
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
Callable<Boolean> transfer = ServletScopes.scopeRequest(callable, seedMap).call();
ExecutorService executor = Executors.newSingleThreadExecutor();
assertTrue(executor.submit(transfer).get());
executor.shutdownNow();
}
public void testTransferNonHttpRequest_closeable() throws Exception {
final Injector injector =
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bindScope(RequestScoped.class, ServletScopes.REQUEST);
}
@Provides
@RequestScoped
Object provideObject() {
return new Object();
}
});
class Data {
Object object;
RequestScoper scoper;
}
Callable<Data> callable =
new Callable<Data>() {
@Override
public Data call() {
Data data = new Data();
data.object = injector.getInstance(Object.class);
data.scoper = ServletScopes.transferRequest();
return data;
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
Data data = ServletScopes.scopeRequest(callable, seedMap).call();
ExecutorService executor = Executors.newSingleThreadExecutor();
RequestScoper.CloseableScope scope = data.scoper.open();
try {
assertSame(data.object, injector.getInstance(Object.class));
} finally {
scope.close();
executor.shutdownNow();
}
}
public void testTransferNonHttpRequest_concurrentUseBlocks() throws Exception {
Callable<Boolean> callable =
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Future<Boolean> future =
executor.submit(ServletScopes.transferRequest(FALSE_CALLABLE));
try {
return future.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
return true;
}
} finally {
executor.shutdownNow();
}
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
assertTrue(ServletScopes.scopeRequest(callable, seedMap).call());
}
public void testTransferNonHttpRequest_concurrentUseBlocks_closeable() throws Exception {
Callable<Boolean> callable =
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
final RequestScoper scoper = ServletScopes.transferRequest();
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Future<Boolean> future =
executor.submit(
new Callable<Boolean>() {
@Override
public Boolean call() {
RequestScoper.CloseableScope scope = scoper.open();
try {
return false;
} finally {
scope.close();
}
}
});
try {
return future.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
return true;
}
} finally {
executor.shutdownNow();
}
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
assertTrue(ServletScopes.scopeRequest(callable, seedMap).call());
}
public void testTransferNonHttpRequest_concurrentUseSameThreadOk() throws Exception {
Callable<Boolean> callable =
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return ServletScopes.transferRequest(FALSE_CALLABLE).call();
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
assertFalse(ServletScopes.scopeRequest(callable, seedMap).call());
}
public void testTransferNonHttpRequest_concurrentUseSameThreadOk_closeable() throws Exception {
Callable<Boolean> callable =
new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
RequestScoper.CloseableScope scope = ServletScopes.transferRequest().open();
try {
return false;
} finally {
scope.close();
}
}
};
ImmutableMap<Key<?>, Object> seedMap = ImmutableMap.of();
assertFalse(ServletScopes.scopeRequest(callable, seedMap).call());
}
}