1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.weblayer.test;
6 
7 import android.app.Activity;
8 import android.content.pm.ActivityInfo;
9 
10 import androidx.fragment.app.Fragment;
11 import androidx.test.filters.SmallTest;
12 
13 import org.hamcrest.Matchers;
14 import org.junit.Assert;
15 import org.junit.Rule;
16 import org.junit.Test;
17 import org.junit.runner.RunWith;
18 
19 import org.chromium.base.test.util.Criteria;
20 import org.chromium.base.test.util.CriteriaHelper;
21 import org.chromium.base.test.util.CriteriaNotSatisfiedException;
22 import org.chromium.content_public.browser.test.util.TestThreadUtils;
23 import org.chromium.weblayer.shell.InstrumentationActivity;
24 
25 import java.lang.ref.PhantomReference;
26 import java.lang.ref.Reference;
27 import java.lang.ref.ReferenceQueue;
28 
29 /**
30  * Basic tests to make sure WebLayer works as expected.
31  */
32 @RunWith(WebLayerJUnit4ClassRunner.class)
33 public class SmokeTest {
34     @Rule
35     public InstrumentationActivityTestRule mActivityTestRule =
36             new InstrumentationActivityTestRule();
37 
38     @Test
39     @SmallTest
testSetSupportEmbedding()40     public void testSetSupportEmbedding() {
41         InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
42 
43         TestThreadUtils.runOnUiThreadBlocking(
44                 () -> { activity.getBrowser().setSupportsEmbedding(true, (result) -> {}); });
45 
46         BoundedCountDownLatch latch = new BoundedCountDownLatch(1);
47         String url = "data:text,foo";
48 
49         TestThreadUtils.runOnUiThreadBlocking(() -> {
50             activity.getBrowser().setSupportsEmbedding(true, (result) -> {
51                 Assert.assertTrue(result);
52                 latch.countDown();
53             });
54         });
55 
56         latch.timedAwait();
57         mActivityTestRule.navigateAndWait(url);
58     }
59 
60     @Test
61     @SmallTest
testActivityShouldNotLeak()62     public void testActivityShouldNotLeak() {
63         ReferenceQueue<InstrumentationActivity> referenceQueue = new ReferenceQueue<>();
64         PhantomReference<InstrumentationActivity> reference;
65         {
66             InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
67             TestThreadUtils.runOnUiThreadBlocking(() -> {
68                 activity.getTab().setFullscreenCallback(new TestFullscreenCallback());
69             });
70             mActivityTestRule.recreateActivity();
71             boolean destroyed =
72                     TestThreadUtils.runOnUiThreadBlockingNoException(() -> activity.isDestroyed());
73             Assert.assertTrue(destroyed);
74 
75             reference = new PhantomReference<>(activity, referenceQueue);
76         }
77 
78         Runtime.getRuntime().gc();
79         CriteriaHelper.pollInstrumentationThread(() -> {
80             Reference enqueuedReference = referenceQueue.poll();
81             if (enqueuedReference == null) {
82                 Runtime.getRuntime().gc();
83                 throw new CriteriaNotSatisfiedException("No enqueued reference");
84             }
85             Criteria.checkThat(reference, Matchers.is(enqueuedReference));
86         });
87     }
88 
89     @Test
90     @SmallTest
testRecreateInstance()91     public void testRecreateInstance() {
92         try {
93             InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
94             TestThreadUtils.runOnUiThreadBlocking(() -> {
95                 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
96             });
97             mActivityTestRule.setRetainInstance(false);
98             Fragment firstFragment = mActivityTestRule.getFragment();
99 
100             mActivityTestRule.recreateByRotatingToLandscape();
101             boolean destroyed =
102                     TestThreadUtils.runOnUiThreadBlockingNoException(() -> activity.isDestroyed());
103             Assert.assertTrue(destroyed);
104 
105             Fragment secondFragment = mActivityTestRule.getFragment();
106             Assert.assertNotSame(firstFragment, secondFragment);
107         } finally {
108             Activity activity = mActivityTestRule.getActivity();
109             TestThreadUtils.runOnUiThreadBlocking(() -> {
110                 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
111             });
112         }
113     }
114 
115     @Test
116     @SmallTest
testSetRetainInstance()117     public void testSetRetainInstance() {
118         ReferenceQueue<InstrumentationActivity> referenceQueue = new ReferenceQueue<>();
119         PhantomReference<InstrumentationActivity> reference;
120         {
121             InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
122 
123             mActivityTestRule.setRetainInstance(true);
124             Fragment firstFragment = mActivityTestRule.getFragment();
125             mActivityTestRule.recreateActivity();
126             Fragment secondFragment = mActivityTestRule.getFragment();
127             Assert.assertEquals(firstFragment, secondFragment);
128 
129             boolean destroyed =
130                     TestThreadUtils.runOnUiThreadBlockingNoException(() -> activity.isDestroyed());
131             Assert.assertTrue(destroyed);
132             reference = new PhantomReference<>(activity, referenceQueue);
133         }
134 
135         CriteriaHelper.pollInstrumentationThread(() -> {
136             Reference enqueuedReference = referenceQueue.poll();
137             if (enqueuedReference == null) {
138                 Runtime.getRuntime().gc();
139                 throw new CriteriaNotSatisfiedException("No enqueued reference");
140             }
141             Criteria.checkThat(reference, Matchers.is(enqueuedReference));
142         });
143     }
144 }
145