1 /*------------------------------------------------------------------------------
2 Name: TestSession.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 org.xmlBlaster.util.Global;
10 import org.xmlBlaster.util.XmlBlasterException;
11 import org.xmlBlaster.client.qos.ConnectQos;
12 import org.xmlBlaster.client.qos.DisconnectQos;
13 import org.xmlBlaster.client.I_XmlBlasterAccess;
14 import org.xmlBlaster.client.I_Callback;
15 import org.xmlBlaster.client.key.UpdateKey;
16 import org.xmlBlaster.client.qos.UpdateQos;
17 import org.xmlBlaster.util.MsgUnit;
18
19 import org.xmlBlaster.test.Util;
20
21 import junit.framework.*;
22
23
24 /**
25 * This client does test login sessions.<br />
26 * login/logout combinations are checked with subscribe()/publish() calls
27 * <p />
28 * This client may be invoked multiple time on the same xmlBlaster server,
29 * as it cleans up everything after his tests are done.
30 * <p>
31 * Invoke examples:<br />
32 * <pre>
33 * java junit.textui.TestRunner org.xmlBlaster.test.authentication.TestSession
34 * java junit.swingui.TestRunner org.xmlBlaster.test.authentication.TestSession
35 * </pre>
36 */
37 public class TestSession extends TestCase implements I_Callback
38 {
39 private final Global glob;
40 private static Logger log = Logger.getLogger(TestSession.class.getName());
41 private String name;
42 private String passwd = "secret";
43 private int numReceived = 0; // error checking
44
45 /**
46 * Constructs the TestSession object.
47 * <p />
48 * @param testName The name used in the test suite
49 * @param name The name to login to the xmlBlaster
50 */
51 public TestSession(Global glob, String testName, String name)
52 {
53 super(testName);
54 this.glob = glob;
55
56 this.name = name;
57 }
58
59 /**
60 * Sets up the fixture.
61 * <p />
62 * Connect to xmlBlaster and login
63 */
64 protected void setUp()
65 {
66 }
67
68 /**
69 * Tears down the fixture.
70 * <p />
71 * cleaning up .... erase() the previous message OID and logout
72 */
73 protected void tearDown()
74 {
75 }
76
77 /**
78 */
79 public void testZeroSessions()
80 {
81 log.info("testZeroSessions() ...");
82 try {
83 log.info("Connecting ...");
84 Global glob = this.glob.getClone(null);
85 I_XmlBlasterAccess con = glob.getXmlBlasterAccess();
86 ConnectQos qos = new ConnectQos(glob, name, passwd);
87 qos.setMaxSessions(-16);
88 con.connect(qos, this); // Login to xmlBlaster
89 assertTrue("Connecting with zero sessions should not be possible", false);
90 }
91 catch (Exception e) {
92 log.info("Success, can't connect with zero sessions");
93 }
94 log.info("Success in testZeroSessions()");
95 }
96
97
98 /**
99 */
100 public void testSessionOverflow()
101 {
102 log.info("testSessionOverflow() ...");
103 int numLogin = 5;
104 int maxSessions = numLogin - 2;
105 I_XmlBlasterAccess[] con = new I_XmlBlasterAccess[5];
106 try {
107 for (int ii=0; ii<numLogin; ii++) {
108 try {
109 log.info("Connecting number " + ii + " of " + numLogin + " max=" + maxSessions);
110 con[ii] = glob.getClone(null).getXmlBlasterAccess();
111 ConnectQos qos = new ConnectQos(con[ii].getGlobal(), name, passwd);
112 qos.setMaxSessions(maxSessions);
113 con[ii].connect(qos, this); // Login to xmlBlaster
114 if (ii >= maxSessions)
115 assertTrue("Connecting number " + ii + " of max=" + maxSessions + " is not allowed", false);
116 }
117 catch (Exception e) {
118 if (ii >= maxSessions) {
119 log.info("Success, connecting number " + ii + " of max=" + maxSessions + " was denied: " + e.toString());
120 }
121 else {
122 log.severe(e.toString());
123 assertTrue("Connecting number " + ii + " of max=" + maxSessions + " should be possible", false);
124 }
125 }
126 }
127 }
128 finally { // clean up
129 try {
130 for (int ii=0; ii<maxSessions; ii++) {
131 DisconnectQos disQos = null;
132 if (con[ii] != null) {
133 con[ii].disconnect(disQos);
134 }
135 }
136 }
137 catch (Throwable e) {
138 assertTrue(e.toString(), false);
139 }
140 }
141 log.info("Success in testSessionOverflow()");
142 }
143
144
145 /**
146 * We login with session timeout 1 sec and sleep for 2 sec.
147 * A get() invocation should fail since the session is expired.
148 */
149 public void testSessionTimeout()
150 {
151 log.info("testSessionTimeout() ...");
152 long timeout = 1000L;
153 I_XmlBlasterAccess con = null;
154 Global glob = this.glob.getClone(null);
155 try {
156 try {
157 con = glob.getXmlBlasterAccess();
158 ConnectQos qos = new ConnectQos(glob, name, passwd);
159 qos.setSessionTimeout(timeout);
160 con.connect(qos, this);
161 }
162 catch (Exception e) {
163 log.severe(e.toString());
164 assertTrue("Login failed" + e.toString(), false);
165 }
166
167 try { Thread.sleep(timeout*2); } catch (Exception e) { } // wait until session expires
168
169 try {
170 log.info("Check that session has dissapeared ...");
171 MsgUnit[] msgs = Util.adminGet(glob, "__cmd:?clientList");
172 assertEquals("Can't access __cmd:?clientList", 1, msgs.length);
173 log.info("Got userList=" + msgs[0].getContentStr());
174 assertEquals("Session of " + name + " was not destroyed by failing callback",
175 -1, msgs[0].getContentStr().indexOf(name));
176 }
177 catch (XmlBlasterException e) {
178 fail("Session was not destroyed: " + e.toString());
179 }
180 }
181 finally { // clean up
182 try {
183 con.disconnect(null);
184 }
185 catch (Throwable e) {
186 assertTrue(e.toString(), false);
187 }
188 }
189 log.info("Success in testSessionTimeout()");
190 }
191
192
193 /**
194 * We login with session timeout 2 sec and let it automatically refresh.
195 * A get() invocation should fail since the session is expired.
196 */
197 public void testSessionRefresh()
198 {
199 log.info("testSessionRefresh() ...");
200 long timeout = 2000L;
201 I_XmlBlasterAccess con = null;
202 Global glob = this.glob.getClone(null);
203 try {
204 try {
205 con = glob.getXmlBlasterAccess();
206 ConnectQos qos = new ConnectQos(glob, name, passwd);
207 qos.setRefreshSession(true);
208 qos.setSessionTimeout(timeout);
209 con.connect(qos, this);
210 }
211 catch (Exception e) {
212 log.severe(e.toString());
213 assertTrue("Login failed" + e.toString(), false);
214 }
215
216 log.info("Wait " + timeout*2 + " sec if session expires (because of inactivity)");
217 try { Thread.sleep(timeout*2); } catch (Exception e) { }
218
219 try {
220 for (int ii=0; ii<1; ii++) {
221 try { Thread.sleep(timeout/2); } catch (Exception e) { }
222 log.info("Check access #" + ii + " ...");
223 con.get("<key oid='__cmd:?freeMem'/>", null);
224 log.info("Check access #" + ii + " OK");
225 }
226 }
227 catch (Exception e) {
228 log.severe("No access: " + e.toString());
229 assertTrue("Session is expired", false);
230 }
231 }
232 finally { // clean up
233 try {
234 con.disconnect(null);
235 }
236 catch (Throwable e) {
237 assertTrue(e.toString(), false);
238 }
239 }
240 log.info("Success in testSessionRefresh()");
241 }
242
243
244 /**
245 * We login with session timeout 2 sec, call every 1000 millis get()
246 * which should respan the session timeout.
247 * If this goes well for 8 sec, the refresh seems to work
248 */
249 public void testSessionTimeoutRespan()
250 {
251 log.info("testSessionTimeoutRespan() ...");
252 long timeout = 2000L;
253 I_XmlBlasterAccess con = null;
254 Global glob = this.glob.getClone(null);
255 try {
256 try {
257 con = glob.getXmlBlasterAccess();
258 ConnectQos qos = new ConnectQos(glob, name, passwd);
259 qos.setSessionTimeout(timeout);
260 con.connect(qos, this);
261 }
262 catch (Exception e) {
263 log.severe(e.toString());
264 assertTrue("Login failed" + e.toString(), false);
265 }
266
267 try {
268 for (int ii=0; ii<4; ii++) {
269 try { Thread.sleep(timeout/2); } catch (Exception e) { }
270 log.info("Check access #" + ii + " ...");
271 con.get("<key oid='__cmd:?freeMem'/>", null);
272 log.info("Check access #" + ii + " OK");
273 }
274 }
275 catch (Exception e) {
276 log.severe("No access: " + e.toString());
277 assertTrue("Session is expired", false);
278 }
279 }
280 finally { // clean up
281 try {
282 con.disconnect(null);
283 }
284 catch (Throwable e) {
285 assertTrue(e.toString(), false);
286 }
287 }
288 log.info("Success in testSessionTimeoutRespan()");
289 }
290
291
292 /**
293 */
294 public void testClearSession()
295 {
296 log.info("***testClearSession() ...");
297 int numLogin = 5;
298 int maxSessions = numLogin - 2;
299 I_XmlBlasterAccess[] con = new I_XmlBlasterAccess[5];
300 for (int ii=0; ii<numLogin; ii++) {
301 try {
302 log.info("Connecting number " + ii + " of " + numLogin + " max=" + maxSessions);
303 con[ii] = glob.getClone(null).getXmlBlasterAccess();
304 ConnectQos qos = new ConnectQos(con[ii].getGlobal(), name, passwd);
305 qos.setMaxSessions(maxSessions);
306 con[ii].connect(qos, this); // Login to xmlBlaster
307 }
308 catch (XmlBlasterException e) {
309 if (ii >= maxSessions) {
310 log.info("Success, connecting number " + ii + " of max=" + maxSessions + " was denied: " + e.toString());
311 log.info("We try to clear the old sessions now");
312 try {
313 ConnectQos qos = new ConnectQos(null, name, passwd);
314 qos.setMaxSessions(maxSessions);
315 qos.clearSessions(true);
316 con[ii].connect(qos, this);
317 log.info("Success, login is possible again");
318 con[ii].get("<key oid='__cmd:?freeMem'/>", null);
319 log.info("Success, get works");
320 }
321 catch (Exception e2) {
322 log.severe("Clear session failed: " + e2.toString());
323 e2.printStackTrace();
324 fail("Login failed" + e2.toString());
325 }
326 }
327 else {
328 log.severe(e.toString());
329 assertTrue("Connecting number " + ii + " of max=" + maxSessions + " should be possible", false);
330 }
331 }
332 }
333
334 // clean up
335 for (int ii=maxSessions; ii<numLogin; ii++) {
336 DisconnectQos disQos = null;
337 if (con[ii] != null) {
338 con[ii].disconnect(disQos);
339 }
340 }
341 log.info("***Success in testClearSession()");
342 }
343
344 /**
345 * This is the callback method invoked from xmlBlaster
346 * delivering us a new asynchronous message.
347 * @see org.xmlBlaster.client.I_Callback#update(String, UpdateKey, byte[], UpdateQos)
348 */
349 public String update(String cbSessionId, UpdateKey updateKey, byte[] content, UpdateQos updateQos)
350 {
351 log.info("Receiving update of a message " + updateKey.getOid());
352 numReceived++;
353 return "";
354 }
355
356
357 /**
358 * Little helper, waits until the wanted number of messages are arrived
359 * or returns when the given timeout occurs.
360 * <p />
361 * @param timeout in milliseconds
362 * @param numWait how many messages to wait
363 */
364 private void waitOnUpdate(final long timeout, final int numWait)
365 {
366 long pollingInterval = 50L; // check every 0.05 seconds
367 if (timeout < 50) pollingInterval = timeout / 10L;
368 long sum = 0L;
369 // check if too few are arriving
370 while (numReceived < numWait) {
371 try { Thread.sleep(pollingInterval); } catch( InterruptedException i) {}
372 sum += pollingInterval;
373 assertTrue("Timeout of " + timeout + " occurred without update", sum <= timeout);
374 }
375
376 // check if too many are arriving
377 try { Thread.sleep(timeout); } catch( InterruptedException i) {}
378 assertEquals("Wrong number of messages arrived", numWait, numReceived);
379
380 numReceived = 0;
381 }
382
383 /**
384 * Method is used by TestRunner to load these tests
385 */
386 public static Test suite()
387 {
388 TestSuite suite= new TestSuite();
389 String loginName = "Tim";
390 Global glob = new Global();
391 suite.addTest(new TestSession(glob, "testZeroSessions", loginName));
392 suite.addTest(new TestSession(glob, "testSessionOverflow", loginName));
393 suite.addTest(new TestSession(glob, "testSessionTimeout", loginName));
394 suite.addTest(new TestSession(glob, "testSessionRefresh", loginName));
395 suite.addTest(new TestSession(glob, "testSessionTimeoutRespan", loginName));
396 suite.addTest(new TestSession(glob, "testClearSession", loginName));
397 return suite;
398 }
399
400 /**
401 * Invoke:
402 * <pre>
403 * java org.xmlBlaster.test.authentication.TestSession
404 * java -Djava.compiler= junit.textui.TestRunner org.xmlBlaster.test.authentication.TestSession
405 * <pre>
406 */
407 public static void main(String args[])
408 {
409 TestSession testSub = new TestSession(new Global(args), "TestSession", "Tim");
410 testSub.setUp();
411 testSub.testZeroSessions();
412 testSub.testSessionOverflow();
413 testSub.testSessionTimeout();
414 testSub.testSessionRefresh();
415 testSub.testSessionTimeoutRespan();
416 testSub.testClearSession();
417 testSub.tearDown();
418 }
419 }
syntax highlighted by Code2HTML, v. 0.9.1