about summary refs log tree commit diff stats
path: root/cpp
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-04-12 23:29:59 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-04-12 23:33:49 -0700
commit43d2d20e55c052c5844a38d0d87526f68c7e2217 (patch)
tree9c85c2b09adbd9f40836649875310c5b23a3ceb6 /cpp
parentd03028a3035fc514a694a89dcec9429625c9217c (diff)
downloadmu-43d2d20e55c052c5844a38d0d87526f68c7e2217.tar.gz
1058 - scenarios can now check trace
Diffstat (limited to 'cpp')
-rw-r--r--cpp/.traces/first_scenario_checking_trace11
-rw-r--r--cpp/.traces/first_scenario_checking_trace_negative11
-rw-r--r--cpp/.traces/trace_in_mu7
-rw-r--r--cpp/031scenario3
-rw-r--r--cpp/034scenario_trace101
-rw-r--r--cpp/035scenario_trace_test.mu27
6 files changed, 160 insertions, 0 deletions
diff --git a/cpp/.traces/first_scenario_checking_trace b/cpp/.traces/first_scenario_checking_trace
new file mode 100644
index 00000000..8ea5d60b
--- /dev/null
+++ b/cpp/.traces/first_scenario_checking_trace
@@ -0,0 +1,11 @@
+parse/0: instruction: 2
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe test-first_scenario_checking_trace
+after-brace/0: add ...
+run/0: instruction test-first_scenario_checking_trace/0
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
diff --git a/cpp/.traces/first_scenario_checking_trace_negative b/cpp/.traces/first_scenario_checking_trace_negative
new file mode 100644
index 00000000..e80d680f
--- /dev/null
+++ b/cpp/.traces/first_scenario_checking_trace_negative
@@ -0,0 +1,11 @@
+parse/0: instruction: 2
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   ingredient: {name: "2", value: 0, type: 0, properties: ["2": "literal"]}
+parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
+after-brace/0: recipe test-first_scenario_checking_trace_negative
+after-brace/0: add ...
+run/0: instruction test-first_scenario_checking_trace_negative/0
+run/0: ingredient 0 is 2
+run/0: ingredient 1 is 2
+run/0: product 0 is 4
+mem/0: storing 4 in location 1
diff --git a/cpp/.traces/trace_in_mu b/cpp/.traces/trace_in_mu
new file mode 100644
index 00000000..dc7d8d8a
--- /dev/null
+++ b/cpp/.traces/trace_in_mu
@@ -0,0 +1,7 @@
+parse/0: instruction: 32
+parse/0:   ingredient: {name: "foo", value: 0, type: 0, properties: ["foo": "literal-string"]}
+parse/0:   ingredient: {name: "aaa", value: 0, type: 0, properties: ["aaa": "literal-string"]}
+after-brace/0: recipe test-trace_in_mu
+after-brace/0: trace ...
+run/0: instruction test-trace_in_mu/0
+foo/0: aaa
diff --git a/cpp/031scenario b/cpp/031scenario
index f3bd582c..c595ce82 100644
--- a/cpp/031scenario
+++ b/cpp/031scenario
@@ -1,8 +1,10 @@
+//: 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")
@@ -28,6 +30,7 @@ for (size_t i = 0; i < Scenarios.size(); ++i) {
       Passed = false;
     }
   }
+  // End Scenario Checks
   if (Passed) cerr << ".";
 }
 
diff --git a/cpp/034scenario_trace b/cpp/034scenario_trace
new file mode 100644
index 00000000..90dab204
--- /dev/null
+++ b/cpp/034scenario_trace
@@ -0,0 +1,101 @@
+:(before "End scenario Fields")
+vector<pair<string, string> > trace_checks;
+vector<pair<string, string> > trace_negative_checks;
+
+:(before "End Scenario Command Handlers")
+else if (scenario_command == "trace") {
+  handle_scenario_trace_directive(inner, x);
+}
+
+:(before "End Scenario Checks")
+check_trace_contents(Scenarios[i]);
+check_trace_negative_contents(Scenarios[i]);
+
+:(code)
+void handle_scenario_trace_directive(istream& in, scenario& out) {
+  if (next_word(in) != "should") {
+    raise << "'trace' directive inside scenario must continue 'trace should'\n";
+  }
+  string s = next_word(in);
+  if (s == "not") {
+    handle_scenario_trace_negative_directive(in, out);
+    return;
+  }
+  if (s != "contain") {
+    raise << "'trace' directive inside scenario must continue 'trace should [not] contain'\n";
+  }
+  skip_bracket(in, "'trace' directive inside scenario must begin with 'trace should contain ['\n");
+  while (true) {
+    skip_whitespace_and_comments(in);
+    if (in.eof()) break;
+    if (in.peek() == ']') break;
+    string curr_line;
+    getline(in, curr_line);
+    istringstream tmp(curr_line);
+    tmp >> std::noskipws;
+    string label = slurp_until(tmp, ':');
+    if (tmp.get() != ' ') {
+      raise << "'trace' directive inside scenario should contain lines of the form 'label: message', instead got " << curr_line;
+      continue;
+    }
+    string message = slurp_rest(tmp);
+    out.trace_checks.push_back(pair<string, string>(label, message));
+    trace("scenario") << "trace: " << label << ": " << message << '\n';
+  }
+  skip_whitespace(in);
+  assert(in.get() == ']');
+}
+
+void handle_scenario_trace_negative_directive(istream& in, scenario& out) {
+  // 'not' already slurped
+  if (next_word(in) != "contain") {
+    raise << "'trace' directive inside scenario must continue 'trace should not contain'\n";
+  }
+  skip_bracket(in, "'trace' directive inside scenario must begin with 'trace should not contain ['\n");
+  while (true) {
+    skip_whitespace_and_comments(in);
+    if (in.eof()) break;
+    if (in.peek() == ']') break;
+    string curr_line;
+    getline(in, curr_line);
+    istringstream tmp(curr_line);
+    tmp >> std::noskipws;
+    string label = slurp_until(tmp, ':');
+    if (tmp.get() != ' ') {
+      raise << "'trace' directive inside scenario should contain lines of the form 'label: message', instead got " << curr_line;
+      continue;
+    }
+    string message = slurp_rest(tmp);
+    out.trace_negative_checks.push_back(pair<string, string>(label, message));
+    trace("scenario") << "trace: " << label << ": " << message << '\n';
+  }
+  skip_whitespace(in);
+  assert(in.get() == ']');
+}
+
+string slurp_rest(istream& in) {
+  ostringstream out;
+  char c;
+  while (in >> c) {
+    out << c;
+  }
+  return out.str();
+}
+
+void check_trace_contents(const scenario& s) {
+  if (s.trace_checks.empty()) return;
+  ostringstream contents;
+  for (size_t i = 0; i < s.trace_checks.size(); ++i) {
+    contents << s.trace_checks[i].first << ": " << s.trace_checks[i].second << "";
+  }
+  CHECK_TRACE_CONTENTS(contents.str());
+}
+
+void check_trace_negative_contents(const scenario& s) {
+  for (size_t i = 0; i < s.trace_negative_checks.size(); ++i) {
+    if (trace_count(s.trace_negative_checks[i].first, s.trace_negative_checks[i].second) > 0) {
+      raise << "trace shouldn't contain " << s.trace_negative_checks[i].first << ": " << s.trace_negative_checks[i].second << '\n';
+      Passed = false;
+    }
+  }
+}
diff --git a/cpp/035scenario_trace_test.mu b/cpp/035scenario_trace_test.mu
new file mode 100644
index 00000000..abf0ef9a
--- /dev/null
+++ b/cpp/035scenario_trace_test.mu
@@ -0,0 +1,27 @@
+# tests for trace-checking scenario in previous layer
+scenario first_scenario_checking_trace [
+  run [
+    1:integer <- add 2:literal, 2:literal
+  ]
+  trace should contain [
+    mem: storing 4 in location 1
+  ]
+]
+
+scenario first_scenario_checking_trace_negative [
+  run [
+    1:integer <- add 2:literal, 2:literal
+  ]
+  trace should not contain [
+    mem: storing 5 in location 1
+  ]
+]
+
+scenario trace_in_mu [
+  run [
+    trace [foo], [aaa]
+  ]
+  trace should contain [
+    foo: aaa
+  ]
+]