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")
--- /dev/null
+# - 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()
--- /dev/null
+// 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>
--- /dev/null
+// 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>
--- /dev/null
+// 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>
--- /dev/null
+# - 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()
--- /dev/null
+# - 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()
add_test(expressions ${EXECUTABLE_OUTPUT_PATH}/test_expressions)
endif(ENABLE_TESTS)
+
+add_boost_test(shared_ptr
+ SOURCES shared_ptr_test.cpp
+ LIBRARIES ${TEST_LIBS}
+)
--- /dev/null
+/// 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 );
+}