• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.phone.vvm.omtp.scheduling;
18 
19 import static org.mockito.Matchers.any;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.when;
22 
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.os.IBinder;
27 import android.os.Message;
28 import android.support.test.InstrumentationRegistry;
29 import android.support.test.rule.ServiceTestRule;
30 import android.support.test.runner.AndroidJUnit4;
31 
32 import com.android.phone.Assert;
33 import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
34 import com.android.phone.vvm.omtp.scheduling.TaskSchedulerService.MainThreadHandler;
35 import com.android.phone.vvm.omtp.scheduling.TaskSchedulerService.WorkerThreadHandler;
36 
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Rule;
40 import org.junit.rules.ExpectedException;
41 import org.junit.runner.RunWith;
42 
43 import java.util.concurrent.TimeoutException;
44 
45 @RunWith(AndroidJUnit4.class)
46 public class TaskSchedulerServiceTestBase {
47 
48     private static final String EXTRA_ID = "test_extra_id";
49     private static final String EXTRA_SUB_ID = "test_extra_sub_id";
50 
51     public TaskSchedulerService mService;
52 
53     @Rule
54     public final ExpectedException thrown = ExpectedException.none();
55 
56     @Rule
57     public final ServiceTestRule mServiceRule = new ServiceTestRule();
58 
59     public Context mTargetContext;
60     public Context mTestContext;
61 
62     private static boolean sIsMainThread = true;
63 
64     private final TestMessageSender mMessageSender = new TestMessageSender();
65 
putTaskId(Intent intent, TaskId taskId)66     public static Intent putTaskId(Intent intent, TaskId taskId) {
67         intent.putExtra(EXTRA_ID, taskId.id);
68         intent.putExtra(EXTRA_SUB_ID, taskId.subId);
69         return intent;
70     }
71 
getTaskId(Intent intent)72     public static TaskId getTaskId(Intent intent) {
73         return new TaskId(intent.getIntExtra(EXTRA_ID, 0), intent.getIntExtra(EXTRA_SUB_ID, 0));
74     }
75 
76     @Before
setUp()77     public void setUp() throws TimeoutException {
78         Assert.setIsMainThreadForTesting(true);
79         mTargetContext = InstrumentationRegistry.getTargetContext();
80         IBinder binder = null;
81         // bindService() might returns null on 2nd invocation because the service is not unbinded
82         // yet. See https://code.google.com/p/android/issues/detail?id=180396
83         while (binder == null) {
84             binder = mServiceRule
85                     .bindService(new Intent(mTargetContext, TaskSchedulerService.class));
86         }
87         mService = ((TaskSchedulerService.LocalBinder) binder).getService();
88         mTestContext = createTestContext(mTargetContext, mService);
89         mService.setMessageSenderForTest(mMessageSender);
90         mService.setTaskAutoRunDisabledForTest(true);
91         mService.setContextForTest(mTestContext);
92     }
93 
94     @After
tearDown()95     public void tearDown() {
96         Assert.setIsMainThreadForTesting(null);
97         mService.setTaskAutoRunDisabledForTest(false);
98         mService.clearTasksForTest();
99         mService.stopSelf();
100     }
101 
submitTask(Intent intent)102     public Task submitTask(Intent intent) {
103         Task task = mService.createTask(intent, 0, 0);
104         mService.addTask(task);
105         return task;
106     }
107 
verifyRanOnce(TestTask task)108     public static void verifyRanOnce(TestTask task) {
109         assertTrue(task.onBeforeExecuteCounter.invokedOnce());
110         assertTrue(task.executeCounter.invokedOnce());
111         assertTrue(task.onCompletedCounter.invokedOnce());
112     }
113 
verifyNotRan(TestTask task)114     public static void verifyNotRan(TestTask task) {
115         assertTrue(task.onBeforeExecuteCounter.neverInvoked());
116         assertTrue(task.executeCounter.neverInvoked());
117         assertTrue(task.onCompletedCounter.neverInvoked());
118     }
119 
120     public static class TestTask implements Task {
121 
122         public int readyInMilliseconds;
123 
124         private TaskId mId;
125 
126         public final InvocationCounter onCreateCounter = new InvocationCounter();
127         public final InvocationCounter onBeforeExecuteCounter = new InvocationCounter();
128         public final InvocationCounter executeCounter = new InvocationCounter();
129         public final InvocationCounter onCompletedCounter = new InvocationCounter();
130         public final InvocationCounter onDuplicatedTaskAddedCounter = new InvocationCounter();
131 
132         @Override
onCreate(Context context, Intent intent, int flags, int startId)133         public void onCreate(Context context, Intent intent, int flags, int startId) {
134             onCreateCounter.invoke();
135             mId = getTaskId(intent);
136         }
137 
138         @Override
getId()139         public TaskId getId() {
140             return mId;
141         }
142 
143         @Override
getReadyInMilliSeconds()144         public long getReadyInMilliSeconds() {
145             Assert.isMainThread();
146             return readyInMilliseconds;
147         }
148 
149         @Override
onBeforeExecute()150         public void onBeforeExecute() {
151             Assert.isMainThread();
152             onBeforeExecuteCounter.invoke();
153         }
154 
155         @Override
onExecuteInBackgroundThread()156         public void onExecuteInBackgroundThread() {
157             Assert.isNotMainThread();
158             executeCounter.invoke();
159         }
160 
161         @Override
onCompleted()162         public void onCompleted() {
163             Assert.isMainThread();
164             onCompletedCounter.invoke();
165         }
166 
167         @Override
onDuplicatedTaskAdded(Task task)168         public void onDuplicatedTaskAdded(Task task) {
169             Assert.isMainThread();
170             onDuplicatedTaskAddedCounter.invoke();
171         }
172     }
173 
174     public static class InvocationCounter {
175 
176         private int mCounter;
177 
invoke()178         public void invoke() {
179             mCounter++;
180         }
181 
invokedOnce()182         public boolean invokedOnce() {
183             return mCounter == 1;
184         }
185 
neverInvoked()186         public boolean neverInvoked() {
187             return mCounter == 0;
188         }
189     }
190 
191     private class TestMessageSender extends TaskSchedulerService.MessageSender {
192 
193         @Override
send(Message message)194         public void send(Message message) {
195             if (message.getTarget() instanceof MainThreadHandler) {
196                 Assert.setIsMainThreadForTesting(true);
197             } else if (message.getTarget() instanceof WorkerThreadHandler) {
198                 Assert.setIsMainThreadForTesting(false);
199             } else {
200                 throw new AssertionError("unexpected Handler " + message.getTarget());
201             }
202             message.getTarget().handleMessage(message);
203         }
204     }
205 
assertTrue(boolean condition)206     public static void assertTrue(boolean condition) {
207         if (!condition) {
208             throw new AssertionError();
209         }
210     }
211 
createTestContext(Context targetContext, TaskSchedulerService service)212     private static Context createTestContext(Context targetContext, TaskSchedulerService service) {
213         TestContext context = mock(TestContext.class);
214         when(context.getService()).thenReturn(service);
215         when(context.startService(any())).thenCallRealMethod();
216         when(context.getPackageName()).thenReturn(targetContext.getPackageName());
217         return context;
218     }
219 
220     public abstract class TestContext extends Context {
221 
222         @Override
startService(Intent service)223         public ComponentName startService(Intent service) {
224             getService().onStartCommand(service, 0, 0);
225             return null;
226         }
227 
getService()228         public abstract TaskSchedulerService getService();
229     }
230 }
231