summaryrefslogtreecommitdiff
path: root/src/expand/test_harness.cpp
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2017-04-13 12:46:01 +0800
committerJohn Hodge <tpg@ucc.asn.au>2017-04-13 12:46:01 +0800
commita223ffb9d0629e8b498f07dc67f056a7fb95385e (patch)
tree2e0f8dd5110e282bd31a071e7060e6d56651269b /src/expand/test_harness.cpp
parent9ee40f479d9b655fefcd45bd10691473d23cf0f0 (diff)
downloadmrust-a223ffb9d0629e8b498f07dc67f056a7fb95385e.tar.gz
All - Add rough support for #[test] (runs basic tests)
Diffstat (limited to 'src/expand/test_harness.cpp')
-rw-r--r--src/expand/test_harness.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/expand/test_harness.cpp b/src/expand/test_harness.cpp
new file mode 100644
index 00000000..883bd2aa
--- /dev/null
+++ b/src/expand/test_harness.cpp
@@ -0,0 +1,116 @@
+/*
+ * MRustC - Rust Compiler
+ * - By John Hodge (Mutabah/thePowersGang)
+ *
+ * expand/mod.cpp
+ * - Expand pass core code
+ */
+#include <ast/ast.hpp>
+#include <ast/expr.hpp>
+#include <ast/crate.hpp>
+#include <main_bindings.hpp>
+#include <hir/hir.hpp> // ABI_RUST
+
+#define NEWNODE(_ty, ...) ::AST::ExprNodeP(new ::AST::ExprNode##_ty(__VA_ARGS__))
+
+void Expand_TestHarness(::AST::Crate& crate)
+{
+ // Create the following module:
+ // ```
+ // mod `#test` {
+ // extern crate std;
+ // extern crate test;
+ // fn main() {
+ // self::test::test_main_static(&::`#test`::TESTS);
+ // }
+ // static TESTS: [test::TestDescAndFn; _] = [
+ // test::TestDescAndFn { desc: test::TestDesc { name: "foo", ignore: false, should_panic: test::ShouldPanic::No }, testfn: ::path::to::foo },
+ // ];
+ // }
+ // ```
+
+ // ---- main function ----
+ auto main_fn = ::AST::Function { Span(), {}, ABI_RUST, false, false, false, TypeRef(TypeRef::TagUnit(), Span()), {} };
+ {
+ auto call_node = NEWNODE(_CallPath,
+ ::AST::Path("test", { ::AST::PathNode("test_main_static") }),
+ ::make_vec1(
+ NEWNODE(_UniOp, ::AST::ExprNode_UniOp::REF,
+ NEWNODE(_NamedValue, ::AST::Path("", { ::AST::PathNode("test#"), ::AST::PathNode("TESTS") }))
+ )
+ )
+ );
+ main_fn.set_code( mv$(call_node) );
+ }
+
+
+ // ---- test list ----
+ ::std::vector< ::AST::ExprNodeP> test_nodes;
+
+ for(const auto& test : crate.m_tests)
+ {
+ ::AST::ExprNode_StructLiteral::t_values desc_vals;
+ // `name: "foo",`
+ desc_vals.push_back( ::std::make_pair("name", NEWNODE(_CallPath,
+ ::AST::Path("test", { ::AST::PathNode("StaticTestName") }),
+ ::make_vec1( NEWNODE(_String, test.name) )
+ ) ));
+ // `ignore: false,`
+ desc_vals.push_back( ::std::make_pair("ignore", NEWNODE(_Bool, test.ignore)) );
+ // `should_panic: ShouldPanic::No,`
+ {
+ ::AST::ExprNodeP should_panic_val;
+ switch(test.panic_type)
+ {
+ case ::AST::TestDesc::ShouldPanic::No:
+ should_panic_val = NEWNODE(_NamedValue, ::AST::Path("test", { ::AST::PathNode("ShouldPanic"), ::AST::PathNode("No") }));
+ break;
+ case ::AST::TestDesc::ShouldPanic::Yes:
+ should_panic_val = NEWNODE(_NamedValue, ::AST::Path("test", { ::AST::PathNode("ShouldPanic"), ::AST::PathNode("Yes") }));
+ break;
+ case ::AST::TestDesc::ShouldPanic::YesWithMessage:
+ should_panic_val = NEWNODE(_CallPath,
+ ::AST::Path("test", { ::AST::PathNode("ShouldPanic"), ::AST::PathNode("YesWithMessage") }),
+ make_vec1( NEWNODE(_String, test.expected_panic_message) )
+ );
+ break;
+ }
+ desc_vals.push_back( ::std::make_pair("should_panic", mv$(should_panic_val)) );
+ }
+ auto desc_expr = NEWNODE(_StructLiteral, ::AST::Path("test", { ::AST::PathNode("TestDesc")}), nullptr, mv$(desc_vals));
+
+ ::AST::ExprNode_StructLiteral::t_values descandfn_vals;
+ descandfn_vals.push_back( ::std::make_pair(::std::string("desc"), mv$(desc_expr)) );
+
+ auto test_type_var_name = test.is_benchmark ? "StaticBenchFn" : "StaticTestFn";
+ descandfn_vals.push_back( ::std::make_pair(::std::string("testfn"), NEWNODE(_CallPath,
+ ::AST::Path("test", { ::AST::PathNode(test_type_var_name) }),
+ ::make_vec1( NEWNODE(_NamedValue, AST::Path(test.path)) )
+ ) ) );
+
+ test_nodes.push_back( NEWNODE(_StructLiteral, ::AST::Path("test", { ::AST::PathNode("TestDescAndFn")}), nullptr, mv$(descandfn_vals) ) );
+ }
+ auto* tests_array = new ::AST::ExprNode_Array(mv$(test_nodes));
+
+ size_t test_count = tests_array->m_values.size();
+ auto tests_list = ::AST::Static { ::AST::Static::Class::STATIC,
+ TypeRef(TypeRef::TagSizedArray(), Span(),
+ TypeRef(Span(), ::AST::Path("test", { ::AST::PathNode("TestDescAndFn") })),
+ ::std::shared_ptr<::AST::ExprNode>( new ::AST::ExprNode_Integer(test_count, CORETYPE_UINT) )
+ ),
+ ::AST::Expr( mv$(tests_array) )
+ };
+
+ // ---- module ----
+ auto newmod = ::AST::Module { ::AST::Path("", { ::AST::PathNode("test#") }) };
+ // - TODO: These need to be loaded too.
+ // > They don't actually need to exist here, just be loaded (and use absolute paths)
+ newmod.add_ext_crate(false, "std", "std", {});
+ newmod.add_ext_crate(false, "test", "test", {});
+
+ newmod.add_item(false, "main", mv$(main_fn), {});
+ newmod.add_item(false, "TESTS", mv$(tests_list), {});
+
+ crate.m_root_module.add_item(false, "test#", mv$(newmod), {});
+ crate.m_lang_items["mrustc-main"] = ::AST::Path("", { AST::PathNode("test#"), AST::PathNode("main") });
+}