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