| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "hidl_test_java_native" |
| |
| #include <android-base/logging.h> |
| |
| #include <android/hardware/tests/baz/1.0/IBaz.h> |
| |
| #include <gtest/gtest.h> |
| |
| #include <hidl/HidlTransportSupport.h> |
| #include <hidl/Status.h> |
| using ::android::sp; |
| using ::android::hardware::tests::baz::V1_0::IBase; |
| using ::android::hardware::tests::baz::V1_0::IBaz; |
| using ::android::hardware::tests::baz::V1_0::IBazCallback; |
| |
| using ::android::hardware::hidl_array; |
| using ::android::hardware::hidl_vec; |
| using ::android::hardware::hidl_string; |
| using ::android::hardware::configureRpcThreadpool; |
| using ::android::hardware::joinRpcThreadpool; |
| using ::android::hardware::Return; |
| using ::android::hardware::Void; |
| |
| struct BazCallback : public IBazCallback { |
| Return<void> heyItsMe(const sp<IBazCallback> &cb) override; |
| Return<void> hey() override; |
| }; |
| |
| Return<void> BazCallback::heyItsMe( |
| const sp<IBazCallback> &cb) { |
| LOG(INFO) << "SERVER: heyItsMe cb = " << cb.get(); |
| |
| return Void(); |
| } |
| |
| Return<void> BazCallback::hey() { |
| LOG(INFO) << "SERVER: hey"; |
| |
| return Void(); |
| } |
| |
| struct Baz : public IBaz { |
| Return<void> someBaseMethod() override; |
| |
| Return<void> someOtherBaseMethod( |
| const IBaz::Foo &foo, someOtherBaseMethod_cb _hidl_cb) override; |
| |
| Return<void> someMethodWithFooArrays( |
| const hidl_array<IBaz::Foo, 2> &fooInput, |
| someMethodWithFooArrays_cb _hidl_cb) override; |
| |
| Return<void> someMethodWithFooVectors( |
| const hidl_vec<IBaz::Foo> &fooInput, |
| someMethodWithFooVectors_cb _hidl_cb) override; |
| |
| Return<void> someMethodWithVectorOfArray( |
| const IBase::VectorOfArray &in, |
| someMethodWithVectorOfArray_cb _hidl_cb) override; |
| |
| Return<void> someMethodTakingAVectorOfArray( |
| const hidl_vec<hidl_array<uint8_t, 6> > &in, |
| someMethodTakingAVectorOfArray_cb _hidl_cb) override; |
| |
| Return<void> transpose( |
| const IBase::StringMatrix5x3 &in, |
| transpose_cb _hidl_cb) override; |
| |
| Return<void> transpose2( |
| const hidl_array<hidl_string, 5, 3> &in, |
| transpose2_cb _hidl_cb) override; |
| |
| Return<bool> someBoolMethod(bool x) override; |
| |
| Return<void> someBoolArrayMethod( |
| const hidl_array<bool, 3> &x, |
| someBoolArrayMethod_cb _hidl_cb) override; |
| |
| Return<void> someBoolVectorMethod( |
| const hidl_vec<bool> &x, someBoolVectorMethod_cb _hidl_cb) override; |
| |
| Return<void> doSomethingElse( |
| const hidl_array<int32_t, 15> ¶m, |
| doSomethingElse_cb _hidl_cb) override; |
| |
| Return<void> doThis(float param) override; |
| |
| Return<int32_t> doThatAndReturnSomething(int64_t param) override; |
| |
| Return<double> doQuiteABit( |
| int32_t a, |
| int64_t b, |
| float c, |
| double d) override; |
| |
| Return<void> doStuffAndReturnAString( |
| doStuffAndReturnAString_cb _hidl_cb) override; |
| |
| Return<void> mapThisVector( |
| const hidl_vec<int32_t>& param, mapThisVector_cb _hidl_cb) override; |
| |
| Return<void> callMe(const sp<IBazCallback>& cb) override; |
| |
| Return<void> callMeLater(const sp<IBazCallback>& cb) override; |
| Return<void> iAmFreeNow() override; |
| Return<void> dieNow() override; |
| |
| Return<IBaz::SomeEnum> useAnEnum(IBaz::SomeEnum zzz) override; |
| |
| Return<void> haveSomeStrings( |
| const hidl_array<hidl_string, 3> &array, |
| haveSomeStrings_cb _hidl_cb) override; |
| |
| Return<void> haveAStringVec( |
| const hidl_vec<hidl_string>& vector, |
| haveAStringVec_cb _hidl_cb) override; |
| |
| Return<void> returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) override; |
| |
| Return<void> takeAMask(IBase::BitField bf, uint8_t first, |
| const IBase::MyMask& second, uint8_t third, takeAMask_cb _hidl_cb) override; |
| |
| Return<uint8_t> returnABitField() override; |
| |
| Return<uint32_t> size(uint32_t size) override; |
| |
| Return<void> getNestedStructs(getNestedStructs_cb _hidl_cb) override; |
| |
| private: |
| sp<IBazCallback> mStoredCallback; |
| }; |
| |
| Return<void> Baz::someBaseMethod() { |
| LOG(INFO) << "Baz::someBaseMethod"; |
| |
| return Void(); |
| } |
| |
| using std::to_string; |
| |
| static std::string to_string(const IBaz::Foo::Bar &bar); |
| static std::string to_string(const IBaz::Foo &foo); |
| static std::string to_string(const hidl_string &s); |
| static std::string to_string(bool x); |
| static std::string to_string(const IBase::StringMatrix5x3 &M); |
| static std::string to_string(const IBase::StringMatrix3x5 &M); |
| |
| template<typename T, size_t SIZE> |
| static std::string to_string(const hidl_array<T, SIZE> &array); |
| |
| template<size_t SIZE> |
| static std::string to_string(const hidl_array<uint8_t, SIZE> &array); |
| |
| template<typename T> |
| static std::string to_string(const hidl_vec<T> &vec) { |
| std::string out; |
| out = "["; |
| for (size_t i = 0; i < vec.size(); ++i) { |
| if (i > 0) { |
| out += ", "; |
| } |
| out += to_string(vec[i]); |
| } |
| out += "]"; |
| |
| return out; |
| } |
| |
| template<typename T, size_t SIZE> |
| static std::string to_string(const hidl_array<T, SIZE> &array) { |
| std::string out; |
| out = "["; |
| for (size_t i = 0; i < SIZE; ++i) { |
| if (i > 0) { |
| out += ", "; |
| } |
| out += to_string(array[i]); |
| } |
| out += "]"; |
| |
| return out; |
| } |
| |
| template<size_t SIZE> |
| static std::string to_string(const hidl_array<uint8_t, SIZE> &array) { |
| std::string out; |
| for (size_t i = 0; i < SIZE; ++i) { |
| if (i > 0) { |
| out += ":"; |
| } |
| |
| char tmp[3]; |
| sprintf(tmp, "%02x", array[i]); |
| |
| out += tmp; |
| } |
| |
| return out; |
| } |
| |
| template<typename T, size_t SIZE1, size_t SIZE2> |
| static std::string to_string(const hidl_array<T, SIZE1, SIZE2> &array) { |
| std::string out; |
| out = "["; |
| for (size_t i = 0; i < SIZE1; ++i) { |
| if (i > 0) { |
| out += ", "; |
| } |
| |
| out += "["; |
| for (size_t j = 0; j < SIZE2; ++j) { |
| if (j > 0) { |
| out += ", "; |
| } |
| |
| out += to_string(array[i][j]); |
| } |
| out += "]"; |
| } |
| out += "]"; |
| |
| return out; |
| } |
| |
| static std::string to_string(bool x) { |
| return x ? "true" : "false"; |
| } |
| |
| static std::string to_string(const hidl_string &s) { |
| return std::string("'") + s.c_str() + "'"; |
| } |
| |
| static std::string to_string(const IBaz::Foo::Bar &bar) { |
| std::string out; |
| out = "Bar("; |
| out += "z = " + to_string(bar.z) + ", "; |
| out += "s = '" + std::string(bar.s.c_str()) + "'"; |
| out += ")"; |
| |
| return out; |
| } |
| |
| static std::string to_string(const IBaz::Foo &foo) { |
| std::string out; |
| out = "Foo("; |
| out += "x = " + to_string(foo.x) + ", "; |
| out += "y = " + to_string(foo.y) + ", "; |
| out += "aaa = " + to_string(foo.aaa); |
| out += ")"; |
| |
| return out; |
| } |
| |
| static std::string to_string(const IBase::StringMatrix5x3 &M) { |
| return to_string(M.s); |
| } |
| |
| static std::string to_string(const IBase::StringMatrix3x5 &M) { |
| return to_string(M.s); |
| } |
| |
| Return<void> Baz::someOtherBaseMethod( |
| const IBaz::Foo &foo, someOtherBaseMethod_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someOtherBaseMethod " |
| << to_string(foo); |
| |
| _hidl_cb(foo); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::someMethodWithFooArrays( |
| const hidl_array<IBaz::Foo, 2> &fooInput, |
| someMethodWithFooArrays_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someMethodWithFooArrays " |
| << to_string(fooInput); |
| |
| hidl_array<IBaz::Foo, 2> fooOutput; |
| fooOutput[0] = fooInput[1]; |
| fooOutput[1] = fooInput[0]; |
| |
| _hidl_cb(fooOutput); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::someMethodWithFooVectors( |
| const hidl_vec<IBaz::Foo> &fooInput, |
| someMethodWithFooVectors_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someMethodWithFooVectors " |
| << to_string(fooInput); |
| |
| hidl_vec<IBaz::Foo> fooOutput; |
| fooOutput.resize(2); |
| fooOutput[0] = fooInput[1]; |
| fooOutput[1] = fooInput[0]; |
| |
| _hidl_cb(fooOutput); |
| |
| return Void(); |
| } |
| |
| static std::string VectorOfArray_to_string(const IBase::VectorOfArray &in) { |
| std::string out; |
| out += "VectorOfArray("; |
| |
| for (size_t i = 0; i < in.addresses.size(); ++i) { |
| if (i > 0) { |
| out += ", "; |
| } |
| |
| for (size_t j = 0; j < 6; ++j) { |
| if (j > 0) { |
| out += ":"; |
| } |
| |
| char tmp[3]; |
| sprintf(tmp, "%02x", in.addresses[i][j]); |
| |
| out += tmp; |
| } |
| } |
| |
| out += ")"; |
| |
| return out; |
| } |
| |
| Return<void> Baz::someMethodWithVectorOfArray( |
| const IBase::VectorOfArray &in, |
| someMethodWithVectorOfArray_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someMethodWithVectorOfArray " |
| << VectorOfArray_to_string(in); |
| |
| IBase::VectorOfArray out; |
| |
| const size_t n = in.addresses.size(); |
| out.addresses.resize(n); |
| |
| for (size_t i = 0; i < n; ++i) { |
| out.addresses[i] = in.addresses[n - 1 - i]; |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::someMethodTakingAVectorOfArray( |
| const hidl_vec<hidl_array<uint8_t, 6> > &in, |
| someMethodTakingAVectorOfArray_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someMethodTakingAVectorOfArray " |
| << to_string(in); |
| |
| const size_t n = in.size(); |
| |
| hidl_vec<hidl_array<uint8_t, 6> > out; |
| out.resize(n); |
| |
| for (size_t i = 0; i < n; ++i) { |
| out[i] = in[n - 1 - i]; |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::transpose( |
| const IBase::StringMatrix5x3 &in, transpose_cb _hidl_cb) { |
| LOG(INFO) << "Baz::transpose " << to_string(in); |
| |
| IBase::StringMatrix3x5 out; |
| for (size_t i = 0; i < 3; ++i) { |
| for (size_t j = 0; j < 5; ++j) { |
| out.s[i][j] = in.s[j][i]; |
| } |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::transpose2( |
| const hidl_array<hidl_string, 5, 3> &in, transpose2_cb _hidl_cb) { |
| LOG(INFO) << "Baz::transpose2 " << to_string(in); |
| |
| hidl_array<hidl_string, 3, 5> out; |
| for (size_t i = 0; i < 3; ++i) { |
| for (size_t j = 0; j < 5; ++j) { |
| out[i][j] = in[j][i]; |
| } |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<bool> Baz::someBoolMethod(bool x) { |
| LOG(INFO) << "Baz::someBoolMethod(" << to_string(x) << ")"; |
| |
| return !x; |
| } |
| |
| Return<void> Baz::someBoolArrayMethod( |
| const hidl_array<bool, 3> &x, someBoolArrayMethod_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someBoolArrayMethod(" |
| << to_string(x[0]) |
| << ", " |
| << to_string(x[1]) |
| << ", " |
| << to_string(x[2]) |
| << ")"; |
| |
| hidl_array<bool, 4> out; |
| out[0] = !x[0]; |
| out[1] = !x[1]; |
| out[2] = !x[2]; |
| out[3] = true; |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::someBoolVectorMethod( |
| const hidl_vec<bool> &x, someBoolVectorMethod_cb _hidl_cb) { |
| LOG(INFO) << "Baz::someBoolVectorMethod(" << to_string(x) << ")"; |
| |
| hidl_vec<bool> out; |
| out.resize(x.size()); |
| for (size_t i = 0; i < x.size(); ++i) { |
| out[i] = !x[i]; |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::doSomethingElse( |
| const hidl_array<int32_t, 15> ¶m, doSomethingElse_cb _hidl_cb) { |
| LOG(INFO) << "Baz::doSomethingElse(...)"; |
| |
| hidl_array<int32_t, 32> result; |
| for (size_t i = 0; i < 15; ++i) { |
| result[i] = 2 * param[i]; |
| result[15 + i] = param[i]; |
| } |
| result[30] = 1; |
| result[31] = 2; |
| |
| _hidl_cb(result); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::doThis(float param) { |
| LOG(INFO) << "Baz::doThis(" << param << ")"; |
| |
| return Void(); |
| } |
| |
| Return<int32_t> Baz::doThatAndReturnSomething(int64_t param) { |
| LOG(INFO) << "Baz::doThatAndReturnSomething(" << param << ")"; |
| |
| return 666; |
| } |
| |
| Return<double> Baz::doQuiteABit( |
| int32_t a, |
| int64_t b, |
| float c, |
| double d) { |
| LOG(INFO) << "Baz::doQuiteABit(" |
| << a |
| << ", " |
| << b |
| << ", " |
| << c |
| << ", " |
| << d |
| << ")"; |
| |
| return 666.5; |
| } |
| |
| Return<void> Baz::doStuffAndReturnAString( |
| doStuffAndReturnAString_cb _hidl_cb) { |
| LOG(INFO) << "doStuffAndReturnAString"; |
| |
| hidl_string s; |
| s = "Hello, world!"; |
| |
| _hidl_cb(s); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::mapThisVector( |
| const hidl_vec<int32_t>& param, mapThisVector_cb _hidl_cb) { |
| LOG(INFO) << "mapThisVector"; |
| |
| hidl_vec<int32_t> out; |
| out.resize(param.size()); |
| for (size_t i = 0; i < param.size(); ++i) { |
| out[i] = param[i] * 2; |
| } |
| |
| _hidl_cb(out); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::callMe(const sp<IBazCallback>& cb) { |
| LOG(INFO) << "callMe " << cb.get(); |
| |
| if (cb != NULL) { |
| sp<IBazCallback> my_cb = new BazCallback; |
| cb->heyItsMe(my_cb); |
| } |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::callMeLater(const sp<IBazCallback>& cb) { |
| LOG(INFO) << "callMeLater " << cb.get(); |
| |
| mStoredCallback = cb; |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::iAmFreeNow() { |
| if (mStoredCallback != nullptr) { |
| mStoredCallback->hey(); |
| } |
| return Void(); |
| } |
| |
| Return<void> Baz::dieNow() { |
| exit(1); |
| return Void(); |
| } |
| |
| Return<IBaz::SomeEnum> Baz::useAnEnum(IBaz::SomeEnum zzz) { |
| LOG(INFO) << "useAnEnum " << (int)zzz; |
| |
| return SomeEnum::goober; |
| } |
| |
| Return<void> Baz::haveSomeStrings( |
| const hidl_array<hidl_string, 3> &array, haveSomeStrings_cb _hidl_cb) { |
| LOG(INFO) << "haveSomeStrings(" |
| << to_string(array) |
| << ")"; |
| |
| hidl_array<hidl_string, 2> result; |
| result[0] = "Hello"; |
| result[1] = "World"; |
| |
| _hidl_cb(result); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::haveAStringVec( |
| const hidl_vec<hidl_string>& vector, |
| haveAStringVec_cb _hidl_cb) { |
| LOG(INFO) << "haveAStringVec(" << to_string(vector) << ")"; |
| |
| hidl_vec<hidl_string> result; |
| result.resize(2); |
| |
| result[0] = "Hello"; |
| result[1] = "World"; |
| |
| _hidl_cb(result); |
| |
| return Void(); |
| } |
| |
| Return<void> Baz::returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) { |
| hidl_string eins; eins = "Eins"; |
| hidl_string zwei; zwei = "Zwei"; |
| hidl_string drei; drei = "Drei"; |
| _hidl_cb(eins, zwei, drei); |
| |
| return Void(); |
| } |
| |
| |
| Return<void> Baz::takeAMask(IBase::BitField bf, uint8_t first, |
| const IBase::MyMask& second, uint8_t third, takeAMask_cb _hidl_cb) { |
| _hidl_cb(bf, bf | first, second.value & bf, (bf | bf) & third); |
| return Void(); |
| } |
| |
| Return<uint8_t> Baz::returnABitField() { |
| return 0; |
| } |
| |
| Return<uint32_t> Baz::size(uint32_t size) { |
| return size; |
| } |
| |
| Return<void> Baz::getNestedStructs(IBaz::getNestedStructs_cb _hidl_cb) { |
| int size = 5; |
| hidl_vec<IBaz::NestedStruct> result; |
| result.resize(size); |
| for (int i = 0; i < size; i++) { |
| result[i].a = i; |
| if (i == 1) { |
| result[i].matrices.resize(6); |
| } |
| } |
| _hidl_cb(result); |
| return Void(); |
| } |
| |
| static void usage(const char *me) { |
| fprintf(stderr, "%s [-c]lient | [-s]erver\n", me); |
| } |
| |
| struct HidlEnvironment : public ::testing::Environment { |
| void SetUp() override { |
| } |
| |
| void TearDown() override { |
| } |
| }; |
| |
| struct HidlTest : public ::testing::Test { |
| sp<IBaz> baz; |
| |
| void SetUp() override { |
| using namespace ::android::hardware; |
| |
| baz = IBaz::getService("baz"); |
| |
| CHECK(baz != NULL); |
| } |
| |
| void TearDown() override { |
| } |
| }; |
| |
| template <typename T> |
| static void EXPECT_OK(::android::hardware::Return<T> ret) { |
| EXPECT_TRUE(ret.isOk()); |
| } |
| |
| TEST_F(HidlTest, GetDescriptorTest) { |
| EXPECT_OK(baz->interfaceDescriptor([&] (const auto &desc) { |
| EXPECT_EQ(desc, IBaz::descriptor); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeBaseMethodTest) { |
| EXPECT_OK(baz->someBaseMethod()); |
| } |
| |
| TEST_F(HidlTest, BazSomeOtherBaseMethodTest) { |
| IBase::Foo foo; |
| foo.x = 1; |
| foo.y.z = 2.5; |
| foo.y.s = "Hello, world"; |
| |
| foo.aaa.resize(5); |
| for (size_t i = 0; i < foo.aaa.size(); ++i) { |
| foo.aaa[i].z = 1.0f + (float)i * 0.01f; |
| foo.aaa[i].s = ("Hello, world " + std::to_string(i)).c_str(); |
| } |
| |
| EXPECT_OK( |
| baz->someOtherBaseMethod( |
| foo, |
| [&](const auto &result) { |
| // Strings should have the same size as they did before |
| // marshaling. b/35038064 |
| EXPECT_EQ(result.y.s.size(), foo.y.s.size()); |
| |
| EXPECT_EQ( |
| to_string(result), |
| "Foo(x = 1, " |
| "y = Bar(z = 2.500000, s = 'Hello, world'), " |
| "aaa = [Bar(z = 1.000000, s = 'Hello, world 0'), " |
| "Bar(z = 1.010000, s = 'Hello, world 1'), " |
| "Bar(z = 1.020000, s = 'Hello, world 2'), " |
| "Bar(z = 1.030000, s = 'Hello, world 3'), " |
| "Bar(z = 1.040000, s = 'Hello, world 4')])"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeMethodWithFooArraysTest) { |
| hidl_array<IBase::Foo, 2> foo; |
| |
| foo[0].x = 1; |
| foo[0].y.z = 2.5; |
| foo[0].y.s = "Hello, world"; |
| |
| foo[0].aaa.resize(5); |
| for (size_t i = 0; i < foo[0].aaa.size(); ++i) { |
| foo[0].aaa[i].z = 1.0f + (float)i * 0.01f; |
| foo[0].aaa[i].s = ("Hello, world " + std::to_string(i)).c_str(); |
| } |
| |
| foo[1].x = 2; |
| foo[1].y.z = -2.5; |
| foo[1].y.s = "Morituri te salutant"; |
| |
| foo[1].aaa.resize(3); |
| for (size_t i = 0; i < foo[1].aaa.size(); ++i) { |
| foo[1].aaa[i].z = 2.0f - (float)i * 0.01f; |
| foo[1].aaa[i].s = ("Alea iacta est: " + std::to_string(i)).c_str(); |
| } |
| |
| EXPECT_OK( |
| baz->someMethodWithFooArrays( |
| foo, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), |
| "[Foo(x = 2, " |
| "y = Bar(z = -2.500000, s = 'Morituri te salutant'), " |
| "aaa = [Bar(z = 2.000000, s = 'Alea iacta est: 0'), " |
| "Bar(z = 1.990000, s = 'Alea iacta est: 1'), " |
| "Bar(z = 1.980000, s = 'Alea iacta est: 2')]), " |
| "Foo(x = 1, " |
| "y = Bar(z = 2.500000, s = 'Hello, world'), " |
| "aaa = [Bar(z = 1.000000, s = 'Hello, world 0'), " |
| "Bar(z = 1.010000, s = 'Hello, world 1'), " |
| "Bar(z = 1.020000, s = 'Hello, world 2'), " |
| "Bar(z = 1.030000, s = 'Hello, world 3'), " |
| "Bar(z = 1.040000, s = 'Hello, world 4')])]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeMethodWithFooVectorsTest) { |
| hidl_vec<IBase::Foo> foo; |
| foo.resize(2); |
| |
| foo[0].x = 1; |
| foo[0].y.z = 2.5; |
| foo[0].y.s = "Hello, world"; |
| |
| foo[0].aaa.resize(5); |
| for (size_t i = 0; i < foo[0].aaa.size(); ++i) { |
| foo[0].aaa[i].z = 1.0f + (float)i * 0.01f; |
| foo[0].aaa[i].s = ("Hello, world " + std::to_string(i)).c_str(); |
| } |
| |
| foo[1].x = 2; |
| foo[1].y.z = -2.5; |
| foo[1].y.s = "Morituri te salutant"; |
| |
| foo[1].aaa.resize(3); |
| for (size_t i = 0; i < foo[1].aaa.size(); ++i) { |
| foo[1].aaa[i].z = 2.0f - (float)i * 0.01f; |
| foo[1].aaa[i].s = ("Alea iacta est: " + std::to_string(i)).c_str(); |
| } |
| |
| EXPECT_OK( |
| baz->someMethodWithFooVectors( |
| foo, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), |
| "[Foo(x = 2, " |
| "y = Bar(z = -2.500000, s = 'Morituri te salutant'), " |
| "aaa = [Bar(z = 2.000000, s = 'Alea iacta est: 0'), " |
| "Bar(z = 1.990000, s = 'Alea iacta est: 1'), " |
| "Bar(z = 1.980000, s = 'Alea iacta est: 2')]), " |
| "Foo(x = 1, " |
| "y = Bar(z = 2.500000, s = 'Hello, world'), " |
| "aaa = [Bar(z = 1.000000, s = 'Hello, world 0'), " |
| "Bar(z = 1.010000, s = 'Hello, world 1'), " |
| "Bar(z = 1.020000, s = 'Hello, world 2'), " |
| "Bar(z = 1.030000, s = 'Hello, world 3'), " |
| "Bar(z = 1.040000, s = 'Hello, world 4')])]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeMethodWithVectorOfArray) { |
| IBase::VectorOfArray in; |
| in.addresses.resize(3); |
| |
| size_t k = 0; |
| for (size_t i = 0; i < in.addresses.size(); ++i) { |
| for (size_t j = 0; j < 6; ++j, ++k) { |
| in.addresses[i][j] = k; |
| } |
| } |
| |
| EXPECT_OK( |
| baz->someMethodWithVectorOfArray( |
| in, |
| [&](const auto &out) { |
| EXPECT_EQ( |
| VectorOfArray_to_string(out), |
| "VectorOfArray(" |
| "0c:0d:0e:0f:10:11, " |
| "06:07:08:09:0a:0b, " |
| "00:01:02:03:04:05)"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeMethodTakingAVectorOfArray) { |
| hidl_vec<hidl_array<uint8_t, 6> > in; |
| in.resize(3); |
| |
| size_t k = 0; |
| for (size_t i = 0; i < in.size(); ++i) { |
| for (size_t j = 0; j < 6; ++j, ++k) { |
| in[i][j] = k; |
| } |
| } |
| |
| EXPECT_OK( |
| baz->someMethodTakingAVectorOfArray( |
| in, |
| [&](const auto &out) { |
| EXPECT_EQ( |
| to_string(out), |
| "[0c:0d:0e:0f:10:11, 06:07:08:09:0a:0b, 00:01:02:03:04:05]"); |
| })); |
| } |
| |
| static std::string numberToEnglish(int x) { |
| static const char *const kDigits[] = { |
| "zero", |
| "one", |
| "two", |
| "three", |
| "four", |
| "five", |
| "six", |
| "seven", |
| "eight", |
| "nine", |
| }; |
| |
| if (x < 0) { |
| return "negative " + numberToEnglish(-x); |
| } |
| |
| if (x < 10) { |
| return kDigits[x]; |
| } |
| |
| if (x <= 15) { |
| static const char *const kSpecialTens[] = { |
| "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", |
| }; |
| |
| return kSpecialTens[x - 10]; |
| } |
| |
| if (x < 20) { |
| return std::string(kDigits[x % 10]) + "teen"; |
| } |
| |
| if (x < 100) { |
| static const char *const kDecades[] = { |
| "twenty", "thirty", "forty", "fifty", "sixty", "seventy", |
| "eighty", "ninety", |
| }; |
| |
| return std::string(kDecades[x / 10 - 2]) + kDigits[x % 10]; |
| } |
| |
| return "positively huge!"; |
| } |
| |
| TEST_F(HidlTest, BazTransposeTest) { |
| IBase::StringMatrix5x3 in; |
| |
| for (int i = 0; i < 5; ++i) { |
| for (int j = 0; j < 3; ++j) { |
| in.s[i][j] = numberToEnglish(3 * i + j + 1).c_str(); |
| } |
| } |
| |
| EXPECT_OK(baz->transpose( |
| in, |
| [&](const auto &out) { |
| EXPECT_EQ( |
| to_string(out), |
| "[['one', 'four', 'seven', 'ten', 'thirteen'], " |
| "['two', 'five', 'eight', 'eleven', 'fourteen'], " |
| "['three', 'six', 'nine', 'twelve', 'fifteen']]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazTranspose2Test) { |
| hidl_array<hidl_string, 5, 3> in; |
| |
| for (int i = 0; i < 5; ++i) { |
| for (int j = 0; j < 3; ++j) { |
| in[i][j] = numberToEnglish(3 * i + j + 1).c_str(); |
| } |
| } |
| |
| EXPECT_OK(baz->transpose2( |
| in, |
| [&](const auto &out) { |
| EXPECT_EQ( |
| to_string(out), |
| "[['one', 'four', 'seven', 'ten', 'thirteen'], " |
| "['two', 'five', 'eight', 'eleven', 'fourteen'], " |
| "['three', 'six', 'nine', 'twelve', 'fifteen']]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeBoolMethodTest) { |
| auto result = baz->someBoolMethod(true); |
| EXPECT_OK(result); |
| EXPECT_EQ(to_string(result), "false"); |
| } |
| |
| TEST_F(HidlTest, BazSomeBoolArrayMethodTest) { |
| hidl_array<bool, 3> someBoolArray; |
| someBoolArray[0] = true; |
| someBoolArray[1] = false; |
| someBoolArray[2] = true; |
| |
| EXPECT_OK( |
| baz->someBoolArrayMethod( |
| someBoolArray, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), |
| "[false, true, false, true]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazSomeBoolVectorMethodTest) { |
| hidl_vec<bool> someBoolVector; |
| someBoolVector.resize(4); |
| for (size_t i = 0; i < someBoolVector.size(); ++i) { |
| someBoolVector[i] = ((i & 1) == 0); |
| } |
| |
| EXPECT_OK( |
| baz->someBoolVectorMethod( |
| someBoolVector, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), "[false, true, false, true]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazDoThisMethodTest) { |
| EXPECT_OK(baz->doThis(1.0f)); |
| } |
| |
| TEST_F(HidlTest, BazDoThatAndReturnSomethingMethodTest) { |
| auto result = baz->doThatAndReturnSomething(1); |
| EXPECT_OK(result); |
| EXPECT_EQ(to_string(result), "666"); |
| } |
| |
| TEST_F(HidlTest, BazDoQuiteABitMethodTest) { |
| auto result = baz->doQuiteABit(1, 2ll, 3.0f, 4.0); |
| |
| EXPECT_OK(result); |
| EXPECT_EQ(to_string(result), "666.500000"); |
| } |
| |
| TEST_F(HidlTest, BazDoSomethingElseMethodTest) { |
| hidl_array<int32_t, 15> param; |
| for (size_t i = 0; i < 15; ++i) { |
| param[i] = i; |
| } |
| |
| EXPECT_OK( |
| baz->doSomethingElse( |
| param, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), |
| "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, " |
| "28, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, " |
| "1, 2]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazDoStuffAndReturnAStringMethodTest) { |
| EXPECT_OK( |
| baz->doStuffAndReturnAString( |
| [&](const auto &result) { |
| EXPECT_EQ(to_string(result), "'Hello, world!'"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazMapThisVectorMethodTest) { |
| hidl_vec<int32_t> vec_param; |
| vec_param.resize(15); |
| for (size_t i = 0; i < 15; ++i) { |
| vec_param[i] = i; |
| } |
| |
| EXPECT_OK( |
| baz->mapThisVector( |
| vec_param, |
| [&](const auto &result) { |
| EXPECT_EQ( |
| to_string(result), |
| "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, " |
| "28]"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazCallMeMethodTest) { |
| EXPECT_OK(baz->callMe(new BazCallback())); |
| } |
| |
| TEST_F(HidlTest, BazCallMeLaterMethodTest) { |
| EXPECT_OK(baz->callMeLater(new BazCallback())); |
| EXPECT_OK(baz->iAmFreeNow()); |
| } |
| |
| TEST_F(HidlTest, BazUseAnEnumMethodTest) { |
| auto result = baz->useAnEnum(IBaz::SomeEnum::bar); |
| |
| EXPECT_OK(result); |
| EXPECT_TRUE(result == IBaz::SomeEnum::quux); |
| } |
| |
| TEST_F(HidlTest, BazHaveSomeStringsMethodTest) { |
| hidl_array<hidl_string, 3> string_params; |
| string_params[0] = "one"; |
| string_params[1] = "two"; |
| string_params[2] = "three"; |
| |
| EXPECT_OK( |
| baz->haveSomeStrings( |
| string_params, |
| [&](const auto &result) { |
| EXPECT_EQ(to_string(result), "['Hello', 'World']"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazHaveAStringVecMethodTest) { |
| hidl_vec<hidl_string> string_vec; |
| string_vec.resize(4); |
| string_vec[0] = "Uno"; |
| string_vec[1] = "Dos"; |
| string_vec[2] = "Tres"; |
| string_vec[3] = "Cuatro"; |
| |
| EXPECT_OK( |
| baz->haveAStringVec( |
| string_vec, |
| [&](const auto &result) { |
| EXPECT_EQ(to_string(result), "['Hello', 'World']"); |
| })); |
| } |
| |
| TEST_F(HidlTest, BazReturnABunchOfStringsMethodTest) { |
| EXPECT_OK( |
| baz->returnABunchOfStrings( |
| [&](const auto &a, const auto &b, const auto &c) { |
| EXPECT_EQ( |
| to_string(a) + ", " + to_string(b) + ", " + to_string(c), |
| "'Eins', 'Zwei', 'Drei'"); |
| })); |
| } |
| |
| int main(int argc, char **argv) { |
| using namespace android::hardware; |
| |
| const char *me = argv[0]; |
| |
| bool wantClient = false; |
| bool wantServer = false; |
| |
| int res; |
| while ((res = getopt(argc, argv, "chs")) >= 0) { |
| switch (res) { |
| case 'c': |
| { |
| wantClient = true; |
| break; |
| } |
| |
| case 's': |
| { |
| wantServer = true; |
| break; |
| } |
| |
| case '?': |
| case 'h': |
| default: |
| { |
| usage(me); |
| exit(1); |
| break; |
| } |
| } |
| } |
| |
| if ((!wantClient && !wantServer) || (wantClient && wantServer)) { |
| usage(me); |
| exit(1); |
| } |
| |
| if (wantClient) { |
| ::testing::AddGlobalTestEnvironment(new HidlEnvironment); |
| ::testing::InitGoogleTest(&argc, argv); |
| int status = RUN_ALL_TESTS(); |
| return status; |
| } else { |
| sp<Baz> baz = new Baz; |
| configureRpcThreadpool(1, true /* callerWillJoin */); |
| baz->registerAsService("baz"); |
| joinRpcThreadpool(); |
| } |
| |
| return 0; |
| } |
| |