From 6b8b0495560bc6a4df8e1bc495a81e1bff0d992b Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 21:02:19 -0600 Subject: [PATCH 01/12] Work towards merging coverage.yml and tests.yml --- .github/workflows/coverage.yml | 50 ++++++++++++++--- .github/workflows/tests.yml | 56 ++++++++++++++++--- CMakeLists.txt | 50 +++++++++++------ codecov.yml | 4 ++ .../Autonomy-Dictionary.txt | 1 + tests/Integration/main.cc | 28 ---------- tests/{Unit => }/main.cc | 14 ++--- 7 files changed, 134 insertions(+), 69 deletions(-) delete mode 100644 tests/Integration/main.cc rename tests/{Unit => }/main.cc (68%) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 85e049725..2c27fc988 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -59,15 +59,45 @@ jobs: cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS_MODE=ON -DBUILD_CODE_COVERAGE=ON -DBUILD_VERBOSE_MODE=ON make -j8 - - name: Test + - name: Run Tests run: | cd /opt/Autonomy_Software/build - ctest --output-on-failure -T Test -T Coverage - ctest --output-on-failure --output-junit Test.xml - gcovr --root .. --xml-pretty --output Coverage.xml - lcov -c -d . -o coverage.info - - name: Upload coverage to Codecov + ctest --output-on-failure -T Test -T Coverage -R UnitTest + ctest --output-on-failure --output-junit UnitTests.xml + gcovr --root .. --xml-pretty --output UnitCoverage.xml + lcov -c -d . -o unit_coverage.info + + ctest --output-on-failure -T Test -T Coverage -R IntegrationTest + ctest --output-on-failure --output-junit IntegrationTests.xml + gcovr --root .. --xml-pretty --output IntegrationCoverage.xml + lcov -c -d . -o integration_coverage.info + + - name: Upload Unit Test Coverage to Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software + verbose: true + plugin: gcov + directory: /opt/Autonomy_Software/build + file: /opt/Autonomy_Software/build/UnitCoverage.xml + flags: unit_tests + + - name: Upload Unit Test Results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software/build + verbose: true + directory: /opt/Autonomy_Software/build/ + file: UnitTests.xml + flags: unit_tests + + - name: Upload Integration Test Coverage to Codecov uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -76,9 +106,10 @@ jobs: verbose: true plugin: gcov directory: /opt/Autonomy_Software/build - file: /opt/Autonomy_Software/build/Coverage.xml + file: /opt/Autonomy_Software/build/IntegrationCoverage.xml + flags: integration_tests - - name: Upload test results to Codecov + - name: Upload Integration Test Results to Codecov if: ${{ !cancelled() }} uses: codecov/test-results-action@v1 with: @@ -87,7 +118,8 @@ jobs: working-directory: /opt/Autonomy_Software/build verbose: true directory: /opt/Autonomy_Software/build/ - file: Test.xml + file: IntegrationTests.xml + flags: integration_tests - name: Cleanup Action Environment if: always() diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 36365c2b5..1216ea86b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: Unit and Integration Tests +name: Unit and Integration Tests with Coverage Reports on: pull_request: @@ -31,6 +31,7 @@ jobs: uses: actions/checkout@v4 with: submodules: recursive + ref: ${{ github.event.pull_request.head.sha }} - name: Fix Dubious Ownership run: git config --global --add safe.directory /opt/Autonomy_Software @@ -45,14 +46,15 @@ jobs: cd /opt/Autonomy_Software/ git fetch --force --recurse-submodules branch=${{ steps.extract_branch.outputs.branch }} - echo $branch - git reset --hard origin/$branch - git checkout $branch - git pull --ff-only + echo ${{ github.event.pull_request.head.sha }} + git reset --hard ${{ github.event.pull_request.head.sha }} + git checkout ${{ github.event.pull_request.head.sha }} + # git pull --ff-only git submodule update --force --recursive --init git config --global --add safe.directory /opt/Autonomy_Software/external - name: Build and Run Tests if they exist + id: build-and-test run: | DIRECTORY="/opt/Autonomy_Software/tests/${{ matrix.type }}/src" @@ -65,23 +67,61 @@ jobs: if [ -d "build" ]; then rm -Rf build; fi mkdir build cd build - cmake -DBUILD_TESTS_MODE=ON .. - make + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS_MODE=ON -DBUILD_CODE_COVERAGE=ON -DBUILD_VERBOSE_MODE=ON + make -j8 # Check if the built test file exists TEST_BINARY="/opt/Autonomy_Software/build/Autonomy_Software_${{ matrix.type }}Tests" if [ -f "$TEST_BINARY" ]; then cd /opt/Autonomy_Software/build ./Autonomy_Software_${{ matrix.type }}Tests + + ctest --output-on-failure -T Test -T Coverage -R ${{ matrix.type }}Test + ctest --output-on-failure --output-junit ${{ matrix.type }}Tests.xml + gcovr --root .. --xml-pretty --output ${{ matrix.type }}Coverage.xml + lcov -c -d . -o ${{ matrix.type }}Coverage.info + + echo "tests_exist=true" >> $GITHUB_OUTPUT + echo "test_type=$(echo ${{ matrix.type }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT else echo "No ${{ matrix.type }} Tests Exist." fi - else + echo "tests_exist=false" >> $GITHUB_OUTPUT echo "The directory $DIRECTORY does not exist. Skipping the rest of the GitHub Action." exit 0 fi + - name: Check Test Existence + run: | + echo "Tests Exist: ${{ steps.build-and-test.outputs.tests_exist }}" + echo "Test Type: ${{ steps.build-and-test.outputs.test_type }}" + + - name: Upload ${{ matrix.type }} Test Coverage to Codecov + if: ${{ steps.build-and-test.outputs.tests_exist == 'true' }} + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software + verbose: true + plugin: gcov + directory: /opt/Autonomy_Software/build + file: /opt/Autonomy_Software/build/${{ matrix.type }}Coverage.xml + flags: ${{ steps.build-and-test.outputs.test_type }}_tests + + - name: Upload ${{ matrix.type }} Test Results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software/build + verbose: true + directory: /opt/Autonomy_Software/build/ + file: ${{ matrix.type }}Tests.xml + flags: ${{ steps.build-and-test.outputs.test_type }}_tests + - name: Cleanup Action Environment if: always() run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index b3b7705f1..f6bb99f18 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ option(BUILD_VERBOSE_MODE "Enable Verbose Makefile" OFF) option(BUILD_INSTALL_MODE "Enable Install Mode" OFF) ## Enable or Disable Tests Mode -option(BUILD_TESTS_MODE "Enable Tests Mode" OFF) +option(BUILD_TESTS_MODE "Enable Tests Mode" ON) ## Enable or Disable Examples Mode option(BUILD_EXAMPLES_MODE "Enable Examples Mode" OFF) @@ -77,18 +77,6 @@ if (BUILD_CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fprofile-arcs -ftest-coverage --coverage") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") - - add_custom_target(run_coverage ALL - COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure - COMMAND gcovr --root ${CMAKE_SOURCE_DIR} --xml-pretty --output Coverage.xml - COMMAND lcov -c -d . -o coverage.info - WORKING_DIRECTORY ${CMAKE_BINARY_DIR} - COMMENT "Running tests and generating coverage reports..." - VERBATIM - ) - - # Ensure dependencies for the run_coverage target. Tests must be built first. - add_dependencies(run_coverage ${EXE_NAME}_UnitTests ${EXE_NAME}_IntegrationTests) else() message("-- [ ]: Code Coverage: Disabled") endif() @@ -343,11 +331,12 @@ endif() ## Tests Mode if (BUILD_TESTS_MODE) - file(GLOB_RECURSE UnitTests_SRC CONFIGURE_DEPENDS "tests/Unit/*.cc") - file(GLOB_RECURSE IntegrationTests_SRC CONFIGURE_DEPENDS "tests/Integration/*.cc") + file(GLOB_RECURSE UnitTests_SRC CONFIGURE_DEPENDS "tests/Unit/src/*.cc") + file(GLOB_RECURSE IntegrationTests_SRC CONFIGURE_DEPENDS "tests/Integration/src/*.cc") file(GLOB_RECURSE Algorithms_SRC CONFIGURE_DEPENDS "src/algorithms/*.cpp") file(GLOB_RECURSE Drivers_SRC CONFIGURE_DEPENDS "src/drivers/*.cpp") file(GLOB_RECURSE Vision_SRC CONFIGURE_DEPENDS "src/vision/*.cpp") + file(GLOB Runner_SRC CONFIGURE_DEPENDS "src/tests/main.cc") file(GLOB Network_SRC CONFIGURE_DEPENDS "src/AutonomyNetworking.cpp") file(GLOB Logging_SRC CONFIGURE_DEPENDS "src/AutonomyLogging.cpp") file(GLOB Globals_SRC CONFIGURE_DEPENDS "src/AutonomyGlobals.cpp") @@ -356,9 +345,13 @@ if (BUILD_TESTS_MODE) list(LENGTH IntegrationTests_SRC IntegrationTests_LEN) if (UnitTests_LEN GREATER 0) - add_executable(${EXE_NAME}_UnitTests ${UnitTests_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) + add_executable(${EXE_NAME}_UnitTests ${UnitTests_SRC} ${Runner_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) target_link_libraries(${EXE_NAME}_UnitTests GTest::gtest GTest::gtest_main ${AUTONOMY_LIBRARIES}) - add_test(Unit_Tests ${EXE_NAME}_UnitTests) + + foreach(test_file ${UnitTests_SRC}) + get_filename_component(test_name ${test_file} NAME_WE) + add_test(NAME ${test_name}_UnitTest COMMAND ${EXE_NAME}_UnitTests --gtest_filter=${test_name}Test.*) + endforeach() else() message("No Unit Tests!") endif() @@ -370,6 +363,29 @@ if (BUILD_TESTS_MODE) else() message("No Integration Tests!") endif() + + if (BUILD_CODE_COVERAGE) + add_custom_target(run_coverage ALL + COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure + COMMAND gcovr --root ${CMAKE_SOURCE_DIR} --xml-pretty --output Coverage.xml + COMMAND lcov -c -d . -o coverage.info + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running tests and generating coverage reports..." + VERBATIM + ) + + # Ensure dependencies for the run_coverage target. Tests must be built first. + if (UnitTests_LEN GREATER 0 AND IntegrationTests_LEN GREATER 0) + add_dependencies(run_coverage ${EXE_NAME}_UnitTests ${EXE_NAME}_IntegrationTests) + elseif (UnitTests_LEN GREATER 0) + add_dependencies(run_coverage ${EXE_NAME}_UnitTests) + elseif (IntegrationTests_LEN GREATER 0) + add_dependencies(run_coverage ${EXE_NAME}_IntegrationTests) + else() + message("No Tests to Run! run_coverage target will not be created.") + set_target_properties(run_coverage PROPERTIES EXCLUDE_FROM_ALL TRUE) + endif() + endif() endif() #################################################################################################################### diff --git a/codecov.yml b/codecov.yml index 65760f2f5..d4ba735f7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,9 +6,13 @@ coverage: project: default: target: auto + threshold: 1% patch: default: target: auto + informational: true + threshold: 1% + carryforward: true changes: false ignore: diff --git a/data/Custom_Dictionaries/Autonomy-Dictionary.txt b/data/Custom_Dictionaries/Autonomy-Dictionary.txt index fb1037b9c..53bb3f3fa 100644 --- a/data/Custom_Dictionaries/Autonomy-Dictionary.txt +++ b/data/Custom_Dictionaries/Autonomy-Dictionary.txt @@ -39,6 +39,7 @@ bytem byteswap CAFFE CALIB +carryforward CELLVOLTAGE charconv chromaprint diff --git a/tests/Integration/main.cc b/tests/Integration/main.cc deleted file mode 100644 index 95c4c053b..000000000 --- a/tests/Integration/main.cc +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** - * @brief Main integration test file. Calls for all Integration Tests to be executed. - * - * @file main.cc - * @author Eli Byrd (edbgkk@mst.edu) - * @date 2023-07-24 - * - * @copyright Copyright Mars Rover Design Team 2023 - All Rights Reserved - ******************************************************************************/ - -/// \cond -#include - -/// \endcond - -/****************************************************************************** - * @brief Integration Tests - Main Function - * - * @return int - Integration Tests Exit Status - * - * @author Eli Byrd (edbgkk@mst.edu) - * @date 2023-07-24 - ******************************************************************************/ -int main() -{ - ::testing::InitGoogleTest(); - return RUN_ALL_TESTS(); -} diff --git a/tests/Unit/main.cc b/tests/main.cc similarity index 68% rename from tests/Unit/main.cc rename to tests/main.cc index 8122f906d..9a9649c0c 100644 --- a/tests/Unit/main.cc +++ b/tests/main.cc @@ -1,5 +1,5 @@ /****************************************************************************** - * @brief Main unit test file. Calls for all Unit Tests to be executed. + * @brief Main test file. Acts as a runner for all Unit and Integration Tests. * * @file main.cc * @author Eli Byrd (edbgkk@mst.edu) @@ -8,8 +8,8 @@ * @copyright Copyright Mars Rover Design Team 2023 - All Rights Reserved ******************************************************************************/ -#include "../../src/AutonomyConstants.h" -#include "../../src/AutonomyLogging.h" +#include "../src/AutonomyConstants.h" +#include "../src/AutonomyLogging.h" /// \cond #include @@ -17,19 +17,19 @@ /// \endcond /****************************************************************************** - * @brief Unit Tests - Main Function + * @brief Unit/Integration Tests Runner - Main Function * - * @return int - Unit Tests Exit Status + * @return int - Unit/Integration Tests Exit Status * * @author Eli Byrd (edbgkk@mst.edu) * @date 2023-07-24 ******************************************************************************/ -int main() +int main(int argc, char** argv) { // Setup logging. logging::InitializeLoggers(constants::LOGGING_OUTPUT_PATH_ABSOLUTE); // Initialize tests. - testing::InitGoogleTest(); + testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } From cb2ae6c7ec835c9da47a25d3011da609b4a8857f Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 22:27:05 -0600 Subject: [PATCH 02/12] Fix Extra "/" in Logging Path --- src/AutonomyLogging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AutonomyLogging.cpp b/src/AutonomyLogging.cpp index a902d75cc..5567881e4 100644 --- a/src/AutonomyLogging.cpp +++ b/src/AutonomyLogging.cpp @@ -78,7 +78,7 @@ namespace logging // Assemble filepath string. std::filesystem::path szFilePath; std::filesystem::path szFilename; - szFilePath = szLoggingOutputPath + "/"; // Main location for all recordings. + szFilePath = szLoggingOutputPath; // Main location for all recordings. szFilePath += g_szProgramStartTimeString + "/"; // Folder for each program run. szFilename = "console_output"; // Base file name. From b879ed7b7beebe589f62030dae2f10aef92264a9 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 22:27:11 -0600 Subject: [PATCH 03/12] Updates to CMake --- CMakeLists.txt | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f6bb99f18..6a2e2d35c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ option(BUILD_VERBOSE_MODE "Enable Verbose Makefile" OFF) option(BUILD_INSTALL_MODE "Enable Install Mode" OFF) ## Enable or Disable Tests Mode -option(BUILD_TESTS_MODE "Enable Tests Mode" ON) +option(BUILD_TESTS_MODE "Enable Tests Mode" OFF) ## Enable or Disable Examples Mode option(BUILD_EXAMPLES_MODE "Enable Examples Mode" OFF) @@ -331,35 +331,42 @@ endif() ## Tests Mode if (BUILD_TESTS_MODE) - file(GLOB_RECURSE UnitTests_SRC CONFIGURE_DEPENDS "tests/Unit/src/*.cc") - file(GLOB_RECURSE IntegrationTests_SRC CONFIGURE_DEPENDS "tests/Integration/src/*.cc") + ## Find Unit and Integration Tests + file(GLOB_RECURSE UTests_SRC CONFIGURE_DEPENDS "tests/Unit/src/*.cc") + file(GLOB_RECURSE ITests_SRC CONFIGURE_DEPENDS "tests/Integration/src/*.cc") + file(GLOB Runner_SRC CONFIGURE_DEPENDS "tests/main.cc") + + ## Find Source Files Required for Tests file(GLOB_RECURSE Algorithms_SRC CONFIGURE_DEPENDS "src/algorithms/*.cpp") file(GLOB_RECURSE Drivers_SRC CONFIGURE_DEPENDS "src/drivers/*.cpp") file(GLOB_RECURSE Vision_SRC CONFIGURE_DEPENDS "src/vision/*.cpp") - file(GLOB Runner_SRC CONFIGURE_DEPENDS "src/tests/main.cc") file(GLOB Network_SRC CONFIGURE_DEPENDS "src/AutonomyNetworking.cpp") file(GLOB Logging_SRC CONFIGURE_DEPENDS "src/AutonomyLogging.cpp") file(GLOB Globals_SRC CONFIGURE_DEPENDS "src/AutonomyGlobals.cpp") - list(LENGTH UnitTests_SRC UnitTests_LEN) - list(LENGTH IntegrationTests_SRC IntegrationTests_LEN) + list(LENGTH UTests_SRC UnitTests_LEN) + list(LENGTH ITests_SRC IntegrationTests_LEN) if (UnitTests_LEN GREATER 0) - add_executable(${EXE_NAME}_UnitTests ${UnitTests_SRC} ${Runner_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) + add_executable(${EXE_NAME}_UnitTests ${Runner_SRC} ${UTests_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) target_link_libraries(${EXE_NAME}_UnitTests GTest::gtest GTest::gtest_main ${AUTONOMY_LIBRARIES}) - foreach(test_file ${UnitTests_SRC}) + foreach(test_file ${UTests_SRC}) get_filename_component(test_name ${test_file} NAME_WE) - add_test(NAME ${test_name}_UnitTest COMMAND ${EXE_NAME}_UnitTests --gtest_filter=${test_name}Test.*) + add_test(NAME UTest_${test_name} COMMAND ${EXE_NAME}_UnitTests --gtest_filter=${test_name}Test.*) endforeach() else() message("No Unit Tests!") endif() if (IntegrationTests_LEN GREATER 0) - add_executable(${EXE_NAME}_IntegrationTests ${IntegrationTests_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) + add_executable(${EXE_NAME}_IntegrationTests ${Runner_SRC} ${ITests_SRC} ${Algorithms_SRC} ${Drivers_SRC} ${Vision_SRC} ${Network_SRC} ${Logging_SRC} ${Globals_SRC}) target_link_libraries(${EXE_NAME}_IntegrationTests GTest::gtest GTest::gtest_main ${AUTONOMY_LIBRARIES}) - add_test(Integration_Tests ${EXE_NAME}_IntegrationTests) + + foreach(test_file ${ITests_SRC}) + get_filename_component(test_name ${test_file} NAME_WE) + add_test(NAME ITest_${test_name} COMMAND ${EXE_NAME}_IntegrationTests --gtest_filter=${test_name}Test.*) + endforeach() else() message("No Integration Tests!") endif() From f9dafecc1405c0e7e98905e3e0688f613f4b6234 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 22:46:19 -0600 Subject: [PATCH 04/12] Unseparate Tests and Coverage Reports --- .github/workflows/coverage.yml | 46 ++++++++------------------- .github/workflows/tests.yml | 58 ++++++---------------------------- 2 files changed, 23 insertions(+), 81 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 2c27fc988..bd5552b60 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -63,29 +63,23 @@ jobs: run: | cd /opt/Autonomy_Software/build - ctest --output-on-failure -T Test -T Coverage -R UnitTest - ctest --output-on-failure --output-junit UnitTests.xml - gcovr --root .. --xml-pretty --output UnitCoverage.xml - lcov -c -d . -o unit_coverage.info + ctest --output-on-failure -T Test -T Coverage -R UTest --output-junit UTests.xml + ctest --output-on-failure -T Test -T Coverage -R ITest --output-junit ITests.xml + gcovr --root .. --xml-pretty --output AllCoverage.xml - ctest --output-on-failure -T Test -T Coverage -R IntegrationTest - ctest --output-on-failure --output-junit IntegrationTests.xml - gcovr --root .. --xml-pretty --output IntegrationCoverage.xml - lcov -c -d . -o integration_coverage.info - - - name: Upload Unit Test Coverage to Codecov - uses: codecov/codecov-action@v4 + - name: Upload Unit Test Results to Codecov + if: ${{ !cancelled() }} + uses: codecov/test-results-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software/build verbose: true - plugin: gcov - directory: /opt/Autonomy_Software/build - file: /opt/Autonomy_Software/build/UnitCoverage.xml + directory: /opt/Autonomy_Software/build/ + file: UTests.xml flags: unit_tests - - name: Upload Unit Test Results to Codecov + - name: Upload Integration Test Results to Codecov if: ${{ !cancelled() }} uses: codecov/test-results-action@v1 with: @@ -94,8 +88,8 @@ jobs: working-directory: /opt/Autonomy_Software/build verbose: true directory: /opt/Autonomy_Software/build/ - file: UnitTests.xml - flags: unit_tests + file: ITests.xml + flags: integration_tests - name: Upload Integration Test Coverage to Codecov uses: codecov/codecov-action@v4 @@ -106,20 +100,8 @@ jobs: verbose: true plugin: gcov directory: /opt/Autonomy_Software/build - file: /opt/Autonomy_Software/build/IntegrationCoverage.xml - flags: integration_tests - - - name: Upload Integration Test Results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software/build - verbose: true - directory: /opt/Autonomy_Software/build/ - file: IntegrationTests.xml - flags: integration_tests + file: /opt/Autonomy_Software/build/AllCoverage.xml + flags: unit_tests, integration_tests - name: Cleanup Action Environment if: always() diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1216ea86b..f6cc29b6a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,4 +1,4 @@ -name: Unit and Integration Tests with Coverage Reports +name: Unit and Integration Tests on: pull_request: @@ -31,7 +31,6 @@ jobs: uses: actions/checkout@v4 with: submodules: recursive - ref: ${{ github.event.pull_request.head.sha }} - name: Fix Dubious Ownership run: git config --global --add safe.directory /opt/Autonomy_Software @@ -46,15 +45,14 @@ jobs: cd /opt/Autonomy_Software/ git fetch --force --recurse-submodules branch=${{ steps.extract_branch.outputs.branch }} - echo ${{ github.event.pull_request.head.sha }} - git reset --hard ${{ github.event.pull_request.head.sha }} - git checkout ${{ github.event.pull_request.head.sha }} - # git pull --ff-only + echo $branch + git reset --hard origin/$branch + git checkout $branch + git pull --ff-only git submodule update --force --recursive --init git config --global --add safe.directory /opt/Autonomy_Software/external - name: Build and Run Tests if they exist - id: build-and-test run: | DIRECTORY="/opt/Autonomy_Software/tests/${{ matrix.type }}/src" @@ -67,61 +65,23 @@ jobs: if [ -d "build" ]; then rm -Rf build; fi mkdir build cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS_MODE=ON -DBUILD_CODE_COVERAGE=ON -DBUILD_VERBOSE_MODE=ON - make -j8 + cmake -DBUILD_TESTS_MODE=ON .. + make # Check if the built test file exists TEST_BINARY="/opt/Autonomy_Software/build/Autonomy_Software_${{ matrix.type }}Tests" if [ -f "$TEST_BINARY" ]; then cd /opt/Autonomy_Software/build ./Autonomy_Software_${{ matrix.type }}Tests - - ctest --output-on-failure -T Test -T Coverage -R ${{ matrix.type }}Test - ctest --output-on-failure --output-junit ${{ matrix.type }}Tests.xml - gcovr --root .. --xml-pretty --output ${{ matrix.type }}Coverage.xml - lcov -c -d . -o ${{ matrix.type }}Coverage.info - - echo "tests_exist=true" >> $GITHUB_OUTPUT - echo "test_type=$(echo ${{ matrix.type }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT else echo "No ${{ matrix.type }} Tests Exist." fi + else - echo "tests_exist=false" >> $GITHUB_OUTPUT echo "The directory $DIRECTORY does not exist. Skipping the rest of the GitHub Action." exit 0 fi - - name: Check Test Existence - run: | - echo "Tests Exist: ${{ steps.build-and-test.outputs.tests_exist }}" - echo "Test Type: ${{ steps.build-and-test.outputs.test_type }}" - - - name: Upload ${{ matrix.type }} Test Coverage to Codecov - if: ${{ steps.build-and-test.outputs.tests_exist == 'true' }} - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software - verbose: true - plugin: gcov - directory: /opt/Autonomy_Software/build - file: /opt/Autonomy_Software/build/${{ matrix.type }}Coverage.xml - flags: ${{ steps.build-and-test.outputs.test_type }}_tests - - - name: Upload ${{ matrix.type }} Test Results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software/build - verbose: true - directory: /opt/Autonomy_Software/build/ - file: ${{ matrix.type }}Tests.xml - flags: ${{ steps.build-and-test.outputs.test_type }}_tests - - name: Cleanup Action Environment if: always() run: | @@ -206,4 +166,4 @@ jobs: if: always() run: | cd /opt - rm -rf /opt/Autonomy_Software + rm -rf /opt/Autonomy_Software \ No newline at end of file From d243c8713dd3b680178a864996bf49fd5995dd19 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 22:59:00 -0600 Subject: [PATCH 05/12] Try to fix confused codecov.io --- .github/workflows/coverage.yml | 2 +- codecov.yml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index bd5552b60..ae986532c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -91,7 +91,7 @@ jobs: file: ITests.xml flags: integration_tests - - name: Upload Integration Test Coverage to Codecov + - name: Upload All Test Coverage to Codecov uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/codecov.yml b/codecov.yml index d4ba735f7..65760f2f5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,13 +6,9 @@ coverage: project: default: target: auto - threshold: 1% patch: default: target: auto - informational: true - threshold: 1% - carryforward: true changes: false ignore: From c2547d0b0ed156e97e5c586ea9a9a4f26110ce24 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 23:11:48 -0600 Subject: [PATCH 06/12] Add Ability to Enable or Disable Auto-Test Watching --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a2e2d35c..4b580489a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,9 @@ option(BUILD_SIM_MODE "Enable Simulation Mode" OFF) ## Enable or Disable Code Coverage Mode option(BUILD_CODE_COVERAGE "Enable Code Coverage Mode" OFF) +## Enable or Disable Coverage Watch Mode +option(BUILD_COVERAGE_WATCH "Enable Code Coverage Watch Mode" ON) + ## Enable or Disable Verbose Makefile option(BUILD_VERBOSE_MODE "Enable Verbose Makefile" OFF) @@ -371,7 +374,7 @@ if (BUILD_TESTS_MODE) message("No Integration Tests!") endif() - if (BUILD_CODE_COVERAGE) + if (BUILD_CODE_COVERAGE AND BUILD_COVERAGE_WATCH) add_custom_target(run_coverage ALL COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure COMMAND gcovr --root ${CMAKE_SOURCE_DIR} --xml-pretty --output Coverage.xml From 1560cda9448f68ba11277cd43111970e341c6129 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 23:11:58 -0600 Subject: [PATCH 07/12] Attempt to Fix Coverage Errors --- .github/workflows/coverage.yml | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ae986532c..6456a9596 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -56,7 +56,7 @@ jobs: if [ -d "build" ]; then rm -Rf build; fi mkdir build cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS_MODE=ON -DBUILD_CODE_COVERAGE=ON -DBUILD_VERBOSE_MODE=ON + cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTS_MODE=ON -DBUILD_CODE_COVERAGE=ON -DBUILD_COVERAGE_WATCH=OFF -DBUILD_VERBOSE_MODE=ON make -j8 - name: Run Tests @@ -67,6 +67,30 @@ jobs: ctest --output-on-failure -T Test -T Coverage -R ITest --output-junit ITests.xml gcovr --root .. --xml-pretty --output AllCoverage.xml + - name: Upload Unit Test Coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software + verbose: true + plugins: gcov + directory: /opt/Autonomy_Software/build + files: /opt/Autonomy_Software/build/AllCoverage.xml + flags: unit_tests + + - name: Upload Integration Test Coverage to Codecov + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + root_dir: /opt/Autonomy_Software + working-directory: /opt/Autonomy_Software + verbose: true + plugins: gcov + directory: /opt/Autonomy_Software/build + files: /opt/Autonomy_Software/build/AllCoverage.xml + flags: integration_tests + - name: Upload Unit Test Results to Codecov if: ${{ !cancelled() }} uses: codecov/test-results-action@v1 @@ -91,18 +115,6 @@ jobs: file: ITests.xml flags: integration_tests - - name: Upload All Test Coverage to Codecov - uses: codecov/codecov-action@v4 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software - verbose: true - plugin: gcov - directory: /opt/Autonomy_Software/build - file: /opt/Autonomy_Software/build/AllCoverage.xml - flags: unit_tests, integration_tests - - name: Cleanup Action Environment if: always() run: | From f7ee76572b4abe2ee149527d7d267be6247d7b17 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 6 Jan 2025 23:21:02 -0600 Subject: [PATCH 08/12] Another Attempt --- .github/workflows/coverage.yml | 34 ++++------------------------------ codecov.yml | 10 +--------- 2 files changed, 5 insertions(+), 39 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 6456a9596..9caa9816f 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -67,7 +67,7 @@ jobs: ctest --output-on-failure -T Test -T Coverage -R ITest --output-junit ITests.xml gcovr --root .. --xml-pretty --output AllCoverage.xml - - name: Upload Unit Test Coverage to Codecov + - name: Upload Test Coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} @@ -77,33 +77,8 @@ jobs: plugins: gcov directory: /opt/Autonomy_Software/build files: /opt/Autonomy_Software/build/AllCoverage.xml - flags: unit_tests - - - name: Upload Integration Test Coverage to Codecov - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software - verbose: true - plugins: gcov - directory: /opt/Autonomy_Software/build - files: /opt/Autonomy_Software/build/AllCoverage.xml - flags: integration_tests - - - name: Upload Unit Test Results to Codecov - if: ${{ !cancelled() }} - uses: codecov/test-results-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} - root_dir: /opt/Autonomy_Software - working-directory: /opt/Autonomy_Software/build - verbose: true - directory: /opt/Autonomy_Software/build/ - file: UTests.xml - flags: unit_tests - - - name: Upload Integration Test Results to Codecov + + - name: Upload Test Results to Codecov if: ${{ !cancelled() }} uses: codecov/test-results-action@v1 with: @@ -112,8 +87,7 @@ jobs: working-directory: /opt/Autonomy_Software/build verbose: true directory: /opt/Autonomy_Software/build/ - file: ITests.xml - flags: integration_tests + files: UTests.xml, ITests.xml - name: Cleanup Action Environment if: always() diff --git a/codecov.yml b/codecov.yml index 65760f2f5..cac640849 100644 --- a/codecov.yml +++ b/codecov.yml @@ -21,14 +21,6 @@ ignore: - "**/build/*" - "/usr/include/*" -flags: - unit_tests: - paths: - - "tests/Unit/**" - integration_tests: - paths: - - "tests/Integration/**" - component_management: individual_components: - component_id: algorithms @@ -67,7 +59,7 @@ component_management: - src/*.cpp comment: - layout: "header, diff, flags, files, components" + layout: "header, diff, files, components" behavior: default require_changes: false require_base: false From 41d8bd5b4d9979939d39eb97ed76a7b5f06c0949 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Tue, 7 Jan 2025 00:16:07 -0600 Subject: [PATCH 09/12] Create TimeOps Namespace and Clean Old Locations --- src/AutonomyLogging.cpp | 18 ++------------- src/util/TimeOperations.hpp | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 src/util/TimeOperations.hpp diff --git a/src/AutonomyLogging.cpp b/src/AutonomyLogging.cpp index 5567881e4..ad8b64ecd 100644 --- a/src/AutonomyLogging.cpp +++ b/src/AutonomyLogging.cpp @@ -9,6 +9,7 @@ ******************************************************************************/ #include "AutonomyLogging.h" +#include "./util/TimeOperations.hpp" #include "AutonomyNetworking.h" /// \cond @@ -57,23 +58,8 @@ namespace logging ******************************************************************************/ void InitializeLoggers(std::string szLoggingOutputPath) { - // Retrieve the current time for the log file name - std::chrono::time_point tmCurrentTime = std::chrono::system_clock::now(); - std::time_t tCurrentTime = std::chrono::system_clock::to_time_t(tmCurrentTime); - - // Convert time to local time - std::tm* tLocalTime = std::localtime(&tCurrentTime); - - // Format the current time in a format that can be used as a file name. - std::array cCurrentTime; - size_t siTimeCharacters; - siTimeCharacters = std::strftime(cCurrentTime.data(), cCurrentTime.size(), "%Y%m%d-%H%M%S", tLocalTime); - if (siTimeCharacters == 0) - { - std::cerr << "Unable to format calendar date & time (exceeds string length)" << std::endl; - } // Store start time string in member variable. - g_szProgramStartTimeString = cCurrentTime.data(); + g_szProgramStartTimeString = timeops::GetTimestamp(); // Assemble filepath string. std::filesystem::path szFilePath; diff --git a/src/util/TimeOperations.hpp b/src/util/TimeOperations.hpp new file mode 100644 index 000000000..0106c0f41 --- /dev/null +++ b/src/util/TimeOperations.hpp @@ -0,0 +1,45 @@ +/****************************************************************************** + * @brief + * + * @file TimeOperations.hpp + * @author Eli Byrd (Eli@thebyrdnest.net) + * @date 2025-01-07 + * + * @copyright Copyright Mars Rover Design Team 2025 - All Rights Reserved + ******************************************************************************/ + +#ifndef TIME_OPERATIONS_HPP +#define TIME_OPERATIONS_HPP + +/// \cond +#include +#include +#include + +/// \endcond + +namespace timeops +{ + inline std::string GetTimestamp(std::string szFormat = "%Y%m%d-%H%M%S") + { + // Retrieve the current time for the log file name + std::chrono::time_point tmCurrentTime = std::chrono::system_clock::now(); + std::time_t tCurrentTime = std::chrono::system_clock::to_time_t(tmCurrentTime); + + // Convert time to local time + std::tm* tLocalTime = std::localtime(&tCurrentTime); + + // Format the current time in a format that can be used as a file name. + std::array cCurrentTime; + size_t siTimeCharacters; + siTimeCharacters = std::strftime(cCurrentTime.data(), cCurrentTime.size(), szFormat, tLocalTime); + if (siTimeCharacters == 0) + { + std::cerr << "Unable to format calendar date & time (exceeds string length)" << std::endl; + } + + return cCurrentTime.data(); + } +} // namespace timeops + +#endif // TIME_OPERATIONS_HPP \ No newline at end of file From ca653c380e3d2f29a4c8636e607a4b6bf2eadaed Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Tue, 7 Jan 2025 01:01:14 -0600 Subject: [PATCH 10/12] More updates --- src/util/TimeOperations.hpp | 25 +++++++++++++++++++++---- tests/main.cc | 19 +++++++++++++++++-- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/util/TimeOperations.hpp b/src/util/TimeOperations.hpp index 0106c0f41..9bcadcff1 100644 --- a/src/util/TimeOperations.hpp +++ b/src/util/TimeOperations.hpp @@ -1,8 +1,9 @@ /****************************************************************************** - * @brief + * @brief Defines and implements functions related to operations on time and + * date within the timeops namespace. * * @file TimeOperations.hpp - * @author Eli Byrd (Eli@thebyrdnest.net) + * @author Eli Byrd (edbgkk@mst.edu) * @date 2025-01-07 * * @copyright Copyright Mars Rover Design Team 2025 - All Rights Reserved @@ -18,8 +19,24 @@ /// \endcond +/****************************************************************************** + * @brief Namespace containing functions related to operations on time and + * date related data types. + * + * @author Eli Byrd (edbgkk@mst.edu) + * @date 2025-01-07 + ******************************************************************************/ namespace timeops { + /****************************************************************************** + * @brief Accessor for getting the current time in a specified format. + * + * @param szFormat - The format to return the time in. + * @return std::string - The current time in the specified format. + * + * @author Eli Byrd (edbgkk@mst.edu) + * @date 2025-01-07 + ******************************************************************************/ inline std::string GetTimestamp(std::string szFormat = "%Y%m%d-%H%M%S") { // Retrieve the current time for the log file name @@ -32,7 +49,7 @@ namespace timeops // Format the current time in a format that can be used as a file name. std::array cCurrentTime; size_t siTimeCharacters; - siTimeCharacters = std::strftime(cCurrentTime.data(), cCurrentTime.size(), szFormat, tLocalTime); + siTimeCharacters = std::strftime(cCurrentTime.data(), cCurrentTime.size(), szFormat.c_str(), tLocalTime); if (siTimeCharacters == 0) { std::cerr << "Unable to format calendar date & time (exceeds string length)" << std::endl; @@ -42,4 +59,4 @@ namespace timeops } } // namespace timeops -#endif // TIME_OPERATIONS_HPP \ No newline at end of file +#endif // TIME_OPERATIONS_HPP diff --git a/tests/main.cc b/tests/main.cc index 9a9649c0c..3ae28a66a 100644 --- a/tests/main.cc +++ b/tests/main.cc @@ -26,8 +26,23 @@ ******************************************************************************/ int main(int argc, char** argv) { - // Setup logging. - logging::InitializeLoggers(constants::LOGGING_OUTPUT_PATH_ABSOLUTE); + bool skipLogging = false; + + // Check if the test being run is "AutonomyLogging" + for (int i = 1; i < argc; ++i) + { + if (std::string(argv[i]).find("--gtest_filter=AutonomyLoggingTest") != std::string::npos) + { + skipLogging = true; + break; + } + } + + // Setup logging if not skipped. + if (!skipLogging) + { + logging::InitializeLoggers(constants::LOGGING_OUTPUT_PATH_ABSOLUTE); + } // Initialize tests. testing::InitGoogleTest(&argc, argv); From 1902ae8c9efcf22a5f4fe07df954eb027ed877bf Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Tue, 7 Jan 2025 01:09:56 -0600 Subject: [PATCH 11/12] A few updates --- codecov.yml | 3 +++ tests/main.cc | 16 ++++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/codecov.yml b/codecov.yml index cac640849..03693f731 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,9 +6,12 @@ coverage: project: default: target: auto + threshold: 5% patch: default: target: auto + informational: true + threshold: 5% changes: false ignore: diff --git a/tests/main.cc b/tests/main.cc index 3ae28a66a..e92c8f7bc 100644 --- a/tests/main.cc +++ b/tests/main.cc @@ -26,20 +26,24 @@ ******************************************************************************/ int main(int argc, char** argv) { - bool skipLogging = false; + bool bSkipLogging = false; + std::vector vConditionsToSkipLogging = {"--gtest_filter=AutonomyLoggingTest"}; - // Check if the test being run is "AutonomyLogging" + // Check if the test being run is in the list of tests to skip setting up logging. for (int i = 1; i < argc; ++i) { - if (std::string(argv[i]).find("--gtest_filter=AutonomyLoggingTest") != std::string::npos) + for (const std::string& szCondition : vConditionsToSkipLogging) { - skipLogging = true; - break; + if (std::string(argv[i]).find(szCondition) != std::string::npos) + { + bSkipLogging = true; + break; + } } } // Setup logging if not skipped. - if (!skipLogging) + if (!bSkipLogging) { logging::InitializeLoggers(constants::LOGGING_OUTPUT_PATH_ABSOLUTE); } From 120f3754c34a79ca0cd47e3e17ba66d98fae16ee Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Tue, 7 Jan 2025 01:36:18 -0600 Subject: [PATCH 12/12] Attempt to add more coverage --- tests/Unit/src/util/NumberOperations.cc | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/Unit/src/util/NumberOperations.cc b/tests/Unit/src/util/NumberOperations.cc index bec010d40..3525486af 100644 --- a/tests/Unit/src/util/NumberOperations.cc +++ b/tests/Unit/src/util/NumberOperations.cc @@ -189,3 +189,33 @@ TEST(NumOpsTest, CoordinateFrameRotate3D) EXPECT_NEAR(vPointCloud[0].tZ, aExpectedZ[nIter], 0.01); } } + +/****************************************************************************** + * @brief Write a test for the CoordinatePoint type. + * + * @author Eli Byrd (edbgkk@mst.edu) + * @date 2025-01-07 + ******************************************************************************/ +TEST(NumOpsTest, CoordinatePoint) +{ + // Create array for storing input and expect output values. + const int nTestValuesLength = 8; + const double aX[nTestValuesLength] = {607350.5439843171, 15.0, 1.0, 1.0, 1.0, 5.0, 10.0, 420000.0}; + const double aY[nTestValuesLength] = {314.26934576034546, 10.0, 0.0, 0.0, 0.0, 5.0, 10.0, 315.0}; + const double aZ[nTestValuesLength] = {4201167.977962418, 40.0, 0.0, 0.0, 0.0, 5.0, 10.0, -65780.0}; + const double aExpectedX[nTestValuesLength] = {607350.5439843171, 15.0, 1.0, 1.0, 1.0, 5.0, 10.0, 420000.0}; + const double aExpectedY[nTestValuesLength] = {314.26934576034546, 10.0, 0.0, 0.0, 0.0, 5.0, 10.0, 315.0}; + const double aExpectedZ[nTestValuesLength] = {4201167.977962418, 40.0, 0.0, 0.0, 0.0, 5.0, 10.0, -65780.0}; + + // Loop through each value and compare inputs and outputs. + for (int nIter = 0; nIter < nTestValuesLength; ++nIter) + { + // Create a CoordinatePoint object. + numops::CoordinatePoint stPoint(aX[nIter], aY[nIter], aZ[nIter]); + + // Check that the expected output values were calculated. + EXPECT_EQ(stPoint.tX, aExpectedX[nIter]); + EXPECT_EQ(stPoint.tY, aExpectedY[nIter]); + EXPECT_EQ(stPoint.tZ, aExpectedZ[nIter]); + } +}