From a5d29aa27f4dd3faa62054ebfd675d373876aa5b Mon Sep 17 00:00:00 2001 From: pravirkr Date: Wed, 24 Apr 2024 22:36:21 +0300 Subject: [PATCH] tests added --- .github/workflows/ci.yml | 8 +- CMakeLists.txt | 2 +- pyproject.toml | 2 +- tests/cpp/CMakeLists.txt | 2 +- tests/cpp/fdmt_t.cpp | 34 ++++++- tests/cpp/fdmt_utils_t.cpp | 192 ++++++++++++++++++++++++++++++++++++ tests/python/test_libdmt.py | 22 +++++ 7 files changed, 251 insertions(+), 11 deletions(-) create mode 100644 tests/cpp/fdmt_utils_t.cpp create mode 100644 tests/python/test_libdmt.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b45970e..30506e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,11 +37,13 @@ jobs: - name: Build run: > cmake --build ${{ steps.strings.outputs.build-output-dir }} - --config ${{ matrix.build_type }} --verbose + --config ${{ matrix.build_type }} - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} - run: ctest -C ${{ matrix.build_type }} --output-on-failure + run: > + ctest --build-config ${{ matrix.build_type }} --output-on-failure + --test-dir ${{ steps.strings.outputs.build-output-dir }}/tests/cpp python: runs-on: ${{ matrix.os }} @@ -49,7 +51,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - python-version: ['3.9', '3.10', '3.11'] + python-version: ['3.9', '3.10'] steps: - uses: actions/checkout@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f77caa..bc0e4a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ if(BUILD_PYTHON) endif() # Build tests if(BUILD_TESTING) - add_subdirectory(tests) + add_subdirectory(tests/cpp) endif() # Install targets and configuration diff --git a/pyproject.toml b/pyproject.toml index 7ec705c..a7b10e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ omit = ["tests/*", "*__init__.py", "docs/*"] show_missing = true ignore_errors = true #fail_under = 85 -exclude_also = ["*__init__.py", "docs/*", "raise NotImplementedError", "@jit"] +exclude_lines = ['raise AssertionError', 'raise NotImplementedError'] [tool.coverage.path] source = "src/dmt" diff --git a/tests/cpp/CMakeLists.txt b/tests/cpp/CMakeLists.txt index 68e8ab6..1324521 100644 --- a/tests/cpp/CMakeLists.txt +++ b/tests/cpp/CMakeLists.txt @@ -12,7 +12,7 @@ file(GLOB TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) add_executable(${TARGET_TESTS} ${TEST_SOURCES}) target_include_directories(${TARGET_TESTS} PUBLIC ${CMAKE_SOURCE_DIR}/include) target_include_directories(${TARGET_TESTS} PRIVATE ${CMAKE_SOURCE_DIR}/lib) -target_link_libraries(${TARGET_TESTS} PRIVATE ${LIBRARY_NAME} Catch2::Catch2withMain) +target_link_libraries(${TARGET_TESTS} PRIVATE ${LIBRARY_NAME} Catch2::Catch2WithMain) include(Catch) include(CTest) diff --git a/tests/cpp/fdmt_t.cpp b/tests/cpp/fdmt_t.cpp index 469424e..51a7643 100644 --- a/tests/cpp/fdmt_t.cpp +++ b/tests/cpp/fdmt_t.cpp @@ -1,10 +1,34 @@ #include +#include #include -TEST_CASE("make_vector", "[make_vector]") { - REQUIRE(make_vector(0) == std::vector{}); - REQUIRE(make_vector(5) == std::vector{0, 1, 2, 3, 4}); - REQUIRE(make_vector(3) == std::vector{0, 1, 2}); - REQUIRE(make_vector(4) == std::vector{0, 1, 2, 3}); +TEST_CASE("FDMT class tests", "[fdmt]") { + SECTION("Test case 1: Constructor and getter methods") { + FDMT fdmt(1000.0F, 1500.0F, 500, 1024, 0.001F, 512, 1, 0); + REQUIRE(fdmt.get_df() == 1.0F); + REQUIRE(fdmt.get_correction() == 0.5F); + REQUIRE(fdmt.get_dt_grid_final().size() == 513); + REQUIRE(fdmt.get_niters() == 9); + REQUIRE(fdmt.get_plan().df_top.size() == 10); + REQUIRE(fdmt.get_plan().df_bot.size() == 10); + REQUIRE(fdmt.get_plan().state_shape.size() == 10); + REQUIRE(fdmt.get_plan().sub_plan.size() == 10); + } + SECTION("Test case 2: initialise method") { + FDMT fdmt(1000.0F, 1500.0F, 500, 1024, 0.001F, 512, 1, 0); + std::vector waterfall(500 * 1024, 1.0f); + const size_t dt_init_size = fdmt.get_dt_grid_init().size(); + std::vector state(500 * 1024 * dt_init_size, 0.0f); + REQUIRE_NOTHROW(fdmt.initialise(waterfall.data(), state.data())); + } + + SECTION("Test case 3: execute method") { + FDMT fdmt(1000.0F, 1500.0F, 500, 1024, 0.001F, 512, 1, 0); + std::vector waterfall(500 * 1024, 1.0f); + const size_t dt_final_size = fdmt.get_dt_grid_final().size(); + std::vector dmt(dt_final_size * 1024, 0.0f); + REQUIRE_NOTHROW(fdmt.execute(waterfall.data(), waterfall.size(), + dmt.data(), dmt.size())); + } } diff --git a/tests/cpp/fdmt_utils_t.cpp b/tests/cpp/fdmt_utils_t.cpp new file mode 100644 index 0000000..5060ed3 --- /dev/null +++ b/tests/cpp/fdmt_utils_t.cpp @@ -0,0 +1,192 @@ +#include + +#include + +TEST_CASE("cff", "[fdmt_utils]") { + REQUIRE(fdmt::cff(1000.0F, 1500.0F, 1000.0F, 1500.0F) == 1.0F); + REQUIRE(fdmt::cff(1500.0F, 1000.0F, 1500.0F, 1000.0F) == 1.0F); + REQUIRE(fdmt::cff(1000.0F, 1000.0F, 1000.0F, 1500.0F) == 0.0F); +} + +TEST_CASE("calculate_dt_sub", "[fdmt_utils]") { + REQUIRE(fdmt::calculate_dt_sub(1000.0F, 1500.0F, 1000.0F, 1500.0F, 100) + == 100); + REQUIRE(fdmt::calculate_dt_sub(1000.0F, 1500.0F, 1000.0F, 1500.0F, 0) == 0); +} + +TEST_CASE("calculate_dt_grid_sub", "[fdmt_utils]") { + SECTION("Test case 1: only dt_max") { + const size_t dt_max = 512; + const size_t dt_step = 1; + const size_t dt_min = 0; + auto dt_grid = fdmt::calculate_dt_grid_sub( + 1000.0F, 1500.0F, 1000.0F, 1500.0F, dt_max, dt_step, dt_min); + REQUIRE(dt_grid.size() == dt_max - dt_min + 1); + REQUIRE(dt_grid[0] == dt_min); + REQUIRE(dt_grid[512] == dt_max); + } + SECTION("Test case 2: dt_max and dt_min") { + const size_t dt_max = 512; + const size_t dt_step = 1; + const size_t dt_min = 100; + auto dt_grid = fdmt::calculate_dt_grid_sub( + 1000.0F, 1500.0F, 1000.0F, 1500.0F, dt_max, dt_step, dt_min); + REQUIRE(dt_grid.size() == dt_max - dt_min + 1); + REQUIRE(dt_grid[0] == dt_min); + REQUIRE(dt_grid[412] == dt_max); + } +} + +TEST_CASE("add_offset_kernel", "[fdmt_utils]") { + SECTION("Test case 1: Valid input and output vectors") { + std::vector arr1 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + std::vector arr2 = {6.0f, 7.0f, 8.0f}; + std::vector arr_out(8, 0.0f); + size_t offset = 2; + REQUIRE_NOTHROW(fdmt::add_offset_kernel(arr1.data(), arr1.size(), + arr2.data(), arr_out.data(), + arr_out.size(), offset)); + std::vector expected_output + = {1.0f, 2.0f, 9.0f, 11.0f, 13.0f, 0.0f, 0.0f, 0.0f}; + REQUIRE(arr_out == expected_output); + } + SECTION("Test case 2: Output size less than input size") { + std::vector arr1 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + std::vector arr2 = {6.0f, 7.0f, 8.0f}; + std::vector arr_out(4, 0.0f); + size_t offset = 2; + REQUIRE_THROWS_AS(fdmt::add_offset_kernel(arr1.data(), arr1.size(), + arr2.data(), arr_out.data(), + arr_out.size(), offset), + std::runtime_error); + } + + SECTION("Test case 3: Offset greater than input size") { + std::vector arr1 = {1.0f, 2.0f, 3.0f}; + std::vector arr2 = {4.0f, 5.0f}; + std::vector arr_out(5, 0.0f); + size_t offset = 4; + REQUIRE_THROWS_AS(fdmt::add_offset_kernel(arr1.data(), arr1.size(), + arr2.data(), arr_out.data(), + arr_out.size(), offset), + std::runtime_error); + } + SECTION("Test case 4: Empty input vectors") { + std::vector arr1; + std::vector arr2; + std::vector arr_out(3, 0.0f); + size_t offset = 0; + REQUIRE_THROWS_AS(fdmt::add_offset_kernel(arr1.data(), arr1.size(), + arr2.data(), arr_out.data(), + arr_out.size(), offset), + std::runtime_error); + } +} + +TEST_CASE("copy_kernel", "[fdmt_utils]") { + SECTION("Test case 1: Valid input and output vectors") { + std::vector arr1 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + std::vector arr_out(10, 0.0f); + ; + REQUIRE_NOTHROW(fdmt::copy_kernel(arr1.data(), arr1.size(), + arr_out.data(), arr_out.size())); + for (size_t i = 0; i < arr1.size(); ++i) { + REQUIRE(arr_out[i] == arr1[i]); + } + for (size_t i = arr1.size(); i < arr_out.size(); ++i) { + REQUIRE(arr_out[i] == 0.0f); + } + } + SECTION("Test case 2: Output size less than input size") { + std::vector arr1 = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; + std::vector arr_out(3, 0.0f); + REQUIRE_THROWS_AS(fdmt::copy_kernel(arr1.data(), arr1.size(), + arr_out.data(), arr_out.size()), + std::runtime_error); + } + SECTION("Test case 4: Empty input vector") { + std::vector arr1; + std::vector arr_out(5, 0.0f); + REQUIRE_NOTHROW(fdmt::copy_kernel(arr1.data(), arr1.size(), + arr_out.data(), arr_out.size())); + for (size_t i = 0; i < arr_out.size(); ++i) { + REQUIRE(arr_out[i] == 0.0f); + } + } +} + +TEST_CASE("find_closest_index", "[fdmt_utils]") { + SECTION("Test case 1: Empty array") { + std::vector arr_sorted; + REQUIRE_THROWS_AS(fdmt::find_closest_index(arr_sorted, 10), + std::runtime_error); + } + + SECTION("Test case 2: Array with one element - exact match") { + std::vector arr_sorted{10}; + size_t val = 10; + size_t expected = 0; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION("Test case 3: Array with one element - closest match") { + std::vector arr_sorted{10}; + size_t val = 15; + size_t expected = 0; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION("Test case 4: Array with multiple elements - exact match") { + std::vector arr_sorted{10, 20, 30, 40, 50}; + size_t val = 30; + size_t expected = 2; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION( + "Test case 5: Array with multiple elements - closest match (lower)") { + std::vector arr_sorted{10, 20, 30, 40, 50}; + size_t val = 24; + size_t expected = 1; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION( + "Test case 6: Array with multiple elements - closest match (upper)") { + std::vector arr_sorted{10, 20, 30, 40, 50}; + size_t val = 26; + size_t expected = 2; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION("Test case 7: Array with multiple elements - value smaller than " + "all elements") { + std::vector arr_sorted{10, 20, 30, 40, 50}; + size_t val = 5; + size_t expected = 0; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION("Test case 8: Array with multiple elements - value larger than all " + "elements") { + std::vector arr_sorted{10, 20, 30, 40, 50}; + size_t val = 60; + size_t expected = 4; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } + + SECTION("Test case 9: Array with multiple elements - duplicate values") { + std::vector arr_sorted{10, 20, 20, 30, 40, 50}; + size_t val = 20; + size_t expected = 1; + size_t result = fdmt::find_closest_index(arr_sorted, val); + REQUIRE(result == expected); + } +} \ No newline at end of file diff --git a/tests/python/test_libdmt.py b/tests/python/test_libdmt.py new file mode 100644 index 0000000..c57202b --- /dev/null +++ b/tests/python/test_libdmt.py @@ -0,0 +1,22 @@ +import numpy as np +from dmt import libdmt + + +class TestFDMT: + def test_initialise_ones(self) -> None: + nchans = 500 + nsamples = 1024 + dt_max = 512 + thefdmt = libdmt.FDMT(1000, 1500, nchans, nsamples, 0.001, dt_max) + waterfall = np.ones((nchans, nsamples), dtype=np.float32) + thefdmt_init = thefdmt.initialise(waterfall) + np.testing.assert_equal( + thefdmt_init.shape, + (nchans, thefdmt.dt_grid_init.size, nsamples), + ) + """ + np.testing.assert_equal( + thefdmt_init, + np.ones((nchans, thefdmt.dt_grid_init.size, nsamples), dtype=np.float32), + ) + """