Skip to content

Commit

Permalink
Fix multiline-result tests; escape backslashes
Browse files Browse the repository at this point in the history
Fixes:
- #28
- The warning at https://ci.appveyor.com/project/xuhdev/editorconfig-core-c/builds/28235086/job/u9ebs7f3b9u3gowk#L1660

Major changes:
- Always use add_test(NAME ... COMMAND ...):
  This is for consistency - add_test(NAME ... COMMAND ...)
  escapes differently than add_test(<name> <command>...).
- Fix backslash escaping:
  Now that we are using the add_test(NAME ... COMMAND ...) form,
  backslash escaping works differently.  In my tests, backslashes
  are not collapsed in that form.
- Specify `-C Debug` on the `ctest` command line:
  This permits the Visual Studio generator to run tests.
  • Loading branch information
cxw42 authored and xuhdev committed Oct 21, 2019
1 parent 3bd4fc8 commit 48610d4
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[CMakeLists.txt]
[{CMakeLists.txt,*.cmake}]
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@ CTestTestfile.cmake

# Eclipse
.project

# Editor backup files
~*
*~
*.swp
63 changes: 49 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,52 @@
# POSSIBILITY OF SUCH DAMAGE.
#

# New escape-sequence processing.
cmake_minimum_required(VERSION 3.5)
cmake_policy(VERSION 3.5.1)

# Don't check any language compiler. This project is for EditorConfig Core
# testing only.
project(editorconfig-core-test NONE)

# Where this file lives
set(tests_cmakelists_dir "${CMAKE_CURRENT_LIST_DIR}")
#message(STATUS "Tests are in ${tests_cmakelists_dir}")
message(STATUS "Tests are in ${tests_cmakelists_dir}")

# Only when we are using editorconfig-core-test independently should we check
# cmake version, set EDITORCONFIG_CMD as cache string, and enable_testing()
# here.
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
cmake_minimum_required(VERSION 3.5)
set(EDITORCONFIG_CMD "editorconfig" CACHE STRING "editorconfig command.")
set(EDITORCONFIG_CMD_IS_TARGET OFF CACHE BOOL
"EDITORCONFIG_CMD names a CMake target rather than an executable.")
enable_testing()
message(STATUS "tests: Standalone testing enabled")
endif()

if(${EDITORCONFIG_CMD_IS_TARGET})
message(STATUS "tests: Using editorconfig target ${EDITORCONFIG_CMD}")
else()
message(STATUS "tests: Using editorconfig binary ${EDITORCONFIG_CMD}")
endif()

# The most common test function
function(new_ec_test name ec_file src_file regex)
add_test(${name} ${EDITORCONFIG_CMD} -f ${ec_file}
add_test(NAME ${name} COMMAND ${EDITORCONFIG_CMD} -f ${ec_file}
"${CMAKE_CURRENT_SOURCE_DIR}/${src_file}")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()

# The tests that requires version specified
# A test that requires a version specified
function(new_ec_test_version name ec_file src_file regex version)
add_test(${name} ${EDITORCONFIG_CMD} -b ${version} -f ${ec_file}
add_test(NAME ${name} COMMAND ${EDITORCONFIG_CMD} -b ${version} -f ${ec_file}
"${CMAKE_CURRENT_SOURCE_DIR}/${src_file}")
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()

# The tests that requires the full path EditorConfig files
# A test that requires the full path to the EditorConfig files
function(new_ec_test_full_ec_file_path name ec_file src_file regex)
add_test(${name} ${EDITORCONFIG_CMD} -f ${ec_file} "${src_file}")
add_test(NAME ${name} COMMAND ${EDITORCONFIG_CMD} -f ${ec_file} ${src_file})
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${regex}")
endfunction()

Expand All @@ -67,18 +78,42 @@ endfunction()
function(new_ec_test_multiline name ec_file src_file regex)
#message(STATUS "Building multiline test ${name} with tests_cmakelists_dir ${tests_cmakelists_dir}")
#message(STATUS "List dir ${CMAKE_CURRENT_LIST_DIR}, source dir ${CMAKE_CURRENT_SOURCE_DIR}")
add_test(${name} "cmake"
"-D" "EDITORCONFIG_CMD=${EDITORCONFIG_CMD}"
# Since variables aren't autpmatically passed to the inner cmake
"-D" "ECARGS:LIST=-f;${ec_file};${CMAKE_CURRENT_SOURCE_DIR}/${src_file}"
# Note: the semicolons separate list elements.
"-P" "${tests_cmakelists_dir}/cmake/ec_sort.cmake")
if(${EDITORCONFIG_CMD_IS_TARGET})
add_test(NAME ${name} COMMAND "cmake"
"-D" "EDITORCONFIG_CMD=$<TARGET_FILE:${EDITORCONFIG_CMD}>"
# Since variables aren't automatically passed to the inner cmake
"-D" "ECARGS:LIST=-f;${ec_file};${CMAKE_CURRENT_SOURCE_DIR}/${src_file}"
# Note: the semicolons separate list elements.
"-P" "${tests_cmakelists_dir}/cmake/ec_sort.cmake")
else()
add_test(NAME ${name} COMMAND "cmake"
"-D" "EDITORCONFIG_CMD=${EDITORCONFIG_CMD}"
# Since variables aren't automatically passed to the inner cmake
"-D" "ECARGS:LIST=-f;${ec_file};${CMAKE_CURRENT_SOURCE_DIR}/${src_file}"
# Note: the semicolons separate list elements.
"-P" "${tests_cmakelists_dir}/cmake/ec_sort.cmake")
endif()

set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION
"^[\n]*${regex}$")
"^[\r\n]*${regex}$")
# Permit leading \n's because I can't always get rid of them using
# only CMake-provided facilities.
endfunction()

# Tests for other CLI arguments. Usage:
# new_ec_cli_test(NAME name MATCH pass_regex ARGS arguments...)
function(new_ec_cli_test)
# Parse args
set(one_value_keywords NAME MATCH)
set(multi_value_keywords ARGS)
cmake_parse_arguments(P
"" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN})

# Add test
add_test(NAME ${P_NAME} COMMAND ${EDITORCONFIG_CMD} ${P_ARGS})
set_tests_properties(${name} PROPERTIES PASS_REGULAR_EXPRESSION "${P_MATCH}")

endfunction()

# First, make sure the test harness works.
add_subdirectory(meta)
Expand Down
22 changes: 10 additions & 12 deletions cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,24 @@
# Tests for version switches

# test --version option returns version information
add_test(test_long_version_switch ${EDITORCONFIG_CMD} --version)
set_tests_properties(test_long_version_switch PROPERTIES
PASS_REGULAR_EXPRESSION
"^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")
new_ec_cli_test(NAME test_long_version_switch
ARGS --version
MATCH "^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")

# test -v option returns version information
add_test(test_short_version_switch ${EDITORCONFIG_CMD} -v)
set_tests_properties(test_short_version_switch PROPERTIES
PASS_REGULAR_EXPRESSION
"^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")
new_ec_cli_test(NAME test_short_version_switch
ARGS -v
MATCH "^EditorConfig.* Version [0-9]+\\.[0-9]+\\.[0-9]+(-[a-z]+)?[ \t\n\r]$")

# Test for multiple input files

# when files are specified on command line. The files can appear in either
# order in the output, but each file's output line must be grouped with its
# file header. Handle this by listing both possibilities manually in the regex.
add_test(multiple_files_on_command_line ${EDITORCONFIG_CMD} -f cli.in
new_ec_cli_test(NAME multiple_files_on_command_line
ARGS -f cli.in
"${CMAKE_CURRENT_SOURCE_DIR}/file1.c"
"${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp")
set_tests_properties(multiple_files_on_command_line PROPERTIES
PASS_REGULAR_EXPRESSION
"${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp"
MATCH
"^(\\[${CMAKE_CURRENT_SOURCE_DIR}/file1.c\\][ \t]*[\n\r]+key1=value1[ \t]*[\n\r]+\\[${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp\\][ \t]*[\n\r]+key2=value2)|(\\[${CMAKE_CURRENT_SOURCE_DIR}/file2.cpp\\][ \t]*[\n\r]+key2=value2[ \t]*[\n\r]+\\[${CMAKE_CURRENT_SOURCE_DIR}/file1.c\\][ \t]*[\n\r]+key1=value1)[ \t\n\r]*$"
)
21 changes: 11 additions & 10 deletions cmake/runandsort.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ function(run_and_sort)
cmake_parse_arguments(P "${option_keywords}" "${one_value_keywords}"
"${multi_value_keywords}" ${ARGN})

#message(STATUS "Running ${P_CMDLINE}")
#message(STATUS "Running ${P_CMDLINE}") # DEBUG
execute_process(COMMAND ${P_CMDLINE}
RESULT_VARIABLE ep_retval
OUTPUT_VARIABLE ep_stdout
ERROR_VARIABLE ep_stderr
)
)

# Which one are we processing?
if(${P_CAPTURE_STDERR})
Expand All @@ -82,8 +82,9 @@ function(run_and_sort)
set(ep_out "${ep_stdout}")
endif()

#message(STATUS "Got stdout =${ep_stdout}=")
#message(STATUS "Got stderr =${ep_stderr}=")
#message(STATUS "Got retval =${ep_retval}=") # DEBUG
#message(STATUS "Got stdout =${ep_stdout}=") # DEBUG
#message(STATUS "Got stderr =${ep_stderr}=") # DEBUG

# Early bail on failure
if(NOT("${ep_retval}" EQUAL "0"))
Expand All @@ -102,30 +103,30 @@ function(run_and_sort)
# Change all the semicolons in the output to \x01
string(ASCII 1 ONE)
string(REPLACE ";" "${ONE}" ep_out "${ep_out}")
#message(STATUS "After escaping =${ep_out}=")
#message(STATUS "After escaping =${ep_out}=") # DEBUG

# Normalize line endings, just in case
string(REGEX REPLACE "\r|\n|\r\n" "\n" ep_out "${ep_out}")
#message(STATUS "After line-endings =${ep_out}=")
#message(STATUS "After line-endings =${ep_out}=") # DEBUG

# Turn the string into a list
string(REPLACE "\n" ";" ep_out "${ep_out}")
#message(STATUS "After listifying =${ep_out}=")
#message(STATUS "After listifying =${ep_out}=") # DEBUG

# Sort the list
list(SORT ep_out)

# Back to individual lines
string(REPLACE ";" "\n" ep_out "${ep_out}")
#message(STATUS "After back to lines =${ep_out}=")
#message(STATUS "After back to lines =${ep_out}=") # DEBUG

# And back to semicolons. Note: I am not trying to reverse line endings.
string(REPLACE "${ONE}" ";" ep_out "${ep_out}")
#message(STATUS "After unescaping =${ep_out}=")
#message(STATUS "After unescaping =${ep_out}=") # DEBUG

# Out to the caller
set(${P_RETVAL} "${ep_out}" PARENT_SCOPE)
#message(STATUS "Returned =${ep_out}=")
#message(STATUS "Returned =${ep_out}=") # DEBUG

endfunction(run_and_sort)

5 changes: 3 additions & 2 deletions filetree/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ else(WIN32)
set(path_separator_backslash_in_cmd_line_regex "^[ \t\n\r]*$")
endif(WIN32)
new_ec_test_full_ec_file_path(path_separator_backslash_in_cmd_line
path_separator.in "${CMAKE_CURRENT_SOURCE_DIR}\\\\path\\\\separator"
path_separator.in
"${CMAKE_CURRENT_SOURCE_DIR}\\path\\separator"
${path_separator_backslash_in_cmd_line_regex})

# Tests path separator match below top of path
Expand All @@ -83,7 +84,7 @@ new_ec_test(windows_separator2 path_separator.in windows/separator2 "^[ \t\n\r]*

# Globs with backslash in it but should be considered as file name on Non-Windows system
if((NOT WIN32) AND (NOT CYGWIN))
new_ec_test(backslash_not_on_windows path_separator.in "windows\\\\separator2" "^key4=value4[ \t\n\r]*$")
new_ec_test(backslash_not_on_windows path_separator.in "windows\\separator2" "^key4=value4[ \t\n\r]*$")
endif()

new_ec_test(path_with_special_chars path_with_special_chars.in "path_with_special_[chars/test.a" "^key=value[ \t\n\r]*$")
Expand Down
2 changes: 1 addition & 1 deletion glob/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ new_ec_test(braces_escaped_brace3 braces.in f.txt "^closing=yes[ \t\n\r]*$")
# escaped backslash
new_ec_test(braces_escaped_backslash1 braces.in g.txt "^backslash=yes[ \t\n\r]*$")
if((NOT WIN32) AND (NOT CYGWIN)) # this case is impossible on Windows.
new_ec_test(braces_escaped_backslash2 braces.in \\\\.txt "^backslash=yes[ \t\n\r]*$")
new_ec_test(braces_escaped_backslash2 braces.in "\\.txt" "^backslash=yes[ \t\n\r]*$")
endif()
new_ec_test(braces_escaped_backslash3 braces.in i.txt "^backslash=yes[ \t\n\r]*$")

Expand Down
8 changes: 5 additions & 3 deletions meta/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ message(STATUS "meta: Using editorconfig ${EDITORCONFIG_CMD}")
# Test run_and_sort()
add_test(meta_runandsort cmake -P "${tests_meta_cmakelists_dir}/sample.cmake")
set_tests_properties(meta_runandsort PROPERTIES PASS_REGULAR_EXPRESSION
"^[\n]*0${L}a;b${L}b;c${L}b;e${L}b;f${L}c;b;a${L}d${L}$")
"^[\r\n]*0${L}a;b${L}b;c${L}b;e${L}b;f${L}c;b;a${L}d${L}$")
# Have to permit leading \n's - I don't know how to get rid of them

# Test the new multiline macro on a simple case
# Test the new multiline macro on a simple case. The new_ec_test_multiline
# function adds /^[\r\n]*/ to the beginning of the provided regex, and
# /$/ to the end.
new_ec_test_multiline(meta_multiline meta.in meta.c
"^[\n]*answer=42${L}$")
"answer=42${L}")

0 comments on commit 48610d4

Please sign in to comment.