You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Use fopen() as a no-RTFM function instead of std::atomic_bool, as the latter has an inlined implementation on linux. * Add missing tests for modf() and modff(). Add the missing modfl() registration which these caught. * Fix RTFM_vswprintf() count calculations for non-windows. vswprintf() is horribly non-portable, and returns -1 if the buffer is too short. * Adjust the printf tests to handle other non-portablity issues. * Wrap wide string literals with std::wstring_view() when in REQUIRES(), as catch2 prints a bunch of '?' on error otherwise. #rb neil.henning [CL 35365141 by ben clayton in ue5-main branch]
1426 lines
31 KiB
C++
1426 lines
31 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Catch2Includes.h"
|
|
#include "CoreGlobals.h"
|
|
#include "Logging/LogVerbosity.h"
|
|
#include "Misc/FeedbackContext.h"
|
|
#include <AutoRTFM/AutoRTFM.h>
|
|
#include <catch_amalgamated.hpp>
|
|
#include <cstring>
|
|
|
|
#ifdef __clang__
|
|
#define CLANG_BEGIN_DISABLE_OPTIMIZATIONS _Pragma("clang optimize off")
|
|
#define CLANG_END_DISABLE_OPTIMIZATIONS _Pragma("clang optimize on")
|
|
#define CLANG_BEGIN_DISABLE_WARN_FORMAT_TRUNCATED \
|
|
_Pragma("clang diagnostic push") \
|
|
_Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \
|
|
_Pragma("clang diagnostic ignored \"-Wformat-truncation\"")
|
|
#define CLANG_END_DISABLE_WARN_FORMAT_TRUNCATED \
|
|
_Pragma("clang diagnostic pop")
|
|
#else
|
|
#define CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
#define CLANG_END_DISABLE_OPTIMIZATIONS
|
|
#define CLANG_BEGIN_DISABLE_WARN_FORMAT_TRUNCATED
|
|
#define CLANG_END_DISABLE_WARN_FORMAT_TRUNCATED
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
#define MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION \
|
|
__pragma(warning(push)) \
|
|
__pragma(warning(disable : 4996))
|
|
#define MSVC_END_DISABLE_UNSAFE_FN __pragma(warning(pop))
|
|
#else
|
|
#define MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
#define MSVC_END_DISABLE_UNSAFE_FN
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
|
|
// The expected AutoRTFM warning message when attempting to printf() using a
|
|
// format string containing a '%n' format specifier.
|
|
static constexpr auto* kPercentNWarning = TEXT("AutoRTFM does not support format strings containing '%n'");
|
|
|
|
// CheckWCharFunction calls Function with WChar outside a transaction, in an
|
|
// aborted transaction and committed transaction. The value returned when called
|
|
// in the committed transation is expected to match the value returned when
|
|
// called outside the transaction.
|
|
// Function must be the deterministic function with the signature 'int(wchar_t)'.
|
|
template<typename FUNCTION>
|
|
void CheckWCharFunction(FUNCTION&& Function, wchar_t WChar)
|
|
{
|
|
int Expect = Function(WChar);
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Got = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Got = Function(WChar);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Got);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Got = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Got = Function(WChar); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(Expect == Got);
|
|
}
|
|
}
|
|
|
|
// A helper class that for the lifetime of the object, intercepts and records
|
|
// UE_LOG warnings.
|
|
class FCaptureWarningContext : private FFeedbackContext
|
|
{
|
|
public:
|
|
FCaptureWarningContext() : OldContext(GWarn) { GWarn = this; }
|
|
~FCaptureWarningContext() { GWarn = OldContext; }
|
|
|
|
void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) override
|
|
{
|
|
if (Verbosity == ELogVerbosity::Warning)
|
|
{
|
|
Warnings.push_back(V);
|
|
}
|
|
else
|
|
{
|
|
OldContext->Serialize(V, Verbosity, Category);
|
|
}
|
|
}
|
|
|
|
void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category, double Time) override
|
|
{
|
|
if (Verbosity == ELogVerbosity::Warning)
|
|
{
|
|
Warnings.push_back(V);
|
|
}
|
|
else
|
|
{
|
|
OldContext->Serialize(V, Verbosity, Category, Time);
|
|
}
|
|
}
|
|
|
|
const std::vector<FString>& GetWarnings() const
|
|
{
|
|
return Warnings;
|
|
}
|
|
|
|
private:
|
|
FCaptureWarningContext(const FCaptureWarningContext&) = delete;
|
|
FCaptureWarningContext& operator = (const FCaptureWarningContext&) = delete;
|
|
|
|
FFeedbackContext* OldContext = nullptr;
|
|
std::vector<FString> Warnings;
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
TEST_CASE("CString.memcpy")
|
|
{
|
|
const char* const From = "Kittie says meow";
|
|
char To[] = "Doggie says woof";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
memcpy(To, From, 6);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Doggie says woof" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { memcpy(To, From, 6); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Kittie says woof" == std::string_view(To));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.memmove")
|
|
{
|
|
char To[] = "Hello, world!";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
memmove(To + 7, To, 5);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Hello, world!" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { memmove(To + 7, To, 5); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Hello, Hello!" == std::string_view(To));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strcpy")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
const char From[] = "Kittie says meow";
|
|
char To[] = "Doggie says woof____";
|
|
static_assert(sizeof(From) <= sizeof(To));
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
strcpy(To, From);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Doggie says woof____" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { strcpy(To, From); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Kittie says meow" == std::string_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.strncpy")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
const char* const From = "Kittie says meow";
|
|
char To[] = "Doggie says woof";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
strncpy(To, From, 6);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Doggie says woof" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { strncpy(To, From, 6); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Kittie says woof" == std::string_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.strcat")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
constexpr unsigned Size = 128;
|
|
char To[Size] = "Hello";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
strcat(To, ", world!");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Hello" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { strcat(To, ", world!"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Hello, world!" == std::string_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.strncat")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
constexpr unsigned Size = 128;
|
|
char To[Size] = "Hello";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
strncat(To, ", world! Not this!", 8);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE("Hello" == std::string_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { strncat(To, ", world! Not this!", 8); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE("Hello, world!" == std::string_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.memcmp")
|
|
{
|
|
constexpr unsigned Size = 128;
|
|
char A[Size] = "This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Compare = memcmp(A, "That", 4);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Compare);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Compare = memcmp(A, "That", 4); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 < Compare);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strcmp")
|
|
{
|
|
const char* A = "This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Compare = strcmp(A, "That");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Compare);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Compare = strcmp(A, "That"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 < Compare);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strncmp")
|
|
{
|
|
const char* A = "This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Compare = strncmp(A, "That", 3);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Compare);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Compare = strncmp(A, "That", 3); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 < Compare);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strchr")
|
|
{
|
|
const char* A = "Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strchr(A, 'i');
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strchr(A, 'i'); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strrchr")
|
|
{
|
|
const char* A = "Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strrchr(A, 'i');
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strrchr(A, 'i'); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 5) == Value);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strstr")
|
|
{
|
|
const char* A = "This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strstr(A, "is");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
const char* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strstr(A, "is"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strlen")
|
|
{
|
|
const char* A = "This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
size_t Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strlen(A);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
size_t Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strlen(A); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(4 == Value);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.strtol")
|
|
{
|
|
const char* Str = "123xyz";
|
|
|
|
SECTION("With end pointer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
long int Value = 0;
|
|
char* EndPtr = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strtol(Str, &EndPtr, 10);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Value);
|
|
REQUIRE(nullptr == EndPtr);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
long int Value = 0;
|
|
char* EndPtr = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strtol(Str, &EndPtr, 10); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(123 == Value);
|
|
REQUIRE((Str + 3) == EndPtr);
|
|
}
|
|
}
|
|
|
|
SECTION("Without end pointer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
long int Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = strtol(Str, nullptr, 10);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
long int Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = strtol(Str, nullptr, 10); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(123 == Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TEST_CASE("CString.wcscpy")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
const wchar_t From[] = L"Kittie says meow";
|
|
wchar_t To[] = L"Doggie says woof____";
|
|
static_assert(sizeof(From) <= sizeof(To));
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
wcscpy(To, From);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(std::wstring_view(L"Doggie says woof____") == std::wstring_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { wcscpy(To, From); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(std::wstring_view(L"Kittie says meow") == std::wstring_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.wcsncpy")
|
|
{
|
|
MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
|
|
const wchar_t* const From = L"Kittie says meow";
|
|
wchar_t To[] = L"Doggie says woof";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
wcsncpy(To, From, 6);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(std::wstring_view(L"Doggie says woof") == std::wstring_view(To));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { wcsncpy(To, From, 6); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(std::wstring_view(L"Kittie says woof") == std::wstring_view(To));
|
|
}
|
|
|
|
MSVC_END_DISABLE_UNSAFE_FN
|
|
}
|
|
|
|
TEST_CASE("CString.wcsncmp")
|
|
{
|
|
const wchar_t* A = L"This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Compare = wcsncmp(A, L"That", 3);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Compare);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Compare = wcsncmp(A, L"That", 3); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 < Compare);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.wcschr")
|
|
{
|
|
SECTION("Const")
|
|
{
|
|
const wchar_t* A = L"Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
const wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = wcschr(A, L'i');
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
const wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = wcschr(A, L'i'); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
|
|
SECTION("Non-Const")
|
|
{
|
|
wchar_t A[] = L"Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = wcschr(A, L'i');
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = wcschr(A, L'i'); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.wcsstr")
|
|
{
|
|
SECTION("Const")
|
|
{
|
|
const wchar_t* A = L"Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
const wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = wcsstr(A, L"ink");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
const wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = wcsstr(A, L"ink"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
|
|
SECTION("Non-Const")
|
|
{
|
|
wchar_t A[] = L"Thinking";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = wcsstr(A, L"ink");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(nullptr == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
wchar_t* Value = nullptr;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = wcsstr(A, L"ink"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE((A + 2) == Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.wcscmp")
|
|
{
|
|
const wchar_t* A = L"This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Compare = wcscmp(A, L"That");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Compare);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Compare = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Compare = wcscmp(A, L"That"); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 < Compare);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.wcslen")
|
|
{
|
|
const wchar_t* A = L"This";
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
size_t Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Value = wcslen(A);
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Value);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
size_t Value = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&] { Value = wcslen(A); });
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(4 == Value);
|
|
}
|
|
}
|
|
|
|
|
|
TEST_CASE("CString.iswupper")
|
|
{
|
|
CheckWCharFunction(iswupper, L'X');
|
|
CheckWCharFunction(iswupper, L'x');
|
|
}
|
|
|
|
TEST_CASE("CString.iswlower")
|
|
{
|
|
CheckWCharFunction(iswlower, L'X');
|
|
CheckWCharFunction(iswlower, L'x');
|
|
}
|
|
|
|
TEST_CASE("CString.iswalpha")
|
|
{
|
|
CheckWCharFunction(iswalpha, L'X');
|
|
CheckWCharFunction(iswalpha, L'5');
|
|
}
|
|
|
|
TEST_CASE("CString.iswgraph")
|
|
{
|
|
CheckWCharFunction(iswgraph, L'X');
|
|
CheckWCharFunction(iswgraph, L'x');
|
|
}
|
|
|
|
TEST_CASE("CString.iswprint")
|
|
{
|
|
CheckWCharFunction(iswprint, L'X');
|
|
CheckWCharFunction(iswprint, L'x');
|
|
}
|
|
|
|
TEST_CASE("CString.iswpunct")
|
|
{
|
|
CheckWCharFunction(iswpunct, L'X');
|
|
CheckWCharFunction(iswpunct, L'^');
|
|
}
|
|
|
|
TEST_CASE("CString.iswalnum")
|
|
{
|
|
CheckWCharFunction(iswalnum, L'X');
|
|
CheckWCharFunction(iswalnum, L'6');
|
|
CheckWCharFunction(iswalnum, L' ');
|
|
}
|
|
|
|
TEST_CASE("CString.iswdigit")
|
|
{
|
|
CheckWCharFunction(iswdigit, L'X');
|
|
CheckWCharFunction(iswdigit, L'5');
|
|
}
|
|
|
|
TEST_CASE("CString.iswxdigit")
|
|
{
|
|
CheckWCharFunction(iswxdigit, L'X');
|
|
CheckWCharFunction(iswxdigit, L'q');
|
|
}
|
|
|
|
TEST_CASE("CString.iswspace")
|
|
{
|
|
CheckWCharFunction(iswspace, L'X');
|
|
CheckWCharFunction(iswspace, L' ');
|
|
}
|
|
|
|
TEST_CASE("CString.iswcntrl")
|
|
{
|
|
CheckWCharFunction(iswcntrl, L'X');
|
|
CheckWCharFunction(iswcntrl, L'\u2028');
|
|
}
|
|
|
|
TEST_CASE("CString.snprintf")
|
|
{
|
|
static constexpr size_t BufferSize = 64;
|
|
char Buffer[BufferSize] = "_____________________";
|
|
|
|
SECTION("Fits in buffer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = snprintf(Buffer, BufferSize, "cat says '%s'!", "meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE("_____________________" == std::string_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = snprintf(Buffer, BufferSize, "cat says '%s'!", "meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(16 == Count);
|
|
REQUIRE("cat says 'meow'!" == std::string_view(Buffer));
|
|
}
|
|
}
|
|
|
|
SECTION("Buffer too small")
|
|
{
|
|
CLANG_BEGIN_DISABLE_WARN_FORMAT_TRUNCATED
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = snprintf(Buffer, 8, "cat says '%s'!", "meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE("_____________________" == std::string_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = snprintf(Buffer, 8, "cat says '%s'!", "meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(16 == Count);
|
|
REQUIRE("cat say" == std::string_view(Buffer));
|
|
}
|
|
|
|
CLANG_END_DISABLE_WARN_FORMAT_TRUNCATED
|
|
}
|
|
|
|
SECTION("Null buffer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = snprintf(nullptr, 0, "cat says '%s'!", "meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = snprintf(nullptr, 0, "cat says '%s'!", "meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(16 == Count);
|
|
}
|
|
}
|
|
|
|
SECTION("PercentN")
|
|
{
|
|
FCaptureWarningContext WarningContext;
|
|
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
snprintf(Buffer, 8, "%n", &Count);
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByLanguage == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE("_____________________" == std::string_view(Buffer));
|
|
REQUIRE_THAT(WarningContext.GetWarnings(),
|
|
Catch::Matchers::VectorContains(FString(kPercentNWarning)));
|
|
}
|
|
|
|
SECTION("PercentPercentN")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = snprintf(Buffer, 8, "%%n");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE("_____________________" == std::string_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = snprintf(Buffer, 8, "%%n");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(2 == Count);
|
|
REQUIRE("%n" == std::string_view(Buffer));
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.swprintf")
|
|
{
|
|
static constexpr size_t BufferSize = 64;
|
|
wchar_t Buffer[BufferSize] = L"_____________________";
|
|
|
|
SECTION("Fits in buffer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = swprintf(Buffer, BufferSize, L"cat says '%ls'!", L"meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE(std::wstring_view(L"_____________________") == std::wstring_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = swprintf(Buffer, BufferSize, L"cat says '%ls'!", L"meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(16 == Count);
|
|
REQUIRE(std::wstring_view(L"cat says 'meow'!") == std::wstring_view(Buffer));
|
|
}
|
|
}
|
|
|
|
SECTION("Buffer too small")
|
|
{
|
|
CLANG_BEGIN_DISABLE_WARN_FORMAT_TRUNCATED
|
|
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = swprintf(Buffer, 8, L"cat says '%ls'!", L"meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE(std::wstring_view(L"_____________________") == std::wstring_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = swprintf(Buffer, 8, L"cat says '%ls'!", L"meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(0 > Count);
|
|
REQUIRE(std::wstring_view(L"cat say") == std::wstring_view(Buffer, 7));
|
|
}
|
|
|
|
CLANG_END_DISABLE_WARN_FORMAT_TRUNCATED
|
|
}
|
|
|
|
SECTION("Null buffer")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = swprintf(nullptr, 0, L"cat says '%ls'!", L"meow");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = swprintf(nullptr, 0, L"cat says '%ls'!", L"meow");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(((0 > Count) || (16 == Count)));
|
|
}
|
|
}
|
|
|
|
SECTION("PercentN")
|
|
{
|
|
FCaptureWarningContext WarningContext;
|
|
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
swprintf(Buffer, 8, L"%n", &Count);
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByLanguage == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE(std::wstring_view(L"_____________________") == std::wstring_view(Buffer));
|
|
REQUIRE_THAT(WarningContext.GetWarnings(),
|
|
Catch::Matchers::VectorContains(FString(kPercentNWarning)));
|
|
}
|
|
|
|
SECTION("PercentPercentN")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = swprintf(Buffer, 8, L"%%n");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE(std::wstring_view(L"_____________________") == std::wstring_view(Buffer));
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = swprintf(Buffer, 8, L"%%n");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(2 == Count);
|
|
REQUIRE(std::wstring_view(L"%n") == std::wstring_view(Buffer));
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.printf")
|
|
{
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = printf("AutoRTFM printf test: %%n\n");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::Commit([&]
|
|
{
|
|
Count = printf("AutoRTFM printf test: %%n\n");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(25 == Count);
|
|
}
|
|
|
|
SECTION("PercentN")
|
|
{
|
|
FCaptureWarningContext WarningContext;
|
|
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
printf("%n", &Count);
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByLanguage == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE_THAT(WarningContext.GetWarnings(),
|
|
Catch::Matchers::VectorContains(FString(kPercentNWarning)));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("CString.wprintf")
|
|
{
|
|
#if PLATFORM_WINDOWS // wprintf() can error on linux
|
|
SECTION("With Abort")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = wprintf(L"AutoRTFM wprintf test: %%n\n");
|
|
AutoRTFM::AbortTransaction();
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByRequest == Result);
|
|
REQUIRE(0 == Count);
|
|
}
|
|
|
|
SECTION("With Commit")
|
|
{
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
Count = wprintf(L"AutoRTFM wprintf test: %%n\n");
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::Committed == Result);
|
|
REQUIRE(26 == Count);
|
|
}
|
|
#endif // PLATFORM_WINDOWS
|
|
|
|
SECTION("PercentN")
|
|
{
|
|
FCaptureWarningContext WarningContext;
|
|
|
|
int Count = 0;
|
|
|
|
CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
AutoRTFM::ETransactionResult Result = AutoRTFM::Transact([&]
|
|
{
|
|
wprintf(L"%n", &Count);
|
|
});
|
|
CLANG_END_DISABLE_OPTIMIZATIONS
|
|
|
|
REQUIRE(AutoRTFM::ETransactionResult::AbortedByLanguage == Result);
|
|
REQUIRE(0 == Count);
|
|
REQUIRE_THAT(WarningContext.GetWarnings(),
|
|
Catch::Matchers::VectorContains(FString(kPercentNWarning)));
|
|
}
|
|
}
|
|
|
|
#undef CLANG_BEGIN_DISABLE_OPTIMIZATIONS
|
|
#undef CLANG_END_DISABLE_OPTIMIZATIONS
|
|
#undef MSVC_BEGIN_DISABLE_WARN_UNSAFE_FUNCTION
|
|
#undef MSVC_END_DISABLE_UNSAFE_FN
|