about summary refs log tree commit diff stats
path: root/cpp/050scenario.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/050scenario.cc')
-rw-r--r--cpp/050scenario.cc242
1 files changed, 76 insertions, 166 deletions
diff --git a/cpp/050scenario.cc b/cpp/050scenario.cc
index 5dbc940a..dc839a10 100644
--- a/cpp/050scenario.cc
+++ b/cpp/050scenario.cc
@@ -4,10 +4,7 @@
 :(before "End Types")
 struct scenario {
   string name;
-  string dump_layer;
   string to_run;
-  map<int, int> memory_expectations;
-  // End scenario Fields
 };
 
 :(before "End Globals")
@@ -15,178 +12,111 @@ vector<scenario> 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<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
-  teardown();
-  if (Passed) cerr << ".";
-}
-
-//:: How we create Scenarios.
+:(scenarios run_mu_scenario)
+:(scenario scenario_block)
+scenario foo [
+  run [
+    1:integer <- copy 13:literal
+  ]
+  memory-should-contain [
+    1 <- 13
+  ]
+]
+# checks are inside scenario
 
-:(scenarios "parse_scenario")
-:(scenario parse_scenario_memory_expectation)
+:(scenario scenario_multiple_blocks)
 scenario foo [
   run [
-    a <- b
+    1:integer <- copy 13:literal
+  ]
+  memory-should-contain [
+    1 <- 13
+  ]
+  run [
+    2:integer <- copy 13:literal
   ]
-  memory should contain [
-    1 <- 0
+  memory-should-contain [
+    1 <- 13
+    2 <- 13
   ]
 ]
-+parse: scenario will run: a <- b
 
-:(scenario parse_scenario_memory_expectation_duplicate)
-% Hide_warnings = true;
+:(scenario scenario_check_memory_and_trace)
 scenario foo [
   run [
-    a <- b
+    1:integer <- copy 13:literal
+    trace [a], [a b c]
   ]
-  memory should contain [
-    1 <- 0
-    1 <- 1
+  memory-should-contain [
+    1 <- 13
+  ]
+  trace-should-contain [
+    a: a b c
+  ]
+  trace-should-not-contain [
+    a: x y z
   ]
 ]
-+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)
+// just for tests
+void run_mu_scenario(const string& form) {
+  istringstream in(form);
+  in >> std::noskipws;
+  assert(next_word(in) == "scenario");
+  scenario s = parse_scenario(in);
+  run_mu_scenario(s);
 }
 
-:(code)
 scenario parse_scenario(istream& in) {
-  scenario x;
-  x.name = next_word(in);
-  trace("parse") << "reading scenario " << x.name;
+  scenario result;
+  result.name = next_word(in);
   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;
+  result.to_run = buffer.str();
+  return result;
 }
 
-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 run_mu_scenario(const scenario& s) {
+  setup();
+  // In this layer we're writing tangle scenarios about mu scenarios.
+  // Don't need to set Trace_file and Trace_stream in that situation.
+  // Hackily simulate a conditional START_TRACING_UNTIL_END_OF_SCOPE.
+  bool temporary_trace_file = Trace_file.empty();
+  if (temporary_trace_file) Trace_file = s.name;
+  cerr << Trace_file << '\n';
+  bool delete_trace_stream = !Trace_stream;
+  if (delete_trace_stream) Trace_stream = new trace_stream;
+//?   START_TRACING_UNTIL_END_OF_SCOPE;
+  run("recipe "+s.name+" [ " + s.to_run + " ]");
+  teardown();
+  if (delete_trace_stream) {
+    ofstream fout((Trace_dir+Trace_file).c_str());
+    fout << Trace_stream->readable_contents("");
+    fout.close();
+    delete Trace_stream;
+    Trace_stream = NULL;
+  }
+  if (temporary_trace_file) Trace_file = "";
 }
 
-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() == ']');
+:(before "End Command Handlers")
+else if (command == "scenario") {
+  Scenarios.push_back(parse_scenario(in));
 }
 
-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';
+:(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_scenario(Scenarios[i]);
+  if (Passed) cerr << ".";
 }
 
 //:: Helpers
 
+:(code)
 void slurp_until_matching_bracket(istream& in, ostream& out) {
   int brace_depth = 1;  // just scanned '['
   char c;
@@ -197,23 +127,3 @@ void slurp_until_matching_bracket(istream& in, ostream& out) {
     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);
-}
-
-:(before "End Includes")
-#include <sys/stat.h>
-:(code)
-bool file_exists(const string& filename) {
-  struct stat buffer;
-  return stat(filename.c_str(), &buffer) == 0;
-}