001 // Copyright 2004, 2005 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.junit.utils; 016 017 import java.io.File; 018 import java.io.Serializable; 019 import java.lang.reflect.Constructor; 020 import java.math.BigDecimal; 021 import java.net.URL; 022 import java.net.URLClassLoader; 023 import java.util.HashMap; 024 import java.util.Map; 025 026 import org.apache.hivemind.ApplicationRuntimeException; 027 import org.apache.hivemind.ClassResolver; 028 import org.apache.hivemind.impl.DefaultClassResolver; 029 import org.apache.hivemind.util.PropertyUtils; 030 import org.apache.tapestry.BaseComponentTestCase; 031 import org.apache.tapestry.services.DataSqueezer; 032 import org.apache.tapestry.util.ComponentAddress; 033 import org.apache.tapestry.util.io.DataSqueezerImpl; 034 import org.apache.tapestry.util.io.DataSqueezerUtil; 035 import org.apache.tapestry.util.io.SerializableAdaptor; 036 import org.apache.tapestry.util.io.SqueezeAdaptor; 037 import org.testng.annotations.Test; 038 039 /** 040 * A series of tests for {@link DataSqueezerImpl} and friends. 041 * 042 * @author Howard Lewis Ship 043 */ 044 @Test 045 public class TestDataSqueezer extends BaseComponentTestCase 046 { 047 private DataSqueezerImpl ds = DataSqueezerUtil.createUnitTestSqueezer(); 048 049 public TestDataSqueezer(String name) 050 { 051 } 052 053 private void attempt(Object input, String expectedEncoding) 054 { 055 attempt(input, expectedEncoding, ds); 056 } 057 058 private void attempt(Object input, String expectedEncoding, DataSqueezer squeezer) 059 060 { 061 String encoding = squeezer.squeeze(input); 062 063 assertEquals(expectedEncoding, encoding); 064 065 Object output = squeezer.unsqueeze(encoding); 066 067 assertEquals(input, output); 068 } 069 070 public void testBoolean() 071 { 072 attempt(Boolean.TRUE, "T"); 073 attempt(Boolean.FALSE, "F"); 074 } 075 076 public void testNull() 077 { 078 attempt(null, "X"); 079 } 080 081 public void testByte() 082 { 083 attempt(new Byte((byte) 0), "b0"); 084 attempt(new Byte((byte) -5), "b-5"); 085 attempt(new Byte((byte) 72), "b72"); 086 } 087 088 public void testFloat() 089 { 090 attempt(new Float(0), "f0.0"); 091 attempt(new Float(3.1459), "f3.1459"); 092 attempt(new Float(-37.23), "f-37.23"); 093 } 094 095 public void testDouble() 096 { 097 attempt(new Double(0), "d0.0"); 098 attempt(new Double(3.1459), "d3.1459"); 099 attempt(new Double(-37.23), "d-37.23"); 100 } 101 102 public void testInteger() 103 { 104 attempt(new Integer(0), "0"); 105 attempt(new Integer(205), "205"); 106 attempt(new Integer(-173), "-173"); 107 } 108 109 public void testLong() 110 { 111 attempt(new Long(0), "l0"); 112 attempt(new Long(800400300l), "l800400300"); 113 attempt(new Long(-987654321l), "l-987654321"); 114 } 115 116 public void testShort() 117 { 118 attempt(new Short((short) 0), "s0"); 119 attempt(new Short((short) -10), "s-10"); 120 attempt(new Short((short) 57), "s57"); 121 } 122 123 /** @since 2.2 * */ 124 125 public void testCharacter() 126 { 127 attempt(new Character('a'), "ca"); 128 attempt(new Character('Z'), "cZ"); 129 } 130 131 public void test_Empty_Value() 132 { 133 Object output = ds.unsqueeze(""); 134 135 assert output == null; 136 } 137 138 public void testString() 139 { 140 attempt("Now is the time for all good men ...", "SNow is the time for all good men ..."); 141 attempt("X marks the spot!", "SX marks the spot!"); 142 attempt("So long, sucker!", "SSo long, sucker!"); 143 } 144 145 public void testComponentAddress() 146 { 147 ComponentAddress objAddress = new ComponentAddress("framework:DirectLink", 148 "component.subcomponent"); 149 attempt(objAddress, "Aframework:DirectLink,component.subcomponent"); 150 151 objAddress = new ComponentAddress("framework:DirectLink", null); 152 attempt(objAddress, "Aframework:DirectLink,"); 153 } 154 155 public void testArray() 156 { 157 Object[] input = 158 { new Short((short) -82), "Time to encode an array.", new Long(38383833273789l), null, 159 Boolean.TRUE, new Double(22. / 7.) }; 160 161 String[] encoded = ds.squeeze(input); 162 163 assertEquals(input.length, encoded.length); 164 165 Object[] output = ds.unsqueeze(encoded); 166 167 assertEquals(input.length, output.length); 168 169 for (int i = 0; i < input.length; i++) 170 { 171 assertEquals(input[i], output[i]); 172 } 173 } 174 175 public void testNullArray() 176 { 177 Object[] input = null; 178 179 String[] encoded = ds.squeeze(input); 180 181 assertNull(encoded); 182 183 Object[] output = ds.unsqueeze(encoded); 184 185 assertNull(output); 186 } 187 188 private void attempt(Serializable s, DataSqueezer squeezer) 189 { 190 String encoded = squeezer.squeeze(s); 191 192 Object output = squeezer.unsqueeze(encoded); 193 194 assertEquals(s, output); 195 } 196 197 public void testSerializableShort() 198 { 199 attempt(new StringHolder("X"), ds); 200 } 201 202 public void testSerializableLong() 203 { 204 205 Map map = new HashMap(); 206 207 map.put("alpha", Boolean.TRUE); 208 map.put("beta", new StringHolder("FredFlintstone")); 209 map.put("gamma", new BigDecimal( 210 "2590742358742358972.234592348957230948578975248972390857490725")); 211 212 attempt((Serializable) map, ds); 213 } 214 215 public static class BooleanHolder 216 { 217 private boolean value; 218 219 public BooleanHolder() 220 { 221 } 222 223 public BooleanHolder(boolean value) 224 { 225 this.value = value; 226 } 227 228 public boolean getValue() 229 { 230 return value; 231 } 232 233 public void setValue(boolean value) 234 { 235 this.value = value; 236 } 237 238 public boolean equals(Object other) 239 { 240 if (other == null) 241 return false; 242 243 if (this == other) 244 return true; 245 246 if (!(other instanceof BooleanHolder)) 247 return false; 248 249 BooleanHolder otherHolder = (BooleanHolder) other; 250 251 return value == otherHolder.value; 252 } 253 } 254 255 public static class BHSqueezer implements SqueezeAdaptor 256 { 257 private final String prefix_; 258 259 private final Class dataClass_; 260 261 private static final String TRUE = "BT"; 262 263 private static final String FALSE = "BF"; 264 265 public BHSqueezer() 266 { 267 this("B", BooleanHolder.class); 268 } 269 270 public BHSqueezer(String prefix) 271 { 272 this(prefix, BooleanHolder.class); 273 } 274 275 public BHSqueezer(String prefix, Class dataClass) 276 { 277 prefix_ = prefix; 278 dataClass_ = dataClass; 279 } 280 281 public String getPrefix() 282 { 283 return prefix_; 284 } 285 286 public Class getDataClass() 287 { 288 return dataClass_; 289 } 290 291 public String squeeze(DataSqueezer squeezer, Object data) 292 { 293 BooleanHolder h = (BooleanHolder) data; 294 295 return h.getValue() ? TRUE : FALSE; 296 } 297 298 public Object unsqueeze(DataSqueezer squeezer, String string) 299 { 300 if (string.equals(TRUE)) 301 return new BooleanHolder(true); 302 303 if (string.equals(FALSE)) 304 return new BooleanHolder(false); 305 306 throw new ApplicationRuntimeException("Unexpected value."); 307 } 308 309 } 310 311 public void testCustom() 312 { 313 DataSqueezerImpl squeezer = DataSqueezerUtil.createUnitTestSqueezer(); 314 squeezer.register(new BHSqueezer()); 315 316 attempt(new BooleanHolder(true), "BT", squeezer); 317 attempt(new BooleanHolder(false), "BF", squeezer); 318 319 attempt("BooleanHolder", "SBooleanHolder", squeezer); 320 } 321 322 public void testRegisterShortPrefix() 323 { 324 try 325 { 326 ds.register(new BHSqueezer("")); 327 328 throw new AssertionError("Null prefix should be invalid."); 329 } 330 catch (IllegalArgumentException ex) 331 { 332 } 333 } 334 335 public void testRegisterInvalidPrefix() 336 { 337 try 338 { 339 ds.register(new BHSqueezer("\n")); 340 341 throw new AssertionError("Prefix should be invalid."); 342 } 343 catch (IllegalArgumentException ex) 344 { 345 } 346 } 347 348 public void testRegisterDupePrefix() 349 { 350 try 351 { 352 ds.register(new BHSqueezer("b")); 353 354 throw new AssertionError("Duplicate prefix should be invalid."); 355 } 356 catch (IllegalArgumentException ex) 357 { 358 } 359 } 360 361 public void testRegisterNullClass() 362 { 363 try 364 { 365 ds.register(new BHSqueezer("B", null)); 366 367 throw new AssertionError("Null data class should be invalid."); 368 } 369 catch (IllegalArgumentException ex) 370 { 371 } 372 } 373 374 public void testRegisterNullSqueezer() 375 { 376 try 377 { 378 ds.register(null); 379 380 throw new AssertionError("Null squeezer should be invalid."); 381 } 382 catch (IllegalArgumentException ex) 383 { 384 } 385 } 386 387 public void testClassLoader() throws Exception 388 { 389 File springJAR = new File("tapestry-framework/src/test-data/spring-1.1.jar"); 390 if (!springJAR.exists()) 391 springJAR = new File("src/test-data/spring-1.1.jar"); 392 393 if (!springJAR.exists()) 394 throw new RuntimeException("File " + springJAR 395 + " does not exist; this should have been downloaded by the Ant build scripts."); 396 397 ClassResolver resolver = newClassResolver(springJAR); 398 399 Class propertyValueClass = resolver.findClass("org.springframework.beans.PropertyValue"); 400 Constructor constructor = propertyValueClass.getConstructor(new Class[] 401 { String.class, Object.class }); 402 403 Serializable instance = (Serializable) constructor.newInstance(new Object[] 404 { "fred", "flintstone" }); 405 406 assertEquals("fred", PropertyUtils.read(instance, "name")); 407 assertEquals("flintstone", PropertyUtils.read(instance, "value")); 408 409 DataSqueezer dsq = newDataSqueezer(resolver); 410 411 String encoded = dsq.squeeze(instance); 412 413 // OK; build a whole new class loader & stack to decode that 414 // string back into an object. 415 416 ClassResolver resolver2 = newClassResolver(springJAR); 417 418 DataSqueezer ds2 = newDataSqueezer(resolver2); 419 420 Object output = ds2.unsqueeze(encoded); 421 422 assertEquals("fred", PropertyUtils.read(output, "name")); 423 assertEquals("flintstone", PropertyUtils.read(output, "value")); 424 } 425 426 private ClassResolver newClassResolver(File jarFile) throws Exception 427 { 428 URLClassLoader classLoader = new URLClassLoader(new URL[] 429 { jarFile.toURL() }); 430 431 return new DefaultClassResolver(classLoader); 432 433 } 434 435 private DataSqueezer newDataSqueezer(ClassResolver resolver) 436 { 437 DataSqueezerImpl dsq = new DataSqueezerImpl(); 438 SerializableAdaptor adaptor = new SerializableAdaptor(); 439 adaptor.setResolver(resolver); 440 441 dsq.register(adaptor); 442 return dsq; 443 } 444 }