about summary refs log tree commit diff stats
path: root/cpp
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-05-01 23:37:12 -0700
committerKartik K. Agaram <vc@akkartik.com>2015-05-01 23:37:12 -0700
commit36d163092fe951fd897dfb396c5e2cb301977800 (patch)
tree1535345df9949c1c8dcebee848ad0c47e283daa6 /cpp
parentb35ac82d06c3e5e30d6751b62f2baa40c9787ffd (diff)
downloadmu-36d163092fe951fd897dfb396c5e2cb301977800.tar.gz
1234 - support for trace checks
Diffstat (limited to 'cpp')
-rw-r--r--cpp/.traces/trace_check_passes_silently37
-rw-r--r--cpp/.traces/trace_check_warns_on_failure21
-rw-r--r--cpp/.traces/trace_check_warns_on_failure_in_later_line42
-rw-r--r--cpp/.traces/trace_should_contain17
-rw-r--r--cpp/003trace.cc3
-rw-r--r--cpp/049scenario_helpers.cc95
-rw-r--r--cpp/050scenario.cc14
7 files changed, 212 insertions, 17 deletions
diff --git a/cpp/.traces/trace_check_passes_silently b/cpp/.traces/trace_check_passes_silently
new file mode 100644
index 00000000..3fd17d2f
--- /dev/null
+++ b/cpp/.traces/trace_check_passes_silently
@@ -0,0 +1,37 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    trace [a], [b]
+  ", value: 0, type: 0, properties: ["
+    trace [a], [b]
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    a: b
+  ", value: 0, type: 0, properties: ["
+    a: b
+  ": "literal-string"]}
+after-brace/0: recipe main
+after-brace/0: run ...
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: main
+run/0: instruction main/0
+run/0: run {name: "
+    trace [a], [b]
+  ", value: 0, type: 0, properties: ["
+    trace [a], [b]
+  ": "literal-string"]}
+parse/0: instruction: trace
+parse/0:   ingredient: {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}
+parse/0:   ingredient: {name: "b", value: 0, type: 0, properties: ["b": "literal-string"]}
+after-brace/0: recipe tmp0
+after-brace/0: trace ...
+run/0: instruction tmp0/0
+run/0: trace {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}, {name: "b", value: 0, type: 0, properties: ["b": "literal-string"]}
+a/0: b
+run/0: instruction main/1
+run/0: trace-should-contain {name: "
+    a: b
+  ", value: 0, type: 0, properties: ["
+    a: b
+  ": "literal-string"]}
diff --git a/cpp/.traces/trace_check_warns_on_failure b/cpp/.traces/trace_check_warns_on_failure
new file mode 100644
index 00000000..e8ea7894
--- /dev/null
+++ b/cpp/.traces/trace_check_warns_on_failure
@@ -0,0 +1,21 @@
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    a: b
+    a: d
+  ", value: 0, type: 0, properties: ["
+    a: b
+    a: d
+  ": "literal-string"]}
+after-brace/0: recipe main
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: main
+run/0: instruction main/0
+run/0: trace-should-contain {name: "
+    a: b
+    a: d
+  ", value: 0, type: 0, properties: ["
+    a: b
+    a: d
+  ": "literal-string"]}
+warn/0: missing [b] in trace layer a
diff --git a/cpp/.traces/trace_check_warns_on_failure_in_later_line b/cpp/.traces/trace_check_warns_on_failure_in_later_line
new file mode 100644
index 00000000..066765be
--- /dev/null
+++ b/cpp/.traces/trace_check_warns_on_failure_in_later_line
@@ -0,0 +1,42 @@
+parse/0: instruction: run
+parse/0:   ingredient: {name: "
+    trace [a], [b]
+  ", value: 0, type: 0, properties: ["
+    trace [a], [b]
+  ": "literal-string"]}
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    a: b
+    a: d
+  ", value: 0, type: 0, properties: ["
+    a: b
+    a: d
+  ": "literal-string"]}
+after-brace/0: recipe main
+after-brace/0: run ...
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: main
+run/0: instruction main/0
+run/0: run {name: "
+    trace [a], [b]
+  ", value: 0, type: 0, properties: ["
+    trace [a], [b]
+  ": "literal-string"]}
+parse/0: instruction: trace
+parse/0:   ingredient: {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}
+parse/0:   ingredient: {name: "b", value: 0, type: 0, properties: ["b": "literal-string"]}
+after-brace/0: recipe tmp0
+after-brace/0: trace ...
+run/0: instruction tmp0/0
+run/0: trace {name: "a", value: 0, type: 0, properties: ["a": "literal-string"]}, {name: "b", value: 0, type: 0, properties: ["b": "literal-string"]}
+a/0: b
+run/0: instruction main/1
+run/0: trace-should-contain {name: "
+    a: b
+    a: d
+  ", value: 0, type: 0, properties: ["
+    a: b
+    a: d
+  ": "literal-string"]}
+warn/0: missing [d] in trace layer a
diff --git a/cpp/.traces/trace_should_contain b/cpp/.traces/trace_should_contain
new file mode 100644
index 00000000..471d332e
--- /dev/null
+++ b/cpp/.traces/trace_should_contain
@@ -0,0 +1,17 @@
+parse/0: instruction: trace-should-contain
+parse/0:   ingredient: {name: "
+    a: b
+  ", value: 0, type: 0, properties: ["
+    a: b
+  ": "literal-string"]}
+after-brace/0: recipe main
+after-brace/0: trace-should-contain ...
+new/0: routine allocated memory from 1000 to 101000
+schedule/0: main
+run/0: instruction main/0
+run/0: trace-should-contain {name: "
+    a: b
+  ", value: 0, type: 0, properties: ["
+    a: b
+  ": "literal-string"]}
+warn/0: undefined operation 1001: trace-should-contain
diff --git a/cpp/003trace.cc b/cpp/003trace.cc
index 4f5f6254..18a80c7c 100644
--- a/cpp/003trace.cc
+++ b/cpp/003trace.cc
@@ -218,7 +218,6 @@ bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expecte
     ++curr_expected_line;
   if (curr_expected_line == expected_lines.size()) return true;
   Trace_stream->newline();
-  ostringstream output;
   string layer, frame, contents;
   parse_layer_frame_contents(expected_lines[curr_expected_line], &layer, &frame, &contents);
   for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
@@ -285,7 +284,6 @@ bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer,
     ++curr_expected_line;
   if (curr_expected_line == expected_lines.size()) return true;
   Trace_stream->newline();
-  ostringstream output;
   vector<string> layers = split(layer, ",");
   for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
     if (!layer.empty() && !any_prefix_match(layers, p->first))
@@ -385,7 +383,6 @@ bool check_trace_contents(string FUNCTION, string FILE, int LINE, string layer,
     ++curr_expected_line;
   if (curr_expected_line == expected_lines.size()) return true;
   Trace_stream->newline();
-  ostringstream output;
   vector<string> layers = split(layer, ",");
   for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
     if (!layer.empty() && !any_prefix_match(layers, p->first))
diff --git a/cpp/049scenario_helpers.cc b/cpp/049scenario_helpers.cc
index 8e303430..a2f4db2c 100644
--- a/cpp/049scenario_helpers.cc
+++ b/cpp/049scenario_helpers.cc
@@ -156,3 +156,98 @@ recipe main [
 +run: checking location 2
 +run: checking location 3
 +run: checking location 4
+
+//:: trace-should-contain and trace-should-not-contain raise warnings if the
+//:: trace doesn't meet given conditions
+
+:(scenario trace_check_warns_on_failure)
+% Hide_warnings = true;
+recipe main [
+  trace-should-contain [
+    a: b
+    a: d
+  ]
+]
++warn: missing [b] in trace layer a
+
+:(before "End Primitive Recipe Declarations")
+TRACE_SHOULD_CONTAIN,
+:(before "End Primitive Recipe Numbers")
+Recipe_number["trace-should-contain"] = TRACE_SHOULD_CONTAIN;
+:(before "End Primitive Recipe Implementations")
+case TRACE_SHOULD_CONTAIN: {
+  check_trace(current_instruction().ingredients[0].name);
+  break;
+}
+
+:(code)
+// simplified version of check_trace_contents() that emits warnings rather
+// than just printing to stderr
+bool check_trace(const string& expected) {
+  Trace_stream->newline();
+  vector<pair<string, string> > expected_lines = parse_trace(expected);
+  if (expected_lines.empty()) return true;
+  size_t curr_expected_line = 0;
+  for (vector<pair<string, pair<int, string> > >::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
+    if (expected_lines[curr_expected_line].first != p->first) continue;
+    if (expected_lines[curr_expected_line].second != p->second.second) continue;
+    // match
+    ++curr_expected_line;
+    if (curr_expected_line == expected_lines.size()) return true;
+  }
+
+  raise << "missing [" << expected_lines[curr_expected_line].second << "] "
+        << "in trace layer " << expected_lines[curr_expected_line].first << '\n';
+  return false;
+}
+
+vector<pair<string, string> > parse_trace(const string& expected) {
+  vector<string> buf = split(expected, "\n");
+  vector<pair<string, string> > result;
+  for (size_t i = 0; i < buf.size(); ++i) {
+    buf[i] = trim(buf[i]);
+    if (buf[i].empty()) continue;
+    size_t delim = buf[i].find(": ");
+    result.push_back(pair<string, string>(buf[i].substr(0, delim), buf[i].substr(delim+2)));
+  }
+  return result;
+}
+
+// see tests for this function in tangle/030tangle.test.cc
+string trim(const string& s) {
+  string::const_iterator first = s.begin();
+  while (first != s.end() && isspace(*first))
+    ++first;
+  if (first == s.end()) return "";
+
+  string::const_iterator last = --s.end();
+  while (last != s.begin() && isspace(*last))
+    --last;
+  ++last;
+  return string(first, last);
+}
+
+:(scenario trace_check_warns_on_failure_in_later_line)
+% Hide_warnings = true;
+recipe main [
+  run [
+    trace [a], [b]
+  ]
+  trace-should-contain [
+    a: b
+    a: d
+  ]
+]
++warn: missing [d] in trace layer a
+
+:(scenario trace_check_passes_silently)
+% Hide_warnings = true;
+recipe main [
+  run [
+    trace [a], [b]
+  ]
+  trace-should-contain [
+    a: b
+  ]
+]
+-warn: missing [b] in trace layer a
diff --git a/cpp/050scenario.cc b/cpp/050scenario.cc
index e67bb172..5dbc940a 100644
--- a/cpp/050scenario.cc
+++ b/cpp/050scenario.cc
@@ -210,20 +210,6 @@ void parse_scenario(const string& s) {
   parse_scenario(in);
 }
 
-string &trim(string &s) {
-  return ltrim(rtrim(s));
-}
-
-string &ltrim(string &s) {
-  s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(isspace))));
-  return s;
-}
-
-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)