0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.openide.util;
0043:
0044: import java.lang.ref.*;
0045: import java.util.*;
0046: import org.openide.ErrorManager;
0047: import junit.framework.*;
0048: import org.netbeans.junit.*;
0049: import org.openide.util.Task;
0050:
0051: public class RequestProcessorTest extends NbTestCase {
0052: static {
0053: System.setProperty("org.openide.util.Lookup",
0054: "org.openide.util.RequestProcessorTest$Lkp");
0055: }
0056:
0057: private ErrorManager log;
0058:
0059: public RequestProcessorTest(java.lang.String testName) {
0060: super (testName);
0061: }
0062:
0063: protected void setUp() throws Exception {
0064: super .setUp();
0065:
0066: log = ErrorManager.getDefault()
0067: .getInstance("TEST-" + getName());
0068: }
0069:
0070: protected void runTest() throws Throwable {
0071: assertNotNull("ErrManager has to be in lookup",
0072: org.openide.util.Lookup.getDefault().lookup(
0073: ErrManager.class));
0074: ErrManager.messages.setLength(0);
0075:
0076: try {
0077: super .runTest();
0078: } catch (Throwable ex) {
0079: throw new junit.framework.AssertionFailedError(ex
0080: .getMessage()
0081: + "\n" + ErrManager.messages.toString())
0082: .initCause(ex);
0083: }
0084: }
0085:
0086: /** A test to check that objects are executed in the right order.
0087: */
0088: public void testOrder() throws Exception {
0089: final int[] count = new int[1];
0090: final String[] fail = new String[1];
0091:
0092: class X extends Object implements Runnable, Comparable {
0093: public int order;
0094:
0095: public void run() {
0096: if (order != count[0]++) {
0097: if (fail[0] == null) {
0098: fail[0] = "Executing task " + order
0099: + " instead of " + count[0];
0100: }
0101: }
0102: }
0103:
0104: public int compareTo(Object o) {
0105: X x = (X) o;
0106:
0107: return System.identityHashCode(x)
0108: - System.identityHashCode(this );
0109: }
0110:
0111: public String toString() {
0112: return "O: " + order;
0113: }
0114: }
0115: ;
0116:
0117: // prepare the tasks
0118: X[] arr = new X[10];
0119: for (int i = 0; i < arr.length; i++) {
0120: arr[i] = new X();
0121: }
0122:
0123: // sort it
0124: // Arrays.sort (arr);
0125:
0126: for (int i = 0; i < arr.length; i++) {
0127: arr[i].order = i;
0128: }
0129:
0130: // execute the task as quickly as possible (only those with the same time
0131: // can have wrong order
0132: RequestProcessor.Task[] wait = new RequestProcessor.Task[arr.length];
0133: for (int i = 0; i < arr.length; i++) {
0134: wait[i] = RequestProcessor.postRequest(arr[i]);
0135: }
0136:
0137: // wait to all tasks to finish
0138: for (int i = 0; i < arr.length; i++) {
0139: wait[i].waitFinished();
0140: }
0141:
0142: if (fail[0] != null) {
0143: fail(fail[0]);
0144: }
0145:
0146: }
0147:
0148: public void testTaskLeakWhenCancelled() throws Exception {
0149: Runnable r = new Runnable() {
0150: public void run() {
0151: }
0152: };
0153:
0154: // schedule (1hour) and cancel immediatelly
0155: new RequestProcessor(getName()).post(r, 3600 * 1000).cancel();
0156:
0157: WeakReference<Runnable> wr = new WeakReference<Runnable>(r);
0158: r = null;
0159: assertGC("runnable should be collected", wr);
0160: }
0161:
0162: /* This might be issue as well, but taking into account the typical lifecycle
0163: of a RP and its size, I won't invest in fixing this now.
0164: *//*
0165: public void testRPLeakWhenLastTaskCancelled() throws Exception {
0166: Runnable r = new Runnable() {public void run() {}};
0167:
0168: // schedule (1hour) and cancel immediatelly
0169: RequestProcessor rp = new RequestProcessor(getName());
0170: rp.post(r, 3600*1000).cancel();
0171:
0172: WeakReference wr = new WeakReference(rp);
0173: rp = null;
0174: assertGC("runnable should be collected", wr);
0175: } /**/
0176:
0177: public void testScheduleAndIsFinished() throws InterruptedException {
0178: class Run implements Runnable {
0179: public boolean run;
0180: public boolean second;
0181:
0182: public synchronized void run() {
0183: if (run) {
0184: second = true;
0185: return;
0186: }
0187:
0188: try {
0189: notifyAll();
0190: wait();
0191: } catch (InterruptedException ex) {
0192: fail(ex.getMessage());
0193: }
0194: run = true;
0195: }
0196: }
0197:
0198: Run r = new Run();
0199: RequestProcessor.Task task;
0200: synchronized (r) {
0201: task = new RequestProcessor(getName()).post(r);
0202: r.wait();
0203: task.schedule(200);
0204: r.notifyAll();
0205: }
0206:
0207: Thread.sleep(100);
0208: assertTrue("Run successfully", r.run);
0209: assertFalse("Not for the second time1", r.second);
0210: assertFalse("Not finished as it is scheduled", task
0211: .isFinished());
0212: assertFalse("Not for the second time2", r.second);
0213:
0214: task.waitFinished();
0215: assertTrue("Finished now", task.isFinished());
0216: assertTrue("Run again", r.second);
0217:
0218: }
0219:
0220: /**
0221: * A test that check that priorities are handled well.
0222: */
0223: public void testPriorityQueue() throws Exception {
0224:
0225: final Runnable[] arr = new Runnable[5];
0226:
0227: class R implements Runnable {
0228:
0229: public int index;
0230:
0231: public R(int i) {
0232: index = i;
0233: }
0234:
0235: public synchronized void run() {
0236: for (int i = 0; /*i < arr.length*/; i++) {
0237: if (arr[i] == null) {
0238: arr[i] = this ;
0239: break;
0240: }
0241: }
0242:
0243: }
0244:
0245: public String toString() {
0246: return " R index " + index;
0247: }
0248: }
0249:
0250: Runnable r[] = new Runnable[5];
0251: // expected order of execution
0252: for (int i = 0; i < 5; i++) {
0253: r[i] = new R(i);
0254: }
0255:
0256: RequestProcessor rp = new RequestProcessor("PrioriyTest");
0257:
0258: RequestProcessor.Task t[] = new RequestProcessor.Task[5];
0259: synchronized (r[0]) {
0260: t[4] = rp.post(r[0], 0, 3);
0261: t[0] = rp.post(r[4], 0, 1);
0262: t[1] = rp.post(r[2], 0, 2);
0263: t[2] = rp.post(r[1], 0, 2);
0264: t[3] = rp.post(r[3], 0, 2);
0265: t[2].setPriority(3);
0266: }
0267:
0268: for (int i = 0; i < 5; i++) {
0269: t[i].waitFinished();
0270: }
0271:
0272: for (int i = 0; i < 5; i++) {
0273: R next = (R) arr[i];
0274: if (next.index != i)
0275: fail("Expected at " + i + " but was " + next.index);
0276: }
0277: }
0278:
0279: /** Test bug http://www.netbeans.org/issues/show_bug.cgi?id=31906
0280: */
0281: public void testBug31906_SimulateDataFolderTest() {
0282: RequestProcessor rp = new RequestProcessor("dataFolderTest");
0283:
0284: class X implements Runnable {
0285: private RequestProcessor.Task wait;
0286: private int cnt;
0287:
0288: public synchronized void run() {
0289: if (wait != null) {
0290: wait.waitFinished();
0291: cnt++;
0292: } else {
0293: cnt++;
0294: }
0295: }
0296:
0297: public synchronized void assertCnt(String msg, int cnt) {
0298: assertEquals(msg, cnt, this .cnt);
0299: this .cnt = 0;
0300: }
0301:
0302: public synchronized void waitFor(RequestProcessor.Task t) {
0303: wait = t;
0304: }
0305:
0306: }
0307: X[] arr = { new X(), new X() };
0308: RequestProcessor.Task[] tasks = { rp.create(arr[0]),
0309: rp.create(arr[1]) };
0310: tasks[0].setPriority(Thread.NORM_PRIORITY - 1);
0311: tasks[1].setPriority(Thread.NORM_PRIORITY + 1);
0312:
0313: tasks[0].schedule(0);
0314: tasks[1].schedule(0);
0315:
0316: tasks[0].waitFinished();
0317: arr[0].assertCnt(" Once", 1);
0318: tasks[1].waitFinished();
0319: arr[1].assertCnt(" Once as well", 1);
0320:
0321: tasks[0].schedule(100);
0322: tasks[1].schedule(100);
0323: tasks[0].schedule(10);
0324: tasks[1].schedule(10);
0325:
0326: tasks[0].waitFinished();
0327: tasks[1].waitFinished();
0328:
0329: arr[0].assertCnt(" 1a", 1);
0330: arr[1].assertCnt(" 1b", 1);
0331:
0332: arr[0].waitFor(tasks[1]);
0333: tasks[1].schedule(100);
0334: tasks[0].schedule(10);
0335: tasks[0].waitFinished();
0336: arr[0].assertCnt(" task 0 is executed", 1);
0337: arr[1].assertCnt(" but it also executes task 1", 1);
0338:
0339: tasks[0].schedule(10);
0340: tasks[0].waitFinished();
0341: arr[0].assertCnt(" task O is executed", 1);
0342: arr[1].assertCnt(" but it does not execute 1", 0);
0343: }
0344:
0345: /** Test priority inversion and whether it is properly notified
0346: */
0347: public void testPriorityInversionProblemAndItsDiagnosis()
0348: throws Exception {
0349: RequestProcessor rp = new RequestProcessor(
0350: "testPriorityInversionProblemAndItsDiagnosis");
0351:
0352: final Runnable[] arr = new Runnable[3];
0353:
0354: class R implements Runnable {
0355:
0356: public int index;
0357: public Task t;
0358:
0359: public R(int i) {
0360: index = i;
0361: }
0362:
0363: public synchronized void run() {
0364: for (int i = 0; /*i < arr.length*/; i++) {
0365: if (arr[i] == null) {
0366: arr[i] = this ;
0367: break;
0368: }
0369: }
0370:
0371: if (t != null) {
0372: t.waitFinished();
0373: }
0374: }
0375:
0376: public String toString() {
0377: return " R index " + index;
0378: }
0379: }
0380:
0381: R r1 = new R(1);
0382: R r2 = new R(2);
0383: R r3 = new R(3);
0384:
0385: Task t1;
0386: Task t2;
0387: Task t3;
0388:
0389: synchronized (r1) {
0390: t1 = rp.post(r1);
0391: t2 = rp.post(r2);
0392:
0393: // r1 will call the waitFinished of r3
0394: r1.t = t3 = rp.post(r3);
0395: }
0396:
0397: t1.waitFinished();
0398: t2.waitFinished();
0399: t3.waitFinished();
0400:
0401: assertEquals("First started is t1", r1, arr[0]);
0402: assertEquals("Second started is t3", r3, arr[1]);
0403: assertEquals("Last started is t2", r2, arr[2]);
0404:
0405: // now we should ensure that the RP warned everyone about the
0406: // priority inheritance and all its possible complications (t2 running
0407: // later than t3)
0408: }
0409:
0410: /** Test of finalize method, of class org.openide.util.RequestProcessor. */
0411: public void testFinalize() throws Exception {
0412: RequestProcessor rp = new RequestProcessor("toGarbageCollect");
0413: Reference<RequestProcessor> ref = new WeakReference<RequestProcessor>(
0414: rp);
0415: Reference<Task> task;
0416:
0417: final Object lock = new Object();
0418:
0419: synchronized (lock) {
0420: task = new WeakReference<Task>(rp.post(new Runnable() {
0421: public void run() {
0422: synchronized (lock) {
0423: lock.notify();
0424: }
0425: }
0426: }));
0427:
0428: rp = null;
0429:
0430: doGc(10, null);
0431:
0432: if (ref.get() == null) {
0433: fail("garbage collected even a task is planed."); // NOI18N
0434: }
0435:
0436: // run the task
0437: lock.wait();
0438:
0439: }
0440:
0441: doGc(1000, task);
0442:
0443: if (task.get() != null) {
0444: fail("task is not garbage collected.");
0445: }
0446:
0447: doGc(1000, ref);
0448: if (ref.get() != null) {
0449: fail("not garbage collected at all."); // NOI18N
0450: }
0451:
0452: }
0453:
0454: /** Check whether task is finished when it should be.
0455: */
0456: public void testCheckFinished() {
0457: doCheckFinished(false);
0458: }
0459:
0460: public void testCheckFinishedWithFalse() {
0461: doCheckFinished(true);
0462: }
0463:
0464: private void doCheckFinished(boolean usefalse) {
0465: RequestProcessor rp = new RequestProcessor("Finish");
0466:
0467: class R extends Object implements Runnable {
0468: RequestProcessor.Task t;
0469:
0470: public void run() {
0471: if (t.isFinished()) {
0472: fail("Finished when running");
0473: }
0474: }
0475: }
0476:
0477: R r = new R();
0478: RequestProcessor.Task task = usefalse ? rp.create(r, false)
0479: : rp.create(r);
0480: r.t = task;
0481:
0482: if (task.isFinished()) {
0483: fail("Finished after creation");
0484: }
0485:
0486: doCommonTestWithScheduling(task);
0487: }
0488:
0489: private void doCommonTestWithScheduling(
0490: final RequestProcessor.Task task) {
0491:
0492: task.schedule(200);
0493:
0494: if (task.isFinished()) {
0495: fail("Finished when planed");
0496: }
0497:
0498: task.waitFinished();
0499:
0500: if (!task.isFinished()) {
0501: fail("Not finished after waitFinished");
0502: }
0503:
0504: task.schedule(200);
0505:
0506: if (task.isFinished()) {
0507: fail("Finished when planed");
0508: }
0509: }
0510:
0511: public void testCheckFinishedWithTrue() {
0512: RequestProcessor rp = new RequestProcessor("Finish");
0513:
0514: class R extends Object implements Runnable {
0515: RequestProcessor.Task t;
0516:
0517: public void run() {
0518: if (t.isFinished()) {
0519: fail("Finished when running");
0520: }
0521: }
0522: }
0523:
0524: R r = new R();
0525: RequestProcessor.Task task = rp.create(r, true);
0526: r.t = task;
0527:
0528: assertTrue("It has to be finished after creation", task
0529: .isFinished());
0530:
0531: task.waitFinished();
0532:
0533: // rest is the same
0534: doCommonTestWithScheduling(task);
0535: }
0536:
0537: /** Test to check the waiting in request processor.
0538: */
0539: public void testWaitFinishedOnNotStartedTask() throws Exception {
0540: Counter x = new Counter();
0541: final RequestProcessor.Task task = RequestProcessor
0542: .getDefault().create(x);
0543:
0544: //
0545: // Following code tests whether the RP.create().waitFinished really blocks
0546: // until somebody schedules the task.
0547: //
0548: class WaitThread extends Thread {
0549: public boolean finished;
0550:
0551: public void run() {
0552: task.waitFinished();
0553: synchronized (this ) {
0554: finished = true;
0555: notifyAll();
0556: }
0557: }
0558:
0559: public synchronized void w(int timeOut) throws Exception {
0560: if (!finished) {
0561: wait(timeOut);
0562: }
0563: }
0564: }
0565: WaitThread wt = new WaitThread();
0566: wt.start();
0567: wt.w(100);
0568: assertTrue(
0569: "The waitFinished has not ended, because the task has not been planned",
0570: !wt.finished);
0571: task.schedule(0);
0572: wt.w(0);
0573: assertTrue(
0574: "The waitFinished finished, as the task is now planned",
0575: wt.finished);
0576: x.assertCnt("The task has been executed", 1);
0577: }
0578:
0579: /** Test to check the waiting in request processor.
0580: */
0581: public void testWaitFinishedOnNotStartedTaskFromRPThread()
0582: throws Exception {
0583: Counter x = new Counter();
0584: RequestProcessor rp = new RequestProcessor(
0585: "testWaitFinishedOnNotStartedTaskFromRPThread");
0586: final RequestProcessor.Task task = rp.create(x);
0587:
0588: //
0589: // Following code tests whether the RP.create().waitFinished really blocks
0590: // until somebody schedules the task.
0591: //
0592: class WaitTask implements Runnable {
0593: public boolean finished;
0594:
0595: public synchronized void run() {
0596: task.waitFinished();
0597: finished = true;
0598: notifyAll();
0599: }
0600:
0601: public synchronized void w(int timeOut) throws Exception {
0602: if (!finished) {
0603: wait(timeOut);
0604: }
0605: }
0606: }
0607: WaitTask wt = new WaitTask();
0608: rp.post(wt);
0609: wt.w(0);
0610: assertTrue(
0611: "The task.waitFinished has to finish, otherwise the RequestProcessor thread will stay occupied forever",
0612: wt.finished);
0613: x
0614: .assertCnt(
0615: "The task has been executed - wait from RP made it start",
0616: 1);
0617: }
0618:
0619: public void testWaitFinished2() {
0620: Counter x = new Counter();
0621: final RequestProcessor.Task task = RequestProcessor
0622: .getDefault().create(x);
0623: task.schedule(500);
0624: if (task.cancel()) {
0625: // ok, task is canceled
0626: task.waitFinished();
0627: }
0628:
0629: // does a task that is scheduled means that it is not finished?
0630: task.schedule(200);
0631: task.waitFinished();
0632: x
0633: .assertCnt(
0634: "Wait does not wait for finish of scheduled tasks, that already has been posted",
0635: 1);
0636: }
0637:
0638: /** Ensure that it is safe to call schedule() while the task is running
0639: * (should finish the task and run it again).
0640: */
0641: public void testScheduleWhileRunning() throws Exception {
0642: class X implements Runnable {
0643: public synchronized void run() {
0644: try {
0645: if (cnt == 0) {
0646: this .notify(); // #1
0647: this .wait(9999); // #2
0648: cnt++;
0649: } else {
0650: cnt++;
0651: this .notify(); // #3
0652: }
0653: } catch (InterruptedException ie) {
0654: ie.printStackTrace();
0655: }
0656: }
0657:
0658: public int cnt = 0;
0659: }
0660: X x = new X();
0661: synchronized (x) {
0662: RequestProcessor.Task task = RequestProcessor
0663: .postRequest(x);
0664: x.wait(9999); // #1
0665: assertEquals(0, x.cnt);
0666: task.schedule(0);
0667: x.notify(); // #2
0668: x.wait(9999); // #3
0669: assertEquals(2, x.cnt);
0670: }
0671: }
0672:
0673: /** Make sure it is safe to call waitFinished() on a task from within
0674: * a task listener.
0675: */
0676: public void testWaitFinishedFromNotification() throws Exception {
0677: class X implements Runnable {
0678: private Task task;
0679: private int cnt;
0680:
0681: public synchronized Task start() {
0682: if (task == null) {
0683: task = RequestProcessor.postRequest(this );
0684: }
0685: return task;
0686: }
0687:
0688: public void run() {
0689: cnt++;
0690: }
0691:
0692: public int getCount() {
0693: return cnt;
0694: }
0695:
0696: public void block() {
0697: start().waitFinished();
0698: }
0699: }
0700: final X x = new X();
0701: final Object lock = "wait for task to finish";
0702: final boolean[] finished = new boolean[1];
0703: x.start().addTaskListener(new TaskListener() {
0704: public void taskFinished(Task t) {
0705: x.block();
0706: finished[0] = true;
0707: synchronized (lock) {
0708: lock.notify();
0709: }
0710: }
0711: });
0712: synchronized (lock) {
0713: lock.wait(5000);
0714: }
0715: assertTrue(finished[0]);
0716: assertEquals(1, x.getCount());
0717: }
0718:
0719: /** Make sure that successfully canceled task is not performed.
0720: */
0721: public void testCancel() throws Exception {
0722: class X implements Runnable {
0723: public boolean performed = false;
0724:
0725: public void run() {
0726: performed = true;
0727: }
0728: }
0729:
0730: X x = new X();
0731: final boolean[] finished = new boolean[1];
0732: finished[0] = false;
0733:
0734: // post task with some delay
0735: RequestProcessor.Task task = RequestProcessor.postRequest(x,
0736: 1000);
0737: task.addTaskListener(new TaskListener() {
0738: public void taskFinished(Task t) {
0739: finished[0] = true;
0740: }
0741: });
0742:
0743: boolean canceled = task.cancel();
0744: assertTrue("Task was not canceled", canceled);
0745: assertTrue("The taskFinished was not called for canceled task",
0746: finished[0]);
0747: Thread.sleep(1500); // wait longer than task delay
0748: assertTrue("Task was performed even if it is canceled",
0749: !x.performed);
0750: }
0751:
0752: public void testWaitWithTimeOutCanFinishEvenTheTaskHasNotRun()
0753: throws Exception {
0754: class Run implements Runnable {
0755: public boolean runned;
0756:
0757: public synchronized void run() {
0758: runned = true;
0759: }
0760: }
0761:
0762: Run run = new Run();
0763:
0764: synchronized (run) {
0765: RequestProcessor.Task task = RequestProcessor.getDefault()
0766: .post(run);
0767: task.waitFinished(100);
0768: assertFalse("We are here and the task has not finished",
0769: run.runned);
0770: assertFalse("Not finished", task.isFinished());
0771: }
0772: }
0773:
0774: public void testWhenWaitingForALimitedTimeFromTheSameProcessorThenInterruptedExceptionIsThrownImmediatelly()
0775: throws Exception {
0776: Counter x = new Counter();
0777: RequestProcessor rp = new RequestProcessor(
0778: "testWaitFinishedOnNotStartedTaskFromRPThread");
0779: final RequestProcessor.Task task = rp.create(x);
0780:
0781: class WaitTask implements Runnable {
0782: public boolean finished;
0783:
0784: public synchronized void run() {
0785: long time = System.currentTimeMillis();
0786: try {
0787: task.waitFinished(1000);
0788: fail("This should throw an exception. Btw time was: "
0789: + (System.currentTimeMillis() - time));
0790: } catch (InterruptedException ex) {
0791: // ok, this is expected
0792: } finally {
0793: time = System.currentTimeMillis() - time;
0794: notifyAll();
0795: }
0796: if (time > 100) {
0797: fail("Exception should be thrown quickly. Was: "
0798: + time);
0799: }
0800: finished = true;
0801: }
0802:
0803: }
0804: WaitTask wt = new WaitTask();
0805: synchronized (wt) {
0806: rp.post(wt);
0807: wt.wait();
0808: }
0809: assertTrue("The task.waitFinished has to finish", wt.finished);
0810: x.assertCnt("The task has NOT been executed", 0);
0811: }
0812:
0813: public void testWhenWaitingForAlreadyFinishedTaskWithTimeOutTheResultIsGood()
0814: throws Exception {
0815: Counter x = new Counter();
0816: RequestProcessor rp = new RequestProcessor(
0817: "testWaitFinishedOnStartedTaskFromRPThread");
0818: final RequestProcessor.Task task = rp.post(x);
0819: task.waitFinished();
0820: x.assertCnt("The task has been executed before", 1);
0821:
0822: class WaitTask implements Runnable {
0823: public boolean finished;
0824:
0825: public synchronized void run() {
0826: notifyAll();
0827: try {
0828: assertTrue("The task has been already finished",
0829: task.waitFinished(1000));
0830: } catch (InterruptedException ex) {
0831: ex.printStackTrace();
0832: fail("Should not happen");
0833: }
0834: finished = true;
0835: }
0836:
0837: }
0838: WaitTask wt = new WaitTask();
0839: synchronized (wt) {
0840: rp.post(wt);
0841: wt.wait();
0842: }
0843: assertTrue("The task.waitFinished has to finish", wt.finished);
0844: }
0845:
0846: /**
0847: * A processing thread must survive throwable thrown during
0848: * execution of given taks. RuntimeException
0849: */
0850: public void testSurvivesException() throws Exception {
0851: doSurviveTest(false); // NPE
0852: doSurviveTest(true); // AssertionError
0853: }
0854:
0855: private void doSurviveTest(final boolean error) throws Exception {
0856: RequestProcessor rp = new RequestProcessor("SurvivesTest");
0857: Counter x = new Counter();
0858:
0859: final Locker lock = new Locker();
0860:
0861: rp.post(new Runnable() {
0862: public void run() {
0863: lock.waitOn();
0864:
0865: if (error) {
0866: throw new AssertionError();
0867: } else {
0868: throw new NullPointerException();
0869: }
0870: }
0871: });
0872:
0873: rp.post(x);
0874: lock.notifyOn();
0875:
0876: x.assertCntWaiting("Second task not performed after "
0877: + (error ? "error" : "exception"), 1);
0878: }
0879:
0880: public void testCancelInterruptsTheRunningThread() throws Exception {
0881: RequestProcessor rp = new RequestProcessor("Cancellable", 1,
0882: true);
0883:
0884: class R implements Runnable {
0885: private String name;
0886:
0887: public boolean checkBefore;
0888: public boolean checkAfter;
0889: public boolean interrupted;
0890:
0891: public R(String n) {
0892: this .name = n;
0893: }
0894:
0895: public synchronized void run() {
0896: checkBefore = Thread.interrupted();
0897:
0898: log.log("in runnable " + name + " check before: "
0899: + checkBefore);
0900:
0901: notifyAll();
0902:
0903: log.log("in runnable " + name + " after notify");
0904:
0905: try {
0906: wait();
0907: log.log("in runnable " + name
0908: + " after wait, not interrupted");
0909: interrupted = false;
0910: } catch (InterruptedException ex) {
0911: interrupted = true;
0912: log.log("in runnable " + name
0913: + " after wait, interrupted");
0914: }
0915:
0916: notifyAll();
0917:
0918: log.log("in runnable " + name + " after notifyAll");
0919:
0920: try {
0921: wait();
0922: log.log("in runnable " + name
0923: + " after second wait, not interrupted");
0924: checkAfter = Thread.interrupted();
0925: } catch (InterruptedException ex) {
0926: log.log("in runnable " + name
0927: + " after second wait, interrupted");
0928: checkAfter = true;
0929: }
0930:
0931: log.log("in runnable " + name + " checkAfter: "
0932: + checkAfter);
0933:
0934: notifyAll();
0935: }
0936: }
0937:
0938: R r = new R("First");
0939: RequestProcessor.Task t;
0940: synchronized (r) {
0941: t = rp.post(r);
0942: r.wait();
0943: assertTrue("The task is already running", !t.cancel());
0944: log.log("Main checkpoint1");
0945: r.wait();
0946: log.log("Main checkpoint2");
0947: r.notifyAll();
0948: log.log("Main checkpoint3");
0949: r.wait();
0950: log.log("Main checkpoint4");
0951: assertTrue("The task has been interrupted", r.interrupted);
0952: assertTrue("Not before", !r.checkBefore);
0953: assertTrue(
0954: "Not after - as the notification was thru InterruptedException",
0955: !r.checkAfter);
0956: }
0957: log.log("Main checkpoint5");
0958: t.waitFinished();
0959: log.log("Main checkpoint6");
0960: /*
0961: try {
0962: assertGC("no", new java.lang.ref.WeakReference(this));
0963: } catch (Error e) {
0964: // ok
0965: }
0966: */
0967:
0968: // interrupt after the task has finished
0969: r = new R("Second");
0970: synchronized (r) {
0971: t = rp.post(r);
0972: log.log("Second checkpoint1");
0973: r.wait();
0974: r.notifyAll();
0975: log.log("Second checkpoint2");
0976: r.wait();
0977: log.log("Second checkpoint3");
0978: assertTrue("The task is already running", !t.cancel());
0979: log.log("Second checkpoint4");
0980: r.notifyAll();
0981: log.log("Second checkpoint5");
0982: r.wait();
0983: assertTrue(
0984: "The task has not been interrupted by exception",
0985: !r.interrupted);
0986: assertTrue("Not interupted before", !r.checkBefore);
0987: assertTrue("But interupted after", r.checkAfter);
0988: }
0989: log.log("Second checkpoint6");
0990: t.waitFinished();
0991: log.log("Second checkpoint7");
0992: }
0993:
0994: public void testCancelDoesNotInterruptTheRunningThread()
0995: throws Exception {
0996: RequestProcessor rp = new RequestProcessor("Not Cancellable",
0997: 1, false);
0998:
0999: class R implements Runnable {
1000: public boolean checkBefore;
1001: public boolean checkAfter;
1002: public boolean interrupted;
1003:
1004: public synchronized void run() {
1005: checkBefore = Thread.interrupted();
1006:
1007: notifyAll();
1008:
1009: try {
1010: wait();
1011: interrupted = false;
1012: } catch (InterruptedException ex) {
1013: interrupted = true;
1014: }
1015:
1016: notifyAll();
1017:
1018: try {
1019: wait();
1020: } catch (InterruptedException ex) {
1021: }
1022:
1023: checkAfter = Thread.interrupted();
1024:
1025: notifyAll();
1026: }
1027: }
1028:
1029: R r = new R();
1030: synchronized (r) {
1031: RequestProcessor.Task t = rp.post(r);
1032: r.wait();
1033: assertTrue("The task is already running", !t.cancel());
1034: r.notifyAll();
1035: r.wait();
1036: r.notifyAll();
1037: r.wait();
1038: assertFalse("The task has not been interrupted",
1039: r.interrupted);
1040: assertTrue("Not before", !r.checkBefore);
1041: assertTrue(
1042: "Not after - as the notification was thru InterruptedException",
1043: !r.checkAfter);
1044: }
1045:
1046: // interrupt after the task has finished
1047: r = new R();
1048: synchronized (r) {
1049: RequestProcessor.Task t = rp.post(r);
1050: r.wait();
1051: r.notifyAll();
1052: r.wait();
1053: assertTrue("The task is already running", !t.cancel());
1054: r.notifyAll();
1055: r.wait();
1056: assertTrue(
1057: "The task has not been interrupted by exception",
1058: !r.interrupted);
1059: assertFalse("Not interupted before", r.checkBefore);
1060: assertFalse("Not interupted after", r.checkAfter);
1061: }
1062: }
1063:
1064: public void testInterruptedStatusIsClearedBetweenTwoTaskExecution()
1065: throws Exception {
1066: RequestProcessor rp = new RequestProcessor(
1067: "testInterruptedStatusIsClearedBetweenTwoTaskExecution",
1068: 1, true);
1069:
1070: final RequestProcessor.Task[] task = new RequestProcessor.Task[1];
1071: // test interrupted status is cleared after task ends
1072: class Fail implements Runnable {
1073: public boolean checkBefore;
1074: public Thread runIn;
1075: public boolean goodThread;
1076:
1077: public synchronized void run() {
1078: if (runIn == null) {
1079: runIn = Thread.currentThread();
1080: task[0].schedule(0);
1081:
1082: // wait to make sure the task is scheduled
1083: try {
1084: Thread.sleep(100);
1085: } catch (InterruptedException ex) {
1086: ex.printStackTrace();
1087: }
1088: } else {
1089: goodThread = Thread.currentThread() == runIn;
1090: }
1091:
1092: checkBefore = runIn.isInterrupted();
1093: // set the flag for next execution
1094: runIn.interrupt();
1095:
1096: notifyAll();
1097: }
1098: }
1099:
1100: Fail f = new Fail();
1101: synchronized (f) {
1102: task[0] = rp.post(f);
1103:
1104: // wait for the first execution
1105: f.wait();
1106: }
1107: // wait for the second
1108: task[0].waitFinished();
1109:
1110: /* Shall be true, but sometimes the threads get GCed, so we cannot really check that.
1111: assertTrue ("This shall be always true, but if not, than it does not mean too much"
1112: + " just that the tasks were not executed in the same thread. In such case it "
1113: + " this test does not do anything useful as it needs to execute the task twice "
1114: + " in the same thread", f.goodThread);
1115: */
1116:
1117: if (f.goodThread) {
1118: assertTrue(
1119: "Interrupted state has been cleared between two executions of the task",
1120: !f.checkBefore);
1121: }
1122: }
1123:
1124: public void testInterruptedStatusWorksInInversedTasks()
1125: throws Exception {
1126: RequestProcessor rp = new RequestProcessor(
1127: "testInterruptedStatusWorksInInversedTasks", 1, true);
1128:
1129: class Fail implements Runnable {
1130: public Fail(String n) {
1131: name = n;
1132: }
1133:
1134: private String name;
1135: public RequestProcessor.Task wait;
1136: public Object lock;
1137: public Exception ex;
1138:
1139: public boolean checkBefore;
1140: public boolean checkAfter;
1141:
1142: public void run() {
1143: synchronized (this ) {
1144: checkBefore = Thread.interrupted();
1145: log("checkBefore: " + checkBefore);
1146: notifyAll();
1147: }
1148: if (lock != null) {
1149: synchronized (lock) {
1150: lock.notify();
1151: try {
1152: lock.wait();
1153: } catch (InterruptedException ex) {
1154: this .ex = ex;
1155: ex.printStackTrace();
1156: fail("No InterruptedException");
1157: }
1158: log.log("wait for lock over");
1159: }
1160: }
1161:
1162: if (wait != null) {
1163: wait.schedule(100);
1164: wait.waitFinished();
1165: }
1166:
1167: synchronized (this ) {
1168: checkAfter = Thread.interrupted();
1169: log.log("checkAfter: " + checkAfter);
1170: notifyAll();
1171: }
1172: }
1173:
1174: public String toString() {
1175: return name;
1176: }
1177: }
1178:
1179: Object initLock = new Object();
1180:
1181: Fail smaller = new Fail("smaller");
1182: smaller.lock = initLock;
1183: Fail bigger = new Fail("BIGGER");
1184: RequestProcessor.Task smallerTask, biggerTask;
1185:
1186: smallerTask = rp.create(smaller);
1187: biggerTask = rp.create(bigger);
1188:
1189: bigger.wait = smallerTask;
1190:
1191: synchronized (initLock) {
1192: log.log("schedule 0");
1193: biggerTask.schedule(0);
1194: initLock.wait();
1195: initLock.notifyAll();
1196: log.log("doing cancel");
1197: assertFalse("Already running", biggerTask.cancel());
1198: log.log("biggerTask cancelled");
1199: }
1200:
1201: biggerTask.waitFinished();
1202: log.log("waitFinished over");
1203:
1204: assertFalse("bigger not interrupted at begining",
1205: bigger.checkBefore);
1206: assertFalse("smaller not interrupted at all",
1207: smaller.checkBefore);
1208: assertFalse("smaller not interrupted at all2",
1209: smaller.checkAfter);
1210: assertTrue("bigger interrupted at end", bigger.checkAfter);
1211:
1212: }
1213:
1214: public void testInterruptedStatusWorksInInversedTasksWhenInterruptedSoon()
1215: throws Exception {
1216: RequestProcessor rp = new RequestProcessor(
1217: "testInterruptedStatusWorksInInversedTasksWhenInterruptedSoon",
1218: 1, true);
1219:
1220: class Fail implements Runnable {
1221: public Fail(String n) {
1222: name = n;
1223: }
1224:
1225: private String name;
1226: public RequestProcessor.Task wait;
1227: public Object lock;
1228:
1229: public boolean checkBefore;
1230: public boolean checkAfter;
1231:
1232: public volatile boolean alreadyCanceled;
1233:
1234: public void run() {
1235: synchronized (this ) {
1236: checkBefore = Thread.interrupted();
1237: log.log(name + " checkBefore: " + checkBefore);
1238: notifyAll();
1239: }
1240: if (lock != null) {
1241: synchronized (lock) {
1242: lock.notify();
1243: }
1244: }
1245:
1246: if (wait != null) {
1247: // we cannot call Thread.sleep, so lets slow things own
1248: // in other way
1249:
1250: log(name + " do waitFinished");
1251: wait.waitFinished();
1252: log(name + " waitFinished in task is over");
1253:
1254: log.log(name + " slowing by using System.gc");
1255: while (!alreadyCanceled) {
1256: System.gc();
1257: }
1258: log.log(name + " ended slowing");
1259:
1260: }
1261:
1262: synchronized (this ) {
1263: checkAfter = Thread.interrupted();
1264: log.log(name + " checkAfter: " + checkAfter);
1265: notifyAll();
1266: }
1267: }
1268: }
1269:
1270: Object initLock = new Object();
1271:
1272: Fail smaller = new Fail("smaller");
1273: Fail bigger = new Fail("bigger");
1274: RequestProcessor.Task smallerTask, biggerTask;
1275:
1276: smallerTask = rp.create(smaller);
1277: biggerTask = rp.create(bigger);
1278:
1279: bigger.lock = initLock;
1280: bigger.wait = smallerTask;
1281:
1282: synchronized (initLock) {
1283: log.log("Do schedule");
1284: biggerTask.schedule(0);
1285: initLock.wait();
1286: log.log("do cancel");
1287: assertFalse("Already running", biggerTask.cancel());
1288: bigger.alreadyCanceled = true;
1289: log.log("cancel done");
1290: }
1291:
1292: biggerTask.waitFinished();
1293: log.log("waitFinished is over");
1294:
1295: assertFalse("bigger not interrupted at begining",
1296: bigger.checkBefore);
1297: assertFalse("smaller not interrupted at all",
1298: smaller.checkBefore);
1299: assertFalse("smaller not interrupted at all2",
1300: smaller.checkAfter);
1301: assertTrue("bigger interrupted at end", bigger.checkAfter);
1302: }
1303:
1304: public void testTaskFinishedOnCancelFiredAfterTaskHasReallyFinished()
1305: throws Exception {
1306: RequestProcessor rp = new RequestProcessor("Cancellable", 1,
1307: true);
1308:
1309: class X implements Runnable {
1310:
1311: volatile boolean reallyFinished = false;
1312:
1313: public synchronized void run() {
1314: notifyAll();
1315:
1316: try {
1317: wait();
1318: } catch (InterruptedException e) {
1319: // interrupted by Task.cancel()
1320: }
1321:
1322: notifyAll();
1323:
1324: try {
1325: wait();
1326: } catch (InterruptedException e) {
1327: }
1328:
1329: reallyFinished = true;
1330: }
1331: }
1332:
1333: final X x = new X();
1334: synchronized (x) {
1335: RequestProcessor.Task t = rp.post(x);
1336: t.addTaskListener(new TaskListener() {
1337: public void taskFinished(Task t) {
1338: assertTrue(x.reallyFinished);
1339: }
1340: });
1341: x.wait();
1342: t.cancel();
1343: x.wait();
1344: x.notifyAll();
1345: }
1346: }
1347:
1348: private static void doGc(int count, Reference toClear) {
1349: java.util.ArrayList<byte[]> l = new java.util.ArrayList<byte[]>(
1350: count);
1351: while (count-- > 0) {
1352: if (toClear != null && toClear.get() == null)
1353: break;
1354:
1355: l.add(new byte[1000]);
1356: System.gc();
1357: System.runFinalization();
1358: try {
1359: Thread.sleep(10);
1360: } catch (InterruptedException e) {
1361: }
1362: }
1363: }
1364:
1365: private static class Counter extends Object implements Runnable {
1366: private int count = 0;
1367:
1368: public synchronized void run() {
1369: count++;
1370: }
1371:
1372: public synchronized void assertCnt(String msg, int cnt) {
1373: assertEquals(msg, cnt, this .count);
1374: this .count = 0;
1375: }
1376:
1377: public synchronized void assertCntWaiting(String msg, int cnt) {
1378: // have to wait actively to recognize starvation :-(
1379: for (int i = 1; i < 10; i++) {
1380: try {
1381: wait(20 * i * i);
1382: } catch (InterruptedException e) {
1383: }
1384: if (count == cnt) { // passed
1385: count = 0;
1386: return;
1387: }
1388: }
1389: assertEquals(msg, cnt, count); // let it fail
1390: }
1391: }
1392:
1393: private static class Locker {
1394: boolean ready = false;
1395:
1396: public synchronized void waitOn() {
1397: while (ready == false) {
1398: try {
1399: wait();
1400: } catch (InterruptedException e) {
1401: }
1402: }
1403: }
1404:
1405: public synchronized void notifyOn() {
1406: ready = true;
1407: notifyAll();
1408: }
1409: }
1410:
1411: //
1412: // Our fake lookup
1413: //
1414: public static final class Lkp extends
1415: org.openide.util.lookup.AbstractLookup {
1416: private ErrManager err = new ErrManager();
1417: private org.openide.util.lookup.InstanceContent ic;
1418:
1419: public Lkp() {
1420: this (new org.openide.util.lookup.InstanceContent());
1421: }
1422:
1423: private Lkp(org.openide.util.lookup.InstanceContent ic) {
1424: super (ic);
1425: ic.add(err);
1426: this .ic = ic;
1427: }
1428:
1429: public static void turn(boolean on) {
1430: Lkp lkp = (Lkp) org.openide.util.Lookup.getDefault();
1431: if (on) {
1432: lkp.ic.add(lkp.err);
1433: } else {
1434: lkp.ic.remove(lkp.err);
1435: }
1436: }
1437: }
1438:
1439: //
1440: // Manager to delegate to
1441: //
1442: public static final class ErrManager extends
1443: org.openide.ErrorManager {
1444: public static final StringBuffer messages = new StringBuffer();
1445:
1446: private String prefix;
1447:
1448: public ErrManager() {
1449: this (null);
1450: }
1451:
1452: public ErrManager(String prefix) {
1453: this .prefix = prefix;
1454: }
1455:
1456: public static ErrManager get() {
1457: return (ErrManager) org.openide.util.Lookup.getDefault()
1458: .lookup(ErrManager.class);
1459: }
1460:
1461: public Throwable annotate(Throwable t, int severity,
1462: String message, String localizedMessage,
1463: Throwable stackTrace, java.util.Date date) {
1464: return t;
1465: }
1466:
1467: public Throwable attachAnnotations(Throwable t,
1468: org.openide.ErrorManager.Annotation[] arr) {
1469: return t;
1470: }
1471:
1472: public org.openide.ErrorManager.Annotation[] findAnnotations(
1473: Throwable t) {
1474: return null;
1475: }
1476:
1477: public org.openide.ErrorManager getInstance(String name) {
1478: if (name.startsWith("org.openide.util.RequestProcessor")
1479: || name.startsWith("TEST")) {
1480: return new ErrManager('[' + name + ']');
1481: } else {
1482: // either new non-logging or myself if I am non-logging
1483: return new ErrManager();
1484: }
1485: }
1486:
1487: public void log(int severity, String s) {
1488: lastSeverity = severity;
1489: lastText = s;
1490: if (this != get()) {
1491: messages.append(prefix);
1492: messages.append(s);
1493: messages.append('\n');
1494: }
1495: }
1496:
1497: public void notify(int severity, Throwable t) {
1498: lastThrowable = t;
1499: lastSeverity = severity;
1500: }
1501:
1502: private static int lastSeverity;
1503: private static Throwable lastThrowable;
1504: private static String lastText;
1505:
1506: public static void assertNotify(int sev, Throwable t) {
1507: assertEquals("Severity is same", sev, lastSeverity);
1508: assertSame("Throwable is the same", t, lastThrowable);
1509: lastThrowable = null;
1510: lastSeverity = -1;
1511: }
1512:
1513: public static void assertLog(int sev, String t) {
1514: assertEquals("Severity is same", sev, lastSeverity);
1515: assertEquals("Text is the same", t, lastText);
1516: lastText = null;
1517: lastSeverity = -1;
1518: }
1519:
1520: }
1521:
1522: }
|