Skip to content

Commit

Permalink
Merge pull request #272 from AsherGlick/base64_tests
Browse files Browse the repository at this point in the history
Adding a couple of sanity tests and making base64 logic more readable
  • Loading branch information
AsherGlick authored Feb 4, 2024
2 parents 2649e7b + 886a0dc commit 9c27810
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 24 deletions.
50 changes: 26 additions & 24 deletions xml_converter/src/string_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,41 +144,41 @@ static const char base64_chars[] =

std::string base64_encode(uint8_t const* buf, unsigned int bufLen) {
std::string ret;
int i = 0;
int j = 0;
uint8_t char_array_3[3];
uint8_t char_array_4[4];
int input_chunk_index = 0;
int output_chunk_index = 0;
uint8_t input_chunk[3];
uint8_t output_chunk[4];

while (bufLen--) {
char_array_3[i++] = *(buf++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;

for (i = 0; (i < 4); i++) {
ret += base64_chars[char_array_4[i]];
input_chunk[input_chunk_index++] = *(buf++);
if (input_chunk_index == 3) {
output_chunk[0] = (input_chunk[0] & 0xfc) >> 2;
output_chunk[1] = ((input_chunk[0] & 0x03) << 4) + ((input_chunk[1] & 0xf0) >> 4);
output_chunk[2] = ((input_chunk[1] & 0x0f) << 2) + ((input_chunk[2] & 0xc0) >> 6);
output_chunk[3] = input_chunk[2] & 0x3f;

for (output_chunk_index = 0; output_chunk_index < 4; output_chunk_index++) {
ret += base64_chars[output_chunk[output_chunk_index]];
}
i = 0;
input_chunk_index = 0;
}
}

if (i) {
for (j = i; j < 3; j++) {
char_array_3[j] = '\0';
if (input_chunk_index > 0) {
for (output_chunk_index = input_chunk_index; output_chunk_index < 3; output_chunk_index++) {
input_chunk[output_chunk_index] = 0;
}

char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
output_chunk[0] = (input_chunk[0] & 0xfc) >> 2;
output_chunk[1] = ((input_chunk[0] & 0x03) << 4) + ((input_chunk[1] & 0xf0) >> 4);
output_chunk[2] = ((input_chunk[1] & 0x0f) << 2) + ((input_chunk[2] & 0xc0) >> 6);
output_chunk[3] = input_chunk[2] & 0x3f;

for (j = 0; (j < i + 1); j++) {
ret += base64_chars[char_array_4[j]];
for (output_chunk_index = 0; (output_chunk_index < input_chunk_index + 1); output_chunk_index++) {
ret += base64_chars[output_chunk[output_chunk_index]];
}

while (i++ < 3) {
while (input_chunk_index++ < 3) {
ret += '=';
}
}
Expand Down Expand Up @@ -239,6 +239,7 @@ std::vector<uint8_t> base64_decode(std::string const& encoded_string) {

if (char_array_4[i] == 255) {
// TODO: Throw an error or something
std::cerr << "Found an invalid letter when decoding base64" << std::endl;
return std::vector<uint8_t>();
}
}
Expand All @@ -259,6 +260,7 @@ std::vector<uint8_t> base64_decode(std::string const& encoded_string) {

if (char_array_4[i] == 255) {
// TODO: Throw an error or something
std::cerr << "Found an invalid letter when decoding base64" << std::endl;
return std::vector<uint8_t>();
}
}
Expand Down
67 changes: 67 additions & 0 deletions xml_converter/tests/test_base64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "../src/string_helper.hpp"
#include <gtest/gtest.h>

class Base64Test : public ::testing::Test {};

// Test Strip Bits

////////////////////////////////////////////////////////////////////////////////
// Test Double Strip Bits
//
// When there are `len%4 = 2` there are 4 extra bits stored in the base64 string
// This means that decoding and encoding that data will result in slightly
// different data bsecause those 4 extra bits get stripped off. This tests all
// of those different values so that we can be sure everything is happening
// deterministically.
////////////////////////////////////////////////////////////////////////////////
TEST_F(Base64Test, DoubleStripBits00) {
// These are all of the base 64 characters which start with the binary
// digits 00 and end with nonzero digits.
std::string b64_00_characters = "BCDEFGHIJKLMNOP";

for (size_t i = 0; i < b64_00_characters.size(); i++) {
std::string input = "A_";
input[1] = b64_00_characters[i];
std::vector<uint8_t> decoded_value = base64_decode(input);
std::string output = base64_encode(&decoded_value[0], decoded_value.size());
EXPECT_EQ(output, "AA==");
}
}
TEST_F(Base64Test, DoubleStripBits01) {
// These are all of the base 64 characters which start with the binary
// digits 01 and end with nonzero digits.
std::string b64_00_characters = "RSTUVWXYZabcdef";

for (size_t i = 0; i < b64_00_characters.size(); i++) {
std::string input = "A_";
input[1] = b64_00_characters[i];
std::vector<uint8_t> decoded_value = base64_decode(input);
std::string output = base64_encode(&decoded_value[0], decoded_value.size());
EXPECT_EQ(output, "AQ==");
}
}
TEST_F(Base64Test, DoubleStripBits10) {
// These are all of the base 64 characters which start with the binary
// digits 10 and end with nonzero digits.
std::string b64_00_characters = "hijklmnopqrstuv";

for (size_t i = 0; i < b64_00_characters.size(); i++) {
std::string input = "A_";
input[1] = b64_00_characters[i];
std::vector<uint8_t> decoded_value = base64_decode(input);
std::string output = base64_encode(&decoded_value[0], decoded_value.size());
EXPECT_EQ(output, "Ag==");
}
}
TEST_F(Base64Test, DoubleStripBits11) {
// These are all of the base 64 characters which start with the binary
// digits 11 and end with nonzero digits.
std::string b64_00_characters = "xyz0123456789+/";
for (size_t i = 0; i < b64_00_characters.size(); i++) {
std::string input = "A_";
input[1] = b64_00_characters[i];
std::vector<uint8_t> decoded_value = base64_decode(input);
std::string output = base64_encode(&decoded_value[0], decoded_value.size());
EXPECT_EQ(output, "Aw==");
}
}

0 comments on commit 9c27810

Please sign in to comment.