1 /*
2 * Copyright 2021 Google LLC
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "encoder.h"
17
18 #include <cstdint>
19 #include <limits>
20 #include <string>
21
22 #include <gtest/gtest.h>
23
24 namespace dist_proc {
25 namespace aggregation {
26 namespace encoding {
27
28 namespace {
29
30 ////////////////////////////////////////////////////////////////////////////////
31 // ------------------------ Tests for AppendToString ------------------------ //
32
33 struct EncodedTupleParam {
34 int64_t input;
35 const char* encoding;
36 uint8_t encoding_length;
37 };
38
39 class EncodingCorrectnessTest : public ::testing::TestWithParam<EncodedTupleParam> {};
40
TEST_P(EncodingCorrectnessTest,CorrectEncoding)41 TEST_P(EncodingCorrectnessTest, CorrectEncoding) {
42 EncodedTupleParam params = GetParam();
43 std::string s;
44 Encoder::AppendToString(params.input, &s);
45
46 std::string_view expected(params.encoding, params.encoding_length);
47 EXPECT_EQ(expected, s);
48 EXPECT_EQ(params.encoding_length, s.length());
49 }
50
TEST_P(EncodingCorrectnessTest,CorrectAppendedEncoding)51 TEST_P(EncodingCorrectnessTest, CorrectAppendedEncoding) {
52 EncodedTupleParam params = GetParam();
53 std::string_view suffix(params.encoding, params.encoding_length);
54 std::string with_prefix("thisisaprefix");
55
56 Encoder::AppendToString(params.input, &with_prefix);
57 EXPECT_EQ(with_prefix.length(), params.encoding_length + strlen("thisisaprefix"));
58 EXPECT_EQ("thisisaprefix", with_prefix.substr(0, strlen("thisisaprefix")));
59 EXPECT_EQ(suffix, with_prefix.substr(strlen("thisisaprefix")));
60 }
61
62 const EncodedTupleParam cases[] = {
63 {0x0LL, "\0", 1},
64 {0x1LL, "\x1\0", 1},
65 {0xALL, "\xA\0", 1},
66 {0x80LL, "\x80\x01", 2},
67 {0x4000LL, "\x80\x80\x01", 3},
68 {0x200000LL, "\x80\x80\x80\x01", 4},
69 {0x10000000LL, "\x80\x80\x80\x80\x01", 5},
70 {0xFFFFFFFFLL, "\xFF\xFF\xFF\xFF\x0F", 5},
71 {0x03FFFFFFFFLL, "\xFF\xFF\xFF\xFF\x3F", 5},
72 {0x800000000LL, "\x80\x80\x80\x80\x80\x01", 6},
73 {0x40000000000LL, "\x80\x80\x80\x80\x80\x80\x01", 7},
74 {0x2000000000000LL, "\x80\x80\x80\x80\x80\x80\x80\x01", 8},
75 {0x100000000000000LL, "\x80\x80\x80\x80\x80\x80\x80\x80\x01", 9},
76 {-0x01LL, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01", 10},
77 {std::numeric_limits<int64_t>::min(), "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x1", 10},
78 {std::numeric_limits<int64_t>::max(), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 9}};
79
80 INSTANTIATE_TEST_SUITE_P(EncodingCorrectnessTestCases, EncodingCorrectnessTest,
81 ::testing::ValuesIn(cases));
82
83 ////////////////////////////////////////////////////////////////////////////////
84 // ------------------ Tests for SerializeToPackedStringAll ------------------ //
85
86 struct PackedEncodingTupleParam {
87 std::vector<int64_t> values;
88 const char* encoding;
89 uint8_t encoding_length;
90 };
91
92 class PackedSerializationTest : public ::testing::TestWithParam<PackedEncodingTupleParam> {};
93
TEST_P(PackedSerializationTest,CorrectPackedEncoding)94 TEST_P(PackedSerializationTest, CorrectPackedEncoding) {
95 PackedEncodingTupleParam params = GetParam();
96 std::string packed;
97
98 Encoder::SerializeToPackedStringAll(params.values.begin(), params.values.end(), &packed);
99 std::string_view expected(params.encoding, params.encoding_length);
100 EXPECT_EQ(packed, expected);
101 EXPECT_EQ(packed.length(), params.encoding_length);
102 }
103
104 const PackedEncodingTupleParam packedCases[] = {
105 {{}, "", 0},
106 // Encoding one item should be identical to AppendToString.
107 {{0x0LL}, "\0", 1},
108 {{0x1LL}, "\x1\0", 1},
109 {{0x80LL}, "\x80\x01", 2},
110 {{0x200000LL}, "\x80\x80\x80\x01", 4},
111 {{0x10000000LL}, "\x80\x80\x80\x80\x01", 5},
112 {{0x03FFFFFFFFLL}, "\xFF\xFF\xFF\xFF\x3F", 5},
113 // Combining items from above.
114 {{0x1LL, 0x80LL}, "\x1\x80\x1", 3},
115 {{0x200000LL, 0x03FFFFFFFFLL}, "\x80\x80\x80\x1\xFF\xFF\xFF\xFF?", 9},
116 {{0x1LL, 0x80LL, 0x200000LL, 0x03FFFFFFFFLL},
117 "\x1\x80\x1\x80\x80\x80\x1\xFF\xFF\xFF\xFF?",
118 12},
119 // Multiple items.
120 {{1, 0xdeadbeef, 0x0aaabbbbccccddddL, 5},
121 "\x1\xEF\xFD\xB6\xF5\r\xDD\xBB\xB3\xE6\xBC\xF7\xAE\xD5\n\x5",
122 16},
123 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB}, "\x1\x2\x3\x4\x5\x6\a\b\t\n\v", 11}};
124
125 INSTANTIATE_TEST_SUITE_P(PackedSerializationTestCases, PackedSerializationTest,
126 ::testing::ValuesIn(packedCases));
127
TEST(EncoderTest,SerializeToPackedStringAllClearsPrepopulatedString)128 TEST(EncoderTest, SerializeToPackedStringAllClearsPrepopulatedString) {
129 std::string empty;
130 std::string prepopulated = "some leftovers";
131 std::vector<int64_t> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB};
132 Encoder::SerializeToPackedStringAll(v.begin(), v.end(), &empty);
133 Encoder::SerializeToPackedStringAll(v.begin(), v.end(), &prepopulated);
134 EXPECT_EQ(prepopulated, "\x1\x2\x3\x4\x5\x6\a\b\t\n\v");
135
136 EXPECT_EQ(empty, prepopulated);
137 }
138
139 } // namespace
140
141 } // namespace encoding
142 } // namespace aggregation
143 } // namespace dist_proc
144