1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.tests.java.lang.ref;
19
20import java.lang.ref.PhantomReference;
21import java.lang.ref.Reference;
22import java.lang.ref.ReferenceQueue;
23import java.lang.ref.SoftReference;
24import java.lang.ref.WeakReference;
25import java.util.concurrent.CountDownLatch;
26import libcore.java.lang.ref.FinalizationTester;
27
28public class ReferenceQueueTest extends junit.framework.TestCase {
29    static Boolean b;
30
31    static Integer integer;
32    boolean isThrown = false;
33
34    protected void doneSuite() {
35        b = null;
36        integer = null;
37    }
38
39    public class ChildThread implements Runnable {
40        public ChildThread() {
41        }
42
43        public void run() {
44            try {
45                Thread.sleep(100);
46            } catch (Exception e) {}
47            // store in a static so it won't be gc'ed because the jit
48            // optimized it out
49            integer = new Integer(667);
50            SoftReference sr = new SoftReference(integer, rq);
51            sr.enqueue();
52        }
53    }
54
55    ReferenceQueue rq;
56
57    /**
58     * java.lang.ref.ReferenceQueue#poll()
59     */
60    public void test_poll() {
61        // store in a static so it won't be gc'ed because the jit
62        // optimized it out
63        b = new Boolean(true);
64        Object obj = new Object();
65        String str = "Test";
66
67        SoftReference sr = new SoftReference(b, rq);
68        WeakReference wr = new WeakReference(obj, rq);
69        PhantomReference pr = new PhantomReference(str, rq);
70        assertNull(rq.poll());
71        sr.enqueue();
72        wr.enqueue();
73        pr.enqueue();
74
75        try {
76            assertTrue("Remove failed.", ((Boolean) rq.poll().get())
77                    .booleanValue());
78        } catch (Exception e) {
79            fail("Exception during the test : " + e.getMessage());
80        }
81
82        try {
83            assertEquals("Remove failed.", obj, (rq.poll().get()));
84        } catch (Exception e) {
85            fail("Exception during the test : " + e.getMessage());
86        }
87
88        try {
89            assertNull("Remove failed.", rq.poll().get());
90        } catch (Exception e) {
91            fail("Exception during the test : " + e.getMessage());
92        }
93
94        assertNull(rq.poll());
95
96        sr.enqueue();
97        wr.enqueue();
98
99        FinalizationTester.induceFinalization();
100
101        assertNull(rq.poll());
102    }
103
104    /**
105     * java.lang.ref.ReferenceQueue#remove()
106     */
107    public void test_remove() {
108        // store in a static so it won't be gc'ed because the jit
109        // optimized it out
110        b = new Boolean(true);
111
112        SoftReference sr = new SoftReference(b, rq);
113        sr.enqueue();
114        try {
115            assertTrue("Remove failed.", ((Boolean) rq.remove().get())
116                    .booleanValue());
117        } catch (Exception e) {
118            fail("Exception during the test : " + e.getMessage());
119        }
120
121        assertNull(rq.poll());
122
123        sr.enqueue();
124
125        class RemoveThread extends Thread {
126            public void run() {
127                try {
128                    rq.remove();
129                } catch(InterruptedException ie) {
130                    isThrown = true;
131                }
132            }
133        }
134        RemoveThread rt = new RemoveThread();
135        rt.start();
136        try {
137            Thread.sleep(100);
138        } catch(InterruptedException ie) {
139
140        }
141        rt.interrupt();
142        try {
143            Thread.sleep(100);
144        } catch(InterruptedException ie) {
145
146        }
147        assertTrue(isThrown);
148        assertNull(rq.poll());
149    }
150
151    /**
152     * java.lang.ref.ReferenceQueue#remove(long)
153     */
154    public void test_removeJ() {
155        try {
156            assertNull("Queue should be empty. (poll)", rq.poll());
157            assertNull("Queue should be empty. (remove(1))",
158                    rq.remove((long) 1));
159            Thread ct = new Thread(new ChildThread());
160            ct.start();
161            Reference ret = rq.remove(0L);
162            assertNotNull("Delayed remove failed.", ret);
163        } catch (InterruptedException e) {
164            fail("InterruptedExeException during test : " + e.getMessage());
165        }
166        catch (Exception e) {
167            fail("Exception during test : " + e.getMessage());
168        }
169
170        Object obj = new Object();
171        WeakReference wr = new WeakReference(obj, rq);
172        Boolean b = new Boolean(true);
173        SoftReference sr = new SoftReference(b, rq);
174        String str = "Test";
175        PhantomReference pr = new PhantomReference(str, rq);
176
177        pr.enqueue();
178        wr.enqueue();
179        sr.enqueue();
180
181        try {
182            Reference result = rq.remove(1L);
183            assertNull(result.get());
184            result = rq.remove(1L);
185            assertEquals(obj, result.get());
186            result = rq.remove(1L);
187            assertTrue((Boolean)result.get());
188        } catch (IllegalArgumentException e1) {
189            fail("IllegalArgumentException was thrown.");
190        } catch (InterruptedException e1) {
191            fail("InterruptedException was thrown.");
192        }
193        rq = new ReferenceQueue();
194        isThrown = false;
195        assertNull(rq.poll());
196
197        class RemoveThread extends Thread {
198            public final CountDownLatch inBlock = new CountDownLatch(1);
199            public final CountDownLatch outOfBlock = new CountDownLatch(1);
200            public void run() {
201                try {
202                    inBlock.countDown();
203                    rq.remove(1000L);
204                } catch(InterruptedException ie) {
205                    isThrown = true;
206                }
207                outOfBlock.countDown();
208            }
209        }
210        RemoveThread rt = new RemoveThread();
211        rt.start();
212        try {
213            rt.inBlock.await();
214            // Try to be inside of rq.remove(1000L) if possible.
215            Thread.sleep(10);
216        } catch(InterruptedException ie) {}
217        rt.interrupt();
218        try {
219            rt.outOfBlock.await();
220        } catch(InterruptedException ie) {}
221        assertTrue(isThrown);
222        assertNull(rq.poll());
223
224        try {
225            rq.remove(-1);
226            fail("IllegalArgumentException expected.");
227        } catch(IllegalArgumentException iae) {
228            //expected
229        } catch (InterruptedException e) {
230            fail("Unexpected InterruptedException.");
231        }
232    }
233
234    /**
235     * java.lang.ref.ReferenceQueue#ReferenceQueue()
236     */
237    public void test_Constructor() {
238        ReferenceQueue rq = new ReferenceQueue();
239        assertNull(rq.poll());
240        try {
241            rq.remove(100L);
242        } catch (InterruptedException e) {
243            fail("InterruptedException was thrown.");
244        }
245    }
246
247    protected void setUp() {
248        rq = new ReferenceQueue();
249    }
250
251    protected void tearDown() {
252    }
253}
254