From 2ce0d60db190115140f6929fc15a98de343b9ae0 Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Wed, 4 Mar 2015 12:50:42 +0100 Subject: [PATCH] Squashed 'third_party/libosmium/' changes from 6522da5..f074d94 f074d94 Use shorter path names in Doxygen doc. 5117d5a Make Doxygen-generated HTML docs work better on small screens. 41607ac Appveyor config: Use lowercase command names everywhere. Filter 7z output. 9e77a39 Remove debug output. 3416c4b Revert "Comment out test to see if there are dependencies between tests." fa49dde Comment out test to see if there are dependencies between tests. 5add75d Fix typo in appveyor conf: nul. 53b3778 Use different file names for tests. 1091c0b Fix Windows munmap() to return the same as the posix one. 14fdc4e Revert "CMake: Remove unneeded build type setting." 0270087 Workaround for MSVC. 56c2120 Another try... 8e96a6f Trying to fix test on Windows... 11a64c2 CMake workaround: Set CMAKE_CONFIGURATION_TYPES before project(). As per http://www.cmake.org/pipermail/cmake/2012-January/048856.html 3847e7a CMake: Remove unneeded build type setting. a1bcaf1 CMake: Make CMAKE_CONFIGURATION_TYPES a cache variable. ddab3e3 Create test file in test_typed_mmap in current dir instead of tmp. ce1d3bd Build "RelWithDebInfo" on appveyor instead of "Release". b6db34f Add README showing source of FindGem.cmake. 2c86c55 Better error message and some comments in CMake for sparsetable check. b16a5a3 Fix ctest on Windows. 2203bc8 Fix FindGem.cmake. 5d1f81d Another try to fix travis build. ddd3f5e Hopefully fix problem where travis doesn't find osm-testdata. 0e673ea More debug output to find travis problem. eb01107 Updated data-tests README. 8a971c8 Remove special case of the multipolygon test in travis/appveyor config. dce792c CMake: Check dependencies of multipolygon test and run as CMake script. b967677 Add tests for thread pool. 400e9b3 Bugfix: Handle exception in one pool threads properly. a1ba489 More detailed error reporting from zlib. 95cf621 Disable SparseMemTable if sparsetable size_type is smaller than 8. 7b601b5 Add missing overload to cast_with_assert() function. 60a7d86 Giving up on trying to remove LNK4221 warning. 35ed5df Try another way to get rid of MSV warning... f9c7d92 Disable a warning about changed behaviour on MSVC. c3c6b2d CTest: Only output failed tests. 9c99996 Try setting option in a different way for getting rid of LNK4221 on MSVC. 4ac563c Another ssize_t fix for Windows. 11db84f Fix mmap for windows. Convert macro to function. 95d8f75 Fix test on Windows (which doesn't have ssize_t). df51aa4 Do not write huge files in one system call. 9c4f772 Change mmap() implementation for Windows. 5be817c Rewrote function to work on Windows without warnings. ea84f73 Fix warnings on Windows. 572d692 Fixed the static_cast_with_assert function and added tests. 89ef86b Use SparseMemArray instead of SparseMemTable in examples. git-subtree-dir: third_party/libosmium git-subtree-split: f074d949a5585a81578d682035f2163de971beb3 --- .travis.yml | 6 +- CMakeLists.txt | 15 +- appveyor.yml | 39 +++-- cmake/FindGem.cmake | 153 ++++++++++++++++++ cmake/FindOsmium.cmake | 31 +++- cmake/README | 3 + doc/CMakeLists.txt | 1 + doc/Doxyfile.in | 4 +- doc/README.md | 8 + doc/header.html | 56 +++++++ examples/osmium_area_test.cpp | 4 +- examples/osmium_toogr2.cpp | 8 +- include/mmap_for_windows.hpp | 29 ++-- include/osmium/index/map/sparse_mem_table.hpp | 4 + include/osmium/io/compression.hpp | 6 +- include/osmium/io/detail/pbf_input_format.hpp | 7 +- include/osmium/io/detail/read_write.hpp | 8 +- include/osmium/io/detail/zlib.hpp | 38 +++-- include/osmium/thread/queue.hpp | 4 +- include/osmium/util/cast.hpp | 48 ++++-- test/CMakeLists.txt | 3 + test/data-tests/CMakeLists.txt | 41 +++-- test/data-tests/README.md | 17 +- test/data-tests/run-testdata-multipolygon.bat | 7 - .../run-testdata-multipolygon.cmake | 46 ++++++ test/data-tests/run-testdata-multipolygon.sh | 10 -- test/data-tests/testdata-xml.cpp | 2 +- test/t/index/test_id_to_location.cpp | 4 + test/t/index/test_typed_mmap.cpp | 12 +- test/t/io/test_reader.cpp | 6 +- test/t/thread/test_pool.cpp | 69 ++++++++ test/t/util/test_cast_with_assert.cpp | 89 ++++++++++ 32 files changed, 628 insertions(+), 150 deletions(-) create mode 100644 cmake/FindGem.cmake create mode 100644 cmake/README create mode 100644 doc/README.md create mode 100644 doc/header.html delete mode 100644 test/data-tests/run-testdata-multipolygon.bat create mode 100644 test/data-tests/run-testdata-multipolygon.cmake delete mode 100755 test/data-tests/run-testdata-multipolygon.sh create mode 100644 test/t/thread/test_pool.cpp create mode 100644 test/t/util/test_cast_with_assert.cpp diff --git a/.travis.yml b/.travis.yml index ea8794ecb..73dff72a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,7 @@ before_install: - sudo apt-get update --yes --quiet install: + - cd .. # upgrade compilers - sudo apt-get install --yes gcc-4.8 g++-4.8 # make sure 'cpp' is the just installed current one @@ -35,6 +36,7 @@ install: - make - sudo make install - cd ../.. + - cd libosmium before_script: - true @@ -45,7 +47,5 @@ script: - cd build - cmake -LA -DCMAKE_BUILD_TYPE=${CONFIGURATION} .. - make VERBOSE=1 - # Disable multipolygon test because it needs ruby and the 'json' gem, but the - # travis ruby installation doesn't find the gem it did install itself. - - ctest -V -E testdata-multipolygon + - ctest --output-on-failure diff --git a/CMakeLists.txt b/CMakeLists.txt index 373bf8eb1..b48f27166 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,11 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") # #----------------------------------------------------------------------------- +set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev" + CACHE STRING + "List of available configuration types" + FORCE) + project(libosmium) set(LIBOSMIUM_VERSION_MAJOR 0) @@ -137,8 +142,6 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}" # Build Type # #----------------------------------------------------------------------------- -set(CMAKE_CONFIGURATION_TYPES "Debug Release RelWithDebInfo MinSizeRel Dev") - # In 'Dev' mode: compile with very strict warnings and turn them into errors. if(CMAKE_BUILD_TYPE STREQUAL "Dev") if(NOT MSVC) @@ -279,14 +282,6 @@ if(BUILD_HEADERS) # so we pretend to build a library here. add_library(${libname} STATIC ${DUMMYCPP} include/${hpp}) - if(MSVC) - # Remove warning LNK4221: "This object file does not define any - # previously undefined public symbols, so it will not be used by - # any link operation that consumes this library". This is a dummy - # library anyways. - target_link_libraries(${libname} /wd4221) - endif() - #### this is better but only supported from cmake 3.0: ###add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp}) diff --git a/appveyor.yml b/appveyor.yml index c112d4f77..b3b3f51e4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ environment: matrix: - config: Dev - - config: Release + - config: RelWithDebInfo # branches to build branches: @@ -28,35 +28,35 @@ platform: x64 install: # show all availble env vars - - SET - - ECHO cmake on AppVeyor + - set + - echo cmake on AppVeyor - cmake -version - - CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 - - SET PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% - - SET LODEPSDIR=c:\projects\libosmium\libosmium-deps - - SET PROJ_LIB=%LODEPSDIR%\proj\share + - call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64 + - set PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH% + - set LODEPSDIR=c:\projects\libosmium\libosmium-deps + - set PROJ_LIB=%LODEPSDIR%\proj\share - set GDAL_DATA=%LODEPSDIR%\gdal\data #geos.dll - - SET PATH=%LODEPSDIR%\geos\lib;%PATH% + - set PATH=%LODEPSDIR%\geos\lib;%PATH% #gdal.dll - - SET PATH=%LODEPSDIR%\gdal\lib;%PATH% + - set PATH=%LODEPSDIR%\gdal\lib;%PATH% #libexpat.dll - - SET PATH=%LODEPSDIR%\expat\lib;%PATH% + - set PATH=%LODEPSDIR%\expat\lib;%PATH% #libtiff.dll - - SET PATH=%LODEPSDIR%\libtiff\lib;%PATH% + - set PATH=%LODEPSDIR%\libtiff\lib;%PATH% #zlibwapi.dll - - SET PATH=%LODEPSDIR%\zlib\lib;%PATH% + - set PATH=%LODEPSDIR%\zlib\lib;%PATH% #convert backslashes in bzip2 path to forward slashes #cmake cannot find it otherwise - - SET LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib - - SET LIBBZIP2=%LIBBZIP2:\=/% + - set LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib + - set LIBBZIP2=%LIBBZIP2:\=/% - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z - ps: Start-FileDownload https://mapnik.s3.amazonaws.com/dist/dev/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z - - 7z x cm.7z > null - - 7z x lodeps.7z > nul + - 7z x cm.7z | %windir%\system32\find "ing archive" + - 7z x lodeps.7z | %windir%\system32\find "ing archive" - echo %LODEPSDIR% - dir %LODEPSDIR% - - ECHO our own cmake + - echo our own cmake - cmake -version - cd c:\projects - git clone https://github.com/osmcode/osm-testdata.git @@ -67,11 +67,10 @@ build_script: - cd build - echo %config% - cmake .. -LA -G "Visual Studio 14 Win64" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include - - msbuild libosmium.sln /p:Configuration=Release /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 + - msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140 #- cmake .. -LA -G "NMake Makefiles" -DOsmium_DEBUG=TRUE -DCMAKE_BUILD_TYPE=%config% -DBOOST_ROOT=%LODEPSDIR%\boost -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib -DOSMPBF_LIBRARY=%LODEPSDIR%\osmpbf\lib\osmpbf.lib -DOSMPBF_INCLUDE_DIR=%LODEPSDIR%\osmpbf\include -DPROTOBUF_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf.lib -DPROTOBUF_LITE_LIBRARY=%LODEPSDIR%\protobuf\lib\libprotobuf-lite.lib -DPROTOBUF_INCLUDE_DIR=%LODEPSDIR%\protobuf\include -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include -DBZIP2_LIBRARIES=%LIBBZIP2% -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include #- nmake test_script: - # Disable multipolygon test because it needs ruby and the 'json' gem - - ctest -V -C %config% -E testdata-multipolygon + - ctest --output-on-failure -C %config% diff --git a/cmake/FindGem.cmake b/cmake/FindGem.cmake new file mode 100644 index 000000000..f5389d1e8 --- /dev/null +++ b/cmake/FindGem.cmake @@ -0,0 +1,153 @@ +# Author thomas.roehr@dfki.de +# +# Version 0.3 2013-07-02 +# - rely on `gem content` to find library and header +# - introduce GEM_OS_PKG to allow search via pkgconfig +# Version 0.2 2010-01-14 +# - add support for searching for multiple gems +# Version 0.1 2010-12-15 +# - support basic search functionality +# - tested to find rice +# +# OUTPUT: +# +# GEM_INCLUDE_DIRS After successful search contains the include directores +# +# GEM_LIBRARIES After successful search contains the full path of each found library +# +# +# Usage: +# set(GEM_DEBUG TRUE) +# find_package(Gem COMPONENTS rice hoe) +# include_directories(${GEM_INCLUDE_DIRS}) +# target_link_libraries(${GEM_LIBRARIES} +# +# in case pkg-config should be used to search for the os pkg, set GEM_OS_PKG, i.e. +# set(GEM_OS_PKG TRUE) +# +# Check for how 'gem' should be called +include(FindPackageHandleStandardArgs) +find_program(GEM_EXECUTABLE + NAMES "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}" + "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}" + "gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}" + "gem") + +# Making backward compatible +if(Gem_DEBUG) + set(GEM_DEBUG TRUE) +endif() + +if(NOT GEM_EXECUTABLE) + MESSAGE(FATAL_ERROR "Could not find the gem executable - install 'gem' first") +endif() + +if(NOT Gem_FIND_COMPONENTS) + MESSAGE(FATAL_ERROR "If searching for a Gem you have to provide COMPONENTS with the name of the gem") +endif() + +foreach(Gem_NAME ${Gem_FIND_COMPONENTS}) + set(GEM_${Gem_NAME}_FOUND TRUE) + list(APPEND components_found_vars GEM_${Gem_NAME}_FOUND) + # If the gem is installed as a gem + if(NOT GEM_OS_PKG) + set(GEM_HOME ENV{GEM_HOME}) + + # Use `gem content ` to extract current information about installed gems + # Store the information into ${GEM_LOCAL_INFO} + EXECUTE_PROCESS(COMMAND ${GEM_EXECUTABLE} content ${Gem_NAME} + RESULT_VARIABLE GEM_RUN_RESULT + OUTPUT_VARIABLE GEM_LOCAL_INFO) + + if(GEM_RUN_RESULT STREQUAL "0") + list(APPEND FOUND_GEMS ${Gem_NAME}) + set(_library_NAME_PATTERN lib${Gem_NAME}.a + lib${Gem_NAME}.so + lib${Gem_NAME}.dylib + ${Gem_NAME}.a + ${Gem_NAME}.so + ${Gem_NAME}.dylib + .*.a + .*.so + .*.dylib + ) + + set(_header_SUFFIX_PATTERN + .h + .hh + .hpp + ) + + # Create a list from the output results of the gem command + string(REPLACE "\n" ";" GEM_CONTENT_LIST "${GEM_LOCAL_INFO}") + foreach(_gem_CONTENT_PATH ${GEM_CONTENT_LIST}) + + # Convert so that only '/' Unix path separator are being using + # needed to do proper regex matching + FILE(TO_CMAKE_PATH ${_gem_CONTENT_PATH} gem_CONTENT_PATH) + + # Identify library -- checking for a library in the gems 'lib' (sub)directory + # Search for an existing library, but only within the gems folder + foreach(_library_NAME ${_library_NAME_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/lib/.*${_library_NAME}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + list(APPEND GEM_LIBRARIES ${GEM_PATH_INFO}) + break() + endif() + endforeach() + + # Identify headers + # Checking for available headers in an include directory + foreach(_header_PATTERN ${_header_SUFFIX_PATTERN}) + STRING(REGEX MATCH ".*${Gem_NAME}.*/include/.*${_header_PATTERN}$" GEM_PATH_INFO "${gem_CONTENT_PATH}") + if(NOT "${GEM_PATH_INFO}" STREQUAL "") + STRING(REGEX REPLACE "(.*${Gem_NAME}.*/include/).*${_header_PATTERN}$" "\\1" GEM_PATH_INFO "${gem_CONTENT_PATH}") + list(APPEND GEM_INCLUDE_DIRS ${GEM_PATH_INFO}) + break() + endif() + endforeach() + endforeach() + else() + set(GEM_${Gem_NAME}_FOUND FALSE) + endif() + else(NOT GEM_OS_PKG) + pkg_check_modules(GEM_PKG ${Gem_NAME}) + set(GEM_${GEM_NAME}_FOUND GEM_PKG_FOUND) + set(GEM_INCLUDE_DIRS ${GEM_PKG_INCLUDE_DIRS}) + set(GEM_LIBRARIES ${GEM_PKG_LIBRARIES} ${GEM_PKG_STATIC_LIBRARIES}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS} ${GEM_PKG_STATIC_LDFLAGS}) + list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS_OTHER} ${GEM_PKG_STATIC_LDFLAGS_OTHER}) + + if(GEM_DEBUG) + message(STATUS "GEM_OS_PKG is defined") + message(STATUS "GEM_INCLUDE_DIRS ${GEM_INCLUDE_DIRS}") + message(STATUS "GEM_STATIC_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}") + message(STATUS "GEM_STATIC_LIBRARIES ${GEM_PKG_STATIC_LIBRARIES}") + message(STATUS "GEM_LIBRARIES ${GEM_LIBRARIES}") + endif() + endif() + + if(GEM_DEBUG) + message(STATUS "${Gem_NAME} library dir: ${GEM_LIBRARIES}") + message(STATUS "${Gem_NAME} include dir: ${GEM_INCLUDE_DIRS}") + endif() +endforeach() + +# Compact the lists +if(DEFINED GEM_LIBRARIES) + LIST(REMOVE_DUPLICATES GEM_LIBRARIES) +endif() +if(DEFINED GEM_INCLUDE_DIRS) + LIST(REMOVE_DUPLICATES GEM_INCLUDE_DIRS) +endif() + +find_package_handle_standard_args(GEM + REQUIRED_VARS ${components_found_vars} + FAIL_MESSAGE "Could not find all required gems") + diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake index 15b1e013f..4c3370843 100644 --- a/cmake/FindOsmium.cmake +++ b/cmake/FindOsmium.cmake @@ -224,8 +224,27 @@ if(Osmium_USE_SPARSEHASH) find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable) if(SPARSEHASH_INCLUDE_DIR) - set(SPARSEHASH_FOUND 1) - list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + # Find size of sparsetable::size_type. This does not work on older + # CMake versions because they can do this check only in C, not in C++. + # Until we find a better way, we'll live with that. + include(CheckTypeSize) + set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR}) + set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable") + check_type_size("google::sparsetable::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX) + set(CMAKE_EXTRA_INCLUDE_FILES) + set(CMAKE_REQUIRED_INCLUDES) + + # Sparsetable::size_type must be at least 8 bytes (64bit), otherwise + # OSM object IDs will not fit. + if(SPARSETABLE_SIZE_TYPE GREATER 7) + set(SPARSEHASH_FOUND 1) + add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND}) + list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) + elseif(SPARSETABLE_SIZE_TYPE STREQUAL "") + message(WARNING "Osmium: Disabled Google SparseHash library because we can't detect whether we are on a 64bit system.") + else() + message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).") + endif() else() set(_missing_libraries 1) message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.") @@ -270,12 +289,20 @@ add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) if(MSVC) add_definitions(-wd4996) + + # Disable warning C4068: "unknown pragma" because we want it to ignore + # pragmas for other compilers. add_definitions(-wd4068) # Disable warning C4715: "not all control paths return a value" because # it generates too many false positives. add_definitions(-wd4715) + # Disable warning C4351: new behavior: elements of array '...' will be + # default initialized. The new behaviour is correct and we don't support + # old compilers anyway. + add_definitions(-wd4351) + add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) endif() diff --git a/cmake/README b/cmake/README new file mode 100644 index 000000000..4a035f7b2 --- /dev/null +++ b/cmake/README @@ -0,0 +1,3 @@ + +FindGem.cmake from https://github.com/rock-core/base-cmake + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 903aad12e..9d69a16bd 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -13,6 +13,7 @@ find_package(Doxygen) if(DOXYGEN_FOUND) message(STATUS "Looking for doxygen - found") + configure_file(header.html ${CMAKE_CURRENT_BINARY_DIR}/header.html @ONLY) configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 5ce78ab59..6535259f3 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/include # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -1047,7 +1047,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 000000000..7ca8e7cf7 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,8 @@ + +The `header.html` is created with: + +`doxygen -w html header.html footer.html stylesheet.css` + +This might have to be rn again for newer Doxygen versions. After that add +changes back in. + diff --git a/doc/header.html b/doc/header.html new file mode 100644 index 000000000..495d50024 --- /dev/null +++ b/doc/header.html @@ -0,0 +1,56 @@ + + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + diff --git a/examples/osmium_area_test.cpp b/examples/osmium_area_test.cpp index b3030a354..ee2ba1296 100644 --- a/examples/osmium_area_test.cpp +++ b/examples/osmium_area_test.cpp @@ -18,12 +18,12 @@ #include #include #include -#include +#include #include #include typedef osmium::index::map::Dummy index_neg_type; -typedef osmium::index::map::SparseMemTable index_pos_type; +typedef osmium::index::map::SparseMemArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; class WKTDump : public osmium::handler::Handler { diff --git a/examples/osmium_toogr2.cpp b/examples/osmium_toogr2.cpp index dc5c77325..a966c5edc 100644 --- a/examples/osmium_toogr2.cpp +++ b/examples/osmium_toogr2.cpp @@ -15,9 +15,7 @@ // usually you only need one or two of these #include -#include -#include -#include +#include #include #include @@ -32,9 +30,7 @@ typedef osmium::index::map::Dummy index_neg_type; -//typedef osmium::index::map::SparseMemArray index_pos_type; -//typedef osmium::index::map::SparseMmapArray index_pos_type; -typedef osmium::index::map::SparseMemTable index_pos_type; +typedef osmium::index::map::SparseMemArray index_pos_type; typedef osmium::handler::NodeLocationsForWays location_handler_type; diff --git a/include/mmap_for_windows.hpp b/include/mmap_for_windows.hpp index d14c81148..abe62d640 100644 --- a/include/mmap_for_windows.hpp +++ b/include/mmap_for_windows.hpp @@ -34,13 +34,13 @@ #define MAP_ANON MAP_ANONYMOUS #define MAP_FAILED ((void *) -1) -#ifdef __USE_FILE_OFFSET64 -# define DWORD_HI(x) (x >> 32) -# define DWORD_LO(x) ((x) & 0xffffffff) -#else -# define DWORD_HI(x) (0) -# define DWORD_LO(x) (x) -#endif +static DWORD dword_hi(uint64_t x) { + return static_cast(x >> 32); +} + +static DWORD dword_lo(uint64_t x) { + return static_cast(x & 0xffffffff); +} static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { @@ -66,13 +66,14 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t } else flProtect = PAGE_READONLY; - off_t end = length + offset; - HANDLE mmap_fd, h; + uint64_t end = static_cast(length) + offset; + HANDLE mmap_fd; if (fd == -1) mmap_fd = INVALID_HANDLE_VALUE; else mmap_fd = (HANDLE)_get_osfhandle(fd); - h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + + HANDLE h = CreateFileMapping(mmap_fd, NULL, flProtect, dword_hi(end), dword_lo(end), NULL); if (h == NULL) return MAP_FAILED; @@ -85,7 +86,7 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t dwDesiredAccess |= FILE_MAP_EXECUTE; if (flags & MAP_PRIVATE) dwDesiredAccess |= FILE_MAP_COPY; - void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + void *ret = MapViewOfFile(h, dwDesiredAccess, dword_hi(offset), dword_lo(offset), length); if (ret == NULL) { CloseHandle(h); ret = MAP_FAILED; @@ -95,12 +96,8 @@ static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t static int munmap(void *addr, size_t length) { - UnmapViewOfFile(addr); - return 0; + return UnmapViewOfFile(addr) ? 0 : -1; /* ruh-ro, we leaked handle from CreateFileMapping() ... */ } -#undef DWORD_HI -#undef DWORD_LO - #endif diff --git a/include/osmium/index/map/sparse_mem_table.hpp b/include/osmium/index/map/sparse_mem_table.hpp index 27b8f3963..8998a91f5 100644 --- a/include/osmium/index/map/sparse_mem_table.hpp +++ b/include/osmium/index/map/sparse_mem_table.hpp @@ -33,6 +33,8 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef OSMIUM_WITH_SPARSEHASH + #include #include #include @@ -139,4 +141,6 @@ namespace osmium { } // namespace osmium +#endif // OSMIUM_WITH_SPARSEHASH + #endif // OSMIUM_INDEX_BYID_SPARSE_MEM_TABLE_HPP diff --git a/include/osmium/io/compression.hpp b/include/osmium/io/compression.hpp index f5308eacb..c1f8de2e7 100644 --- a/include/osmium/io/compression.hpp +++ b/include/osmium/io/compression.hpp @@ -75,7 +75,7 @@ namespace osmium { public: - static constexpr size_t input_buffer_size = 256 * 1024; + static constexpr unsigned int input_buffer_size = 1024 * 1024; Decompressor() = default; @@ -245,11 +245,11 @@ namespace osmium { } } else { buffer.resize(osmium::io::Decompressor::input_buffer_size); - ssize_t nread = ::read(m_fd, const_cast(buffer.data()), buffer.size()); + auto nread = ::read(m_fd, const_cast(buffer.data()), osmium::io::Decompressor::input_buffer_size); if (nread < 0) { throw std::system_error(errno, std::system_category(), "Read failed"); } - buffer.resize(static_cast(nread)); + buffer.resize(nread); } return buffer; diff --git a/include/osmium/io/detail/pbf_input_format.hpp b/include/osmium/io/detail/pbf_input_format.hpp index dc161ebab..8b997ec25 100644 --- a/include/osmium/io/detail/pbf_input_format.hpp +++ b/include/osmium/io/detail/pbf_input_format.hpp @@ -214,7 +214,12 @@ namespace osmium { if (!m_done || !m_queue.empty()) { std::future buffer_future; m_queue.wait_and_pop(buffer_future); - return buffer_future.get(); + try { + return buffer_future.get(); + } catch (...) { + m_done = true; + throw; + } } return osmium::memory::Buffer(); diff --git a/include/osmium/io/detail/read_write.hpp b/include/osmium/io/detail/read_write.hpp index 564d72147..6651cced9 100644 --- a/include/osmium/io/detail/read_write.hpp +++ b/include/osmium/io/detail/read_write.hpp @@ -43,7 +43,6 @@ DEALINGS IN THE SOFTWARE. # include #else # include -typedef int ssize_t; #endif #include @@ -123,9 +122,14 @@ namespace osmium { * @throws std::system_error On error. */ inline void reliable_write(const int fd, const unsigned char* output_buffer, const size_t size) { + constexpr size_t max_write = 100 * 1024 * 1024; // Max 100 MByte per write size_t offset = 0; do { - ssize_t length = ::write(fd, output_buffer + offset, size - offset); + auto write_count = size - offset; + if (write_count > max_write) { + write_count = max_write; + } + auto length = ::write(fd, output_buffer + offset, static_cast(write_count)); if (length < 0) { throw std::system_error(errno, std::system_category(), "Write failed"); } diff --git a/include/osmium/io/detail/zlib.hpp b/include/osmium/io/detail/zlib.hpp index d78949c08..a402bf7e6 100644 --- a/include/osmium/io/detail/zlib.hpp +++ b/include/osmium/io/detail/zlib.hpp @@ -39,6 +39,8 @@ DEALINGS IN THE SOFTWARE. #include +#include + namespace osmium { namespace io { @@ -48,19 +50,26 @@ namespace osmium { /** * Compress data using zlib. * + * Note that this function can not compress data larger than + * what fits in an unsigned long, on Windows this is usually 32bit. + * * @param input Data to compress. * @returns Compressed data. */ inline std::string zlib_compress(const std::string& input) { - unsigned long output_size = ::compressBound(input.size()); + unsigned long output_size = ::compressBound(osmium::static_cast_with_assert(input.size())); std::string output(output_size, '\0'); - if (::compress(reinterpret_cast(const_cast(output.data())), - &output_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to compress data"); + auto result = ::compress( + reinterpret_cast(const_cast(output.data())), + &output_size, + reinterpret_cast(input.data()), + osmium::static_cast_with_assert(input.size()) + ); + + if (result != Z_OK) { + throw std::runtime_error(std::string("failed to compress data: ") + zError(result)); } output.resize(output_size); @@ -71,6 +80,9 @@ namespace osmium { /** * Uncompress data using zlib. * + * Note that this function can not uncompress data larger than + * what fits in an unsigned long, on Windows this is usually 32bit. + * * @param input Compressed input data. * @param raw_size Size of uncompressed data. * @returns Uncompressed data. @@ -78,11 +90,15 @@ namespace osmium { inline std::unique_ptr zlib_uncompress(const std::string& input, unsigned long raw_size) { auto output = std::unique_ptr(new std::string(raw_size, '\0')); - if (::uncompress(reinterpret_cast(const_cast(output->data())), - &raw_size, - reinterpret_cast(input.data()), - input.size()) != Z_OK) { - throw std::runtime_error("failed to uncompress data"); + auto result = ::uncompress( + reinterpret_cast(const_cast(output->data())), + &raw_size, + reinterpret_cast(input.data()), + osmium::static_cast_with_assert(input.size()) + ); + + if (result != Z_OK) { + throw std::runtime_error(std::string("failed to uncompress data: ") + zError(result)); } return output; diff --git a/include/osmium/thread/queue.hpp b/include/osmium/thread/queue.hpp index 5c5f8e768..12e593274 100644 --- a/include/osmium/thread/queue.hpp +++ b/include/osmium/thread/queue.hpp @@ -43,11 +43,13 @@ DEALINGS IN THE SOFTWARE. #include #include +#include + namespace osmium { namespace thread { - constexpr std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX + OSMIUM_CONSTEXPR std::chrono::milliseconds full_queue_sleep_duration { 10 }; // XXX /** * A thread-safe queue. diff --git a/include/osmium/util/cast.hpp b/include/osmium/util/cast.hpp index 13e6e3a9c..80adadf80 100644 --- a/include/osmium/util/cast.hpp +++ b/include/osmium/util/cast.hpp @@ -33,36 +33,66 @@ DEALINGS IN THE SOFTWARE. */ -#include +#ifndef assert +# include +#endif + #include #include namespace osmium { - template ::value && std::is_integral::value && std::is_signed::value && std::is_signed::value, int>::type = 0> + // These functions are wrappers around static_cast<>() that call assert() + // to check that there is no integer overflow happening before doing the + // cast. There are several versions of this templated function here + // depending on the types of the input and output. In any case, both input + // and output have to be integral types. If the cast can't overflow, no + // check is done. + + template + struct are_real_integers : + std::integral_constant::value && + std::is_integral::value && + !std::is_same::value && + !std::is_same::value> { + }; + + template ::value && std::is_same::value, int>::type = 0> + inline T static_cast_with_assert(const F value) { + return value; + } + + template ::value && !std::is_same::value && (sizeof(T) > sizeof(F)), int>::type = 0> + inline T static_cast_with_assert(const F value) { + return static_cast(value); + } + + template ::value && !std::is_same::value && std::is_signed::value == std::is_signed::value && (sizeof(T) == sizeof(F)), int>::type = 0> + inline T static_cast_with_assert(const F value) { + return static_cast(value); + } + + template ::value && !std::is_same::value && (sizeof(T) < sizeof(F)) && std::is_signed::value && std::is_signed::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); assert(value >= std::numeric_limits::min() && value <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_signed::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) <= sizeof(F)) && std::is_unsigned::value && std::is_signed::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); assert(value >= 0 && static_cast::type>(value) <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) < sizeof(F)) && std::is_unsigned::value && std::is_unsigned::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) < sizeof(F), "unnecessary static_cast_with_assert when casting into type of equal or larger size"); assert(value <= std::numeric_limits::max()); return static_cast(value); } - template ::value && std::is_integral::value && std::is_signed::value && std::is_unsigned::value, int>::type = 0> + template ::value && !std::is_same::value && (sizeof(T) <= sizeof(F)) && std::is_signed::value && std::is_unsigned::value, int>::type = 0> inline T static_cast_with_assert(const F value) { - static_assert(sizeof(T) <= sizeof(F), "unnecessary static_cast_with_assert when casting into type of larger size"); assert(value <= std::numeric_limits::max()); return static_cast(value); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9e27b120c..334fe3130 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -109,6 +109,9 @@ add_unit_test(tags test_filter) add_unit_test(tags test_operators) add_unit_test(tags test_tag_list) +add_unit_test(thread test_pool ${Threads_FOUND} ${CMAKE_THREAD_LIBS_INIT}) + +add_unit_test(util test_cast_with_assert) add_unit_test(util test_double) add_unit_test(util test_options) add_unit_test(util test_string) diff --git a/test/data-tests/CMakeLists.txt b/test/data-tests/CMakeLists.txt index a2938e519..89aead98e 100644 --- a/test/data-tests/CMakeLists.txt +++ b/test/data-tests/CMakeLists.txt @@ -87,32 +87,29 @@ set_tests_properties(testdata-overview PROPERTIES # multipolygon # #----------------------------------------------------------------------------- -add_executable(testdata-multipolygon testdata-multipolygon.cpp) -target_link_libraries(testdata-multipolygon - ${OSMIUM_XML_LIBRARIES} - ${GDAL_LIBRARIES} -) -if(WIN32) - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.bat") +find_package(Ruby 1.9) +find_package(Gem COMPONENTS json) +find_program(SPATIALITE spatialite) + +if(RUBY_FOUND AND GEM_json_FOUND AND SPATIALITE) + add_executable(testdata-multipolygon testdata-multipolygon.cpp) + target_link_libraries(testdata-multipolygon + ${OSMIUM_XML_LIBRARIES} + ${GDAL_LIBRARIES} + ) + + add_test(NAME testdata-multipolygon + COMMAND ${CMAKE_COMMAND} + -D OSM_TESTDATA=${OSM_TESTDATA} + -D RUBY=${RUBY_EXECUTABLE} + -P ${CMAKE_CURRENT_SOURCE_DIR}/run-testdata-multipolygon.cmake) + + set_tests_properties(testdata-multipolygon PROPERTIES LABELS "data;slow") else() - set(MULTIPOLYGON_TEST_SCRIPT "run-testdata-multipolygon.sh") + message(WARNING "Disabled testdata-multipolygon test because 'ruby' and/or 'json' ruby gem and/or 'spatialite' was not found") endif() -if(MSVC) - set(EXE_DIR ${CMAKE_BUILD_TYPE}) -else() - set(EXE_DIR .) -endif() - -add_test(NAME testdata-multipolygon - COMMAND ${CMAKE_SOURCE_DIR}/test/data-tests/${MULTIPOLYGON_TEST_SCRIPT} - ${OSM_TESTDATA} - ${EXE_DIR} -) -set_tests_properties(testdata-multipolygon PROPERTIES - LABELS "data;slow") - #----------------------------------------------------------------------------- message(STATUS "Configuring data tests - done") diff --git a/test/data-tests/README.md b/test/data-tests/README.md index d381f6540..5138bf856 100644 --- a/test/data-tests/README.md +++ b/test/data-tests/README.md @@ -5,19 +5,6 @@ repository at https://github.com/osmcode/osm-testdata . To use it, clone the `osm-testdata` repository in the same directory where you cloned the `libosmium` repository. -## Overview - -The `testdata-overview` program can be used to create a Spatialite file -containing all the nodes and ways from the test data files. - -Compile it by running `make testdata-overview`, run it my calling -`make overview`. - -## Running the Tests - -Actual tests are in `testcases` subdirectory, one per test from the -osm-testdata repository. - -To compile the tests, call `make runtests`, to run them call -`make test`. +Tests will be built if the CMake option `BUILD_DATA_TESTS` is set and run as +part of the `ctest` run. diff --git a/test/data-tests/run-testdata-multipolygon.bat b/test/data-tests/run-testdata-multipolygon.bat deleted file mode 100644 index 838ce9f7f..000000000 --- a/test/data-tests/run-testdata-multipolygon.bat +++ /dev/null @@ -1,7 +0,0 @@ -set TESTDATA_DIR=%1 - -del multipolygon.db multipolygon-tests.json -%2\testdata-multipolygon %TESTDATA_DIR%\grid\data\all.osm >multipolygon.log 2>&1 -if ERRORLEVEL 1 (exit /b 1) -ruby %TESTDATA_DIR%\bin\compare-areas.rb %TESTDATA_DIR%\grid\data\tests.json multipolygon-tests.json -if ERRORLEVEL 1 (exit /b 1) diff --git a/test/data-tests/run-testdata-multipolygon.cmake b/test/data-tests/run-testdata-multipolygon.cmake new file mode 100644 index 000000000..0d08f5a52 --- /dev/null +++ b/test/data-tests/run-testdata-multipolygon.cmake @@ -0,0 +1,46 @@ +#----------------------------------------------------------------------------- +# +# Helper script that runs the 'multipolygon' test. +# +#----------------------------------------------------------------------------- + +# Remove files that might be left over from previous run +file(REMOVE multipolygon.db multipolygon-tests.json) + + +#----------------------------------------------------------------------------- +# +# Create multipolygons from test data. +# +#----------------------------------------------------------------------------- +execute_process( + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/testdata-multipolygon + ${OSM_TESTDATA}/grid/data/all.osm + RESULT_VARIABLE _result + OUTPUT_FILE multipolygon.log + ERROR_FILE multipolygon.log +) + +if(_result) + message(FATAL_ERROR "Error running testdata-multipolygon command") +endif() + + +#----------------------------------------------------------------------------- +# +# Compare created multipolygons with reference data. +# +#----------------------------------------------------------------------------- +execute_process( + COMMAND ${RUBY} ${OSM_TESTDATA}/bin/compare-areas.rb + ${OSM_TESTDATA}/grid/data/tests.json + multipolygon-tests.json + RESULT_VARIABLE _result +) + +if(_result) + message(FATAL_ERROR "Error running compare-areas command") +endif() + + +#----------------------------------------------------------------------------- diff --git a/test/data-tests/run-testdata-multipolygon.sh b/test/data-tests/run-testdata-multipolygon.sh deleted file mode 100755 index dcd57a84a..000000000 --- a/test/data-tests/run-testdata-multipolygon.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -# helper script needed by cmake to run test - -TESTDATA_DIR=$1 - -rm -f multipolygon.db multipolygon-tests.json -./testdata-multipolygon ${TESTDATA_DIR}/grid/data/all.osm >multipolygon.log 2>&1 && - ${TESTDATA_DIR}/bin/compare-areas.rb ${TESTDATA_DIR}/grid/data/tests.json multipolygon-tests.json - diff --git a/test/data-tests/testdata-xml.cpp b/test/data-tests/testdata-xml.cpp index 16133a92a..94af6f961 100644 --- a/test/data-tests/testdata-xml.cpp +++ b/test/data-tests/testdata-xml.cpp @@ -46,7 +46,7 @@ std::string read_file(const char* test_id) { assert(fd >= 0); std::string input(10000, '\0'); - ssize_t n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); + auto n = ::read(fd, reinterpret_cast(const_cast(input.data())), 10000); assert(n >= 0); input.resize(static_cast(n)); diff --git a/test/t/index/test_id_to_location.cpp b/test/t/index/test_id_to_location.cpp index bc2ec446a..fbb3f6a97 100644 --- a/test/t/index/test_id_to_location.cpp +++ b/test/t/index/test_id_to_location.cpp @@ -108,6 +108,8 @@ SECTION("DenseFileArray") { test_func_real(index2); } +#ifdef OSMIUM_WITH_SPARSEHASH + SECTION("SparseMemTable") { typedef osmium::index::map::SparseMemTable index_type; @@ -118,6 +120,8 @@ SECTION("SparseMemTable") { test_func_real(index2); } +#endif + SECTION("SparseMemMap") { typedef osmium::index::map::SparseMemMap index_type; diff --git a/test/t/index/test_typed_mmap.cpp b/test/t/index/test_typed_mmap.cpp index 745535d95..df95dc267 100644 --- a/test/t/index/test_typed_mmap.cpp +++ b/test/t/index/test_typed_mmap.cpp @@ -53,10 +53,9 @@ SECTION("Remap") { SECTION("FileSize") { const int size = 100; - char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + char filename[] = "test_mmap_file_size_XXXXXX"; const int fd = mkstemp(filename); REQUIRE(fd > 0); - REQUIRE(0 == unlink(filename)); REQUIRE(0 == osmium::detail::typed_mmap::file_size(fd)); REQUIRE(0 == ftruncate(fd, size * sizeof(uint64_t))); REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); @@ -69,14 +68,16 @@ SECTION("FileSize") { osmium::detail::typed_mmap::grow_file(size * 2, fd); REQUIRE((size * 2) == osmium::detail::typed_mmap::file_size(fd)); + + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); } SECTION("GrowAndMap") { const int size = 100; - char filename[] = "/tmp/osmium_unit_test_XXXXXX"; + char filename[] = "test_mmap_grow_and_map_XXXXXX"; const int fd = mkstemp(filename); REQUIRE(fd > 0); - REQUIRE(0 == unlink(filename)); uint64_t* data = osmium::detail::typed_mmap::grow_and_map(size, fd); REQUIRE(size == osmium::detail::typed_mmap::file_size(fd)); @@ -90,6 +91,9 @@ SECTION("GrowAndMap") { REQUIRE(27ul == data[99]); osmium::detail::typed_mmap::unmap(data, size); + + REQUIRE(0 == close(fd)); + REQUIRE(0 == unlink(filename)); } } diff --git a/test/t/io/test_reader.cpp b/test/t/io/test_reader.cpp index 22f1aa24b..9a06d8408 100644 --- a/test/t/io/test_reader.cpp +++ b/test/t/io/test_reader.cpp @@ -65,7 +65,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm"); @@ -83,7 +83,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm.gz"); @@ -101,7 +101,7 @@ TEST_CASE("Reader") { const size_t buffer_size = 1000; char buffer[buffer_size]; - ssize_t length = ::read(fd, buffer, buffer_size); + auto length = ::read(fd, buffer, buffer_size); REQUIRE(length > 0); osmium::io::File file(buffer, static_cast(length), "osm.bz2"); diff --git a/test/t/thread/test_pool.cpp b/test/t/thread/test_pool.cpp new file mode 100644 index 000000000..4bbf9ee59 --- /dev/null +++ b/test/t/thread/test_pool.cpp @@ -0,0 +1,69 @@ +#include "catch.hpp" + +#include +#include +#include + +#include + +static std::atomic result; + +struct test_job_ok { + void operator()() const { + result = 1; + } +}; + +struct test_job_with_result { + int operator()() const { + return 42; + } +}; + +struct test_job_throw { + void operator()() const { + throw std::runtime_error("exception in pool thread"); + } +}; + +TEST_CASE("thread") { + + SECTION("can get access to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + REQUIRE(pool.queue_empty()); + } + + SECTION("can send job to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + result = 0; + auto future = pool.submit(test_job_ok{}); + + // wait a bit for the other thread to get a chance to run + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + REQUIRE(result == 1); + + future.get(); + + REQUIRE(true); + } + + SECTION("can send job to thread pool") { + auto& pool = osmium::thread::Pool::instance(); + auto future = pool.submit(test_job_with_result{}); + + REQUIRE(future.get() == 42); + } + + SECTION("can throw from job in thread pool") { + auto& pool = osmium::thread::Pool::instance(); + result = 0; + + bool got_exception = false; + auto future = pool.submit(test_job_throw{}); + + REQUIRE_THROWS_AS(future.get(), std::runtime_error); + } + +} + diff --git a/test/t/util/test_cast_with_assert.cpp b/test/t/util/test_cast_with_assert.cpp new file mode 100644 index 000000000..0231f30e1 --- /dev/null +++ b/test/t/util/test_cast_with_assert.cpp @@ -0,0 +1,89 @@ +#include "catch.hpp" + +// Define assert() to throw this error. This enables the tests to check that +// the assert() fails. +struct assert_error : public std::runtime_error { + assert_error(const char* what_arg) : std::runtime_error(what_arg) { + } +}; +#define assert(x) if (!(x)) { throw(assert_error(#x)); } + +#include + +TEST_CASE("static_cast_with_assert") { + + SECTION("same types is always okay") { + int f = 10; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("casting to larger type is always okay") { + int16_t f = 10; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + + SECTION("cast int32_t -> int_16t should not trigger assert for small int") { + int32_t f = 100; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int32_t -> int_16t should trigger assert for large int") { + int32_t f = 100000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast int16_t -> uint16_t should not trigger assert for zero") { + int16_t f = 0; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int16_t -> uint16_t should not trigger assert for positive int") { + int16_t f = 1; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int16_t -> uint16_t should trigger assert for negative int") { + int16_t f = -1; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast uint32_t -> uint_16t should not trigger assert for zero") { + uint32_t f = 0; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast uint32_t -> uint_16t should not trigger assert for small int") { + uint32_t f = 100; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast int32_t -> int_16t should trigger assert for large int") { + uint32_t f = 100000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + + SECTION("cast uint16_t -> int16_t should not trigger assert for small int") { + uint16_t f = 1; + auto t = osmium::static_cast_with_assert(f); + REQUIRE(t == f); + } + + SECTION("cast uint16_t -> int16_t should trigger assert for large int") { + uint16_t f = 65000; + REQUIRE_THROWS_AS(osmium::static_cast_with_assert(f), assert_error); + } + + +} +