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