From e77b6152932217bd4fc2eca805f3adb92163555b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Fr=C3=B6jdh?= Date: Fri, 15 Nov 2024 15:17:52 +0100 Subject: [PATCH] Added expression templates (#98) - Works with NDArray - Works with NDView --- CMakeLists.txt | 6 ++ benchmarks/CMakeLists.txt | 11 +++ benchmarks/ndarray_benchmark.cpp | 136 +++++++++++++++++++++++++++++++ include/aare/ArrayExpr.hpp | 99 ++++++++++++++++++++++ include/aare/NDArray.hpp | 60 +++++--------- include/aare/NDView.hpp | 7 +- python/examples/play.py | 2 + src/NDArray.test.cpp | 50 ++++++++++-- src/NumpyFile.test.cpp | 6 +- src/RawFile.test.cpp | 18 ++-- src/RawMasterFile.test.cpp | 6 +- tests/test.cpp | 4 +- 12 files changed, 341 insertions(+), 64 deletions(-) create mode 100644 benchmarks/CMakeLists.txt create mode 100644 benchmarks/ndarray_benchmark.cpp create mode 100644 include/aare/ArrayExpr.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cb9d68..be5fad3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) # General options option(AARE_PYTHON_BINDINGS "Build python bindings" ON) option(AARE_TESTS "Build tests" OFF) +option(AARE_BENCHMARKS "Build benchmarks" OFF) option(AARE_EXAMPLES "Build examples" OFF) option(AARE_IN_GITHUB_ACTIONS "Running in Github Actions" OFF) option(AARE_DOCS "Build documentation" OFF) @@ -63,6 +64,10 @@ if(AARE_CUSTOM_ASSERT) add_compile_definitions(AARE_CUSTOM_ASSERT) endif() +if(AARE_BENCHMARKS) + add_subdirectory(benchmarks) +endif() + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -242,6 +247,7 @@ endif() ###------------------------------------------------------------------------------------------ set(PUBLICHEADERS + include/aare/ArrayExpr.hpp include/aare/ClusterFinder.hpp include/aare/ClusterFile.hpp include/aare/CtbRawFile.hpp diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 0000000..d083bab --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,11 @@ +find_package(benchmark REQUIRED) + +add_executable(ndarray_benchmark ndarray_benchmark.cpp) + +target_link_libraries(ndarray_benchmark benchmark::benchmark aare_core aare_compiler_flags) +# target_link_libraries(tests PRIVATE aare_core aare_compiler_flags) + +set_target_properties(ndarray_benchmark PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + # OUTPUT_NAME run_tests +) \ No newline at end of file diff --git a/benchmarks/ndarray_benchmark.cpp b/benchmarks/ndarray_benchmark.cpp new file mode 100644 index 0000000..55fa263 --- /dev/null +++ b/benchmarks/ndarray_benchmark.cpp @@ -0,0 +1,136 @@ +#include +#include "aare/NDArray.hpp" + + +using aare::NDArray; + +constexpr ssize_t size = 1024; +class TwoArrays : public benchmark::Fixture { +public: + NDArray a{{size,size},0}; + NDArray b{{size,size},0}; + void SetUp(::benchmark::State& state) { + for(uint32_t i = 0; i < size; i++){ + for(uint32_t j = 0; j < size; j++){ + a(i, j)= i*j+1; + b(i, j)= i*j+1; + } + } + } + + // void TearDown(::benchmark::State& state) { + // } +}; + + + + +BENCHMARK_F(TwoArrays, AddWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a+b; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, AddWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) + b(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_F(TwoArrays, SubtractWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a-b; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, SubtractWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) - b(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_F(TwoArrays, MultiplyWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a*b; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, MultiplyWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) * b(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_F(TwoArrays, DivideWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a/b; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, DivideWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) / b(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_F(TwoArrays, FourAddWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a+b+a+b; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, FourAddWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) + b(i) + a(i) + b(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_F(TwoArrays, MultiplyAddDivideWithOperator)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res = a*a+b/a; + benchmark::DoNotOptimize(res); + } +} +BENCHMARK_F(TwoArrays, MultiplyAddDivideWithIndex)(benchmark::State& st) { + for (auto _ : st) { + // This code gets timed + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + res(i) = a(i) * a(i) + b(i) / a(i); + } + benchmark::DoNotOptimize(res); + } +} + +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/include/aare/ArrayExpr.hpp b/include/aare/ArrayExpr.hpp new file mode 100644 index 0000000..7f8015c --- /dev/null +++ b/include/aare/ArrayExpr.hpp @@ -0,0 +1,99 @@ +#pragma once +#include //int64_t +#include //size_t +#include + +#include +namespace aare { + +template class ArrayExpr { + public: + static constexpr bool is_leaf = false; + + auto operator[](size_t i) const { return static_cast(*this)[i]; } + auto operator()(size_t i) const { return static_cast(*this)[i]; } + auto size() const { return static_cast(*this).size(); } + std::array shape() const { return static_cast(*this).shape(); } +}; + +template +class ArrayAdd : public ArrayExpr, Ndim> { + const A &arr1_; + const B &arr2_; + + public: + ArrayAdd(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { + assert(arr1.size() == arr2.size()); + } + auto operator[](int i) const { return arr1_[i] + arr2_[i]; } + size_t size() const { return arr1_.size(); } + std::array shape() const { return arr1_.shape(); } +}; + +template +class ArraySub : public ArrayExpr, Ndim> { + const A &arr1_; + const B &arr2_; + + public: + ArraySub(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { + assert(arr1.size() == arr2.size()); + } + auto operator[](int i) const { return arr1_[i] - arr2_[i]; } + size_t size() const { return arr1_.size(); } + std::array shape() const { return arr1_.shape(); } +}; + +template +class ArrayMul : public ArrayExpr,Ndim> { + const A &arr1_; + const B &arr2_; + + public: + ArrayMul(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { + assert(arr1.size() == arr2.size()); + } + auto operator[](int i) const { return arr1_[i] * arr2_[i]; } + size_t size() const { return arr1_.size(); } + std::array shape() const { return arr1_.shape(); } +}; + +template +class ArrayDiv : public ArrayExpr, Ndim> { + const A &arr1_; + const B &arr2_; + + public: + ArrayDiv(const A &arr1, const B &arr2) : arr1_(arr1), arr2_(arr2) { + assert(arr1.size() == arr2.size()); + } + auto operator[](int i) const { return arr1_[i] / arr2_[i]; } + size_t size() const { return arr1_.size(); } + std::array shape() const { return arr1_.shape(); } +}; + + + +template +auto operator+(const ArrayExpr &arr1, const ArrayExpr &arr2) { + return ArrayAdd, ArrayExpr, Ndim>(arr1, arr2); +} + +template +auto operator-(const ArrayExpr &arr1, const ArrayExpr &arr2) { + return ArraySub, ArrayExpr, Ndim>(arr1, arr2); +} + +template +auto operator*(const ArrayExpr &arr1, const ArrayExpr &arr2) { + return ArrayMul, ArrayExpr, Ndim>(arr1, arr2); +} + +template +auto operator/(const ArrayExpr &arr1, const ArrayExpr &arr2) { + return ArrayDiv, ArrayExpr, Ndim>(arr1, arr2); +} + + + +} // namespace aare \ No newline at end of file diff --git a/include/aare/NDArray.hpp b/include/aare/NDArray.hpp index 75f4c1c..c91ae14 100644 --- a/include/aare/NDArray.hpp +++ b/include/aare/NDArray.hpp @@ -7,6 +7,7 @@ memory. TODO! Add expression templates for operators */ +#include "aare/ArrayExpr.hpp" #include "aare/NDView.hpp" #include @@ -20,7 +21,8 @@ TODO! Add expression templates for operators namespace aare { -template class NDArray { +template +class NDArray : public ArrayExpr, Ndim> { std::array shape_; std::array strides_; size_t size_{}; @@ -43,7 +45,7 @@ template class NDArray { : shape_(shape), strides_(c_strides(shape_)), size_(std::accumulate(shape_.begin(), shape_.end(), 1, std::multiplies<>())), - data_(new T[size_]) {}; + data_(new T[size_]) {} /** * @brief Construct a new NDArray object with a shape and value. @@ -69,8 +71,7 @@ template class NDArray { NDArray(NDArray &&other) noexcept : shape_(other.shape_), strides_(c_strides(shape_)), size_(other.size_), data_(other.data_) { - - other.reset(); + other.reset(); // TODO! is this necessary? } // Copy constructor @@ -78,7 +79,14 @@ template class NDArray { : shape_(other.shape_), strides_(c_strides(shape_)), size_(other.size_), data_(new T[size_]) { std::copy(other.data_, other.data_ + size_, data_); - // fmt::print("NDArray(const NDArray &other)\n"); + } + + // Conversion operator from array expression to array + template + NDArray(ArrayExpr &&expr) : NDArray(expr.shape()) { + for (int i = 0; i < size_; ++i) { + data_[i] = expr[i]; + } } ~NDArray() { delete[] data_; } @@ -90,14 +98,10 @@ template class NDArray { NDArray &operator=(NDArray &&other) noexcept; // Move assign NDArray &operator=(const NDArray &other); // Copy assign - - NDArray operator+(const NDArray &other); NDArray &operator+=(const NDArray &other); - NDArray operator-(const NDArray &other); NDArray &operator-=(const NDArray &other); - NDArray operator*(const NDArray &other); NDArray &operator*=(const NDArray &other); - NDArray operator/(const NDArray &other); + // NDArray& operator/=(const NDArray& other); template NDArray &operator/=(const NDArray &other) { @@ -151,12 +155,16 @@ template class NDArray { return data_[element_offset(strides_, index...)]; } + // TODO! is int the right type for index? T &operator()(int i) { return data_[i]; } const T &operator()(int i) const { return data_[i]; } + T &operator[](int i) { return data_[i]; } + const T &operator[](int i) const { return data_[i]; } + T *data() { return data_; } std::byte *buffer() { return reinterpret_cast(data_); } - uint64_t size() const { return size_; } + size_t size() const { return size_; } size_t total_bytes() const { return size_ * sizeof(T); } std::array shape() const noexcept { return shape_; } int64_t shape(int64_t i) const noexcept { return shape_[i]; } @@ -204,17 +212,11 @@ NDArray::operator=(NDArray &&other) noexcept { return *this; } -template -NDArray NDArray::operator+(const NDArray &other) { - NDArray result(*this); - result += other; - return result; -} template NDArray &NDArray::operator+=(const NDArray &other) { // check shape if (shape_ == other.shape_) { - for (uint32_t i = 0; i < size_; ++i) { + for (size_t i = 0; i < size_; ++i) { data_[i] += other.data_[i]; } return *this; @@ -222,13 +224,6 @@ NDArray &NDArray::operator+=(const NDArray &other) { throw(std::runtime_error("Shape of ImageDatas must match")); } -template -NDArray NDArray::operator-(const NDArray &other) { - NDArray result{*this}; - result -= other; - return result; -} - template NDArray &NDArray::operator-=(const NDArray &other) { // check shape @@ -240,12 +235,6 @@ NDArray &NDArray::operator-=(const NDArray &other) { } throw(std::runtime_error("Shape of ImageDatas must match")); } -template -NDArray NDArray::operator*(const NDArray &other) { - NDArray result = *this; - result *= other; - return result; -} template NDArray &NDArray::operator*=(const NDArray &other) { @@ -259,13 +248,6 @@ NDArray &NDArray::operator*=(const NDArray &other) { throw(std::runtime_error("Shape of ImageDatas must match")); } -template -NDArray NDArray::operator/(const NDArray &other) { - NDArray result = *this; - result /= other; - return result; -} - template NDArray &NDArray::operator&=(const T &mask) { for (auto it = begin(); it != end(); ++it) @@ -276,7 +258,7 @@ NDArray &NDArray::operator&=(const T &mask) { template NDArray NDArray::operator>(const NDArray &other) { if (shape_ == other.shape_) { - NDArray result{shape_}; + NDArray result{shape_}; for (int i = 0; i < size_; ++i) { result(i) = (data_[i] > other.data_[i]); } diff --git a/include/aare/NDView.hpp b/include/aare/NDView.hpp index e02b3b2..e3a6d30 100644 --- a/include/aare/NDView.hpp +++ b/include/aare/NDView.hpp @@ -1,4 +1,7 @@ #pragma once + +#include "aare/ArrayExpr.hpp" + #include #include #include @@ -45,7 +48,7 @@ template std::array make_array(const std::vector class NDView { +template class NDView : public ArrayExpr, Ndim> { public: NDView() = default; ~NDView() = default; @@ -68,7 +71,7 @@ template class NDView { return buffer_[element_offset(strides_, index...)]; } - uint64_t size() const { return size_; } + size_t size() const { return size_; } size_t total_bytes() const { return size_ * sizeof(T); } std::array strides() const noexcept { return strides_; } diff --git a/python/examples/play.py b/python/examples/play.py index fca5370..bac7c18 100644 --- a/python/examples/play.py +++ b/python/examples/play.py @@ -5,7 +5,9 @@ from pathlib import Path from aare import ClusterFile base = Path('~/data/aare_test_data/clusters').expanduser() + # f = ClusterFile(base / 'beam_En700eV_-40deg_300V_10us_d0_f0_100.clust') f = ClusterFile(base / 'single_frame_97_clustrers.clust') + diff --git a/src/NDArray.test.cpp b/src/NDArray.test.cpp index 90a8d8e..34bd788 100644 --- a/src/NDArray.test.cpp +++ b/src/NDArray.test.cpp @@ -1,5 +1,6 @@ #include "aare/NDArray.hpp" #include +#include #include using aare::NDArray; @@ -101,7 +102,8 @@ TEST_CASE("Elementwise multiplication of 3D image") { a(i) = i; b(i) = i; } - auto c = a * b; + // auto c = a * b; // This works but the result is a lazy ArrayMul object + NDArray c = a * b; REQUIRE(c(0, 0, 0) == 0 * 0); REQUIRE(c(0, 0, 1) == 1 * 1); REQUIRE(c(0, 1, 1) == 3 * 3); @@ -109,6 +111,39 @@ TEST_CASE("Elementwise multiplication of 3D image") { REQUIRE(c(2, 3, 1) == 23 * 23); } +NDArray MultiplyNDArrayUsingOperator(NDArray &a, NDArray &b) { + // return a * a * b * b; + NDArrayc = a*b; + return c; +} + +NDArray MultiplyNDArrayUsingIndex(NDArray &a, NDArray &b) { + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + // res(i) = a(i) * a(i) * b(i) * b(i); + res(i) = a(i) * b(i); + } + return res; +} + +NDArray AddNDArrayUsingOperator(NDArray &a, NDArray &b) { + // return a * a * b * b; + // NDArrayc = a+b; + NDArray c(a.shape()); + c = a + b; + return c; +} + +NDArray AddNDArrayUsingIndex(NDArray &a, NDArray &b) { + NDArray res(a.shape()); + for (uint32_t i = 0; i < a.size(); i++) { + // res(i) = a(i) * a(i) * b(i) * b(i); + res(i) = a(i) + b(i); + } + return res; +} + + TEST_CASE("Compare two images") { NDArray a; NDArray b; @@ -168,7 +203,6 @@ TEST_CASE("Bitwise and on data") { REQUIRE(a(2) == 384); } - TEST_CASE("Elementwise operations on images") { std::array shape{5, 5}; double a_val = 3.0; @@ -178,7 +212,8 @@ TEST_CASE("Elementwise operations on images") { NDArray A(shape, a_val); NDArray B(shape, b_val); - auto C = A + B; + NDArray C = A + B; + // auto C = A+B; // This works but the result is a lazy ArraySum object // Value of C matches for (uint32_t i = 0; i < C.size(); ++i) { @@ -202,7 +237,8 @@ TEST_CASE("Elementwise operations on images") { SECTION("Subtract two images") { NDArray A(shape, a_val); NDArray B(shape, b_val); - auto C = A - B; + NDArray C = A - B; + // auto C = A - B; // This works but the result is a lazy ArraySub object // Value of C matches for (uint32_t i = 0; i < C.size(); ++i) { @@ -226,7 +262,8 @@ TEST_CASE("Elementwise operations on images") { SECTION("Multiply two images") { NDArray A(shape, a_val); NDArray B(shape, b_val); - auto C = A * B; + // auto C = A * B; // This works but the result is a lazy ArrayMul object + NDArray C = A * B; // Value of C matches for (uint32_t i = 0; i < C.size(); ++i) { @@ -250,7 +287,8 @@ TEST_CASE("Elementwise operations on images") { SECTION("Divide two images") { NDArray A(shape, a_val); NDArray B(shape, b_val); - auto C = A / B; + // auto C = A / B; // This works but the result is a lazy ArrayDiv object + NDArray C = A / B; // Value of C matches for (uint32_t i = 0; i < C.size(); ++i) { diff --git a/src/NumpyFile.test.cpp b/src/NumpyFile.test.cpp index daa3903..bdd6451 100644 --- a/src/NumpyFile.test.cpp +++ b/src/NumpyFile.test.cpp @@ -6,7 +6,7 @@ using aare::Dtype; using aare::NumpyFile; -TEST_CASE("Read a 1D numpy file with int32 data type") { +TEST_CASE("Read a 1D numpy file with int32 data type", "[.integration]") { auto fpath = test_data_path() / "numpy" / "test_1d_int32.npy"; REQUIRE(std::filesystem::exists(fpath)); @@ -23,8 +23,8 @@ TEST_CASE("Read a 1D numpy file with int32 data type") { REQUIRE(data(i) == i); } } - -TEST_CASE("Read a 3D numpy file with np.double data type") { + +TEST_CASE("Read a 3D numpy file with np.double data type", "[.integration]") { auto fpath = test_data_path() / "numpy" / "test_3d_double.npy"; REQUIRE(std::filesystem::exists(fpath)); diff --git a/src/RawFile.test.cpp b/src/RawFile.test.cpp index ce991ce..faefd28 100644 --- a/src/RawFile.test.cpp +++ b/src/RawFile.test.cpp @@ -7,7 +7,7 @@ using aare::File; -TEST_CASE("Read number of frames from a jungfrau raw file") { +TEST_CASE("Read number of frames from a jungfrau raw file", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -16,7 +16,7 @@ TEST_CASE("Read number of frames from a jungfrau raw file") { REQUIRE(f.total_frames() == 10); } -TEST_CASE("Read frame numbers from a jungfrau raw file") { +TEST_CASE("Read frame numbers from a jungfrau raw file", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -32,7 +32,7 @@ TEST_CASE("Read frame numbers from a jungfrau raw file") { } } -TEST_CASE("Read a frame number too high throws") { +TEST_CASE("Read a frame number too high throws", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -46,7 +46,7 @@ TEST_CASE("Read a frame number too high throws") { REQUIRE_THROWS(f.frame_number(10)); } -TEST_CASE("Read a frame numbers where the subfile is missing throws") { +TEST_CASE("Read a frame numbers where the subfile is missing throws", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_missing_subfile_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -67,7 +67,7 @@ TEST_CASE("Read a frame numbers where the subfile is missing throws") { } -TEST_CASE("Read data from a jungfrau 500k single port raw file") { +TEST_CASE("Read data from a jungfrau 500k single port raw file", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -83,7 +83,7 @@ TEST_CASE("Read data from a jungfrau 500k single port raw file") { } } -TEST_CASE("Read frame numbers from a raw file") { +TEST_CASE("Read frame numbers from a raw file", "[.integration]") { auto fpath = test_data_path() / "eiger" / "eiger_500k_16bit_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -96,7 +96,7 @@ TEST_CASE("Read frame numbers from a raw file") { } } -TEST_CASE("Compare reading from a numpy file with a raw file") { +TEST_CASE("Compare reading from a numpy file with a raw file", "[.integration]") { auto fpath_raw = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath_raw)); @@ -116,7 +116,7 @@ TEST_CASE("Compare reading from a numpy file with a raw file") { } } -TEST_CASE("Read multipart files") { +TEST_CASE("Read multipart files", "[.integration]") { auto fpath = test_data_path() / "jungfrau" / "jungfrau_double_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); @@ -141,7 +141,7 @@ TEST_CASE("Read multipart files") { } } -TEST_CASE("Read file with unordered frames") { +TEST_CASE("Read file with unordered frames", "[.integration]") { //TODO! Better explanation and error message auto fpath = test_data_path() / "mythen" / "scan242_master_3.raw"; REQUIRE(std::filesystem::exists(fpath)); diff --git a/src/RawMasterFile.test.cpp b/src/RawMasterFile.test.cpp index d8e1e87..17041c9 100644 --- a/src/RawMasterFile.test.cpp +++ b/src/RawMasterFile.test.cpp @@ -58,7 +58,7 @@ TEST_CASE("A disabled scan"){ } -TEST_CASE("Parse a master file in .json format"){ +TEST_CASE("Parse a master file in .json format", "[.integration]"){ auto fpath = test_data_path() / "jungfrau" / "jungfrau_single_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); RawMasterFile f(fpath); @@ -139,7 +139,7 @@ TEST_CASE("Parse a master file in .json format"){ } -TEST_CASE("Parse a master file in .raw format"){ +TEST_CASE("Parse a master file in .raw format", "[.integration]"){ auto fpath = test_data_path() / "moench/moench04_noise_200V_sto_both_100us_no_light_thresh_900_master_0.raw"; REQUIRE(std::filesystem::exists(fpath)); @@ -204,7 +204,7 @@ TEST_CASE("Parse a master file in .raw format"){ } -TEST_CASE("Read eiger master file"){ +TEST_CASE("Read eiger master file", "[.integration]"){ auto fpath = test_data_path() / "eiger" / "eiger_500k_32bit_master_0.json"; REQUIRE(std::filesystem::exists(fpath)); RawMasterFile f(fpath); diff --git a/tests/test.cpp b/tests/test.cpp index 1a76f0a..7c638e4 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -4,12 +4,12 @@ #include #include -TEST_CASE("Test suite can find data assets") { +TEST_CASE("Test suite can find data assets", "[.integration]") { auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy"; REQUIRE(std::filesystem::exists(fpath)); } -TEST_CASE("Test suite can open data assets") { +TEST_CASE("Test suite can open data assets", "[.integration]") { auto fpath = test_data_path() / "numpy" / "test_numpy_file.npy"; auto f = std::ifstream(fpath, std::ios::binary); REQUIRE(f.is_open());