1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Exercise Object.wait(), comparing results against wall clock time.
19  */
20 public class Main {
21     /* delays, in milliseconds */
22     private final static long[] DELAYS = {
23         200, 500, 1000, 2000, 3500, 8000
24     };
25     // This test is inherently prone to failures through scheduling delays and spurious wakeups.
26     // We try it repeatedly, and check that failures are "rare enough".
27     // Currently we go for success on the first try or 2 out of 3.
28     private final static int NUM_TRIES = 3;
29     private final static int MAX_FAILURES = 1;
30     private final static int NANOS_PER_MILLI = 1_000_000;
31 
32     // Allow a random scheduling delay of up to 400 msecs.  That value is empirically determined
33     // from failure logs, though we do get occasional violations.
34     // We seem to get very occasional very long delays on host, perhaps due to getting paged out.
35     private final static int MAX_SCHED_MILLIS = 400;
36 
main(String[] args)37     public static void main(String[] args) {
38         boolean timing = (args.length >= 1) && args[0].equals("--timing");
39         doit(timing);
40     }
41 
doit(boolean timing)42     public static void doit(boolean timing) {
43         Object sleepy = new Object();
44 
45         synchronized (sleepy) {
46             try {
47                 sleepy.wait(-500);
48                 System.out.println("HEY: didn't throw on negative arg");
49             } catch (IllegalArgumentException iae) {
50                 System.out.println("Caught expected exception on neg arg");
51             } catch (InterruptedException ie) {
52                 ie.printStackTrace(System.out);
53             }
54 
55             for (long delay : DELAYS) {
56                 System.out.println("Waiting for " + delay + "ms...");
57                 long min = delay - 1;
58                 long max = delay + MAX_SCHED_MILLIS;
59 
60                 int num_failures = 0;
61                 long elapsed_to_report = 0;
62                 boolean showTime = timing;
63                 for (int i = 0; i < (timing ? 1 : NUM_TRIES); ++i) {
64                     final long start = System.nanoTime();
65                     try {
66                         sleepy.wait(delay);
67                     } catch (InterruptedException ie) {
68                         ie.printStackTrace(System.out);
69                     }
70                     final long end = System.nanoTime();
71 
72                     long elapsed = (end - start + NANOS_PER_MILLI / 2) / NANOS_PER_MILLI;
73 
74                     if (timing) {
75                         elapsed_to_report = elapsed;
76                     } else {
77                         if (elapsed < min || elapsed > max) {
78                             ++ num_failures;
79                             elapsed_to_report = elapsed;
80                         } else if (i == 0) {
81                             // Save time if we immediately succeeded.
82                             break;
83                         }
84                     }
85                 }
86                 if (num_failures > MAX_FAILURES) {
87                     System.out.println("Failed " + num_failures + " times out of "
88                             + NUM_TRIES + " tries.");
89                     showTime = true;
90                     if (elapsed_to_report < min) {
91                         // This can legitimately happen due to premature wake-ups.
92                         // This seems rare and unexpected enough in practice that we should
93                         // still report if it occurs repeatedly.
94                         System.out.println("  Elapsed time was too short");
95                     } else if (elapsed_to_report > max) {
96                         System.out.println("  Elapsed time was too long: "
97                              + "elapsed = " + elapsed_to_report + " max = " + max);
98                     }
99                 }
100                 if (showTime) {
101                     System.out.println("  Wall clock elapsed "
102                             + elapsed_to_report + "ms");
103                 }
104             }
105         }
106     }
107 }
108