void test_tangle() {
istringstream in("a\n"
"b\n"
"c\n"
":(before b)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"d"
"b"
"c");
}
void test_tangle_with_linenumber() {
istringstream in("a\n"
"b\n"
"c\n"
":(before b)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "#line 1"
"a"
"#line 5"
"d"
"#line 2"
"b"
"c");
// no other #line directives
CHECK_TRACE_DOESNT_CONTAIN("tangle", "#line 3");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "#line 4");
}
void test_tangle_linenumbers_with_filename() {
istringstream in("a\n"
"b\n"
"c\n"
":(before b)\n"
"d\n");
list<Line> dummy;
tangle(in, "foo", dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"#line 5 \"foo\""
"d"
"b"
"c");
}
void test_tangle_line_numbers_with_multiple_filenames() {
istringstream in1("a\n"
"b\n"
"c");
list<Line> dummy;
tangle(in1, "foo", dummy);
CLEAR_TRACE;
istringstream in2(":(before b)\n"
"d\n");
tangle(in2, "bar", dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"#line 2 \"bar\""
"d"
"#line 2 \"foo\""
"b"
"c");
}
void test_tangle_linenumbers_with_multiple_directives() {
istringstream in1("a\n"
"b\n"
"c");
list<Line> dummy;
tangle(in1, "foo", dummy);
CLEAR_TRACE;
istringstream in2(":(before b)\n"
"d\n"
":(before c)\n"
"e");
tangle(in2, "bar", dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"#line 2 \"bar\""
"d"
"#line 2 \"foo\""
"b"
"#line 4 \"bar\""
"e"
"#line 3 \"foo\""
"c");
}
void test_tangle_with_multiple_filenames_after() {
istringstream in1("a\n"
"b\n"
"c");
list<Line> dummy;
tangle(in1, "foo", dummy);
CLEAR_TRACE;
istringstream in2(":(after b)\n"
"d\n");
tangle(in2, "bar", dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"b"
"#line 2 \"bar\""
"d"
"#line 3 \"foo\""
"c");
}
void test_tangle_skip_tanglecomments() {
istringstream in("a\n"
"b\n"
"c\n"
"//: 1\n"
"//: 2\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"b"
"c"
""
""
"d");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "//: 1");
}
void test_tangle_with_tanglecomments_and_directive() {
istringstream in("a\n"
"//: 1\n"
"b\n"
"c\n"
":(before b)\n"
"d\n"
":(code)\n"
"e\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"#line 6"
"d"
"#line 3"
"b"
"c"
"#line 8"
"e");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "//: 1");
}
void test_tangle_with_tanglecomments_inside_directive() {
istringstream in("a\n"
"//: 1\n"
"b\n"
"c\n"
":(before b)\n"
"//: abc\n"
"d\n"
":(code)\n"
"e\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"#line 7"
"d"
"#line 3"
"b"
"c"
"#line 9"
"e");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "//: 1");
}
void test_tangle_with_multiword_directives() {
istringstream in("a b\n"
"c\n"
":(after \"a b\")\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a b"
"d"
"c");
}
void test_tangle_with_quoted_multiword_directives() {
istringstream in("a \"b\"\n"
"c\n"
":(after \"a \\\"b\\\"\")\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a \"b\""
"d"
"c");
}
void test_tangle2() {
istringstream in("a\n"
"b\n"
"c\n"
":(after b)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"b"
"d"
"c");
}
void test_tangle_at_end() {
istringstream in("a\n"
"b\n"
"c\n"
":(after c)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"b"
"c"
"d");
}
void test_tangle_indents_hunks_correctly() {
istringstream in("a\n"
" b\n"
"c\n"
":(after b)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
" b"
" d"
"c");
}
void test_tangle_warns_on_missing_target() {
Hide_warnings = true;
istringstream in(":(before)\n"
"abc def\n");
list<Line> lines;
tangle(in, lines);
CHECK_TRACE_WARNS();
}
void test_tangle_warns_on_unknown_target() {
Hide_warnings = true;
istringstream in(":(before \"foo\")\n"
"abc def\n");
list<Line> lines;
tangle(in, lines);
CHECK_TRACE_WARNS();
}
void test_tangle_delete_range_of_lines() {
istringstream in("a\n"
"b {\n"
"c\n"
"}\n"
":(delete{} \"b\")\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "b");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "c");
}
void test_tangle_replace() {
istringstream in("a\n"
"b\n"
"c\n"
":(replace b)\n"
"d\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"d"
"c");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "b");
}
void test_tangle_replace_range_of_lines() {
istringstream in("a\n"
"b {\n"
"c\n"
"}\n"
":(replace{} \"b\")\n"
"d\n"
"e\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"d"
"e");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "b {");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "c");
}
void test_tangle_replace_tracks_old_lines() {
istringstream in("a\n"
"b {\n"
"c\n"
"}\n"
":(replace{} \"b\")\n"
"d\n"
":OLD_CONTENTS\n"
"e\n");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"d"
"c"
"e");
CHECK_TRACE_DOESNT_CONTAIN("tangle", "b {");
}
void test_tangle_nested_patterns() {
istringstream in("a\n"
"c\n"
"b\n"
"c\n"
"d\n"
":(after \"b\" then \"c\")\n"
"e");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"c"
"b"
"c"
"e"
"d");
}
void test_tangle_nested_patterns2() {
istringstream in("a\n"
"c\n"
"b\n"
"c\n"
"d\n"
":(after \"c\" following \"b\")\n"
"e");
list<Line> dummy;
tangle(in, dummy);
CHECK_TRACE_CONTENTS("tangle", "a"
"c"
"b"
"c"
"e"
"d");
}
// todo: include line numbers in tangle errors
//// scenarios
void test_tangle_supports_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"+layer1: pqr\n"
"+layer2: xyz");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_ignores_empty_lines_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"+layer1: pqr\n"
" \n"
"+layer2: xyz");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_handles_empty_lines_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"\n"
"+layer1: pqr\n"
"+layer2: xyz");
list<Line> lines;
tangle(in, lines);
// no infinite loop
}
void test_tangle_supports_configurable_toplevel() {
istringstream in(":(scenarios foo)\n"
":(scenario does_bar)\n"
"abc def\n"
"+layer1: pqr");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " foo("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
istringstream cleanup(":(scenarios run)\n");
tangle(cleanup, lines);
}
void test_tangle_can_hide_warnings_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"% Hide_warnings = true;\n"
"abc def\n"
"+layer1: pqr\n"
"+layer2: xyz");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " Hide_warnings = true;"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_include_c_code_at_end_of_scenario() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"+layer1: pqr\n"
"+layer2: xyz\n"
"% int x = 1;");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " int x = 1;"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_include_c_code_at_end_of_scenario_without_trace_expectations() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"% int x = 1;");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " int x = 1;"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_supports_strings_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc \"def\"\n"
"+layer1: pqr\n"
"+layer2: \"xyz\"");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc \\\"def\\\"\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: \\\"xyz\\\"\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_supports_strings_in_scenarios2() {
istringstream in(":(scenario does_bar)\n"
"abc \"\"\n"
"+layer1: pqr\n"
"+layer2: \"\"");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc \\\"\\\"\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: \\\"\\\"\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_supports_multiline_input_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
" efg\n"
"+layer1: pqr\n"
"+layer2: \"\"");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: \\\"\\\"\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_supports_reset_in_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"===\n"
"efg\n"
"+layer1: pqr\n"
"+layer2: \"\"");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CLEAR_TRACE;"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: \\\"\\\"\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_check_for_absence_at_end_of_scenarios() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
" efg\n"
"+layer1: pqr\n"
"-layer1: xyz");
list<Line> lines;
tangle(in, lines);
//? for (list<Line>::iterator p = lines.begin(); p != lines.end(); ++p)
//? cerr << p->contents << '\n';
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_DOESNT_CONTAIN(\"layer1: xyz\");"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_check_for_absence_at_end_of_scenarios2() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
" efg\n"
"-layer1: pqr\n"
"-layer1: xyz");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_DOESNT_CONTAIN(\"layer1: pqr\");"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_DOESNT_CONTAIN(\"layer1: xyz\");"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_check_for_count_in_scenario() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
" efg\n"
"$layer1: 2");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_COUNT(\"layer1\", 2);"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_handle_mu_comments_in_scenario() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"# comment1\n"
" efg\n"
" # indented comment 2\n"
"+layer1: pqr\n"
"# comment inside expected_trace\n"
"+layer1: xyz\n"
"# comment after expected trace\n"
"-layer1: z\n"
"# comment before trace count\n"
"$layer1: 2\n"
"# comment at end\n"
"\n");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"# comment1\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" efg\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \" # indented comment 2\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_DOESNT_CONTAIN(\"layer1: z\");"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_COUNT(\"layer1\", 2);"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
void test_tangle_can_interleave_present_and_absent_lines_to_kludgily_avoid_specifying_order() {
istringstream in(":(scenario does_bar)\n"
"abc def\n"
"+layer1: pqr\n"
"-absent\n"
"+layer2: xyz");
list<Line> lines;
tangle(in, lines);
CHECK_EQ(lines.front().contents, "void test_does_bar() {"); lines.pop_front();
CHECK_EQ(lines.front().contents, " run("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"abc def\\n\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer1: pqr\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_DOESNT_CONTAIN(\"absent\");"); lines.pop_front();
CHECK_EQ(lines.front().contents, " CHECK_TRACE_CONTENTS("); lines.pop_front();
CHECK_EQ(lines.front().contents, " \"layer2: xyz\""); lines.pop_front();
CHECK_EQ(lines.front().contents, " );"); lines.pop_front();
CHECK_EQ(lines.front().contents, "}"); lines.pop_front();
CHECK(lines.empty());
}
//// helpers
void test_trim() {
CHECK_EQ(trim(""), "");
CHECK_EQ(trim(" "), "");
CHECK_EQ(trim(" "), "");
CHECK_EQ(trim("a"), "a");
CHECK_EQ(trim(" a"), "a");
CHECK_EQ(trim(" a"), "a");
CHECK_EQ(trim(" ab"), "ab");
CHECK_EQ(trim("a "), "a");
CHECK_EQ(trim("a "), "a");
CHECK_EQ(trim("ab "), "ab");
CHECK_EQ(trim(" a "), "a");
CHECK_EQ(trim(" a "), "a");
CHECK_EQ(trim(" ab "), "ab");
}
void test_strip_indent() {
CHECK_EQ(strip_indent("", 0), "");
CHECK_EQ(strip_indent("", 1), "");
CHECK_EQ(strip_indent("", 3), "");
CHECK_EQ(strip_indent(" ", 0), " ");
CHECK_EQ(strip_indent(" a", 0), " a");
CHECK_EQ(strip_indent(" ", 1), "");
CHECK_EQ(strip_indent(" a", 1), "a");
CHECK_EQ(strip_indent(" ", 2), "");
CHECK_EQ(strip_indent(" a", 2), "a");
CHECK_EQ(strip_indent(" ", 0), " ");
CHECK_EQ(strip_indent(" a", 0), " a");
CHECK_EQ(strip_indent(" ", 1), " ");
CHECK_EQ(strip_indent(" a", 1), " a");
CHECK_EQ(strip_indent(" ", 2), "");
CHECK_EQ(strip_indent(" a", 2), "a");
CHECK_EQ(strip_indent(" ", 3), "");
CHECK_EQ(strip_indent(" a", 3), "a");
}