Bug 1678651 - Added ProfileChunkedBuffer state tests - r=canaltinova

Differential Revision: https://phabricator.services.mozilla.com/D99975
This commit is contained in:
Gerald Squelart 2020-12-22 10:48:26 +00:00
Родитель c0e87f0baa
Коммит f11383c57a
1 изменённых файлов: 116 добавлений и 2 удалений

Просмотреть файл

@ -1313,6 +1313,16 @@ static void TestControlledChunkManagerWithLocalLimit() {
printf("TestControlledChunkManagerWithLocalLimit done\n");
}
# define VERIFY_PCB_START_END_PUSHED_CLEARED(aProfileChunkedBuffer, aStart, \
aEnd, aPushed, aCleared) \
{ \
ProfileChunkedBuffer::State state = (aProfileChunkedBuffer).GetState(); \
MOZ_RELEASE_ASSERT(state.mRangeStart == (aStart)); \
MOZ_RELEASE_ASSERT(state.mRangeEnd == (aEnd)); \
MOZ_RELEASE_ASSERT(state.mPushedBlockCount == (aPushed)); \
MOZ_RELEASE_ASSERT(state.mClearedBlockCount == (aCleared)); \
}
static void TestChunkedBuffer() {
printf("TestChunkedBuffer...\n");
@ -1325,6 +1335,8 @@ static void TestChunkedBuffer() {
MOZ_RELEASE_ASSERT(cb.BufferLength().isNothing());
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
int result = 0;
result = cb.ReserveAndPut(
[]() {
@ -1333,20 +1345,25 @@ static void TestChunkedBuffer() {
},
[](Maybe<ProfileBufferEntryWriter>& aEW) { return aEW ? 2 : 3; });
MOZ_RELEASE_ASSERT(result == 3);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
result = 0;
result = cb.Put(
1, [](Maybe<ProfileBufferEntryWriter>& aEW) { return aEW ? 1 : 2; });
MOZ_RELEASE_ASSERT(result == 2);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
blockIndex = cb.PutFrom(&result, 1);
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
blockIndex = cb.PutObjects(123, result, "hello");
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
blockIndex = cb.PutObject(123);
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
auto chunks = cb.GetAllChunks();
static_assert(std::is_same_v<decltype(chunks), UniquePtr<ProfileBufferChunk>>,
@ -1380,6 +1397,7 @@ static void TestChunkedBuffer() {
constexpr ProfileChunkedBuffer::Length chunkMinSize = 128;
ProfileBufferChunkManagerWithLocalLimit cm(bufferMaxSize, chunkMinSize);
cb.SetChunkManager(cm);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
// Let the chunk manager fulfill the initial request for an extra chunk.
cm.FulfillChunkRequests();
@ -1387,6 +1405,7 @@ static void TestChunkedBuffer() {
MOZ_RELEASE_ASSERT(cm.MaxTotalSize() == bufferMaxSize);
MOZ_RELEASE_ASSERT(cb.BufferLength().isSome());
MOZ_RELEASE_ASSERT(*cb.BufferLength() == bufferMaxSize);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1, 1, 0, 0);
// Write an int with the main `ReserveAndPut` function.
const int test = 123;
@ -1408,6 +1427,8 @@ static void TestChunkedBuffer() {
MOZ_RELEASE_ASSERT(ran);
MOZ_RELEASE_ASSERT(success);
MOZ_RELEASE_ASSERT(blockIndex.ConvertToProfileBufferIndex() == 1);
VERIFY_PCB_START_END_PUSHED_CLEARED(
cb, 1, 1 + ULEB128Size(sizeof(test)) + sizeof(test), 1, 0);
ran = false;
result = 0;
@ -1504,6 +1525,10 @@ static void TestChunkedBuffer() {
MOZ_RELEASE_ASSERT(result == 6);
MOZ_RELEASE_ASSERT(read == 1);
// No changes after reads.
VERIFY_PCB_START_END_PUSHED_CLEARED(
cb, 1, 1 + ULEB128Size(sizeof(test)) + sizeof(test), 1, 0);
// Steal the underlying ProfileBufferChunks from the ProfileChunkedBuffer.
chunks = cb.GetAllChunks();
MOZ_RELEASE_ASSERT(!!chunks, "Expected at least one chunk");
@ -1515,6 +1540,10 @@ static void TestChunkedBuffer() {
MOZ_RELEASE_ASSERT(chunks->OffsetFirstBlock() == 0);
MOZ_RELEASE_ASSERT(chunks->OffsetPastLastBlock() == 1 + sizeof(test));
// GetAllChunks() should have advanced the index one full chunk forward.
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1 + chunkActualSize,
1 + chunkActualSize, 1, 0);
// Nothing more to read from the now-empty ProfileChunkedBuffer.
cb.ReadEach([](ProfileBufferEntryReader&) { MOZ_RELEASE_ASSERT(false); });
cb.ReadEach([](ProfileBufferEntryReader&, ProfileBufferBlockIndex) {
@ -1541,6 +1570,10 @@ static void TestChunkedBuffer() {
});
MOZ_RELEASE_ASSERT(read == 1);
// No changes after reads.
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, 1 + chunkActualSize,
1 + chunkActualSize, 1, 0);
// Write lots of numbers (by memcpy), which should trigger Chunk destructions.
ProfileBufferBlockIndex firstBlockIndex;
MOZ_RELEASE_ASSERT(!firstBlockIndex);
@ -1558,6 +1591,16 @@ static void TestChunkedBuffer() {
lastBlockIndex = blockIndex;
}
ProfileChunkedBuffer::State stateAfterPuts = cb.GetState();
ProfileBufferIndex startAfterPuts = stateAfterPuts.mRangeStart;
MOZ_RELEASE_ASSERT(startAfterPuts > 1 + chunkActualSize);
ProfileBufferIndex endAfterPuts = stateAfterPuts.mRangeEnd;
MOZ_RELEASE_ASSERT(endAfterPuts > startAfterPuts);
uint64_t pushedAfterPuts = stateAfterPuts.mPushedBlockCount;
MOZ_RELEASE_ASSERT(pushedAfterPuts > 0);
uint64_t clearedAfterPuts = stateAfterPuts.mClearedBlockCount;
MOZ_RELEASE_ASSERT(clearedAfterPuts > 0);
// Read extant numbers, which should at least follow each other.
read = 0;
size_t i = 0;
@ -1630,6 +1673,10 @@ static void TestChunkedBuffer() {
} while (blockIndex);
MOZ_RELEASE_ASSERT(read > 1);
// No changes after reads.
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterPuts, endAfterPuts,
pushedAfterPuts, clearedAfterPuts);
# ifdef DEBUG
// cb.Dump();
# endif
@ -1640,6 +1687,14 @@ static void TestChunkedBuffer() {
// cb.Dump();
# endif
ProfileChunkedBuffer::State stateAfterClear = cb.GetState();
ProfileBufferIndex startAfterClear = stateAfterClear.mRangeStart;
MOZ_RELEASE_ASSERT(startAfterClear > startAfterPuts);
ProfileBufferIndex endAfterClear = stateAfterClear.mRangeEnd;
MOZ_RELEASE_ASSERT(endAfterClear == startAfterClear);
MOZ_RELEASE_ASSERT(stateAfterClear.mPushedBlockCount == 0);
MOZ_RELEASE_ASSERT(stateAfterClear.mClearedBlockCount == 0);
// Start writer threads.
constexpr int ThreadCount = 32;
std::thread threads[ThreadCount];
@ -1679,9 +1734,25 @@ static void TestChunkedBuffer() {
// cb.Dump();
# endif
ProfileChunkedBuffer::State stateAfterMTPuts = cb.GetState();
ProfileBufferIndex startAfterMTPuts = stateAfterMTPuts.mRangeStart;
MOZ_RELEASE_ASSERT(startAfterMTPuts > startAfterClear);
ProfileBufferIndex endAfterMTPuts = stateAfterMTPuts.mRangeEnd;
MOZ_RELEASE_ASSERT(endAfterMTPuts > startAfterMTPuts);
MOZ_RELEASE_ASSERT(stateAfterMTPuts.mPushedBlockCount > 0);
MOZ_RELEASE_ASSERT(stateAfterMTPuts.mClearedBlockCount > 0);
// Reset to out-of-session.
cb.ResetChunkManager();
ProfileChunkedBuffer::State stateAfterReset = cb.GetState();
ProfileBufferIndex startAfterReset = stateAfterReset.mRangeStart;
MOZ_RELEASE_ASSERT(startAfterReset == endAfterMTPuts);
ProfileBufferIndex endAfterReset = stateAfterReset.mRangeEnd;
MOZ_RELEASE_ASSERT(endAfterReset == startAfterReset);
MOZ_RELEASE_ASSERT(stateAfterReset.mPushedBlockCount == 0);
MOZ_RELEASE_ASSERT(stateAfterReset.mClearedBlockCount == 0);
success = cb.ReserveAndPut(
[]() {
MOZ_RELEASE_ASSERT(false);
@ -1689,30 +1760,38 @@ static void TestChunkedBuffer() {
},
[](Maybe<ProfileBufferEntryWriter>& aEW) { return !!aEW; });
MOZ_RELEASE_ASSERT(!success);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
success =
cb.Put(1, [](Maybe<ProfileBufferEntryWriter>& aEW) { return !!aEW; });
MOZ_RELEASE_ASSERT(!success);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
blockIndex = cb.PutFrom(&success, 1);
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
blockIndex = cb.PutObjects(123, success, "hello");
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
blockIndex = cb.PutObject(123);
MOZ_RELEASE_ASSERT(!blockIndex);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
chunks = cb.GetAllChunks();
MOZ_RELEASE_ASSERT(!chunks, "Expected no chunks when out-of-session");
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
cb.ReadEach([](ProfileBufferEntryReader&) { MOZ_RELEASE_ASSERT(false); });
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
success = cb.ReadAt(nullptr, [](Maybe<ProfileBufferEntryReader>&& er) {
MOZ_RELEASE_ASSERT(er.isNothing());
return true;
});
MOZ_RELEASE_ASSERT(success);
VERIFY_PCB_START_END_PUSHED_CLEARED(cb, startAfterReset, endAfterReset, 0, 0);
printf("TestChunkedBuffer done\n");
}
@ -1732,19 +1811,41 @@ static void TestChunkedBufferSingle() {
MOZ_RELEASE_ASSERT(cbSingle.BufferLength().isSome());
MOZ_RELEASE_ASSERT(*cbSingle.BufferLength() >= chunkMinSize);
VERIFY_PCB_START_END_PUSHED_CLEARED(cbSingle, 1, 1, 0, 0);
// Write lots of numbers (as objects), which should trigger the release of our
// single Chunk.
constexpr size_t blockSize = ULEB128Size(sizeof(size_t)) + sizeof(size_t);
size_t firstIndexToFail = 0;
ProfileBufferBlockIndex lastBlockIndex;
for (size_t i = 1; i < 3 * chunkMinSize / (1 + sizeof(int)); ++i) {
ProfileBufferBlockIndex blockIndex = cbSingle.PutObject(i);
ProfileChunkedBuffer::State stateAfterReset = cbSingle.GetState();
if (blockIndex) {
MOZ_RELEASE_ASSERT(
firstIndexToFail == 0,
"We should successfully write after we have failed once");
lastBlockIndex = blockIndex;
} else if (firstIndexToFail == 0) {
firstIndexToFail = i;
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeStart == 1);
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeEnd == 1 + blockSize * i);
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeEnd ==
lastBlockIndex.ConvertToProfileBufferIndex() +
blockSize);
MOZ_RELEASE_ASSERT(stateAfterReset.mPushedBlockCount == i);
MOZ_RELEASE_ASSERT(stateAfterReset.mClearedBlockCount == 0);
} else {
if (firstIndexToFail == 0) {
firstIndexToFail = i;
}
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeStart == 1);
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeEnd ==
1 + blockSize * (firstIndexToFail - 1));
MOZ_RELEASE_ASSERT(stateAfterReset.mRangeEnd ==
lastBlockIndex.ConvertToProfileBufferIndex() +
blockSize);
MOZ_RELEASE_ASSERT(stateAfterReset.mPushedBlockCount ==
firstIndexToFail - 1);
MOZ_RELEASE_ASSERT(stateAfterReset.mClearedBlockCount == 0);
}
}
MOZ_RELEASE_ASSERT(firstIndexToFail != 0,
@ -1752,6 +1853,10 @@ static void TestChunkedBufferSingle() {
MOZ_RELEASE_ASSERT(firstIndexToFail != 1, "We shouldn't fail from the start");
MOZ_RELEASE_ASSERT(!!lastBlockIndex, "We shouldn't fail from the start");
VERIFY_PCB_START_END_PUSHED_CLEARED(cbSingle, 1,
1 + blockSize * (firstIndexToFail - 1),
firstIndexToFail - 1, 0);
// Read extant numbers, which should go from 1 to firstIndexToFail-1.
size_t read = 0;
cbSingle.ReadEach(
@ -1767,6 +1872,10 @@ static void TestChunkedBufferSingle() {
MOZ_RELEASE_ASSERT(read == firstIndexToFail - 1,
"We should have read up to before the first failure");
VERIFY_PCB_START_END_PUSHED_CLEARED(cbSingle, 1,
1 + blockSize * (firstIndexToFail - 1),
firstIndexToFail - 1, 0);
// Test AppendContent:
// Create another ProfileChunkedBuffer that will use a
// ProfileBufferChunkManagerWithLocalLimit, which will give away
@ -1780,6 +1889,7 @@ static void TestChunkedBufferSingle() {
// It should start empty.
cbTarget.ReadEach(
[](ProfileBufferEntryReader&) { MOZ_RELEASE_ASSERT(false); });
VERIFY_PCB_START_END_PUSHED_CLEARED(cbTarget, 1, 1, 0, 0);
// Copy the contents from cbSingle to cbTarget.
cbTarget.AppendContents(cbSingle);
@ -1798,6 +1908,10 @@ static void TestChunkedBufferSingle() {
});
MOZ_RELEASE_ASSERT(read == firstIndexToFail - 1,
"We should have read up to before the first failure");
// The state should be the same as the source.
VERIFY_PCB_START_END_PUSHED_CLEARED(cbTarget, 1,
1 + blockSize * (firstIndexToFail - 1),
firstIndexToFail - 1, 0);
# ifdef DEBUG
// cbSingle.Dump();