92643c1d34
Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev 063b86ac10af16cade5c0754adcbf27e7e9ae266 Related work items: MSFT-34534216, MSFT-36986009, MSFT-36986203
120 lines
3.9 KiB
C++
120 lines
3.9 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
#include "WexTestClass.h"
|
|
|
|
#include <til/rand.h>
|
|
#include <wincrypt.h>
|
|
|
|
#include "base64.hpp"
|
|
|
|
using namespace WEX::Common;
|
|
using namespace WEX::Logging;
|
|
using namespace WEX::TestExecution;
|
|
|
|
namespace Microsoft
|
|
{
|
|
namespace Console
|
|
{
|
|
namespace VirtualTerminal
|
|
{
|
|
class Base64Test;
|
|
};
|
|
};
|
|
};
|
|
|
|
using namespace Microsoft::Console::VirtualTerminal;
|
|
|
|
class Microsoft::Console::VirtualTerminal::Base64Test
|
|
{
|
|
TEST_CLASS(Base64Test);
|
|
|
|
TEST_METHOD(DecodeFuzz)
|
|
{
|
|
// NOTE: Modify testRounds to get the feeling of running a fuzz test on Base64::Decode.
|
|
static constexpr auto testRounds = 8;
|
|
pcg_engines::oneseq_dxsm_64_32 rng{ til::gen_random<uint64_t>() };
|
|
|
|
// Fills referenceData with random ASCII characters.
|
|
// We use ASCII as Base64::Decode uses til:u8u16 internally and I don't want to test that.
|
|
char referenceData[128];
|
|
{
|
|
uint32_t randomData[sizeof(referenceData) / sizeof(uint32_t)];
|
|
for (auto& i : randomData)
|
|
{
|
|
i = rng();
|
|
}
|
|
|
|
const std::string_view randomDataView{ reinterpret_cast<const char*>(randomData), sizeof(randomData) };
|
|
auto out = std::begin(referenceData);
|
|
|
|
for (const auto& ch : randomDataView)
|
|
{
|
|
*out++ = static_cast<char>(ch & 0x7f);
|
|
}
|
|
}
|
|
|
|
wchar_t wideReferenceData[std::size(referenceData)];
|
|
std::copy_n(std::begin(referenceData), std::size(referenceData), std::begin(wideReferenceData));
|
|
|
|
std::wstring encoded;
|
|
std::wstring decoded;
|
|
|
|
for (auto i = 0; i < testRounds; ++i)
|
|
{
|
|
const auto referenceLength = rng(static_cast<uint32_t>(std::size(referenceData)));
|
|
const std::wstring_view wideReference{ std::begin(wideReferenceData), referenceLength };
|
|
|
|
if (!referenceLength)
|
|
{
|
|
encoded.clear();
|
|
}
|
|
else
|
|
{
|
|
const auto reference = reinterpret_cast<const BYTE*>(std::begin(referenceData));
|
|
DWORD encodedLen;
|
|
THROW_IF_WIN32_BOOL_FALSE(CryptBinaryToStringW(reference, referenceLength, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &encodedLen));
|
|
|
|
// encodedLen is returned by CryptBinaryToStringW including the trailing null byte.
|
|
encoded.resize(encodedLen - 1);
|
|
|
|
THROW_IF_WIN32_BOOL_FALSE(CryptBinaryToStringW(reference, referenceLength, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, encoded.data(), &encodedLen));
|
|
}
|
|
|
|
// Test whether Decode() handles strings with and without trailing "=".
|
|
if (rng(2))
|
|
{
|
|
while (!encoded.empty() && encoded.back() == '=')
|
|
{
|
|
encoded.pop_back();
|
|
}
|
|
}
|
|
|
|
// Test whether Decode() handles null-pointer arguments correctly.
|
|
std::wstring_view encodedView{ encoded };
|
|
if (encodedView.empty() && rng(2))
|
|
{
|
|
encodedView = {};
|
|
}
|
|
|
|
Base64::Decode(encodedView, decoded);
|
|
VERIFY_ARE_EQUAL(wideReference, decoded);
|
|
}
|
|
}
|
|
|
|
TEST_METHOD(DecodeUTF8)
|
|
{
|
|
std::wstring result;
|
|
|
|
// U+306b U+307b U+3093 U+3054 U+6c49 U+8bed U+d55c U+ad6d
|
|
Base64::Decode(L"44Gr44G744KT44GU5rGJ6K+t7ZWc6rWt", result);
|
|
VERIFY_ARE_EQUAL(L"にほんご汉语한국", result);
|
|
|
|
// U+d83d U+dc4d U+d83d U+dc4d U+d83c U+dffb U+d83d U+dc4d U+d83c U+dffc U+d83d
|
|
// U+dc4d U+d83c U+dffd U+d83d U+dc4d U+d83c U+dffe U+d83d U+dc4d U+d83c U+dfff
|
|
Base64::Decode(L"8J+RjfCfkY3wn4+78J+RjfCfj7zwn5GN8J+PvfCfkY3wn4++8J+RjfCfj78=", result);
|
|
VERIFY_ARE_EQUAL(L"👍👍🏻👍🏼👍🏽👍🏾👍🏿", result);
|
|
}
|
|
};
|