From 9c4ebc850decbc04b99986584e051787f855c596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Tup=C3=BD?= Date: Wed, 3 Jan 2024 21:12:40 +0100 Subject: [PATCH] Updated tests. Corrected stdout and sterr discrepencies. --- premake5.lua | 2 + .../compiler/compiler/compilation_context.cpp | 4 +- source/compiler/compiler/compiler.cpp | 2 +- source/compiler/compiler/compiler.h | 5 + source/compiler/main.cpp | 2 +- source/intermediate_representation/module.cpp | 2 +- source/tests/main.cpp | 144 ++++++++++-------- source/utility/diagnostics.h | 16 +- source/utility/filesystem/file.h | 4 + source/utility/macros.h | 40 ++--- 10 files changed, 126 insertions(+), 95 deletions(-) diff --git a/premake5.lua b/premake5.lua index b2f21cd6..8a63aec1 100644 --- a/premake5.lua +++ b/premake5.lua @@ -268,6 +268,8 @@ project "tests" libdirs { "../sigma/output/compiler/bin/%{cfg.buildcfg}" } + debugargs { "run", "../../tests" } + includedirs { "source" } diff --git a/source/compiler/compiler/compilation_context.cpp b/source/compiler/compiler/compilation_context.cpp index ed2ba9fc..1ce17793 100644 --- a/source/compiler/compiler/compilation_context.cpp +++ b/source/compiler/compiler/compilation_context.cpp @@ -52,7 +52,7 @@ namespace sigma { default: break; // suppress unhandled enumeration warnings } - utility::console::println(); + utility::console::print("\n"); }); } @@ -63,7 +63,7 @@ namespace sigma { symbol_value = utility::detail::escape_string(syntax.string_table.get(info.symbol_key)); } - utility::console::println("{:<20} {}", info.tok.to_string(), symbol_value); + utility::console::print("{:<20} {}\n", info.tok.to_string(), symbol_value); } } diff --git a/source/compiler/compiler/compiler.cpp b/source/compiler/compiler/compiler.cpp index 61166502..4ddf5e00 100644 --- a/source/compiler/compiler/compiler.cpp +++ b/source/compiler/compiler/compiler.cpp @@ -20,7 +20,7 @@ namespace sigma { : m_description(description) {} auto compiler::compile() const -> utility::result { - utility::console::println("compiling file: {}", m_description.path.string()); + utility::console::print("compiling file: {}\n", m_description.path.string()); ASSERT(m_description.emit != emit_target::EXECUTABLE, "executable support not implemented"); TRY(verify_file(m_description.path)); diff --git a/source/compiler/compiler/compiler.h b/source/compiler/compiler/compiler.h index f35dae5a..84c6539b 100644 --- a/source/compiler/compiler/compiler.h +++ b/source/compiler/compiler/compiler.h @@ -24,6 +24,7 @@ namespace sigma { } // namespace sigma::ir enum emit_target : u8 { + NONE, OBJECT, EXECUTABLE }; @@ -87,6 +88,10 @@ struct parametric::options_parser { template<> struct parametric::options_parser { static auto parse(const std::string& value) -> sigma::emit_target { + if (value == "none") { + return sigma::emit_target::NONE; + } + if (value == "object") { return sigma::emit_target::OBJECT; } diff --git a/source/compiler/main.cpp b/source/compiler/main.cpp index 5f573747..59d7d1bc 100644 --- a/source/compiler/main.cpp +++ b/source/compiler/main.cpp @@ -15,7 +15,7 @@ i32 compile(const parametric::parameters& params) { const auto result = sigma::compiler::compile(description); if (result.has_error()) { - utility::console::println(result.get_error_message()); + utility::console::printerr(result.get_error_message()); return 1; } diff --git a/source/intermediate_representation/module.cpp b/source/intermediate_representation/module.cpp index 003deb2c..652850e0 100644 --- a/source/intermediate_representation/module.cpp +++ b/source/intermediate_representation/module.cpp @@ -79,7 +79,7 @@ namespace sigma::ir { } // DEBUG - utility::console::println("{}", assembly.get_underlying()); + utility::console::print("{}\n", assembly.get_underlying()); } auto module::generate_object_file() -> utility::object_file { diff --git a/source/tests/main.cpp b/source/tests/main.cpp index 2d780161..55552dab 100644 --- a/source/tests/main.cpp +++ b/source/tests/main.cpp @@ -1,68 +1,86 @@ -#include #include -#include +#include +#include -// Runs all tests in sigma/tests and checks against a database of expected results. Should only -// be invoked via the run_tests.bat file. - -//#define WIN_COMPILER_PATH utility::fs::get_canonical_path("../../../../output/compiler/bin/Debug/compiler.exe").string() -//#define ERR_FILE_PATH "err.txt" -// using namespace utility::types; -// -//auto compile_file(const filepath& path) -> utility::result { -// const std::string command = WIN_COMPILER_PATH + " " + utility::fs::get_canonical_path(path).string() + " NO_EMIT" + " 1> err.txt"; -// const bool has_error = system(command.c_str()); -// -// if(has_error) { -// TRY(std::string message, utility::file::read_text_file(ERR_FILE_PATH)); -// -// // message = utility::detail::remove_first_line(message); -// // message.erase(message.size() - 1); // remove the trailing newline -// // utility::console::println("\033[31m'{}'\033[0m", message); -// } -// -// return has_error; -//} - -//i32 main() { -// std::queue paths({ utility::fs::get_canonical_path("../../../../tests") }); -// -// std::cout << paths.front() << '\n'; -// -// utility::console::println("running tests..."); -// utility::console::println("{}", std::string(32, '-')); -// -// while(!paths.empty()) { -// const filepath current = paths.front(); -// paths.pop(); -// -// utility::directory::for_all_directory_items(current, [&](const filepath& path) { -// if(utility::fs::is_directory(path)) { -// paths.push(path); -// return; -// } -// -// static const char* result_codes[] = { -// "OK", -// "ERROR", -// }; -// -// const auto result = compile_file(path); -// -// if(result.has_error()) { -// utility::console::println(result.get_error_message()); -// return; -// } -// -// utility::console::println("{:<30}{}", path.stem().string(), result_codes[result.get_value()]); -// }); -// } -// -// utility::fs::remove(ERR_FILE_PATH); -// return 0; -//} + +#define STOUD_FILE "STDOUT.txt" +#define STERR_FILE "STDERR.txt" + +auto get_compiler_path() -> std::string { +#ifdef SYSTEM_WINDOWS + return utility::fs::get_canonical_path("../../output/compiler/bin/Debug/compiler.exe").string(); +#elif defined SYSTEM_LINUX + return utility::fs::get_canonical_path("../../output/compiler/bin/Debug/compiler").string(); +#else + PANIC("unhandled system path"); + return std::string(); +#endif +} + +bool test_file(const filepath& path) { + const std::string command = std::format("{} compile {} -e none > {} 2> {}", get_compiler_path(), path.string(), STOUD_FILE, STERR_FILE); + const i32 return_code = utility::shell::execute(command); + + if(return_code == 0) { + utility::console::print("{:<20} OK\n", path.filename().string()); + return false; + } + + utility::console::printerr("{:<20} ERROR\n", path.filename().string()); + + const auto file_result = utility::file::read_text_file(STERR_FILE); + if(file_result.has_error()) { + throw std::exception(std::format("cannot open file {}", STERR_FILE).c_str()); + } + + utility::console::printerr("'{}'\n", file_result.get_value()); + + return true; +} + +i32 run_all_tests(const parametric::parameters& params) { + const auto test_directory = params.get("directory"); + std::queue paths({ utility::fs::get_canonical_path(test_directory) }); + bool encountered_error = false; + + // run our tests + try { + while (!paths.empty()) { + const filepath current = paths.front(); + paths.pop(); + + utility::directory::for_all_directory_items(current, [&](const filepath& path) { + if (utility::fs::is_directory(path)) { + paths.push(path); + return; + } + + encountered_error |= test_file(path); + }); + } + } catch(const std::exception& exception) { + utility::console::printerr("error: {}\n", exception.what()); + encountered_error = true; + } + + // cleanup + try { + utility::fs::remove(STOUD_FILE); + utility::fs::remove(STERR_FILE); + } catch(const std::exception& exception) { + utility::console::printerr("error: {}\n", exception.what()); + encountered_error = true; + } + + return encountered_error ? 1 : 0; +} i32 main(i32 argc, char* argv[]) { - // -} \ No newline at end of file + parametric::program program; + + auto& run_all = program.add_command("run", "run all tests in the specified directory", run_all_tests); + run_all.add_positional_argument("directory", "test directory"); + + return program.parse(argc, argv); +} diff --git a/source/utility/diagnostics.h b/source/utility/diagnostics.h index 16e9d20b..e1ca47d9 100644 --- a/source/utility/diagnostics.h +++ b/source/utility/diagnostics.h @@ -18,22 +18,22 @@ namespace utility { std::cout << format_str(std::move(fmt), std::forward(args)...); } - static void println(const std::string& message) { - std::cout << message << '\n'; + static void printerr(const std::string& message) { + std::cerr << message; } template - static void println(std::format_string fmt, arguments&&... args) { - std::cout << format_str(std::move(fmt), std::forward(args)...) << '\n'; - } - - static void println() { - std::cout << '\n'; + static void printerr(std::format_string fmt, arguments&&... args) { + std::cerr << format_str(std::move(fmt), std::forward(args)...); } static void flush() { std::cout << std::flush; } + + static void errflush() { + std::cerr << std::flush; + } private: template static auto format_str(std::format_string fmt, arguments&&... args) -> std::string { diff --git a/source/utility/filesystem/file.h b/source/utility/filesystem/file.h index e774c060..8e088e83 100644 --- a/source/utility/filesystem/file.h +++ b/source/utility/filesystem/file.h @@ -16,6 +16,10 @@ namespace utility { return std::filesystem::is_regular_file(path); } + static auto get_working_directory() -> filepath { + return std::filesystem::current_path(); + } + static auto get_canonical_path(const filepath& path) -> filepath { try { return canonical(path); diff --git a/source/utility/macros.h b/source/utility/macros.h index 3d2bc320..69875337 100644 --- a/source/utility/macros.h +++ b/source/utility/macros.h @@ -17,29 +17,31 @@ #endif #ifdef DEBUG -#define ASSERT(__condition, __fmt, ...) \ - do { \ - if(!(__condition)) { \ - utility::console::print("ASSERTION FAILED: ({}:{}): ", __FILE__, __LINE__); \ - utility::console::println((__fmt), ##__VA_ARGS__); \ - utility::console::flush(); \ - DEBUG_BREAK(); \ - } \ +#define ASSERT(__condition, __fmt, ...) \ + do { \ + if(!(__condition)) { \ + utility::console::printerr("ASSERTION FAILED: ({}:{}): ", __FILE__, __LINE__); \ + utility::console::printerr((__fmt), ##__VA_ARGS__); \ + utility::console::printerr("\n"); \ + utility::console::flush(); \ + DEBUG_BREAK(); \ + } \ } while(false) -#define NOT_IMPLEMENTED() \ - do { \ - utility::console::println("ASSERTION FAILED: ({}:{}): NOT IMPLEMENTED", __FILE__, __LINE__); \ - utility::console::flush(); \ - DEBUG_BREAK(); \ +#define NOT_IMPLEMENTED() \ + do { \ + utility::console::printerr("ASSERTION FAILED: ({}:{}): NOT IMPLEMENTED\n", __FILE__, __LINE__); \ + utility::console::errflush(); \ + DEBUG_BREAK(); \ } while(false) -#define PANIC( __fmt, ...) \ - do { \ - utility::console::print("ASSERTION FAILED: ({}:{}): ", __FILE__, __LINE__); \ - utility::console::println((__fmt), ##__VA_ARGS__); \ - utility::console::flush(); \ - DEBUG_BREAK(); \ +#define PANIC( __fmt, ...) \ + do { \ + utility::console::printerr("ASSERTION FAILED: ({}:{}): ", __FILE__, __LINE__); \ + utility::console::printerr((__fmt), ##__VA_ARGS__); \ + utility::console::printerr("\n"); \ + utility::console::errflush(); \ + DEBUG_BREAK(); \ } while(false) #else #define ASSERT(__condition, __fmt, ...)