From e98a24230d0f0c3adc4ea3268464056a4bd7fc53 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 17:42:05 +0200 Subject: [PATCH 1/9] Remove assertions --- test/units/include/modle/test/self_deleting_folder.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/units/include/modle/test/self_deleting_folder.hpp b/test/units/include/modle/test/self_deleting_folder.hpp index 7871eb48..2944b3a5 100644 --- a/test/units/include/modle/test/self_deleting_folder.hpp +++ b/test/units/include/modle/test/self_deleting_folder.hpp @@ -27,8 +27,6 @@ class SelfDeletingFolder { tmpdir = std::filesystem::temp_directory_path(); } catch (const std::filesystem::filesystem_error& e) { // Workaround spurious CI failures due to missing /tmp folder exception - assert(absl::StartsWith(e.what(), "std::filesystem::temp_directory_path: Not a directory")); - assert(absl::EndsWith(e.what(), "\"/tmp\"")); tmpdir = "test/data/unit_tests/scratch"; } From d9fa1a8abc678e4e5a1cc3021687167371954238 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:20:09 +0200 Subject: [PATCH 2/9] Refactor unit tests for correlation tests This commit simplifies the code used to test Pearson and Spearman (incl. weighted variants). These changes should also address spurious CI failures due to SIGPIPE signals. [ci full] --- test/CMakeLists.txt | 1 - test/units/stats/common.hpp | 237 -------------- test/units/stats/correlation_test.cpp | 427 ++++++++++++++++++-------- 3 files changed, 292 insertions(+), 373 deletions(-) delete mode 100644 test/units/stats/common.hpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b2c70fbe..4941d881 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,7 +32,6 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/units/simulation_cpu/simulation_complex_unit_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/simulation_cpu/simulation_simple_unit_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/simulation_internal/extrusion_barriers_test.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/units/stats/common.hpp ${CMAKE_CURRENT_SOURCE_DIR}/units/stats/correlation_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/stats/correlation_utils_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/stats/descriptive_test.cpp diff --git a/test/units/stats/common.hpp b/test/units/stats/common.hpp deleted file mode 100644 index c7dad974..00000000 --- a/test/units/stats/common.hpp +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (C) 2022 Roberto Rossini -// -// SPDX-License-Identifier: MIT - -#pragma once -#include // for flat_hash_set, operator!= -#include // for Hash -#include -#include - -#include // for max, generate -#include // for array -#include -#include -#include // for pclose, fgets, popen, FILE -#include // for create_directories, exists, path, remove -#include // for basic_ofstream, operator<<, basic_ostream -#include // for allocator, unique_ptr -#include // for iota -#include // for runtime_error -#include // for string, operator+, char_traits, stod -#include -#include // for enable_if, is_arithmetic -#include // for pair -#include // for vector - -#include "modle/common/common.hpp" // for u32, i32, i64 -#include "modle/common/const_map.hpp" -#include "modle/common/numeric_utils.hpp" -#include "modle/common/random.hpp" - -namespace modle::test::stats { -using namespace std::string_view_literals; - -// clang-format off -#define MAKE_CORR_TEST_CASE(METHOD) \ - std::make_pair(std::string_view{METHOD}, \ - "#!/usr/bin/env python3\n" \ - "from scipy.stats import " METHOD "r\n" \ - "from numpy import fromstring\n" \ - "import fileinput\n" \ - \ - "for line in fileinput.input():\n" \ - " v1, _, v2 = line.strip().partition(\"\\t\")\n" \ - " v1 = fromstring(v1, sep=\",\")\n" \ - " v2 = fromstring(v2, sep=\",\")\n" \ - \ - " corr, pv = " METHOD "r(v1, v2)\n" \ - " print(f\"{corr:.16e}\\t{pv:.16e}\", flush=True)\n"sv) - -#define MAKE_WEIGHTED_CORR_TEST_CASE(METHOD) \ - std::make_pair(std::string_view{METHOD}, \ - "#!/usr/bin/env Rscript\n" \ - "library(\"wCorr\")\n" \ - "f <- file(\"stdin\")\n" \ - "open(f)\n" \ - "method=sub(\"weighted_\", \"\", \"" METHOD "\")\n" \ - "while(length(line <- readLines(f, n=1)) > 0) {\n" \ - " toks <- strsplit(line, '\\t')[[1]]\n" \ - " v1 <- as.numeric(strsplit(toks[[1]], ',')[[1]])\n" \ - " v2 <- as.numeric(strsplit(toks[[2]], ',')[[1]])\n" \ - " w <- as.numeric(strsplit(toks[[3]], ',')[[1]])\n" \ - \ - " corr <- weightedCorr(v1, v2, weights=w, method=method)\n" \ - " write(sprintf(\"%.22f\\t-1\", corr), stdout())\n" \ - " flush.console()\n" \ - "}"sv) - -static constexpr utils::ConstMap external_cmds{ - MAKE_CORR_TEST_CASE("pearson"), - MAKE_CORR_TEST_CASE("spearman"), - MAKE_WEIGHTED_CORR_TEST_CASE("weighted_pearson"), - MAKE_WEIGHTED_CORR_TEST_CASE("weighted_spearman") -}; // clang-format on - -template >> -inline void generate_random_vect(random::PRNG_t& rand_eng, std::vector& buff, N min, N max, - bool allow_duplicates = true) { - using dist_t = - typename std::conditional, random::uniform_real_distribution, - random::uniform_int_distribution>::type; - dist_t dist(min, max); - if (allow_duplicates) { - std::generate(buff.begin(), buff.end(), [&]() { return dist(rand_eng); }); - } else { - absl::flat_hash_set s; - while (s.size() < buff.size()) { - s.insert(dist(rand_eng)); - } - std::copy(s.begin(), s.end(), buff.begin()); - } -} - -template >> -[[nodiscard]] inline std::vector generate_random_vect(random::PRNG_t& rand_eng, usize size, - N min, N max, - bool allow_duplicates = true) { - std::vector v(size); - generate_random_vect(rand_eng, v, min, max, allow_duplicates); - return v; -} - -inline std::pair, std::vector> generate_correlated_vects( - random::PRNG_t& rand_eng, u32 size) { - random::uniform_int_distribution dist(static_cast(size) / -50, - static_cast(size / 50)); - std::vector v1(size); - std::vector v2(size); - std::iota(v1.begin(), v1.end(), 0); - std::iota(v2.begin(), v2.end(), 0); - for (usize i = 0; i < size; ++i) { - auto n = static_cast(v1[i]) + dist(rand_eng); - v1[i] = static_cast(std::max(i64(0), n)); - n = static_cast(v2[i]) + dist(rand_eng); - v2[i] = static_cast(std::max(i64(0), n)); - } - return {v1, v2}; -} - -template ::value, N>::type> -inline void run_external_corr(std::string_view method, std::vector& v1, std::vector& v2, - std::vector& weights, std::atomic& rho, - std::atomic& pv, std::mutex& data_mutex, - std::condition_variable& input_data_cv, - std::condition_variable& output_data_cv, - std::atomic& input_data_ready, - std::atomic& output_data_ready) { - boost::process::ipstream stdout_stream; - boost::process::ipstream stderr_stream; - boost::process::opstream stdin_stream; - - try { - auto c = [&]() { - if (absl::StartsWith(method, "weighted_"sv)) { - return boost::process::child( - boost::process::search_path("Rscript").string(), "--quiet", "-e", - std::string{external_cmds.at(method)}, - boost::process::std_in stdout_stream, - boost::process::std_err > stderr_stream); - } - - return boost::process::child( - boost::process::search_path("python3").string(), "-c", - std::string{external_cmds.at(method)}, - boost::process::std_in stdout_stream, - boost::process::std_err > stderr_stream); - }(); - assert(c.running()); - - std::string sbuff; - while (true) { - { - std::unique_lock l(data_mutex); - input_data_cv.wait(l, [&]() { return input_data_ready.load(); }); - input_data_ready = false; - } - - if (v1.empty()) { // EOQ signal - assert(v2.empty()); - stdin_stream.pipe().close(); - c.wait(); - return; - } - - sbuff = [&]() { - if (absl::StartsWith(method, "weighted_")) { - return fmt::format(FMT_COMPILE("{}\t{}\t{}\n"), fmt::join(v1, ","), fmt::join(v2, ","), - fmt::join(weights, ",")); - } - return fmt::format(FMT_COMPILE("{}\t{}\n"), fmt::join(v1, ","), fmt::join(v2, ",")); - }(); - stdin_stream.write(sbuff.data(), static_cast(sbuff.size())); - stdin_stream.flush(); - - std::getline(stdout_stream, sbuff); - const auto sep_idx = sbuff.find('\t'); - assert(sep_idx < sbuff.size()); - rho = utils::parse_numeric_or_throw(std::string_view(sbuff.data(), sep_idx)); - pv = utils::parse_numeric_or_throw( - std::string_view(sbuff.data() + sep_idx + 1, sbuff.size() - sep_idx)); - output_data_ready = true; - output_data_cv.notify_one(); - } - } catch (const std::exception& e) { - std::string buff1; - std::string buff2; - while (std::getline(stderr_stream, buff1)) { - buff2.append(buff1); - buff2.append("\n"); - } - - if (!buff2.empty()) { - throw std::runtime_error(fmt::format(FMT_STRING("{}:\n{}"), e.what(), buff2)); - } - throw; - } -} - -template ::value, N>::type> -[[nodiscard]] inline std::pair external_corr(const std::vector& v1, - const std::vector& v2, - const std::vector& w, - std::string_view method) { - boost::process::ipstream stdout_stream; - boost::process::opstream stdin_stream; - if (absl::StartsWith(method, "weighted_"sv)) { - boost::process::spawn( - boost::process::search_path("Rscript").string(), "--quiet", "-e", - std::string{external_cmds.at(method)}, - boost::process::std_in stdout_stream); - } else { - boost::process::spawn( - boost::process::search_path("python3").string(), "-c", - std::string{external_cmds.at(method)}, - boost::process::std_in stdout_stream); - } - - std::string buff; - if (absl::StartsWith(method, "weighted_"sv)) { - buff = fmt::format(FMT_COMPILE("{}\t{}\t{}\n"), fmt::join(v1, ","), fmt::join(v2, ","), - fmt::join(w, ",")); - } else { - buff = fmt::format(FMT_COMPILE("{}\t{}\n"), fmt::join(v1, ","), fmt::join(v2, ",")); - } - stdin_stream.write(buff.data(), static_cast(buff.size())); - stdin_stream.close(); - - std::getline(stdout_stream, buff); - const auto sep_idx = buff.find('\t'); - assert(sep_idx < buff.size()); - const auto rho = utils::parse_numeric_or_throw(std::string_view(buff.data(), sep_idx)); - const auto pv = utils::parse_numeric_or_throw( - std::string_view(buff.data() + sep_idx + 1, buff.size() - sep_idx)); - - return {rho, pv}; -} -} // namespace modle::test::stats diff --git a/test/units/stats/correlation_test.cpp b/test/units/stats/correlation_test.cpp index 4f01b516..96970151 100644 --- a/test/units/stats/correlation_test.cpp +++ b/test/units/stats/correlation_test.cpp @@ -6,102 +6,287 @@ #include // for BitMask, operator!= #include // for StartsWith +#include // for FMT_COMPILE #include // for format -#include // for atomic -#include // for clone_base -#include // for assert -#include // for Approx, operator==, AssertionHandler, operator... -#include // for condition_variable -#include // for exception -#include // for mutex, unique_lock -#include // for random_device -#include // for overflow_error -#include // for char_traits -#include // for operator==, operator""sv, basic_string_view -#include // for thread -#include // for make_pair -#include // for vector - -#include "./common.hpp" // for generate_random_vect, external_corr, run_exter... +#include +#include +#include // for assert +#include // for Approx, operator==, AssertionHandler, operator... +#include // for exception +#include // for ostream +#include // for random_device +#include // for char_traits +#include // for operator==, operator""sv, basic_string_view +#include // for make_pair +#include // for vector + #include "modle/common/common.hpp" // for u32, usize +#include "modle/common/const_map.hpp" +#include "modle/common/numeric_utils.hpp" #include "modle/common/random.hpp" // for PRNG_t -#include "modle/test/self_deleting_folder.hpp" // for SelfDeletingFolder namespace modle::test::stats { using namespace modle::stats; +using namespace std::string_view_literals; + +// clang-format off +#define MAKE_CORR_TEST_CASE(METHOD) \ + std::make_pair(std::string_view{METHOD}, \ + "#!/usr/bin/env python3\n" \ + "from scipy.stats import " METHOD "r\n" \ + "from numpy import fromstring\n" \ + "import fileinput\n" \ + \ + "for line in fileinput.input():\n" \ + " v1, _, v2 = line.strip().partition(\"\\t\")\n" \ + " v1 = fromstring(v1, sep=\",\")\n" \ + " v2 = fromstring(v2, sep=\",\")\n" \ + \ + " corr, pv = " METHOD "r(v1, v2)\n" \ + " print(f\"{corr:.16e}\\t{pv:.16e}\", flush=True)\n"sv) + +#define MAKE_WEIGHTED_CORR_TEST_CASE(METHOD) \ + std::make_pair(std::string_view{METHOD}, \ + "#!/usr/bin/env Rscript\n" \ + "library(\"wCorr\")\n" \ + "f <- file(\"stdin\")\n" \ + "open(f)\n" \ + "method <- sub(\"weighted_\", \"\", \"" METHOD "\")\n" \ + "while(length(line <- readLines(f, n=1)) > 0) {\n" \ + " toks <- strsplit(line, '\\t')[[1]]\n" \ + " v1 <- as.numeric(strsplit(toks[[1]], ',')[[1]])\n" \ + " v2 <- as.numeric(strsplit(toks[[2]], ',')[[1]])\n" \ + " w <- as.numeric(strsplit(toks[[3]], ',')[[1]])\n" \ + \ + " corr <- weightedCorr(v1, v2, weights=w, method=method)\n" \ + " write(sprintf(\"%.22f\\t-1\", corr), stdout())\n" \ + " flush.console()\n" \ + "}"sv) + +static constexpr utils::ConstMap external_cmds{ + MAKE_CORR_TEST_CASE("pearson"), + MAKE_CORR_TEST_CASE("spearman"), + MAKE_WEIGHTED_CORR_TEST_CASE("weighted_pearson"), + MAKE_WEIGHTED_CORR_TEST_CASE("weighted_spearman") +}; // clang-format on + +template +void generate_random_vector(random::PRNG_t& rand_eng, std::vector& buff, N min, N max, + bool allow_duplicates = true) { + using DistrT = + typename std::conditional, random::uniform_real_distribution, + random::uniform_int_distribution>::type; + DistrT dist(min, max); + if (allow_duplicates) { + std::generate(buff.begin(), buff.end(), [&]() { return dist(rand_eng); }); + return; + } -template -static void test_correlation_w_random_vector(std::string_view method, usize vector_size, - usize iterations, N min, N max) { - static_assert(std::is_arithmetic_v, "N should be an arithmetic type."); - random::PRNG_t rand_eng{std::random_device{}()}; - - std::mutex data_mutex; - std::condition_variable input_data_cv; - std::condition_variable output_data_cv; - std::atomic input_data_ready{false}; - std::atomic output_data_ready{false}; - - std::vector v1(vector_size); - std::vector v2(vector_size); - std::vector weights(vector_size); - - std::atomic cfx_reference{}; - std::atomic pv_reference{}; - - std::thread t([&]() { - run_external_corr(method, v1, v2, weights, cfx_reference, pv_reference, data_mutex, - input_data_cv, output_data_cv, input_data_ready, output_data_ready); - }); - - auto pearson = Pearson<>{}; - auto spearman = Spearman<>{}; - for (usize i = 0; i < iterations; ++i) { - assert(!input_data_ready); - generate_random_vect(rand_eng, v1, min, max); - generate_random_vect(rand_eng, v2, min, max); - if (absl::StartsWith(method, "weighted_")) { - generate_random_vect(rand_eng, weights, 0.0, 1.0); - // fmt::print(stderr, FMT_STRING("{}\n"), fmt::join(weights, ",")); + absl::flat_hash_set s(buff.size()); + while (s.size() < buff.size()) { + s.insert(dist(rand_eng)); + } + std::copy(s.begin(), s.end(), buff.begin()); +} + +template +[[nodiscard]] std::vector generate_random_vector(random::PRNG_t& rand_eng, usize size, N min, + N max, bool allow_duplicates = true) { + std::vector v(size); + generate_random_vector(rand_eng, v, min, max, allow_duplicates); + return v; +} + +template +class CorrelationBuff { + static_assert(std::is_arithmetic_v); + static_assert(std::is_arithmetic_v); + std::vector _v1; + std::vector _v2; + std::vector _weights; + + public: + CorrelationBuff() = delete; + CorrelationBuff(usize size, bool with_weights) + : _v1(size, N1(0)), _v2(size, N1(0)), _weights(with_weights ? size : 0, N2(0)) {} + [[nodiscard]] const std::vector& v1() const noexcept { return this->_v1; } + [[nodiscard]] const std::vector& v2() const noexcept { return this->_v2; } + [[nodiscard]] const std::vector& weights() const noexcept { return this->_weights; } + + void generate(random::PRNG_t& rand_eng, N1 min, N1 max) { + assert(this->_v1.size() == this->_v2.size()); + generate_random_vector(rand_eng, this->_v1, min, max); + generate_random_vector(rand_eng, this->_v2, min, max); + assert(this->_v1.size() == this->_v2.size()); + + if (!this->_weights.empty()) { + assert(this->_v1.size() == this->_weights.size()); + generate_random_vector(rand_eng, this->_weights, N2(0), N2(1)); + assert(this->_v1.size() == this->_weights.size()); } - input_data_ready = true; - input_data_cv.notify_one(); - { - std::unique_lock l(data_mutex); - output_data_cv.wait(l, [&]() { return output_data_ready.load(); }); - output_data_ready = false; + } + + void serialize(std::string& buff) const { + if (!this->_weights.empty()) { + buff = fmt::format(FMT_COMPILE("{}\t{}\t{}\n"), fmt::join(this->_v1, ","), + fmt::join(this->_v2, ","), fmt::join(this->_weights, ",")); + return; } - const auto [cfx, pv] = [&]() { - if (method == "pearson"sv) { - const auto res = pearson(v1, v2); - return std::make_pair(res.pcc, res.pvalue); - } + buff = + fmt::format(FMT_COMPILE("{}\t{}\n"), fmt::join(this->_v1, ","), fmt::join(this->_v2, ",")); + } + [[nodiscard]] std::string serialize() const { + std::string buff; + this->serialize(buff); + return buff; + } +}; + +template +[[nodiscard]] static std::pair compute_correlation( + std::string_view method, const CorrelationBuff& data) { + const auto is_weighted = absl::StartsWith(method, "weighted_"); + const auto is_pearson = absl::EndsWith(method, "pearson"); + const auto is_spearman = absl::EndsWith(method, "spearman"); + + if (is_pearson && is_weighted) { + const auto res = Pearson{}(data.v1(), data.v2(), data.weights()); + return std::make_pair(res.pcc, res.pvalue); + } - if (method == "weighted_pearson"sv) { - const auto res = pearson(v1, v2, weights); - return std::make_pair(res.pcc, res.pvalue); - } + if (is_spearman && is_weighted) { + const auto res = Spearman{}(data.v1(), data.v2(), data.weights()); + return std::make_pair(res.rho, res.pvalue); + } + + if (is_pearson) { + const auto res = Pearson{}(data.v1(), data.v2()); + return std::make_pair(res.pcc, res.pvalue); + } + + assert(is_spearman); + + const auto res = Spearman{}(data.v1(), data.v2()); + return std::make_pair(res.rho, res.pvalue); +} + +class ExternalCorrelationRunner { + boost::process::ipstream _stdout{}; + boost::process::ipstream _stderr{}; + boost::process::opstream _stdin{}; + + boost::process::child _c{}; + + public: + ExternalCorrelationRunner() = delete; + explicit ExternalCorrelationRunner(std::string_view method) { + if (absl::StartsWith(method, "weighted_")) { + this->_c = boost::process::child( + boost::process::search_path("Rscript").string(), "--quiet", "-e", + std::string{external_cmds.at(method)}, + boost::process::std_in_stdin, boost::process::std_out> this->_stdout, + boost::process::std_err > this->_stderr); + } else { + this->_c = boost::process::child( + boost::process::search_path("python3").string(), "-c", + std::string{external_cmds.at(method)}, + boost::process::std_in_stdin, boost::process::std_out> this->_stdout, + boost::process::std_err > this->_stderr); + } + assert(this->_c.running()); + } - if (method == "spearman"sv) { - const auto res = spearman(v1, v2); - return std::make_pair(res.rho, res.pvalue); + ~ExternalCorrelationRunner() noexcept { + try { + assert(!this->_c.running()); + if (!this->_c) { + std::ostringstream buff; + buff << this->_stderr.rdbuf(); + if (const auto s = buff.str(); !s.empty()) { + throw std::runtime_error(fmt::format(FMT_STRING("{}\n"), s)); + } } + } catch (const std::exception& e) { + fmt::print( + stderr, + FMT_STRING("An exception was raised while calling ~ExternalCorrelationRunner(): {}"), + e.what()); + } catch (...) { + fmt::print( + stderr, + FMT_STRING("An unknown error occurred while calling ~ExternalCorrelationRunner()\n")); + } + } + + void wait(std::chrono::milliseconds duration = std::chrono::seconds(15)) { + this->_c.wait_for(duration); + } + + void write_to_stdin(const std::string& msg) { + assert(!msg.empty() && msg.back() == '\n'); + this->_stdin.write(msg.data(), static_cast(msg.size())); + this->_stdin.flush(); + } + + void read_from_stdout(std::string& buff) { std::getline(this->_stdout, buff); } + [[nodiscard]] std::string read_from_stdout() { + std::string buff; + this->read_from_stdout(buff); + return buff; + } + + void read_from_stderr(std::string& buff) { std::getline(this->_stderr, buff); } + [[nodiscard]] std::string read_from_stderr() { + std::string buff; + this->read_from_stderr(buff); + return buff; + } + + void signal_end_of_input() { this->_stdin.pipe().close(); } +}; + +template +static void run_correlation_test(std::string_view method, usize vector_size, N1 min, N1 max, + u64 seed = std::random_device{}()) { + static_assert(std::is_arithmetic_v); + static_assert(std::is_arithmetic_v); + + const auto weighted_corr = absl::StartsWith(method, "weighted_"); + CorrelationBuff buff(vector_size, weighted_corr); + std::string sbuff; + std::vector tok_buff; + + auto rand_eng = random::PRNG(seed); + + ExternalCorrelationRunner runner(method); + try { + for (usize i = 0; i < iterations; ++i) { + buff.generate(rand_eng, min, max); + buff.serialize(sbuff); - assert(method == "weighted_spearman"sv); - const auto res = spearman(v1, v2, weights); - return std::make_pair(res.rho, res.pvalue); - }(); + runner.write_to_stdin(sbuff); + const auto [corr, pv] = compute_correlation(method, buff); + runner.read_from_stdout(sbuff); + tok_buff = absl::StrSplit(sbuff, '\t'); + REQUIRE(tok_buff.size() == 2); - CHECK(Approx(cfx) == cfx_reference); - CHECK(Approx(pv) == pv_reference); + const auto expected_corr = utils::parse_numeric_or_throw(tok_buff.front()); + const auto expected_pv = utils::parse_numeric_or_throw(tok_buff.back()); + + CHECK(Approx(expected_corr) == corr); + CHECK(Approx(expected_pv) == pv); + } + runner.signal_end_of_input(); + runner.wait(); + } catch (const std::exception& e) { + const auto stderr_ = runner.read_from_stderr(); + if (!stderr_.empty()) { + throw std::runtime_error(fmt::format(FMT_STRING("{}:\n{}"), e.what(), stderr_)); + } + throw; } - v1.clear(); - v2.clear(); - input_data_ready = true; - input_data_cv.notify_one(); - t.join(); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -144,54 +329,40 @@ TEST_CASE("Corr. test: Weighted Pearson w ties", "[correlation][pearson][short]" // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Pearson (SciPy)", "[correlation][pearson][short]") { - random::PRNG_t rand_eng{2427588200550938527ULL}; - const auto v1 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto v2 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - std::vector dummy_weights{}; - const auto [pcc, pv] = Pearson<>{}(v1, v2); - const auto [pcc_reference, pv_reference] = external_corr(v1, v2, dummy_weights, "pearson"); - CHECK(Approx(pcc) == pcc_reference); - CHECK(Approx(pv) == pv_reference); + run_correlation_test("pearson", 1'000, 0, 15'000, 2427588200550938527ULL); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Pearson (wCorr)", "[correlation][pearson][short]") { - random::PRNG_t rand_eng{17383284879759537016ULL}; - const auto v1 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto v2 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto w = generate_random_vect(rand_eng, 1'000, 0.0, 1.0); - const auto [pcc, pv] = Pearson<>{}(v1, v2, w); - const auto [pcc_reference, pv_reference] = external_corr(v1, v2, w, "weighted_pearson"); - CHECK(Approx(pcc) == pcc_reference); - CHECK(Approx(pv) == pv_reference); + run_correlation_test("weighted_pearson", 1'000, 0, 15'000, 17383284879759537016ULL); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Pearson long (SciPy)", "[correlation][pearson][medium]") { - test_correlation_w_random_vector("pearson", 1'000, 250, 0U, 15'000U); - test_correlation_w_random_vector("pearson", 1'000, 250, -7'250, 7'250); - test_correlation_w_random_vector("pearson", 1'000, 250, -7'250.0, 7'250.0); + run_correlation_test("pearson", 1'000, 0, 15'000); + run_correlation_test("pearson", 1'000, -7'250, 7'250); + run_correlation_test("pearson", 1'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Pearson long vect. (SciPy)", "[correlation][pearson][long]") { - test_correlation_w_random_vector("pearson", 500'000, 2, 0U, 15'000U); - test_correlation_w_random_vector("pearson", 500'000, 2, -7'250, 7'250); - test_correlation_w_random_vector("pearson", 500'000, 2, -7'250.0, 7'250.0); + run_correlation_test("pearson", 100'000, 0U, 15'000U); + run_correlation_test("pearson", 100'000, -7'250, 7'250); + run_correlation_test("pearson", 100'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Pearson long (wCorr)", "[correlation][pearson][medium]") { - test_correlation_w_random_vector("weighted_pearson", 1'000, 250, 0U, 15'000U); - test_correlation_w_random_vector("weighted_pearson", 1'000, 250, -7'250, 7'250); - test_correlation_w_random_vector("weighted_pearson", 1'000, 250, -7'250.0, 7'250.0); + run_correlation_test("weighted_pearson", 1'000, 0U, 15'000U); + run_correlation_test("weighted_pearson", 1'000, -7'250, 7'250); + run_correlation_test("weighted_pearson", 1'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Pearson long vect. (wCorr)", "[correlation][pearson][long]") { - test_correlation_w_random_vector("weighted_pearson", 500'000, 2, 0U, 15'000U); - test_correlation_w_random_vector("weighted_pearson", 500'000, 2, -7'250, 7'250); - test_correlation_w_random_vector("weighted_pearson", 500'000, 2, -7'250.0, 7'250.0); + run_correlation_test("weighted_pearson", 100'000, 0U, 15'000U); + run_correlation_test("weighted_pearson", 100'000, -7'250, 7'250); + run_correlation_test("weighted_pearson", 100'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -214,54 +385,40 @@ TEST_CASE("Corr. test: Spearman w ties", "[correlation][spearman][short]") { // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Spearman (SciPy)", "[correlation][spearman][short]") { - random::PRNG_t rand_eng{3860329809333667103ULL}; - const auto v1 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto v2 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - std::vector dummy_weights{}; - const auto [rho, pv] = Spearman<>{}(v1, v2); - const auto [rho_reference, pv_reference] = external_corr(v1, v2, dummy_weights, "spearman"); - CHECK(Approx(rho) == rho_reference); - CHECK(Approx(pv) == pv_reference); + run_correlation_test("spearman", 1'000, 0, 15'000, 3860329809333667103ULL); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Spearman (wCorr)", "[correlation][spearman][short]") { - random::PRNG_t rand_eng{8469130800688738654ULL}; - const auto v1 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto v2 = generate_random_vect(rand_eng, 1'000, 0, 15'000); - const auto w = generate_random_vect(rand_eng, 1'000, 0.0, 1.0); - const auto [rho, pv] = Spearman<>{}(v1, v2, w); - const auto [rho_reference, pv_reference] = external_corr(v1, v2, w, "weighted_spearman"); - CHECK(Approx(rho) == rho_reference); - CHECK(Approx(pv) == pv_reference); + run_correlation_test("weighted_spearman", 1'000, 0, 15'000, 8469130800688738654ULL); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Spearman long (SciPy)", "[correlation][spearman][long]") { - test_correlation_w_random_vector("spearman", 1'000, 250, 0U, 15'000U); - test_correlation_w_random_vector("spearman", 1'000, 250, -7'250, 7'250); - test_correlation_w_random_vector("spearman", 1'000, 250, -7'250.0, 7'250.0); + run_correlation_test("spearman", 1'000, 0, 15'000); + run_correlation_test("spearman", 1'000, -7'250, 7'250); + run_correlation_test("spearman", 1'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Spearman long vect. (SciPy)", "[correlation][spearman][long]") { - test_correlation_w_random_vector("spearman", 500'000, 2, 0U, 15'000U); - test_correlation_w_random_vector("spearman", 500'000, 2, -7'250, 7'250); - test_correlation_w_random_vector("spearman", 500'000, 2, -7'250.0, 7'250.0); + run_correlation_test("spearman", 100'000, 0U, 15'000U); + run_correlation_test("spearman", 100'000, -7'250, 7'250); + run_correlation_test("spearman", 100'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Spearman long (wCorr)", "[correlation][spearman][medium]") { - test_correlation_w_random_vector("weighted_spearman", 1'000, 250, 0U, 15'000U); - test_correlation_w_random_vector("weighted_spearman", 1'000, 250, -7'250, 7'250); - test_correlation_w_random_vector("weighted_spearman", 1'000, 250, -7'250.0, 7'250.0); + run_correlation_test("weighted_spearman", 1'000, 0U, 15'000U); + run_correlation_test("weighted_spearman", 1'000, -7'250, 7'250); + run_correlation_test("weighted_spearman", 1'000, -7'250.0, 7'250.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) TEST_CASE("Corr. test: Weighted Spearman long vect. (wCorr)", "[correlation][spearman][long]") { - test_correlation_w_random_vector("weighted_spearman", 500'000, 2, 0U, 15'000U); - test_correlation_w_random_vector("weighted_spearman", 500'000, 2, -7'250, 7'250); - test_correlation_w_random_vector("weighted_spearman", 500'000, 2, -7'250.0, 7'250.0); + run_correlation_test("weighted_spearman", 100'000, 0U, 15'000U); + run_correlation_test("weighted_spearman", 100'000, -7'250, 7'250); + run_correlation_test("weighted_spearman", 100'000, -7'250.0, 7'250.0); } } // namespace modle::test::stats From 395a5acb5073a88227c6580ac04ac87c609504f2 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:28:59 +0200 Subject: [PATCH 3/9] Bugfix in Build Docker image GHA [no ci] --- .github/workflows/build-docker-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docker-image.yml b/.github/workflows/build-docker-image.yml index 22a0533f..8b80e656 100644 --- a/.github/workflows/build-docker-image.yml +++ b/.github/workflows/build-docker-image.yml @@ -6,7 +6,7 @@ name: Build Docker image on: create: branches-ignore: - - "*" + - "**" tags: - 'v*.*.*' From c3b6fed8f7b88b6bedef20c7b302e80ea26b283c Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:40:58 +0200 Subject: [PATCH 4/9] Fix Clang8 builds --- test/units/stats/correlation_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/units/stats/correlation_test.cpp b/test/units/stats/correlation_test.cpp index 96970151..375f970a 100644 --- a/test/units/stats/correlation_test.cpp +++ b/test/units/stats/correlation_test.cpp @@ -152,23 +152,23 @@ template const auto is_spearman = absl::EndsWith(method, "spearman"); if (is_pearson && is_weighted) { - const auto res = Pearson{}(data.v1(), data.v2(), data.weights()); + const auto res = Pearson<>{}(data.v1(), data.v2(), data.weights()); return std::make_pair(res.pcc, res.pvalue); } if (is_spearman && is_weighted) { - const auto res = Spearman{}(data.v1(), data.v2(), data.weights()); + const auto res = Spearman<>{}(data.v1(), data.v2(), data.weights()); return std::make_pair(res.rho, res.pvalue); } if (is_pearson) { - const auto res = Pearson{}(data.v1(), data.v2()); + const auto res = Pearson<>{}(data.v1(), data.v2()); return std::make_pair(res.pcc, res.pvalue); } assert(is_spearman); - const auto res = Spearman{}(data.v1(), data.v2()); + const auto res = Spearman<>{}(data.v1(), data.v2()); return std::make_pair(res.rho, res.pvalue); } From b5e6ea6a7b8fd12d13c256aa3f9a8ab9c394c2b2 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:43:14 +0200 Subject: [PATCH 5/9] Try to re-enable wCorr/SciPy tests in macOS CI --- .github/workflows/unit-tests-macos.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests-macos.yml b/.github/workflows/unit-tests-macos.yml index 449db945..8c41217d 100644 --- a/.github/workflows/unit-tests-macos.yml +++ b/.github/workflows/unit-tests-macos.yml @@ -50,6 +50,7 @@ jobs: - run: | echo 'conan==${{ matrix.conan-ver }}' > requirements.txt echo 'cmake==${{ matrix.cmake-ver }}' >> requirements.txt + echo 'scipy' >> requirements.txt - uses: actions/setup-python@v4 with: @@ -106,6 +107,21 @@ jobs: - name: Build project run: cmake --build ${{ github.workspace }}/build -j $(nproc) + - run: | + printf 'Package: foo\nVersion: 0.0.1\nLicense: MIT\nDescription: foo\n"' >> DESCRIPTION + printf 'Title: foo\nAuthor: me\nMaintainer: me\nImports: wCorr' >> DESCRIPTION + + - name: Install setup-r action dependencies + run: brew install imagemagick@6 libgit2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: '4.2.0' + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + cache: true + - name: Run unit tests working-directory: ${{ github.workspace }}/build run: | @@ -114,8 +130,6 @@ jobs: --output-on-failure \ --no-tests=error \ --timeout 120 \ - --repeat after-timeout:3 \ - -E '(SciPy)|(wCorr)' \ -j $(nproc) - name: Inspect MoDLE version From eb8d2569ed0b4eaf32f160a50339e6d60d15ce52 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Fri, 17 Jun 2022 21:46:56 +0200 Subject: [PATCH 6/9] Remove --repeat after-timeout from ctest args. Reduce test timeout --- .github/workflows/unit-tests-macos.yml | 11 +++++------ .github/workflows/unit-tests-ubuntu.yml | 12 +++++------- Dockerfile | 1 - 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/.github/workflows/unit-tests-macos.yml b/.github/workflows/unit-tests-macos.yml index 8c41217d..d9d2739f 100644 --- a/.github/workflows/unit-tests-macos.yml +++ b/.github/workflows/unit-tests-macos.yml @@ -125,12 +125,11 @@ jobs: - name: Run unit tests working-directory: ${{ github.workspace }}/build run: | - ctest --test-dir . \ - --schedule-random \ - --output-on-failure \ - --no-tests=error \ - --timeout 120 \ - -j $(nproc) + ctest --test-dir . \ + --schedule-random \ + --output-on-failure \ + --no-tests=error \ + --timeout 60 - name: Inspect MoDLE version run: | diff --git a/.github/workflows/unit-tests-ubuntu.yml b/.github/workflows/unit-tests-ubuntu.yml index f85d78c6..9b7bfe73 100644 --- a/.github/workflows/unit-tests-ubuntu.yml +++ b/.github/workflows/unit-tests-ubuntu.yml @@ -234,7 +234,6 @@ jobs: --output-on-failure \ --no-tests=error \ --timeout 120 \ - --repeat after-timeout:3 \ -j $(nproc) - name: Run integration tests @@ -359,12 +358,11 @@ jobs: - name: Run unit tests working-directory: ${{ github.workspace }}/build run: | - ctest --test-dir . \ - --schedule-random \ - --output-on-failure \ - --no-tests=error \ - --timeout 120 \ - --repeat after-timeout:3 \ + ctest --test-dir . \ + --schedule-random \ + --output-on-failure \ + --no-tests=error \ + --timeout 60 \ -j $(nproc) - name: Run integration tests diff --git a/Dockerfile b/Dockerfile index 4db8802e..0e95d316 100644 --- a/Dockerfile +++ b/Dockerfile @@ -117,7 +117,6 @@ RUN cd "$src_dir/build" \ --output-on-failure \ --no-tests=error \ --timeout 60 \ - --repeat after-timeout:3 \ && rm -rf "$src_dir/test/Testing" ARG FINAL_BASE_IMAGE From 394b7bf4d6f8ea2df13438cca45b50c3a3761c63 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Sat, 18 Jun 2022 13:27:08 +0200 Subject: [PATCH 7/9] Update unit tests relying on R to work on macOS It turns out that R on macOS does not like when an expression is passed directly to R or Rscript. The workaround consists in writing expressions to a temporary file, and use that as script --- test/units/stats/correlation_test.cpp | 38 +++++++++++++++++---------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/test/units/stats/correlation_test.cpp b/test/units/stats/correlation_test.cpp index 375f970a..32409e4f 100644 --- a/test/units/stats/correlation_test.cpp +++ b/test/units/stats/correlation_test.cpp @@ -25,6 +25,11 @@ #include "modle/common/const_map.hpp" #include "modle/common/numeric_utils.hpp" #include "modle/common/random.hpp" // for PRNG_t +#include "modle/test/self_deleting_folder.hpp" + +namespace modle::test { +inline const SelfDeletingFolder testdir{true}; // NOLINT(cert-err58-cpp) +} // namespace modle::test namespace modle::test::stats { using namespace modle::stats; @@ -178,29 +183,32 @@ class ExternalCorrelationRunner { boost::process::opstream _stdin{}; boost::process::child _c{}; + std::filesystem::path _script{}; public: ExternalCorrelationRunner() = delete; explicit ExternalCorrelationRunner(std::string_view method) { - if (absl::StartsWith(method, "weighted_")) { - this->_c = boost::process::child( - boost::process::search_path("Rscript").string(), "--quiet", "-e", - std::string{external_cmds.at(method)}, - boost::process::std_in_stdin, boost::process::std_out> this->_stdout, - boost::process::std_err > this->_stderr); - } else { - this->_c = boost::process::child( - boost::process::search_path("python3").string(), "-c", - std::string{external_cmds.at(method)}, - boost::process::std_in_stdin, boost::process::std_out> this->_stdout, - boost::process::std_err > this->_stderr); - } + _script = testdir() / boost::filesystem::unique_path().string(); + std::ofstream f(_script); + f << external_cmds.at(method); + f.close(); + std::filesystem::permissions(_script, std::filesystem::perms::owner_exec, + std::filesystem::perm_options::add); + + const auto exec = + boost::process::search_path(absl::StartsWith(method, "weighted_") ? "Rscript" : "python3"); + + this->_c = boost::process::child( + exec.string(), _script.string(), + boost::process::std_in_stdin, boost::process::std_out> this->_stdout, + boost::process::std_err > this->_stderr); + assert(this->_c.running()); } ~ExternalCorrelationRunner() noexcept { + std::filesystem::remove(_script); try { - assert(!this->_c.running()); if (!this->_c) { std::ostringstream buff; buff << this->_stderr.rdbuf(); @@ -231,6 +239,7 @@ class ExternalCorrelationRunner { } void read_from_stdout(std::string& buff) { std::getline(this->_stdout, buff); } + [[nodiscard]] std::string read_from_stdout() { std::string buff; this->read_from_stdout(buff); @@ -238,6 +247,7 @@ class ExternalCorrelationRunner { } void read_from_stderr(std::string& buff) { std::getline(this->_stderr, buff); } + [[nodiscard]] std::string read_from_stderr() { std::string buff; this->read_from_stderr(buff); From d6446e771362e6d99bf3f44d05d43553a9c077b9 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Sat, 18 Jun 2022 13:29:39 +0200 Subject: [PATCH 8/9] Minor changes to macOS CI --- .github/workflows/unit-tests-macos.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/unit-tests-macos.yml b/.github/workflows/unit-tests-macos.yml index d9d2739f..2db8d0f7 100644 --- a/.github/workflows/unit-tests-macos.yml +++ b/.github/workflows/unit-tests-macos.yml @@ -47,7 +47,15 @@ jobs: steps: - uses: actions/checkout@v3 - - run: | + - name: Detect number available CPUs + run: | + ncpus=$(python -c 'import multiprocessing as mp; print(mp.cpu_count())') + + echo "CMAKE_BUILD_PARALLEL_LEVEL=$ncpus" >> $GITHUB_ENV + echo "CTEST_PARALLEL_LEVEL=$ncpus" >> $GITHUB_ENV + + - name: Generate requirements.txt for pip + run: | echo 'conan==${{ matrix.conan-ver }}' > requirements.txt echo 'cmake==${{ matrix.cmake-ver }}' >> requirements.txt echo 'scipy' >> requirements.txt @@ -105,20 +113,23 @@ jobs: -B "${{ github.workspace }}/build" - name: Build project - run: cmake --build ${{ github.workspace }}/build -j $(nproc) + run: cmake --build ${{ github.workspace }}/build - - run: | + - name: Generate R package requirement list + run: | printf 'Package: foo\nVersion: 0.0.1\nLicense: MIT\nDescription: foo\n"' >> DESCRIPTION printf 'Title: foo\nAuthor: me\nMaintainer: me\nImports: wCorr' >> DESCRIPTION - name: Install setup-r action dependencies run: brew install imagemagick@6 libgit2 - - uses: r-lib/actions/setup-r@v2 + - name: Setup R + uses: r-lib/actions/setup-r@v2 with: r-version: '4.2.0' - - uses: r-lib/actions/setup-r-dependencies@v2 + - name: Install R packages + uses: r-lib/actions/setup-r-dependencies@v2 with: cache: true From 20b40f4e6b7bd84fe88d0600b771b42d5f0803c8 Mon Sep 17 00:00:00 2001 From: Roberto Rossini <71787608+robomics@users.noreply.github.com> Date: Sat, 18 Jun 2022 14:24:14 +0200 Subject: [PATCH 9/9] Migrate unit tests to Catch2 v3 --- conanfile.py | 2 +- test/CMakeLists.txt | 17 ++----- test/test_main.cpp | 19 -------- test/units/common/cli_utils_test.cpp | 2 +- test/units/common/const_map_test.cpp | 2 +- test/units/common/dna_test.cpp | 2 +- .../contact_matrix/contact_matrix_test.cpp | 22 +++++---- .../interval_tree/interval_tree_test.cpp | 12 ++--- test/units/libmodle_io/bed_parser_test.cpp | 12 ++--- test/units/libmodle_io/bed_tree_test.cpp | 12 ++--- test/units/libmodle_io/compressed_io_test.cpp | 10 ++-- test/units/libmodle_io/cooler_test.cpp | 17 +++---- test/units/libmodle_io/hdf5_test.cpp | 27 ++++++----- .../collision_encoding_test.cpp | 4 +- test/units/simulation_cpu/common.hpp | 2 +- .../simulation_complex_unit_test.cpp | 8 ++-- .../simulation_simple_unit_test.cpp | 16 +++---- .../extrusion_barriers_test.cpp | 10 ++-- test/units/stats/correlation_test.cpp | 47 ++++++++++--------- test/units/stats/correlation_utils_test.cpp | 4 +- test/units/stats/descriptive_test.cpp | 31 ++++++------ test/units/stats/misc_test.cpp | 5 +- test/units/stats/tests_test.cpp | 39 +++++++-------- 23 files changed, 155 insertions(+), 167 deletions(-) delete mode 100644 test/test_main.cpp diff --git a/conanfile.py b/conanfile.py index c768488f..65b4ae1b 100644 --- a/conanfile.py +++ b/conanfile.py @@ -17,7 +17,7 @@ class MoDLE(ConanFile): requires = ["abseil/20211102.0", "boost/1.79.0", "bzip2/1.0.8", - "catch2/2.13.9", + "catch2/3.0.1", "cli11/2.2.0", "concurrentqueue/1.0.3", "cpp-sort/1.13.0", diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4941d881..6b479e55 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -16,8 +16,7 @@ add_executable(test_main) target_sources( test_main - PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test_main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/units/common/cli_utils_test.cpp + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/units/common/cli_utils_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/common/const_map_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/common/dna_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/units/contact_matrix/contact_matrix_test.cpp @@ -66,7 +65,7 @@ target_link_system_libraries( absl::strings Boost::filesystem Boost::headers - Catch2::Catch2 + Catch2::Catch2WithMain fmt::fmt HDF5::HDF5 spdlog::spdlog @@ -84,12 +83,8 @@ catch_discover_tests( " - SHORT" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../ - REPORTER - xml OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Testing/ - OUTPUT_SUFFIX - .xml EXTRA_ARGS --success) @@ -101,12 +96,8 @@ catch_discover_tests( " - MEDIUM" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../ - REPORTER - xml OUTPUT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Testing/ - OUTPUT_SUFFIX - .xml EXTRA_ARGS --success) @@ -118,7 +109,7 @@ catch_discover_tests( " - LONG" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../ - REPORTER - compact # This dramatically speeds up the test suit + OUTPUT_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/Testing/ EXTRA_ARGS --success) diff --git a/test/test_main.cpp b/test/test_main.cpp deleted file mode 100644 index 72a5985b..00000000 --- a/test/test_main.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (C) 2022 Roberto Rossini -// -// SPDX-License-Identifier: MIT - -#define CATCH_CONFIG_MAIN - -// clang-format off -#include "modle/common/suppress_compiler_warnings.hpp" -DISABLE_WARNING_PUSH -DISABLE_WARNING_MAYBE_UNINITIALIZED -#include -DISABLE_WARNING_POP -// clang-format on - -#include "modle/test/self_deleting_folder.hpp" // for SelfDeletingFolder - -namespace modle::test { -[[maybe_unused]] inline const SelfDeletingFolder testdir{true}; // NOLINT(cert-err58-cpp) -} // namespace modle::test diff --git a/test/units/common/cli_utils_test.cpp b/test/units/common/cli_utils_test.cpp index 9097df0c..d03c0c29 100644 --- a/test/units/common/cli_utils_test.cpp +++ b/test/units/common/cli_utils_test.cpp @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -#include // for operator""_catch_sr, AssertionHandler +#include // clang-format off #include "modle/common/suppress_compiler_warnings.hpp" DISABLE_WARNING_PUSH diff --git a/test/units/common/const_map_test.cpp b/test/units/common/const_map_test.cpp index 78281085..aa8657e3 100644 --- a/test/units/common/const_map_test.cpp +++ b/test/units/common/const_map_test.cpp @@ -4,7 +4,7 @@ #include "modle/common/const_map.hpp" -#include +#include #include namespace modle::test::utils { diff --git a/test/units/common/dna_test.cpp b/test/units/common/dna_test.cpp index 36fc6bcb..dbee204c 100644 --- a/test/units/common/dna_test.cpp +++ b/test/units/common/dna_test.cpp @@ -4,7 +4,7 @@ #include "modle/common/dna.hpp" -#include +#include #include "modle/common/common.hpp" diff --git a/test/units/contact_matrix/contact_matrix_test.cpp b/test/units/contact_matrix/contact_matrix_test.cpp index 6dc3dfa8..5c0db577 100644 --- a/test/units/contact_matrix/contact_matrix_test.cpp +++ b/test/units/contact_matrix/contact_matrix_test.cpp @@ -8,7 +8,9 @@ #include // for generate, max #include // for dynamic_bitset, dynamic_bitset<>::ref... #include -#include // for operator""_catch_sr, AssertionHandler +#include +#include +#include #include // for path #include // for runtime_error #include // for string @@ -171,12 +173,14 @@ TEST_CASE("CMatrix in/decrement", "[cmatrix][short]") { if constexpr (utils::ndebug_not_defined()) { CHECK_THROWS_WITH(m.increment(25, 25), - Catch::Contains("Detected an out-of-bound read: attempt to access item at")); + Catch::Matchers::ContainsSubstring( + "Detected an out-of-bound read: attempt to access item at")); CHECK(m.get_n_of_missed_updates() == 1); CHECK(m.get_tot_contacts() == 1); CHECK_THROWS_WITH(m.decrement(25, 25), - Catch::Contains("Detected an out-of-bound read: attempt to access item at")); + Catch::Matchers::ContainsSubstring( + "Detected an out-of-bound read: attempt to access item at")); CHECK(m.get_n_of_missed_updates() == 1); CHECK(m.get_tot_contacts() == 1); } @@ -368,7 +372,7 @@ TEST_CASE("CMatrix blur (SciPy)", "[cmatrix][long]") { for (usize j = 4; j < input_matrix.nrows(); ++j) { for (auto k = j; k < input_matrix.ncols() - 4; ++k) { - CHECK(Approx(reference_matrix.get(j, k)) == blurred_matrix.get(j, k)); + CHECK(Catch::Approx(reference_matrix.get(j, k)) == blurred_matrix.get(j, k)); } } } @@ -408,7 +412,7 @@ TEST_CASE("CMatrix blur parallel (SciPy)", "[cmatrix][long]") { for (usize j = 4; j < input_matrix.nrows(); ++j) { for (auto k = j; k < input_matrix.ncols() - 4; ++k) { - CHECK(Approx(reference_matrix.get(j, k)) == blurred_matrix.get(j, k)); + CHECK(Catch::Approx(reference_matrix.get(j, k)) == blurred_matrix.get(j, k)); } } } @@ -450,8 +454,8 @@ TEST_CASE("CMatrix difference of gaussians (SciPy)", "[cmatrix][long]") { for (usize j = 4; j < input_matrix.nrows(); ++j) { for (auto k = j; k < input_matrix.ncols() - 4; ++k) { - CHECK(Approx(reference_matrix.get(j, k)) == gauss_diff_matrix.get(j, k)); - CHECK(Approx(m1.get(j, k) - m2.get(j, k)) == gauss_diff_matrix.get(j, k)); + CHECK(Catch::Approx(reference_matrix.get(j, k)) == gauss_diff_matrix.get(j, k)); + CHECK(Catch::Approx(m1.get(j, k) - m2.get(j, k)) == gauss_diff_matrix.get(j, k)); } } } @@ -496,8 +500,8 @@ TEST_CASE("CMatrix difference of gaussians - parallel (SciPy)", "[cmatrix][long] for (usize j = 4; j < input_matrix.nrows(); ++j) { for (auto k = j; k < input_matrix.ncols() - 4; ++k) { - CHECK(Approx(reference_matrix.get(j, k)) == gauss_diff_matrix.get(j, k)); - CHECK(Approx(m1.get(j, k) - m2.get(j, k)) == gauss_diff_matrix.get(j, k)); + CHECK(Catch::Approx(reference_matrix.get(j, k)) == gauss_diff_matrix.get(j, k)); + CHECK(Catch::Approx(m1.get(j, k) - m2.get(j, k)) == gauss_diff_matrix.get(j, k)); } } } diff --git a/test/units/interval_tree/interval_tree_test.cpp b/test/units/interval_tree/interval_tree_test.cpp index 9d202a9e..238d6483 100644 --- a/test/units/interval_tree/interval_tree_test.cpp +++ b/test/units/interval_tree/interval_tree_test.cpp @@ -7,12 +7,12 @@ #include // for StrSplit, Splitter, ByAnyChar #include // for format -#include // for max -#include // for AssertionHandler, operator""_catch_sr, SourceLineInfo -#include // for path -#include // for string, basic_string, operator== -#include // for string_view -#include // for vector, allocator +#include // for max +#include +#include // for path +#include // for string, basic_string, operator== +#include // for string_view +#include // for vector, allocator #include "modle/common/numeric_utils.hpp" // for parse_numeric_or_throw #include "modle/compressed_io/compressed_io.hpp" // for Reader diff --git a/test/units/libmodle_io/bed_parser_test.cpp b/test/units/libmodle_io/bed_parser_test.cpp index eca96df7..fe978481 100644 --- a/test/units/libmodle_io/bed_parser_test.cpp +++ b/test/units/libmodle_io/bed_parser_test.cpp @@ -5,12 +5,12 @@ #include // for StrSplit, Splitter #include // for to_string -#include // for sort, max -#include // for AssertionHandler, operator""_catch_sr, SourceLineInfo -#include // for path -#include // for string, basic_string, operator==, char_traits, stoull -#include // for operator!=, basic_string_view, string_view, operator< -#include // for vector +#include // for sort, max +#include +#include // for path +#include // for string, basic_string, operator==, char_traits, stoull +#include // for operator!=, basic_string_view, string_view, operator< +#include // for vector #include "absl/strings/match.h" // for StrContains #include "modle/bed/bed.hpp" // for BED, Parser, formatter<>::format, BED::BED3 diff --git a/test/units/libmodle_io/bed_tree_test.cpp b/test/units/libmodle_io/bed_tree_test.cpp index d117b0f7..1a242e3f 100644 --- a/test/units/libmodle_io/bed_tree_test.cpp +++ b/test/units/libmodle_io/bed_tree_test.cpp @@ -6,12 +6,12 @@ #include // for Span #include // for format -#include // for max, min -#include // for AssertionHandler, operator""_catch_sr, SourceLineInfo -#include // for path -#include // for basic_string, operator==, string -#include // for string_view -#include // for vector +#include // for max, min +#include +#include // for path +#include // for basic_string, operator==, string +#include // for string_view +#include // for vector #include "modle/bed/bed.hpp" // for BED, BED_tree, BED_tree::contains, BED_tree::count_... #include "modle/common/common.hpp" // for usize, u8 diff --git a/test/units/libmodle_io/compressed_io_test.cpp b/test/units/libmodle_io/compressed_io_test.cpp index 8ec6e939..295feb34 100644 --- a/test/units/libmodle_io/compressed_io_test.cpp +++ b/test/units/libmodle_io/compressed_io_test.cpp @@ -4,11 +4,11 @@ #include "modle/compressed_io/compressed_io.hpp" // for Reader -#include // for AssertionHandler, operator""_catch_sr, Source... -#include // for path, operator/ -#include // for ifstream, basic_ios, basic_istream, operator<< -#include // for cerr -#include // for operator==, string, basic_string, getline +#include +#include // for path, operator/ +#include // for ifstream, basic_ios, basic_istream, operator<< +#include // for cerr +#include // for operator==, string, basic_string, getline #include "modle/test/self_deleting_folder.hpp" // for SelfDeletingFolder diff --git a/test/units/libmodle_io/cooler_test.cpp b/test/units/libmodle_io/cooler_test.cpp index 1c91e556..6e51bf27 100644 --- a/test/units/libmodle_io/cooler_test.cpp +++ b/test/units/libmodle_io/cooler_test.cpp @@ -11,13 +11,14 @@ #include // for null_sink_mt #include // for set_default_logger -#include // for max, max_element, transform -#include // for operator""_catch_sr, AssertionHandler, Source... -#include // for exception -#include // for operator/, path -#include // for make_shared, allocator_traits<>::value_type -#include // for runtime_error -#include // for string_view +#include // for max, max_element, transform +#include +#include +#include // for exception +#include // for operator/, path +#include // for make_shared, allocator_traits<>::value_type +#include // for runtime_error +#include // for string_view #include "modle/common/common.hpp" // for u64, u32, usize, i64, u8 #include "modle/common/utils.hpp" // for parse_numeric_or_throw @@ -51,7 +52,7 @@ TEST_CASE("cooler ctor", "[io][cooler][short]") { CHECK(Cooler::validate_file_format(f, Cooler::FLAVOR::COOL)); CHECK_THROWS_WITH(!Cooler::validate_file_format(f, Cooler::FLAVOR::MCOOL, Cooler::IO_MODE::READ_ONLY, 1'000'000), - Catch::Matchers::Contains("Expected format flavor MCOOL, found COOL")); + Catch::Matchers::ContainsSubstring("Expected format flavor MCOOL, found COOL")); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) diff --git a/test/units/libmodle_io/hdf5_test.cpp b/test/units/libmodle_io/hdf5_test.cpp index e4d4b778..89309ddb 100644 --- a/test/units/libmodle_io/hdf5_test.cpp +++ b/test/units/libmodle_io/hdf5_test.cpp @@ -11,14 +11,16 @@ #include // for H5S_UNLIMITED #include // for format -#include // for max -#include // for operator""_catch_sr, AssertionHandler, Source... -#include // for operator/, path -#include // for numeric_limits -#include // for string, basic_string, allocator, operator== -#include // for string_view -#include // for ignore -#include // for vector +#include // for max +#include +#include +#include +#include // for operator/, path +#include // for numeric_limits +#include // for string, basic_string, allocator, operator== +#include // for string_view +#include // for ignore +#include // for vector #include "H5Ppublic.h" // for H5F_ACC_TRUNC, H5T_CSET_ASCII, H5T_STR_NULLPAD #include "modle/common/common.hpp" // for i64, usize @@ -169,11 +171,11 @@ TEST_CASE("check_dataset_type HDF5", "[io][hdf5][short]") { CHECK(!check_dataset_type(str_dataset, H5::PredType::NATIVE_INT64, false)); CHECK_THROWS_WITH(check_dataset_type(int_dataset, H5::PredType::NATIVE_INT), - Catch::Matchers::Contains("incorrect datasize")); + Catch::Matchers::ContainsSubstring("incorrect datasize")); CHECK_THROWS_WITH(check_dataset_type(int_dataset, H5::PredType::NATIVE_FLOAT), Catch::Matchers::EndsWith("incorrect datatype")); CHECK_THROWS_WITH(check_dataset_type(int_dataset, H5::PredType::NATIVE_UINT64), - Catch::Matchers::Contains("incorrect signedness")); + Catch::Matchers::ContainsSubstring("incorrect signedness")); std::filesystem::remove_all(testdir()); if (const auto& p = testdir().parent_path(); std::filesystem::is_empty(p)) { @@ -192,8 +194,9 @@ TEST_CASE("read_write_string HDF5 - long string", "[io][hdf5][short]") { auto dataset = init_test_str_dataset(f); #ifndef NDEBUG - CHECK_THROWS_WITH(write_str(s, dataset, init_str_type(), 0), - Catch::Contains("string does not fit in the receiving dataset")); + CHECK_THROWS_WITH( + write_str(s, dataset, init_str_type(), 0), + Catch::Matchers::ContainsSubstring("string does not fit in the receiving dataset")); #else CHECK(write_str(s, dataset, init_str_type(), 0) == 1); #endif diff --git a/test/units/simulation_cpu/collision_encoding_test.cpp b/test/units/simulation_cpu/collision_encoding_test.cpp index 9e778b83..c88bfb93 100644 --- a/test/units/simulation_cpu/collision_encoding_test.cpp +++ b/test/units/simulation_cpu/collision_encoding_test.cpp @@ -6,7 +6,9 @@ #include -#include // for SourceLineInfo, StringRef, TEST_CASE +#include +#include + namespace modle::test::libmodle { [[maybe_unused]] static std::string event_to_str(const CollisionEvent<> event) { diff --git a/test/units/simulation_cpu/common.hpp b/test/units/simulation_cpu/common.hpp index 686a3aee..ad2e19ec 100644 --- a/test/units/simulation_cpu/common.hpp +++ b/test/units/simulation_cpu/common.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/test/units/simulation_cpu/simulation_complex_unit_test.cpp b/test/units/simulation_cpu/simulation_complex_unit_test.cpp index 117490eb..a703d165 100644 --- a/test/units/simulation_cpu/simulation_complex_unit_test.cpp +++ b/test/units/simulation_cpu/simulation_complex_unit_test.cpp @@ -6,10 +6,10 @@ #include // for dynamic_bitset #include // for assert -#include // for SourceLineInfo, StringRef, TEST_CASE -#include // for allocator, allocator_traits<>::value_... -#include // for string_view -#include // for vector +#include +#include // for allocator, allocator_traits<>::value_... +#include // for string_view +#include // for vector #include "./common.hpp" // for construct_lef, NO_COLLISION, check_si... #include "modle/common/common.hpp" // for bp_t, usize diff --git a/test/units/simulation_cpu/simulation_simple_unit_test.cpp b/test/units/simulation_cpu/simulation_simple_unit_test.cpp index 204f893e..ba4cd74d 100644 --- a/test/units/simulation_cpu/simulation_simple_unit_test.cpp +++ b/test/units/simulation_cpu/simulation_simple_unit_test.cpp @@ -4,14 +4,14 @@ #include // for MakeSpan, Span, MakeConstSpan -#include // for all_of, equal, copy, for_each, gene... -#include // for assert -#include // for AssertionHandler, operator""_catch_sr -#include // for back_insert_iterator, back_inserter -#include // for allocator, allocator_traits<>::valu... -#include // for iota -#include // for string_view -#include // for vector +#include // for all_of, equal, copy, for_each, gene... +#include // for assert +#include +#include // for back_insert_iterator, back_inserter +#include // for allocator, allocator_traits<>::valu... +#include // for iota +#include // for string_view +#include // for vector #include "./common.hpp" // for construct_lef, NO_COLLISION, requir... #include "modle/common/common.hpp" // for usize, bp_t diff --git a/test/units/simulation_internal/extrusion_barriers_test.cpp b/test/units/simulation_internal/extrusion_barriers_test.cpp index d99b7a4d..3f0e0db4 100644 --- a/test/units/simulation_internal/extrusion_barriers_test.cpp +++ b/test/units/simulation_internal/extrusion_barriers_test.cpp @@ -4,7 +4,8 @@ #include "modle/extrusion_barriers.hpp" // for ExtrusionBarrier -#include // for AssertionHandler, operator""_catch_sr +#include +#include #include "modle/common/common.hpp" // for dna::Direction @@ -46,8 +47,8 @@ TEST_CASE("Extrusion barriers - occupancy", "[barriers][simulation][short]") { {stp_inactive1, stp_inactive2}, {State::ACTIVE, State::ACTIVE}}; - CHECK(barriers.occupancy(0) == Approx(occupancy1)); - CHECK(barriers.occupancy(1) == Approx(occupancy2)); + CHECK(barriers.occupancy(0) == Catch::Approx(occupancy1)); + CHECK(barriers.occupancy(1) == Catch::Approx(occupancy2)); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -79,7 +80,8 @@ TEST_CASE("Extrusion barriers - compute_occupancy", "[barriers][simulation][shor stp_active = 0.7; stp_inactive = 0.5; - CHECK(ExtrusionBarrier::compute_occupancy_from_stp(stp_active, stp_inactive) == Approx(0.625)); + CHECK(ExtrusionBarrier::compute_occupancy_from_stp(stp_active, stp_inactive) == + Catch::Approx(0.625)); stp_active = 1.0; stp_inactive = 0.5; diff --git a/test/units/stats/correlation_test.cpp b/test/units/stats/correlation_test.cpp index 32409e4f..31e59576 100644 --- a/test/units/stats/correlation_test.cpp +++ b/test/units/stats/correlation_test.cpp @@ -11,15 +11,16 @@ #include #include -#include // for assert -#include // for Approx, operator==, AssertionHandler, operator... -#include // for exception -#include // for ostream -#include // for random_device -#include // for char_traits -#include // for operator==, operator""sv, basic_string_view -#include // for make_pair -#include // for vector +#include // for assert +#include +#include +#include // for exception +#include // for ostream +#include // for random_device +#include // for char_traits +#include // for operator==, operator""sv, basic_string_view +#include // for make_pair +#include // for vector #include "modle/common/common.hpp" // for u32, usize #include "modle/common/const_map.hpp" @@ -285,8 +286,8 @@ static void run_correlation_test(std::string_view method, usize vector_size, N1 const auto expected_corr = utils::parse_numeric_or_throw(tok_buff.front()); const auto expected_pv = utils::parse_numeric_or_throw(tok_buff.back()); - CHECK(Approx(expected_corr) == corr); - CHECK(Approx(expected_pv) == pv); + CHECK(Catch::Approx(expected_corr) == corr); + CHECK(Catch::Approx(expected_pv) == pv); } runner.signal_end_of_input(); runner.wait(); @@ -304,8 +305,8 @@ TEST_CASE("Corr. test: Pearson wo ties", "[correlation][pearson][short]") { const std::vector v1{17, 86, 60, 77, 47, 3, 70, 87, 88, 92}; const std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const auto [pcc, pv] = Pearson<>{}(v1, v2); - CHECK(Approx(pcc) == -0.033621194725622014); - CHECK(Approx(pv) == 0.926536715854247); + CHECK(Catch::Approx(pcc) == -0.033621194725622014); + CHECK(Catch::Approx(pv) == 0.926536715854247); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -314,8 +315,8 @@ TEST_CASE("Corr. test: Weighted Pearson wo ties", "[correlation][pearson][short] const std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const std::vector w{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; const auto [pcc, pv] = Pearson<>{}(v1, v2, w); - CHECK(Approx(pcc) == 0.1892337717235999250409); - CHECK(Approx(pv) == -1.0); + CHECK(Catch::Approx(pcc) == 0.1892337717235999250409); + CHECK(Catch::Approx(pv) == -1.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -323,8 +324,8 @@ TEST_CASE("Corr. test: Pearson w ties", "[correlation][pearson][short]") { std::vector v1{17, 86, 60, 77, 47, 3, 70, 47, 88, 92}; std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const auto [pcc, pv] = Pearson<>{}(v1, v2); - CHECK(Approx(pcc) == 0.16426413174421572); - CHECK(Approx(pv) == 0.6502118872600098); + CHECK(Catch::Approx(pcc) == 0.16426413174421572); + CHECK(Catch::Approx(pv) == 0.6502118872600098); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -333,8 +334,8 @@ TEST_CASE("Corr. test: Weighted Pearson w ties", "[correlation][pearson][short]" const std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const std::vector w{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}; const auto [pcc, pv] = Pearson<>{}(v1, v2, w); - CHECK(Approx(pcc) == 0.5009581087644285890548); - CHECK(Approx(pv) == -1.0); + CHECK(Catch::Approx(pcc) == 0.5009581087644285890548); + CHECK(Catch::Approx(pv) == -1.0); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -380,8 +381,8 @@ TEST_CASE("Corr. test: Spearman wo ties", "[correlation][spearman][short]") { const std::vector v1{17, 86, 60, 77, 47, 3, 70, 87, 88, 92}; const std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const auto [rho, pv] = Spearman<>{}(v1, v2); - CHECK(Approx(rho) == -0.16363636363636364); - CHECK(Approx(pv) == 0.6514773427962428); + CHECK(Catch::Approx(rho) == -0.16363636363636364); + CHECK(Catch::Approx(pv) == 0.6514773427962428); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -389,8 +390,8 @@ TEST_CASE("Corr. test: Spearman w ties", "[correlation][spearman][short]") { const std::vector v1{17, 86, 60, 77, 47, 3, 70, 47, 88, 92}; const std::vector v2{70, 29, 85, 61, 80, 34, 60, 31, 73, 66}; const auto [rho, pv] = Spearman<>{}(v1, v2); - CHECK(Approx(rho) == 0.024316221747202587); - CHECK(Approx(pv) == 0.9468397049085097); + CHECK(Catch::Approx(rho) == 0.024316221747202587); + CHECK(Catch::Approx(pv) == 0.9468397049085097); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) diff --git a/test/units/stats/correlation_utils_test.cpp b/test/units/stats/correlation_utils_test.cpp index e546bcb8..ddeaaaec 100644 --- a/test/units/stats/correlation_utils_test.cpp +++ b/test/units/stats/correlation_utils_test.cpp @@ -1,8 +1,8 @@ // Copyright (C) 2022 Roberto Rossini // // SPDX-License-Identifier: MIT -#include // for AssertionHandler, operator""_catch_sr, SourceLineInfo -#include // for vector +#include +#include // for vector #include "modle/common/common.hpp" // for u32 #include "modle/stats/correlation.hpp" diff --git a/test/units/stats/descriptive_test.cpp b/test/units/stats/descriptive_test.cpp index b63ad9ad..9f77b941 100644 --- a/test/units/stats/descriptive_test.cpp +++ b/test/units/stats/descriptive_test.cpp @@ -4,10 +4,11 @@ #include "modle/stats/descriptive.hpp" -#include // for transform -#include // for Approx, operator==, AssertionHandler, operator""_catc... -#include // for string_view_literals -#include // for vector +#include // for transform +#include +#include +#include // for string_view_literals +#include // for vector #include "modle/common/common.hpp" // for u8, usize #include "modle/common/utils.hpp" // for identity::operator(), identity @@ -27,7 +28,7 @@ TEST_CASE("Mean", "[stats][short]") { std::transform(v1.begin(), v1.end(), v2.begin(), [](const auto n) { return FP{static_cast(n)}; }); - const auto result = Approx(5.0); + const auto result = Catch::Approx(5.0); CHECK(stats::mean(v1.begin(), v1.end()) == result); CHECK(stats::mean(v2.begin(), v2.end(), [](const auto& fp) { return fp.n; }) == result); @@ -48,7 +49,7 @@ TEST_CASE("Moving average", "[stats][short]") { v1.size() - window_size); for (usize i = 0; i < results.size(); ++i) { - CHECK(results[i] == Approx(output[i])); + CHECK(results[i] == Catch::Approx(output[i])); } output.clear(); @@ -57,13 +58,13 @@ TEST_CASE("Moving average", "[stats][short]") { [](const auto& fp) { return fp.n; }) == v1.size() - window_size); for (usize i = 0; i < results.size(); ++i) { - CHECK(results[i] == Approx(output[i])); + CHECK(results[i] == Catch::Approx(output[i])); } output.clear(); output.resize(1); REQUIRE(stats::moving_average(v1.begin(), v1.end(), output.begin(), v1.size() + 1) == 1); - CHECK(stats::mean(v1.begin(), v1.end()) == Approx(output.front())); + CHECK(stats::mean(v1.begin(), v1.end()) == Catch::Approx(output.front())); } // NOLINTNEXTLINE(readability-function-cognitive-complexity) @@ -73,7 +74,7 @@ TEST_CASE("Sum of squared deviations", "[stats][short]") { std::transform(v1.begin(), v1.end(), v2.begin(), [](const auto n) { return FP{static_cast(n)}; }); - const auto result = Approx(110.0); + const auto result = Catch::Approx(110.0); CHECK(stats::sum_of_squared_deviations(v1.begin(), v1.end()) == result); CHECK(stats::sum_of_squared_deviations(v2.begin(), v2.end(), @@ -87,7 +88,7 @@ TEST_CASE("Variance", "[stats][short]") { std::transform(v1.begin(), v1.end(), v2.begin(), [](const auto n) { return FP{static_cast(n)}; }); - const auto result = Approx(10.0); + const auto result = Catch::Approx(10.0); CHECK(stats::variance(v1.begin(), v1.end()) == result); CHECK(stats::variance(v2.begin(), v2.end(), [](const auto& fp) { return fp.n; }) == result); @@ -100,7 +101,7 @@ TEST_CASE("Standard Deviation", "[stats][short]") { std::transform(v1.begin(), v1.end(), v2.begin(), [](const auto n) { return FP{static_cast(n)}; }); - const auto result = Approx(3.1622776601683795); + const auto result = Catch::Approx(3.1622776601683795); CHECK(stats::standard_dev(v1.begin(), v1.end()) == result); CHECK(stats::standard_dev(v2.begin(), v2.end(), [](const auto& fp) { return fp.n; }) == result); @@ -116,8 +117,8 @@ TEST_CASE("SED", "[stats][short]") { const std::vector weights{0.97302005, 0.05226173, 0.15995629, 0.31495018, 0.95241483, 0.87420081, 0.21360278, 0.0822476, 0.26402032, 0.49666325}; // computed with scipy.spatial.distance.euclidean - const auto result = Approx(154.65977964758991); - const auto result_weighted = Approx(99.94033647108283); + const auto result = Catch::Approx(154.65977964758991); + const auto result_weighted = Catch::Approx(99.94033647108283); CHECK(stats::sed(v1.begin(), v1.end(), v2.begin()) == result); CHECK(stats::weighted_sed(v1.begin(), v1.end(), v2.begin(), weights.begin()) == result_weighted); @@ -134,8 +135,8 @@ TEST_CASE("RMSE", "[stats][short]") { 0.87420081, 0.21360278, 0.0822476, 0.26402032, 0.49666325}; // computed with mean_squared_error from sklearn.metrics - const auto result = Approx(48.90771661061378); - const auto result_weighted = Approx(47.73515476405454); + const auto result = Catch::Approx(48.90771661061378); + const auto result_weighted = Catch::Approx(47.73515476405454); CHECK(stats::rmse(v1.begin(), v1.end(), v2.begin()) == result); CHECK(stats::weighted_rmse(v1.begin(), v1.end(), v2.begin(), weights.begin()) == result_weighted); diff --git a/test/units/stats/misc_test.cpp b/test/units/stats/misc_test.cpp index fbfa20fe..0ac93f14 100644 --- a/test/units/stats/misc_test.cpp +++ b/test/units/stats/misc_test.cpp @@ -8,7 +8,8 @@ #include #include -#include +#include +#include #include #include "modle/common/numeric_utils.hpp" @@ -60,7 +61,7 @@ TEST_CASE("Gaussian kernel (SciPy)", "[stats][short]") { const auto kernel = compute_gauss_kernel(size, sigma); REQUIRE(ref_kernel.size() == kernel.size()); for (usize i = 0; i < kernel.size(); ++i) { - CHECK(Approx(ref_kernel[i]) == kernel[i]); + CHECK(Catch::Approx(ref_kernel[i]) == kernel[i]); } } } diff --git a/test/units/stats/tests_test.cpp b/test/units/stats/tests_test.cpp index 558511d6..c618076c 100644 --- a/test/units/stats/tests_test.cpp +++ b/test/units/stats/tests_test.cpp @@ -19,20 +19,21 @@ #include // for opstream, ipstream #include // for search_path #include // for assert -#include // for Approx, operator==, Ass... -#include // for trunc -#include // for condition_variable -#include // for path -#include // for make_shared -#include // for mutex, unique_lock -#include // for basic_ostream::flush -#include // for random_device -#include // for overflow_error -#include // for string, getline -#include // for string_view, basic_stri... -#include // for thread -#include // for make_pair -#include // for vector +#include +#include +#include // for trunc +#include // for condition_variable +#include // for path +#include // for make_shared +#include // for mutex, unique_lock +#include // for basic_ostream::flush +#include // for random_device +#include // for overflow_error +#include // for string, getline +#include // for string_view, basic_stri... +#include // for thread +#include // for make_pair +#include // for vector #include "modle/common/common.hpp" // for i64, usize #include "modle/common/const_map.hpp" @@ -116,8 +117,8 @@ TEST_CASE("Binom test - two-sided", "[stats][short]") { const auto n1 = 143; const auto n2 = 220; - const auto result_two_sided_n1 = Approx(2.1004568301653535e-06); - const auto result_two_sided_n2 = Approx(0.20009222902827126); + const auto result_two_sided_n1 = Catch::Approx(2.1004568301653535e-06); + const auto result_two_sided_n2 = Catch::Approx(0.20009222902827126); CHECK(stats::binomial_test(k, n1) == result_two_sided_n1); CHECK(stats::binomial_test(k, n2) == result_two_sided_n2); @@ -128,7 +129,7 @@ TEST_CASE("Binom test - less", "[stats][short]") { const auto k = 100; const auto n = 143; - const auto result_less = Approx(0.9999995628468261); + const auto result_less = Catch::Approx(0.9999995628468261); CHECK(stats::binomial_test(k, n) == result_less); } @@ -138,7 +139,7 @@ TEST_CASE("Binom test - greater", "[stats][short]") { const auto k = 100; const auto n = 143; - const auto result_greater = Approx(1.0502284150826767e-06); + const auto result_greater = Catch::Approx(1.0502284150826767e-06); CHECK(stats::binomial_test(k, n) == result_greater); } @@ -180,7 +181,7 @@ TEST_CASE("Binom test - two-sided randomized (SciPy)", "[stats][long]") { output_data_ready = false; } const auto pv = stats::binomial_test(k, n); - CHECK(Approx(pv).margin(1.0e-250) == pv_py); + CHECK(Catch::Approx(pv).margin(1.0e-250) == pv_py); } k = 0; n = 0;