#include "base64.h"
#include <contrib/libs/base64/avx2/libbase64.h>
#include <contrib/libs/base64/neon32/libbase64.h>
#include <contrib/libs/base64/neon64/libbase64.h>
#include <contrib/libs/base64/plain32/libbase64.h>
#include <contrib/libs/base64/plain64/libbase64.h>
#include <contrib/libs/base64/ssse3/libbase64.h>
#include <library/cpp/testing/unittest/registar.h>
#include <util/generic/vector.h>
#include <util/random/fast.h>
#include <util/system/cpu_id.h>
#include <util/system/platform.h>
#include <array>
using namespace std::string_view_literals;
#define BASE64_UT_DECLARE_BASE64_IMPL(prefix, encFunction, decFunction) \
Y_DECLARE_UNUSED \
static size_t prefix##Base64Decode(void* dst, const char* b, const char* e) { \
const auto size = e - b; \
Y_ENSURE(!(size % 4), "incorrect input length for base64 decode"); \
\
size_t outLen; \
decFunction(b, size, (char*)dst, &outLen); \
return outLen; \
} \
\
Y_DECLARE_UNUSED \
static inline TStringBuf prefix##Base64Decode(const TStringBuf& src, void* dst) { \
return TStringBuf((const char*)dst, ::NB64Etalon::prefix##Base64Decode(dst, src.begin(), src.end())); \
} \
\
Y_DECLARE_UNUSED \
static inline void prefix##Base64Decode(const TStringBuf& src, TString& dst) { \
dst.ReserveAndResize(Base64DecodeBufSize(src.size())); \
dst.resize(::NB64Etalon::prefix##Base64Decode(src, dst.begin()).size()); \
} \
\
Y_DECLARE_UNUSED \
static inline TString prefix##Base64Decode(const TStringBuf& s) { \
TString ret; \
prefix##Base64Decode(s, ret); \
return ret; \
} \
\
Y_DECLARE_UNUSED \
static char* prefix##Base64Encode(char* outstr, const unsigned char* instr, size_t len) { \
size_t outLen; \
encFunction((char*)instr, len, outstr, &outLen); \
*(outstr + outLen) = '\0'; \
return outstr + outLen; \
} \
\
Y_DECLARE_UNUSED \
static inline TStringBuf prefix##Base64Encode(const TStringBuf& src, void* tmp) { \
return TStringBuf((const char*)tmp, ::NB64Etalon::prefix##Base64Encode((char*)tmp, (const unsigned char*)src.data(), src.size())); \
} \
\
Y_DECLARE_UNUSED \
static inline void prefix##Base64Encode(const TStringBuf& src, TString& dst) { \
dst.ReserveAndResize(Base64EncodeBufSize(src.size())); \
dst.resize(::NB64Etalon::prefix##Base64Encode(src, dst.begin()).size()); \
} \
\
Y_DECLARE_UNUSED \
static inline TString prefix##Base64Encode(const TStringBuf& s) { \
TString ret; \
prefix##Base64Encode(s, ret); \
return ret; \
}
namespace NB64Etalon {
BASE64_UT_DECLARE_BASE64_IMPL(PLAIN32, plain32_base64_encode, plain32_base64_decode)
BASE64_UT_DECLARE_BASE64_IMPL(PLAIN64, plain64_base64_encode, plain64_base64_decode)
BASE64_UT_DECLARE_BASE64_IMPL(NEON32, neon32_base64_encode, neon32_base64_decode)
BASE64_UT_DECLARE_BASE64_IMPL(NEON64, neon64_base64_encode, neon64_base64_decode)
BASE64_UT_DECLARE_BASE64_IMPL(AVX2, avx2_base64_encode, avx2_base64_decode)
BASE64_UT_DECLARE_BASE64_IMPL(SSSE3, ssse3_base64_encode, ssse3_base64_decode)
#undef BASE64_UT_DECLARE_BASE64_IMPL
struct TImpls {
enum EImpl : size_t {
PLAIN32_IMPL,
PLAIN64_IMPL,
NEON32_IMPL,
NEON64_IMPL,
AVX2_IMPL,
SSSE3_IMPL,
MAX_IMPL
};
using TEncodeF = void (*)(const TStringBuf&, TString&);
using TDecodeF = void (*)(const TStringBuf&, TString&);
struct TImpl {
TEncodeF Encode = nullptr;
TDecodeF Decode = nullptr;
};
std::array<TImpl, MAX_IMPL> Impl;
TImpls() {
Impl[PLAIN32_IMPL].Encode = PLAIN32Base64Encode;
Impl[PLAIN32_IMPL].Decode = PLAIN32Base64Decode;
Impl[PLAIN64_IMPL].Encode = PLAIN64Base64Encode;
Impl[PLAIN64_IMPL].Decode = PLAIN64Base64Decode;
#if defined(_arm32_)
Impl[NEON32_IMPL].Encode = NEON32Base64Encode;
Impl[NEON32_IMPL].Decode = NEON32Base64Decode;
#elif defined(_arm64_)
Impl[NEON64_IMPL].Encode = NEON64Base64Encode;
Impl[NEON64_IMPL].Decode = NEON64Base64Decode;
#elif defined(_x86_64_)
if (NX86::HaveSSSE3()) {
Impl[SSSE3_IMPL].Encode = SSSE3Base64Encode;
Impl[SSSE3_IMPL].Decode = SSSE3Base64Decode;
}
if (NX86::HaveAVX2()) {
Impl[AVX2_IMPL].Encode = AVX2Base64Encode;
Impl[AVX2_IMPL].Decode = AVX2Base64Decode;
}
#else
ythrow yexception() << "Failed to identify the platform";
#endif
}
};
TImpls GetImpls() {
static const TImpls IMPLS;
return IMPLS;
}
}
template <>
void Out<NB64Etalon::TImpls::EImpl>(IOutputStream& o, typename TTypeTraits<NB64Etalon::TImpls::EImpl>::TFuncParam v) {
switch (v) {
case NB64Etalon::TImpls::PLAIN32_IMPL:
o << TStringBuf{"PLAIN32"};
return;
case NB64Etalon::TImpls::PLAIN64_IMPL:
o << TStringBuf{"PLAIN64"};
return;
case NB64Etalon::TImpls::NEON64_IMPL:
o << TStringBuf{"NEON64"};
return;
case NB64Etalon::TImpls::NEON32_IMPL:
o << TStringBuf{"NEON32"};
return;
case NB64Etalon::TImpls::SSSE3_IMPL:
o << TStringBuf{"SSSE3"};
return;
case NB64Etalon::TImpls::AVX2_IMPL:
o << TStringBuf{"AVX2"};
return;
default:
ythrow yexception() << "invalid";
}
}
static void TestEncodeDecodeIntoString(const TString& plain, const TString& encoded, const TString& encodedUrl, const TString& encodedNoPadding, const TString& encodedUrlNoPadding) {
TString a, b;
Base64Encode(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encoded);
Base64Decode(a, b);
UNIT_ASSERT_VALUES_EQUAL(b, plain);
Base64EncodeUrl(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encodedUrl);
Base64Decode(a, b);
UNIT_ASSERT_VALUES_EQUAL(b, plain);
Base64EncodeNoPadding(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encodedNoPadding);
TString c = Base64DecodeUneven(a);
UNIT_ASSERT_VALUES_EQUAL(c, plain);
Base64EncodeUrlNoPadding(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encodedUrlNoPadding);
TString d = Base64DecodeUneven(a);
UNIT_ASSERT_VALUES_EQUAL(d, plain);
}
static void TestEncodeStrictDecodeIntoString(const TString& plain, const TString& encoded, const TString& encodedUrl) {
TString a, b;
Base64Encode(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encoded);
Base64StrictDecode(a, b);
UNIT_ASSERT_VALUES_EQUAL(b, plain);
Base64EncodeUrl(plain, a);
UNIT_ASSERT_VALUES_EQUAL(a, encodedUrl);
Base64StrictDecode(a, b);
UNIT_ASSERT_VALUES_EQUAL(b, plain);
}
Y_UNIT_TEST_SUITE(TBase64) {
Y_UNIT_TEST(TestEncode) {
UNIT_ASSERT_VALUES_EQUAL(Base64Encode("12z"), "MTJ6");
UNIT_ASSERT_VALUES_EQUAL(Base64Encode("123"), "MTIz");
UNIT_ASSERT_VALUES_EQUAL(Base64Encode("12"), "MTI=");
UNIT_ASSERT_VALUES_EQUAL(Base64Encode("1"), "MQ==");
}
Y_UNIT_TEST(TestIntoString) {
{
TString str;
for (size_t i = 0; i < 256; ++i)
str += char(i);
const TString base64 =
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJy"
"gpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9Q"
"UVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eH"
"l6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch"
"oqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIyc"
"rLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy"
"8/T19vf4+fr7/P3+/w==";
const TString base64Url =
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJy"
"gpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9Q"
"UVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eH"
"l6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch"
"oqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIyc"
"rLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy"
"8_T19vf4-fr7_P3-_w,,";
const TString base64WithoutPadding =
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJy"
"gpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9Q"
"UVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eH"
"l6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch"
"oqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIyc"
"rLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy"
"8/T19vf4+fr7/P3+/w";
const TString base64UrlWithoutPadding =
"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJy"
"gpKissLS4vMDEyMzQ1Njc4OTo7PD0-P0BBQkNERUZHSElKS0xNTk9Q"
"UVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eH"
"l6e3x9fn-AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6Ch"
"oqOkpaanqKmqq6ytrq-wsbKztLW2t7i5uru8vb6_wMHCw8TFxsfIyc"
"rLzM3Oz9DR0tPU1dbX2Nna29zd3t_g4eLj5OXm5-jp6uvs7e7v8PHy"
"8_T19vf4-fr7_P3-_w";
TestEncodeDecodeIntoString(str, base64, base64Url, base64WithoutPadding, base64UrlWithoutPadding);
TestEncodeStrictDecodeIntoString(str, base64, base64Url);
}
{
const TString str = "http://yandex.ru:1234/request?param=value&lll=fff#fragment";
const TString base64 = "aHR0cDovL3lhbmRleC5ydToxMjM0L3JlcXVlc3Q/cGFyYW09dmFsdWUmbGxsPWZmZiNmcmFnbWVudA==";
const TString base64Url = "aHR0cDovL3lhbmRleC5ydToxMjM0L3JlcXVlc3Q_cGFyYW09dmFsdWUmbGxsPWZmZiNmcmFnbWVudA,,";
const TString base64WithoutPadding = "aHR0cDovL3lhbmRleC5ydToxMjM0L3JlcXVlc3Q/cGFyYW09dmFsdWUmbGxsPWZmZiNmcmFnbWVudA";
const TString base64UrlWithoutPadding = "aHR0cDovL3lhbmRleC5ydToxMjM0L3JlcXVlc3Q_cGFyYW09dmFsdWUmbGxsPWZmZiNmcmFnbWVudA";
TestEncodeDecodeIntoString(str, base64, base64Url, base64WithoutPadding, base64UrlWithoutPadding);
TestEncodeStrictDecodeIntoString(str, base64, base64Url);
}
}
Y_UNIT_TEST(TestDecode) {
UNIT_ASSERT_EXCEPTION(Base64Decode("a"), yexception);
UNIT_ASSERT_EXCEPTION(Base64StrictDecode("a"), yexception);
UNIT_ASSERT_VALUES_EQUAL(Base64Decode(""), "");
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode(""), "");
UNIT_ASSERT_VALUES_EQUAL(Base64Decode("MTI="), "12");
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode("MTI="), "12");
UNIT_ASSERT_VALUES_EQUAL(Base64Decode("QQ=="), "A");
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode("QQ=="), "A");
UNIT_ASSERT_EXCEPTION(Base64StrictDecode("M=I="), yexception);
UNIT_ASSERT_VALUES_EQUAL(Base64Decode("dnluZHg="), "vyndx");
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode("dnluZHg="), "vyndx");
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode("dnluZHg=dmlkZW8="), "vyndxvideo");
UNIT_ASSERT_EXCEPTION(Base64StrictDecode("aHR0cDovL2ltZy5tZWdhLXBvcm5vLnJ1Lw=a"), yexception);
UNIT_ASSERT_EXCEPTION(Base64StrictDecode("aHh=="), yexception);
UNIT_ASSERT_EXCEPTION(Base64StrictDecode("\1\1\1\2"), yexception);
}
Y_UNIT_TEST(TestDecodeUneven) {
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven(""), "");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("YWFh"), "aaa");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("MTI="), "12");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("MTI,"), "12");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("MTI"), "12");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("QQ=="), "A");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("QQ,,"), "A");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("QQ"), "A");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("dnluZHg="), "vyndx");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("dnluZHg,"), "vyndx");
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven("dnluZHg"), "vyndx");
}
Y_UNIT_TEST(TestDecodeRandom) {
TString input;
constexpr size_t testSize = 240000;
for (size_t i = 0; i < testSize; ++i) {
input.push_back(rand() % 256);
}
TString output;
TString encoded = Base64Encode(input);
TString encodedUrl = TString::Uninitialized(Base64EncodeBufSize(input.length()));
Base64EncodeUrlNoPadding(input, encodedUrl);
UNIT_ASSERT_VALUES_EQUAL(Base64Decode(encoded), input);
UNIT_ASSERT_VALUES_EQUAL(Base64StrictDecode(encoded), input);
UNIT_ASSERT_VALUES_EQUAL(Base64DecodeUneven(encodedUrl), input);
}
Y_UNIT_TEST(TestAllPossibleOctets) {
const TString x("\0\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0B\f\r\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7F"sv);
const TString xEnc = "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn8=";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestTwoPaddingCharacters) {
const TString x("a");
const TString xEnc = "YQ==";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestOnePaddingCharacter) {
const TString x("aa");
const TString xEnc = "YWE=";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestNoPaddingCharacters) {
const TString x("aaa");
const TString xEnc = "YWFh";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestTrailingZero) {
const TString x("foo\0"sv);
const TString xEnc = "Zm9vAA==";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestTwoTrailingZeroes) {
const TString x("foo\0\0"sv);
const TString xEnc = "Zm9vAAA=";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestZero) {
const TString x("\0"sv);
const TString xEnc = "AA==";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestSymbolsAfterZero) {
const TString x("\0a"sv);
const TString xEnc = "AGE=";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestEmptyString) {
const TString x = "";
const TString xEnc = "";
const TString y = Base64Decode(xEnc);
const TString yEnc = Base64Encode(x);
UNIT_ASSERT_VALUES_EQUAL(x, y);
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
}
Y_UNIT_TEST(TestBackendsConsistencyOnRandomData) {
constexpr size_t TEST_CASES_COUNT = 1000;
constexpr size_t MAX_DATA_SIZE = 1000;
TFastRng<ui32> prng{42};
TVector<TString> xs{TEST_CASES_COUNT};
TString xEnc;
TString xDec;
TString yEnc;
TString yDec;
for (auto& x : xs) {
const size_t size = prng() % MAX_DATA_SIZE;
for (size_t j = 0; j < size; ++j) {
x += static_cast<char>(prng() % 256);
}
}
static const auto IMPLS = NB64Etalon::GetImpls();
for (size_t i = 0; i < static_cast<size_t>(NB64Etalon::TImpls::MAX_IMPL); ++i) {
for (size_t j = 0; j < static_cast<size_t>(NB64Etalon::TImpls::MAX_IMPL); ++j) {
const auto ei = static_cast<NB64Etalon::TImpls::EImpl>(i);
const auto ej = static_cast<NB64Etalon::TImpls::EImpl>(j);
const auto impl = IMPLS.Impl[i];
const auto otherImpl = IMPLS.Impl[j];
if (!impl.Encode && !impl.Decode || !otherImpl.Encode && !otherImpl.Decode) {
continue;
}
for (const auto& x : xs) {
impl.Encode(x, xEnc);
impl.Decode(xEnc, xDec);
Y_ENSURE(x == xDec, "something is wrong with " << ei << " implementation");
otherImpl.Encode(x, yEnc);
otherImpl.Decode(xEnc, yDec);
Y_ENSURE(x == yDec, "something is wrong with " << ej << " implementation");
UNIT_ASSERT_VALUES_EQUAL(xEnc, yEnc);
UNIT_ASSERT_VALUES_EQUAL(xDec, yDec);
}
}
}
}
Y_UNIT_TEST(TestIfEncodedDataIsZeroTerminatedOnRandomData) {
constexpr size_t TEST_CASES_COUNT = 1000;
constexpr size_t MAX_DATA_SIZE = 1000;
TFastRng<ui32> prng{42};
TString x;
TVector<char> buf;
for (size_t i = 0; i < TEST_CASES_COUNT; ++i) {
const size_t size = prng() % MAX_DATA_SIZE;
x.clear();
for (size_t j = 0; j < size; ++j) {
x += static_cast<char>(prng() % 256);
}
buf.assign(Base64EncodeBufSize(x.size()), Max<char>());
const auto* const xEncEnd = Base64Encode(buf.data(), (const unsigned char*)x.data(), x.size());
UNIT_ASSERT_VALUES_EQUAL(*xEncEnd, '\0');
}
}
Y_UNIT_TEST(TestDecodeURLEncodedNoPadding) {
const auto x = "123";
const auto xDec = Base64Decode("MTIz");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedOnePadding) {
const auto x = "12";
const auto xDec = Base64Decode("MTI,");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedTwoPadding) {
const auto x = "1";
const auto xDec = Base64Decode("MQ,,");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedWithoutPadding) {
const auto x = "1";
const auto xDec = Base64DecodeUneven("MQ");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeNoPaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?a";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz9h");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeOnePaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz8=");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeTwoPaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?aa";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz9hYQ==");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedNoPaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?a";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz9h");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedOnePaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz8,");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeURLEncodedTwoPaddingLongString) {
const auto x = "How do I convert between big-endian and little-endian values in C++?aa";
const auto xDec = Base64Decode("SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz9hYQ,,");
UNIT_ASSERT_VALUES_EQUAL(x, xDec);
}
Y_UNIT_TEST(TestDecodeUnevenDst) {
const auto x = "How do I convert between big-endian and little-endian values in C++?aa";
TString b64 = "SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz9hYQ";
TVector<char> buf(Base64DecodeBufSize(b64.size()), '\0');
Base64DecodeUneven(buf.begin(), b64);
TString res(buf.data());
UNIT_ASSERT_VALUES_EQUAL(x, res);
}
Y_UNIT_TEST(TestDecodeUnevenDst2) {
const auto x = "How do I convert between big-endian and little-endian values in C++?";
TString b64 = "SG93IGRvIEkgY29udmVydCBiZXR3ZWVuIGJpZy1lbmRpYW4gYW5kIGxpdHRsZS1lbmRpYW4gdmFsdWVzIGluIEMrKz8";
TVector<char> buf(Base64DecodeBufSize(b64.size()), '\0');
Base64DecodeUneven(buf.begin(), b64);
TString res(buf.data());
UNIT_ASSERT_VALUES_EQUAL(x, res);
}
}