mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-05-20 20:13:15 +08:00
Update release
This commit is contained in:
+2
-2
@@ -8279,7 +8279,7 @@ namespace vl
|
||||
struct QueryServiceHelper;
|
||||
|
||||
template<typename T>
|
||||
struct QueryServiceHelper<T, typename RequiresConvertable<decltype(T::Identifier), const wchar_t* const>::YesNoType>
|
||||
struct QueryServiceHelper<T, typename PointerConvertable<decltype(T::Identifier), const wchar_t* const>::YesNoType>
|
||||
{
|
||||
static WString GetIdentifier()
|
||||
{
|
||||
@@ -8288,7 +8288,7 @@ namespace vl
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct QueryServiceHelper<T, typename RequiresConvertable<decltype(T::GetIdentifier()), WString>::YesNoType>
|
||||
struct QueryServiceHelper<T, typename PointerConvertable<decltype(T::GetIdentifier()), WString>::YesNoType>
|
||||
{
|
||||
static WString GetIdentifier()
|
||||
{
|
||||
|
||||
+247
-32
@@ -1189,6 +1189,8 @@ PartialOrderingProcessor
|
||||
/***********************************************************************
|
||||
.\UNITTEST\UNITTEST.CPP
|
||||
***********************************************************************/
|
||||
#ifdef VCZH_MSVC
|
||||
#endif
|
||||
|
||||
namespace vl
|
||||
{
|
||||
@@ -1200,56 +1202,269 @@ namespace vl
|
||||
UnitTest
|
||||
***********************************************************************/
|
||||
|
||||
void UnitTest::PrintMessage(const WString& string)
|
||||
namespace execution_impl
|
||||
{
|
||||
Console::SetColor(false, true, false, true);
|
||||
Console::WriteLine(string);
|
||||
struct UnitTestLink
|
||||
{
|
||||
const char* fileName;
|
||||
UnitTestFileProc testProc = nullptr;
|
||||
UnitTestLink* next = nullptr;
|
||||
};
|
||||
UnitTestLink* testHead = nullptr;
|
||||
UnitTestLink** testTail = &testHead;
|
||||
|
||||
enum class UnitTestContextKind
|
||||
{
|
||||
File,
|
||||
Category,
|
||||
Case,
|
||||
};
|
||||
|
||||
struct UnitTestContext
|
||||
{
|
||||
UnitTestContext* parent = nullptr;
|
||||
WString indentation;
|
||||
UnitTestContextKind kind = UnitTestContextKind::File;
|
||||
bool failed = false;
|
||||
};
|
||||
|
||||
UnitTestContext* testContext = nullptr;
|
||||
vint totalFiles = 0;
|
||||
vint passedFiles = 0;
|
||||
vint totalCases = 0;
|
||||
vint passedCases = 0;
|
||||
bool suppressFailure = false;
|
||||
|
||||
template<typename TMessage>
|
||||
void RecordFailure(TMessage errorMessage)
|
||||
{
|
||||
UnitTest::PrintMessage(errorMessage, UnitTest::MessageKind::Error);
|
||||
auto current = testContext;
|
||||
while (current)
|
||||
{
|
||||
current->failed = true;
|
||||
current = current->parent;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TCallback>
|
||||
void SuppressCppFailure(TCallback&& callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
callback();
|
||||
}
|
||||
catch (const UnitTestAssertError& e)
|
||||
{
|
||||
RecordFailure(e.message);
|
||||
}
|
||||
catch (const UnitTestConfigError& e)
|
||||
{
|
||||
RecordFailure(e.message);
|
||||
}
|
||||
catch (const Error& e)
|
||||
{
|
||||
RecordFailure(e.Description());
|
||||
}
|
||||
catch (const Exception& e)
|
||||
{
|
||||
RecordFailure(e.Message());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
RecordFailure(L"Unknown exception occurred!");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TCallback>
|
||||
void SuppressCFailure(TCallback&& callback)
|
||||
{
|
||||
#ifdef VCZH_MSVC
|
||||
__try
|
||||
{
|
||||
SuppressCppFailure(ForwardValue<TCallback&&>(callback));
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
RecordFailure(L"Runtime exception occurred!");
|
||||
}
|
||||
#else
|
||||
SuppressCppFailure(callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename TCallback>
|
||||
void ExecuteAndSuppressFailure(TCallback&& callback)
|
||||
{
|
||||
if (suppressFailure)
|
||||
{
|
||||
SuppressCFailure(ForwardValue<TCallback&&>(callback));
|
||||
}
|
||||
else
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
using namespace execution_impl;
|
||||
|
||||
void UnitTest::PrintMessage(const WString& string, MessageKind kind)
|
||||
{
|
||||
if (kind != MessageKind::Error && !testContext)
|
||||
{
|
||||
throw UnitTestConfigError(L"Cannot print message when unit test is not running.");
|
||||
}
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case MessageKind::Error:
|
||||
Console::SetColor(true, false, false, true);
|
||||
break;
|
||||
case MessageKind::Info:
|
||||
Console::SetColor(true, true, true, true);
|
||||
break;
|
||||
case MessageKind::File:
|
||||
Console::SetColor(true, false, true, true);
|
||||
break;
|
||||
case MessageKind::Category:
|
||||
Console::SetColor(true, true, false, true);
|
||||
break;
|
||||
case MessageKind::Case:
|
||||
Console::SetColor(false, true, false, true);
|
||||
break;
|
||||
}
|
||||
Console::WriteLine((testContext ? testContext->indentation : L"") + string);
|
||||
Console::SetColor(true, true, true, false);
|
||||
}
|
||||
|
||||
void UnitTest::PrintInfo(const WString& string)
|
||||
#ifdef VCZH_MSVC
|
||||
int UnitTest::RunAndDisposeTests(int argc, wchar_t* argv[])
|
||||
#else
|
||||
int UnitTest::RunAndDisposeTests(int argc, char* argv[])
|
||||
#endif
|
||||
{
|
||||
Console::SetColor(true, true, true, true);
|
||||
Console::WriteLine(string);
|
||||
Console::SetColor(true, true, true, false);
|
||||
if (argc < 3)
|
||||
{
|
||||
if (argc == 2)
|
||||
{
|
||||
#ifdef VCZH_MSVC
|
||||
WString option = argv[1];
|
||||
#else
|
||||
WString option = atow(argv[1]);
|
||||
#endif
|
||||
if (option == L"/D")
|
||||
{
|
||||
suppressFailure = false;
|
||||
}
|
||||
else if (option == L"/R")
|
||||
{
|
||||
suppressFailure = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINT_USAGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef VCZH_MSVC
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
suppressFailure = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
suppressFailure = true;
|
||||
}
|
||||
#else
|
||||
suppressFailure = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
auto current = testHead;
|
||||
testHead = nullptr;
|
||||
testTail = nullptr;
|
||||
|
||||
UnitTestContext context;
|
||||
testContext = &context;
|
||||
totalFiles = 0;
|
||||
passedFiles = 0;
|
||||
totalCases = 0;
|
||||
passedCases = 0;
|
||||
|
||||
if (suppressFailure)
|
||||
{
|
||||
PrintMessage(L"Failures are suppressed.", MessageKind::Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
PrintMessage(L"Failures are not suppressed.", MessageKind::Info);
|
||||
}
|
||||
|
||||
while (current)
|
||||
{
|
||||
context.failed = false;
|
||||
PrintMessage(atow(current->fileName), MessageKind::File);
|
||||
context.indentation = L" ";
|
||||
ExecuteAndSuppressFailure(current->testProc);
|
||||
if (!testContext->failed) passedFiles++;
|
||||
totalFiles++;
|
||||
context.indentation = L"";
|
||||
auto temp = current;
|
||||
current = current->next;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
bool passed = totalFiles == passedFiles;
|
||||
auto messageKind = passed ? MessageKind::Case : MessageKind::Error;
|
||||
PrintMessage(L"Passed test files: " + itow(passedFiles) + L"/" + itow(totalFiles), messageKind);
|
||||
PrintMessage(L"Passed test cases: " + itow(passedCases) + L"/" + itow(totalCases), messageKind);
|
||||
testContext = nullptr;
|
||||
return passed ? 0 : 1;
|
||||
}
|
||||
PRINT_USAGE:
|
||||
PrintMessage(L"Usage: [/D | /R]", MessageKind::Error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UnitTest::PrintError(const WString& string)
|
||||
{
|
||||
Console::SetColor(true, false, false, true);
|
||||
Console::WriteLine(string);
|
||||
Console::SetColor(true, true, true, false);
|
||||
}
|
||||
|
||||
struct UnitTestLink
|
||||
{
|
||||
UnitTest::TestProc testProc = nullptr;
|
||||
UnitTestLink* next = nullptr;
|
||||
};
|
||||
UnitTestLink* testHead = nullptr;
|
||||
UnitTestLink** testTail = &testHead;
|
||||
|
||||
void UnitTest::PushTest(TestProc testProc)
|
||||
void UnitTest::RegisterTestFile(const char* fileName, UnitTestFileProc testProc)
|
||||
{
|
||||
auto link = new UnitTestLink;
|
||||
link->fileName = fileName;
|
||||
link->testProc = testProc;
|
||||
*testTail = link;
|
||||
testTail = &link->next;
|
||||
}
|
||||
|
||||
void UnitTest::RunAndDisposeTests()
|
||||
void UnitTest::RunCategoryOrCase(const WString& description, bool isCategory, Func<void()>&& callback)
|
||||
{
|
||||
auto current = testHead;
|
||||
testHead = nullptr;
|
||||
testTail = nullptr;
|
||||
if (!testContext) throw UnitTestConfigError(L"TEST_CATEGORY is not allowed to execute outside of TEST_FILE.");
|
||||
if (testContext->kind == UnitTestContextKind::Case) throw UnitTestConfigError(
|
||||
isCategory ?
|
||||
L"TEST_CATEGORY is not allowed to execute inside TEST_CASE" :
|
||||
L"TEST_CASE is not allowed to execute inside TEST_CASE");
|
||||
|
||||
while (current)
|
||||
PrintMessage(description, (isCategory ? MessageKind::Category : MessageKind::Case));
|
||||
|
||||
UnitTestContext context;
|
||||
context.parent = testContext;
|
||||
context.indentation = testContext->indentation + L" ";
|
||||
context.kind = isCategory ? UnitTestContextKind::Category : UnitTestContextKind::Case;
|
||||
|
||||
testContext = &context;
|
||||
ExecuteAndSuppressFailure(callback);
|
||||
if (!isCategory)
|
||||
{
|
||||
current->testProc();
|
||||
auto temp = current;
|
||||
current = current->next;
|
||||
delete temp;
|
||||
if (!testContext->failed) passedCases++;
|
||||
totalCases++;
|
||||
}
|
||||
testContext = context.parent;
|
||||
}
|
||||
|
||||
void UnitTest::EnsureLegalToAssert()
|
||||
{
|
||||
if (!testContext) throw UnitTestConfigError(L"Assertion is not allowed to execute outside of TEST_CASE.");
|
||||
if (testContext->kind != UnitTestContextKind::Case) throw UnitTestConfigError(L"Assertion is not allowed to execute outside of TEST_CASE.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+543
-415
File diff suppressed because it is too large
Load Diff
@@ -471,7 +471,7 @@ ReferenceCounterOperator
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct ReferenceCounterOperator<T, typename RequiresConvertable<T, reflection::DescriptableObject>::YesNoType>
|
||||
struct ReferenceCounterOperator<T, typename PointerConvertable<T, reflection::DescriptableObject>::YesNoType>
|
||||
{
|
||||
static __forceinline volatile vint* CreateCounter(T* reference)
|
||||
{
|
||||
@@ -4916,7 +4916,7 @@ Class
|
||||
protected:\
|
||||
bool IsAggregatable()override\
|
||||
{\
|
||||
return AcceptValue<typename RequiresConvertable<TYPENAME, AggregatableDescription<TYPENAME>>::YesNoType>::Result;\
|
||||
return AcceptValue<typename PointerConvertable<TYPENAME, AggregatableDescription<TYPENAME>>::YesNoType>::Result;\
|
||||
}\
|
||||
void LoadInternal()override\
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user