MockAccessibilityService.java revision 0b29a587142b19ed25dd6489cfa037d06145afd1
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import android.accessibilityservice.AccessibilityService; 20import android.accessibilityservice.AccessibilityServiceInfo; 21import android.os.Message; 22import android.view.accessibility.AccessibilityEvent; 23 24import java.util.Iterator; 25import java.util.LinkedList; 26import java.util.List; 27import java.util.Queue; 28 29import junit.framework.TestCase; 30 31/** 32 * This is the base class for mock {@link AccessibilityService}s. 33 */ 34public abstract class MockAccessibilityService extends AccessibilityService { 35 36 /** 37 * The event this service expects to receive. 38 */ 39 private final Queue<AccessibilityEvent> mExpectedEvents = new LinkedList<AccessibilityEvent>(); 40 41 /** 42 * Interruption call this service expects to receive. 43 */ 44 private boolean mExpectedInterrupt; 45 46 /** 47 * Flag if the mock is currently replaying. 48 */ 49 private boolean mReplaying; 50 51 /** 52 * Creates an {@link AccessibilityServiceInfo} populated with default 53 * values. 54 * 55 * @return The default info. 56 */ 57 public static AccessibilityServiceInfo createDefaultInfo() { 58 AccessibilityServiceInfo defaultInfo = new AccessibilityServiceInfo(); 59 defaultInfo.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED; 60 defaultInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE; 61 defaultInfo.flags = 0; 62 defaultInfo.notificationTimeout = 0; 63 defaultInfo.packageNames = new String[] { 64 "foo.bar.baz" 65 }; 66 67 return defaultInfo; 68 } 69 70 /** 71 * Starts replaying the mock. 72 */ 73 public void replay() { 74 mReplaying = true; 75 } 76 77 /** 78 * Verifies if all expected service methods have been called. 79 */ 80 public void verify() { 81 if (!mReplaying) { 82 throw new IllegalStateException("Did you forget to call replay()"); 83 } 84 85 if (mExpectedInterrupt) { 86 throw new IllegalStateException("Expected call to #interrupt() not received"); 87 } 88 if (!mExpectedEvents.isEmpty()) { 89 throw new IllegalStateException("Expected a call to onAccessibilityEvent() for " 90 + "events \"" + mExpectedEvents + "\" not received"); 91 } 92 } 93 94 /** 95 * Resets this instance so it can be reused. 96 */ 97 public void reset() { 98 mExpectedEvents.clear(); 99 mExpectedInterrupt = false; 100 mReplaying = false; 101 } 102 103 /** 104 * Sets an expected call to 105 * {@link #onAccessibilityEvent(AccessibilityEvent)} with given event as 106 * argument. 107 * 108 * @param expectedEvent The expected event argument. 109 */ 110 public void expectEvent(AccessibilityEvent expectedEvent) { 111 mExpectedEvents.add(expectedEvent); 112 } 113 114 /** 115 * Sets an expected call of {@link #onInterrupt()}. 116 */ 117 public void expectInterrupt() { 118 mExpectedInterrupt = true; 119 } 120 121 @Override 122 public void onAccessibilityEvent(AccessibilityEvent receivedEvent) { 123 if (!mReplaying) { 124 return; 125 } 126 127 if (mExpectedEvents.isEmpty()) { 128 throw new IllegalStateException("Unexpected event: " + receivedEvent); 129 } 130 131 AccessibilityEvent expectedEvent = mExpectedEvents.poll(); 132 assertEqualsAccessiblityEvent(expectedEvent, receivedEvent); 133 } 134 135 @Override 136 public void onInterrupt() { 137 if (!mReplaying) { 138 return; 139 } 140 141 if (!mExpectedInterrupt) { 142 throw new IllegalStateException("Unexpected call to onInterrupt()"); 143 } 144 145 mExpectedInterrupt = false; 146 } 147 148 /** 149 * Compares all properties of the <code>expectedEvent</code> and the 150 * <code>receviedEvent</code> to verify that the received event is the one 151 * that is expected. 152 */ 153 private void assertEqualsAccessiblityEvent(AccessibilityEvent expectedEvent, 154 AccessibilityEvent receivedEvent) { 155 TestCase.assertEquals("addedCount has incorrect value", expectedEvent.getAddedCount(), 156 receivedEvent.getAddedCount()); 157 TestCase.assertEquals("beforeText has incorrect value", expectedEvent.getBeforeText(), 158 receivedEvent.getBeforeText()); 159 TestCase.assertEquals("checked has incorrect value", expectedEvent.isChecked(), 160 receivedEvent.isChecked()); 161 TestCase.assertEquals("className has incorrect value", expectedEvent.getClassName(), 162 receivedEvent.getClassName()); 163 TestCase.assertEquals("contentDescription has incorrect value", expectedEvent 164 .getContentDescription(), receivedEvent.getContentDescription()); 165 TestCase.assertEquals("currentItemIndex has incorrect value", expectedEvent 166 .getCurrentItemIndex(), receivedEvent.getCurrentItemIndex()); 167 TestCase.assertEquals("enabled has incorrect value", expectedEvent.isEnabled(), 168 receivedEvent.isEnabled()); 169 TestCase.assertEquals("eventType has incorrect value", expectedEvent.getEventType(), 170 receivedEvent.getEventType()); 171 TestCase.assertEquals("fromIndex has incorrect value", expectedEvent.getFromIndex(), 172 receivedEvent.getFromIndex()); 173 TestCase.assertEquals("fullScreen has incorrect value", expectedEvent.isFullScreen(), 174 receivedEvent.isFullScreen()); 175 TestCase.assertEquals("itemCount has incorrect value", expectedEvent.getItemCount(), 176 receivedEvent.getItemCount()); 177 assertEqualsNotificationAsParcelableData(expectedEvent, receivedEvent); 178 TestCase.assertEquals("password has incorrect value", expectedEvent.isPassword(), 179 receivedEvent.isPassword()); 180 TestCase.assertEquals("removedCount has incorrect value", expectedEvent.getRemovedCount(), 181 receivedEvent.getRemovedCount()); 182 assertEqualsText(expectedEvent, receivedEvent); 183 } 184 185 /** 186 * Compares the {@link android.os.Parcelable} data of the 187 * <code>expectedEvent</code> and <code>receivedEvent</code> to verify that 188 * the received event is the one that is expected. 189 */ 190 private void assertEqualsNotificationAsParcelableData(AccessibilityEvent expectedEvent, 191 AccessibilityEvent receivedEvent) { 192 String message = "parcelableData has incorrect value"; 193 Message expectedMessage = (Message) expectedEvent.getParcelableData(); 194 Message receivedMessage = (Message) receivedEvent.getParcelableData(); 195 196 if (expectedMessage == null) { 197 if (receivedMessage == null) { 198 return; 199 } 200 } 201 202 TestCase.assertNotNull(message, receivedMessage); 203 204 // we do a very simple sanity check since we do not test Message 205 TestCase.assertEquals(message, expectedMessage.what, receivedMessage.what); 206 } 207 208 /** 209 * Compares the text of the <code>expectedEvent</code> and 210 * <code>receivedEvent</code> by comparing the string representation of the 211 * corresponding {@link CharSequence}s. 212 */ 213 private void assertEqualsText(AccessibilityEvent expectedEvent, 214 AccessibilityEvent receivedEvent) { 215 String message = "text has incorrect value"; 216 List<CharSequence> expectedText = expectedEvent.getText(); 217 List<CharSequence> receivedText = receivedEvent.getText(); 218 219 TestCase.assertEquals(message, expectedText.size(), receivedText.size()); 220 221 Iterator<CharSequence> expectedTextIterator = expectedText.iterator(); 222 Iterator<CharSequence> receivedTextIterator = receivedText.iterator(); 223 224 for (int i = 0; i < expectedText.size(); i++) { 225 // compare the string representation 226 TestCase.assertEquals(message, expectedTextIterator.next().toString(), 227 receivedTextIterator.next().toString()); 228 } 229 } 230} 231