summaryrefslogtreecommitdiff
path: root/nn
diff options
context:
space:
mode:
authorMichael Butler <butlermichael@google.com>2020-05-01 04:05:15 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-05-01 04:05:15 +0000
commite6ed0fc145d449239ad753d8b268a96b928dc830 (patch)
tree304f9ef1871d5579d62f91a3753118f446630432 /nn
parentbd71fcc8c1959c0b5b0d3529169c51e94f666953 (diff)
parent56443eb92c61db057948394493d6a5a237d68de7 (diff)
downloadml-e6ed0fc145d449239ad753d8b268a96b928dc830.tar.gz
Merge changes I3e1eb543,I012eb4df into rvc-dev
* changes: Create tests for VersionedInterfaces errors Simplify IDevice reboot logic
Diffstat (limited to 'nn')
-rw-r--r--nn/common/include/HalInterfaces.h1
-rw-r--r--nn/runtime/Manager.cpp37
-rw-r--r--nn/runtime/Manager.h5
-rw-r--r--nn/runtime/Memory.cpp2
-rw-r--r--nn/runtime/VersionedInterfaces.cpp22
-rw-r--r--nn/runtime/VersionedInterfaces.h13
-rw-r--r--nn/runtime/test/Android.bp4
-rw-r--r--nn/runtime/test/TestVersionedInterfaces.cpp2916
8 files changed, 2969 insertions, 31 deletions
diff --git a/nn/common/include/HalInterfaces.h b/nn/common/include/HalInterfaces.h
index fe1ff563e..4e3a3800b 100644
--- a/nn/common/include/HalInterfaces.h
+++ b/nn/common/include/HalInterfaces.h
@@ -103,6 +103,7 @@ using OperandExtraParams = V1_2::Operand::ExtraParams;
using CacheToken =
hardware::hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using DeviceFactory = std::function<sp<V1_0::IDevice>(bool blocking)>;
using ModelFactory = std::function<Model()>;
inline constexpr Priority kDefaultPriority = Priority::MEDIUM;
diff --git a/nn/runtime/Manager.cpp b/nn/runtime/Manager.cpp
index 7be8419ad..310710e3c 100644
--- a/nn/runtime/Manager.cpp
+++ b/nn/runtime/Manager.cpp
@@ -55,9 +55,10 @@ const Timing kNoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX
// A Device with actual underlying driver
class DriverDevice : public Device {
public:
- // Create a DriverDevice from a name and an IDevice.
+ // Create a DriverDevice from a name and a DeviceFactory function.
// Returns nullptr on failure.
- static std::shared_ptr<DriverDevice> create(std::string name, sp<V1_0::IDevice> device);
+ static std::shared_ptr<DriverDevice> create(const std::string& name,
+ const DeviceFactory& makeDevice);
// Prefer using DriverDevice::create
DriverDevice(std::shared_ptr<VersionedIDevice> device);
@@ -159,6 +160,7 @@ class DriverPreparedModel : public PreparedModel {
DriverDevice::DriverDevice(std::shared_ptr<VersionedIDevice> device)
: kInterface(std::move(device)) {
+ CHECK(kInterface != nullptr);
#ifdef NN_DEBUGGABLE
static const char samplePrefix[] = "sample";
if (getName().substr(0, sizeof(samplePrefix) - 1) == samplePrefix) {
@@ -167,17 +169,17 @@ DriverDevice::DriverDevice(std::shared_ptr<VersionedIDevice> device)
#endif // NN_DEBUGGABLE
}
-std::shared_ptr<DriverDevice> DriverDevice::create(std::string name, sp<V1_0::IDevice> device) {
- CHECK(device != nullptr);
- std::shared_ptr<VersionedIDevice> versionedDevice =
- VersionedIDevice::create(name, std::move(device));
- if (versionedDevice == nullptr) {
+std::shared_ptr<DriverDevice> DriverDevice::create(const std::string& name,
+ const DeviceFactory& makeDevice) {
+ CHECK(makeDevice != nullptr);
+ std::shared_ptr<VersionedIDevice> device = VersionedIDevice::create(name, makeDevice);
+ if (device == nullptr) {
LOG(ERROR) << "DriverDevice::create failed to create VersionedIDevice object for service "
<< name;
return nullptr;
}
- return std::make_shared<DriverDevice>(std::move(versionedDevice));
+ return std::make_shared<DriverDevice>(std::move(device));
}
std::vector<bool> DriverDevice::getSupportedOperations(const MetaModel& metaModel) const {
@@ -817,7 +819,8 @@ std::shared_ptr<Device> DeviceManager::getCpuDevice() {
std::shared_ptr<Device> DeviceManager::forTest_makeDriverDevice(const std::string& name,
const sp<V1_0::IDevice>& device) {
- const auto driverDevice = DriverDevice::create(name, device);
+ const DeviceFactory makeDevice = [device](bool /*blocking*/) { return device; };
+ const auto driverDevice = DriverDevice::create(name, makeDevice);
CHECK(driverDevice != nullptr);
return driverDevice;
}
@@ -829,12 +832,10 @@ void DeviceManager::findAvailableDevices() {
const auto names = hardware::getAllHalInstanceNames(V1_0::IDevice::descriptor);
for (const auto& name : names) {
VLOG(MANAGER) << "Found interface " << name;
- sp<V1_0::IDevice> device = V1_0::IDevice::getService(name);
- if (device == nullptr) {
- LOG(ERROR) << "Got a null IDEVICE for " << name;
- continue;
- }
- registerDevice(name, device);
+ const DeviceFactory makeDevice = [name](bool blocking) {
+ return blocking ? V1_0::IDevice::getService(name) : V1_0::IDevice::tryGetService(name);
+ };
+ registerDevice(name, makeDevice);
}
// register CPU fallback device
@@ -842,9 +843,9 @@ void DeviceManager::findAvailableDevices() {
mDevicesCpuOnly.push_back(CpuDevice::get());
}
-void DeviceManager::registerDevice(const std::string& name, const sp<V1_0::IDevice>& device) {
- if (const auto d = DriverDevice::create(name, device)) {
- mDevices.push_back(d);
+void DeviceManager::registerDevice(const std::string& name, const DeviceFactory& makeDevice) {
+ if (auto device = DriverDevice::create(name, makeDevice)) {
+ mDevices.push_back(std::move(device));
}
}
diff --git a/nn/runtime/Manager.h b/nn/runtime/Manager.h
index c28ee49a6..d6d483576 100644
--- a/nn/runtime/Manager.h
+++ b/nn/runtime/Manager.h
@@ -169,7 +169,8 @@ class DeviceManager {
// Register a test device.
void forTest_registerDevice(const std::string& name, const sp<hal::V1_0::IDevice>& device) {
- registerDevice(name, device);
+ const hal::DeviceFactory makeDevice = [device](bool /*blocking*/) { return device; };
+ registerDevice(name, makeDevice);
}
// Re-initialize the list of available devices.
@@ -192,7 +193,7 @@ class DeviceManager {
DeviceManager();
// Adds a device for the manager to use.
- void registerDevice(const std::string& name, const sp<hal::V1_0::IDevice>& device);
+ void registerDevice(const std::string& name, const hal::DeviceFactory& makeDevice);
void findAvailableDevices();
diff --git a/nn/runtime/Memory.cpp b/nn/runtime/Memory.cpp
index 7bfaf5562..e0bd6b953 100644
--- a/nn/runtime/Memory.cpp
+++ b/nn/runtime/Memory.cpp
@@ -194,7 +194,7 @@ Memory::Memory(sp<hal::IBuffer> buffer, uint32_t token)
: kBuffer(std::move(buffer)), kToken(token) {}
Memory::~Memory() {
- for (const auto [ptr, weakBurst] : mUsedBy) {
+ for (const auto& [ptr, weakBurst] : mUsedBy) {
if (const std::shared_ptr<ExecutionBurstController> burst = weakBurst.lock()) {
burst->freeMemory(getKey());
}
diff --git a/nn/runtime/VersionedInterfaces.cpp b/nn/runtime/VersionedInterfaces.cpp
index cd39a52a7..3ae950eac 100644
--- a/nn/runtime/VersionedInterfaces.cpp
+++ b/nn/runtime/VersionedInterfaces.cpp
@@ -703,8 +703,16 @@ std::optional<InitialData> initialize(const Core& core) {
}
std::shared_ptr<VersionedIDevice> VersionedIDevice::create(std::string serviceName,
- sp<V1_0::IDevice> device) {
- CHECK(device != nullptr) << "VersionedIDevice::create passed invalid device object.";
+ const DeviceFactory& makeDevice) {
+ CHECK(makeDevice != nullptr)
+ << "VersionedIDevice::create passed invalid device factory object.";
+
+ // get handle to IDevice object
+ sp<V1_0::IDevice> device = makeDevice(/*blocking=*/true);
+ if (device == nullptr) {
+ VLOG(DRIVER) << "VersionedIDevice::create got a null IDevice for " << serviceName;
+ return nullptr;
+ }
auto core = Core::create(std::move(device));
if (!core.has_value()) {
@@ -722,20 +730,22 @@ std::shared_ptr<VersionedIDevice> VersionedIDevice::create(std::string serviceNa
std::move(*initialData);
return std::make_shared<VersionedIDevice>(
std::move(capabilities), std::move(supportedExtensions), type, std::move(versionString),
- numberOfCacheFilesNeeded, std::move(serviceName), std::move(core.value()));
+ numberOfCacheFilesNeeded, std::move(serviceName), makeDevice, std::move(core.value()));
}
VersionedIDevice::VersionedIDevice(hal::Capabilities capabilities,
std::vector<hal::Extension> supportedExtensions, int32_t type,
std::string versionString,
std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
- std::string serviceName, Core core)
+ std::string serviceName, const DeviceFactory& makeDevice,
+ Core core)
: kCapabilities(std::move(capabilities)),
kSupportedExtensions(std::move(supportedExtensions)),
kType(type),
kVersionString(std::move(versionString)),
kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded),
kServiceName(std::move(serviceName)),
+ kMakeDevice(makeDevice),
mCore(std::move(core)) {}
std::optional<VersionedIDevice::Core> VersionedIDevice::Core::create(sp<V1_0::IDevice> device) {
@@ -874,7 +884,7 @@ Return<T_Return> VersionedIDevice::recoverable(
if (pingReturn.isDeadObject()) {
VLOG(DRIVER) << "VersionedIDevice::recoverable(" << context << ") -- Recovering "
<< kServiceName;
- sp<V1_0::IDevice> recoveredDevice = V1_0::IDevice::tryGetService(kServiceName);
+ sp<V1_0::IDevice> recoveredDevice = kMakeDevice(/*blocking=*/false);
if (recoveredDevice == nullptr) {
VLOG(DRIVER) << "VersionedIDevice::recoverable got a null IDEVICE for "
<< kServiceName;
@@ -911,7 +921,7 @@ int VersionedIDevice::wait() const {
auto pingReturn = mCore.getDevice<V1_0::IDevice>()->ping();
if (pingReturn.isDeadObject()) {
VLOG(DRIVER) << "VersionedIDevice::wait -- Recovering " << kServiceName;
- sp<V1_0::IDevice> recoveredDevice = V1_0::IDevice::getService(kServiceName);
+ sp<V1_0::IDevice> recoveredDevice = kMakeDevice(/*blocking=*/true);
if (recoveredDevice == nullptr) {
LOG(ERROR) << "VersionedIDevice::wait got a null IDevice for " << kServiceName;
return ANEURALNETWORKS_OP_FAILED;
diff --git a/nn/runtime/VersionedInterfaces.h b/nn/runtime/VersionedInterfaces.h
index 94ca3fe49..efde0bdf5 100644
--- a/nn/runtime/VersionedInterfaces.h
+++ b/nn/runtime/VersionedInterfaces.h
@@ -72,12 +72,12 @@ class VersionedIDevice {
* protections.
*
* @param serviceName The name of the service that provides "device".
- * @param device A device object that is at least version 1.0 of the IDevice
- * interface.
+ * @param makeDevice A device factory function that returns a device object
+ * that is at least version 1.0 of the IDevice interface.
* @return A valid VersionedIDevice object, otherwise nullptr.
*/
static std::shared_ptr<VersionedIDevice> create(std::string serviceName,
- sp<hal::V1_0::IDevice> device);
+ const hal::DeviceFactory& makeDevice);
/**
* Constructor for the VersionedIDevice object.
@@ -92,6 +92,8 @@ class VersionedIDevice {
* @param numberOfCacheFilesNeeded Number of model cache and data cache
* files needed by the driver.
* @param serviceName The name of the service that provides core.getDevice<V1_0::IDevice>().
+ * @param makeDevice A device factory function that returns a device object
+ * that is at least version 1.0 of the IDevice interface.
* @param core An object that encapsulates a V1_0::IDevice, any appropriate downcasts to
* newer interfaces, and a hidl_death_recipient that will proactively handle
* the case when the service containing the IDevice object crashes.
@@ -100,7 +102,7 @@ class VersionedIDevice {
std::vector<hal::Extension> supportedExtensions, int32_t type,
std::string versionString,
std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
- std::string serviceName, Core core);
+ std::string serviceName, const hal::DeviceFactory& makeDevice, Core core);
/**
* Gets the capabilities of a driver.
@@ -554,6 +556,9 @@ class VersionedIDevice {
// The name of the service that implements the driver.
const std::string kServiceName;
+ // Factory function object to generate an IDevice object.
+ const hal::DeviceFactory kMakeDevice;
+
// Guards access to mCore.
mutable std::shared_mutex mMutex;
diff --git a/nn/runtime/test/Android.bp b/nn/runtime/test/Android.bp
index f832d90f5..aed0c4e60 100644
--- a/nn/runtime/test/Android.bp
+++ b/nn/runtime/test/Android.bp
@@ -130,6 +130,7 @@ cc_defaults {
"TestPartitioning.cpp",
"TestPartitioningRandom.cpp",
"TestRemoveDefaultArguments.cpp",
+ "TestVersionedInterfaces.cpp",
"fibonacci_extension/FibonacciDriver.cpp",
"fibonacci_extension/FibonacciExtensionTest.cpp",
@@ -139,7 +140,9 @@ cc_defaults {
],
static_libs: [
"android.hardware.neuralnetworks@1.0-adapter-helper",
+ "android.hardware.neuralnetworks@1.1-adapter-helper",
"android.hardware.neuralnetworks@1.2-adapter-helper",
+ "android.hardware.neuralnetworks@1.3-adapter-helper",
"libSampleDriver",
"libgmock",
"libhidladapter",
@@ -152,6 +155,7 @@ cc_defaults {
],
header_libs: [
"libneuralnetworks_private_headers",
+ "libutils_headers",
"neuralnetworks_example_fibonacci_extension",
],
}
diff --git a/nn/runtime/test/TestVersionedInterfaces.cpp b/nn/runtime/test/TestVersionedInterfaces.cpp
new file mode 100644
index 000000000..6d1306d57
--- /dev/null
+++ b/nn/runtime/test/TestVersionedInterfaces.cpp
@@ -0,0 +1,2916 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/ADevice.h>
+#include <android/hardware/neuralnetworks/1.1/ADevice.h>
+#include <android/hardware/neuralnetworks/1.2/ADevice.h>
+#include <android/hardware/neuralnetworks/1.3/ADevice.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/Status.h>
+#include <utils/Errors.h>
+
+#include <limits>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "HalInterfaces.h"
+#include "MemoryUtils.h"
+#include "MetaModel.h"
+#include "VersionedInterfaces.h"
+
+namespace android::nn {
+namespace {
+
+using namespace hal;
+using testing::_;
+using testing::Invoke;
+using testing::InvokeWithoutArgs;
+using testing::MockFunction;
+using MockDeviceFactory = MockFunction<sp<V1_0::IDevice>(bool blocking)>;
+
+constexpr uint32_t kNoCacheFilesNeeded = 0;
+constexpr uint32_t kMaxNumberOfCacheFiles =
+ static_cast<uint32_t>(Constant::MAX_NUMBER_OF_CACHE_FILES);
+constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits<uint64_t>::max(),
+ .timeInDriver = std::numeric_limits<uint64_t>::max()};
+
+template <typename... Args>
+auto makeCallbackReturn(Args&&... args) {
+ return [argPack = std::make_tuple(std::forward<Args>(args)...)](const auto& cb) {
+ std::apply(cb, argPack);
+ return Void();
+ };
+};
+
+class MockDevice : public IDevice {
+ public:
+ static sp<MockDevice> create() {
+ const sp<MockDevice> mockDevice = new MockDevice();
+
+ const auto linkToDeathRet_ret = []() -> Return<bool> { return true; };
+ const auto getCapabilities_ret =
+ makeCallbackReturn(V1_0::ErrorStatus::NONE, V1_0::Capabilities{});
+ const auto getCapabilities_1_1_ret =
+ makeCallbackReturn(V1_0::ErrorStatus::NONE, V1_1::Capabilities{});
+ const auto getVersionString_ret =
+ makeCallbackReturn(V1_0::ErrorStatus::NONE, "Google-MockV1");
+ const auto getType_ret = makeCallbackReturn(V1_0::ErrorStatus::NONE, DeviceType::OTHER);
+ const auto getCapabilities_1_2_ret =
+ makeCallbackReturn(V1_0::ErrorStatus::NONE, V1_2::Capabilities{});
+ const auto getSupportedExtensions_ret =
+ makeCallbackReturn(V1_0::ErrorStatus::NONE, hidl_vec<Extension>{});
+ const auto getNumberOfCacheFilesNeeded_ret = makeCallbackReturn(
+ V1_0::ErrorStatus::NONE, kMaxNumberOfCacheFiles, kMaxNumberOfCacheFiles);
+ const auto getCapabilities_1_3_ret =
+ makeCallbackReturn(V1_3::ErrorStatus::NONE, V1_3::Capabilities{});
+
+ ON_CALL(*mockDevice, linkToDeathRet()).WillByDefault(Invoke(linkToDeathRet_ret));
+ ON_CALL(*mockDevice, getCapabilities(_)).WillByDefault(Invoke(getCapabilities_ret));
+ ON_CALL(*mockDevice, getCapabilities_1_1(_)).WillByDefault(Invoke(getCapabilities_1_1_ret));
+ ON_CALL(*mockDevice, getVersionString(_)).WillByDefault(Invoke(getVersionString_ret));
+ ON_CALL(*mockDevice, getType(_)).WillByDefault(Invoke(getType_ret));
+ ON_CALL(*mockDevice, getCapabilities_1_2(_)).WillByDefault(Invoke(getCapabilities_1_2_ret));
+ ON_CALL(*mockDevice, getSupportedExtensions(_))
+ .WillByDefault(Invoke(getSupportedExtensions_ret));
+ ON_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
+ .WillByDefault(Invoke(getNumberOfCacheFilesNeeded_ret));
+ ON_CALL(*mockDevice, getCapabilities_1_3(_)).WillByDefault(Invoke(getCapabilities_1_3_ret));
+
+ // These EXPECT_CALL(...).Times(testing::AnyNumber()) calls are to
+ // suppress warnings on the uninteresting methods calls.
+ EXPECT_CALL(*mockDevice, linkToDeathRet()).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getVersionString(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getType(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getCapabilities_1_2(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getSupportedExtensions(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, getCapabilities_1_3(_)).Times(testing::AnyNumber());
+
+ return mockDevice;
+ }
+
+ // IBase methods below.
+ Return<bool> linkToDeath(const sp<hidl_death_recipient>& recipient,
+ uint64_t /*cookie*/) override {
+ mDeathRecipient = recipient;
+ return linkToDeathRet();
+ }
+ MOCK_METHOD(Return<void>, ping, (), (override));
+
+ // V1_0 methods below.
+ MOCK_METHOD(Return<void>, getCapabilities, (getCapabilities_cb cb), (override));
+ MOCK_METHOD(Return<void>, getSupportedOperations,
+ (const V1_0::Model& model, getSupportedOperations_cb cb), (override));
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, prepareModel,
+ (const V1_0::Model& model, const sp<V1_0::IPreparedModelCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<DeviceStatus>, getStatus, (), (override));
+
+ // V1_1 methods below.
+ MOCK_METHOD(Return<void>, getCapabilities_1_1, (getCapabilities_1_1_cb cb), (override));
+ MOCK_METHOD(Return<void>, getSupportedOperations_1_1,
+ (const V1_1::Model& model, getSupportedOperations_1_1_cb cb), (override));
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, prepareModel_1_1,
+ (const V1_1::Model& model, ExecutionPreference preference,
+ const sp<V1_0::IPreparedModelCallback>& callback),
+ (override));
+
+ // V1_2 methods below.
+ MOCK_METHOD(Return<void>, getVersionString, (getVersionString_cb cb), (override));
+ MOCK_METHOD(Return<void>, getType, (getType_cb cb), (override));
+ MOCK_METHOD(Return<void>, getCapabilities_1_2, (getCapabilities_1_2_cb cb), (override));
+ MOCK_METHOD(Return<void>, getSupportedExtensions, (getSupportedExtensions_cb cb), (override));
+ MOCK_METHOD(Return<void>, getSupportedOperations_1_2,
+ (const V1_2::Model& model, getSupportedOperations_1_2_cb cb), (override));
+ MOCK_METHOD(Return<void>, getNumberOfCacheFilesNeeded, (getNumberOfCacheFilesNeeded_cb cb),
+ (override));
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, prepareModel_1_2,
+ (const V1_2::Model& model, ExecutionPreference preference,
+ const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, prepareModelFromCache,
+ (const hidl_vec<hidl_handle>& modelCache, const hidl_vec<hidl_handle>& dataCache,
+ const CacheToken& token, const sp<V1_2::IPreparedModelCallback>& callback),
+ (override));
+
+ // V1_3 methods below.
+ MOCK_METHOD(Return<void>, getCapabilities_1_3, (getCapabilities_1_3_cb cb), (override));
+ MOCK_METHOD(Return<void>, getSupportedOperations_1_3,
+ (const V1_3::Model& model, getSupportedOperations_1_3_cb cb), (override));
+ MOCK_METHOD(Return<V1_3::ErrorStatus>, prepareModel_1_3,
+ (const V1_3::Model& model, ExecutionPreference preference, Priority priority,
+ const OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<V1_3::ErrorStatus>, prepareModelFromCache_1_3,
+ (const OptionalTimePoint& deadline, const hidl_vec<hidl_handle>& modelCache,
+ const hidl_vec<hidl_handle>& dataCache, const CacheToken& token,
+ const sp<V1_3::IPreparedModelCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<void>, allocate,
+ (const BufferDesc& desc, const hidl_vec<sp<V1_3::IPreparedModel>>& preparedModels,
+ const hidl_vec<BufferRole>& inputRoles, const hidl_vec<BufferRole>& outputRoles,
+ allocate_cb cb),
+ (override));
+
+ // Helper methods.
+ MOCK_METHOD(Return<bool>, linkToDeathRet, ());
+ void simulateCrash() {
+ ASSERT_NE(nullptr, mDeathRecipient.get());
+
+ // Currently, the VersionedInterfaces code will not use the `cookie` or
+ // `who` arguments, so we pass in 0 and nullptr for these arguments
+ // instead. Normally, they are used by the hidl_death_recipient to
+ // determine which object is dead. However, the VersionedInterfaces
+ // code only pairs a single death recipient with a single HIDL
+ // interface object, so these arguments are redundant.
+ mDeathRecipient->serviceDied(0, nullptr);
+ }
+
+ private:
+ // Members.
+ sp<hidl_death_recipient> mDeathRecipient;
+};
+
+class MockPreparedModel : public IPreparedModel {
+ public:
+ static sp<MockPreparedModel> create() {
+ const sp<MockPreparedModel> mockPreparedModel = new MockPreparedModel();
+
+ const auto linkToDeathRet_ret = []() -> Return<bool> { return true; };
+ ON_CALL(*mockPreparedModel, linkToDeathRet()).WillByDefault(Invoke(linkToDeathRet_ret));
+
+ // This EXPECT_CALL(...).Times(testing::AnyNumber()) calls are to
+ // suppress warnings on the uninteresting methods calls.
+ EXPECT_CALL(*mockPreparedModel, linkToDeathRet()).Times(testing::AnyNumber());
+
+ return mockPreparedModel;
+ }
+
+ // IBase methods below.
+ Return<bool> linkToDeath(const sp<hidl_death_recipient>& recipient,
+ uint64_t /*cookie*/) override {
+ mDeathRecipient = recipient;
+ return linkToDeathRet();
+ }
+ MOCK_METHOD(Return<void>, ping, (), (override));
+
+ // V1_0 methods below.
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, execute,
+ (const V1_0::Request& request, const sp<V1_0::IExecutionCallback>& callback),
+ (override));
+
+ // V1_2 methods below.
+ MOCK_METHOD(Return<V1_0::ErrorStatus>, execute_1_2,
+ (const V1_0::Request& request, MeasureTiming measure,
+ const sp<V1_2::IExecutionCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<void>, executeSynchronously,
+ (const V1_0::Request& request, MeasureTiming measure, executeSynchronously_cb cb),
+ (override));
+ MOCK_METHOD(Return<void>, configureExecutionBurst,
+ (const sp<V1_2::IBurstCallback>& callback,
+ const hardware::MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
+ const hardware::MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
+ configureExecutionBurst_cb cb),
+ (override));
+
+ // V1_3 methods below.
+ MOCK_METHOD(Return<ErrorStatus>, execute_1_3,
+ (const V1_3::Request& request, MeasureTiming measure,
+ const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration,
+ const sp<IExecutionCallback>& callback),
+ (override));
+ MOCK_METHOD(Return<void>, executeSynchronously_1_3,
+ (const V1_3::Request& request, MeasureTiming measure,
+ const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration,
+ executeSynchronously_1_3_cb cb),
+ (override));
+ MOCK_METHOD(Return<void>, executeFenced,
+ (const V1_3::Request& request, const hidl_vec<hidl_handle>& waitFor,
+ MeasureTiming measure, const OptionalTimePoint& deadline,
+ const OptionalTimeoutDuration& loopTimeoutDuration,
+ const OptionalTimeoutDuration& duration, executeFenced_cb cb),
+ (override));
+
+ // Helper methods.
+ MOCK_METHOD(Return<bool>, linkToDeathRet, ());
+ void simulateCrash() {
+ ASSERT_NE(nullptr, mDeathRecipient.get());
+
+ // Currently, the VersionedInterfaces code will not use the `cookie` or
+ // `who` arguments, so we pass in 0 and nullptr for these arguments
+ // instead. Normally, they are used by the hidl_death_recipient to
+ // determine which object is dead. However, the VersionedInterfaces
+ // code only pairs a single death recipient with a single HIDL
+ // interface object, so these arguments are redundant.
+ mDeathRecipient->serviceDied(0, nullptr);
+ }
+
+ private:
+ // Members.
+ sp<hidl_death_recipient> mDeathRecipient;
+};
+
+class MockBurstContext : public V1_2::IBurstContext {
+ public:
+ // V1_2 methods below.
+ MOCK_METHOD(Return<void>, freeMemory, (int32_t slot), (override));
+};
+
+class MockFencedExecutionCallback : public IFencedExecutionCallback {
+ public:
+ // V1_3 methods below.
+ MOCK_METHOD(Return<void>, getExecutionInfo, (getExecutionInfo_cb cb), (override));
+};
+
+class MockBuffer : public IBuffer {
+ public:
+ // V1_3 methods below.
+ MOCK_METHOD(Return<ErrorStatus>, copyTo, (const hidl_memory& dst), (override));
+ MOCK_METHOD(Return<ErrorStatus>, copyFrom,
+ (const hidl_memory& src, const hidl_vec<uint32_t>& dimensions), (override));
+};
+
+enum class Version { V1_0, V1_1, V1_2, V1_3, MOCK };
+
+sp<V1_0::IDevice> adaptAs(const sp<MockDevice>& mockDevice, Version version) {
+ switch (version) {
+ case Version::V1_0:
+ return new V1_0::ADevice(mockDevice);
+ case Version::V1_1:
+ return new V1_1::ADevice(mockDevice);
+ case Version::V1_2:
+ return new V1_2::ADevice(mockDevice);
+ case Version::V1_3:
+ return new V1_3::ADevice(mockDevice);
+ case Version::MOCK:
+ return mockDevice;
+ }
+ LOG(FATAL) << "unrecognized version: " << static_cast<int>(version);
+ return nullptr;
+}
+
+auto makePreparedModelReturn(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
+ const sp<MockPreparedModel>& preparedModel) {
+ return [launchStatus, returnStatus, preparedModel](
+ const V1_0::Model& /*model*/,
+ const sp<V1_0::IPreparedModelCallback>& cb) -> Return<V1_0::ErrorStatus> {
+ cb->notify(returnStatus, preparedModel).isOk();
+ return launchStatus;
+ };
+}
+auto makePreparedModel_1_1Return(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
+ const sp<MockPreparedModel>& preparedModel) {
+ return [launchStatus, returnStatus, preparedModel](
+ const V1_1::Model& /*model*/, ExecutionPreference /*preference*/,
+ const sp<V1_0::IPreparedModelCallback>& cb) -> Return<V1_0::ErrorStatus> {
+ cb->notify(returnStatus, preparedModel).isOk();
+ return launchStatus;
+ };
+}
+auto makePreparedModel_1_2Return(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
+ const sp<MockPreparedModel>& preparedModel) {
+ return [launchStatus, returnStatus, preparedModel](
+ const V1_2::Model& /*model*/, ExecutionPreference /*preference*/,
+ const auto& /*modelCache*/, const auto& /*dataCache*/, const auto& /*token*/,
+ const sp<V1_2::IPreparedModelCallback>& cb) -> Return<V1_0::ErrorStatus> {
+ cb->notify_1_2(returnStatus, preparedModel).isOk();
+ return launchStatus;
+ };
+}
+auto makePreparedModel_1_3Return(V1_3::ErrorStatus launchStatus, V1_3::ErrorStatus returnStatus,
+ const sp<MockPreparedModel>& preparedModel) {
+ return [launchStatus, returnStatus, preparedModel](
+ const V1_3::Model& /*model*/, ExecutionPreference /*preference*/,
+ Priority /*priority*/, const OptionalTimePoint& /*deadline*/,
+ const hidl_vec<hidl_handle>& /*modelCache*/,
+ const hidl_vec<hidl_handle>& /*dataCache*/, const CacheToken& /*token*/,
+ const sp<V1_3::IPreparedModelCallback>& cb) -> Return<V1_3::ErrorStatus> {
+ cb->notify_1_3(returnStatus, preparedModel).isOk();
+ return launchStatus;
+ };
+}
+
+auto makeExecuteReturn(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus) {
+ return [launchStatus, returnStatus](
+ const V1_0::Request& /*request*/,
+ const sp<V1_0::IExecutionCallback>& cb) -> Return<V1_0::ErrorStatus> {
+ cb->notify(returnStatus);
+ return launchStatus;
+ };
+}
+auto makeExecute_1_2Return(V1_0::ErrorStatus launchStatus, V1_0::ErrorStatus returnStatus,
+ const std::vector<OutputShape>& outputShapes, const Timing& timing) {
+ return [launchStatus, returnStatus, outputShapes, timing](
+ const V1_0::Request& /*request*/, MeasureTiming /*measureTiming*/,
+ const sp<V1_2::IExecutionCallback>& cb) -> Return<V1_0::ErrorStatus> {
+ cb->notify_1_2(returnStatus, outputShapes, timing);
+ return launchStatus;
+ };
+}
+auto makeExecute_1_3Return(V1_3::ErrorStatus launchStatus, V1_3::ErrorStatus returnStatus,
+ const std::vector<OutputShape>& outputShapes, const Timing& timing) {
+ return [launchStatus, returnStatus, outputShapes, timing](
+ const V1_3::Request& /*request*/, MeasureTiming /*measureTiming*/,
+ const OptionalTimePoint& /*deadline*/,
+ const OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const sp<V1_3::IExecutionCallback>& cb) -> Return<V1_3::ErrorStatus> {
+ cb->notify_1_3(returnStatus, outputShapes, timing);
+ return launchStatus;
+ };
+}
+auto makeExecuteSynchronouslyReturn(V1_0::ErrorStatus status,
+ const std::vector<OutputShape>& outputShapes,
+ const Timing& timing) {
+ return [status, outputShapes, timing](const V1_0::Request& /*request*/,
+ MeasureTiming /*measureTiming*/,
+ const V1_2::IPreparedModel::executeSynchronously_cb& cb) {
+ cb(status, outputShapes, timing);
+ return Void();
+ };
+}
+auto makeExecuteSynchronously_1_3Return(V1_3::ErrorStatus status,
+ const std::vector<OutputShape>& outputShapes,
+ const Timing& timing) {
+ return [status, outputShapes, timing](
+ const V1_3::Request& /*request*/, MeasureTiming /*measureTiming*/,
+ const OptionalTimePoint& /*deadline*/,
+ const OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const V1_3::IPreparedModel::executeSynchronously_1_3_cb& cb) {
+ cb(status, outputShapes, timing);
+ return Void();
+ };
+}
+auto makeConfigureExecutionBurst(V1_0::ErrorStatus status,
+ const sp<MockBurstContext>& burstContext) {
+ return [status, burstContext](
+ const sp<V1_2::IBurstCallback>& /*callback*/,
+ const hardware::MQDescriptorSync<V1_2::FmqRequestDatum>& /*requestChannel*/,
+ const hardware::MQDescriptorSync<V1_2::FmqResultDatum>& /*resultChannel*/,
+ V1_2::IPreparedModel::configureExecutionBurst_cb cb) {
+ cb(status, burstContext);
+ return Void();
+ };
+}
+auto makeExecuteFencedReturn(V1_3::ErrorStatus status, const hidl_handle& syncFence,
+ const sp<IFencedExecutionCallback>& dispatchCallback) {
+ return [status, syncFence, dispatchCallback](
+ const V1_3::Request& /*request*/, const hidl_vec<hidl_handle>& /*waitFor*/,
+ MeasureTiming /*measure*/, const OptionalTimePoint& /*deadline*/,
+ const OptionalTimeoutDuration& /*loopTimeoutDuration*/,
+ const OptionalTimeoutDuration& /*duration*/,
+ V1_3::IPreparedModel::executeFenced_cb cb) {
+ cb(status, syncFence, dispatchCallback);
+ return Void();
+ };
+}
+
+// TODO: The "setupInitializationExpectation*" calls below re-specify the
+// number of expected times each initialization method is called. Because
+// this was originally set to `testing::AnyNumber()` when the object was
+// created, do these calls act as no-ops, do they override the previous
+// expectations, or are both expectations still active?
+
+void setupInitializationExpectationsV1_0(const sp<MockDevice>& mockDevice) {
+ EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_2(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_3(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getVersionString(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getType(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getSupportedExtensions(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(0);
+}
+
+void setupInitializationExpectationsV1_1(const sp<MockDevice>& mockDevice) {
+ EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_2(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_3(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getVersionString(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getType(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getSupportedExtensions(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(0);
+}
+
+void setupInitializationExpectationsV1_2(const sp<MockDevice>& mockDevice) {
+ EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_3(_)).Times(0);
+}
+
+void setupInitializationExpectationsV1_3(const sp<MockDevice>& mockDevice) {
+ EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_2(_)).Times(0);
+}
+
+void setupInitializationExpectations(const sp<MockDevice>& mockDevice, Version version) {
+ switch (version) {
+ case Version::V1_0:
+ setupInitializationExpectationsV1_0(mockDevice);
+ return;
+ case Version::V1_1:
+ setupInitializationExpectationsV1_1(mockDevice);
+ return;
+ case Version::V1_2:
+ setupInitializationExpectationsV1_2(mockDevice);
+ return;
+ case Version::V1_3:
+ setupInitializationExpectationsV1_3(mockDevice);
+ return;
+ case Version::MOCK:
+ setupInitializationExpectationsV1_3(mockDevice);
+ return;
+ }
+ LOG(FATAL) << "unrecognized version: " << static_cast<int>(version);
+}
+
+void setupSuccessfulInitializationExpectations(const sp<MockDevice>& mockDevice, Version version) {
+ EXPECT_CALL(*mockDevice, linkToDeathRet()).Times(testing::AnyNumber());
+
+ const int numCallsForV1_0 = (version == Version::V1_0 ? 1 : 0);
+ EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(numCallsForV1_0);
+
+ const int numCallsForV1_1 = (version == Version::V1_1 ? 1 : 0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_1(_)).Times(numCallsForV1_1);
+
+ const int numCallsForV1_2 = (version == Version::V1_2 ? 1 : 0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_2(_)).Times(numCallsForV1_2);
+
+ const int numCallsForAtLeastV1_3 = (version >= Version::V1_3 ? 1 : 0);
+ EXPECT_CALL(*mockDevice, getCapabilities_1_3(_)).Times(numCallsForAtLeastV1_3);
+
+ const int numCallsForAtLeastV1_2 = (version >= Version::V1_2 ? 1 : 0);
+ EXPECT_CALL(*mockDevice, getVersionString(_)).Times(numCallsForAtLeastV1_2);
+ EXPECT_CALL(*mockDevice, getType(_)).Times(numCallsForAtLeastV1_2);
+ EXPECT_CALL(*mockDevice, getSupportedExtensions(_)).Times(numCallsForAtLeastV1_2);
+ EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(numCallsForAtLeastV1_2);
+}
+
+std::shared_ptr<VersionedIDevice> makeVersionedIDeviceFrom(const sp<MockDevice>& mockDevice,
+ MockDeviceFactory* mockDeviceFactory,
+ Version version) {
+ setupInitializationExpectations(mockDevice, version);
+ const auto device = adaptAs(mockDevice, version);
+ ON_CALL(*mockDeviceFactory, Call(_)).WillByDefault(testing::Return(device));
+ EXPECT_CALL(*mockDeviceFactory, Call(/*blocking=*/true)).Times(testing::AtLeast(1));
+ const DeviceFactory makeDevice = mockDeviceFactory->AsStdFunction();
+ return VersionedIDevice::create("MockDevice", makeDevice);
+}
+
+std::shared_ptr<VersionedIDevice> makeVersionedIDeviceSuccessfulInitializationFrom(
+ const sp<MockDevice>& device, MockDeviceFactory* mockDeviceFactory, Version version) {
+ setupSuccessfulInitializationExpectations(device, version);
+ return makeVersionedIDeviceFrom(device, mockDeviceFactory, version);
+}
+
+std::function<hardware::Status()> makeTransportFailure(status_t status) {
+ return [status] { return hardware::Status::fromStatusT(status); };
+}
+
+const auto makeGeneralTransportFailure = makeTransportFailure(NO_MEMORY);
+const auto makeDeadObjectFailure = makeTransportFailure(DEAD_OBJECT);
+
+class VersionedIDeviceTest : public testing::Test {
+ protected:
+ const sp<MockDevice> kMockDevice = MockDevice::create();
+ const std::unique_ptr<MockDeviceFactory> kMockMakeDevice =
+ std::make_unique<MockDeviceFactory>();
+};
+
+class VersionedIDeviceInitializationTest : public VersionedIDeviceTest {};
+
+template <Version version>
+class VersionedIDeviceInitializedTest : public VersionedIDeviceTest {
+ protected:
+ void SetUp() override {
+ VersionedIDeviceTest::SetUp();
+ ASSERT_NE(nullptr, kDevice.get());
+ }
+
+ const std::shared_ptr<VersionedIDevice> kDevice =
+ makeVersionedIDeviceSuccessfulInitializationFrom(kMockDevice, kMockMakeDevice.get(),
+ version);
+};
+
+class VersionedIDeviceV1_0Test : public VersionedIDeviceInitializedTest<Version::V1_0> {};
+class VersionedIDeviceV1_1Test : public VersionedIDeviceInitializedTest<Version::V1_1> {};
+class VersionedIDeviceV1_2Test : public VersionedIDeviceInitializedTest<Version::V1_2> {};
+class VersionedIDeviceV1_3Test : public VersionedIDeviceInitializedTest<Version::V1_3> {};
+class VersionedIDeviceMockTest : public VersionedIDeviceInitializedTest<Version::MOCK> {};
+
+// Simulate initialization/link error
+
+TEST_F(VersionedIDeviceInitializationTest, creationFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockMakeDevice, Call(_)).Times(1).WillOnce(testing::Return(nullptr));
+ const DeviceFactory makeDevice = kMockMakeDevice->AsStdFunction();
+
+ // run test
+ const auto device = VersionedIDevice::create("MockDevice", makeDevice);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, linkToDeathTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, linkToDeathRet())
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+ EXPECT_CALL(*kMockMakeDevice, Call(_)).Times(1).WillOnce(testing::Return(kMockDevice));
+ const DeviceFactory makeDevice = kMockMakeDevice->AsStdFunction();
+
+ // run test
+ const auto device = VersionedIDevice::create("MockDevice", makeDevice);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, linkToDeathReturnError) {
+ // setup failure
+ const auto ret = []() -> Return<bool> { return false; };
+ EXPECT_CALL(*kMockMakeDevice, Call(_)).Times(1).WillOnce(testing::Return(kMockDevice));
+ EXPECT_CALL(*kMockDevice, linkToDeathRet()).Times(1).WillOnce(InvokeWithoutArgs(ret));
+ const DeviceFactory makeDevice = kMockMakeDevice->AsStdFunction();
+
+ // run test
+ const auto device = VersionedIDevice::create("MockDevice", makeDevice);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilitiesFailure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, V1_0::Capabilities{});
+ EXPECT_CALL(*kMockDevice, getCapabilities(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_0);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_1Failure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, V1_1::Capabilities{});
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_1(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_1);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_2Failure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, V1_2::Capabilities{});
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_2(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_3Failure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_3::ErrorStatus::GENERAL_FAILURE, V1_3::Capabilities{});
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_3(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_3);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getVersionStringFailure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, "");
+ EXPECT_CALL(*kMockDevice, getVersionString(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getTypeFailure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, DeviceType::OTHER);
+ EXPECT_CALL(*kMockDevice, getType(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getSupportedExtensionsFailure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, hidl_vec<Extension>{});
+ EXPECT_CALL(*kMockDevice, getSupportedExtensions(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getNumberOfCacheFilesNeededFailure) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::GENERAL_FAILURE, kMaxNumberOfCacheFiles,
+ kMaxNumberOfCacheFiles);
+ EXPECT_CALL(*kMockDevice, getNumberOfCacheFilesNeeded(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, dataCacheFilesExceedsSpecifiedMax) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::NONE, kMaxNumberOfCacheFiles + 1,
+ kMaxNumberOfCacheFiles);
+ EXPECT_CALL(*kMockDevice, getNumberOfCacheFilesNeeded(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, modelCacheFilesExceedsSpecifiedMax) {
+ // setup failure
+ const auto ret = makeCallbackReturn(V1_0::ErrorStatus::NONE, kMaxNumberOfCacheFiles,
+ kMaxNumberOfCacheFiles + 1);
+ EXPECT_CALL(*kMockDevice, getNumberOfCacheFilesNeeded(_)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilitiesTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getCapabilities(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_0);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_1TransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_1(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_1);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_2TransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_2(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getCapabilities_1_3TransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getCapabilities_1_3(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_3);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getVersionStringTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getVersionString(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getTypeTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getType(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getSupportedExtensionsTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getSupportedExtensions(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+TEST_F(VersionedIDeviceInitializationTest, getNumberOfCacheFilesNeededTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getNumberOfCacheFilesNeeded(_))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto device = makeVersionedIDeviceFrom(kMockDevice, kMockMakeDevice.get(), Version::V1_2);
+
+ // verify failure
+ EXPECT_EQ(nullptr, device.get());
+}
+
+// Ensure device has cached metadata
+
+TEST_F(VersionedIDeviceV1_0Test, getCapabilities) {
+ // run test
+ const auto capabilities = kDevice->getCapabilities();
+ const auto cached = kDevice->getCapabilities();
+
+ // verify success
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceScalar);
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceTensor);
+ EXPECT_LT(0u, capabilities.operandPerformance.size());
+ EXPECT_EQ(cached, capabilities);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getCapabilities) {
+ // run test
+ const auto capabilities = kDevice->getCapabilities();
+ const auto cached = kDevice->getCapabilities();
+
+ // verify success
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceScalar);
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceTensor);
+ EXPECT_LT(0u, capabilities.operandPerformance.size());
+ EXPECT_EQ(cached, capabilities);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getCapabilities) {
+ // run test
+ const auto capabilities = kDevice->getCapabilities();
+ const auto cached = kDevice->getCapabilities();
+
+ // verify success
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceScalar);
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceTensor);
+ EXPECT_EQ(0u, capabilities.operandPerformance.size());
+ EXPECT_EQ(cached, capabilities);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getCapabilities) {
+ // run test
+ const auto capabilities = kDevice->getCapabilities();
+ const auto cached = kDevice->getCapabilities();
+
+ // verify success
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceScalar);
+ EXPECT_EQ(PerformanceInfo{}, capabilities.relaxedFloat32toFloat16PerformanceTensor);
+ EXPECT_EQ(0u, capabilities.operandPerformance.size());
+ EXPECT_EQ(cached, capabilities);
+}
+
+TEST_F(VersionedIDeviceV1_0Test, getVersionString) {
+ // run test
+ const auto versionString = kDevice->getVersionString();
+ const auto cached = kDevice->getVersionString();
+
+ // verify success
+ EXPECT_EQ("UNKNOWN", versionString);
+ EXPECT_EQ(cached, versionString);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getVersionString) {
+ // run test
+ const auto versionString = kDevice->getVersionString();
+ const auto cached = kDevice->getVersionString();
+
+ // verify success
+ EXPECT_EQ("UNKNOWN", versionString);
+ EXPECT_EQ(cached, versionString);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getVersionString) {
+ // run test
+ const auto versionString = kDevice->getVersionString();
+ const auto cached = kDevice->getVersionString();
+
+ // verify success
+ EXPECT_EQ("Google-MockV1", versionString);
+ EXPECT_EQ(cached, versionString);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getVersionString) {
+ // run test
+ const auto versionString = kDevice->getVersionString();
+ const auto cached = kDevice->getVersionString();
+
+ // verify success
+ EXPECT_EQ("Google-MockV1", versionString);
+ EXPECT_EQ(cached, versionString);
+}
+
+TEST_F(VersionedIDeviceV1_0Test, getType) {
+ // run test
+ const auto type = kDevice->getType();
+ const auto cached = kDevice->getType();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_DEVICE_UNKNOWN, type);
+ EXPECT_EQ(cached, type);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getType) {
+ // run test
+ const auto type = kDevice->getType();
+ const auto cached = kDevice->getType();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_DEVICE_UNKNOWN, type);
+ EXPECT_EQ(cached, type);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getType) {
+ // run test
+ const auto type = kDevice->getType();
+ const auto cached = kDevice->getType();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_DEVICE_OTHER, type);
+ EXPECT_EQ(cached, type);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getType) {
+ // run test
+ const auto type = kDevice->getType();
+ const auto cached = kDevice->getType();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_DEVICE_OTHER, type);
+ EXPECT_EQ(cached, type);
+}
+
+TEST_F(VersionedIDeviceV1_0Test, getSupportedExtensions) {
+ // run test
+ const auto supportedExtensions = kDevice->getSupportedExtensions();
+ const auto cached = kDevice->getSupportedExtensions();
+
+ // verify success
+ EXPECT_EQ(0u, supportedExtensions.size());
+ EXPECT_EQ(cached, supportedExtensions);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getSupportedExtensions) {
+ // run test
+ const auto supportedExtensions = kDevice->getSupportedExtensions();
+ const auto cached = kDevice->getSupportedExtensions();
+
+ // verify success
+ EXPECT_EQ(0u, supportedExtensions.size());
+ EXPECT_EQ(cached, supportedExtensions);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getSupportedExtensions) {
+ // run test
+ const auto supportedExtensions = kDevice->getSupportedExtensions();
+ const auto cached = kDevice->getSupportedExtensions();
+
+ // verify success
+ EXPECT_EQ(0u, supportedExtensions.size());
+ EXPECT_EQ(cached, supportedExtensions);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getSupportedExtensions) {
+ // run test
+ const auto supportedExtensions = kDevice->getSupportedExtensions();
+ const auto cached = kDevice->getSupportedExtensions();
+
+ // verify success
+ EXPECT_EQ(0u, supportedExtensions.size());
+ EXPECT_EQ(cached, supportedExtensions);
+}
+
+TEST_F(VersionedIDeviceV1_0Test, getNumberOfCacheFilesNeeded) {
+ // run test
+ const auto [dataCacheFilesNeeded, modelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+ const auto [cachedDataCacheFilesNeeded, cachedModelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+
+ // verify success
+ EXPECT_EQ(kNoCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(kNoCacheFilesNeeded, modelCacheFilesNeeded);
+ EXPECT_EQ(cachedDataCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(cachedModelCacheFilesNeeded, modelCacheFilesNeeded);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getNumberOfCacheFilesNeeded) {
+ // run test
+ const auto [dataCacheFilesNeeded, modelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+ const auto [cachedDataCacheFilesNeeded, cachedModelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+
+ // verify success
+ EXPECT_EQ(kNoCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(kNoCacheFilesNeeded, modelCacheFilesNeeded);
+ EXPECT_EQ(cachedDataCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(cachedModelCacheFilesNeeded, modelCacheFilesNeeded);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getNumberOfCacheFilesNeeded) {
+ // run test
+ const auto [dataCacheFilesNeeded, modelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+ const auto [cachedDataCacheFilesNeeded, cachedModelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+
+ // verify success
+ EXPECT_EQ(kMaxNumberOfCacheFiles, dataCacheFilesNeeded);
+ EXPECT_EQ(kMaxNumberOfCacheFiles, modelCacheFilesNeeded);
+ EXPECT_EQ(cachedDataCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(cachedModelCacheFilesNeeded, modelCacheFilesNeeded);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getNumberOfCacheFilesNeeded) {
+ // run test
+ const auto [dataCacheFilesNeeded, modelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+ const auto [cachedDataCacheFilesNeeded, cachedModelCacheFilesNeeded] =
+ kDevice->getNumberOfCacheFilesNeeded();
+
+ // verify success
+ EXPECT_EQ(kMaxNumberOfCacheFiles, dataCacheFilesNeeded);
+ EXPECT_EQ(kMaxNumberOfCacheFiles, modelCacheFilesNeeded);
+ EXPECT_EQ(cachedDataCacheFilesNeeded, dataCacheFilesNeeded);
+ EXPECT_EQ(cachedModelCacheFilesNeeded, modelCacheFilesNeeded);
+}
+
+TEST_F(VersionedIDeviceV1_0Test, getFeatureLevel) {
+ // run test
+ const auto featureLevel = kDevice->getFeatureLevel();
+ const auto cached = kDevice->getFeatureLevel();
+
+ // verify success
+ constexpr int64_t expectedFeatureLevel = __ANDROID_API_O_MR1__;
+ EXPECT_EQ(expectedFeatureLevel, featureLevel);
+ EXPECT_EQ(cached, featureLevel);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getFeatureLevel) {
+ // run test
+ const auto featureLevel = kDevice->getFeatureLevel();
+ const auto cached = kDevice->getFeatureLevel();
+
+ // verify success
+ constexpr int64_t expectedFeatureLevel = __ANDROID_API_P__;
+ EXPECT_EQ(expectedFeatureLevel, featureLevel);
+ EXPECT_EQ(cached, featureLevel);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getFeatureLevel) {
+ // run test
+ const auto featureLevel = kDevice->getFeatureLevel();
+ const auto cached = kDevice->getFeatureLevel();
+
+ // verify success
+ constexpr int64_t expectedFeatureLevel = __ANDROID_API_Q__;
+ EXPECT_EQ(expectedFeatureLevel, featureLevel);
+ EXPECT_EQ(cached, featureLevel);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getFeatureLevel) {
+ // run test
+ const auto featureLevel = kDevice->getFeatureLevel();
+ const auto cached = kDevice->getFeatureLevel();
+
+ // verify success
+ constexpr int64_t expectedFeatureLevel = __ANDROID_API_R__;
+ EXPECT_EQ(expectedFeatureLevel, featureLevel);
+ EXPECT_EQ(cached, featureLevel);
+}
+
+// Simulate successful test
+
+TEST_F(VersionedIDeviceV1_0Test, getSupportedOperations) {
+ // setup call
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::NONE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::NONE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getSupportedOperations) {
+ // setup call
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::NONE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_1(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::NONE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getSupportedOperations) {
+ // setup call
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::NONE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_2(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::NONE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getSupportedOperations) {
+ // setup call
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_3::ErrorStatus::NONE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_3(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::NONE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, prepareModel) {
+ // setup call
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModelReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, prepareModel) {
+ // setup call
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_1Return(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_1(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, prepareModel) {
+ // setup call
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_2Return(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_2(_, _, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, prepareModel) {
+ // setup call
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, allocate) {
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, status);
+ EXPECT_EQ(nullptr, buffer.get());
+ EXPECT_EQ(0u, token);
+}
+
+TEST_F(VersionedIDeviceV1_1Test, allocate) {
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, status);
+ EXPECT_EQ(nullptr, buffer.get());
+ EXPECT_EQ(0u, token);
+}
+
+TEST_F(VersionedIDeviceV1_2Test, allocate) {
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, status);
+ EXPECT_EQ(nullptr, buffer.get());
+ EXPECT_EQ(0u, token);
+}
+
+TEST_F(VersionedIDeviceV1_3Test, allocate) {
+ // setup call
+ const sp<MockBuffer> mockBuffer = new MockBuffer();
+ constexpr uint32_t mockToken = 1;
+ const auto ret = [mockBuffer](const BufferDesc& /*desc*/,
+ const hidl_vec<sp<V1_3::IPreparedModel>>& /*preparedModels*/,
+ const hidl_vec<BufferRole>& /*inputRoles*/,
+ const hidl_vec<BufferRole>& /*outputRoles*/,
+ V1_3::IDevice::allocate_cb cb) -> Return<void> {
+ cb(V1_3::ErrorStatus::NONE, mockBuffer, mockToken);
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, allocate(_, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(V1_3::ErrorStatus::NONE, status);
+ EXPECT_NE(nullptr, buffer.get());
+ EXPECT_NE(0u, token);
+}
+
+TEST_F(VersionedIDeviceMockTest, wait) {
+ // setup call
+ const auto ret = []() -> Return<void> { return {}; };
+ EXPECT_CALL(*kMockDevice, ping()).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto resultCode = kDevice->wait();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+}
+
+// Simulate general failure
+
+TEST_F(VersionedIDeviceV1_0Test, getSupportedOperationsFailure) {
+ // setup failure
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getSupportedOperationsFailure) {
+ // setup failure
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_1(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getSupportedOperationsFailure) {
+ // setup failure
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_2(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getSupportedOperationsFailure) {
+ // setup failure
+ const auto ret = [](const auto& /*model*/, const auto cb) {
+ cb(V1_3::ErrorStatus::GENERAL_FAILURE, {});
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_3(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, prepareModelLaunchFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModelReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::NONE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, prepareModelLaunchFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_1Return(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::NONE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_1(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, prepareModelLaunchFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_2Return(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::NONE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_2(_, _, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, prepareModelLaunchFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::GENERAL_FAILURE,
+ V1_3::ErrorStatus::NONE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, prepareModelReturnFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModelReturn(V1_0::ErrorStatus::NONE,
+ V1_0::ErrorStatus::GENERAL_FAILURE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, prepareModelReturnFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_1Return(
+ V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_1(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, prepareModelReturnFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_2Return(
+ V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_2(_, _, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, prepareModelReturnFailure) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_3Return(
+ V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::GENERAL_FAILURE, mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, prepareModelNullptrError) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = nullptr;
+ const auto ret = makePreparedModelReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, prepareModelNullptrError) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = nullptr;
+ const auto ret = makePreparedModel_1_1Return(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_1(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, prepareModelNullptrError) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = nullptr;
+ const auto ret = makePreparedModel_1_2Return(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_2(_, _, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, prepareModelNullptrError) {
+ // setup failure
+ const sp<MockPreparedModel> mockPreparedModel = nullptr;
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, allocateFailure) {
+ // setup failure
+ const auto ret = [](const BufferDesc& /*desc*/,
+ const hidl_vec<sp<V1_3::IPreparedModel>>& /*preparedModels*/,
+ const hidl_vec<BufferRole>& /*inputRoles*/,
+ const hidl_vec<BufferRole>& /*outputRoles*/,
+ V1_3::IDevice::allocate_cb cb) -> Return<void> {
+ cb(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr, 0);
+ return Void();
+ };
+ EXPECT_CALL(*kMockDevice, allocate(_, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, status);
+ EXPECT_EQ(nullptr, buffer.get());
+ EXPECT_EQ(0u, token);
+}
+
+// Simulate transport failure
+
+TEST_F(VersionedIDeviceV1_0Test, getSupportedOperationsTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getSupportedOperations(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, getSupportedOperationsTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_1(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, getSupportedOperationsTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_2(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, getSupportedOperationsTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, getSupportedOperations_1_3(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto metaModel = MetaModel({}, /*strictSlicing=*/true);
+ const auto [resultCode, supportedOperations] = kDevice->getSupportedOperations(metaModel);
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, resultCode);
+ EXPECT_EQ(0u, supportedOperations.size());
+}
+
+TEST_F(VersionedIDeviceV1_0Test, prepareModelTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, prepareModel(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_1Test, prepareModelTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, prepareModel_1_1(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_2Test, prepareModelTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, prepareModel_1_2(_, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, prepareModelTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceV1_3Test, allocateTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, allocate(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [status, buffer, token] = kDevice->allocate({}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(V1_3::ErrorStatus::GENERAL_FAILURE, status);
+ EXPECT_EQ(nullptr, buffer.get());
+ EXPECT_EQ(0u, token);
+}
+
+TEST_F(VersionedIDeviceMockTest, waitTransportFailure) {
+ // setup call
+ EXPECT_CALL(*kMockDevice, ping())
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto resultCode = kDevice->wait();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+}
+
+// Simulate service crash
+
+// TODO: enable this test once b/154183300 is fixed.
+TEST_F(VersionedIDeviceMockTest, DISABLED_prepareModelRecoverCrash) {
+ // setup original device calls
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+ EXPECT_CALL(*kMockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // setup recovery call
+ const sp<MockDevice> mockRecoveredDevice = MockDevice::create();
+ EXPECT_CALL(*kMockMakeDevice, Call(/*blocking=*/false))
+ .Times(1)
+ .WillOnce(testing::Return(mockRecoveredDevice));
+
+ // setup recovered device calls
+ const sp<MockPreparedModel> mockPreparedModel = MockPreparedModel::create();
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ mockPreparedModel);
+ EXPECT_CALL(*mockRecoveredDevice, linkToDeathRet()).Times(1);
+ EXPECT_CALL(*mockRecoveredDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceMockTest, prepareModelFullCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillRepeatedly(InvokeWithoutArgs(makeDeadObjectFailure));
+ EXPECT_CALL(*kMockDevice, ping())
+ .Times(1)
+ .WillRepeatedly(InvokeWithoutArgs(makeDeadObjectFailure));
+ EXPECT_CALL(*kMockMakeDevice, Call(/*blocking=*/false))
+ .Times(1)
+ .WillOnce(testing::Return(nullptr));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceMockTest, prepareModelAsyncCrash) {
+ // setup failure
+ const auto ret = [this]() -> Return<V1_3::ErrorStatus> {
+ kMockDevice->simulateCrash();
+ return V1_3::ErrorStatus::NONE;
+ };
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIDeviceMockTest, waitCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockDevice, ping())
+ .Times(1)
+ .WillRepeatedly(InvokeWithoutArgs(makeDeadObjectFailure));
+ EXPECT_CALL(*kMockMakeDevice, Call(/*blocking=*/true))
+ .Times(1)
+ .WillOnce(testing::Return(nullptr));
+
+ // run test
+ const auto resultCode = kDevice->wait();
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+}
+
+TEST_F(VersionedIDeviceMockTest, waitRecoverCrash) {
+ // setup original device calls
+ EXPECT_CALL(*kMockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // setup recovery call
+ const sp<MockDevice> mockRecoveredDevice = MockDevice::create();
+ EXPECT_CALL(*kMockMakeDevice, Call(/*blocking=*/true))
+ .Times(1)
+ .WillOnce(testing::Return(mockRecoveredDevice));
+
+ // setup recovered device calls
+ const auto ret = []() -> Return<bool> { return true; };
+ EXPECT_CALL(*mockRecoveredDevice, linkToDeathRet()).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto resultCode = kDevice->wait();
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+}
+
+TEST_F(VersionedIDeviceMockTest, waitFailedRecoverCrash) {
+ // setup original device calls
+ EXPECT_CALL(*kMockDevice, ping()).Times(1).WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // setup recovery call
+ const sp<MockDevice> mockRecoveredDevice = MockDevice::create();
+ EXPECT_CALL(*kMockMakeDevice, Call(/*blocking=*/true))
+ .Times(1)
+ .WillOnce(testing::Return(mockRecoveredDevice));
+
+ // setup recovered device calls
+ EXPECT_CALL(*mockRecoveredDevice, linkToDeathRet())
+ .Times(1)
+ .WillOnce(makeGeneralTransportFailure);
+
+ // run test
+ const auto resultCode = kDevice->wait();
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+}
+
+// Harness for VersionedIPreparedModel failures.
+
+class VersionedIPreparedModelInitializationTest : public VersionedIDeviceMockTest {
+ protected:
+ const sp<MockPreparedModel> kMockPreparedModel = MockPreparedModel::create();
+};
+
+std::shared_ptr<VersionedIPreparedModel> makeVersionedIPreparedModelSuccessfulInitializationFrom(
+ const sp<MockDevice>& mockDevice, const sp<MockPreparedModel>& mockPreparedModel,
+ const VersionedIDevice& device) {
+ const auto retV1_0 = makePreparedModelReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE,
+ mockPreparedModel);
+ const auto retV1_1 = makePreparedModel_1_1Return(V1_0::ErrorStatus::NONE,
+ V1_0::ErrorStatus::NONE, mockPreparedModel);
+ const auto retV1_2 = makePreparedModel_1_2Return(V1_0::ErrorStatus::NONE,
+ V1_0::ErrorStatus::NONE, mockPreparedModel);
+ const auto retV1_3 = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE,
+ V1_3::ErrorStatus::NONE, mockPreparedModel);
+
+ ON_CALL(*mockDevice, prepareModel(_, _)).WillByDefault(Invoke(retV1_0));
+ ON_CALL(*mockDevice, prepareModel_1_1(_, _, _)).WillByDefault(Invoke(retV1_1));
+ ON_CALL(*mockDevice, prepareModel_1_2(_, _, _, _, _, _)).WillByDefault(Invoke(retV1_2));
+ ON_CALL(*mockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _)).WillByDefault(Invoke(retV1_3));
+
+ EXPECT_CALL(*mockDevice, prepareModel(_, _)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, prepareModel_1_1(_, _, _)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, prepareModel_1_2(_, _, _, _, _, _)).Times(testing::AnyNumber());
+ EXPECT_CALL(*mockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _)).Times(testing::AnyNumber());
+
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = device.prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ CHECK_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ CHECK(preparedModel != nullptr);
+
+ return preparedModel;
+}
+
+template <Version version>
+class VersionedIPreparedModelTest : public VersionedIDeviceInitializedTest<version> {
+ using Base = VersionedIDeviceInitializedTest<version>;
+
+ protected:
+ void SetUp() override {
+ VersionedIDeviceInitializedTest<version>::SetUp();
+ ASSERT_NE(nullptr, kPreparedModel.get());
+ }
+
+ const sp<MockPreparedModel> kMockPreparedModel = MockPreparedModel::create();
+ const std::shared_ptr<VersionedIPreparedModel> kPreparedModel =
+ makeVersionedIPreparedModelSuccessfulInitializationFrom(
+ Base::kMockDevice, kMockPreparedModel, *Base::kDevice);
+};
+
+class VersionedIPreparedModelV1_0Test : public VersionedIPreparedModelTest<Version::V1_0> {};
+class VersionedIPreparedModelV1_1Test : public VersionedIPreparedModelTest<Version::V1_1> {};
+class VersionedIPreparedModelV1_2Test : public VersionedIPreparedModelTest<Version::V1_2> {};
+class VersionedIPreparedModelV1_3Test : public VersionedIPreparedModelTest<Version::V1_3> {};
+class VersionedIPreparedModelMockTest : public VersionedIPreparedModelTest<Version::MOCK> {};
+
+// Simulate initialization/link error
+
+TEST_F(VersionedIPreparedModelInitializationTest, linkToDeathTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, linkToDeathRet())
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ kMockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIPreparedModelInitializationTest, linkToDeathDeadObject) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, linkToDeathRet())
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ kMockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+TEST_F(VersionedIPreparedModelInitializationTest, linkToDeathReturnError) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, linkToDeathRet())
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs([]() -> Return<bool> { return false; }));
+ const auto ret = makePreparedModel_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE,
+ kMockPreparedModel);
+ EXPECT_CALL(*kMockDevice, prepareModel_1_3(_, _, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const ModelFactory makeModel = [] { return V1_3::Model{}; };
+ const auto [resultCode, preparedModel] = kDevice->prepareModel(makeModel, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, preparedModel.get());
+}
+
+// Simulate successful test
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeAsync) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeAsync) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeAsync) {
+ // setup call
+ const auto ret =
+ makeExecute_1_2Return(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeAsync) {
+ // setup call
+ const auto ret =
+ makeExecute_1_3Return(V1_3::ErrorStatus::NONE, V1_3::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executePreferSync) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executePreferSync) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executePreferSync) {
+ // setup call
+ const auto ret = makeExecuteSynchronouslyReturn(V1_0::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executePreferSync) {
+ // setup call
+ const auto ret = makeExecuteSynchronously_1_3Return(V1_3::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeFenced) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeFenced) {
+ // setup call
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeFenced) {
+ // setup call
+ const auto ret = makeExecuteSynchronouslyReturn(V1_0::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeFenced) {
+ // setup call
+ auto memory = allocateSharedMemory(4);
+ hidl_handle fakeSyncFence(memory.handle());
+ const sp<IFencedExecutionCallback> callback = new MockFencedExecutionCallback();
+ const auto ret = makeExecuteFencedReturn(V1_3::ErrorStatus::NONE, fakeSyncFence, callback);
+ EXPECT_CALL(*kMockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify success
+ EXPECT_EQ(ANEURALNETWORKS_NO_ERROR, resultCode);
+ EXPECT_NE(nullptr, syncFence.getNativeHandle());
+ EXPECT_NE(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, configureExecutionBurst) {
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify success
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, configureExecutionBurst) {
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify success
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, configureExecutionBurst) {
+ // setup call
+ const sp<MockBurstContext> burstContext = new MockBurstContext();
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::NONE, burstContext);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify success
+ EXPECT_NE(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, configureExecutionBurst) {
+ // setup call
+ const sp<MockBurstContext> burstContext = new MockBurstContext();
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::NONE, burstContext);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify success
+ EXPECT_NE(nullptr, executionBurstController);
+}
+
+// Simulate general failure
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeAsyncLaunchFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeAsyncLaunchFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE, V1_0::ErrorStatus::NONE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeAsyncLaunchFailure) {
+ // setup failure
+ const auto ret = makeExecute_1_2Return(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeAsyncLaunchFailure) {
+ // setup failure
+ const auto ret = makeExecute_1_3Return(V1_3::ErrorStatus::GENERAL_FAILURE,
+ V1_3::ErrorStatus::NONE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeAsyncReturnFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeAsyncReturnFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::NONE, V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeAsyncReturnFailure) {
+ // setup failure
+ const auto ret = makeExecute_1_2Return(V1_0::ErrorStatus::NONE,
+ V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_2(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeAsyncReturnFailure) {
+ // setup failure
+ const auto ret = makeExecute_1_3Return(V1_3::ErrorStatus::NONE,
+ V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executePreferSyncFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executePreferSyncFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executePreferSyncFailure) {
+ // setup failure
+ const auto ret =
+ makeExecuteSynchronouslyReturn(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executePreferSyncFailure) {
+ // setup failure
+ const auto ret =
+ makeExecuteSynchronously_1_3Return(V1_3::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeFencedFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeFencedFailure) {
+ // setup failure
+ const auto ret = makeExecuteReturn(V1_0::ErrorStatus::GENERAL_FAILURE,
+ V1_0::ErrorStatus::GENERAL_FAILURE);
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeFencedFailure) {
+ // setup failure
+ const auto ret =
+ makeExecuteSynchronouslyReturn(V1_0::ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _)).Times(1).WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeFencedFailure) {
+ // setup failure
+ auto memory = allocateSharedMemory(4);
+ hidl_handle fakeSyncFence(memory.handle());
+ const sp<IFencedExecutionCallback> callback = new MockFencedExecutionCallback();
+ const auto ret =
+ makeExecuteFencedReturn(V1_3::ErrorStatus::GENERAL_FAILURE, fakeSyncFence, callback);
+ EXPECT_CALL(*kMockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, configureExecutionBurstFailure) {
+ // setup failure
+ const sp<MockBurstContext> burstContext = new MockBurstContext();
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::GENERAL_FAILURE, burstContext);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, configureExecutionBurstFailure) {
+ // setup failure
+ const sp<MockBurstContext> burstContext = new MockBurstContext();
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::GENERAL_FAILURE, burstContext);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, configureExecutionBurstNullptrError) {
+ // setup failure
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::NONE, nullptr);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, configureExecutionBurstNullptrError) {
+ // setup failure
+ const auto ret = makeConfigureExecutionBurst(V1_0::ErrorStatus::NONE, nullptr);
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(Invoke(ret));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+// Simulate transport failure
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeAsyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeAsyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeAsyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute_1_2(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeAsyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executePreferSyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executePreferSyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executePreferSyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executePreferSyncTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeFencedTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeFencedTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeFencedTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeFencedTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeFenced(_, _, _, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto [resultCode, syncFence, dispatchCallback, timing] =
+ kPreparedModel->executeFenced({}, {}, {}, {}, {}, {});
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_OP_FAILED, resultCode);
+ EXPECT_EQ(nullptr, syncFence.getNativeHandle());
+ EXPECT_EQ(nullptr, dispatchCallback.get());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, configureExecutionBurstTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, configureExecutionBurstTransportFailure) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, configureExecutionBurst(_, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
+
+ // run test
+ const auto executionBurstController =
+ kPreparedModel->configureExecutionBurst(/*preferPowerOverLatency=*/false);
+
+ // verify failure
+ EXPECT_EQ(nullptr, executionBurstController);
+}
+
+// Simulate service crash
+
+TEST_F(VersionedIPreparedModelV1_0Test, executeAsyncLaunchCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_1Test, executeAsyncLaunchCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute(_, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executeAsyncLaunchCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute_1_2(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executeAsyncLaunchCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_2Test, executePreferSyncCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously(_, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelV1_3Test, executePreferSyncCrash) {
+ // setup failure
+ EXPECT_CALL(*kMockPreparedModel, executeSynchronously_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/true);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+TEST_F(VersionedIPreparedModelMockTest, executeAsyncReturnCrash) {
+ // setup failure
+ const auto ret = [this]() -> Return<V1_3::ErrorStatus> {
+ kMockPreparedModel->simulateCrash();
+ return V1_3::ErrorStatus::NONE;
+ };
+ EXPECT_CALL(*kMockPreparedModel, execute_1_3(_, _, _, _, _))
+ .Times(1)
+ .WillOnce(InvokeWithoutArgs(ret));
+
+ // run test
+ const auto [resultCode, outputShapes, timing] =
+ kPreparedModel->execute({}, {}, {}, {}, /*preferSynchronous=*/false);
+
+ // verify failure
+ EXPECT_EQ(ANEURALNETWORKS_DEAD_OBJECT, resultCode);
+ EXPECT_EQ(0u, outputShapes.size());
+ EXPECT_EQ(kNoTiming, timing);
+}
+
+} // namespace
+} // namespace android::nn