001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.ws.rm.soap;
019:
020: import java.math.BigInteger;
021: import java.util.ArrayList;
022: import java.util.Date;
023: import java.util.List;
024: import java.util.concurrent.Executor;
025:
026: import org.apache.cxf.message.Message;
027: import org.apache.cxf.ws.policy.AssertionInfoMap;
028: import org.apache.cxf.ws.rm.Identifier;
029: import org.apache.cxf.ws.rm.RMManager;
030: import org.apache.cxf.ws.rm.RMMessageConstants;
031: import org.apache.cxf.ws.rm.RMProperties;
032: import org.apache.cxf.ws.rm.SequenceType;
033: import org.apache.cxf.ws.rm.SourceSequence;
034: import org.apache.cxf.ws.rm.persistence.RMStore;
035: import org.apache.cxf.ws.rm.policy.RMAssertion;
036: import org.easymock.IMocksControl;
037: import org.easymock.classextension.EasyMock;
038: import org.junit.After;
039: import org.junit.Assert;
040: import org.junit.Before;
041: import org.junit.Test;
042:
043: /**
044: * Test resend logic.
045: */
046: public class RetransmissionQueueImplTest extends Assert {
047:
048: private IMocksControl control;
049: private RMManager manager;
050: private Executor executor;
051: private RetransmissionQueueImpl queue;
052: private TestResender resender;
053: private List<Message> messages = new ArrayList<Message>();
054: private List<RMProperties> properties = new ArrayList<RMProperties>();
055: private List<SequenceType> sequences = new ArrayList<SequenceType>();
056: private List<Identifier> identifiers = new ArrayList<Identifier>();
057: private List<Object> mocks = new ArrayList<Object>();
058: private RMAssertion rma;
059:
060: @Before
061: public void setUp() {
062: control = EasyMock.createNiceControl();
063: manager = createMock(RMManager.class);
064: queue = new RetransmissionQueueImpl(manager);
065: resender = new TestResender();
066: queue.replaceResender(resender);
067: executor = createMock(Executor.class);
068: rma = createMock(RMAssertion.class);
069: assertNotNull(executor);
070: }
071:
072: @After
073: public void tearDown() {
074: control.verify();
075: messages.clear();
076: properties.clear();
077: sequences.clear();
078: mocks.clear();
079: control.reset();
080: }
081:
082: @Test
083: public void testCtor() {
084: ready(false);
085: assertNotNull("expected unacked map", queue.getUnacknowledged());
086: assertEquals("expected empty unacked map", 0, queue
087: .getUnacknowledged().size());
088:
089: queue = new RetransmissionQueueImpl(null);
090: assertNull(queue.getManager());
091: queue.setManager(manager);
092: assertSame("Unexpected RMManager", manager, queue.getManager());
093: }
094:
095: @Test
096: public void testResendCandidateCtor() {
097: Message message = createMock(Message.class);
098: setupMessagePolicies(message);
099: control.replay();
100: long now = System.currentTimeMillis();
101: RetransmissionQueueImpl.ResendCandidate candidate = queue
102: .createResendCandidate(message);
103: assertSame(message, candidate.getMessage());
104: assertEquals(0, candidate.getResends());
105: Date refDate = new Date(now + 5000);
106: assertTrue(!candidate.getNext().before(refDate));
107: refDate = new Date(now + 7000);
108: assertTrue(!candidate.getNext().after(refDate));
109: assertTrue(!candidate.isPending());
110: }
111:
112: @Test
113: public void testResendCandidateAttempted() {
114: Message message = createMock(Message.class);
115: setupMessagePolicies(message);
116: ready(true);
117: long now = System.currentTimeMillis();
118: RetransmissionQueueImpl.ResendCandidate candidate = queue
119: .createResendCandidate(message);
120: candidate.attempted();
121: assertEquals(1, candidate.getResends());
122: Date refDate = new Date(now + 15000);
123: assertTrue(!candidate.getNext().before(refDate));
124: refDate = new Date(now + 17000);
125: assertTrue(!candidate.getNext().after(refDate));
126: assertTrue(!candidate.isPending());
127: }
128:
129: @Test
130: public void testCacheUnacknowledged() {
131: Message message1 = setUpMessage("sequence1");
132: Message message2 = setUpMessage("sequence2");
133: Message message3 = setUpMessage("sequence1");
134:
135: setupMessagePolicies(message1);
136: setupMessagePolicies(message2);
137: setupMessagePolicies(message3);
138:
139: ready(false);
140:
141: assertNotNull("expected resend candidate", queue
142: .cacheUnacknowledged(message1));
143: assertEquals("expected non-empty unacked map", 1, queue
144: .getUnacknowledged().size());
145: List<RetransmissionQueueImpl.ResendCandidate> sequence1List = queue
146: .getUnacknowledged().get("sequence1");
147: assertNotNull("expected non-null context list", sequence1List);
148: assertSame("expected context list entry", message1,
149: sequence1List.get(0).getMessage());
150:
151: assertNotNull("expected resend candidate", queue
152: .cacheUnacknowledged(message2));
153: assertEquals("unexpected unacked map size", 2, queue
154: .getUnacknowledged().size());
155: List<RetransmissionQueueImpl.ResendCandidate> sequence2List = queue
156: .getUnacknowledged().get("sequence2");
157: assertNotNull("expected non-null context list", sequence2List);
158: assertSame("expected context list entry", message2,
159: sequence2List.get(0).getMessage());
160:
161: assertNotNull("expected resend candidate", queue
162: .cacheUnacknowledged(message3));
163: assertEquals("un expected unacked map size", 2, queue
164: .getUnacknowledged().size());
165: sequence1List = queue.getUnacknowledged().get("sequence1");
166: assertNotNull("expected non-null context list", sequence1List);
167: assertSame("expected context list entry", message3,
168: sequence1List.get(1).getMessage());
169: }
170:
171: @Test
172: public void testPurgeAcknowledgedSome() {
173: BigInteger[] messageNumbers = { BigInteger.TEN, BigInteger.ONE };
174: SourceSequence sequence = setUpSequence("sequence1",
175: messageNumbers, new boolean[] { true, false });
176: List<RetransmissionQueueImpl.ResendCandidate> sequenceList = new ArrayList<RetransmissionQueueImpl.ResendCandidate>();
177: queue.getUnacknowledged().put("sequence1", sequenceList);
178: Message message1 = setUpMessage("sequence1", messageNumbers[0]);
179: setupMessagePolicies(message1);
180: Message message2 = setUpMessage("sequence1", messageNumbers[1]);
181: setupMessagePolicies(message2);
182: ready(false);
183:
184: sequenceList.add(queue.createResendCandidate(message1));
185: sequenceList.add(queue.createResendCandidate(message2));
186:
187: queue.purgeAcknowledged(sequence);
188: assertEquals("unexpected unacked map size", 1, queue
189: .getUnacknowledged().size());
190: assertEquals("unexpected unacked list size", 1, sequenceList
191: .size());
192: }
193:
194: @Test
195: public void testPurgeAcknowledgedNone() {
196: BigInteger[] messageNumbers = { BigInteger.TEN, BigInteger.ONE };
197: SourceSequence sequence = setUpSequence("sequence1",
198: messageNumbers, new boolean[] { false, false });
199: List<RetransmissionQueueImpl.ResendCandidate> sequenceList = new ArrayList<RetransmissionQueueImpl.ResendCandidate>();
200: queue.getUnacknowledged().put("sequence1", sequenceList);
201: Message message1 = setUpMessage("sequence1", messageNumbers[0]);
202: setupMessagePolicies(message1);
203: Message message2 = setUpMessage("sequence1", messageNumbers[1]);
204: setupMessagePolicies(message2);
205: ready(false);
206:
207: sequenceList.add(queue.createResendCandidate(message1));
208: sequenceList.add(queue.createResendCandidate(message2));
209:
210: queue.purgeAcknowledged(sequence);
211: assertEquals("unexpected unacked map size", 1, queue
212: .getUnacknowledged().size());
213: assertEquals("unexpected unacked list size", 2, sequenceList
214: .size());
215: }
216:
217: @Test
218: public void testIsEmpty() {
219: ready(false);
220: assertTrue("queue is not empty", queue.isEmpty());
221: }
222:
223: @Test
224: public void testCountUnacknowledged() {
225: BigInteger[] messageNumbers = { BigInteger.TEN, BigInteger.ONE };
226: SourceSequence sequence = setUpSequence("sequence1",
227: messageNumbers, null);
228: List<RetransmissionQueueImpl.ResendCandidate> sequenceList = new ArrayList<RetransmissionQueueImpl.ResendCandidate>();
229:
230: queue.getUnacknowledged().put("sequence1", sequenceList);
231: Message message1 = setUpMessage("sequence1", messageNumbers[0],
232: false);
233: setupMessagePolicies(message1);
234: Message message2 = setUpMessage("sequence1", messageNumbers[1],
235: false);
236: setupMessagePolicies(message2);
237: ready(false);
238:
239: sequenceList.add(queue.createResendCandidate(message1));
240: sequenceList.add(queue.createResendCandidate(message2));
241:
242: assertEquals("unexpected unacked count", 2, queue
243: .countUnacknowledged(sequence));
244: assertTrue("queue is empty", !queue.isEmpty());
245: }
246:
247: @Test
248: public void testCountUnacknowledgedUnknownSequence() {
249: BigInteger[] messageNumbers = { BigInteger.TEN, BigInteger.ONE };
250: SourceSequence sequence = setUpSequence("sequence1",
251: messageNumbers, null);
252: ready(false);
253:
254: assertEquals("unexpected unacked count", 0, queue
255: .countUnacknowledged(sequence));
256: }
257:
258: @Test
259: public void testStartStop() {
260: control.replay();
261: queue.start();
262: }
263:
264: private Message setUpMessage(String sid) {
265: return setUpMessage(sid, null);
266: }
267:
268: private Message setUpMessage(String sid, BigInteger messageNumber) {
269: return setUpMessage(sid, messageNumber, true);
270: }
271:
272: private Message setUpMessage(String sid, BigInteger messageNumber,
273: boolean storeSequence) {
274: Message message = createMock(Message.class);
275: if (storeSequence) {
276: setUpSequenceType(message, sid, messageNumber);
277: }
278: messages.add(message);
279:
280: return message;
281: }
282:
283: private void setupMessagePolicies(Message message) {
284: EasyMock.expect(message.get(AssertionInfoMap.class)).andReturn(
285: null);
286: EasyMock.expect(manager.getRMAssertion()).andReturn(rma);
287: RMAssertion.BaseRetransmissionInterval bri = createMock(RMAssertion.BaseRetransmissionInterval.class);
288: EasyMock.expect(rma.getBaseRetransmissionInterval()).andReturn(
289: bri);
290: EasyMock.expect(bri.getMilliseconds()).andReturn(
291: new BigInteger("5000"));
292: RMAssertion.ExponentialBackoff eb = createMock(RMAssertion.ExponentialBackoff.class);
293: EasyMock.expect(rma.getExponentialBackoff()).andReturn(eb);
294: }
295:
296: private void ready(boolean doStart) {
297: control.replay();
298: if (doStart) {
299: queue.start();
300: }
301: }
302:
303: private SequenceType setUpSequenceType(Message message, String sid,
304: BigInteger messageNumber) {
305: RMProperties rmps = createMock(RMProperties.class);
306: if (message != null) {
307: message.get(RMMessageConstants.RM_PROPERTIES_OUTBOUND);
308: EasyMock.expectLastCall().andReturn(rmps);
309: }
310: properties.add(rmps);
311: SequenceType sequence = createMock(SequenceType.class);
312: if (message != null) {
313: rmps.getSequence();
314: EasyMock.expectLastCall().andReturn(sequence);
315: }
316: if (messageNumber != null) {
317: sequence.getMessageNumber();
318: EasyMock.expectLastCall().andReturn(messageNumber);
319: } else {
320: Identifier id = createMock(Identifier.class);
321: sequence.getIdentifier();
322: EasyMock.expectLastCall().andReturn(id);
323: id.getValue();
324: EasyMock.expectLastCall().andReturn(sid);
325: identifiers.add(id);
326: }
327: sequences.add(sequence);
328: return sequence;
329: }
330:
331: private SourceSequence setUpSequence(String sid,
332: BigInteger[] messageNumbers, boolean[] isAcked) {
333: SourceSequence sequence = createMock(SourceSequence.class);
334: Identifier id = createMock(Identifier.class);
335: sequence.getIdentifier();
336: EasyMock.expectLastCall().andReturn(id);
337: id.getValue();
338: EasyMock.expectLastCall().andReturn(sid);
339: identifiers.add(id);
340: boolean includesAcked = false;
341: for (int i = 0; isAcked != null && i < isAcked.length; i++) {
342: sequence.isAcknowledged(messageNumbers[i]);
343: EasyMock.expectLastCall().andReturn(isAcked[i]);
344: if (isAcked[i]) {
345: includesAcked = true;
346: }
347: }
348: if (includesAcked) {
349: sequence.getIdentifier();
350: EasyMock.expectLastCall().andReturn(id);
351: RMStore store = createMock(RMStore.class);
352: manager.getStore();
353: EasyMock.expectLastCall().andReturn(store);
354: }
355: return sequence;
356: }
357:
358: /**
359: * Creates a mock object ensuring it remains referenced, so as to
360: * avoid garbage collection and attendant issues with finalizer
361: * calls on mocks.
362: *
363: * @param toMock the class to mock up
364: * @return the mock object
365: */
366: <T> T createMock(Class<T> toMock) {
367: T ret = control.createMock(toMock);
368: mocks.add(ret);
369: return ret;
370: }
371:
372: private static class TestResender implements
373: RetransmissionQueueImpl.Resender {
374: Message message;
375: boolean includeAckRequested;
376:
377: public void resend(Message ctx, boolean requestAcknowledge) {
378: message = ctx;
379: includeAckRequested = requestAcknowledge;
380: }
381:
382: void clear() {
383: message = null;
384: includeAckRequested = false;
385: }
386: };
387: }
|