diff options
Diffstat (limited to 'tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java')
-rw-r--r-- | tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java b/tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java new file mode 100644 index 0000000..cc2d016 --- /dev/null +++ b/tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java @@ -0,0 +1,317 @@ +/** + * Copyright (c) 2015, The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.cyanogenmod.tests.settings.unit; + +import android.app.INotificationManager; +import android.content.Context; +import android.net.Uri; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.service.notification.Condition; +import android.service.notification.IConditionListener; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.provider.Settings; +import android.text.format.DateUtils; +import android.util.Log; +import cyanogenmod.app.PartnerInterface; + +import java.util.List; + +/** + * Unit test for PartnerInterface + */ +public class CMPartnerInterfaceTest extends AndroidTestCase { + + private static final String TAG = "CMPartnerInterfaceTest"; + + private PartnerInterface mPartnerInterface; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mPartnerInterface = PartnerInterface.getInstance(getContext()); + + setupAirplaneModeTests(); + setupZenModeTests(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + teardownAirplaneModeTests(); + teardownZenModeTests(); + } + + @SmallTest + public void testPartnerInterfaceExists() { + assertNotNull(mPartnerInterface); + } + + @SmallTest + public void testPartnerInterfaceAvailable() { + assertNotNull(mPartnerInterface.getService()); + } + + ///////////////////////////////////////////////////// + // Airplane Mode tests + + private boolean mAirplaneModeEnabled; + private void setupAirplaneModeTests() { + // Remember the initial state + mAirplaneModeEnabled = getAirplaneModeEnabled(); + } + + private void teardownAirplaneModeTests() { + // Restore airplane mode + mPartnerInterface.setAirplaneModeEnabled(mAirplaneModeEnabled); + } + @SmallTest + public void testSetAirplaneModeOn() { + mPartnerInterface.setAirplaneModeEnabled(true); + assertTrue(getAirplaneModeEnabled()); + } + + @SmallTest + public void testSetAirplaneModeOff() { + mPartnerInterface.setAirplaneModeEnabled(false); + assertTrue(getAirplaneModeEnabled() == false); + } + + private boolean getAirplaneModeEnabled() { + return Settings.System.getInt(getContext().getContentResolver(), + Settings.System.AIRPLANE_MODE_ON, 0) == 1; + } + + ///////////////////////////////////////////////////// + // Zen Mode Testing: + // Allow the tests below for now, but in the future + // implement a valid method for restoring the zen mode + // setting, e.g. in tearDownZenModeTests + + // Because it's not possible to get & restore zen mode + // duration, these tests will contaminate system state + // whenver they're run. Ideally testing should instead + // be done in another suite, such as using Mokito + // https://corner.squareup.com/2012/10/mockito-android.html + // + // However because of the complexity, for now allow + // these unit tests as-is. + // + // THESE WILL WIPE OUT any duration-based zen modes in + // effect! + private static final long DURATION_30s_MS = 30 * DateUtils.SECOND_IN_MILLIS; + private static final long DURATION_TOLERANCE_MS = 5; //5 ms in tolerance due to latency + private static final long DURATION_TEST_MAX_MS = DateUtils.MINUTE_IN_MILLIS; //Allow 1 minute max for unit testing + + private INotificationManager mNotificationManager; + private CountdownConditionListener mConditionListener; + + private void setupZenModeTests() { + mNotificationManager = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + + mConditionListener = new CountdownConditionListener(); + try { + mNotificationManager.requestZenModeConditions(mConditionListener, Condition.FLAG_RELEVANT_ALWAYS); + } catch (RemoteException e) { + fail("requestZenModeConditions exception " + e); + } + } + + private void teardownZenModeTests() { + // For now, restore the zen mode to the system default + mPartnerInterface.setZenMode(PartnerInterface.ZEN_MODE_OFF); + } + + @SmallTest + public void testSetZenModeImportantInterruptions() { + mPartnerInterface.setZenMode(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + assertEquals(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, getZenMode()); + } + + @SmallTest + public void testSetZenModeImportantInterruptionsWithDurations() { + // 0 duration + testZenModeWithDuration(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, 0); + + // Indefinitely + testZenModeWithDuration(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, Long.MAX_VALUE); + testZenModeWithDuration(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, -1); + + // normal duration values (1, 5s) + // NOTE: these tests do not return until duration has passed. Use with care! + testZenModeWithDuration(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, DateUtils.SECOND_IN_MILLIS); + testZenModeWithDuration(PartnerInterface.ZEN_MODE_IMPORTANT_INTERRUPTIONS, 5 * DateUtils.SECOND_IN_MILLIS); + } + + @SmallTest + public void testSetZenModeNoInterruptions() { + mPartnerInterface.setZenMode(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS); + assertEquals(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, getZenMode()); + } + + @SmallTest + public void testSetZenModeNoInterruptionsWithDurations() { + // 0 duration + testZenModeWithDuration(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, 0); + + // Indefinitely + testZenModeWithDuration(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, Long.MAX_VALUE); + testZenModeWithDuration(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, -1); + + // normal duration values (1, 5s) + // NOTE: these tests do not return until duration has passed. Use with care! + testZenModeWithDuration(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, DateUtils.SECOND_IN_MILLIS); + testZenModeWithDuration(PartnerInterface.ZEN_MODE_NO_INTERRUPTIONS, 5 * DateUtils.SECOND_IN_MILLIS); + } + + @SmallTest + public void testSetZenModeOff() { + mPartnerInterface.setZenMode(PartnerInterface.ZEN_MODE_OFF); + assertEquals(PartnerInterface.ZEN_MODE_OFF, getZenMode()); + } + + /** + * testZenModeWithDuration: sets Zen Mode with duration and blocks + * until the duration is verified. Use with care! This does not + * return until after durationMillis + * @param mode + * @param durationMillis + */ + private void testZenModeWithDuration(int mode, long durationMillis) { + + final long startTimeMillis = System.currentTimeMillis(); + mPartnerInterface.setZenModeWithDuration(mode, durationMillis); + final int actualZenMode = getZenMode(); + + // check zen mode is correct + if (durationMillis == 0) { + assertTrue(actualZenMode == mode || actualZenMode == PartnerInterface.ZEN_MODE_OFF); + } else { + assertEquals(mode, actualZenMode); + } + // skip durations that are indefinite + if (actualZenMode == PartnerInterface.ZEN_MODE_OFF || durationMillis < 0 || durationMillis == Long.MAX_VALUE) { + return; + } + // check duration is correct + final long zenDuration = getZenModeDuration(startTimeMillis); + assertTrue(Math.abs(zenDuration - durationMillis) <= DURATION_TOLERANCE_MS); //Allow a tolerance + } + + /** + * getZenModeDuration: Blocking call to wait for ZenMode duration. + * @param startTimeMillis - start time of the duration + * @return + */ + private long getZenModeDuration(long startTimeMillis) { + // NOTE: waits for the next duration to be triggered + return mConditionListener.waitForDuration(startTimeMillis); + } + + private int getZenMode() { + int zenMode = -1; + try { + zenMode = mNotificationManager.getZenMode(); + } catch (RemoteException rex) { + fail("INotificationManager.getZenMode() " + rex.getMessage()); + return -1; + } + Log.d(TAG, "getZenMode returning " + zenMode); + return zenMode; + } + /** + * CountdownConditionListener + * This class is passed to blocks until the Countdown is received + */ + private static class CountdownConditionListener + extends IConditionListener.Stub { + + private static long INVALID_ENDTIME = -1; + private long mEndTime = INVALID_ENDTIME; + + public CountdownConditionListener() { + } + + /** + * waitForDuration: blocks until onConditionReceived + * This CountdownConditionListener was previously passed + * to the + * @return + * the duration of + */ + public synchronized long waitForDuration(long startTimeMillis) { + Log.d(TAG, "waitForDuration"); + // If we have a stale endtime, then discard it + if (mEndTime < startTimeMillis) { + mEndTime = INVALID_ENDTIME; + } + // If no valid endtime, then block and wait for the current + // duration to expire. The wait ends when + // onConditionsReceived is called + if (mEndTime == INVALID_ENDTIME) { + try { + // wait no more than DURATION_TEST_MAX_MS + wait(DURATION_TEST_MAX_MS); + } catch (InterruptedException iex) { + Log.e(TAG, "waitForDuration", iex); + + return -1; + } + } + if (mEndTime == INVALID_ENDTIME) { + Log.d(TAG, "waitForDuration found invalid endtime. Did you exceed the max duration (" + DURATION_TEST_MAX_MS + " ms)?"); + return -1; + } + + Log.d(TAG, "waitForDuration returning endtime:" + mEndTime + " duration:" + (mEndTime - startTimeMillis)); + final long duration = mEndTime - startTimeMillis; + + // Reset endtime to show that it's been consumed + mEndTime = INVALID_ENDTIME; + return duration; + } + + /** + * onConditionReceived: called when a condition is triggered + * @param conditions - conditions that triggered + * This is actually just the Alarm endtime that CountdownConditionProvider + * previously submitted + * @throws RemoteException + */ + @Override + public synchronized void onConditionsReceived(Condition[] conditions) throws RemoteException { + // CountdownConditionProvider only triggers 1 condition at a time + mEndTime = parseEndTime(conditions[0].id); + notify(); + } + + private long parseEndTime(Uri conditionUri) { + final List<String> pathSegments = conditionUri.getPathSegments(); + return Long.decode(pathSegments.get(pathSegments.size() - 1)); + } + + // Private method for debugging + private void logConditions(Condition[] conditions) { + for (int i = 0; i < conditions.length; i++) { + Log.d(TAG, "condition[" + i + "]:" + conditions[i].id); + } + } + } +} + |