blob: 6c41e4b34662811d62cd9de0d28b56046653d777 [file] [log] [blame]
Rui Qiu337cb242021-06-03 11:26:16 -07001/*
2 * Copyright (C) 2021 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.car.telemetry.databroker;
18
19import static com.google.common.truth.Truth.assertThat;
Rui Qiu033041e2021-06-21 14:59:11 -070020import static com.google.common.truth.Truth.assertWithMessage;
Rui Qiu337cb242021-06-03 11:26:16 -070021
Rui Qiua86ab602021-07-02 10:40:36 -070022import static org.mockito.ArgumentMatchers.any;
23import static org.mockito.ArgumentMatchers.anyInt;
24import static org.mockito.ArgumentMatchers.anyString;
Rui Qiuaba02082021-08-16 16:24:00 -070025import static org.mockito.ArgumentMatchers.eq;
Rui Qiua86ab602021-07-02 10:40:36 -070026import static org.mockito.Mockito.verify;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070027import static org.mockito.Mockito.when;
Rui Qiu337cb242021-06-03 11:26:16 -070028
Rui Qiua86ab602021-07-02 10:40:36 -070029import android.annotation.Nullable;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070030import android.car.hardware.CarPropertyConfig;
Rui Qiua86ab602021-07-02 10:40:36 -070031import android.content.Context;
32import android.content.ServiceConnection;
Zhomart Mukhamejanovcdcb4e12021-08-23 18:24:40 -070033import android.content.SharedPreferences;
Rui Qiu033041e2021-06-21 14:59:11 -070034import android.os.Handler;
Rui Qiua86ab602021-07-02 10:40:36 -070035import android.os.IBinder;
Rui Qiuaba02082021-08-16 16:24:00 -070036import android.os.PersistableBundle;
Rui Qiua86ab602021-07-02 10:40:36 -070037import android.os.RemoteException;
Rui Qiu033041e2021-06-21 14:59:11 -070038import android.os.SystemClock;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070039
40import com.android.car.CarPropertyService;
Rui Qiuaba02082021-08-16 16:24:00 -070041import com.android.car.telemetry.ResultStore;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070042import com.android.car.telemetry.TelemetryProto;
43import com.android.car.telemetry.publisher.PublisherFactory;
Zhomart Mukhamejanovcdcb4e12021-08-23 18:24:40 -070044import com.android.car.telemetry.publisher.StatsManagerProxy;
Max Dashouk9912ac32021-08-13 17:54:51 +000045import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutor;
46import com.android.car.telemetry.scriptexecutorinterface.IScriptExecutorListener;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070047
48import org.junit.Before;
Rui Qiu337cb242021-06-03 11:26:16 -070049import org.junit.Test;
50import org.junit.runner.RunWith;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070051import org.mockito.Mock;
Rui Qiuac8b5ba2021-08-25 16:04:17 -070052import org.mockito.Mockito;
Rui Qiu337cb242021-06-03 11:26:16 -070053import org.mockito.junit.MockitoJUnitRunner;
54
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070055import java.util.Collections;
Rui Qiuac8b5ba2021-08-25 16:04:17 -070056import java.util.concurrent.CountDownLatch;
Rui Qiu033041e2021-06-21 14:59:11 -070057import java.util.concurrent.PriorityBlockingQueue;
Rui Qiuac8b5ba2021-08-25 16:04:17 -070058import java.util.concurrent.TimeUnit;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070059
Rui Qiu337cb242021-06-03 11:26:16 -070060@RunWith(MockitoJUnitRunner.class)
Rui Qiuac8b5ba2021-08-25 16:04:17 -070061public class DataBrokerTest {
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070062 private static final int PROP_ID = 100;
63 private static final int PROP_AREA = 200;
Rui Qiu033041e2021-06-21 14:59:11 -070064 private static final int PRIORITY_HIGH = 1;
Rui Qiud95f95d2021-08-17 12:29:33 -070065 private static final int PRIORITY_LOW = 100;
Rui Qiu033041e2021-06-21 14:59:11 -070066 private static final long TIMEOUT_MS = 5_000L;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070067 private static final CarPropertyConfig<Integer> PROP_CONFIG =
68 CarPropertyConfig.newBuilder(Integer.class, PROP_ID, PROP_AREA).setAccess(
69 CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ).build();
Rui Qiu337cb242021-06-03 11:26:16 -070070 private static final TelemetryProto.VehiclePropertyPublisher
71 VEHICLE_PROPERTY_PUBLISHER_CONFIGURATION =
72 TelemetryProto.VehiclePropertyPublisher.newBuilder().setReadRate(
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070073 1).setVehiclePropertyId(PROP_ID).build();
Rui Qiu337cb242021-06-03 11:26:16 -070074 private static final TelemetryProto.Publisher PUBLISHER_CONFIGURATION =
75 TelemetryProto.Publisher.newBuilder().setVehicleProperty(
76 VEHICLE_PROPERTY_PUBLISHER_CONFIGURATION).build();
77 private static final TelemetryProto.Subscriber SUBSCRIBER_FOO =
78 TelemetryProto.Subscriber.newBuilder().setHandler("function_name_foo").setPublisher(
Rui Qiud95f95d2021-08-17 12:29:33 -070079 PUBLISHER_CONFIGURATION).setPriority(PRIORITY_HIGH).build();
Rui Qiu337cb242021-06-03 11:26:16 -070080 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_FOO =
81 TelemetryProto.MetricsConfig.newBuilder().setName("Foo").setVersion(
82 1).addSubscribers(SUBSCRIBER_FOO).build();
83 private static final TelemetryProto.Subscriber SUBSCRIBER_BAR =
84 TelemetryProto.Subscriber.newBuilder().setHandler("function_name_bar").setPublisher(
Rui Qiud95f95d2021-08-17 12:29:33 -070085 PUBLISHER_CONFIGURATION).setPriority(PRIORITY_LOW).build();
Rui Qiu337cb242021-06-03 11:26:16 -070086 private static final TelemetryProto.MetricsConfig METRICS_CONFIG_BAR =
87 TelemetryProto.MetricsConfig.newBuilder().setName("Bar").setVersion(
88 1).addSubscribers(SUBSCRIBER_BAR).build();
89
Rui Qiuea6a4942021-09-07 15:05:34 -070090
91 // when count reaches 0, all handler messages are scheduled to be dispatched after current time
Rui Qiuac8b5ba2021-08-25 16:04:17 -070092 private CountDownLatch mIdleHandlerLatch = new CountDownLatch(1);
Rui Qiuea6a4942021-09-07 15:05:34 -070093 private PersistableBundle mData = new PersistableBundle();
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070094 private DataBrokerImpl mDataBroker;
Rui Qiua86ab602021-07-02 10:40:36 -070095 private FakeScriptExecutor mFakeScriptExecutor;
Rui Qiu033041e2021-06-21 14:59:11 -070096 private ScriptExecutionTask mHighPriorityTask;
97 private ScriptExecutionTask mLowPriorityTask;
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -070098
Rui Qiua86ab602021-07-02 10:40:36 -070099 @Mock
100 private Context mMockContext;
101 @Mock
102 private CarPropertyService mMockCarPropertyService;
103 @Mock
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700104 private Handler mMockHandler;
105 @Mock
Zhomart Mukhamejanovcdcb4e12021-08-23 18:24:40 -0700106 private StatsManagerProxy mMockStatsManager;
107 @Mock
108 private SharedPreferences mMockSharedPreferences;
109 @Mock
Rui Qiua86ab602021-07-02 10:40:36 -0700110 private IBinder mMockScriptExecutorBinder;
Rui Qiuaba02082021-08-16 16:24:00 -0700111 @Mock
112 private ResultStore mMockResultStore;
Rui Qiua86ab602021-07-02 10:40:36 -0700113
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -0700114 @Before
115 public void setUp() {
116 when(mMockCarPropertyService.getPropertyList())
117 .thenReturn(Collections.singletonList(PROP_CONFIG));
Rui Qiua86ab602021-07-02 10:40:36 -0700118 // bind service should return true, otherwise broker is disabled
119 when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true);
Zhomart Mukhamejanovcdcb4e12021-08-23 18:24:40 -0700120 PublisherFactory factory = new PublisherFactory(
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700121 mMockCarPropertyService, mMockHandler, mMockStatsManager, mMockSharedPreferences);
Rui Qiuaba02082021-08-16 16:24:00 -0700122 mDataBroker = new DataBrokerImpl(mMockContext, factory, mMockResultStore);
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700123 // add IdleHandler to get notified when all messages and posts are handled
124 mDataBroker.getTelemetryHandler().getLooper().getQueue().addIdleHandler(() -> {
125 mIdleHandlerLatch.countDown();
126 return true;
127 });
Rui Qiua86ab602021-07-02 10:40:36 -0700128
129 mFakeScriptExecutor = new FakeScriptExecutor();
130 when(mMockScriptExecutorBinder.queryLocalInterface(anyString()))
131 .thenReturn(mFakeScriptExecutor);
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700132 when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(i -> {
133 ServiceConnection conn = i.getArgument(1);
134 conn.onServiceConnected(null, mMockScriptExecutorBinder);
135 return true;
136 });
Rui Qiua86ab602021-07-02 10:40:36 -0700137
Rui Qiu033041e2021-06-21 14:59:11 -0700138 mHighPriorityTask = new ScriptExecutionTask(
Rui Qiud95f95d2021-08-17 12:29:33 -0700139 new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
Rui Qiuea6a4942021-09-07 15:05:34 -0700140 mData,
Rui Qiu033041e2021-06-21 14:59:11 -0700141 SystemClock.elapsedRealtime());
142 mLowPriorityTask = new ScriptExecutionTask(
Rui Qiud95f95d2021-08-17 12:29:33 -0700143 new DataSubscriber(mDataBroker, METRICS_CONFIG_BAR, SUBSCRIBER_BAR),
Rui Qiuea6a4942021-09-07 15:05:34 -0700144 mData,
Rui Qiu033041e2021-06-21 14:59:11 -0700145 SystemClock.elapsedRealtime());
146 }
147
148 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700149 public void testSetTaskExecutionPriority_whenNoTask_shouldNotInvokeScriptExecutor()
150 throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700151 mDataBroker.setTaskExecutionPriority(PRIORITY_HIGH);
152
Rui Qiua86ab602021-07-02 10:40:36 -0700153 waitForHandlerThreadToFinish();
154 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(0);
Rui Qiu033041e2021-06-21 14:59:11 -0700155 }
156
157 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700158 public void testSetTaskExecutionPriority_whenNextTaskPriorityLow_shouldNotRunTask()
159 throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700160 mDataBroker.getTaskQueue().add(mLowPriorityTask);
161
162 mDataBroker.setTaskExecutionPriority(PRIORITY_HIGH);
163
164 waitForHandlerThreadToFinish();
165 // task is not polled
166 assertThat(mDataBroker.getTaskQueue().peek()).isEqualTo(mLowPriorityTask);
Rui Qiua86ab602021-07-02 10:40:36 -0700167 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(0);
Rui Qiu033041e2021-06-21 14:59:11 -0700168 }
169
170 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700171 public void testSetTaskExecutionPriority_whenNextTaskPriorityHigh_shouldInvokeScriptExecutor()
172 throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700173 mDataBroker.getTaskQueue().add(mHighPriorityTask);
174
175 mDataBroker.setTaskExecutionPriority(PRIORITY_HIGH);
176
177 waitForHandlerThreadToFinish();
178 // task is polled and run
179 assertThat(mDataBroker.getTaskQueue().peek()).isNull();
Rui Qiua86ab602021-07-02 10:40:36 -0700180 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
Rui Qiu033041e2021-06-21 14:59:11 -0700181 }
182
183 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700184 public void testScheduleNextTask_whenNoTask_shouldNotInvokeScriptExecutor() throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700185 mDataBroker.scheduleNextTask();
186
Rui Qiua86ab602021-07-02 10:40:36 -0700187 waitForHandlerThreadToFinish();
188 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(0);
Rui Qiu033041e2021-06-21 14:59:11 -0700189 }
190
191 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700192 public void testScheduleNextTask_whenTaskInProgress_shouldNotInvokeScriptExecutorAgain()
193 throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700194 PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
195 taskQueue.add(mHighPriorityTask);
196 mDataBroker.scheduleNextTask(); // start a task
197 waitForHandlerThreadToFinish();
198 assertThat(taskQueue.peek()).isNull(); // assert that task is polled and running
199 taskQueue.add(mHighPriorityTask); // add another task into the queue
200
201 mDataBroker.scheduleNextTask(); // schedule next task while the last task is in progress
202
Rui Qiuea6a4942021-09-07 15:05:34 -0700203 waitForHandlerThreadToFinish();
Rui Qiua86ab602021-07-02 10:40:36 -0700204 // verify task is not polled
205 assertThat(taskQueue.peek()).isEqualTo(mHighPriorityTask);
206 // expect one invocation for the task that is running
207 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
208 }
209
210 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700211 public void testScheduleNextTask_whenTaskCompletes_shouldAutomaticallyScheduleNextTask()
212 throws Exception {
Rui Qiua86ab602021-07-02 10:40:36 -0700213 PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
214 // add two tasks into the queue for execution
215 taskQueue.add(mHighPriorityTask);
216 taskQueue.add(mHighPriorityTask);
217
218 mDataBroker.scheduleNextTask(); // start a task
219 waitForHandlerThreadToFinish();
220 // end a task, should automatically schedule the next task
Rui Qiuea6a4942021-09-07 15:05:34 -0700221 mFakeScriptExecutor.notifyScriptSuccess(mData); // posts to telemetry handler
Rui Qiua86ab602021-07-02 10:40:36 -0700222
223 waitForHandlerThreadToFinish();
224 // verify queue is empty, both tasks are polled and executed
225 assertThat(taskQueue.peek()).isNull();
226 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(2);
227 }
228
229 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700230 public void testScheduleNextTask_onScriptSuccess_shouldStoreInterimResult() throws Exception {
Rui Qiuea6a4942021-09-07 15:05:34 -0700231 mData.putBoolean("script is finished", false);
232 mData.putDouble("value of euler's number", 2.71828);
Rui Qiuaba02082021-08-16 16:24:00 -0700233 mDataBroker.getTaskQueue().add(mHighPriorityTask);
Rui Qiuaba02082021-08-16 16:24:00 -0700234
235 mDataBroker.scheduleNextTask();
236 waitForHandlerThreadToFinish();
Rui Qiuea6a4942021-09-07 15:05:34 -0700237 mFakeScriptExecutor.notifyScriptSuccess(mData); // posts to telemetry handler
Rui Qiuaba02082021-08-16 16:24:00 -0700238
Rui Qiuea6a4942021-09-07 15:05:34 -0700239 waitForHandlerThreadToFinish();
Rui Qiuaba02082021-08-16 16:24:00 -0700240 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
Rui Qiuea6a4942021-09-07 15:05:34 -0700241 verify(mMockResultStore).putInterimResult(
242 eq(mHighPriorityTask.getMetricsConfig().getName()), eq(mData));
243 }
244
245 @Test
246 public void testScheduleNextTask_whenScriptFinishes_shouldStoreFinalResult()
247 throws Exception {
248 mData.putBoolean("script is finished", true);
249 mData.putDouble("value of pi", 3.14159265359);
250 mDataBroker.getTaskQueue().add(mHighPriorityTask);
251
252 mDataBroker.scheduleNextTask();
253 waitForHandlerThreadToFinish();
254 mFakeScriptExecutor.notifyScriptFinish(mData); // posts to telemetry handler
255
256 waitForHandlerThreadToFinish();
257 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
258 verify(mMockResultStore).putFinalResult(
259 eq(mHighPriorityTask.getMetricsConfig().getName()), eq(mData));
260 }
261
262 @Test
263 public void testScheduleNextTask_whenInterimDataExists_shouldPassToScriptExecutor()
264 throws Exception {
265 mData.putDouble("value of golden ratio", 1.618033);
266 mDataBroker.getTaskQueue().add(mHighPriorityTask);
267 when(mMockResultStore.getInterimResult(mHighPriorityTask.getMetricsConfig().getName()))
268 .thenReturn(mData);
269
270 mDataBroker.scheduleNextTask();
271
272 waitForHandlerThreadToFinish();
273 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
274 assertThat(mFakeScriptExecutor.getSavedState()).isEqualTo(mData);
Rui Qiuaba02082021-08-16 16:24:00 -0700275 }
276
277 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700278 public void testScheduleNextTask_whenBindScriptExecutorFailed_shouldDisableBroker()
279 throws Exception {
280 // fail all future attempts to bind to it
281 Mockito.reset(mMockContext);
282 when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(false);
Rui Qiua86ab602021-07-02 10:40:36 -0700283 mDataBroker.addMetricsConfiguration(METRICS_CONFIG_FOO);
284 PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
285 taskQueue.add(mHighPriorityTask);
Rui Qiua86ab602021-07-02 10:40:36 -0700286
287 // will rebind to ScriptExecutor if it is null
288 mDataBroker.scheduleNextTask();
289
290 waitForHandlerThreadToFinish();
291 // all subscribers should have been removed
292 assertThat(mDataBroker.getSubscriptionMap()).hasSize(0);
293 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(0);
294 }
295
296 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700297 public void testScheduleNextTask_whenScriptExecutorThrowsException_shouldRequeueTask()
298 throws Exception {
Rui Qiua86ab602021-07-02 10:40:36 -0700299 PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
300 taskQueue.add(mHighPriorityTask);
301 mFakeScriptExecutor.failNextApiCalls(1); // fail the next invokeScript() call
302
303 mDataBroker.scheduleNextTask();
304
305 waitForHandlerThreadToFinish();
306 // expect invokeScript() to be called and failed, causing the same task to be re-queued
307 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
Rui Qiu033041e2021-06-21 14:59:11 -0700308 assertThat(taskQueue.peek()).isEqualTo(mHighPriorityTask);
309 }
310
311 @Test
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700312 public void testAddTaskToQueue_shouldInvokeScriptExecutor() throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700313 mDataBroker.addTaskToQueue(mHighPriorityTask);
314
Rui Qiua86ab602021-07-02 10:40:36 -0700315 waitForHandlerThreadToFinish();
316 assertThat(mFakeScriptExecutor.getApiInvocationCount()).isEqualTo(1);
Zhomart Mukhamejanov44570cb2021-06-07 10:23:13 -0700317 }
318
Rui Qiu337cb242021-06-03 11:26:16 -0700319 @Test
320 public void testAddMetricsConfiguration_newMetricsConfig() {
Rui Qiuf14c6a22021-07-14 10:39:16 -0700321 mDataBroker.addMetricsConfiguration(METRICS_CONFIG_BAR);
322
Rui Qiuf14c6a22021-07-14 10:39:16 -0700323 assertThat(mDataBroker.getSubscriptionMap()).hasSize(1);
324 assertThat(mDataBroker.getSubscriptionMap()).containsKey(METRICS_CONFIG_BAR.getName());
325 // there should be one data subscriber in the subscription list of METRICS_CONFIG_BAR
326 assertThat(mDataBroker.getSubscriptionMap().get(METRICS_CONFIG_BAR.getName())).hasSize(1);
327 }
328
329
330 @Test
331 public void testAddMetricsConfiguration_duplicateMetricsConfig_shouldDoNothing() {
332 // this metrics config has already been added in setUp()
Rui Qiu337cb242021-06-03 11:26:16 -0700333 mDataBroker.addMetricsConfiguration(METRICS_CONFIG_FOO);
334
Rui Qiuf14c6a22021-07-14 10:39:16 -0700335 assertThat(mDataBroker.getSubscriptionMap()).hasSize(1);
Rui Qiu337cb242021-06-03 11:26:16 -0700336 assertThat(mDataBroker.getSubscriptionMap()).containsKey(METRICS_CONFIG_FOO.getName());
Rui Qiu337cb242021-06-03 11:26:16 -0700337 assertThat(mDataBroker.getSubscriptionMap().get(METRICS_CONFIG_FOO.getName())).hasSize(1);
338 }
339
340 @Test
Rui Qiuf14c6a22021-07-14 10:39:16 -0700341 public void testRemoveMetricsConfiguration_shouldRemoveAllAssociatedTasks() {
Rui Qiu337cb242021-06-03 11:26:16 -0700342 mDataBroker.addMetricsConfiguration(METRICS_CONFIG_FOO);
343 mDataBroker.addMetricsConfiguration(METRICS_CONFIG_BAR);
Rui Qiud95f95d2021-08-17 12:29:33 -0700344 ScriptExecutionTask taskWithMetricsConfigFoo = new ScriptExecutionTask(
345 new DataSubscriber(mDataBroker, METRICS_CONFIG_FOO, SUBSCRIBER_FOO),
Rui Qiuea6a4942021-09-07 15:05:34 -0700346 mData,
Rui Qiuf14c6a22021-07-14 10:39:16 -0700347 SystemClock.elapsedRealtime());
348 PriorityBlockingQueue<ScriptExecutionTask> taskQueue = mDataBroker.getTaskQueue();
349 taskQueue.add(mHighPriorityTask); // associated with METRICS_CONFIG_FOO
Rui Qiud95f95d2021-08-17 12:29:33 -0700350 taskQueue.add(mLowPriorityTask); // associated with METRICS_CONFIG_BAR
351 taskQueue.add(taskWithMetricsConfigFoo); // associated with METRICS_CONFIG_FOO
Rui Qiuf14c6a22021-07-14 10:39:16 -0700352 assertThat(taskQueue).hasSize(3);
353
354 mDataBroker.removeMetricsConfiguration(METRICS_CONFIG_FOO);
Rui Qiu337cb242021-06-03 11:26:16 -0700355
Rui Qiuf14c6a22021-07-14 10:39:16 -0700356 assertThat(taskQueue).hasSize(1);
Rui Qiud95f95d2021-08-17 12:29:33 -0700357 assertThat(taskQueue.poll()).isEqualTo(mLowPriorityTask);
Rui Qiuf14c6a22021-07-14 10:39:16 -0700358 }
359
360 @Test
361 public void testRemoveMetricsConfiguration_whenMetricsConfigNonExistent_shouldDoNothing() {
362 mDataBroker.removeMetricsConfiguration(METRICS_CONFIG_BAR);
363
Rui Qiuf14c6a22021-07-14 10:39:16 -0700364 assertThat(mDataBroker.getSubscriptionMap()).hasSize(0);
Rui Qiu337cb242021-06-03 11:26:16 -0700365 }
366
Rui Qiuac8b5ba2021-08-25 16:04:17 -0700367 private void waitForHandlerThreadToFinish() throws Exception {
Rui Qiu033041e2021-06-21 14:59:11 -0700368 assertWithMessage("handler not idle in %sms", TIMEOUT_MS)
Rui Qiua4a8fd02021-09-02 19:08:40 -0700369 .that(mIdleHandlerLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
Rui Qiuea6a4942021-09-07 15:05:34 -0700370 mIdleHandlerLatch = new CountDownLatch(1); // reset idle handler condition
Rui Qiu337cb242021-06-03 11:26:16 -0700371 }
Rui Qiua86ab602021-07-02 10:40:36 -0700372
373 private static class FakeScriptExecutor implements IScriptExecutor {
374 private IScriptExecutorListener mListener;
375 private int mApiInvocationCount = 0;
376 private int mFailApi = 0;
Rui Qiuea6a4942021-09-07 15:05:34 -0700377 private PersistableBundle mSavedState = null;
Rui Qiua86ab602021-07-02 10:40:36 -0700378
379 @Override
Max Dashoukdafdd222021-08-20 10:42:25 -0700380 public void invokeScript(String scriptBody, String functionName,
381 PersistableBundle publishedData, @Nullable PersistableBundle savedState,
382 IScriptExecutorListener listener)
Rui Qiua86ab602021-07-02 10:40:36 -0700383 throws RemoteException {
384 mApiInvocationCount++;
Rui Qiuea6a4942021-09-07 15:05:34 -0700385 mSavedState = savedState;
Rui Qiua86ab602021-07-02 10:40:36 -0700386 mListener = listener;
387 if (mFailApi > 0) {
388 mFailApi--;
389 throw new RemoteException("Simulated failure");
390 }
391 }
392
393 @Override
394 public IBinder asBinder() {
395 return null;
396 }
397
Rui Qiuaba02082021-08-16 16:24:00 -0700398 /** Mocks script temporary completion. */
Max Dashoukdafdd222021-08-20 10:42:25 -0700399 public void notifyScriptSuccess(PersistableBundle bundle) {
Rui Qiua86ab602021-07-02 10:40:36 -0700400 try {
Rui Qiuaba02082021-08-16 16:24:00 -0700401 mListener.onSuccess(bundle);
Rui Qiua86ab602021-07-02 10:40:36 -0700402 } catch (RemoteException e) {
403 // nothing to do
404 }
405 }
406
Rui Qiuea6a4942021-09-07 15:05:34 -0700407 /** Mocks script producing final result. */
408 public void notifyScriptFinish(PersistableBundle bundle) {
409 try {
410 mListener.onScriptFinished(bundle);
411 } catch (RemoteException e) {
412 // nothing to do
413 }
414 }
415
Rui Qiua86ab602021-07-02 10:40:36 -0700416 /** Fails the next N invokeScript() call. */
417 public void failNextApiCalls(int n) {
418 mFailApi = n;
419 }
420
421 /** Returns number of times the ScriptExecutor API was invoked. */
422 public int getApiInvocationCount() {
423 return mApiInvocationCount;
424 }
Rui Qiuea6a4942021-09-07 15:05:34 -0700425
426 /** Returns the interim data passed in invokeScript(). */
427 public PersistableBundle getSavedState() {
428 return mSavedState;
429 }
Rui Qiua86ab602021-07-02 10:40:36 -0700430 }
Rui Qiu337cb242021-06-03 11:26:16 -0700431}