1 /*------------------------------------------------------------------------------
  2 Name:      TestSubLostClient.java
  3 Project:   xmlBlaster.org
  4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
  5 ------------------------------------------------------------------------------*/
  6 package org.xmlBlaster.test.qos;
  7 
  8 import java.util.logging.Level;
  9 import java.util.logging.Logger;
 10 
 11 import junit.framework.Test;
 12 import junit.framework.TestCase;
 13 import junit.framework.TestSuite;
 14 
 15 import org.xmlBlaster.client.I_Callback;
 16 import org.xmlBlaster.client.I_XmlBlasterAccess;
 17 import org.xmlBlaster.client.key.SubscribeKey;
 18 import org.xmlBlaster.client.key.UpdateKey;
 19 import org.xmlBlaster.client.qos.ConnectQos;
 20 import org.xmlBlaster.client.qos.EraseReturnQos;
 21 import org.xmlBlaster.client.qos.SubscribeQos;
 22 import org.xmlBlaster.client.qos.UpdateQos;
 23 import org.xmlBlaster.test.Util;
 24 import org.xmlBlaster.util.Global;
 25 import org.xmlBlaster.util.MsgUnit;
 26 import org.xmlBlaster.util.StopWatch;
 27 import org.xmlBlaster.util.XmlBlasterException;
 28 
 29 
 30 /**
 31  * This client tests if a subscribe still works when an other subcriber
 32  * on the same messages disappears.
 33  * <p>
 34  * This bug was reported by
 35  *       "Stefan Nickisch" <nickisch.stefan@stn-atlas.de>
 36  * <p>
 37  * Invoke examples:<br />
 38  * <pre>
 39  *  java org.xmlBlaster.Main
 40  *
 41  *  java org.xmlBlaster.test.qos.TestSubLostClient -dispatch/connection/protocol IIOP
 42  *
 43  *  java junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubLostClient
 44  *  java junit.swingui.TestRunner org.xmlBlaster.test.qos.TestSubLostClient
 45  * </pre>
 46  */
 47 public class TestSubLostClient extends TestCase implements I_Callback
 48 {
 49    private static String ME = "TestSubLostClient";
 50    private final Global glob;
 51    private static Logger log = Logger.getLogger(TestSubLostClient.class.getName());
 52 
 53    private final String publishOid1 = "dummy1";
 54    private I_XmlBlasterAccess oneConnection;
 55    private String oneName;
 56 
 57    private int numReceived = 0;         // error checking
 58    private final String contentMime = "text/xml";
 59    private final String contentMimeExtended = "1.0";
 60 
 61    class Client {
 62       String loginName;
 63       I_XmlBlasterAccess connection;
 64       String subscribeOid;
 65    }
 66 
 67    private int numClients;
 68    private Client[] manyClients;
 69 
 70    private StopWatch stopWatch = new StopWatch();
 71 
 72    /**
 73     * Constructs the TestSubLostClient object.
 74     * <p />
 75     * @param testName  The name used in the test suite
 76     * @param loginName The name to login to the xmlBlaster
 77     */
 78    public TestSubLostClient(Global glob, String testName, String loginName)
 79    {
 80       super(testName);
 81       this.glob = glob;
 82 
 83       this.oneName = loginName;
 84       numClients = 2;
 85    }
 86 
 87 
 88    /**
 89     * Sets up the fixture.
 90     * <p />
 91     * Connect to xmlBlaster and login
 92     */
 93    protected void setUp()
 94    {
 95       log.info("Setting up test ...");
 96       numReceived = 0;
 97       try {
 98          oneConnection = glob.getXmlBlasterAccess(); // Find orb
 99          String passwd = "secret";
100          ConnectQos connectQos = new ConnectQos(glob, oneName, passwd);
101          oneConnection.connect(connectQos, this); // Login to xmlBlaster
102       }
103       catch (Exception e) {
104           log.severe("Login failed: " + e.toString());
105           e.printStackTrace();
106           assertTrue("Login failed: " + e.toString(), false);
107       }
108    }
109 
110 
111    /**
112     * Tears down the fixture.
113     * <p />
114     * cleaning up .... erase() the previous message OID and logout
115     */
116    protected void tearDown()
117    {
118       if (numReceived != (numClients-1)) log.severe("numClients=" + (numClients-1) + " but numReceived=" + numReceived);
119       assertEquals("numClients=1 but numReceived=" + numReceived, numClients-1, numReceived);
120 
121       if (manyClients != null) {
122          for (int ii=0; ii<numClients; ii++) {
123             Client sub = manyClients[ii];
124             sub.connection.disconnect(null);
125          }
126       }
127 
128       {
129          String xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
130                          "<key oid='" + publishOid1 + "' queryType='EXACT'>\n" +
131                          "</key>";
132          try {
133             EraseReturnQos[] arr = oneConnection.erase(xmlKey, "<qos/>");
134             assertEquals("Erase", 1, arr.length);
135          } catch(XmlBlasterException e) { fail("Erase XmlBlasterException: " + e.getMessage()); }
136       }
137 
138       oneConnection.disconnect(null);
139       log.info("Logout done");
140    }
141 
142 
143    /**
144     * Many clients subscribe to a message.
145     */
146    public void susbcribeMany()
147    {
148       if (log.isLoggable(Level.FINE)) log.fine("Subscribing ...");
149 
150       String passwd = "secret";
151 
152       SubscribeKey subKeyW = new SubscribeKey(glob, publishOid1);
153       String subKey = subKeyW.toXml(); // "<key oid='" + publishOid1 + "' queryType='EXACT'></key>";
154 
155       SubscribeQos subQosW = new SubscribeQos(glob); // "<qos></qos>";
156       String subQos = subQosW.toXml();
157 
158       manyClients = new Client[numClients];
159 
160       log.info("Setting up " + numClients + " subscriber clients ...");
161       stopWatch = new StopWatch();
162       for (int ii=0; ii<numClients; ii++) {
163          Client sub = new Client();
164          sub.loginName = "Joe-" + ii;
165 
166          try {
167             Global globSub = glob.getClone(null);
168             sub.connection = globSub.getXmlBlasterAccess();
169             ConnectQos loginQosW = new ConnectQos(globSub, sub.loginName, passwd); // "<qos></qos>"; During login this is manipulated (callback address added)
170             sub.connection.connect(loginQosW, this);
171          }
172          catch (Exception e) {
173              log.severe("Login failed: " + e.toString());
174              assertTrue("Login failed: " + e.toString(), false);
175          }
176 
177          try {
178             sub.subscribeOid = sub.connection.subscribe(subKey, subQos).getSubscriptionId();
179             log.info("Client " + sub.loginName + " subscribed to " + subKeyW.getOid());
180          } catch(XmlBlasterException e) {
181             log.warning("XmlBlasterException: " + e.getMessage());
182             assertTrue("subscribe - XmlBlasterException: " + e.getMessage(), false);
183          }
184 
185          manyClients[ii] = sub;
186       }
187       double timeForLogins = stopWatch.elapsed()/1000.; // msec -> sec
188 
189       log.info(numClients + " subscriber clients are ready.");
190       log.info("Time " + (long)(numClients/timeForLogins) + " logins/sec");
191       try {
192          org.xmlBlaster.test.util.Client.shutdownCb(manyClients[0].connection, org.xmlBlaster.test.util.Client.Shutdown.LOGOUT);
193       }
194       catch (XmlBlasterException ex) {
195          assertTrue("An exception should not occur " + ex.getMessage(), false);
196       }
197    }
198 
199 
200    /**
201     * TEST: Construct a message and publish it.
202     * <p />
203     * The returned publishOid1 is checked
204     */
205    public void publishOne()
206    {
207       if (log.isLoggable(Level.FINE)) log.fine("Publishing a message ...");
208 
209       numReceived = 0;
210       String xmlKey = "<?xml version='1.0' encoding='ISO-8859-1' ?>\n" +
211                       "<key oid='" + publishOid1 + "' contentMime='" + contentMime + "' contentMimeExtended='" + contentMimeExtended + "'>\n" +
212                       "</key>";
213       String senderContent = "Yeahh, i'm the new content";
214       try {
215          MsgUnit msgUnit = new MsgUnit(xmlKey, senderContent.getBytes(), "<qos></qos>");
216          stopWatch = new StopWatch();
217          String tmp = oneConnection.publish(msgUnit).getKeyOid();
218          assertEquals("Wrong publishOid1", publishOid1, tmp);
219          log.info("Success: Publishing done, returned oid=" + publishOid1);
220       } catch(XmlBlasterException e) {
221          log.severe("XmlBlasterException in publish: " + e.getMessage());
222          assertTrue("XmlBlasterException in publish: " + e.getMessage(), true);
223       }
224    }
225 
226 
227    /**
228     * TEST: Construct a message and publish it,
229     * all clients should receive an update.
230     */
231    public void testManyClients()
232    {
233       System.out.println("");
234       log.info("TEST 1, many subscribers, one publisher ...");
235 
236       susbcribeMany();
237       try { Thread.sleep(1000L); } catch( InterruptedException i) {}                                            // Wait some time for callback to arrive ...
238       assertEquals("numReceived after subscribe", 0, numReceived);  // there should be no Callback
239 
240       publishOne();
241       log.info("Waiting long enough for updates ...");
242       Util.delay(2000L + 10 * numClients);                          // Wait some time for callback to arrive ...
243       log.info("Received " + numReceived + " updates");
244       assertEquals("Wrong number of updates", numClients-1, numReceived); // One client killed its callback server
245    }
246 
247    /**
248     * This is the callback method invoked from xmlBlaster
249     * delivering us a new asynchronous message. 
250     * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
251     */
252    public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
253    {
254       log.info("Client " + cbSessionId + " receiving update of message oid=" + updateKey.getOid() + "...");
255       numReceived++;
256       return "";
257    }
258 
259    /**
260     * Method is used by TestRunner to load these tests
261     */
262    public static Test suite()
263    {
264        TestSuite suite= new TestSuite();
265        String loginName = "Tim";
266        suite.addTest(new TestSubLostClient(new Global(), "testManyClients", loginName));
267        return suite;
268    }
269 
270 
271    /**
272     * Invoke: java org.xmlBlaster.test.qos.TestSubLostClient
273     * <p />
274     * @deprecated Use the TestRunner from the testsuite to run it:<p />
275     * <pre>   java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.qos.TestSubLostClient</pre>
276     */
277    public static void main(String args[])
278    {
279       Global glob = new Global();
280       if (glob.init(args) != 0) {
281          System.err.println(ME + ": Init failed");
282          System.exit(1);
283       }
284       TestSubLostClient testSub = new TestSubLostClient(glob, "TestSubLostClient", "Tim");
285       testSub.setUp();
286       testSub.testManyClients();
287       testSub.tearDown();
288    }
289 }


syntax highlighted by Code2HTML, v. 0.9.1