001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.content;
028:
029: import com.sun.midp.i3test.TestCase;
030:
031: import javax.microedition.content.Invocation;
032:
033: import java.util.Vector;
034:
035: /**
036: * Test that InvocationImpl instances with a wide range of values
037: * can be stored in the InvocationStore and retrieved.
038: * <p>
039: * The tested functions of Invocation are:
040: * <UL>
041: * <LI>The settable fields of Invocation can be retrieved and verified.</LI>
042: * </UL>
043: */
044: public class TestInvocStore extends ExtendedTestCase {
045:
046: /** The application. */
047: AppProxy appl;
048:
049: /** Number of application ids to test in stress test. */
050: static final int NUM_APPLICATION_IDS = 3;
051: /** Number of content handlers per application to stress test. */
052: static final int NUM_CONTENT_HANDLERS = 2;
053: /** A Long string to test against. */
054: static final String LONG_STRING = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
055: + "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
056: + "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
057: + "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD";
058:
059: /** A suite Id to test against. */
060: static final int SUITE_ID = 65535;
061: /** First test string; empty. */
062: static final String STRING1 = "";
063: /** Second test string; short. */
064: static final String STRING2 = "1";
065: /** Third test string; longer. */
066: static final String STRING3 = "12";
067: /** Fourth test string; equal length. */
068: static final String STRING4 = "1*";
069: /** Fifth test string; shorter (forced to be different from string2.) */
070: static final String STRING5 = new String("1");
071: /** Sixth test string; shorter (forced to be different from string1.) */
072: static final String STRING6 = new String("");
073:
074: /** First args array; empty. */
075: static final String[] ARGS1 = new String[0];
076: /** First args array; 1 string. */
077: static final String[] ARGS2 = new String[1];
078: /** First args array; longer, 2 strings. */
079: static final String[] ARGS3 = new String[2];
080: /** First args array; different two. */
081: static final String[] ARGS4 = new String[2];
082: /** First args array; shorter, 1 string. */
083: static final String[] ARGS5 = new String[1];
084: /** First args array; empty again. */
085: static final String[] ARGS6 = new String[0];
086:
087: /** Maximum number of ARGUMENTS supported. */
088: static final int MAX_ARGUMENTS = 10;
089: /** Long argument list to test with. */
090: static String[] LONG_ARGUMENTS;
091:
092: static {
093: LONG_ARGUMENTS = new String[MAX_ARGUMENTS];
094: for (int i = 0; i < MAX_ARGUMENTS; i++) {
095: LONG_ARGUMENTS[i] = LONG_STRING;
096: }
097: }
098:
099: /**
100: * Run the tests.
101: */
102: public void runTests() {
103: try {
104: appl = AppProxy.getCurrent().forClass(classname);
105: } catch (ClassNotFoundException cnfe) {
106: fail("Unexpected exception");
107: cnfe.printStackTrace();
108: }
109:
110: test001();
111: test002();
112: test003();
113: // test004(); // OutOfMemory is unpredictable
114: test005();
115: test006();
116: test007();
117: test008();
118: test009();
119: test010();
120: }
121:
122: /**
123: * Create a new Invocation test case.
124: */
125: public TestInvocStore() {
126:
127: }
128:
129: /**
130: * Verify that each field of an {@link com.sun.midp.content.InvocationImpl}
131: * can be set,
132: * put into the store and retrieved and verified.
133: * The only test is if the field is saved and restored
134: * correctly for values of <code>null</code> and <code>non-null</code>.
135: */
136: void test001() {
137: declare("InvocationStore put/get");
138: String[] args = { null, "", "arg1", "arg2" };
139: byte[] data = new byte[47];
140:
141: InvocationImpl get;
142: InvocationImpl put;
143:
144: for (int i = 0; i < data.length; i++) {
145: data[i] = (byte) i;
146: }
147:
148: // Test with most fields empty
149: put = new InvocationImpl();
150: put.suiteId = appl.getStorageId();
151: put.classname = classname;
152: put.responseRequired = false;
153: InvocationStore.put(put);
154: assertTrue("Verify tid assigned", put.tid != 0);
155:
156: get = InvocationStore.getRequest(appl.getStorageId(),
157: classname, false);
158: assertEquals("Verify active status", Invocation.ACTIVE, get
159: .getStatus());
160: assertEquals("Verify get request equals put request", put, get);
161:
162: // Finalize the status to have the Invocation discarded
163: put.status = Invocation.OK;
164: InvocationStore.setStatus(put);
165:
166: // Try one with non-null fields
167: put = new InvocationImpl();
168: put.suiteId = appl.getStorageId();
169: put.classname = classname;
170: put.setID("ID");
171: put.setType("type");
172: put.setURL("URL");
173: put.setAction("ACTION");
174: put.setArgs(args);
175: put.setData(data);
176: put.setResponseRequired(true);
177: put.setCredentials("USERNAME", "PASSWORD".toCharArray());
178:
179: put.status = Invocation.OK;
180: put.suiteId = appl.getStorageId();
181: put.classname = classname;
182: put.tid = 0x80808080;
183: put.previousTid = 999;
184: put.invokingSuiteId = 60000;
185: put.invokingClassname = "invokingClassname";
186: put.invokingAuthority = "invokingAuthority";
187: put.invokingID = "invokingID";
188: put.invokingAppName = "invokingAppName";
189: put.argsLen = 0x52525252;
190: InvocationStore.put(put);
191: assertTrue("Verify tid assigned", get.tid != 0);
192:
193: get = InvocationStore.getResponse(new InvocationImpl(), appl
194: .getStorageId(), appl.getClassname(), false);
195: assertEquals("Non-empty", put, get);
196: assertEquals("Verify OK status", Invocation.OK, get.getStatus());
197:
198: get = InvocationStore.getResponse(new InvocationImpl(), appl
199: .getStorageId(), appl.getClassname(), false);
200: assertNull("Verify nothing lingering", get);
201:
202: }
203:
204: /**
205: * Verify that each field of an
206: * {@link com.sun.midp.content.InvocationImpl} can be set,
207: * put into the store and retrieved and verified.
208: * The only test is if the field is saved and restored
209: * correctly for values of <code>null</code> and <code>non-null</code>.
210: */
211: void test002() {
212: declare("Test mark and cleanup");
213:
214: /**
215: * Generate and post a request for each status value.
216: * Mark all of those and generate another bunch after the mark.
217: */
218: InvocationImpl[] invoc = genEachStatus();
219: InvocationStore.setCleanup(appl.getStorageId(), appl
220: .getClassname(), true);
221: // InvocationImpl[] invoc2 = genEachStatus();
222:
223: // Cycle on cleanup and Verify which ones should be returned
224: InvocationImpl get;
225: for (int i = Invocation.INIT; i <= Invocation.ACTIVE; i++) {
226:
227: /*
228: * Should get back an INIT, ACTIVE; those need an ERROR Response
229: * OK, CANCELLED, INITIATED, ERROR, WAITING should have
230: * been discarded.
231: */
232: get = InvocationStore.getCleanup(appl.getStorageId(), appl
233: .getClassname());
234: assertEquals("Verify cleanup needed", invoc[i], get);
235: if (get != null) {
236: assertEquals("Verify status", invoc[i].status,
237: get.status);
238: invoc[i].status = Invocation.ERROR;
239: InvocationStore.setStatus(invoc[i]);
240:
241: }
242: }
243:
244: // Verify that no others are returned
245: get = InvocationStore.getCleanup(appl.getStorageId(), appl
246: .getClassname());
247: assertNull("Verify no more cleanup needed", get);
248:
249: // Now the only invocations in the queue should be the responses
250: for (int i = Invocation.INIT; i <= Invocation.ACTIVE; i++) {
251:
252: // Retrieve the response and Verify
253: get = InvocationStore.getResponse(new InvocationImpl(),
254: appl.getStorageId(), appl.getClassname(), false);
255: assertEquals("Verify error response delivered", invoc[i],
256: get);
257: if (get != null) {
258: assertEquals("Verify error response status",
259: Invocation.ERROR, get.getStatus());
260: }
261: }
262:
263: /*
264: * What should remain is a HOLD invocation
265: * that needs to be changed before they can be removed.
266: */
267: for (int i = Invocation.HOLD; i <= Invocation.HOLD; i++) {
268: invoc[i].status = Invocation.OK;
269: InvocationStore.setStatus(invoc[i]);
270: get = InvocationStore.getResponse(new InvocationImpl(),
271: appl.getStorageId(), appl.getClassname(), false);
272: assertEquals("Verify received response", invoc[i], get);
273: if (get != null) {
274: assertEquals("Verify response status", invoc[i].status,
275: get.status);
276: }
277: }
278:
279: assertEmpty();
280: }
281:
282: /**
283: * Test that for a large number of inserts the order
284: * is maintained when multiple entries have the same ID, classname.
285: * A dataset is generated with only the TID differing.
286: * The verification fetches them and verifies the order.
287: */
288: void test003() {
289: declare("Maintaining order");
290: int NUM = 50;
291: Vector v = new Vector(NUM);
292: InvocationImpl put;
293: for (int i = 0; i < NUM; i++) {
294: put = new InvocationImpl();
295: put.suiteId = appl.getStorageId();
296: put.classname = classname;
297: put.status = Invocation.OK; // Use ok so they are removed later
298: v.addElement(put);
299: InvocationStore.put(put);
300: }
301: InvocationImpl get;
302: for (int i = 0; i < NUM; i++) {
303: get = InvocationStore.getResponse(new InvocationImpl(),
304: appl.getStorageId(), appl.getClassname(), false);
305: put = (InvocationImpl) v.elementAt(i);
306: assertEquals("Non-empty", put, get);
307: }
308: }
309:
310: /**
311: * Test exhausting the native heap storage with Invocations.
312: * Max size invocations are created, saved and put in the Invocation
313: * store until put throws OutOfMemoryError.
314: * All of the Invocations are read back and compared.
315: */
316: void test004() {
317: declare("Force out of memory and recovery");
318: int maxInvocations = 10000;
319: InvocationImpl get = null;
320: InvocationImpl put = null;
321: InvocationImpl last = null;
322: Vector v = new Vector(maxInvocations);
323: byte[] space = new byte[64000]; /* Space to free on out of memory */
324:
325: try {
326: for (int i = 0; i < maxInvocations; i++) {
327: try {
328: put = newMaxInvocation();
329: put.status = Invocation.OK;
330: v.addElement(put);
331: } catch (OutOfMemoryError mex) {
332: System.out.println("exhausted Java heap " + i
333: + " iterations");
334: // Free some heap so the test can continue
335: space = null;
336: break;
337: }
338: try {
339: InvocationStore.put(put);
340: } catch (OutOfMemoryError ex) {
341: // exhausted native heap
342: System.out.println("exhausted native heap " + i
343: + " iterations");
344: // Remove the final element that was not put and save
345: v.removeElement(put);
346: last = put;
347: break;
348: }
349: }
350: try {
351: // Verify that all the stored Invocations are correct
352: for (int i = 0; i < v.size(); i++) {
353: get = InvocationStore.getResponse(
354: new InvocationImpl(), appl.getStorageId(),
355: appl.getClassname(), false);
356: put = (InvocationImpl) v.elementAt(i);
357: assertEquals(
358: "Check invocations before OutOfMemory",
359: put, get);
360: if (get == null) {
361: break;
362: }
363: }
364: } catch (OutOfMemoryError mex) {
365: System.out.println("exhausted Java heap on get ");
366: System.out.println("available memory = "
367: + Runtime.getRuntime().freeMemory());
368: }
369:
370: try {
371: System.out.println("v.size(): " + v.size());
372: System.out.println("get.tid: "
373: + ((get != null) ? get.tid : -1));
374: if (last != null) {
375: // Now store and Verify the failed Invocation
376: put = last;
377: InvocationStore.put(put);
378: get = InvocationStore.getResponse(
379: new InvocationImpl(), appl.getStorageId(),
380: appl.getClassname(), false);
381: assertEquals(
382: "Check store/Verify after OutOfMemory",
383: put, get);
384: }
385: } catch (OutOfMemoryError mex) {
386: System.out.println("exhausted Java heap on 2nd get ");
387: System.out.println("available memory = "
388: + Runtime.getRuntime().freeMemory());
389: }
390:
391: assertEmpty();
392:
393: } catch (Throwable t) {
394: space = null;
395: t.printStackTrace();
396: }
397: }
398:
399: /**
400: * Test that the selection based on request/response values works.
401: * Both the {@link com.sun.midp.content.InvocationStore#get} and
402: * {@link com.sun.midp.content.InvocationStore#listen}
403: * are tested at the same time.
404: * Every status is put into the queue and then the response
405: * status values are retrieved and verified. Then the active
406: * status value is verified.
407: *
408: * Each test expects the results to come back in a particular
409: * order and verifies it.
410: */
411: void test005() {
412: declare("Selection based on status");
413: InvocationImpl get;
414: InvocationImpl put;
415: boolean pending;
416:
417: assertEmpty();
418:
419: /**
420: * Listen and Get work by status
421: */
422: InvocationImpl[] invoc = genEachStatus();
423:
424: // Verify that the responses can be found
425: for (int i = Invocation.OK; i <= Invocation.INITIATED; i++) {
426: pending = InvocationStore.listen(appl.getStorageId(), appl
427: .getClassname(), false, false);
428: assertTrue("1. listen for pending response", pending);
429:
430: get = InvocationStore.getResponse(new InvocationImpl(),
431: appl.getStorageId(), appl.getClassname(), false);
432: assertEquals("2. fetch a response", invoc[i], get);
433: }
434:
435: // Try again to Verify nothing there
436: get = InvocationStore.getResponse(new InvocationImpl(), appl
437: .getStorageId(), appl.getClassname(), false);
438: assertNull("3. Verify no pending response ", get);
439:
440: // Verify that the one ACTIVE request can be found
441: pending = InvocationStore.listen(appl.getStorageId(), appl
442: .getClassname(), true, false);
443: assertTrue("4. listen for pending request", pending);
444:
445: put = InvocationStore.getRequest(appl.getStorageId(), appl
446: .getClassname(), false);
447: assertEquals("5. fetch a request", invoc[Invocation.INIT], put);
448: if (put != null) {
449: assertEquals("Verify state is ACTIVE", Invocation.ACTIVE,
450: put.getStatus());
451: assertTrue("Verify responseRequired is true", put
452: .getResponseRequired());
453: }
454:
455: // Try again to Verify nothing there
456: get = InvocationStore.getRequest(appl.getStorageId(), appl
457: .getClassname(), false);
458: assertNull("6. Verify no extra response", get);
459:
460: // Set its status to OK and discard it
461: put.status = Invocation.OK;
462: InvocationStore.setStatus(put);
463:
464: // ResponseRequired is true so expect a response
465: get = InvocationStore.getResponse(new InvocationImpl(), appl
466: .getStorageId(), appl.getClassname(), false);
467: assertEquals("7. fetch a response", put, get);
468:
469: // Verify nothing there
470: get = InvocationStore.getResponse(new InvocationImpl(), appl
471: .getStorageId(), appl.getClassname(), false);
472: assertNull("8. Verify no extra response", get);
473:
474: // Change status of ACTIVE, WAITING, HOLD to OK to discard
475: for (int i = Invocation.ACTIVE; i <= Invocation.HOLD; i++) {
476: put = invoc[i];
477: put.status = Invocation.OK;
478: InvocationStore.setStatus(put);
479: }
480:
481: // Verify nothing there
482: get = InvocationStore.getRequest(appl.getStorageId(), appl
483: .getClassname(), false);
484: assertNull("11. extra Invocation", get);
485: }
486:
487: /**
488: * Test that get requests can be interrupted with the cancel method.
489: * Check that cancel doesn't corrupt the queue or loose requests.
490: * drain(); cancel(); get(); cancel(); put(); get(); cancel();
491: */
492: void test006() {
493: declare("Cancelling of get and listen");
494:
495: InvocStoreCancel tracker = new InvocStoreCancel(true, appl);
496:
497: // Start the get processing
498: tracker.reset();
499:
500: // Do a cancel without nothing pending
501: InvocationStore.cancel();
502:
503: assertEquals("Check the initial condition", 0, tracker.check());
504:
505: Thread thread = new Thread(tracker);
506: thread.start();
507:
508: sleep(500);
509:
510: // Do a cancel and see if a get was cancelled
511: InvocationStore.cancel();
512:
513: sleep(500);
514:
515: assertEquals("Check the get was cancelled", 1,
516: tracker.numNotPending);
517:
518: // Stop the tracking thread and wait for the thread to terminate
519: tracker.stop();
520: InvocationStore.cancel(); // Unblock
521: assertEquals("Check the get was unblocked", 1,
522: tracker.numNotPending);
523:
524: sleep(500);
525:
526: try {
527: thread.join();
528: } catch (InterruptedException ie) {
529: assertNull("Verify InterruptedException on join", ie);
530: }
531: }
532:
533: /**
534: * Test that get by <code>tid</code> works.
535: * An instance of each status is created and then they are
536: * fetched by tid.
537: */
538: void test007() {
539: declare("Get by TID");
540: InvocationImpl get;
541: InvocationImpl put;
542:
543: assertEmpty();
544:
545: /*
546: * Create one of each status and Verify that they can be
547: * found by {@link com.sun.midp.content.InvocationStore#getByTid}.
548: * GetByTid does not remove or modify the Invocations.
549: */
550: InvocationImpl[] invoc = genEachStatus();
551: for (int i = Invocation.OK; i <= Invocation.INITIATED; i++) {
552: get = InvocationStore.getByTid(invoc[i].tid, 0);
553: assertEquals("Verify getByTid matches put", invoc[i], get);
554: }
555:
556: // Verify 1 active request pending
557: put = invoc[Invocation.INIT];
558: get = InvocationStore.getRequest(appl.getStorageId(), appl
559: .getClassname(), false);
560: assertEquals("Verify a pending request after getByTid", put,
561: get);
562: if (get != null) {
563: put.status = Invocation.OK;
564: InvocationStore.setStatus(put);
565: get = InvocationStore.getResponse(new InvocationImpl(),
566: appl.getStorageId(), appl.getClassname(), false);
567: assertEquals("Verify response matches request", put, get);
568: }
569: // Verify no active request pending
570: get = InvocationStore.getRequest(appl.getStorageId(), appl
571: .getClassname(), false);
572: assertNull("Verify no pending request after getByTid", get);
573:
574: // Change status of INIT, ACTIVE, WAITING, HOLD to OK to discard
575: for (int i = Invocation.ACTIVE; i <= Invocation.INITIATED; i++) {
576: put = invoc[i];
577: put.status = Invocation.OK;
578: InvocationStore.setStatus(put);
579:
580: // Get and discard the response generated by setStatus
581: get = InvocationStore.getResponse(new InvocationImpl(),
582: appl.getStorageId(), appl.getClassname(), false);
583: assertEquals("Verify response matches put", put, get);
584: }
585:
586: assertEmpty();
587: }
588:
589: /**
590: * Test that setParams can correctly set and reset all
591: * parameters and not result in and not result in any leaks.
592: * <br>
593: * An invocation is put into the store and then a series of
594: * setParams calls are used to modify the parameters.
595: * After each modification the request is retrieved and
596: * compared with the expected modified request.
597: */
598: void test008() {
599: declare("setParams integrity");
600:
601: // Create an invocation a put it in the native store
602: InvocationImpl invoc = new InvocationImpl();
603: invoc.suiteId = appl.getStorageId();
604: invoc.classname = classname;
605: invoc.status = Invocation.ACTIVE;
606: invoc.responseRequired = false;
607: InvocationStore.put(invoc);
608:
609: String[] args = null;
610: do {
611: /*
612: * For each argument case.
613: */
614: String string = null;
615: do {
616: /*
617: * For each string value; check the type, url, ID, and action.
618: * Call setParams to put the values to native and then getByTid
619: * to get back a copy of the request and compare them.
620: */
621: fillInvocation(invoc, string, args);
622: InvocationStore.setParams(invoc);
623:
624: InvocationImpl req = InvocationStore.getByTid(
625: invoc.tid, 0);
626: assertNotNull("Verify the request was returned", req);
627: if (req != null) {
628: assertEquals("Verify parameter values", invoc, req);
629: }
630:
631: // Generate the next set of string values
632: string = nextString(string);
633: } while (string != null);
634: args = nextArgs(args);
635: } while (args != null);
636:
637: // Discard the pending request
638: invoc.status = Invocation.OK;
639: InvocationStore.setStatus(invoc);
640: assertEmpty();
641: }
642:
643: /**
644: * Fill in the invocation with the next data case.
645: * The same data is used in every field in the Invocation.
646: * The args are initialized with the string as appropriate.
647: * The data is filled from the string if non-null.
648: *
649: * @param invoc Invocation
650: * @param string to fill into Invocation fields and args and data
651: * @param args a prototype args array to fill
652: */
653: void fillInvocation(InvocationImpl invoc, String string,
654: String[] args) {
655: invoc.setID(string);
656: invoc.setURL(string);
657: invoc.setType(string);
658: invoc.setAction(string);
659: invoc.setArgs(args);
660: if (args != null) {
661: for (int i = 0; i < args.length; i++) {
662: args[i] = string;
663: }
664: }
665: invoc.setData((string == null) ? null : string.getBytes());
666: }
667:
668: /**
669: * Sequence through the test strings; can start anywhere
670: * but typically start/end with null.
671: * @param string the current string in the sequence
672: * @return the nextt string in the sequence
673: */
674: String nextString(String string) {
675: if (string == null) {
676: return STRING1;
677: } else if (string == STRING1) {
678: return STRING2;
679: } else if (string == STRING2) {
680: return STRING3;
681: } else if (string == STRING3) {
682: return STRING4;
683: } else if (string == STRING4) {
684: return STRING5;
685: } else if (string == STRING5) {
686: return STRING6;
687: } else {
688: // Start over
689: return null;
690: }
691: }
692:
693: /**
694: * Generate the next array to test.
695: * The sequence is null, 0, 1, 2, 2, 1, 0; back to null.
696: * @param args an String array; may be null.
697: * @return the next args array; not filled with anything in particular
698: */
699: String[] nextArgs(String[] args) {
700: if (args == null) {
701: return ARGS1;
702: } else if (args == ARGS1) {
703: return ARGS2;
704: } else if (args == ARGS2) {
705: return ARGS3;
706: } else if (args == ARGS3) {
707: return ARGS4;
708: } else if (args == ARGS4) {
709: return ARGS5;
710: } else if (args == ARGS5) {
711: return ARGS6;
712: } else {
713: return null;
714: }
715: }
716:
717: /**
718: * Test that getByTid handles next, equals, and previous correctly.
719: */
720: void test009() {
721: declare("getByTid testing next, previous, same");
722: assertEmpty();
723:
724: // Test that when empty there is no next, previous, equal.
725: InvocationImpl invoc = null;
726: invoc = InvocationStore.getByTid(0, -1);
727: assertNull("Verify no previous on empty queue", invoc);
728: invoc = InvocationStore.getByTid(0, 0);
729: assertNull("Verify no zeroth on empty queue", invoc);
730: invoc = InvocationStore.getByTid(0, +1);
731: assertNull("Verify no next on empty queue", invoc);
732:
733: // Insert a single Invocation
734: InvocationImpl invoc1 = new InvocationImpl();
735: invoc1.suiteId = appl.getStorageId();
736: invoc1.classname = classname;
737: invoc1.status = Invocation.ACTIVE;
738: invoc1.responseRequired = false;
739: InvocationStore.put(invoc1);
740:
741: invoc = InvocationStore.getByTid(invoc1.tid, -1);
742: assertNull("Verify no previous on single entry", invoc);
743: invoc = InvocationStore.getByTid(invoc1.tid, 0);
744: assertEquals("Verify equal on single entry", invoc1.tid,
745: invoc.tid);
746: invoc = InvocationStore.getByTid(invoc1.tid, +1);
747: assertNull("Verify no next in single entry", invoc);
748:
749: // Insert a second Invocation
750: InvocationImpl invoc2 = new InvocationImpl();
751: invoc2.suiteId = appl.getStorageId();
752: invoc2.classname = classname;
753: invoc2.status = Invocation.ACTIVE;
754: invoc2.responseRequired = false;
755: InvocationStore.put(invoc2);
756:
757: invoc = InvocationStore.getByTid(invoc2.tid, -1);
758: assertEquals("Verify previous on double entry", invoc1.tid,
759: invoc.tid);
760: invoc = InvocationStore.getByTid(invoc2.tid, 0);
761: assertEquals("Verify equal on double entry", invoc2.tid,
762: invoc.tid);
763: invoc = InvocationStore.getByTid(invoc2.tid, +1);
764: assertNull("Verify no next in double entry", invoc);
765:
766: // Discard the pending request(s)
767: invoc1.status = Invocation.OK;
768: InvocationStore.setStatus(invoc1);
769: invoc2.status = Invocation.OK;
770: InvocationStore.setStatus(invoc2);
771:
772: assertEmpty();
773: }
774:
775: /**
776: * Stress test using multiple threads to pound on the queue.
777: * Each thread performs a series of gets and puts with
778: * pseudo random choices of target id, classname, and status
779: */
780: void test010() {
781: declare("Multithread Stress Test");
782: InvocStoreStress[][] stress = new InvocStoreStress[NUM_APPLICATION_IDS][NUM_CONTENT_HANDLERS];
783: for (int i = 0; i < NUM_APPLICATION_IDS; i++) {
784: for (int j = 0; j < NUM_CONTENT_HANDLERS; j++) {
785: InvocStoreStress s = new InvocStoreStress(i, j,
786: NUM_APPLICATION_IDS, NUM_CONTENT_HANDLERS,
787: this , appl);
788: stress[i][j] = s;
789: new Thread(s).start();
790: }
791: }
792:
793: // Join all the threads to make sure they are done
794: for (int i = 0; i < NUM_APPLICATION_IDS; i++) {
795: for (int j = 0; j < NUM_CONTENT_HANDLERS; j++) {
796: InvocStoreStress s = stress[i][j];
797: try {
798: while (s.thread == null) {
799: sleep(1000L);
800: }
801: s.thread.join();
802: } catch (InterruptedException ii) {
803: ii.printStackTrace();
804: }
805: }
806: }
807: }
808:
809: /**
810: * Setup and put an Invocation with each status value
811: * from Invocation.INIT (1) to Invocation.INITIATED (8).
812: * @return Vector of posted InvocationImpls
813: */
814: InvocationImpl[] genEachStatus() {
815: InvocationImpl[] invoc = new InvocationImpl[Invocation.INITIATED + 1];
816: for (int i = Invocation.INIT; i <= Invocation.INITIATED; i++) {
817: InvocationImpl put = new InvocationImpl();
818: put.suiteId = appl.getStorageId();
819: put.classname = classname;
820: put.invokingSuiteId = appl.getStorageId();
821: put.invokingClassname = classname;
822: put.status = i;
823: invoc[i] = put;
824: InvocationStore.put(put);
825: }
826: return invoc;
827: }
828:
829: /**
830: * Check that there are no Invocations pending;
831: * none should be.
832: */
833: void assertEmpty() {
834: InvocationImpl get;
835: do {
836: get = InvocationStore.getRequest(appl.getStorageId(), appl
837: .getClassname(), false);
838: assertNull("Verify request queue is empty", get);
839: } while (get != null);
840:
841: do {
842: get = InvocationStore.getResponse(new InvocationImpl(),
843: appl.getStorageId(), appl.getClassname(), false);
844: assertNull("Verify response queue is empty", get);
845: } while (get != null);
846:
847: assertEquals("Verify invocation queue is empty", 0,
848: InvocationStore.size());
849: }
850:
851: /**
852: * Make a new maximum size Invocation.
853: * @return a new InvocationImpl
854: */
855: InvocationImpl newMaxInvocation() {
856: InvocationImpl put = new InvocationImpl();
857: put.setID(LONG_STRING);
858: put.setType(LONG_STRING);
859: put.setURL(LONG_STRING);
860: put.setAction(LONG_STRING);
861: put.setArgs(LONG_ARGUMENTS);
862: put.setResponseRequired(true);
863: put.suiteId = appl.getStorageId();
864: put.classname = classname;
865: put.invokingSuiteId = SUITE_ID;
866: put.invokingClassname = LONG_STRING;
867: put.invokingAuthority = LONG_STRING;
868: put.invokingID = LONG_STRING;
869: return put;
870: }
871:
872: }
|