From 2c4e02329b6bcc33e3d520f3cc4e80ab7b83cf4a Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Thu, 26 Dec 2019 18:03:56 -0800 Subject: [PATCH] Add VTS tests for NNAPI IPreparedModel::executeFenced - Validation tests - Generated tests to exercise executeFenced path Bug: 142778241 Test: mm Change-Id: I509f0b5713fc86885d597940aae5ade0502c97ad --- neuralnetworks/1.3/vts/functional/Android.bp | 1 + .../vts/functional/GeneratedTestHarness.cpp | 46 +++++++++++++++++-- .../1.3/vts/functional/ValidateRequest.cpp | 18 ++++++++ .../vts/functional/VtsHalNeuralnetworks.cpp | 30 ++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp index ce2d3a917a..8e7e9b9d62 100644 --- a/neuralnetworks/1.3/vts/functional/Android.bp +++ b/neuralnetworks/1.3/vts/functional/Android.bp @@ -65,6 +65,7 @@ cc_test { "libhidlmemory", "libneuralnetworks_generated_test_harness", "libneuralnetworks_utils", + "libsync", ], whole_static_libs: [ "neuralnetworks_generated_V1_0_example", diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp index a2c0c4efa0..dec931bd42 100644 --- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp @@ -29,11 +29,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -70,7 +72,7 @@ using HidlToken = hidl_array(Constant::BYTE_SIZE_ namespace { -enum class Executor { ASYNC, SYNC, BURST }; +enum class Executor { ASYNC, SYNC, BURST, FENCED }; enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT }; @@ -562,6 +564,43 @@ void EvaluatePreparedModel(const sp& device, const sp& break; } + case Executor::FENCED: { + SCOPED_TRACE("fenced"); + ErrorStatus result; + hidl_handle sync_fence_handle; + sp fenced_callback; + Return ret = preparedModel->executeFenced( + request, {}, testConfig.measureTiming, + [&result, &sync_fence_handle, &fenced_callback]( + ErrorStatus error, const hidl_handle& handle, + const sp& callback) { + result = error; + sync_fence_handle = handle; + fenced_callback = callback; + }); + ASSERT_TRUE(ret.isOk()); + if (result != ErrorStatus::NONE) { + ASSERT_EQ(sync_fence_handle.getNativeHandle(), nullptr); + ASSERT_EQ(fenced_callback, nullptr); + executionStatus = ErrorStatus::GENERAL_FAILURE; + } else if (sync_fence_handle.getNativeHandle()) { + constexpr int kInfiniteTimeout = -1; + int sync_fd = sync_fence_handle.getNativeHandle()->data[0]; + ASSERT_GT(sync_fd, 0); + int r = sync_wait(sync_fd, kInfiniteTimeout); + ASSERT_GE(r, 0); + } + if (result == ErrorStatus::NONE) { + ASSERT_NE(fenced_callback, nullptr); + Return ret = fenced_callback->getExecutionInfo( + [&executionStatus, &timing](ErrorStatus error, Timing t) { + executionStatus = error; + timing = t; + }); + ASSERT_TRUE(ret.isOk()); + } + break; + } } if (testConfig.outputType != OutputType::FULLY_SPECIFIED && @@ -635,7 +674,7 @@ void EvaluatePreparedModel(const sp& device, const sp& case TestKind::GENERAL: { outputTypesList = {OutputType::FULLY_SPECIFIED}; measureTimingList = {MeasureTiming::NO, MeasureTiming::YES}; - executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST}; + executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, Executor::FENCED}; } break; case TestKind::DYNAMIC_SHAPE: { outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT}; @@ -671,7 +710,8 @@ void EvaluatePreparedCoupledModels(const sp& device, const TestModel& coupledModel) { const std::vector outputTypesList = {OutputType::FULLY_SPECIFIED}; const std::vector measureTimingList = {MeasureTiming::NO, MeasureTiming::YES}; - const std::vector executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST}; + const std::vector executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, + Executor::FENCED}; for (const OutputType outputType : outputTypesList) { for (const MeasureTiming measureTiming : measureTimingList) { diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp index be4112ac2d..1ddd09c033 100644 --- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp @@ -16,7 +16,9 @@ #define LOG_TAG "neuralnetworks_hidl_hal_test" +#include #include + #include "1.0/Utils.h" #include "1.3/Callbacks.h" #include "ExecutionBurstController.h" @@ -136,6 +138,22 @@ static void validate(const sp& preparedModel, const std::string& burst->freeMemory(keys.front()); } } + + // dispatch + { + SCOPED_TRACE(message + " [executeFenced]"); + Return ret = preparedModel->executeFenced( + request, {}, MeasureTiming::NO, + [](ErrorStatus error, const hidl_handle& handle, + const sp& callback) { + if (error != ErrorStatus::DEVICE_UNAVAILABLE) { + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error); + } + ASSERT_EQ(handle.getNativeHandle(), nullptr); + ASSERT_EQ(callback, nullptr); + }); + ASSERT_TRUE(ret.isOk()); + } } ///////////////////////// REMOVE INPUT //////////////////////////////////// diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp index 93c8f13c17..28cc8ffe65 100644 --- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp +++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp @@ -133,6 +133,35 @@ void validateRequestFailure(const sp& preparedModel, const Reque // Forward declaration from ValidateBurst.cpp void validateBurst(const sp& preparedModel, const V1_0::Request& request); +// Validate sync_fence handles for dispatch with valid input +void validateExecuteFenced(const sp& preparedModel, const Request& request) { + SCOPED_TRACE("Expecting request to fail [executeFenced]"); + Return ret_null = + preparedModel->executeFenced(request, {hidl_handle(nullptr)}, V1_2::MeasureTiming::NO, + [](ErrorStatus error, const hidl_handle& handle, + const sp& callback) { + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error); + ASSERT_EQ(handle.getNativeHandle(), nullptr); + ASSERT_EQ(callback, nullptr); + }); + ASSERT_TRUE(ret_null.isOk()); + + native_handle_t* nativeHandle = native_handle_create(1, 0); + ASSERT_NE(nullptr, nativeHandle); + nativeHandle->data[0] = -1; + hidl_handle hidlHandle; + hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true); + Return ret_invalid = + preparedModel->executeFenced(request, {hidlHandle}, V1_2::MeasureTiming::NO, + [](ErrorStatus error, const hidl_handle& handle, + const sp& callback) { + ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error); + ASSERT_EQ(handle.getNativeHandle(), nullptr); + ASSERT_EQ(callback, nullptr); + }); + ASSERT_TRUE(ret_invalid.isOk()); +} + void validateEverything(const sp& device, const Model& model, const Request& request, std::pair supportsDeadlines) { const auto [prepareModelDeadlineSupported, executionDeadlineSupported] = supportsDeadlines; @@ -144,6 +173,7 @@ void validateEverything(const sp& device, const Model& model, const Req if (preparedModel == nullptr) return; validateRequest(preparedModel, request, executionDeadlineSupported); + validateExecuteFenced(preparedModel, request); // TODO(butlermichael): Check if we need to test burst in V1_3 if the interface remains V1_2. ASSERT_TRUE(nn::compliantWithV1_0(request));