001: // Copyright 2006, 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.ioc.internal.services;
016:
017: import java.math.BigDecimal;
018: import java.math.BigInteger;
019: import java.util.Arrays;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
026: import org.apache.tapestry.ioc.services.TypeCoercer;
027: import org.testng.annotations.AfterClass;
028: import org.testng.annotations.BeforeClass;
029: import org.testng.annotations.DataProvider;
030: import org.testng.annotations.Test;
031: import org.xml.sax.XMLReader;
032:
033: public class TypeCoercerImplTest extends IOCInternalTestCase {
034: private TypeCoercer _coercer;
035:
036: @BeforeClass
037: public void setup_coercer() {
038: _coercer = getService(TypeCoercer.class);
039: }
040:
041: @AfterClass
042: public void cleanup_coercer() {
043: _coercer = null;
044: }
045:
046: @Test
047: public void builtin_coercion() {
048: // String to Double
049:
050: assertEquals(_coercer.coerce("-15", Double.class), new Double(
051: -15));
052:
053: // Now a second pass through, to exercise the internal cache
054:
055: assertEquals(_coercer.coerce("2.27", Double.class), new Double(
056: 2.27));
057: }
058:
059: @Test
060: public void primitive_type_as_target() {
061: assertEquals(_coercer.coerce(227l, int.class), new Integer(227));
062: }
063:
064: @Test
065: public void no_coercion_necessary() {
066: Object input = new Integer(-37);
067:
068: assertSame(_coercer.coerce(input, Number.class), input);
069: }
070:
071: @Test
072: public void combined_coercion() {
073: StringBuilder builder = new StringBuilder("12345");
074:
075: // This should trigger Object -> String, String -> Integer
076:
077: assertEquals(_coercer.coerce(builder, int.class), new Integer(
078: 12345));
079:
080: // This should trigger String -> Double, Number -> Integer
081:
082: assertEquals(_coercer.coerce("52", Integer.class), new Integer(
083: 52));
084: }
085:
086: @Test
087: public void no_coercion_found() {
088: try {
089: _coercer.coerce("", Map.class);
090: unreachable();
091: } catch (IllegalArgumentException ex) {
092: assertTrue(ex
093: .getMessage()
094: .contains(
095: "Could not find a coercion from type java.lang.String to type java.util.Map"));
096: }
097: }
098:
099: @Test
100: public void coercion_failure() {
101: try {
102: _coercer.coerce(Collections.EMPTY_MAP, Float.class);
103: unreachable();
104: } catch (RuntimeException ex) {
105: assertTrue(ex
106: .getMessage()
107: .contains(
108: "Coercion of {} to type java.lang.Float (via Object --> String, String --> Double, Double --> Float) failed"));
109: assertTrue(ex.getCause() instanceof NumberFormatException);
110: }
111: }
112:
113: @SuppressWarnings("unchecked")
114: @Test(dataProvider="coercions_inputs")
115: public void builtin_coercions(Object input, Class targetType,
116: Object expected) {
117: Object actual = _coercer.coerce(input, targetType);
118:
119: assertEquals(actual, expected);
120: }
121:
122: @SuppressWarnings("unchecked")
123: @DataProvider(name="coercions_inputs")
124: public Object[][] coercions_inputs() {
125: String bigDecimalValue = "12345656748352435842385234598234958234574358723485.35843534285293857298457234587";
126: String bigIntegerValue = "12384584574874385743";
127:
128: Object object = new Object();
129: // Over time, some of these may evolve from testing specific tuples to
130: // compound tuples (built around specific tuples).
131:
132: Float floatValue = new Float(31.14);
133: return new Object[][] {
134: // There's a lot of these!
135:
136: { this , String.class, toString() },
137: { 55l, Integer.class, 55 },
138: { "", Boolean.class, false },
139: { " ", Boolean.class, false },
140: { "x", Boolean.class, true },
141: { " z ", Boolean.class, true },
142: { "false", Boolean.class, false },
143: { " False ", Boolean.class, false },
144: { null, Boolean.class, false },
145: { new Double(256), Integer.class, new Integer(256) },
146: { new Double(22.7), Integer.class, new Integer(22) },
147: { new Integer(0), Boolean.class, false },
148: { new Long(32838), Boolean.class, true },
149: { new Integer(127), Byte.class, new Byte("127") },
150: { new Double(58), Short.class, new Short("58") },
151: { new Integer(33), Long.class, new Long(33) },
152: { new Integer(22), Float.class, new Float(22) },
153: { new Integer(1234), Double.class, new Double(1234) },
154: { floatValue, Double.class, floatValue.doubleValue() },
155: { Collections.EMPTY_LIST, Boolean.class, false },
156: { Collections.singleton(this ), Boolean.class, true },
157: { bigDecimalValue, BigDecimal.class,
158: new BigDecimal(bigDecimalValue) },
159: { new BigDecimal(bigDecimalValue), Double.class,
160: 1.2345656748352436E49 },
161: { bigIntegerValue, BigInteger.class,
162: new BigInteger(bigIntegerValue) },
163: { new BigInteger("12345678"), Long.class, 12345678l },
164: { -12345678l, BigInteger.class,
165: new BigInteger("-12345678") },
166: { object, List.class, Collections.singletonList(object) },
167: { null, Iterable.class, null },
168: { null, List.class, null },
169: { null, Collection.class, null },
170: { null, String.class, null },
171: { new Object[] { "a", 123 }, List.class,
172: Arrays.asList("a", 123) },
173: { new String[] { "a", "b" }, List.class,
174: Arrays.asList("a", "b") },
175:
176: // null to arbitrary object is still null
177:
178: { null, XMLReader.class, null } };
179: }
180:
181: @Test(dataProvider="explain_inputs")
182: public <S, T> void explain(Class<S> inputType, Class<T> outputType,
183: String expected) {
184: assertEquals(_coercer.explain(inputType, outputType), expected);
185: }
186:
187: @DataProvider(name="explain_inputs")
188: public Object[][] explain_inputs() {
189: return new Object[][] {
190: { StringBuffer.class, Integer.class,
191: "Object --> String, String --> Long, Long --> Integer" },
192: { void.class, Map.class, "null --> null" },
193: { void.class, Boolean.class, "null --> Boolean" },
194: { String[].class, List.class,
195: "Object[] --> java.util.List" },
196: { Float.class, Double.class, "Float --> Double" },
197: { Double.class, BigDecimal.class,
198: "Object --> String, String --> java.math.BigDecimal" },
199:
200: };
201: }
202:
203: }
|