From 991967761d3a6fe46809ced125f006df88f3a942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jules=20P=C3=A9nuchot?= Date: Mon, 6 Oct 2025 17:03:54 +0200 Subject: [PATCH] Added Ubuntu 24.04 tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jules Pénuchot See merge request oss/rotgen!33 --- .gitlab-ci.yml | 189 +++++++++++++++++++++++++--------- ci-cd/ci-setup.sh | 16 +++ ci-cd/test-wrapper.sh | 14 +++ docker-here.sh | 8 ++ test/unit/block/basic_api.cpp | 22 ++-- test/unit/block/extract.cpp | 147 ++++++++++++-------------- 6 files changed, 254 insertions(+), 142 deletions(-) create mode 100755 ci-cd/ci-setup.sh create mode 100755 ci-cd/test-wrapper.sh create mode 100755 docker-here.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 656ec43..da88d5f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,61 +1,152 @@ # https://docs.gitlab.com/ee/ci/yaml/ -.native-job: &native-job +.run-tests: &run-tests + stage: test + script: + - echo -e "\e[0Ksection_start:`date +%s`:build-tests[collapsed=true]\r\e[0KBuilding tests for preset $CMAKE_PRESET" + - cmake --preset $CMAKE_PRESET + - cmake --build --preset $CMAKE_PRESET + - cmake --build --preset $CMAKE_PRESET --target rotgen-test + - echo -e "\e[0Ksection_end:`date +%s`:build-tests\r\e[0K" + - echo -e "\e[0Ksection_start:`date +%s`:run-tests[collapsed=false]\r\e[0KRunning tests for preset $CMAKE_PRESET" + - ./ci-cd/test-wrapper.sh + - echo -e "\e[0Ksection_end:`date +%s`:run-tests\r\e[0K" + +.test-native: &test-native tags: ["shell"] + <<: *run-tests + +.test-ubuntu2404: &test-ubuntu2404 + tags: [docker] + image: ubuntu:24.04 + cache: + paths: [/var/cache/apt/, /var/lib/apt/lists/] + before_script: + - echo -e "\e[0Ksection_start:`date +%s`:ci-setup[collapsed=true]\r\e[0KInstall packages" + - ./ci-cd/ci-setup.sh + - echo -e "\e[0Ksection_end:`date +%s`:ci-setup\r\e[0K" + + <<: *run-tests stages: - test -test-debug: - <<: *native-job - stage: test - script: - - cmake --preset debug -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset debug - - cmake --build --preset debug --target rotgen-test - - cd build/debug && ctest --output-on-failure --verbose +# Native (Clang) -test-debug-static: - <<: *native-job - stage: test - script: - - cmake --preset debug-static -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset debug-static - - cmake --build --preset debug-static --target rotgen-test - - cd build/debug-static && ctest --output-on-failure --verbose +test-native-debug: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: debug -test-debug-et: - <<: *native-job - stage: test - script: - - cmake --preset debug-et -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset debug-et - - cmake --build --preset debug-et --target rotgen-test - - cd build/debug-et && ctest --output-on-failure --verbose +test-native-debug-static: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: debug-static -test-release: - <<: *native-job - stage: test - script: - - cmake --preset release -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset release - - cmake --build --preset release --target rotgen-test - - cd build/release && ctest --output-on-failure --verbose +test-native-debug-et: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: debug-et -test-release-static: - <<: *native-job - stage: test - script: - - cmake --preset release-static -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset release-static - - cmake --build --preset release-static --target rotgen-test - - cd build/release-static && ctest --output-on-failure --verbose +test-native-release: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: release -test-release-et: - <<: *native-job - stage: test - script: - - cmake --preset release-et -DCMAKE_CXX_COMPILER=clang++ - - cmake --build --preset release-et - - cmake --build --preset release-et --target rotgen-test - - cd build/release-et && ctest --output-on-failure --verbose +test-native-release-static: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: release-static + +test-native-release-et: + <<: *test-native + variables: + CXX: clang++ + CMAKE_PRESET: release-et + +# Ubuntu 24.04 (Clang 14) + +test-ubuntu-clang14-debug: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: debug + +test-ubuntu-clang14-debug-static: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: debug-static + +test-ubuntu-clang14-debug-et: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: debug-et + +test-ubuntu-clang14-release: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: release + +test-ubuntu-clang14-release-static: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: release-static + +test-ubuntu-clang14-release-et: + <<: *test-ubuntu2404 + variables: + CXX: clang++-14 + CXXFLAGS: --stdlib=libc++ + CMAKE_PRESET: release-et + +# Ubuntu 24.04 (GCC) + +test-ubuntu-gcc-debug: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: debug + +test-ubuntu-gcc-debug-static: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: debug-static + +test-ubuntu-gcc-debug-et: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: debug-et + +test-ubuntu-gcc-release: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: release + +test-ubuntu-gcc-release-static: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: release-static + +test-ubuntu-gcc-release-et: + <<: *test-ubuntu2404 + variables: + CXX: g++ + CMAKE_PRESET: release-et diff --git a/ci-cd/ci-setup.sh b/ci-cd/ci-setup.sh new file mode 100755 index 0000000..09bd842 --- /dev/null +++ b/ci-cd/ci-setup.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +export DEBIAN_FRONTEND="noninteractive" + +apt update -y +apt upgrade -y +apt install -y \ + automake \ + build-essential \ + clang-14 \ + cmake \ + gdb \ + libc++-14-dev \ + libc++abi-14-dev \ + libeigen3-dev \ + ninja-build diff --git a/ci-cd/test-wrapper.sh b/ci-cd/test-wrapper.sh new file mode 100755 index 0000000..04cd666 --- /dev/null +++ b/ci-cd/test-wrapper.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +cd build/$CMAKE_PRESET + +ctest --output-on-failure +CTEST_EXIT_CODE=$? + +# If the program fails, show the backtracs +if [ $CTEST_EXIT_CODE -ne '0' ]; then + gdb -ex run -ex bt --args ctest --output-on-failure +fi + +# Forward exit code +exit $CTEST_EXIT_CODE diff --git a/docker-here.sh b/docker-here.sh new file mode 100755 index 0000000..9af38cf --- /dev/null +++ b/docker-here.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Helper script to facilitate debugging in a Dockerized environment + +docker container run \ + -v $(pwd):$(pwd) -w $(pwd) -i -t \ + ubuntu:24.04 \ + /bin/bash diff --git a/test/unit/block/basic_api.cpp b/test/unit/block/basic_api.cpp index 0b89dc9..0a5015f 100644 --- a/test/unit/block/basic_api.cpp +++ b/test/unit/block/basic_api.cpp @@ -8,19 +8,23 @@ #include "unit/tests.hpp" #include +// Helper: fill matrix from raw data +// NB: This function must not be turned into a lambda, otherwise +// `test-ubuntu-gcc-release` will not pass and the CI will fail. +// This is likely due to a compilation bug from GCC 13.3.0. +void fill(auto &m, int r, int c, auto data[]) { + for (int k = 0; k < r * c; ++k) + m.data()[k] = data[k]; +} + TTS_CASE_TPL("Function size", rotgen::tests::types) (tts::type>) { T data[] = {1,2,3,4,5,6,7,8,9,10,11,12}; - // Helper: fill matrix from raw data - auto fill = [&](auto& m, int r, int c) { - for(int k = 0; k < r * c; ++k) m.data()[k] = data[k]; - }; - // 1x12 dynamic block at (0,0) rotgen::matrix dm(1,12); - fill(dm,1,12); + fill(dm,1,12,data); auto b1 = rotgen::block(dm, 0,0,1,12); TTS_EQUAL(b1.rows(), rotgen::Index{1}); TTS_EQUAL(b1.cols(), rotgen::Index{12}); @@ -32,7 +36,7 @@ TTS_CASE_TPL("Function size", rotgen::tests::types) // 3x2 dynamic block at (1,4) in 4x6 rotgen::matrix dm2(4,6); - fill(dm2,4,6); + fill(dm2,4,6,data); auto b3 = rotgen::block(dm2, 1,4,3,2); TTS_EQUAL(b3.rows(), rotgen::Index{3}); TTS_EQUAL(b3.cols(), rotgen::Index{2}); @@ -40,7 +44,7 @@ TTS_CASE_TPL("Function size", rotgen::tests::types) // 3x4 static block rotgen::matrix sm; - fill(sm,3,4); + fill(sm,3,4,data); auto b4 = rotgen::block(sm, 0,0); TTS_EQUAL(b4.rows(), rotgen::Index{3}); TTS_EQUAL(b4.cols(), rotgen::Index{4}); @@ -48,7 +52,7 @@ TTS_CASE_TPL("Function size", rotgen::tests::types) // 6x2 static block rotgen::matrix sm2; - fill(sm2,6,2); + fill(sm2,6,2,data); auto b5 = rotgen::block(sm2, 0,0); TTS_EQUAL(b5.rows(), rotgen::Index{6}); TTS_EQUAL(b5.cols(), rotgen::Index{2}); diff --git a/test/unit/block/extract.cpp b/test/unit/block/extract.cpp index dc1e7c5..318caa9 100644 --- a/test/unit/block/extract.cpp +++ b/test/unit/block/extract.cpp @@ -44,17 +44,17 @@ MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case void validate_block_behavior(MatrixType& matrix, BlockType& block, - rotgen::Index i0, rotgen::Index j0, - rotgen::Index ni, rotgen::Index nj) + rotgen::Index block_i, rotgen::Index block_j, + rotgen::Index block_m, rotgen::Index block_n) { using T = typename MatrixType::value_type; - TTS_EQUAL(block.rows(), ni); - TTS_EQUAL(block.cols(), nj); - TTS_EQUAL(block.size(), ni * nj); + TTS_EQUAL(block.rows(), block_m); + TTS_EQUAL(block.cols(), block_n); + TTS_EQUAL(block.size(), block_m * block_n); // test block values - for_each_element(block, [&](auto i, auto j, auto val) { - TTS_EQUAL(val, matrix(i0 + i, j0 + j)); + for_each_element(block, [&](auto i, auto j, auto block_val) { + TTS_EQUAL(block_val, matrix(block_i + i, block_j + j)); }); // test aliasing if non immutable @@ -67,15 +67,15 @@ void validate_block_behavior(MatrixType& matrix, BlockType& block, value = 1; for_each_element(block, [&](auto i, auto j, auto&) { - TTS_EQUAL(matrix(i0 + i, j0 + j), value++); + TTS_EQUAL(matrix(block_i + i, block_j + j), value++); }); for_each_element(block, [&](auto i, auto j, auto&) { - matrix(i0 + i, j0 + j) = T(42); + matrix(block_i + i, block_j + j) = T(42); }); - for_each_element(block, [&](auto&, auto&, auto val) { - TTS_EQUAL(val, T(42)); + for_each_element(block, [&](auto&, auto&, auto block_val) { + TTS_EQUAL(block_val, T(42)); }); } } @@ -347,83 +347,62 @@ TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types) ); }; -TTS_CASE_TPL("Check vector-only extractions", rotgen::tests::types) -( tts::type< tts::types> ) -{ - auto refs = []() - { - if constexpr(O::value == rotgen::RowMajor) - { - using mat_t = rotgen::matrix; - mat_t m(1,11); +TTS_CASE_TPL("Check vector-only extractions", + rotgen::tests::types)( + tts::type>) { + auto run_case = [](auto &&matrix, auto &&block, int i_offset, int j_offset, + int ni, int nj, auto const &rows_ct, auto const &cols_ct) { + using block_t = std::remove_reference_t; - for(rotgen::Index i=0;i<11;++i) m(i) = 1 + i; + TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); + TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); - return std::make_tuple( m, - std::make_tuple - ( - std::make_tuple(head(m, 1), 0, 0, 1, 1, 1, rotgen::Dynamic) - , std::make_tuple(head(m, 5), 0, 0, 1, 5, 1, rotgen::Dynamic) - , std::make_tuple(head(m,11), 0, 0, 1,11, 1, rotgen::Dynamic) - , std::make_tuple(head<1>(m), 0, 0, 1, 1, 1, 1) - , std::make_tuple(head<4>(m), 0, 0, 1, 4, 1, 4) - , std::make_tuple(head<9>(m), 0, 0, 1, 9, 1, 9) - , std::make_tuple(tail(m, 1), 0,10, 1, 1, 1, rotgen::Dynamic) - , std::make_tuple(tail(m, 5), 0, 6, 1, 5, 1, rotgen::Dynamic) - , std::make_tuple(tail(m,11), 0, 0, 1,11, 1, rotgen::Dynamic) - , std::make_tuple(tail<1>(m), 0,10, 1, 1, 1, 1) - , std::make_tuple(tail<4>(m), 0, 7, 1, 4, 1, 4) - , std::make_tuple(tail<9>(m), 0, 2, 1, 9, 1, 9) - , std::make_tuple(segment(m,0,11), 0, 0, 1, 11, 1, rotgen::Dynamic) - , std::make_tuple(segment(m,0, 7), 0, 0, 1, 7, 1, rotgen::Dynamic) - , std::make_tuple(segment(m,5, 6), 0, 5, 1, 6, 1, rotgen::Dynamic) - , std::make_tuple(segment<11>(m,0), 0, 0, 1, 11, 1, 11) - , std::make_tuple(segment< 7>(m,0), 0, 0, 1, 7, 1, 7) - , std::make_tuple(segment< 6>(m,5), 0, 5, 1, 6, 1, 6) - ) - ); - } - else - { - using mat_t = rotgen::matrix; - mat_t m(11,1); + validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); + }; - for(rotgen::Index i=0;i<11;++i) m(i) = 1 + i; + if constexpr (O::value == rotgen::RowMajor) { + using mat_t = rotgen::matrix; + mat_t m(1, 11); - return std::make_tuple( m, - std::make_tuple - ( - std::make_tuple(head(m, 1), 0, 0, 1, 1, rotgen::Dynamic, 1) - , std::make_tuple(head(m, 5), 0, 0, 5, 1, rotgen::Dynamic, 1) - , std::make_tuple(head(m,11), 0, 0,11, 1, rotgen::Dynamic, 1) - , std::make_tuple(head<1>(m), 0, 0, 1, 1, 1, 1) - , std::make_tuple(head<4>(m), 0, 0, 4, 1, 4, 1) - , std::make_tuple(head<9>(m), 0, 0, 9, 1, 9, 1) - , std::make_tuple(tail(m, 1),10, 0, 1, 1, rotgen::Dynamic, 1) - , std::make_tuple(tail(m, 5), 6, 0, 5, 1, rotgen::Dynamic, 1) - , std::make_tuple(tail(m,11), 0, 0,11, 1, rotgen::Dynamic, 1) - , std::make_tuple(tail<1>(m),10, 0, 1, 1, 1, 1) - , std::make_tuple(tail<4>(m), 7, 0, 4, 1, 4, 1) - , std::make_tuple(tail<9>(m), 2, 0, 9, 1, 9, 1) - ) - ); - } - }(); + for (rotgen::Index i = 0; i < 11; ++i) + m(i) = 1 + i; - auto matrix = std::get<0>(refs); - auto blocks = std::get<1>(refs); + run_case(m, head(m, 1), 0, 0, 1, 1, 1, rotgen::Dynamic); + run_case(m, head(m, 5), 0, 0, 1, 5, 1, rotgen::Dynamic); + run_case(m, head(m, 11), 0, 0, 1, 11, 1, rotgen::Dynamic); + run_case(m, head<1>(m), 0, 0, 1, 1, 1, 1); + run_case(m, head<4>(m), 0, 0, 1, 4, 1, 4); + run_case(m, head<9>(m), 0, 0, 1, 9, 1, 9); + run_case(m, tail(m, 1), 0, 10, 1, 1, 1, rotgen::Dynamic); + run_case(m, tail(m, 5), 0, 6, 1, 5, 1, rotgen::Dynamic); + run_case(m, tail(m, 11), 0, 0, 1, 11, 1, rotgen::Dynamic); + run_case(m, tail<1>(m), 0, 10, 1, 1, 1, 1); + run_case(m, tail<4>(m), 0, 7, 1, 4, 1, 4); + run_case(m, tail<9>(m), 0, 2, 1, 9, 1, 9); + run_case(m, segment(m, 0, 11), 0, 0, 1, 11, 1, rotgen::Dynamic); + run_case(m, segment(m, 0, 7), 0, 0, 1, 7, 1, rotgen::Dynamic); + run_case(m, segment(m, 5, 6), 0, 5, 1, 6, 1, rotgen::Dynamic); + run_case(m, segment<11>(m, 0), 0, 0, 1, 11, 1, 11); + run_case(m, segment<7>(m, 0), 0, 0, 1, 7, 1, 7); + run_case(m, segment<6>(m, 5), 0, 5, 1, 6, 1, 6); + } else { + using mat_t = rotgen::matrix; + mat_t m(11, 1); - std::apply([&](auto&&... block_entries) - { - (([&] - { - auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct] = block_entries; - using block_t = std::remove_reference_t; + for (rotgen::Index i = 0; i < 11; ++i) + m(i) = 1 + i; - TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); - TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); - - validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); - })(), ...); - }, blocks); -}; \ No newline at end of file + run_case(m, head(m, 1), 0, 0, 1, 1, rotgen::Dynamic, 1); + run_case(m, head(m, 5), 0, 0, 5, 1, rotgen::Dynamic, 1); + run_case(m, head(m, 11), 0, 0, 11, 1, rotgen::Dynamic, 1); + run_case(m, head<1>(m), 0, 0, 1, 1, 1, 1); + run_case(m, head<4>(m), 0, 0, 4, 1, 4, 1); + run_case(m, head<9>(m), 0, 0, 9, 1, 9, 1); + run_case(m, tail(m, 1), 10, 0, 1, 1, rotgen::Dynamic, 1); + run_case(m, tail(m, 5), 6, 0, 5, 1, rotgen::Dynamic, 1); + run_case(m, tail(m, 11), 0, 0, 11, 1, rotgen::Dynamic, 1); + run_case(m, tail<1>(m), 10, 0, 1, 1, 1, 1); + run_case(m, tail<4>(m), 7, 0, 4, 1, 4, 1); + run_case(m, tail<9>(m), 2, 0, 9, 1, 9, 1); + } +};