aboutsummaryrefslogtreecommitdiffstats
path: root/tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java')
-rw-r--r--tests/src/org/cyanogenmod/tests/settings/unit/CMPartnerInterfaceTest.java317
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);
+ }
+ }
+ }
+}
+