1990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson/*
2990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * Copyright (C) 2007 The Android Open Source Project
3990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson *
4990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * you may not use this file except in compliance with the License.
6990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * You may obtain a copy of the License at
7990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson *
8990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson *
10990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * Unless required by applicable law or agreed to in writing, software
11990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * See the License for the specific language governing permissions and
14990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson * limitations under the License.
15990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson */
16990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
17990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilsonpackage libcore.java.lang;
18990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
19990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilsonimport junit.framework.TestCase;
20990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
219ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamathimport java.util.concurrent.CountDownLatch;
229ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath
23990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilsonpublic class OldAndroidMonitorTest extends TestCase {
24990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
25990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson    public void testWaitArgumentsTest() throws Exception {
26990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            /* Try some valid arguments.  These should all
27990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson             * return very quickly.
28990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson             */
29990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            try {
30990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                synchronized (this) {
31990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    /* millisecond version */
32990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(1);
33990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(10);
34990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
35990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    /* millisecond + nanosecond version */
36990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(0, 1);
37990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(0, 999999);
38990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(1, 1);
39990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(1, 999999);
40990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                }
41990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (InterruptedException ex) {
42990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("good Object.wait() interrupted",
43990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        ex);
44990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (Exception ex) {
45990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("Unexpected exception when calling" +
46990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "Object.wait() with good arguments", ex);
47990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
48990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
49990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            /* Try some invalid arguments.
50990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson             */
51990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            boolean sawException = false;
52990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            try {
53990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                synchronized (this) {
54990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(-1);
55990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                }
56990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (InterruptedException ex) {
57990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad Object.wait() interrupted", ex);
58990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (IllegalArgumentException ex) {
59990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                sawException = true;
60990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (Exception ex) {
61990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("Unexpected exception when calling" +
62990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "Object.wait() with bad arguments", ex);
63990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
64990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            if (!sawException) {
65990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad call to Object.wait() should " +
66990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "have thrown IllegalArgumentException");
67990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
68990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
69990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            sawException = false;
70990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            try {
71990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                synchronized (this) {
72990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(0, -1);
73990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                }
74990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (InterruptedException ex) {
75990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad Object.wait() interrupted", ex);
76990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (IllegalArgumentException ex) {
77990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                sawException = true;
78990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (Exception ex) {
79990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("Unexpected exception when calling" +
80990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "Object.wait() with bad arguments", ex);
81990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
82990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            if (!sawException) {
83990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad call to Object.wait() should " +
84990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "have thrown IllegalArgumentException");
85990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
86990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
87990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            sawException = false;
88990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            try {
89990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                synchronized (this) {
90990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    /* The legal range of nanos is 0-999999. */
91990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    wait(0, 1000000);
92990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                }
93990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (InterruptedException ex) {
94990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad Object.wait() interrupted", ex);
95990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (IllegalArgumentException ex) {
96990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                sawException = true;
97990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            } catch (Exception ex) {
98990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("Unexpected exception when calling" +
99990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "Object.wait() with bad arguments", ex);
100990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
101990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            if (!sawException) {
102990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                throw new RuntimeException("bad call to Object.wait() should " +
103990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                        "have thrown IllegalArgumentException");
104990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
105990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson    }
106990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1079ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath    /**
1089ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath     * A thread that blocks forever on {@code wait()} until it's interrupted.
1099ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath     */
1109ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath    static class Waiter extends Thread {
1119ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        private final Object lock;
1129ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        private final CountDownLatch cdl;
1139ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        private boolean wasInterrupted;
1149ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath
1159ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        public Waiter(Object lock, CountDownLatch cdl) {
1169ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            this.lock = lock;
1179ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            this.cdl = cdl;
1189ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            wasInterrupted = false;
1199ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        }
120990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1219ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        @Override
1229ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        public void run() {
1239ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            synchronized (lock) {
124990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                try {
1259ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath                    cdl.countDown();
1269ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath                    while (true) {
1279ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath                        lock.wait();
128990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                    }
129990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                } catch (InterruptedException ex) {
1309ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath                    wasInterrupted = true;
131990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson                }
132990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
133990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson        }
134990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1359ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        public boolean wasInterrupted() {
1369ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            synchronized (lock) {
1379ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath                return wasInterrupted;
138990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson            }
139990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson        }
1409ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath    }
141990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1429ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath    public void testInterrupt() throws Exception {
1439ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        final Object lock = new Object();
1449ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        final CountDownLatch cdl = new CountDownLatch(1);
1459ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        final Waiter waiter = new Waiter(lock, cdl);
146990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1479ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        waiter.start();
148990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1499ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        // Wait for the "waiter" to start and acquire |lock| for the first time.
1509ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        try {
1519ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            cdl.await();
1529ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        } catch (InterruptedException ie) {
1539ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            fail();
1549ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        }
155990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1569ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        // Interrupt |waiter| after we acquire |lock|. This ensures that |waiter| is
1579ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        // currently blocked on a call to "wait".
1589ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        synchronized (lock) {
1599ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            waiter.interrupt();
1609ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        }
161990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1629ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        // Wait for the waiter to complete.
1639ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        try {
1649ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            waiter.join();
1659ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        } catch (InterruptedException ie) {
1669ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath            fail();
1679ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        }
168990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson
1699ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        // Assert than an InterruptedException was thrown.
1709ec2565efafc8aa11b118e011a7492d75eb6f28bNarayan Kamath        assertTrue(waiter.wasInterrupted());
171990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson    }
172990640f1775dc6f429a5f8b9fc6cab6b4220c03aJesse Wilson}
173