Switch fragment tests to use TestableLooper

Test: runtest systemui
Change-Id: Iccbbaca2ef02cb3f5b08eef66c6c939e4ec2a5eb
This commit is contained in:
Jason Monk
2017-02-02 13:08:31 -05:00
parent efdb428959
commit 28d5d220cc
6 changed files with 99 additions and 58 deletions

View File

@@ -29,6 +29,7 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import com.android.systemui.utils.TestableLooper;
import com.android.systemui.utils.ViewUtils;
import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -59,12 +60,14 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
}
@Before
public void setupFragment() throws IllegalAccessException, InstantiationException {
public void setupFragment() throws Exception {
mView = new FrameLayout(mContext);
mView.setId(VIEW_ID);
mHandler = new Handler(Looper.getMainLooper());
mFragment = mCls.newInstance();
postAndWait(() -> {
TestableLooper.get(this).runWithLooper(() -> {
mHandler = new Handler();
mFragment = mCls.newInstance();
mFragments = FragmentController.createController(new HostCallbacks());
mFragments.attachHost(null);
mFragments.getFragmentManager().beginTransaction()
@@ -73,30 +76,39 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
});
}
private String hex(Looper looper) {
return Integer.toHexString(System.identityHashCode(looper));
}
@After
public void tearDown() {
public void tearDown() throws Exception {
if (mFragments != null) {
// Set mFragments to null to let it know not to destroy.
postAndWait(() -> mFragments.dispatchDestroy());
TestableLooper.get(this).runWithLooper(() -> mFragments.dispatchDestroy());
}
}
@Test
public void testCreateDestroy() {
postAndWait(() -> mFragments.dispatchCreate());
mFragments.dispatchCreate();
processAllMessages();
destroyFragments();
}
@Test
public void testStartStop() {
postAndWait(() -> mFragments.dispatchStart());
postAndWait(() -> mFragments.dispatchStop());
mFragments.dispatchStart();
processAllMessages();
mFragments.dispatchStop();
processAllMessages();
}
@Test
public void testResumePause() {
postAndWait(() -> mFragments.dispatchResume());
postAndWait(() -> mFragments.dispatchPause());
mFragments.dispatchResume();
processAllMessages();
mFragments.dispatchPause();
processAllMessages();
}
@Test
@@ -105,54 +117,57 @@ public abstract class FragmentTestCase extends LeakCheckedTest {
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
LayoutParams.TYPE_SYSTEM_ALERT,
0, PixelFormat.TRANSLUCENT);
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
attachFragmentToWindow();
detachFragmentToWindow();
postAndWait(() -> mFragments.dispatchPause());
}
protected void attachFragmentToWindow() {
ViewUtils.attachView(mView);
}
protected void detachFragmentToWindow() {
ViewUtils.detachView(mView);
mFragments.dispatchPause();
processAllMessages();
}
@Test
public void testRecreate() {
postAndWait(() -> mFragments.dispatchResume());
postAndWait(() -> {
mFragments.dispatchPause();
Parcelable p = mFragments.saveAllState();
mFragments.dispatchDestroy();
mFragments.dispatchResume();
processAllMessages();
mFragments.dispatchPause();
Parcelable p = mFragments.saveAllState();
mFragments.dispatchDestroy();
mFragments = FragmentController.createController(new HostCallbacks());
mFragments.attachHost(null);
mFragments.restoreAllState(p, (FragmentManagerNonConfig) null);
mFragments.dispatchResume();
});
mFragments = FragmentController.createController(new HostCallbacks());
mFragments.attachHost(null);
mFragments.restoreAllState(p, (FragmentManagerNonConfig) null);
mFragments.dispatchResume();
processAllMessages();
}
@Test
public void testMultipleResumes() {
postAndWait(() -> mFragments.dispatchResume());
postAndWait(() -> mFragments.dispatchStop());
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
mFragments.dispatchStop();
processAllMessages();
mFragments.dispatchResume();
processAllMessages();
}
protected void attachFragmentToWindow() {
ViewUtils.attachView(mView);
TestableLooper.get(this).processMessages(1);
}
protected void detachFragmentToWindow() {
ViewUtils.detachView(mView);
TestableLooper.get(this).processMessages(1);
}
protected void destroyFragments() {
postAndWait(() -> mFragments.dispatchDestroy());
mFragments.dispatchDestroy();
processAllMessages();
mFragments = null;
}
protected void postAndWait(Runnable r) {
mHandler.post(r);
waitForFragments();
}
protected void waitForFragments() {
waitForIdleSync(mHandler);
protected void processAllMessages() {
TestableLooper.get(this).processAllMessages();
}
private View findViewById(int id) {

View File

@@ -14,17 +14,23 @@
package com.android.systemui.qs;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import android.os.Looper;
import com.android.systemui.Dependency;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.R;
import com.android.systemui.SysUIRunner;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.LayoutInflaterBuilder;
import com.android.systemui.utils.TestableLooper;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
import org.junit.Before;
import org.junit.Test;
@@ -37,7 +43,8 @@ import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.widget.FrameLayout;
@RunWith(AndroidJUnit4.class)
@RunWith(SysUIRunner.class)
@RunWithLooper(setAsMainLooper = true)
public class QSFragmentTest extends FragmentTestCase {
public QSFragmentTest() {
@@ -53,32 +60,31 @@ public class QSFragmentTest extends FragmentTestCase {
.replace("TextClock", View.class)
.build());
injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper());
injectMockDependency(UserSwitcherController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Test
public void testListening() {
assertEquals(Looper.myLooper(), Looper.getMainLooper());
QSFragment qs = (QSFragment) mFragment;
postAndWait(() -> mFragments.dispatchResume());
QSTileHost host = new QSTileHost(mContext, null,
mock(StatusBarIconController.class));
mFragments.dispatchResume();
processAllMessages();
QSTileHost host = new QSTileHost(mContext, null, mock(StatusBarIconController.class));
qs.setHost(host);
Handler h = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
qs.setListening(true);
waitForIdleSync(h);
processAllMessages();
qs.setListening(false);
waitForIdleSync(h);
processAllMessages();
// Manually push header through detach so it can handle standard cleanup it does on
// removed from window.
((QuickStatusBarHeader) qs.getView().findViewById(R.id.header)).onDetachedFromWindow();
host.destroy();
// Ensure the tuner cleans up its persistent listeners.
Dependency.get(TunerService.class).destroy();
processAllMessages();
}
}

View File

@@ -14,12 +14,18 @@
package com.android.systemui.statusbar;
import com.android.systemui.SysUIRunner;
import com.android.systemui.utils.TestableLooper;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
import com.android.systemui.utils.ViewUtils;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SysUIRunner.class)
@RunWithLooper
public class NotificationMenuRowTest extends LeakCheckedTest {
@Before
@@ -31,6 +37,8 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
public void testAttachDetach() {
NotificationMenuRow row = new NotificationMenuRow(mContext);
ViewUtils.attachView(row);
TestableLooper.get(this).processAllMessages();
ViewUtils.detachView(row);
TestableLooper.get(this).processAllMessages();
}
}

View File

@@ -25,16 +25,21 @@ import android.view.ViewPropertyAnimator;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.R;
import com.android.systemui.SysUIRunner;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.junit.Test;
import org.mockito.Mockito;
@RunWith(SysUIRunner.class)
@RunWithLooper(setAsMainLooper = true)
public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
private NotificationIconAreaController mMockNotificiationAreaController;
@@ -59,7 +64,8 @@ public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
@Test
public void testDisableNone() throws Exception {
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
@@ -71,7 +77,8 @@ public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
@Test
public void testDisableSystemInfo() throws Exception {
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);
@@ -88,7 +95,8 @@ public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
@Test
public void testDisableNotifications() throws Exception {
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
fragment.initNotificationIconArea(mMockNotificiationAreaController);

View File

@@ -24,13 +24,18 @@ import android.view.WindowManager;
import com.android.systemui.Dependency;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.SysUIRunner;
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.utils.TestableLooper.RunWithLooper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SysUIRunner.class)
@RunWithLooper(setAsMainLooper = true)
public class NavigationBarFragmentTest extends FragmentTestCase {
public NavigationBarFragmentTest() {
@@ -56,7 +61,8 @@ public class NavigationBarFragmentTest extends FragmentTestCase {
public void testHomeLongPress() {
NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment;
postAndWait(() -> mFragments.dispatchResume());
mFragments.dispatchResume();
processAllMessages();
navigationBarFragment.onHomeLongClick(navigationBarFragment.getView());
}

View File

@@ -34,13 +34,11 @@ public class ViewUtils {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> InstrumentationRegistry.getContext()
.getSystemService(WindowManager.class).addView(view, lp));
SysuiTestCase.waitForIdleSync(handler);
}
public static void detachView(View view) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(() -> InstrumentationRegistry.getContext()
.getSystemService(WindowManager.class).removeView(view));
SysuiTestCase.waitForIdleSync(handler);
}
}