1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.castor.xmlctf;
36
37 import java.io.File;
38 import java.io.FileInputStream;
39 import java.io.FileWriter;
40 import java.io.InputStream;
41 import java.io.PrintWriter;
42 import java.io.StringWriter;
43 import java.lang.reflect.Method;
44 import java.util.Enumeration;
45 import java.util.LinkedList;
46 import java.util.List;
47
48 import junit.framework.TestCase;
49
50 import org.castor.xmlctf.util.CTFUtils;
51 import org.exolab.castor.mapping.Mapping;
52 import org.exolab.castor.tests.framework.testDescriptor.CallMethod;
53 import org.exolab.castor.tests.framework.testDescriptor.Configuration;
54 import org.exolab.castor.tests.framework.testDescriptor.ConfigurationType;
55 import org.exolab.castor.tests.framework.testDescriptor.FailureType;
56 import org.exolab.castor.tests.framework.testDescriptor.ListenerType;
57 import org.exolab.castor.tests.framework.testDescriptor.UnitTestCase;
58 import org.exolab.castor.tests.framework.testDescriptor.Value;
59 import org.exolab.castor.tests.framework.testDescriptor.types.FailureStepType;
60 import org.exolab.castor.tests.framework.testDescriptor.types.TypeType;
61 import org.exolab.castor.util.NestedIOException;
62 import org.exolab.castor.xml.MarshalException;
63 import org.exolab.castor.xml.MarshalListener;
64 import org.exolab.castor.xml.Marshaller;
65 import org.exolab.castor.xml.Unmarshaller;
66 import org.exolab.castor.xml.XMLContext;
67 import org.xml.sax.InputSource;
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public abstract class XMLTestCase extends TestCase {
82
83
84 public static boolean _verbose;
85
86 protected static boolean _printStack;
87
88 static {
89 String v = System.getProperty(TestCaseAggregator.VERBOSE_PROPERTY);
90 _verbose = (v != null && v.equals(Boolean.TRUE.toString()));
91
92 v = System.getProperty(TestCaseAggregator.PRINT_STACK_TRACE);
93 _printStack = (v != null && v.equals(Boolean.TRUE.toString()));
94 }
95
96
97 protected String _suiteName;
98
99
100
101
102 protected String _rootClassName;
103
104 protected Class _rootClass;
105
106 protected boolean _hasDump;
107
108
109
110
111 protected Mapping _mapping;
112
113 protected Object _listener;
114
115 protected TypeType _listenerType;
116
117 protected String _listenerGoldFile;
118
119 protected Configuration _configuration;
120
121 protected final String _name;
122
123 protected final UnitTestCase _unitTest;
124
125 protected final File _outputRootFile;
126
127 protected final boolean _skip;
128
129 protected final FailureType _failure;
130
131 protected final CastorTestCase _test;
132
133 private XMLContext _xmlContext;
134
135
136
137
138
139
140 public XMLTestCase(final String name) {
141 super(name);
142 _name = cleanup(name);
143 throw new IllegalArgumentException("You cannot use the name-only constructor");
144 }
145
146
147
148
149
150
151
152 public XMLTestCase(final CastorTestCase test, final UnitTestCase unit) {
153 super(unit.getName());
154 _name = cleanup(unit.getName());
155 _unitTest = unit;
156 _skip = unit.getSkip();
157 _failure = unit.getFailure();
158 _test = test;
159 _outputRootFile = test.getOutputRootFile();
160 _xmlContext = null;
161 }
162
163
164
165
166
167
168
169 public XMLTestCase(final String name, final XMLTestCase tc) {
170 super(name);
171 _name = cleanup(tc._name);
172 _unitTest = tc._unitTest;
173 _outputRootFile = tc._outputRootFile;
174 _skip = tc._skip;
175 _failure = tc._failure;
176 _test = tc._test;
177 _xmlContext = null;
178 }
179
180 protected abstract void setUp() throws Exception;
181
182 protected abstract void tearDown() throws Exception;
183
184 public void setXMLContext(XMLContext xmlContext) {
185 _xmlContext = xmlContext;
186 }
187
188 public XMLContext getXMLContext() {
189 return _xmlContext;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 static String cleanup(final String name) {
204 return name.replaceAll("[\\*()\\t\\n\\r\\f]", " ").replaceAll(" {2,}", " ").trim();
205 }
206
207
208
209
210
211
212
213 public void setTestSuiteName(final String suiteName) {
214 _suiteName = cleanup(suiteName);
215 }
216
217
218
219
220
221
222 public String getTestSuiteName() {
223 return _suiteName;
224 }
225
226
227
228
229
230
231
232
233
234
235 protected boolean checkExceptionWasExpected(final Exception exception,
236 final FailureStepType checkStep) {
237 if (_printStack) {
238 exception.printStackTrace();
239 }
240
241 if (_failure == null || !_failure.getContent()) {
242 return false;
243 }
244 if (checkStep == null) {
245 fail("CTF coding failure ... checkStep should never be null");
246 }
247
248
249
250 String exceptionName = _failure.getException();
251 FailureStepType expectedStep = _failure.getFailureStep();
252
253
254 if (exceptionName == null && expectedStep == null) {
255 return true;
256 }
257
258
259 Exception ex = exception;
260 if (ex instanceof NestedIOException) {
261 ex = ((NestedIOException) ex).getException();
262 }
263
264 if (exceptionName != null) {
265 try {
266 Class expected = Class.forName(exceptionName);
267 if (!expected.isAssignableFrom(ex.getClass())) {
268 String complaint = "Received Exception: '" + ex.getClass().getName() + ": " + ex
269 + "' but expected: '" + exceptionName + "'.";
270
271 StringWriter sw = new StringWriter();
272 PrintWriter pw = new PrintWriter(sw);
273 pw.print(complaint);
274 if (_verbose) {
275 pw.println("Stacktrace for the Exception that was thrown:");
276 ex.printStackTrace(pw);
277 }
278 pw.flush();
279 System.out.println(sw.toString());
280
281 fail(complaint);
282 }
283
284 } catch (ClassNotFoundException cnfex) {
285 fail("The Exception specified: '" + exceptionName + "' cannot be found in the CLASSPATH");
286 }
287 }
288
289
290 if (expectedStep != null && !expectedStep.equals(checkStep)) {
291 fail("We expected to fail at test step '" + expectedStep.toString()
292 + "' but actually failed at step '" + checkStep.toString() + "'");
293 }
294
295
296 return true;
297 }
298
299
300
301
302
303
304
305
306 protected File testMarshal(final Object object, final String fileName) {
307 verbose("--> Marshaling to: '" + fileName + "'");
308
309 File marshalOutput = new File(_outputRootFile, fileName);
310
311 try {
312 Marshaller marshaller = createMarshaler(marshalOutput);
313 marshaller.marshal(object);
314 } catch (Exception e) {
315 if (!checkExceptionWasExpected(e, FailureStepType.MARSHAL_TO_DISK)) {
316 fail("Exception marshaling to disk " + e);
317 }
318 return null;
319 }
320
321 if (_failure != null && _failure.getContent() && _failure.getFailureStep() != null
322 && _failure.getFailureStep().equals(FailureStepType.MARSHAL_TO_DISK)) {
323 fail("Unmarshaling was expected to fail, but succeeded");
324 }
325 return marshalOutput;
326 }
327
328 private Marshaller createMarshaler(final File marshalOutput) throws Exception {
329 getXMLContext().getInternalContext().getXMLClassDescriptorResolver().cleanDescriptorCache();
330 Marshaller marshaller = getXMLContext().createMarshaller();
331 marshaller.setWriter(new FileWriter(marshalOutput));
332
333
334 Configuration config = _unitTest.getConfiguration();
335 if (config == null) {
336 config = _configuration;
337 }
338
339 if (config != null) {
340 ConfigurationType marshal = config.getMarshal();
341 List returnValues = invokeEnumeratedMethods(marshaller, marshal);
342 returnValues.clear();
343 }
344
345 if (_mapping != null) {
346 marshaller.setMapping(_mapping);
347 }
348
349 if (_listener != null && _listener instanceof MarshalListener
350 && _listenerType != TypeType.UNMARSHAL) {
351 marshaller.setMarshalListener((MarshalListener) _listener);
352 }
353 return marshaller;
354 }
355
356
357
358
359
360
361
362
363
364 protected Object testUnmarshal(final File file) throws Exception {
365 verbose("--> Unmarshaling '" + file.getName() + "'\n");
366 try (InputStream inputStream = new FileInputStream(file)) {
367 Object unmarshaledObject = testUnmarshal(inputStream);
368 assertNotNull("Unmarshaling '" + file.getName() + "' results in a NULL object.",
369 unmarshaledObject);
370 return unmarshaledObject;
371 }
372 }
373
374
375
376
377
378
379
380
381 protected Object testUnmarshal(final InputStream stream) throws Exception {
382 Object result = null;
383 final Unmarshaller unmar = createUnmarshaler();
384 result = unmar.unmarshal(new InputSource(stream));
385 return result;
386 }
387
388 private Unmarshaller createUnmarshaler() throws Exception {
389
390 Configuration config = _unitTest.getConfiguration();
391 if (config == null) {
392 config = _configuration;
393 }
394
395 final Unmarshaller unmar;
396 if (_mapping != null) {
397
398 unmar = getXMLContext().createUnmarshaller();
399 unmar.setMapping(_mapping);
400 } else {
401 if (_test.getClassLoader() != null) {
402
403 unmar = getXMLContext().createUnmarshaller();
404 unmar.setClassLoader(_test.getClassLoader());
405 unmar.setClass(_rootClass);
406 } else {
407
408 unmar = getXMLContext().createUnmarshaller();
409 unmar.setClass(_rootClass);
410 }
411 }
412
413 if (_listener != null && _listener instanceof org.exolab.castor.xml.UnmarshalListener
414 && _listenerType != TypeType.MARSHAL) {
415 unmar.setUnmarshalListener((org.exolab.castor.xml.UnmarshalListener) _listener);
416 }
417
418 if (_listener != null && _listener instanceof org.castor.xml.UnmarshalListener
419 && _listenerType != TypeType.MARSHAL) {
420 unmar.setUnmarshalListener((org.castor.xml.UnmarshalListener) _listener);
421 }
422
423 unmar.setDebug(_verbose);
424
425 if (config != null) {
426 ConfigurationType unmarshal = config.getUnmarshal();
427 List returnValues = invokeEnumeratedMethods(unmar, unmarshal);
428 returnValues.clear();
429 }
430
431 return unmar;
432 }
433
434
435
436
437
438
439
440
441
442
443 protected List invokeEnumeratedMethods(final Object objectInvoked, final ConfigurationType config)
444 throws java.lang.Exception {
445 final List returnValues = new LinkedList();
446
447 if (config == null) {
448 return returnValues;
449 }
450
451 Enumeration methods = config.enumerateCallMethod();
452
453 while (methods.hasMoreElements()) {
454 CallMethod method = (CallMethod) methods.nextElement();
455
456 Method toBeinvoked =
457 getInvokeMethod(objectInvoked.getClass(), method.getName(), method.getValue());
458
459 Object[] arguments = getArguments(method.getValue());
460
461 returnValues.add(toBeinvoked.invoke(objectInvoked, arguments));
462 }
463
464 return returnValues;
465 }
466
467
468
469
470
471
472
473
474
475 protected void initializeListeners(final ListenerType listener)
476 throws ClassNotFoundException, IllegalAccessException, InstantiationException {
477 String listenerClassName = listener.getClassName();
478 if (listenerClassName == null || listenerClassName.length() == 0) {
479 throw new IllegalArgumentException("ClassName must be provided for Listener element.");
480 }
481
482 final Class listenerClass;
483 if (_test.getClassLoader() != null) {
484 listenerClass = _test.getClassLoader().loadClass(listenerClassName);
485 } else {
486 listenerClass = Thread.currentThread().getContextClassLoader().loadClass(listenerClassName);
487 }
488
489 Object o = listenerClass.newInstance();
490 if (o instanceof org.castor.xml.UnmarshalListener
491 || o instanceof org.exolab.castor.xml.UnmarshalListener || o instanceof MarshalListener) {
492 _listener = o;
493 } else {
494 _listener = null;
495 }
496
497 _listenerGoldFile = listener.getGoldFile();
498 _listenerType = listener.getType();
499 }
500
501
502
503
504
505
506
507
508 protected Object buildObjectModel(final String builderName) throws java.lang.Exception {
509 Class builderClass = null;
510 if (_test.getClassLoader() != null) {
511 builderClass = _test.getClassLoader().loadClass(builderName);
512 } else {
513 builderClass = this.getClass().getClassLoader().loadClass(builderName);
514 }
515 ObjectModelBuilder builder = (ObjectModelBuilder) builderClass.newInstance();
516 return builder.buildInstance();
517 }
518
519 private Method getInvokeMethod(final Class dataBinder, final String methodName,
520 final Value[] values) throws ClassNotFoundException, NoSuchMethodException {
521 if (methodName == null) {
522 throw new IllegalArgumentException("The name of the method to invoke is null");
523 }
524 Class[] argumentsClass = null;
525
526
527 if (values != null && values.length > 0) {
528 argumentsClass = new Class[values.length];
529 for (int i = 0; i < values.length; i++) {
530 Value value = values[i];
531 argumentsClass[i] = CTFUtils.getClass(value.getType(), _test.getClassLoader());
532 }
533 }
534 return dataBinder.getMethod(methodName, argumentsClass);
535 }
536
537 private Object[] getArguments(final Value[] values)
538 throws ClassNotFoundException, MarshalException {
539 Object[] result = new Object[values.length];
540 for (int i = 0; i < values.length; i++) {
541 Value value = values[i];
542 result[i] =
543 CTFUtils.instantiateObject(value.getType(), value.getContent(), _test.getClassLoader());
544 }
545 return result;
546 }
547
548
549
550
551
552
553 protected void verbose(final String message) {
554 if (_verbose) {
555 System.out.println(message);
556 }
557 }
558
559 }