1/*
2 * Copyright (C) 2016 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 android.support.transition;
18
19import static org.hamcrest.CoreMatchers.is;
20import static org.hamcrest.CoreMatchers.notNullValue;
21import static org.hamcrest.MatcherAssert.assertThat;
22import static org.hamcrest.Matchers.sameInstance;
23
24import android.support.test.InstrumentationRegistry;
25import android.support.test.annotation.UiThreadTest;
26import android.support.transition.test.R;
27import android.test.suitebuilder.annotation.MediumTest;
28import android.view.ViewGroup;
29
30import org.junit.Before;
31import org.junit.Test;
32
33import java.util.concurrent.CountDownLatch;
34import java.util.concurrent.TimeUnit;
35
36@MediumTest
37public class TransitionManagerTest extends BaseTest {
38
39    private Scene[] mScenes = new Scene[2];
40
41    @Before
42    public void prepareScenes() {
43        TransitionActivity activity = rule.getActivity();
44        ViewGroup root = activity.getRoot();
45        mScenes[0] = Scene.getSceneForLayout(root, R.layout.scene0, activity);
46        mScenes[1] = Scene.getSceneForLayout(root, R.layout.scene1, activity);
47    }
48
49    @Test
50    public void testSetup() {
51        assertThat(mScenes[0], is(notNullValue()));
52        assertThat(mScenes[1], is(notNullValue()));
53    }
54
55    @Test
56    @UiThreadTest
57    public void testGo_enterAction() {
58        CheckCalledRunnable runnable = new CheckCalledRunnable();
59        mScenes[0].setEnterAction(runnable);
60        assertThat(runnable.wasCalled(), is(false));
61        TransitionManager.go(mScenes[0]);
62        assertThat(runnable.wasCalled(), is(true));
63    }
64
65    @Test
66    public void testGo_exitAction() {
67        final CheckCalledRunnable enter = new CheckCalledRunnable();
68        final CheckCalledRunnable exit = new CheckCalledRunnable();
69        mScenes[0].setEnterAction(enter);
70        mScenes[0].setExitAction(exit);
71        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
72            @Override
73            public void run() {
74                assertThat(enter.wasCalled(), is(false));
75                assertThat(exit.wasCalled(), is(false));
76                TransitionManager.go(mScenes[0]);
77                assertThat(enter.wasCalled(), is(true));
78                assertThat(exit.wasCalled(), is(false));
79            }
80        });
81        // Let the main thread catch up with the scene change
82        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
83            @Override
84            public void run() {
85                TransitionManager.go(mScenes[1]);
86                assertThat(exit.wasCalled(), is(true));
87            }
88        });
89    }
90
91    @Test
92    public void testGo_transitionListenerStart() {
93        final SyncTransitionListener listener
94                = new SyncTransitionListener(SyncTransitionListener.EVENT_START);
95        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
96            @Override
97            public void run() {
98                Transition transition = new AutoTransition();
99                transition.setDuration(0);
100                assertThat(transition.addListener(listener), is(sameInstance(transition)));
101                TransitionManager.go(mScenes[0], transition);
102            }
103        });
104        assertThat("Timed out waiting for the TransitionListener",
105                listener.await(), is(true));
106    }
107
108    @Test
109    public void testGo_transitionListenerEnd() {
110        final SyncTransitionListener listener
111                = new SyncTransitionListener(SyncTransitionListener.EVENT_END);
112        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
113            @Override
114            public void run() {
115                Transition transition = new AutoTransition();
116                transition.setDuration(0);
117                assertThat(transition.addListener(listener), is(sameInstance(transition)));
118                TransitionManager.go(mScenes[0], transition);
119            }
120        });
121        assertThat("Timed out waiting for the TransitionListener",
122                listener.await(), is(true));
123    }
124
125    /**
126     * This {@link Transition.TransitionListener} synchronously waits for the specified callback.
127     */
128    private static class SyncTransitionListener implements Transition.TransitionListener {
129
130        static final int EVENT_START = 1;
131        static final int EVENT_END = 2;
132        static final int EVENT_CANCEL = 3;
133        static final int EVENT_PAUSE = 4;
134        static final int EVENT_RESUME = 5;
135
136        private final int mTargetEvent;
137        private final CountDownLatch mLatch = new CountDownLatch(1);
138
139        SyncTransitionListener(int event) {
140            mTargetEvent = event;
141        }
142
143        boolean await() {
144            try {
145                return mLatch.await(3000, TimeUnit.MILLISECONDS);
146            } catch (InterruptedException e) {
147                return false;
148            }
149        }
150
151        @Override
152        public void onTransitionStart(Transition transition) {
153            if (mTargetEvent == EVENT_START) {
154                mLatch.countDown();
155            }
156        }
157
158        @Override
159        public void onTransitionEnd(Transition transition) {
160            if (mTargetEvent == EVENT_END) {
161                mLatch.countDown();
162            }
163        }
164
165        @Override
166        public void onTransitionCancel(Transition transition) {
167            if (mTargetEvent == EVENT_CANCEL) {
168                mLatch.countDown();
169            }
170        }
171
172        @Override
173        public void onTransitionPause(Transition transition) {
174            if (mTargetEvent == EVENT_PAUSE) {
175                mLatch.countDown();
176            }
177        }
178
179        @Override
180        public void onTransitionResume(Transition transition) {
181            if (mTargetEvent == EVENT_RESUME) {
182                mLatch.countDown();
183            }
184        }
185    }
186
187}
188