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