From ebe6c5f671a2ad6ea34fa20aeeda772694b3cf5c Mon Sep 17 00:00:00 2001 From: pantor Date: Tue, 15 Aug 2017 09:44:39 +0200 Subject: [PATCH] fix travis, more tests --- .travis.yml | 18 +-- src/inja.hpp | 197 +++++++++++++++++--------------- test/src/unit-files.cpp | 20 ++-- test/src/unit-parser.cpp | 117 +++++++++++-------- test/src/unit-string-helper.cpp | 48 ++++---- 5 files changed, 213 insertions(+), 187 deletions(-) diff --git a/.travis.yml b/.travis.yml index b035ebd..e810d81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,48 +21,48 @@ matrix: after_success: - make clean # - coveralls --exclude lib --exclude tests --gcov-options '\-lp' - + - compiler: gcc addons: apt: sources: ['ubuntu-toolchain-r-test'] packages: g++-4.9 env: COMPILER=g++-4.9 - + - compiler: gcc addons: apt: sources: ['ubuntu-toolchain-r-test'] packages: g++-5 env: COMPILER=g++-5 - + - compiler: gcc addons: apt: sources: ['ubuntu-toolchain-r-test'] packages: g++-6 env: COMPILER=g++-6 - + - compiler: gcc addons: apt: sources: ['ubuntu-toolchain-r-test'] packages: g++-7 env: COMPILER=g++-7 - + - compiler: clang addons: apt: sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6'] packages: clang-3.6 env: COMPILER=clang++-3.6 - + - compiler: clang addons: apt: - sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8'] - packages: clang-3.8 - env: COMPILER=clang++-3.8 + sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.7'] + packages: clang-3.7 + env: COMPILER=clang++-3.7 script: diff --git a/src/inja.hpp b/src/inja.hpp index 56da247..23b7a1e 100644 --- a/src/inja.hpp +++ b/src/inja.hpp @@ -13,7 +13,7 @@ namespace inja { - + using json = nlohmann::json; using string = std::string; @@ -30,7 +30,7 @@ inline string join_strings(std::vector vector, string delimiter) { struct SearchMatch { SearchMatch() { } - + SearchMatch(std::smatch match, size_t offset): match(match), offset(offset) { position = offset + match.position(); length = match.length(); @@ -41,10 +41,10 @@ struct SearchMatch { prefix = match.prefix(); suffix = match.suffix(); } - + std::smatch match; size_t offset; - + string outer, inner, prefix, suffix; size_t position, end_position; int length; @@ -53,7 +53,7 @@ struct SearchMatch { struct SearchMatchVector: public SearchMatch { SearchMatchVector(): SearchMatch() { } - + SearchMatchVector(std::smatch match, size_t offset, int inner_group, int regex_number): SearchMatch(match, offset), regex_number(regex_number) { inner = match.str(inner_group); } @@ -63,7 +63,7 @@ struct SearchMatchVector: public SearchMatch { struct SearchClosedMatch: public SearchMatch { SearchClosedMatch(): SearchMatch() { } - + SearchClosedMatch(string input, SearchMatch open_match, SearchMatch close_match): SearchMatch(), open_match(open_match), close_match(close_match) { position = open_match.position; length = close_match.end_position - open_match.position; @@ -74,18 +74,18 @@ struct SearchClosedMatch: public SearchMatch { prefix = open_match.prefix; suffix = close_match.suffix; } - + SearchMatch open_match, close_match; }; inline SearchMatch search(string input, std::regex regex, size_t position) { auto first = input.cbegin(); auto last = input.cend(); - + if (position >= input.length()) { return SearchMatch(); } - + std::smatch match; std::regex_search(first + position, last, match, regex); return SearchMatch(match, position); @@ -99,21 +99,20 @@ inline SearchMatchVector search(string input, std::vector regex_patterns regex_mark_counts.push_back(i); } } - - // TODO use search(...) + string regex_pattern = "(" + join_strings(regex_patterns, ")|(") + ")"; std::regex regex(regex_pattern); - + auto first = input.cbegin(); auto last = input.cend(); if (position >= input.length()) { return SearchMatchVector(); } - + std::smatch match; std::regex_search(first + position, last, match, regex); - + int number_regex = -1; int number_inner = 1; for (int i = 1; i < match.size(); i++) { @@ -123,25 +122,25 @@ inline SearchMatchVector search(string input, std::vector regex_patterns break; } } - + return SearchMatchVector(match, position, number_inner, number_regex); } inline SearchClosedMatch search_closed_match_on_level(string input, std::regex regex_statement, std::regex regex_level_up, std::regex regex_level_down, std::regex regex_search, SearchMatch open_match) { - + int level = 0; size_t current_position = open_match.end_position; SearchMatch statement_match = search(input, regex_statement, current_position); while (statement_match.found) { current_position = statement_match.end_position; - + if (level == 0 && std::regex_match(statement_match.inner, regex_search)) break; if (std::regex_match(statement_match.inner, regex_level_up)) level += 1; else if (std::regex_match(statement_match.inner, regex_level_down)) level -= 1; - + statement_match = search(input, regex_statement, current_position); } - + return SearchClosedMatch(input, open_match, statement_match); } @@ -150,7 +149,8 @@ inline SearchClosedMatch search_closed_match(string input, std::regex regex_stat } -namespace Parser { +class Parser { +public: enum Type { String, Loop, @@ -160,7 +160,7 @@ namespace Parser { Comment, Variable }; -} +}; class Environment { @@ -169,30 +169,30 @@ class Environment { std::regex regex_expression; std::regex regex_comment; std::vector regex_pattern_delimiters; - + string global_path; - - + + public: Environment(): Environment("./") { } - + Environment(string global_path): global_path(global_path) { const string regex_pattern_statement = "\\(\\%\\s*(.+?)\\s*\\%\\)"; const string regex_pattern_line_statement = "^##\\s*(.+)\\s*$"; const string regex_pattern_expression = "\\{\\{\\s*(.+?)\\s*\\}\\}"; const string regex_pattern_comment = "\\{#\\s*(.*?)\\s*#\\}"; - + regex_statement = std::regex(regex_pattern_statement); regex_line_statement = std::regex(regex_pattern_line_statement); regex_expression = std::regex(regex_pattern_expression); regex_comment = std::regex(regex_pattern_comment); regex_pattern_delimiters = { regex_pattern_statement, regex_pattern_expression, regex_pattern_comment }; } - + json parse_level(string input) { json result; - + size_t current_position = 0; SearchMatchVector statement_match = search(input, regex_pattern_delimiters, current_position); while (statement_match.found) { @@ -200,24 +200,24 @@ public: if (!statement_match.prefix.empty()) { result += {{"type", Parser::Type::String}, {"text", statement_match.prefix}}; } - + // Regex matched a statement "(% ... %)" if (statement_match.regex_number == 0) { const std::regex regex_loop_open("for (.*)"); const std::regex regex_loop_close("endfor"); - + const std::regex regex_include("include \"(.*)\""); - + const std::regex regex_condition_open("if (.*)"); const std::regex regex_condition_else_if("else if (.*)"); const std::regex regex_condition_else("else"); const std::regex regex_condition_close("endif"); - + std::smatch inner_statement_match; // Loop if (std::regex_match(statement_match.inner, inner_statement_match, regex_loop_open)) { SearchClosedMatch loop_match = search_closed_match(input, regex_statement, regex_loop_open, regex_loop_close, statement_match); - + current_position = loop_match.end_position; string loop_command = inner_statement_match.str(0); result += {{"type", Parser::Type::Loop}, {"command", loop_command}, {"inner", loop_match.inner}}; @@ -232,30 +232,30 @@ public: else if (std::regex_match(statement_match.inner, inner_statement_match, regex_condition_open)) { string if_command = inner_statement_match.str(0); json condition_result = {{"type", Parser::Type::Condition}, {"children", json::array()}}; - - + + SearchMatch condition_match = statement_match; - + SearchClosedMatch else_if_match = search_closed_match_on_level(input, regex_statement, regex_condition_open, regex_condition_close, regex_condition_else_if, condition_match); while (else_if_match.found) { condition_match = else_if_match.close_match; - + condition_result["children"] += {{"type", Parser::Type::ConditionBranch}, {"command", else_if_match.open_match.inner}, {"inner", else_if_match.inner}}; - + else_if_match = search_closed_match_on_level(input, regex_statement, regex_condition_open, regex_condition_close, regex_condition_else_if, condition_match); } - + SearchClosedMatch else_match = search_closed_match_on_level(input, regex_statement, regex_condition_open, regex_condition_close, regex_condition_else, condition_match); if (else_match.found) { condition_match = else_match.close_match; - + condition_result["children"] += {{"type", Parser::Type::ConditionBranch}, {"command", else_match.open_match.inner}, {"inner", else_match.inner}}; } - + SearchClosedMatch last_if_match = search_closed_match(input, regex_statement, regex_condition_open, regex_condition_close, condition_match); condition_result["children"] += {{"type", Parser::Type::ConditionBranch}, {"command", last_if_match.open_match.inner}, {"inner", last_if_match.inner}}; - + current_position = last_if_match.end_position; result += condition_result; } @@ -268,16 +268,16 @@ public: else if (statement_match.regex_number == 2) { result += {{"type", Parser::Type::Comment}, {"text", statement_match.inner}}; } - + statement_match = search(input, regex_pattern_delimiters, current_position); } if (current_position < input.length()) { result += {{"type", Parser::Type::String}, {"text", input.substr(current_position)}}; } - + return result; } - + json parse_tree(json current_element) { if (current_element.find("inner") != current_element.end()) { current_element["children"] = parse_level(current_element["inner"]); @@ -290,41 +290,45 @@ public: } return current_element; } - + json parse(string input) { return parse_tree({{"inner", input}})["children"]; } - - + + json parse_variable(string input, json data) { + return parse_variable(input, data, true); + } + + json parse_variable(string input, json data, bool throw_error) { // Json Raw Data if ( json::accept(input) ) { return json::parse(input); } - + // TODO Implement filter and functions if (input[0] != '/') input.insert(0, "/"); - + json::json_pointer ptr(input); json result = data[ptr]; - - if (result.is_null()) throw std::runtime_error("JSON pointer found no element."); + + if (throw_error && result.is_null()) throw std::runtime_error("JSON pointer found no element."); return result; } - + bool parse_condition(string condition, json data) { - const std::regex regex_condition_not("not (.*)"); - const std::regex regex_condition_equal("(.*) == (.*)"); - const std::regex regex_condition_greater("(.*) > (.*)"); - const std::regex regex_condition_less("(.*) < (.*)"); - const std::regex regex_condition_greater_equal("(.*) >= (.*)"); - const std::regex regex_condition_less_equal("(.*) <= (.*)"); - const std::regex regex_condition_different("(.*) != (.*)"); - const std::regex regex_condition_in("(.*) in (.*)"); - + const std::regex regex_condition_not("not (.+)"); + const std::regex regex_condition_equal("(.+) == (.+)"); + const std::regex regex_condition_greater("(.+) > (.+)"); + const std::regex regex_condition_less("(.+) < (.+)"); + const std::regex regex_condition_greater_equal("(.+) >= (.+)"); + const std::regex regex_condition_less_equal("(.+) <= (.+)"); + const std::regex regex_condition_different("(.+) != (.+)"); + const std::regex regex_condition_in("(.+) in (.+)"); + std::smatch match_condition; - if (std::regex_match(condition, match_condition, regex_condition_equal)) { + if (std::regex_match(condition, match_condition, regex_condition_not)) { return !parse_condition(match_condition.str(1), data); } else if (std::regex_match(condition, match_condition, regex_condition_equal)) { @@ -362,51 +366,52 @@ public: json list = parse_variable(match_condition.str(2), data); return (std::find(list.begin(), list.end(), item) != list.end()); } - - try { - return parse_variable(condition, data); - } - catch (...) { - return false; - } + + json var = parse_variable(condition, data, false); + if (var.empty()) return false; + else if (var.is_boolean()) return var; + else if (var.is_number()) return (var != 0); + else if (var.is_string()) return (var != ""); + return false; } - + string render_json(json data) { if (data.is_string()) { return data; - } else { + } + else { std::stringstream ss; ss << data; return ss.str(); } } - - string render_tree(json input, json data, string path) { - string result = ""; + + string render_tree(json input, json data, string path) { + string result = ""; for (auto element: input) { switch ( (Parser::Type) element["type"] ) { case Parser::Type::String: { result += element["text"]; - break; + break; } case Parser::Type::Variable: { json variable = parse_variable(element["command"], data); result += render_json(variable); - break; + break; } case Parser::Type::Include: { result += render_template(path + element["filename"].get(), data); break; - } + } case Parser::Type::Loop: { const std::regex regex_loop_list("for (\\w+) in (.+)"); - + string command = element["command"].get(); std::smatch match_command; if (std::regex_match(command, match_command, regex_loop_list)) { string item_name = match_command.str(1); string list_name = match_command.str(2); - + json list = parse_variable(list_name, data); for (int i = 0; i < list.size(); i++) { json data_loop = data; @@ -418,23 +423,29 @@ public: result += render_tree(element["children"], data_loop, path); } } + else { + throw std::runtime_error("Unknown loop in renderer."); + } break; } case Parser::Type::Condition: { const std::regex regex_condition("(if|else if|else) ?(.*)"); - + for (auto branch: element["children"]) { string command = branch["command"].get(); std::smatch match_command; if (std::regex_match(command, match_command, regex_condition)) { string condition_type = match_command.str(1); string condition = match_command.str(2); - + if (parse_condition(condition, data) || condition_type == "else") { result += render_tree(branch["children"], data, path); break; } } + else { + throw std::runtime_error("Unknown condition in renderer."); + } } break; } @@ -443,39 +454,39 @@ public: } default: { throw std::runtime_error("Unknown type in renderer."); - } + } } } return result; - } - + } + string render(string input, json data, string path) { json parsed = parse(input); return render_tree(parsed, data, path); } - - + + string render(string input, json data) { return render(input, data, "./"); } - + string render_template(string filename, json data) { string text = load_file(filename); - string path = filename.substr(0, filename.find_last_of("/\\") + 1); // Include / itself + string path = filename.substr(0, filename.find_last_of("/\\") + 1); return render(text, data, path); } - + string render_template_with_json_file(string filename, string filename_data) { json data = load_json(filename_data); return render_template(filename, data); } - + string load_file(string filename) { std::ifstream file(global_path + filename); string text((std::istreambuf_iterator(file)), std::istreambuf_iterator()); return text; } - + json load_json(string filename) { std::ifstream file(global_path + filename); json j; @@ -490,4 +501,4 @@ inline string render(string input, json data) { } // namespace inja -#endif // PANTOR_INJA_HPP \ No newline at end of file +#endif // PANTOR_INJA_HPP diff --git a/test/src/unit-files.cpp b/test/src/unit-files.cpp index f2b8bde..8b2877f 100644 --- a/test/src/unit-files.cpp +++ b/test/src/unit-files.cpp @@ -7,30 +7,30 @@ using Environment = inja::Environment; using json = nlohmann::json; -TEST_CASE("files handling") { +TEST_CASE("Files handling") { Environment env = Environment(); json data; data["name"] = "Jeff"; - - SECTION("files should be loaded") { + + SECTION("Files should be loaded") { CHECK( env.load_file("../test/data/simple.txt") == "Hello {{ name }}." ); } - - SECTION("files should be rendered") { + + SECTION("Files should be rendered") { CHECK( env.render_template("../test/data/simple.txt", data) == "Hello Jeff." ); } - - SECTION("file includes should be rendered") { + + SECTION("File includes should be rendered") { CHECK( env.render_template("../test/data/include.txt", data) == "Answer: Hello Jeff." ); } } -TEST_CASE("complete files") { +TEST_CASE("Complete files") { Environment env = Environment("../test/data/"); - + for (std::string test_name : {"simple-file", "nested"}) { SECTION(test_name) { CHECK( env.render_template_with_json_file(test_name + "/template.txt", test_name + "/data.json") == env.load_file(test_name + "/result.txt") ); } } -} \ No newline at end of file +} diff --git a/test/src/unit-parser.cpp b/test/src/unit-parser.cpp index f503ea9..7853447 100644 --- a/test/src/unit-parser.cpp +++ b/test/src/unit-parser.cpp @@ -8,41 +8,50 @@ using json = nlohmann::json; using Type = inja::Parser::Type; -TEST_CASE("parse structure") { +TEST_CASE("Parse structure") { Environment env = Environment(); - - SECTION("basic") { - std::string test = "asdf"; - json result = {{{"type", Type::String}, {"text", "asdf"}}}; - + + SECTION("Basic string") { + std::string test = "lorem ipsum"; + json result = {{{"type", Type::String}, {"text", "lorem ipsum"}}}; CHECK( env.parse(test) == result ); } - - SECTION("variables") { + + SECTION("Empty string") { + std::string test = ""; + json result = {}; + CHECK( env.parse(test) == result ); + } + + SECTION("Variable") { std::string test = "{{ name }}"; json result = {{{"type", Type::Variable}, {"command", "name"}}}; CHECK( env.parse(test) == result ); - - std::string test_combined = "Hello {{ name }}!"; - json result_combined = { + } + + SECTION("Combined string and variables") { + std::string test = "Hello {{ name }}!"; + json result = { {{"type", Type::String}, {"text", "Hello "}}, {{"type", Type::Variable}, {"command", "name"}}, {{"type", Type::String}, {"text", "!"}} }; - CHECK( env.parse(test_combined) == result_combined ); - - std::string test_multiple = "Hello {{ name }}! I come from {{ city }}."; - json result_multiple = { + CHECK( env.parse(test) == result ); + } + + SECTION("Multiple variables") { + std::string test = "Hello {{ name }}! I come from {{ city }}."; + json result = { {{"type", Type::String}, {"text", "Hello "}}, {{"type", Type::Variable}, {"command", "name"}}, {{"type", Type::String}, {"text", "! I come from "}}, {{"type", Type::Variable}, {"command", "city"}}, {{"type", Type::String}, {"text", "."}} }; - CHECK( env.parse(test_multiple) == result_multiple ); + CHECK( env.parse(test) == result ); } - - SECTION("loops") { + + SECTION("Loops") { std::string test = "open (% for e in list %)lorem(% endfor %) closing"; json result = { {{"type", Type::String}, {"text", "open "}}, @@ -51,21 +60,22 @@ TEST_CASE("parse structure") { }}}, {{"type", Type::String}, {"text", " closing"}} }; - - std::string test_nested = "(% for e in list %)(% for b in list2 %)lorem(% endfor %)(% endfor %)"; - json result_nested = { + CHECK( env.parse(test) == result ); + } + + SECTION("Nested loops") { + std::string test = "(% for e in list %)(% for b in list2 %)lorem(% endfor %)(% endfor %)"; + json result = { {{"type", Type::Loop}, {"command", "for e in list"}, {"children", { {{"type", Type::Loop}, {"command", "for b in list2"}, {"children", { {{"type", Type::String}, {"text", "lorem"}} }}} }}} }; - CHECK( env.parse(test) == result ); - CHECK( env.parse(test_nested) == result_nested ); } - - SECTION("conditionals") { + + SECTION("Basic conditional") { std::string test = "(% if true %)dfgh(% endif %)"; json result = { {{"type", Type::Condition}, {"children", { @@ -74,9 +84,12 @@ TEST_CASE("parse structure") { }}} }}} }; - - std::string test2 = "if: (% if maybe %)first if(% else if perhaps %)first else if(% else if sometimes %)second else if(% else %)test else(% endif %)"; - json result2 = { + CHECK( env.parse(test) == result ); + } + + SECTION("If/else if/else conditional") { + std::string test = "if: (% if maybe %)first if(% else if perhaps %)first else if(% else if sometimes %)second else if(% else %)test else(% endif %)"; + json result = { {{"type", Type::String}, {"text", "if: "}}, {{"type", Type::Condition}, {"children", { {{"type", Type::ConditionBranch}, {"command", "if maybe"}, {"children", { @@ -87,21 +100,25 @@ TEST_CASE("parse structure") { }}}, {{"type", Type::ConditionBranch}, {"command", "else if sometimes"}, {"children", { {{"type", Type::String}, {"text", "second else if"}} - }}}, + }}}, {{"type", Type::ConditionBranch}, {"command", "else"}, {"children", { {{"type", Type::String}, {"text", "test else"}} - }}}, + }}}, }}} }; - CHECK( env.parse(test) == result ); - CHECK( env.parse(test2) == result2 ); + } + + SECTION("Comments") { + std::string test = "{# lorem ipsum #}"; + json result = {{{"type", Type::Comment}, {"text", "lorem ipsum"}}}; + CHECK( env.parse(test) == result ); } } - -TEST_CASE("parse json") { + +TEST_CASE("Parse json") { Environment env = Environment(); - + json data; data["name"] = "Peter"; data["city"] = "Washington D.C."; @@ -110,14 +127,14 @@ TEST_CASE("parse json") { data["brother"]["name"] = "Chris"; data["brother"]["daughters"] = {"Maria", "Helen"}; data["brother"]["daughter0"] = { { "name", "Maria" } }; - - SECTION("variables from values") { + + SECTION("Variables from values") { CHECK( env.parse_variable("42", data) == 42 ); CHECK( env.parse_variable("3.1415", data) == 3.1415 ); CHECK( env.parse_variable("\"hello\"", data) == "hello" ); } - - SECTION("variables from JSON data") { + + SECTION("Variables from JSON data") { CHECK( env.parse_variable("name", data) == "Peter" ); CHECK( env.parse_variable("age", data) == 29 ); CHECK( env.parse_variable("names/1", data) == "Seb" ); @@ -127,20 +144,21 @@ TEST_CASE("parse json") { } } -TEST_CASE("parse conditions") { +TEST_CASE("Parse conditions") { Environment env = Environment(); - + json data; data["age"] = 29; data["brother"] = "Peter"; data["father"] = "Peter"; - - SECTION("elements") { - // CHECK( env.parse_condition("age", data) ); + + SECTION("Elements") { + CHECK( env.parse_condition("age", data) ); CHECK_FALSE( env.parse_condition("size", data) ); + CHECK( env.parse_condition("not size", data) ); } - - SECTION("numbers") { + + SECTION("Numbers") { CHECK( env.parse_condition("age == 29", data) ); CHECK( env.parse_condition("age >= 29", data) ); CHECK( env.parse_condition("age <= 29", data) ); @@ -150,9 +168,10 @@ TEST_CASE("parse conditions") { CHECK_FALSE( env.parse_condition("age < 28", data) ); CHECK_FALSE( env.parse_condition("age < -100.0", data) ); } - - SECTION("strings") { + + SECTION("Strings") { CHECK( env.parse_condition("brother == father", data) ); CHECK( env.parse_condition("brother == \"Peter\"", data) ); + CHECK_FALSE( env.parse_condition("not brother == father", data) ); } -} \ No newline at end of file +} diff --git a/test/src/unit-string-helper.cpp b/test/src/unit-string-helper.cpp index f054d15..256499c 100644 --- a/test/src/unit-string-helper.cpp +++ b/test/src/unit-string-helper.cpp @@ -3,22 +3,18 @@ #include "inja.hpp" -using Environment = inja::Environment; -using json = nlohmann::json; - - -TEST_CASE("string vector join function") { +TEST_CASE("String vector join function") { CHECK( inja::join_strings({"1", "2", "3"}, ",") == "1,2,3" ); CHECK( inja::join_strings({"1", "2", "3", "4", "5"}, " ") == "1 2 3 4 5" ); CHECK( inja::join_strings({}, " ") == "" ); CHECK( inja::join_strings({"single"}, "---") == "single" ); } -TEST_CASE("basic search in string") { +TEST_CASE("Basic search in string") { std::string input = "lorem ipsum dolor it"; std::regex regex("i(.*)m"); - - SECTION("basic search from start") { + + SECTION("Basic search from start") { inja::SearchMatch match = inja::search(input, regex, 0); CHECK( match.found == true ); CHECK( match.position == 6 ); @@ -27,26 +23,26 @@ TEST_CASE("basic search in string") { CHECK( match.outer == "ipsum" ); CHECK( match.inner == "psu" ); } - - SECTION("basic search from position") { + + SECTION("Basic search from position") { inja::SearchMatch match = inja::search(input, regex, 8); CHECK( match.found == false ); CHECK( match.length == 0 ); } } -TEST_CASE("search in string with multiple possible regexes") { +TEST_CASE("Search in string with multiple possible regexes") { std::string input = "lorem ipsum dolor amit estas tronum."; - - SECTION("basic 1") { + + SECTION("Basic 1") { std::vector regex_patterns = { "tras", "do(\\w*)or", "es(\\w*)as", "ip(\\w*)um" }; inja::SearchMatchVector match = inja::search(input, regex_patterns, 0); CHECK( match.regex_number == 3 ); CHECK( match.outer == "ipsum" ); CHECK( match.inner == "s" ); } - - SECTION("basic 2") { + + SECTION("Basic 2") { std::vector regex_patterns = { "tras", "ip(\\w*)um", "do(\\w*)or", "es(\\w*)as" }; inja::SearchMatchVector match = inja::search(input, regex_patterns, 0); CHECK( match.regex_number == 1 ); @@ -55,34 +51,34 @@ TEST_CASE("search in string with multiple possible regexes") { } } -TEST_CASE("search on level") { +TEST_CASE("Search on level") { std::string input = "(% up %)(% up %)Test(% N1 %)(% down %)...(% up %)(% N2 %)(% up %)(% N3 %)(% down %)(% N4 %)(% down %)(% N5 %)(% down %)"; - + std::regex regex_statement("\\(\\% (.*?) \\%\\)"); std::regex regex_level_up("up"); std::regex regex_level_down("down"); std::regex regex_search("N(\\d+)"); - - SECTION("first instance") { + + SECTION("First instance") { inja::SearchMatch open_match = inja::search(input, regex_statement, 0); CHECK( open_match.position == 0 ); CHECK( open_match.end_position == 8 ); CHECK( open_match.inner == "up" ); - + inja::SearchClosedMatch match = inja::search_closed_match_on_level(input, regex_statement, regex_level_up, regex_level_down, regex_search, open_match); CHECK( match.position == 0 ); CHECK( match.end_position == 109 ); } - - SECTION("second instance") { + + SECTION("Second instance") { inja::SearchMatch open_match = inja::search(input, regex_statement, 4); - + CHECK( open_match.position == 8 ); CHECK( open_match.end_position == 16 ); CHECK( open_match.inner == "up" ); - + inja::SearchClosedMatch match = inja::search_closed_match_on_level(input, regex_statement, regex_level_up, regex_level_down, regex_search, open_match); - + CHECK( match.open_match.position == 8 ); CHECK( match.open_match.end_position== 16 ); CHECK( match.close_match.position == 20 ); @@ -92,4 +88,4 @@ TEST_CASE("search on level") { CHECK( match.outer == "(% up %)Test(% N1 %)" ); CHECK( match.inner == "Test" ); } -} \ No newline at end of file +}