summaryrefslogtreecommitdiff
path: root/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'neuralnetworks/1.3/utils/test/PreparedModelTest.cpp')
-rw-r--r--neuralnetworks/1.3/utils/test/PreparedModelTest.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
index 5303c2ad23..6dbbd6bd7e 100644
--- a/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
+++ b/neuralnetworks/1.3/utils/test/PreparedModelTest.cpp
@@ -22,6 +22,7 @@
#include <android/hardware/neuralnetworks/1.3/IFencedExecutionCallback.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <nnapi/IExecution.h>
#include <nnapi/IPreparedModel.h>
#include <nnapi/TypeUtils.h>
#include <nnapi/Types.h>
@@ -462,6 +463,363 @@ TEST(PreparedModelTest, executeFencedDeadObject) {
EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
}
+TEST(PreparedModelTest, reusableExecuteSync) {
+ // setup call
+ const uint32_t kNumberOfComputations = 2;
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(kNumberOfComputations)
+ .WillRepeatedly(
+ Invoke(makeExecuteSynchronously(V1_3::ErrorStatus::NONE, {}, kNoTiming)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute repeatedly
+ for (uint32_t i = 0; i < kNumberOfComputations; i++) {
+ const auto computeResult = createResult.value()->compute({});
+ EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
+ << ": " << computeResult.error().message;
+ }
+}
+
+TEST(PreparedModelTest, reusableExecuteSyncError) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(
+ makeExecuteSynchronously(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteSyncTransportFailure) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteSyncDeadObject) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST(PreparedModelTest, reusableExecuteAsync) {
+ // setup call
+ const uint32_t kNumberOfComputations = 2;
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(kNumberOfComputations)
+ .WillRepeatedly(Invoke(makeExecuteAsynchronously(
+ V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE, {}, kNoTiming)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute repeatedly
+ for (uint32_t i = 0; i < kNumberOfComputations; i++) {
+ const auto computeResult = createResult.value()->compute({});
+ EXPECT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
+ << ": " << computeResult.error().message;
+ }
+}
+
+TEST(PreparedModelTest, reusableExecuteAsyncLaunchError) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeExecuteAsynchronously(V1_3::ErrorStatus::GENERAL_FAILURE,
+ V1_3::ErrorStatus::GENERAL_FAILURE, {},
+ kNoTiming)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteAsyncReturnError) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeExecuteAsynchronously(
+ V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming)));
+
+ // run test
+ const auto result = preparedModel->execute({}, {}, {}, {});
+
+ // verify result
+ ASSERT_FALSE(result.has_value());
+ EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteAsyncTransportFailure) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteAsyncDeadObject) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST(PreparedModelTest, reusableExecuteAsyncCrash) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/false).value();
+ const auto ret = [&mockPreparedModel]() -> hardware::Return<V1_3::ErrorStatus> {
+ mockPreparedModel->simulateCrash();
+ return V1_3::ErrorStatus::NONE;
+ };
+ EXPECT_CALL(*mockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(ret));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->compute({});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
+
+TEST(PreparedModelTest, reusableExecuteFenced) {
+ // setup call
+ const uint32_t kNumberOfComputations = 2;
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_))
+ .Times(kNumberOfComputations)
+ .WillRepeatedly(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::NONE,
+ kNoTiming, kNoTiming)));
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(kNumberOfComputations)
+ .WillRepeatedly(
+ Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute repeatedly
+ for (uint32_t i = 0; i < kNumberOfComputations; i++) {
+ const auto computeResult = createResult.value()->computeFenced({}, {}, {});
+ ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code
+ << ": " << computeResult.error().message;
+ const auto& [syncFence, callback] = computeResult.value();
+ EXPECT_EQ(syncFence.syncWait({}), nn::SyncFence::FenceState::SIGNALED);
+ ASSERT_NE(callback, nullptr);
+
+ // get results from callback
+ const auto callbackResult = callback();
+ ASSERT_TRUE(callbackResult.has_value()) << "Failed with " << callbackResult.error().code
+ << ": " << callbackResult.error().message;
+ }
+}
+
+TEST(PreparedModelTest, reusableExecuteFencedCallbackError) {
+ // setup call
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ const auto mockCallback = MockFencedExecutionCallback::create();
+ EXPECT_CALL(*mockCallback, getExecutionInfo(_))
+ .Times(1)
+ .WillOnce(Invoke(makeExecuteFencedCallbackReturn(V1_3::ErrorStatus::GENERAL_FAILURE,
+ kNoTiming, kNoTiming)));
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, {}, mockCallback)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->computeFenced({}, {}, {});
+ ASSERT_TRUE(computeResult.has_value()) << "Failed with " << computeResult.error().code << ": "
+ << computeResult.error().message;
+ const auto& [syncFence, callback] = computeResult.value();
+ EXPECT_NE(syncFence.syncWait({}), nn::SyncFence::FenceState::ACTIVE);
+ ASSERT_NE(callback, nullptr);
+
+ // verify callback failure
+ const auto callbackResult = callback();
+ ASSERT_FALSE(callbackResult.has_value());
+ EXPECT_EQ(callbackResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteFencedError) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(
+ makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, {}, nullptr)));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->computeFenced({}, {}, {});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteFencedTransportFailure) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->computeFenced({}, {}, {});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::GENERAL_FAILURE);
+}
+
+TEST(PreparedModelTest, reusableExecuteFencedDeadObject) {
+ // setup test
+ const auto mockPreparedModel = createMockPreparedModel();
+ const auto preparedModel =
+ PreparedModel::create(mockPreparedModel, /*executeSynchronously=*/true).value();
+ EXPECT_CALL(*mockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // create execution
+ const auto createResult = preparedModel->createReusableExecution({}, {}, {});
+ ASSERT_TRUE(createResult.has_value())
+ << "Failed with " << createResult.error().code << ": " << createResult.error().message;
+ ASSERT_NE(createResult.value(), nullptr);
+
+ // invoke compute
+ const auto computeResult = createResult.value()->computeFenced({}, {}, {});
+ ASSERT_FALSE(computeResult.has_value());
+ EXPECT_EQ(computeResult.error().code, nn::ErrorStatus::DEAD_OBJECT);
+}
TEST(PreparedModelTest, configureExecutionBurst) {
// setup test
const auto mockPreparedModel = MockPreparedModel::create();