You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
160 lines
4.7 KiB
160 lines
4.7 KiB
// Copyright 2020 The Pigweed Authors
|
|
//
|
|
// 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
|
|
//
|
|
// https://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 "pw_tokenizer/base64.h"
|
|
|
|
#include <cstring>
|
|
#include <span>
|
|
#include <string_view>
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace pw::tokenizer {
|
|
namespace {
|
|
|
|
using std::byte;
|
|
|
|
class PrefixedBase64 : public ::testing::Test {
|
|
protected:
|
|
static constexpr char kUnset = '#';
|
|
|
|
PrefixedBase64() {
|
|
std::memset(binary_, kUnset, sizeof(binary_));
|
|
std::memset(base64_, kUnset, sizeof(base64_));
|
|
}
|
|
|
|
byte binary_[32];
|
|
char base64_[32];
|
|
};
|
|
|
|
const struct TestData {
|
|
template <size_t kSize>
|
|
TestData(const char (&binary_data)[kSize], const char* base64_data)
|
|
: binary{std::as_bytes(std::span(binary_data, kSize - 1))},
|
|
base64(base64_data) {}
|
|
|
|
std::span<const byte> binary;
|
|
std::string_view base64;
|
|
} kTestData[] = {
|
|
{"", "$"},
|
|
{"\x00", "$AA=="},
|
|
{"\x71", "$cQ=="},
|
|
{"\xff", "$/w=="},
|
|
{"\x63\xa9", "$Y6k="},
|
|
{"\x69\x89\x03", "$aYkD"},
|
|
{"\x80\xf5\xc8\xd4", "$gPXI1A=="},
|
|
{"\x6e\xb8\x91\x3f\xac", "$briRP6w="},
|
|
{"\x1f\x88\x91\xbb\xd7\x10", "$H4iRu9cQ"},
|
|
{"\xac\xcf\xb2\xd5\xee\xa2\x8e", "$rM+y1e6ijg=="},
|
|
{"\xff\x15\x25\x7e\x7b\xc9\x7b\x60", "$/xUlfnvJe2A="},
|
|
{"\xd5\xab\xd9\xa6\xae\xaa\x33\x9f\x66", "$1avZpq6qM59m"},
|
|
{"\x6b\xfd\x95\xc5\x4a\xc7\xc2\x39\x45\xdc", "$a/2VxUrHwjlF3A=="},
|
|
{"\x4c\xde\xee\xb8\x68\x0d\x9c\x66\x3e\xea\x46", "$TN7uuGgNnGY+6kY="},
|
|
};
|
|
|
|
TEST_F(PrefixedBase64, Encode) {
|
|
for (auto& [binary, base64] : kTestData) {
|
|
EXPECT_EQ(base64.size(), PrefixedBase64Encode(binary, base64_));
|
|
ASSERT_EQ(base64, base64_);
|
|
EXPECT_EQ('\0', base64_[base64.size()]);
|
|
}
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Encode_EmptyInput_WritesPrefix) {
|
|
EXPECT_EQ(1u, PrefixedBase64Encode(std::span<byte>(), base64_));
|
|
EXPECT_EQ('$', base64_[0]);
|
|
EXPECT_EQ('\0', base64_[1]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Encode_EmptyOutput_WritesNothing) {
|
|
EXPECT_EQ(0u,
|
|
PrefixedBase64Encode(kTestData[5].binary, std::span(base64_, 0)));
|
|
EXPECT_EQ(kUnset, base64_[0]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Encode_SingleByteOutput_OnlyNullTerminates) {
|
|
EXPECT_EQ(0u,
|
|
PrefixedBase64Encode(kTestData[5].binary, std::span(base64_, 1)));
|
|
EXPECT_EQ('\0', base64_[0]);
|
|
EXPECT_EQ(kUnset, base64_[1]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Encode_NoRoomForNullAfterMessage_OnlyNullTerminates) {
|
|
EXPECT_EQ(
|
|
0u,
|
|
PrefixedBase64Encode(kTestData[5].binary,
|
|
std::span(base64_, kTestData[5].base64.size())));
|
|
EXPECT_EQ('\0', base64_[0]);
|
|
EXPECT_EQ(kUnset, base64_[1]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Base64EncodedBufferSize_Empty_RoomForPrefixAndNull) {
|
|
EXPECT_EQ(2u, Base64EncodedBufferSize(0));
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Base64EncodedBufferSize_PositiveSizes) {
|
|
for (unsigned i = 1; i <= 3; ++i) {
|
|
EXPECT_EQ(6u, Base64EncodedBufferSize(i));
|
|
}
|
|
for (unsigned i = 4; i <= 6; ++i) {
|
|
EXPECT_EQ(10u, Base64EncodedBufferSize(i));
|
|
}
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Decode) {
|
|
for (auto& [binary, base64] : kTestData) {
|
|
EXPECT_EQ(binary.size(), PrefixedBase64Decode(base64, binary_));
|
|
ASSERT_EQ(0, std::memcmp(binary.data(), binary_, binary.size()));
|
|
}
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Decode_EmptyInput_WritesNothing) {
|
|
EXPECT_EQ(0u, PrefixedBase64Decode({}, binary_));
|
|
EXPECT_EQ(byte{kUnset}, binary_[0]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Decode_OnlyPrefix_WritesNothing) {
|
|
EXPECT_EQ(0u, PrefixedBase64Decode("$", binary_));
|
|
EXPECT_EQ(byte{kUnset}, binary_[0]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Decode_EmptyOutput_WritesNothing) {
|
|
EXPECT_EQ(0u,
|
|
PrefixedBase64Decode(kTestData[5].base64, std::span(binary_, 0)));
|
|
EXPECT_EQ(byte{kUnset}, binary_[0]);
|
|
}
|
|
|
|
TEST_F(PrefixedBase64, Decode_OutputTooSmall_WritesNothing) {
|
|
auto& item = kTestData[5];
|
|
EXPECT_EQ(0u,
|
|
PrefixedBase64Decode(item.base64,
|
|
std::span(binary_, item.binary.size() - 1)));
|
|
EXPECT_EQ(byte{kUnset}, binary_[0]);
|
|
}
|
|
|
|
TEST(PrefixedBase64, DecodeInPlace) {
|
|
byte buffer[32];
|
|
|
|
for (auto& [binary, base64] : kTestData) {
|
|
std::memcpy(buffer, base64.data(), base64.size());
|
|
|
|
EXPECT_EQ(binary.size(),
|
|
PrefixedBase64DecodeInPlace(std::span(buffer, base64.size())));
|
|
ASSERT_EQ(0, std::memcmp(binary.data(), buffer, binary.size()));
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace pw::tokenizer
|