blob: 5e2ad79df597b54ba16770f80c067a7d57eb04bd [file] [log] [blame]
Michael Butler6e492a62020-12-10 15:38:45 -08001/*
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
Michael Butler8414a6e2021-03-10 18:41:05 -080019#include "MockBurstContext.h"
20
Michael Butler6e492a62020-12-10 15:38:45 -080021#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
Xusong Wang5f6bedb2021-03-03 16:20:37 -080024#include <nnapi/IExecution.h>
Michael Butler6e492a62020-12-10 15:38:45 -080025#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
33namespace android::hardware::neuralnetworks::V1_2::utils {
34namespace {
35
36using ::testing::_;
37using ::testing::Invoke;
38using ::testing::InvokeWithoutArgs;
39
40const sp<V1_2::IPreparedModel> kInvalidPreparedModel;
41constexpr auto kNoTiming = V1_2::Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
42 .timeInDriver = std::numeric_limits<uint64_t>::max()};
43
44sp<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
53auto 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}
63auto 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}
Michael Butler8414a6e2021-03-10 18:41:05 -080073auto 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}
Michael Butler6e492a62020-12-10 15:38:45 -080084
85std::function<hardware::Status()> makeTransportFailure(status_t status) {
86 return [status] { return hardware::Status::fromStatusT(status); };
87}
88
89const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
90const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
91
92} // namespace
93
94TEST(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
103TEST(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
117TEST(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
132TEST(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
147TEST(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
164TEST(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
182TEST(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
199TEST(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
216TEST(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
234TEST(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
253TEST(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
271TEST(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
288TEST(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
305TEST(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
324TEST(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
Xusong Wang5f6bedb2021-03-03 16:20:37 -0800338TEST(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
363TEST(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
385TEST(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
406TEST(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
427TEST(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
452TEST(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
475TEST(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
497TEST(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
518TEST(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
539TEST(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
562TEST(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
Michael Butler8414a6e2021-03-10 18:41:05 -0800580TEST(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
599TEST(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
617TEST(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
634TEST(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}
Michael Butler6e492a62020-12-10 15:38:45 -0800650
651TEST(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