#include "engine/base64.hpp" #include "mocks/mock_datafacade.hpp" #include "engine/hint.hpp" #include #include #include // RFC 4648 "The Base16, Base32, and Base64 Data Encodings" BOOST_AUTO_TEST_SUITE(base64) // For test vectors see section 10: https://tools.ietf.org/html/rfc4648#section-10 BOOST_AUTO_TEST_CASE(rfc4648_test_vectors) { using namespace osrm::engine; BOOST_CHECK_EQUAL(encodeBase64("f"), "Zg=="); BOOST_CHECK_EQUAL(encodeBase64("fo"), "Zm8="); BOOST_CHECK_EQUAL(encodeBase64("foo"), "Zm9v"); BOOST_CHECK_EQUAL(encodeBase64("foob"), "Zm9vYg=="); BOOST_CHECK_EQUAL(encodeBase64("fooba"), "Zm9vYmE="); BOOST_CHECK_EQUAL(encodeBase64("foobar"), "Zm9vYmFy"); } BOOST_AUTO_TEST_CASE(rfc4648_test_vectors_roundtrip) { using namespace osrm::engine; BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("f")), "f"); BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fo")), "fo"); BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foo")), "foo"); BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foob")), "foob"); BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("fooba")), "fooba"); BOOST_CHECK_EQUAL(decodeBase64(encodeBase64("foobar")), "foobar"); } BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip) { using namespace osrm::engine; using namespace osrm::util; const Coordinate coordinate; const PhantomNode phantom; const osrm::test::MockDataFacade facade{}; const SegmentHint seg_hint{phantom, facade.GetCheckSum()}; const auto base64 = seg_hint.ToBase64(); BOOST_CHECK(0 == std::count(begin(base64), end(base64), '+')); BOOST_CHECK(0 == std::count(begin(base64), end(base64), '/')); const auto decoded = SegmentHint::FromBase64(base64); BOOST_CHECK_EQUAL(seg_hint, decoded); } BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip_bytewise) { using namespace osrm::engine; using namespace osrm::util; const Coordinate coordinate; const PhantomNode phantom; const osrm::test::MockDataFacade facade{}; const SegmentHint seg_hint{phantom, facade.GetCheckSum()}; const auto decoded = SegmentHint::FromBase64(seg_hint.ToBase64()); BOOST_CHECK(std::equal(reinterpret_cast(&seg_hint), reinterpret_cast(&seg_hint) + sizeof(Hint), reinterpret_cast(&decoded))); } BOOST_AUTO_TEST_CASE(long_string_encoding) { using namespace osrm::engine; std::string long_string(1000, 'A'); // String of 1000 'A's std::string encoded = encodeBase64(long_string); BOOST_CHECK_EQUAL(decodeBase64(encoded), long_string); } BOOST_AUTO_TEST_CASE(invalid_base64_decoding) { using namespace osrm::engine; BOOST_CHECK_THROW(decodeBase64("Invalid!"), std::exception); } BOOST_AUTO_TEST_CASE(hint_serialization_size) { using namespace osrm::engine; using namespace osrm::util; const Coordinate coordinate; const PhantomNode phantom; const osrm::test::MockDataFacade facade{}; const SegmentHint hint{phantom, facade.GetCheckSum()}; const auto base64 = hint.ToBase64(); BOOST_CHECK_EQUAL(base64.size(), 112); } BOOST_AUTO_TEST_CASE(extended_roundtrip_tests) { using namespace osrm::engine; std::vector test_strings = { "Hello, World!", // Simple ASCII string "1234567890", // Numeric string "!@#$%^&*()_+", // Special characters std::string(1000, 'A'), // Long repeating string "¡Hola, mundo!", // Non-ASCII characters "こんにちは、世界!", // Unicode characters std::string("\x00\x01\x02\x03", 4), // Binary data "a", // Single character "ab", // Two characters "abc", // Three characters (no padding in Base64) std::string(190, 'x') // String that doesn't align with Base64 padding }; for (const auto &test_str : test_strings) { std::string encoded = encodeBase64(test_str); std::string decoded = decodeBase64(encoded); BOOST_CHECK_EQUAL(decoded, test_str); // Additional checks BOOST_CHECK(encoded.find_first_not_of( "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") == std::string::npos); if (test_str.length() % 3 != 0) { BOOST_CHECK(encoded.back() == '='); } } } BOOST_AUTO_TEST_CASE(roundtrip_with_url_safe_chars) { using namespace osrm::engine; std::string original = "Hello+World/Nothing?Is:Impossible"; std::string encoded = encodeBase64(original); // Replace '+' with '-' and '/' with '_' std::replace(encoded.begin(), encoded.end(), '+', '-'); std::replace(encoded.begin(), encoded.end(), '/', '_'); std::string decoded = decodeBase64(encoded); BOOST_CHECK_EQUAL(decoded, original); } BOOST_AUTO_TEST_CASE(roundtrip_stress_test) { using namespace osrm::engine; std::string test_str; for (int i = 0; i < 1000; ++i) { test_str += static_cast(i % 256); } std::string encoded = encodeBase64(test_str); std::string decoded = decodeBase64(encoded); BOOST_CHECK_EQUAL(decoded, test_str); } BOOST_AUTO_TEST_SUITE_END()