]> git.mxchange.org Git - simgear.git/commitdiff
Add smart pointer tests (finally using Boost.Test)
authorThomas Geymayer <tomgey@gmail.com>
Thu, 8 May 2014 00:02:36 +0000 (02:02 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Thu, 8 May 2014 00:17:24 +0000 (02:17 +0200)
CMakeLists.txt
CMakeModules/BoostTestTargets.cmake [new file with mode: 0644]
CMakeModules/BoostTestTargetsDynamic.h [new file with mode: 0644]
CMakeModules/BoostTestTargetsIncluded.h [new file with mode: 0644]
CMakeModules/BoostTestTargetsStatic.h [new file with mode: 0644]
CMakeModules/CopyResourcesToBuildTree.cmake [new file with mode: 0644]
CMakeModules/GetForceIncludeDefinitions.cmake [new file with mode: 0644]
simgear/structure/CMakeLists.txt
simgear/structure/shared_ptr_test.cpp [new file with mode: 0644]

index c2ad568b3a3931f055b4fd4c7435f93128d1567c..7af05c81f267c4ebbf03fb2514776d9379cc008b 100644 (file)
@@ -163,6 +163,9 @@ if(APPLE)
   find_library(COCOA_LIBRARY Cocoa)
 endif()
 
+# Somehow this only works if included before searching for Boost...
+include(BoostTestTargets)
+
 find_package(Boost REQUIRED)
 set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DISABLE_SERIALIZATION")
 
diff --git a/CMakeModules/BoostTestTargets.cmake b/CMakeModules/BoostTestTargets.cmake
new file mode 100644 (file)
index 0000000..c3d5dbe
--- /dev/null
@@ -0,0 +1,275 @@
+# - Add tests using boost::test
+#
+# Add this line to your test files in place of including a basic boost test header:
+#  #include <BoostTestTargetConfig.h>
+#
+# If you cannot do that and must use the included form for a given test,
+# include the line
+#  // OVERRIDE_BOOST_TEST_INCLUDED_WARNING
+# in the same file with the boost test include.
+#
+#  include(BoostTestTargets)
+#  add_boost_test(<testdriver_name> SOURCES <source1> [<more sources...>]
+#   [FAIL_REGULAR_EXPRESSION <additional fail regex>]
+#   [LAUNCHER <generic launcher script>]
+#   [LIBRARIES <library> [<library>...]]
+#   [RESOURCES <resource> [<resource>...]]
+#   [TESTS <testcasename> [<testcasename>...]])
+#
+#  If for some reason you need access to the executable target created,
+#  it can be found in ${${testdriver_name}_TARGET_NAME} as specified when
+#  you called add_boost_test
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Requires:
+#      GetForceIncludeDefinitions
+#      CopyResourcesToBuildTree
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+if(__add_boost_test)
+       return()
+endif()
+set(__add_boost_test YES)
+
+set(BOOST_TEST_TARGET_PREFIX "boosttest")
+
+if(NOT Boost_FOUND)
+       find_package(Boost 1.34.0 QUIET)
+endif()
+if("${Boost_VERSION}0" LESS "1034000")
+       set(_shared_msg
+               "NOTE: boost::test-based targets and tests cannot "
+               "be added: boost >= 1.34.0 required but not found. "
+               "(found: '${Boost_VERSION}'; want >=103400) ")
+       if(BUILD_TESTING)
+               message(FATAL_ERROR
+                       ${_shared_msg}
+                       "You may disable BUILD_TESTING to continue without the "
+                       "tests.")
+       else()
+               message(STATUS
+                       ${_shared_msg}
+                       "BUILD_TESTING disabled, so continuing anyway.")
+       endif()
+endif()
+
+include(GetForceIncludeDefinitions)
+include(CopyResourcesToBuildTree)
+
+if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
+       set(_boosttesttargets_libs)
+       set(_boostConfig "BoostTestTargetsIncluded.h")
+       if(NOT Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
+               find_package(Boost 1.34.0 QUIET COMPONENTS unit_test_framework)
+       endif()
+       if(Boost_UNIT_TEST_FRAMEWORK_LIBRARY)
+               set(_boosttesttargets_libs "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}")
+               if(Boost_USE_STATIC_LIBS)
+                       set(_boostConfig "BoostTestTargetsStatic.h")
+               else()
+                       if(NOT APPLE)
+                               set(_boostConfig "BoostTestTargetsDynamic.h")
+                       endif()
+               endif()
+       endif()
+       get_filename_component(_moddir ${CMAKE_CURRENT_LIST_FILE} PATH)
+       configure_file("${_moddir}/${_boostConfig}"
+               "${CMAKE_CURRENT_BINARY_DIR}/BoostTestTargetConfig.h"
+               COPYONLY)
+       include_directories("${CMAKE_CURRENT_BINARY_DIR}")
+endif()
+
+function(add_boost_test _name)
+       if(NOT BUILD_TESTING)
+               return()
+       endif()
+# TODO check if 2.6 is enough
+#      if("${CMAKE_VERSION}" VERSION_LESS "2.8.0")
+#              if(NOT "${_boost_test_cmakever_pestered}x" EQUAL "${CMAKE_VERSION}x")
+#                      message(STATUS
+#                              "Not adding boost::test targets - CMake 2.8.0 or newer required, using ${CMAKE_VERSION}")
+#                      set(_boost_test_cmakever_pestered
+#                              "${CMAKE_VERSION}"
+#                              CACHE
+#                              INTERNAL
+#                              ""
+#                              FORCE)
+#              endif()
+#              return()
+#      endif()
+
+       # parse arguments
+       set(_nowhere)
+       set(_curdest _nowhere)
+       set(_val_args
+               SOURCES
+               FAIL_REGULAR_EXPRESSION
+               LAUNCHER
+               LIBRARIES
+               RESOURCES
+               TESTS)
+       set(_bool_args
+               USE_COMPILED_LIBRARY)
+       foreach(_arg ${_val_args} ${_bool_args})
+               set(${_arg})
+       endforeach()
+       foreach(_element ${ARGN})
+               list(FIND _val_args "${_element}" _val_arg_find)
+               list(FIND _bool_args "${_element}" _bool_arg_find)
+               if("${_val_arg_find}" GREATER "-1")
+                       set(_curdest "${_element}")
+               elseif("${_bool_arg_find}" GREATER "-1")
+                       set("${_element}" ON)
+                       set(_curdest _nowhere)
+               else()
+                       list(APPEND ${_curdest} "${_element}")
+               endif()
+       endforeach()
+
+       if(_nowhere)
+               message(FATAL_ERROR "Syntax error in use of add_boost_test!")
+       endif()
+
+       if(NOT SOURCES)
+               message(FATAL_ERROR
+                       "Syntax error in use of add_boost_test: at least one source file required!")
+       endif()
+
+       if(Boost_FOUND AND NOT "${Boost_VERSION}0" LESS "1034000")
+
+               include_directories(${Boost_INCLUDE_DIRS})
+
+               set(includeType)
+               foreach(src ${SOURCES})
+                       file(READ ${src} thefile)
+                       if("${thefile}" MATCHES ".*BoostTestTargetConfig.h.*")
+                               set(includeType CONFIGURED)
+                               set(includeFileLoc ${src})
+                               break()
+                       elseif("${thefile}" MATCHES ".*boost/test/included/unit_test.hpp.*")
+                               set(includeType INCLUDED)
+                               set(includeFileLoc ${src})
+                               set(_boosttesttargets_libs)     # clear this out - linking would be a bad idea
+                               if(NOT
+                                       "${thefile}"
+                                       MATCHES
+                                       ".*OVERRIDE_BOOST_TEST_INCLUDED_WARNING.*")
+                                       message("Please replace the include line in ${src} with this alternate include line instead:")
+                                       message("  \#include <BoostTestTargetConfig.h>")
+                                       message("Once you've saved your changes, re-run CMake. (See BoostTestTargets.cmake for more info)")
+                               endif()
+                               break()
+                       endif()
+               endforeach()
+
+               if(NOT _boostTestTargetsNagged${_name} STREQUAL "${includeType}")
+                       if("includeType" STREQUAL "CONFIGURED")
+                               message(STATUS
+                                       "Test '${_name}' uses the CMake-configurable form of the boost test framework - congrats! (Including File: ${includeFileLoc})")
+                       elseif("${includeType}" STREQUAL "INCLUDED")
+                               message("In test '${_name}': ${includeFileLoc} uses the 'included' form of the boost unit test framework.")
+                       else()
+                               message("In test '${_name}': Didn't detect the CMake-configurable boost test include.")
+                               message("Please replace your existing boost test include in that test with the following:")
+                               message("  \#include <BoostTestTargetConfig.h>")
+                               message("Once you've saved your changes, re-run CMake. (See BoostTestTargets.cmake for more info)")
+                       endif()
+               endif()
+               set(_boostTestTargetsNagged${_name}
+                       "${includeType}"
+                       CACHE
+                       INTERNAL
+                       ""
+                       FORCE)
+
+
+               if(RESOURCES)
+                       list(APPEND SOURCES ${RESOURCES})
+               endif()
+
+               # Generate a unique target name, using the relative binary dir
+               # and provided name. (transform all / into _ and remove all other
+               # non-alphabet characters)
+               file(RELATIVE_PATH
+                       targetpath
+                       "${CMAKE_BINARY_DIR}"
+                       "${CMAKE_CURRENT_BINARY_DIR}")
+               string(REGEX REPLACE "[^A-Za-z/_]" "" targetpath "${targetpath}")
+               string(REPLACE "/" "_" targetpath "${targetpath}")
+
+               set(_target_name ${BOOST_TEST_TARGET_PREFIX}-${targetpath}-${_name})
+               set(${_name}_TARGET_NAME "${_target_name}" PARENT_SCOPE)
+
+               # Build the test.
+               add_executable(${_target_name} ${SOURCES})
+
+               list(APPEND LIBRARIES ${_boosttesttargets_libs})
+
+               if(LIBRARIES)
+                       target_link_libraries(${_target_name} ${LIBRARIES})
+               endif()
+
+               if(RESOURCES)
+                       set_property(TARGET ${_target_name} PROPERTY RESOURCE ${RESOURCES})
+                       copy_resources_to_build_tree(${_target_name})
+               endif()
+
+               if(NOT Boost_TEST_FLAGS)
+#                      set(Boost_TEST_FLAGS --catch_system_error=yes --output_format=XML)
+                       set(Boost_TEST_FLAGS --catch_system_error=yes)
+               endif()
+
+               # TODO: Figure out why only recent boost handles individual test running properly
+
+               if(LAUNCHER)
+                       set(_test_command ${LAUNCHER} "\$<TARGET_FILE:${_target_name}>")
+               else()
+                       set(_test_command ${_target_name})
+               endif()
+
+               if(TESTS AND ( "${Boost_VERSION}" VERSION_GREATER "103799" ))
+                       foreach(_test ${TESTS})
+                               add_test(NAME
+                                       ${_name}-${_test}
+                                       COMMAND
+                                       ${_test_command}
+                                       --run_test=${_test}
+                                       ${Boost_TEST_FLAGS})
+                               if(FAIL_REGULAR_EXPRESSION)
+                                       set_tests_properties(${_name}-${_test}
+                                               PROPERTIES
+                                               FAIL_REGULAR_EXPRESSION
+                                               "${FAIL_REGULAR_EXPRESSION}")
+                               endif()
+                       endforeach()
+               else()
+                       add_test(NAME
+                               ${_name}-boost_test
+                               COMMAND
+                               ${_test_command}
+                               ${Boost_TEST_FLAGS})
+                       if(FAIL_REGULAR_EXPRESSION)
+                               set_tests_properties(${_name}-${_test}
+                                       PROPERTIES
+                                       FAIL_REGULAR_EXPRESSION
+                                       "${FAIL_REGULAR_EXPRESSION}")
+                       endif()
+               endif()
+
+               # CppCheck the test if we can.
+               if(COMMAND add_cppcheck)
+                       add_cppcheck(${_target_name} STYLE UNUSED_FUNCTIONS)
+               endif()
+
+       endif()
+endfunction()
diff --git a/CMakeModules/BoostTestTargetsDynamic.h b/CMakeModules/BoostTestTargetsDynamic.h
new file mode 100644 (file)
index 0000000..4bff567
--- /dev/null
@@ -0,0 +1,8 @@
+// Small header computed by CMake to set up boost test.
+// include AFTER #define BOOST_TEST_MODULE whatever
+// but before any other boost test includes.
+
+// Using the Boost UTF dynamic library
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
diff --git a/CMakeModules/BoostTestTargetsIncluded.h b/CMakeModules/BoostTestTargetsIncluded.h
new file mode 100644 (file)
index 0000000..253133c
--- /dev/null
@@ -0,0 +1,7 @@
+// Small header computed by CMake to set up boost test.
+// include AFTER #define BOOST_TEST_MODULE whatever
+// but before any other boost test includes.
+
+// Using the Boost UTF included framework
+
+#include <boost/test/included/unit_test.hpp>
diff --git a/CMakeModules/BoostTestTargetsStatic.h b/CMakeModules/BoostTestTargetsStatic.h
new file mode 100644 (file)
index 0000000..dd3cdda
--- /dev/null
@@ -0,0 +1,7 @@
+// Small header computed by CMake to set up boost test.
+// include AFTER #define BOOST_TEST_MODULE whatever
+// but before any other boost test includes.
+
+// Using the Boost UTF static library
+
+#include <boost/test/unit_test.hpp>
diff --git a/CMakeModules/CopyResourcesToBuildTree.cmake b/CMakeModules/CopyResourcesToBuildTree.cmake
new file mode 100644 (file)
index 0000000..3512cc4
--- /dev/null
@@ -0,0 +1,83 @@
+# - Copy the resources your app needs to the build tree.
+#
+#  copy_resources_to_build_tree(<target_name>)
+#
+# Requires CMake 2.6 or newer (uses the 'function' command)
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+if(__copy_resources_to_build_tree)
+       return()
+endif()
+set(__copy_resources_to_build_tree YES)
+
+function(copy_resources_to_build_tree _target)
+       get_target_property(_resources ${_target} RESOURCE)
+       if(NOT _resources)
+               # Bail if no resources
+               message(STATUS
+                       "Told to copy resources for target ${_target}, but "
+                       "no resources are set!")
+               return()
+       endif()
+
+       get_target_property(_path ${_target} LOCATION)
+       get_filename_component(_path "${_path}" PATH)
+
+       if(NOT MSVC AND NOT "${CMAKE_GENERATOR}" MATCHES "Makefiles")
+               foreach(_config ${CMAKE_CONFIGURATION_TYPES})
+                       get_target_property(_path${_config} ${_target} LOCATION_${_config})
+                       get_filename_component(_path${_config} "${_path${_config}}" PATH)
+                       add_custom_command(TARGET ${_target}
+                                               POST_BUILD
+                                               COMMAND
+                                               ${CMAKE_COMMAND}
+                                               ARGS -E make_directory "${_path${_config}}/"
+                                               COMMENT "Creating directory ${_path${_config}}/")
+               endforeach()
+       endif()
+
+       foreach(_res ${_resources})
+               if(NOT IS_ABSOLUTE "${_res}")
+                       get_filename_component(_res "${_res}" ABSOLUTE)
+               endif()
+               get_filename_component(_name "${_res}" NAME)
+
+               if(MSVC)
+                       # Working dir is solution file dir, not exe file dir.
+                       add_custom_command(TARGET ${_target}
+                               POST_BUILD
+                               COMMAND
+                               ${CMAKE_COMMAND}
+                               ARGS -E copy "${_res}" "${CMAKE_BINARY_DIR}/"
+                               COMMENT "Copying ${_name} to ${CMAKE_BINARY_DIR}/ for MSVC")
+               else()
+                       if("${CMAKE_GENERATOR}" MATCHES "Makefiles")
+                               add_custom_command(TARGET ${_target}
+                                       POST_BUILD
+                                       COMMAND
+                                       ${CMAKE_COMMAND}
+                                       ARGS -E copy "${_res}" "${_path}/"
+                                       COMMENT "Copying ${_name} to ${_path}/")
+                       else()
+                               foreach(_config ${CMAKE_CONFIGURATION_TYPES})
+                                       add_custom_command(TARGET ${_target}
+                                               POST_BUILD
+                                               COMMAND
+                                               ${CMAKE_COMMAND}
+                                               ARGS -E copy "${_res}" "${_path${_config}}"
+                                               COMMENT "Copying ${_name} to ${_path${_config}}")
+                               endforeach()
+
+                       endif()
+               endif()
+       endforeach()
+endfunction()
diff --git a/CMakeModules/GetForceIncludeDefinitions.cmake b/CMakeModules/GetForceIncludeDefinitions.cmake
new file mode 100644 (file)
index 0000000..efcca04
--- /dev/null
@@ -0,0 +1,44 @@
+# - Get the platform-appropriate flags to add to force inclusion of a file
+#
+# The most common use of this is to use a generated config.h-type file
+# placed out of the source tree in all files.
+#
+#  get_force_include_definitions(var forcedincludefiles...) -
+#   where var is the name of  your desired output variable, and everything
+#   else is a source file to forcibly include.
+#   a list item to be filtered.
+#
+# Original Author:
+# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
+# http://academic.cleardefinition.com
+# Iowa State University HCI Graduate Program/VRAC
+#
+# Copyright Iowa State University 2009-2010.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+
+if(__get_force_include_definitions)
+       return()
+endif()
+set(__get_force_include_definitions YES)
+
+function(get_force_include_definitions var)
+       set(_flagprefix)
+       if(CMAKE_COMPILER_IS_GNUCXX)
+               set(_flag "-include")
+       elseif(MSVC)
+               set(_flag "/FI")
+       else()
+               message(SEND_ERROR "You don't seem to be using MSVC or GCC, but")
+               message(SEND_ERROR "the project called get_force_include_definitions.")
+               message(SEND_ERROR "Contact this project with the name of your")
+               message(FATAL_ERROR "compiler and preferably the flag to force includes")
+       endif()
+
+       set(_out)
+       foreach(_item ${ARGN})
+               list(APPEND _out "${_flag} \"${_item}\"")
+       endforeach()
+       set(${var} "${_out}" PARENT_SCOPE)
+endfunction()
index c6180b29d574c81005116fb7830c4ebb80bbcffb..7679588c2da830f52f652b9626591087cc47b8a0 100644 (file)
@@ -55,3 +55,8 @@ target_link_libraries(test_expressions ${TEST_LIBS})
 add_test(expressions ${EXECUTABLE_OUTPUT_PATH}/test_expressions)
 
 endif(ENABLE_TESTS)
+
+add_boost_test(shared_ptr
+  SOURCES shared_ptr_test.cpp
+  LIBRARIES ${TEST_LIBS}
+)
diff --git a/simgear/structure/shared_ptr_test.cpp b/simgear/structure/shared_ptr_test.cpp
new file mode 100644 (file)
index 0000000..d7b7364
--- /dev/null
@@ -0,0 +1,90 @@
+/// Unit tests for reference counting and smart pointer classes
+#define BOOST_TEST_MODULE structure
+#include <BoostTestTargetConfig.h>
+
+#include "SGSharedPtr.hxx"
+#include "SGWeakPtr.hxx"
+
+static int instance_count = 0;
+struct ReferenceCounted:
+  public SGReferenced
+{
+  ReferenceCounted()
+  {
+    ++instance_count;
+  }
+
+  ~ReferenceCounted()
+  {
+    --instance_count;
+  }
+};
+typedef SGSharedPtr<ReferenceCounted> RefPtr;
+
+BOOST_AUTO_TEST_CASE( shared_ptr )
+{
+  BOOST_REQUIRE_EQUAL( ReferenceCounted::count(0), 0 );
+
+  RefPtr ptr( new ReferenceCounted() );
+  BOOST_REQUIRE_EQUAL( instance_count, 1 );
+  BOOST_REQUIRE_EQUAL( ReferenceCounted::count(ptr.get()), 1 );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 1 );
+
+  RefPtr ptr2 = ptr;
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 2 );
+  BOOST_REQUIRE_EQUAL( ptr2.getNumRefs(), 2 );
+
+  BOOST_REQUIRE_EQUAL( ptr, ptr2 );
+  BOOST_REQUIRE_EQUAL( ptr.get(), ptr2.get() );
+
+  ptr.reset();
+  BOOST_REQUIRE( !ptr.get() );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 0 );
+  BOOST_REQUIRE_EQUAL( ReferenceCounted::count(ptr2.get()), 1 );
+  BOOST_REQUIRE_EQUAL( ptr2.getNumRefs(), 1 );
+
+  ptr2.reset();
+  BOOST_REQUIRE( !ptr2.get() );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 0 );
+  BOOST_REQUIRE_EQUAL( ptr2.getNumRefs(), 0 );
+  BOOST_REQUIRE_EQUAL( instance_count, 0) ;
+}
+
+class Base1:
+  public virtual SGVirtualWeakReferenced
+{};
+
+class Base2:
+  public virtual SGVirtualWeakReferenced
+{};
+
+class VirtualDerived:
+  public Base1,
+  public Base2
+{};
+
+BOOST_AUTO_TEST_CASE( virtual_weak_ptr )
+{
+  SGSharedPtr<VirtualDerived> ptr( new VirtualDerived() );
+  SGWeakPtr<VirtualDerived> weak_ptr( ptr );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 1 );
+
+  SGSharedPtr<Base1> ptr1( weak_ptr.lock() );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 2 );
+
+  SGSharedPtr<Base2> ptr2( weak_ptr.lock() );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 3 );
+
+  BOOST_REQUIRE( ptr != NULL );
+  BOOST_REQUIRE_EQUAL( ptr.get(), ptr1.get() );
+  BOOST_REQUIRE_EQUAL( ptr.get(), ptr2.get() );
+
+  SGWeakPtr<Base1> weak_base1( ptr );
+  SGWeakPtr<Base2> weak_base2( ptr );
+  ptr1 = dynamic_cast<VirtualDerived*>(weak_base1.lock().get());
+  ptr2 = dynamic_cast<VirtualDerived*>(weak_base2.lock().get());
+
+  BOOST_REQUIRE_EQUAL( ptr.get(), ptr1.get() );
+  BOOST_REQUIRE_EQUAL( ptr.get(), ptr2.get() );
+  BOOST_REQUIRE_EQUAL( ptr.getNumRefs(), 3 );
+}