blob: fbbd06412dab683e67d6b7173596ed12ae4452f0 [file] [log] [blame]
Wyatt Hepler3c2e9522020-01-09 16:08:54 -08001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_tokenizer/base64.h"
16
17#include <cstring>
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070018#include <span>
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080019#include <string_view>
20
21#include "gtest/gtest.h"
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080022
23namespace pw::tokenizer {
24namespace {
25
Wyatt Hepler67368872020-07-30 16:55:38 -070026using std::byte;
27
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080028class PrefixedBase64 : public ::testing::Test {
29 protected:
Wyatt Heplercdafbb42020-10-05 11:51:05 -070030 static constexpr char kUnset = '#';
31
32 PrefixedBase64() {
33 std::memset(binary_, kUnset, sizeof(binary_));
34 std::memset(base64_, kUnset, sizeof(base64_));
35 }
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080036
Wyatt Hepler67368872020-07-30 16:55:38 -070037 byte binary_[32];
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080038 char base64_[32];
39};
40
41const struct TestData {
42 template <size_t kSize>
Armando Montanez888370d2020-05-01 18:29:22 -070043 TestData(const char (&binary_data)[kSize], const char* base64_data)
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070044 : binary{std::as_bytes(std::span(binary_data, kSize - 1))},
45 base64(base64_data) {}
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080046
Wyatt Hepler67368872020-07-30 16:55:38 -070047 std::span<const byte> binary;
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080048 std::string_view base64;
49} kTestData[] = {
50 {"", "$"},
51 {"\x00", "$AA=="},
52 {"\x71", "$cQ=="},
53 {"\xff", "$/w=="},
54 {"\x63\xa9", "$Y6k="},
55 {"\x69\x89\x03", "$aYkD"},
56 {"\x80\xf5\xc8\xd4", "$gPXI1A=="},
57 {"\x6e\xb8\x91\x3f\xac", "$briRP6w="},
58 {"\x1f\x88\x91\xbb\xd7\x10", "$H4iRu9cQ"},
59 {"\xac\xcf\xb2\xd5\xee\xa2\x8e", "$rM+y1e6ijg=="},
60 {"\xff\x15\x25\x7e\x7b\xc9\x7b\x60", "$/xUlfnvJe2A="},
61 {"\xd5\xab\xd9\xa6\xae\xaa\x33\x9f\x66", "$1avZpq6qM59m"},
62 {"\x6b\xfd\x95\xc5\x4a\xc7\xc2\x39\x45\xdc", "$a/2VxUrHwjlF3A=="},
63 {"\x4c\xde\xee\xb8\x68\x0d\x9c\x66\x3e\xea\x46", "$TN7uuGgNnGY+6kY="},
64};
65
66TEST_F(PrefixedBase64, Encode) {
Wyatt Heplera46bf7d2020-01-08 18:10:25 -080067 for (auto& [binary, base64] : kTestData) {
68 EXPECT_EQ(base64.size(), PrefixedBase64Encode(binary, base64_));
69 ASSERT_EQ(base64, base64_);
Wyatt Heplercdafbb42020-10-05 11:51:05 -070070 EXPECT_EQ('\0', base64_[base64.size()]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080071 }
72}
73
74TEST_F(PrefixedBase64, Encode_EmptyInput_WritesPrefix) {
Wyatt Hepler67368872020-07-30 16:55:38 -070075 EXPECT_EQ(1u, PrefixedBase64Encode(std::span<byte>(), base64_));
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080076 EXPECT_EQ('$', base64_[0]);
Wyatt Hepler9eb16952020-10-09 17:36:27 -070077 EXPECT_EQ('\0', base64_[1]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080078}
79
80TEST_F(PrefixedBase64, Encode_EmptyOutput_WritesNothing) {
Wyatt Heplere2cbadf2020-06-22 11:21:45 -070081 EXPECT_EQ(0u,
82 PrefixedBase64Encode(kTestData[5].binary, std::span(base64_, 0)));
Wyatt Heplercdafbb42020-10-05 11:51:05 -070083 EXPECT_EQ(kUnset, base64_[0]);
84}
85
86TEST_F(PrefixedBase64, Encode_SingleByteOutput_OnlyNullTerminates) {
87 EXPECT_EQ(0u,
88 PrefixedBase64Encode(kTestData[5].binary, std::span(base64_, 1)));
Wyatt Hepler3c2e9522020-01-09 16:08:54 -080089 EXPECT_EQ('\0', base64_[0]);
Wyatt Heplercdafbb42020-10-05 11:51:05 -070090 EXPECT_EQ(kUnset, base64_[1]);
91}
92
93TEST_F(PrefixedBase64, Encode_NoRoomForNullAfterMessage_OnlyNullTerminates) {
94 EXPECT_EQ(
95 0u,
96 PrefixedBase64Encode(kTestData[5].binary,
97 std::span(base64_, kTestData[5].base64.size())));
98 EXPECT_EQ('\0', base64_[0]);
99 EXPECT_EQ(kUnset, base64_[1]);
100}
101
102TEST_F(PrefixedBase64, EncodeToVector_EmptyInput_WritesPrefix) {
103 auto buffer = PrefixedBase64Encode(std::span<byte>());
104 ASSERT_EQ(1u, buffer.size());
105 EXPECT_EQ('$', buffer[0]);
106 EXPECT_EQ('\0', buffer[1]);
107}
108
109TEST_F(PrefixedBase64, EncodeToVector_Successful) {
110 auto buffer = PrefixedBase64Encode(kTestData[5].binary);
111 ASSERT_EQ(buffer.size(), kTestData[5].base64.size());
112 EXPECT_EQ(
113 0, std::memcmp(buffer.data(), kTestData[5].base64.data(), buffer.size()));
114 EXPECT_EQ('\0', buffer[buffer.size()]);
115}
116
117TEST_F(PrefixedBase64, EncodeToVector_VectorTooSmall_OnlyNullTerminates) {
Wyatt Hepler9eb16952020-10-09 17:36:27 -0700118 constexpr byte big[Base64EncodedBufferSize(
Wyatt Heplercdafbb42020-10-05 11:51:05 -0700119 PW_TOKENIZER_CFG_ENCODING_BUFFER_SIZE_BYTES + 1)] = {};
120
121 auto buffer = PrefixedBase64Encode(big);
122 ASSERT_EQ(0u, buffer.size());
123 EXPECT_EQ('\0', buffer[0]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800124}
125
Wyatt Hepler9eb16952020-10-09 17:36:27 -0700126TEST_F(PrefixedBase64, Base64EncodedBufferSize_Empty_RoomForPrefixAndNull) {
127 EXPECT_EQ(2u, Base64EncodedBufferSize(0));
128}
129
130TEST_F(PrefixedBase64, Base64EncodedBufferSize_PositiveSizes) {
131 for (unsigned i = 1; i <= 3; ++i) {
132 EXPECT_EQ(6u, Base64EncodedBufferSize(i));
133 }
134 for (unsigned i = 4; i <= 6; ++i) {
135 EXPECT_EQ(10u, Base64EncodedBufferSize(i));
136 }
137}
138
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800139TEST_F(PrefixedBase64, Decode) {
Wyatt Heplera46bf7d2020-01-08 18:10:25 -0800140 for (auto& [binary, base64] : kTestData) {
141 EXPECT_EQ(binary.size(), PrefixedBase64Decode(base64, binary_));
142 ASSERT_EQ(0, std::memcmp(binary.data(), binary_, binary.size()));
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800143 }
144}
145
146TEST_F(PrefixedBase64, Decode_EmptyInput_WritesNothing) {
147 EXPECT_EQ(0u, PrefixedBase64Decode({}, binary_));
Wyatt Heplercdafbb42020-10-05 11:51:05 -0700148 EXPECT_EQ(byte{kUnset}, binary_[0]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800149}
150
151TEST_F(PrefixedBase64, Decode_OnlyPrefix_WritesNothing) {
152 EXPECT_EQ(0u, PrefixedBase64Decode("$", binary_));
Wyatt Heplercdafbb42020-10-05 11:51:05 -0700153 EXPECT_EQ(byte{kUnset}, binary_[0]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800154}
155
156TEST_F(PrefixedBase64, Decode_EmptyOutput_WritesNothing) {
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700157 EXPECT_EQ(0u,
158 PrefixedBase64Decode(kTestData[5].base64, std::span(binary_, 0)));
Wyatt Heplercdafbb42020-10-05 11:51:05 -0700159 EXPECT_EQ(byte{kUnset}, binary_[0]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800160}
161
162TEST_F(PrefixedBase64, Decode_OutputTooSmall_WritesNothing) {
163 auto& item = kTestData[5];
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700164 EXPECT_EQ(0u,
165 PrefixedBase64Decode(item.base64,
166 std::span(binary_, item.binary.size() - 1)));
Wyatt Heplercdafbb42020-10-05 11:51:05 -0700167 EXPECT_EQ(byte{kUnset}, binary_[0]);
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800168}
169
170TEST(PrefixedBase64, DecodeInPlace) {
Wyatt Hepler67368872020-07-30 16:55:38 -0700171 byte buffer[32];
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800172
Wyatt Heplera46bf7d2020-01-08 18:10:25 -0800173 for (auto& [binary, base64] : kTestData) {
174 std::memcpy(buffer, base64.data(), base64.size());
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800175
Wyatt Heplera46bf7d2020-01-08 18:10:25 -0800176 EXPECT_EQ(binary.size(),
Wyatt Heplere2cbadf2020-06-22 11:21:45 -0700177 PrefixedBase64DecodeInPlace(std::span(buffer, base64.size())));
Wyatt Heplera46bf7d2020-01-08 18:10:25 -0800178 ASSERT_EQ(0, std::memcmp(binary.data(), buffer, binary.size()));
Wyatt Hepler3c2e9522020-01-09 16:08:54 -0800179 }
180}
181
182} // namespace
183} // namespace pw::tokenizer