1 /*------------------------------------------------------------------------------
2 Name: TestSubNoDup.java
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Comment: Demo code for a client using xmlBlaster
6 ------------------------------------------------------------------------------*/
7 package org.xmlBlaster.test.qos;
8
9 import java.util.logging.Logger;
10 import java.util.logging.Level;
11 import org.xmlBlaster.util.Global;
12 import org.xmlBlaster.client.qos.ConnectQos;
13 import org.xmlBlaster.util.XmlBlasterException;
14 import org.xmlBlaster.client.I_XmlBlasterAccess;
15 import org.xmlBlaster.client.I_Callback;
16 import org.xmlBlaster.client.key.UpdateKey;
17 import org.xmlBlaster.client.qos.UpdateQos;
18 import org.xmlBlaster.client.qos.EraseReturnQos;
19 import org.xmlBlaster.util.MsgUnit;
20
21 import junit.framework.*;
22
23
24 /**
25 * This client tests multiple subscribe() on same message oid
26 * and setting duplicateUpdates=false (requirement engine.qos.subscribe.duplicate).
27 * <br />
28 * The subscribe() should be recognized for the later arriving publish()
29 * but only one update should arrive. For example cluster slave nodes
30 * need this feature.
31 * <p>
32 * This client may be invoked multiple time on the same xmlBlaster server,
33 * as it cleans up everything after his tests are done.
34 * <p>
35 * Invoke examples:<br />
36 * <pre>
37 * java junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubNoDup
38 * java junit.swingui.TestRunner -noloading org.xmlBlaster.test.qos.TestSubNoDup
39 * </pre>
40 * @see <a href="http://www.xmlblaster.org/xmlBlaster/doc/requirements/engine.qos.subscribe.duplicate.html" target="others">duplicate subscribe requirement</a>
41 */
42 public class TestSubNoDup extends TestCase implements I_Callback
43 {
44 private static String ME = "TestSubNoDup";
45 private final Global glob;
46 private static Logger log = Logger.getLogger(TestSubNoDup.class.getName());
47
48 private String subscribeId1;
49 private String subscribeId2;
50 private String subscribeId3;
51 private String oidExact = "HelloMessageNoDup";
52 private String publishOid = null;
53 private I_XmlBlasterAccess senderConnection;
54 private String senderContent;
55
56 private boolean duplicates = false;
57
58 private int numReceived = 0; // error checking
59 private final String contentMime = "text/xml";
60
61 /**
62 * Constructs the TestSubNoDup object.
63 * <p />
64 * @param testName The name used in the test suite
65 */
66 public TestSubNoDup(Global glob, String testName) {
67 super(testName);
68 this.glob = glob;
69
70 }
71
72 /**
73 * Sets up the fixture.
74 * <p />
75 * Connect to xmlBlaster and login
76 */
77 protected void setUp() {
78 }
79
80 /**
81 * Tears down the fixture.
82 * <p />
83 * cleaning up .... erase() the previous message OID and logout
84 */
85 protected void tearDown() {
86 if (senderConnection != null) {
87 if (publishOid != null) {
88 String xmlKey = "<key oid='" + publishOid + "' queryType='EXACT'/>";
89 try {
90 EraseReturnQos[] arr = senderConnection.erase(xmlKey, "<qos/>");
91 assertEquals("Erase", 1, arr.length);
92 } catch(XmlBlasterException e) { fail("Erase XmlBlasterException: " + e.getMessage()); }
93 }
94
95 senderConnection.disconnect(null);
96 senderConnection = null;
97 }
98 }
99
100 /**
101 * Subscribe three times to same message.
102 * <p />
103 * The returned subscribeId1 is checked
104 */
105 public void subscribe() {
106 if (log.isLoggable(Level.FINE)) log.fine("Subscribing ...");
107
108 String xmlKey = "<key oid='" + oidExact + "' queryType='EXACT'/>";
109 String qos = "<qos/>";
110 numReceived = 0;
111 subscribeId1 = null;
112 subscribeId2 = null;
113 subscribeId3 = null;
114 try {
115 // if duplicate updates are suppressed, every subscribe gets the same subscription ID
116
117 subscribeId1 = senderConnection.subscribe(xmlKey, qos).getSubscriptionId();
118 assertTrue("returned null subscribeId1", subscribeId1 != null);
119 assertTrue("returned subscribeId1 is empty", 0 != subscribeId1.length());
120 log.info("Success: Subscribe 1 on " + subscribeId1 + " done");
121
122 subscribeId2 = senderConnection.subscribe(xmlKey, qos).getSubscriptionId();
123 assertTrue("returned subscribeId2 is empty", 0 != subscribeId2.length());
124 if (duplicates)
125 assertTrue("Wrong subscriptionId", !subscribeId1.equals(subscribeId2));
126 else
127 assertEquals("Wrong subscriptionId", subscribeId1, subscribeId2);
128 log.info("Success: Subscribe 2 on " + subscribeId2 + " done");
129
130 subscribeId3 = senderConnection.subscribe(xmlKey, qos).getSubscriptionId();
131 assertTrue("returned subscribeId3 is empty", 0 != subscribeId3.length());
132 if (duplicates)
133 assertTrue("Wrong subscriptionId", !subscribeId1.equals(subscribeId2));
134 else
135 assertEquals("Wrong subscriptionId", subscribeId1, subscribeId3);
136 log.info("Success: Subscribe 3 on " + subscribeId3 + " done");
137
138 } catch(XmlBlasterException e) {
139 log.warning("XmlBlasterException: " + e.getMessage());
140 assertTrue("subscribe - XmlBlasterException: " + e.getMessage(), false);
141 }
142 }
143
144 /**
145 * TEST: Construct a message and publish it.
146 * <p />
147 * The returned publishOid is checked
148 */
149 public void publish() {
150 if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
151
152 numReceived = 0;
153 String xmlKey = "<key oid='" + oidExact + "' contentMime='" + contentMime + "'/>";
154 senderContent = "Yeahh, i'm the new content";
155 try {
156 MsgUnit msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), "<qos/>");
157 publishOid = senderConnection.publish(msgUnit).getKeyOid();
158 log.info("Success: Publishing done, returned oid=" + publishOid);
159 } catch(XmlBlasterException e) {
160 log.warning("XmlBlasterException: " + e.getMessage());
161 assertTrue("publish - XmlBlasterException: " + e.getMessage(), false);
162 }
163
164 assertTrue("returned publishOid == null", publishOid != null);
165 assertTrue("returned publishOid", 0 != publishOid.length());
166 assertEquals("returned publishOid is wrong", oidExact, publishOid);
167 }
168
169 /**
170 * unSubscribe three times to same message.
171 */
172 public void unSubscribe() {
173 if (log.isLoggable(Level.FINE)) log.fine("unSubscribing ...");
174
175 String qos = "<qos/>";
176 numReceived = 0;
177 try {
178 senderConnection.unSubscribe("<key oid='" + subscribeId1 + "'/>", qos);
179 log.info("Success: unSubscribe 1 on " + subscribeId1 + " done");
180
181 senderConnection.unSubscribe("<key oid='" + subscribeId2 + "'/>", qos);
182 log.info("Success: unSubscribe 2 on " + subscribeId2 + " done");
183
184 senderConnection.unSubscribe("<key oid='" + subscribeId3 + "'/>", qos);
185 log.info("Success: unSubscribe 3 on " + subscribeId3 + " done");
186 } catch(XmlBlasterException e) {
187 log.warning("XmlBlasterException: " + e.getMessage());
188 assertTrue("unSubscribe - XmlBlasterException: " + e.getMessage(), false);
189 }
190 }
191
192 private void connect() {
193 try {
194 senderConnection = glob.getXmlBlasterAccess(); // Find orb
195 ConnectQos qos = new ConnectQos(glob);
196 qos.setDuplicateUpdates(duplicates);
197 senderConnection.connect(qos, this);
198 }
199 catch (Exception e) {
200 log.severe("Login failed: " + e.toString());
201 e.printStackTrace();
202 assertTrue("Login failed: " + e.toString(), false);
203 }
204 }
205
206 /**
207 * TEST: Construct a message and publish it,<br />
208 * the previous XPath subscription should match and send an update.
209 */
210 public void testPublishAfterMultiSubscribeNoDup() {
211 log.info("testPublishAfterMultiSubscribeNoDup ...");
212 numReceived = 0;
213 duplicates = false; // suppress multi update
214
215 connect();
216
217 subscribe();
218 try { Thread.sleep(1000L); } catch( InterruptedException i) {} // Wait some time for callback to arrive ...
219 assertEquals("numReceived after subscribe", 0, numReceived); // there should be no Callback
220
221 publish();
222 try { Thread.sleep(2000L); } catch( InterruptedException i) {}
223 assertEquals("numReceived after publishing", 1, numReceived); // only one message arrived?
224
225 unSubscribe();
226
227 numReceived = 0;
228 publish();
229 try { Thread.sleep(2000L); } catch( InterruptedException i) {}
230 assertEquals("numReceived after publishing", 0, numReceived); // no message arrived?
231 }
232
233 /**
234 * TEST: Construct a message and publish it,<br />
235 * the previous XPath subscription should match and send an update.
236 */
237 public void testPublishAfterMultiSubscribe() {
238 log.info("testPublishAfterMultiSubscribe ...");
239 numReceived = 0;
240 duplicates = true; // allow multi update (default)
241
242 connect();
243
244 subscribe();
245 try { Thread.sleep(1000L); } catch( InterruptedException i) {} // Wait some time for callback to arrive ...
246 assertEquals("numReceived after subscribe", 0, numReceived); // there should be no Callback
247
248 publish();
249 try { Thread.sleep(2000L); } catch( InterruptedException i) {}
250 assertEquals("numReceived after publishing", 3, numReceived); // only one message arrived?
251
252 unSubscribe();
253
254 numReceived = 0;
255 publish();
256 try { Thread.sleep(2000L); } catch( InterruptedException i) {}
257 assertEquals("numReceived after publishing", 0, numReceived); // no message arrived?
258 }
259
260 /**
261 * This is the callback method invoked from xmlBlaster
262 * delivering us a new asynchronous message.
263 * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
264 */
265 public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos) {
266 log.info("Receiving update of a message " + updateKey.getOid() + " state=" + updateQos.getState());
267
268 numReceived += 1;
269
270 // Wait that publish() returns and set 'publishOid' properly
271 try { Thread.sleep(200); } catch( InterruptedException i) {}
272
273 if (!duplicates)
274 assertEquals("engine.qos.update.subscriptionId: Wrong subscriptionId", subscribeId1, updateQos.getSubscriptionId());
275 assertEquals("Wrong oid of message returned", publishOid, updateKey.getOid());
276 assertEquals("Message content is corrupted", new String(senderContent), new String(content));
277 assertEquals("Message contentMime is corrupted", contentMime, updateKey.getContentMime());
278
279 return "";
280 }
281
282 /**
283 * Method is used by TestRunner to load these tests
284 */
285 public static Test suite() {
286 TestSuite suite= new TestSuite();
287 suite.addTest(new TestSubNoDup(new Global(), "testPublishAfterMultiSubscribeNoDup"));
288 suite.addTest(new TestSubNoDup(new Global(), "testPublishAfterMultiSubscribe"));
289 return suite;
290 }
291
292 /**
293 * Invoke: java org.xmlBlaster.test.qos.TestSubNoDup
294 * @deprecated Use the TestRunner from the testsuite to run it:<p />
295 * <pre> java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubNoDup</pre>
296 */
297 public static void main(String args[]) {
298 Global glob = new Global();
299 if (glob.init(args) != 0) {
300 System.err.println("Init failed");
301 System.exit(1);
302 }
303 TestSubNoDup testSub = new TestSubNoDup(glob, "TestSubNoDup");
304 testSub.setUp();
305 testSub.testPublishAfterMultiSubscribeNoDup();
306 testSub.tearDown();
307 testSub = new TestSubNoDup(glob, "TestSubNoDup");
308 testSub.setUp();
309 testSub.testPublishAfterMultiSubscribe();
310 testSub.tearDown();
311 }
312 }
syntax highlighted by Code2HTML, v. 0.9.1