/* * 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 "src/ipc/buffered_frame_deserializer.h" #include <algorithm> #include <string> #include "perfetto/base/logging.h" #include "perfetto/ext/base/utils.h" #include "test/gtest_and_gmock.h" #include "protos/perfetto/ipc/wire_protocol.gen.h" namespace perfetto { namespace ipc { namespace { constexpr uint32_t kHeaderSize = …; // Generates a parsable Frame of exactly |size| bytes (including header). std::vector<char> GetSimpleFrame(size_t size) { … } void CheckedMemcpy(BufferedFrameDeserializer::ReceiveBuffer rbuf, const std::vector<char>& encoded_frame, size_t offset = 0) { … } bool FrameEq(std::vector<char> expected_frame_with_header, const Frame& frame) { … } // Tests the simple case where each recv() just returns one whole header+frame. TEST(BufferedFrameDeserializerTest, WholeMessages) { … } // Sends first a simple test frame. Then creates a realistic Frame fragmenting // it in three chunks and tests that the decoded Frame matches the original one. // The recv() sequence is as follows: // 1. [ simple_frame ] [ frame_chunk1 ... ] // 2. [ ... frame_chunk2 ... ] // 3. [ ... frame_chunk3 ] TEST(BufferedFrameDeserializerTest, FragmentedFrameIsCorrectlyDeserialized) { … } // Tests the case of a EndReceive(0) while receiving a valid frame in chunks. TEST(BufferedFrameDeserializerTest, ZeroSizedReceive) { … } // Tests the case of a EndReceive(4) where the header has no payload. The frame // should be just skipped and not returned by PopNextFrame(). TEST(BufferedFrameDeserializerTest, EmptyPayload) { … } // Test the case where a single Receive() returns batches of > 1 whole frames. // See case C in the comments for BufferedFrameDeserializer::EndReceive(). TEST(BufferedFrameDeserializerTest, MultipleFramesInOneReceive) { … } TEST(BufferedFrameDeserializerTest, RejectVeryLargeFrames) { … } // Tests the extreme case of recv() fragmentation. Two valid frames are received // but each recv() puts one byte at a time. Covers cases A and B commented in // BufferedFrameDeserializer::EndReceive(). TEST(BufferedFrameDeserializerTest, HighlyFragmentedFrames) { … } // A bunch of valid frames interleaved with frames that have a valid header // but unparsable payload. The expectation is that PopNextFrame() returns // nullptr for the unparsable frames but the other frames are decoded peroperly. TEST(BufferedFrameDeserializerTest, CanRecoverAfterUnparsableFrames) { … } // Test that we can sustain recvs() which constantly max out the capacity. // It sets up four frames: // |frame1|: small, 1024 + 4 bytes. // |frame2|: as big as the |kMaxCapacity|. Its recv() is split into two chunks. // |frame3|: together with the 2nd part of |frame2| it maxes out capacity again. // |frame4|: as big as the |kMaxCapacity|. Received in one recv(), no splits. // // Which are then recv()'d in a loop in the following way. // |------------ max recv capacity ------------| // 1. [ frame1 ] [ frame2_chunk1 ..... ] // 2. [ ... frame2_chunk2 ] // 3. [ frame3 ] // 4. [ frame 4 ] TEST(BufferedFrameDeserializerTest, FillCapacity) { … } } // namespace } // namespace ipc } // namespace perfetto