123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- #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);
- }
- }
|