openide.util/test/unit/src/org/openide/util/lookup/ProxyLookupTest.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 05 Feb 2008 19:43:00 +0100
branchweak_proxy_lookup_but_does_not_GC_template_and_its_class
changeset 340 c059ff4c4133
parent 326 00a401f0f875
child 341 29bbadcb8e5f
permissions -rw-r--r--
An attempt to make the result hold the data weak, but it does not work because of GC of template's class
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.lookup;
jtulach@9
    43
jtulach@94
    44
import java.io.Serializable;
jtulach@9
    45
import org.openide.util.*;
jtulach@9
    46
pnejedly@126
    47
import java.lang.ref.Reference;
jtulach@9
    48
import java.lang.ref.WeakReference;
jtulach@9
    49
import java.util.*;
jtulach@9
    50
import junit.framework.*;
jtulach@9
    51
import org.netbeans.junit.*;
jtulach@306
    52
import org.openide.util.Lookup.Result;
jtulach@9
    53
jtulach@9
    54
/** Runs all NbLookupTest tests on ProxyLookup and adds few additional.
jtulach@9
    55
 */
jtulach@9
    56
public class ProxyLookupTest extends AbstractLookupBaseHid
jtulach@9
    57
implements AbstractLookupBaseHid.Impl {
jtulach@9
    58
    public ProxyLookupTest(java.lang.String testName) {
jtulach@9
    59
        super(testName, null);
jtulach@9
    60
    }
jtulach@189
    61
jtulach@85
    62
    public static Test suite() {
jtulach@85
    63
        return new NbTestSuite (ProxyLookupTest.class);
jtulach@85
    64
        
jtulach@307
    65
        //return new ProxyLookupTest("testArrayIndexWithAddRemoveListenerAsInIssue119292");
jtulach@9
    66
    }
jtulach@9
    67
    
jtulach@9
    68
    /** Creates an lookup for given lookup. This class just returns 
jtulach@9
    69
     * the object passed in, but subclasses can be different.
jtulach@9
    70
     * @param lookup in lookup
jtulach@9
    71
     * @return a lookup to use
jtulach@9
    72
     */
jtulach@9
    73
    public Lookup createLookup (Lookup lookup) {
jtulach@9
    74
        return new ProxyLookup (new Lookup[] { lookup });
jtulach@9
    75
    }
jtulach@9
    76
    
jtulach@9
    77
    public Lookup createInstancesLookup (InstanceContent ic) {
jtulach@9
    78
        return new AbstractLookup (ic);
jtulach@9
    79
    }
jtulach@9
    80
    
jtulach@9
    81
jtulach@9
    82
    public void clearCaches () {
jtulach@9
    83
    }    
jtulach@9
    84
    
jtulach@9
    85
    
jtulach@9
    86
    /** Check whether setLookups method does not fire when there is no
jtulach@9
    87
     * change in the lookups.
jtulach@9
    88
     */
jtulach@9
    89
    public void testProxyListener () {
jtulach@9
    90
        ProxyLookup lookup = new ProxyLookup (new Lookup[0]);
jtulach@325
    91
jtulach@325
    92
        final Lookup.Template<Object> template = new Lookup.Template<Object>(Object.class);
jtulach@325
    93
        final Object[] IGNORE = {
jtulach@325
    94
            ProxyLookup.EMPTY_ARR,
jtulach@325
    95
            Utilities.activeReferenceQueue(),
jtulach@325
    96
            
jtulach@325
    97
        };
jtulach@325
    98
        
jtulach@325
    99
        assertSize("Pretty small", Collections.singleton(lookup), 16, IGNORE);
jtulach@325
   100
        
jtulach@325
   101
        Lookup.Result<Object> res = lookup.lookup (template);
jtulach@325
   102
jtulach@340
   103
        assertSize("Bigger", Collections.singleton(lookup), 368, IGNORE);
jtulach@9
   104
        
jtulach@9
   105
        LL ll = new LL ();
jtulach@9
   106
        res.addLookupListener (ll);
jtulach@9
   107
        Collection allRes = res.allInstances ();
jtulach@9
   108
        
jtulach@9
   109
        lookup.setLookups (new Lookup[0]);
jtulach@9
   110
        
jtulach@9
   111
        if (ll.getCount () != 0) {
jtulach@9
   112
           fail ("Calling setLookups (emptyarray) fired a change");
jtulach@9
   113
        }
jtulach@9
   114
        
jtulach@85
   115
        InstanceContent t = new InstanceContent();
jtulach@85
   116
        Lookup del = new AbstractLookup (t);
jtulach@85
   117
        t.add("Ahoj");
jtulach@9
   118
        lookup.setLookups (new Lookup[] { del });
jtulach@9
   119
        
jtulach@9
   120
        if (ll.getCount () != 1) {
jtulach@9
   121
            fail ("Changing lookups did not generate an event");
jtulach@9
   122
        }
jtulach@9
   123
        
jtulach@9
   124
        lookup.setLookups (new Lookup[] { del });
jtulach@9
   125
        
jtulach@9
   126
        if (ll.getCount () != 0) {
jtulach@9
   127
           fail ("Calling setLookups (thesamearray) fired a change");
jtulach@9
   128
        }
jtulach@9
   129
    }
jtulach@9
   130
jtulach@9
   131
    public void testSetLookups () throws Exception {
jtulach@9
   132
        AbstractLookup a1 = new AbstractLookup (new InstanceContent ());
jtulach@9
   133
        AbstractLookup a2 = new AbstractLookup (new InstanceContent ());
jtulach@9
   134
        
jtulach@9
   135
        InstanceContent i3 = new InstanceContent ();
jtulach@9
   136
        i3.add (i3);
jtulach@9
   137
        AbstractLookup a3 = new AbstractLookup (i3);
jtulach@9
   138
jtulach@9
   139
        final ProxyLookup p = new ProxyLookup (new Lookup[] { a1, a2 });
jtulach@9
   140
        final Lookup.Result res1 = p.lookup (new Lookup.Template (Object.class));
jtulach@9
   141
        Collection c1 = res1.allInstances();
jtulach@9
   142
        
jtulach@9
   143
        Lookup.Result res2 = p.lookup (new Lookup.Template (String.class));
jtulach@9
   144
        Collection c2 = res2.allInstances ();
jtulach@9
   145
        
jtulach@9
   146
        
jtulach@9
   147
        assertTrue ("We need two results", res1 != res2);
jtulach@9
   148
jtulach@9
   149
        final Object blocked = new Object ();
jtulach@9
   150
jtulach@9
   151
        class L extends Object implements LookupListener {
jtulach@9
   152
            public void resultChanged (LookupEvent ev) {
jtulach@9
   153
                try {
jtulach@9
   154
                    res1.removeLookupListener(this);
jtulach@9
   155
                    
jtulach@9
   156
                    // waiting for second thread to start #111#
jtulach@9
   157
                    blocked.wait ();
jtulach@9
   158
jtulach@9
   159
                } catch (Exception ex) {
jtulach@9
   160
                    ex.printStackTrace();
jtulach@9
   161
                    fail ("An exception occured ");
jtulach@9
   162
                }
jtulach@9
   163
            }
jtulach@9
   164
        }
jtulach@9
   165
        
jtulach@9
   166
        final L listener1 = new L ();
jtulach@9
   167
        res1.addLookupListener (listener1);
jtulach@9
   168
        
jtulach@9
   169
jtulach@9
   170
        Runnable newLookupSetter = new Runnable() {
jtulach@9
   171
            public void run () {
jtulach@9
   172
                synchronized (blocked) {
jtulach@9
   173
                    try {
jtulach@9
   174
                        p.setLookups (new Lookup[0]);
jtulach@9
   175
                    } catch (Exception ex) {
jtulach@9
   176
                        ex.printStackTrace();
jtulach@9
   177
                        fail ("setLookups failed.");
jtulach@9
   178
                    } finally {
jtulach@9
   179
                        // starts the main thread #111#
jtulach@9
   180
                        blocked.notify ();
jtulach@9
   181
                    }
jtulach@9
   182
                }
jtulach@9
   183
            }
jtulach@9
   184
        };
jtulach@9
   185
        
jtulach@9
   186
        synchronized (blocked) {
jtulach@9
   187
            new Thread (newLookupSetter).start ();
jtulach@9
   188
            
jtulach@9
   189
            p.setLookups (new Lookup[] { a1, a2, a3 });
jtulach@9
   190
        }
jtulach@9
   191
    }
jtulach@30
   192
    
jtulach@30
   193
    public void testProxyLookupTemplateCaching(){
jtulach@30
   194
        Lookup lookups[] = new Lookup[1];
jtulach@30
   195
        doProxyLookupTemplateCaching(lookups, false);
jtulach@30
   196
    }
jtulach@30
   197
    
jtulach@30
   198
    public void testProxyLookupTemplateCachingOnSizeTwoArray() {
jtulach@30
   199
        Lookup lookups[] = new Lookup[2];
jtulach@30
   200
        lookups[1] = Lookup.EMPTY;
jtulach@30
   201
        doProxyLookupTemplateCaching(lookups, false);
jtulach@30
   202
    }
jtulach@30
   203
    public void testProxyLookupShallNotAllowModificationOfGetLookups(){
jtulach@30
   204
        Lookup lookups[] = new Lookup[1];
jtulach@30
   205
        doProxyLookupTemplateCaching(lookups, true);
jtulach@30
   206
    }
jtulach@30
   207
    
jtulach@30
   208
    public void testProxyLookupShallNotAllowModificationOfGetLookupsOnSizeTwoArray() {
jtulach@30
   209
        Lookup lookups[] = new Lookup[2];
jtulach@30
   210
        lookups[1] = Lookup.EMPTY;
jtulach@30
   211
        doProxyLookupTemplateCaching(lookups, true);
jtulach@30
   212
    }
jtulach@30
   213
    
jtulach@30
   214
    /** Index 0 of lookups will be modified, the rest is up to the 
jtulach@30
   215
     * setup code.
jtulach@30
   216
     */
jtulach@30
   217
    private void doProxyLookupTemplateCaching(Lookup[] lookups, boolean reget) {
jtulach@30
   218
        // Create MyProxyLookup with one lookup containing the String object
jtulach@30
   219
        InstanceContent ic = new InstanceContent();
jtulach@30
   220
        ic.add(new String("Hello World")); //NOI18N
jtulach@30
   221
        lookups[0] = new AbstractLookup(ic);
jtulach@30
   222
        ProxyLookup proxy = new ProxyLookup(lookups);
jtulach@30
   223
        if (reget) {
jtulach@30
   224
            lookups = proxy.getLookups();
jtulach@30
   225
        }
jtulach@30
   226
        
jtulach@30
   227
        // Performing template lookup for String object
jtulach@30
   228
        Lookup.Result result = proxy.lookup(new Lookup.Template(String.class, null, null));
jtulach@30
   229
        int stringTemplateResultSize = result.allInstances().size();
jtulach@30
   230
        assertEquals ("Ensure, there is only one instance of String.class in proxyLookup:", //NOI18N
jtulach@30
   231
                1, stringTemplateResultSize);
jtulach@30
   232
        
jtulach@30
   233
        // Changing lookup in proxy lookup, now it will contain 
jtulach@30
   234
        // StringBuffer Object instead of String
jtulach@30
   235
        InstanceContent ic2 = new InstanceContent();
jtulach@30
   236
        ic2.add(new Integer(1234567890));
jtulach@30
   237
        lookups[0] = new AbstractLookup(ic2);
jtulach@30
   238
        proxy.setLookups(lookups);
jtulach@30
   239
        
jtulach@30
   240
        assertEquals ("the old result is updated", 0, result.allInstances().size());
jtulach@30
   241
jtulach@30
   242
        // Instance of String.class should not appear in proxyLookup
jtulach@30
   243
        Lookup.Result r2 = proxy.lookup(new Lookup.Template(String.class, null, null));
jtulach@30
   244
        assertEquals ("Instance of String.class should not appear in proxyLookup:", //NOI18N
jtulach@30
   245
                0, r2.allInstances().size());
jtulach@30
   246
jtulach@30
   247
        Lookup.Result r3 = proxy.lookup(new Lookup.Template(Integer.class, null, null));
jtulach@30
   248
        assertEquals ("There is only one instance of Integer.class in proxyLookup:", //NOI18N
jtulach@30
   249
                1, r3.allInstances().size());
jtulach@30
   250
    }
jtulach@85
   251
    
jtulach@94
   252
    public void testListeningAndQueryingByTwoListenersInstancesSetLookups() {
jtulach@94
   253
        doListeningAndQueryingByTwoListenersSetLookups(0, 1);
jtulach@94
   254
    }
jtulach@94
   255
    public void testListeningAndQueryingByTwoListenersClassesSetLookups() {
jtulach@94
   256
        doListeningAndQueryingByTwoListenersSetLookups(1, 1);        
jtulach@94
   257
    }
jtulach@94
   258
    public void testListeningAndQueryingByTwoListenersItemsSetLookups() {
jtulach@94
   259
        doListeningAndQueryingByTwoListenersSetLookups(2, 1);
jtulach@94
   260
    }
jtulach@94
   261
    
jtulach@94
   262
    public void testListeningAndQueryingByTwoListenersInstancesSetLookups2() {
jtulach@94
   263
        doListeningAndQueryingByTwoListenersSetLookups(0, 2);
jtulach@94
   264
    }
jtulach@94
   265
    public void testListeningAndQueryingByTwoListenersClassesSetLookups2() {
jtulach@94
   266
        doListeningAndQueryingByTwoListenersSetLookups(1, 2);        
jtulach@94
   267
    }
jtulach@94
   268
    public void testListeningAndQueryingByTwoListenersItemsSetLookups2() {
jtulach@94
   269
        doListeningAndQueryingByTwoListenersSetLookups(2, 2);
jtulach@94
   270
    }
jtulach@94
   271
    public void testListeningAndQueryingByTwoListenersInstancesSetLookups22() {
jtulach@94
   272
        doListeningAndQueryingByTwoListenersSetLookups(0, 22);
jtulach@94
   273
    }
jtulach@94
   274
    public void testListeningAndQueryingByTwoListenersClassesSetLookups22() {
jtulach@94
   275
        doListeningAndQueryingByTwoListenersSetLookups(1, 22);        
jtulach@94
   276
    }
jtulach@94
   277
    public void testListeningAndQueryingByTwoListenersItemsSetLookups22() {
jtulach@94
   278
        doListeningAndQueryingByTwoListenersSetLookups(2, 22);
jtulach@94
   279
    }
jtulach@94
   280
    
jtulach@94
   281
    private void doListeningAndQueryingByTwoListenersSetLookups(final int type, int depth) {
jtulach@94
   282
        ProxyLookup orig = new ProxyLookup();
jtulach@94
   283
        ProxyLookup on = orig;
jtulach@94
   284
        
jtulach@94
   285
        while (--depth > 0) {
jtulach@94
   286
            on = new ProxyLookup(new Lookup[] { on });
jtulach@94
   287
        }
jtulach@94
   288
        
jtulach@94
   289
        
jtulach@94
   290
        final ProxyLookup lookup = on;
jtulach@94
   291
        
jtulach@94
   292
        class L implements LookupListener {
jtulach@94
   293
            Lookup.Result integer = lookup.lookup(new Lookup.Template(Integer.class));
jtulach@94
   294
            Lookup.Result number = lookup.lookup(new Lookup.Template(Number.class));
jtulach@94
   295
            Lookup.Result serial = lookup.lookup(new Lookup.Template(Serializable.class));
jtulach@94
   296
            
jtulach@94
   297
            {
jtulach@94
   298
                integer.addLookupListener(this);
jtulach@94
   299
                number.addLookupListener(this);
jtulach@94
   300
                serial.addLookupListener(this);
jtulach@94
   301
            }
jtulach@94
   302
            
jtulach@94
   303
            int round;
jtulach@94
   304
            
jtulach@94
   305
            public void resultChanged(LookupEvent ev) {
jtulach@94
   306
                Collection c1 = get(type, integer);
jtulach@94
   307
                Collection c2 = get(type, number);
jtulach@94
   308
                Collection c3 = get(type, serial);
jtulach@94
   309
                
jtulach@94
   310
                assertEquals("round " + round + " c1 vs. c2", c1, c2);
jtulach@94
   311
                assertEquals("round " + round + " c1 vs. c3", c1, c3);
jtulach@94
   312
                assertEquals("round " + round + " c2 vs. c3", c2, c3);
jtulach@94
   313
                
jtulach@94
   314
                round++;
jtulach@94
   315
            }            
jtulach@94
   316
jtulach@94
   317
            private Collection get(int type, Lookup.Result res) {
jtulach@94
   318
                Collection c;
jtulach@94
   319
                switch(type) {
jtulach@94
   320
                    case 0: c = res.allInstances(); break;
jtulach@94
   321
                    case 1: c = res.allClasses(); break;
jtulach@94
   322
                    case 2: c = res.allItems(); break;
jtulach@94
   323
                    default: c = null; fail("Type: " + type); break;
jtulach@94
   324
                }
jtulach@94
   325
                
jtulach@94
   326
                assertNotNull(c);
jtulach@94
   327
                return new ArrayList(c);
jtulach@94
   328
            }
jtulach@94
   329
        }
jtulach@94
   330
        
jtulach@94
   331
        L listener = new L();
jtulach@94
   332
        listener.resultChanged(null);
jtulach@94
   333
        ArrayList arr = new ArrayList();
jtulach@94
   334
        for(int i = 0; i < 100; i++) {
jtulach@94
   335
            arr.add(new Integer(i));
jtulach@94
   336
            
jtulach@94
   337
            orig.setLookups(new Lookup[] { Lookups.fixed(arr.toArray()) });
jtulach@94
   338
        }
jtulach@94
   339
        
jtulach@94
   340
        assertEquals("3x100+1 checks", 301, listener.round);
jtulach@94
   341
    }
jtulach@123
   342
pnejedly@126
   343
    static Object holder;
pnejedly@126
   344
    
jtulach@123
   345
    public void testProxyWithLiveResultCanBeCollected() {
pnejedly@126
   346
        Lookup layer0 = Lookups.singleton("Hello");
pnejedly@126
   347
        Lookup layer1 = new ProxyLookup(new Lookup[] { layer0 });
pnejedly@126
   348
        Lookup layer2 = new ProxyLookup(new Lookup[] { layer1 });
pnejedly@126
   349
        Lookup.Result result1 = layer1.lookup(new Lookup.Template(String.class));
pnejedly@126
   350
pnejedly@126
   351
        assertEquals("One instance", 1, result1.allInstances().size());
jtulach@123
   352
jtulach@123
   353
        // this will create ProxyLookup$R which listens on origResult
pnejedly@126
   354
        Lookup.Result result2 = layer2.lookup(new Lookup.Template(String.class));
pnejedly@126
   355
        
pnejedly@126
   356
        // this line is necessary. W/o actually querying the result,
pnejedly@126
   357
        // it will nether compute it nor attach the listener.
pnejedly@126
   358
        assertEquals("One instance", 1, result2.allInstances().size());
pnejedly@126
   359
        
pnejedly@126
   360
        result2.addLookupListener(new LookupListener() {
pnejedly@126
   361
            public void resultChanged(LookupEvent ev) {}
jtulach@123
   362
        });
pnejedly@126
   363
        
pnejedly@126
   364
        Reference ref = new WeakReference(layer2);
pnejedly@126
   365
        layer2 = null;
pnejedly@126
   366
        result2 = null;
pnejedly@126
   367
        try {
pnejedly@126
   368
            holder = result1;
pnejedly@126
   369
            assertGC ("The proxy lookup not been garbage collected!", ref);
pnejedly@126
   370
        } finally {
pnejedly@126
   371
            holder = null;
pnejedly@126
   372
        }
jtulach@123
   373
    }
jtulach@306
   374
    
jtulach@306
   375
    public void testArrayIndexAsInIssue119292() throws Exception {
jtulach@306
   376
        final ProxyLookup pl = new ProxyLookup();
jtulach@306
   377
        final int[] cnt = { 0 };
jtulach@306
   378
        
jtulach@306
   379
        class L extends Lookup {
jtulach@306
   380
            L[] set;
jtulach@306
   381
            Lookup l;
jtulach@306
   382
            
jtulach@306
   383
            public L(String s) {
jtulach@306
   384
                l = Lookups.singleton(s);
jtulach@306
   385
            }
jtulach@306
   386
            
jtulach@306
   387
            @Override
jtulach@306
   388
            public <T> T lookup(Class<T> clazz) {
jtulach@306
   389
                return l.lookup(clazz);
jtulach@306
   390
            }
jtulach@306
   391
jtulach@306
   392
            @Override
jtulach@306
   393
            public <T> Result<T> lookup(Template<T> template) {
jtulach@306
   394
                return l.lookup(template);
jtulach@306
   395
            }
jtulach@306
   396
jtulach@306
   397
            @Override
jtulach@306
   398
            public boolean equals(Object obj) {
jtulach@306
   399
                if (set != null) {
jtulach@306
   400
                    cnt[0]++;
jtulach@306
   401
                    pl.setLookups(set);
jtulach@306
   402
                }
jtulach@306
   403
                return super.equals(obj);
jtulach@306
   404
            }
jtulach@306
   405
jtulach@306
   406
            @Override
jtulach@306
   407
            public int hashCode() {
jtulach@306
   408
                int hash = 3;
jtulach@306
   409
                return hash;
jtulach@306
   410
            }
jtulach@306
   411
        }
jtulach@306
   412
jtulach@306
   413
        Result<String> res = pl.lookupResult(String.class);
jtulach@306
   414
        assertEquals(Collections.EMPTY_LIST, res.allItems());
jtulach@306
   415
        
jtulach@306
   416
        L[] old = { new L("A"), new L("B") };
jtulach@306
   417
        L[] now = { new L("C") };
jtulach@306
   418
        
jtulach@306
   419
        pl.setLookups(old);
jtulach@306
   420
        cnt[0] = 0;
jtulach@306
   421
        
jtulach@306
   422
        old[0].set = new L[0];
jtulach@306
   423
        pl.setLookups(now);
jtulach@306
   424
jtulach@306
   425
        assertEquals("No call to equals", 0, cnt[0]);
jtulach@306
   426
        
jtulach@306
   427
        assertEquals("Still assigned to C", Collections.singletonList("C"), res.allInstances());
jtulach@306
   428
    }
jtulach@307
   429
    
jtulach@307
   430
    public void testArrayIndexWithAddRemoveListenerAsInIssue119292() throws Exception {
jtulach@307
   431
        final ProxyLookup pl = new ProxyLookup();
jtulach@307
   432
        final int[] cnt = { 0 };
jtulach@307
   433
        
jtulach@307
   434
        class L extends Lookup {
jtulach@307
   435
            L[] set;
jtulach@307
   436
            Lookup l;
jtulach@307
   437
            
jtulach@307
   438
            public L(String s) {
jtulach@307
   439
                l = Lookups.singleton(s);
jtulach@307
   440
            }
jtulach@307
   441
            
jtulach@307
   442
            @Override
jtulach@307
   443
            public <T> T lookup(Class<T> clazz) {
jtulach@307
   444
                return l.lookup(clazz);
jtulach@307
   445
            }
jtulach@307
   446
jtulach@307
   447
            @Override
jtulach@307
   448
            public <T> Result<T> lookup(Template<T> template) {
jtulach@307
   449
                Result<T> r = l.lookup(template);
jtulach@307
   450
                return new R<T>(r);
jtulach@307
   451
            }
jtulach@307
   452
jtulach@307
   453
            final class R<T> extends Result<T> {
jtulach@307
   454
                private Result<T> delegate;
jtulach@307
   455
jtulach@307
   456
                public R(Result<T> delegate) {
jtulach@307
   457
                    this.delegate = delegate;
jtulach@307
   458
                }
jtulach@307
   459
                
jtulach@307
   460
                @Override
jtulach@307
   461
                public void addLookupListener(LookupListener l) {
jtulach@307
   462
                    cnt[0]++;
jtulach@307
   463
                    if (set != null) {
jtulach@307
   464
                        pl.setLookups(set);
jtulach@307
   465
                    }
jtulach@307
   466
                    delegate.addLookupListener(l);
jtulach@307
   467
                }
jtulach@307
   468
jtulach@307
   469
                @Override
jtulach@307
   470
                public void removeLookupListener(LookupListener l) {
jtulach@307
   471
                    cnt[0]++;
jtulach@307
   472
                    if (set != null) {
jtulach@307
   473
                        pl.setLookups(set);
jtulach@307
   474
                    }
jtulach@307
   475
                    delegate.removeLookupListener(l);
jtulach@307
   476
                }
jtulach@307
   477
jtulach@307
   478
                @Override
jtulach@307
   479
                public Collection<? extends T> allInstances() {
jtulach@307
   480
                    return delegate.allInstances();
jtulach@307
   481
                }
jtulach@307
   482
            }
jtulach@307
   483
        }
jtulach@307
   484
jtulach@307
   485
        Result<String> res = pl.lookupResult(String.class);
jtulach@307
   486
        assertEquals(Collections.EMPTY_LIST, res.allItems());
jtulach@307
   487
        
jtulach@307
   488
        L[] old = { new L("A"), new L("B") };
jtulach@307
   489
        L[] now = { new L("C") };
jtulach@307
   490
        
jtulach@307
   491
        pl.setLookups(old);
jtulach@307
   492
        cnt[0] = 0;
jtulach@307
   493
        
jtulach@307
   494
        old[0].set = new L[0];
jtulach@307
   495
        pl.setLookups(now);
jtulach@307
   496
jtulach@307
   497
        if (cnt[0] == 0) {
jtulach@307
   498
            fail("There should be calls to listeners");
jtulach@307
   499
        }
jtulach@307
   500
        
jtulach@307
   501
        assertEquals("C is overriden from removeLookupListener", Collections.emptyList(), res.allInstances());
jtulach@307
   502
    }
jtulach@320
   503
    
jtulach@320
   504
    
jtulach@320
   505
    public void testArrayIndexWithSetLookupAsInIssue123679() throws Exception {
jtulach@320
   506
        final ProxyLookup pl = new ProxyLookup();
jtulach@320
   507
        final int[] cnt = { 0 };
jtulach@320
   508
        
jtulach@320
   509
        class L extends Lookup {
jtulach@320
   510
            L[] set;
jtulach@320
   511
            Lookup l;
jtulach@320
   512
            Collection<? extends Serializable> res;
jtulach@320
   513
            
jtulach@320
   514
            public L(String s) {
jtulach@320
   515
                l = Lookups.singleton(s);
jtulach@320
   516
            }
jtulach@320
   517
            
jtulach@320
   518
            @Override
jtulach@320
   519
            public <T> T lookup(Class<T> clazz) {
jtulach@320
   520
                return l.lookup(clazz);
jtulach@320
   521
            }
jtulach@320
   522
jtulach@320
   523
            @Override
jtulach@320
   524
            public <T> Result<T> lookup(Template<T> template) {
jtulach@320
   525
                cnt[0]++;
jtulach@320
   526
                if (set != null) {
jtulach@320
   527
                    pl.setLookups(set);
jtulach@320
   528
                    res = pl.lookupAll(Serializable.class);
jtulach@320
   529
                }
jtulach@320
   530
                Result<T> r = l.lookup(template);
jtulach@320
   531
                return r;
jtulach@320
   532
            }
jtulach@320
   533
        }
jtulach@320
   534
jtulach@320
   535
        L[] now = { new L("A"), new L("B") };
jtulach@320
   536
        L[] old = { new L("C") };
jtulach@320
   537
        pl.setLookups(old);
jtulach@320
   538
        old[0].set = now;
jtulach@320
   539
        
jtulach@320
   540
        Result<String> res = pl.lookupResult(String.class);
jtulach@320
   541
        assertEquals("New items visible", 2, res.allItems().size());
jtulach@320
   542
        
jtulach@320
   543
        
jtulach@320
   544
        pl.setLookups(new L("X"), new L("Y"), new L("Z"));
jtulach@320
   545
    }
jtulach@322
   546
    
jtulach@322
   547
    public void testDuplicatedLookupArrayIndexWithSetLookupAsInIssue123679() throws Exception {
jtulach@322
   548
        final ProxyLookup pl = new ProxyLookup();
jtulach@322
   549
        final int[] cnt = { 0 };
jtulach@322
   550
        
jtulach@322
   551
        class L extends Lookup {
jtulach@322
   552
            L[] set;
jtulach@322
   553
            Lookup l;
jtulach@322
   554
            Collection<? extends Serializable> res;
jtulach@322
   555
            
jtulach@322
   556
            public L(String s) {
jtulach@322
   557
                l = Lookups.singleton(s);
jtulach@322
   558
            }
jtulach@322
   559
            
jtulach@322
   560
            @Override
jtulach@322
   561
            public <T> T lookup(Class<T> clazz) {
jtulach@322
   562
                return l.lookup(clazz);
jtulach@322
   563
            }
jtulach@322
   564
jtulach@322
   565
            @Override
jtulach@322
   566
            public <T> Result<T> lookup(Template<T> template) {
jtulach@322
   567
                cnt[0]++;
jtulach@322
   568
                if (set != null) {
jtulach@322
   569
                    pl.setLookups(set);
jtulach@322
   570
                    res = pl.lookupAll(Serializable.class);
jtulach@322
   571
                }
jtulach@322
   572
                Result<T> r = l.lookup(template);
jtulach@322
   573
                return r;
jtulach@322
   574
            }
jtulach@322
   575
        }
jtulach@322
   576
jtulach@322
   577
        L dupl = new L("A");
jtulach@322
   578
        L[] now = { dupl };
jtulach@322
   579
        L[] old = { new L("C") };
jtulach@322
   580
        pl.setLookups(old);
jtulach@322
   581
        old[0].set = now;
jtulach@322
   582
        
jtulach@322
   583
        Result<String> res = pl.lookupResult(String.class);
jtulach@322
   584
        assertEquals("New items visible", 1, res.allItems().size());
jtulach@322
   585
        
jtulach@322
   586
        
jtulach@322
   587
        pl.setLookups(old);
jtulach@322
   588
    }
jtulach@9
   589
}