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.0/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.0/Device.h>
27
28 #include <functional>
29 #include <memory>
30 #include <string>
31
32 namespace android::hardware::neuralnetworks::V1_0::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_0::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 = makeCallbackReturn(
70 V1_0::ErrorStatus::NONE, V1_0::Capabilities{
71 .float32Performance = kNoPerformanceInfo,
72 .quantized8Performance = kNoPerformanceInfo,
73 });
74
75 // Setup default actions for each relevant call.
76 ON_CALL(*mockDevice, getCapabilities(_)).WillByDefault(Invoke(getCapabilities_ret));
77
78 // These EXPECT_CALL(...).Times(testing::AnyNumber()) calls are to suppress warnings on the
79 // uninteresting methods calls.
80 EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(testing::AnyNumber());
81
82 return mockDevice;
83 }
84
makePreparedModelReturn(V1_0::ErrorStatus launchStatus,V1_0::ErrorStatus returnStatus,const sp<V1_0::utils::MockPreparedModel> & preparedModel)85 auto makePreparedModelReturn(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
86 const sp<V1_0::utils::MockPreparedModel>& preparedModel) {
87 return [launchStatus, returnStatus, preparedModel](const V1_0::Model& /*model*/,
88 const sp<V1_0::IPreparedModelCallback>& cb)
89 -> hardware::Return<V1_0::ErrorStatus> {
90 cb->notify(returnStatus, preparedModel).isOk();
91 return launchStatus;
92 };
93 }
94
makeTransportFailure(status_t status)95 std::function<hardware::Status()> makeTransportFailure(status_t status) {
96 return [status] { return hardware::Status::fromStatusT(status); };
97 }
98
99 const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
100 const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
101
102 } // namespace
103
TEST(DeviceTest,invalidName)104 TEST(DeviceTest, invalidName) {
105 // run test
106 const auto device = MockDevice::create();
107 const auto result = Device::create(kInvalidName, device);
108
109 // verify result
110 ASSERT_FALSE(result.has_value());
111 EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
112 }
113
TEST(DeviceTest,invalidDevice)114 TEST(DeviceTest, invalidDevice) {
115 // run test
116 const auto result = Device::create(kName, kInvalidDevice);
117
118 // verify result
119 ASSERT_FALSE(result.has_value());
120 EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
121 }
122
TEST(DeviceTest,getCapabilitiesError)123 TEST(DeviceTest, getCapabilitiesError) {
124 // setup call
125 const auto mockDevice = createMockDevice();
126 const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
127 V1_0::Capabilities{
128 .float32Performance = kNoPerformanceInfo,
129 .quantized8Performance = kNoPerformanceInfo,
130 });
131 EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(1).WillOnce(Invoke(ret));
132
133 // run test
134 const auto result = Device::create(kName, mockDevice);
135
136 // verify result
137 ASSERT_FALSE(result.has_value());
138 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
139 }
140
TEST(DeviceTest,getCapabilitiesTransportFailure)141 TEST(DeviceTest, getCapabilitiesTransportFailure) {
142 // setup call
143 const auto mockDevice = createMockDevice();
144 EXPECT_CALL(*mockDevice, getCapabilities(_))
145 .Times(1)
146 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
147
148 // run test
149 const auto result = Device::create(kName, mockDevice);
150
151 // verify result
152 ASSERT_FALSE(result.has_value());
153 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
154 }
155
TEST(DeviceTest,getCapabilitiesDeadObject)156 TEST(DeviceTest, getCapabilitiesDeadObject) {
157 // setup call
158 const auto mockDevice = createMockDevice();
159 EXPECT_CALL(*mockDevice, getCapabilities(_))
160 .Times(1)
161 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
162
163 // run test
164 const auto result = Device::create(kName, mockDevice);
165
166 // verify result
167 ASSERT_FALSE(result.has_value());
168 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
169 }
170
TEST(DeviceTest,linkToDeathError)171 TEST(DeviceTest, linkToDeathError) {
172 // setup call
173 const auto mockDevice = createMockDevice();
174 const auto ret = []() -> Return<bool> { return false; };
175 EXPECT_CALL(*mockDevice, linkToDeathRet()).Times(1).WillOnce(InvokeWithoutArgs(ret));
176
177 // run test
178 const auto result = Device::create(kName, mockDevice);
179
180 // verify result
181 ASSERT_FALSE(result.has_value());
182 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
183 }
184
TEST(DeviceTest,linkToDeathTransportFailure)185 TEST(DeviceTest, linkToDeathTransportFailure) {
186 // setup call
187 const auto mockDevice = createMockDevice();
188 EXPECT_CALL(*mockDevice, linkToDeathRet())
189 .Times(1)
190 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
191
192 // run test
193 const auto result = Device::create(kName, mockDevice);
194
195 // verify result
196 ASSERT_FALSE(result.has_value());
197 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
198 }
199
TEST(DeviceTest,linkToDeathDeadObject)200 TEST(DeviceTest, linkToDeathDeadObject) {
201 // setup call
202 const auto mockDevice = createMockDevice();
203 EXPECT_CALL(*mockDevice, linkToDeathRet())
204 .Times(1)
205 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
206
207 // run test
208 const auto result = Device::create(kName, mockDevice);
209
210 // verify result
211 ASSERT_FALSE(result.has_value());
212 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
213 }
214
TEST(DeviceTest,getName)215 TEST(DeviceTest, getName) {
216 // setup call
217 const auto mockDevice = createMockDevice();
218 const auto device = Device::create(kName, mockDevice).value();
219
220 // run test
221 const auto& name = device->getName();
222
223 // verify result
224 EXPECT_EQ(name, kName);
225 }
226
TEST(DeviceTest,getFeatureLevel)227 TEST(DeviceTest, getFeatureLevel) {
228 // setup call
229 const auto mockDevice = createMockDevice();
230 const auto device = Device::create(kName, mockDevice).value();
231
232 // run test
233 const auto featureLevel = device->getFeatureLevel();
234
235 // verify result
236 EXPECT_EQ(featureLevel, nn::kVersionFeatureLevel1);
237 }
238
TEST(DeviceTest,getCachedData)239 TEST(DeviceTest, getCachedData) {
240 // setup call
241 const auto mockDevice = createMockDevice();
242 const auto result = Device::create(kName, mockDevice);
243 ASSERT_TRUE(result.has_value())
244 << "Failed with " << result.error().code << ": " << result.error().message;
245 const auto& device = result.value();
246
247 // run test and verify results
248 EXPECT_EQ(device->getVersionString(), device->getVersionString());
249 EXPECT_EQ(device->getType(), device->getType());
250 EXPECT_EQ(device->getSupportedExtensions(), device->getSupportedExtensions());
251 EXPECT_EQ(device->getNumberOfCacheFilesNeeded(), device->getNumberOfCacheFilesNeeded());
252 EXPECT_EQ(device->getCapabilities(), device->getCapabilities());
253 }
254
TEST(DeviceTest,wait)255 TEST(DeviceTest, wait) {
256 // setup call
257 const auto mockDevice = createMockDevice();
258 const auto ret = []() -> Return<void> { return {}; };
259 EXPECT_CALL(*mockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(ret));
260 const auto device = Device::create(kName, mockDevice).value();
261
262 // run test
263 const auto result = device->wait();
264
265 // verify result
266 ASSERT_TRUE(result.has_value())
267 << "Failed with " << result.error().code << ": " << result.error().message;
268 }
269
TEST(DeviceTest,waitTransportFailure)270 TEST(DeviceTest, waitTransportFailure) {
271 // setup call
272 const auto mockDevice = createMockDevice();
273 EXPECT_CALL(*mockDevice, ping())
274 .Times(1)
275 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
276 const auto device = Device::create(kName, mockDevice).value();
277
278 // run test
279 const auto result = device->wait();
280
281 // verify result
282 ASSERT_FALSE(result.has_value());
283 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
284 }
285
TEST(DeviceTest,waitDeadObject)286 TEST(DeviceTest, waitDeadObject) {
287 // setup call
288 const auto mockDevice = createMockDevice();
289 EXPECT_CALL(*mockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
290 const auto device = Device::create(kName, mockDevice).value();
291
292 // run test
293 const auto result = device->wait();
294
295 // verify result
296 ASSERT_FALSE(result.has_value());
297 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
298 }
299
TEST(DeviceTest,getSupportedOperations)300 TEST(DeviceTest, getSupportedOperations) {
301 // setup call
302 const auto mockDevice = createMockDevice();
303 const auto device = Device::create(kName, mockDevice).value();
304 const auto ret = [](const auto& model, const auto& cb) {
305 cb(V1_0::ErrorStatus::NONE, std::vector<bool>(model.operations.size(), true));
306 return hardware::Void();
307 };
308 EXPECT_CALL(*mockDevice, getSupportedOperations(_, _)).Times(1).WillOnce(Invoke(ret));
309
310 // run test
311 const auto result = device->getSupportedOperations(kSimpleModel);
312
313 // verify result
314 ASSERT_TRUE(result.has_value())
315 << "Failed with " << result.error().code << ": " << result.error().message;
316 const auto& supportedOperations = result.value();
317 EXPECT_EQ(supportedOperations.size(), kSimpleModel.main.operations.size());
318 EXPECT_THAT(supportedOperations, Each(testing::IsTrue()));
319 }
320
TEST(DeviceTest,getSupportedOperationsError)321 TEST(DeviceTest, getSupportedOperationsError) {
322 // setup call
323 const auto mockDevice = createMockDevice();
324 const auto device = Device::create(kName, mockDevice).value();
325 const auto ret = [](const auto& /*model*/, const auto& cb) {
326 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
327 return hardware::Void();
328 };
329 EXPECT_CALL(*mockDevice, getSupportedOperations(_, _)).Times(1).WillOnce(Invoke(ret));
330
331 // run test
332 const auto result = device->getSupportedOperations(kSimpleModel);
333
334 // verify result
335 ASSERT_FALSE(result.has_value());
336 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
337 }
338
TEST(DeviceTest,getSupportedOperationsTransportFailure)339 TEST(DeviceTest, getSupportedOperationsTransportFailure) {
340 // setup call
341 const auto mockDevice = createMockDevice();
342 const auto device = Device::create(kName, mockDevice).value();
343 EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
344 .Times(1)
345 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
346
347 // run test
348 const auto result = device->getSupportedOperations(kSimpleModel);
349
350 // verify result
351 ASSERT_FALSE(result.has_value());
352 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
353 }
354
TEST(DeviceTest,getSupportedOperationsDeadObject)355 TEST(DeviceTest, getSupportedOperationsDeadObject) {
356 // setup call
357 const auto mockDevice = createMockDevice();
358 const auto device = Device::create(kName, mockDevice).value();
359 EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
360 .Times(1)
361 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
362
363 // run test
364 const auto result = device->getSupportedOperations(kSimpleModel);
365
366 // verify result
367 ASSERT_FALSE(result.has_value());
368 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
369 }
370
TEST(DeviceTest,prepareModel)371 TEST(DeviceTest, prepareModel) {
372 // setup call
373 const auto mockDevice = createMockDevice();
374 const auto device = Device::create(kName, mockDevice).value();
375 const auto mockPreparedModel = V1_0::utils::MockPreparedModel::create();
376 EXPECT_CALL(*mockDevice, prepareModel(_, _))
377 .Times(1)
378 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
379 V1_0::ErrorStatus::NONE, mockPreparedModel)));
380
381 // run test
382 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
383 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
384
385 // verify result
386 ASSERT_TRUE(result.has_value())
387 << "Failed with " << result.error().code << ": " << result.error().message;
388 EXPECT_NE(result.value(), nullptr);
389 }
390
TEST(DeviceTest,prepareModelLaunchError)391 TEST(DeviceTest, prepareModelLaunchError) {
392 // setup call
393 const auto mockDevice = createMockDevice();
394 const auto device = Device::create(kName, mockDevice).value();
395 EXPECT_CALL(*mockDevice, prepareModel(_, _))
396 .Times(1)
397 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
398 V1_0::ErrorStatus::GENERAL_FAILURE, nullptr)));
399
400 // run test
401 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
402 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
403
404 // verify result
405 ASSERT_FALSE(result.has_value());
406 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
407 }
408
TEST(DeviceTest,prepareModelReturnError)409 TEST(DeviceTest, prepareModelReturnError) {
410 // setup call
411 const auto mockDevice = createMockDevice();
412 const auto device = Device::create(kName, mockDevice).value();
413 EXPECT_CALL(*mockDevice, prepareModel(_, _))
414 .Times(1)
415 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
416 V1_0::ErrorStatus::GENERAL_FAILURE, nullptr)));
417
418 // run test
419 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
420 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
421
422 // verify result
423 ASSERT_FALSE(result.has_value());
424 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
425 }
426
TEST(DeviceTest,prepareModelNullptrError)427 TEST(DeviceTest, prepareModelNullptrError) {
428 // setup call
429 const auto mockDevice = createMockDevice();
430 const auto device = Device::create(kName, mockDevice).value();
431 EXPECT_CALL(*mockDevice, prepareModel(_, _))
432 .Times(1)
433 .WillOnce(Invoke(makePreparedModelReturn(V1_0::ErrorStatus::NONE,
434 V1_0::ErrorStatus::NONE, nullptr)));
435
436 // run test
437 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
438 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
439
440 // verify result
441 ASSERT_FALSE(result.has_value());
442 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
443 }
444
TEST(DeviceTest,prepareModelTransportFailure)445 TEST(DeviceTest, prepareModelTransportFailure) {
446 // setup call
447 const auto mockDevice = createMockDevice();
448 const auto device = Device::create(kName, mockDevice).value();
449 EXPECT_CALL(*mockDevice, prepareModel(_, _))
450 .Times(1)
451 .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
452
453 // run test
454 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
455 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
456
457 // verify result
458 ASSERT_FALSE(result.has_value());
459 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
460 }
461
TEST(DeviceTest,prepareModelDeadObject)462 TEST(DeviceTest, prepareModelDeadObject) {
463 // setup call
464 const auto mockDevice = createMockDevice();
465 const auto device = Device::create(kName, mockDevice).value();
466 EXPECT_CALL(*mockDevice, prepareModel(_, _))
467 .Times(1)
468 .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
469
470 // run test
471 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
472 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
473
474 // verify result
475 ASSERT_FALSE(result.has_value());
476 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
477 }
478
TEST(DeviceTest,prepareModelAsyncCrash)479 TEST(DeviceTest, prepareModelAsyncCrash) {
480 // setup test
481 const auto mockDevice = createMockDevice();
482 const auto device = Device::create(kName, mockDevice).value();
483 const auto ret = [&mockDevice]() -> hardware::Return<V1_0::ErrorStatus> {
484 mockDevice->simulateCrash();
485 return V1_0::ErrorStatus::NONE;
486 };
487 EXPECT_CALL(*mockDevice, prepareModel(_, _)).Times(1).WillOnce(InvokeWithoutArgs(ret));
488
489 // run test
490 const auto result = device->prepareModel(kSimpleModel, nn::ExecutionPreference::DEFAULT,
491 nn::Priority::DEFAULT, {}, {}, {}, {}, {}, {});
492
493 // verify result
494 ASSERT_FALSE(result.has_value());
495 EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
496 }
497
TEST(DeviceTest,prepareModelFromCacheNotSupported)498 TEST(DeviceTest, prepareModelFromCacheNotSupported) {
499 // setup call
500 const auto mockDevice = createMockDevice();
501 const auto device = Device::create(kName, mockDevice).value();
502
503 // run test
504 const auto result = device->prepareModelFromCache({}, {}, {}, {});
505
506 // verify result
507 ASSERT_FALSE(result.has_value());
508 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
509 }
510
TEST(DeviceTest,allocateNotSupported)511 TEST(DeviceTest, allocateNotSupported) {
512 // setup call
513 const auto mockDevice = createMockDevice();
514 const auto device = Device::create(kName, mockDevice).value();
515
516 // run test
517 const auto result = device->allocate({}, {}, {}, {});
518
519 // verify result
520 ASSERT_FALSE(result.has_value());
521 EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
522 }
523
524 } // namespace android::hardware::neuralnetworks::V1_0::utils
525