|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.nodes; import java.lang.ref.*; import java.util.*; import org.openide.ErrorManager; import junit.framework.*; import org.netbeans.junit.*; public class ChildrenKeysTest extends NbTestCase { public ChildrenKeysTest(java.lang.String testName) { super(testName); } public static void main(java.lang.String[] args) { junit.textui.TestRunner.run(new NbTestSuite (ChildrenKeysTest.class)); } protected void setUp () throws Exception { System.setProperty("org.openide.util.Lookup", "org.openide.nodes.ChildrenKeysTest$Lkp"); assertNotNull ("ErrManager has to be in lookup", org.openide.util.Lookup.getDefault ().lookup (ErrManager.class)); ErrManager.messages.delete (0, ErrManager.messages.length ()); } public void testRefreshKeyCanBeCalledFromReadAccess () throws Exception { final String[] keys = { "Hrebejk", "Tulach" }; final Keys k = new Keys (keys); Keys.MUTEX.readAccess (new Runnable () { public void run () { k.refreshKey ("Hrebejk"); } }); assertEquals ("No messages", "", ErrManager.messages.toString ()); } public void testGCKeys () throws Exception { class K extends Children.Keys { int counterAdd = 0; int counterRem = 0; Object key; K(Object keyObject) { key = keyObject; } protected void addNotify() { counterAdd++; setKeys(Collections.singleton(key)); } protected void removeNotify() { counterRem++; setKeys(Collections.EMPTY_LIST); key = null; } protected Node[] createNodes(Object k) { return new Node[] { Node.EMPTY.cloneNode() }; } } Object myKey = new Object(); K temp = new K(myKey); assertEquals("not touched", 0, temp.counterAdd); assertEquals("not touched", 0, temp.counterRem); Node[] arr = temp.getNodes(); assertEquals("initialized", 1, temp.counterAdd); assertEquals("not touched", 0, temp.counterRem); assertEquals("one item", 1, arr.length); WeakReference ref = new WeakReference(arr[0]); arr = null; assertGC("node freed", ref); assertEquals("initialized", 1, temp.counterAdd); assertEquals("removed", 1, temp.counterRem); ref = new WeakReference(myKey); myKey = null; assertGC("key freed", ref); } /** Check whether a nodes appears when keys are set. */ public void testGetNodes () throws Exception { String[] arr = { "1", "2", "3", "4" }; Children ch = new Keys (arr); checkNames (ch, arr); } /** Check refresh of nodes. */ public void testResetOfNodes () throws Exception { String[] arr; Keys ch = new Keys (); arr = new String[] { "1", "2" }; ch.keys (arr); checkNames (ch, arr); arr = new String[] { "X", "Y", "Z" }; ch.keys (arr); checkNames (ch, arr); Collections.reverse (Arrays.asList (arr)); ch.keys (arr); checkNames (ch, arr); } /** Tests whether nodes in children have the correct names on correct places * @param ch children * @param arr names */ private void checkNames (Children ch, String[] arr) { Node[] nodes = ch.getNodes (); if (nodes.length != arr.length) { fail ("Keys: " + arr.length + " Nodes: " + nodes.length); } for (int i = 0; i < arr.length; i++) { if (!nodes[i].getName ().equals (arr[i])) { fail (i + "th: name: " + nodes[i].getName () + " key: " + arr[i]); } } } public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907SlowAddNotifyWithReadAccess () throws Exception { doBug30907 (true, true, 0, 2); } public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907QuickAddNotifyWithReadAccess () throws Exception { doBug30907 (false, true, 0, 2); } public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907QuickAddNotify () throws Exception { doBug30907 (false, false, 2, 2); } public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907SlowAddNotify () throws Exception { doBug30907 (true, false, 2, 2); } public void testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907AddNotifyWithException () throws Exception { doBug30907 (true, true, false, 0, 0); } public void doBug30907 (final boolean slowAddNotify, boolean readAccess, int mainCount, int threadCount) throws Exception { doBug30907 (slowAddNotify, false, readAccess, mainCount, threadCount); } public void doBug30907 (final boolean slowAddNotify, final boolean throwException, boolean readAccess, int mainCount, int threadCount) throws Exception { // we have to garbage called all objects otherwise they won't let us into // read access for (int i = 0; i < 10; i++) { System.gc (); System.runFinalization(); } // // the purpose of this test is to create a livelock - execution never ends // as described in the bug // final Node node[] = { null }; final Object LOCK = new Object (); class K extends Keys implements Runnable { private String[] arr; public K (String[] arr) { this.arr = arr; } public void addNotify () { if (slowAddNotify) { // let the main thread run synchronized (LOCK) { LOCK.notify (); // to N1 } // and wait a while it reaches getNodes try { Thread.sleep (1000); } catch (InterruptedException ex) { fail ("Exception"); } } setKeys (arr); if (throwException) { throw new IllegalStateException( "testing exception" ); } } Node[] result; public void run () { // forces initialization Node[] arr = new Node[]{}; try { arr = node[0].getChildren ().getNodes (); } catch ( IllegalStateException e ) { // Our exception } if (!slowAddNotify) { // qucik addNotify => notify the main thread to run after the // finish of getNodes synchronized (LOCK) { LOCK.notify (); // to N1 } } synchronized (LOCK) { result = arr; LOCK.notify (); // to N2 } } } K k = new K (new String[] { "1", "2" }); node[0] = new FilterNode (new AbstractNode (k)); Node[] result; synchronized (LOCK) { try { if (readAccess) { Children.PR.enterReadAccess (); } Thread t = new Thread (k, "testProperInitializationEvenIfInvokedFromMultipleThreadsBug30907Thread"); t.setDaemon(true); t.start (); if (!readAccess) { LOCK.wait (); // from N1 } result = node[0].getChildren ().getNodes (); assertNotNull("Get nodes cannot return null", result); assertEquals ("Returns proper value for children as it waits until addNotify finishes", mainCount, result.length); } finally { if (readAccess) { Children.PR.exitReadAccess (); } } if (readAccess) { LOCK.wait (); // from N1 } // finish the work in thread while (k.result == null) { LOCK.wait (); // from N2 } } assertEquals ("Two children there even in the initialization thread", threadCount, k.result.length); } /** Sample keys. */ private static class Keys extends Children.Keys { public Keys () { } /** Constructor. */ public Keys (String[] args) { setKeys (args); } /** Changes the keys. */ public void keys (String[] args) { super.setKeys (args); } /** Changes the keys. */ public void keys (Collection args) { super.setKeys (args); } /** Create nodes for a given key. * @param key the key * @return child nodes for this key or null if there should be no * nodes for this key */ protected Node[] createNodes(Object key) { AbstractNode an = new AbstractNode (Children.LEAF); an.setName (key.toString ()); return new Node[] { an }; } } public static final class Lkp extends org.openide.util.lookup.AbstractLookup { public Lkp () { this (new org.openide.util.lookup.InstanceContent ()); } private Lkp (org.openide.util.lookup.InstanceContent ic) { super (ic); ic.add (new ErrManager ()); } } private static final class ErrManager extends org.openide.ErrorManager { public static final StringBuffer messages = new StringBuffer (); public Throwable annotate (Throwable t, int severity, String message, String localizedMessage, Throwable stackTrace, java.util.Date date) { return t; } public Throwable attachAnnotations (Throwable t, org.openide.ErrorManager.Annotation[] arr) { return t; } public org.openide.ErrorManager.Annotation[] findAnnotations (Throwable t) { return null; } public org.openide.ErrorManager getInstance (String name) { return this; } public void log (int severity, String s) { messages.append (s); messages.append ('\n'); } public void notify (int severity, Throwable t) { messages.append (t.getMessage ()); } } } |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.