chromium/third_party/perfetto/src/tracing/service/trace_buffer_unittest.cc

/*
 * Copyright (C) 2017 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 <string.h>

#include <initializer_list>
#include <random>
#include <sstream>
#include <vector>

#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/basic_types.h"
#include "perfetto/ext/tracing/core/client_identity.h"
#include "perfetto/ext/tracing/core/shared_memory_abi.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/protozero/proto_utils.h"
#include "src/base/test/vm_test_utils.h"
#include "src/tracing/service/trace_buffer.h"
#include "src/tracing/test/fake_packet.h"
#include "test/gtest_and_gmock.h"

namespace perfetto {

ContainerEq;
ElementsAre;
IsEmpty;

class TraceBufferTest : public testing::Test {};

// ----------------------
// Main TraceBuffer tests
// ----------------------

// Note for the test code: remember that the resulting size of a chunk is:
// SUM(packets) + 16 (that is sizeof(ChunkRecord)).
// Also remember that chunks are rounded up to 16. So, unless we are testing the
// rounding logic, might be a good idea to create chunks of that size.

TEST_F(TraceBufferTest, ReadWrite_EmptyBuffer) {}

// On each iteration writes a fixed-size chunk and reads it back.
TEST_F(TraceBufferTest, ReadWrite_Simple) {}

TEST_F(TraceBufferTest, ReadWrite_OneChunkPerWriter) {}

// Writes chunk that up filling the buffer precisely until the end, like this:
// [ c0: 512 ][ c1: 512 ][ c2: 1024 ][ c3: 2048 ]
// | ---------------- 4k buffer --------------- |
TEST_F(TraceBufferTest, ReadWrite_FillTillEnd) {}

// Similar to the above, but this time leaves some gap at the end and then
// tries to add a chunk that doesn't fit to exercise the padding-at-end logic.
// Initial condition:
// [ c0: 128 ][ c1: 256 ][ c2: 512   ][ c3: 1024 ][ c4: 2048 ]{ 128 padding }
// | ------------------------------- 4k buffer ------------------------------ |
//
// At this point we try to insert a 512 Bytes chunk (c5). The result should be:
// [ c5: 512              ]{ padding }[c3: 1024 ][ c4: 2048 ]{ 128 padding }
// | ------------------------------- 4k buffer ------------------------------ |
TEST_F(TraceBufferTest, ReadWrite_Padding) {}

// Like ReadWrite_Padding, but this time the padding introduced is the minimum
// allowed (16 bytes). This is to exercise edge cases in the padding logic.
// [c0: 2048               ][c1: 1024         ][c2: 1008       ][c3: 16]
// [c4: 2032            ][c5: 1040                ][c6 :16][c7: 1080   ]
TEST_F(TraceBufferTest, ReadWrite_MinimalPadding) {}

TEST_F(TraceBufferTest, ReadWrite_RandomChunksNoWrapping) {}

// Tests the case of writing a chunk that leaves just sizeof(ChunkRecord) at
// the end of the buffer.
TEST_F(TraceBufferTest, ReadWrite_WrappingCases) {}

// Tests that when records are removed when adding padding at the end because
// there is no space left. The scenario is the following:
// Initial condition: [ c0: 2048 ][ c1: 2048 ]
// 2nd iteration:     [ c2: 2048] <-- write pointer is here
// At this point we try to add a 3072 bytes chunk. It won't fit because the
// space left till the end is just 2048 bytes. At this point we expect that a
// padding record is added in place of c1, and c1 is removed from the index.
// Final situation:   [ c3: 3072     ][ PAD ]
TEST_F(TraceBufferTest, ReadWrite_PaddingAtEndUpdatesIndex) {}

// Similar to ReadWrite_PaddingAtEndUpdatesIndex but makes it so that the
// various chunks don't perfectly align when wrapping.
TEST_F(TraceBufferTest, ReadWrite_PaddingAtEndUpdatesIndexMisaligned) {}

// Verify that empty packets are skipped.
TEST_F(TraceBufferTest, ReadWrite_EmptyPacket) {}

// --------------------------------------
// Fragments stitching and skipping logic
// --------------------------------------

TEST_F(TraceBufferTest, Fragments_Simple) {}

TEST_F(TraceBufferTest, Fragments_EdgeCases) {}

// The following tests verify that chunks received out-of-order are read in the
// correct order.
//
// Fragment order {0,2,1} for sequence {1,1}, without fragmenting packets.
TEST_F(TraceBufferTest, Fragments_OutOfOrderLastChunkIsMiddle) {}

// Fragment order {0,2,1} for sequence {1,1}, with fragmenting packets.
TEST_F(TraceBufferTest, Fragments_OutOfOrderLastChunkIsMiddleFragmentation) {}

// Fragment order {0,2,1,3} for sequence {1,1}, with fragmenting packets. Also
// verifies that another sequence isn't broken.
TEST_F(TraceBufferTest, Fragments_OutOfOrderLastChunkIsMaxFragmentation) {}

// Fragment order {-2,1,-1,0} for sequence {1,1}, without fragmenting packets.
TEST_F(TraceBufferTest, Fragments_OutOfOrderWithIdOverflowADCB) {}

// Fragment order {-2,0,-1,1} for sequence {1,1}, without fragmenting packets.
TEST_F(TraceBufferTest, Fragments_OutOfOrderWithIdOverflowACBD) {}

TEST_F(TraceBufferTest, Fragments_EmptyChunkBefore) {}

TEST_F(TraceBufferTest, Fragments_EmptyChunkAfter) {}

// Set up a fragmented packet that happens to also have an empty chunk in the
// middle of the sequence. Test that it just gets skipped.
TEST_F(TraceBufferTest, Fragments_EmptyChunkInTheMiddle) {}

// Generates sequences of fragmented packets of increasing length (|seq_len|),
// from [P0, P1a][P1y] to [P0, P1a][P1b][P1c]...[P1y]. Test that they are always
// read as one packet.
TEST_F(TraceBufferTest, Fragments_LongPackets) {}

// Similar to Fragments_LongPacket, but covers also the case of ChunkID wrapping
// over its max value.
TEST_F(TraceBufferTest, Fragments_LongPacketWithWrappingID) {}

TEST_F(TraceBufferTest, Fragments_PreserveUID) {}

TEST_F(TraceBufferTest, Fragments_DiscardedOnPacketSizeDropPacket) {}

TEST_F(TraceBufferTest, Fragments_IncompleteChunkNeedsPatching) {}

// --------------------------
// Out of band patching tests
// --------------------------

TEST_F(TraceBufferTest, Patching_Simple) {}

TEST_F(TraceBufferTest, Patching_SkipIfChunkDoesntExist) {}

TEST_F(TraceBufferTest, Patching_AtBoundariesOfChunk) {}

// Tests kChunkNeedsPatching logic: chunks that are marked as "pending patch"
// should not be read until the patch has happened.
TEST_F(TraceBufferTest, Patching_ReadWaitsForPatchComplete) {}  // namespace perfetto

// ---------------------
// Malicious input tests
// ---------------------

TEST_F(TraceBufferTest, Malicious_ZeroSizedChunk) {}

// Attempting to write a chunk bigger than ChunkRecord::kMaxSize should end up
// in a no-op.
TEST_F(TraceBufferTest, Malicious_ChunkTooBig) {}

TEST_F(TraceBufferTest, Malicious_DeclareMorePacketsBeyondBoundaries) {}

TEST_F(TraceBufferTest, Malicious_ZeroVarintHeader) {}

// Forge a chunk where the first packet is valid but the second packet has a
// varint header that continues beyond the end of the chunk (and also beyond the
// end of the buffer).
TEST_F(TraceBufferTest, Malicious_OverflowingVarintHeader) {}

TEST_F(TraceBufferTest, Malicious_VarintHeaderTooBig) {}

// Similar to Malicious_VarintHeaderTooBig, but this time the full chunk
// contains an enormous varint number that tries to overflow.
TEST_F(TraceBufferTest, Malicious_JumboVarint) {}

// Like the Malicious_ZeroVarintHeader, but put the chunk in the middle of a
// sequence that would be otherwise valid. The zero-sized fragment should be
// skipped.
TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderInSequence) {}

// Similar to Malicious_ZeroVarintHeaderInSequence, but this time the zero-sized
// fragment is the last fragment for a chunk and is marked for continuation. The
// zero-sized fragment should be skipped.
TEST_F(TraceBufferTest, Malicious_ZeroVarintHeaderAtEndOfChunk) {}

TEST_F(TraceBufferTest, Malicious_PatchOutOfBounds) {}

TEST_F(TraceBufferTest, Malicious_OverrideWithShorterChunkSize) {}

TEST_F(TraceBufferTest, Malicious_OverrideWithShorterChunkSizeAfterRead) {}

TEST_F(TraceBufferTest, Malicious_OverrideWithDifferentOffsetAfterRead) {}

// -------------------
// SequenceIterator tests
// -------------------
TEST_F(TraceBufferTest, Iterator_OneStreamOrdered) {}

TEST_F(TraceBufferTest, Iterator_OneStreamWrapping) {}

TEST_F(TraceBufferTest, Iterator_ManyStreamsOrdered) {}

TEST_F(TraceBufferTest, Iterator_ManyStreamsWrapping) {}

// -------------------
// Re-writing same chunk id
// -------------------

TEST_F(TraceBufferTest, Override_ReCommitBeforeRead) {}

TEST_F(TraceBufferTest, Override_ReCommitAfterPartialRead) {}

TEST_F(TraceBufferTest, Override_ReCommitAfterFullRead) {}

// See also the Malicious_Override* tests above.
TEST_F(TraceBufferTest, Override_ReCommitInvalid) {}

TEST_F(TraceBufferTest, Override_ReCommitReordered) {}

TEST_F(TraceBufferTest, Override_ReCommitReorderedFragmenting) {}

TEST_F(TraceBufferTest, Override_ReCommitSameBeforeRead) {}

TEST_F(TraceBufferTest, Override_ReCommitSameAfterRead) {}

TEST_F(TraceBufferTest, Override_ReCommitIncompleteAfterReadOutOfOrder) {}

TEST_F(TraceBufferTest, Override_ReCommitIncompleteFragmenting) {}

TEST_F(TraceBufferTest, Override_EndOfBuffer) {}

TEST_F(TraceBufferTest, DiscardPolicy) {}

TEST_F(TraceBufferTest, MissingPacketsOnSequence) {}

TEST_F(TraceBufferTest, Clone_NoFragments) {}

TEST_F(TraceBufferTest, Clone_FragmentsOutOfOrder) {}

TEST_F(TraceBufferTest, Clone_WithPatches) {}

TEST_F(TraceBufferTest, Clone_Wrapping) {}

TEST_F(TraceBufferTest, Clone_WrappingWithPadding) {}

TEST_F(TraceBufferTest, Clone_CommitOnlyUsedSize) {}

}  // namespace perfetto