1 package org.objectweb.celtix.bus.ws.rm; 2 3 import java.io.OutputStream ; 4 import java.math.BigInteger ; 5 import java.util.ArrayList ; 6 import java.util.List ; 7 8 import javax.xml.ws.handler.MessageContext; 9 10 import junit.framework.TestCase; 11 12 import org.easymock.IMocksControl; 13 import org.easymock.classextension.EasyMock; 14 import org.objectweb.celtix.bindings.AbstractBindingBase; 15 import org.objectweb.celtix.bindings.AbstractBindingImpl; 16 import org.objectweb.celtix.bindings.DataBindingCallback; 17 import org.objectweb.celtix.bindings.ServerDataBindingCallback; 18 import org.objectweb.celtix.bus.ws.addressing.AddressingPropertiesImpl; 19 import org.objectweb.celtix.context.InputStreamMessageContext; 20 import org.objectweb.celtix.context.ObjectMessageContext; 21 import org.objectweb.celtix.context.OutputStreamMessageContext; 22 import org.objectweb.celtix.handlers.HandlerInvoker; 23 import org.objectweb.celtix.transports.ClientTransport; 24 import org.objectweb.celtix.transports.ServerTransport; 25 import org.objectweb.celtix.transports.Transport; 26 import org.objectweb.celtix.workqueue.WorkQueue; 27 import org.objectweb.celtix.ws.rm.Identifier; 28 import org.objectweb.celtix.ws.rm.RMProperties; 29 import org.objectweb.celtix.ws.rm.SequenceType; 30 import org.objectweb.celtix.ws.rm.persistence.RMStore; 31 32 import static org.objectweb.celtix.bindings.JAXWSConstants.DATABINDING_CALLBACK_PROPERTY; 33 import static org.objectweb.celtix.context.ObjectMessageContext.REQUESTOR_ROLE_PROPERTY; 34 import static org.objectweb.celtix.ws.addressing.JAXWSAConstants.CLIENT_ADDRESSING_PROPERTIES_OUTBOUND; 35 import static org.objectweb.celtix.ws.addressing.JAXWSAConstants.SERVER_ADDRESSING_PROPERTIES_OUTBOUND; 36 import static org.objectweb.celtix.ws.rm.JAXWSRMConstants.RM_PROPERTIES_OUTBOUND; 37 38 39 42 public class RetransmissionQueueTest extends TestCase { 43 44 private IMocksControl control; 45 private RMHandler handler; 46 private WorkQueue workQueue; 47 private RetransmissionQueue queue; 48 private TestResender resender; 49 private List <ObjectMessageContext> contexts = 50 new ArrayList <ObjectMessageContext>(); 51 private List <RMProperties> properties = 52 new ArrayList <RMProperties>(); 53 private List <SequenceType> sequences = 54 new ArrayList <SequenceType>(); 55 private List <Identifier> identifiers = 56 new ArrayList <Identifier>(); 57 58 public void setUp() { 59 control = EasyMock.createNiceControl(); 60 handler = control.createMock(RMHandler.class); 61 queue = new RetransmissionQueue(handler); 62 resender = new TestResender(); 63 queue.replaceResender(resender); 64 workQueue = control.createMock(WorkQueue.class); 65 70 } 71 72 public void tearDown() { 73 control.verify(); 74 contexts.clear(); 75 properties.clear(); 76 sequences.clear(); 77 } 78 79 public void testCtor() { 80 ready(); 81 assertNotNull("expected unacked map", queue.getUnacknowledged()); 82 assertEquals("expected empty unacked map", 83 0, 84 queue.getUnacknowledged().size()); 85 assertEquals("unexpected base retransmission interval", 86 3000L, 87 queue.getBaseRetransmissionInterval()); 88 assertEquals("unexpected exponential backoff", 89 2, 90 queue.getExponentialBackoff()); 91 } 92 93 public void testCacheUnacknowledged() { 94 ObjectMessageContext context1 = setUpContext("sequence1"); 95 ObjectMessageContext context2 = setUpContext("sequence2"); 96 ObjectMessageContext context3 = setUpContext("sequence1"); 97 98 setupContextMAPs(context1); 99 setupContextMAPs(context2); 100 setupContextMAPs(context3); 101 102 ready(); 103 104 assertNotNull("expected resend candidate", 105 queue.cacheUnacknowledged(context1)); 106 assertEquals("expected non-empty unacked map", 107 1, 108 queue.getUnacknowledged().size()); 109 List <RetransmissionQueue.ResendCandidate> sequence1List = 110 queue.getUnacknowledged().get("sequence1"); 111 assertNotNull("expected non-null context list", sequence1List); 112 assertSame("expected context list entry", 113 context1, 114 sequence1List.get(0).getContext()); 115 116 assertNotNull("expected resend candidate", 117 queue.cacheUnacknowledged(context2)); 118 assertEquals("unexpected unacked map size", 119 2, 120 queue.getUnacknowledged().size()); 121 List <RetransmissionQueue.ResendCandidate> sequence2List = 122 queue.getUnacknowledged().get("sequence2"); 123 assertNotNull("expected non-null context list", sequence2List); 124 assertSame("expected context list entry", 125 context2, 126 sequence2List.get(0).getContext()); 127 128 assertNotNull("expected resend candidate", 129 queue.cacheUnacknowledged(context3)); 130 assertEquals("un expected unacked map size", 131 2, 132 queue.getUnacknowledged().size()); 133 sequence1List = 134 queue.getUnacknowledged().get("sequence1"); 135 assertNotNull("expected non-null context list", sequence1List); 136 assertSame("expected context list entry", 137 context3, 138 sequence1List.get(1).getContext()); 139 } 140 141 public void testPurgeAcknowledgedSome() { 142 BigInteger [] messageNumbers = {BigInteger.TEN, BigInteger.ONE}; 143 SourceSequence sequence = setUpSequence("sequence1", 144 messageNumbers, 145 new boolean[] {true, false}); 146 List <RetransmissionQueue.ResendCandidate> sequenceList = 147 new ArrayList <RetransmissionQueue.ResendCandidate>(); 148 queue.getUnacknowledged().put("sequence1", sequenceList); 149 ObjectMessageContext context1 = 150 setUpContext("sequence1", messageNumbers[0]); 151 sequenceList.add(queue.createResendCandidate(context1)); 152 ObjectMessageContext context2 = 153 setUpContext("sequence1", messageNumbers[1]); 154 sequenceList.add(queue.createResendCandidate(context2)); 155 ready(); 156 157 queue.purgeAcknowledged(sequence); 158 assertEquals("unexpected unacked map size", 159 1, 160 queue.getUnacknowledged().size()); 161 assertEquals("unexpected unacked list size", 162 1, 163 sequenceList.size()); 164 } 165 166 public void testPurgeAcknowledgedNone() { 167 BigInteger [] messageNumbers = {BigInteger.TEN, BigInteger.ONE}; 168 SourceSequence sequence = setUpSequence("sequence1", 169 messageNumbers, 170 new boolean[] {false, false}); 171 List <RetransmissionQueue.ResendCandidate> sequenceList = 172 new ArrayList <RetransmissionQueue.ResendCandidate>(); 173 queue.getUnacknowledged().put("sequence1", sequenceList); 174 ObjectMessageContext context1 = 175 setUpContext("sequence1", messageNumbers[0]); 176 sequenceList.add(queue.createResendCandidate(context1)); 177 ObjectMessageContext context2 = 178 setUpContext("sequence1", messageNumbers[1]); 179 sequenceList.add(queue.createResendCandidate(context2)); 180 ready(); 181 182 queue.purgeAcknowledged(sequence); 183 assertEquals("unexpected unacked map size", 184 1, 185 queue.getUnacknowledged().size()); 186 assertEquals("unexpected unacked list size", 187 2, 188 sequenceList.size()); 189 } 190 191 public void testCountUnacknowledged() { 192 BigInteger [] messageNumbers = {BigInteger.TEN, BigInteger.ONE}; 193 SourceSequence sequence = setUpSequence("sequence1", 194 messageNumbers, 195 null); 196 List <RetransmissionQueue.ResendCandidate> sequenceList = 197 new ArrayList <RetransmissionQueue.ResendCandidate>(); 198 queue.getUnacknowledged().put("sequence1", sequenceList); 199 ObjectMessageContext context1 = 200 setUpContext("sequence1", messageNumbers[0], false); 201 sequenceList.add(queue.createResendCandidate(context1)); 202 ObjectMessageContext context2 = 203 setUpContext("sequence1", messageNumbers[1], false); 204 sequenceList.add(queue.createResendCandidate(context2)); 205 ready(); 206 207 assertEquals("unexpected unacked count", 208 2, 209 queue.countUnacknowledged(sequence)); 210 } 211 212 public void testCountUnacknowledgedUnknownSequence() { 213 BigInteger [] messageNumbers = {BigInteger.TEN, BigInteger.ONE}; 214 SourceSequence sequence = setUpSequence("sequence1", 215 messageNumbers, 216 null); 217 ready(); 218 219 assertEquals("unexpected unacked count", 220 0, 221 queue.countUnacknowledged(sequence)); 222 } 223 224 public void testResendInitiatorBackoffLogic() { 225 ObjectMessageContext context1 = setUpContext("sequence1"); 226 ObjectMessageContext context2 = setUpContext("sequence2"); 227 ObjectMessageContext context3 = setUpContext("sequence1"); 228 setupContextMAPs(context1); 229 setupContextMAPs(context2); 230 setupContextMAPs(context3); 231 ready(); 232 RetransmissionQueue.ResendCandidate candidate1 = 233 queue.cacheUnacknowledged(context1); 234 RetransmissionQueue.ResendCandidate candidate2 = 235 queue.cacheUnacknowledged(context2); 236 RetransmissionQueue.ResendCandidate candidate3 = 237 queue.cacheUnacknowledged(context3); 238 RetransmissionQueue.ResendCandidate[] allCandidates = 239 {candidate1, candidate2, candidate3}; 240 boolean [] expectAckRequested = {true, true, false}; 241 242 runInitiator(); 244 245 runInitiator(allCandidates); 247 runCandidates(allCandidates, expectAckRequested); 248 249 runInitiator(); 251 252 runInitiator(allCandidates); 254 runCandidates(allCandidates, expectAckRequested); 255 256 for (int i = 0; i < 3; i++) { 257 runInitiator(); 259 } 260 261 runInitiator(allCandidates); 263 runCandidates(allCandidates, expectAckRequested); 264 265 for (int i = 0; i < 7; i++) { 266 runInitiator(); 268 } 269 270 runInitiator(allCandidates); 272 runCandidates(allCandidates, expectAckRequested); 273 } 274 275 276 public void testResendInitiatorDueLogic() { 277 ObjectMessageContext context1 = setUpContext("sequence1"); 278 ObjectMessageContext context2 = setUpContext("sequence2"); 279 ObjectMessageContext context3 = setUpContext("sequence1"); 280 setupContextMAPs(context1); 281 setupContextMAPs(context2); 282 setupContextMAPs(context3); 283 ready(); 284 RetransmissionQueue.ResendCandidate candidate1 = 285 queue.cacheUnacknowledged(context1); 286 RetransmissionQueue.ResendCandidate candidate2 = 287 queue.cacheUnacknowledged(context2); 288 RetransmissionQueue.ResendCandidate candidate3 = 289 queue.cacheUnacknowledged(context3); 290 RetransmissionQueue.ResendCandidate[] allCandidates = 291 {candidate1, candidate2, candidate3}; 292 boolean [] expectAckRequested = {true, true, false}; 293 294 runInitiator(); 296 297 runInitiator(allCandidates); 299 300 runInitiator(); 302 303 candidate1.run(); 304 candidate2.run(); 305 306 runInitiator(); 308 309 runInitiator(new RetransmissionQueue.ResendCandidate[] {candidate1, 311 candidate2}); 312 313 runCandidates(allCandidates, expectAckRequested); 314 315 runInitiator(); 317 318 runInitiator(new RetransmissionQueue.ResendCandidate[] {candidate3}); 320 321 runInitiator(); 323 324 runInitiator(new RetransmissionQueue.ResendCandidate[] {candidate1, 326 candidate2}); 327 } 328 329 public void testResendInitiatorResolvedLogic() { 330 ObjectMessageContext context1 = setUpContext("sequence1"); 331 ObjectMessageContext context2 = setUpContext("sequence2"); 332 ObjectMessageContext context3 = setUpContext("sequence1"); 333 setupContextMAPs(context1); 334 setupContextMAPs(context2); 335 setupContextMAPs(context3); 336 ready(); 337 RetransmissionQueue.ResendCandidate candidate1 = 338 queue.cacheUnacknowledged(context1); 339 RetransmissionQueue.ResendCandidate candidate2 = 340 queue.cacheUnacknowledged(context2); 341 RetransmissionQueue.ResendCandidate candidate3 = 342 queue.cacheUnacknowledged(context3); 343 RetransmissionQueue.ResendCandidate[] allCandidates = 344 {candidate1, candidate2, candidate3}; 345 boolean [] expectAckRequested = {true, true, false}; 346 347 runInitiator(); 349 350 runInitiator(allCandidates); 352 runCandidates(allCandidates, expectAckRequested); 353 354 runInitiator(); 356 357 candidate1.resolved(); 358 candidate3.resolved(); 359 360 runInitiator(new RetransmissionQueue.ResendCandidate[] {candidate2}); 362 } 363 364 public void testResenderInitiatorReschedule() { 365 ready(); 366 367 runInitiator(); 368 } 369 370 public void testResenderInitiatorNoRescheduleOnShutdown() { 371 ready(); 372 373 queue.shutdown(); 374 queue.getResendInitiator().run(); 375 } 376 377 public void testDefaultResenderClient() throws Exception { 378 doTestDefaultResender(true); 379 } 380 381 public void testDefaultResenderServer() throws Exception { 382 doTestDefaultResender(false); 383 } 384 385 private void doTestDefaultResender(boolean isRequestor) throws Exception { 386 ObjectMessageContext context1 = setUpContext("sequence1"); 387 setupContextMAPs(context1); 388 queue.replaceResender(queue.getDefaultResender()); 389 ready(); 390 RetransmissionQueue.ResendCandidate candidate1 = 391 queue.cacheUnacknowledged(context1); 392 RetransmissionQueue.ResendCandidate[] allCandidates = {candidate1}; 393 394 runInitiator(); 396 397 runInitiator(allCandidates); 399 setUpDefaultResender(0, isRequestor); 400 allCandidates[0].run(); 401 } 402 403 private ObjectMessageContext setUpContext(String sid) { 404 return setUpContext(sid, null); 405 } 406 407 private ObjectMessageContext setUpContext(String sid, 408 BigInteger messageNumber) { 409 return setUpContext(sid, messageNumber, true); 410 } 411 412 private ObjectMessageContext setUpContext(String sid, 413 BigInteger messageNumber, 414 boolean storeSequence) { 415 ObjectMessageContext context = 416 control.createMock(ObjectMessageContext.class); 417 if (storeSequence) { 418 setUpSequenceType(context, sid, messageNumber); 419 } 420 contexts.add(context); 421 422 return context; 423 } 424 425 private void setupContextMAPs(ObjectMessageContext context) { 426 AddressingPropertiesImpl maps = control.createMock(AddressingPropertiesImpl.class); 427 context.get(CLIENT_ADDRESSING_PROPERTIES_OUTBOUND); 428 EasyMock.expectLastCall().andReturn(maps); 429 } 430 431 private void ready() { 432 control.replay(); 433 queue.start(workQueue); 434 } 435 436 private void setUpDefaultResender(int i, boolean isRequestor) 437 throws Exception { 438 assertTrue("too few contexts", i < contexts.size()); 439 assertTrue("too few properties", i < properties.size()); 440 assertTrue("too few sequences", i < sequences.size()); 441 control.verify(); 442 control.reset(); 443 444 contexts.get(i).get(RM_PROPERTIES_OUTBOUND); 445 EasyMock.expectLastCall().andReturn(properties.get(i)).times(2); 446 properties.get(i).getSequence(); 447 EasyMock.expectLastCall().andReturn(sequences.get(i)).times(2); 448 AddressingPropertiesImpl maps = 449 control.createMock(AddressingPropertiesImpl.class); 450 contexts.get(i).get(REQUESTOR_ROLE_PROPERTY); 451 EasyMock.expectLastCall().andReturn(Boolean.valueOf(isRequestor)).times(2); 452 contexts.get(i).get(SERVER_ADDRESSING_PROPERTIES_OUTBOUND); 453 EasyMock.expectLastCall().andReturn(maps); 454 sequences.get(i).getIdentifier(); 455 EasyMock.expectLastCall().andReturn(identifiers.get(i)); 456 Transport transport = isRequestor 457 ? control.createMock(ClientTransport.class) 458 : control.createMock(ServerTransport.class); 459 if (isRequestor) { 460 handler.getClientTransport(); 461 EasyMock.expectLastCall().andReturn(transport).times(2); 462 } else { 463 handler.getServerTransport(); 464 EasyMock.expectLastCall().andReturn(transport).times(1); 465 } 466 AbstractBindingBase binding = 467 control.createMock(AbstractBindingBase.class); 468 handler.getBinding(); 469 EasyMock.expectLastCall().andReturn(binding); 470 HandlerInvoker handlerInvoker = 471 control.createMock(HandlerInvoker.class); 472 binding.createHandlerInvoker(); 473 EasyMock.expectLastCall().andReturn(handlerInvoker); 474 AbstractBindingImpl bindingImpl = 475 control.createMock(AbstractBindingImpl.class); 476 binding.getBindingImpl(); 477 EasyMock.expectLastCall().andReturn(bindingImpl).times(isRequestor 478 ? 6 479 : 5); 480 bindingImpl.createBindingMessageContext(contexts.get(i)); 481 MessageContext bindingContext = 482 control.createMock(MessageContext.class); 483 EasyMock.expectLastCall().andReturn(bindingContext); 484 OutputStreamMessageContext outputStreamContext = 485 control.createMock(OutputStreamMessageContext.class); 486 transport.createOutputStreamContext(bindingContext); 487 EasyMock.expectLastCall().andReturn(outputStreamContext); 488 489 if (isRequestor) { 490 setUpClientDispatch(handlerInvoker, 491 contexts.get(i), 492 bindingContext, 493 outputStreamContext, 494 bindingImpl, 495 transport); 496 } else { 497 setUpServerDispatch(bindingContext, outputStreamContext); 498 } 499 500 control.replay(); 501 } 502 503 private void setUpClientDispatch( 504 HandlerInvoker handlerInvoker, 505 ObjectMessageContext objectContext, 506 MessageContext bindingContext, 507 OutputStreamMessageContext outputStreamContext, 508 AbstractBindingImpl bindingImpl, 509 Transport transport) throws Exception { 510 handlerInvoker.invokeProtocolHandlers(true, bindingContext); 511 EasyMock.expectLastCall().andReturn(Boolean.TRUE); 512 InputStreamMessageContext inputStreamContext = 513 control.createMock(InputStreamMessageContext.class); 514 ((ClientTransport)transport).invoke(outputStreamContext); 515 EasyMock.expectLastCall().andReturn(inputStreamContext); 516 bindingImpl.read(inputStreamContext, bindingContext); 517 EasyMock.expectLastCall(); 518 bindingImpl.hasFault(bindingContext); 519 EasyMock.expectLastCall().andReturn(false); 520 bindingImpl.unmarshal(bindingContext, objectContext, null); 521 EasyMock.expectLastCall(); 522 } 523 524 private void setUpServerDispatch( 525 MessageContext bindingContext, 526 OutputStreamMessageContext outputStreamContext) { 527 DataBindingCallback callback = 528 control.createMock(ServerDataBindingCallback.class); 529 bindingContext.get(DATABINDING_CALLBACK_PROPERTY); 530 EasyMock.expectLastCall().andReturn(callback); 531 OutputStream outputStream = control.createMock(OutputStream .class); 532 outputStreamContext.getOutputStream(); 533 EasyMock.expectLastCall().andReturn(outputStream); 534 } 535 536 private void runInitiator() { 537 runInitiator(null); 538 } 539 540 private void runInitiator( 541 RetransmissionQueue.ResendCandidate[] dueCandidates) { 542 control.verify(); 543 control.reset(); 544 545 for (int i = 0; 546 dueCandidates != null && i < dueCandidates.length; 547 i++) { 548 workQueue.execute(dueCandidates[i]); 549 EasyMock.expectLastCall(); 550 } 551 556 control.replay(); 557 queue.getResendInitiator().run(); 558 } 559 560 private void runCandidates( 561 RetransmissionQueue.ResendCandidate[] candidates, 562 boolean[] expectAckRequested) { 563 for (int i = 0; i < candidates.length; i++) { 564 candidates[i].run(); 565 assertEquals("unexpected request acknowledge", 566 expectAckRequested[i], 567 resender.includeAckRequested); 568 assertSame("unexpected context", 569 candidates[i].getContext(), 570 resender.context); 571 resender.clear(); 572 } 573 } 574 575 private SequenceType setUpSequenceType(ObjectMessageContext context, 576 String sid, 577 BigInteger messageNumber) { 578 RMProperties rmps = control.createMock(RMProperties.class); 579 if (context != null) { 580 context.get(RM_PROPERTIES_OUTBOUND); 581 EasyMock.expectLastCall().andReturn(rmps); 582 } 583 properties.add(rmps); 584 SequenceType sequence = control.createMock(SequenceType.class); 585 if (context != null) { 586 rmps.getSequence(); 587 EasyMock.expectLastCall().andReturn(sequence); 588 } 589 if (messageNumber != null) { 590 sequence.getMessageNumber(); 591 EasyMock.expectLastCall().andReturn(messageNumber); 592 } else { 593 Identifier id = control.createMock(Identifier.class); 594 sequence.getIdentifier(); 595 EasyMock.expectLastCall().andReturn(id); 596 id.getValue(); 597 EasyMock.expectLastCall().andReturn(sid); 598 identifiers.add(id); 599 } 600 sequences.add(sequence); 601 return sequence; 602 } 603 604 @SuppressWarnings ("unchecked") 605 private SourceSequence setUpSequence(String sid, 606 BigInteger [] messageNumbers, 607 boolean[] isAcked) { 608 SourceSequence sequence = control.createMock(SourceSequence.class); 609 Identifier id = control.createMock(Identifier.class); 610 sequence.getIdentifier(); 611 EasyMock.expectLastCall().andReturn(id); 612 id.getValue(); 613 EasyMock.expectLastCall().andReturn(sid); 614 identifiers.add(id); 615 boolean includesAcked = false; 616 for (int i = 0; isAcked != null && i < isAcked.length; i++) { 617 sequence.isAcknowledged(messageNumbers[i]); 618 EasyMock.expectLastCall().andReturn(isAcked[i]); 619 if (isAcked[i]) { 620 includesAcked = true; 621 } 622 } 623 if (includesAcked) { 624 sequence.getIdentifier(); 625 EasyMock.expectLastCall().andReturn(id); 626 RMStore store = control.createMock(RMStore.class); 627 handler.getStore(); 628 EasyMock.expectLastCall().andReturn(store); 629 } 630 return sequence; 631 } 632 633 private static class TestResender implements RetransmissionQueue.Resender { 634 ObjectMessageContext context; 635 boolean includeAckRequested; 636 637 public void resend(ObjectMessageContext ctx, boolean requestAcknowledge) { 638 context = ctx; 639 includeAckRequested = requestAcknowledge; 640 } 641 642 void clear() { 643 context = null; 644 includeAckRequested = false; 645 } 646 }; 647 } 648 | Popular Tags |