TestUtils.java revision b86bef286718da421268bc52cf4fab7cccb3104c
1b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets/*
264db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyar * Copyright (C) 2017 The Android Open Source Project
3b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
4b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * Licensed under the Apache License, Version 2.0 (the "License");
5b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * you may not use this file except in compliance with the License.
6b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * You may obtain a copy of the License at
7b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
8b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *      http://www.apache.org/licenses/LICENSE-2.0
9b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets *
10b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * Unless required by applicable law or agreed to in writing, software
11b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * distributed under the License is distributed on an "AS IS" BASIS,
12b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * See the License for the specific language governing permissions and
14b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets * limitations under the License.
15b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets */
16b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
1764db0cc15b78b62a1d44a70fc8b4552e660d952cYigit Boyarpackage android.arch.lifecycle;
18b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
191f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinetsimport android.app.Activity;
20b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.app.Instrumentation;
21b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.app.Instrumentation.ActivityMonitor;
22b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetsimport android.support.test.InstrumentationRegistry;
23450ed382339544eaf6b7886bc765522fc3446148Yigit Boyarimport android.support.test.rule.ActivityTestRule;
24b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
258524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinetsimport java.util.concurrent.CountDownLatch;
268524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
27b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinetspublic class TestUtils {
28b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
29b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets    private static final long TIMEOUT_MS = 2000;
30b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets
311f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets    @SuppressWarnings("unchecked")
32450ed382339544eaf6b7886bc765522fc3446148Yigit Boyar    public static <T extends Activity> T recreateActivity(final T activity, ActivityTestRule rule)
33b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets            throws Throwable {
34b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        ActivityMonitor monitor = new ActivityMonitor(
351f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets                activity.getClass().getCanonicalName(), null, false);
36b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
37b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        instrumentation.addMonitor(monitor);
381f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        rule.runOnUiThread(activity::recreate);
391f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        T result;
40ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets
41ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        // this guarantee that we will reinstall monitor between notifications about onDestroy
42ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        // and onCreate
431f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets        //noinspection SynchronizationOnLocalVariableOrMethodParameter
44ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets        synchronized (monitor) {
45ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets            do {
46ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // the documetation says "Block until an Activity is created
47ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // that matches this monitor." This statement is true, but there are some other
48ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // true statements like: "Block until an Activity is destoyed" or
49ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // "Block until an Activity is resumed"...
50ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets
51ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                // this call will release synchronization monitor's monitor
521f52c94781fdc0d8aefbaa697bb8b52e18badcd5Sergey Vasilinets                result = (T) monitor.waitForActivityWithTimeout(TIMEOUT_MS);
53ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                if (result == null) {
54ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                    throw new RuntimeException("Timeout. Failed to recreate an activity");
55ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets                }
56ede4592947eadcab982f71b186dd9debd52e84ccSergey Vasilinets            } while (result == activity);
57b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        }
58b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets        return result;
59b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets    }
608524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
618524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets    static void waitTillResumed(final LifecycleActivity a, ActivityTestRule<?> activityRule)
628524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            throws Throwable {
638524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        final CountDownLatch latch = new CountDownLatch(1);
648524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        activityRule.runOnUiThread(() -> {
658524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            int currentState = a.getLifecycle().getCurrentState();
668524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            if (currentState == Lifecycle.RESUMED) {
678524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                latch.countDown();
688524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            }
698524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            a.getLifecycle().addObserver(new LifecycleObserver() {
70b86bef286718da421268bc52cf4fab7cccb3104cSergey Vasilinets                @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
71e13540a25fe5460240b6db0e18858c32d16f5399Sergey Vasilinets                public void onStateChanged(LifecycleOwner provider) {
728524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                    latch.countDown();
738524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                    provider.getLifecycle().removeObserver(this);
748524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets                }
758524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets            });
768524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        });
778524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets        latch.await();
788524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets    }
798524c13c97e2c80d270b03f97f8eac5fbd585c5aSergey Vasilinets
80b085e34beddf631062d0e2503911ef4a33152c06Sergey Vasilinets}
81