[+/*] Updated and added a few tests (a hell of a lot more pending)

[*] Update modules
[+] Add auROXTL
This commit is contained in:
Reece Wilson 2022-04-01 05:10:58 +01:00
parent d3f6124c07
commit 05d9537cbc
26 changed files with 678 additions and 93 deletions

3
.gitmodules vendored
View File

@ -67,3 +67,6 @@
[submodule "Tests/googletest"]
path = Tests/googletest
url = https://github.com/google/googletest
[submodule "Aurora/ROXTL"]
path = Aurora/ROXTL
url = https://gitea.reece.sx/AuroraSupport/auROXTL.git

@ -1 +1 @@
Subproject commit 68a3479d137610dff8857c9054454ed8704c642c
Subproject commit 99b365e260db8b7536d10fafbc7be950251780af

1
Aurora/ROXTL Submodule

@ -0,0 +1 @@
Subproject commit a19ae800aa9ba41c185aa4720442fca41732c50d

@ -1 +1 @@
Subproject commit 260442a68449de7368522dd0f2f7b34871f5de89
Subproject commit 7e1bf30131146ac22e08568657b0be0669f343de

View File

@ -1,4 +1,17 @@
require("aurora")
newoption {
trigger = "with-wxWidgets",
description = "enable wxWidgets console + tests"
}
newoption {
trigger = "with-v8",
description = "enable v8 tests"
}
newoption {
trigger = "lite",
description = ""
}
auStartSolution({name = "Hello Aurora"})
@ -11,12 +24,16 @@ local kNamespaceJS = "Vendor - 6 - JAVASCRIPT"
local kNamespaceGraphics = "Vendor - 7 - GRAPHICS"
local kNamespaceAudio = "Vendor - 8 - AUDIO"
auAddVisit({
if (_OPTIONS["with-wxWidgets"]) then
auAddVisit({
namespace = kNamespaceGraphics,
name = "wxwidgets",
path = "Vendor/wxwidgets",
type = "SharedLib"
})
type = "SharedLib",
out = "!"
})
end
auAddVisit({
namespace = kNamespaceStlEx,
@ -39,19 +56,21 @@ auAddVisit({
type = "StaticLib"
})
auAddVisit({
if (not _OPTIONS["lite"]) then
auAddVisit({
namespace = kNamespaceCompression,
name = "bzip2",
path = "Vendor/bzip2",
type = "StaticLib"
})
})
auAddVisit({
auAddVisit({
namespace = kNamespaceCompression,
name = "lz4",
path = "Vendor/lz4",
type = "StaticLib"
})
})
end
--auAddVisit({
-- namespace = kNamespaceCompression,
@ -139,18 +158,45 @@ auAddVisit({
})
auAddVisit({
namespace = "Aurora",
name = "auROXTL",
path = "Aurora/ROXTL",
type = "StaticLib"
})
if (_OPTIONS["with-wxWidgets"]) then
auAddVisit({
namespace = kNamespaceFormats,
name = "png",
path = "Vendor/libpng",
type = "StaticLib"
})
})
auAddVisit({
auAddVisit({
namespace = kNamespaceFormats,
name = "expat",
path = "Vendor/libexpat",
type = "StaticLib"
})
})
end
if (_OPTIONS["with-v8"]) then
auAddVisit({
namespace = kNamespaceJS,
name = "V8",
path = "Vendor/v8",
type = "SharedLib",
out = "!"
})
auAddVisit({
namespace = kNamespaceJS,
name = "icu",
path = "Vendor/unicode",
type = "StaticLib"
})
end
auProcessSolution()
@ -198,6 +244,11 @@ local processTests = function()
addTestGroup("Private")
addTestGroup("Public")
if (_OPTIONS["with-wxWidgets"]) then
addTestGroup("ToolKit")
end
end
processTests()

@ -1 +1 @@
Subproject commit ac9d592fbc1b272f25b1b52bf001c021bcf6765f
Subproject commit e3dd28450807c05c7e5c2a878d8506c839b4857e

View File

@ -0,0 +1,137 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Main.cpp
Date: 2022-2-18
Author: Reece
***/
#include <AuroraRuntime.hpp>
#include <gtest/gtest.h>
TEST(Containers, HashMaps)
{
struct HelloKey : public AuEnableHashCodeOnData<HelloKey>
{
AuUInt32 id {};
AuUInt8 task {};
/**
* inline HelloKey(const AuRemoveConst_t<AuRemoveReference_t<decltype(id)>> &id ,const AuRemoveConst_t<AuRemoveReference_t<decltype(task)>> &task) : id(id) ,task(task) {}
* inline HelloKey(AuRemoveConst_t<AuRemoveReference_t<decltype(id)>> &&id ,AuRemoveConst_t<AuRemoveReference_t<decltype(task)>> &&task) : id(id) ,task(task) {}
* inline HelloKey(HelloKey &&cpy) noexcept : id(AuMove(cpy.id)) ,task(AuMove(cpy.task)) {} bool operator==(const HelloKey & ref) const noexcept { return this->id == ref.id && this->task == ref.task ; }
* bool operator==(const HelloKey & ref) const noexcept { return this->id == ref.id && this->task == ref.task ; }
* HelloKey& operator=( HelloKey && ref) noexcept { this->id = AuMove(ref.id); this->task = AuMove(ref.task); return *this; } HelloKey& operator=(const HelloKey & ref) { this->id = ref.id; this->task = ref.task; return *this; };
*/
AU_DEFINE_FOR_VA(HelloKey,
(AU_DEFINE_CTOR_VA, // initializer-list-like ctor (extending AuEnableHashCodeOnData will break lists)
AU_DEFINE_THIS_MOVE_CTOR_VA, // add move HelloKey(HelloKey &&)
AU_DEFINE_EQUALS_VA, // add equals operator
AU_DEFINE_MOVE_VA, // add move assignment operator
AU_DEFINE_COPY_VA), // add copy assignment operator
(id, task));
};
AuHashMap<HelloKey, AuString> a;
ASSERT_TRUE(AuTryInsert(a, HelloKey {0, 4}, "hello world"));
ASSERT_TRUE(AuTryInsert(a, HelloKey {0, 4}, "hello world2"));
ASSERT_FALSE(AuTryInsert(a, HelloKey {0, 4}, "hello world3", false));
}
TEST(Containers, HashMaps2)
{
struct HelloKey
{
AuUInt32 id {};
AuString name {};
AU_DEFINE_CTOR_VA(HelloKey, (id, name))
AU_DEFINE_THIS_MOVE_CTOR_VA(HelloKey, (id, name))
AU_DEFINE_EQUALS_VA(HelloKey, (id, name))
AU_DEFINE_MOVE_VA(HelloKey, (id, name))
AU_DEFINE_COPY_VA(HelloKey, (id, name))
AU_DEFINE_HASHCODE_VA(HelloKey, (id, name))
/* AuUInt HashCode() const noexcept { return AuHashCode(this->id) ^ AuHashCode(this->task) ; } */
};
AuHashMap<HelloKey, AuString> map;
ASSERT_TRUE(AuTryInsert(map, HelloKey {0, "frog"}, "hello world"));
ASSERT_FALSE(AuTryInsert(map, HelloKey {0, "frog"}, "hello world", false));
ASSERT_FALSE(AuTryInsert(&map, HelloKey {0, "frog"}, "hello world", false));
ASSERT_TRUE(AuTryInsert(&map, HelloKey {0, "frog"}, "hello world overwrite", true));
ASSERT_TRUE(AuTryInsert(&map, HelloKey {0, "frog"}, "hello world overwrite 2"));
ASSERT_TRUE(AuExists(map, HelloKey {0, "frog"}));
ASSERT_TRUE(AuExists(&map, HelloKey {0, "frog"}));
ASSERT_TRUE(AuTryRemove(map, HelloKey {0, "frog"}));
ASSERT_FALSE(AuTryRemove(map, HelloKey {0, "frog"}) );
ASSERT_FALSE(AuExists(map, HelloKey {0, "frog"}));
}
TEST(Containers, Lists)
{
AuList<AuUInt8> test;
ASSERT_TRUE(AuListFromArgs(test, 1, 2, 3, 4, 5, 6, 7, 8));
for (AU_ITERATE_N_TO_X(i, 1, 9))
{
ASSERT_TRUE(AuExists(test, i));
}
ASSERT_FALSE(AuExists(test, 9));
ASSERT_TRUE(AuTryInsert(test, 9));
ASSERT_TRUE(AuExists(test, 9));
ASSERT_TRUE(AuTryRemove(test, 5));
ASSERT_FALSE(AuTryRemove(test, 5));
ASSERT_FALSE(AuExists(test, 5));
}
static void StaticAsserts_Tuples()
{
auto tuplePair = AuMakeTuple(AuUInt32(1), AuUInt16(3));
auto popFront = AuTuplePopFront(tuplePair);
auto popBack = AuTuplePopBack(tuplePair);
static_assert(AuIsSame_v<AuUInt16 &, decltype(AuGet<0>(popFront))>);
static_assert(AuIsSame_v<AuUInt32 &, decltype(AuGet<0>(popBack))>);
// TODO:
// AuTuplePushBack
// AuTuplePushFront
// AuTupleTakeRange
// AuTupleForEach
// AuTupleTransform
// AuTupleTie
// AuTupleForward
}
TEST(Debug, NullPointersThrow)
{
#if !defined(AURORA_ROXTL_NULL_POINTER_CHECKS_DISABLED)
AuSPtr<AuUInt32> pGold;
try
{
auto gVal = *pGold;
ASSERT_TRUE(false);
AuLogDbg("ERROR: {}", gVal);
}
catch (...)
{
ASSERT_TRUE(true);
}
#endif
}
void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
Aurora::RuntimeStart(info);
}

View File

@ -27,10 +27,11 @@ static void PrintCPUSpecs()
AuLogInfo("CpuInfo {} / {} / {} [sockets/cores/threads] ", cpuInfo.uSocket, cpuInfo.uCores, cpuInfo.uThreads);
AuLogInfo("Package: {} by {} (arch: {})", cpuInfo.cpuId.brand, cpuInfo.cpuId.vendor, AuBuild::EArchitectureToString(cpuInfo.cpuArch));
AuLogInfo("Complete CPUs: {} ", cpuInfo.serverTopology.size());
AuLogInfo("All CPUs: {} ({}) ", cpuInfo.maskAllCores.ToString(), cpuInfo.coreTopology.size());
AuLogInfo("E-Cores: {} ", cpuInfo.maskECores.ToString());
for (const auto &cpu : cpuInfo.serverTopology)
AuLogInfo("P-Cores: {} ", cpuInfo.maskPCores.ToString());
for (const auto &cpu : cpuInfo.coreTopology)
{
AuLogInfo("Core: {}", cpu.ToString());
}
@ -99,7 +100,6 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
PrintSoftwareSpecs();

View File

@ -7,17 +7,19 @@
Note: Run the registry template in the ./Aurora/Runtime/Media directory
***/
#include <AuroraRuntime.hpp>
#include <gtest/gtest.h>
static void WriteHelloToEventLogGlobal()
TEST(Echo, HelloReplacedGlobalLogger)
{
auto logger = AuLog::NewLoggerShared(AuList<AuSPtr<AuLog::IBasicSink>>{
AuLog::NewOSNamedEventDirectorySinkShared("Aurora Demo"),
AuLog::NewStdSinkShared()
});
SysAssert(logger);
ASSERT_TRUE(logger);
AuLog::SetGlobalLogger(logger);
AuLogInfo("Hello event log and stdout from from global AuLogInfo shorthand");
AuLogInfo("Hello event log and stdout from the global AuLogInfo shorthand");
try
{
AU_THROW_STRING("Crinkled and delivered with many of seethes, hello event log");
@ -26,23 +28,135 @@ static void WriteHelloToEventLogGlobal()
{
}
AuLog::SetGlobalLogger({});
}
static void SayHelloEventLog()
TEST(Echo, HelloEventDir)
{
auto logger = AuLog::NewLoggerShared(AuList<AuSPtr<AuLog::IBasicSink>>{AuLog::NewOSNamedEventDirectorySinkShared("Aurora Demo")});
ASSERT_TRUE(logger);
logger->LogInfo("hello 2+2={}", 2 + 2);
}
TEST(Echo, TextFile)
{
{
auto logger = AuLog::NewLoggerShared(AuList<AuSPtr<AuLog::IBasicSink>>{AuLog::NewFileSinkShared("~/TestLog.txt")});
ASSERT_TRUE(logger);
logger->LogInfo("hello text file 2+2={}", 2 + 2);
}
AuString log;
ASSERT_TRUE(AuIOFS::ReadString("~/TestLog.txt", log));
ASSERT_TRUE(AuStringContains(log, "hello text file"));
}
TEST(Echo, RingBuffer)
{
AuList<AuSPtr<AuLog::IBasicSink>> sinks;
auto rb = AuLog::NewRingLoggerShared(10'000);
auto cpy = rb;
ASSERT_TRUE(rb);
ASSERT_TRUE(AuListFromArgs(sinks, AuReference(rb)));
auto logger = AuLog::NewLoggerShared(sinks);
ASSERT_TRUE(logger);
for (int i = 0; i < 20'000; i++)
{
logger->LogInfo("hello text file 2+2*n={}", 2 + (2 * i));
}
auto list = cpy->Export();
ASSERT_TRUE(list.size());
logger.reset(); // ensure flush
AuLogInfo("RB contains: {} ({}-{}-{}...)", list.size(), list[0].line, list[1].line, list[2].line);
}
/**
* Test 1) @ 1'000'000 LogInfo with format
* [2022-03-31 03:14:15] [Debug] | [Benchmark] Push a boat-load of messages to a ring buffer took 225.05837ms
* [2022-03-31 13:05:02] [Debug] | [Benchmark] Push a boat-load of messages to a ring buffer took 227.09539ms
* [2022-03-31 13:05:19] [Debug] | [Benchmark] Push a boat-load of messages to a ring buffer took 228.08899ms
* [2022-03-31 13:05:32] [Debug] | [Benchmark] Push a boat-load of messages to a ring buffer took 224.04797ms
* [2022-03-31 13:05:43] [Debug] | [Benchmark] Push a boat-load of messages to a ring buffer took 228.00956ms
* 225.05837 / 1000000 = 0.00022505837 ms/tick
* 1000 / 0.00022505837 = 4'443'291 entries per second
* at 225ns per formatted LogInfo
*/
TEST(Echo, BenchmarckRingbuffer)
{
AuList<AuSPtr<AuLog::IBasicSink>> sinks;
auto rb = AuLog::NewRingLoggerShared(10'000);
auto cpy = rb;
ASSERT_TRUE(rb);
ASSERT_TRUE(AuListFromArgs(sinks, AuReference(rb)));
auto logger = AuLog::NewLoggerShared(sinks);
ASSERT_TRUE(logger);
{
SysBenchmark("Push a boat-load of messages to a ring buffer");
for (int i = 0; i < 1'000'000; i++)
{
logger->LogInfo("hello text file 2+2*n={}", 2 + (2 * i));
}
}
}
// Enabling this test will bog down deinit, on-crash, or a dtor somewhere
// One does not simply buffer ~400-500MB of data and expect the notoriously slow
// terminal hosts, character devices, and so on to keep up
// Benchmark data is unreliable, though the relevant profiled user-code seems to be limited to a spinlock
#if 0
TEST(Echo, BenchmarckMain)
{
{
SysBenchmark("Push a boat-load of messages to a stdout");
for (int i = 0; i < 1'000'000; i++)
{
AuLogInfo("hello main 2+2*n={}", 2 + (2 * i));
}
}
}
#endif
/**
* Test 1) @ 10'000 AuLogInfo with format
* [2022-03-31 13:01:09] [Debug] | [Benchmark] Push a few messages to a stdout took 2.06834ms
* [2022-03-31 13:06:54] [Debug] | [Benchmark] Push a few messages to a stdout took 2.06753ms
* [2022-03-31 13:07:23] [Debug] | [Benchmark] Push a few messages to a stdout took 3.00249ms
* [2022-03-31 13:07:32] [Debug] | [Benchmark] Push a few messages to a stdout took 2.05887ms
* 2 / 10000 = 0.000206834 ms/tick
* 1000 / 0.000206834 = 4'834'795 entries per second
* at 206.834ns per formatted AuLogInfo
*/
TEST(Echo, BenchmarckLite)
{
{
SysBenchmark("Push a few messages to a stdout and friends");
for (int i = 0; i < 10'000; i++)
{
AuLogInfo("hello global logger 2+2*n={}", 2 + (2 * i));
}
}
}
void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
info.console.asyncVSLog = true;
Aurora::RuntimeStart(info);
SayHelloEventLog();
WriteHelloToEventLogGlobal();
AuLogInfo("Hello global logger");
}

View File

@ -35,13 +35,12 @@ TEST(Process, RunSystem)
}
process->AsWaitable()->Lock();
AuLogDbg("Exit Code: 0x{:x}", process->GetExitCode());
AuLogDbg("Exit Code: 0x{:x}", (AuUInt)process->GetExitCode());
}
void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
}

View File

@ -104,6 +104,76 @@ TEST(RWLocks, GodMode)
rwlock->AsReadable()->Unlock();
}
/**
* @brief Test write-entrant read-routines
*/
TEST(RWLocks, GodMode2)
{
auto rwlock = AuThreadPrimitives::RWLockUnique();
// Test exclusive ownership
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_FALSE(rwlock->AsWritable()->TryLock());
rwlock->AsReadable()->Unlock();
// Test write-entrancy
{
AU_LOCK_GUARD(rwlock->AsWritable())
// Enter read routines
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
rwlock->AsReadable()->Unlock(); // NOP
rwlock->AsReadable()->Unlock(); // NOP
rwlock->AsReadable()->Unlock(); // NOP
}
// Confirm release
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
rwlock->AsReadable()->Unlock();
}
/**
* @brief Test write-entrant read-routines w/ write-mode escalation
*
* UpgradeReadToWrite:
* "Allows for read-to-write upgrades when the decision to esclate is made based upon a shared resource
* "which would be lost by unlocking and relocking in exclusive mode"
*
*/
TEST(RWLocks, SlashGod)
{
auto rwlock = AuThreadPrimitives::RWLockUnique();
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_FALSE(rwlock->AsWritable()->TryLock());
ASSERT_TRUE(rwlock->UpgradeReadToWrite(0));
{
// Enter read routines
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
rwlock->AsReadable()->Unlock(); // NOP
rwlock->AsReadable()->Unlock(); // NOP
rwlock->AsReadable()->Unlock(); // NOP
}
ASSERT_TRUE(rwlock->DowngradeWriteToRead());
ASSERT_FALSE(rwlock->DowngradeWriteToRead());
rwlock->AsReadable()->Unlock();
}
/**
* @brief Allocates a new thread, dispatches the ep, destroys the thread, and waits a reasonable amount of time
* to rejoin until the the context is terminated by the watchdog. In this instance, the thread exists in time.
@ -229,7 +299,7 @@ TEST(Thread, ForcefulExitNoFree)
}
// TODO: sample and test code for:
// * Events
// * Events (does it run igors piss 7zip code was a good test lmao)
// * Condition Variables
// * Rentrant Mutexes
// * Sleep
@ -241,6 +311,5 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
}

View File

@ -18,9 +18,15 @@
* Despite this, GetFlags and GetValues will unescape \\ on NT platforms.
*
* EG: "3. Hello Command Line.Stage.Win32.x86_64.exe" --test=Hello\ World
* "3. Hello Command Line.Stage.Win32.x86_64.exe" --test="Hello World"
* "3. Hello Command Line.Stage.Win32.x86_64.exe" --test "Hello World"
* "3. Hello Command Line.Stage.Win32.x86_64.exe" /test="Hello World"
* "3. Hello Command Line.Stage.Win32.x86_64.exe" /test "Hello World"
* "3. Hello Command Line.Stage.Win32.x86_64.exe" test="Hello World"
* "3. Hello Command Line.Stage.Win32.x86_64.exe" test=Hello\ World
* [2022-02-20 18:25:48][Info] | Flags: 0
* [2022-02-20 18:25:48][Info] | Values: 1
* [2022-02-20 18:25:48][Info] | --test=Hello World
* [2022-02-20 18:25:48][Info] | test=Hello World
*/
static void PrintAll()
@ -51,7 +57,6 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
PrintAll();

View File

@ -8,12 +8,40 @@
#include <AuroraRuntime.hpp>
#include <gtest/gtest.h>
/*
Blocking read/write test
Test 1)
Input parameters: 1k cycles, 32B RNG
With 4k ops and 1600ms average
~= 0.4ms per blocking read/write
Test 2)
Input parameters: 1k cycles, 64KiB RNG
Result: FS.WriteRead (9248 ms)
> 9248 / 4 (ops)
2312 (time per op)
> (64 *1024 * 1000) / 2312 (bytes / ms)
28346.020761245676
> 28346 / 1024 (kB / ms)
27.681640625
> 27 * 1000 (kB / s)
27000
> 27000 / 1024 (mB / s)
26.3671875
26 MB/s or 208Mb/s
29/03/2022 (under vm vdisk and with nt caching)
*/
TEST(FS, WriteRead)
{
AuByteBuffer rngbuffer(32);
AuByteBuffer inputblob;
AuRng::RngFillRange(rngbuffer);
for (int i = 0; i < 1000; i++)
{
// Write and read back the RNG blob from a read/writable CWD
ASSERT_TRUE(AuIOFS::WriteFile("./test_rng_blob", rngbuffer));
ASSERT_TRUE(AuIOFS::ReadFile("./test_rng_blob", inputblob));
@ -24,6 +52,7 @@ TEST(FS, WriteRead)
ASSERT_TRUE(AuIOFS::WriteFile("~/my_app_rng_blob", rngbuffer));
ASSERT_TRUE(AuIOFS::ReadFile("~/my_app_rng_blob", inputblob));
ASSERT_EQ(inputblob, rngbuffer);
}
}
TEST(FS, WriteCopyRead)
@ -151,7 +180,6 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
info.fio.defaultBrand = "AuSdkBrand";
Aurora::RuntimeStart(info);

View File

@ -20,13 +20,11 @@ TEST(Loop, Semaphore)
ASSERT_TRUE(loop->SourceAdd(semaB));
ASSERT_TRUE(loop->SourceAddWithTimeout(semac, 2000));
// Commit source changes
ASSERT_TRUE(loop->Commit());
auto semACallback = AuMakeShared<Aurora::Loop::ILoopSourceSubscriberFunctional>([](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> bool
{
AuLogInfo("Hello from semaphore a's work queue");
return false; // dont evict, we'll reuse this *1
return false; // dont evict, we'll reuse this *1 (search for me)
});
auto semBCallback = AuMakeShared<Aurora::Loop::ILoopSourceSubscriberFunctional>([](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> bool
@ -47,11 +45,15 @@ TEST(Loop, Semaphore)
AuLogInfo("C timedout succesfully!");
});
// Add optional subscriptions (must come after commit)
// Add optional subscriptions
ASSERT_TRUE(loop->AddCallback(semaA, semACallback));
ASSERT_TRUE(loop->AddCallback(semaB, semBCallback));
ASSERT_TRUE(loop->AddCallbackEx(semac, semCCallback));
// Commit source changes
ASSERT_TRUE(loop->Commit());
// Dispatch any (IE: semaphore A) non-blocking
ASSERT_TRUE(loop->IsSignaled());
@ -61,6 +63,7 @@ TEST(Loop, Semaphore)
// And demonstrate blocking function
ASSERT_TRUE(loop->WaitAny(0)); // *1
// ...or what about now? now will you block?
ASSERT_FALSE(loop->WaitAny(1000));
// Trigger A and B
@ -81,10 +84,146 @@ TEST(Loop, Semaphore)
ASSERT_TRUE(loop->WaitAll(100));
}
TEST(Loop, Performance)
{
SysBenchmark("Loop Performance A");
auto semaA = Aurora::Loop::NewLSSemaphore(1);
auto semaB = Aurora::Loop::NewLSSemaphore(0);
auto semac = Aurora::Loop::NewLSSemaphore(0);
auto loop = Aurora::Loop::NewLoopQueue();
auto semACallback = AuMakeShared<Aurora::Loop::ILoopSourceSubscriberFunctional>([](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> bool
{
//AuLogInfo("Hello from semaphore a's work queue");
return false; // dont evict, we'll reuse this *1
});
auto semBCallback = AuMakeShared<Aurora::Loop::ILoopSourceSubscriberFunctional>([](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> bool
{
//AuLogInfo("Hello from semaphore b's work queue");
return true; // evict
});
auto semCCallback = AuMakeShared<Aurora::Loop::ILoopSourceSubscriberExFunctional>([](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> bool
{
//AuLogInfo("This should not have been triggered from C");
return false;
},
[](const AuSPtr<Aurora::Loop::ILoopSource> &source) -> void
{
//AuLogInfo("C timedout succesfully!");
});
/*
------------------------------------------------------------------------------------
NT:
At 10k iterations:
[2022-03-31 13:10:29] [Debug] | [Benchmark] Loop Performance A took 51.01004ms
[2022-03-31 13:10:54] [Debug] | [Benchmark] Loop Performance A took 50.02065ms
...not bad, here's why:
Reece, [30/03/2022 19:39]
1 whole frame (~20Hhz) of work to blast WaitForMultipleObjectsEx/io_submit/epoll abstraction with a test covering multiple apis 10k times/iterations
Reece, [30/03/2022 19:39]
imagine a scheduling thread working on 10k unique kernel work objects per frame
Reece, [30/03/2022 19:39]
that alone isn't comparable to sockets because sockets are grouped into 1 worker event per thread
Reece, [30/03/2022 19:40]
general purpose work should go through semaphores and condition variables, not a unique object per work item
Reece, [30/03/2022 19:40]
it would be like sleeping on a kernel object 40,000 times per frame
Reece, [30/03/2022 19:40]
by "like" i mean 10k iterations * 4 apis that can dispatch a callback or yield to kernel
Reece, [30/03/2022 19:42]
best practices say you dont fucking spam resources. 40k is a hell of a lot more than, idk, checking a file read transaction a few tens-to-hundreds of times a second on an serializer thread that's not-io bound
Further data:
VS Profiler reports: 1.6% other, 77.5% IO, kernel: 20%
[TODO: link]
...almost all of the overhead is the semaphore callbacks themselves
[TODO: link]
Needless to say, I think this is alright.
------------------------------------------------------------------------------------
Linux: TODO: io_submit
------------------------------------------------------------------------------------
BSD: kevent is a long way away
------------------------------------------------------------------------------------
*/
for (int i = 0; i < 10'000; i++)
{
// Add initial loop sources
ASSERT_TRUE(loop->SourceAdd(semaA));
ASSERT_TRUE(loop->SourceAdd(semaB));
ASSERT_TRUE(loop->SourceAddWithTimeout(semac, 2000));
// Add optional subscriptions
ASSERT_TRUE(loop->AddCallback(semaA, semACallback));
ASSERT_TRUE(loop->AddCallback(semaB, semBCallback));
ASSERT_TRUE(loop->AddCallbackEx(semac, semCCallback));
// Commit source changes
ASSERT_TRUE(loop->Commit());
// Dispatch any (IE: semaphore A) non-blocking
ASSERT_TRUE(loop->IsSignaled());
// Reuse semaphore A
semaA->AddOne(); // *1
// And demonstrate blocking function
ASSERT_TRUE(loop->WaitAny(0)); // *1
//ASSERT_FALSE(loop->WaitAny(1000));
// Trigger A and B
semaB->AddOne();
semaA->AddOne();
// Dispatch all
ASSERT_TRUE(loop->WaitAny(1000));
// Stall for 10s unless A comes alives (it wont)
//loop->WaitAll(10000);
//ASSERT_FALSE(loop->WaitAll(100));
// Manually evict semaphore A
loop->SourceRemove(semaA);
loop->SourceRemove(semac);
loop->Commit();
ASSERT_TRUE(loop->WaitAll(100));
semaA->AddOne(); // account for initial starting count of 1
}
printf(".");
}
void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
info.console.asyncVSLog = true;
Aurora::RuntimeStart(info);
}

View File

@ -89,7 +89,7 @@ static AuByteBuffer GetCompressableBlob()
return compressMeBytes;
}
static void TestBasicCompression(AuCompression::ECompresionType type)
static void TestBasicCompression(AuCompression::ECompressionType type)
{
auto compressMeBytes = GetCompressableBlob();
@ -172,7 +172,7 @@ static void TestBasicCompression(AuCompression::ECompresionType type)
#define ADD_TESTS_BASIC(algorithm) \
TEST(BasicCompression, algorithm) \
{ \
TestBasicCompression(AuCompression::ECompresionType::e ## algorithm); \
TestBasicCompression(AuCompression::ECompressionType::e ## algorithm); \
}
#define ADD_TESTS(...) AU_FOR_EACH(ADD_TESTS_BASIC, __VA_ARGS__)
@ -183,6 +183,5 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
}

View File

@ -80,7 +80,7 @@ TEST(Parse, Vararg)
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseNumber, "Bravo"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "String", false, false, true)
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "Charlie", false, false, true)
};
AuString str = "4 5.3 \"re eee\" hello world";
@ -109,7 +109,7 @@ TEST(Parse, Arrays)
AuParse::ParseObject exampleStructure =
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Int Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "String Fren", true, false, false)
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "String Bravo", true, false, false)
};
AuString str = "4 3 \"re eee\" hello world";
@ -142,7 +142,7 @@ TEST(Parse, ArraysReserialize)
AuParse::ParseObject exampleStructure =
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Int Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "String Fren", true, false, false)
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "String Bravo", true, false, false)
};
AuString reserialized;
@ -214,8 +214,8 @@ TEST(Parse, NewLine)
AuParse::ParseObject exampleStructure =
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "StringHog"),
AuParse::ParseBit(AuParse::ParsableTag::kParseStringVararg, "String")
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "Bravo"),
AuParse::ParseBit(AuParse::ParsableTag::kParseStringVararg, "Charlie")
};
AuString magicStringEscaped = "\"world\nhello\"";
@ -250,7 +250,7 @@ TEST(Parse, Escapes)
AuParse::ParseObject exampleStructure =
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "StringHog"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "Bravo"),
};
AuString magicStringEscaped = "\"world \\\"hello\"";
@ -280,7 +280,7 @@ TEST(Parse, EscapesReserialize)
AuParse::ParseObject exampleStructure =
{
AuParse::ParseBit(AuParse::ParsableTag::kParseUInt, "Alpha"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "StringHog"),
AuParse::ParseBit(AuParse::ParsableTag::kParseString, "Bravo"),
};
AuString reserialized;
@ -297,6 +297,5 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
}

View File

@ -85,7 +85,6 @@ void RunTests()
{
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
info.console.forceToolKitWindow = false;
Aurora::RuntimeStart(info);
PrintLocale();

View File

@ -0,0 +1,34 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Main.cpp
Date: 2022-2-18
Author: Reece
***/
#include <AuroraRuntime.hpp>
void RunTests()
{
std::random_device dev;
std::mt19937 mt(dev());
uuids::uuid_random_generator gen(mt);
Aurora::RuntimeStartInfo info;
info.console.fio.enableLogging = false;
Aurora::RuntimeStart(info);
auto A = gen();
auto B = gen();
auto C = uuids::uuid::from_string(A.to_string());
auto D = uuids::uuid::from_string(B.to_string());
SysAssert(C == A);
SysAssert(B == D);
AuLogDbg("a");
}

@ -1 +1 @@
Subproject commit 955c7f837efad184ec63e771c42542d37545eaef
Subproject commit af29db7ec28d6df1c7f0f745186884091e602e07

2
Vendor/nlohmannjson vendored

@ -1 +1 @@
Subproject commit e4643d1f1b03fc7a1d7b65f17e012ca93680cad8
Subproject commit 66f6b4b6a0b897e91f7fdd5f6058a8c62137895f

2
Vendor/wxConfig vendored

@ -1 +1 @@
Subproject commit dc2f9971d1f60aa357a758a014b79dd2f31345a5
Subproject commit 014af5d92895b598e866b441131e43eef9e57dd7

2
Vendor/wxwidgets vendored

@ -1 +1 @@
Subproject commit f81e0ed2cbccf2d9ffba4a93b5948f4cf46111d7
Subproject commit 37d983ef6f3461c19e0e983eb3886e4e6978859f

2
Win_x64_Lite.bat Normal file
View File

@ -0,0 +1,2 @@
cd .\Build_Scripts
win_x64.bat --lite %*

2
Win_x64_NoToolkit.bat Normal file
View File

@ -0,0 +1,2 @@
cd .\Build_Scripts
win_x64.bat

2
Win_x64_wxWidgets.bat Normal file
View File

@ -0,0 +1,2 @@
cd .\Build_Scripts
win_x64.bat --with-wxWidgets %*

2
Win_x86_Lite.bat Normal file
View File

@ -0,0 +1,2 @@
cd .\Build_Scripts
win_x86.bat --lite %*