Skip to content

Commit

Permalink
Base64 tests (#1242)
Browse files Browse the repository at this point in the history
I wrote independent tests for the original base64 module; this
upstreams them and fixes a few bugs that my original tests exposed
in the new base64 library.

Also fix a few bugs that I discovered when running the tests in
valgrind.
  • Loading branch information
trainman419 authored and mikepurvis committed Dec 12, 2017
1 parent 5bc9cbe commit 97bb693
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 16 deletions.
6 changes: 5 additions & 1 deletion utilities/xmlrpcpp/libb64/src/cdecode.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ int base64_decode_block(const char* code_in, const int length_in, char* plaintex
char* plainchar = plaintext_out;
char fragment;

if(length_in == 0) {
return 0;
}

*plainchar = state_in->plainchar;

switch (state_in->step)
Expand All @@ -39,7 +43,7 @@ int base64_decode_block(const char* code_in, const int length_in, char* plaintex
if (codechar == code_in+length_in)
{
state_in->step = step_a;
state_in->plainchar = *plainchar;
state_in->plainchar = 0; // no state to save; use default value
return plainchar - plaintext_out;
}
fragment = (char)base64_decode_value(*codechar++);
Expand Down
1 change: 0 additions & 1 deletion utilities/xmlrpcpp/src/XmlRpcValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,6 @@ namespace XmlRpc {
// might reserve too much, we'll shrink later
_value.asBinary = new BinaryData(base64DecodedSize(encoded_size), '\0');

std::stringstream buffer;
base64::decoder decoder;
std::size_t size = decoder.decode(&valueXml[*offset], encoded_size, &(*_value.asBinary)[0]);
_value.asBinary->resize(size);
Expand Down
4 changes: 4 additions & 0 deletions utilities/xmlrpcpp/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ if(TARGET xmlrpcvalue_base64)
target_link_libraries(xmlrpcvalue_base64 xmlrpcpp)
endif()

catkin_add_gtest(test_base64 test_base64.cpp)
target_link_libraries(test_base64 xmlrpcpp)
set_target_properties(test_base64 PROPERTIES COMPILE_FLAGS -std=c++11)

add_library(mock_socket mock_socket.cpp)

catkin_add_gtest(test_client
Expand Down
165 changes: 165 additions & 0 deletions utilities/xmlrpcpp/test/test_base64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Unit tests for XmlRpc++
*
* Copyright (C) 2017, Zoox Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Austin Hendrix <[email protected]>
*
*/

#include <b64/encode.h>
#include <b64/decode.h>

#include <gtest/gtest.h>

// Test Data for a Base64 encode/decode test
class Base64TestData {
public:
Base64TestData(std::vector<char> raw, std::string encoded)
: raw(raw), encoded(encoded) {}

std::vector<char> raw;
std::string encoded;
};

class Base64Test : public ::testing::TestWithParam<Base64TestData> {};

TEST_P(Base64Test, Encode) {
const std::vector<char> & data = GetParam().raw;

std::stringstream is;
is.write(&data[0], data.size());
std::stringstream os;
base64::encoder encoder;
encoder.encode(is, os);

std::string expected = GetParam().encoded;

EXPECT_EQ(expected, os.str());
}

TEST_P(Base64Test, Decode) {
const std::string& in = GetParam().encoded;
const int encoded_size = in.length();

// oversize our output vector (same method used by XmlRpcValue)
std::vector<char> out;
out.resize(encoded_size);

base64::decoder decoder;
const int size = decoder.decode(in.c_str(), encoded_size, &out[0]);
ASSERT_LE(0, size);
out.resize(size);

const std::vector<char> & expected = GetParam().raw;

EXPECT_EQ(expected, out);
}

INSTANTIATE_TEST_CASE_P(
Multiline,
Base64Test,
::testing::Values(
Base64TestData({0}, "AA==\n"),
Base64TestData({1, 2}, "AQI=\n"),
Base64TestData({1, 2, 3}, "AQID\n"),
Base64TestData(
// clang-format off
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
125, 126, 127, -128, -127, -126, -125, -124, -123, -122, -121,
-120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110,
-109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99,
-98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86,
-85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73,
-72, -71, -70, -69, -68, -67, -66, -65, -64, -63, -62, -61, -60,
-59, -58, -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47,
-46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34,
-33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21,
-20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7,
-6, -5, -4, -3, -2, -1},
// clang-format on
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMD"
"EyMzQ1\nNjc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYG"
"FiY2RlZmdoaWpr\nbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJ"
"GSk5SVlpeYmZqbnJ2en6Ch\noqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wM"
"HCw8TFxsfIycrLzM3Oz9DR0tPU1dbX\n2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8P"
"Hy8/T19vf4+fr7/P3+/w==\n")));

class Base64ErrorData {
public:
// TODO(future work): add error code representation here and check that error
// codes are reported correctly.
Base64ErrorData(std::string encoded)
: encoded(encoded) {}

std::string encoded;
};

class Base64ErrorTest : public ::testing::TestWithParam<Base64ErrorData> {};

TEST_P(Base64ErrorTest, DecodeErrors) {
const std::string& in = GetParam().encoded;
const int encoded_size = in.length();

// oversize our output vector (same method used by XmlRpcValue)
std::vector<char> out;
out.resize(encoded_size);

base64::decoder decoder;
const int size = decoder.decode(in.c_str(), encoded_size, &out[0]);
// Assert that size is greater or equal to 0, to make sure that the follow-up
// resize will always succeed.
ASSERT_LE(0, size);
out.resize(size);

// FIXME(future work): decode does not report error on garbage input
}

INSTANTIATE_TEST_CASE_P(
Multiline,
Base64ErrorTest,
::testing::Values(// Tests on incomplete data.
Base64ErrorData("="),
Base64ErrorData("A="),
Base64ErrorData("A"),
Base64ErrorData("AA"),
Base64ErrorData("AAA"),
Base64ErrorData("AA="),
// Tests with 4 bytes of good data but which does not
// terminate on the correct boundary.
Base64ErrorData("BBBBA="),
Base64ErrorData("BBBBA"),
Base64ErrorData("BBBBAA"),
Base64ErrorData("BBBBAAA"),
Base64ErrorData("BBBBAA="),
// Decode should succeed and do nothing on empty string.
Base64ErrorData(""),
// Character out of bounds for base64 encoding.
Base64ErrorData("<")));

int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
28 changes: 14 additions & 14 deletions utilities/xmlrpcpp/test/test_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ using namespace XmlRpc;

class FakeLogHandler : public XmlRpcLogHandler {
public:
FakeLogHandler() : last_level(-1), last_msg(NULL){};
FakeLogHandler() : last_level(-1), last_msg(""){};

virtual void log(int level, const char* msg) {
last_level = level;
last_msg = msg;
}

int last_level;
const char* last_msg;
std::string last_msg;
};

TEST(XmlRpc, Log) {
Expand All @@ -55,7 +55,7 @@ TEST(XmlRpc, Log) {
for (int i = 1; i < 6; i++) {
XmlRpcUtil::log(i, "Hello");
ASSERT_EQ(-1, fakelog.last_level);
ASSERT_EQ(NULL, fakelog.last_msg);
ASSERT_EQ("", fakelog.last_msg);
}

// Test masking at levels below maximum verbosity.
Expand All @@ -65,43 +65,43 @@ TEST(XmlRpc, Log) {
for (int j = 1; j <= i; j++) {
XmlRpcUtil::log(j, "Hello1");
EXPECT_EQ(j, fakelog.last_level);
EXPECT_STREQ("Hello1", fakelog.last_msg);
EXPECT_EQ("Hello1", fakelog.last_msg);

fakelog.last_level = -1;
fakelog.last_msg = NULL;
fakelog.last_msg = "";
}

XmlRpcUtil::log(i + 1, "Hello2");
ASSERT_EQ(-1, fakelog.last_level);
ASSERT_EQ(NULL, fakelog.last_msg);
ASSERT_EQ("", fakelog.last_msg);
}

// Test no messages masked at max verbosity.
XmlRpc::setVerbosity(5);
for (int i = 1; i < 5; i++) {
XmlRpcUtil::log(i, "Hello3");
EXPECT_EQ(i, fakelog.last_level);
EXPECT_STREQ("Hello3", fakelog.last_msg);
EXPECT_EQ("Hello3", fakelog.last_msg);

fakelog.last_level = -1;
fakelog.last_msg = NULL;
fakelog.last_msg = "";
}

// Basic formatting test.
XmlRpcUtil::log(2, "Hello %d", 42);
EXPECT_EQ(2, fakelog.last_level);
EXPECT_STREQ("Hello 42", fakelog.last_msg);
EXPECT_EQ("Hello 42", fakelog.last_msg);
}

class FakeErrorHandler : public XmlRpcErrorHandler {
public:
FakeErrorHandler() : last_msg(NULL){};
FakeErrorHandler() : last_msg(""){};

virtual void error(const char* msg) {
last_msg = msg;
}

const char* last_msg;
std::string last_msg;
};

TEST(XmlRpc, error) {
Expand All @@ -113,12 +113,12 @@ TEST(XmlRpc, error) {

// Basic error check.
XmlRpcUtil::error("Error!");
EXPECT_STREQ("Error!", errors.last_msg);
errors.last_msg = NULL;
EXPECT_EQ("Error!", errors.last_msg);
errors.last_msg = "";

// Error check with formatting.
XmlRpcUtil::error("%d: I'm a teapot", 408);
EXPECT_STREQ("408: I'm a teapot", errors.last_msg);
EXPECT_EQ("408: I'm a teapot", errors.last_msg);
}

int main(int argc, char **argv)
Expand Down

0 comments on commit 97bb693

Please sign in to comment.