Browse Source

Merge topic 'GoogleTest-source-line'

a0343abd59 GoogleTest: Add DEF_SOURCE_LINE property to gtest_add_tests

Acked-by: Kitware Robot <[email protected]>
Acked-by: buildbot <[email protected]>
Merge-request: !9327
Brad King 1 year ago
parent
commit
bdaa6b5457
2 changed files with 62 additions and 5 deletions
  1. 41 4
      Modules/GoogleTest.cmake
  2. 21 1
      Tests/GoogleTest/Test/CMakeLists.txt

+ 41 - 4
Modules/GoogleTest.cmake

@@ -347,16 +347,51 @@ function(gtest_add_tests)
 
   unset(testList)
 
-  set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*")
+  set(gtest_case_name_regex ".*\\([ \r\n\t]*([A-Za-z_0-9]+)[ \r\n\t]*,[ \r\n\t]*([A-Za-z_0-9]+)[ \r\n\t]*\\).*")
   set(gtest_test_type_regex "(TYPED_TEST|TEST)_?[FP]?")
+  set(each_line_regex "([^\r\n]*[\r\n])")
 
   foreach(source IN LISTS ARGS_SOURCES)
     if(NOT ARGS_SKIP_DEPENDENCY)
       set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source})
     endif()
     file(READ "${source}" contents)
-    string(REGEX MATCHALL "${gtest_test_type_regex} *\\(([A-Za-z_0-9 ,]+)\\)" found_tests "${contents}")
-    foreach(hit ${found_tests})
+    # Replace characters in file content that are special to CMake
+    string(REPLACE "[" "<OPEN_BRACKET>" contents "${contents}")
+    string(REPLACE "]" "<CLOSE_BRACKET>" contents "${contents}")
+    string(REPLACE ";" "\\;" contents "${contents}")
+    # Split into lines
+    string(REGEX MATCHALL "${each_line_regex}" content_lines "${contents}")
+    set(line "0")
+    # Stores the line number of the start of a test definition
+    set(accumulate_line "0")
+    # Stores accumulated lines to match multi-line test definitions
+    set(accumulated "")
+    # Iterate over each line in the file so that we know the line number of a test definition
+    foreach(line_str IN LISTS content_lines)
+      MATH(EXPR line "${line}+1")
+      # Check if the current line is the start of a test definition
+      string(REGEX MATCH "[ \t]*${gtest_test_type_regex}[ \t]*[\\(]*" accumlate_start_hit "${line_str}")
+      if(accumlate_start_hit)
+        set(accumulate_line "${line}")
+      endif()
+      # Append the current line to the accumulated string
+      set(accumulated "${accumulated}${line_str}")
+      # Attempt to match a complete test definition in the accumulated string
+      string(REGEX MATCH "${gtest_test_type_regex}[ \r\n\t]*\\(([A-Za-z_0-9 ,\r\n\t]+)\\)" hit "${accumulated}")
+      if(hit)
+        # Reset accumulated for the next match
+        set(accumulated "")
+      else()
+        # Continue accumulating lines
+        continue()
+      endif()
+      # At this point, the start line of the test definition is known
+      # Hence, we can set the test's DEF_SOURCE_LINE property with
+      # ${source}:${accumulate_line} below.
+      # VS Code CMake Tools extension looks for DEF_SOURCE_LINE
+      # to locate the test definition for its "Go to test" feature.
+
       string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit})
 
       # Parameterized tests have a different signature for the filter
@@ -394,7 +429,8 @@ function(gtest_add_tests)
                      --gtest_filter=${gtest_test_name}
                      ${ARGS_EXTRA_ARGS}
           )
-          set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE)
+          set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE
+            DEF_SOURCE_LINE "${source}:${accumulate_line}")
           list(APPEND testList ${ctest_test_name})
         endif()
       else()
@@ -410,6 +446,7 @@ function(gtest_add_tests)
           ${ctest_test_name}
           PROPERTIES
           SKIP_REGULAR_EXPRESSION "\\[  SKIPPED \\]"
+          DEF_SOURCE_LINE "${source}:${accumulate_line}"
         )
         list(APPEND testList ${ctest_test_name})
       endif()

+ 21 - 1
Tests/GoogleTest/Test/CMakeLists.txt

@@ -81,10 +81,30 @@ gtest_add_tests(test_gtest3 "" AUTO)
 if(NOT TEST GoogleTest.Foo)
   message(FATAL_ERROR "Test case GoogleTest.Foo not defined")
 endif()
+# Check if test has property DEF_SOURCE_LINE
+get_test_property(GoogleTest.Foo DEF_SOURCE_LINE testSourceLineFoo)
+if(NOT testSourceLineFoo)
+  message(FATAL_ERROR "Test GoogleTest.Foo should have DEF_SOURCE_LINE property")
+endif()
+# If check property ends with correct value
+string(FIND "${testSourceLineFoo}" "main3.cxx:3" testSourceLineFooFound)
+if(${testSourceLineFooFound} EQUAL -1)
+  message(FATAL_ERROR "Test GoogleTest.Foo should have DEF_SOURCE_LINE property with value main3.cxx:3")
+endif()
+
 if(NOT TEST GoogleTest.Bar)
   message(FATAL_ERROR "Test case GoogleTest.Bar not defined")
 endif()
-
+# Check if test has property DEF_SOURCE_LINE
+get_test_property(GoogleTest.Bar DEF_SOURCE_LINE testSourceLineBar)
+if(NOT testSourceLineBar)
+  message(FATAL_ERROR "Test GoogleTest.Bar should have DEF_SOURCE_LINE property")
+endif()
+# If check property ends with correct value
+string(FIND "${testSourceLineBar}" "main3.cxx:8" testSourceLineBarFound)
+if(${testSourceLineBarFound} EQUAL -1)
+  message(FATAL_ERROR "Test GoogleTest.Bar should have DEF_SOURCE_LINE property with value main3.cxx:8")
+endif()
 
 # Non-keyword form, explicitly specified sources. Allows a non-target to be
 # given for the executable.