package com.bazaarvoice.ostrich.pool; import com.bazaarvoice.ostrich.PartitionContext; import com.bazaarvoice.ostrich.partition.PartitionKey; import com.google.common.collect.ImmutableMap; import org.junit.Test; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class AnnotationPartitionContextSupplierTest { @Test public void testImplExtendsIfc() { new AnnotationPartitionContextSupplier(List.class, ArrayList.class); } @SuppressWarnings("unchecked") @Test(expected = IllegalArgumentException.class) public void testImplDoesntExtendsIfc() { new AnnotationPartitionContextSupplier((Class) ArrayList.class, List.class); } @Test(expected = IllegalStateException.class) public void testDuplicateKey() { new AnnotationPartitionContextSupplier(MyService.class, MyServiceDup.class); } @Test public void testNoArgs() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); PartitionContext partitionContext = contextSupplier.forCall(MyService.class.getMethod("noArgs")); assertTrue(partitionContext.asMap().isEmpty()); } @Test public void testUnnamedKey() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); // Call unnamed(String) assertEquals(ImmutableMap.<String, Object>of("", "a"), contextSupplier.forCall(MyService.class.getMethod("unnamed", String.class), "a").asMap()); } @Test public void testNamedKey() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); // Call unnamed(int) assertEquals(ImmutableMap.<String, Object>of("n", "named"), contextSupplier.forCall(MyService.class.getMethod("named", String.class), "named").asMap()); } @Test public void testOverloadedMethod() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); // Call overloaded(String) assertEquals(ImmutableMap.<String, Object>of("string", "data"), contextSupplier.forCall(MyService.class.getMethod("overloaded", String.class), "data").asMap()); // Call overloaded(int) assertEquals(ImmutableMap.<String, Object>of("int", 5), contextSupplier.forCall(MyService.class.getMethod("overloaded", int.class), 5).asMap()); } @Test public void testNoKeys() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); // Call unnamed(boolean) assertTrue(contextSupplier.forCall(MyService.class.getMethod("noKey", boolean.class), false).asMap().isEmpty()); } @Test public void testTwoArg() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); assertEquals(ImmutableMap.<String, Object>of("", "a"), contextSupplier.forCall(MyService.class.getMethod("twoArgsOneKey", int.class, String.class), 1, "a") .asMap()); } /** * Multiple arguments have @PartitionKey annotations. */ @Test public void testMultiplePartitionKeys() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); assertEquals(ImmutableMap.<String, Object>of("", "one", "b", "two", "c", "three"), contextSupplier.forCall( MyService.class.getMethod("threeKey", String.class, String.class, String.class), "one", "two", "three").asMap()); } /** * Implementation return type is more specific than the interface return type (ArrayList vs List) */ @Test public void testCovariant() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyService.class, MyServiceImpl.class); PartitionContext partitionContext = contextSupplier.forCall( MyService.class.getMethod("covariant", String.class), "value"); assertEquals(ImmutableMap.<String, Object>of("", "value"), partitionContext.asMap()); } @Test public void testSubclassInheritedMethod() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyExtendedService.class, MyExtendedServiceImpl.class); PartitionContext partitionContext = contextSupplier.forCall( MyExtendedService.class.getMethod("unnamed", String.class), "value"); assertEquals(ImmutableMap.<String, Object>of("", "value"), partitionContext.asMap()); } @Test public void testSubclassNewMethod() throws Exception { PartitionContextSupplier contextSupplier = new AnnotationPartitionContextSupplier(MyExtendedService.class, MyExtendedServiceImpl.class); PartitionContext partitionContext = contextSupplier.forCall( MyExtendedService.class.getMethod("extension", String.class), "value"); assertEquals(ImmutableMap.<String, Object>of("", "value"), partitionContext.asMap()); } private static interface MyService { void noArgs(); void unnamed(String string); void named(String string); void overloaded(int num); void overloaded(String string); void noKey(boolean flag); void twoArgsOneKey(int num, String string); void threeKey(String a1, String a2, String a3); List<?> covariant(String string); } private static interface MyExtendedService extends MyService { void extension(String string); } private static class MyServiceImpl implements MyService { @Override public void noArgs() {} @Override public void unnamed(@PartitionKey String string) {} @Override public void named(@PartitionKey ("n") String string) {} @Override public void overloaded(@PartitionKey ("string") String string) {} @Override public void overloaded(@PartitionKey ("int") int num) {} @Override public void noKey(boolean flag) {} @Override public void twoArgsOneKey(int num, @PartitionKey String string) {} @Override public void threeKey(@PartitionKey String x, @PartitionKey ("b") String y, @PartitionKey ("c") String z) {} @Override public ArrayList<?> covariant(@PartitionKey String string) {return null;} } private static class MyExtendedServiceImpl extends MyServiceImpl implements MyExtendedService { @Override public void extension(@PartitionKey String string) { } } private static class MyServiceDup extends MyServiceImpl { @Override public void twoArgsOneKey(@PartitionKey int num, @PartitionKey String string) {} } }