• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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