From 6d8ef6b12d37336a92c7a6b20b4b66f3ab424464 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 24 Apr 2015 22:49:29 -0700 Subject: 1189 - add extensions to all layers I'm sick of fighting vim's filetype detection. No modeline and files highlight in random colors. I add a modeline and it stops highlighting tangle comments. Even though it read my #$%# vimrc! Fuck this shite. --- cpp/050scenario.cc | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 cpp/050scenario.cc (limited to 'cpp/050scenario.cc') diff --git a/cpp/050scenario.cc b/cpp/050scenario.cc new file mode 100644 index 00000000..d8152219 --- /dev/null +++ b/cpp/050scenario.cc @@ -0,0 +1,232 @@ +//: Allow tests to be written in mu files. + +:(before "End Types") +struct scenario { + string name; + string dump_layer; + string to_run; + map memory_expectations; + // End scenario Fields +}; + +:(before "End Globals") +vector 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) { + run_mu_test(i); +} + +:(code) +void run_mu_test(size_t 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::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 + teardown(); + if (Passed) cerr << "."; +} + +//:: How we create Scenarios. + +:(scenarios "parse_scenario") +:(scenario parse_scenario_memory_expectation) +scenario foo [ + run [ + a <- b + ] + memory should contain [ + 1 <- 0 + ] +] ++parse: scenario will run: a <- b + +:(scenario parse_scenario_memory_expectation_duplicate) +% Hide_warnings = true; +scenario foo [ + run [ + a <- b + ] + memory should contain [ + 1 <- 0 + 1 <- 1 + ] +] ++warn: duplicate expectation for location 1: 0 -> 1 + +:(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); + } + else if (scenario_command == "memory") { + handle_scenario_memory_directive(inner, x); + } + else if (scenario_command == "dump") { + skip_whitespace_and_comments(inner); + x.dump_layer = next_word(inner); + } + // 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); + string trace_result = buffer.str(); // temporary copy + trace("parse") << "scenario will run: " << trim(trace_result); +//? cout << buffer.str() << '\n'; //? 1 + 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; + string lhs = next_word(in); + if (!is_number(lhs)) { + handle_type(lhs, in, out); + continue; + } + int address = to_int(lhs); +//? 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; + if (out.memory_expectations.find(address) != out.memory_expectations.end()) + raise << "duplicate expectation for location " << address << ": " << out.memory_expectations[address] << " -> " << value << '\n'; + out.memory_expectations[address] = value; + trace("parse") << "memory expectation: *" << address << " == " << value; + } + skip_whitespace(in); + assert(in.get() == ']'); +} + +void handle_type(const string& lhs, istream& in, scenario& out) { + reagent x(lhs); + if (x.properties[0].second[0] == "string") { + x.set_value(to_int(x.name)); +//? cerr << x.name << ' ' << x.value << '\n'; //? 1 + skip_whitespace_and_comments(in); + string _assign = next_word(in); +//? cerr << _assign << '\n'; //? 1 + assert(_assign == "<-"); + skip_whitespace_and_comments(in); + string literal = next_word(in); +//? cerr << literal << '\n'; //? 1 + size_t address = x.value; + out.memory_expectations[address] = literal.size()-2; // exclude quoting brackets + ++address; + for (size_t i = 1; i < literal.size()-1; ++i) { +//? cerr << "checking " << address << ": " << literal[i] << '\n'; //? 1 + out.memory_expectations[address] = literal[i]; + ++address; + } + return; + } + raise << "scenario doesn't know how to parse memory expectation on " << lhs << '\n'; +} + +//:: Helpers + +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; + } +} + +:(code) +// for tests +void parse_scenario(const string& s) { + istringstream in(s); + in >> std::noskipws; + skip_whitespace_and_comments(in); + string _scenario = next_word(in); +//? cout << _scenario << '\n'; //? 1 + assert(_scenario == "scenario"); + parse_scenario(in); +} + +string &trim(string &s) { + return ltrim(rtrim(s)); +} + +string <rim(string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(isspace)))); + return s; +} + +string &rtrim(string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(isspace))).base(), s.end()); + return s; +} + +:(before "End Includes") +#include +:(code) +bool file_exists(const string& filename) { + struct stat buffer; + return stat(filename.c_str(), &buffer) == 0; +} -- cgit 1.4.1-2-gfad0