diff options
| -rw-r--r-- | libs/binder/tests/Android.bp | 1 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 489 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcTestCommon.h | 8 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcUniversalTests.cpp | 513 |
4 files changed, 522 insertions, 489 deletions
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index 92d132f37c..03e4a23bd8 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -232,6 +232,7 @@ cc_defaults { srcs: [ "binderRpcTest.cpp", "binderRpcTestCommon.cpp", + "binderRpcUniversalTests.cpp", ], test_suites: ["general-tests"], diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 5d5b5303d3..004dea317d 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -15,7 +15,6 @@ */ #include <android-base/stringprintf.h> -#include <gtest/gtest.h> #include <chrono> #include <cstdlib> @@ -45,29 +44,6 @@ constexpr bool kEnableSharedLibs = false; constexpr bool kEnableSharedLibs = true; #endif -static_assert(RPC_WIRE_PROTOCOL_VERSION + 1 == RPC_WIRE_PROTOCOL_VERSION_NEXT || - RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL); - -TEST(BinderRpcParcel, EntireParcelFormatted) { - Parcel p; - p.writeInt32(3); - - EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), "format must be set before data is written"); -} - -TEST(BinderRpc, CannotUseNextWireVersion) { - auto session = RpcSession::make(); - EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT)); - EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 1)); - EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 2)); - EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 15)); -} - -TEST(BinderRpc, CanUseExperimentalWireVersion) { - auto session = RpcSession::make(); - EXPECT_TRUE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL)); -} - static std::string WaitStatusToString(int wstatus) { if (WIFEXITED(wstatus)) { return base::StringPrintf("exit status %d", WEXITSTATUS(wstatus)); @@ -362,380 +338,6 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc( return ret; } -TEST_P(BinderRpc, Ping) { - auto proc = createRpcTestSocketServerProcess({}); - ASSERT_NE(proc.rootBinder, nullptr); - EXPECT_EQ(OK, proc.rootBinder->pingBinder()); -} - -TEST_P(BinderRpc, GetInterfaceDescriptor) { - auto proc = createRpcTestSocketServerProcess({}); - ASSERT_NE(proc.rootBinder, nullptr); - EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor()); -} - -TEST_P(BinderRpc, MultipleSessions) { - if (serverSingleThreaded()) { - // Tests with multiple sessions require a multi-threaded service, - // but work fine on a single-threaded client - GTEST_SKIP() << "This test requires a multi-threaded service"; - } - - auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 5}); - for (auto session : proc.proc->sessions) { - ASSERT_NE(nullptr, session.root); - EXPECT_EQ(OK, session.root->pingBinder()); - } -} - -TEST_P(BinderRpc, SeparateRootObject) { - if (serverSingleThreaded()) { - GTEST_SKIP() << "This test requires a multi-threaded service"; - } - - SocketType type = std::get<0>(GetParam()); - if (type == SocketType::PRECONNECTED || type == SocketType::UNIX || - type == SocketType::UNIX_BOOTSTRAP) { - // we can't get port numbers for unix sockets - return; - } - - auto proc = createRpcTestSocketServerProcess({.numSessions = 2}); - - int port1 = 0; - EXPECT_OK(proc.rootIface->getClientPort(&port1)); - - sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc->sessions.at(1).root); - int port2; - EXPECT_OK(rootIface2->getClientPort(&port2)); - - // we should have a different IBinderRpcTest object created for each - // session, because we use setPerSessionRootObject - EXPECT_NE(port1, port2); -} - -TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { - auto proc = createRpcTestSocketServerProcess({}); - Parcel data; - Parcel reply; - EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); -} - -TEST_P(BinderRpc, AppendSeparateFormats) { - auto proc1 = createRpcTestSocketServerProcess({}); - auto proc2 = createRpcTestSocketServerProcess({}); - - Parcel pRaw; - - Parcel p1; - p1.markForBinder(proc1.rootBinder); - p1.writeInt32(3); - - EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, pRaw.dataSize())); - EXPECT_EQ(BAD_TYPE, pRaw.appendFrom(&p1, 0, p1.dataSize())); - - Parcel p2; - p2.markForBinder(proc2.rootBinder); - p2.writeInt32(7); - - EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize())); - EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize())); -} - -TEST_P(BinderRpc, UnknownTransaction) { - auto proc = createRpcTestSocketServerProcess({}); - Parcel data; - data.markForBinder(proc.rootBinder); - Parcel reply; - EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); -} - -TEST_P(BinderRpc, SendSomethingOneway) { - auto proc = createRpcTestSocketServerProcess({}); - EXPECT_OK(proc.rootIface->sendString("asdf")); -} - -TEST_P(BinderRpc, SendAndGetResultBack) { - auto proc = createRpcTestSocketServerProcess({}); - std::string doubled; - EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); - EXPECT_EQ("cool cool ", doubled); -} - -TEST_P(BinderRpc, SendAndGetResultBackBig) { - auto proc = createRpcTestSocketServerProcess({}); - std::string single = std::string(1024, 'a'); - std::string doubled; - EXPECT_OK(proc.rootIface->doubleString(single, &doubled)); - EXPECT_EQ(single + single, doubled); -} - -TEST_P(BinderRpc, InvalidNullBinderReturn) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> outBinder; - EXPECT_EQ(proc.rootIface->getNullBinder(&outBinder).transactionError(), UNEXPECTED_NULL); -} - -TEST_P(BinderRpc, CallMeBack) { - auto proc = createRpcTestSocketServerProcess({}); - - int32_t pingResult; - EXPECT_OK(proc.rootIface->pingMe(new MyBinderRpcSession("foo"), &pingResult)); - EXPECT_EQ(OK, pingResult); - - EXPECT_EQ(0, MyBinderRpcSession::gNum); -} - -TEST_P(BinderRpc, RepeatBinder) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> inBinder = new MyBinderRpcSession("foo"); - sp<IBinder> outBinder; - EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder)); - EXPECT_EQ(inBinder, outBinder); - - wp<IBinder> weak = inBinder; - inBinder = nullptr; - outBinder = nullptr; - - // Force reading a reply, to process any pending dec refs from the other - // process (the other process will process dec refs there before processing - // the ping here). - EXPECT_EQ(OK, proc.rootBinder->pingBinder()); - - EXPECT_EQ(nullptr, weak.promote()); - - EXPECT_EQ(0, MyBinderRpcSession::gNum); -} - -TEST_P(BinderRpc, RepeatTheirBinder) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinderRpcSession> session; - EXPECT_OK(proc.rootIface->openSession("aoeu", &session)); - - sp<IBinder> inBinder = IInterface::asBinder(session); - sp<IBinder> outBinder; - EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder)); - EXPECT_EQ(inBinder, outBinder); - - wp<IBinder> weak = inBinder; - session = nullptr; - inBinder = nullptr; - outBinder = nullptr; - - // Force reading a reply, to process any pending dec refs from the other - // process (the other process will process dec refs there before processing - // the ping here). - EXPECT_EQ(OK, proc.rootBinder->pingBinder()); - - EXPECT_EQ(nullptr, weak.promote()); -} - -TEST_P(BinderRpc, RepeatBinderNull) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> outBinder; - EXPECT_OK(proc.rootIface->repeatBinder(nullptr, &outBinder)); - EXPECT_EQ(nullptr, outBinder); -} - -TEST_P(BinderRpc, HoldBinder) { - auto proc = createRpcTestSocketServerProcess({}); - - IBinder* ptr = nullptr; - { - sp<IBinder> binder = new BBinder(); - ptr = binder.get(); - EXPECT_OK(proc.rootIface->holdBinder(binder)); - } - - sp<IBinder> held; - EXPECT_OK(proc.rootIface->getHeldBinder(&held)); - - EXPECT_EQ(held.get(), ptr); - - // stop holding binder, because we test to make sure references are cleaned - // up - EXPECT_OK(proc.rootIface->holdBinder(nullptr)); - // and flush ref counts - EXPECT_EQ(OK, proc.rootBinder->pingBinder()); -} - -// START TESTS FOR LIMITATIONS OF SOCKET BINDER -// These are behavioral differences form regular binder, where certain usecases -// aren't supported. - -TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketSessions) { - auto proc1 = createRpcTestSocketServerProcess({}); - auto proc2 = createRpcTestSocketServerProcess({}); - - sp<IBinder> outBinder; - EXPECT_EQ(INVALID_OPERATION, - proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); -} - -TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) { - if (serverSingleThreaded()) { - GTEST_SKIP() << "This test requires a multi-threaded service"; - } - - auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 2}); - - sp<IBinder> outBinder; - EXPECT_EQ(INVALID_OPERATION, - proc.rootIface->repeatBinder(proc.proc->sessions.at(1).root, &outBinder) - .transactionError()); -} - -TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) { - if (!kEnableKernelIpc || noKernel()) { - GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled " - "at build time."; - } - - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); - sp<IBinder> outBinder; - EXPECT_EQ(INVALID_OPERATION, - proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); -} - -TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) { - if (!kEnableKernelIpc || noKernel()) { - GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled " - "at build time."; - } - - auto proc = createRpcTestSocketServerProcess({}); - - // for historical reasons, IServiceManager interface only returns the - // exception code - EXPECT_EQ(binder::Status::EX_TRANSACTION_FAILED, - defaultServiceManager()->addService(String16("not_suspicious"), proc.rootBinder)); -} - -// END TESTS FOR LIMITATIONS OF SOCKET BINDER - -TEST_P(BinderRpc, RepeatRootObject) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> outBinder; - EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &outBinder)); - EXPECT_EQ(proc.rootBinder, outBinder); -} - -TEST_P(BinderRpc, NestedTransactions) { - auto proc = createRpcTestSocketServerProcess({ - // Enable FD support because it uses more stack space and so represents - // something closer to a worst case scenario. - .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX, - .serverSupportedFileDescriptorTransportModes = - {RpcSession::FileDescriptorTransportMode::UNIX}, - }); - - auto nastyNester = sp<MyBinderRpcTest>::make(); - EXPECT_OK(proc.rootIface->nestMe(nastyNester, 10)); - - wp<IBinder> weak = nastyNester; - nastyNester = nullptr; - EXPECT_EQ(nullptr, weak.promote()); -} - -TEST_P(BinderRpc, SameBinderEquality) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> a; - EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a)); - - sp<IBinder> b; - EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b)); - - EXPECT_EQ(a, b); -} - -TEST_P(BinderRpc, SameBinderEqualityWeak) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinder> a; - EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a)); - wp<IBinder> weak = a; - a = nullptr; - - sp<IBinder> b; - EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b)); - - // this is the wrong behavior, since BpBinder - // doesn't implement onIncStrongAttempted - // but make sure there is no crash - EXPECT_EQ(nullptr, weak.promote()); - - GTEST_SKIP() << "Weak binders aren't currently re-promotable for RPC binder."; - - // In order to fix this: - // - need to have incStrongAttempted reflected across IPC boundary (wait for - // response to promote - round trip...) - // - sendOnLastWeakRef, to delete entries out of RpcState table - EXPECT_EQ(b, weak.promote()); -} - -#define expectSessions(expected, iface) \ - do { \ - int session; \ - EXPECT_OK((iface)->getNumOpenSessions(&session)); \ - EXPECT_EQ(expected, session); \ - } while (false) - -TEST_P(BinderRpc, SingleSession) { - auto proc = createRpcTestSocketServerProcess({}); - - sp<IBinderRpcSession> session; - EXPECT_OK(proc.rootIface->openSession("aoeu", &session)); - std::string out; - EXPECT_OK(session->getName(&out)); - EXPECT_EQ("aoeu", out); - - expectSessions(1, proc.rootIface); - session = nullptr; - expectSessions(0, proc.rootIface); -} - -TEST_P(BinderRpc, ManySessions) { - auto proc = createRpcTestSocketServerProcess({}); - - std::vector<sp<IBinderRpcSession>> sessions; - - for (size_t i = 0; i < 15; i++) { - expectSessions(i, proc.rootIface); - sp<IBinderRpcSession> session; - EXPECT_OK(proc.rootIface->openSession(std::to_string(i), &session)); - sessions.push_back(session); - } - expectSessions(sessions.size(), proc.rootIface); - for (size_t i = 0; i < sessions.size(); i++) { - std::string out; - EXPECT_OK(sessions.at(i)->getName(&out)); - EXPECT_EQ(std::to_string(i), out); - } - expectSessions(sessions.size(), proc.rootIface); - - while (!sessions.empty()) { - sessions.pop_back(); - expectSessions(sessions.size(), proc.rootIface); - } - expectSessions(0, proc.rootIface); -} - -size_t epochMillis() { - using std::chrono::duration_cast; - using std::chrono::milliseconds; - using std::chrono::seconds; - using std::chrono::system_clock; - return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); -} - TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) { if (clientOrServerSingleThreaded()) { GTEST_SKIP() << "This test requires multiple threads"; @@ -873,20 +475,6 @@ TEST_P(BinderRpc, OnewayStressTest) { saturateThreadPool(kNumServerThreads, proc.rootIface); } -TEST_P(BinderRpc, OnewayCallDoesNotWait) { - constexpr size_t kReallyLongTimeMs = 100; - constexpr size_t kSleepMs = kReallyLongTimeMs * 5; - - auto proc = createRpcTestSocketServerProcess({}); - - size_t epochMsBefore = epochMillis(); - - EXPECT_OK(proc.rootIface->sleepMsAsync(kSleepMs)); - - size_t epochMsAfter = epochMillis(); - EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); -} - TEST_P(BinderRpc, OnewayCallQueueingWithFds) { if (!supportsFdTransport()) { GTEST_SKIP() << "Would fail trivially (which is tested elsewhere)"; @@ -1003,65 +591,6 @@ TEST_P(BinderRpc, OnewayCallExhaustion) { proc.proc->sessions.erase(proc.proc->sessions.begin() + 1); } -TEST_P(BinderRpc, Callbacks) { - const static std::string kTestString = "good afternoon!"; - - for (bool callIsOneway : {true, false}) { - for (bool callbackIsOneway : {true, false}) { - for (bool delayed : {true, false}) { - if (clientOrServerSingleThreaded() && - (callIsOneway || callbackIsOneway || delayed)) { - // we have no incoming connections to receive the callback - continue; - } - - size_t numIncomingConnections = clientOrServerSingleThreaded() ? 0 : 1; - auto proc = createRpcTestSocketServerProcess( - {.numThreads = 1, - .numSessions = 1, - .numIncomingConnections = numIncomingConnections}); - auto cb = sp<MyBinderRpcCallback>::make(); - - if (callIsOneway) { - EXPECT_OK(proc.rootIface->doCallbackAsync(cb, callbackIsOneway, delayed, - kTestString)); - } else { - EXPECT_OK( - proc.rootIface->doCallback(cb, callbackIsOneway, delayed, kTestString)); - } - - // if both transactions are synchronous and the response is sent back on the - // same thread, everything should have happened in a nested call. Otherwise, - // the callback will be processed on another thread. - if (callIsOneway || callbackIsOneway || delayed) { - using std::literals::chrono_literals::operator""s; - RpcMutexUniqueLock _l(cb->mMutex); - cb->mCv.wait_for(_l, 1s, [&] { return !cb->mValues.empty(); }); - } - - EXPECT_EQ(cb->mValues.size(), 1) - << "callIsOneway: " << callIsOneway - << " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed; - if (cb->mValues.empty()) continue; - EXPECT_EQ(cb->mValues.at(0), kTestString) - << "callIsOneway: " << callIsOneway - << " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed; - - // since we are severing the connection, we need to go ahead and - // tell the server to shutdown and exit so that waitpid won't hang - if (auto status = proc.rootIface->scheduleShutdown(); !status.isOk()) { - EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; - } - - // since this session has an incoming connection w/ a threadpool, we - // need to manually shut it down - EXPECT_TRUE(proc.proc->sessions.at(0).session->shutdownAndWait(true)); - proc.expectAlreadyShutdown = true; - } - } - } -} - TEST_P(BinderRpc, SingleDeathRecipient) { if (clientOrServerSingleThreaded()) { GTEST_SKIP() << "This test requires multiple threads"; @@ -1178,14 +707,6 @@ TEST_P(BinderRpc, UnlinkDeathRecipient) { proc.expectAlreadyShutdown = true; } -TEST_P(BinderRpc, OnewayCallbackWithNoThread) { - auto proc = createRpcTestSocketServerProcess({}); - auto cb = sp<MyBinderRpcCallback>::make(); - - Status status = proc.rootIface->doCallback(cb, true /*oneway*/, false /*delayed*/, "anything"); - EXPECT_EQ(WOULD_BLOCK, status.transactionError()); -} - TEST_P(BinderRpc, Die) { for (bool doDeathCleanup : {true, false}) { auto proc = createRpcTestSocketServerProcess({}); @@ -1431,16 +952,6 @@ TEST_P(BinderRpc, Fds) { ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); } -TEST_P(BinderRpc, AidlDelegatorTest) { - auto proc = createRpcTestSocketServerProcess({}); - auto myDelegator = sp<IBinderRpcTestDelegator>::make(proc.rootIface); - ASSERT_NE(nullptr, myDelegator); - - std::string doubled; - EXPECT_OK(myDelegator->doubleString("cool ", &doubled)); - EXPECT_EQ("cool cool ", doubled); -} - static bool testSupportVsockLoopback() { // We don't need to enable TLS to know if vsock is supported. unsigned int vsockPort = allocateVsockPort(); diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h index 823bbf6b7f..dc7d26491b 100644 --- a/libs/binder/tests/binderRpcTestCommon.h +++ b/libs/binder/tests/binderRpcTestCommon.h @@ -91,6 +91,14 @@ static inline std::string PrintToString(SocketType socketType) { } } +static inline size_t epochMillis() { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::seconds; + using std::chrono::system_clock; + return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); +} + struct BinderRpcOptions { size_t numThreads = 1; size_t numSessions = 1; diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp new file mode 100644 index 0000000000..1e8d93d81f --- /dev/null +++ b/libs/binder/tests/binderRpcUniversalTests.cpp @@ -0,0 +1,513 @@ +/* + * Copyright (C) 2022 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 <chrono> +#include <cstdlib> +#include <type_traits> + +#include "binderRpcTestCommon.h" +#include "binderRpcTestFixture.h" + +using namespace std::chrono_literals; +using namespace std::placeholders; +using testing::AssertionFailure; +using testing::AssertionResult; +using testing::AssertionSuccess; + +namespace android { + +static_assert(RPC_WIRE_PROTOCOL_VERSION + 1 == RPC_WIRE_PROTOCOL_VERSION_NEXT || + RPC_WIRE_PROTOCOL_VERSION == RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL); + +TEST(BinderRpcParcel, EntireParcelFormatted) { + Parcel p; + p.writeInt32(3); + + EXPECT_DEATH_IF_SUPPORTED(p.markForBinder(sp<BBinder>::make()), + "format must be set before data is written"); +} + +TEST(BinderRpc, CannotUseNextWireVersion) { + auto session = RpcSession::make(); + EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT)); + EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 1)); + EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 2)); + EXPECT_FALSE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_NEXT + 15)); +} + +TEST(BinderRpc, CanUseExperimentalWireVersion) { + auto session = RpcSession::make(); + EXPECT_TRUE(session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL)); +} + +TEST_P(BinderRpc, Ping) { + auto proc = createRpcTestSocketServerProcess({}); + ASSERT_NE(proc.rootBinder, nullptr); + EXPECT_EQ(OK, proc.rootBinder->pingBinder()); +} + +TEST_P(BinderRpc, GetInterfaceDescriptor) { + auto proc = createRpcTestSocketServerProcess({}); + ASSERT_NE(proc.rootBinder, nullptr); + EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor()); +} + +TEST_P(BinderRpc, MultipleSessions) { + if (serverSingleThreaded()) { + // Tests with multiple sessions require a multi-threaded service, + // but work fine on a single-threaded client + GTEST_SKIP() << "This test requires a multi-threaded service"; + } + + auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 5}); + for (auto session : proc.proc->sessions) { + ASSERT_NE(nullptr, session.root); + EXPECT_EQ(OK, session.root->pingBinder()); + } +} + +TEST_P(BinderRpc, SeparateRootObject) { + if (serverSingleThreaded()) { + GTEST_SKIP() << "This test requires a multi-threaded service"; + } + + SocketType type = std::get<0>(GetParam()); + if (type == SocketType::PRECONNECTED || type == SocketType::UNIX || + type == SocketType::UNIX_BOOTSTRAP) { + // we can't get port numbers for unix sockets + return; + } + + auto proc = createRpcTestSocketServerProcess({.numSessions = 2}); + + int port1 = 0; + EXPECT_OK(proc.rootIface->getClientPort(&port1)); + + sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc->sessions.at(1).root); + int port2; + EXPECT_OK(rootIface2->getClientPort(&port2)); + + // we should have a different IBinderRpcTest object created for each + // session, because we use setPerSessionRootObject + EXPECT_NE(port1, port2); +} + +TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { + auto proc = createRpcTestSocketServerProcess({}); + Parcel data; + Parcel reply; + EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); +} + +TEST_P(BinderRpc, AppendSeparateFormats) { + auto proc1 = createRpcTestSocketServerProcess({}); + auto proc2 = createRpcTestSocketServerProcess({}); + + Parcel pRaw; + + Parcel p1; + p1.markForBinder(proc1.rootBinder); + p1.writeInt32(3); + + EXPECT_EQ(BAD_TYPE, p1.appendFrom(&pRaw, 0, pRaw.dataSize())); + EXPECT_EQ(BAD_TYPE, pRaw.appendFrom(&p1, 0, p1.dataSize())); + + Parcel p2; + p2.markForBinder(proc2.rootBinder); + p2.writeInt32(7); + + EXPECT_EQ(BAD_TYPE, p1.appendFrom(&p2, 0, p2.dataSize())); + EXPECT_EQ(BAD_TYPE, p2.appendFrom(&p1, 0, p1.dataSize())); +} + +TEST_P(BinderRpc, UnknownTransaction) { + auto proc = createRpcTestSocketServerProcess({}); + Parcel data; + data.markForBinder(proc.rootBinder); + Parcel reply; + EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); +} + +TEST_P(BinderRpc, SendSomethingOneway) { + auto proc = createRpcTestSocketServerProcess({}); + EXPECT_OK(proc.rootIface->sendString("asdf")); +} + +TEST_P(BinderRpc, SendAndGetResultBack) { + auto proc = createRpcTestSocketServerProcess({}); + std::string doubled; + EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); + EXPECT_EQ("cool cool ", doubled); +} + +TEST_P(BinderRpc, SendAndGetResultBackBig) { + auto proc = createRpcTestSocketServerProcess({}); + std::string single = std::string(1024, 'a'); + std::string doubled; + EXPECT_OK(proc.rootIface->doubleString(single, &doubled)); + EXPECT_EQ(single + single, doubled); +} + +TEST_P(BinderRpc, InvalidNullBinderReturn) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> outBinder; + EXPECT_EQ(proc.rootIface->getNullBinder(&outBinder).transactionError(), UNEXPECTED_NULL); +} + +TEST_P(BinderRpc, CallMeBack) { + auto proc = createRpcTestSocketServerProcess({}); + + int32_t pingResult; + EXPECT_OK(proc.rootIface->pingMe(new MyBinderRpcSession("foo"), &pingResult)); + EXPECT_EQ(OK, pingResult); + + EXPECT_EQ(0, MyBinderRpcSession::gNum); +} + +TEST_P(BinderRpc, RepeatBinder) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> inBinder = new MyBinderRpcSession("foo"); + sp<IBinder> outBinder; + EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder)); + EXPECT_EQ(inBinder, outBinder); + + wp<IBinder> weak = inBinder; + inBinder = nullptr; + outBinder = nullptr; + + // Force reading a reply, to process any pending dec refs from the other + // process (the other process will process dec refs there before processing + // the ping here). + EXPECT_EQ(OK, proc.rootBinder->pingBinder()); + + EXPECT_EQ(nullptr, weak.promote()); + + EXPECT_EQ(0, MyBinderRpcSession::gNum); +} + +TEST_P(BinderRpc, RepeatTheirBinder) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinderRpcSession> session; + EXPECT_OK(proc.rootIface->openSession("aoeu", &session)); + + sp<IBinder> inBinder = IInterface::asBinder(session); + sp<IBinder> outBinder; + EXPECT_OK(proc.rootIface->repeatBinder(inBinder, &outBinder)); + EXPECT_EQ(inBinder, outBinder); + + wp<IBinder> weak = inBinder; + session = nullptr; + inBinder = nullptr; + outBinder = nullptr; + + // Force reading a reply, to process any pending dec refs from the other + // process (the other process will process dec refs there before processing + // the ping here). + EXPECT_EQ(OK, proc.rootBinder->pingBinder()); + + EXPECT_EQ(nullptr, weak.promote()); +} + +TEST_P(BinderRpc, RepeatBinderNull) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> outBinder; + EXPECT_OK(proc.rootIface->repeatBinder(nullptr, &outBinder)); + EXPECT_EQ(nullptr, outBinder); +} + +TEST_P(BinderRpc, HoldBinder) { + auto proc = createRpcTestSocketServerProcess({}); + + IBinder* ptr = nullptr; + { + sp<IBinder> binder = new BBinder(); + ptr = binder.get(); + EXPECT_OK(proc.rootIface->holdBinder(binder)); + } + + sp<IBinder> held; + EXPECT_OK(proc.rootIface->getHeldBinder(&held)); + + EXPECT_EQ(held.get(), ptr); + + // stop holding binder, because we test to make sure references are cleaned + // up + EXPECT_OK(proc.rootIface->holdBinder(nullptr)); + // and flush ref counts + EXPECT_EQ(OK, proc.rootBinder->pingBinder()); +} + +// START TESTS FOR LIMITATIONS OF SOCKET BINDER +// These are behavioral differences form regular binder, where certain usecases +// aren't supported. + +TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketSessions) { + auto proc1 = createRpcTestSocketServerProcess({}); + auto proc2 = createRpcTestSocketServerProcess({}); + + sp<IBinder> outBinder; + EXPECT_EQ(INVALID_OPERATION, + proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); +} + +TEST_P(BinderRpc, CannotMixBindersBetweenTwoSessionsToTheSameServer) { + if (serverSingleThreaded()) { + GTEST_SKIP() << "This test requires a multi-threaded service"; + } + + auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 2}); + + sp<IBinder> outBinder; + EXPECT_EQ(INVALID_OPERATION, + proc.rootIface->repeatBinder(proc.proc->sessions.at(1).root, &outBinder) + .transactionError()); +} + +TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) { + if (!kEnableKernelIpc || noKernel()) { + GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled " + "at build time."; + } + + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); + sp<IBinder> outBinder; + EXPECT_EQ(INVALID_OPERATION, + proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); +} + +TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) { + if (!kEnableKernelIpc || noKernel()) { + GTEST_SKIP() << "Test disabled because Binder kernel driver was disabled " + "at build time."; + } + + auto proc = createRpcTestSocketServerProcess({}); + + // for historical reasons, IServiceManager interface only returns the + // exception code + EXPECT_EQ(binder::Status::EX_TRANSACTION_FAILED, + defaultServiceManager()->addService(String16("not_suspicious"), proc.rootBinder)); +} + +// END TESTS FOR LIMITATIONS OF SOCKET BINDER + +TEST_P(BinderRpc, RepeatRootObject) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> outBinder; + EXPECT_OK(proc.rootIface->repeatBinder(proc.rootBinder, &outBinder)); + EXPECT_EQ(proc.rootBinder, outBinder); +} + +TEST_P(BinderRpc, NestedTransactions) { + auto proc = createRpcTestSocketServerProcess({ + // Enable FD support because it uses more stack space and so represents + // something closer to a worst case scenario. + .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX, + .serverSupportedFileDescriptorTransportModes = + {RpcSession::FileDescriptorTransportMode::UNIX}, + }); + + auto nastyNester = sp<MyBinderRpcTest>::make(); + EXPECT_OK(proc.rootIface->nestMe(nastyNester, 10)); + + wp<IBinder> weak = nastyNester; + nastyNester = nullptr; + EXPECT_EQ(nullptr, weak.promote()); +} + +TEST_P(BinderRpc, SameBinderEquality) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> a; + EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a)); + + sp<IBinder> b; + EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b)); + + EXPECT_EQ(a, b); +} + +TEST_P(BinderRpc, SameBinderEqualityWeak) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinder> a; + EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&a)); + wp<IBinder> weak = a; + a = nullptr; + + sp<IBinder> b; + EXPECT_OK(proc.rootIface->alwaysGiveMeTheSameBinder(&b)); + + // this is the wrong behavior, since BpBinder + // doesn't implement onIncStrongAttempted + // but make sure there is no crash + EXPECT_EQ(nullptr, weak.promote()); + + GTEST_SKIP() << "Weak binders aren't currently re-promotable for RPC binder."; + + // In order to fix this: + // - need to have incStrongAttempted reflected across IPC boundary (wait for + // response to promote - round trip...) + // - sendOnLastWeakRef, to delete entries out of RpcState table + EXPECT_EQ(b, weak.promote()); +} + +#define expectSessions(expected, iface) \ + do { \ + int session; \ + EXPECT_OK((iface)->getNumOpenSessions(&session)); \ + EXPECT_EQ(expected, session); \ + } while (false) + +TEST_P(BinderRpc, SingleSession) { + auto proc = createRpcTestSocketServerProcess({}); + + sp<IBinderRpcSession> session; + EXPECT_OK(proc.rootIface->openSession("aoeu", &session)); + std::string out; + EXPECT_OK(session->getName(&out)); + EXPECT_EQ("aoeu", out); + + expectSessions(1, proc.rootIface); + session = nullptr; + expectSessions(0, proc.rootIface); +} + +TEST_P(BinderRpc, ManySessions) { + auto proc = createRpcTestSocketServerProcess({}); + + std::vector<sp<IBinderRpcSession>> sessions; + + for (size_t i = 0; i < 15; i++) { + expectSessions(i, proc.rootIface); + sp<IBinderRpcSession> session; + EXPECT_OK(proc.rootIface->openSession(std::to_string(i), &session)); + sessions.push_back(session); + } + expectSessions(sessions.size(), proc.rootIface); + for (size_t i = 0; i < sessions.size(); i++) { + std::string out; + EXPECT_OK(sessions.at(i)->getName(&out)); + EXPECT_EQ(std::to_string(i), out); + } + expectSessions(sessions.size(), proc.rootIface); + + while (!sessions.empty()) { + sessions.pop_back(); + expectSessions(sessions.size(), proc.rootIface); + } + expectSessions(0, proc.rootIface); +} + +TEST_P(BinderRpc, OnewayCallDoesNotWait) { + constexpr size_t kReallyLongTimeMs = 100; + constexpr size_t kSleepMs = kReallyLongTimeMs * 5; + + auto proc = createRpcTestSocketServerProcess({}); + + size_t epochMsBefore = epochMillis(); + + EXPECT_OK(proc.rootIface->sleepMsAsync(kSleepMs)); + + size_t epochMsAfter = epochMillis(); + EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); +} + +TEST_P(BinderRpc, Callbacks) { + const static std::string kTestString = "good afternoon!"; + + for (bool callIsOneway : {true, false}) { + for (bool callbackIsOneway : {true, false}) { + for (bool delayed : {true, false}) { + if (clientOrServerSingleThreaded() && + (callIsOneway || callbackIsOneway || delayed)) { + // we have no incoming connections to receive the callback + continue; + } + + size_t numIncomingConnections = clientOrServerSingleThreaded() ? 0 : 1; + auto proc = createRpcTestSocketServerProcess( + {.numThreads = 1, + .numSessions = 1, + .numIncomingConnections = numIncomingConnections}); + auto cb = sp<MyBinderRpcCallback>::make(); + + if (callIsOneway) { + EXPECT_OK(proc.rootIface->doCallbackAsync(cb, callbackIsOneway, delayed, + kTestString)); + } else { + EXPECT_OK( + proc.rootIface->doCallback(cb, callbackIsOneway, delayed, kTestString)); + } + + // if both transactions are synchronous and the response is sent back on the + // same thread, everything should have happened in a nested call. Otherwise, + // the callback will be processed on another thread. + if (callIsOneway || callbackIsOneway || delayed) { + using std::literals::chrono_literals::operator""s; + RpcMutexUniqueLock _l(cb->mMutex); + cb->mCv.wait_for(_l, 1s, [&] { return !cb->mValues.empty(); }); + } + + EXPECT_EQ(cb->mValues.size(), 1) + << "callIsOneway: " << callIsOneway + << " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed; + if (cb->mValues.empty()) continue; + EXPECT_EQ(cb->mValues.at(0), kTestString) + << "callIsOneway: " << callIsOneway + << " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed; + + // since we are severing the connection, we need to go ahead and + // tell the server to shutdown and exit so that waitpid won't hang + if (auto status = proc.rootIface->scheduleShutdown(); !status.isOk()) { + EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status; + } + + // since this session has an incoming connection w/ a threadpool, we + // need to manually shut it down + EXPECT_TRUE(proc.proc->sessions.at(0).session->shutdownAndWait(true)); + proc.expectAlreadyShutdown = true; + } + } + } +} + +TEST_P(BinderRpc, OnewayCallbackWithNoThread) { + auto proc = createRpcTestSocketServerProcess({}); + auto cb = sp<MyBinderRpcCallback>::make(); + + Status status = proc.rootIface->doCallback(cb, true /*oneway*/, false /*delayed*/, "anything"); + EXPECT_EQ(WOULD_BLOCK, status.transactionError()); +} + +TEST_P(BinderRpc, AidlDelegatorTest) { + auto proc = createRpcTestSocketServerProcess({}); + auto myDelegator = sp<IBinderRpcTestDelegator>::make(proc.rootIface); + ASSERT_NE(nullptr, myDelegator); + + std::string doubled; + EXPECT_OK(myDelegator->doubleString("cool ", &doubled)); + EXPECT_EQ("cool cool ", doubled); +} + +} // namespace android |