From d11f41b62e32430b71a97be5afb3e3bf7bda1cd9 Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Fri, 9 Mar 2018 17:00:12 -0500 Subject: [PATCH 1/9] Initial commit adding unittests for base64 --- test/Makefile | 5 ++++- test/base64_unittest.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 test/base64_unittest.cc diff --git a/test/Makefile b/test/Makefile index efb58a36..89b3f6ae 100644 --- a/test/Makefile +++ b/test/Makefile @@ -21,7 +21,8 @@ TEST_DIR=. TEST_SOURCES=$(wildcard $(TEST_DIR)/*_unittest.cc) TEST_OBJS=$(TEST_SOURCES:$(TEST_DIR)/%.cc=%.o) TESTS=\ - format_unittest + format_unittest\ + base64_unittest GTEST_LIB=gtest_lib.a @@ -63,5 +64,7 @@ $(GTEST_LIB): gtest-all.o gtest_main.o format_unittest: $(GTEST_LIB) format_unittest.o $(SRC_DIR)/format.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ +base64_unittest: $(GTEST_LIB) base64_unittest.o $(SRC_DIR)/base64.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ .PHONY: all test clean purge diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc new file mode 100644 index 00000000..34a421e5 --- /dev/null +++ b/test/base64_unittest.cc @@ -0,0 +1,38 @@ +#include "../src/base64.h" +#include "gtest/gtest.h" + +namespace { + +TEST(EncodeTest, EmptyEncode) { + const std::string empty_str(""); + EXPECT_EQ( + "", + base64::Encode(empty_str) + ); +} + +TEST(EncodeTest, SimpleEncode) { + const std::string simple_str("tes"); + EXPECT_EQ( + "dGVz", + base64::Encode(simple_str) + ); +} + +TEST(EncodeTest, NoPaddingEncode) { + const std::string simple_str("test0"); + EXPECT_EQ( + "dGVzdDA", + base64::Encode(simple_str) + ); +} + +TEST(EncodeTest, NoDoublePaddingEncode) { + const std::string simple_str("test"); + EXPECT_EQ( + "dGVzdA", + base64::Encode(simple_str) + ); +} + +} // namespace From a671f168556787858733723edbdacdfeff375710 Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Fri, 9 Mar 2018 18:22:48 -0500 Subject: [PATCH 2/9] Comment decode out of header file for clarity --- src/base64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base64.h b/src/base64.h index 0f2b076d..f512b20e 100644 --- a/src/base64.h +++ b/src/base64.h @@ -22,7 +22,7 @@ namespace base64 { std::string Encode(const std::string &source); -std::string Decode(const std::string &source); +//std::string Decode(const std::string &source); } From 9d8bb62fa22e3170d4f2e2250e49b89697370b51 Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Mon, 12 Mar 2018 09:40:50 -0400 Subject: [PATCH 3/9] Update base64 tests and Makefile based on PR 71 --- test/Makefile | 2 +- test/base64_unittest.cc | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/test/Makefile b/test/Makefile index 89b3f6ae..5b33fc2a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -21,7 +21,7 @@ TEST_DIR=. TEST_SOURCES=$(wildcard $(TEST_DIR)/*_unittest.cc) TEST_OBJS=$(TEST_SOURCES:$(TEST_DIR)/%.cc=%.o) TESTS=\ - format_unittest\ + format_unittest \ base64_unittest GTEST_LIB=gtest_lib.a diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index 34a421e5..0d8dbcc2 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -4,34 +4,32 @@ namespace { TEST(EncodeTest, EmptyEncode) { - const std::string empty_str(""); EXPECT_EQ( "", - base64::Encode(empty_str) + base64::Encode("") ); } TEST(EncodeTest, SimpleEncode) { - const std::string simple_str("tes"); EXPECT_EQ( "dGVz", - base64::Encode(simple_str) + base64::Encode("tes") ); } +//Base64 encodings typically pad messages to ensure output length % 4 == 0, our +//implementation does not TEST(EncodeTest, NoPaddingEncode) { - const std::string simple_str("test0"); EXPECT_EQ( "dGVzdDA", - base64::Encode(simple_str) + base64::Encode("test0") ); } TEST(EncodeTest, NoDoublePaddingEncode) { - const std::string simple_str("test"); EXPECT_EQ( "dGVzdA", - base64::Encode(simple_str) + base64::Encode("test") ); } From bda699509b91693fbe829bd00ffa522120b99ff1 Mon Sep 17 00:00:00 2001 From: Igor Peshansky Date: Sat, 10 Mar 2018 15:40:32 -0500 Subject: [PATCH 4/9] Fix bug in alternate base64::Encode implementation; enable base64::Decode. --- src/base64.cc | 41 ++++++++++++++++++++++------------------- src/base64.h | 2 +- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/base64.cc b/src/base64.cc index f54ddaed..fe8fbbae 100644 --- a/src/base64.cc +++ b/src/base64.cc @@ -16,6 +16,8 @@ #include "base64.h" +#include + namespace base64 { namespace { @@ -27,21 +29,23 @@ constexpr const unsigned char base64url_chars[] = std::string Encode(const std::string &source) { std::string result; #if 0 - const std::size_t remainder = source.size() % 3; + const std::size_t remainder = (source.size() - 1) % 3; for (std::size_t i = 0; i < source.size(); i += 3) { + const bool one_more = i < source.size() - 3 || remainder > 0; + const bool two_more = i < source.size() - 3 || remainder > 1; const unsigned char c0 = source[i]; - const unsigned char c1 = remainder > 0 ? source[i + 1] : 0u; - const unsigned char c2 = remainder > 1 ? source[i + 2] : 0u; + const unsigned char c1 = one_more ? source[i + 1] : 0u; + const unsigned char c2 = two_more ? source[i + 2] : 0u; result.push_back(base64url_chars[0x3f & c0 >> 2]); - result.push_back(base64url_chars[0x3f & c0 << 4 | c1 >> 4]); - if (remainder > 0) { - result.push_back(base64url_chars[0x3f & c1 << 2 | c2 >> 6]); + result.push_back(base64url_chars[(0x3f & c0 << 4) | c1 >> 4]); + if (one_more) { + result.push_back(base64url_chars[(0x3f & c1 << 2) | c2 >> 6]); } - if (remainder > 1) { + if (two_more) { result.push_back(base64url_chars[0x3f & c2]); } } -#endif +#else unsigned int code_buffer = 0; int code_buffer_size = -6; for (unsigned char c : source) { @@ -57,30 +61,29 @@ std::string Encode(const std::string &source) { code_buffer_size += 8; result.push_back(base64url_chars[(code_buffer >> code_buffer_size) & 0x3f]); } +#endif // No padding needed. return result; } -#if 0 std::string Decode(const std::string &source) { std::string result; - std::vector T(256,-1); - for (int i=0; i<64; i++) T[base64url_chars[i]] = i; + std::vector T(256, -1); + for (int i = 0; i < 64; i++) T[base64url_chars[i]] = i; - int val=0, valb=-8; - for (uchar c : source) { + int val = 0, shift = -8; + for (char c : source) { if (T[c] == -1) break; - val = (val<<6) + T[c]; - valb += 6; - if (valb>=0) { - result.push_back(char((val>>valb)&0xFF)); - valb-=8; + val = (val << 6) + T[c]; + shift += 6; + if (shift >= 0) { + result.push_back(char((val >> shift) & 0xFF)); + shift -= 8; } } return result; } -#endif } diff --git a/src/base64.h b/src/base64.h index f512b20e..0f2b076d 100644 --- a/src/base64.h +++ b/src/base64.h @@ -22,7 +22,7 @@ namespace base64 { std::string Encode(const std::string &source); -//std::string Decode(const std::string &source); +std::string Decode(const std::string &source); } From 58b786f1da50b1bd5d45b03dbc95925a8c8ada5a Mon Sep 17 00:00:00 2001 From: Igor Peshansky Date: Sun, 11 Mar 2018 21:54:30 -0400 Subject: [PATCH 5/9] Add base64 round-trip tests. --- test/base64_unittest.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index 0d8dbcc2..f8b1948f 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -33,4 +33,16 @@ TEST(EncodeTest, NoDoublePaddingEncode) { ); } +TEST(RoundTripTest, FullString) { + EXPECT_EQ("tes", base64::Decode(base64::Encode("tes"))); +} + +TEST(RoundTripTest, OnePhantom) { + EXPECT_EQ("test0", base64::Decode(base64::Encode("test0"))); +} + +TEST(RoundTripTest, TwoPhantoms) { + EXPECT_EQ("test", base64::Decode(base64::Encode("test"))); +} + } // namespace From 8217506025e67a3f7d139260d62d2b9af4a18b3a Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Mon, 12 Mar 2018 13:15:23 -0400 Subject: [PATCH 6/9] Address further comments on PR 71 --- test/base64_unittest.cc | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index f8b1948f..e579d5ce 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -4,33 +4,23 @@ namespace { TEST(EncodeTest, EmptyEncode) { - EXPECT_EQ( - "", - base64::Encode("") - ); + EXPECT_EQ("", base64::Encode("")); } TEST(EncodeTest, SimpleEncode) { - EXPECT_EQ( - "dGVz", - base64::Encode("tes") - ); + EXPECT_EQ("dGVz", base64::Encode("tes")); } -//Base64 encodings typically pad messages to ensure output length % 4 == 0, our -//implementation does not -TEST(EncodeTest, NoPaddingEncode) { - EXPECT_EQ( - "dGVzdDA", - base64::Encode("test0") - ); +// Base64 encoders typically pad messages to ensure output length % 4 == 0. To +// acheive this, encoders will pad messages with either one or two "=". Our +// implementation does not do this. The following two tests ensure that +// base64::Encode does not append one or two "=". +TEST(EncodeTest, OnePhantom) { + EXPECT_EQ("dGVzdDA", base64::Encode("test0")); } -TEST(EncodeTest, NoDoublePaddingEncode) { - EXPECT_EQ( - "dGVzdA", - base64::Encode("test") - ); +TEST(EncodeTest, TwoPhantom) { + EXPECT_EQ("dGVzdA", base64::Encode("test")); } TEST(RoundTripTest, FullString) { From e50cd9ed635202f3c6771c2f734483c209f2cd1e Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Mon, 12 Mar 2018 13:24:40 -0400 Subject: [PATCH 7/9] Added further testing for base64::Decode --- test/base64_unittest.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index e579d5ce..3f0573fe 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -23,6 +23,30 @@ TEST(EncodeTest, TwoPhantom) { EXPECT_EQ("dGVzdA", base64::Encode("test")); } +TEST(DecodeTest, EmptyDecode) { + EXPECT_EQ("", base64::Decode("")); +} + +TEST(DecodeTest, SimpleDecode) { + EXPECT_EQ("tes", base64::Decode("dGVz")); +} + +TEST(DecodeTest, OnePadding) { + EXPECT_EQ("test0", base64::Decode("dGVzdDA=")); +} + +TEST(DecodeTest, OnePhantom) { + EXPECT_EQ("test0", base64::Decode("dGVzdDA")); +} + +TEST(DecodeTest, TwoPadding) { + EXPECT_EQ("test", base64::Decode("dGVzdA==")); +} + +TEST(DecodeTest, TwoPhantom) { + EXPECT_EQ("test", base64::Decode("dGVzdA")); +} + TEST(RoundTripTest, FullString) { EXPECT_EQ("tes", base64::Decode(base64::Encode("tes"))); } From 2e04d0e397a731818e1969ed2837572e12867995 Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Mon, 12 Mar 2018 16:13:09 -0400 Subject: [PATCH 8/9] One space after periods. Removed whitespace to reflect surrounding style --- test/base64_unittest.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index 3f0573fe..69d31279 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -12,8 +12,8 @@ TEST(EncodeTest, SimpleEncode) { } // Base64 encoders typically pad messages to ensure output length % 4 == 0. To -// acheive this, encoders will pad messages with either one or two "=". Our -// implementation does not do this. The following two tests ensure that +// acheive this, encoders will pad messages with either one or two "=". Our +// implementation does not do this. The following two tests ensure that // base64::Encode does not append one or two "=". TEST(EncodeTest, OnePhantom) { EXPECT_EQ("dGVzdDA", base64::Encode("test0")); @@ -58,5 +58,4 @@ TEST(RoundTripTest, OnePhantom) { TEST(RoundTripTest, TwoPhantoms) { EXPECT_EQ("test", base64::Decode(base64::Encode("test"))); } - } // namespace From 893b6f838fe975f8bb3bc1a045bfeb28396bafcb Mon Sep 17 00:00:00 2001 From: Andrew Emil Date: Mon, 12 Mar 2018 20:00:36 -0400 Subject: [PATCH 9/9] Spelling error --- test/base64_unittest.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index 69d31279..57f331d2 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -12,7 +12,7 @@ TEST(EncodeTest, SimpleEncode) { } // Base64 encoders typically pad messages to ensure output length % 4 == 0. To -// acheive this, encoders will pad messages with either one or two "=". Our +// achieve this, encoders will pad messages with either one or two "=". Our // implementation does not do this. The following two tests ensure that // base64::Encode does not append one or two "=". TEST(EncodeTest, OnePhantom) {