1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "logging/rtc_event_log/encoder/blob_encoding.h"
12
13 #include <string>
14 #include <vector>
15
16 #include "logging/rtc_event_log/encoder/var_int.h"
17 #include "rtc_base/checks.h"
18 #include "test/gtest.h"
19
20 using CharT = std::string::value_type;
21
22 namespace webrtc {
23
24 namespace {
25
TestEncodingAndDecoding(const std::vector<std::string> & blobs)26 void TestEncodingAndDecoding(const std::vector<std::string>& blobs) {
27 RTC_DCHECK(!blobs.empty());
28
29 const std::string encoded = EncodeBlobs(blobs);
30 ASSERT_FALSE(encoded.empty());
31
32 const std::vector<absl::string_view> decoded =
33 DecodeBlobs(encoded, blobs.size());
34
35 ASSERT_EQ(decoded.size(), blobs.size());
36 for (size_t i = 0; i < decoded.size(); ++i) {
37 ASSERT_EQ(decoded[i], blobs[i]);
38 }
39 }
40
TestGracefulErrorHandling(absl::string_view encoded_blobs,size_t num_of_blobs)41 void TestGracefulErrorHandling(absl::string_view encoded_blobs,
42 size_t num_of_blobs) {
43 const std::vector<absl::string_view> decoded =
44 DecodeBlobs(encoded_blobs, num_of_blobs);
45 EXPECT_TRUE(decoded.empty());
46 }
47
48 } // namespace
49
TEST(BlobEncoding,EmptyBlob)50 TEST(BlobEncoding, EmptyBlob) {
51 TestEncodingAndDecoding({""});
52 }
53
TEST(BlobEncoding,SingleCharacterBlob)54 TEST(BlobEncoding, SingleCharacterBlob) {
55 TestEncodingAndDecoding({"a"});
56 }
57
TEST(BlobEncoding,LongBlob)58 TEST(BlobEncoding, LongBlob) {
59 std::string blob = "";
60 for (size_t i = 0; i < 100000; ++i) {
61 blob += std::to_string(i + 1) + " Mississippi\n";
62 }
63 TestEncodingAndDecoding({blob});
64 }
65
TEST(BlobEncoding,BlobsOfVariousLengths)66 TEST(BlobEncoding, BlobsOfVariousLengths) {
67 constexpr size_t kJump = 0xf032d; // Arbitrary.
68 constexpr size_t kMax = 0xffffff; // Arbitrary.
69
70 std::string blob;
71 blob.reserve(kMax);
72
73 for (size_t i = 0; i < kMax; i += kJump) {
74 blob.append(kJump, 'x');
75 TestEncodingAndDecoding({blob});
76 }
77 }
78
TEST(BlobEncoding,MultipleBlobs)79 TEST(BlobEncoding, MultipleBlobs) {
80 std::vector<std::string> blobs;
81 for (size_t i = 0; i < 100000; ++i) {
82 blobs.push_back(std::to_string(i + 1) + " Mississippi\n");
83 }
84 TestEncodingAndDecoding(blobs);
85 }
86
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyEmptyInput)87 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyEmptyInput) {
88 TestGracefulErrorHandling("", 1);
89 }
90
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyZeroBlobs)91 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyZeroBlobs) {
92 const std::string encoded = EncodeBlobs({"a"});
93 ASSERT_FALSE(encoded.empty());
94 TestGracefulErrorHandling(encoded, 0);
95 }
96
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyBlobLengthTooSmall)97 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyBlobLengthTooSmall) {
98 std::string encoded = EncodeBlobs({"ab"});
99 ASSERT_FALSE(encoded.empty());
100 ASSERT_EQ(encoded[0], 0x02);
101 encoded[0] = 0x01;
102 TestGracefulErrorHandling(encoded, 1);
103 }
104
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyBlobLengthTooLarge)105 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyBlobLengthTooLarge) {
106 std::string encoded = EncodeBlobs({"a"});
107 ASSERT_FALSE(encoded.empty());
108 ASSERT_EQ(encoded[0], 0x01);
109 encoded[0] = 0x02;
110 TestGracefulErrorHandling(encoded, 1);
111 }
112
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyNumberOfBlobsIncorrectlyHigh)113 TEST(BlobEncoding,
114 DecodeBlobsHandlesErrorsGracefullyNumberOfBlobsIncorrectlyHigh) {
115 const std::vector<std::string> blobs = {"a", "b"};
116 const std::string encoded = EncodeBlobs(blobs);
117 // Test focus - two empty strings encoded, but DecodeBlobs() told way more
118 // blobs are in the strings than could be expected.
119 TestGracefulErrorHandling(encoded, 1000);
120
121 // Test sanity - show that DecodeBlobs() would have worked if it got the
122 // correct input.
123 TestEncodingAndDecoding(blobs);
124 }
125
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyDefectiveVarInt)126 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyDefectiveVarInt) {
127 std::string defective_varint;
128 for (size_t i = 0; i < kMaxVarIntLengthBytes; ++i) {
129 ASSERT_LE(kMaxVarIntLengthBytes, 0xffu);
130 defective_varint += static_cast<CharT>(static_cast<size_t>(0x80u) | i);
131 }
132 defective_varint += 0x01u;
133
134 const std::string defective_encoded = defective_varint + "whatever";
135
136 TestGracefulErrorHandling(defective_encoded, 1);
137 }
138
TEST(BlobEncoding,DecodeBlobsHandlesErrorsGracefullyLengthSumWrapAround)139 TEST(BlobEncoding, DecodeBlobsHandlesErrorsGracefullyLengthSumWrapAround) {
140 std::string max_size_varint;
141 for (size_t i = 0; i < kMaxVarIntLengthBytes - 1; ++i) {
142 max_size_varint += 0xffu;
143 }
144 max_size_varint += 0x7fu;
145
146 const std::string defective_encoded =
147 max_size_varint + max_size_varint + "whatever";
148
149 TestGracefulErrorHandling(defective_encoded, 2);
150 }
151
152 } // namespace webrtc
153