/* * Copyright 2021 Google LLC * * 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 "encoder.h" #include #include #include #include namespace dist_proc { namespace aggregation { namespace encoding { namespace { //////////////////////////////////////////////////////////////////////////////// // ------------------------ Tests for AppendToString ------------------------ // struct EncodedTupleParam { int64_t input; const char* encoding; uint8_t encoding_length; }; class EncodingCorrectnessTest : public ::testing::TestWithParam {}; TEST_P(EncodingCorrectnessTest, CorrectEncoding) { EncodedTupleParam params = GetParam(); std::string s; Encoder::AppendToString(params.input, &s); std::string_view expected(params.encoding, params.encoding_length); EXPECT_EQ(expected, s); EXPECT_EQ(params.encoding_length, s.length()); } TEST_P(EncodingCorrectnessTest, CorrectAppendedEncoding) { EncodedTupleParam params = GetParam(); std::string_view suffix(params.encoding, params.encoding_length); std::string with_prefix("thisisaprefix"); Encoder::AppendToString(params.input, &with_prefix); EXPECT_EQ(with_prefix.length(), params.encoding_length + strlen("thisisaprefix")); EXPECT_EQ("thisisaprefix", with_prefix.substr(0, strlen("thisisaprefix"))); EXPECT_EQ(suffix, with_prefix.substr(strlen("thisisaprefix"))); } const EncodedTupleParam cases[] = { {0x0LL, "\0", 1}, {0x1LL, "\x1\0", 1}, {0xALL, "\xA\0", 1}, {0x80LL, "\x80\x01", 2}, {0x4000LL, "\x80\x80\x01", 3}, {0x200000LL, "\x80\x80\x80\x01", 4}, {0x10000000LL, "\x80\x80\x80\x80\x01", 5}, {0xFFFFFFFFLL, "\xFF\xFF\xFF\xFF\x0F", 5}, {0x03FFFFFFFFLL, "\xFF\xFF\xFF\xFF\x3F", 5}, {0x800000000LL, "\x80\x80\x80\x80\x80\x01", 6}, {0x40000000000LL, "\x80\x80\x80\x80\x80\x80\x01", 7}, {0x2000000000000LL, "\x80\x80\x80\x80\x80\x80\x80\x01", 8}, {0x100000000000000LL, "\x80\x80\x80\x80\x80\x80\x80\x80\x01", 9}, {-0x01LL, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x01", 10}, {std::numeric_limits::min(), "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x1", 10}, {std::numeric_limits::max(), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 9}}; INSTANTIATE_TEST_SUITE_P(EncodingCorrectnessTestCases, EncodingCorrectnessTest, ::testing::ValuesIn(cases)); //////////////////////////////////////////////////////////////////////////////// // ------------------ Tests for SerializeToPackedStringAll ------------------ // struct PackedEncodingTupleParam { std::vector values; const char* encoding; uint8_t encoding_length; }; class PackedSerializationTest : public ::testing::TestWithParam {}; TEST_P(PackedSerializationTest, CorrectPackedEncoding) { PackedEncodingTupleParam params = GetParam(); std::string packed; Encoder::SerializeToPackedStringAll(params.values.begin(), params.values.end(), &packed); std::string_view expected(params.encoding, params.encoding_length); EXPECT_EQ(packed, expected); EXPECT_EQ(packed.length(), params.encoding_length); } const PackedEncodingTupleParam packedCases[] = { {{}, "", 0}, // Encoding one item should be identical to AppendToString. {{0x0LL}, "\0", 1}, {{0x1LL}, "\x1\0", 1}, {{0x80LL}, "\x80\x01", 2}, {{0x200000LL}, "\x80\x80\x80\x01", 4}, {{0x10000000LL}, "\x80\x80\x80\x80\x01", 5}, {{0x03FFFFFFFFLL}, "\xFF\xFF\xFF\xFF\x3F", 5}, // Combining items from above. {{0x1LL, 0x80LL}, "\x1\x80\x1", 3}, {{0x200000LL, 0x03FFFFFFFFLL}, "\x80\x80\x80\x1\xFF\xFF\xFF\xFF?", 9}, {{0x1LL, 0x80LL, 0x200000LL, 0x03FFFFFFFFLL}, "\x1\x80\x1\x80\x80\x80\x1\xFF\xFF\xFF\xFF?", 12}, // Multiple items. {{1, 0xdeadbeef, 0x0aaabbbbccccddddL, 5}, "\x1\xEF\xFD\xB6\xF5\r\xDD\xBB\xB3\xE6\xBC\xF7\xAE\xD5\n\x5", 16}, {{1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB}, "\x1\x2\x3\x4\x5\x6\a\b\t\n\v", 11}}; INSTANTIATE_TEST_SUITE_P(PackedSerializationTestCases, PackedSerializationTest, ::testing::ValuesIn(packedCases)); TEST(EncoderTest, SerializeToPackedStringAllClearsPrepopulatedString) { std::string empty; std::string prepopulated = "some leftovers"; std::vector v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB}; Encoder::SerializeToPackedStringAll(v.begin(), v.end(), &empty); Encoder::SerializeToPackedStringAll(v.begin(), v.end(), &prepopulated); EXPECT_EQ(prepopulated, "\x1\x2\x3\x4\x5\x6\a\b\t\n\v"); EXPECT_EQ(empty, prepopulated); } } // namespace } // namespace encoding } // namespace aggregation } // namespace dist_proc