about summary refs log tree commit diff stats
path: root/cpp/050scenario.cc
blob: bc60fcbc94d77f5134b5fea28d89f371169b1899 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//: Support a scenario [ ... ] form at the top level so we can start creating
//: scenarios in mu files just like we do in C++.

:(before "End Types")
struct scenario {
  string name;
  string to_run;
};

:(before "End Globals")
vector<scenario> Scenarios;

//:: How we check 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

:(scenario scenario_multiple_blocks)
scenario foo [
  run [
    1:integer <- copy 13:literal
  ]
  memory-should-contain [
    1 <- 13
  ]
  run [
    2:integer <- copy 13:literal
  ]
  memory-should-contain [
    1 <- 13
    2 <- 13
  ]
]

:(scenario scenario_check_memory_and_trace)
scenario foo [
  run [
    1:integer <- copy 13:literal
    trace [a], [a b c]
  ]
  memory-should-contain [
    1 <- 13
  ]
  trace-should-contain [
    a: a b c
  ]
  trace-should-not-contain [
    a: x y z
  ]
]

:(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);
}

scenario parse_scenario(istream& in) {
  scenario result;
  result.name = next_word(in);
  skip_bracket(in, "'scenario' must begin with '['");
  ostringstream buffer;
  slurp_until_matching_bracket(in, buffer);
  result.to_run = buffer.str();
  return result;
}

void run_mu_scenario(const scenario& s) {
  bool not_already_inside_test = !Trace_stream;
  if (not_already_inside_test) {
    Trace_file = s.name;
    Trace_stream = new trace_stream;
    setup();
  }
  run("recipe "+s.name+" [ " + s.to_run + " ]");
  if (not_already_inside_test) {
    teardown();
    ofstream fout((Trace_dir+Trace_file).c_str());
    fout << Trace_stream->readable_contents("");
    fout.close();
    delete Trace_stream;
    Trace_stream = NULL;
    Trace_file = "";
  }
}

:(before "End Command Handlers")
else if (command == "scenario") {
  Scenarios.push_back(parse_scenario(in));
}

:(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) {
//?   cerr << Passed << '\n'; //? 1
  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;
  while (in >> c) {
    if (c == '[') ++brace_depth;
    if (c == ']') --brace_depth;
    if (brace_depth == 0) break;  // drop final ']'
    out << c;
  }
}