Home | History | Annotate | Download | only in server
      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 
     17 package com.android.server;
     18 
     19 import android.accessibilityservice.AccessibilityService;
     20 import android.accessibilityservice.AccessibilityServiceInfo;
     21 import android.content.Intent;
     22 import android.os.Message;
     23 import android.view.accessibility.AccessibilityEvent;
     24 
     25 import java.util.Iterator;
     26 import java.util.LinkedList;
     27 import java.util.List;
     28 import java.util.Queue;
     29 
     30 import junit.framework.TestCase;
     31 
     32 /**
     33  * This is the base class for mock {@link AccessibilityService}s.
     34  */
     35 public abstract class MockAccessibilityService extends AccessibilityService {
     36 
     37     /**
     38      * The event this service expects to receive.
     39      */
     40     private final Queue<AccessibilityEvent> mExpectedEvents = new LinkedList<AccessibilityEvent>();
     41 
     42     /**
     43      * Interruption call this service expects to receive.
     44      */
     45     private boolean mExpectedInterrupt;
     46 
     47     /**
     48      * Flag if the mock is currently replaying.
     49      */
     50     private boolean mReplaying;
     51 
     52     /**
     53      * Flag if the system is bound as a client to this service.
     54      */
     55     private boolean mIsSystemBoundAsClient;
     56 
     57     /**
     58      * Creates an {@link AccessibilityServiceInfo} populated with default
     59      * values.
     60      *
     61      * @return The default info.
     62      */
     63     public static AccessibilityServiceInfo createDefaultInfo() {
     64         AccessibilityServiceInfo defaultInfo = new AccessibilityServiceInfo();
     65         defaultInfo.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED;
     66         defaultInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE;
     67         defaultInfo.flags = 0;
     68         defaultInfo.notificationTimeout = 0;
     69         defaultInfo.packageNames = new String[] {
     70             "foo.bar.baz"
     71         };
     72 
     73         return defaultInfo;
     74     }
     75 
     76     /**
     77      * Starts replaying the mock.
     78      */
     79     public void replay() {
     80         mReplaying = true;
     81     }
     82 
     83     /**
     84      * Verifies if all expected service methods have been called.
     85      */
     86     public void verify() {
     87         if (!mReplaying) {
     88             throw new IllegalStateException("Did you forget to call replay()");
     89         }
     90 
     91         if (mExpectedInterrupt) {
     92             throw new IllegalStateException("Expected call to #interrupt() not received");
     93         }
     94         if (!mExpectedEvents.isEmpty()) {
     95             throw new IllegalStateException("Expected a call to onAccessibilityEvent() for "
     96                     + "events \"" + mExpectedEvents + "\" not received");
     97         }
     98     }
     99 
    100     /**
    101      * Resets this instance so it can be reused.
    102      */
    103     public void reset() {
    104         mExpectedEvents.clear();
    105         mExpectedInterrupt = false;
    106         mReplaying = false;
    107     }
    108 
    109     /**
    110      * Sets an expected call to
    111      * {@link #onAccessibilityEvent(AccessibilityEvent)} with given event as
    112      * argument.
    113      *
    114      * @param expectedEvent The expected event argument.
    115      */
    116     public void expectEvent(AccessibilityEvent expectedEvent) {
    117         mExpectedEvents.add(expectedEvent);
    118     }
    119 
    120     /**
    121      * Sets an expected call of {@link #onInterrupt()}.
    122      */
    123     public void expectInterrupt() {
    124         mExpectedInterrupt = true;
    125     }
    126 
    127     @Override
    128     public void onAccessibilityEvent(AccessibilityEvent receivedEvent) {
    129         if (!mReplaying) {
    130             return;
    131         }
    132 
    133         if (mExpectedEvents.isEmpty()) {
    134             throw new IllegalStateException("Unexpected event: " + receivedEvent);
    135         }
    136 
    137         AccessibilityEvent expectedEvent = mExpectedEvents.poll();
    138         assertEqualsAccessiblityEvent(expectedEvent, receivedEvent);
    139     }
    140 
    141     @Override
    142     public void onInterrupt() {
    143         if (!mReplaying) {
    144             return;
    145         }
    146 
    147         if (!mExpectedInterrupt) {
    148             throw new IllegalStateException("Unexpected call to onInterrupt()");
    149         }
    150 
    151         mExpectedInterrupt = false;
    152     }
    153 
    154     @Override
    155     protected void onServiceConnected() {
    156         mIsSystemBoundAsClient = true;
    157     }
    158 
    159     @Override
    160     public boolean onUnbind(Intent intent) {
    161         mIsSystemBoundAsClient = false;
    162         return false;
    163     }
    164 
    165     /**
    166      * Returns if the system is bound as client to this service.
    167      *
    168      * @return True if the system is bound, false otherwise.
    169      */
    170     public boolean isSystemBoundAsClient() {
    171         return mIsSystemBoundAsClient;
    172     }
    173 
    174     /**
    175      * Compares all properties of the <code>expectedEvent</code> and the
    176      * <code>receviedEvent</code> to verify that the received event is the one
    177      * that is expected.
    178      */
    179     private void assertEqualsAccessiblityEvent(AccessibilityEvent expectedEvent,
    180             AccessibilityEvent receivedEvent) {
    181         TestCase.assertEquals("addedCount has incorrect value", expectedEvent.getAddedCount(),
    182                 receivedEvent.getAddedCount());
    183         TestCase.assertEquals("beforeText has incorrect value", expectedEvent.getBeforeText(),
    184                 receivedEvent.getBeforeText());
    185         TestCase.assertEquals("checked has incorrect value", expectedEvent.isChecked(),
    186                 receivedEvent.isChecked());
    187         TestCase.assertEquals("className has incorrect value", expectedEvent.getClassName(),
    188                 receivedEvent.getClassName());
    189         TestCase.assertEquals("contentDescription has incorrect value", expectedEvent
    190                 .getContentDescription(), receivedEvent.getContentDescription());
    191         TestCase.assertEquals("currentItemIndex has incorrect value", expectedEvent
    192                 .getCurrentItemIndex(), receivedEvent.getCurrentItemIndex());
    193         TestCase.assertEquals("enabled has incorrect value", expectedEvent.isEnabled(),
    194                 receivedEvent.isEnabled());
    195         TestCase.assertEquals("eventType has incorrect value", expectedEvent.getEventType(),
    196                 receivedEvent.getEventType());
    197         TestCase.assertEquals("fromIndex has incorrect value", expectedEvent.getFromIndex(),
    198                 receivedEvent.getFromIndex());
    199         TestCase.assertEquals("fullScreen has incorrect value", expectedEvent.isFullScreen(),
    200                 receivedEvent.isFullScreen());
    201         TestCase.assertEquals("itemCount has incorrect value", expectedEvent.getItemCount(),
    202                 receivedEvent.getItemCount());
    203         assertEqualsNotificationAsParcelableData(expectedEvent, receivedEvent);
    204         TestCase.assertEquals("password has incorrect value", expectedEvent.isPassword(),
    205                 receivedEvent.isPassword());
    206         TestCase.assertEquals("removedCount has incorrect value", expectedEvent.getRemovedCount(),
    207                 receivedEvent.getRemovedCount());
    208         assertEqualsText(expectedEvent, receivedEvent);
    209     }
    210 
    211     /**
    212      * Compares the {@link android.os.Parcelable} data of the
    213      * <code>expectedEvent</code> and <code>receivedEvent</code> to verify that
    214      * the received event is the one that is expected.
    215      */
    216     private void assertEqualsNotificationAsParcelableData(AccessibilityEvent expectedEvent,
    217             AccessibilityEvent receivedEvent) {
    218         String message = "parcelableData has incorrect value";
    219         Message expectedMessage = (Message) expectedEvent.getParcelableData();
    220         Message receivedMessage = (Message) receivedEvent.getParcelableData();
    221 
    222         if (expectedMessage == null) {
    223             if (receivedMessage == null) {
    224                 return;
    225             }
    226         }
    227 
    228         TestCase.assertNotNull(message, receivedMessage);
    229 
    230         // we do a very simple sanity check since we do not test Message
    231         TestCase.assertEquals(message, expectedMessage.what, receivedMessage.what);
    232     }
    233 
    234     /**
    235      * Compares the text of the <code>expectedEvent</code> and
    236      * <code>receivedEvent</code> by comparing the string representation of the
    237      * corresponding {@link CharSequence}s.
    238      */
    239     private void assertEqualsText(AccessibilityEvent expectedEvent,
    240             AccessibilityEvent receivedEvent) {
    241         String message = "text has incorrect value";
    242         List<CharSequence> expectedText = expectedEvent.getText();
    243         List<CharSequence> receivedText = receivedEvent.getText();
    244 
    245         TestCase.assertEquals(message, expectedText.size(), receivedText.size());
    246 
    247         Iterator<CharSequence> expectedTextIterator = expectedText.iterator();
    248         Iterator<CharSequence> receivedTextIterator = receivedText.iterator();
    249 
    250         for (int i = 0; i < expectedText.size(); i++) {
    251             // compare the string representation
    252             TestCase.assertEquals(message, expectedTextIterator.next().toString(),
    253                     receivedTextIterator.next().toString());
    254         }
    255     }
    256 }
    257