diff --git a/tests/src/org/cyanogenmod/tests/themes/unit/ThemeManagerTest.java b/tests/src/org/cyanogenmod/tests/themes/unit/ThemeManagerTest.java index 383a4a2..bae7664 100644 --- a/tests/src/org/cyanogenmod/tests/themes/unit/ThemeManagerTest.java +++ b/tests/src/org/cyanogenmod/tests/themes/unit/ThemeManagerTest.java @@ -26,13 +26,14 @@ import android.test.suitebuilder.annotation.SmallTest; import android.text.TextUtils; import android.util.Log; +import cyanogenmod.providers.CMSettings; +import cyanogenmod.providers.ThemesContract; import cyanogenmod.themes.IThemeService; import cyanogenmod.themes.ThemeChangeRequest; import cyanogenmod.themes.ThemeManager; import cyanogenmod.themes.ThemeManager.ThemeChangeListener; -import cyanogenmod.providers.CMSettings; -import cyanogenmod.providers.ThemesContract; +import org.mockito.Mockito; import java.util.ArrayList; import java.util.HashMap; @@ -43,6 +44,7 @@ import java.util.concurrent.CountDownLatch; public class ThemeManagerTest extends AndroidTestCase { private static final String TAG = ThemeManagerTest.class.getSimpleName(); private static final int COUNTDOWN = 1; + private static final int INVALID_PROGRESS = -1; private ThemeManager mThemeManager; @@ -209,6 +211,77 @@ public class ThemeManagerTest extends AndroidTestCase { mThemeManager.unregisterProcessingListener(dummyThemeProcessingListener); } + @SmallTest + public void testAddAndRemoveClient() { + // Exploit the illegalArgumentException thrown by addClient to verify registration. + mThemeManager.addClient(dummyThemeChangeListener); + + try { + mThemeManager.addClient(dummyThemeChangeListener); + throw new AssertionError("Failed to add client!"); + } catch (IllegalArgumentException e) { + // EXPECTED! + } + + // Inversely, exploit that the illegal argument exception isn't thrown + // if adding and removing + mThemeManager.removeClient(dummyThemeChangeListener); + + try { + mThemeManager.addClient(dummyThemeChangeListener); + } catch (IllegalArgumentException e) { + throw new AssertionError("Failed to remove client!"); + } + + // Cleanup! + mThemeManager.removeClient(dummyThemeChangeListener); + } + + @SmallTest + public void testOnClientPausedResumedAndDestroyed() { + // Exploit the illegalArgumentException thrown by addClient to verify registration. + mThemeManager.addClient(dummyThemeChangeListener); + + try { + mThemeManager.addClient(dummyThemeChangeListener); + throw new AssertionError("Failed to add client!"); + } catch (IllegalArgumentException e) { + // EXPECTED! + } + + // Inversely, exploit that the illegal argument exception isn't thrown + // if pausing and resuming + mThemeManager.onClientPaused(dummyThemeChangeListener); + + try { + mThemeManager.onClientResumed(dummyThemeChangeListener); + } catch (IllegalArgumentException e) { + throw new AssertionError("Failed to pause client!"); + } + + // Once again exploit the illegalArgumentException thrown by onClientResumed to verify + // the previous call to onClientResumed added the client back + try { + mThemeManager.onClientResumed(dummyThemeChangeListener); + throw new AssertionError("Failed to resume client!"); + } catch (IllegalArgumentException e) { + // EXPECTED! + } + + // Inversely, exploit that the illegal argument exception isn't thrown + // if destroying and adding + mThemeManager.onClientDestroyed(dummyThemeChangeListener); + + try { + mThemeManager.addClient(dummyThemeChangeListener); + } catch (IllegalArgumentException e) { + throw new AssertionError("Failed to destroy client!"); + } + + // Cleanup! + mThemeManager.removeClient(dummyThemeChangeListener); + } + boolean actualRequestThemeChangeAsMapResponse = false; @SmallTest public void testRequestThemeChangeAsMapAndCallback() { @@ -234,6 +307,7 @@ public class ThemeManagerTest extends AndroidTestCase { @Override public void onFinish(boolean isSuccess) { actualRequestThemeChangeAsMapResponse = isSuccess; + mThemeManager.unregisterThemeChangeListener(this); signal.countDown(); } }); @@ -270,6 +344,7 @@ public class ThemeManagerTest extends AndroidTestCase { @Override public void onFinish(boolean isSuccess) { actualRequestThemeChangeAsStringListResponse = isSuccess; + mThemeManager.unregisterThemeChangeListener(this); signal.countDown(); } }); @@ -311,6 +386,7 @@ public class ThemeManagerTest extends AndroidTestCase { @Override public void onFinish(boolean isSuccess) { actualRequestThemeChangeAsRequestResponse = isSuccess; + mThemeManager.unregisterThemeChangeListener(this); signal.countDown(); } }); @@ -327,6 +403,181 @@ public class ThemeManagerTest extends AndroidTestCase { assertTrue(actualRequestThemeChangeAsRequestResponse); } + @SmallTest + public void testGetLastThemeChangeRequestType() { + final CountDownLatch signal = new CountDownLatch(COUNTDOWN); + + // Get the default theme package + final String defaultThemePkg = getDefaultThemePackageName(mContext); + + ThemeChangeRequest request = new ThemeChangeRequest.Builder() + .setStatusBar(defaultThemePkg) + .setRequestType(ThemeChangeRequest.RequestType.USER_REQUEST_MIXNMATCH) + .build(); + + mThemeManager.registerThemeChangeListener(new ThemeChangeListener() { + @Override + public void onProgress(int progress) {} + + @Override + public void onFinish(boolean isSuccess) { + mThemeManager.unregisterThemeChangeListener(this); + signal.countDown(); + } + }); + + mThemeManager.requestThemeChange(request, true); + + // Lock + try { + signal.await(); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + + assertEquals(ThemeChangeRequest.RequestType.USER_REQUEST_MIXNMATCH, + mThemeManager.getLastThemeChangeRequestType()); + } + + @SmallTest + public void testGetLastThemeChangeTime() { + final CountDownLatch signal = new CountDownLatch(COUNTDOWN); + + // Get the default theme package + final String defaultThemePkg = getDefaultThemePackageName(mContext); + + ThemeChangeRequest request = new ThemeChangeRequest.Builder() + .setStatusBar(defaultThemePkg) + .setRequestType(ThemeChangeRequest.RequestType.USER_REQUEST_MIXNMATCH) + .build(); + + mThemeManager.registerThemeChangeListener(new ThemeChangeListener() { + @Override + public void onProgress(int progress) {} + + @Override + public void onFinish(boolean isSuccess) { + mThemeManager.unregisterThemeChangeListener(this); + signal.countDown(); + } + }); + + final long preThemeChangeTime = System.currentTimeMillis(); + mThemeManager.requestThemeChange(request, true); + + // Lock + try { + signal.await(); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + + final long postThemeChangeTime = System.currentTimeMillis(); + final long lastThemeChangeTime = mThemeManager.getLastThemeChangeTime(); + // lastThemeChangeTime should be between preThemeChangeTime and postThemeChangeTime + assertTrue(lastThemeChangeTime >= preThemeChangeTime); + assertTrue(lastThemeChangeTime <= postThemeChangeTime); + } + + @SmallTest + public void testIsThemeApplying() { + boolean themeApplying; + final CountDownLatch signal = new CountDownLatch(COUNTDOWN); + + // Get the default theme package + final String defaultThemePkg = getDefaultThemePackageName(mContext); + + ThemeChangeRequest request = new ThemeChangeRequest.Builder() + .setStatusBar(defaultThemePkg) + .setRequestType(ThemeChangeRequest.RequestType.USER_REQUEST_MIXNMATCH) + .build(); + + mThemeManager.registerThemeChangeListener(new ThemeChangeListener() { + @Override + public void onProgress(int progress) { + signal.countDown(); + } + + @Override + public void onFinish(boolean isSuccess) { + mThemeManager.unregisterThemeChangeListener(this); + } + }); + + mThemeManager.requestThemeChange(request, true); + + // Lock + try { + signal.await(); + themeApplying = mThemeManager.isThemeApplying(); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + + assertTrue(themeApplying); + } + + int progress = INVALID_PROGRESS; + @SmallTest + public void testGetProgress() { + final CountDownLatch signal = new CountDownLatch(COUNTDOWN); + + // Get the default theme package + final String defaultThemePkg = getDefaultThemePackageName(mContext); + + ThemeChangeRequest request = new ThemeChangeRequest.Builder() + .setStatusBar(defaultThemePkg) + .setRequestType(ThemeChangeRequest.RequestType.USER_REQUEST_MIXNMATCH) + .build(); + + mThemeManager.registerThemeChangeListener(new ThemeChangeListener() { + @Override + public void onProgress(int p) { + if (progress == INVALID_PROGRESS) progress = mThemeManager.getProgress(); + } + + @Override + public void onFinish(boolean isSuccess) { + mThemeManager.unregisterThemeChangeListener(this); + signal.countDown(); + } + }); + + mThemeManager.requestThemeChange(request, true); + + // Lock + try { + signal.await(); + } catch (InterruptedException e) { + throw new AssertionError(e); + } + + // Verify that progress was updating during the theme change + assertTrue(progress != INVALID_PROGRESS); + + // Verify that getProgress returns 0 now that the theme change has finished + assertEquals(0, mThemeManager.getProgress()); + } + + @SmallTest + public void testThemeProcessing() { + // Get the default theme package + final String defaultThemePkg = getDefaultThemePackageName(mContext); + + ThemeManager mockedThemeManager = Mockito.mock(ThemeManager.class); + + Mockito.doReturn(true) + .when(mockedThemeManager) + .processThemeResources(Mockito.anyString()); + + Mockito.doReturn(true) + .when(mockedThemeManager) + .isThemeBeingProcessed(Mockito.anyString()); + + assertTrue(mockedThemeManager.processThemeResources(defaultThemePkg)); + assertTrue(mockedThemeManager.isThemeBeingProcessed(defaultThemePkg)); + } + private boolean verifyThemeAppliedFromPackageForRow(String packageName, String expectedPackage, boolean systemTheme) { boolean verified = TextUtils.isEmpty(expectedPackage) ||