1 /*------------------------------------------------------------------------------
  2 Name:      TestSubNoInitial.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 Comment:   Demo code for a client using xmlBlaster
  6 Version:   $Id: TestSubNoInitial.java 16640 2007-12-02 23:07:47Z laghi $
  7 ------------------------------------------------------------------------------*/
  8 package org.xmlBlaster.test.qos;
  9 
 10 import java.util.logging.Logger;
 11 import java.util.logging.Level;
 12 import org.xmlBlaster.util.Global;
 13 import org.xmlBlaster.util.XmlBlasterException;
 14 import org.xmlBlaster.client.qos.ConnectQos;
 15 import org.xmlBlaster.util.Timestamp;
 16 import org.xmlBlaster.util.qos.address.CallbackAddress;
 17 import org.xmlBlaster.client.I_XmlBlasterAccess;
 18 import org.xmlBlaster.client.I_Callback;
 19 import org.xmlBlaster.client.key.UpdateKey;
 20 import org.xmlBlaster.client.qos.UpdateQos;
 21 import org.xmlBlaster.client.qos.SubscribeQos;
 22 import org.xmlBlaster.client.qos.PublishReturnQos;
 23 import org.xmlBlaster.client.qos.EraseReturnQos;
 24 import org.xmlBlaster.util.MsgUnit;
 25 
 26 import junit.framework.*;
 27 
 28 
 29 /**
 30  * This client tests the method subscribe() with a later publish() with XPath query.
 31  * <br />
 32  * The subscribe() should be recognized for this later arriving publish()
 33  * <p>
 34  * This client may be invoked multiple time on the same xmlBlaster server,
 35  * as it cleans up everything after his tests are done.
 36  * <p>
 37  * Invoke examples:<br />
 38  * <pre>
 39  *    java junit.textui.TestRunner -noloading org.xmlBlaster.test.qos.TestSubNoInitial
 40  *    java junit.swingui.TestRunner -noloading org.xmlBlaster.test.qos.TestSubNoInitial
 41  * </pre>
 42  */
 43 public class TestSubNoInitial extends TestCase implements I_Callback
 44 {
 45    private static String ME = "TestSubNoInitial";
 46    private final Global glob;
 47    private static Logger log = Logger.getLogger(TestSubNoInitial.class.getName());
 48    private boolean messageArrived = false;
 49 
 50    private String subscribeOid;
 51    private String publishOid = "dummyTestSubNoInitial";
 52    private I_XmlBlasterAccess senderConnection;
 53    private String senderName;
 54    private String senderContent;
 55    private String receiverName;         // sender/receiver is here the same client
 56    private Timestamp sentTimestamp;
 57    private String cbSessionId = "0fxrc83plP";
 58 
 59    private int numReceived = 0;         // error checking
 60    private final String contentMime = "text/xml";
 61    private final String contentMimeExtended = "1.0";
 62 
 63    private String assertInUpdate = null;
 64 
 65    /**
 66     * Constructs the TestSubNoInitial object.
 67     * <p />
 68     * @param testName  The name used in the test suite
 69     * @param loginName The name to login to the xmlBlaster
 70     */
 71    public TestSubNoInitial(Global glob, String testName, String loginName)
 72    {
 73       super(testName);
 74       this.glob = glob;
 75 
 76       this.senderName = loginName;
 77       this.receiverName = loginName;
 78    }
 79 
 80 
 81    /**
 82     * Sets up the fixture.
 83     * <p />
 84     * Connect to xmlBlaster and login
 85     */
 86    protected void setUp()
 87    {
 88       try {
 89          senderConnection = glob.getXmlBlasterAccess(); // Find orb
 90 
 91          String passwd = "secret";
 92          ConnectQos qos = new ConnectQos(glob, senderName, passwd);
 93          CallbackAddress cbAddress = new CallbackAddress(this.glob);
 94          cbAddress.setSecretSessionId(cbSessionId); // to protect our callback server - see method update()
 95          cbAddress.setDispatchPlugin("undef");
 96          qos.addCallbackAddress(cbAddress);
 97          senderConnection.connect(qos, this); // Login to xmlBlaster
 98       }
 99       catch (Exception e) {
100           log.severe("Login failed: " + e.toString());
101           e.printStackTrace();
102           assertTrue("Login failed: " + e.toString(), false);
103       }
104    }
105 
106 
107    /**
108     * Tears down the fixture.
109     * <p />
110     * cleaning up .... erase() the previous message OID and logout
111     */
112    protected void tearDown()
113    {
114       String xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
115                       "<key oid='" + publishOid + "' queryType='EXACT'>\n" +
116                       "</key>";
117       String qos = "<qos></qos>";
118       try {
119          EraseReturnQos[] arr = senderConnection.erase(xmlKey, qos);
120          assertEquals("Erase", 1, arr.length);
121          waitOnUpdate(5000L);
122          assertTrue(assertInUpdate, assertInUpdate == null);
123       } catch(XmlBlasterException e) { fail("Erase XmlBlasterException: " + e.getMessage()); }
124 
125       senderConnection.disconnect(null);
126    }
127 
128 
129    /**
130     * Subscribe to messages with XPATH.
131     */
132    public void subscribeXPath()
133    {
134       if (log.isLoggable(Level.FINE)) log.fine("Subscribing using XPath syntax ...");
135 
136       String xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
137                       "<key oid='' queryType='XPATH'>\n" +
138                       "   //TestSubNoInitial-AGENT" +
139                       "</key>";
140       numReceived = 0;
141       subscribeOid = null;
142       SubscribeQos sk = new SubscribeQos(glob);
143       sk.setWantInitialUpdate(false);
144       String qos = sk.toXml(); // "<qos><initialUpdate>false</initialUpdate></qos>";
145       try {
146          subscribeOid = senderConnection.subscribe(xmlKey, qos).getSubscriptionId();
147          log.info("Success: Subscribe subscription-id=" + subscribeOid + " done");
148       } catch(XmlBlasterException e) {
149          log.warning("XmlBlasterException: " + e.getMessage());
150          assertTrue("subscribe - XmlBlasterException: " + e.getMessage(), false);
151       }
152       assertTrue("returned null subscribeOid", subscribeOid != null);
153       assertTrue("returned subscribeOid is empty", 0 != subscribeOid.length());
154    }
155 
156 
157    /**
158     * TEST: Construct a message and publish it.
159     * <p />
160     * The returned publishOid is checked
161     */
162    public void publish()
163    {
164       if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
165 
166       numReceived = 0;
167       String xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
168                       "<key oid='" + publishOid + "' contentMime='" + contentMime + "' contentMimeExtended='" + contentMimeExtended + "'>\n" +
169                       "   <TestSubNoInitial-AGENT id='192.168.124.10' subId='1' type='generic'>" +
170                       "      <TestSubNoInitial-DRIVER id='FileProof' pollingFreq='10'>" +
171                       "      </TestSubNoInitial-DRIVER>"+
172                       "   </TestSubNoInitial-AGENT>" +
173                       "</key>";
174       senderContent = "Yeahh, i'm the new content";
175       try {
176          MsgUnit msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), "<qos></qos>");
177          sentTimestamp = new Timestamp();
178          PublishReturnQos tmp = senderConnection.publish(msgUnit);
179          assertEquals("Wrong publishOid", publishOid, tmp.getKeyOid());
180          log.info("Success: Publishing done, returned oid=" + publishOid);
181       } catch(XmlBlasterException e) {
182          log.warning("XmlBlasterException: " + e.getMessage());
183          assertTrue("publish - XmlBlasterException: " + e.getMessage(), false);
184       }
185    }
186 
187 
188    /**
189     * TEST: Construct a message and publish it,<br />
190     * the previous XPath subscription should match and send an update.
191     */
192    public void testNoInitialUpdate()
193    {
194       publish();
195       try { Thread.sleep(1000L); } catch( InterruptedException i) {}
196       assertTrue(assertInUpdate, assertInUpdate == null);
197       assertEquals("numReceived after subscribe", 0, numReceived);
198 
199       subscribeXPath();
200       try { Thread.sleep(1000L); } catch( InterruptedException i) {}
201       assertTrue(assertInUpdate, assertInUpdate == null);
202       assertEquals("numReceived after subscribe", 0, numReceived);  // there should be no Callback
203 
204       publish();
205       waitOnUpdate(5000L);
206       assertTrue(assertInUpdate, assertInUpdate == null);
207       assertEquals("numReceived after publishing", 1, numReceived); // message arrived?
208    }
209 
210 
211    /**
212     * This is the callback method invoked from xmlBlaster
213     * delivering us a new asynchronous message. 
214     * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
215     */
216    public String update(String cbSessionId_, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
217    {
218       log.info("Receiving update of message oid=" + updateKey.getOid() + " subId=" + updateQos.getSubscriptionId() + " ...");
219 
220       numReceived += 1;
221 
222       if (updateQos.isErased())
223          return "";
224 
225       assertInUpdate = "Wrong cbSessionId, expected:" + this.cbSessionId + " but was:" + cbSessionId_;
226       assertEquals("Wrong cbSessionId", this.cbSessionId, cbSessionId_);
227 
228       assertInUpdate = "Wrong sender, expected:" + senderName + " but was:" + updateQos.getSender();
229       assertEquals("Wrong sender", senderName, updateQos.getSender().getLoginName());
230 
231       assertInUpdate = "Wrong subscriptionId, expected:" + subscribeOid + " but was:" + updateQos.getSubscriptionId();
232       assertEquals("engine.qos.update.subscriptionId: Wrong subscriptionId", subscribeOid, updateQos.getSubscriptionId());
233 
234       assertInUpdate = "Wrong oid of message returned expected:" + publishOid + " but was:" + updateKey.getOid();
235       assertEquals("Wrong oid of message returned", publishOid, updateKey.getOid());
236 
237       assertInUpdate = "Message content is corrupted expected:" + new String(senderContent) + " but was:" + new String(content);
238       assertEquals("Message content is corrupted", new String(senderContent), new String(content));
239       
240       assertInUpdate = "Message contentMime is corrupted expected:" + contentMime + " but was:" + updateKey.getContentMime();
241       assertEquals("Message contentMime is corrupted", contentMime, updateKey.getContentMime());
242       
243       assertInUpdate = "Message contentMimeExtended is corrupted expected:" + contentMimeExtended + " but was: " + updateKey.getContentMimeExtended();
244       assertEquals("Message contentMimeExtended is corrupted", contentMimeExtended, updateKey.getContentMimeExtended());
245 
246       // Test requirement "engine.qos.update.rcvTimestamp":
247       assertInUpdate = "sentTimestamp not in hamony with rcvTimestamp";
248       assertTrue("sentTimestamp="+sentTimestamp+" not in hamony with rcvTimestamp="+updateQos.getRcvTimestamp(),
249              sentTimestamp.getMillis() <= updateQos.getRcvTimestamp().getMillis() &&
250              (sentTimestamp.getMillis()+1000) > updateQos.getRcvTimestamp().getMillis());
251 
252       assertInUpdate = null;
253       messageArrived = true;
254       return "";
255    }
256 
257 
258    /**
259     * Little helper, waits until the variable 'messageArrive' is set
260     * to true, or returns when the given timeout occurs.
261     * @param timeout in milliseconds
262     */
263    private void waitOnUpdate(final long timeout)
264    {
265       long pollingInterval = 50L;  // check every 0.05 seconds
266       if (timeout < 50)  pollingInterval = timeout / 10L;
267       long sum = 0L;
268       while (!messageArrived) {
269          try {
270             Thread.sleep(pollingInterval);
271          }
272          catch( InterruptedException i)
273          {}
274          sum += pollingInterval;
275          if (sum > timeout) {
276             log.warning("Timeout of " + timeout + " occurred");
277             break;
278          }
279       }
280       messageArrived = false;
281    }
282 
283 
284    /**
285     * Method is used by TestRunner to load these tests
286     */
287    public static Test suite()
288    {
289        TestSuite suite= new TestSuite();
290        String loginName = "Tim";
291        suite.addTest(new TestSubNoInitial(new Global(), "testNoInitialUpdate", loginName));
292        return suite;
293    }
294 
295 
296    /**
297     * Invoke: java org.xmlBlaster.test.qos.TestSubNoInitial
298     * @deprecated Use the TestRunner from the testsuite to run it:<p />
299     * <pre>   java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubNoInitial</pre>
300     */
301    public static void main(String args[])
302    {
303       Global glob = new Global();
304       if (glob.init(args) != 0) {
305          System.out.println("Init failed");
306          System.exit(1);
307       }
308       TestSubNoInitial testSub = new TestSubNoInitial(glob, "TestSubNoInitial", "Tim");
309       testSub.setUp();
310       testSub.testNoInitialUpdate();
311       testSub.tearDown();
312    }
313 }


syntax highlighted by Code2HTML, v. 0.9.1