diff options
author | Xusong Wang <xusongw@google.com> | 2020-05-01 05:34:27 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-05-01 05:34:27 +0000 |
commit | 7ef73c26b5af4f563be3926c0c2070e0871e67da (patch) | |
tree | de22f71ad1ee5367fd3de4c37441a230cd7ba1b5 /nn/runtime/test | |
parent | e6ed0fc145d449239ad753d8b268a96b928dc830 (diff) | |
parent | 7f7e3874339e9ff4fe3bdb24e627f4e0f7edcf97 (diff) | |
download | ml-7ef73c26b5af4f563be3926c0c2070e0871e67da.tar.gz |
Merge "Add internal NNT_static tests for buffer copying." into rvc-dev
Diffstat (limited to 'nn/runtime/test')
-rw-r--r-- | nn/runtime/test/TestGenerated.cpp | 47 | ||||
-rw-r--r-- | nn/runtime/test/TestMemoryDomain.cpp | 107 | ||||
-rw-r--r-- | nn/runtime/test/TestUtils.h | 82 |
3 files changed, 161 insertions, 75 deletions
diff --git a/nn/runtime/test/TestGenerated.cpp b/nn/runtime/test/TestGenerated.cpp index 60f866cab..cc0b61983 100644 --- a/nn/runtime/test/TestGenerated.cpp +++ b/nn/runtime/test/TestGenerated.cpp @@ -15,9 +15,6 @@ */ #include <android-base/logging.h> -#include <android-base/mapped_file.h> -#include <android-base/unique_fd.h> -#include <android/sharedmem.h> #include <ftw.h> #include <gtest/gtest.h> #include <unistd.h> @@ -37,6 +34,7 @@ #include "GeneratedTestUtils.h" #include "TestHarness.h" #include "TestNeuralNetworksWrapper.h" +#include "TestUtils.h" // Systrace is not available from CTS tests due to platform layering // constraints. We reuse the NNTEST_ONLY_PUBLIC_API flag, as that should also be @@ -140,49 +138,6 @@ static void computeWithPtrs(const TestModel& testModel, Execution* execution, Re *result = execution->compute(); } -// Convenience class to manage the file, mapping, and memory object. -class TestAshmem { - public: - TestAshmem(::android::base::unique_fd fd, std::unique_ptr<::android::base::MappedFile> mapped, - Memory memory) - : mFd(std::move(fd)), mMapped(std::move(mapped)), mMemory(std::move(memory)) {} - - // Factory function for TestAshmem; prefer this over the raw constructor - static std::unique_ptr<TestAshmem> createFrom(const TestBuffer& buffer) { - // Create ashmem-based fd. - int fd = ASharedMemory_create(nullptr, buffer.size()); - if (fd <= 0) return nullptr; - ::android::base::unique_fd managedFd(fd); - - // Map and populate ashmem. - auto mappedFile = - ::android::base::MappedFile::FromFd(fd, 0, buffer.size(), PROT_READ | PROT_WRITE); - if (!mappedFile) return nullptr; - memcpy(mappedFile->data(), buffer.get<void>(), buffer.size()); - - // Create NNAPI memory object. - Memory memory(buffer.size(), PROT_READ | PROT_WRITE, fd, 0); - if (!memory.isValid()) return nullptr; - - // Store everything in managing class. - return std::make_unique<TestAshmem>(std::move(managedFd), std::move(mappedFile), - std::move(memory)); - } - - size_t size() { return mMapped->size(); } - Memory* get() { return &mMemory; } - - template <typename Type> - Type* dataAs() { - return static_cast<Type*>(static_cast<void*>(mMapped->data())); - } - - private: - ::android::base::unique_fd mFd; - std::unique_ptr<::android::base::MappedFile> mMapped; - Memory mMemory; -}; - static ANeuralNetworksMemory* createDeviceMemoryForInput(const Compilation& compilation, uint32_t index) { ANeuralNetworksMemoryDesc* desc = nullptr; diff --git a/nn/runtime/test/TestMemoryDomain.cpp b/nn/runtime/test/TestMemoryDomain.cpp index 88ca2f4d8..4a9c394ad 100644 --- a/nn/runtime/test/TestMemoryDomain.cpp +++ b/nn/runtime/test/TestMemoryDomain.cpp @@ -29,7 +29,9 @@ #include "Manager.h" #include "Memory.h" #include "SampleDriver.h" +#include "SampleDriverFull.h" #include "TestNeuralNetworksWrapper.h" +#include "TestUtils.h" using namespace android::nn; using namespace hal; @@ -163,16 +165,10 @@ test_wrapper::Model createTestModel() { return model; } -// Test memory domain with the following parameters -// - If true, use a V1_2 driver, otherwise, use the latest version; -// - If true, compile with explicit device list, otherwise, compile in the default way; -// - The return of the allocate function. -using MemoryDomainTestParam = std::tuple<bool, bool, AllocateReturn>; - -class MemoryDomainTest : public ::testing::TestWithParam<MemoryDomainTestParam> { +class MemoryDomainTestBase : public ::testing::Test { protected: void SetUp() override { - ::testing::TestWithParam<MemoryDomainTestParam>::SetUp(); + ::testing::Test::SetUp(); if (DeviceManager::get()->getUseCpuOnly()) { GTEST_SKIP(); } @@ -182,28 +178,14 @@ class MemoryDomainTest : public ::testing::TestWithParam<MemoryDomainTestParam> void TearDown() override { DeviceManager::get()->forTest_reInitializeDeviceList(); - ::testing::TestWithParam<MemoryDomainTestParam>::TearDown(); - } - - // If kUseV1_2Driver, allocateReturn must be AllocateReturn::NOT_SUPPORTED. - void createAndRegisterDriver(const char* name, std::set<OperationType> supportedOperations, - AllocateReturn allocateReturn) { - sp<V1_0::IDevice> driver; - if (kUseV1_2Driver) { - CHECK(allocateReturn == AllocateReturn::NOT_SUPPORTED); - const sp<TestDriverLatest> testDriver = - new TestDriverLatest(name, supportedOperations, AllocateReturn::NOT_SUPPORTED); - driver = new V1_2::ADevice(testDriver); - } else { - driver = new TestDriverLatest(name, std::move(supportedOperations), allocateReturn); - } - DeviceManager::get()->forTest_registerDevice(name, driver); + ::testing::Test::TearDown(); } - // If not kCompileWithExplicitDeviceList, the input argument "deviceNames" is ignored. + // If "deviceNames" is not empty, the compilation is created with explicit device list; + // otherwise, it is created normally. test_wrapper::Compilation createCompilation(const std::vector<std::string>& deviceNames) { test_wrapper::Compilation compilation; - if (kCompileWithExplicitDeviceList) { + if (!deviceNames.empty()) { // Map device names to ANeuralNetworksDevice. std::map<std::string, ANeuralNetworksDevice*> deviceMap; uint32_t numDevices = 0; @@ -251,14 +233,49 @@ class MemoryDomainTest : public ::testing::TestWithParam<MemoryDomainTestParam> return {n, test_wrapper::Memory(memory)}; } + static const test_wrapper::Model kModel; +}; + +const test_wrapper::Model MemoryDomainTestBase::kModel = createTestModel(); + +// Test memory domain with the following parameters +// - If true, use a V1_2 driver, otherwise, use the latest version; +// - If true, compile with explicit device list, otherwise, compile in the default way; +// - The return of the allocate function. +using MemoryDomainTestParam = std::tuple<bool, bool, AllocateReturn>; + +class MemoryDomainTest : public MemoryDomainTestBase, + public ::testing::WithParamInterface<MemoryDomainTestParam> { + protected: + // If kUseV1_2Driver, allocateReturn must be AllocateReturn::NOT_SUPPORTED. + void createAndRegisterDriver(const char* name, std::set<OperationType> supportedOperations, + AllocateReturn allocateReturn) { + sp<V1_0::IDevice> driver; + if (kUseV1_2Driver) { + CHECK(allocateReturn == AllocateReturn::NOT_SUPPORTED); + const sp<TestDriverLatest> testDriver = + new TestDriverLatest(name, supportedOperations, AllocateReturn::NOT_SUPPORTED); + driver = new V1_2::ADevice(testDriver); + } else { + driver = new TestDriverLatest(name, std::move(supportedOperations), allocateReturn); + } + DeviceManager::get()->forTest_registerDevice(name, driver); + } + + // If not kCompileWithExplicitDeviceList, the input argument "deviceNames" is ignored. + test_wrapper::Compilation createCompilation(const std::vector<std::string>& deviceNames) { + if (kCompileWithExplicitDeviceList) { + return MemoryDomainTestBase::createCompilation(deviceNames); + } else { + return MemoryDomainTestBase::createCompilation({}); + } + } + const bool kUseV1_2Driver = std::get<0>(GetParam()); const bool kCompileWithExplicitDeviceList = std::get<1>(GetParam()); const AllocateReturn kAllocateReturn = std::get<2>(GetParam()); - static const test_wrapper::Model kModel; }; -const test_wrapper::Model MemoryDomainTest::kModel = createTestModel(); - // Test device memory allocation on a compilation with only a single partition. TEST_P(MemoryDomainTest, SinglePartition) { createAndRegisterDriver("test_driver", @@ -412,4 +429,36 @@ INSTANTIATE_TEST_CASE_P(DeviceVersionV1_2, MemoryDomainTest, testing::Combine(testing::Values(true), testing::Bool(), testing::Values(AllocateReturn::NOT_SUPPORTED))); +class MemoryDomainCopyTest : public MemoryDomainTestBase {}; + +TEST_F(MemoryDomainCopyTest, MemoryCopyTest) { + sp<sample_driver::SampleDriverFull> driver(new sample_driver::SampleDriverFull( + "test_driver", {.execTime = 0.1f, .powerUsage = 0.1f})); + DeviceManager::get()->forTest_registerDevice("test_driver", driver); + auto compilation = createCompilation({"test_driver"}); + ASSERT_NE(compilation.getHandle(), nullptr); + + // Allocate ashmem. + const float initValue1 = 3.14f, initValue2 = 2.72f; + auto ashmem1 = TestAshmem::createFrom(&initValue1, sizeof(float)); + auto ashmem2 = TestAshmem::createFrom(&initValue2, sizeof(float)); + ASSERT_NE(ashmem1, nullptr); + ASSERT_NE(ashmem2, nullptr); + + // Allocate device memories. + auto [n1, memory1] = allocateDeviceMemory(compilation, {0}, {}); + auto [n2, memory2] = allocateDeviceMemory(compilation, {0}, {}); + ASSERT_EQ(n1, ANEURALNETWORKS_NO_ERROR); + ASSERT_EQ(n2, ANEURALNETWORKS_NO_ERROR); + + // Test memory copying: ashmem1 -> memory1 -> memory2 -> ashmem2 + ASSERT_EQ(ANeuralNetworksMemory_copy(ashmem1->get()->get(), memory1.get()), + ANEURALNETWORKS_NO_ERROR); + ASSERT_EQ(ANeuralNetworksMemory_copy(memory1.get(), memory2.get()), ANEURALNETWORKS_NO_ERROR); + ASSERT_EQ(ANeuralNetworksMemory_copy(memory2.get(), ashmem2->get()->get()), + ANEURALNETWORKS_NO_ERROR); + + EXPECT_EQ(ashmem2->dataAs<float>()[0], initValue1); +} + } // namespace diff --git a/nn/runtime/test/TestUtils.h b/nn/runtime/test/TestUtils.h new file mode 100644 index 000000000..61f7ef8f5 --- /dev/null +++ b/nn/runtime/test/TestUtils.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_FRAMEWORKS_ML_NN_RUNTIME_TEST_TEST_UTILS_H +#define ANDROID_FRAMEWORKS_ML_NN_RUNTIME_TEST_TEST_UTILS_H + +#include <android-base/mapped_file.h> +#include <android-base/unique_fd.h> +#include <android/sharedmem.h> + +#include <memory> +#include <utility> + +#include "TestHarness.h" +#include "TestNeuralNetworksWrapper.h" + +namespace android::nn { + +// Convenience class to manage the file, mapping, and memory object. +class TestAshmem { + public: + TestAshmem(::android::base::unique_fd fd, std::unique_ptr<::android::base::MappedFile> mapped, + test_wrapper::Memory memory) + : mFd(std::move(fd)), mMapped(std::move(mapped)), mMemory(std::move(memory)) {} + + // Factory function for TestAshmem; prefer this over the raw constructor + static std::unique_ptr<TestAshmem> createFrom(const test_helper::TestBuffer& buffer) { + return createFrom(buffer.get<void>(), buffer.size()); + } + + // Factory function for TestAshmem; prefer this over the raw constructor + static std::unique_ptr<TestAshmem> createFrom(const void* data, uint32_t length) { + // Create ashmem-based fd. + int fd = ASharedMemory_create(nullptr, length); + if (fd <= 0) return nullptr; + ::android::base::unique_fd managedFd(fd); + + // Map and populate ashmem. + auto mappedFile = + ::android::base::MappedFile::FromFd(fd, 0, length, PROT_READ | PROT_WRITE); + if (!mappedFile) return nullptr; + memcpy(mappedFile->data(), data, length); + + // Create NNAPI memory object. + test_wrapper::Memory memory(length, PROT_READ | PROT_WRITE, fd, 0); + if (!memory.isValid()) return nullptr; + + // Store everything in managing class. + return std::make_unique<TestAshmem>(std::move(managedFd), std::move(mappedFile), + std::move(memory)); + } + + size_t size() { return mMapped->size(); } + test_wrapper::Memory* get() { return &mMemory; } + + template <typename Type> + Type* dataAs() { + return static_cast<Type*>(static_cast<void*>(mMapped->data())); + } + + private: + ::android::base::unique_fd mFd; + std::unique_ptr<::android::base::MappedFile> mMapped; + test_wrapper::Memory mMemory; +}; + +} // namespace android::nn + +#endif // ANDROID_FRAMEWORKS_ML_NN_RUNTIME_TEST_TEST_UTILS_H |