Skip to content

Commit 3f11c43

Browse files
devinmoore-googGerrit Code Review
authored andcommitted
Merge "Add simple AccessorProvider case to binderAllocationLimits" into main
2 parents 92af73a + b616049 commit 3f11c43

1 file changed

Lines changed: 118 additions & 4 deletions

File tree

libs/binder/tests/binderAllocationLimits.cpp

Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,33 @@
2222
#include <binder/RpcServer.h>
2323
#include <binder/RpcSession.h>
2424
#include <cutils/trace.h>
25+
#include <gtest/gtest-spi.h>
2526
#include <gtest/gtest.h>
2627
#include <utils/CallStack.h>
2728

2829
#include <malloc.h>
30+
#include <atomic>
2931
#include <functional>
32+
#include <numeric>
3033
#include <vector>
3134

3235
using namespace android::binder::impl;
3336

3437
static android::String8 gEmpty(""); // make sure first allocation from optimization runs
3538

39+
struct State {
40+
State(std::vector<size_t>&& expectedMallocs) : expectedMallocs(std::move(expectedMallocs)) {}
41+
~State() {
42+
size_t num = numMallocs.load();
43+
if (expectedMallocs.size() != num) {
44+
ADD_FAILURE() << "Expected " << expectedMallocs.size() << " allocations, but got "
45+
<< num;
46+
}
47+
}
48+
const std::vector<size_t> expectedMallocs;
49+
std::atomic<size_t> numMallocs;
50+
};
51+
3652
struct DestructionAction {
3753
DestructionAction(std::function<void()> f) : mF(std::move(f)) {}
3854
~DestructionAction() { mF(); };
@@ -95,8 +111,7 @@ namespace LambdaHooks {
95111

96112
// Action to execute when malloc is hit. Supports nesting. Malloc is not
97113
// restricted when the allocation hook is being processed.
98-
__attribute__((warn_unused_result))
99-
DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
114+
__attribute__((warn_unused_result)) DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
100115
MallocHooks before = MallocHooks::save();
101116
LambdaHooks::lambdas.emplace_back(std::move(f));
102117
LambdaHooks::lambda_malloc_hooks.overwrite();
@@ -106,6 +121,22 @@ DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
106121
});
107122
}
108123

124+
DestructionAction setExpectedMallocs(std::vector<size_t>&& expected) {
125+
auto state = std::make_shared<State>(std::move(expected));
126+
return OnMalloc([state = state](size_t bytes) {
127+
size_t num = state->numMallocs.fetch_add(1);
128+
if (num >= state->expectedMallocs.size() || state->expectedMallocs[num] != bytes) {
129+
ADD_FAILURE() << "Unexpected allocation number " << num << " of size " << bytes
130+
<< " bytes" << std::endl
131+
<< android::CallStack::stackToString("UNEXPECTED ALLOCATION",
132+
android::CallStack::getCurrent(
133+
4 /*ignoreDepth*/)
134+
.get())
135+
<< std::endl;
136+
}
137+
});
138+
}
139+
109140
// exported symbol, to force compiler not to optimize away pointers we set here
110141
const void* imaginary_use;
111142

@@ -119,16 +150,53 @@ TEST(TestTheTest, OnMalloc) {
119150

120151
imaginary_use = new int[10];
121152
}
153+
delete[] reinterpret_cast<const int*>(imaginary_use);
122154
EXPECT_EQ(mallocs, 1u);
123155
}
124156

157+
TEST(TestTheTest, OnMallocWithExpectedMallocs) {
158+
std::vector<size_t> expectedMallocs = {
159+
4,
160+
16,
161+
8,
162+
};
163+
{
164+
const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
165+
imaginary_use = new int32_t[1];
166+
delete[] reinterpret_cast<const int*>(imaginary_use);
167+
imaginary_use = new int32_t[4];
168+
delete[] reinterpret_cast<const int*>(imaginary_use);
169+
imaginary_use = new int32_t[2];
170+
delete[] reinterpret_cast<const int*>(imaginary_use);
171+
}
172+
}
173+
174+
TEST(TestTheTest, OnMallocWithExpectedMallocsWrongSize) {
175+
std::vector<size_t> expectedMallocs = {
176+
4,
177+
16,
178+
100000,
179+
};
180+
EXPECT_NONFATAL_FAILURE(
181+
{
182+
const auto on_malloc = setExpectedMallocs(std::move(expectedMallocs));
183+
imaginary_use = new int32_t[1];
184+
delete[] reinterpret_cast<const int*>(imaginary_use);
185+
imaginary_use = new int32_t[4];
186+
delete[] reinterpret_cast<const int*>(imaginary_use);
187+
imaginary_use = new int32_t[2];
188+
delete[] reinterpret_cast<const int*>(imaginary_use);
189+
},
190+
"Unexpected allocation number 2 of size 8 bytes");
191+
}
125192

126193
__attribute__((warn_unused_result))
127194
DestructionAction ScopeDisallowMalloc() {
128195
return OnMalloc([&](size_t bytes) {
129-
ADD_FAILURE() << "Unexpected allocation: " << bytes;
196+
FAIL() << "Unexpected allocation: " << bytes;
130197
using android::CallStack;
131-
std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION", CallStack::getCurrent(4 /*ignoreDepth*/).get())
198+
std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION",
199+
CallStack::getCurrent(4 /*ignoreDepth*/).get())
132200
<< std::endl;
133201
});
134202
}
@@ -224,6 +292,51 @@ TEST(BinderAllocation, SmallTransaction) {
224292
EXPECT_EQ(mallocs, 1u);
225293
}
226294

295+
TEST(BinderAccessorAllocation, AddAccessorCheckService) {
296+
// Need to call defaultServiceManager() before checking malloc because it
297+
// will allocate an instance in the call_once
298+
const auto sm = defaultServiceManager();
299+
const std::string kInstanceName1 = "foo.bar.IFoo/default";
300+
const std::string kInstanceName2 = "foo.bar.IFoo2/default";
301+
const String16 kInstanceName16(kInstanceName1.c_str());
302+
std::vector<size_t> expectedMallocs = {
303+
// addAccessorProvider
304+
112, // new AccessorProvider
305+
16, // new AccessorProviderEntry
306+
// checkService
307+
45, // String8 from String16 in CppShim::checkService
308+
128, // writeInterfaceToken
309+
16, // getInjectedAccessor, new AccessorProviderEntry
310+
66, // getInjectedAccessor, String16
311+
45, // String8 from String16 in AccessorProvider::provide
312+
};
313+
std::set<std::string> supportedInstances = {kInstanceName1, kInstanceName2};
314+
auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
315+
316+
auto receipt =
317+
android::addAccessorProvider(std::move(supportedInstances),
318+
[&](const String16&) -> sp<IBinder> { return nullptr; });
319+
EXPECT_FALSE(receipt.expired());
320+
321+
sp<IBinder> binder = sm->checkService(kInstanceName16);
322+
323+
status_t status = android::removeAccessorProvider(receipt);
324+
}
325+
326+
TEST(BinderAccessorAllocation, AddAccessorEmpty) {
327+
std::vector<size_t> expectedMallocs = {
328+
48, // From ALOGE with empty set of instances
329+
};
330+
std::set<std::string> supportedInstances = {};
331+
auto onMalloc = setExpectedMallocs(std::move(expectedMallocs));
332+
333+
auto receipt =
334+
android::addAccessorProvider(std::move(supportedInstances),
335+
[&](const String16&) -> sp<IBinder> { return nullptr; });
336+
337+
EXPECT_TRUE(receipt.expired());
338+
}
339+
227340
TEST(RpcBinderAllocation, SetupRpcServer) {
228341
std::string tmp = getenv("TMPDIR") ?: "/tmp";
229342
std::string addr = tmp + "/binderRpcBenchmark";
@@ -255,6 +368,7 @@ TEST(RpcBinderAllocation, SetupRpcServer) {
255368
}
256369

257370
int main(int argc, char** argv) {
371+
LOG(INFO) << "Priming static log variables for binderAllocationLimits.";
258372
if (getenv("LIBC_HOOKS_ENABLE") == nullptr) {
259373
CHECK(0 == setenv("LIBC_HOOKS_ENABLE", "1", true /*overwrite*/));
260374
execv(argv[0], argv);

0 commit comments

Comments
 (0)