diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..92250cb --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,46 @@ +on: [push, pull_request] + +env: + BUILD_TYPE: Debug + +jobs: + test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + include: + - os: macos-latest + - os: ubuntu-latest + + steps: + + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.7 + + - name: Install Conan + run: pip install conan pytest && conan --version + + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v1.13 + with: + cmake-version: '3.22.x' + + - name: Build + run: | + mkdir build && cd build + conan profile new ./.conan --detect + conan profile update settings.compiler.libcxx=libstdc++11 ./.conan + conan install --profile ./.conan .. + cmake -S .. -B . && make + + - name: Test + run: | + build/bin/tests + env: + TRX_TMPDIR: ${{ runner.temp }} diff --git a/.gitignore b/.gitignore index 94a144d..88cb477 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ libtrx.a tests/data .vscode +data \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b3a8300..ed15b0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,27 @@ +set(LOCAL_PROJECT_NAME "trx") +set(LOCAL_PROJECT_VERSION "0.1.0") + cmake_minimum_required(VERSION 3.0.0) cmake_policy(SET CMP0074 NEW) cmake_policy(SET CMP0079 NEW) -project(trx VERSION 0.1.0) -set (CMAKE_CXX_STANDARD 11) +project(${LOCAL_PROJECT_NAME} VERSION ${LOCAL_PROJECT_VERSION}) +set(CMAKE_CXX_STANDARD 11) + +option(TRX_USE_CONAN "Should Conan package manager be used?" ON) #set(CMAKE_BUILD_TYPE RelWithDebInfo) set(CMAKE_BUILD_TYPE Debug) +#set(CMAKE_BUILD_TYPE Release) -find_package(libzip REQUIRED) -find_package (Eigen3 CONFIG REQUIRED) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(spdlog CONFIG REQUIRED) - -add_library(trx src/trx.cpp src/trx.tpp src/trx.h) - -TARGET_LINK_LIBRARIES(trx - PRIVATE - nlohmann_json::nlohmann_json - libzip::zip - Eigen3::Eigen - spdlog::spdlog - spdlog::spdlog_header_only -) +add_library(${LOCAL_PROJECT_NAME} src/trx.cpp src/trx.tpp) +include(cmake/ConanSetup.cmake) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) + +option(TRX_TESTS "Build the tests" ON) +if(TRX_TESTS) + add_subdirectory(tests) +endif() diff --git a/README.md b/README.md index 5809b04..953b8e9 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,48 @@ The C++ implementations to the memory-mapped tractography file format. ## Installation + +The project requires `gcc`, `make` and `cmake`. Please refer to your OS instructions +for proper installation. + ### Dependencies -- c++11 compiler / cmake -- libzip -- nlohmann::json -- Eigen3 -- spdlog -- GTest (optional) -### Installing -`cmake . && make` +The project dependencies are handled using [Conan](https://conan.io/). +Its installation can be found in their [documentation](https://docs.conan.io/en/latest/installation.html). +TL;DR: It is basically `pip install conan`, and works for Python >= 3.6. + +To install the dependencies, run the following: +```bash +# Fresh build +rm -Rf build && mkdir build && cd build + +# Creates a Conan profile relative to the project +conan profile new ./.conan --detect && conan profile update settings.compiler.libcxx=libstdc++11 ./.conan + +# Install dependencies +conan install --build=missing --settings=build_type=Debug --profile ./.conan .. + +# Build +cmake -S .. -B . && make +``` +### Running tests + +In `./build`: +```bash +bin/tests +``` + +### Iterating the code with new changes + +In `./build`: +```bash +make && bin/tests +``` ## How to use COMING SOON + +Examples to set up: +- Adding to my project without cmake? +- Adding to my project without conan +- Adding to my project with conan diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000..2f6b509 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,19 @@ +from conans import ConanFile, CMake + + +class TRX(ConanFile): + name = "trx" + version = "1.0.0" + description = "TRX (tee-ar-ex), a community-oriented unified tractography file" + license = "BSD-2-Clause" + url = "https://tee-ar-ex.github.io/" + settings = "os", "arch", "compiler", "build_type" + generators = "cmake" + requires = [ + "eigen/3.4.0@#3bc2bf84eff697283b6bd64d8262c423", + "spdlog/1.10.0@#1e0f4eb6338d05e4bd6fcc6bf4734172", + "nlohmann_json/3.11.2@#a35423bb6e1eb8f931423557e282c7ed", + "libzip/1.8.0@#5a0a692ec9d7d8a4337eb79e55869639", + "mio/cci.20201220", + "gtest/cci.20210126", + ] diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt deleted file mode 100644 index 22e116c..0000000 --- a/examples/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.0.0) -cmake_policy(SET CMP0074 NEW) -cmake_policy(SET CMP0079 NEW) -project(trx) -set (CMAKE_CXX_STANDARD 11) - -set(CMAKE_BUILD_TYPE Debug) - -find_package(libzip REQUIRED) -find_package (Eigen3 CONFIG REQUIRED) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(spdlog CONFIG REQUIRED) - -include_directories(../src) -add_executable(load_trx load_trx.cpp ../src/trx.h ../src/trx.tpp ../src/trx.cpp) - - -TARGET_LINK_LIBRARIES(load_trx - nlohmann_json::nlohmann_json - Eigen3::Eigen - libzip::zip - spdlog::spdlog - spdlog::spdlog_header_only -) - - -set(CPACK_PROJECT_NAME ${PROJECT_NAME}) -set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) diff --git a/examples/install-using-conan/CMakeLists.txt b/examples/install-using-conan/CMakeLists.txt new file mode 100644 index 0000000..cb8af49 --- /dev/null +++ b/examples/install-using-conan/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.0.0) +cmake_policy(SET CMP0074 NEW) +cmake_policy(SET CMP0079 NEW) +project(trx_example) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_BUILD_TYPE Debug) + +add_executable(load_trx load_trx.cpp) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +# target_link_libraries( +# ${LOCAL_PROJECT_NAME} +# PRIVATE ${CONAN_LIBS} +# ) + +# target_include_directories(${LOCAL_PROJECT_NAME} +# PUBLIC +# $ +# $ +# PRIVATE +# ${CMAKE_CURRENT_SOURCE_DIR}/src +# ${CMAKE_CURRENT_BINARY_DIR}/gen-private-include +# ${CONAN_INCLUDE_DIRS} +# ) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) diff --git a/examples/install-using-conan/README.md b/examples/install-using-conan/README.md new file mode 100644 index 0000000..e5c2d03 --- /dev/null +++ b/examples/install-using-conan/README.md @@ -0,0 +1,11 @@ + +```bash +conan editable add ../.. trx/1.0.0@user/channel +``` + +```bash +cd .. && rm -Rf build && mkdir build && cd build +conan profile new ./.conan --detect && conan profile update settings.compiler.libcxx=libstdc++11 ./.conan +conan install --build=missing --settings=build_type=Debug --profile ./.conan .. +cmake -S .. -B . && make +``` diff --git a/examples/install-using-conan/conanfile.txt b/examples/install-using-conan/conanfile.txt new file mode 100644 index 0000000..1aa8816 --- /dev/null +++ b/examples/install-using-conan/conanfile.txt @@ -0,0 +1,5 @@ +[requires] +trx/1.0.0@user/channel + +[generators] +cmake \ No newline at end of file diff --git a/examples/load_trx.cpp b/examples/install-using-conan/load_trx.cpp similarity index 97% rename from examples/load_trx.cpp rename to examples/install-using-conan/load_trx.cpp index 0f41601..de2e99b 100644 --- a/examples/load_trx.cpp +++ b/examples/install-using-conan/load_trx.cpp @@ -1,4 +1,4 @@ -#include "../src/trx.h" +#include using namespace trxmmap; int main(int argc, char **argv) diff --git a/examples/install-using-vendor/CMakeLists.txt b/examples/install-using-vendor/CMakeLists.txt new file mode 100644 index 0000000..5d95187 --- /dev/null +++ b/examples/install-using-vendor/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.0.0) +project(trx_example) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_BUILD_TYPE Debug) + +add_executable(load_trx load_trx.cpp) + +set(TRX_USE_CONAN OFF) +add_subdirectory(vendor/trx) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) diff --git a/examples/install-using-vendor/load_trx.cpp b/examples/install-using-vendor/load_trx.cpp new file mode 100644 index 0000000..de2e99b --- /dev/null +++ b/examples/install-using-vendor/load_trx.cpp @@ -0,0 +1,33 @@ +#include + +using namespace trxmmap; +int main(int argc, char **argv) +{ + trxmmap::TrxFile *trx = trxmmap::load_from_zip(argv[1]); + + std::cout << "Vertices: " << trx->streamlines->_data.size() / 3 << "\n"; + std::cout << "First vertex (x,y,z): " << trx->streamlines->_data(0, 0) + << "," << trx->streamlines->_data(0, 1) + << "," << trx->streamlines->_data(0, 2) << "\n"; + std::cout << "Streamlines: " << trx->streamlines->_offsets.size() << "\n"; + std::cout << "Vertices in first streamline: " << trx->streamlines->_offsets(1) - trx->streamlines->_offsets(0) << "\n"; + std::cout << "dpg (data_per_group) items: " << trx->data_per_group.size() << "\n"; + std::cout << "dps (data_per_streamline) items: " << trx->data_per_streamline.size() << "\n"; + + for (auto const &x : trx->data_per_streamline) + { + std::cout << "'" << x.first << "' items: " + << x.second->_matrix.size() + << "\n"; + } + + std::cout << "dpv (data_per_vertex) items:" << trx->data_per_vertex.size() << "\n"; + for (auto const &x : trx->data_per_vertex) + { + std::cout << "'" << x.first << "' items: " + << x.second->_data.size() + << "\n"; + } + + std::cout << *trx << std::endl; +} \ No newline at end of file diff --git a/src/trx.h b/include/trx/trx.h similarity index 98% rename from src/trx.h rename to include/trx/trx.h index 4cf112a..288fb33 100644 --- a/src/trx.h +++ b/include/trx/trx.h @@ -17,6 +17,9 @@ #include #include +#ifndef SPDLOG_FMT_EXTERNAL +#define SPDLOG_FMT_EXTERNAL +#endif #include "spdlog/spdlog.h" using namespace Eigen; @@ -282,6 +285,8 @@ namespace trxmmap */ void zip_from_folder(zip_t *zf, const std::string root, const std::string directory, zip_uint32_t compression_standard = ZIP_CM_STORE); + std::string get_extraction_dir(); + int free_extraction_dir(std::string extraction_dir); std::string get_base(const std::string &delimiter, const std::string &str); std::string get_ext(const std::string &str); void populate_fps(const char *name, std::map> &file_pointer_size); @@ -291,6 +296,7 @@ namespace trxmmap int rm_dir(const char *d); std::string rm_root(std::string root, const std::string path); + #include "trx.tpp" } diff --git a/scripts/fetch_test.sh b/scripts/fetch_test.sh new file mode 100755 index 0000000..5a50a11 --- /dev/null +++ b/scripts/fetch_test.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR/.. + +function hashcheck() { + MD5=$(md5sum "$1" | cut -d " " -f1) + if [[ $MD5 != $2 ]] + then + echo "md5sum for $1 does not match. Please remove the file to download it again." + exit 1 + fi +} + +mkdir -p data + +curl -L https://figshare.com/ndownloader/files/37624154 --output data/DSI.zip +hashcheck data/DSI.zip b847f053fc694d55d935c0be0e5268f7 # V1 (27.09.2022) + +curl -L https://figshare.com/ndownloader/files/37624148 --output data/memmap_test_data.zip +hashcheck data/memmap_test_data.zip 03f7651a0f9e3eeabee9aed0ad5f69e1 # V2 (27.09.2022) + +curl -L https://figshare.com/ndownloader/files/37624151 --output data/trx_from_scratch.zip +hashcheck data/trx_from_scratch.zip d9f220a095ce7f027772fcd9451a2ee5 # V2 (27.09.2022) diff --git a/src/trx.cpp b/src/trx.cpp index e65ff2d..0e3541a 100644 --- a/src/trx.cpp +++ b/src/trx.cpp @@ -1,4 +1,4 @@ -#include "trx.h" +#include #include #include #include @@ -78,6 +78,33 @@ namespace trxmmap } closedir(dir); } + + std::string get_extraction_dir() + { + std::string dir_template = "/tmp/trx_XXXXXX"; + char* extraction_dir; + + if (const char* trx_tmp_dir = std::getenv("TRX_TMPDIR")) { + std::string trx_tmp_dir_s(trx_tmp_dir); + if (trx_tmp_dir_s.compare("use_working_dir") == 0) { + dir_template = "./trx_XXXXXX"; + } else { + dir_template = trx_tmp_dir_s + "/trx_XXXXXX"; + } + } + extraction_dir = mkdtemp(&dir_template[0]); + if (extraction_dir == NULL) { + spdlog::error("Could not create temporary directory {}", dir_template); + exit(1); + } + return std::string(extraction_dir); + } + + int free_extraction_dir(std::string extraction_dir) + { + return rm_dir(extraction_dir.c_str()); + } + std::string get_base(const std::string &delimiter, const std::string &str) { std::string token; @@ -271,6 +298,7 @@ namespace trxmmap mio::shared_mmap_sink _create_memmap(std::string &filename, std::tuple &shape, std::string mode, std::string dtype, long long offset) { + if (dtype.compare("bool") == 0) { std::string ext = "bit"; @@ -287,10 +315,7 @@ namespace trxmmap allocate_file(filename, filesize); } - // std::error_code error; - mio::shared_mmap_sink rw_mmap(filename, offset, filesize); - return rw_mmap; } @@ -425,7 +450,7 @@ namespace trxmmap { if (entry->d_type == DT_DIR) { - char path[1024]; + char path[PATH_MAX]; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; snprintf(path, sizeof(path), "%s%s%s", d, SEPARATOR.c_str(), entry->d_name); @@ -433,7 +458,7 @@ namespace trxmmap } else { - char fn[1024]; + char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s%s%s", d, SEPARATOR.c_str(), entry->d_name); if (remove(fn) != 0) { @@ -458,7 +483,7 @@ namespace trxmmap { if (entry->d_type == DT_DIR) { - char path[1024]; + char path[PATH_MAX]; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; snprintf(path, sizeof(path), "%s%s%s", directory.c_str(), SEPARATOR.c_str(), entry->d_name); @@ -471,18 +496,23 @@ namespace trxmmap else { std::string fn; - char fullpath[1024]; + char fullpath[PATH_MAX]; snprintf(fullpath, sizeof(fullpath), "%s%s%s", directory.c_str(), SEPARATOR.c_str(), entry->d_name); fn = rm_root(root, std::string(fullpath)); zip_source_t *s; + zip_int64_t idx; - if ((s = zip_source_file(zf, fullpath, 0, 0)) == NULL || - zip_file_add(zf, fn.c_str(), s, ZIP_FL_ENC_UTF_8) < 0) + if ( + (s = zip_source_file(zf, fullpath, 0, 0)) == NULL || + (idx = zip_file_add(zf, fn.c_str(), s, ZIP_FL_ENC_UTF_8)) < 0 + ) { zip_source_free(s); spdlog::error("error adding file {}: {}", fn, zip_strerror(zf)); + } else { + zip_set_file_compression(zf, idx, compression_standard, 0); } } } diff --git a/src/trx.tpp b/src/trx.tpp index 92eebdc..f46b61f 100644 --- a/src/trx.tpp +++ b/src/trx.tpp @@ -223,11 +223,7 @@ TrxFile
*_initialize_empty_trx(int nb_streamlines, int nb_vertices, const Tr { TrxFile
*trx = new TrxFile
(); - char *dirname; - char t[] = "/tmp/trx_XXXXXX"; - dirname = mkdtemp(t); - - std::string tmp_dir(dirname); + std::string tmp_dir = get_extraction_dir(); spdlog::info("Temporary folder for memmaps: {}", tmp_dir); @@ -285,7 +281,7 @@ TrxFile
*_initialize_empty_trx(int nb_streamlines, int nb_vertices, const Tr std::tuple shape_off = std::make_tuple(nb_streamlines, 1); trx->streamlines->mmap_off = trxmmap::_create_memmap(offsets_filename, shape_off, "w+", offsets_dtype); - new (&(trx->streamlines->_offsets)) Map>(reinterpret_cast(trx->streamlines->mmap_off.data()), std::get<0>(shape_off), std::get<1>(shape_off)); + new (&(trx->streamlines->_offsets)) Map>(reinterpret_cast(trx->streamlines->mmap_off.data()), std::get<0>(shape_off) + 1, std::get<1>(shape_off)); trx->streamlines->_lengths.resize(nb_streamlines); @@ -343,7 +339,7 @@ TrxFile
*_initialize_empty_trx(int nb_streamlines, int nb_vertices, const Tr new (&(trx->data_per_vertex[x.first]->_data)) Map>(reinterpret_cast(trx->data_per_vertex[x.first]->mmap_pos.data()), rows, cols); } - new (&(trx->data_per_vertex[x.first]->_offsets)) Map>(trx->streamlines->_offsets.data(), int(trx->streamlines->_offsets.rows()), int(trx->streamlines->_offsets.cols())); + new (&(trx->data_per_vertex[x.first]->_offsets)) Map>(trx->streamlines->_offsets.data(), int(trx->streamlines->_offsets.rows()) + 1, int(trx->streamlines->_offsets.cols())); trx->data_per_vertex[x.first]->_lengths = trx->streamlines->_lengths; } @@ -481,16 +477,16 @@ TrxFile
*TrxFile
::_create_trx_from_pointer(json header, std::mapheader["NB_STREAMLINES"]) || dim != 1) + int nb_streamlines = int(trx->header["NB_STREAMLINES"]); + if (size != nb_streamlines + 1 || dim != 1) { - throw std::invalid_argument("Wrong offsets size/dimensionality"); } std::tuple shape = std::make_tuple(trx->header["NB_STREAMLINES"], 1); trx->streamlines->mmap_off = trxmmap::_create_memmap(filename, shape, "r+", ext, mem_adress); - new (&(trx->streamlines->_offsets)) Map>(reinterpret_cast(trx->streamlines->mmap_off.data()), std::get<0>(shape), std::get<1>(shape)); + new (&(trx->streamlines->_offsets)) Map>(reinterpret_cast(trx->streamlines->mmap_off.data()), std::get<0>(shape) + 1, std::get<1>(shape)); // TODO : adapt compute_lengths to accept a map Matrix offsets; @@ -533,9 +529,10 @@ TrxFile
*TrxFile
::_create_trx_from_pointer(json header, std::map shape; trx->data_per_vertex[base] = new ArraySequence
(); - int nb_scalar = size / int(trx->header["NB_VERTICES"]); + int nb_vertices = int(trx->header["NB_VERTICES"]); + int nb_scalar = size / nb_vertices; - if (size % int(trx->header["NB_VERTICES"]) != 0 || nb_scalar != dim) + if (size % nb_vertices != 0 || nb_scalar != dim) { throw std::invalid_argument("Wrong dpv size/dimensionality"); @@ -617,7 +614,7 @@ TrxFile
*TrxFile
::_create_trx_from_pointer(json header, std::mapstreamlines->_data.size() == 0 || trx->streamlines->_offsets.size() == 0) + if (trx->streamlines->_data.size() == 0 || trx->streamlines->_offsets.size() <= 1) { throw std::invalid_argument("Missing essential data."); @@ -630,11 +627,7 @@ TrxFile
*TrxFile
::_create_trx_from_pointer(json header, std::map TrxFile
*TrxFile
::deepcopy() { - char *dirname; - char t[] = "/tmp/trx_XXXXXX"; - dirname = mkdtemp(t); - - std::string tmp_dir(dirname); + std::string tmp_dir = get_extraction_dir(); std::string header = tmp_dir + SEPARATOR + "header.json"; std::ofstream out_json(header); @@ -650,12 +643,12 @@ TrxFile
*TrxFile
::deepcopy() if (!this->_copy_safe) { - tmp_header["NB_STREAMLINES"] = to_dump->_offsets.size(); + tmp_header["NB_STREAMLINES"] = to_dump->_offsets.size() - 1; tmp_header["NB_VERTICES"] = to_dump->_data.size() / 3; } if (out_json.is_open()) { - out_json << std::setw(4) << tmp_header << std::endl; + out_json << tmp_header << std::endl; out_json.close(); } @@ -813,7 +806,7 @@ std::tuple TrxFile
::_copy_fixed_arrays_from(TrxFile
*trx, int return std::make_tuple(strs_start, pts_start); this->streamlines->_data(seq(pts_start, pts_end - 1), all) = trx->streamlines->_data(seq(0, curr_pts_len - 1), all); - this->streamlines->_offsets(seq(strs_start, strs_end - 1), all) = (trx->streamlines->_offsets(seq(0, curr_strs_len - 1), all).array() + pts_start).matrix(); + this->streamlines->_offsets(seq(strs_start, strs_end), all) = (trx->streamlines->_offsets(seq(0, curr_strs_len), all).array() + pts_start).matrix(); this->streamlines->_lengths(seq(strs_start, strs_end - 1), all) = trx->streamlines->_lengths(seq(0, curr_strs_len - 1), all); for (auto const &x : this->data_per_vertex) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 847dc83..267552e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,41 +1,20 @@ -cmake_minimum_required(VERSION 3.0.0) -cmake_policy(SET CMP0074 NEW) -cmake_policy(SET CMP0079 NEW) -project(trx) -set (CMAKE_CXX_STANDARD 11) +if(TRX_USE_CONAN) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +endif() -set(PROJECT_BINARY_DIR ../../builds) -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/tests) -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/tests) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - -set(CMAKE_BUILD_TYPE Debug) - -find_package(libzip REQUIRED) -find_package (Eigen3 CONFIG REQUIRED) -find_package(nlohmann_json CONFIG REQUIRED) -find_package(spdlog CONFIG REQUIRED) -find_package(GTest CONFIG REQUIRED) +include_directories(${PROJECT_SOURCE_DIR}/src) enable_testing() +find_package(GTest REQUIRED) +include(GoogleTest) -include_directories(../src) -add_executable(test_mmap test_trx_mmap.cpp ../src/trx.h ../src/trx.tpp ../src/trx.cpp) - - -TARGET_LINK_LIBRARIES(test_mmap - nlohmann_json::nlohmann_json - Eigen3::Eigen - libzip::zip - GTest::gtest - GTest::gtest_main - spdlog::spdlog - spdlog::spdlog_header_only -) +add_definitions(-DDATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}/data") +add_executable(tests src/test_trx_mmap.cpp) +if(TRX_USE_CONAN) + target_link_libraries(tests PRIVATE ${CONAN_LIBS} ${LOCAL_PROJECT_NAME}) +else() + target_link_libraries(tests PRIVATE GTest::GTest GTest::Main) +endif() -set(CPACK_PROJECT_NAME ${PROJECT_NAME}) -set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) -include(CPack) -include(GoogleTest) -gtest_discover_tests(test_mmap) +gtest_discover_tests(tests) diff --git a/tests/test_trx_mmap.cpp b/tests/src/test_trx_mmap.cpp similarity index 89% rename from tests/test_trx_mmap.cpp rename to tests/src/test_trx_mmap.cpp index d381731..7a76aaf 100644 --- a/tests/test_trx_mmap.cpp +++ b/tests/src/test_trx_mmap.cpp @@ -1,5 +1,7 @@ +#include +#include #include -#include "../src/trx.h" +#include #include using namespace Eigen; @@ -171,13 +173,10 @@ TEST(TrxFileMemmap, __dichotomic_search) TEST(TrxFileMemmap, __create_memmap) { + setenv("TRX_TMPDIR", DATA_DIR, 1); - char *dirname; - char t[] = "/tmp/trx_XXXXXX"; - dirname = mkdtemp(t); - - std::string path(dirname); - path += "/offsets.int16"; + std::string dir = get_extraction_dir(); + std::string path = dir + "/offsets.int16"; std::tuple shape = std::make_tuple(3, 4); @@ -200,11 +199,16 @@ TEST(TrxFileMemmap, __create_memmap) Map> real_m(reinterpret_cast(filled_mmap.data()), std::get<0>(shape), std::get<1>(shape)); EXPECT_EQ(expected_m, real_m); + + free_extraction_dir(dir); + + unsetenv("TRX_TMPDIR"); } TEST(TrxFileMemmap, load_header) { - std::string path = "data/small.trx"; + std::string path = DATA_DIR "/small.trx"; + int *errorp; zip_t *zf = zip_open(path.c_str(), 0, errorp); json root = trxmmap::load_header(zf); @@ -247,7 +251,7 @@ TEST(TrxFileMemmap, load_header) TEST(TrxFileMemmap, load_zip) { - trxmmap::TrxFile *trx = trxmmap::load_from_zip("data/small.trx"); + trxmmap::TrxFile *trx = trxmmap::load_from_zip(DATA_DIR "/small.trx"); EXPECT_GT(trx->streamlines->_data.size(), 0); } @@ -268,7 +272,7 @@ TEST(TrxFileMemmap, TrxFile) EXPECT_EQ(trx->header, expected); - std::string path = "data/small.trx"; + std::string path = DATA_DIR "/small.trx"; int *errorp; zip_t *zf = zip_open(path.c_str(), 0, errorp); json root = trxmmap::load_header(zf); @@ -290,13 +294,13 @@ TEST(TrxFileMemmap, TrxFile) EXPECT_EQ(root_init->header, init_as); EXPECT_EQ(trx_init->streamlines->_data.size(), 33886 * 3); - EXPECT_EQ(trx_init->streamlines->_offsets.size(), 1000); + EXPECT_EQ(trx_init->streamlines->_offsets.size(), 1001); EXPECT_EQ(trx_init->streamlines->_lengths.size(), 1000); } TEST(TrxFileMemmap, deepcopy) { - trxmmap::TrxFile *trx = trxmmap::load_from_zip("data/small.trx"); + trxmmap::TrxFile *trx = trxmmap::load_from_zip(DATA_DIR "/small.trx"); trxmmap::TrxFile *copy = trx->deepcopy(); EXPECT_EQ(trx->header, copy->header); @@ -307,18 +311,17 @@ TEST(TrxFileMemmap, deepcopy) TEST(TrxFileMemmap, resize) { - trxmmap::TrxFile *trx = trxmmap::load_from_zip("data/small.trx"); + trxmmap::TrxFile *trx = trxmmap::load_from_zip(DATA_DIR "/small.trx"); trx->resize(); trx->resize(10); } TEST(TrxFileMemmap, save) { - trxmmap::TrxFile *trx = trxmmap::load_from_zip("data/small.trx"); - trxmmap::save(*trx, (std::string) "testsave"); - trxmmap::save(*trx, (std::string) "testsave.trx"); + trxmmap::TrxFile *trx = trxmmap::load_from_zip(DATA_DIR "/small.trx"); + trxmmap::save(*trx, "/testsave.trx"); + trxmmap::TrxFile *saved = trxmmap::load_from_zip("/testsave.trx"); - // trxmmap::TrxFile *saved = trxmmap::load_from_zip("testsave.trx"); - // EXPECT_EQ(saved->data_per_vertex["color_x.float16"]->_data, trx->data_per_vertex["color_x.float16"]->_data); + EXPECT_EQ(saved->data_per_vertex["color_x"]->_data, trx->data_per_vertex["color_x"]->_data); } int main(int argc, char **argv)