diff --git a/CMakeLists.txt b/CMakeLists.txt index c907892..efbba9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,19 +1,11 @@ cmake_minimum_required(VERSION 3.12) -project(gifscript CXX) +project(gifscript CXX C) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}) -# Using CMAKE_CXX_STANDARD doesn't work for GCC... -# This also doesn't work for Clang 14... -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - set(CPP_23_ARG "-std=c++2b") -elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - set(CPP_23_ARG "-std=c++23") -endif() - find_package(RAGEL REQUIRED) set(CORE_DIR ${CMAKE_SOURCE_DIR}/core) @@ -45,9 +37,11 @@ RAGEL_TARGET(gifscript COMPILE_FLAGS -G2 ) +set_source_files_properties(parser.cpp PROPERTIES COMPILE_FLAGS "-Wno-unused-variable") + set(GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/parser.h - ${CMAKE_CURRENT_BINARY_DIR}/parser.c + ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp ${RAGEL_gifscript_OUTPUTS} ) @@ -64,6 +58,7 @@ set(CORE_SOURCES ${CORE_INCLUDE}/logger.hpp ${CORE_INCLUDE}/machine.hpp ${CORE_INCLUDE}/registers.hpp + ${CORE_SRC}/logger.cpp ${CORE_SRC}/machine.cpp ${CORE_SRC}/registers.cpp ) @@ -93,16 +88,22 @@ execute_process( string(CONCAT GIT_VERSION "\"" ${GIT_VERSION} "\"") message("git version: ${GIT_VERSION}") -target_compile_options(gifscript_core PRIVATE -Wall -Werror -Wno-unused-const-variable ${CPP_23_ARG}) -target_compile_options(gifscript PRIVATE -DGIT_VERSION=${GIT_VERSION} -Wall -Werror -Wno-unused-const-variable ${CPP_23_ARG}) -target_compile_options(tpircsfig PRIVATE -DGIT_VERSION=${GIT_VERSION} -Wall -Werror -Wno-unused-const-variable ${CPP_23_ARG}) +target_compile_options(gifscript_core PRIVATE -Wall -Werror -Wno-unused-const-variable) +target_compile_options(gifscript PRIVATE -DGIT_VERSION=${GIT_VERSION} -Wall -Werror -Wno-unused-const-variable) +target_compile_options(tpircsfig PRIVATE -DGIT_VERSION=${GIT_VERSION} -Wall -Werror -Wno-unused-const-variable) target_include_directories(gifscript PUBLIC ${fmt_SOURCE_DIR}/include) target_link_libraries(gifscript_core PUBLIC fmt::fmt) add_custom_command( - OUTPUT parser.c parser.h - COMMAND lemon -q ${CORE_SRC}/parser.y -d${CMAKE_CURRENT_BINARY_DIR} ${LEMON_PARSER_TEMPLATE} + OUTPUT parser.cpp parser.h + COMMAND lemon -q ${CORE_SRC}/parser.y -d${CMAKE_CURRENT_BINARY_DIR} && mv parser.c parser.cpp && sed -i 's/parser.c/parser.cpp/g' parser.cpp DEPENDS ${CORE_SRC}/parser.y USES_TERMINAL ) + +if(NOT DISABLE_TESTS) + include(CTest) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/backends/include/backend.hpp b/backends/include/backend.hpp index 21d960b..a35b420 100644 --- a/backends/include/backend.hpp +++ b/backends/include/backend.hpp @@ -15,3 +15,31 @@ class Backend virtual void emit(GIFBlock& block) = 0; }; + +class DummyBackend : public Backend +{ +public: + DummyBackend() = default; + ~DummyBackend() override = default; + + bool arg_parse(int argc, char** argv) override + { + return true; + } + + void set_output(const std::string_view& output) override + { + (void)output; + } + + void print_help() const override + { + } + + void emit(GIFBlock& block) override + { + (void)block; + } +}; + +static DummyBackend dummy_backend; diff --git a/core/include/logger.hpp b/core/include/logger.hpp index 78288cd..5fa5421 100644 --- a/core/include/logger.hpp +++ b/core/include/logger.hpp @@ -6,6 +6,11 @@ namespace logger { + // Primarily used to disable logging in tests + extern bool g_log_enabled; +#define CHECK_LOGGING_ENABLED() \ + if(!g_log_enabled) \ + return; struct fmt_location { const char* fmt; @@ -23,6 +28,7 @@ namespace logger template void log(fmt_location format, fmt::color fgcol, Args&&... args) { + CHECK_LOGGING_ENABLED(); int size_s = std::snprintf(nullptr, 0, format.fmt, std::forward(args)...); char* buf = new char[size_s + 1]; std::snprintf(buf, size_s + 1, format.fmt, std::forward(args)...); @@ -34,6 +40,7 @@ namespace logger template void info(fmt_location format, Args&&... args) { + CHECK_LOGGING_ENABLED(); fmt::print(fg(fmt::color::blue), "[INFO ] "); log(format, fmt::color::blue, std::forward(args)...); } @@ -41,6 +48,7 @@ namespace logger template void warn(fmt_location format, Args&&... args) { + CHECK_LOGGING_ENABLED(); fmt::print(fg(fmt::color::yellow), "[WARN ] "); log(format, fmt::color::yellow, std::forward(args)...); } @@ -48,6 +56,7 @@ namespace logger template void error(fmt_location format, Args&&... args) { + CHECK_LOGGING_ENABLED(); fmt::print(fg(fmt::color::red), "[ERROR] "); log(format, fmt::color::red, std::forward(args)...); } @@ -55,7 +64,10 @@ namespace logger template void debug(fmt_location format, Args&&... args) { + CHECK_LOGGING_ENABLED(); fmt::print(fg(fmt::color::green), "[DEBUG] "); log(format, fmt::color::green, std::forward(args)...); } }; // namespace logger + +#undef CHECK_LOGGING_ENABLED diff --git a/core/include/machine.hpp b/core/include/machine.hpp index a18a3e3..87314bd 100644 --- a/core/include/machine.hpp +++ b/core/include/machine.hpp @@ -11,7 +11,7 @@ class Machine { - Backend* backend = nullptr; + Backend* backend = &dummy_backend; std::list blocks; std::map macros; diff --git a/core/include/registers.hpp b/core/include/registers.hpp index 5d634c6..c6ddba2 100644 --- a/core/include/registers.hpp +++ b/core/include/registers.hpp @@ -147,10 +147,10 @@ class GifRegister virtual bool Ready() const noexcept = 0; - virtual void Push(uint32_t) = 0; - virtual void Push(Vec2) = 0; - virtual void Push(Vec3) = 0; - virtual void Push(Vec4) = 0; + virtual bool Push(uint32_t) = 0; + virtual bool Push(Vec2) = 0; + virtual bool Push(Vec3) = 0; + virtual bool Push(Vec4) = 0; virtual bool ApplyModifier(RegModifier) = 0; @@ -196,29 +196,28 @@ struct PRIM : public GifRegister return type.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - logger::error("Not supported!"); + return false; } - void Push(Vec2) override + bool Push(Vec2) override { - logger::error("Not supported!"); + return false; } - void Push(Vec3) override + bool Push(Vec3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4) override + bool Push(Vec4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier mod) override { - std::cout << "Applying modifier: " << mod << std::endl; switch(mod) { case Point: @@ -255,7 +254,6 @@ struct PRIM : public GifRegister texture = true; break; default: - std::cerr << "Unknown modifier: " << mod << std::endl; return false; } @@ -308,25 +306,27 @@ struct RGBAQ : public GifRegister return value.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - std::cout << "RGBAQ::Push(uint32_t) Not supported!" << std::endl; + return false; } - void Push(Vec2) override + bool Push(Vec2) override { - std::cout << "RGBAQ::Push(Vec2) Not supported!" << std::endl; + return false; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { value = Vec4(v3.x, v3.y, v3.z, 0xff); + return true; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { std::cout << "!!!! RGBAQ PUSHED " << v4.x << " " << v4.y << " " << v4.z << " " << v4.w << std::endl; value = v4; + return true; } bool ApplyModifier(RegModifier) override @@ -360,24 +360,25 @@ struct UV : public GifRegister return value.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - logger::error("Not supported!"); + return false; } - void Push(Vec2 v2) override + bool Push(Vec2 v2) override { value = v2; + return true; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier) override @@ -410,24 +411,25 @@ struct XYZ2 : public GifRegister return value.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - std::cerr << "XYZ2::Push(uint32_t) Not supported!" << std::endl; + return false; } - void Push(Vec2) override + bool Push(Vec2) override { - std::cerr << "XYZ2::Push(Vec2) Not supported!" << std::endl; + return false; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { value = v3; + return true; } - void Push(Vec4) override + bool Push(Vec4) override { - std::cerr << "XYZ2::Push(Vec4) Not supported!" << std::endl; + return false; } bool ApplyModifier(RegModifier) override @@ -481,7 +483,7 @@ struct TEX0 : public GifRegister return tbp.has_value() && tbw.has_value() && psm.has_value() && tw.has_value() && th.has_value(); } - void Push(uint32_t i) override + bool Push(uint32_t i) override { if(!tbp.has_value()) tbp = i; @@ -492,30 +494,32 @@ struct TEX0 : public GifRegister else if(!th.has_value()) th = i; else - logger::error("Unsure what you're trying to push to TEX0 (%d)", i); + return false; + + + return true; } - void Push(Vec2 v2) override + bool Push(Vec2 v2) override { if(!tw.has_value() && !th.has_value()) { tw = v2.x; th = v2.y; + return true; } - else - { - logger::error("Unsure what you're trying to push to TEX0 (%d, %d)", v2.x, v2.y); - } + + return false; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4) override + bool Push(Vec4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier mod) override @@ -607,24 +611,25 @@ class FOG : public GifRegister return value.has_value(); } - void Push(uint32_t i) override + bool Push(uint32_t i) override { value = i; + return true; } - void Push(Vec2) override + bool Push(Vec2) override { - logger::error("Not supported!"); + return false; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4) override + bool Push(Vec4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier) override @@ -658,24 +663,25 @@ class FOGCOL : public GifRegister return value.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - logger::error("Not supported!"); + return false; } - void Push(Vec2) override + bool Push(Vec2) override { - logger::error("Not supported!"); + return false; } - void Push(Vec3 v3) override + bool Push(Vec3 v3) override { value = v3; + return true; } - void Push(Vec4) override + bool Push(Vec4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier) override @@ -709,24 +715,25 @@ class SCISSOR : public GifRegister return value.has_value(); } - void Push(uint32_t) override + bool Push(uint32_t) override { - logger::error("Not supported!"); + return false; } - void Push(Vec2) override + bool Push(Vec2) override { - logger::error("Not supported!"); + return false; } - void Push(Vec3) override + bool Push(Vec3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { value = v4; + return true; } bool ApplyModifier(RegModifier) override @@ -761,24 +768,26 @@ class SIGNAL : public GifRegister } // Assume that all bits are not masked - void Push(uint32_t i) override + bool Push(uint32_t i) override { value = Vec2(i, ~0u); + return true; } - void Push(Vec2 v2) override + bool Push(Vec2 v2) override { value = v2; + return true; } - void Push(Vec3) override + bool Push(Vec3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier) override @@ -814,24 +823,25 @@ class FINISH : public GifRegister return true; } - void Push(uint32_t i) override + bool Push(uint32_t i) override { value = i; + return true; } - void Push(Vec2) override + bool Push(Vec2) override { - logger::warn("Non-Integer value pushed to FINISH register, ignored."); + return false; } - void Push(Vec3) override + bool Push(Vec3) override { - logger::warn("Non-Integer value pushed to FINISH register, ignored."); + return false; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { - logger::warn("Non-Integer value pushed to FINISH register, ignored."); + return false; } bool ApplyModifier(RegModifier) override @@ -866,24 +876,26 @@ class LABEL : public GifRegister } // Assume that all bits are not masked - void Push(uint32_t i) override + bool Push(uint32_t i) override { value = Vec2{i, ~0u}; + return true; } - void Push(Vec2 v2) override + bool Push(Vec2 v2) override { value = v2; + return true; } - void Push(Vec3) override + bool Push(Vec3) override { - logger::error("Not supported!"); + return false; } - void Push(Vec4 v4) override + bool Push(Vec4 v4) override { - logger::error("Not supported!"); + return false; } bool ApplyModifier(RegModifier) override diff --git a/core/include/types.hpp b/core/include/types.hpp index d7becb8..b5b27ee 100644 --- a/core/include/types.hpp +++ b/core/include/types.hpp @@ -40,6 +40,17 @@ struct Vec2 { uint32_t x, y; + Vec2() + : x(0) + , y(0) + { + } + Vec2(uint32_t x, uint32_t y) + : x(x) + , y(y) + { + } + static Vec2 Parse(const std::string& s) { Vec2 v2; @@ -54,6 +65,19 @@ struct Vec3 { uint32_t x, y, z; + Vec3() + : x(0) + , y(0) + , z(0) + { + } + Vec3(uint32_t x, uint32_t y, uint32_t z) + : x(x) + , y(y) + , z(z) + { + } + static Vec3 Parse(const std::string& s) { Vec3 v3; @@ -69,6 +93,21 @@ struct Vec4 { uint32_t x, y, z, w; + Vec4() + : x(0) + , y(0) + , z(0) + , w(0) + { + } + Vec4(uint32_t x, uint32_t y, uint32_t z, uint32_t w) + : x(x) + , y(y) + , z(z) + , w(w) + { + } + static Vec4 Parse(const std::string& s) { Vec4 v4; diff --git a/core/src/logger.cpp b/core/src/logger.cpp new file mode 100644 index 0000000..a907014 --- /dev/null +++ b/core/src/logger.cpp @@ -0,0 +1,3 @@ +#include "logger.hpp" + +bool logger::g_log_enabled = true; diff --git a/core/src/machine.cpp b/core/src/machine.cpp index 3d99543..91e80f2 100644 --- a/core/src/machine.cpp +++ b/core/src/machine.cpp @@ -78,6 +78,15 @@ auto Machine::TryStartMacro(const std::string& name) -> bool auto Machine::TryEndBlockMacro() -> bool { + if(HasCurrentBlockOrMacro()) + { + if(CurrentBlockMacro().registers.empty()) + { + logger::error("Block/Macro %s has no registers\n", CurrentBlockMacro().name.c_str()); + return false; + } + } + if(HasCurrentBlock()) { FirstPassOptimize(); @@ -180,8 +189,7 @@ auto Machine::TryPushReg(int32_t value) -> bool { if(HasCurrentBlockOrMacro() && CurrentBlockMacro().HasRegister()) [[likely]] { - CurrentBlockMacro().CurrentRegister().Push(value); - return true; + return CurrentBlockMacro().CurrentRegister().Push(value); } logger::error("There is no block, macro or register to push a integer to."); @@ -192,8 +200,7 @@ auto Machine::TryPushReg(Vec2 value) -> bool { if(HasCurrentBlockOrMacro() && CurrentBlockMacro().HasRegister()) [[likely]] { - CurrentBlockMacro().CurrentRegister().Push(value); - return true; + return CurrentBlockMacro().CurrentRegister().Push(value); } logger::error("There is no block, macro or register to push a Vec2 to."); @@ -204,8 +211,7 @@ auto Machine::TryPushReg(Vec3 value) -> bool { if(HasCurrentBlockOrMacro() && CurrentBlockMacro().HasRegister()) [[likely]] { - CurrentBlockMacro().CurrentRegister().Push(value); - return true; + return CurrentBlockMacro().CurrentRegister().Push(value); } logger::error("There is no block, macro or register to push a Vec3 to."); @@ -216,8 +222,7 @@ auto Machine::TryPushReg(Vec4 value) -> bool { if(HasCurrentBlockOrMacro() && CurrentBlockMacro().HasRegister()) [[likely]] { - CurrentBlockMacro().CurrentRegister().Push(value); - return true; + return CurrentBlockMacro().CurrentRegister().Push(value); } logger::error("There is no block, macro or register to push a Vec4 to."); diff --git a/frontends/gifscript.rl b/frontends/gifscript.rl index 06426d9..0c2ff20 100644 --- a/frontends/gifscript.rl +++ b/frontends/gifscript.rl @@ -13,7 +13,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" -#include "parser.c" +#include "parser.cpp" #pragma GCC diagnostic pop #include "registers.hpp" diff --git a/frontends/tpircsfig.cpp b/frontends/tpircsfig.cpp index ce639dc..6404066 100644 --- a/frontends/tpircsfig.cpp +++ b/frontends/tpircsfig.cpp @@ -11,7 +11,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" -#include "parser.c" +#include "parser.cpp" #pragma GCC diagnostic pop static bool valid = true; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..93c800e --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,21 @@ +set(CMAKE_CXX_CLANG_TIDY "") + +cmake_policy(SET CMP0135 NEW) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) + +FetchContent_MakeAvailable(googletest) + +# Type tests +add_executable(type_tests type_tests.cpp) +target_link_libraries(type_tests gtest_main gcov) +target_include_directories(type_tests PRIVATE ${CORE_INCLUDE}) +add_test(NAME type_tests COMMAND type_tests) + +# Core tests +add_executable(core_tests core_tests.cpp) +target_link_libraries(core_tests gtest_main gifscript_core gcov) +target_include_directories(core_tests PRIVATE ${CORE_INCLUDE} ${BACKEND_INCLUDE} ${CMAKE_BINARY_DIR}) +add_test(NAME core_tests COMMAND core_tests) diff --git a/tests/core_tests.cpp b/tests/core_tests.cpp new file mode 100644 index 0000000..4e90c9e --- /dev/null +++ b/tests/core_tests.cpp @@ -0,0 +1,257 @@ +#include +#include + +#include "logger.hpp" +#include "registers.hpp" +#include "machine.hpp" +#include "parser.h" +#include "parser.cpp" + +TEST(MachineTests_StartBlock, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartBlock("block1")); +} + +TEST(MachineTests_StartBlock, Invalid_InBlock) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_FALSE(machine.TryStartBlock("block2")); +} + +TEST(MachineTests_StartBlock, Invalid_ExistingName) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); + + EXPECT_FALSE(machine.TryStartBlock("block1")); +} + +TEST(MachineTests_EndBlock, Invalid_NoBlock) +{ + Machine machine; + + EXPECT_FALSE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_EndBlock, Invalid_EmptyBlock) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_FALSE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_EndBlock, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_StartMacro, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); +} + +TEST(MachineTests_StartMacro, Invalid_InMacro) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_FALSE(machine.TryStartMacro("macro2")); +} + +TEST(MachineTests_EndMacro, Invalid_NoMacro) +{ + Machine machine; + + EXPECT_FALSE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_EndMacro, Invalid_EmptyMacro) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_FALSE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_EndMacro, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); +} + +TEST(MachineTests_StartMacro, Invalid_SameName) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); + + EXPECT_FALSE(machine.TryStartMacro("macro1")); +} + +TEST(MachineTests_SetRegister, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); +} + +TEST(MachineTests_SetRegister, Invalid_NoBlock) +{ + Machine machine; + + EXPECT_FALSE(machine.TrySetRegister(std::make_unique())); +} + +TEST(MachineTests_SetRegister, Invalid_LastRegisterNotFulfilled) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TrySetRegister(std::make_unique())); +} + +TEST(MachineTests_SetRegister, Valid_AfterPreviousSet) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(Vec3(0, 0, 0))); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); +} + +TEST(MachineTests_SetRegister, Invalid_UnexpectedArgument_INT) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryPushReg(0)); +} + +TEST(MachineTests_SetRegister, Invalid_UnexpectedArgument_VEC2) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryPushReg(Vec2(0, 0))); +} + +TEST(MachineTests_SetRegister, Invalid_UnexpectedArgument_VEC3) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryPushReg(Vec3(0, 0, 0))); +} + +TEST(MachineTests_SetRegister, Invalid_UnexpectedArgument_VEC4) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryPushReg(Vec4(0, 0, 0, 0))); +} + +TEST(MachineTests_ApplyModifier, Invalid_NoBlock) +{ + Machine machine; + + EXPECT_FALSE(machine.TryApplyModifier(RegModifier::Gouraud)); +} + +TEST(MachineTests_ApplyModifier, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryApplyModifier(RegModifier::Gouraud)); +} + +TEST(MachineTests_ApplyModifier, Invalid_RegisterAcceptsModifiers) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryApplyModifier(RegModifier::CT32)); +} + +TEST(MachineTests_ApplyModifier, Invalid_RegisterDoesNotAcceptModifiers) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_FALSE(machine.TryApplyModifier(RegModifier::CT32)); +} + +TEST(MachineTests_InsertMacro, Valid) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_TRUE(machine.TryInsertMacro("macro1")); +} + +TEST(MachineTests_InsertMacro, Invalid_DoesNotExist) +{ + Machine machine; + + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); + EXPECT_TRUE(machine.TryStartBlock("block1")); + EXPECT_FALSE(machine.TryInsertMacro("macro2")); +} + +TEST(MachineTests_InsertMacro, Invalid_NoBlock) +{ + Machine machine; + EXPECT_TRUE(machine.TryStartMacro("macro1")); + EXPECT_TRUE(machine.TrySetRegister(std::make_unique())); + EXPECT_TRUE(machine.TryPushReg(0)); + EXPECT_TRUE(machine.TryEndBlockMacro()); + EXPECT_FALSE(machine.TryInsertMacro("macro1")); +} + +int main(void) +{ + logger::g_log_enabled = false; + testing::InitGoogleTest(); + return RUN_ALL_TESTS(); +} diff --git a/tests/type_tests.cpp b/tests/type_tests.cpp new file mode 100644 index 0000000..4af9a73 --- /dev/null +++ b/tests/type_tests.cpp @@ -0,0 +1,275 @@ +#include +#include + +#include "types.hpp" + + +TEST(TypeTests, Vec2_Default) +{ + Vec2 vec; + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); +} + +TEST(TypeTests, Vec2_Constructor) +{ + Vec2 vec(1, 2); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); +} + +TEST(TypeTests, Vec2_ParseInteger) +{ + auto vec = Vec2::Parse("1,2"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); +} + +TEST(TypeTests, Vec2_ParseFloat) +{ + auto vec = Vec2::Parse("1.5,2.5"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); +} + +TEST(TypeTests, Vec2_ParseFloatSuffix) +{ + auto vec = Vec2::Parse("1.5f,2.5f"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); +} + +TEST(TypeTests, Vec2_ParseHex) +{ + auto vec = Vec2::Parse("0xA,0xB"); + EXPECT_EQ(vec.x, 0xA); + EXPECT_EQ(vec.y, 0xB); +} + +TEST(TypeTests, Vec2_ParseMixed) +{ + auto vec = Vec2::Parse("1,2.5"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); +} + +TEST(TypeTests, Vec2_ParseMixed2) +{ + auto vec = Vec2::Parse("1.5,2"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); +} + +TEST(TypeTests, Vec2_ParseMixed3) +{ + auto vec = Vec2::Parse("1.5f,2"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); +} + +TEST(TypeTests, Vec2_ParseMixed4) +{ + auto vec = Vec2::Parse("1,0xF"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 0xF); +} + +TEST(TypeTests, Vec2_ParseMixed5) +{ + auto vec = Vec2::Parse("0xF,1"); + EXPECT_EQ(vec.x, 0xF); + EXPECT_EQ(vec.y, 1); +} + +TEST(TypeTests, Vec3_Default) +{ + Vec3 vec; + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + EXPECT_EQ(vec.z, 0); +} + +TEST(TypeTests, Vec3_Constructor) +{ + Vec3 vec(1, 2, 3); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); +} + +TEST(TypeTests, Vec3_ParseInteger) +{ + auto vec = Vec3::Parse("1,2,3"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); +} + +TEST(TypeTests, Vec3_ParseFloat) +{ + auto vec = Vec3::Parse("1.5,2.5,3.5"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); +} + +TEST(TypeTests, Vec3_ParseFloatSuffix) +{ + auto vec = Vec3::Parse("1.5f,2.5f,3.5f"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); +} + +TEST(TypeTests, Vec3_ParseHex) +{ + auto vec = Vec3::Parse("0xA,0xB,0xC"); + EXPECT_EQ(vec.x, 0xA); + EXPECT_EQ(vec.y, 0xB); + EXPECT_EQ(vec.z, 0xC); +} + +TEST(TypeTests, Vec3_ParseMixed) +{ + auto vec = Vec3::Parse("1,2.5,3"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, 3); +} + +TEST(TypeTests, Vec3_ParseMixed2) +{ + auto vec = Vec3::Parse("1.5,2,3"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); +} + +TEST(TypeTests, Vec3_ParseMixed3) +{ + auto vec = Vec3::Parse("1.5f,2,3.5"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); +} + +TEST(TypeTests, Vec3_ParseMixed4) +{ + auto vec = Vec3::Parse("1,0xF,3"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 0xF); + EXPECT_EQ(vec.z, 3); +} + +TEST(TypeTests, Vec3_ParseMixed5) +{ + auto vec = Vec3::Parse("0xF,1,0xF"); + EXPECT_EQ(vec.x, 0xF); + EXPECT_EQ(vec.y, 1); + EXPECT_EQ(vec.z, 0xF); +} + +TEST(TypeTests, Vec4_Default) +{ + Vec4 vec; + EXPECT_EQ(vec.x, 0); + EXPECT_EQ(vec.y, 0); + EXPECT_EQ(vec.z, 0); + EXPECT_EQ(vec.w, 0); +} + +TEST(TypeTests, Vec4_Constructor) +{ + Vec4 vec(1, 2, 3, 4); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); + EXPECT_EQ(vec.w, 4); +} + +TEST(TypeTests, Vec4_ParseInteger) +{ + auto vec = Vec4::Parse("1,2,3,4"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); + EXPECT_EQ(vec.w, 4); +} + +TEST(TypeTests, Vec4_ParseFloat) +{ + auto vec = Vec4::Parse("1.5,2.5,3.5,4.5"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); + EXPECT_EQ(vec.w, std::bit_cast(4.5f)); +} + +TEST(TypeTests, Vec4_ParseFloatSuffix) +{ + auto vec = Vec4::Parse("1.5f,2.5f,3.5f,4.5f"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); + EXPECT_EQ(vec.w, std::bit_cast(4.5f)); +} + +TEST(TypeTests, Vec4_ParseHex) +{ + auto vec = Vec4::Parse("0xA,0xB,0xC,0xD"); + EXPECT_EQ(vec.x, 0xA); + EXPECT_EQ(vec.y, 0xB); + EXPECT_EQ(vec.z, 0xC); + EXPECT_EQ(vec.w, 0xD); +} + +TEST(TypeTests, Vec4_ParseMixed) +{ + auto vec = Vec4::Parse("1,2.5,3,4"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, std::bit_cast(2.5f)); + EXPECT_EQ(vec.z, 3); + EXPECT_EQ(vec.w, 4); +} + +TEST(TypeTests, Vec4_ParseMixed2) +{ + auto vec = Vec4::Parse("1.5,2,3,4"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, 3); + EXPECT_EQ(vec.w, 4); +} + +TEST(TypeTests, Vec4_ParseMixed3) +{ + auto vec = Vec4::Parse("1.5f,2,3.5,0xB"); + EXPECT_EQ(vec.x, std::bit_cast(1.5f)); + EXPECT_EQ(vec.y, 2); + EXPECT_EQ(vec.z, std::bit_cast(3.5f)); + EXPECT_EQ(vec.w, 0xB); +} + +TEST(TypeTests, Vec4_ParseMixed4) +{ + auto vec = Vec4::Parse("1,0xF,3,4.0f"); + EXPECT_EQ(vec.x, 1); + EXPECT_EQ(vec.y, 0xF); + EXPECT_EQ(vec.z, 3); + EXPECT_EQ(vec.w, std::bit_cast(4.0f)); +} + +TEST(TypeTests, Vec4_ParseMixed5) +{ + auto vec = Vec4::Parse("0xF,1,0xF,0xE"); + EXPECT_EQ(vec.x, 0xF); + EXPECT_EQ(vec.y, 1); + EXPECT_EQ(vec.z, 0xF); + EXPECT_EQ(vec.w, 0xE); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}