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 package org.apache.harmony.tests.java.lang;
18 
19 import java.util.ArrayList;
20 import java.util.List;
21 
22 public class ObjectTest extends junit.framework.TestCase {
23 
24     final Object lock = new Object();
25 
26     // Helpers for test_notify() and test_notifyAll(). Access is guarded by {@code lock}'s monitor.
27     int ready = 0;
28     int finished = 0;
29     int outstandingNotifications = 0;
30     int spuriousNotifications = 0;
31     Throwable backgroundException;
32 
33     @Override
setUp()34     protected void setUp() throws Exception {
35         super.setUp();
36         synchronized (lock) {
37             backgroundException = null;
38         }
39     }
40 
41     @Override
tearDown()42     protected void tearDown() throws Exception {
43         synchronized (lock) {
44             if (backgroundException != null) {
45                 fail("Encountered " + backgroundException);
46             }
47         }
48         super.tearDown();
49     }
50 
51     /**
52      * java.lang.Object#Object()
53      */
test_constructor()54     public void test_constructor() {
55         // Test for method java.lang.Object()
56         assertNotNull("Constructor failed", new Object());
57     }
58 
59     /**
60      * java.lang.Object#equals(java.lang.Object)
61      */
test_equalsLjava_lang_Object()62     public void test_equalsLjava_lang_Object() {
63         Object obj1 = new Object();
64         Object obj2 = new Object();
65         // Test for method boolean java.lang.Object.equals(java.lang.Object)
66         assertTrue("Same object should be equal", obj1.equals(obj1));
67         assertTrue("Different objects should not be equal", !obj1.equals(obj2));
68     }
69 
70     /**
71      * java.lang.Object#getClass()
72      */
test_getClass()73     public void test_getClass() throws Exception {
74         // Test for method java.lang.Class java.lang.Object.getClass()
75         String[] classNames = { "java.lang.Object", "java.lang.Throwable",
76                 "java.lang.StringBuffer" };
77         for (String className : classNames) {
78             final Class<?> classToTest = Class.forName(className);
79             final Object instanceToTest = classToTest.newInstance();
80             assertSame("Instance didn't match creator class.", instanceToTest.getClass(),
81                     classToTest);
82             assertSame("Instance didn't match class with matching name.", instanceToTest.getClass(),
83                     Class.forName(className));
84         }
85     }
86 
87     /**
88      * java.lang.Object#hashCode()
89      */
test_hashCode()90     public void test_hashCode() {
91         // Test for method int java.lang.Object.hashCode()
92         Object obj1 = new Object();
93         Object obj2;
94         int origHashCodeForObj1 = obj1.hashCode();
95         // Force obj1 lock inflation.
96         synchronized (obj1) {
97             obj2 = new Object();
98         }
99         assertEquals("Same object should have same hash.", obj1.hashCode(), obj1.hashCode());
100         assertEquals("Lock inflation shouldn't change hash code.",
101                 obj1.hashCode(), origHashCodeForObj1);
102         assertEquals("Same object should have same hash.", obj2.hashCode(), obj2.hashCode());
103         Runtime.getRuntime().gc();
104         assertEquals("Gc shouldn't change hash code.", obj1.hashCode(), origHashCodeForObj1);
105     }
106 
107     /**
108      * java.lang.Object#notify()
109      */
test_notify()110     public void test_notify() {
111         // Test for method void java.lang.Object.notify()
112         class TestThread extends Thread {
113             public TestThread(String name) {
114                 super(name);
115             }
116 
117             @Override
118             public void run() {
119                 synchronized (lock) {
120                     try {
121                         ready++;
122                         lock.wait(); // Wait to be notified.
123                         while (outstandingNotifications <= 0) {
124                             spuriousNotifications++;
125                             lock.wait();
126                         }
127                         outstandingNotifications--;
128                     } catch (InterruptedException ex) {
129                         backgroundException = ex;
130                     }
131                 }
132             }
133         }
134 
135         // Warning:
136         // This code relies on each thread getting serviced within
137         // 400 msec of when it is notified. Although this
138         // seems reasonable, it could lead to false-failures.
139 
140         ready = 0;
141         outstandingNotifications = 0;
142         spuriousNotifications = 0;
143         final int readyWaitSecs = 3;
144 
145         final int threadCount = 20;
146         List<TestThread> threads = new ArrayList<>();
147         for (int i = 0; i < threadCount; ++i) {
148             TestThread thread = new TestThread("TestThread " + i);
149             threads.add(thread);
150             thread.start();
151         }
152         synchronized (lock) {
153             try {
154                 // Wait up to readyWaitSeconds for all threads to be waiting on
155                 // monitor
156                 for (int i = 0; i < 10 * readyWaitSecs; i++) {
157                     lock.wait(100, 0);
158                     if (ready == threadCount) {
159                         break;
160                     }
161                 }
162                 assertEquals("Not all launched threads are waiting. (ready=" + ready + ")",
163                         ready, threadCount);
164                 for (int i = 1; i <= threadCount; ++i) {
165                     outstandingNotifications++;
166                     lock.notify();
167                     for (int j = 0; j < 10 && outstandingNotifications > 0; ++j) {
168                         lock.wait(100);  // Sleep for 100 msecs, releasing lock.
169                     }
170                     assertEquals("Notification #" + i + "  took too long to wake a thread.",
171                             0, outstandingNotifications);
172                     // Spurious notifications are allowed, but should be very rare.
173                     assertTrue("Too many spurious notifications: " + spuriousNotifications,
174                             spuriousNotifications <= 1);
175                 }
176             } catch (InterruptedException ex) {
177                 fail("Unexpectedly got an InterruptedException.");
178             }
179         }
180     }
181 
182     /**
183      * java.lang.Object#notifyAll()
184      */
test_notifyAll()185     public void test_notifyAll() {
186         // Test for method void java.lang.Object.notifyAll()
187 
188         // Inner class to run test thread.
189         class TestThread implements Runnable {
190             public void run() {
191                 synchronized (lock) {
192                     try {
193                         ready += 1;
194                         lock.wait();// Wait forever.
195                         finished += 1;
196                     } catch (InterruptedException ex) {
197                         backgroundException = ex;
198                     }
199                 }
200             }
201         }
202         ;
203 
204         // Start of test code.
205 
206         // Warning:
207         // This code relies on all threads getting serviced within
208         // 5 seconds of when they are notified. Although this
209         // seems reasonable, it could lead to false-failures.
210 
211         ready = 0;
212         finished = 0;
213         final int readyWaitSecs = 3;
214         final int finishedWaitSecs = 5;
215         final int threadCount = 20;
216         for (int i = 0; i < threadCount; ++i) {
217             new Thread(new TestThread()).start();
218         }
219 
220         synchronized (lock) {
221 
222             try {
223                 // Wait up to readyWaitSeconds for all threads to be waiting on
224                 // monitor
225                 for (int i = 0; i < readyWaitSecs; i++) {
226                     lock.wait(1000, 0);
227                     if (ready == threadCount) {
228                         break;
229                     }
230                 }
231 
232                 // Check pre-conditions of testing notifyAll
233                 assertEquals("Not all launched threads are waiting.", threadCount, ready);
234                 // This assumes no spurious wakeups. If we ever see any, we might check for at
235                 // most one finished thread instead.
236                 assertEquals("At least one thread woke too early.", 0, finished);
237 
238                 lock.notifyAll();
239 
240                 for (int i = 0; finished < threadCount && i < finishedWaitSecs; ++i) {
241                   lock.wait(1000, 0);
242                 }
243 
244                 assertEquals("At least one thread did not get notified.", threadCount, finished);
245 
246             } catch (InterruptedException ex) {
247                 fail("Unexpectedly got an InterruptedException. (finished = " + finished + ")");
248             }
249 
250         }
251     }
252 
253     /**
254      * java.lang.Object#toString()
255      */
test_toString()256     public void test_toString() {
257         // Test for method java.lang.String java.lang.Object.toString()
258         assertNotNull("Object toString returned null.", lock.toString());
259     }
260 
261     /**
262      * java.lang.Object#wait()
263      */
test_wait()264     public void test_wait() {
265         // Test for method void java.lang.Object.wait()
266 
267         // Inner class to run test thread.
268         class TestThread extends Thread {
269             int status;
270 
271             public void run() {
272                 synchronized (lock) {
273                     try {
274                         do {
275                             lock.wait(); // Wait to be notified.
276                         } while (outstandingNotifications <= 0);
277                         outstandingNotifications--;
278                         status = 1;
279                     } catch (InterruptedException ex) {
280                         backgroundException = ex;
281                     }
282                 }
283             }
284         }
285 
286         // Start of test code.
287 
288         // Warning:
289         // This code relies on threads getting serviced within
290         // 1 second of when they are notified. Although this
291         // seems reasonable, it could lead to false-failures.
292 
293         TestThread thread = new TestThread();
294         synchronized (lock) {
295             thread.status = 0;
296         }
297         thread.start();
298         synchronized (lock) {
299             try {
300                 lock.wait(1000, 0);
301                 assertEquals("Thread woke too early. (status=" + thread.status + ")",
302                         0, thread.status);
303                 outstandingNotifications = 1;
304                 lock.notifyAll();
305                 lock.wait(1000, 0);
306                 assertEquals("Thread did not get notified. (status=" + thread.status + ")",
307                         1, thread.status);
308             } catch (InterruptedException ex) {
309                 fail("Unexpectedly got an InterruptedException. (status=" + thread.status + ")");
310             }
311         }
312     }
313 
314     /**
315      * java.lang.Object#wait(long)
316      */
test_waitJ()317     public void test_waitJ() {
318         // Test for method void java.lang.Object.wait(long)
319 
320         // Start of test code.
321 
322         final int loopCount = 20;
323         final int allowableError = 100; // milliseconds
324         final int delay = 200; // milliseconds
325         synchronized (lock) {
326             try {
327                 int count = 0;
328                 long[][] toLong = new long[3][3];
329                 for (int i = 0; i < loopCount; ++i) {
330                     long before = System.currentTimeMillis();
331                     lock.wait(delay, 0);
332                     long after = System.currentTimeMillis();
333                     long error = (after - before - delay);
334                     if (error < 0)
335                         error = -error;
336                     if (i > 0 && error > allowableError) {
337                         // Allow jit to warm up before testing
338                         if (count < toLong.length) {
339                             toLong[count][0] = i;
340                             toLong[count][1] = before;
341                             toLong[count][2] = after;
342                             count++;
343                         }
344                         if (error > (1000 + delay) || count == toLong.length) {
345                             StringBuilder sb = new StringBuilder();
346                             for (int j = 0; j < count; j++) {
347                                 sb.append("wakeup time too inaccurate, iteration ");
348                                 sb.append(toLong[j][0]);
349                                 sb.append(", before: ");
350                                 sb.append(toLong[j][1]);
351                                 sb.append(" after: ");
352                                 sb.append(toLong[j][2]);
353                                 sb.append(" diff: ");
354                                 sb.append(toLong[j][2] - toLong[j][1]);
355                                 sb.append("\n");
356                             }
357                             fail(sb.toString());
358                         }
359                     }
360                 }
361             } catch (InterruptedException ex) {
362                 fail("Unexpectedly got an InterruptedException.");
363             }
364         }
365     }
366 
367     /**
368      * java.lang.Object#wait(long, int)
369      */
test_waitJI()370     public void test_waitJI() {
371         // Test for method void java.lang.Object.wait(long, int)
372 
373         // Inner class to run test thread.
374         class TestThread extends Thread {
375             int status;
376 
377             @Override
378             public void run() {
379                 synchronized (lock) {
380                     try {
381                         lock.wait(0, 1); // Don't wait very long.
382                         status = 1;
383                         do {
384                             lock.wait(0, 0); // Wait to be notified.
385                         } while (outstandingNotifications <= 0);
386                         outstandingNotifications--;
387                         status = 2;
388                     } catch (InterruptedException ex) {
389                         backgroundException = ex;
390                     }
391                 }
392             }
393         }
394 
395         // Start of test code.
396 
397         // Warning:
398         // This code relies on threads getting serviced within
399         // 1 second of when they are notified. Although this
400         // seems reasonable, it could lead to false-failures.
401 
402         TestThread thread = new TestThread();
403         synchronized (lock) {
404             thread.status = 0;
405         }
406         thread.start();
407         synchronized (lock) {
408             try {
409                 lock.wait(1000, 0);
410                 assertEquals("Thread did not wake after 1sec. (status=" + thread.status + ")",
411                         1, thread.status);
412                 outstandingNotifications++;
413                 lock.notifyAll();
414                 lock.wait(1000, 0);
415                 assertEquals("Thread did not get notified. (status=" +
416                         thread.status + ")", 2, thread.status);
417             } catch (InterruptedException ex) {
418                 fail("Unexpectedly got an InterruptedException. (status = " +
419                         thread.status + ")");
420             }
421         }
422     }
423 }
424