openide.util/test/unit/src/org/openide/util/WeakSetTest.java
author Jesse Glick <jglick@netbeans.org>
Fri, 19 Dec 2008 10:24:30 -0500
changeset 490 9ca5b3d4a70a
parent 361 b8bf023cf23e
child 829 3b2ed3e1f01b
permissions -rw-r--r--
Random failure, and some warnings.
jtulach@9
     1
/*
jtulach@302
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jtulach@189
     3
 *
jtulach@302
     4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
jtulach@189
     5
 *
jtulach@302
     6
 * The contents of this file are subject to the terms of either the GNU
jtulach@302
     7
 * General Public License Version 2 only ("GPL") or the Common
jtulach@302
     8
 * Development and Distribution License("CDDL") (collectively, the
jtulach@302
     9
 * "License"). You may not use this file except in compliance with the
jtulach@302
    10
 * License. You can obtain a copy of the License at
jtulach@302
    11
 * http://www.netbeans.org/cddl-gplv2.html
jtulach@302
    12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jtulach@302
    13
 * specific language governing permissions and limitations under the
jtulach@302
    14
 * License.  When distributing the software, include this License Header
jtulach@302
    15
 * Notice in each file and include the License file at
jtulach@302
    16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jtulach@302
    17
 * particular file as subject to the "Classpath" exception as provided
jtulach@302
    18
 * by Sun in the GPL Version 2 section of the License file that
jtulach@302
    19
 * accompanied this code. If applicable, add the following below the
jtulach@302
    20
 * License Header, with the fields enclosed by brackets [] replaced by
jtulach@302
    21
 * your own identifying information:
jtulach@189
    22
 * "Portions Copyrighted [year] [name of copyright owner]"
jtulach@189
    23
 *
jtulach@302
    24
 * Contributor(s):
jtulach@302
    25
 *
jtulach@189
    26
 * The Original Software is NetBeans. The Initial Developer of the Original
jtulach@189
    27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
jtulach@9
    28
 * Microsystems, Inc. All Rights Reserved.
jtulach@302
    29
 *
jtulach@302
    30
 * If you wish your version of this file to be governed by only the CDDL
jtulach@302
    31
 * or only the GPL Version 2, indicate your decision by adding
jtulach@302
    32
 * "[Contributor] elects to include this software in this distribution
jtulach@302
    33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jtulach@302
    34
 * single choice of license, a recipient has the option to distribute
jtulach@302
    35
 * your version of this file under either the CDDL, the GPL Version 2 or
jtulach@302
    36
 * to extend the choice of license to its licensees as provided above.
jtulach@302
    37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jtulach@302
    38
 * Version 2 license, then the option applies only if the new code is
jtulach@302
    39
 * made subject to such option by the copyright holder.
jtulach@9
    40
 */
jtulach@9
    41
jtulach@9
    42
package org.openide.util;
jtulach@9
    43
jglick@490
    44
import java.lang.ref.Reference;
jtulach@9
    45
import java.lang.ref.WeakReference;
t_h@351
    46
import java.util.ArrayList;
jtulach@9
    47
import java.util.Iterator;
t_h@351
    48
import java.util.List;
t_h@351
    49
import java.util.Set;
t_h@351
    50
import java.util.concurrent.ExecutorService;
t_h@351
    51
import java.util.concurrent.Executors;
jglick@490
    52
import org.netbeans.junit.NbTestCase;
jglick@490
    53
import org.netbeans.junit.RandomlyFails;
jtulach@9
    54
jtulach@9
    55
public class WeakSetTest extends NbTestCase {
jtulach@189
    56
jglick@490
    57
    public WeakSetTest(String testName) {
jtulach@9
    58
        super(testName);
jtulach@9
    59
    }
jtulach@189
    60
jtulach@9
    61
    public void testToArrayMayContainNullsIssue42271 () {
jtulach@9
    62
        class R implements Runnable {
jtulach@9
    63
            Object[] arr;
jtulach@9
    64
            Object last;
jtulach@9
    65
            
jtulach@9
    66
            public R () {
jtulach@9
    67
                int cnt = 10;
jtulach@9
    68
                arr = new Object[cnt];
jtulach@9
    69
                for (int i = 0; i < cnt; i++) {
jglick@490
    70
                    arr[i] = new Integer(i); // autoboxing makes test fail!
jtulach@9
    71
                }
jtulach@9
    72
            }
jtulach@9
    73
            
jtulach@9
    74
            
jtulach@9
    75
            public void run () {
jtulach@9
    76
                
jglick@490
    77
                Reference<?> r = new WeakReference<Object>(last);
jtulach@9
    78
                for (int i = 0; i < arr.length; i++) {
jtulach@9
    79
                    arr[i] = null;
jtulach@9
    80
                }
jtulach@9
    81
                arr = null;
jtulach@9
    82
                last = null;
jtulach@9
    83
                assertGC ("Last item has to disappear", r);
jtulach@9
    84
            }
jtulach@9
    85
            
jtulach@9
    86
            public void putToSet (NotifyWhenIteratedSet s) {
jtulach@9
    87
                for (int i = 0; i < arr.length; i++) {
jtulach@9
    88
                    s.add (arr[i]);
jtulach@9
    89
                }
jtulach@9
    90
                assertEquals (arr.length, s.size ());
jglick@490
    91
                Iterator<Object> it = s.superIterator();
jtulach@9
    92
                Object prev = it.next ();
jtulach@9
    93
                while (it.hasNext ()) {
jtulach@9
    94
                    prev = it.next ();
jtulach@9
    95
                }
jtulach@9
    96
                last = prev;
jtulach@9
    97
            }
jtulach@9
    98
        }
jtulach@9
    99
        R r = new R ();
jtulach@9
   100
        
jtulach@9
   101
        
jtulach@9
   102
        
jtulach@9
   103
        NotifyWhenIteratedSet ws = new NotifyWhenIteratedSet (r, 1);
jtulach@9
   104
        
jtulach@9
   105
        r.putToSet (ws);
jtulach@9
   106
        
jtulach@9
   107
        Object[] arr = ws.toArray ();
jtulach@9
   108
        for (int i = 0; i < arr.length; i++) {
jtulach@9
   109
            assertNotNull (i + "th index should not be null", arr[i]);
jtulach@9
   110
        }
jtulach@9
   111
    }
jtulach@9
   112
    
jglick@490
   113
    private static final class NotifyWhenIteratedSet extends WeakSet<Object> {
jtulach@9
   114
        private Runnable run;
jtulach@9
   115
        private int cnt;
jtulach@9
   116
        
jtulach@9
   117
        public NotifyWhenIteratedSet (Runnable run, int cnt) {
jtulach@9
   118
            this.run = run;
jtulach@9
   119
            this.cnt = cnt;
jtulach@9
   120
        }
jtulach@9
   121
        
jglick@490
   122
        public Iterator<Object> superIterator() {
jtulach@9
   123
            return super.iterator ();
jtulach@9
   124
        }
jtulach@9
   125
        
jglick@490
   126
        @Override
jglick@490
   127
        public Iterator<Object> iterator() {
jglick@490
   128
            final Iterator<Object> it = super.iterator();
jglick@490
   129
            class I implements Iterator<Object> {
jtulach@9
   130
                public boolean hasNext() {
jtulach@9
   131
                    return it.hasNext ();
jtulach@9
   132
                }
jtulach@9
   133
jtulach@9
   134
                public Object next() {
jtulach@9
   135
                    if (--cnt == 0) {
jtulach@9
   136
                        run.run ();
jtulach@9
   137
                    }
jtulach@9
   138
                    return it.next ();
jtulach@9
   139
                }
jtulach@9
   140
jtulach@9
   141
                public void remove() {
jtulach@9
   142
                    it.remove();
jtulach@9
   143
                }
jtulach@9
   144
            }
jtulach@9
   145
            return new I ();
jtulach@9
   146
        }
jtulach@9
   147
    }
t_h@351
   148
    
t_h@351
   149
    private final static class TestObj {
t_h@351
   150
        static final Set<TestObj> testObjs = new WeakSet<TestObj>();
t_h@351
   151
        private final String name;
t_h@351
   152
        TestObj(String name) {
t_h@351
   153
            this.name = name;
t_h@351
   154
            synchronized (testObjs) {
t_h@351
   155
                testObjs.add(this);
t_h@351
   156
            }
t_h@351
   157
        }
t_h@351
   158
t_h@351
   159
        @Override
t_h@351
   160
        public String toString() {
t_h@351
   161
            return name;
t_h@351
   162
        }
t_h@351
   163
        
t_h@351
   164
    }
t_h@351
   165
    
t_h@351
   166
    private final static class GC implements Runnable {
t_h@351
   167
t_h@351
   168
        public void run() {
t_h@351
   169
            try {
t_h@351
   170
                for (int i = 0; i < 5; i++) {
t_h@351
   171
                    gc();
t_h@351
   172
                }
t_h@351
   173
            } catch (InterruptedException ex) {
t_h@351
   174
                // ignore
t_h@351
   175
            }
t_h@351
   176
        }
t_h@351
   177
t_h@351
   178
        static void gc() throws InterruptedException {
t_h@351
   179
            List<byte[]> alloc = new ArrayList<byte[]>();
t_h@351
   180
            int size = 100000;
t_h@351
   181
            for (int i = 0; i < 50; i++) {
t_h@351
   182
                System.gc();
t_h@351
   183
                System.runFinalization();
t_h@351
   184
                try {
t_h@351
   185
                    alloc.add(new byte[size]);
t_h@351
   186
                    size = (int) (((double) size) * 1.3);
t_h@351
   187
                } catch (OutOfMemoryError error) {
t_h@351
   188
                    size = size / 2;
t_h@351
   189
                }
t_h@351
   190
                if (i % 3 == 0) {
t_h@351
   191
                    Thread.sleep(100);
t_h@351
   192
                }
t_h@351
   193
            }
t_h@351
   194
        }
t_h@351
   195
    }
t_h@351
   196
t_h@351
   197
    /**
t_h@351
   198
     * test for issue #106218
t_h@351
   199
     * @throws java.lang.Exception
t_h@351
   200
     */
jglick@490
   201
    @RandomlyFails // OOME in NB-Core-Build #1908
t_h@351
   202
    public void testWeakSetIntegrity() throws Exception {
t_h@351
   203
        //CharSequence log = Log.enable(WeakSet.class.getName(), Level.FINE);
t_h@351
   204
        ArrayList<WeakReference<TestObj>> awr = new ArrayList<WeakReference<TestObj>>();
t_h@351
   205
        ExecutorService exec = Executors.newFixedThreadPool(5);
t_h@361
   206
        exec.execute(new GC());
t_h@351
   207
        for (int i = 0; i < 1000; i++) {
t_h@351
   208
            TestObj to = new TestObj("T" + i);
t_h@351
   209
            awr.add(new WeakReference<TestObj>(to));
t_h@361
   210
            Thread.yield();
t_h@351
   211
            for (WeakReference<TestObj> wro : awr) {
t_h@351
   212
                TestObj wroo = wro.get();
t_h@351
   213
                if (wroo != null) {
t_h@351
   214
                    synchronized (TestObj.testObjs) {
t_h@351
   215
                        boolean found = false;
t_h@351
   216
                        for (TestObj o : TestObj.testObjs) {
t_h@351
   217
                            if (o == wroo) {
t_h@351
   218
                                found = true;
t_h@351
   219
                            }
t_h@351
   220
                        }
t_h@351
   221
                        if (found != TestObj.testObjs.contains(wroo)) {
t_h@351
   222
                            //System.out.println(log.toString());
t_h@351
   223
                            fail("Inconsistency of iterator chain and hash map");
t_h@351
   224
                        }
t_h@351
   225
                    }
t_h@351
   226
                }
t_h@351
   227
            }
t_h@351
   228
        }
t_h@351
   229
        exec.shutdownNow();
t_h@351
   230
    }    
jtulach@9
   231
}