KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > nodes > ChildrenKeysIssue30907Test


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.nodes;
21
22 import java.lang.ref.*;
23 import java.util.*;
24 import org.openide.ErrorManager;
25 import junit.framework.*;
26 import org.netbeans.junit.*;
27
28 public class ChildrenKeysIssue30907Test extends NbTestCase {
29
30     public ChildrenKeysIssue30907Test(java.lang.String JavaDoc testName) {
31         super(testName);
32     }
33
34     protected void setUp () throws Exception JavaDoc {
35         System.setProperty("org.openide.util.Lookup", "org.openide.nodes.ChildrenKeysIssue30907Test$Lkp");
36         assertNotNull ("ErrManager has to be in lookup", org.openide.util.Lookup.getDefault ().lookup (ErrManager.class));
37         ErrManager.messages.delete (0, ErrManager.messages.length ());
38     }
39     
40
41     protected void runTest () throws Throwable JavaDoc {
42         try {
43             super.runTest();
44         } catch (Error JavaDoc err) {
45             AssertionFailedError newErr = new AssertionFailedError (err.getMessage () + "\n" + ErrManager.messages);
46             newErr.initCause (err);
47             throw newErr;
48         }
49         
50         waitRemoveNotified ();
51     }
52     
53     private Object JavaDoc FINAL_LOCK;
54     private boolean removeNotified;
55     protected void doRemoveNotify () {
56         synchronized (FINAL_LOCK) {
57             removeNotified = true;
58             notifyAll ();
59         }
60     }
61
62     private final void waitRemoveNotified () throws Exception JavaDoc {
63         if (FINAL_LOCK == null) {
64             return;
65         }
66         
67         int cnt = 0;
68         for (;;) {
69             synchronized (FINAL_LOCK) {
70                 if (removeNotified) {
71                     return;
72                 }
73                 FINAL_LOCK.wait (500);
74             }
75             if (cnt++ == 10) {
76                 fail ("waitRemoveNotified failed, too many waits: " + cnt);
77             }
78             System.gc ();
79             System.runFinalization();
80         }
81     }
82     
83     
84     public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907SlowAddNotifyWithReadAccess () throws Exception JavaDoc {
85         doBug30907 (true, true, 0, 2);
86     }
87     
88     public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907QuickAddNotifyWithReadAccess () throws Exception JavaDoc {
89         doBug30907 (false, true, 0, 2);
90     }
91     
92     public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907QuickAddNotify () throws Exception JavaDoc {
93         doBug30907 (false, false, 2, 2);
94     }
95     public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907SlowAddNotify () throws Exception JavaDoc {
96         doBug30907 (true, false, 2, 2);
97     }
98     
99     public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907AddNotifyWithException () throws Exception JavaDoc {
100         doBug30907 (true, true, false, 0, 0);
101     }
102     
103     public void testDeadlock50379 () throws Exception JavaDoc {
104         class K extends Children.Keys<Object JavaDoc> implements Runnable JavaDoc {
105             
106             public void run () {
107                 if (!MUTEX.isWriteAccess ()) {
108                     MUTEX.writeAccess (this);
109                     return;
110                 }
111                 
112                 synchronized (this) {
113                     notifyAll ();
114                 }
115                 
116                 try {
117                     Thread.sleep (100);
118                 } catch (InterruptedException JavaDoc ex) {
119                     fail ("No interrupts");
120                 }
121                 
122                 
123                 setKeys (java.util.Collections.singleton(this));
124             }
125             
126             @Override JavaDoc
127             protected synchronized void addNotify () {
128                 org.openide.util.RequestProcessor.getDefault().post (this);
129                 try {
130                     wait ();
131                 } catch (InterruptedException JavaDoc ex) {
132                     fail ("No interrupts");
133                 }
134             }
135             
136             protected Node[] createNodes (Object JavaDoc key) {
137                 return new Node[0];
138             }
139
140         }
141         
142         
143         K keys = new K ();
144         // deadlocks
145
keys.getNodes ();
146     }
147     
148     private void doBug30907 (final boolean slowAddNotify, boolean readAccess, int mainCount, int threadCount) throws Exception JavaDoc {
149         doBug30907 (slowAddNotify, false, readAccess, mainCount, threadCount);
150     }
151     
152     private void doBug30907 (final boolean slowAddNotify, final boolean throwException, boolean readAccess, int mainCount, int threadCount) throws Exception JavaDoc {
153         FINAL_LOCK = new Object JavaDoc ();
154         
155         ErrManager.messages.append ("doBug30907 slowAddNotify: " + slowAddNotify
156             + " throwException: " + throwException + " readAccess: " + readAccess + " mainCount: " + mainCount +
157             " threadCount: " + threadCount + '\n');
158         
159         //
160
// the purpose of this test is to create a livelock - execution never ends
161
// as described in the bug
162
//
163

164         
165         final Node node[] = { null };
166         
167         final Object JavaDoc LOCK = new Object JavaDoc ();
168         
169         class K extends Children.Keys implements Runnable JavaDoc {
170             private String JavaDoc[] arr;
171             
172             public K (String JavaDoc[] arr) {
173                 this.arr = arr;
174             }
175             
176             protected Node[] createNodes(Object JavaDoc key) {
177                 AbstractNode an = new AbstractNode (Children.LEAF);
178                 an.setName (key.toString ());
179                 ErrManager.messages.append (" creating node: " + key.toString () + " by thread: " + Thread.currentThread ().getName () + "\n");
180
181                 return new Node[] { an };
182             }
183             
184             public void addNotify () {
185                 if (slowAddNotify) {
186                     try {
187                         // let the main thread run
188
synchronized (LOCK) {
189                             ErrManager.messages.append (" blocking in addNotify: " + Thread.currentThread ().getName () + "\n");
190                             LOCK.notify (); // to N1
191
}
192
193                         // and wait a while it reaches getNodes
194
Thread.sleep (300);
195                         ErrManager.messages.append (" end of blocking in addNotify: " + Thread.currentThread ().getName () + "\n");
196                     } catch (InterruptedException JavaDoc ex) {
197                         fail ("Exception");
198                     }
199                 }
200                 
201                 ErrManager.messages.append (" set keys: " + java.util.Arrays.asList (arr) + " by " + Thread.currentThread ().getName () + "\n");
202                 setKeys (arr);
203                 ErrManager.messages.append (" end of keys by " + Thread.currentThread ().getName () + "\n");
204                 
205                 if (throwException) {
206                     ErrManager.messages.append (" throwing exception by " + Thread.currentThread ().getName () + "\n");
207                     throw new IllegalStateException JavaDoc( "testing exception" );
208                 }
209             }
210             
211             Node[] result;
212             public void run () {
213                 // forces initialization
214
Node[] arr = new Node[]{};
215                 try {
216                     ErrManager.messages.append ("Run: computing nodes\n");
217                     arr = node[0].getChildren ().getNodes ();
218                     ErrManager.messages.append ("Run: nodes computed" + Arrays.asList (arr) + "\n");
219                 }
220                 catch ( IllegalStateException JavaDoc e ) {
221                     // Our exception
222
ErrManager.messages.append ("Run: exception caught: " + e.getMessage () + "\n");
223                 }
224
225                 if (!slowAddNotify) {
226                     // qucik addNotify => notify the main thread to run after the
227
// finish of getNodes
228
synchronized (LOCK) {
229                         ErrManager.messages.append ("Run: Notifying others to run\n");
230                         LOCK.notify (); // to N1
231
}
232                 }
233                 
234                 synchronized (LOCK) {
235                     ErrManager.messages.append ("Run: Assigning result: " + Arrays.asList (arr) + "\n");
236                     result = arr;
237                     LOCK.notify (); // to N2
238
}
239             }
240             
241             protected void removeNotify () {
242                 super.removeNotify();
243                 doRemoveNotify ();
244             }
245         }
246
247         K k = new K (new String JavaDoc[] { "1", "2" });
248         node[0] = new FilterNode (new AbstractNode (k));
249         
250         Node[] result;
251         synchronized (LOCK) {
252             try {
253                 if (readAccess) {
254                     ErrManager.messages.append ("Main: Before read access\n");
255                     Children.PR.enterReadAccess ();
256                     ErrManager.messages.append ("Main: In read access\n");
257                 }
258
259                 Thread JavaDoc t = new Thread JavaDoc (k, "testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907Thread");
260                 t.setDaemon(true);
261                 ErrManager.messages.append ("Main: Starting the thread\n");
262                 t.start ();
263
264                 if (!readAccess) {
265                     ErrManager.messages.append ("Main: Wait for N1\n");
266                     LOCK.wait (); // from N1
267
ErrManager.messages.append ("Main: Waiting for N1 is over\n");
268                 }
269
270                 ErrManager.messages.append ("Main: Calling getNodes()\n");
271                 result = node[0].getChildren ().getNodes ();
272                 ErrManager.messages.append ("Main: getNodes() finished: " + Arrays.asList (result) + "\n");
273                 assertNotNull("Get nodes cannot return null", result);
274                 assertEquals ("Returns proper value for children as it waits until addNotify finishes", mainCount, result.length);
275             } finally {
276                 if (readAccess) {
277                     ErrManager.messages.append ("Main: before exitReadAccess\n");
278                     Children.PR.exitReadAccess ();
279                     ErrManager.messages.append ("Main: after exitReadAccess\n");
280                 }
281             }
282             
283             if (readAccess) {
284                 ErrManager.messages.append ("Main: wait for N1 two\n");
285                 LOCK.wait (); // from N1
286
ErrManager.messages.append ("Main: wait for N1 two finished\n");
287             }
288             
289             // finish the work in thread
290
while (k.result == null) {
291                 LOCK.wait (); // from N2
292
}
293         }
294         assertEquals ("Two children there even in the initialization thread", threadCount, k.result.length);
295     }
296     
297     public static final class Lkp extends org.openide.util.lookup.AbstractLookup {
298         public Lkp () {
299             this (new org.openide.util.lookup.InstanceContent ());
300         }
301         
302         private Lkp (org.openide.util.lookup.InstanceContent ic) {
303             super (ic);
304             ic.add (new ErrManager ());
305         }
306     }
307     
308     private static final class ErrManager extends org.openide.ErrorManager {
309         public static final StringBuffer JavaDoc messages = new StringBuffer JavaDoc ();
310         
311         public Throwable JavaDoc annotate (Throwable JavaDoc t, int severity, String JavaDoc message, String JavaDoc localizedMessage, Throwable JavaDoc stackTrace, java.util.Date JavaDoc date) {
312             return t;
313         }
314         
315         public Throwable JavaDoc attachAnnotations (Throwable JavaDoc t, org.openide.ErrorManager.Annotation[] arr) {
316             return t;
317         }
318         
319         public org.openide.ErrorManager.Annotation[] findAnnotations (Throwable JavaDoc t) {
320             return null;
321         }
322         
323         public org.openide.ErrorManager getInstance (String JavaDoc name) {
324             return this;
325         }
326         
327         public void log (int severity, String JavaDoc s) {
328             messages.append (s);
329             messages.append ('\n');
330         }
331         
332         public void notify (int severity, Throwable JavaDoc t) {
333             messages.append (t.getMessage ());
334         }
335         
336     }
337 }
338
Popular Tags