# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.

#[=======================================================================[.rst:
FindCxxTest
-----------

Find CxxTest unit testing framework.

Find the `CxxTest`_ suite and declare a helper macro for creating
unit tests and integrating them with CTest.

.. _`CxxTest`: https://github.com/CxxTest/cxxtest

Input Variables
^^^^^^^^^^^^^^^

``CXXTEST_USE_PYTHON``
  .. deprecated:: 1.3

  Only used in the case both Python & Perl
  are detected on the system to control
  which CxxTest code generator is used.
  Valid only for CxxTest version 3.

  In older versions of this Find Module,
  this variable controlled if the Python test
  generator was used instead of the Perl one,
  regardless of which scripting language the
  user had installed.

``CXXTEST_TESTGEN_ARGS``
  .. versionadded:: 2.8.3

  Specify a list of options to pass to the CxxTest code
  generator.  If not defined, ``--error-printer`` is passed.

Result Variables
^^^^^^^^^^^^^^^^

``CXXTEST_FOUND``
  True if the CxxTest framework was found

``CXXTEST_INCLUDE_DIRS``
  Where to find the CxxTest include directory

``CXXTEST_PERL_TESTGEN_EXECUTABLE``
  The perl-based test generator

``CXXTEST_PYTHON_TESTGEN_EXECUTABLE``
  The python-based test generator

``CXXTEST_TESTGEN_EXECUTABLE``
  .. versionadded:: 2.8.3

  The test generator that is actually used (chosen using user preferences
  and interpreters found in the system)

``CXXTEST_TESTGEN_INTERPRETER``
  .. versionadded:: 2.8.3

  The full path to the Perl or Python executable on the system, on
  platforms where the script cannot be executed using its shebang line.


Module Commands
^^^^^^^^^^^^^^^

.. command:: cxxtest_add_test

  Create a CxxTest runner and adds it to the CTest testing suite:

  .. code-block:: cmake

    CXXTEST_ADD_TEST(<test_name> <gen_source_file>
                     <input_files_to_testgen>...)

  Parameters:

  ``test_name``
    The name of the test

  ``gen_source_file``
    The generated source filename to be generated by CxxTest

  ``input_files_to_testgen``
    The list of header files containing the CxxTest::TestSuite's
    to be included in this runner

Example Usage
^^^^^^^^^^^^^

The following example, if CxxTest is found, will:

* Invoke the testgen executable to autogenerate foo_test.cc in the
  binary tree from "foo_test.h" in the current source directory.
* Create an executable and test called unittest_foo.

.. code-block:: cmake

  find_package(CxxTest)
  if(CXXTEST_FOUND)
    include_directories(${CXXTEST_INCLUDE_DIR})
    enable_testing()
    CXXTEST_ADD_TEST(unittest_foo foo_test.cc
                     ${CMAKE_CURRENT_SOURCE_DIR}/foo_test.h)
    target_link_libraries(unittest_foo foo) # as needed
  endif()

``foo_test.h`` contains:

.. code-block:: c++

  #include <cxxtest/TestSuite.h>
  class MyTestSuite : public CxxTest::TestSuite
  {
  public:
     void testAddition( void )
     {
        TS_ASSERT( 1 + 1 > 1 );
        TS_ASSERT_EQUALS( 1 + 1, 2 );
     }
  };

#]=======================================================================]

# Version 1.4 (11/18/10) (CMake 2.8.4)
#     Issue 11384: Added support to the CXX_ADD_TEST macro so header
#                  files (containing the tests themselves) show up in
#                  Visual Studio and other IDEs.
#
# Version 1.3 (8/19/10) (CMake 2.8.3)
#     Included patch by Simone Rossetto to check if either Python or Perl
#     are present in the system.  Whichever interpreter that is detected
#     is now used to run the test generator program.  If both interpreters
#     are detected, the CXXTEST_USE_PYTHON variable is obeyed.
#
#     Also added support for CXXTEST_TESTGEN_ARGS, for manually specifying
#     options to the CxxTest code generator.
# Version 1.2 (3/2/08)
#     Included patch from Tyler Roscoe to have the perl & python binaries
#     detected based on CXXTEST_INCLUDE_DIR
# Version 1.1 (2/9/08)
#     Clarified example to illustrate need to call target_link_libraries()
#     Changed commands to lowercase
#     Added licensing info
# Version 1.0 (1/8/08)
#     Fixed CXXTEST_INCLUDE_DIRS so it will work properly
#     Eliminated superfluous CXXTEST_FOUND assignment
#     Cleaned up and added more documentation

#=============================================================
# CXXTEST_ADD_TEST (public macro)
#=============================================================
macro(CXXTEST_ADD_TEST _cxxtest_testname _cxxtest_outfname)
    set(_cxxtest_real_outfname ${CMAKE_CURRENT_BINARY_DIR}/${_cxxtest_outfname})

    add_custom_command(
        OUTPUT  ${_cxxtest_real_outfname}
        DEPENDS ${ARGN}
        COMMAND ${CXXTEST_TESTGEN_INTERPRETER}
        ${CXXTEST_TESTGEN_EXECUTABLE} ${CXXTEST_TESTGEN_ARGS} -o ${_cxxtest_real_outfname} ${ARGN}
    )

    set_source_files_properties(${_cxxtest_real_outfname} PROPERTIES GENERATED true)
    add_executable(${_cxxtest_testname} ${_cxxtest_real_outfname} ${ARGN})

    # There's no target used for these commands, so we don't need to do
    # anything here for CMP0178.
    if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
        add_test(${_cxxtest_testname} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_cxxtest_testname})
    elseif(EXECUTABLE_OUTPUT_PATH)
        add_test(${_cxxtest_testname} ${EXECUTABLE_OUTPUT_PATH}/${_cxxtest_testname})
    else()
        add_test(${_cxxtest_testname} ${CMAKE_CURRENT_BINARY_DIR}/${_cxxtest_testname})
    endif()

endmacro()

#=============================================================
# main()
#=============================================================
if(NOT DEFINED CXXTEST_TESTGEN_ARGS)
  set(CXXTEST_TESTGEN_ARGS --error-printer)
endif()

find_package(Python QUIET)
find_package(Perl QUIET)

find_path(CXXTEST_INCLUDE_DIR cxxtest/TestSuite.h)
find_program(CXXTEST_PYTHON_TESTGEN_EXECUTABLE
         NAMES cxxtestgen cxxtestgen.py
         PATHS ${CXXTEST_INCLUDE_DIR})
find_program(CXXTEST_PERL_TESTGEN_EXECUTABLE cxxtestgen.pl
         PATHS ${CXXTEST_INCLUDE_DIR})

if(PYTHON_FOUND OR PERL_FOUND)
  include(FindPackageHandleStandardArgs)

  if(PYTHON_FOUND AND (CXXTEST_USE_PYTHON OR NOT PERL_FOUND OR NOT DEFINED CXXTEST_USE_PYTHON))
    set(CXXTEST_TESTGEN_EXECUTABLE ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE})
    execute_process(COMMAND ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE} --version
      OUTPUT_VARIABLE _CXXTEST_OUT ERROR_VARIABLE _CXXTEST_OUT RESULT_VARIABLE _CXXTEST_RESULT)
    if(_CXXTEST_RESULT EQUAL 0)
      set(CXXTEST_TESTGEN_INTERPRETER "")
    else()
      set(CXXTEST_TESTGEN_INTERPRETER ${Python_EXECUTABLE})
    endif()
    find_package_handle_standard_args(CxxTest DEFAULT_MSG
        CXXTEST_INCLUDE_DIR CXXTEST_PYTHON_TESTGEN_EXECUTABLE)

  elseif(PERL_FOUND)
    set(CXXTEST_TESTGEN_EXECUTABLE ${CXXTEST_PERL_TESTGEN_EXECUTABLE})
    set(CXXTEST_TESTGEN_INTERPRETER ${PERL_EXECUTABLE})
    find_package_handle_standard_args(CxxTest DEFAULT_MSG
        CXXTEST_INCLUDE_DIR CXXTEST_PERL_TESTGEN_EXECUTABLE)
  endif()

  if(CXXTEST_FOUND)
    set(CXXTEST_INCLUDE_DIRS ${CXXTEST_INCLUDE_DIR})
  endif()

else()

  set(CXXTEST_FOUND false)
  if(NOT CxxTest_FIND_QUIETLY)
    if(CxxTest_FIND_REQUIRED)
      message(FATAL_ERROR "Neither Python nor Perl found, cannot use CxxTest, aborting!")
    else()
      message(STATUS "Neither Python nor Perl found, CxxTest will not be used.")
    endif()
  endif()

endif()
