1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "MockDevice.h"
18 #include "MockPreparedModel.h"
19
20 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <nnapi/IDevice.h>
24 #include <nnapi/TypeUtils.h>
25 #include <nnapi/Types.h>
26 #include <nnapi/hal/1.1/Device.h>
27
28 #include <functional>
29 #include <memory>
30 #include <string>
31
32 namespace android::hardware::neuralnetworks::V1_1::utils {
33 namespace {
34
35 using ::testing::_;
36 using ::testing::Invoke;
37 using ::testing::InvokeWithoutArgs;
38
39 const nn::Model kSimpleModel = {
40 .main = {.operands = {{.type = nn::OperandType::TENSOR_FLOAT32,
41 .dimensions = {1},
42 .lifetime = nn::Operand::LifeTime::SUBGRAPH_INPUT},
43 {.type = nn::OperandType::TENSOR_FLOAT32,
44 .dimensions = {1},
45 .lifetime = nn::Operand::LifeTime::SUBGRAPH_OUTPUT}},
46 .operations = {{.type = nn::OperationType::RELU, .inputs = {0}, .outputs = {1}}},
47 .inputIndexes = {0},
48 .outputIndexes = {1}}};
49
50 const std::string kName = "Google-MockV1";
51 const std::string kInvalidName = "";
52 const sp<V1_1::IDevice> kInvalidDevice;
53 constexpr V1_0::PerformanceInfo kNoPerformanceInfo = {
54 .execTime = std::numeric_limits<float>::max(),
55 .powerUsage = std::numeric_limits<float>::max()};
56
57 template <typename... Args>
makeCallbackReturn(Args &&...args)58 auto makeCallbackReturn(Args&&... args) {
59 return [argPack = std::make_tuple(std::forward<Args>(args)...)](const auto& cb) {
60 std::apply(cb, argPack);
61 return Void();
62 };
63 }
64
createMockDevice()65 sp<MockDevice> createMockDevice() {
66 const auto mockDevice = MockDevice::create();
67
68 // Setup default actions for each relevant call.
69 const auto getCapabilities_ret =
70 makeCallbackReturn(V1_0::ErrorStatus::NONE,
71 V1_1::Capabilities{
72 .float32Performance = kNoPerformanceInfo,
73 .quantized8Performance = kNoPerformanceInfo,
74 .relaxedFloat32toFloat16Performance = kNoPerformanceInfo,
75 });
76
77 // Setup default actions for each relevant call.
78 ON_CALL(*mockDevice, getCapabilities_1_1(_)).WillByDefault(Invoke(getCapabilities_ret));
79
80 // Ensure that older calls are not used.
81 EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(0);
82 EXPECT_CALL(*mockDevice, getSupportedOperations(_, _)).Times(0);
83 EXPECT_CALL(*mockDevice, prepareModel(_, _)).Times(0);
84
85 // These EXPECT_CALL(...).Times(testing::AnyNumber()) calls are to suppress warnings on the
86 // uninteresting methods calls.
87 EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(testing::AnyNumber());
88
89 return mockDevice;
90 }
91
makePreparedModelReturn(V1_0::ErrorStatus launchStatus,V1_0::ErrorStatus returnStatus,const sp<V1_0::utils::MockPreparedModel> & preparedModel)92 auto makePreparedModelReturn(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
93 const sp<V1_0::utils::MockPreparedModel>& preparedModel) {
94 return [launchStatus, returnStatus, preparedModel](const V1_1::Model& /*model*/,
95 V1_1::ExecutionPreference /*preference*/,
96 const sp<V1_0::IPreparedModelCallback>& cb)
97 -> hardware::Return<V1_0::ErrorStatus> {
98 cb->notify(returnStatus, preparedModel).isOk();
99 return launchStatus;
100 };
101 }
102
makeTransportFailure(status_t status)103 std::function<hardware::Status()> makeTransportFailure(status_t status) {
104 return [status] { return hardware::Status::fromStatusT(status); };
105 }
106
107 const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
108 const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
109
110 } // namespace
111
TEST(DeviceTest,invalidName)112 TEST(DeviceTest, invalidName) {
113 // run test
114 const auto device = MockDevice::create();
115 const auto result = Device::create(kInvalidName, device);
116
117 // verify result
118 ASSERT_FALSE(result.has_value());
119 EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
120 }
121
TEST(DeviceTest,invalidDevice)122 TEST(DeviceTest, invalidDevice) {
123 // run test
124 const auto result = Device::create(kName, kInvalidDevice);
125
126 // verify result
127 ASSERT_FALSE(result.has_value());
128 EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
129 }
130
TEST(DeviceTest,getCapabilitiesError)131 TEST(DeviceTest, getCapabilitiesError) {
132 // setup call
133 const auto mockDevice = createMockDevice();
134 const auto ret =
135 makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
136 V1_1::Capabilities{
137 .float32Performance = kNoPerformanceInfo,
138 .quantized8Performance = kNoPerformanceInfo,
139 .relaxedFloat32toFloat16Performance = kNoPerformanceInfo,
140 });
141 EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(1).WillOnce(Invoke(ret));
142
143 // run test
144 const auto result = Device::create(kName, mockDevice);
145
146 // verify result
147 ASSERT_FALSE(result.has_value());
148 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
149 }
150
TEST(DeviceTest,getCapabilitiesTransportFailure)151 TEST(DeviceTest, getCapabilitiesTransportFailure) {
152 // setup call
153 const auto mockDevice = createMockDevice();
154 EXPECT_CALL(*mockDevice, getCapabilities_1_1(_))
155 .Times(1)
156 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
157
158 // run test
159 const auto result = Device::create(kName, mockDevice);
160
161 // verify result
162 ASSERT_FALSE(result.has_value());
163 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
164 }
165
TEST(DeviceTest,getCapabilitiesDeadObject)166 TEST(DeviceTest, getCapabilitiesDeadObject) {
167 // setup call
168 const auto mockDevice = createMockDevice();
169 EXPECT_CALL(*mockDevice, getCapabilities_1_1(_))
170 .Times(1)
171 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
172
173 // run test
174 const auto result = Device::create(kName, mockDevice);
175
176 // verify result
177 ASSERT_FALSE(result.has_value());
178 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
179 }
180
TEST(DeviceTest,linkToDeathError)181 TEST(DeviceTest, linkToDeathError) {
182 // setup call
183 const auto mockDevice = createMockDevice();
184 const auto ret = []() -> Return<bool> { return false; };
185 EXPECT_CALL(*mockDevice, linkToDeathRet()).Times(1).WillOnce(InvokeWithoutArgs(ret));
186
187 // run test
188 const auto result = Device::create(kName, mockDevice);
189
190 // verify result
191 ASSERT_FALSE(result.has_value());
192 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
193 }
194
TEST(DeviceTest,linkToDeathTransportFailure)195 TEST(DeviceTest, linkToDeathTransportFailure) {
196 // setup call
197 const auto mockDevice = createMockDevice();
198 EXPECT_CALL(*mockDevice, linkToDeathRet())
199 .Times(1)
200 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
201
202 // run test
203 const auto result = Device::create(kName, mockDevice);
204
205 // verify result
206 ASSERT_FALSE(result.has_value());
207 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
208 }
209
TEST(DeviceTest,linkToDeathDeadObject)210 TEST(DeviceTest, linkToDeathDeadObject) {
211 // setup call
212 const auto mockDevice = createMockDevice();
213 EXPECT_CALL(*mockDevice, linkToDeathRet())
214 .Times(1)
215 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
216
217 // run test
218 const auto result = Device::create(kName, mockDevice);
219
220 // verify result
221 ASSERT_FALSE(result.has_value());
222 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
223 }
224
TEST(DeviceTest,getName)225 TEST(DeviceTest, getName) {
226 // setup call
227 const auto mockDevice = createMockDevice();
228 const auto device = Device::create(kName, mockDevice).value();
229
230 // run test
231 const auto& name = device->getName();
232
233 // verify result
234 EXPECT_EQ(name, kName);
235 }
236
TEST(DeviceTest,getFeatureLevel)237 TEST(DeviceTest, getFeatureLevel) {
238 // setup call
239 const auto mockDevice = createMockDevice();
240 const auto device = Device::create(kName, mockDevice).value();
241
242 // run test
243 const auto featureLevel = device->getFeatureLevel();
244
245 // verify result
246 EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel2);
247 }
248
TEST(DeviceTest,getCachedData)249 TEST(DeviceTest, getCachedData) {
250 // setup call
251 const auto mockDevice = createMockDevice();
252 const auto result = Device::create(kName, mockDevice);
253 ASSERT_TRUE(result.has_value())
254 << "Failed with " << result.error().code << ": " << result.error().message;
255 const auto& device = result.value();
256
257 // run test and verify results
258 EXPECT_EQ(device->getVersionString(), device->getVersionString());
259 EXPECT_EQ(device->getType(), device->getType());
260 EXPECT_EQ(device->getSupportedExtensions(), device->getSupportedExtensions());
261 EXPECT_EQ(device->getNumberOfCacheFilesNeeded(), device->getNumberOfCacheFilesNeeded());
262 EXPECT_EQ(device->getCapabilities(), device->getCapabilities());
263 }
264
TEST(DeviceTest,wait)265 TEST(DeviceTest, wait) {
266 // setup call
267 const auto mockDevice = createMockDevice();
268 const auto ret = []() -> Return<void> { return {}; };
269 EXPECT_CALL(*mockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(ret));
270 const auto device = Device::create(kName, mockDevice).value();
271
272 // run test
273 const auto result = device->wait();
274
275 // verify result
276 ASSERT_TRUE(result.has_value())
277 << "Failed with " << result.error().code << ": " << result.error().message;
278 }
279
TEST(DeviceTest,waitTransportFailure)280 TEST(DeviceTest, waitTransportFailure) {
281 // setup call
282 const auto mockDevice = createMockDevice();
283 EXPECT_CALL(*mockDevice, ping())
284 .Times(1)
285 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
286 const auto device = Device::create(kName, mockDevice).value();
287
288 // run test
289 const auto result = device->wait();
290
291 // verify result
292 ASSERT_FALSE(result.has_value());
293 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
294 }
295
TEST(DeviceTest,waitDeadObject)296 TEST(DeviceTest, waitDeadObject) {
297 // setup call
298 const auto mockDevice = createMockDevice();
299 EXPECT_CALL(*mockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
300 const auto device = Device::create(kName, mockDevice).value();
301
302 // run test
303 const auto result = device->wait();
304
305 // verify result
306 ASSERT_FALSE(result.has_value());
307 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
308 }
309
TEST(DeviceTest,getSupportedOperations)310 TEST(DeviceTest, getSupportedOperations) {
311 // setup call
312 const auto mockDevice = createMockDevice();
313 const auto device = Device::create(kName, mockDevice).value();
314 const auto ret = [](const auto& model, const auto& cb) {
315 cb(V1_0::ErrorStatus::NONE, std::vector<bool>(model.operations.size(), true));
316 return hardware::Void();
317 };
318 EXPECT_CALL(*mockDevice, getSupportedOperations_1_1(_, _)).Times(1).WillOnce(Invoke(ret));
319
320 // run test
321 const auto result = device->getSupportedOperations(kSimpleModel);
322
323 // verify result
324 ASSERT_TRUE(result.has_value())
325 << "Failed with " << result.error().code << ": " << result.error().message;
326 const auto& supportedOperations = result.value();
327 EXPECT_EQ(supportedOperations.size(), kSimpleModel.main.operations.size());
328 EXPECT_THAT(supportedOperations, Each(testing::IsTrue()));
329 }
330
TEST(DeviceTest,getSupportedOperationsError)331 TEST(DeviceTest, getSupportedOperationsError) {
332 // setup call
333 const auto mockDevice = createMockDevice();
334 const auto device = Device::create(kName, mockDevice).value();
335 const auto ret = [](const auto& /*model*/, const auto& cb) {
336 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
337 return hardware::Void();
338 };
339 EXPECT_CALL(*mockDevice, getSupportedOperations_1_1(_, _)).Times(1).WillOnce(Invoke(ret));
340
341 // run test
342 const auto result = device->getSupportedOperations(kSimpleModel);
343
344 // verify result
345 ASSERT_FALSE(result.has_value());
346 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
347 }
348
TEST(DeviceTest,getSupportedOperationsTransportFailure)349 TEST(DeviceTest, getSupportedOperationsTransportFailure) {
350 // setup call
351 const auto mockDevice = createMockDevice();
352 const auto device = Device::create(kName, mockDevice).value();
353 EXPECT_CALL(*mockDevice, getSupportedOperations_1_1(_, _))
354 .Times(1)
355 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
356
357 // run test
358 const auto result = device->getSupportedOperations(kSimpleModel);
359
360 // verify result
361 ASSERT_FALSE(result.has_value());
362 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
363 }
364
TEST(DeviceTest,getSupportedOperationsDeadObject)365 TEST(DeviceTest, getSupportedOperationsDeadObject) {
366 // setup call
367 const auto mockDevice = createMockDevice();
368 const auto device = Device::create(kName, mockDevice).value();
369 EXPECT_CALL(*mockDevice, getSupportedOperations_1_1(_, _))
370 .Times(1)
371 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
372
373 // run test
374 const auto result = device->getSupportedOperations(kSimpleModel);
375
376 // verify result
377 ASSERT_FALSE(result.has_value());
378 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
379 }
380
TEST(DeviceTest,prepareModel)381 TEST(DeviceTest, prepareModel) {
382 // setup call
383 const auto mockDevice = createMockDevice();
384 const auto device = Device::create(kName, mockDevice).value();
385 const auto mockPreparedModel = V1_0::utils::MockPreparedModel::create();
386 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
387 .Times(1)
388 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
389 V1_0::ErrorStatus::NONE, mockPreparedModel)));
390
391 // run test
392 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
393 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
394
395 // verify result
396 ASSERT_TRUE(result.has_value())
397 << "Failed with " << result.error().code << ": " << result.error().message;
398 EXPECT_NE(result.value(), nullptr);
399 }
400
TEST(DeviceTest,prepareModelLaunchError)401 TEST(DeviceTest, prepareModelLaunchError) {
402 // setup call
403 const auto mockDevice = createMockDevice();
404 const auto device = Device::create(kName, mockDevice).value();
405 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
406 .Times(1)
407 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
408 V1_0::ErrorStatus::GENERAL_FAILURE, nullptr)));
409
410 // run test
411 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
412 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
413
414 // verify result
415 ASSERT_FALSE(result.has_value());
416 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
417 }
418
TEST(DeviceTest,prepareModelReturnError)419 TEST(DeviceTest, prepareModelReturnError) {
420 // setup call
421 const auto mockDevice = createMockDevice();
422 const auto device = Device::create(kName, mockDevice).value();
423 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
424 .Times(1)
425 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
426 V1_0::ErrorStatus::GENERAL_FAILURE, nullptr)));
427
428 // run test
429 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
430 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
431
432 // verify result
433 ASSERT_FALSE(result.has_value());
434 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
435 }
436
TEST(DeviceTest,prepareModelNullptrError)437 TEST(DeviceTest, prepareModelNullptrError) {
438 // setup call
439 const auto mockDevice = createMockDevice();
440 const auto device = Device::create(kName, mockDevice).value();
441 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
442 .Times(1)
443 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
444 V1_0::ErrorStatus::NONE, nullptr)));
445
446 // run test
447 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
448 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
449
450 // verify result
451 ASSERT_FALSE(result.has_value());
452 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
453 }
454
TEST(DeviceTest,prepareModelTransportFailure)455 TEST(DeviceTest, prepareModelTransportFailure) {
456 // setup call
457 const auto mockDevice = createMockDevice();
458 const auto device = Device::create(kName, mockDevice).value();
459 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
460 .Times(1)
461 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
462
463 // run test
464 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
465 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
466
467 // verify result
468 ASSERT_FALSE(result.has_value());
469 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
470 }
471
TEST(DeviceTest,prepareModelDeadObject)472 TEST(DeviceTest, prepareModelDeadObject) {
473 // setup call
474 const auto mockDevice = createMockDevice();
475 const auto device = Device::create(kName, mockDevice).value();
476 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _))
477 .Times(1)
478 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
479
480 // run test
481 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
482 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
483
484 // verify result
485 ASSERT_FALSE(result.has_value());
486 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
487 }
488
TEST(DeviceTest,prepareModelAsyncCrash)489 TEST(DeviceTest, prepareModelAsyncCrash) {
490 // setup test
491 const auto mockDevice = createMockDevice();
492 const auto device = Device::create(kName, mockDevice).value();
493 const auto ret = [&mockDevice]() -> hardware::Return<V1_0::ErrorStatus> {
494 mockDevice->simulateCrash();
495 return V1_0::ErrorStatus::NONE;
496 };
497 EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
498
499 // run test
500 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
501 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
502
503 // verify result
504 ASSERT_FALSE(result.has_value());
505 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
506 }
507
TEST(DeviceTest,prepareModelFromCacheNotSupported)508 TEST(DeviceTest, prepareModelFromCacheNotSupported) {
509 // setup call
510 const auto mockDevice = createMockDevice();
511 const auto device = Device::create(kName, mockDevice).value();
512
513 // run test
514 const auto result = device->prepareModelFromCache({}, {}, {}, {});
515
516 // verify result
517 ASSERT_FALSE(result.has_value());
518 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
519 }
520
TEST(DeviceTest,allocateNotSupported)521 TEST(DeviceTest, allocateNotSupported) {
522 // setup call
523 const auto mockDevice = createMockDevice();
524 const auto device = Device::create(kName, mockDevice).value();
525
526 // run test
527 const auto result = device->allocate({}, {}, {}, {});
528
529 // verify result
530 ASSERT_FALSE(result.has_value());
531 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
532 }
533
534 } // namespace android::hardware::neuralnetworks::V1_1::utils
535