diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2015-04-22 11:49:24 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2015-04-22 11:49:24 -0700 |
commit | ccd792dace1439b60882fafd1d1bd4b06c405d9e (patch) | |
tree | e1c5b825eab5a0173bf57d114eeeb2c5fb26a6de /cpp | |
parent | 3c6784a87bb362a7a2f32d617c5950fec23460cd (diff) | |
download | mu-ccd792dace1439b60882fafd1d1bd4b06c405d9e.tar.gz |
1126 - 'mu test x.mu' runs just scenarios in x.mu
Required still more tweaking of Recipe namespaces. Mindlessly inserting setup() took a couple of hours to debug because the test function and the function it was testing ended up getting the same recipe number, with the inevitable infinite loop :/
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/.traces/factorial-test | 210 | ||||
-rw-r--r-- | cpp/001test | 2 | ||||
-rw-r--r-- | cpp/010vm | 3 | ||||
-rw-r--r-- | cpp/020run | 7 | ||||
-rw-r--r-- | cpp/050scenario | 75 | ||||
-rw-r--r-- | cpp/factorial.mu | 33 |
6 files changed, 303 insertions, 27 deletions
diff --git a/cpp/.traces/factorial-test b/cpp/.traces/factorial-test new file mode 100644 index 00000000..1729d718 --- /dev/null +++ b/cpp/.traces/factorial-test @@ -0,0 +1,210 @@ +parse/0: instruction: 108 +parse/0: ingredient: {name: "5", value: 0, type: 0, properties: ["5": "literal"]} +parse/0: product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]} +after-brace/0: recipe test-factorial-test +after-brace/0: factorial ... +run/0: instruction test-factorial-test/0 +run/0: instruction factorial/0 +mem/0: new alloc: 1000 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 5 +mem/0: storing 5 in location 1002 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1002 is 5 +run/0: ingredient 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1003 +run/0: instruction factorial/4 +mem/0: location 1003 is 0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is +run/0: jumping to instruction 6 +run/0: instruction factorial/7 +run/0: ingredient 0 is n +mem/0: location 1002 is 5 +run/0: ingredient 1 is 1 +run/0: product 0 is 4 +mem/0: storing 4 in location 1004 +run/0: instruction factorial/8 +mem/0: location 1004 is 4 +run/0: instruction factorial/0 +mem/0: new alloc: 1030 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 4 +mem/0: storing 4 in location 1032 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1032 is 4 +run/0: ingredient 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1033 +run/0: instruction factorial/4 +mem/0: location 1033 is 0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is +run/0: jumping to instruction 6 +run/0: instruction factorial/7 +run/0: ingredient 0 is n +mem/0: location 1032 is 4 +run/0: ingredient 1 is 1 +run/0: product 0 is 3 +mem/0: storing 3 in location 1034 +run/0: instruction factorial/8 +mem/0: location 1034 is 3 +run/0: instruction factorial/0 +mem/0: new alloc: 1060 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 3 +mem/0: storing 3 in location 1062 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1062 is 3 +run/0: ingredient 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1063 +run/0: instruction factorial/4 +mem/0: location 1063 is 0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is +run/0: jumping to instruction 6 +run/0: instruction factorial/7 +run/0: ingredient 0 is n +mem/0: location 1062 is 3 +run/0: ingredient 1 is 1 +run/0: product 0 is 2 +mem/0: storing 2 in location 1064 +run/0: instruction factorial/8 +mem/0: location 1064 is 2 +run/0: instruction factorial/0 +mem/0: new alloc: 1090 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 2 +mem/0: storing 2 in location 1092 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1092 is 2 +run/0: ingredient 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1093 +run/0: instruction factorial/4 +mem/0: location 1093 is 0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is +run/0: jumping to instruction 6 +run/0: instruction factorial/7 +run/0: ingredient 0 is n +mem/0: location 1092 is 2 +run/0: ingredient 1 is 1 +run/0: product 0 is 1 +mem/0: storing 1 in location 1094 +run/0: instruction factorial/8 +mem/0: location 1094 is 1 +run/0: instruction factorial/0 +mem/0: new alloc: 1120 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 1 +mem/0: storing 1 in location 1122 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1122 is 1 +run/0: ingredient 1 is 0 +run/0: product 0 is 0 +mem/0: storing 0 in location 1123 +run/0: instruction factorial/4 +mem/0: location 1123 is 0 +run/0: ingredient 0 is 0 +run/0: ingredient 1 is +run/0: jumping to instruction 6 +run/0: instruction factorial/7 +run/0: ingredient 0 is n +mem/0: location 1122 is 1 +run/0: ingredient 1 is 1 +run/0: product 0 is 0 +mem/0: storing 0 in location 1124 +run/0: instruction factorial/8 +mem/0: location 1124 is 0 +run/0: instruction factorial/0 +mem/0: new alloc: 1150 +mem/0: array size is 30 +run/0: instruction factorial/1 +run/0: product 0 is 0 +mem/0: storing 0 in location 1152 +run/0: instruction factorial/3 +run/0: ingredient 0 is n +mem/0: location 1152 is 0 +run/0: ingredient 1 is 0 +run/0: product 0 is 1 +mem/0: storing 1 in location 1153 +run/0: instruction factorial/4 +mem/0: location 1153 is 1 +run/0: ingredient 0 is 1 +run/0: jump-unless fell through +run/0: instruction factorial/5 +run/0: result 0 is 1 +mem/0: storing 1 in location 1125 +run/0: instruction factorial/9 +run/0: ingredient 0 is subresult +mem/0: location 1125 is 1 +run/0: ingredient 1 is n +mem/0: location 1122 is 1 +run/0: ingredient 1 is 1 +run/0: product 0 is 1 +mem/0: storing 1 in location 1126 +run/0: instruction factorial/10 +mem/0: location 1126 is 1 +run/0: result 0 is 1 +mem/0: storing 1 in location 1095 +run/0: instruction factorial/9 +run/0: ingredient 0 is subresult +mem/0: location 1095 is 1 +run/0: ingredient 1 is n +mem/0: location 1092 is 2 +run/0: ingredient 1 is 2 +run/0: product 0 is 2 +mem/0: storing 2 in location 1096 +run/0: instruction factorial/10 +mem/0: location 1096 is 2 +run/0: result 0 is 2 +mem/0: storing 2 in location 1065 +run/0: instruction factorial/9 +run/0: ingredient 0 is subresult +mem/0: location 1065 is 2 +run/0: ingredient 1 is n +mem/0: location 1062 is 3 +run/0: ingredient 1 is 3 +run/0: product 0 is 6 +mem/0: storing 6 in location 1066 +run/0: instruction factorial/10 +mem/0: location 1066 is 6 +run/0: result 0 is 6 +mem/0: storing 6 in location 1035 +run/0: instruction factorial/9 +run/0: ingredient 0 is subresult +mem/0: location 1035 is 6 +run/0: ingredient 1 is n +mem/0: location 1032 is 4 +run/0: ingredient 1 is 4 +run/0: product 0 is 24 +mem/0: storing 24 in location 1036 +run/0: instruction factorial/10 +mem/0: location 1036 is 24 +run/0: result 0 is 24 +mem/0: storing 24 in location 1005 +run/0: instruction factorial/9 +run/0: ingredient 0 is subresult +mem/0: location 1005 is 24 +run/0: ingredient 1 is n +mem/0: location 1002 is 5 +run/0: ingredient 1 is 5 +run/0: product 0 is 120 +mem/0: storing 120 in location 1006 +run/0: instruction factorial/10 +mem/0: location 1006 is 120 +run/0: result 0 is 120 +mem/0: storing 120 in location 1 diff --git a/cpp/001test b/cpp/001test index 8c4bc5e3..0db10e4b 100644 --- a/cpp/001test +++ b/cpp/001test @@ -60,6 +60,8 @@ if (argc > 2 && is_equal(argv[1], "test") && is_number(argv[2])) { return 0; } +// End Test Runs + :(code) void run_tests() { time_t t; time(&t); diff --git a/cpp/010vm b/cpp/010vm index a900a56e..0a1ada2c 100644 --- a/cpp/010vm +++ b/cpp/010vm @@ -152,9 +152,6 @@ setup_recipes(); assert(MAX_PRIMITIVE_RECIPES < 100); // level 0 is primitives; until 99 Next_recipe_number = 100; // End Load Recipes -// give tests a consistent starting point -assert(Next_recipe_number < 1000); -Next_recipe_number = 1000; delete Trace_stream; Trace_stream = new trace_stream; :(before "End Setup") Next_recipe_number = 1000; // consistent new numbers for each test diff --git a/cpp/020run b/cpp/020run index 164bc5ac..0ce86d7a 100644 --- a/cpp/020run +++ b/cpp/020run @@ -104,6 +104,7 @@ if (argc > 1) { //? Trace_stream->dump_layer = "all"; //? 2 transform_all(); recipe_number r = Recipe_number[string("main")]; +//? Trace_stream->dump_layer = "all"; //? 1 if (r) run(r); dump_memory(); } @@ -119,14 +120,14 @@ void load(string filename) { add_recipes(fin); transform_all(); fin.close(); + // freeze everything so it doesn't get cleared by tests + recently_added_recipes.clear(); + recently_added_types.clear(); } //:: On startup, load everything in core.mu :(before "End Load Recipes") load("core.mu"); -// freeze everything so it doesn't get cleared by tests -recently_added_recipes.clear(); -recently_added_types.clear(); :(code) // helper for tests diff --git a/cpp/050scenario b/cpp/050scenario index 16949048..34edbe71 100644 --- a/cpp/050scenario +++ b/cpp/050scenario @@ -12,35 +12,41 @@ struct scenario { :(before "End Globals") vector<scenario> Scenarios; -//: How we check Scenarios. +//:: How we check Scenarios. :(before "End Tests") time_t mu_time; time(&mu_time); cerr << "\nMu tests: " << ctime(&mu_time); -for (size_t i = 0; i < Scenarios.size(); ++i) { - setup(); - Trace_file = Scenarios[i].name; - START_TRACING_UNTIL_END_OF_SCOPE - if (!Scenarios[i].dump_layer.empty()) - Trace_stream->dump_layer = Scenarios[i].dump_layer; -//? cout << Scenarios[i].to_run; //? 2 - run(Scenarios[i].to_run); -//? cout << "after: " << Memory[1] << '\n'; //? 1 -//? cout << "After:\n"; dump_memory(); //? 1 - for (map<int, int>::iterator p = Scenarios[i].memory_expectations.begin(); - p != Scenarios[i].memory_expectations.end(); - ++p) { - if (Memory[p->first] != p->second) { - // todo: unit tests for the test parsing infrastructure; use raise? - cerr << Scenarios[i].name << ": Expected location " << p->first << " to contain " << p->second << " but saw " << Memory[p->first] << '\n'; - Passed = false; +run_mu_tests(); + +:(code) +void run_mu_tests() { + for (size_t i = 0; i < Scenarios.size(); ++i) { + setup(); + Trace_file = Scenarios[i].name; + START_TRACING_UNTIL_END_OF_SCOPE + if (!Scenarios[i].dump_layer.empty()) + Trace_stream->dump_layer = Scenarios[i].dump_layer; +//? cerr << "AAA " << Scenarios[i].name << '\n'; //? 1 +//? cout << Scenarios[i].to_run; //? 2 + run(Scenarios[i].to_run); +//? cout << "after: " << Memory[1] << '\n'; //? 1 +//? cout << "After:\n"; dump_memory(); //? 1 + for (map<int, int>::iterator p = Scenarios[i].memory_expectations.begin(); + p != Scenarios[i].memory_expectations.end(); + ++p) { + if (Memory[p->first] != p->second) { + // todo: unit tests for the test parsing infrastructure; use raise? + cerr << Scenarios[i].name << ": Expected location " << p->first << " to contain " << p->second << " but saw " << Memory[p->first] << '\n'; + Passed = false; + } } + // End Scenario Checks + if (Passed) cerr << "."; } - // End Scenario Checks - if (Passed) cerr << "."; } -//: How we create Scenarios. +//:: How we create Scenarios. :(scenarios "parse_scenario") :(scenario "parse_scenario_memory_expectation") @@ -188,6 +194,25 @@ void slurp_until_matching_bracket(istream& in, ostream& out) { } } +//:: Run tests for loaded mu files (rather than running 'main'). + +:(before "End Test Runs") +if (argc > 2 && is_equal(argv[1], "test") && file_exists(argv[2])) { + Scenarios.clear(); // ignore core.mu + assert(Next_recipe_number < 1000); // don't load into test space + for (int i = 2; i < argc; ++i) { + load(argv[i]); + } + run_mu_tests(); + cerr << '\n'; + if (Num_failures > 0) + cerr << Num_failures << " failure" + << (Num_failures > 1 ? "s" : "") + << '\n'; + return 0; +} + +:(code) // for tests void parse_scenario(const string& s) { istringstream in(s); @@ -212,3 +237,11 @@ string &rtrim(string &s) { s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(isspace))).base(), s.end()); return s; } + +:(before "End Includes") +#include <sys/stat.h> +:(code) +bool file_exists(const string& filename) { + struct stat buffer; + return stat(filename.c_str(), &buffer) == 0; +} diff --git a/cpp/factorial.mu b/cpp/factorial.mu new file mode 100644 index 00000000..08d8afee --- /dev/null +++ b/cpp/factorial.mu @@ -0,0 +1,33 @@ +recipe factorial [ + default-space:address:array:location <- new location:type, 30:literal + n:integer <- next-ingredient + { + # if n=0 return 1 + zero?:boolean <- equal n:integer, 0:literal + break-unless zero?:boolean + reply 1:literal + } + # return n * factorial(n - 1) + x:integer <- subtract n:integer, 1:literal + subresult:integer <- factorial x:integer + result:integer <- multiply subresult:integer, n:integer + reply result:integer +] + +recipe main [ + default-space:address:space <- new location:type, 30:literal + x:integer <- factorial 7:literal + $print x:integer + $print [ +] +] + +scenario factorial-test [ +#? dump all #? 1 + run [ + 1:integer <- factorial 5:literal + ] + memory should contain [ + 1 <- 120 + ] +] |