1 /*------------------------------------------------------------------------------
  2 Name:      TestLogin.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 ------------------------------------------------------------------------------*/
  6 package org.xmlBlaster.test.authentication;
  7 
  8 import java.util.logging.Logger;
  9 import java.util.logging.Level;
 10 import org.xmlBlaster.util.Global;
 11 import org.xmlBlaster.util.def.ErrorCode;
 12 import org.xmlBlaster.util.XmlBlasterException;
 13 import org.xmlBlaster.client.qos.ConnectQos;
 14 import org.xmlBlaster.client.qos.DisconnectQos;
 15 import org.xmlBlaster.util.SessionName;
 16 import org.xmlBlaster.util.MsgUnit;
 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.key.PublishKey;
 21 import org.xmlBlaster.client.qos.PublishQos;
 22 import org.xmlBlaster.client.qos.UpdateQos;
 23 import org.xmlBlaster.client.qos.EraseReturnQos;
 24 import org.xmlBlaster.util.qos.address.Destination;
 25 
 26 import junit.framework.*;
 27 
 28 
 29 /**
 30  * This client does test login and logout.<br />
 31  * login/logout combinations are checked with subscribe()/publish() calls
 32  * <p />
 33  * This client may be invoked multiple time on the same xmlBlaster server,
 34  * as it cleans up everything after his tests are done.
 35  * <p>
 36  * Invoke examples:<br />
 37  * <pre>
 38  *    java junit.textui.TestRunner org.xmlBlaster.test.authentication.TestLogin
 39  *    java junit.swingui.TestRunner -noloading org.xmlBlaster.test.authentication.TestLogin
 40  * </pre>
 41  */
 42 public class TestLogin extends TestCase implements I_Callback
 43 {
 44    private static String ME = "TestLogin";
 45    private final Global glob;
 46    private static Logger log = Logger.getLogger(TestLogin.class.getName());
 47 
 48    private String publishOid = "";
 49    private String firstOid = "FirstOid";
 50    private I_XmlBlasterAccess callbackConnection;
 51    private String senderName;
 52    private String senderContent;
 53 
 54    private I_XmlBlasterAccess secondConnection;
 55    private String secondName;
 56    private String secondOid = "SecondOid";
 57 
 58    private MsgUnit msgUnit;     // a message to play with
 59 
 60    private int numReceived = 0;         // error checking
 61    private final String contentMime = "text/plain";
 62    private final String contentMimeExtended = "1.0";
 63 
 64    private final boolean IS_PTP = true;
 65    private final boolean IS_PUBSUB = false;
 66 
 67    /**
 68     * Constructs the TestLogin object.
 69     * <p />
 70     * @param testName   The name used in the test suite
 71     * @param loginName  The name to login to the xmlBlaster
 72     * @param secondName The name to login to the xmlBlaster again
 73     */
 74    public TestLogin(Global glob, String testName, String senderName, String secondName)
 75    {
 76       super(testName);
 77       this.glob = glob;
 78 
 79       this.senderName = senderName;
 80       this.secondName = secondName;
 81    }
 82 
 83 
 84    /**
 85     * Sets up the fixture.
 86     * <p />
 87     * Connect to xmlBlaster and login
 88     */
 89    protected void setUp()
 90    {
 91       log.info("######## Entering setup");
 92       try {
 93          String passwd = "secret";
 94 
 95          callbackConnection = glob.getXmlBlasterAccess(); // Find orb
 96          ConnectQos qos = new ConnectQos(glob, senderName, passwd);
 97          callbackConnection.connect(qos, this); // Login to xmlBlaster
 98 
 99          Global secondGlobal = glob.getClone(null);
100          secondConnection = secondGlobal.getXmlBlasterAccess(); // Find orb
101          qos = new ConnectQos(secondGlobal, secondName, passwd);
102          secondConnection.connect(qos, this);
103 
104       }
105       catch (XmlBlasterException e) {
106          if (e.getErrorCode() == ErrorCode.USER_CONNECT_MULTIPLE) {
107             // ignore
108          }
109          else {
110             log.severe(e.toString());
111             fail(ME + ".setup failed: " + e.toString());
112          }
113       }
114 
115       // a sample message unit
116       String xmlKey = "<key oid='" + firstOid + "' contentMime='" + contentMime + "' contentMimeExtended='" + contentMimeExtended + "'>\n" +
117                         "   <TestLogin-AGENT>" +
118                         "   </TestLogin-AGENT>" +
119                         "</key>";
120       senderContent = "Some content";
121       try {
122          msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), "<qos></qos>");
123       }
124       catch (XmlBlasterException e) {
125          log.severe("setup() failed: " + e.getMessage());
126          fail(e.getMessage());
127       }
128    }
129 
130 
131    /**
132     * Tears down the fixture.
133     * <p />
134     * cleaning up .... erase() the previous message OID and logout
135     */
136    protected void tearDown()
137    {
138       {
139          String xmlKey = "<key oid='" + firstOid + "' queryType='EXACT'>\n</key>";
140          String qos = "<qos></qos>";
141          try {
142             EraseReturnQos[] arr = callbackConnection.erase(xmlKey, qos);
143             if (arr != null && arr.length != 1) log.severe("Erased " + arr.length + " messages:");
144             assertEquals("Wrong number of messages erased", 1, arr.length);
145          } catch(XmlBlasterException e) {
146             log.severe("XmlBlasterException in erase(): " + e.getMessage());
147             fail(ME+"-tearDown() XmlBlasterException in erase(): " + e.getMessage());
148          }
149       }
150 
151       {
152          String xmlKey = "<key oid='" + secondOid + "' queryType='EXACT'>\n</key>";
153          String qos = "<qos></qos>";
154          try {
155             EraseReturnQos[] arr = callbackConnection.erase(xmlKey, qos);
156             if (arr.length != 1)
157                log.severe("Erased " + arr.length + " messages of '" + secondOid + "'");
158             assertEquals("Wrong number of messages '" + secondOid + "' erased", 1, arr.length);
159          } catch(XmlBlasterException e) { 
160             log.severe("XmlBlasterException in erase(): " + e.getMessage());
161             fail(ME+"-tearDown() XmlBlasterException in erase(): " + e.getMessage());
162          }
163       }
164 
165       DisconnectQos qos = new DisconnectQos(glob);
166       qos.clearSessions(true);
167       callbackConnection.disconnect(qos);
168       secondConnection.disconnect(null);
169    }
170 
171 
172    /**
173     * TEST: Subscribe to messages with XPATH.
174     * <p />
175     * The returned subscribeOid is checked
176     */
177    public void doSubscribeXPath()
178    {
179       if (log.isLoggable(Level.FINE)) log.fine("Subscribing using XPath syntax ...");
180 
181       String xmlKey = "<key oid='' queryType='XPATH'>\n" +
182                       "   //TestLogin-AGENT" +
183                       "</key>";
184       String qos = "<qos></qos>";
185       numReceived = 0;
186       try {
187          String subscribeOid = callbackConnection.subscribe(xmlKey, qos).getSubscriptionId();
188          assertTrue("returned null subscribeOid", subscribeOid != null);
189          assertTrue("returned subscribeOid is empty", 0 != subscribeOid.length());
190          log.info("Success: Subscribe on " + subscribeOid + " done");
191       } catch(XmlBlasterException e) {
192          log.warning("XmlBlasterException: " + e.getMessage());
193          assertTrue("subscribe - XmlBlasterException: " + e.getMessage(), false);
194       }
195    }
196 
197 
198    /**
199     * TEST: Construct a message and publish it.
200     * <p />
201     * The returned publishOid is checked
202     * @param ptp Use the Point to Point style
203     */
204    public void doPublish(boolean ptp)
205    {
206       if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
207 
208       numReceived = 0;
209       try {
210          PublishQos publishQos = new PublishQos(glob);
211          msgUnit = new MsgUnit(msgUnit, null, null, publishQos.getData());
212          if (ptp) {
213             PublishKey pk = new PublishKey(glob);
214             PublishQos pq = new PublishQos(glob);
215             pq.addDestination(new Destination(new SessionName(glob, secondName)));
216             msgUnit = new MsgUnit(msgUnit, pk.getData(), null, pq.getData());
217          }
218          publishOid = callbackConnection.publish(msgUnit).getKeyOid();
219          log.info("Success: Publish " + msgUnit.getKey() + " done");
220          if (!ptp)
221             assertEquals("oid is different", firstOid, publishOid);
222       } catch(XmlBlasterException e) {
223          log.warning("XmlBlasterException: " + e.getMessage());
224          assertTrue("publish - XmlBlasterException: " + e.getMessage(), false);
225       }
226 
227       assertTrue("returned publishOid == null", publishOid != null);
228       assertTrue("returned publishOid", 0 != publishOid.length());
229    }
230 
231 
232    /**
233     * TEST: Construct a message and publish it,<br />
234     * the previous XPath subscription should match and send an update.
235     */
236    public void testLoginLogout()
237    {
238       log.info("TEST 1: Subscribe and publish -> Expecting one update");
239       numReceived = 0;
240       doSubscribeXPath();
241       doPublish(IS_PUBSUB);
242       waitOnUpdate(2000L, 1);              // message arrived?
243 
244       log.info("TEST 2: Login again without logout and publish PtP -> Expecting one update");
245       setUp();
246       doPublish(IS_PTP);                 // sending directly PtP to 'receiver'
247       waitOnUpdate(2000L, 1);              // 2 times logged in, 2 messages arrived?
248 
249       log.info("TEST 3: Login again without logout and publish Pub/Sub -> Expecting no update");
250       setUp();
251       doPublish(IS_PUBSUB);
252       waitOnUpdate(2000L, 1);              // 1 times subscribed (TEST 1), 1 messages arrived?
253       numReceived = 0;
254 
255       log.info("TEST 4: Now subscribe -> Expecting one update");
256       numReceived = 0;
257       doSubscribeXPath();
258       waitOnUpdate(2000L, 1);              // message arrived?
259 
260       log.info("TEST 5: Test publish from other user -> Expecting one update");
261       numReceived = 0;
262       try {
263          // a sample message unit
264          String xmlKey = "<key oid='" + secondOid + "' contentMime='" + contentMime + "' contentMimeExtended='" + contentMimeExtended + "'>\n" +
265                          "   <TestLogin-AGENT>" +
266                          "   </TestLogin-AGENT>" +
267                          "</key>";
268          String content = "Some content";
269          MsgUnit mu = new MsgUnit(xmlKey, content.getBytes(), "<qos></qos>");
270          publishOid = secondConnection.publish(mu).getKeyOid();
271       } catch(XmlBlasterException e) {
272          log.warning("XmlBlasterException: " + e.getMessage());
273          assertTrue("second - publish - XmlBlasterException: " + e.getMessage(), false);
274       }
275       waitOnUpdate(2000L, 2); // 2 messages (we have subscribed 2 times, and the old session remained on relogin)
276 
277       assertTrue("returned publishOid == null", publishOid != null);
278       assertTrue("returned publishOid", 0 != publishOid.length());
279 
280       log.info("TEST 6: Test logout with following publish -> Should not be possible");
281       // test logout with following subscribe()
282       callbackConnection.disconnect(null);
283       try {
284          publishOid = callbackConnection.publish(msgUnit).getKeyOid();
285          assertTrue("Didn't expect successful publish after logout", false);
286       } catch(XmlBlasterException e) {
287          log.info("Success got exception for publishing after logout: " + e.toString());
288       }
289       try { Thread.sleep(1000L); } catch (Exception e) { } // wait a second
290       assertEquals("Didn't expect an update", 0, numReceived);
291 
292       log.info("SUCCESS in testLoginLogout()");
293 
294       // login again
295       setUp();
296 
297    }
298 
299    /**
300     * This is the callback method invoked from xmlBlaster
301     * delivering us a new asynchronous message. 
302     * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
303     */
304    public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
305    {
306       log.info("Receiving update of a message " + updateKey.getOid() + " state=" + updateQos.getState() +
307                " rcvTime=" + updateQos.getRcvTimestamp().toString());
308       log.info("Receiving update of a message " + updateKey.getOid() + updateQos.toXml());
309       numReceived++;
310       return "";
311    }
312 
313 
314    /**
315     * Little helper, waits until the wanted number of messages are arrived
316     * or returns when the given timeout occurs.
317     * <p />
318     * @param timeout in milliseconds
319     * @param numWait how many messages to wait
320     */
321    private void waitOnUpdate(final long timeout, final int numWait)
322    {
323       long pollingInterval = 50L;  // check every 0.05 seconds
324       if (timeout < 50)  pollingInterval = timeout / 10L;
325       long sum = 0L;
326       // check if too few are arriving
327       while (numReceived < numWait) {
328          try { Thread.sleep(pollingInterval); } catch( InterruptedException i) {}
329          sum += pollingInterval;
330          if (sum > timeout) {
331             log.severe("Timeout of " + timeout + " occurred without update");
332             Thread.dumpStack();
333          }
334          assertTrue("Timeout of " + timeout + " occurred without update", sum <= timeout);
335       }
336 
337       // check if too many are arriving
338       try { Thread.sleep(timeout); } catch( InterruptedException i) {}
339       if (numWait != numReceived) {
340          log.severe("Wrong number of messages arrived, expected numWait=" + numWait + " but got numReceived=" + numReceived);
341          Thread.dumpStack();
342       }
343       assertEquals("Wrong number of messages arrived", numWait, numReceived);
344 
345       numReceived = 0;
346    }
347 
348 
349    /**
350     * Method is used by TestRunner to load these tests
351     */
352    public static Test suite()
353    {
354        TestSuite suite= new TestSuite();
355        String loginName = "Tim";
356        suite.addTest(new TestLogin(new Global(), "testLoginLogout", loginName, "Joe"));
357        return suite;
358    }
359 
360 
361    /**
362     * Invoke: java org.xmlBlaster.test.authentication.TestLogin
363     * <br />
364     * @deprecated Use the TestRunner from the testsuite to run it:<p />
365     * <pre>   java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.authentication.TestLogin</pre>
366     */
367    public static void main(String args[])
368    {
369       Global glob = new Global();
370       if (glob.init(args) != 0) {
371          System.err.println(ME + ": Init failed");
372          System.exit(1);
373       }
374       TestLogin testSub = new TestLogin(glob, "TestLogin", "Tim", "Joe");
375       testSub.setUp();
376       testSub.testLoginLogout();
377       testSub.tearDown();
378    }
379 }


syntax highlighted by Code2HTML, v. 0.9.1