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