summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/testsuite/testsuite-generator.cc
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/testsuite/testsuite-generator.cc
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/src/testsuite/testsuite-generator.cc')
-rw-r--r--tiger-compiler/src/testsuite/testsuite-generator.cc143
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