1 /*
2 * Copyright (C) 2020 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 #include "MockPreparedModel.h"
18
19 #include "MockBurstContext.h"
20
21 #include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include <nnapi/IExecution.h>
25 #include <nnapi/IPreparedModel.h>
26 #include <nnapi/TypeUtils.h>
27 #include <nnapi/Types.h>
28 #include <nnapi/hal/1.2/PreparedModel.h>
29
30 #include <functional>
31 #include <memory>
32
33 namespace android::hardware::neuralnetworks::V1_2::utils {
34 namespace {
35
36 using ::testing::_;
37 using ::testing::Invoke;
38 using ::testing::InvokeWithoutArgs;
39
40 const sp<V1_2::IPreparedModel> kInvalidPreparedModel;
41 constexpr auto kNoTiming = V1_2::Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
42 .timeInDriver = std::numeric_limits<uint64_t>::max()};
43
createMockPreparedModel()44 sp<MockPreparedModel> createMockPreparedModel() {
45 const auto mockPreparedModel = MockPreparedModel::create();
46
47 // Ensure that older calls are not used.
48 EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(0);
49
50 return mockPreparedModel;
51 }
52
makeExecuteSynchronously(V1_0::ErrorStatus status,const std::vector<V1_2::OutputShape> & outputShapes,const V1_2::Timing & timing)53 auto makeExecuteSynchronously(V1_0::ErrorStatus status,
54 const std::vector<V1_2::OutputShape>& outputShapes,
55 const V1_2::Timing& timing) {
56 return [status, outputShapes, timing](const V1_0::Request& /*request*/,
57 V1_2::MeasureTiming /*measureTiming*/,
58 const V1_2::IPreparedModel::executeSynchronously_cb& cb) {
59 cb(status, outputShapes, timing);
60 return hardware::Void();
61 };
62 }
makeExecuteAsynchronously(V1_0::ErrorStatus launchStatus,V1_0::ErrorStatus returnStatus,const std::vector<V1_2::OutputShape> & outputShapes,const V1_2::Timing & timing)63 auto makeExecuteAsynchronously(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
64 const std::vector<V1_2::OutputShape>& outputShapes,
65 const V1_2::Timing& timing) {
66 return [launchStatus, returnStatus, outputShapes, timing](
67 const V1_0::Request& /*request*/, V1_2::MeasureTiming /*measureTiming*/,
68 const sp<V1_2::IExecutionCallback>& cb) -> Return<V1_0::ErrorStatus> {
69 cb->notify_1_2(returnStatus, outputShapes, timing);
70 return launchStatus;
71 };
72 }
makeConfigureExecutionBurstReturn(V1_0::ErrorStatus status,const sp<MockBurstContext> & burstContext)73 auto makeConfigureExecutionBurstReturn(V1_0::ErrorStatus status,
74 const sp<MockBurstContext>& burstContext) {
75 return [status, burstContext](
76 const sp<V1_2::IBurstCallback>& /*callback*/,
77 const MQDescriptorSync<V1_2::FmqRequestDatum>& /*requestChannel*/,
78 const MQDescriptorSync<V1_2::FmqResultDatum>& /*resultChannel*/,
79 V1_2::IPreparedModel::configureExecutionBurst_cb cb) -> hardware::Return<void> {
80 cb(status, burstContext);
81 return hardware::Void();
82 };
83 }
84
makeTransportFailure(status_t status)85 std::function<hardware::Status()> makeTransportFailure(status_t status) {
86 return [status] { return hardware::Status::fromStatusT(status); };
87 }
88
89 const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
90 const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
91
92 } // namespace
93
TEST(PreparedModelTest,invalidPreparedModel)94 TEST(PreparedModelTest, invalidPreparedModel) {
95 // run test
96 const auto result = PreparedModel::create(kInvalidPreparedModel, /*executeSynchronously=*/true);
97
98 // verify result
99 ASSERT_FALSE(result.has_value());
100 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
101 }
102
TEST(PreparedModelTest,linkToDeathError)103 TEST(PreparedModelTest, linkToDeathError) {
104 // setup call
105 const auto mockPreparedModel = createMockPreparedModel();
106 const auto ret = []() -> Return<bool> { return false; };
107 EXPECT_CALL(*mockPreparedModel, linkToDeathRet()).Times(1).WillOnce(InvokeWithoutArgs(ret));
108
109 // run test
110 const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
111
112 // verify result
113 ASSERT_FALSE(result.has_value());
114 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
115 }
116
TEST(PreparedModelTest,linkToDeathTransportFailure)117 TEST(PreparedModelTest, linkToDeathTransportFailure) {
118 // setup call
119 const auto mockPreparedModel = createMockPreparedModel();
120 EXPECT_CALL(*mockPreparedModel, linkToDeathRet())
121 .Times(1)
122 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
123
124 // run test
125 const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
126
127 // verify result
128 ASSERT_FALSE(result.has_value());
129 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
130 }
131
TEST(PreparedModelTest,linkToDeathDeadObject)132 TEST(PreparedModelTest, linkToDeathDeadObject) {
133 // setup call
134 const auto mockPreparedModel = createMockPreparedModel();
135 EXPECT_CALL(*mockPreparedModel, linkToDeathRet())
136 .Times(1)
137 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
138
139 // run test
140 const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
141
142 // verify result
143 ASSERT_FALSE(result.has_value());
144 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
145 }
146
TEST(PreparedModelTest,executeSync)147 TEST(PreparedModelTest, executeSync) {
148 // setup call
149 const auto mockPreparedModel = createMockPreparedModel();
150 const auto preparedModel =
151 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
152 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
153 .Times(1)
154 .WillOnce(Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
155
156 // run test
157 const auto result = preparedModel->execute({}, {}, {}, {});
158
159 // verify result
160 EXPECT_TRUE(result.has_value())
161 << "Failed with " << result.error().code << ": " << result.error().message;
162 }
163
TEST(PreparedModelTest,executeSyncError)164 TEST(PreparedModelTest, executeSyncError) {
165 // setup test
166 const auto mockPreparedModel = createMockPreparedModel();
167 const auto preparedModel =
168 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
169 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
170 .Times(1)
171 .WillOnce(Invoke(
172 makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
173
174 // run test
175 const auto result = preparedModel->execute({}, {}, {}, {});
176
177 // verify result
178 ASSERT_FALSE(result.has_value());
179 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
180 }
181
TEST(PreparedModelTest,executeSyncTransportFailure)182 TEST(PreparedModelTest, executeSyncTransportFailure) {
183 // setup test
184 const auto mockPreparedModel = createMockPreparedModel();
185 const auto preparedModel =
186 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
187 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
188 .Times(1)
189 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
190
191 // run test
192 const auto result = preparedModel->execute({}, {}, {}, {});
193
194 // verify result
195 ASSERT_FALSE(result.has_value());
196 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
197 }
198
TEST(PreparedModelTest,executeSyncDeadObject)199 TEST(PreparedModelTest, executeSyncDeadObject) {
200 // setup test
201 const auto mockPreparedModel = createMockPreparedModel();
202 const auto preparedModel =
203 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
204 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
205 .Times(1)
206 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
207
208 // run test
209 const auto result = preparedModel->execute({}, {}, {}, {});
210
211 // verify result
212 ASSERT_FALSE(result.has_value());
213 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
214 }
215
TEST(PreparedModelTest,executeAsync)216 TEST(PreparedModelTest, executeAsync) {
217 // setup call
218 const auto mockPreparedModel = createMockPreparedModel();
219 const auto preparedModel =
220 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
221 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
222 .Times(1)
223 .WillOnce(Invoke(makeExecuteAsynchronously(V1_0::ErrorStatus::NONE,
224 V1_0::ErrorStatus::NONE, {}, kNoTiming)));
225
226 // run test
227 const auto result = preparedModel->execute({}, {}, {}, {});
228
229 // verify result
230 EXPECT_TRUE(result.has_value())
231 << "Failed with " << result.error().code << ": " << result.error().message;
232 }
233
TEST(PreparedModelTest,executeAsyncLaunchError)234 TEST(PreparedModelTest, executeAsyncLaunchError) {
235 // setup test
236 const auto mockPreparedModel = createMockPreparedModel();
237 const auto preparedModel =
238 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
239 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
240 .Times(1)
241 .WillOnce(Invoke(makeExecuteAsynchronously(V1_0::ErrorStatus::GENERAL_FAILURE,
242 V1_0::ErrorStatus::GENERAL_FAILURE, {},
243 kNoTiming)));
244
245 // run test
246 const auto result = preparedModel->execute({}, {}, {}, {});
247
248 // verify result
249 ASSERT_FALSE(result.has_value());
250 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
251 }
252
TEST(PreparedModelTest,executeAsyncReturnError)253 TEST(PreparedModelTest, executeAsyncReturnError) {
254 // setup test
255 const auto mockPreparedModel = createMockPreparedModel();
256 const auto preparedModel =
257 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
258 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
259 .Times(1)
260 .WillOnce(Invoke(makeExecuteAsynchronously(
261 V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
262
263 // run test
264 const auto result = preparedModel->execute({}, {}, {}, {});
265
266 // verify result
267 ASSERT_FALSE(result.has_value());
268 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
269 }
270
TEST(PreparedModelTest,executeAsyncTransportFailure)271 TEST(PreparedModelTest, executeAsyncTransportFailure) {
272 // setup test
273 const auto mockPreparedModel = createMockPreparedModel();
274 const auto preparedModel =
275 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
276 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
277 .Times(1)
278 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
279
280 // run test
281 const auto result = preparedModel->execute({}, {}, {}, {});
282
283 // verify result
284 ASSERT_FALSE(result.has_value());
285 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
286 }
287
TEST(PreparedModelTest,executeAsyncDeadObject)288 TEST(PreparedModelTest, executeAsyncDeadObject) {
289 // setup test
290 const auto mockPreparedModel = createMockPreparedModel();
291 const auto preparedModel =
292 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
293 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
294 .Times(1)
295 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
296
297 // run test
298 const auto result = preparedModel->execute({}, {}, {}, {});
299
300 // verify result
301 ASSERT_FALSE(result.has_value());
302 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
303 }
304
TEST(PreparedModelTest,executeAsyncCrash)305 TEST(PreparedModelTest, executeAsyncCrash) {
306 // setup test
307 const auto mockPreparedModel = createMockPreparedModel();
308 const auto preparedModel =
309 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
310 const auto ret = [&mockPreparedModel]() -> hardware::Return<V1_0::ErrorStatus> {
311 mockPreparedModel->simulateCrash();
312 return V1_0::ErrorStatus::NONE;
313 };
314 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
315
316 // run test
317 const auto result = preparedModel->execute({}, {}, {}, {});
318
319 // verify result
320 ASSERT_FALSE(result.has_value());
321 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
322 }
323
TEST(PreparedModelTest,executeFencedNotSupported)324 TEST(PreparedModelTest, executeFencedNotSupported) {
325 // setup test
326 const auto mockPreparedModel = createMockPreparedModel();
327 const auto preparedModel =
328 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
329
330 // run test
331 const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
332
333 // verify result
334 ASSERT_FALSE(result.has_value());
335 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
336 }
337
TEST(PreparedModelTest,reusableExecuteSync)338 TEST(PreparedModelTest, reusableExecuteSync) {
339 // setup call
340 const uint32_t kNumberOfComputations = 2;
341 const auto mockPreparedModel = createMockPreparedModel();
342 const auto preparedModel =
343 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
344 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
345 .Times(kNumberOfComputations)
346 .WillRepeatedly(
347 Invoke(makeExecuteSynchronously(V1_0::ErrorStatus::NONE, {}, kNoTiming)));
348
349 // create execution
350 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
351 ASSERT_TRUE(createResult.has_value())
352 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
353 ASSERT_NE(createResult.value(), nullptr);
354
355 // invoke compute repeatedly
356 for (uint32_t i = 0; i < kNumberOfComputations; i++) {
357 const auto computeResult = createResult.value()->compute({});
358 EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
359 << ": " << computeResult.error().message;
360 }
361 }
362
TEST(PreparedModelTest,reusableExecuteSyncError)363 TEST(PreparedModelTest, reusableExecuteSyncError) {
364 // setup test
365 const auto mockPreparedModel = createMockPreparedModel();
366 const auto preparedModel =
367 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
368 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
369 .Times(1)
370 .WillOnce(Invoke(
371 makeExecuteSynchronously(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
372
373 // create execution
374 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
375 ASSERT_TRUE(createResult.has_value())
376 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
377 ASSERT_NE(createResult.value(), nullptr);
378
379 // invoke compute
380 const auto computeResult = createResult.value()->compute({});
381 ASSERT_FALSE(computeResult.has_value());
382 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
383 }
384
TEST(PreparedModelTest,reusableExecuteSyncTransportFailure)385 TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
386 // setup test
387 const auto mockPreparedModel = createMockPreparedModel();
388 const auto preparedModel =
389 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
390 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
391 .Times(1)
392 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
393
394 // create execution
395 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
396 ASSERT_TRUE(createResult.has_value())
397 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
398 ASSERT_NE(createResult.value(), nullptr);
399
400 // invoke compute
401 const auto computeResult = createResult.value()->compute({});
402 ASSERT_FALSE(computeResult.has_value());
403 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
404 }
405
TEST(PreparedModelTest,reusableExecuteSyncDeadObject)406 TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
407 // setup test
408 const auto mockPreparedModel = createMockPreparedModel();
409 const auto preparedModel =
410 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
411 EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _))
412 .Times(1)
413 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
414
415 // create execution
416 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
417 ASSERT_TRUE(createResult.has_value())
418 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
419 ASSERT_NE(createResult.value(), nullptr);
420
421 // invoke compute
422 const auto computeResult = createResult.value()->compute({});
423 ASSERT_FALSE(computeResult.has_value());
424 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
425 }
426
TEST(PreparedModelTest,reusableExecuteAsync)427 TEST(PreparedModelTest, reusableExecuteAsync) {
428 // setup call
429 const uint32_t kNumberOfComputations = 2;
430 const auto mockPreparedModel = createMockPreparedModel();
431 const auto preparedModel =
432 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
433 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
434 .Times(kNumberOfComputations)
435 .WillRepeatedly(Invoke(makeExecuteAsynchronously(
436 V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE, {}, kNoTiming)));
437
438 // create execution
439 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
440 ASSERT_TRUE(createResult.has_value())
441 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
442 ASSERT_NE(createResult.value(), nullptr);
443
444 // invoke compute repeatedly
445 for (uint32_t i = 0; i < kNumberOfComputations; i++) {
446 const auto computeResult = createResult.value()->compute({});
447 EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
448 << ": " << computeResult.error().message;
449 }
450 }
451
TEST(PreparedModelTest,reusableExecuteAsyncLaunchError)452 TEST(PreparedModelTest, reusableExecuteAsyncLaunchError) {
453 // setup test
454 const auto mockPreparedModel = createMockPreparedModel();
455 const auto preparedModel =
456 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
457 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
458 .Times(1)
459 .WillOnce(Invoke(makeExecuteAsynchronously(V1_0::ErrorStatus::GENERAL_FAILURE,
460 V1_0::ErrorStatus::GENERAL_FAILURE, {},
461 kNoTiming)));
462
463 // create execution
464 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
465 ASSERT_TRUE(createResult.has_value())
466 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
467 ASSERT_NE(createResult.value(), nullptr);
468
469 // invoke compute
470 const auto computeResult = createResult.value()->compute({});
471 ASSERT_FALSE(computeResult.has_value());
472 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
473 }
474
TEST(PreparedModelTest,reusableExecuteAsyncReturnError)475 TEST(PreparedModelTest, reusableExecuteAsyncReturnError) {
476 // setup test
477 const auto mockPreparedModel = createMockPreparedModel();
478 const auto preparedModel =
479 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
480 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
481 .Times(1)
482 .WillOnce(Invoke(makeExecuteAsynchronously(
483 V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
484
485 // create execution
486 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
487 ASSERT_TRUE(createResult.has_value())
488 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
489 ASSERT_NE(createResult.value(), nullptr);
490
491 // invoke compute
492 const auto computeResult = createResult.value()->compute({});
493 ASSERT_FALSE(computeResult.has_value());
494 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
495 }
496
TEST(PreparedModelTest,reusableExecuteAsyncTransportFailure)497 TEST(PreparedModelTest, reusableExecuteAsyncTransportFailure) {
498 // setup test
499 const auto mockPreparedModel = createMockPreparedModel();
500 const auto preparedModel =
501 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
502 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
503 .Times(1)
504 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
505
506 // create execution
507 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
508 ASSERT_TRUE(createResult.has_value())
509 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
510 ASSERT_NE(createResult.value(), nullptr);
511
512 // invoke compute
513 const auto computeResult = createResult.value()->compute({});
514 ASSERT_FALSE(computeResult.has_value());
515 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
516 }
517
TEST(PreparedModelTest,reusableExecuteAsyncDeadObject)518 TEST(PreparedModelTest, reusableExecuteAsyncDeadObject) {
519 // setup test
520 const auto mockPreparedModel = createMockPreparedModel();
521 const auto preparedModel =
522 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
523 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _))
524 .Times(1)
525 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
526
527 // create execution
528 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
529 ASSERT_TRUE(createResult.has_value())
530 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
531 ASSERT_NE(createResult.value(), nullptr);
532
533 // invoke compute
534 const auto computeResult = createResult.value()->compute({});
535 ASSERT_FALSE(computeResult.has_value());
536 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
537 }
538
TEST(PreparedModelTest,reusableExecuteAsyncCrash)539 TEST(PreparedModelTest, reusableExecuteAsyncCrash) {
540 // setup test
541 const auto mockPreparedModel = createMockPreparedModel();
542 const auto preparedModel =
543 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
544 const auto ret = [&mockPreparedModel]() -> hardware::Return<V1_0::ErrorStatus> {
545 mockPreparedModel->simulateCrash();
546 return V1_0::ErrorStatus::NONE;
547 };
548 EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
549
550 // create execution
551 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
552 ASSERT_TRUE(createResult.has_value())
553 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
554 ASSERT_NE(createResult.value(), nullptr);
555
556 // invoke compute
557 const auto computeResult = createResult.value()->compute({});
558 ASSERT_FALSE(computeResult.has_value());
559 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
560 }
561
TEST(PreparedModelTest,reusableExecuteFencedNotSupported)562 TEST(PreparedModelTest, reusableExecuteFencedNotSupported) {
563 // setup test
564 const auto mockPreparedModel = createMockPreparedModel();
565 const auto preparedModel =
566 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
567
568 // create execution
569 const auto createResult = preparedModel->createReusableExecution({}, {}, {});
570 ASSERT_TRUE(createResult.has_value())
571 << "Failed with " << createResult.error().code << ": " << createResult.error().message;
572 ASSERT_NE(createResult.value(), nullptr);
573
574 // invoke compute
575 const auto computeResult = createResult.value()->computeFenced({}, {}, {});
576 ASSERT_FALSE(computeResult.has_value());
577 EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
578 }
579
TEST(PreparedModelTest,configureExecutionBurst)580 TEST(PreparedModelTest, configureExecutionBurst) {
581 // setup test
582 const auto mockPreparedModel = MockPreparedModel::create();
583 const auto mockBurstContext = sp<MockBurstContext>::make();
584 EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
585 .Times(1)
586 .WillOnce(makeConfigureExecutionBurstReturn(V1_0::ErrorStatus::NONE, mockBurstContext));
587 const auto preparedModel =
588 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
589
590 // run test
591 const auto result = preparedModel->configureExecutionBurst();
592
593 // verify result
594 ASSERT_TRUE(result.has_value())
595 << "Failed with " << result.error().code << ": " << result.error().message;
596 EXPECT_NE(result.value(), nullptr);
597 }
598
TEST(PreparedModelTest,configureExecutionBurstError)599 TEST(PreparedModelTest, configureExecutionBurstError) {
600 // setup test
601 const auto mockPreparedModel = MockPreparedModel::create();
602 const auto preparedModel =
603 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
604 EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
605 .Times(1)
606 .WillOnce(
607 makeConfigureExecutionBurstReturn(V1_0::ErrorStatus::GENERAL_FAILURE, nullptr));
608
609 // run test
610 const auto result = preparedModel->configureExecutionBurst();
611
612 // verify result
613 ASSERT_FALSE(result.has_value());
614 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
615 }
616
TEST(PreparedModelTest,configureExecutionBurstTransportFailure)617 TEST(PreparedModelTest, configureExecutionBurstTransportFailure) {
618 // setup test
619 const auto mockPreparedModel = MockPreparedModel::create();
620 const auto preparedModel =
621 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
622 EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
623 .Times(1)
624 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
625
626 // run test
627 const auto result = preparedModel->configureExecutionBurst();
628
629 // verify result
630 ASSERT_FALSE(result.has_value());
631 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
632 }
633
TEST(PreparedModelTest,configureExecutionBurstDeadObject)634 TEST(PreparedModelTest, configureExecutionBurstDeadObject) {
635 // setup test
636 const auto mockPreparedModel = MockPreparedModel::create();
637 const auto preparedModel =
638 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
639 EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
640 .Times(1)
641 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
642
643 // run test
644 const auto result = preparedModel->configureExecutionBurst();
645
646 // verify result
647 ASSERT_FALSE(result.has_value());
648 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
649 }
650
TEST(PreparedModelTest,getUnderlyingResource)651 TEST(PreparedModelTest, getUnderlyingResource) {
652 // setup test
653 const auto mockPreparedModel = createMockPreparedModel();
654 const auto preparedModel =
655 PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
656
657 // run test
658 const auto resource = preparedModel->getUnderlyingResource();
659
660 // verify resource
661 const sp<V1_2::IPreparedModel>* maybeMock = std::any_cast<sp<V1_2::IPreparedModel>>(&resource);
662 ASSERT_NE(maybeMock, nullptr);
663 EXPECT_EQ(maybeMock->get(), mockPreparedModel.get());
664 }
665
666 } // namespace android::hardware::neuralnetworks::V1_2::utils
667