1 /* ==================================================================== 2 * License: 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * 3. The end-user documentation included with the redistribution, 17 * if any, must include the following acknowledgment: 18 * "This product includes software developed by 19 * Robert Half International (http://www.rhi.com/)." 20 * Alternately, this acknowledgment may appear in the software itself, 21 * if and wherever such third-party acknowledgments normally appear. 22 * 23 * 4. The names "Parc", "RHI", and "Robert Half International" must 24 * not be used to endorse or promote products derived from this 25 * software without prior written permission. For written 26 * permission, please contact pete.mckinstry@rhi.com. 27 * 28 * 5. Products derived from this software may not be called "PARC", 29 * nor may "PARC" appear in their name, without prior written 30 * permission of Robert Half International. 31 * 32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 33 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 34 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 36 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 37 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 38 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 39 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 41 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 42 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 43 * SUCH DAMAGE. 44 * ==================================================================== 45 * 46 */ 47 package com.rhi.architecture.parc.adapter; 48 49 import com.rhi.architecture.batch.AuditAgent; 50 import com.rhi.architecture.batch.TestAuditAgent; 51 import com.rhi.architecture.config.ConfigFacility; 52 import com.rhi.architecture.parc.ArrayListQueue; 53 import com.rhi.architecture.parc.Channel; 54 import com.rhi.architecture.parc.ExceptionHandler; 55 import com.rhi.architecture.parc.PARCTest; 56 import com.rhi.architecture.parc.TestError; 57 import com.rhi.architecture.parc.TestRecord; 58 import com.rhi.architecture.resource.ResourceContext; 59 import com.rhi.architecture.xa.Transaction; 60 61 import java.util.ArrayList; 62 import java.util.Collection; 63 import java.util.List; 64 import java.util.Properties; 65 66 import junit.framework.Test; 67 import junit.framework.TestSuite; 68 69 /*** 70 * OutputAdapterTest.java 71 * 72 * @author <a href="mailto:pete.mckinstry@rhi.com">Pete McKinstry</a> 73 * @copyright 2002, Robert Half International, All rights reserved. 74 * 75 * @version 1.0 76 */ 77 public class OutputAdapterTest extends PARCTest { 78 79 private TestOutputAdapter oa; 80 private Channel valid; 81 private Channel error; 82 private ExceptionHandler handler; 83 private AuditAgent auditAgent; 84 85 /*** 86 * Constructor for OutputAdapterTest. 87 * @param name 88 */ 89 public OutputAdapterTest(String name) { 90 super(name); 91 } 92 93 /*** 94 * Allow subclasses to add extra params. Default impl provided. 95 * @param p 96 * @return 97 */ 98 public Properties doGetProperties(Properties p) { 99 p.setProperty( 100 Transaction.TYPE_KEY, 101 "com.rhi.architecture.xa.TestTransaction"); 102 p.setProperty("AbstractOutputAdapter.MaxSleep", "100"); 103 super.setLoadDriver(false); 104 105 return p; 106 } 107 108 /*** 109 * setup 110 * @throws Exception 111 */ 112 protected void setUp() throws Exception { 113 super.setUp(); 114 oa = new TestOutputAdapter(); 115 valid = new ArrayListQueue(); 116 error = new ArrayListQueue(); 117 handler = new ExceptionHandler(); 118 auditAgent = new TestAuditAgent(); 119 120 ResourceContext ctx = new ResourceContext(); 121 ConfigFacility config = (ConfigFacility) ctx.lookup(ConfigFacility.KEY); 122 Properties p = config.getProperties(); 123 124 oa.init(p); 125 oa.setValidChannel(valid); 126 oa.setErrorChannel(error); 127 oa.setExceptionHandler(handler); 128 oa.setAuditAgent(auditAgent); 129 } 130 131 /*** 132 * tear down 133 * @throws Exception 134 */ 135 protected void tearDown() throws Exception { 136 super.tearDown(); 137 oa.cleanup(); 138 } 139 140 /*** 141 * Test the error handling 142 * 143 * Set the valid channel to null, thus causing the output 144 * adapter to fail w/ a fatal runtime exception. The run() 145 * method should detect this error & instead of crashing, 146 * signal the error handler. 147 * 148 * @throws Exception 149 * @since 1,1 150 */ 151 public void testExceptionThrown() throws Exception { 152 this.oa.setValidChannel(null); 153 154 // just immediately after processing records. 155 this.oa.markComplete(); 156 157 Thread oaThread = new Thread(this.oa); 158 159 oaThread.start(); 160 161 while (oaThread.isAlive()) { 162 try { 163 Thread.sleep(100); 164 } 165 catch (InterruptedException e) { 166 // ignore 167 } 168 } 169 170 assertTrue( 171 "exception not caught by OutputAdapter.", 172 handler.hasError() == true); 173 } 174 175 /*** 176 * Simple test 177 * Push record into inbound channel before starting OA, 178 * then check that record comes out the other end. 179 * 180 * @throws Exception 181 * @since 1,1 182 */ 183 public void testOneRecord() throws Exception { 184 List records = new ArrayList(); 185 186 records.add(new TestRecord()); 187 this.valid.push(records); 188 189 // just immediately after processing records. 190 this.oa.markComplete(); 191 192 Thread oaThread = new Thread(this.oa); 193 194 oaThread.start(); 195 196 while (oaThread.isAlive()) { 197 try { 198 Thread.sleep(100); 199 } 200 catch (InterruptedException e) { 201 // ignore 202 } 203 } 204 205 assertTrue( 206 "exception thrown by OutputAdapter.", 207 handler.hasError() == false); 208 records = oa.getValidRecords(); 209 assertTrue("valid record size wrong.", records.size() == 1); 210 records = oa.getErrorRecords(); 211 assertTrue("error record size wrong.", records.size() == 0); 212 } 213 214 /*** 215 * Test of non-thread version to ensure backward compatibility. 216 * 217 * @throws Exception 218 * @since 1,1 219 */ 220 public void testNonThreadOutputAdapter() throws Exception { 221 List records = new ArrayList(); 222 223 records.add(new TestRecord()); 224 this.valid.push(records); 225 226 // just immediately after processing records. 227 this.oa.markComplete(); 228 229 this.oa.run(); 230 231 assertTrue( 232 "exception thrown by OutputAdapter.", 233 handler.hasError() == false); 234 records = oa.getValidRecords(); 235 assertTrue("valid record size wrong.", records.size() == 1); 236 records = oa.getErrorRecords(); 237 assertTrue("error record size wrong.", records.size() == 0); 238 } 239 240 /*** 241 * Start the output adapter first, then push some records into 242 * the channel multiple times to simulate a multi-batch interface 243 * After both batches are pushed, mark the OA complete & ensure 244 * that it shuts down properly (w/ all the records accounted for. 245 * 246 * @throws Exception 247 * @since 1,1 248 */ 249 public void testNormalScenario() throws Exception { 250 Thread oaThread = new Thread(this.oa); 251 252 oaThread.start(); 253 254 // wait for a bit. 255 try { 256 Thread.sleep(1000); 257 } 258 catch (InterruptedException e) { 259 // ignore 260 } 261 262 // now, push some records into the channel. 263 List records1 = new ArrayList(); 264 265 records1.add(new TestRecord()); 266 records1.add(new TestRecord()); 267 records1.add(new TestRecord()); 268 this.valid.push(records1); 269 270 // and push some more. 271 List records2 = new ArrayList(); 272 273 records2.add(new TestRecord()); 274 records2.add(new TestRecord()); 275 this.valid.push(records2); 276 277 // after it's done w/ these 5, exit. 278 this.oa.markComplete(); 279 280 while (oaThread.isAlive()) { 281 try { 282 Thread.sleep(100); 283 } 284 catch (InterruptedException e) { 285 // ignore 286 } 287 } 288 289 assertTrue( 290 "exception not caught by OutputAdapter.", 291 handler.hasError() == false); 292 293 Collection records = oa.getValidRecords(); 294 295 assertTrue("valid record size wrong.", records.size() == 5); 296 records = oa.getErrorRecords(); 297 assertTrue("error record size wrong.", records.size() == 0); 298 } 299 300 /*** 301 * Test of wait/notify logic. 302 * 303 * Start the output adapter first, then push some records into 304 * the channel multiple times to simulate a multi-batch interface 305 * After both batches are pushed, mark the OA complete & ensure 306 * that it shuts down properly (w/ all the records accounted for. 307 * 308 * @throws Exception 309 * @since 1,1 310 */ 311 public void testOutputAdapterNotifyWaitCycle() throws Exception { 312 Thread oaThread = new Thread(this.oa); 313 314 oaThread.start(); 315 316 // wait for a bit, forcing the OA to sleep (no records yet) 317 try { 318 Thread.sleep(250); 319 } 320 catch (InterruptedException e) { 321 // ignore 322 } 323 324 // Batch 1 325 List records1 = new ArrayList(); 326 327 records1.add(new TestRecord()); 328 records1.add(new TestRecord()); 329 records1.add(new TestRecord()); 330 this.valid.push(records1); 331 332 // wait for a bit, forcing the OA to sleep. 1 cycle, then empty cycle. 333 try { 334 Thread.sleep(1000); 335 } 336 catch (InterruptedException e) { 337 // ignore 338 } 339 340 // Batch 2 341 List records2 = new ArrayList(); 342 343 records2.add(new TestRecord()); 344 records2.add(new TestRecord()); 345 this.valid.push(records2); 346 347 // after it's done w/ these 5, exit. 348 this.oa.markComplete(); 349 350 while (oaThread.isAlive()) { 351 try { 352 Thread.sleep(100); 353 } 354 catch (InterruptedException e) { 355 // ignore 356 } 357 } 358 359 int writeCount = ((TestOutputAdapter)this.oa).getWriteCount(); 360 System.out.println("write called " + writeCount + " times"); 361 assertTrue( "incorrect number of batches. wait/notify logic broken. " + 362 "write() called " + writeCount, 363 writeCount<15); 364 365 int handleValidCount = ((TestOutputAdapter)this.oa).getHandleValidCount(); 366 System.out.println("handleValid called " + handleValidCount + " times"); 367 assertTrue( "wait/notify logic broken. " + 368 "handleValid called " + handleValidCount + " times", 369 handleValidCount==2); 370 371 372 assertTrue( "exception not caught by OutputAdapter.", 373 handler.hasError() == false); 374 375 Collection records = oa.getValidRecords(); 376 377 assertTrue("valid record size wrong.", records.size() == 5); 378 records = oa.getErrorRecords(); 379 assertTrue("error record size wrong.", records.size() == 0); 380 } 381 382 /*** 383 * Add errored records to error channel & make sure they 384 * are propertly accounted for. 385 * 386 * @throws Exception 387 * @since 1,1 388 */ 389 public void testErrorChannel() throws Exception { 390 List records = new ArrayList(); 391 TestRecord r = new TestRecord(); 392 393 r.addError(new TestError()); 394 records.add(r); 395 records.add(r); 396 this.error.push(records); 397 398 // just immediately after processing records. 399 this.oa.markComplete(); 400 401 Thread oaThread = new Thread(this.oa); 402 403 oaThread.start(); 404 405 while (oaThread.isAlive()) { 406 try { 407 Thread.sleep(100); 408 } 409 catch (InterruptedException e) { 410 // ignore 411 } 412 } 413 414 assertTrue( 415 "exception thrown by OutputAdapter.", 416 handler.hasError() == false); 417 records = oa.getValidRecords(); 418 assertTrue("valid record size wrong.", records.size() == 0); 419 records = oa.getErrorRecords(); 420 assertTrue("error record size wrong.", records.size() == 2); 421 } 422 423 /*** 424 * Add errored records to valid channel & make sure they 425 * are propertly accounted for. 426 * 427 * @throws Exception 428 * @since 1,1 429 */ 430 public void testErrorsInValidChannel() throws Exception { 431 List records = new ArrayList(); 432 TestRecord r = new TestRecord(); 433 434 r.addError(new TestError()); 435 records.add(r); 436 records.add(r); 437 this.valid.push(records); 438 439 // just immediately after processing records. 440 this.oa.markComplete(); 441 442 Thread oaThread = new Thread(this.oa); 443 444 oaThread.start(); 445 446 while (oaThread.isAlive()) { 447 try { 448 Thread.sleep(100); 449 } 450 catch (InterruptedException e) { 451 // ignore 452 } 453 } 454 455 assertTrue( 456 "exception thrown by OutputAdapter.", 457 handler.hasError() == false); 458 records = oa.getValidRecords(); 459 assertTrue("valid record size wrong.", records.size() == 0); 460 records = oa.getErrorRecords(); 461 assertTrue("error record size wrong.", records.size() == 2); 462 } 463 464 /*** 465 * suite of all tests 466 * @return Test 467 */ 468 public static Test suite() { 469 return new TestSuite(OutputAdapterTest.class); 470 } 471 472 }

This page was automatically generated by Maven