1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage tests.api.org.apache.harmony.kernel.dalvik;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.lang.reflect.Field;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport junit.framework.Assert;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport junit.framework.TestCase;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport sun.misc.Unsafe;
248fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumannimport dalvik.annotation.AndroidOnly;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport dalvik.annotation.TestLevel;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport dalvik.annotation.TestTargetClass;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport dalvik.annotation.TestTargetNew;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Tests for the <code>park()</code> functionality of {@link Unsafe}.
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project@TestTargetClass(Unsafe.class)
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class ThreadsTest extends TestCase {
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static Unsafe UNSAFE = null;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static RuntimeException INITIALIZEFAILED = null;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static {
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Set up {@link #UNSAFE}. This subverts the access check to
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * get the unique Unsafe instance. We can do this because
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * there's no security manager installed when running the
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * test.
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Field field = Unsafe.class.getDeclaredField("THE_ONE");
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            field.setAccessible(true);
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            UNSAFE = (Unsafe) field.get(null);
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (NoSuchFieldException ex) {
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            INITIALIZEFAILED = new RuntimeException(ex);
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (IllegalAccessException ex) {
52373e615d325c2bde095360e29dd6341acbf75de9Urs Grob            INITIALIZEFAILED = new RuntimeException(ex);
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the park times out. */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
638fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkFor_1() {
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(false, 500);
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread waiterThread =
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new Thread(new WaitAndUnpark(1000, parkerThread));
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        waiterThread.start();
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(500);
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the unpark happens before the timeout. */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
828fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkFor_2() {
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(false, 1000);
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread waiterThread =
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new Thread(new WaitAndUnpark(300, parkerThread));
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        waiterThread.start();
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(300);
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the thread is preemptively unparked. */
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
1018fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkFor_3() {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(false, 1000);
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        UNSAFE.unpark(parkerThread);
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(0);
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the park times out. */
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
1188fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkUntil_1() {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(true, 500);
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread waiterThread =
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new Thread(new WaitAndUnpark(1000, parkerThread));
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        waiterThread.start();
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(500);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the unpark happens before the timeout. */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
1378fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkUntil_2() {
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(true, 1000);
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread waiterThread =
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            new Thread(new WaitAndUnpark(300, parkerThread));
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        waiterThread.start();
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(300);
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** Test the case where the thread is preemptively unparked. */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @TestTargetNew(
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        level = TestLevel.PARTIAL,
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        notes = "",
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method = "unpark",
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = {Object.class}
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    )
1568fc6b356871b0d750c355bb528afdb93011577e4Jorg Pleumann    @AndroidOnly("Accesses Android-specific private field")
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void test_parkUntil_3() {
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Parker parker = new Parker(true, 1000);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Thread parkerThread = new Thread(parker);
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        UNSAFE.unpark(parkerThread);
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parkerThread.start();
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parker.assertDurationIsInRange(0);
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // TODO: Add more tests.
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper <code>Runnable</code> for tests, which parks for or until
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the indicated value, noting the duration of time actually parked.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class Parker implements Runnable {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** whether {@link #amount} is milliseconds to wait in an
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * absolute fashion (<code>true</code>) or nanoseconds to wait
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * in a relative fashion (<code>false</code>) */
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final boolean absolute;
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** amount to wait (see above) */
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final long amount;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** whether the run has completed */
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private boolean completed;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** recorded start time */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private long startMillis;
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** recorded end time */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private long endMillis;
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Construct an instance.
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param absolute whether to use an absolute time or not; in
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * either case, this constructor takes a duration to park for
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param parkMillis the number of milliseconds to be parked
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Parker(boolean absolute, long parkMillis) {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.absolute = absolute;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Multiply by 1000000 because parkFor() takes nanoseconds.
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.amount = absolute ? parkMillis : parkMillis * 1000000;
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void run() {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean absolute = this.absolute;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long amount = this.amount;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long start = System.currentTimeMillis();
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (absolute) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                UNSAFE.park(true, start + amount);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                UNSAFE.park(false, amount);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long end = System.currentTimeMillis();
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            synchronized (this) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                startMillis = start;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                endMillis = end;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                completed = true;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                notifyAll();
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Wait for the test to complete and return the duration.
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param maxWaitMillis the maximum amount of time to
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * wait for the test to complete
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @return the duration in milliseconds
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public long getDurationMillis(long maxWaitMillis) {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            synchronized (this) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (! completed) {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        wait(maxWaitMillis);
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } catch (InterruptedException ex) {
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        // Ignore it.
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (! completed) {
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        Assert.fail("parker hanging");
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return endMillis - startMillis;
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Asserts that the actual duration is within 5% of the
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * given expected time.
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @param expectedMillis the expected duration, in milliseconds
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void assertDurationIsInRange(long expectedMillis) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Allow a bit more slop for the maximum on "expected
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * instantaneous" results.
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long minimum = (long) ((double) expectedMillis * 0.95);
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long maximum =
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Math.max((long) ((double) expectedMillis * 1.05), 10);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long waitMillis = Math.max(expectedMillis * 10, 10);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long duration = getDurationMillis(waitMillis);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (duration < minimum) {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Assert.fail("expected duration: " + expectedMillis +
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "; actual too short: " + duration);
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (duration > maximum) {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Assert.fail("expected duration: " + expectedMillis +
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "; actual too long: " + duration);
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper <code>Runnable</code> for tests, which waits for the
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * specified amount of time and then unparks an indicated thread.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class WaitAndUnpark implements Runnable {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final long waitMillis;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final Thread thread;
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public WaitAndUnpark(long waitMillis, Thread thread) {
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.waitMillis = waitMillis;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.thread = thread;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void run() {
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Thread.sleep(waitMillis);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (InterruptedException ex) {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException("shouldn't happen", ex);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            UNSAFE.unpark(thread);
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void setUp() throws Exception {
302373e615d325c2bde095360e29dd6341acbf75de9Urs Grob        if (INITIALIZEFAILED != null) {
303373e615d325c2bde095360e29dd6341acbf75de9Urs Grob            throw INITIALIZEFAILED;
304373e615d325c2bde095360e29dd6341acbf75de9Urs Grob        }
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
307