GTest test-cases for HIDL safe unions
This change implements test-cases to exercise correctness of the HIDL
safe_union construct.
Bug: 79878527
Test: Ran the hidl_test suite (including new tests) on a real device.
Change-Id: I8131ee5453ee65952b08a95c0cb8bc698ce888d5
diff --git a/test/hidl_test/Android.bp b/test/hidl_test/Android.bp
index 60982d4..ea0ba1f 100644
--- a/test/hidl_test/Android.bp
+++ b/test/hidl_test/Android.bp
@@ -35,6 +35,7 @@
"android.hardware.tests.memory@1.0",
"android.hardware.tests.multithread@1.0",
"android.hardware.tests.trie@1.0",
+ "android.hardware.tests.safeunion@1.0",
],
// impls should never be static, these are used only for testing purposes
@@ -50,6 +51,7 @@
"android.hardware.tests.memory@1.0-impl",
"android.hardware.tests.multithread@1.0-impl",
"android.hardware.tests.trie@1.0-impl",
+ "android.hardware.tests.safeunion@1.0-impl",
],
group_static_libs: true,
diff --git a/test/hidl_test/hidl_test.h b/test/hidl_test/hidl_test.h
index 0ad17ef..c90521e 100644
--- a/test/hidl_test/hidl_test.h
+++ b/test/hidl_test/hidl_test.h
@@ -10,6 +10,7 @@
#include <android/hardware/tests/multithread/1.0/IMultithread.h>
#include <android/hardware/tests/pointer/1.0/IGraph.h>
#include <android/hardware/tests/pointer/1.0/IPointer.h>
+#include <android/hardware/tests/safeunion/1.0/ISafeUnion.h>
#include <android/hardware/tests/trie/1.0/ITrie.h>
template <template <typename Type> class Service>
@@ -23,6 +24,7 @@
using ::android::hardware::tests::multithread::V1_0::IMultithread;
using ::android::hardware::tests::pointer::V1_0::IGraph;
using ::android::hardware::tests::pointer::V1_0::IPointer;
+ using ::android::hardware::tests::safeunion::V1_0::ISafeUnion;
using ::android::hardware::tests::trie::V1_0::ITrie;
Service<IMemoryTest>::run("memory");
@@ -35,6 +37,7 @@
Service<IPointer>::run("pointer");
Service<IMultithread>::run("multithread");
Service<ITrie>::run("trie");
+ Service<ISafeUnion>::run("safeunion");
}
#endif // HIDL_TEST_H_
diff --git a/test/hidl_test/hidl_test_client.cpp b/test/hidl_test/hidl_test_client.cpp
index 620f197..57e25fa 100644
--- a/test/hidl_test/hidl_test_client.cpp
+++ b/test/hidl_test/hidl_test_client.cpp
@@ -32,6 +32,7 @@
#include <android/hardware/tests/multithread/1.0/IMultithread.h>
#include <android/hardware/tests/pointer/1.0/IGraph.h>
#include <android/hardware/tests/pointer/1.0/IPointer.h>
+#include <android/hardware/tests/safeunion/1.0/ISafeUnion.h>
#include <android/hardware/tests/trie/1.0/ITrie.h>
#include <gtest/gtest.h>
@@ -51,6 +52,7 @@
#include <condition_variable>
#include <fstream>
#include <future>
+#include <limits>
#include <mutex>
#include <random>
#include <set>
@@ -91,52 +93,57 @@
static HidlEnvironment *gHidlEnvironment = nullptr;
+using ::android::Condition;
+using ::android::DELAY_NS;
+using ::android::DELAY_S;
using ::android::FQName;
+using ::android::MultiDimensionalToString;
+using ::android::Mutex;
+using ::android::ONEWAY_TOLERANCE_NS;
+using ::android::sp;
+using ::android::to_string;
+using ::android::TOLERANCE_NS;
+using ::android::wp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::HidlMemory;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tests::bar::V1_0::IBar;
+using ::android::hardware::tests::bar::V1_0::IComplicated;
+using ::android::hardware::tests::baz::V1_0::IBaz;
using ::android::hardware::tests::foo::V1_0::Abc;
using ::android::hardware::tests::foo::V1_0::IFoo;
using ::android::hardware::tests::foo::V1_0::IFooCallback;
using ::android::hardware::tests::foo::V1_0::ISimple;
using ::android::hardware::tests::foo::V1_0::implementation::FooCallback;
-using ::android::hardware::tests::bar::V1_0::IBar;
-using ::android::hardware::tests::bar::V1_0::IComplicated;
-using ::android::hardware::tests::baz::V1_0::IBaz;
using ::android::hardware::tests::hash::V1_0::IHash;
+using ::android::hardware::tests::inheritance::V1_0::IChild;
using ::android::hardware::tests::inheritance::V1_0::IFetcher;
using ::android::hardware::tests::inheritance::V1_0::IGrandparent;
using ::android::hardware::tests::inheritance::V1_0::IParent;
-using ::android::hardware::tests::inheritance::V1_0::IChild;
-using ::android::hardware::tests::pointer::V1_0::IGraph;
-using ::android::hardware::tests::pointer::V1_0::IPointer;
using ::android::hardware::tests::memory::V1_0::IMemoryTest;
using ::android::hardware::tests::multithread::V1_0::IMultithread;
+using ::android::hardware::tests::pointer::V1_0::IGraph;
+using ::android::hardware::tests::pointer::V1_0::IPointer;
+using ::android::hardware::tests::safeunion::V1_0::ISafeUnion;
+using ::android::hardware::tests::safeunion::V1_0::J;
+using ::android::hardware::tests::safeunion::V1_0::LargeSafeUnion;
+using ::android::hardware::tests::safeunion::V1_0::MiscTypesSafeUnion;
+using ::android::hardware::tests::safeunion::V1_0::SmallSafeUnion;
using ::android::hardware::tests::trie::V1_0::ITrie;
using ::android::hardware::tests::trie::V1_0::TrieNode;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_death_recipient;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::HidlMemory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::hidl::manager::V1_2::IServiceManager;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::hidl::memory::token::V1_0::IMemoryToken;
using ::android::hidl::memory::block::V1_0::MemoryBlock;
+using ::android::hidl::memory::token::V1_0::IMemoryToken;
+using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::token::V1_0::ITokenManager;
-using ::android::sp;
-using ::android::wp;
-using ::android::to_string;
-using ::android::Mutex;
-using ::android::MultiDimensionalToString;
-using ::android::Condition;
-using ::android::DELAY_S;
-using ::android::DELAY_NS;
-using ::android::TOLERANCE_NS;
-using ::android::ONEWAY_TOLERANCE_NS;
using std::to_string;
template <typename T>
@@ -317,6 +324,7 @@
sp<IPointer> validationPointerInterface;
sp<IMultithread> multithreadInterface;
sp<ITrie> trieInterface;
+ sp<ISafeUnion> safeunionInterface;
TestMode mode;
bool enableDelayMeasurementTests;
HidlEnvironment(TestMode mode, bool enableDelayMeasurementTests) :
@@ -355,8 +363,8 @@
ASSERT_EQ(foo->isRemote(), mode == BINDERIZED);
dyingBaz = IBaz::getService("dyingBaz", mode == PASSTHROUGH /* getStub */);
- ASSERT_NE(foo, nullptr);
- ASSERT_EQ(foo->isRemote(), mode == BINDERIZED);
+ ASSERT_NE(dyingBaz, nullptr);
+ ASSERT_EQ(dyingBaz->isRemote(), mode == BINDERIZED);
bar = IBar::getService("foo", mode == PASSTHROUGH /* getStub */);
ASSERT_NE(bar, nullptr);
@@ -382,6 +390,10 @@
trieInterface = ITrie::getService("trie", mode == PASSTHROUGH /* getStub */);
ASSERT_NE(trieInterface, nullptr);
ASSERT_EQ(trieInterface->isRemote(), mode == BINDERIZED);
+
+ safeunionInterface = ISafeUnion::getService("safeunion", mode == PASSTHROUGH /* getStub */);
+ ASSERT_NE(safeunionInterface, nullptr);
+ ASSERT_EQ(safeunionInterface->isRemote(), mode == BINDERIZED);
}
virtual void SetUp() {
@@ -405,6 +417,7 @@
sp<IPointer> pointerInterface;
sp<IPointer> validationPointerInterface;
sp<ITrie> trieInterface;
+ sp<ISafeUnion> safeunionInterface;
TestMode mode = TestMode::PASSTHROUGH;
virtual void SetUp() override {
@@ -421,6 +434,7 @@
pointerInterface = gHidlEnvironment->pointerInterface;
validationPointerInterface = gHidlEnvironment->validationPointerInterface;
trieInterface = gHidlEnvironment->trieInterface;
+ safeunionInterface = gHidlEnvironment->safeunionInterface;
mode = gHidlEnvironment->mode;
ALOGI("Test setup complete");
}
@@ -1814,6 +1828,144 @@
});
}
+TEST_F(HidlTest, SafeUnionNoInitTest) {
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::hidl_no_init, safeUnion.getDiscriminator());
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionSimpleTest) {
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_OK(safeunionInterface->setA(safeUnion, -5, [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::a, safeUnion.getDiscriminator());
+ EXPECT_EQ(-5, safeUnion.a());
+
+ uint64_t max = std::numeric_limits<uint64_t>::max();
+ EXPECT_OK(
+ safeunionInterface->setD(safeUnion, max, [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::d, safeUnion.getDiscriminator());
+ EXPECT_EQ(max, safeUnion.d());
+ }));
+ }));
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionArrayLikeTypesTest) {
+ const std::array<int64_t, 5> testArray{1, -2, 3, -4, 5};
+ const hidl_vec<uint64_t> testVector{std::numeric_limits<uint64_t>::max()};
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_OK(
+ safeunionInterface->setF(safeUnion, testArray, [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::f, safeUnion.getDiscriminator());
+
+ for (size_t i = 0; i < testArray.size(); i++) {
+ EXPECT_EQ(testArray[i], safeUnion.f()[i]);
+ }
+ }));
+
+ EXPECT_OK(
+ safeunionInterface->setI(safeUnion, testVector, [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::i, safeUnion.getDiscriminator());
+ EXPECT_EQ(testVector, safeUnion.i());
+ }));
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionStringTypeTest) {
+ const std::string testString =
+ "This is an inordinately long test string to exercise hidl_string types in safe unions.";
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_OK(safeunionInterface->setG(
+ safeUnion, hidl_string(testString), [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::g, safeUnion.getDiscriminator());
+ EXPECT_EQ(testString, std::string(safeUnion.g()));
+ }));
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionCopyTest) {
+ const hidl_vec<bool> testVector{true, false, true, false, false, false, true, false,
+ true, true, true, false, false, true, false, true};
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_OK(
+ safeunionInterface->setH(safeUnion, testVector, [&](const LargeSafeUnion& safeUnion) {
+ LargeSafeUnion safeUnionCopy(safeUnion);
+
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::h, safeUnionCopy.getDiscriminator());
+ EXPECT_EQ(testVector, safeUnionCopy.h());
+ }));
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionMutateTest) {
+ const std::array<int64_t, 5> testArray{-1, -2, -3, -4, -5};
+ const std::string testString = "Test string";
+ LargeSafeUnion safeUnion;
+
+ safeUnion.f(testArray);
+ safeUnion.f()[0] += 10;
+ EXPECT_EQ(testArray[0] + 10, safeUnion.f()[0]);
+
+ safeUnion.j(J());
+ safeUnion.j().j3 = testString;
+ EXPECT_EQ(testString, std::string(safeUnion.j().j3));
+}
+
+TEST_F(HidlTest, SafeUnionNestedTest) {
+ SmallSafeUnion smallSafeUnion;
+ smallSafeUnion.a(1);
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& safeUnion) {
+ EXPECT_OK(safeunionInterface->setL(
+ safeUnion, smallSafeUnion, [&](const LargeSafeUnion& safeUnion) {
+ EXPECT_EQ(LargeSafeUnion::hidl_discriminator::l, safeUnion.getDiscriminator());
+
+ EXPECT_EQ(SmallSafeUnion::hidl_discriminator::a, safeUnion.l().getDiscriminator());
+ EXPECT_EQ(1, safeUnion.l().a());
+ }));
+ }));
+}
+
+TEST_F(HidlTest, SafeUnionEqualityTest) {
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& one) {
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+ EXPECT_FALSE(one == two);
+ EXPECT_TRUE(one != two);
+ }));
+
+ EXPECT_OK(safeunionInterface->setA(one, 1, [&](const LargeSafeUnion& one) {
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+ EXPECT_FALSE(one == two);
+ EXPECT_TRUE(one != two);
+ }));
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+ EXPECT_OK(safeunionInterface->setB(two, 1, [&](const LargeSafeUnion& two) {
+ EXPECT_FALSE(one == two);
+ EXPECT_TRUE(one != two);
+ }));
+ }));
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+ EXPECT_OK(safeunionInterface->setA(two, 2, [&](const LargeSafeUnion& two) {
+ EXPECT_FALSE(one == two);
+ EXPECT_TRUE(one != two);
+ }));
+ }));
+
+ EXPECT_OK(safeunionInterface->newLargeSafeUnion([&](const LargeSafeUnion& two) {
+ EXPECT_OK(safeunionInterface->setA(two, 1, [&](const LargeSafeUnion& two) {
+ EXPECT_TRUE(one == two);
+ EXPECT_FALSE(one != two);
+ }));
+ }));
+ }));
+ }));
+}
+
class HidlMultithreadTest : public ::testing::Test {
public:
sp<IMultithread> multithreadInterface;