diff options
| author | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
|---|---|---|
| committer | Martial Simon <msimon_fr@hotmail.com> | 2025-09-15 01:07:58 +0200 |
| commit | 967be9e750221ab2ab783f95df79bb26d290a45e (patch) | |
| tree | 6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/testsuite/testsuite-generator.cc | |
Diffstat (limited to 'tiger-compiler/src/testsuite/testsuite-generator.cc')
| -rw-r--r-- | tiger-compiler/src/testsuite/testsuite-generator.cc | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/tiger-compiler/src/testsuite/testsuite-generator.cc b/tiger-compiler/src/testsuite/testsuite-generator.cc new file mode 100644 index 0000000..87ca479 --- /dev/null +++ b/tiger-compiler/src/testsuite/testsuite-generator.cc @@ -0,0 +1,143 @@ +/** + ** \file testsuite/testsuite-generator.cc + ** \brief Implementation of testsuite::TestsuiteGenerator. + */ + +#include <testsuite/testsuite-generator.hh> + +#include <ast/function-dec.hh> +#include <parse/libparse.hh> +#include <parse/tweast.hh> + +namespace testsuite + { + + /** + * Generate a function which calls the provided test with no arguments. + * @param definitions the testsuite definition + * @param test_reference the function to create a unit test for + * @return the new function's name + */ + static std::string add_test_to_testsuite( + parse::Tweast& definitions, + const ast::FunctionDec* test_reference) + { + const std::string test_name = test_reference->name_get().get(); + const std::string callback_name = "testsuite_" + test_name; + + definitions << "function " + callback_name + "() = " + "let " + "var child_pid := -1 " + "var status_code := -1 " + "var exit_code := -1 " + "in " + "child_pid := fork(); " + "if (child_pid = -1) then ( " + "print_err(\"could not run child process. skipping test\"); " + "skipped := skipped + 1 " + ") " + "else if (child_pid = 0) then ( " + + test_name + "(); " + "exit(0) " + ") " + "else ( " + "status_code := wait_pid(child_pid); " + + "if (status_code = 0) then ( " + "print(\" o \") " + ") " + "else (" + "print(\" x \") " + "); " + + "print(\"" + test_name + " test \"); " + "if (status_code = 0) then ( " + "print(\"passed\"); " + "passed := passed + 1 " + ") " + "else (" + "print(\"failed with \"); " + "exit_code := get_exit_code(status_code); " + "if (status_code = 6) then " + "print(\"assertion failure\") " + "else if (status_code = 8) then " + "print(\"illegal instruction\") " + "else if (status_code = 11) then " + "print(\"segmentation fault\") " + "else if (exit_code = 120) then " + "print(\"runtime failure\") " + "else ( " + "print(\"other error code \"); " + "print_int(exit_code) " + "); " + "failed := failed + 1" + "); " + "print(\"\\n\"); " + "flush() " + ") " + "end "; + + return callback_name; + } + + /** + * Build the testsuite runtime, parse the result and return the AST. + * @param definitions the function declarations to add within the runtime + * @param names the names of the tests to run, once declared + * @return the resulting AST + */ + static ast::ChunkInterface* build_testsuite( + const parse::Tweast& definitions, + const std::vector<std::string>& names) + { + parse::Tweast runtime; + + runtime << "function _main() = let " + "var skipped := 0 " + "var passed := 0 " + "var failed := 0 "; + + runtime << definitions.input_get(); + + runtime << " in " + "print(\"====================== Begin testing =====================\\n\\n\"); "; + + for (const std::string& test : names) + { + runtime << test << "(); "; + } + + runtime << "print(\"\\n=============== TC-RITERION testing result ===============\\n\"); " + "print(\" o Passed: \"); " + "print_int(passed); " + "print(\"\\n o Failed: \"); " + "print_int(failed); " + "if (skipped > 0) then ( " + "print(\"\\n o Skipped: \"); " + "print_int(skipped) " + "); " + "print(\"\\n==========================================================\\n\"); " + "flush() " + "end"; + + return parse::parse_chunks(runtime); + } + + ast::ChunkInterface* + generate_testsuite_runtime( + const std::vector<const ast::FunctionDec*>& tests) + { + parse::Tweast declarations; + std::vector<std::string> test_names; + + for (const auto test : tests) + { + const std::string test_name = + add_test_to_testsuite(declarations, test); + test_names.push_back(test_name); + } + + return build_testsuite(declarations, test_names); + } + + } // namespace testsuite |
