1/*
2 * Copyright (C) 2010 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
17package com.android.email;
18
19import com.android.emailcommon.Logging;
20
21import android.app.KeyguardManager;
22import android.content.Context;
23import android.os.PowerManager;
24import android.test.MoreAsserts;
25import android.test.suitebuilder.annotation.LargeTest;
26import android.util.Log;
27import android.view.View;
28import android.view.ViewParent;
29
30import junit.framework.AssertionFailedError;
31import junit.framework.TestCase;
32
33/**
34 * Utility methods used only by tests.
35 */
36@LargeTest
37public class TestUtils extends TestCase /* It tests itself */ {
38    public interface Condition {
39        public boolean isMet();
40    }
41
42    /** Shortcut to create byte array */
43    public static byte[] b(int... array) {
44        if (array == null) {
45            return null;
46        }
47        byte[] ret = new byte[array.length];
48        for (int i = 0; i < ret.length; i++) {
49            ret[i] = (byte) array[i];
50        }
51        return ret;
52    }
53
54    public void testB() {
55        assertNull(b(null));
56        MoreAsserts.assertEquals(new byte[] {}, b());
57        MoreAsserts.assertEquals(new byte[] {1, 2, (byte) 0xff}, b(1, 2, 0xff));
58    }
59
60    /**
61     * Run {@code runnable} and fails if it doesn't throw a {@code expectedThrowable} or a subclass
62     * of it.
63     */
64    public static void expectThrowable(Runnable runnable,
65            Class<? extends Throwable> expectedThrowable) {
66        try {
67            runnable.run();
68            fail("Expected throwable not thrown.");
69        } catch (Throwable th) {
70            if (expectedThrowable.isAssignableFrom(th.getClass())) {
71                return; // Expcted. OK
72            }
73            fail("Cought unexpected throwable " + th.getClass().getName());
74        }
75    }
76
77    public void testExpectThrowable() {
78        try {
79            expectThrowable(new Runnable() {
80                @Override public void run() {
81                    // Throwing no exception
82                }
83            }, Throwable.class);
84            fail();
85        } catch (AssertionFailedError ok) {
86        }
87
88        try {
89            expectThrowable(new Runnable() {
90                @Override public void run() {
91                    // Throw RuntimeException, which is not a subclass of Error.
92                    throw new RuntimeException();
93                }
94            }, Error.class);
95            fail();
96        } catch (AssertionFailedError ok) {
97        }
98
99        expectThrowable(new Runnable() {
100            @Override public void run() {
101                throw new RuntimeException();
102            }
103        }, Exception.class);
104    }
105
106    /**
107     * Wait until a {@code Condition} is met.
108     */
109    public static void waitUntil(Condition condition, int timeoutSeconds) {
110        waitUntil("", condition, timeoutSeconds);
111    }
112
113    /**
114     * Wait until a {@code Condition} is met.
115     */
116    public static void waitUntil(String message, Condition condition, int timeoutSeconds) {
117        Log.d(Logging.LOG_TAG, message + ": Waiting...");
118        final long timeout = System.currentTimeMillis() + timeoutSeconds * 1000;
119        while (System.currentTimeMillis() < timeout) {
120            if (condition.isMet()) {
121                return;
122            }
123            try {
124                Thread.sleep(500);
125            } catch (InterruptedException ignore) {
126            }
127        }
128        fail(message + ": Timeout");
129    }
130
131    public void testWaitUntil() {
132        // Shouldn't fail.
133        waitUntil("message", new Condition() {
134            @Override public boolean isMet() {
135                return true;
136            }
137        }, 1000000);
138
139        expectThrowable(new Runnable() {
140            @Override public void run() {
141                // Condition never meets, should fail.
142                waitUntil("message", new Condition() {
143                    @Override public boolean isMet() {
144                        return false;
145                    }
146                }, 0);
147            }
148        }, AssertionFailedError.class);
149    }
150
151    /**
152     * @return true if the screen is on and not locked; false otherwise, in which case tests that
153     * send key events will fail.
154     */
155    public static boolean isScreenOnAndNotLocked(Context context) {
156        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
157        if (!pm.isScreenOn()) {
158            return false;
159        }
160        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
161        if (km.inKeyguardRestrictedInputMode()) {
162            return false;
163        }
164        return true;
165    }
166
167    public static void assertViewVisible(View v) {
168        if (v == null) {
169            throw new NullPointerException();
170        }
171        for (;;) {
172            assertTrue("visibility for " + v, View.VISIBLE == v.getVisibility());
173            ViewParent parent = v.getParent();
174            if (parent == null || !(parent instanceof View)) {
175                break;
176            }
177            v = (View) parent;
178        }
179    }
180}
181