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