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 "MockBurstContext.h"
18 #include "MockFencedExecutionCallback.h"
19 #include "MockPreparedModel.h"
20 
21 #include <android/hardware/neuralnetworks/1.3/IExecutionCallback.h>
22 #include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include <nnapi/IExecution.h>
26 #include <nnapi/IPreparedModel.h>
27 #include <nnapi/TypeUtils.h>
28 #include <nnapi/Types.h>
29 #include <nnapi/hal/1.3/PreparedModel.h>
30 
31 #include <functional>
32 #include <memory>
33 
34 namespace android::hardware::neuralnetworks::V1_3::utils {
35 namespace {
36 
37 using ::testing::_;
38 using ::testing::Invoke;
39 using ::testing::InvokeWithoutArgs;
40 
41 const sp<V1_3::IPreparedModel> kInvalidPreparedModel;
42 constexpr auto kNoTiming = V1_2::Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
43                                         .timeInDriver = std::numeric_limits<uint64_t>::max()};
44 
createMockPreparedModel()45 sp<MockPreparedModel> createMockPreparedModel() {
46     const auto mockPreparedModel = MockPreparedModel::create();
47 
48     // Ensure that older calls are not used.
49     EXPECT_CALL(*mockPreparedModel, execute(_, _)).Times(0);
50     EXPECT_CALL(*mockPreparedModel, execute_1_2(_, _, _)).Times(0);
51     EXPECT_CALL(*mockPreparedModel, executeSynchronously(_, _, _)).Times(0);
52 
53     return mockPreparedModel;
54 }
55 
makeExecuteSynchronously(V1_3::ErrorStatus status,const std::vector<V1_2::OutputShape> & outputShapes,const V1_2::Timing & timing)56 auto makeExecuteSynchronously(V1_3::ErrorStatus status,
57                               const std::vector<V1_2::OutputShape>& outputShapes,
58                               const V1_2::Timing& timing) {
59     return [status, outputShapes, timing](
60                    const V1_3::Request& /*request*/, V1_2::MeasureTiming /*measureTiming*/,
61                    const V1_3::OptionalTimePoint& /*deadline*/,
62                    const V1_3::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
63                    const V1_3::IPreparedModel::executeSynchronously_1_3_cb& cb) {
64         cb(status, outputShapes, timing);
65         return hardware::Void();
66     };
67 }
makeExecuteAsynchronously(V1_3::ErrorStatus launchStatus,V1_3::ErrorStatus returnStatus,const std::vector<V1_2::OutputShape> & outputShapes,const V1_2::Timing & timing)68 auto makeExecuteAsynchronously(V1_3::ErrorStatus launchStatus, V1_3::ErrorStatus returnStatus,
69                                const std::vector<V1_2::OutputShape>& outputShapes,
70                                const V1_2::Timing& timing) {
71     return [launchStatus, returnStatus, outputShapes, timing](
72                    const V1_3::Request& /*request*/, V1_2::MeasureTiming /*measureTiming*/,
73                    const V1_3::OptionalTimePoint& /*deadline*/,
74                    const V1_3::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
75                    const sp<V1_3::IExecutionCallback>& cb) -> Return<V1_3::ErrorStatus> {
76         cb->notify_1_3(returnStatus, outputShapes, timing);
77         return launchStatus;
78     };
79 }
makeExecuteFencedReturn(V1_3::ErrorStatus status,const hardware::hidl_handle & syncFence,const sp<V1_3::IFencedExecutionCallback> & dispatchCallback)80 auto makeExecuteFencedReturn(V1_3::ErrorStatus status, const hardware::hidl_handle& syncFence,
81                              const sp<V1_3::IFencedExecutionCallback>& dispatchCallback) {
82     return [status, syncFence, dispatchCallback](
83                    const V1_3::Request& /*request*/,
84                    const hardware::hidl_vec<hardware::hidl_handle>& /*waitFor*/,
85                    V1_2::MeasureTiming /*measure*/, const V1_3::OptionalTimePoint& /*deadline*/,
86                    const V1_3::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
87                    const V1_3::OptionalTimeoutDuration& /*duration*/,
88                    const V1_3::IPreparedModel::executeFenced_cb& cb) {
89         cb(status, syncFence, dispatchCallback);
90         return hardware::Void();
91     };
92 }
makeExecuteFencedCallbackReturn(V1_3::ErrorStatus status,const V1_2::Timing & timingA,const V1_2::Timing & timingB)93 auto makeExecuteFencedCallbackReturn(V1_3::ErrorStatus status, const V1_2::Timing& timingA,
94                                      const V1_2::Timing& timingB) {
95     return [status, timingA,
96             timingB](const V1_3::IFencedExecutionCallback::getExecutionInfo_cb& cb) {
97         cb(status, timingA, timingB);
98         return hardware::Void();
99     };
100 }
makeConfigureExecutionBurstReturn(V1_0::ErrorStatus status,const sp<MockBurstContext> & burstContext)101 auto makeConfigureExecutionBurstReturn(V1_0::ErrorStatus status,
102                                        const sp<MockBurstContext>& burstContext) {
103     return [status, burstContext](
104                    const sp<V1_2::IBurstCallback>& /*callback*/,
105                    const MQDescriptorSync<V1_2::FmqRequestDatum>& /*requestChannel*/,
106                    const MQDescriptorSync<V1_2::FmqResultDatum>& /*resultChannel*/,
107                    V1_2::IPreparedModel::configureExecutionBurst_cb cb) -> hardware::Return<void> {
108         cb(status, burstContext);
109         return hardware::Void();
110     };
111 }
112 
makeTransportFailure(status_t status)113 std::function<hardware::Status()> makeTransportFailure(status_t status) {
114     return [status] { return hardware::Status::fromStatusT(status); };
115 }
116 
117 const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
118 const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
119 
120 }  // namespace
121 
TEST(PreparedModelTest,invalidPreparedModel)122 TEST(PreparedModelTest, invalidPreparedModel) {
123     // run test
124     const auto result = PreparedModel::create(kInvalidPreparedModel, /*executeSynchronously=*/true);
125 
126     // verify result
127     ASSERT_FALSE(result.has_value());
128     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
129 }
130 
TEST(PreparedModelTest,linkToDeathError)131 TEST(PreparedModelTest, linkToDeathError) {
132     // setup call
133     const auto mockPreparedModel = createMockPreparedModel();
134     const auto ret = []() -> Return<bool> { return false; };
135     EXPECT_CALL(*mockPreparedModel, linkToDeathRet()).Times(1).WillOnce(InvokeWithoutArgs(ret));
136 
137     // run test
138     const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
139 
140     // verify result
141     ASSERT_FALSE(result.has_value());
142     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
143 }
144 
TEST(PreparedModelTest,linkToDeathTransportFailure)145 TEST(PreparedModelTest, linkToDeathTransportFailure) {
146     // setup call
147     const auto mockPreparedModel = createMockPreparedModel();
148     EXPECT_CALL(*mockPreparedModel, linkToDeathRet())
149             .Times(1)
150             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
151 
152     // run test
153     const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
154 
155     // verify result
156     ASSERT_FALSE(result.has_value());
157     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
158 }
159 
TEST(PreparedModelTest,linkToDeathDeadObject)160 TEST(PreparedModelTest, linkToDeathDeadObject) {
161     // setup call
162     const auto mockPreparedModel = createMockPreparedModel();
163     EXPECT_CALL(*mockPreparedModel, linkToDeathRet())
164             .Times(1)
165             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
166 
167     // run test
168     const auto result = PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true);
169 
170     // verify result
171     ASSERT_FALSE(result.has_value());
172     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
173 }
174 
TEST(PreparedModelTest,executeSync)175 TEST(PreparedModelTest, executeSync) {
176     // setup call
177     const auto mockPreparedModel = createMockPreparedModel();
178     const auto preparedModel =
179             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
180     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
181             .Times(1)
182             .WillOnce(Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
183 
184     // run test
185     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
186 
187     // verify result
188     EXPECT_TRUE(result.has_value())
189             << "Failed with " << result.error().code << ": " << result.error().message;
190 }
191 
TEST(PreparedModelTest,executeSyncError)192 TEST(PreparedModelTest, executeSyncError) {
193     // setup test
194     const auto mockPreparedModel = createMockPreparedModel();
195     const auto preparedModel =
196             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
197     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
198             .Times(1)
199             .WillOnce(Invoke(
200                     makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
201 
202     // run test
203     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
204 
205     // verify result
206     ASSERT_FALSE(result.has_value());
207     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
208 }
209 
TEST(PreparedModelTest,executeSyncTransportFailure)210 TEST(PreparedModelTest, executeSyncTransportFailure) {
211     // setup test
212     const auto mockPreparedModel = createMockPreparedModel();
213     const auto preparedModel =
214             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
215     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
216             .Times(1)
217             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
218 
219     // run test
220     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
221 
222     // verify result
223     ASSERT_FALSE(result.has_value());
224     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
225 }
226 
TEST(PreparedModelTest,executeSyncDeadObject)227 TEST(PreparedModelTest, executeSyncDeadObject) {
228     // setup test
229     const auto mockPreparedModel = createMockPreparedModel();
230     const auto preparedModel =
231             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
232     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
233             .Times(1)
234             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
235 
236     // run test
237     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
238 
239     // verify result
240     ASSERT_FALSE(result.has_value());
241     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
242 }
243 
TEST(PreparedModelTest,executeAsync)244 TEST(PreparedModelTest, executeAsync) {
245     // setup call
246     const auto mockPreparedModel = createMockPreparedModel();
247     const auto preparedModel =
248             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
249     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
250             .Times(1)
251             .WillOnce(Invoke(makeExecuteAsynchronously(V1_3::ErrorStatus::NONE,
252                                                        V1_3::ErrorStatus::NONE, {}, kNoTiming)));
253 
254     // run test
255     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
256 
257     // verify result
258     EXPECT_TRUE(result.has_value())
259             << "Failed with " << result.error().code << ": " << result.error().message;
260 }
261 
TEST(PreparedModelTest,executeAsyncLaunchError)262 TEST(PreparedModelTest, executeAsyncLaunchError) {
263     // setup test
264     const auto mockPreparedModel = createMockPreparedModel();
265     const auto preparedModel =
266             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
267     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
268             .Times(1)
269             .WillOnce(Invoke(makeExecuteAsynchronously(V1_3::ErrorStatus::GENERAL_FAILURE,
270                                                        V1_3::ErrorStatus::GENERAL_FAILURE, {},
271                                                        kNoTiming)));
272 
273     // run test
274     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
275 
276     // verify result
277     ASSERT_FALSE(result.has_value());
278     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
279 }
280 
TEST(PreparedModelTest,executeAsyncReturnError)281 TEST(PreparedModelTest, executeAsyncReturnError) {
282     // setup test
283     const auto mockPreparedModel = createMockPreparedModel();
284     const auto preparedModel =
285             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
286     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
287             .Times(1)
288             .WillOnce(Invoke(makeExecuteAsynchronously(
289                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
290 
291     // run test
292     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
293 
294     // verify result
295     ASSERT_FALSE(result.has_value());
296     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
297 }
298 
TEST(PreparedModelTest,executeAsyncTransportFailure)299 TEST(PreparedModelTest, executeAsyncTransportFailure) {
300     // setup test
301     const auto mockPreparedModel = createMockPreparedModel();
302     const auto preparedModel =
303             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
304     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
305             .Times(1)
306             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
307 
308     // run test
309     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
310 
311     // verify result
312     ASSERT_FALSE(result.has_value());
313     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
314 }
315 
TEST(PreparedModelTest,executeAsyncDeadObject)316 TEST(PreparedModelTest, executeAsyncDeadObject) {
317     // setup test
318     const auto mockPreparedModel = createMockPreparedModel();
319     const auto preparedModel =
320             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
321     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
322             .Times(1)
323             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
324 
325     // run test
326     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
327 
328     // verify result
329     ASSERT_FALSE(result.has_value());
330     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
331 }
332 
TEST(PreparedModelTest,executeAsyncCrash)333 TEST(PreparedModelTest, executeAsyncCrash) {
334     // setup test
335     const auto mockPreparedModel = createMockPreparedModel();
336     const auto preparedModel =
337             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
338     const auto ret = [&mockPreparedModel]() -> hardware::Return<V1_3::ErrorStatus> {
339         mockPreparedModel->simulateCrash();
340         return V1_3::ErrorStatus::NONE;
341     };
342     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
343             .Times(1)
344             .WillOnce(InvokeWithoutArgs(ret));
345 
346     // run test
347     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
348 
349     // verify result
350     ASSERT_FALSE(result.has_value());
351     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
352 }
353 
TEST(PreparedModelTest,executeFenced)354 TEST(PreparedModelTest, executeFenced) {
355     // setup call
356     const auto mockPreparedModel = createMockPreparedModel();
357     const auto preparedModel =
358             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
359     const auto mockCallback = MockFencedExecutionCallback::create();
360     EXPECT_CALL(*mockCallback, getExecutionInfo(_))
361             .Times(1)
362             .WillOnce(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::NONE, kNoTiming,
363                                                              kNoTiming)));
364     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
365             .Times(1)
366             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
367 
368     // run test
369     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
370 
371     // verify result
372     ASSERT_TRUE(result.has_value())
373             << "Failed with " << result.error().code << ": " << result.error().message;
374     const auto& [syncFence, callback] = result.value();
375     EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
376     ASSERT_NE(callback, nullptr);
377 
378     // get results from callback
379     const auto callbackResult = callback();
380     ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code << ": "
381                                             << callbackResult.error().message;
382 }
383 
TEST(PreparedModelTest,executeFencedCallbackError)384 TEST(PreparedModelTest, executeFencedCallbackError) {
385     // setup call
386     const auto mockPreparedModel = createMockPreparedModel();
387     const auto preparedModel =
388             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
389     const auto mockCallback = MockFencedExecutionCallback::create();
390     EXPECT_CALL(*mockCallback, getExecutionInfo(_))
391             .Times(1)
392             .WillOnce(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::GENERAL_FAILURE,
393                                                              kNoTiming, kNoTiming)));
394     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
395             .Times(1)
396             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
397 
398     // run test
399     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
400 
401     // verify result
402     ASSERT_TRUE(result.has_value())
403             << "Failed with " << result.error().code << ": " << result.error().message;
404     const auto& [syncFence, callback] = result.value();
405     EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
406     ASSERT_NE(callback, nullptr);
407 
408     // verify callback failure
409     const auto callbackResult = callback();
410     ASSERT_FALSE(callbackResult.has_value());
411     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
412 }
413 
TEST(PreparedModelTest,executeFencedError)414 TEST(PreparedModelTest, executeFencedError) {
415     // setup test
416     const auto mockPreparedModel = createMockPreparedModel();
417     const auto preparedModel =
418             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
419     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
420             .Times(1)
421             .WillOnce(Invoke(
422                     makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
423 
424     // run test
425     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
426 
427     // verify result
428     ASSERT_FALSE(result.has_value());
429     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
430 }
431 
TEST(PreparedModelTest,executeFencedTransportFailure)432 TEST(PreparedModelTest, executeFencedTransportFailure) {
433     // setup test
434     const auto mockPreparedModel = createMockPreparedModel();
435     const auto preparedModel =
436             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
437     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
438             .Times(1)
439             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
440 
441     // run test
442     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
443 
444     // verify result
445     ASSERT_FALSE(result.has_value());
446     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
447 }
448 
TEST(PreparedModelTest,executeFencedDeadObject)449 TEST(PreparedModelTest, executeFencedDeadObject) {
450     // setup test
451     const auto mockPreparedModel = createMockPreparedModel();
452     const auto preparedModel =
453             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
454     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
455             .Times(1)
456             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
457 
458     // run test
459     const auto result = preparedModel->executeFenced({}, {}, {}, {}, {}, {}, {}, {});
460 
461     // verify result
462     ASSERT_FALSE(result.has_value());
463     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
464 }
465 
TEST(PreparedModelTest,reusableExecuteSync)466 TEST(PreparedModelTest, reusableExecuteSync) {
467     // setup call
468     const uint32_t kNumberOfComputations = 2;
469     const auto mockPreparedModel = createMockPreparedModel();
470     const auto preparedModel =
471             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
472     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
473             .Times(kNumberOfComputations)
474             .WillRepeatedly(
475                     Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
476 
477     // create execution
478     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
479     ASSERT_TRUE(createResult.has_value())
480             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
481     ASSERT_NE(createResult.value(), nullptr);
482 
483     // invoke compute repeatedly
484     for (uint32_t i = 0; i < kNumberOfComputations; i++) {
485         const auto computeResult = createResult.value()->compute({});
486         EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
487                                                << ": " << computeResult.error().message;
488     }
489 }
490 
TEST(PreparedModelTest,reusableExecuteSyncError)491 TEST(PreparedModelTest, reusableExecuteSyncError) {
492     // setup test
493     const auto mockPreparedModel = createMockPreparedModel();
494     const auto preparedModel =
495             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
496     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
497             .Times(1)
498             .WillOnce(Invoke(
499                     makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
500 
501     // create execution
502     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
503     ASSERT_TRUE(createResult.has_value())
504             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
505     ASSERT_NE(createResult.value(), nullptr);
506 
507     // invoke compute
508     const auto computeResult = createResult.value()->compute({});
509     ASSERT_FALSE(computeResult.has_value());
510     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
511 }
512 
TEST(PreparedModelTest,reusableExecuteSyncTransportFailure)513 TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
514     // setup test
515     const auto mockPreparedModel = createMockPreparedModel();
516     const auto preparedModel =
517             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
518     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
519             .Times(1)
520             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
521 
522     // create execution
523     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
524     ASSERT_TRUE(createResult.has_value())
525             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
526     ASSERT_NE(createResult.value(), nullptr);
527 
528     // invoke compute
529     const auto computeResult = createResult.value()->compute({});
530     ASSERT_FALSE(computeResult.has_value());
531     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
532 }
533 
TEST(PreparedModelTest,reusableExecuteSyncDeadObject)534 TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
535     // setup test
536     const auto mockPreparedModel = createMockPreparedModel();
537     const auto preparedModel =
538             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
539     EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
540             .Times(1)
541             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
542 
543     // create execution
544     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
545     ASSERT_TRUE(createResult.has_value())
546             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
547     ASSERT_NE(createResult.value(), nullptr);
548 
549     // invoke compute
550     const auto computeResult = createResult.value()->compute({});
551     ASSERT_FALSE(computeResult.has_value());
552     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
553 }
554 
TEST(PreparedModelTest,reusableExecuteAsync)555 TEST(PreparedModelTest, reusableExecuteAsync) {
556     // setup call
557     const uint32_t kNumberOfComputations = 2;
558     const auto mockPreparedModel = createMockPreparedModel();
559     const auto preparedModel =
560             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
561     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
562             .Times(kNumberOfComputations)
563             .WillRepeatedly(Invoke(makeExecuteAsynchronously(
564                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE, {}, kNoTiming)));
565 
566     // create execution
567     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
568     ASSERT_TRUE(createResult.has_value())
569             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
570     ASSERT_NE(createResult.value(), nullptr);
571 
572     // invoke compute repeatedly
573     for (uint32_t i = 0; i < kNumberOfComputations; i++) {
574         const auto computeResult = createResult.value()->compute({});
575         EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
576                                                << ": " << computeResult.error().message;
577     }
578 }
579 
TEST(PreparedModelTest,reusableExecuteAsyncLaunchError)580 TEST(PreparedModelTest, reusableExecuteAsyncLaunchError) {
581     // setup test
582     const auto mockPreparedModel = createMockPreparedModel();
583     const auto preparedModel =
584             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
585     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
586             .Times(1)
587             .WillOnce(Invoke(makeExecuteAsynchronously(V1_3::ErrorStatus::GENERAL_FAILURE,
588                                                        V1_3::ErrorStatus::GENERAL_FAILURE, {},
589                                                        kNoTiming)));
590 
591     // create execution
592     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
593     ASSERT_TRUE(createResult.has_value())
594             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
595     ASSERT_NE(createResult.value(), nullptr);
596 
597     // invoke compute
598     const auto computeResult = createResult.value()->compute({});
599     ASSERT_FALSE(computeResult.has_value());
600     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
601 }
602 
TEST(PreparedModelTest,reusableExecuteAsyncReturnError)603 TEST(PreparedModelTest, reusableExecuteAsyncReturnError) {
604     // setup test
605     const auto mockPreparedModel = createMockPreparedModel();
606     const auto preparedModel =
607             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
608     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
609             .Times(1)
610             .WillOnce(Invoke(makeExecuteAsynchronously(
611                     V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
612 
613     // run test
614     const auto result = preparedModel->execute({}, {}, {}, {}, {}, {});
615 
616     // verify result
617     ASSERT_FALSE(result.has_value());
618     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
619 }
620 
TEST(PreparedModelTest,reusableExecuteAsyncTransportFailure)621 TEST(PreparedModelTest, reusableExecuteAsyncTransportFailure) {
622     // setup test
623     const auto mockPreparedModel = createMockPreparedModel();
624     const auto preparedModel =
625             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
626     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
627             .Times(1)
628             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
629 
630     // create execution
631     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
632     ASSERT_TRUE(createResult.has_value())
633             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
634     ASSERT_NE(createResult.value(), nullptr);
635 
636     // invoke compute
637     const auto computeResult = createResult.value()->compute({});
638     ASSERT_FALSE(computeResult.has_value());
639     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
640 }
641 
TEST(PreparedModelTest,reusableExecuteAsyncDeadObject)642 TEST(PreparedModelTest, reusableExecuteAsyncDeadObject) {
643     // setup test
644     const auto mockPreparedModel = createMockPreparedModel();
645     const auto preparedModel =
646             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
647     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
648             .Times(1)
649             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
650 
651     // create execution
652     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
653     ASSERT_TRUE(createResult.has_value())
654             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
655     ASSERT_NE(createResult.value(), nullptr);
656 
657     // invoke compute
658     const auto computeResult = createResult.value()->compute({});
659     ASSERT_FALSE(computeResult.has_value());
660     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
661 }
662 
TEST(PreparedModelTest,reusableExecuteAsyncCrash)663 TEST(PreparedModelTest, reusableExecuteAsyncCrash) {
664     // setup test
665     const auto mockPreparedModel = createMockPreparedModel();
666     const auto preparedModel =
667             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
668     const auto ret = [&mockPreparedModel]() -> hardware::Return<V1_3::ErrorStatus> {
669         mockPreparedModel->simulateCrash();
670         return V1_3::ErrorStatus::NONE;
671     };
672     EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
673             .Times(1)
674             .WillOnce(InvokeWithoutArgs(ret));
675 
676     // create execution
677     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
678     ASSERT_TRUE(createResult.has_value())
679             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
680     ASSERT_NE(createResult.value(), nullptr);
681 
682     // invoke compute
683     const auto computeResult = createResult.value()->compute({});
684     ASSERT_FALSE(computeResult.has_value());
685     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
686 }
687 
TEST(PreparedModelTest,reusableExecuteFenced)688 TEST(PreparedModelTest, reusableExecuteFenced) {
689     // setup call
690     const uint32_t kNumberOfComputations = 2;
691     const auto mockPreparedModel = createMockPreparedModel();
692     const auto preparedModel =
693             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
694     const auto mockCallback = MockFencedExecutionCallback::create();
695     EXPECT_CALL(*mockCallback, getExecutionInfo(_))
696             .Times(kNumberOfComputations)
697             .WillRepeatedly(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::NONE,
698                                                                    kNoTiming, kNoTiming)));
699     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
700             .Times(kNumberOfComputations)
701             .WillRepeatedly(
702                     Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
703 
704     // create execution
705     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
706     ASSERT_TRUE(createResult.has_value())
707             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
708     ASSERT_NE(createResult.value(), nullptr);
709 
710     // invoke compute repeatedly
711     for (uint32_t i = 0; i < kNumberOfComputations; i++) {
712         const auto computeResult = createResult.value()->computeFenced({}, {}, {});
713         ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
714                                                << ": " << computeResult.error().message;
715         const auto& [syncFence, callback] = computeResult.value();
716         EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
717         ASSERT_NE(callback, nullptr);
718 
719         // get results from callback
720         const auto callbackResult = callback();
721         ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code
722                                                 << ": " << callbackResult.error().message;
723     }
724 }
725 
TEST(PreparedModelTest,reusableExecuteFencedCallbackError)726 TEST(PreparedModelTest, reusableExecuteFencedCallbackError) {
727     // setup call
728     const auto mockPreparedModel = createMockPreparedModel();
729     const auto preparedModel =
730             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
731     const auto mockCallback = MockFencedExecutionCallback::create();
732     EXPECT_CALL(*mockCallback, getExecutionInfo(_))
733             .Times(1)
734             .WillOnce(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::GENERAL_FAILURE,
735                                                              kNoTiming, kNoTiming)));
736     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
737             .Times(1)
738             .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
739 
740     // create execution
741     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
742     ASSERT_TRUE(createResult.has_value())
743             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
744     ASSERT_NE(createResult.value(), nullptr);
745 
746     // invoke compute
747     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
748     ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code << ": "
749                                            << computeResult.error().message;
750     const auto& [syncFence, callback] = computeResult.value();
751     EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
752     ASSERT_NE(callback, nullptr);
753 
754     // verify callback failure
755     const auto callbackResult = callback();
756     ASSERT_FALSE(callbackResult.has_value());
757     EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
758 }
759 
TEST(PreparedModelTest,reusableExecuteFencedError)760 TEST(PreparedModelTest, reusableExecuteFencedError) {
761     // setup test
762     const auto mockPreparedModel = createMockPreparedModel();
763     const auto preparedModel =
764             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
765     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
766             .Times(1)
767             .WillOnce(Invoke(
768                     makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
769 
770     // create execution
771     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
772     ASSERT_TRUE(createResult.has_value())
773             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
774     ASSERT_NE(createResult.value(), nullptr);
775 
776     // invoke compute
777     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
778     ASSERT_FALSE(computeResult.has_value());
779     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
780 }
781 
TEST(PreparedModelTest,reusableExecuteFencedTransportFailure)782 TEST(PreparedModelTest, reusableExecuteFencedTransportFailure) {
783     // setup test
784     const auto mockPreparedModel = createMockPreparedModel();
785     const auto preparedModel =
786             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
787     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
788             .Times(1)
789             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
790 
791     // create execution
792     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
793     ASSERT_TRUE(createResult.has_value())
794             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
795     ASSERT_NE(createResult.value(), nullptr);
796 
797     // invoke compute
798     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
799     ASSERT_FALSE(computeResult.has_value());
800     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
801 }
802 
TEST(PreparedModelTest,reusableExecuteFencedDeadObject)803 TEST(PreparedModelTest, reusableExecuteFencedDeadObject) {
804     // setup test
805     const auto mockPreparedModel = createMockPreparedModel();
806     const auto preparedModel =
807             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
808     EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
809             .Times(1)
810             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
811 
812     // create execution
813     const auto createResult = preparedModel->createReusableExecution({}, {}, {}, {}, {});
814     ASSERT_TRUE(createResult.has_value())
815             << "Failed with " << createResult.error().code << ": " << createResult.error().message;
816     ASSERT_NE(createResult.value(), nullptr);
817 
818     // invoke compute
819     const auto computeResult = createResult.value()->computeFenced({}, {}, {});
820     ASSERT_FALSE(computeResult.has_value());
821     EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
822 }
TEST(PreparedModelTest,configureExecutionBurst)823 TEST(PreparedModelTest, configureExecutionBurst) {
824     // setup test
825     const auto mockPreparedModel = MockPreparedModel::create();
826     const auto mockBurstContext = sp<MockBurstContext>::make();
827     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
828             .Times(1)
829             .WillOnce(makeConfigureExecutionBurstReturn(V1_0::ErrorStatus::NONE, mockBurstContext));
830     const auto preparedModel =
831             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
832 
833     // run test
834     const auto result = preparedModel->configureExecutionBurst();
835 
836     // verify result
837     ASSERT_TRUE(result.has_value())
838             << "Failed with " << result.error().code << ": " << result.error().message;
839     EXPECT_NE(result.value(), nullptr);
840 }
841 
TEST(PreparedModelTest,configureExecutionBurstError)842 TEST(PreparedModelTest, configureExecutionBurstError) {
843     // setup test
844     const auto mockPreparedModel = MockPreparedModel::create();
845     const auto preparedModel =
846             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
847     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
848             .Times(1)
849             .WillOnce(
850                     makeConfigureExecutionBurstReturn(V1_0::ErrorStatus::GENERAL_FAILURE, nullptr));
851 
852     // run test
853     const auto result = preparedModel->configureExecutionBurst();
854 
855     // verify result
856     ASSERT_FALSE(result.has_value());
857     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
858 }
859 
TEST(PreparedModelTest,configureExecutionBurstTransportFailure)860 TEST(PreparedModelTest, configureExecutionBurstTransportFailure) {
861     // setup test
862     const auto mockPreparedModel = MockPreparedModel::create();
863     const auto preparedModel =
864             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
865     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
866             .Times(1)
867             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
868 
869     // run test
870     const auto result = preparedModel->configureExecutionBurst();
871 
872     // verify result
873     ASSERT_FALSE(result.has_value());
874     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
875 }
876 
TEST(PreparedModelTest,configureExecutionBurstDeadObject)877 TEST(PreparedModelTest, configureExecutionBurstDeadObject) {
878     // setup test
879     const auto mockPreparedModel = MockPreparedModel::create();
880     const auto preparedModel =
881             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
882     EXPECT_CALL(*mockPreparedModel, configureExecutionBurst(_, _, _, _))
883             .Times(1)
884             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
885 
886     // run test
887     const auto result = preparedModel->configureExecutionBurst();
888 
889     // verify result
890     ASSERT_FALSE(result.has_value());
891     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
892 }
893 
TEST(PreparedModelTest,getUnderlyingResource)894 TEST(PreparedModelTest, getUnderlyingResource) {
895     // setup test
896     const auto mockPreparedModel = createMockPreparedModel();
897     const auto preparedModel =
898             PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
899 
900     // run test
901     const auto resource = preparedModel->getUnderlyingResource();
902 
903     // verify resource
904     const sp<V1_3::IPreparedModel>* maybeMock = std::any_cast<sp<V1_3::IPreparedModel>>(&resource);
905     ASSERT_NE(maybeMock, nullptr);
906     EXPECT_EQ(maybeMock->get(), mockPreparedModel.get());
907 }
908 
909 }  // namespace android::hardware::neuralnetworks::V1_3::utils
910