1 /* 2 * Copyright (C) 2017 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 #define LOG_TAG "neuralnetworks_hidl_hal_test" 18 19 #include "VtsHalNeuralnetworksV1_0TargetTest.h" 20 21 #include "Callbacks.h" 22 #include "Models.h" 23 #include "TestHarness.h" 24 25 #include <android-base/logging.h> 26 #include <android/hidl/memory/1.0/IMemory.h> 27 #include <hidlmemory/mapping.h> 28 29 namespace android { 30 namespace hardware { 31 namespace neuralnetworks { 32 namespace V1_0 { 33 namespace vts { 34 namespace functional { 35 36 using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback; 37 using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback; 38 using ::generated_tests::MixedTypedExampleType; 39 40 namespace generated_tests { 41 extern void Execute(const sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>, 42 const std::vector<MixedTypedExampleType>&); 43 } 44 45 // A class for test environment setup 46 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {} 47 48 NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {} 49 50 NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() { 51 // This has to return a "new" object because it is freed inside 52 // ::testing::AddGlobalTestEnvironment when the gtest is being torn down 53 static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment(); 54 return instance; 55 } 56 57 void NeuralnetworksHidlEnvironment::registerTestServices() { 58 registerTestService<IDevice>(); 59 } 60 61 // The main test class for NEURALNETWORK HIDL HAL. 62 NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {} 63 64 void NeuralnetworksHidlTest::SetUp() { 65 device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>( 66 NeuralnetworksHidlEnvironment::getInstance()); 67 ASSERT_NE(nullptr, device.get()); 68 } 69 70 void NeuralnetworksHidlTest::TearDown() {} 71 72 sp<IPreparedModel> NeuralnetworksHidlTest::doPrepareModelShortcut() { 73 Model model = createValidTestModel(); 74 75 sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback(); 76 if (preparedModelCallback == nullptr) { 77 return nullptr; 78 } 79 Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); 80 if (!prepareLaunchStatus.isOk() || prepareLaunchStatus != ErrorStatus::NONE) { 81 return nullptr; 82 } 83 84 preparedModelCallback->wait(); 85 ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); 86 sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel(); 87 if (prepareReturnStatus != ErrorStatus::NONE || preparedModel == nullptr) { 88 return nullptr; 89 } 90 91 return preparedModel; 92 } 93 94 // create device test 95 TEST_F(NeuralnetworksHidlTest, CreateDevice) {} 96 97 // status test 98 TEST_F(NeuralnetworksHidlTest, StatusTest) { 99 Return<DeviceStatus> status = device->getStatus(); 100 ASSERT_TRUE(status.isOk()); 101 EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status)); 102 } 103 104 // initialization 105 TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) { 106 Return<void> ret = 107 device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) { 108 EXPECT_EQ(ErrorStatus::NONE, status); 109 EXPECT_LT(0.0f, capabilities.float32Performance.execTime); 110 EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage); 111 EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime); 112 EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage); 113 }); 114 EXPECT_TRUE(ret.isOk()); 115 } 116 117 // supported operations positive test 118 TEST_F(NeuralnetworksHidlTest, SupportedOperationsPositiveTest) { 119 Model model = createValidTestModel(); 120 Return<void> ret = device->getSupportedOperations( 121 model, [&](ErrorStatus status, const hidl_vec<bool>& supported) { 122 EXPECT_EQ(ErrorStatus::NONE, status); 123 EXPECT_EQ(model.operations.size(), supported.size()); 124 }); 125 EXPECT_TRUE(ret.isOk()); 126 } 127 128 // supported operations negative test 1 129 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest1) { 130 Model model = createInvalidTestModel1(); 131 Return<void> ret = device->getSupportedOperations( 132 model, [&](ErrorStatus status, const hidl_vec<bool>& supported) { 133 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status); 134 (void)supported; 135 }); 136 EXPECT_TRUE(ret.isOk()); 137 } 138 139 // supported operations negative test 2 140 TEST_F(NeuralnetworksHidlTest, SupportedOperationsNegativeTest2) { 141 Model model = createInvalidTestModel2(); 142 Return<void> ret = device->getSupportedOperations( 143 model, [&](ErrorStatus status, const hidl_vec<bool>& supported) { 144 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status); 145 (void)supported; 146 }); 147 EXPECT_TRUE(ret.isOk()); 148 } 149 150 // prepare simple model positive test 151 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelPositiveTest) { 152 Model model = createValidTestModel(); 153 sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback(); 154 ASSERT_NE(nullptr, preparedModelCallback.get()); 155 Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); 156 ASSERT_TRUE(prepareLaunchStatus.isOk()); 157 EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus)); 158 159 preparedModelCallback->wait(); 160 ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); 161 EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus); 162 sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel(); 163 EXPECT_NE(nullptr, preparedModel.get()); 164 } 165 166 // prepare simple model negative test 1 167 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest1) { 168 Model model = createInvalidTestModel1(); 169 sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback(); 170 ASSERT_NE(nullptr, preparedModelCallback.get()); 171 Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); 172 ASSERT_TRUE(prepareLaunchStatus.isOk()); 173 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus)); 174 175 preparedModelCallback->wait(); 176 ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); 177 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus); 178 sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel(); 179 EXPECT_EQ(nullptr, preparedModel.get()); 180 } 181 182 // prepare simple model negative test 2 183 TEST_F(NeuralnetworksHidlTest, SimplePrepareModelNegativeTest2) { 184 Model model = createInvalidTestModel2(); 185 sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback(); 186 ASSERT_NE(nullptr, preparedModelCallback.get()); 187 Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback); 188 ASSERT_TRUE(prepareLaunchStatus.isOk()); 189 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus)); 190 191 preparedModelCallback->wait(); 192 ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus(); 193 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus); 194 sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel(); 195 EXPECT_EQ(nullptr, preparedModel.get()); 196 } 197 198 // execute simple graph positive test 199 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphPositiveTest) { 200 std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f}; 201 std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f}; 202 const uint32_t OUTPUT = 1; 203 204 sp<IPreparedModel> preparedModel = doPrepareModelShortcut(); 205 ASSERT_NE(nullptr, preparedModel.get()); 206 Request request = createValidTestRequest(); 207 208 auto postWork = [&] { 209 sp<IMemory> outputMemory = mapMemory(request.pools[OUTPUT]); 210 if (outputMemory == nullptr) { 211 return false; 212 } 213 float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer())); 214 if (outputPtr == nullptr) { 215 return false; 216 } 217 outputMemory->read(); 218 std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin()); 219 outputMemory->commit(); 220 return true; 221 }; 222 223 sp<ExecutionCallback> executionCallback = new ExecutionCallback(); 224 ASSERT_NE(nullptr, executionCallback.get()); 225 executionCallback->on_finish(postWork); 226 Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback); 227 ASSERT_TRUE(executeLaunchStatus.isOk()); 228 EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeLaunchStatus)); 229 230 executionCallback->wait(); 231 ErrorStatus executionReturnStatus = executionCallback->getStatus(); 232 EXPECT_EQ(ErrorStatus::NONE, executionReturnStatus); 233 EXPECT_EQ(expectedData, outputData); 234 } 235 236 // execute simple graph negative test 1 237 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest1) { 238 sp<IPreparedModel> preparedModel = doPrepareModelShortcut(); 239 ASSERT_NE(nullptr, preparedModel.get()); 240 Request request = createInvalidTestRequest1(); 241 242 sp<ExecutionCallback> executionCallback = new ExecutionCallback(); 243 ASSERT_NE(nullptr, executionCallback.get()); 244 Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback); 245 ASSERT_TRUE(executeLaunchStatus.isOk()); 246 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus)); 247 248 executionCallback->wait(); 249 ErrorStatus executionReturnStatus = executionCallback->getStatus(); 250 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus); 251 } 252 253 // execute simple graph negative test 2 254 TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphNegativeTest2) { 255 sp<IPreparedModel> preparedModel = doPrepareModelShortcut(); 256 ASSERT_NE(nullptr, preparedModel.get()); 257 Request request = createInvalidTestRequest2(); 258 259 sp<ExecutionCallback> executionCallback = new ExecutionCallback(); 260 ASSERT_NE(nullptr, executionCallback.get()); 261 Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback); 262 ASSERT_TRUE(executeLaunchStatus.isOk()); 263 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus)); 264 265 executionCallback->wait(); 266 ErrorStatus executionReturnStatus = executionCallback->getStatus(); 267 EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus); 268 } 269 270 // Mixed-typed examples 271 typedef MixedTypedExampleType MixedTypedExample; 272 273 // in frameworks/ml/nn/runtime/tests/generated/ 274 #include "all_generated_vts_tests.cpp" 275 276 // TODO: Add tests for execution failure, or wait_for/wait_until timeout. 277 // Discussion: 278 // https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222 279 280 } // namespace functional 281 } // namespace vts 282 } // namespace V1_0 283 } // namespace neuralnetworks 284 } // namespace hardware 285 } // namespace android 286 287 using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment; 288 289 int main(int argc, char** argv) { 290 ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance()); 291 ::testing::InitGoogleTest(&argc, argv); 292 NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv); 293 294 int status = RUN_ALL_TESTS(); 295 return status; 296 } 297