blob: c595ce823963d93a22c8941f2f2073e062c060ef (
plain) (
tree)
|
|
//: 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")
vector<scenario> 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) {
setup();
Trace_file = Scenarios[i].name;
START_TRACING_UNTIL_END_OF_SCOPE
//? Trace_stream->dump_layer = "all"; //? 1
//? cout << "Before:\n"; dump_memory(); //? 1
//? cout << Scenarios[i].to_run; //? 1
run(Scenarios[i].to_run);
//? 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) {
cerr << Scenarios[i].name << ": Expected location " << p->first << " to contain " << p->second << " but saw " << Memory[p->first] << '\n';
Passed = false;
}
}
// End Scenario Checks
if (Passed) cerr << ".";
}
:(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);
trace("parse") << "scenario will run: " << x.to_run;
}
else if (scenario_command == "memory") {
handle_scenario_memory_directive(inner, x);
}
// 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);
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;
int address = 0; in >> address;
//? 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;
out.memory_expectations[address] = value;
trace("parse") << "memory expectation: *" << address << " == " << value;
}
skip_whitespace(in);
assert(in.get() == ']');
}
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;
}
}
void skip_bracket(istream& in, string message) {
skip_whitespace(in); skip_comments_and_newlines(in); skip_whitespace(in);
if (in.get() != '[')
raise << message << '\n';
}
void skip_whitespace_and_comments(istream& in) {
while (true) {
if (isspace(in.peek())) in.get();
else if (in.peek() == '#') skip_comment(in);
else break;
}
}
|