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 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 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 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 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