120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki/*
220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * Copyright (C) 2010 The Android Open Source Project
320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki *
420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
520225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * you may not use this file except in compliance with the License.
620225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * You may obtain a copy of the License at
720225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki *
820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
920225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki *
1020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * Unless required by applicable law or agreed to in writing, software
1120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
1220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * See the License for the specific language governing permissions and
1420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * limitations under the License.
1520225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki */
1620225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki
1720225d57609d6a5e482c088fdad60c29212d31a0Makoto Onukipackage com.android.email;
1820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki
19e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onukiimport android.app.KeyguardManager;
20e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onukiimport android.content.Context;
21e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onukiimport android.os.PowerManager;
22fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onukiimport android.test.MoreAsserts;
2357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onukiimport android.test.suitebuilder.annotation.LargeTest;
247c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onukiimport android.view.View;
257c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onukiimport android.view.ViewParent;
2620225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki
2717d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xieimport com.android.emailcommon.Logging;
2817d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xieimport com.android.mail.utils.LogUtils;
2917d3a29c9d8f7a27c463239f190bdcc4e0804527Jerry Xie
3057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onukiimport junit.framework.AssertionFailedError;
3120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onukiimport junit.framework.TestCase;
3220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki
3320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki/**
3420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki * Utility methods used only by tests.
3520225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki */
3657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki@LargeTest
3720225d57609d6a5e482c088fdad60c29212d31a0Makoto Onukipublic class TestUtils extends TestCase /* It tests itself */ {
3857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    public interface Condition {
3957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        public boolean isMet();
4057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    }
4157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
4220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki    /** Shortcut to create byte array */
4320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki    public static byte[] b(int... array) {
4420225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        if (array == null) {
4520225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki            return null;
4620225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        }
4720225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        byte[] ret = new byte[array.length];
4820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        for (int i = 0; i < ret.length; i++) {
4920225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki            ret[i] = (byte) array[i];
5020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        }
5120225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki        return ret;
5220225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki    }
5320225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki
54fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onuki    public void testB() {
55fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onuki        assertNull(b(null));
56fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onuki        MoreAsserts.assertEquals(new byte[] {}, b());
57fe61f358ab67cac2aa454a6dd3ea6bbf876e343cMakoto Onuki        MoreAsserts.assertEquals(new byte[] {1, 2, (byte) 0xff}, b(1, 2, 0xff));
5820225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki    }
5957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
6057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    /**
6157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki     * Run {@code runnable} and fails if it doesn't throw a {@code expectedThrowable} or a subclass
6257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki     * of it.
6357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki     */
6457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    public static void expectThrowable(Runnable runnable,
6557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            Class<? extends Throwable> expectedThrowable) {
6657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        try {
6757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            runnable.run();
6857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            fail("Expected throwable not thrown.");
6957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        } catch (Throwable th) {
7057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            if (expectedThrowable.isAssignableFrom(th.getClass())) {
7157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                return; // Expcted. OK
7257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
7357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            fail("Cought unexpected throwable " + th.getClass().getName());
7457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }
7557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    }
7657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
7757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    public void testExpectThrowable() {
7857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        try {
7957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            expectThrowable(new Runnable() {
8057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                @Override public void run() {
8157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                    // Throwing no exception
8257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                }
8357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }, Throwable.class);
8457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            fail();
8557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        } catch (AssertionFailedError ok) {
8657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }
8757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
8857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        try {
8957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            expectThrowable(new Runnable() {
9057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                @Override public void run() {
9157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                    // Throw RuntimeException, which is not a subclass of Error.
9257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                    throw new RuntimeException();
9357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                }
9457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }, Error.class);
9557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            fail();
9657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        } catch (AssertionFailedError ok) {
9757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }
9857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
9957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        expectThrowable(new Runnable() {
10057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            @Override public void run() {
10157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                throw new RuntimeException();
10257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
10357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }, Exception.class);
10457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    }
10557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
10657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    /**
10757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki     * Wait until a {@code Condition} is met.
10857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki     */
109206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki    public static void waitUntil(Condition condition, int timeoutSeconds) {
110206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki        waitUntil("", condition, timeoutSeconds);
111206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki    }
112206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki
113206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki    /**
114206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki     * Wait until a {@code Condition} is met.
115206d4e842d287a7a4e6bedf4963fb7f0f58e113fMakoto Onuki     */
11657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    public static void waitUntil(String message, Condition condition, int timeoutSeconds) {
117560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy        LogUtils.d(Logging.LOG_TAG, message + ": Waiting...");
11857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        final long timeout = System.currentTimeMillis() + timeoutSeconds * 1000;
11957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        while (System.currentTimeMillis() < timeout) {
12057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            if (condition.isMet()) {
12157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                return;
12257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
12357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            try {
12457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                Thread.sleep(500);
12557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            } catch (InterruptedException ignore) {
12657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
12757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }
12857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        fail(message + ": Timeout");
12957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    }
13057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
13157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    public void testWaitUntil() {
13257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        // Shouldn't fail.
13357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        waitUntil("message", new Condition() {
13457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            @Override public boolean isMet() {
13557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                return true;
13657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
13757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }, 1000000);
13857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki
13957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        expectThrowable(new Runnable() {
14057f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            @Override public void run() {
14157f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                // Condition never meets, should fail.
14257f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                waitUntil("message", new Condition() {
14357f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                    @Override public boolean isMet() {
14457f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                        return false;
14557f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                    }
14657f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki                }, 0);
14757f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki            }
14857f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki        }, AssertionFailedError.class);
14957f4d0222b0a5647793d7ea14acda055223ea11dMakoto Onuki    }
150e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki
151e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki    /**
152e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki     * @return true if the screen is on and not locked; false otherwise, in which case tests that
153e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki     * send key events will fail.
154e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki     */
155e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki    public static boolean isScreenOnAndNotLocked(Context context) {
156e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
157e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        if (!pm.isScreenOn()) {
158e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki            return false;
159e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        }
160e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
161e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        if (km.inKeyguardRestrictedInputMode()) {
162e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki            return false;
163e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        }
164e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki        return true;
165e9919377ee02958da4f2d2dde3b65c93505b4343Makoto Onuki    }
1667c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki
1677c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki    public static void assertViewVisible(View v) {
1687c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki        if (v == null) {
1697c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            throw new NullPointerException();
1707c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki        }
1717c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki        for (;;) {
1727c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            assertTrue("visibility for " + v, View.VISIBLE == v.getVisibility());
1737c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            ViewParent parent = v.getParent();
1747c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            if (parent == null || !(parent instanceof View)) {
1757c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki                break;
1767c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            }
1777c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki            v = (View) parent;
1787c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki        }
1797c1fa2c16195098453b3f3bd9c44a1f7a058e356Makoto Onuki    }
18020225d57609d6a5e482c088fdad60c29212d31a0Makoto Onuki}
181