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