From 9c7c41849b4877da066c923796d94a196f210617 Mon Sep 17 00:00:00 2001 From: Alex Overchenko Date: Wed, 2 Dec 2020 20:14:27 +0300 Subject: [PATCH 1/6] TEST_MATRIX was added: Can be helpful for iterating every combination: * for usual TEST_CASE simplification Based on TEST_RANGE implementation --- auto/generate_test_runner.rb | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 9401ad88..766c4509 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -130,7 +130,7 @@ def find_tests(source) lines.each_with_index do |line, _index| # find tests - next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE|TEST_MATRIX)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m arguments = Regexp.last_match(1) name = Regexp.last_match(2) @@ -155,6 +155,27 @@ def find_tests(source) arg_combinations.flatten.join(', ') end end + + # Based on: + ## https://en.cppreference.com/w/cpp/language/integer_literal + ## https://en.cppreference.com/w/cpp/language/character_literal + ## https://en.cppreference.com/w/cpp/language/floating_literal + ## https://en.cppreference.com/w/cpp/language/escape + ## Strings & chars with '[', ']', '(', ')' + ## Empty args + + one_arg_regex_string = /(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^"',\s\]][^,\s\]]*|)/.source + + arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/).flatten.each do |values| + args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/).flatten.map do |one_arg_values| + # Force appending comma for usual regular matching + (one_arg_values + ',').scan(/(#{one_arg_regex_string})\s*,/) + end.reduce do |result, arg_range_expanded| + result.product(arg_range_expanded) + end.map do |arg_combinations| + arg_combinations.flatten.join(', ') + end + end end tests_and_line_numbers << { test: name, args: args, call: call, params: params, line_number: 0 } From c8b56ac5542575fbad72e918c91a7f05c3b0d902 Mon Sep 17 00:00:00 2001 From: Alex Overchenko Date: Mon, 7 Dec 2020 10:05:36 +0300 Subject: [PATCH 2/6] TEST_MATRIX will match arguments with spaces and string concatenations now --- auto/generate_test_runner.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 766c4509..576004a7 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -159,12 +159,16 @@ def find_tests(source) # Based on: ## https://en.cppreference.com/w/cpp/language/integer_literal ## https://en.cppreference.com/w/cpp/language/character_literal + ## https://en.cppreference.com/w/cpp/language/string_literal ## https://en.cppreference.com/w/cpp/language/floating_literal ## https://en.cppreference.com/w/cpp/language/escape ## Strings & chars with '[', ']', '(', ')' ## Empty args + ## Args with spaces (not strings or char sequences) + ## String concatenations: "Hello" "World" - one_arg_regex_string = /(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|[^"',\s\]][^,\s\]]*|)/.source + one_number_or_text_regex_string = /(?:[^"',\s\]](?:[^"',\]]*[^"',\s\]])*|(?:(?:\+\-)\s*)?\d+(?:'\d+)*)/.source + one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*|)"(?:[^"\\]|\\.)*")+|(?:#{one_number_or_text_regex_string}\s*|)'(?:[^'\\]|\\.)*'|(?:#{one_number_or_text_regex_string}|))\s*/.source arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/).flatten.each do |values| args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/).flatten.map do |one_arg_values| From 32d4923c4c7c192fec2ddc0577b3d9c5665abe92 Mon Sep 17 00:00:00 2001 From: Aleksey Date: Mon, 7 Dec 2020 11:24:13 +0300 Subject: [PATCH 3/6] TEST_MATRIX regex optimizations --- auto/generate_test_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 576004a7..a18ceffa 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -167,7 +167,7 @@ def find_tests(source) ## Args with spaces (not strings or char sequences) ## String concatenations: "Hello" "World" - one_number_or_text_regex_string = /(?:[^"',\s\]](?:[^"',\]]*[^"',\s\]])*|(?:(?:\+\-)\s*)?\d+(?:'\d+)*)/.source + one_number_or_text_regex_string = /(?:[^"',\s\]](?:[^"',\]][^"',\s\]]?)*|(?:(?:\+\-)\s*)?\d+(?:'\d+)*)/.source one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*|)"(?:[^"\\]|\\.)*")+|(?:#{one_number_or_text_regex_string}\s*|)'(?:[^'\\]|\\.)*'|(?:#{one_number_or_text_regex_string}|))\s*/.source arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/).flatten.each do |values| From e14bd3c71ff273fc57af9e4a42990a014ab3f6d8 Mon Sep 17 00:00:00 2001 From: Alex Overchenko Date: Tue, 8 Dec 2020 09:28:13 +0300 Subject: [PATCH 4/6] TEST_MATRIX generator: * (DEFINED_VALUE + 1) calls will be correctly detected now * signed numbers should be correctly detected now * regex speed improvements --- auto/generate_test_runner.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index a18ceffa..0de05667 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -166,9 +166,12 @@ def find_tests(source) ## Empty args ## Args with spaces (not strings or char sequences) ## String concatenations: "Hello" "World" + # Not supported: array addressing (with []) - one_number_or_text_regex_string = /(?:[^"',\s\]](?:[^"',\]][^"',\s\]]?)*|(?:(?:\+\-)\s*)?\d+(?:'\d+)*)/.source - one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*|)"(?:[^"\\]|\\.)*")+|(?:#{one_number_or_text_regex_string}\s*|)'(?:[^'\\]|\\.)*'|(?:#{one_number_or_text_regex_string}|))\s*/.source + one_number_or_text_regex_string = /[^"',\s\]](?:['\s]*[^"',\s\]])*/.source + one_string_regex_string = /"(?:[^"\\]|\\.)*"/.source + one_char_regex_string = /'(?:[^'\\]|\\.)*'/.source + one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*)?#{one_string_regex_string})+|(?:#{one_number_or_text_regex_string}\s*)?#{one_char_regex_string}|(?:#{one_number_or_text_regex_string}))/.source arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/).flatten.each do |values| args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/).flatten.map do |one_arg_values| From b56a7f7645052bece78e0090f54f4a776010b3b0 Mon Sep 17 00:00:00 2001 From: Alex Overchenko Date: Tue, 8 Dec 2020 10:52:10 +0300 Subject: [PATCH 5/6] Multiline TEST_* matches support was added --- auto/generate_test_runner.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 0de05667..59221a2a 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -140,10 +140,10 @@ def find_tests(source) if @options[:use_param_tests] && !arguments.empty? args = [] - arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) { |a| args << a[0] } + arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/m) { |a| args << a[0] } - arguments.scan(/\s*TEST_RANGE\s*\((.*)\)\s*$/).flatten.each do |range_str| - args += range_str.scan(/\[\s*(-?\d+.?\d*),\s*(-?\d+.?\d*),\s*(-?\d+.?\d*)\s*\]/).map do |arg_values_str| + arguments.scan(/\s*TEST_RANGE\s*\((.*)\)\s*$/m).flatten.each do |range_str| + args += range_str.scan(/\[\s*(-?\d+.?\d*),\s*(-?\d+.?\d*),\s*(-?\d+.?\d*)\s*\]/m).map do |arg_values_str| arg_values_str.map do |arg_value_str| arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i end @@ -173,10 +173,10 @@ def find_tests(source) one_char_regex_string = /'(?:[^'\\]|\\.)*'/.source one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*)?#{one_string_regex_string})+|(?:#{one_number_or_text_regex_string}\s*)?#{one_char_regex_string}|(?:#{one_number_or_text_regex_string}))/.source - arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/).flatten.each do |values| - args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/).flatten.map do |one_arg_values| + arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/m).flatten.each do |values| + args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/m).flatten.map do |one_arg_values| # Force appending comma for usual regular matching - (one_arg_values + ',').scan(/(#{one_arg_regex_string})\s*,/) + (one_arg_values + ',').scan(/(#{one_arg_regex_string})\s*,/m) end.reduce do |result, arg_range_expanded| result.product(arg_range_expanded) end.map do |arg_combinations| From 0e39ff7d14798531c21869e1920e3f267b5c7e44 Mon Sep 17 00:00:00 2001 From: Alex Overchenko Date: Tue, 8 Dec 2020 14:13:15 +0300 Subject: [PATCH 6/6] Multiline generation for multiple entries was fixed --- auto/generate_test_runner.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/auto/generate_test_runner.rb b/auto/generate_test_runner.rb index 59221a2a..e35b69a3 100644 --- a/auto/generate_test_runner.rb +++ b/auto/generate_test_runner.rb @@ -129,8 +129,10 @@ def find_tests(source) .map { |line| line.gsub(substring_unre, substring_unsubs) } # unhide the problematic characters previously removed lines.each_with_index do |line, _index| + tests_regex_string = /\s*(?:TEST_CASE|TEST_RANGE|TEST_MATRIX)\s*\(.*?\)\s*/.source + # find tests - next unless line =~ /^((?:\s*(?:TEST_CASE|TEST_RANGE|TEST_MATRIX)\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m + next unless line =~ /^((?:#{tests_regex_string})*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/m arguments = Regexp.last_match(1) name = Regexp.last_match(2) @@ -140,9 +142,9 @@ def find_tests(source) if @options[:use_param_tests] && !arguments.empty? args = [] - arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/m) { |a| args << a[0] } + arguments.scan(/\s*TEST_CASE\s*\(((?:(?!#{tests_regex_string}).)*)\)\s*$/m) { |a| args << a[0] } - arguments.scan(/\s*TEST_RANGE\s*\((.*)\)\s*$/m).flatten.each do |range_str| + arguments.scan(/\s*TEST_RANGE\s*\(((?:(?!#{tests_regex_string}).)*)\)\s*$/m).flatten.each do |range_str| args += range_str.scan(/\[\s*(-?\d+.?\d*),\s*(-?\d+.?\d*),\s*(-?\d+.?\d*)\s*\]/m).map do |arg_values_str| arg_values_str.map do |arg_value_str| arg_value_str.include?('.') ? arg_value_str.to_f : arg_value_str.to_i @@ -173,7 +175,7 @@ def find_tests(source) one_char_regex_string = /'(?:[^'\\]|\\.)*'/.source one_arg_regex_string = /(?:(?:(?:#{one_number_or_text_regex_string}\s*)?#{one_string_regex_string})+|(?:#{one_number_or_text_regex_string}\s*)?#{one_char_regex_string}|(?:#{one_number_or_text_regex_string}))/.source - arguments.scan(/\s*TEST_MATRIX\s*\((.*)\)\s*$/m).flatten.each do |values| + arguments.scan(/\s*TEST_MATRIX\s*\(((?:(?!#{tests_regex_string}).)*)\)\s*$/m).flatten.each do |values| args += values.scan(/\[\s*((?:#{one_arg_regex_string}\s*,\s*)*#{one_arg_regex_string})\s*\]/m).flatten.map do |one_arg_values| # Force appending comma for usual regular matching (one_arg_values + ',').scan(/(#{one_arg_regex_string})\s*,/m)