| // Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation |
| // |
| // 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 org.apache.tapestry5.ioc.internal.util; |
| |
| import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap; |
| import static org.apache.tapestry5.ioc.internal.util.InternalUtils.toList; |
| import static org.easymock.EasyMock.eq; |
| import static org.easymock.EasyMock.isA; |
| |
| import java.io.Closeable; |
| import java.io.IOException; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Enumeration; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.tapestry5.func.F; |
| import org.apache.tapestry5.func.Predicate; |
| import org.apache.tapestry5.ioc.AnnotationProvider; |
| import org.apache.tapestry5.ioc.Locatable; |
| import org.apache.tapestry5.ioc.Location; |
| import org.apache.tapestry5.ioc.ObjectCreator; |
| import org.apache.tapestry5.ioc.ObjectLocator; |
| import org.apache.tapestry5.ioc.OperationTracker; |
| import org.apache.tapestry5.ioc.ScopeConstants; |
| import org.apache.tapestry5.ioc.ServiceBuilderResources; |
| import org.apache.tapestry5.ioc.annotations.Inject; |
| import org.apache.tapestry5.ioc.def.ServiceDef; |
| import org.apache.tapestry5.ioc.def.ServiceDef2; |
| import org.apache.tapestry5.ioc.internal.QuietOperationTracker; |
| import org.apache.tapestry5.ioc.services.Builtin; |
| import org.apache.tapestry5.ioc.services.Coercion; |
| import org.apache.tapestry5.ioc.services.SymbolSource; |
| import org.apache.tapestry5.ioc.test.IOCTestCase; |
| import org.easymock.EasyMock; |
| import org.easymock.IAnswer; |
| import org.testng.annotations.DataProvider; |
| import org.testng.annotations.Test; |
| |
| public class InternalUtilsTest extends IOCTestCase |
| { |
| private final OperationTracker tracker = new QuietOperationTracker(); |
| |
| private static class PrivateInnerClass |
| { |
| public PrivateInnerClass() |
| { |
| } |
| } |
| |
| public static class PublicInnerClass |
| { |
| protected PublicInnerClass() |
| { |
| } |
| } |
| |
| @Test |
| public void method_as_string_no_args() throws Exception |
| { |
| |
| Method m = Object.class.getMethod("toString"); |
| |
| assertEquals(InternalUtils.asString(m), "java.lang.Object.toString()"); |
| } |
| |
| @Test |
| public void method_as_string_with_args() throws Exception |
| { |
| Method m = Collections.class.getMethod("sort", List.class, Comparator.class); |
| |
| assertEquals(InternalUtils.asString(m), "java.util.Collections.sort(List, Comparator)"); |
| } |
| |
| @Test |
| public void method_as_string_primitive_arg() throws Exception |
| { |
| Method m = Object.class.getMethod("wait", long.class); |
| |
| assertEquals(InternalUtils.asString(m), "java.lang.Object.wait(long)"); |
| } |
| |
| @Test |
| public void method_as_string_primitive_array_arg() throws Exception |
| { |
| Method m = Arrays.class.getMethod("sort", int[].class); |
| |
| assertEquals(InternalUtils.asString(m), "java.util.Arrays.sort(int[])"); |
| } |
| |
| @Test |
| public void method_as_string_array_arg() throws Exception |
| { |
| Method m = Arrays.class.getMethod("sort", Object[].class); |
| |
| assertEquals(InternalUtils.asString(m), "java.util.Arrays.sort(Object[])"); |
| } |
| |
| @Test |
| public void array_size_when_null() |
| { |
| Object[] array = null; |
| |
| assertEquals(InternalUtils.size(array), 0); |
| } |
| |
| @Test |
| public void array_size_when_non_null() |
| { |
| Object[] array = |
| { 1, 2, 3 }; |
| |
| assertEquals(InternalUtils.size(array), 3); |
| } |
| |
| @Test(dataProvider = "memberNameData") |
| public void strip_member_name(String input, String expected) |
| { |
| assertEquals(InternalUtils.stripMemberName(input), expected); |
| } |
| |
| @DataProvider |
| public Object[][] memberNameData() |
| { |
| return new Object[][] |
| { |
| { "simple", "simple" }, |
| { "_name", "name" }, |
| { "$name", "name" }, |
| { "ruby_style", "ruby_style" }, |
| { "__$ruby_style_", "ruby_style" }, |
| { "$_$__$__$_$___$_$_$_$$name$", "name" }, |
| { "foo_", "foo" }, |
| { "_foo_", "foo" } }; |
| } |
| |
| @Test |
| public void strip_illegal_member_name() |
| { |
| try |
| { |
| InternalUtils.stripMemberName("!foo"); |
| unreachable(); |
| } |
| catch (IllegalArgumentException ex) |
| { |
| assertEquals(ex.getMessage(), "Input '!foo' is not a valid Java identifier."); |
| } |
| } |
| |
| @Test |
| public void enumeration_to_list() |
| { |
| List<String> input = Arrays.asList("wilma", "fred", "barney"); |
| Enumeration e = Collections.enumeration(input); |
| |
| List<String> output = toList(e); |
| |
| assertEquals(output, Arrays.asList("barney", "fred", "wilma")); |
| } |
| |
| @Test |
| public void join_empty_list() |
| { |
| List<String> empty = CollectionFactory.newList(); |
| |
| assertEquals(InternalUtils.join(empty), ""); |
| } |
| |
| @Test |
| public void join_single() |
| { |
| List<String> single = Arrays.asList("barney"); |
| |
| assertEquals(InternalUtils.join(single), "barney"); |
| } |
| |
| @Test |
| public void join_multiple() |
| { |
| List<String> many = Arrays.asList("fred", "barney", "wilma"); |
| assertEquals(InternalUtils.join(many), "fred, barney, wilma"); |
| } |
| |
| @Test |
| public void join_with_blank() |
| { |
| List<String> many = Arrays.asList("fred", "barney", "", "wilma"); |
| assertEquals(InternalUtils.join(many), "fred, barney, (blank), wilma"); |
| } |
| |
| @Test |
| public void join_sorted() |
| { |
| List<String> unsorted = Arrays.asList("betty", "fred", "barney", "wilma"); |
| List<String> copy = CollectionFactory.newList(unsorted); |
| |
| assertEquals(InternalUtils.joinSorted(copy), "barney, betty, fred, wilma"); |
| |
| // Make sure that joinSorted() doesn't change the input list |
| |
| assertEquals(copy, unsorted); |
| } |
| |
| @Test |
| public void join_sorted_with_blank() |
| { |
| List<String> unsorted = Arrays.asList("betty", "fred", "barney", "", "wilma"); |
| |
| assertEquals(InternalUtils.joinSorted(unsorted), "(blank), barney, betty, fred, wilma"); |
| } |
| |
| @Test(dataProvider = "capitalize_inputs") |
| public void capitalize(String input, String expected) |
| { |
| assertEquals(InternalUtils.capitalize(input), expected); |
| } |
| |
| @DataProvider(name = "capitalize_inputs") |
| public Object[][] capitalize_inputs() |
| { |
| return new Object[][] |
| { |
| { "hello", "Hello" }, |
| { "Goodbye", "Goodbye" }, |
| { "", "" }, |
| { "a", "A" }, |
| { "A", "A" } }; |
| } |
| |
| @Test |
| public void location_of_not_found() |
| { |
| assertNull(InternalUtils.locationOf(null)); |
| assertNull(InternalUtils.locationOf("La! La!")); |
| } |
| |
| @Test |
| public void location_of_location() |
| { |
| Location l = mockLocation(); |
| |
| replay(); |
| |
| assertSame(l, InternalUtils.locationOf(l)); |
| |
| verify(); |
| } |
| |
| @Test |
| public void location_of_locatable() |
| { |
| Location l = mockLocation(); |
| Locatable locatable = newMock(Locatable.class); |
| |
| expect(locatable.getLocation()).andReturn(l); |
| |
| replay(); |
| |
| assertSame(l, InternalUtils.locationOf(locatable)); |
| |
| verify(); |
| } |
| |
| @Test |
| public void sorted_keys_from_null_map() |
| { |
| List<String> list = InternalUtils.sortedKeys(null); |
| |
| assertTrue(list.isEmpty()); |
| } |
| |
| @Test |
| public void sorted_keys_from_map() |
| { |
| Map<String, String> map = newMap(); |
| |
| map.put("fred", "flintstone"); |
| map.put("barney", "rubble"); |
| |
| assertEquals(InternalUtils.sortedKeys(map), Arrays.asList("barney", "fred")); |
| } |
| |
| @Test |
| public void get_from_null_map() |
| { |
| assertNull(InternalUtils.get(null, null)); |
| } |
| |
| @Test |
| public void get_from_map() |
| { |
| Map<String, String> map = newMap(); |
| |
| map.put("fred", "flintstone"); |
| |
| assertEquals("flintstone", InternalUtils.get(map, "fred")); |
| } |
| |
| @Test |
| public void reverse_iterator() |
| { |
| List<String> list = Arrays.asList("a", "b", "c"); |
| |
| Iterator<String> i = InternalUtils.reverseIterator(list); |
| |
| assertTrue(i.hasNext()); |
| assertEquals(i.next(), "c"); |
| |
| assertTrue(i.hasNext()); |
| assertEquals(i.next(), "b"); |
| |
| assertTrue(i.hasNext()); |
| assertEquals(i.next(), "a"); |
| |
| assertFalse(i.hasNext()); |
| } |
| |
| @Test |
| public void reverse_iterator_does_not_support_remove() |
| { |
| List<String> list = Arrays.asList("a", "b", "c"); |
| |
| Iterator<String> i = InternalUtils.reverseIterator(list); |
| |
| try |
| { |
| i.remove(); |
| unreachable(); |
| } |
| catch (UnsupportedOperationException ex) |
| { |
| |
| } |
| } |
| |
| @Test |
| public void last_term() |
| { |
| String input = "SimpleInput"; |
| |
| assertSame(InternalUtils.lastTerm(input), input); |
| |
| assertEquals(InternalUtils.lastTerm("fie.fie.foe.fum"), "fum"); |
| } |
| |
| @Test |
| public void add_to_list_map() |
| { |
| Map<String, List<Integer>> map = CollectionFactory.newMap(); |
| |
| InternalUtils.addToMapList(map, "fred", 1); |
| |
| assertEquals(map.get("fred"), Arrays.asList(1)); |
| |
| InternalUtils.addToMapList(map, "fred", 2); |
| |
| assertEquals(map.get("fred"), Arrays.asList(1, 2)); |
| } |
| |
| // Test the check for runtime annotation. This is all well and good, we actually don't have a proper test |
| // that this code is used (ideally we should have tests for @Marker on a module, on a service impl, and passed |
| // to ServiceBindingOptions.withMarker(), to prove that those are wired for checks. |
| |
| @Test |
| public void validate_marker_annotation() |
| { |
| InternalUtils.validateMarkerAnnotation(Inject.class); |
| |
| try |
| { |
| InternalUtils.validateMarkerAnnotations(new Class[] |
| { Inject.class, NotRetainedRuntime.class }); |
| unreachable(); |
| } |
| catch (IllegalArgumentException ex) |
| { |
| assertEquals( |
| ex.getMessage(), |
| "Marker annotation class org.apache.tapestry5.ioc.internal.util.NotRetainedRuntime is not valid because it is not visible at runtime. Add a @Retention(RetentionPolicy.RUNTIME) to the class."); |
| } |
| } |
| |
| @Test |
| public void join_sorted_null() |
| { |
| assertEquals(InternalUtils.joinSorted(null), "(none)"); |
| } |
| |
| @Test |
| public void join_sorted_empty() |
| { |
| assertEquals(InternalUtils.joinSorted(Collections.emptyList()), "(none)"); |
| } |
| |
| @Test |
| public void close_null_is_noop() |
| { |
| InternalUtils.close(null); |
| } |
| |
| @Test |
| public void close_success() throws Exception |
| { |
| Closeable c = newMock(Closeable.class); |
| |
| c.close(); |
| |
| replay(); |
| |
| InternalUtils.close(c); |
| |
| verify(); |
| } |
| |
| @Test |
| public void close_ignores_exceptions() throws Exception |
| { |
| Closeable c = newMock(Closeable.class); |
| |
| c.close(); |
| setThrowable(new IOException()); |
| |
| replay(); |
| |
| InternalUtils.close(c); |
| |
| verify(); |
| } |
| |
| @Test |
| public void constructor_with_inject_annotation() |
| { |
| Constructor c = InternalUtils.findAutobuildConstructor(InjectoBean.class); |
| |
| assertEquals(c.getParameterTypes().length, 1); |
| assertEquals(c.getParameterTypes()[0], String.class); |
| } |
| |
| @Test |
| public void validate_constructor_class_not_public() |
| { |
| Class clazz = PrivateInnerClass.class; |
| Constructor cons = clazz.getConstructors()[0]; |
| |
| try |
| { |
| InternalUtils.validateConstructorForAutobuild(cons); |
| unreachable(); |
| } |
| catch (IllegalArgumentException ex) |
| { |
| assertEquals( |
| ex.getMessage(), |
| "Class org.apache.tapestry5.ioc.internal.util.InternalUtilsTest$PrivateInnerClass is not a public class and may not be autobuilt."); |
| } |
| } |
| |
| @Test |
| public void validate_constructor_check_for_public() |
| { |
| Class clazz = PublicInnerClass.class; |
| Constructor cons = clazz.getDeclaredConstructors()[0]; |
| |
| try |
| { |
| InternalUtils.validateConstructorForAutobuild(cons); |
| unreachable(); |
| } |
| catch (IllegalArgumentException ex) |
| { |
| assertMessageContains( |
| ex, |
| "Constructor protected org.apache.tapestry5.ioc.internal.util.InternalUtilsTest$PublicInnerClass() is not public and may not be used for autobuilding an instance of the class."); |
| } |
| } |
| |
| @Test |
| public void inject_service_annotation_on_field() |
| { |
| ObjectLocator ol = mockObjectLocator(); |
| FieldInjectionViaInjectService target = new FieldInjectionViaInjectService(); |
| Runnable fred = mockRunnable(); |
| |
| train_getService(ol, "FredService", Runnable.class, fred); |
| |
| replay(); |
| |
| InternalUtils.injectIntoFields(target, ol, null, tracker); |
| |
| assertSame(target.getFred(), fred); |
| |
| verify(); |
| } |
| |
| @Test |
| public void inject_annotation_on_field() |
| { |
| ObjectLocator ol = mockObjectLocator(); |
| FieldInjectionViaInject target = new FieldInjectionViaInject(); |
| final SymbolSource ss = mockSymbolSource(); |
| |
| IAnswer answer = new IAnswer() |
| { |
| public Object answer() throws Throwable |
| { |
| Object[] args = EasyMock.getCurrentArguments(); |
| |
| AnnotationProvider ap = (AnnotationProvider) args[1]; |
| |
| // Verify that annotations on the field are accessible. |
| |
| assertNotNull(ap.getAnnotation(Builtin.class)); |
| |
| return ss; |
| } |
| }; |
| |
| expect(ol.getObject(eq(SymbolSource.class), isA(AnnotationProvider.class))).andAnswer(answer); |
| |
| replay(); |
| |
| InternalUtils.injectIntoFields(target, ol, null, tracker); |
| |
| assertSame(target.getSymbolSource(), ss); |
| |
| verify(); |
| } |
| |
| @Test |
| public void exception_injecting_into_field() |
| { |
| ObjectLocator ol = mockObjectLocator(); |
| FieldInjectionViaInjectService target = new FieldInjectionViaInjectService(); |
| |
| // It's very hard to come up with a value that causes an error when assigned. We have to break |
| // a lot of rules. |
| |
| ol.getService("FredService", Runnable.class); |
| EasyMock.expectLastCall().andReturn("NotTheRightType"); |
| |
| replay(); |
| |
| try |
| { |
| InternalUtils.injectIntoFields(target, ol, null, tracker); |
| |
| unreachable(); |
| } |
| catch (Exception ex) |
| { |
| assertMessageContains(ex, |
| "Unable to set field 'fred' of <FieldInjectionViaInjectService> to NotTheRightType"); |
| } |
| |
| verify(); |
| } |
| |
| @Test |
| public void keys_on_null_is_empty() |
| { |
| assertTrue(InternalUtils.keys(null).isEmpty()); |
| } |
| |
| @Test |
| public void keys_on_actual_map() |
| { |
| Map<String, Integer> map = CollectionFactory.newMap(); |
| |
| map.put("frobozz", 41); |
| map.put("gnip", 97); |
| |
| assertSame(InternalUtils.keys(map), map.keySet()); |
| } |
| |
| @Test |
| public void collection_size() |
| { |
| Collection c = null; |
| |
| assertEquals(InternalUtils.size(c), 0); |
| |
| c = Arrays.asList("moe", "larry", "curly"); |
| |
| assertEquals(InternalUtils.size(c), 3); |
| } |
| |
| @Test |
| public void servicedef_to_servicedef2() |
| { |
| final ObjectCreator oc = mockObjectCreator(); |
| final String serviceId = "RocketLauncher"; |
| final Set<Class> markers = Collections.emptySet(); |
| final Class serviceInterface = Runnable.class; |
| |
| ServiceDef sd = new ServiceDef() |
| { |
| public ObjectCreator createServiceCreator(ServiceBuilderResources resources) |
| { |
| return oc; |
| } |
| |
| public String getServiceId() |
| { |
| return serviceId; |
| } |
| |
| public Set<Class> getMarkers() |
| { |
| return markers; |
| } |
| |
| public Class getServiceInterface() |
| { |
| return serviceInterface; |
| } |
| |
| public String getServiceScope() |
| { |
| return ScopeConstants.PERTHREAD; |
| } |
| |
| public boolean isEagerLoad() |
| { |
| return true; |
| } |
| }; |
| |
| replay(); |
| |
| ServiceDef2 sd2 = InternalUtils.toServiceDef2(sd); |
| |
| assertSame(sd2.createServiceCreator(null), oc); |
| assertSame(sd2.getServiceId(), serviceId); |
| assertSame(sd2.getMarkers(), markers); |
| assertSame(sd2.getServiceInterface(), serviceInterface); |
| assertSame(sd2.getServiceScope(), ScopeConstants.PERTHREAD); |
| assertTrue(sd2.isEagerLoad()); |
| assertFalse(sd2.isPreventDecoration()); |
| |
| verify(); |
| } |
| |
| @Test |
| public void match_and_sort() |
| { |
| List<String> input = CollectionFactory.newList("Fred", "Barney", "..", ".hidden", "Wilma"); |
| |
| List<String> output = InternalUtils.matchAndSort(input, new Predicate<String>() |
| { |
| public boolean accept(String object) |
| { |
| return !object.startsWith("."); |
| } |
| }); |
| |
| assertListsEquals(output, "Barney", "Fred", "Wilma"); |
| } |
| |
| @Test |
| public void wrap_coercion_as_mapper() |
| { |
| Coercion<String, String> toUpper = new Coercion<String, String>() |
| { |
| public String coerce(String input) |
| { |
| return input.toUpperCase(); |
| } |
| }; |
| |
| assertListsEquals(F.flow("Mary", "had", "a", "little", "lamb").map(InternalUtils.toMapper(toUpper)).toList(), |
| "MARY", "HAD", "A", "LITTLE", "LAMB"); |
| } |
| } |