diff --git a/README.md b/README.md
index 7108fdd..9759a87 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,6 @@ It is a general purpose C++ library that can help developers create various kind
Please go to https://gitlab.com/ii887522/nitro to start contributing instead.
## Prerequisites
-- Windows 10
- [Docker Desktop](https://www.docker.com/products/docker-desktop) using Windows containers
- [Visual Studio Code](https://code.visualstudio.com/)
- Docker
@@ -33,23 +32,23 @@ Please go to https://gitlab.com/ii887522/nitro to start contributing instead.
## Update .NET Framework SDK version used by ms-build-tools to match your OS
1. Left click on the start button at the bottom left corner of your desktop.
-
+
2. Left click on the settings button at the left side of the start menu.
-
+
3. Left click on the system button at the top left corner of settings window.
-
+
4. Left click on the about button at the bottom left corner of settings window.
-
+
5. Take note of the version shown in the settings window. You will need it to search for appropriate tags later.
-
+
6. Go to https://hub.docker.com/_/microsoft-dotnet-framework-sdk/ and find Full Tag Listing section.
@@ -81,3 +80,8 @@ install
```sh
build
```
+
+### Deploy project
+```sh
+deploy
+```
diff --git a/deploy.cmd b/deploy.cmd
new file mode 100644
index 0000000..0ba693f
--- /dev/null
+++ b/deploy.cmd
@@ -0,0 +1,4 @@
+docker run --rm --name nitro_bundler -w C:\nitro -v %CD%:C:\nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c mkdir libs && cd libs && mkdir nitro && cd nitro && mkdir include && cd include && xcopy ..\..\..\nitro\src\main\ .\ /s && cd .. && mkdir lib && cd lib && mkdir x86 && cd x86 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\Release\nitro.lib .\ && cd .. && cd .. && mkdir x64 && cd x64 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\x64\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\x64\Release\nitro.lib .\ && cd .. && cd .. && cd .. && cd .. && cd ..
+docker run --rm --name nitro_zipper -w C:\nitro\libs -v %CD%\libs:C:\nitro\libs kiazhi/nanoserver.7-zip:1709-18.05 7z a nitro.zip nitro\
+docker run --rm --name nitro_publisher -v %CD%\libs:C:\nitro\libs stefanscherer/curl-windows:7.58.0 --header "PRIVATE-TOKEN: %1" --upload-file C:\nitro\libs\nitro.zip https://gitlab.com/api/v4/projects/23530641/packages/generic/nitro/1.0.0/nitro.zip
+docker run --rm --name nitro_cleaner -w C:\nitro -v %CD%:C:\nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c rmdir libs /s /q
diff --git a/deploy.sh b/deploy.sh
new file mode 100644
index 0000000..44b9597
--- /dev/null
+++ b/deploy.sh
@@ -0,0 +1,4 @@
+docker run --rm --name nitro_bundler -w C:/nitro -v $PWD:C:/nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c mkdir libs && cd libs && mkdir nitro && cd nitro && mkdir include && cd include && xcopy ..\..\..\nitro\src\main\ .\ /s && cd .. && mkdir lib && cd lib && mkdir x86 && cd x86 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\Release\nitro.lib .\ && cd .. && cd .. && mkdir x64 && cd x64 && mkdir Debug && cd Debug && copy ..\..\..\..\..\nitro\x64\Debug\nitro.lib .\ && cd .. && mkdir Release && cd Release && copy ..\..\..\..\..\nitro\x64\Release\nitro.lib .\ && cd .. && cd .. && cd .. && cd .. && cd ..
+docker run --rm --name nitro_zipper -w C:/nitro/libs -v $PWD/libs:C:/nitro/libs kiazhi/nanoserver.7-zip:1709-18.05 7z a nitro.zip nitro\
+docker run --rm --name nitro_publisher -v $PWD/libs:C:/nitro/libs stefanscherer/curl-windows:7.58.0 --header "PRIVATE-TOKEN: %1" --upload-file C:\nitro\libs\nitro.zip https://gitlab.com/api/v4/projects/23530641/packages/generic/nitro/1.0.0/nitro.zip
+docker run --rm --name nitro_cleaner -w C:/nitro -v $PWD:C:/nitro mcr.microsoft.com/windows/servercore:20H2 cmd /c rmdir libs /s /q
diff --git a/nitro/nitro.vcxproj b/nitro/nitro.vcxproj
index e508d93..2bc712e 100644
--- a/nitro/nitro.vcxproj
+++ b/nitro/nitro.vcxproj
@@ -26,6 +26,34 @@
x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
16.0
Win32Proj
@@ -134,7 +162,7 @@
Level4
true
- TEST;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ TEST;LINEAR_ALLOCATOR;LONG_TERM_ALLOCATOR_SIZE=5304u;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpplatest
stdc17
@@ -187,7 +215,7 @@
Level4
true
- TEST;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ TEST;LINEAR_ALLOCATOR;LONG_TERM_ALLOCATOR_SIZE=8168u;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpplatest
stdc17
@@ -220,9 +248,6 @@
true
-
-
-
diff --git a/nitro/nitro.vcxproj.filters b/nitro/nitro.vcxproj.filters
index 79656db..6590d8f 100644
--- a/nitro/nitro.vcxproj.filters
+++ b/nitro/nitro.vcxproj.filters
@@ -19,10 +19,120 @@
{b6579c0e-bfe8-4b51-a187-60404b74ee71}
+
+ {f0392f57-51f8-4dc9-97a3-b81564a6f838}
+
+
+ {a72974c4-fac4-4d9d-b801-d13def8aac60}
+
+
+ {179e3bd4-fe02-4d7f-b2c3-639b6eb8d1b2}
+
+
+ {8784fcff-f52c-416a-b6f4-8a214819be53}
+
+
+ {a853a5d0-5bcd-465b-82a6-3dffb5baa298}
+
+
+ {72b06555-60e9-4409-a99e-73b6d6a528d2}
+
+
+ {3d0bbcbf-74bb-4101-ac26-4038e54e4683}
+
+
+ {19558d27-8bc0-4ec7-9c03-6af01d816423}
+
+
+ {82739f87-9db2-42b4-b145-3e1617770a1d}
+
+
+ {3e1422de-17a3-4af0-b792-303b91900ac7}
+
+
+ {3bed952f-5fd6-4645-8fb4-13f0598a4dbe}
+
+
+ {89423a92-d04d-44fb-b078-e3c3909887d4}
+
+
+ {32fab255-14c2-421b-b489-35537f8e9d5e}
+
+
+
+
+ Header Files\Any
+
+
+ Header Files\Any
+
+
+ Header Files\Functions
+
+
+ Header Files\Functions
+
+
+ Header Files\Struct
+
+
+ Header Files\Struct
+
+
+ Header Files\Reactive
+
+
+ Header Files\Reactive
+
+
+ Test Header Files\Any
+
+
+ Test Header Files\Any
+
+
+ Test Header Files\Functions
+
+
+ Test Header Files\Functions
+
+
+ Test Header Files\Struct
+
+
+ Test Header Files\Reactive
+
+
+ Test Header Files\Reactive
+
-
- Test Source Files
+
+ Test Source Files\Functions
+
+
+ Test Source Files\Functions
+
+
+ Test Source Files\Functions
+
+
+ Test Source Files\Struct
+
+
+ Test Source Files\Reactive
+
+
+ Test Source Files\Reactive
+
+
+ Test Source Files\Any
+
+
+ Test Source Files\Any
+
+
+ Header Files\Allocator
\ No newline at end of file
diff --git a/nitro/src/main/Allocator/linear_allocator.h b/nitro/src/main/Allocator/linear_allocator.h
new file mode 100644
index 0000000..fb973f3
--- /dev/null
+++ b/nitro/src/main/Allocator/linear_allocator.h
@@ -0,0 +1,103 @@
+#ifdef LINEAR_ALLOCATOR
+
+#ifndef II887522_NITRO_LINEAR_ALLOCATOR_H
+#define II887522_NITRO_LINEAR_ALLOCATOR_H
+
+#include "../Functions/math_ext.h"
+#include
+
+using ii887522::nitro::min;
+using std::bad_alloc;
+
+#ifdef _DEBUG
+#include
+
+using std::cout;
+#endif
+
+namespace ii887522::nitro
+{
+ enum class Term : unsigned int
+ {
+ LONG, SHORT
+ };
+
+ static char longTermData[LONG_TERM_ALLOCATOR_SIZE];
+ static size_t longTermDataSize{ 0u };
+#ifdef SHORT_TERM_ALLOCATOR_SIZE
+ static char shortTermData[SHORT_TERM_ALLOCATOR_SIZE];
+ static size_t shortTermDataSize{ 0u };
+#endif
+ static Term term{ Term::LONG };
+
+ constexpr static size_t getAlignedDataSize(const size_t dataSize, const size_t size)
+ {
+ const auto alignmentRequirement{ min(size, alignof(max_align_t)) };
+ return (dataSize / alignmentRequirement + 1u) * alignmentRequirement;
+ }
+
+ // Not Thread Safe
+ static void* longTermAlloc(const size_t size)
+ {
+ longTermDataSize = getAlignedDataSize(longTermDataSize, size);
+ const auto result{ longTermData + longTermDataSize };
+ longTermDataSize += size;
+#ifdef _DEBUG
+ cout << "Long term data usage: " << longTermDataSize << " bytes\n";
+#endif
+ return result;
+ }
+
+
+ // Not Thread Safe
+ static void* shortTermAlloc(const size_t size)
+ {
+#ifdef SHORT_TERM_ALLOCATOR_SIZE
+ shortTermDataSize = getAlignedDataSize(shortTermDataSize, size);
+ const auto result{ shortTermData + shortTermDataSize };
+ shortTermDataSize += size;
+#ifdef _DEBUG
+ cout << "Short term data usage: " << shortTermDataSize << " bytes\n";
+#endif
+ return result;
+#else
+ size;
+ return nullptr;
+#endif
+ }
+
+#ifdef SHORT_TERM_ALLOCATOR_SIZE
+ constexpr void beginShortTermAlloc()
+ {
+ term = Term::SHORT;
+ }
+
+ constexpr void endShortTermAlloc()
+ {
+ shortTermDataSize = 0u;
+ term = Term::LONG;
+ }
+#endif
+}
+
+using ii887522::nitro::Term;
+using ii887522::nitro::term;
+using ii887522::nitro::longTermAlloc;
+using ii887522::nitro::shortTermAlloc;
+
+// Not Thread Safe
+void* operator new(const size_t size)
+{
+ switch (term)
+ {
+ case Term::LONG: return longTermAlloc(size);
+ case Term::SHORT: return shortTermAlloc(size);
+ }
+ throw bad_alloc{ };
+}
+
+// Not Thread Safe
+void operator delete(void*const) { }
+
+#endif
+#endif
diff --git a/nitro/src/main/Any/AnimatedAny.h b/nitro/src/main/Any/AnimatedAny.h
new file mode 100644
index 0000000..915ce62
--- /dev/null
+++ b/nitro/src/main/Any/AnimatedAny.h
@@ -0,0 +1,114 @@
+#ifndef II887522_NITRO_ANIMATED_ANY_H
+#define II887522_NITRO_ANIMATED_ANY_H
+
+#include "../Functions/math_ext.h"
+#include "../Struct/Range.h"
+#include
+#include
+#include
+#include "Reactive.h"
+#include
+
+using std::runtime_error;
+using std::string;
+using std::function;
+
+namespace ii887522::nitro
+{
+ // Param T: it must not be equal to unsigned type
+ template struct AnimatedAny final
+ {
+ // Not Thread Safe
+ class Builder final
+ {
+ // remove copy semantics
+ Builder(const Builder&) = delete;
+ Builder& operator=(const Builder&) = delete;
+
+ // remove move semantics
+ Builder(Builder&&) = delete;
+ Builder& operator=(Builder&&) = delete;
+
+ const T value;
+ unsigned int duration; // animation duration
+ bool hasSetDuration; // has set animation duration
+ const function onAnimationEnd;
+
+ public:
+ explicit constexpr Builder(const T& value, const function& onAnimationEnd = []() { }) : value{ value }, duration{ 0u },
+ hasSetDuration{ false }, onAnimationEnd{ onAnimationEnd } { }
+
+ // Animation duration
+ // Param p_value: it must not be assigned to 0
+ // Must Call Time(s): At least 1
+ constexpr Builder& setDuration(const unsigned int p_value)
+ {
+ duration = p_value;
+ hasSetDuration = true;
+ return *this;
+ }
+
+ // Must Call Time(s): At least 1
+ AnimatedAny build()
+ {
+ if (hasSetDuration) return AnimatedAny{ *this };
+ throw runtime_error{ string{ "AnimatedAny<" } + typeid(T).name() + "> duration is required!" };
+ }
+
+ friend struct AnimatedAny;
+ };
+
+ private:
+ T start;
+ T now;
+ T end;
+ const unsigned int duration; // animation duration
+ unsigned int elaspedTime;
+ const function onAnimationEnd;
+
+ explicit constexpr AnimatedAny(const Builder& builder) : start{ builder.value }, now{ builder.value }, end{ builder.value },
+ duration{ builder.duration }, elaspedTime{ 0u }, onAnimationEnd{ builder.onAnimationEnd } { }
+
+ public:
+ constexpr const T& getStart() const
+ {
+ return start;
+ }
+
+ constexpr const T& get() const
+ {
+ return now;
+ }
+
+ constexpr const T& getEnd() const
+ {
+ return end;
+ }
+
+ constexpr void set(const T& value)
+ {
+ start = now;
+ end = value;
+ elaspedTime = 0u;
+ }
+
+ constexpr void teleport(const T& value)
+ {
+ start = now;
+ now = value;
+ end = value;
+ elaspedTime = duration;
+ }
+
+ constexpr void step(const unsigned int dt)
+ {
+ if (elaspedTime == duration) return;
+ elaspedTime += dt;
+ clamp(elaspedTime, Range{ 0u, duration });
+ now = static_cast(start + (end - start) * (static_cast(elaspedTime) / duration));
+ if (elaspedTime == duration) onAnimationEnd();
+ }
+ };
+}
+
+#endif
diff --git a/nitro/src/main/Any/Reactive.h b/nitro/src/main/Any/Reactive.h
new file mode 100644
index 0000000..ad32038
--- /dev/null
+++ b/nitro/src/main/Any/Reactive.h
@@ -0,0 +1,47 @@
+#ifndef II887522_NITRO_REACTIVE_H
+#define II887522_NITRO_REACTIVE_H
+
+#include
+#include
+
+using std::function;
+using std::vector;
+
+namespace ii887522::nitro
+{
+ // Not Thread Safe
+ template class Reactive
+ {
+ // remove copy semantics
+ Reactive(const Reactive&) = delete;
+ Reactive& operator=(const Reactive&) = delete;
+
+ // remove move semantics
+ Reactive(Reactive&&) = delete;
+ Reactive& operator=(Reactive&&) = delete;
+
+ T value;
+ vector> handlers;
+
+ public:
+ explicit constexpr Reactive(const T& value) : value{ value } { }
+
+ constexpr const T& get() const
+ {
+ return value;
+ }
+
+ virtual void set(const T& p_value, const int ignoredHandlerI = -1)
+ {
+ value = p_value;
+ for (auto i{ 0u }; i != handlers.size(); ++i) if (static_cast(i) != ignoredHandlerI) handlers[i](value, i);
+ }
+
+ constexpr void watch(const function& handler)
+ {
+ handlers.push_back(handler);
+ }
+ };
+}
+
+#endif
diff --git a/nitro/src/main/Functions/math_ext.h b/nitro/src/main/Functions/math_ext.h
new file mode 100644
index 0000000..8947f50
--- /dev/null
+++ b/nitro/src/main/Functions/math_ext.h
@@ -0,0 +1,35 @@
+#ifndef II887522_NITRO_MATH_EXT_H
+#define II887522_NITRO_MATH_EXT_H
+
+#include "../Struct/Range.h"
+
+namespace ii887522::nitro
+{
+ template constexpr void clamp(T& value, const Range& range)
+ {
+ if (value < range.min) value = range.min;
+ else if (value > range.max) value = range.max;
+ }
+
+ template constexpr bool isOverlapX(const T& x, const Range& xRange)
+ {
+ return x >= xRange.min && x < xRange.max;
+ }
+
+ template constexpr bool isOverlapY(const T& y, const Range& yRange)
+ {
+ return y >= yRange.min && y < yRange.max;
+ }
+
+ template constexpr T min(const T& l, const T& r)
+ {
+ return l < r ? l : r;
+ }
+
+ template constexpr T max(const T& l, const T& r)
+ {
+ return l > r ? l : r;
+ }
+}
+
+#endif
diff --git a/nitro/src/main/Functions/queue_ext.h b/nitro/src/main/Functions/queue_ext.h
new file mode 100644
index 0000000..30622f2
--- /dev/null
+++ b/nitro/src/main/Functions/queue_ext.h
@@ -0,0 +1,16 @@
+#ifndef II887522_NITRO_QUEUE_EXT_H
+#define II887522_NITRO_QUEUE_EXT_H
+
+#include
+
+using std::queue;
+
+namespace ii887522::nitro
+{
+ template void clear(queue& queue)
+ {
+ while (!queue.empty()) queue.pop();
+ }
+}
+
+#endif
diff --git a/nitro/src/main/Reactive/BinaryReactive.h b/nitro/src/main/Reactive/BinaryReactive.h
new file mode 100644
index 0000000..ea6edbc
--- /dev/null
+++ b/nitro/src/main/Reactive/BinaryReactive.h
@@ -0,0 +1,57 @@
+#ifndef II887522_NITRO_BINARY_REACTIVE_H
+#define II887522_NITRO_BINARY_REACTIVE_H
+
+#include "../Any/Reactive.h"
+#include
+#include
+
+using std::vector;
+using std::function;
+
+namespace ii887522::nitro
+{
+ // Not Thread Safe
+ template class BinaryReactive final : public Reactive
+ {
+ // remove copy semantics
+ BinaryReactive(const BinaryReactive&) = delete;
+ BinaryReactive& operator=(const BinaryReactive&) = delete;
+
+ // remove move semantics
+ BinaryReactive(BinaryReactive&&) = delete;
+ BinaryReactive& operator=(BinaryReactive&&) = delete;
+
+ vector*> children;
+ vector> functions;
+ vector*> thats;
+
+ public:
+ explicit constexpr BinaryReactive(const T& value) : Reactive{ value } { }
+
+ explicit constexpr BinaryReactive(BinaryReactive*const leftParent, BinaryReactive*const rightParent,
+ const function& function) :
+ Reactive{ function(leftParent ? &leftParent->get() : nullptr, rightParent ? &rightParent->get() : nullptr) }
+ {
+ if (leftParent)
+ {
+ leftParent->children.push_back(this);
+ leftParent->functions.push_back(function);
+ leftParent->thats.push_back(rightParent);
+ }
+ if (rightParent)
+ {
+ rightParent->children.push_back(this);
+ rightParent->functions.push_back(function);
+ rightParent->thats.push_back(leftParent);
+ }
+ }
+
+ virtual void set(const T& value, const int ignoredHandlerI = -1) override
+ {
+ Reactive::set(value, ignoredHandlerI);
+ for (auto i{ 0u }; i != children.size(); ++i) children[i]->set(functions[i](&this->get(), thats[i] ? &thats[i]->get() : nullptr));
+ }
+ };
+}
+
+#endif
diff --git a/nitro/src/main/Reactive/UnaryReactive.h b/nitro/src/main/Reactive/UnaryReactive.h
new file mode 100644
index 0000000..6beab9c
--- /dev/null
+++ b/nitro/src/main/Reactive/UnaryReactive.h
@@ -0,0 +1,46 @@
+#ifndef II887522_NITRO_UNARY_REACTIVE_H
+#define II887522_NITRO_UNARY_REACTIVE_H
+
+#include "../Any/Reactive.h"
+#include
+#include
+
+using std::vector;
+using std::function;
+
+namespace ii887522::nitro
+{
+ // Not Thread Safe
+ template class UnaryReactive final : public Reactive
+ {
+ // remove copy semantics
+ UnaryReactive(const UnaryReactive&) = delete;
+ UnaryReactive& operator=(const UnaryReactive&) = delete;
+
+ // remove move semantics
+ UnaryReactive(UnaryReactive&&) = delete;
+ UnaryReactive& operator=(UnaryReactive&&) = delete;
+
+ vector*> children;
+ vector> functions;
+
+ public:
+ explicit constexpr UnaryReactive(const T& value) : Reactive{ value } { }
+
+ explicit constexpr UnaryReactive(UnaryReactive*const parent, const function& function) :
+ Reactive{ function(parent ? &parent->get() : nullptr) }
+ {
+ if (!parent) return;
+ parent->children.push_back(this);
+ parent->functions.push_back(function);
+ }
+
+ virtual void set(const T& value, const int ignoredHandlerI = -1) override
+ {
+ Reactive::set(value, ignoredHandlerI);
+ for (auto i{ 0u }; i != children.size(); ++i) children[i]->set(functions[i](&this->get()));
+ }
+ };
+}
+
+#endif
diff --git a/nitro/src/main/Struct/Range.h b/nitro/src/main/Struct/Range.h
new file mode 100644
index 0000000..d3dba27
--- /dev/null
+++ b/nitro/src/main/Struct/Range.h
@@ -0,0 +1,24 @@
+#ifndef II887522_NITRO_RANGE_H
+#define II887522_NITRO_RANGE_H
+
+namespace ii887522::nitro
+{
+ template struct Range final
+ {
+ // remove copy semantics
+ Range(const Range&) = delete;
+ Range& operator=(const Range&) = delete;
+
+ // remove move semantics
+ Range(Range&&) = delete;
+ Range& operator=(Range&&) = delete;
+
+ const T min;
+ const T max;
+
+ public:
+ explicit constexpr Range(const T& min, const T& max) : min{ min }, max{ max } { }
+ };
+}
+
+#endif
diff --git a/nitro/src/main/Struct/Vector.h b/nitro/src/main/Struct/Vector.h
new file mode 100644
index 0000000..ebf0ba7
--- /dev/null
+++ b/nitro/src/main/Struct/Vector.h
@@ -0,0 +1,20 @@
+#ifndef II887522_NITRO_VECTOR_H
+#define II887522_NITRO_VECTOR_H
+
+namespace ii887522::nitro
+{
+ template struct Vector final
+ {
+ T x;
+ T y;
+
+ explicit constexpr Vector(const T& x, const T& y) : x{ x }, y{ y } { }
+
+ template constexpr Vector operator*(const U& scale) const
+ {
+ return Vector{ static_cast(x * scale), static_cast(y * scale) };
+ }
+ };
+}
+
+#endif
diff --git a/nitro/src/test/Any/AnimatedAny.test.cpp b/nitro/src/test/Any/AnimatedAny.test.cpp
new file mode 100644
index 0000000..808f3df
--- /dev/null
+++ b/nitro/src/test/Any/AnimatedAny.test.cpp
@@ -0,0 +1,244 @@
+#ifdef TEST
+
+#include "AnimatedAny.test.h"
+#include
+#include "../../main/Any/AnimatedAny.h"
+#include "../../main/Any/Reactive.h"
+#include
+
+using std::runtime_error;
+
+namespace ii887522::nitro
+{
+ static void testBuild()
+ {
+ assert(AnimatedAny::Builder{ 0 }.setDuration(250u).build().get() == 0);
+ assert(AnimatedAny::Builder{ 1 }.setDuration(250u).build().get() == 1);
+ assert(AnimatedAny::Builder{ 1 }.setDuration(500u).build().get() == 1);
+ {
+ auto n{ 0u };
+ assert((AnimatedAny::Builder{ 1, [&n]() {
+ ++n;
+ } }.setDuration(500u).build().get() == 1));
+ assert(n == 0u);
+ }
+ try
+ {
+ AnimatedAny::Builder{ 0 }.build();
+ }
+ catch (const runtime_error&)
+ {
+ try
+ {
+ AnimatedAny::Builder{ 1 }.build();
+ }
+ catch (const runtime_error&)
+ {
+ try
+ {
+ auto n{ 0u };
+ AnimatedAny::Builder{ 1, [&n]() {
+ ++n;
+ } }.build();
+ }
+ catch (const runtime_error&)
+ {
+ return;
+ }
+ }
+ }
+ assert(false);
+ }
+
+ static void testTeleport()
+ {
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 0 }.setDuration(250u).build() };
+ n.teleport(1);
+ assert(n.getStart() == 0);
+ assert(n.get() == 1);
+ assert(n.getEnd() == 1);
+ n.teleport(2);
+ assert(n.getStart() == 1);
+ assert(n.get() == 2);
+ assert(n.getEnd() == 2);
+ }
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(250u).build() };
+ n.teleport(1);
+ assert(n.getStart() == 10);
+ assert(n.get() == 1);
+ assert(n.getEnd() == 1);
+ n.teleport(2);
+ assert(n.getStart() == 1);
+ assert(n.get() == 2);
+ assert(n.getEnd() == 2);
+ }
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(500u).build() };
+ n.teleport(1);
+ assert(n.getStart() == 10);
+ assert(n.get() == 1);
+ assert(n.getEnd() == 1);
+ n.teleport(2);
+ assert(n.getStart() == 1);
+ assert(n.get() == 2);
+ assert(n.getEnd() == 2);
+ }
+ {
+ auto m{ 0u };
+ AnimatedAny n{ AnimatedAny::Builder{ 10, [&m]() {
+ ++m;
+ } }.setDuration(500u).build() };
+ n.teleport(1);
+ assert(n.getStart() == 10);
+ assert(n.get() == 1);
+ assert(n.getEnd() == 1);
+ assert(m == 0u);
+ n.teleport(2);
+ assert(n.getStart() == 1);
+ assert(n.get() == 2);
+ assert(n.getEnd() == 2);
+ assert(m == 0u);
+ }
+ }
+
+ static void testStep()
+ {
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 0 }.setDuration(250u).build() };
+ n.set(100);
+ n.step(0u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 0);
+ assert(n.getEnd() == 100);
+ n.step(30u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 12);
+ assert(n.getEnd() == 100);
+ n.step(40u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 28);
+ assert(n.getEnd() == 100);
+ n.step(50u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 48);
+ assert(n.getEnd() == 100);
+ n.step(60u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 72);
+ assert(n.getEnd() == 100);
+ n.step(70u);
+ assert(n.getStart() == 0);
+ assert(n.get() == 100);
+ assert(n.getEnd() == 100);
+ }
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(250u).build() };
+ n.set(110);
+ n.step(0u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 10);
+ assert(n.getEnd() == 110);
+ n.step(30u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 22);
+ assert(n.getEnd() == 110);
+ n.step(40u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 38);
+ assert(n.getEnd() == 110);
+ n.step(50u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 58);
+ assert(n.getEnd() == 110);
+ n.step(60u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 82);
+ assert(n.getEnd() == 110);
+ n.step(70u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 110);
+ assert(n.getEnd() == 110);
+ }
+ {
+ AnimatedAny n{ AnimatedAny::Builder{ 10 }.setDuration(500u).build() };
+ n.set(110);
+ n.step(0u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 10);
+ assert(n.getEnd() == 110);
+ n.step(60u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 22);
+ assert(n.getEnd() == 110);
+ n.step(80u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 38);
+ assert(n.getEnd() == 110);
+ n.step(100u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 58);
+ assert(n.getEnd() == 110);
+ n.step(120u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 82);
+ assert(n.getEnd() == 110);
+ n.step(140u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 110);
+ assert(n.getEnd() == 110);
+ }
+ {
+ auto m{ 0u };
+ AnimatedAny n{ AnimatedAny::Builder{ 10, [&m]() {
+ ++m;
+ } }.setDuration(500u).build() };
+ n.set(110);
+ n.step(0u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 10);
+ assert(n.getEnd() == 110);
+ assert(m == 0u);
+ n.step(60u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 22);
+ assert(n.getEnd() == 110);
+ assert(m == 0u);
+ n.step(80u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 38);
+ assert(n.getEnd() == 110);
+ assert(m == 0u);
+ n.step(100u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 58);
+ assert(n.getEnd() == 110);
+ assert(m == 0u);
+ n.step(120u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 82);
+ assert(n.getEnd() == 110);
+ assert(m == 0u);
+ n.step(140u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 110);
+ assert(n.getEnd() == 110);
+ assert(m == 1u);
+ n.step(10u);
+ assert(n.getStart() == 10);
+ assert(n.get() == 110);
+ assert(n.getEnd() == 110);
+ assert(m == 1u);
+ }
+ }
+
+ void testAnimatedAny()
+ {
+ testBuild();
+ testTeleport();
+ testStep();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Any/AnimatedAny.test.h b/nitro/src/test/Any/AnimatedAny.test.h
new file mode 100644
index 0000000..1d60e8f
--- /dev/null
+++ b/nitro/src/test/Any/AnimatedAny.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_ANIMATED_ANY_TEST_H
+#define II887522_NITRO_ANIMATED_ANY_TEST_H
+
+namespace ii887522::nitro
+{
+ void testAnimatedAny();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Any/Reactive.test.cpp b/nitro/src/test/Any/Reactive.test.cpp
new file mode 100644
index 0000000..9881f48
--- /dev/null
+++ b/nitro/src/test/Any/Reactive.test.cpp
@@ -0,0 +1,69 @@
+#ifdef TEST
+
+#include "Reactive.test.h"
+#include "../../main/Any/Reactive.h"
+#include
+
+namespace ii887522::nitro
+{
+ static void testSet()
+ {
+ {
+ Reactive n{ 0u };
+ n.set(1u);
+ assert(n.get() == 1u);
+ auto count{ 0u };
+ n.watch([&count](const unsigned int& value, const int) {
+ count += value;
+ });
+ n.set(2u);
+ assert(n.get() == 2u);
+ assert(count == 2u);
+ n.watch([&count](const unsigned int& value, const int) {
+ count += value;
+ });
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(count == 8u);
+ n.watch([&n, &count](const unsigned int& value, const int handlerI) {
+ count += value;
+ n.set(count, handlerI);
+ });
+ n.set(4u);
+ assert(n.get() == 20u);
+ assert(count == 60u);
+ }
+ {
+ Reactive n{ 2u };
+ n.set(1u);
+ assert(n.get() == 1u);
+ auto count{ 0u };
+ n.watch([&count](const unsigned int& value, const int) {
+ count += value;
+ });
+ n.set(2u);
+ assert(n.get() == 2u);
+ assert(count == 2u);
+ n.watch([&count](const unsigned int& value, const int) {
+ count += value;
+ });
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(count == 8u);
+ n.watch([&n, &count](const unsigned int& value, const int handlerI) {
+ count += value;
+ n.set(count, handlerI);
+ });
+ n.set(4u);
+ assert(n.get() == 20u);
+ assert(count == 60u);
+ }
+ }
+
+ void testReactive()
+ {
+ testSet();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Any/Reactive.test.h b/nitro/src/test/Any/Reactive.test.h
new file mode 100644
index 0000000..18e34f2
--- /dev/null
+++ b/nitro/src/test/Any/Reactive.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_REACTIVE_TEST_H
+#define II887522_NITRO_REACTIVE_TEST_H
+
+namespace ii887522::nitro
+{
+ void testReactive();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Functions/math_ext.test.cpp b/nitro/src/test/Functions/math_ext.test.cpp
new file mode 100644
index 0000000..546475f
--- /dev/null
+++ b/nitro/src/test/Functions/math_ext.test.cpp
@@ -0,0 +1,118 @@
+#ifdef TEST
+
+#include "math_ext.test.h"
+#include
+#include "../../main/Functions/math_ext.h"
+#include "../../main/Struct/Range.h"
+
+namespace ii887522::nitro
+{
+ static void testClamp()
+ {
+ {
+ auto n{ 0u };
+ clamp(n, Range{ 1u, 3u });
+ assert(n == 1u);
+ }
+ {
+ auto n{ 1u };
+ clamp(n, Range{ 1u, 3u });
+ assert(n == 1u);
+ }
+ {
+ auto n{ 2u };
+ clamp(n, Range{ 1u, 3u });
+ assert(n == 2u);
+ }
+ {
+ auto n{ 3u };
+ clamp(n, Range{ 1u, 3u });
+ assert(n == 3u);
+ }
+ {
+ auto n{ 4u };
+ clamp(n, Range{ 1u, 3u });
+ assert(n == 3u);
+ }
+ {
+ auto n{ 0u };
+ clamp(n, Range{ 2u, 6u });
+ assert(n == 2u);
+ }
+ {
+ auto n{ 2u };
+ clamp(n, Range{ 2u, 6u });
+ assert(n == 2u);
+ }
+ {
+ auto n{ 4u };
+ clamp(n, Range{ 2u, 6u });
+ assert(n == 4u);
+ }
+ {
+ auto n{ 6u };
+ clamp(n, Range{ 2u, 6u });
+ assert(n == 6u);
+ }
+ {
+ auto n{ 8u };
+ clamp(n, Range{ 2u, 6u });
+ assert(n == 6u);
+ }
+ }
+
+ constexpr static void testIsOverlapX()
+ {
+ static_assert(!isOverlapX(0u, Range{ 1u, 3u }));
+ static_assert(isOverlapX(1u, Range{ 1u, 3u }));
+ static_assert(isOverlapX(2u, Range{ 1u, 3u }));
+ static_assert(!isOverlapX(3u, Range{ 1u, 3u }));
+ static_assert(!isOverlapX(4u, Range{ 1u, 3u }));
+ static_assert(!isOverlapX(0u, Range{ 2u, 6u }));
+ static_assert(isOverlapX(2u, Range{ 2u, 6u }));
+ static_assert(isOverlapX(4u, Range{ 2u, 6u }));
+ static_assert(!isOverlapX(6u, Range{ 2u, 6u }));
+ static_assert(!isOverlapX(8u, Range{ 2u, 6u }));
+ }
+
+ constexpr static void testIsOverlapY()
+ {
+ static_assert(!isOverlapY(0u, Range{ 1u, 3u }));
+ static_assert(isOverlapY(1u, Range{ 1u, 3u }));
+ static_assert(isOverlapY(2u, Range{ 1u, 3u }));
+ static_assert(!isOverlapY(3u, Range{ 1u, 3u }));
+ static_assert(!isOverlapY(4u, Range{ 1u, 3u }));
+ static_assert(!isOverlapY(0u, Range{ 2u, 6u }));
+ static_assert(isOverlapY(2u, Range{ 2u, 6u }));
+ static_assert(isOverlapY(4u, Range{ 2u, 6u }));
+ static_assert(!isOverlapY(6u, Range{ 2u, 6u }));
+ static_assert(!isOverlapY(8u, Range{ 2u, 6u }));
+ }
+
+ constexpr static void testMin()
+ {
+ static_assert(min(0u, 0u) == 0u);
+ static_assert(min(1u, 0u) == 0u);
+ static_assert(min(1u, 1u) == 1u);
+ static_assert(min(1u, 2u) == 1u);
+ }
+
+ constexpr static void testMax()
+ {
+ static_assert(max(0u, 0u) == 0u);
+ static_assert(max(1u, 0u) == 1u);
+ static_assert(max(1u, 1u) == 1u);
+ static_assert(max(1u, 2u) == 2u);
+ }
+
+ void testMathExt()
+ {
+ testClamp();
+ testIsOverlapX();
+ testIsOverlapY();
+ testMin();
+ testMax();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Functions/math_ext.test.h b/nitro/src/test/Functions/math_ext.test.h
new file mode 100644
index 0000000..59fbfcd
--- /dev/null
+++ b/nitro/src/test/Functions/math_ext.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_MATH_EXT_TEST_H
+#define II887522_NITRO_MATH_EXT_TEST_H
+
+namespace ii887522::nitro
+{
+ void testMathExt();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Functions/queue_ext.test.cpp b/nitro/src/test/Functions/queue_ext.test.cpp
new file mode 100644
index 0000000..caf22a5
--- /dev/null
+++ b/nitro/src/test/Functions/queue_ext.test.cpp
@@ -0,0 +1,41 @@
+#ifdef TEST
+
+#include "queue_ext.test.h"
+#include "../../main/Functions/queue_ext.h"
+#include
+#include
+
+using std::queue;
+
+namespace ii887522::nitro
+{
+ static void testClear()
+ {
+ queue queue;
+ clear(queue);
+ assert(queue.empty());
+ assert(queue.size() == 0u);
+ queue.push(1u);
+ clear(queue);
+ assert(queue.empty());
+ assert(queue.size() == 0u);
+ queue.push(2u);
+ queue.push(3u);
+ clear(queue);
+ assert(queue.empty());
+ assert(queue.size() == 0u);
+ queue.push(4u);
+ queue.push(5u);
+ queue.push(6u);
+ clear(queue);
+ assert(queue.empty());
+ assert(queue.size() == 0u);
+ }
+
+ void testQueueExt()
+ {
+ testClear();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Functions/queue_ext.test.h b/nitro/src/test/Functions/queue_ext.test.h
new file mode 100644
index 0000000..d65ee24
--- /dev/null
+++ b/nitro/src/test/Functions/queue_ext.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_QUEUE_EXT_TEST_H
+#define II887522_NITRO_QUEUE_EXT_TEST_H
+
+namespace ii887522::nitro
+{
+ void testQueueExt();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Functions/test.cpp b/nitro/src/test/Functions/test.cpp
new file mode 100644
index 0000000..b433ea4
--- /dev/null
+++ b/nitro/src/test/Functions/test.cpp
@@ -0,0 +1,31 @@
+#ifdef TEST
+
+#include "../Struct/Vector.test.h"
+#include "math_ext.test.h"
+#include "../Any/AnimatedAny.test.h"
+#include "../Any/Reactive.test.h"
+#include "../Functions/queue_ext.test.h"
+#include "../Reactive/UnaryReactive.test.h"
+#include "../Reactive/BinaryReactive.test.h"
+
+namespace ii887522::nitro
+{
+ static int main()
+ {
+ testVector();
+ testMathExt();
+ testAnimatedAny();
+ testReactive();
+ testQueueExt();
+ testUnaryReactive();
+ testBinaryReactive();
+ return 0;
+ }
+}
+
+int main()
+{
+ return ii887522::nitro::main();
+}
+
+#endif
diff --git a/nitro/src/test/Reactive/BinaryReactive.test.cpp b/nitro/src/test/Reactive/BinaryReactive.test.cpp
new file mode 100644
index 0000000..deefda6
--- /dev/null
+++ b/nitro/src/test/Reactive/BinaryReactive.test.cpp
@@ -0,0 +1,198 @@
+#ifdef TEST
+
+#include "BinaryReactive.test.h"
+#include "../../main/Reactive/BinaryReactive.h"
+#include
+#include
+
+namespace ii887522::nitro
+{
+ static void testSet()
+ {
+ {
+ BinaryReactive m{ 0u };
+ m.set(1u);
+ assert(m.get() == 1u);
+ BinaryReactive n{ 1u };
+ n.set(2u);
+ assert(n.get() == 2u);
+ BinaryReactive p{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return *left + *right;
+ }
+ };
+ m.set(2u);
+ assert(m.get() == 2u);
+ assert(p.get() == 4u);
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(p.get() == 5u);
+ BinaryReactive q{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return *left * *right;
+ }
+ };
+ m.set(3u);
+ assert(m.get() == 3u);
+ assert(p.get() == 6u);
+ assert(q.get() == 9u);
+ n.set(4u);
+ assert(n.get() == 4u);
+ assert(p.get() == 7u);
+ assert(q.get() == 12u);
+ BinaryReactive r{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return static_cast(pow(*left, *right));
+ }
+ };
+ m.set(4u);
+ assert(m.get() == 4u);
+ assert(p.get() == 8u);
+ assert(q.get() == 16u);
+ assert(r.get() == 256u);
+ n.set(5u);
+ assert(n.get() == 5u);
+ assert(p.get() == 9u);
+ assert(q.get() == 20u);
+ assert(r.get() == 625u);
+
+ BinaryReactive s{
+ &m, nullptr, [](const unsigned int*const left, const unsigned int*const) {
+ return *left;
+ }
+ };
+ m.set(5u);
+ assert(m.get() == 5u);
+ assert(p.get() == 10u);
+ assert(q.get() == 25u);
+ assert(r.get() == 3125u);
+ assert(s.get() == 5u);
+ n.set(6u);
+ assert(n.get() == 6u);
+ assert(p.get() == 11u);
+ assert(q.get() == 30u);
+ assert(r.get() == 7776u);
+ assert(s.get() == 5u);
+ BinaryReactive t{
+ nullptr, &n, [](const unsigned int*const, const unsigned int*const) {
+ return 0u;
+ }
+ };
+ m.set(6u);
+ assert(m.get() == 6u);
+ assert(p.get() == 12u);
+ assert(q.get() == 36u);
+ assert(r.get() == 46656u);
+ assert(s.get() == 6u);
+ assert(t.get() == 0u);
+ n.set(7u);
+ assert(n.get() == 7u);
+ assert(p.get() == 13u);
+ assert(q.get() == 42u);
+ assert(r.get() == 117649u);
+ assert(s.get() == 6u);
+ assert(t.get() == 0u);
+ BinaryReactive u{
+ nullptr, nullptr, [](const unsigned int*const, const unsigned int*const) {
+ return 1u;
+ }
+ };
+ }
+ {
+ BinaryReactive m{ 2u };
+ m.set(1u);
+ assert(m.get() == 1u);
+ BinaryReactive n{ 3u };
+ n.set(2u);
+ assert(n.get() == 2u);
+ BinaryReactive p{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return *left + *right;
+ }
+ };
+ m.set(2u);
+ assert(m.get() == 2u);
+ assert(p.get() == 4u);
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(p.get() == 5u);
+ BinaryReactive q{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return *left * *right;
+ }
+ };
+ m.set(3u);
+ assert(m.get() == 3u);
+ assert(p.get() == 6u);
+ assert(q.get() == 9u);
+ n.set(4u);
+ assert(n.get() == 4u);
+ assert(p.get() == 7u);
+ assert(q.get() == 12u);
+ BinaryReactive r{
+ &m, &n, [](const unsigned int*const left, const unsigned int*const right) {
+ return static_cast(pow(*left, *right));
+ }
+ };
+ m.set(4u);
+ assert(m.get() == 4u);
+ assert(p.get() == 8u);
+ assert(q.get() == 16u);
+ assert(r.get() == 256u);
+ n.set(5u);
+ assert(n.get() == 5u);
+ assert(p.get() == 9u);
+ assert(q.get() == 20u);
+ assert(r.get() == 625u);
+
+ BinaryReactive s{
+ &m, nullptr, [](const unsigned int*const left, const unsigned int*const) {
+ return *left;
+ }
+ };
+ m.set(5u);
+ assert(m.get() == 5u);
+ assert(p.get() == 10u);
+ assert(q.get() == 25u);
+ assert(r.get() == 3125u);
+ assert(s.get() == 5u);
+ n.set(6u);
+ assert(n.get() == 6u);
+ assert(p.get() == 11u);
+ assert(q.get() == 30u);
+ assert(r.get() == 7776u);
+ assert(s.get() == 5u);
+ BinaryReactive t{
+ nullptr, &n, [](const unsigned int*const, const unsigned int*const) {
+ return 0u;
+ }
+ };
+ m.set(6u);
+ assert(m.get() == 6u);
+ assert(p.get() == 12u);
+ assert(q.get() == 36u);
+ assert(r.get() == 46656u);
+ assert(s.get() == 6u);
+ assert(t.get() == 0u);
+ n.set(7u);
+ assert(n.get() == 7u);
+ assert(p.get() == 13u);
+ assert(q.get() == 42u);
+ assert(r.get() == 117649u);
+ assert(s.get() == 6u);
+ assert(t.get() == 0u);
+ BinaryReactive u{
+ nullptr, nullptr, [](const unsigned int* const, const unsigned int* const) {
+ return 1u;
+ }
+ };
+ }
+ }
+
+ void testBinaryReactive()
+ {
+ testSet();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Reactive/BinaryReactive.test.h b/nitro/src/test/Reactive/BinaryReactive.test.h
new file mode 100644
index 0000000..e8e2923
--- /dev/null
+++ b/nitro/src/test/Reactive/BinaryReactive.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_BINARY_REACTIVE_TEST_H
+#define II887522_NITRO_BINARY_REACTIVE_TEST_H
+
+namespace ii887522::nitro
+{
+ void testBinaryReactive();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Reactive/UnaryReactive.test.cpp b/nitro/src/test/Reactive/UnaryReactive.test.cpp
new file mode 100644
index 0000000..2c257ce
--- /dev/null
+++ b/nitro/src/test/Reactive/UnaryReactive.test.cpp
@@ -0,0 +1,78 @@
+#ifdef TEST
+
+#include "UnaryReactive.test.h"
+#include "../../main/Reactive/UnaryReactive.h"
+#include
+#include
+
+namespace ii887522::nitro
+{
+ static void testSet()
+ {
+ {
+ UnaryReactive n{ 0u };
+ n.set(1u);
+ assert(n.get() == 1u);
+ UnaryReactive nx{ &n, [](const unsigned int*const value) {
+ return *value + *value;
+ } };
+ n.set(2u);
+ assert(n.get() == 2u);
+ assert(nx.get() == 4u);
+ UnaryReactive ny{ &n, [](const unsigned int*const value) {
+ return *value * *value;
+ } };
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(nx.get() == 6u);
+ assert(ny.get() == 9u);
+ UnaryReactive nz{ &n, [](const unsigned int*const value) {
+ return static_cast(sqrt(*value));
+ } };
+ n.set(4u);
+ assert(n.get() == 4u);
+ assert(nx.get() == 8u);
+ assert(ny.get() == 16u);
+ assert(nz.get() == 2u);
+ UnaryReactive nw{ nullptr, [](const unsigned int*const) {
+ return 0u;
+ } };
+ }
+ {
+ UnaryReactive n{ 2u };
+ n.set(1u);
+ assert(n.get() == 1u);
+ UnaryReactive nx{ &n, [](const unsigned int*const value) {
+ return *value + *value;
+ } };
+ n.set(2u);
+ assert(n.get() == 2u);
+ assert(nx.get() == 4u);
+ UnaryReactive ny{ &n, [](const unsigned int*const value) {
+ return *value * *value;
+ } };
+ n.set(3u);
+ assert(n.get() == 3u);
+ assert(nx.get() == 6u);
+ assert(ny.get() == 9u);
+ UnaryReactive nz{ &n, [](const unsigned int*const value) {
+ return static_cast(sqrt(*value));
+ } };
+ n.set(4u);
+ assert(n.get() == 4u);
+ assert(nx.get() == 8u);
+ assert(ny.get() == 16u);
+ assert(nz.get() == 2u);
+ UnaryReactive nw{ nullptr, [](const unsigned int*const) {
+ return 0u;
+ } };
+ }
+ }
+
+ void testUnaryReactive()
+ {
+ testSet();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Reactive/UnaryReactive.test.h b/nitro/src/test/Reactive/UnaryReactive.test.h
new file mode 100644
index 0000000..2721c19
--- /dev/null
+++ b/nitro/src/test/Reactive/UnaryReactive.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_UNARY_REACTIVE_TEST_H
+#define II887522_NITRO_UNARY_REACTIVE_TEST_H
+
+namespace ii887522::nitro
+{
+ void testUnaryReactive();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/Struct/Vector.test.cpp b/nitro/src/test/Struct/Vector.test.cpp
new file mode 100644
index 0000000..d296a82
--- /dev/null
+++ b/nitro/src/test/Struct/Vector.test.cpp
@@ -0,0 +1,22 @@
+#ifdef TEST
+
+#include "Vector.test.h"
+#include "../../main/Struct/Vector.h"
+
+namespace ii887522::nitro
+{
+ constexpr static void testMultiplication()
+ {
+ static_assert((Vector{ 1u, 2u } * 0u).x == 0u);
+ static_assert((Vector{ 3u, 4u } * 1u).y == 4u);
+ static_assert((Vector{ 5u, 6u } * 2u).x == 10u);
+ static_assert((Vector{ 7u, 8u } * 3u).y == 24u);
+ }
+
+ void testVector()
+ {
+ testMultiplication();
+ }
+}
+
+#endif
diff --git a/nitro/src/test/Struct/Vector.test.h b/nitro/src/test/Struct/Vector.test.h
new file mode 100644
index 0000000..18ec28c
--- /dev/null
+++ b/nitro/src/test/Struct/Vector.test.h
@@ -0,0 +1,12 @@
+#ifdef TEST
+
+#ifndef II887522_NITRO_VECTOR_TEST_H
+#define II887522_NITRO_VECTOR_TEST_H
+
+namespace ii887522::nitro
+{
+ void testVector();
+}
+
+#endif
+#endif
diff --git a/nitro/src/test/test.cpp b/nitro/src/test/test.cpp
deleted file mode 100644
index 1496e06..0000000
--- a/nitro/src/test/test.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifdef TEST
-
-namespace ii887522::nitro
-{
- static int main()
- {
-
- return 0;
- }
-}
-
-int main()
-{
- return ii887522::nitro::main();
-}
-
-#endif