From 14acf1aa28218d7754b8cfbac532653fd30a126b Mon Sep 17 00:00:00 2001
From: Pradipta Samanta <samanta@dkrz.de>
Date: Sun, 23 Feb 2025 14:47:17 +0100
Subject: [PATCH] added unit-tests for c++ codes using googletest

---
 test/CMakeLists.txt         |  3 +-
 test/c/CMakeLists.txt       | 30 +++++++++++++++
 test/c/main.cpp             | 14 +++++++
 test/c/test_tdma_solver.cpp | 77 +++++++++++++++++++++++++++++++++++++
 4 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 test/c/CMakeLists.txt
 create mode 100644 test/c/main.cpp
 create mode 100644 test/c/test_tdma_solver.cpp

diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c8fa8e2..2a5f5df 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -9,4 +9,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # ---------------------------------------------------------------
 
-add_subdirectory(fortran)
+# add_subdirectory(fortran)
+add_subdirectory(c)
diff --git a/test/c/CMakeLists.txt b/test/c/CMakeLists.txt
new file mode 100644
index 0000000..be1af9e
--- /dev/null
+++ b/test/c/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Fetch GoogleTest via FetchContent
+include(FetchContent)
+FetchContent_Declare(
+  googletest
+  URL https://github.com/google/googletest/archive/refs/tags/release-1.12.1.zip
+)
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest)
+
+# Find Kokkos (or use your existing Kokkos installation)
+# find_package(Kokkos REQUIRED)
+
+set(SOURCES
+  main.cpp
+  test_tdma_solver.cpp
+)
+# Create the test executable from your test files, including main.cpp.
+add_executable(iconmath_test_c ${SOURCES})
+
+# Link the test executable with GoogleTest and Kokkos.
+target_link_libraries(iconmath_test_c
+  PUBLIC
+    iconmath-support
+  PRIVATE
+    gtest_main
+    Kokkos::kokkos
+)
+
+include(GoogleTest)
+gtest_discover_tests(iconmath_test_c)
diff --git a/test/c/main.cpp b/test/c/main.cpp
new file mode 100644
index 0000000..2df720d
--- /dev/null
+++ b/test/c/main.cpp
@@ -0,0 +1,14 @@
+#include <Kokkos_Core.hpp>
+#include <gtest/gtest.h>
+
+int main(int argc, char** argv) {
+  // Initialize Kokkos before any tests run.
+  Kokkos::initialize(argc, argv);
+  
+  ::testing::InitGoogleTest(&argc, argv);
+  int result = RUN_ALL_TESTS();
+  
+  // Finalize Kokkos after all tests have completed.
+  Kokkos::finalize();
+  return result;
+}
diff --git a/test/c/test_tdma_solver.cpp b/test/c/test_tdma_solver.cpp
new file mode 100644
index 0000000..7c3c3a8
--- /dev/null
+++ b/test/c/test_tdma_solver.cpp
@@ -0,0 +1,77 @@
+#include <gtest/gtest.h>
+#include <vector>
+#include <algorithm>
+#include "mo_math_utilities.hpp"
+
+// Helper function to compute the 1D index for column-major storage.
+inline int idx(int i, int j, int nrows) {
+  return i + j * nrows;
+}
+
+// Test fixture for the TDMA solver tests.
+class TDMASolverTestFixture : public ::testing::Test {
+protected:
+  const int n = 10;             // Matrix dimension.
+  std::vector<double> a;        // Input matrix a.
+  std::vector<double> b;        // Input matrix b.
+  std::vector<double> c;        // Input matrix c.
+  std::vector<double> d;        // Input matrix d.
+  std::vector<double> x;        // Output matrix.
+
+  TDMASolverTestFixture()
+      : a(n * n), b(n * n), c(n * n), d(n * n), x(n * n, 0.0) {}
+
+  // SetUp is run before each test.
+  void SetUp() override {
+    // Fill arrays in column-major order.
+    for (int j = 0; j < n; j++) {
+      for (int i = 0; i < n; i++) {
+        double value = (i + 1) + (j + 1);
+        a[idx(i, j, n)] = 1.0 * value;
+        b[idx(i, j, n)] = 2.0 * value;
+        c[idx(i, j, n)] = 1.0 * value;
+        d[idx(i, j, n)] = 1.0 * value;
+      }
+    }
+    // Clear the output vector.
+    std::fill(x.begin(), x.end(), 0.0);
+  }
+};
+
+TEST_F(TDMASolverTestFixture, FullTest) {
+  // Call the solver over the full range:
+  tdma_solver_vec_double(a.data(), b.data(), c.data(), d.data(),
+                         0, n, 0, n, n, n, x.data());
+
+  // Compute the sum of all elements in the output matrix.
+  double sum = 0.0;
+  for (int j = 0; j < n; j++) {
+    for (int i = 0; i < n; i++) {
+      sum += x[idx(i, j, n)];
+    }
+  }
+
+  // Expected reference sum
+  double sum_ref = 27.2727272727272769;
+  double tol = 1e-13;
+  EXPECT_NEAR(sum, sum_ref, tol);
+}
+
+TEST_F(TDMASolverTestFixture, PartialTest) {
+  // Call the solver for a partial region:
+  // For C++: slev = 1, elev = n-1, startidx = 1, endidx = n-1.
+  tdma_solver_vec_double(a.data(), b.data(), c.data(), d.data(),
+                         1, n - 1, 1, n - 1, n, n, x.data());
+
+  // Compute the sum over a region
+  double sum = 0.0;
+  for (int j = 1; j < n - 1; j++) {
+    for (int i = 1; i < n - 1; i++) {
+      sum += x[idx(i, j, n)];
+    }
+  }
+
+  double sum_ref = 17.7777777777777679;
+  double tol = 1e-13;
+  EXPECT_NEAR(sum, sum_ref, tol);
+}
-- 
GitLab