diff options
Diffstat (limited to 'cpp/040scenario')
-rw-r--r-- | cpp/040scenario | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/cpp/040scenario b/cpp/040scenario new file mode 100644 index 00000000..c595ce82 --- /dev/null +++ b/cpp/040scenario @@ -0,0 +1,132 @@ +//: Allow tests to be written in mu files. +:(before "End Types") +struct scenario { + string name; + string to_run; + map<int, int> memory_expectations; + // End scenario Fields +}; + +:(before "End Globals") +vector<scenario> 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 +//? Trace_stream->dump_layer = "all"; //? 1 +//? cout << "Before:\n"; dump_memory(); //? 1 +//? cout << Scenarios[i].to_run; //? 1 + run(Scenarios[i].to_run); +//? 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) { + 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 << "."; +} + +:(before "End Command Handlers") +else if (command == "scenario") { +//? cout << "AAA scenario\n"; //? 1 + Scenarios.push_back(parse_scenario(in)); +} + +:(code) +scenario parse_scenario(istream& in) { + scenario x; + x.name = next_word(in); + trace("parse") << "reading scenario " << x.name; + skip_bracket(in, "'scenario' must begin with '['"); + ostringstream buffer; + slurp_until_matching_bracket(in, buffer); +//? cout << "inner buffer: ^" << buffer.str() << "$\n"; //? 1 + istringstream inner(buffer.str()); + inner >> std::noskipws; + while (!inner.eof()) { + skip_whitespace_and_comments(inner); + string scenario_command = next_word(inner); + if (scenario_command.empty() && inner.eof()) break; + // Scenario Command Handlers + if (scenario_command == "run") { + handle_scenario_run_directive(inner, x); + trace("parse") << "scenario will run: " << x.to_run; + } + else if (scenario_command == "memory") { + handle_scenario_memory_directive(inner, x); + } + // End Scenario Command Handlers + else { + raise << "unknown command in scenario: ^" << scenario_command << "$\n"; + } + } + return x; +} + +void handle_scenario_run_directive(istream& in, scenario& result) { + skip_bracket(in, "'run' inside scenario must begin with '['"); + ostringstream buffer; + slurp_until_matching_bracket(in, buffer); + result.to_run = "recipe test-"+result.name+" [" + buffer.str() + "]"; +} + +void handle_scenario_memory_directive(istream& in, scenario& out) { + if (next_word(in) != "should") { + raise << "'memory' directive inside scenario must continue 'memory should'\n"; + } + if (next_word(in) != "contain") { + raise << "'memory' directive inside scenario must continue 'memory should contain'\n"; + } + skip_bracket(in, "'memory' directive inside scenario must begin with 'memory should contain ['\n"); + while (true) { + skip_whitespace_and_comments(in); + if (in.eof()) break; +//? cout << "a: " << in.peek() << '\n'; //? 1 + if (in.peek() == ']') break; + int address = 0; in >> address; +//? cout << "address: " << address << '\n'; //? 2 +//? cout << "b: " << in.peek() << '\n'; //? 1 + skip_whitespace_and_comments(in); +//? cout << "c: " << in.peek() << '\n'; //? 1 + string _assign; in >> _assign; assert(_assign == "<-"); + skip_whitespace_and_comments(in); + int value = 0; in >> value; + out.memory_expectations[address] = value; + trace("parse") << "memory expectation: *" << address << " == " << value; + } + skip_whitespace(in); + assert(in.get() == ']'); +} + +void slurp_until_matching_bracket(istream& in, ostream& out) { + int brace_depth = 1; // just scanned '[' + char c; + while (in >> c) { + if (c == '[') ++brace_depth; + if (c == ']') --brace_depth; + if (brace_depth == 0) break; // drop final ']' + out << c; + } +} + +void skip_bracket(istream& in, string message) { + skip_whitespace(in); skip_comments_and_newlines(in); skip_whitespace(in); + if (in.get() != '[') + raise << message << '\n'; +} + +void skip_whitespace_and_comments(istream& in) { + while (true) { + if (isspace(in.peek())) in.get(); + else if (in.peek() == '#') skip_comment(in); + else break; + } +} |