Code View

mstring / mstring-1.3.1.2 / cmake / run_and_diff.cmake
# run_and_diff.cmake — shared ctest helper for the tests/ and examples/ smoke tests.
#
# (From cparse, MIT.) Runs one binary and checks its output against a fixture, without
# depending on GTest (these are plain add_test() entries so they register
# whenever EXAMPLE=ON, regardless of whether TESTING=ON/GTest was found —
# see the root CMakeLists.txt comment on enable_testing()).
#
# Required:
#   EXE       path to the built executable ($<TARGET_FILE:...>)
#   EXPECTED  file holding the expected text
# Optional:
#   ARG       single command-line argument (e.g. an input file path). Omit
#             entirely (do not pass -DARG=) to run EXE with no arguments at
#             all — e.g. to check a "missing argument" usage message.
#   ARGS      several command-line arguments, separated by '|' (a ';' would
#             be split by add_test() itself). Appended after ARG.
#   INPUT     file piped to the executable's stdin
#   MATCH     if set, EXPECTED only needs to appear as a SUBSTRING of
#             stdout+stderr (for a diagnostic message that also carries a
#             machine-specific absolute path); otherwise stdout must equal
#             EXPECTED exactly (leading/trailing whitespace ignored) and
#             stderr must be empty.
#   RC        if set, the exit code must equal this value; otherwise the
#             exit code is not checked.

if(NOT EXE)
  message(FATAL_ERROR "run_and_diff.cmake: EXE not set")
endif()
if(NOT EXPECTED)
  message(FATAL_ERROR "run_and_diff.cmake: EXPECTED not set")
endif()

set(_cmd "${EXE}")
if(ARG)
  list(APPEND _cmd "${ARG}")
endif()
if(ARGS)
  string(REPLACE "|" ";" _args "${ARGS}")
  list(APPEND _cmd ${_args})
endif()

if(INPUT)
  execute_process(
    COMMAND ${_cmd}
    INPUT_FILE "${INPUT}"
    OUTPUT_VARIABLE actual_out
    ERROR_VARIABLE  actual_err
    RESULT_VARIABLE rc
  )
else()
  execute_process(
    COMMAND ${_cmd}
    OUTPUT_VARIABLE actual_out
    ERROR_VARIABLE  actual_err
    RESULT_VARIABLE rc
  )
endif()

file(READ "${EXPECTED}" expected)

if(DEFINED RC AND NOT "${rc}" STREQUAL "${RC}")
  message(FATAL_ERROR
    "run_and_diff: exit code mismatch — expected ${RC}, got ${rc}.\n"
    "--- actual stdout ---\n${actual_out}\n"
    "--- actual stderr ---\n${actual_err}")
endif()

if(MATCH)
  string(FIND "${actual_out}${actual_err}" "${expected}" pos)
  if(pos EQUAL -1)
    message(FATAL_ERROR
      "run_and_diff: expected substring not found.\n"
      "--- expected (substring) ---\n${expected}\n"
      "--- actual stdout ---\n${actual_out}\n"
      "--- actual stderr ---\n${actual_err}\n"
      "--- exit code ---\n${rc}")
  endif()
else()
  string(STRIP "${actual_out}" actual_stripped)
  string(STRIP "${expected}"   expected_stripped)
  string(STRIP "${actual_err}" err_stripped)
  if(NOT actual_stripped STREQUAL expected_stripped)
    message(FATAL_ERROR
      "run_and_diff: stdout mismatch.\n"
      "--- expected ---\n${expected}\n"
      "--- actual ---\n${actual_out}\n"
      "--- stderr ---\n${actual_err}\n"
      "--- exit code ---\n${rc}")
  endif()
  if(NOT err_stripped STREQUAL "")
    message(FATAL_ERROR "run_and_diff: expected no stderr, got:\n${actual_err}")
  endif()
endif()