1 /*
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 
17 #include "MockBurst.h"
18 #include "MockFencedExecutionCallback.h"
19 #include "MockPreparedModel.h"
20 
21 #include <aidl/android/hardware/neuralnetworks/IFencedExecutionCallback.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/aidl/PreparedModel.h>
29 
30 #include <functional>
31 #include <memory>
32 
33 namespace aidl::android::hardware::neuralnetworks::utils {
34 namespace {
35 
36 using ::testing::_;
37 using ::testing::DoAll;
38 using ::testing::Invoke;
39 using ::testing::InvokeWithoutArgs;
40 using ::testing::SetArgPointee;
41 
42 const std::shared_ptr<IPreparedModel> kInvalidPreparedModel;
43 constexpr auto kNoTiming = Timing{.timeOnDeviceNs = -1, .timeInDriverNs = -1};
44 
__anon2b5db16f0202null45 constexpr auto makeStatusOk = [] { return ndk::ScopedAStatus::ok(); };
46 
__anon2b5db16f0302null47 constexpr auto makeGeneralFailure = [] {
48     return ndk::ScopedAStatus::fromServiceSpecificError(
49             static_cast<int32_t>(ErrorStatus::GENERAL_FAILURE));
50 };
__anon2b5db16f0402null51 constexpr auto makeGeneralTransportFailure = [] {
52     return ndk::ScopedAStatus::fromStatus(STATUS_NO_MEMORY);
53 };
__anon2b5db16f0502null54 constexpr auto makeDeadObjectFailure = [] {
55     return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
56 };
57 
makeFencedExecutionResult(const std::shared_ptr<MockFencedExecutionCallback> & callback)58 auto makeFencedExecutionResult(const std::shared_ptr<MockFencedExecutionCallback>& callback) {
59     return [callback](const Request& /*request*/,
60                       const std::vector<ndk::ScopedFileDescriptor>& /*waitFor*/,
61                       bool /*measureTiming*/, int64_t /*deadline*/, int64_t /*loopTimeoutDuration*/,
62                       int64_t /*duration*/, FencedExecutionResult* fencedExecutionResult) {
63         *fencedExecutionResult = FencedExecutionResult{.callback = callback,
64                                                        .syncFence = ndk::ScopedFileDescriptor(-1)};
65         return ndk::ScopedAStatus::ok();
66     };
67 }
68 
69 }  // namespace
70 
TEST(PreparedModelTest,invalidPreparedModel)71 TEST(PreparedModelTest, invalidPreparedModel) {
72     // run test
73     const auto result = PreparedModel::create(kInvalidPreparedModel);
74 
75     // verify result
76     ASSERT_FALSE(result.has_value());
77     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
78 }
79 
TEST(PreparedModelTest,executeSync)80 TEST(PreparedModelTest, executeSync) {
81     // setup call
82     const auto mockPreparedModel = MockPreparedModel::create();
83     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
84     const auto mockExecutionResult = ExecutionResult{
85             .outputSufficientSize = true,
86             .outputShapes = {},
87             .timing = kNoTiming,
88     };
89     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
90             .Times(1)
91             .WillOnce(
92                     DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
93 
94     // run test
95     const auto result = preparedModel->execute({}, {}, {}, {});
96 
97     // verify result
98     EXPECT_TRUE(result.has_value())
99             << "Failed with " << result.error().code << ": " << result.error().message;
100 }
101 
TEST(PreparedModelTest,executeSyncError)102 TEST(PreparedModelTest, executeSyncError) {
103     // setup test
104     const auto mockPreparedModel = MockPreparedModel::create();
105     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
106     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
107             .Times(1)
108             .WillOnce(Invoke(makeGeneralFailure));
109 
110     // run test
111     const auto result = preparedModel->execute({}, {}, {}, {});
112 
113     // verify result
114     ASSERT_FALSE(result.has_value());
115     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
116 }
117 
TEST(PreparedModelTest,executeSyncTransportFailure)118 TEST(PreparedModelTest, executeSyncTransportFailure) {
119     // setup test
120     const auto mockPreparedModel = MockPreparedModel::create();
121     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
122     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
123             .Times(1)
124             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
125 
126     // run test
127     const auto result = preparedModel->execute({}, {}, {}, {});
128 
129     // verify result
130     ASSERT_FALSE(result.has_value());
131     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
132 }
133 
TEST(PreparedModelTest,executeSyncDeadObject)134 TEST(PreparedModelTest, executeSyncDeadObject) {
135     // setup test
136     const auto mockPreparedModel = MockPreparedModel::create();
137     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
138     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
139             .Times(1)
140             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
141 
142     // run test
143     const auto result = preparedModel->execute({}, {}, {}, {});
144 
145     // verify result
146     ASSERT_FALSE(result.has_value());
147     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
148 }
149 
TEST(PreparedModelTest,executeFenced)150 TEST(PreparedModelTest, executeFenced) {
151     // setup call
152     const auto mockPreparedModel = MockPreparedModel::create();
153     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
154     const auto mockCallback = MockFencedExecutionCallback::create();
155     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
156             .Times(1)
157             .WillOnce(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
158                             SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
159     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
160             .Times(1)
161             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
162 
163     // run test
164     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
165 
166     // verify result
167     ASSERT_TRUE(result.has_value())
168             << "Failed with " << result.error().code << ": " << result.error().message;
169     const auto& [syncFence, callback] = result.value();
170     EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
171     ASSERT_NE(callback, nullptr);
172 
173     // get results from callback
174     const auto callbackResult = callback();
175     ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
176                                             << callbackResult.error().message;
177 }
178 
TEST(PreparedModelTest,executeFencedCallbackError)179 TEST(PreparedModelTest, executeFencedCallbackError) {
180     // setup call
181     const auto mockPreparedModel = MockPreparedModel::create();
182     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
183     const auto mockCallback = MockFencedExecutionCallback::create();
184     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
185             .Times(1)
186             .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
187                                    SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
188                                    Invoke(makeStatusOk))));
189     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
190             .Times(1)
191             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
192 
193     // run test
194     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
195 
196     // verify result
197     ASSERT_TRUE(result.has_value())
198             << "Failed with " << result.error().code << ": " << result.error().message;
199     const auto& [syncFence, callback] = result.value();
200     EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
201     ASSERT_NE(callback, nullptr);
202 
203     // verify callback failure
204     const auto callbackResult = callback();
205     ASSERT_FALSE(callbackResult.has_value());
206     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
207 }
208 
TEST(PreparedModelTest,executeFencedError)209 TEST(PreparedModelTest, executeFencedError) {
210     // setup test
211     const auto mockPreparedModel = MockPreparedModel::create();
212     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
213     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
214             .Times(1)
215             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
216 
217     // run test
218     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
219 
220     // verify result
221     ASSERT_FALSE(result.has_value());
222     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
223 }
224 
TEST(PreparedModelTest,executeFencedTransportFailure)225 TEST(PreparedModelTest, executeFencedTransportFailure) {
226     // setup test
227     const auto mockPreparedModel = MockPreparedModel::create();
228     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
229     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
230             .Times(1)
231             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
232 
233     // run test
234     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
235 
236     // verify result
237     ASSERT_FALSE(result.has_value());
238     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
239 }
240 
TEST(PreparedModelTest,executeFencedDeadObject)241 TEST(PreparedModelTest, executeFencedDeadObject) {
242     // setup test
243     const auto mockPreparedModel = MockPreparedModel::create();
244     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
245     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
246             .Times(1)
247             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
248 
249     // run test
250     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {});
251 
252     // verify result
253     ASSERT_FALSE(result.has_value());
254     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
255 }
256 
TEST(PreparedModelTest,reusableExecuteSync)257 TEST(PreparedModelTest, reusableExecuteSync) {
258     // setup call
259     const uint32_t kNumberOfComputations = 2;
260     const auto mockPreparedModel = MockPreparedModel::create();
261     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
262     const auto mockExecutionResult = ExecutionResult{
263             .outputSufficientSize = true,
264             .outputShapes = {},
265             .timing = kNoTiming,
266     };
267     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
268             .Times(kNumberOfComputations)
269             .WillRepeatedly(
270                     DoAll(SetArgPointee<4>(mockExecutionResult), InvokeWithoutArgs(makeStatusOk)));
271 
272     // create execution
273     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
274     ASSERT_TRUE(createResult.has_value())
275             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
276     ASSERT_NE(createResult.value(), nullptr);
277 
278     // invoke compute repeatedly
279     for (uint32_t i = 0; i < kNumberOfComputations; i++) {
280         const auto computeResult = createResult.value()->compute({});
281         EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
282                                                << ": " << computeResult.error().message;
283     }
284 }
285 
TEST(PreparedModelTest,reusableExecuteSyncError)286 TEST(PreparedModelTest, reusableExecuteSyncError) {
287     // setup test
288     const auto mockPreparedModel = MockPreparedModel::create();
289     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
290     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
291             .Times(1)
292             .WillOnce(Invoke(makeGeneralFailure));
293 
294     // create execution
295     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
296     ASSERT_TRUE(createResult.has_value())
297             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
298     ASSERT_NE(createResult.value(), nullptr);
299 
300     // invoke compute
301     const auto computeResult = createResult.value()->compute({});
302     ASSERT_FALSE(computeResult.has_value());
303     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
304 }
305 
TEST(PreparedModelTest,reusableExecuteSyncTransportFailure)306 TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
307     // setup test
308     const auto mockPreparedModel = MockPreparedModel::create();
309     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
310     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
311             .Times(1)
312             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
313 
314     // create execution
315     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
316     ASSERT_TRUE(createResult.has_value())
317             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
318     ASSERT_NE(createResult.value(), nullptr);
319 
320     // invoke compute
321     const auto computeResult = createResult.value()->compute({});
322     ASSERT_FALSE(computeResult.has_value());
323     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
324 }
325 
TEST(PreparedModelTest,reusableExecuteSyncDeadObject)326 TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
327     // setup test
328     const auto mockPreparedModel = MockPreparedModel::create();
329     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
330     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _, _, _))
331             .Times(1)
332             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
333 
334     // create execution
335     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
336     ASSERT_TRUE(createResult.has_value())
337             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
338     ASSERT_NE(createResult.value(), nullptr);
339 
340     // invoke compute
341     const auto computeResult = createResult.value()->compute({});
342     ASSERT_FALSE(computeResult.has_value());
343     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
344 }
345 
TEST(PreparedModelTest,reusableExecuteFenced)346 TEST(PreparedModelTest, reusableExecuteFenced) {
347     // setup call
348     const uint32_t kNumberOfComputations = 2;
349     const auto mockPreparedModel = MockPreparedModel::create();
350     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
351     const auto mockCallback = MockFencedExecutionCallback::create();
352     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
353             .Times(kNumberOfComputations)
354             .WillRepeatedly(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
355                                   SetArgPointee<2>(ErrorStatus::NONE), Invoke(makeStatusOk)));
356     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
357             .Times(kNumberOfComputations)
358             .WillRepeatedly(Invoke(makeFencedExecutionResult(mockCallback)));
359 
360     // create execution
361     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
362     ASSERT_TRUE(createResult.has_value())
363             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
364     ASSERT_NE(createResult.value(), nullptr);
365 
366     // invoke compute repeatedly
367     for (uint32_t i = 0; i < kNumberOfComputations; i++) {
368         const auto computeResult = createResult.value()->computeFenced({}, {}, {});
369         ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
370                                                << ": " << computeResult.error().message;
371         const auto& [syncFence, callback] = computeResult.value();
372         EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
373         ASSERT_NE(callback, nullptr);
374 
375         // get results from callback
376         const auto callbackResult = callback();
377         ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code
378                                                 << ": " << callbackResult.error().message;
379     }
380 }
381 
TEST(PreparedModelTest,reusableExecuteFencedCallbackError)382 TEST(PreparedModelTest, reusableExecuteFencedCallbackError) {
383     // setup call
384     const auto mockPreparedModel = MockPreparedModel::create();
385     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
386     const auto mockCallback = MockFencedExecutionCallback::create();
387     EXPECT_CALL(*mockCallback, getExecutionInfo(_, _, _))
388             .Times(1)
389             .WillOnce(Invoke(DoAll(SetArgPointee<0>(kNoTiming), SetArgPointee<1>(kNoTiming),
390                                    SetArgPointee<2>(ErrorStatus::GENERAL_FAILURE),
391                                    Invoke(makeStatusOk))));
392     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
393             .Times(1)
394             .WillOnce(Invoke(makeFencedExecutionResult(mockCallback)));
395 
396     // create execution
397     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
398     ASSERT_TRUE(createResult.has_value())
399             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
400     ASSERT_NE(createResult.value(), nullptr);
401 
402     // invoke compute
403     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
404     ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code << ": "
405                                            << computeResult.error().message;
406     const auto& [syncFence, callback] = computeResult.value();
407     EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
408     ASSERT_NE(callback, nullptr);
409 
410     // verify callback failure
411     const auto callbackResult = callback();
412     ASSERT_FALSE(callbackResult.has_value());
413     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
414 }
415 
TEST(PreparedModelTest,reusableExecuteFencedError)416 TEST(PreparedModelTest, reusableExecuteFencedError) {
417     // setup test
418     const auto mockPreparedModel = MockPreparedModel::create();
419     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
420     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
421             .Times(1)
422             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
423 
424     // create execution
425     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
426     ASSERT_TRUE(createResult.has_value())
427             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
428     ASSERT_NE(createResult.value(), nullptr);
429 
430     // invoke compute
431     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
432     ASSERT_FALSE(computeResult.has_value());
433     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
434 }
435 
TEST(PreparedModelTest,reusableExecuteFencedTransportFailure)436 TEST(PreparedModelTest, reusableExecuteFencedTransportFailure) {
437     // setup test
438     const auto mockPreparedModel = MockPreparedModel::create();
439     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
440     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
441             .Times(1)
442             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
443 
444     // create execution
445     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
446     ASSERT_TRUE(createResult.has_value())
447             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
448     ASSERT_NE(createResult.value(), nullptr);
449 
450     // invoke compute
451     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
452     ASSERT_FALSE(computeResult.has_value());
453     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
454 }
455 
TEST(PreparedModelTest,reusableExecuteFencedDeadObject)456 TEST(PreparedModelTest, reusableExecuteFencedDeadObject) {
457     // setup test
458     const auto mockPreparedModel = MockPreparedModel::create();
459     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
460     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
461             .Times(1)
462             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
463 
464     // create execution
465     const auto createResult = preparedModel->createReusableExecution({}, {}, {});
466     ASSERT_TRUE(createResult.has_value())
467             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
468     ASSERT_NE(createResult.value(), nullptr);
469 
470     // invoke compute
471     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
472     ASSERT_FALSE(computeResult.has_value());
473     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
474 }
475 
TEST(PreparedModelTest,configureExecutionBurst)476 TEST(PreparedModelTest, configureExecutionBurst) {
477     // setup test
478     const auto mockPreparedModel = MockPreparedModel::create();
479     const auto mockBurst = ndk::SharedRefBase::make<MockBurst>();
480     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
481             .Times(1)
482             .WillOnce(DoAll(SetArgPointee<0>(mockBurst), Invoke(makeStatusOk)));
483     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
484 
485     // run test
486     const auto result = preparedModel->configureExecutionBurst();
487 
488     // verify result
489     ASSERT_TRUE(result.has_value())
490             << "Failed with " << result.error().code << ": " << result.error().message;
491     EXPECT_NE(result.value(), nullptr);
492 }
493 
TEST(PreparedModelTest,configureExecutionBurstError)494 TEST(PreparedModelTest, configureExecutionBurstError) {
495     // setup test
496     const auto mockPreparedModel = MockPreparedModel::create();
497     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
498             .Times(1)
499             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
500     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
501 
502     // run test
503     const auto result = preparedModel->configureExecutionBurst();
504 
505     // verify result
506     ASSERT_FALSE(result.has_value());
507     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
508 }
509 
TEST(PreparedModelTest,configureExecutionBurstTransportFailure)510 TEST(PreparedModelTest, configureExecutionBurstTransportFailure) {
511     // setup test
512     const auto mockPreparedModel = MockPreparedModel::create();
513     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
514             .Times(1)
515             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
516     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
517 
518     // run test
519     const auto result = preparedModel->configureExecutionBurst();
520 
521     // verify result
522     ASSERT_FALSE(result.has_value());
523     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
524 }
525 
TEST(PreparedModelTest,configureExecutionBurstDeadObject)526 TEST(PreparedModelTest, configureExecutionBurstDeadObject) {
527     // setup test
528     const auto mockPreparedModel = MockPreparedModel::create();
529     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_))
530             .Times(1)
531             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
532     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
533 
534     // run test
535     const auto result = preparedModel->configureExecutionBurst();
536 
537     // verify result
538     ASSERT_FALSE(result.has_value());
539     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
540 }
541 
TEST(PreparedModelTest,getUnderlyingResource)542 TEST(PreparedModelTest, getUnderlyingResource) {
543     // setup test
544     const auto mockPreparedModel = MockPreparedModel::create();
545     const auto preparedModel = PreparedModel::create(mockPreparedModel).value();
546 
547     // run test
548     const auto resource = preparedModel->getUnderlyingResource();
549 
550     // verify resource
551     const std::shared_ptr<IPreparedModel>* maybeMock =
552             std::any_cast<std::shared_ptr<IPreparedModel>>(&resource);
553     ASSERT_NE(maybeMock, nullptr);
554     EXPECT_EQ(maybeMock->get(), mockPreparedModel.get());
555 }
556 
557 }  // namespace aidl::android::hardware::neuralnetworks::utils
558