From 46f31b59c1be1e8541048be8c52237d5c43f6628 Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:54:01 -0700 Subject: [PATCH 1/8] add sanitizer workflow --- .github/workflows/sanitize.yml | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/sanitize.yml diff --git a/.github/workflows/sanitize.yml b/.github/workflows/sanitize.yml new file mode 100644 index 00000000..110cf030 --- /dev/null +++ b/.github/workflows/sanitize.yml @@ -0,0 +1,48 @@ +name: Sanitize + +on: + push: + branches: + - main + + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + sanitize: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: + sudo apt-get update + sudo apt-get install -y libhdf5-dev libboost-all-dev + git clone https://github.com/catchorg/Catch2.git + cd Catch2 + git checkout "v3.5.3" + cmake -Bbuild -H. -DBUILD_TESTING=OFF + sudo cmake --build build/ --target install + + - name: Configure + run: cmake --preset=ci-sanitize + + - name: Build + run: cmake --build build/sanitize -j 2 + + - name: Test + working-directory: build/sanitize + env: + ASAN_OPTIONS: "strict_string_checks=1:\ + detect_stack_use_after_return=1:\ + check_initialization_order=1:\ + strict_init_order=1:\ + detect_leaks=1:\ + halt_on_error=1" + UBSAN_OPTIONS: "print_stacktrace=1:\ + halt_on_error=1" + run: ctest --output-on-failure --no-tests=error -j 2 From b20105f6e43d4daf5ad0a66c82f94e584bebf54e Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:54:12 -0700 Subject: [PATCH 2/8] remove timestamps test --- tests/testBase.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/tests/testBase.cpp b/tests/testBase.cpp index d296292d..f79ccda5 100644 --- a/tests/testBase.cpp +++ b/tests/testBase.cpp @@ -56,29 +56,4 @@ TEST_CASE("TimeSeries", "[base]") delete[] dataBuffer; REQUIRE_THAT(dataRead, Catch::Matchers::Approx(data).margin(1)); } - - SECTION("test writing timeseries without timestamps") - { - // setup timeseries object - std::string path = getTestFilePath("testTimeseriesNoTimestamps.h5"); - std::shared_ptr io = createIO("HDF5", path); - io->open(); - NWB::TimeSeries ts = NWB::TimeSeries(dataPath, io, dataType, "unit"); - ts.initialize(); - - // Write data to file - Status writeStatus = ts.writeData(dataShape, positionOffset, data.data()); - REQUIRE(writeStatus == Status::Success); - - // Read data back from file - double* tsBuffer = new double[numSamples]; - BaseRecordingData* tsDset = io->getDataSet(dataPath + "/timestamps"); - readH5DataBlock(static_cast(tsDset)->getDataSet(), - timestampsType, - tsBuffer); - std::vector tsRead(tsBuffer, tsBuffer + numSamples); - delete[] tsBuffer; - std::vector zeros(numSamples, 0.0); - REQUIRE(tsRead == zeros); - } } From 1fba650dee2f836ea8c46491f12f05733368b8d8 Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:38:26 -0700 Subject: [PATCH 3/8] fix overflow from chunking array --- src/hdf5/HDF5IO.cpp | 3 +++ src/nwb/NWBFile.cpp | 2 +- tests/testEcephys.cpp | 6 ++++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/hdf5/HDF5IO.cpp b/src/hdf5/HDF5IO.cpp index 066c6f87..69f03707 100644 --- a/src/hdf5/HDF5IO.cpp +++ b/src/hdf5/HDF5IO.cpp @@ -415,6 +415,9 @@ AQNWB::BaseRecordingData* HDF5IO::createArrayDataSet(const BaseDataType& type, if (dimension < 1) // Check for at least one dimension return nullptr; + // Ensure chunking is properly allocated and has at least 'dimension' elements + assert(chunking.size() >= dimension); + // Use vectors to support an arbitrary number of dimensions std::vector dims(dimension), chunk_dims(dimension), max_dims(dimension); diff --git a/src/nwb/NWBFile.cpp b/src/nwb/NWBFile.cpp index ea1d5ea6..252ba313 100644 --- a/src/nwb/NWBFile.cpp +++ b/src/nwb/NWBFile.cpp @@ -115,7 +115,7 @@ Status NWBFile::createElectricalSeries( "Stores continuously sampled voltage data from an " "extracellular ephys recording", SizeArray {0, channelVector.size()}, - SizeArray {CHUNK_XSIZE}); + SizeArray {CHUNK_XSIZE, 0}); electricalSeries->initialize(); recordingContainers->addData(std::move(electricalSeries)); diff --git a/tests/testEcephys.cpp b/tests/testEcephys.cpp index 5c324e19..a4c50ce4 100644 --- a/tests/testEcephys.cpp +++ b/tests/testEcephys.cpp @@ -63,7 +63,8 @@ TEST_CASE("ElectricalSeries", "[ecephys]") elecTable.getPath(), "volts", "no description", - SizeArray {0, mockArrays[0].size()}); + SizeArray {0, mockArrays[0].size()}, + SizeArray {1, 1}); es.initialize(); // write channel data @@ -118,7 +119,8 @@ TEST_CASE("ElectricalSeries", "[ecephys]") elecTable.getPath(), "volts", "no description", - SizeArray {0, mockArrays[0].size()}); + SizeArray {0, mockArrays[0].size()}, + SizeArray {1, 1}); es.initialize(); // write channel data in segments From 5c054e96c8853cd69b78f7b87d98425ca2387a2f Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:47:29 -0700 Subject: [PATCH 4/8] fix sanitize workflow command --- .github/workflows/sanitize.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sanitize.yml b/.github/workflows/sanitize.yml index 110cf030..5f17b234 100644 --- a/.github/workflows/sanitize.yml +++ b/.github/workflows/sanitize.yml @@ -19,7 +19,7 @@ jobs: uses: actions/checkout@v4 - name: Install dependencies - run: + run: | sudo apt-get update sudo apt-get install -y libhdf5-dev libboost-all-dev git clone https://github.com/catchorg/Catch2.git From 82fb8f3ef02a66106a542e034d429c3876297919 Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:04:08 -0700 Subject: [PATCH 5/8] fix memory leak --- src/hdf5/HDF5IO.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hdf5/HDF5IO.cpp b/src/hdf5/HDF5IO.cpp index 69f03707..cafa63ef 100644 --- a/src/hdf5/HDF5IO.cpp +++ b/src/hdf5/HDF5IO.cpp @@ -438,7 +438,11 @@ AQNWB::BaseRecordingData* HDF5IO::createArrayDataSet(const BaseDataType& type, data = std::make_unique( file->createDataSet(path, H5type, dSpace, prop)); - return new HDF5RecordingData(data.release()); + + std::unique_ptr recordingData = + std::make_unique(data.release()); + + return recordingData.release(); } H5O_type_t HDF5IO::getObjectType(const std::string& path) From cd6a667a20c0a950119c4751045cf05524a24179 Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:47:02 -0700 Subject: [PATCH 6/8] update io to return smart pointers --- src/BaseIO.hpp | 17 ++++------ src/hdf5/HDF5IO.cpp | 21 ++++++------ src/hdf5/HDF5IO.hpp | 14 ++++---- tests/testBase.cpp | 19 ++++++----- tests/testFile.cpp | 9 +++-- tests/testHDF5IO.cpp | 81 +++++++++++++++++++++----------------------- 6 files changed, 77 insertions(+), 84 deletions(-) diff --git a/src/BaseIO.hpp b/src/BaseIO.hpp index 77c3213e..f9c0fa2b 100644 --- a/src/BaseIO.hpp +++ b/src/BaseIO.hpp @@ -246,17 +246,19 @@ class BaseIO * @param path The location in the file of the new dataset. * @return A pointer to the created dataset. */ - virtual BaseRecordingData* createArrayDataSet(const BaseDataType& type, - const SizeArray& size, - const SizeArray& chunking, - const std::string& path) = 0; + virtual std::unique_ptr createArrayDataSet( + const BaseDataType& type, + const SizeArray& size, + const SizeArray& chunking, + const std::string& path) = 0; /** * @brief Returns a pointer to a dataset at a given path. * @param path The location in the file of the dataset. * @return A pointer to the dataset. */ - virtual BaseRecordingData* getDataSet(const std::string& path) = 0; + virtual std::unique_ptr getDataSet( + const std::string& path) = 0; /** * @brief Convenience function for creating NWB related attributes. @@ -383,11 +385,6 @@ class BaseRecordingData const void* data) = 0; protected: - /** - * @brief The current position in the x dimension. - */ - SizeType xPos; - /** * @brief The size of the dataset in each dimension. */ diff --git a/src/hdf5/HDF5IO.cpp b/src/hdf5/HDF5IO.cpp index cafa63ef..6f9ce86e 100644 --- a/src/hdf5/HDF5IO.cpp +++ b/src/hdf5/HDF5IO.cpp @@ -377,7 +377,8 @@ Status HDF5IO::createStringDataSet(const std::string& path, return Status::Success; } -AQNWB::BaseRecordingData* HDF5IO::getDataSet(const std::string& path) +std::unique_ptr HDF5IO::getDataSet( + const std::string& path) { std::unique_ptr data; @@ -386,7 +387,7 @@ AQNWB::BaseRecordingData* HDF5IO::getDataSet(const std::string& path) try { data = std::make_unique(file->openDataSet(path)); - return new HDF5RecordingData(data.release()); + return std::make_unique(std::move(data)); } catch (DataSetIException error) { error.printErrorStack(); return nullptr; @@ -399,10 +400,11 @@ AQNWB::BaseRecordingData* HDF5IO::getDataSet(const std::string& path) } } -AQNWB::BaseRecordingData* HDF5IO::createArrayDataSet(const BaseDataType& type, - const SizeArray& size, - const SizeArray& chunking, - const std::string& path) +std::unique_ptr HDF5IO::createArrayDataSet( + const BaseDataType& type, + const SizeArray& size, + const SizeArray& chunking, + const std::string& path) { std::unique_ptr data; DSetCreatPropList prop; @@ -439,10 +441,7 @@ AQNWB::BaseRecordingData* HDF5IO::createArrayDataSet(const BaseDataType& type, data = std::make_unique( file->createDataSet(path, H5type, dSpace, prop)); - std::unique_ptr recordingData = - std::make_unique(data.release()); - - return recordingData.release(); + return std::make_unique(std::move(data)); } H5O_type_t HDF5IO::getObjectType(const std::string& path) @@ -565,7 +564,7 @@ H5::DataType HDF5IO::getH5Type(BaseDataType type) } // HDF5RecordingData -HDF5RecordingData::HDF5RecordingData(H5::DataSet* data) +HDF5RecordingData::HDF5RecordingData(std::unique_ptr data) { DataSpace dSpace = data->getSpace(); DSetCreatPropList prop = data->getCreatePlist(); diff --git a/src/hdf5/HDF5IO.hpp b/src/hdf5/HDF5IO.hpp index 51cbe966..4fec9adb 100644 --- a/src/hdf5/HDF5IO.hpp +++ b/src/hdf5/HDF5IO.hpp @@ -185,17 +185,19 @@ class HDF5IO : public BaseIO * @param path The location in the file of the new dataset. * @return A pointer to the created dataset. */ - BaseRecordingData* createArrayDataSet(const BaseDataType& type, - const SizeArray& size, - const SizeArray& chunking, - const std::string& path) override; + std::unique_ptr createArrayDataSet( + const BaseDataType& type, + const SizeArray& size, + const SizeArray& chunking, + const std::string& path) override; /** * @brief Returns a pointer to a dataset at a given path. * @param path The location in the file of the dataset. * @return A pointer to the dataset. */ - BaseRecordingData* getDataSet(const std::string& path) override; + std::unique_ptr getDataSet( + const std::string& path) override; /** * @brief Returns the HDF5 type of object at a given path. @@ -246,7 +248,7 @@ class HDF5RecordingData : public BaseRecordingData * @brief Constructs an HDF5RecordingData object. * @param data A pointer to the HDF5 dataset. */ - HDF5RecordingData(H5::DataSet* data); + HDF5RecordingData(std::unique_ptr data); /** * @brief Deleted copy constructor to prevent construction-copying. diff --git a/tests/testBase.cpp b/tests/testBase.cpp index f79ccda5..b3f46bc1 100644 --- a/tests/testBase.cpp +++ b/tests/testBase.cpp @@ -37,21 +37,22 @@ TEST_CASE("TimeSeries", "[base]") // Read data back from file double* tsBuffer = new double[numSamples]; - BaseRecordingData* tsDset = io->getDataSet(dataPath + "/timestamps"); - readH5DataBlock(static_cast(tsDset)->getDataSet(), - timestampsType, - tsBuffer); + std::unique_ptr tsDset = + io->getDataSet(dataPath + "/timestamps"); + std::unique_ptr tsH5Dataset( + dynamic_cast(tsDset.release())); + readH5DataBlock(tsH5Dataset->getDataSet(), timestampsType, tsBuffer); std::vector tsRead(tsBuffer, tsBuffer + numSamples); delete[] tsBuffer; REQUIRE(tsRead == timestamps); // Read data back from file float* dataBuffer = new float[numSamples]; - BaseRecordingData* dataDset = io->getDataSet(dataPath + "/data"); - readH5DataBlock( - static_cast(dataDset)->getDataSet(), - dataType, - dataBuffer); + std::unique_ptr dataDset = + io->getDataSet(dataPath + "/data"); + std::unique_ptr dataH5Dataset( + dynamic_cast(dataDset.release())); + readH5DataBlock(dataH5Dataset->getDataSet(), dataType, dataBuffer); std::vector dataRead(dataBuffer, dataBuffer + numSamples); delete[] dataBuffer; REQUIRE_THAT(dataRead, Catch::Matchers::Approx(data).margin(1)); diff --git a/tests/testFile.cpp b/tests/testFile.cpp index 7c815102..5887f54d 100644 --- a/tests/testFile.cpp +++ b/tests/testFile.cpp @@ -35,12 +35,11 @@ TEST_CASE("ElectrodeTable", "[ecephys]") // Check if id datasets are created correctly SizeType numChannels = 3; - BaseRecordingData* id_data = io->getDataSet(path + "id"); + std::unique_ptr id_data = io->getDataSet(path + "id"); + std::unique_ptr idDataset( + dynamic_cast(id_data.release())); int* buffer = new int[numChannels]; - readH5DataBlock( - static_cast(id_data)->getDataSet(), - BaseDataType::I32, - buffer); + readH5DataBlock(idDataset->getDataSet(), BaseDataType::I32, buffer); std::vector read_channels(buffer, buffer + numChannels); delete[] buffer; REQUIRE(channelIDs == read_channels); diff --git a/tests/testHDF5IO.cpp b/tests/testHDF5IO.cpp index e13e03cc..cad5ed52 100644 --- a/tests/testHDF5IO.cpp +++ b/tests/testHDF5IO.cpp @@ -54,21 +54,20 @@ TEST_CASE("writeDataset", "[hdf5io]") SizeType numSamples = 10; // Create HDF5RecordingData object and dataset - BaseRecordingData* dataset = hdf5io->createArrayDataSet( + std::unique_ptr dataset = hdf5io->createArrayDataSet( BaseDataType::I32, SizeArray {0}, SizeArray {1}, dataPath); // Write data block std::vector dataShape = {numSamples}; std::vector positionOffset = {0}; - static_cast(dataset)->writeDataBlock( + dataset->writeDataBlock( dataShape, positionOffset, BaseDataType::I32, &testData[0]); - BaseRecordingData* dataRead = hdf5io->getDataSet(dataPath); + std::unique_ptr dataRead = hdf5io->getDataSet(dataPath); + std::unique_ptr datasetRead1D( + dynamic_cast(dataRead.release())); int* buffer = new int[numSamples]; - readH5DataBlock( - static_cast(dataRead)->getDataSet(), - BaseDataType::I32, - buffer); + readH5DataBlock(datasetRead1D->getDataSet(), BaseDataType::I32, buffer); std::vector dataOut(buffer, buffer + numSamples); delete[] buffer; @@ -89,22 +88,21 @@ TEST_CASE("writeDataset", "[hdf5io]") std::vector dataShape = {numRows, numCols}; std::vector positionOffset = {0, 0}; - BaseRecordingData* dataset = + std::unique_ptr dataset = hdf5io->createArrayDataSet(BaseDataType::I32, SizeArray {numRows, numCols}, SizeArray {0, 0}, dataPath); - Status status = - static_cast(dataset)->writeDataBlock( - dataShape, positionOffset, BaseDataType::I32, testData.data()); + Status status = dataset->writeDataBlock( + dataShape, positionOffset, BaseDataType::I32, testData.data()); // Read back the 1D data block from 3D dataset - BaseRecordingData* dataRead1D = hdf5io->getDataSet(dataPath); + std::unique_ptr dataRead1D = + hdf5io->getDataSet(dataPath); + std::unique_ptr dataset1DRead( + dynamic_cast(dataRead1D.release())); int* buffer1D = new int[numCols]; - readH5DataBlock( - static_cast(dataRead1D)->getDataSet(), - BaseDataType::I32, - buffer1D); + readH5DataBlock(dataset1DRead->getDataSet(), BaseDataType::I32, buffer1D); std::vector dataOut1D(buffer1D, buffer1D + numCols); delete[] buffer1D; @@ -127,24 +125,23 @@ TEST_CASE("writeDataset", "[hdf5io]") std::vector positionOffset = {0, 0}; // Create HDF5RecordingData object and dataset for 2D data - BaseRecordingData* dataset = hdf5io->createArrayDataSet( + std::unique_ptr dataset = hdf5io->createArrayDataSet( BaseDataType::I32, SizeArray {numRows, numCols}, // Initial size SizeArray {0, 0}, // chunking dataPath); // Write 2D data block - Status status = - static_cast(dataset)->writeDataBlock( - dataShape, positionOffset, BaseDataType::I32, testData.data()); + Status status = dataset->writeDataBlock( + dataShape, positionOffset, BaseDataType::I32, testData.data()); // Read back the 2D data block - BaseRecordingData* dataRead = hdf5io->getDataSet(dataPath); + std::unique_ptr dsetRead2D = + hdf5io->getDataSet(dataPath); + std::unique_ptr data2DRead( + dynamic_cast(dsetRead2D.release())); int* buffer = new int[numRows * numCols]; - readH5DataBlock( - static_cast(dataRead)->getDataSet(), - BaseDataType::I32, - buffer); + readH5DataBlock(data2DRead->getDataSet(), BaseDataType::I32, buffer); std::vector dataOut(buffer, buffer + numRows * numCols); delete[] buffer; @@ -166,23 +163,22 @@ TEST_CASE("writeDataset", "[hdf5io]") std::vector dataShape = {depth, height, width}; std::vector positionOffset = {0, 0, 0}; - BaseRecordingData* dataset = + std::unique_ptr dataset = hdf5io->createArrayDataSet(BaseDataType::I32, SizeArray {depth, height, width}, SizeArray {0, 0, 0}, dataPath); - Status status = - static_cast(dataset)->writeDataBlock( - dataShape, positionOffset, BaseDataType::I32, testData.data()); + Status status = dataset->writeDataBlock( + dataShape, positionOffset, BaseDataType::I32, testData.data()); // Read back the 1D data block from 3D dataset - BaseRecordingData* dataRead1D = hdf5io->getDataSet(dataPath); + std::unique_ptr dataRead1D = + hdf5io->getDataSet(dataPath); + std::unique_ptr dSet1D( + dynamic_cast(dataRead1D.release())); int* buffer1D = new int[width]; // Assuming 'width' is the size of the 1D data block - readH5DataBlock( - static_cast(dataRead1D)->getDataSet(), - BaseDataType::I32, - buffer1D); + readH5DataBlock(dSet1D->getDataSet(), BaseDataType::I32, buffer1D); std::vector dataOut1D(buffer1D, buffer1D + width); delete[] buffer1D; @@ -203,24 +199,23 @@ TEST_CASE("writeDataset", "[hdf5io]") std::vector dataShape = {depth, height, width}; std::vector positionOffset = {0, 0, 0}; - BaseRecordingData* dataset = + std::unique_ptr dataset = hdf5io->createArrayDataSet(BaseDataType::I32, SizeArray {depth, height, width}, SizeArray {0, 0, 0}, dataPath); - Status status = - static_cast(dataset)->writeDataBlock( - dataShape, positionOffset, BaseDataType::I32, testData.data()); + Status status = dataset->writeDataBlock( + dataShape, positionOffset, BaseDataType::I32, testData.data()); // Read back the 2D data block from 3D dataset - BaseRecordingData* dataRead2D = hdf5io->getDataSet(dataPath); + std::unique_ptr dataRead2D = + hdf5io->getDataSet(dataPath); + std::unique_ptr dSetRead2D( + dynamic_cast(dataset.release())); int* buffer2D = new int[height * width]; // Assuming 'numRows' and 'numCols' define the // 2D data block size - readH5DataBlock( - static_cast(dataRead2D)->getDataSet(), - BaseDataType::I32, - buffer2D); + readH5DataBlock(dSetRead2D->getDataSet(), BaseDataType::I32, buffer2D); std::vector dataOut2D(buffer2D, buffer2D + height * width); delete[] buffer2D; From f916e1c71cef8d633a940612a711c7bca4a3478e Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:58:23 -0700 Subject: [PATCH 7/8] move sanitize to tests workflow --- .github/workflows/sanitize.yml | 48 ---------------------------------- .github/workflows/tests.yml | 42 +++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 50 deletions(-) delete mode 100644 .github/workflows/sanitize.yml diff --git a/.github/workflows/sanitize.yml b/.github/workflows/sanitize.yml deleted file mode 100644 index 5f17b234..00000000 --- a/.github/workflows/sanitize.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Sanitize - -on: - push: - branches: - - main - - pull_request: - branches: - - main - workflow_dispatch: - -jobs: - sanitize: - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y libhdf5-dev libboost-all-dev - git clone https://github.com/catchorg/Catch2.git - cd Catch2 - git checkout "v3.5.3" - cmake -Bbuild -H. -DBUILD_TESTING=OFF - sudo cmake --build build/ --target install - - - name: Configure - run: cmake --preset=ci-sanitize - - - name: Build - run: cmake --build build/sanitize -j 2 - - - name: Test - working-directory: build/sanitize - env: - ASAN_OPTIONS: "strict_string_checks=1:\ - detect_stack_use_after_return=1:\ - check_initialization_order=1:\ - strict_init_order=1:\ - detect_leaks=1:\ - halt_on_error=1" - UBSAN_OPTIONS: "print_stacktrace=1:\ - halt_on_error=1" - run: ctest --output-on-failure --no-tests=error -j 2 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 14c55228..0c3ac824 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ on: workflow_dispatch: jobs: - tests: + test: defaults: run: shell: bash @@ -65,8 +65,46 @@ jobs: path: | build/tests/data/*.nwb + sanitize: + needs: test + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libhdf5-dev libboost-all-dev + git clone https://github.com/catchorg/Catch2.git + cd Catch2 + git checkout "v3.5.3" + cmake -Bbuild -H. -DBUILD_TESTING=OFF + sudo cmake --build build/ --target install + + - name: Configure + run: cmake --preset=ci-sanitize + + - name: Build + run: cmake --build build/sanitize -j 2 + + - name: Test + working-directory: build/sanitize + env: + ASAN_OPTIONS: "strict_string_checks=1:\ + detect_stack_use_after_return=1:\ + check_initialization_order=1:\ + strict_init_order=1:\ + detect_leaks=1:\ + halt_on_error=1" + UBSAN_OPTIONS: "print_stacktrace=1:\ + halt_on_error=1" + run: ctest --output-on-failure --no-tests=error -j 2 + validate: - needs: tests + needs: [test, sanitize] defaults: run: shell: bash From 58d68e050ca5dc4af3e14039b08c4cd5ca09db1b Mon Sep 17 00:00:00 2001 From: Steph Prince <40640337+stephprince@users.noreply.github.com> Date: Tue, 30 Jul 2024 22:04:42 -0700 Subject: [PATCH 8/8] add include for unique_ptr --- src/BaseIO.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/BaseIO.hpp b/src/BaseIO.hpp index f9c0fa2b..80a72390 100644 --- a/src/BaseIO.hpp +++ b/src/BaseIO.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include