Skip to content

Commit 4e7fec5

Browse files
authored
Merge pull request #6 from rsps/add-testing
Add "mini" testing framework
2 parents 143c9ce + e9b1c9d commit 4e7fec5

23 files changed

+2702
-14
lines changed

.github/workflows/tests.yaml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# --------------------------------------------------------------------------------------------------------- #
2+
# Code analysis and tests workflow
3+
# --------------------------------------------------------------------------------------------------------- #
4+
5+
name: 'Tests'
6+
7+
on:
8+
push:
9+
pull_request:
10+
11+
# TODO: Schedule tests to run once in a while at 06:00 (if possible)
12+
# schedule:
13+
# - cron: '0 6 * * *'
14+
15+
jobs:
16+
cmake_scripts:
17+
name: "CMake Scripts Tests"
18+
runs-on: ${{ matrix.os }}
19+
strategy:
20+
matrix:
21+
os: [ ubuntu-latest ]
22+
23+
# Version(s) of cmake to test
24+
cmake_version: [
25+
'3.30.0',
26+
'latest'
27+
]
28+
29+
steps:
30+
31+
# ------------------------------------------------------------------------------------------------------- #
32+
# Checkout code ...
33+
# ------------------------------------------------------------------------------------------------------- #
34+
35+
- name: "Checkout"
36+
uses: actions/checkout@v4
37+
38+
# ------------------------------------------------------------------------------------------------------- #
39+
# Setup CMake
40+
# ------------------------------------------------------------------------------------------------------- #
41+
42+
- name: "Setup CMake"
43+
uses: jwlawson/actions-setup-cmake@v2
44+
with:
45+
cmake-version: ${{ matrix.cmake_version }}
46+
47+
# ------------------------------------------------------------------------------------------------------- #
48+
# Configure Git
49+
# ------------------------------------------------------------------------------------------------------- #
50+
51+
# This step is required due to some of the git related tests in the project.
52+
- name: "Configure locale git"
53+
run: |
54+
git config --global user.email "[email protected]"
55+
git config --global user.name "RSP Systems A/S"
56+
57+
# ------------------------------------------------------------------------------------------------------- #
58+
# Build
59+
# ------------------------------------------------------------------------------------------------------- #
60+
61+
- name: "Build"
62+
run: cmake -DRSP_CMAKE_SCRIPTS_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -B build
63+
64+
# ------------------------------------------------------------------------------------------------------- #
65+
# Tests
66+
# ------------------------------------------------------------------------------------------------------- #
67+
68+
- name: "Run Tests"
69+
run: ctest --output-on-failure --parallel --test-dir build/tests

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
* Project's root `CMakeLists.txt`.
1313
* `dependencies.cmake` and `dev-dependencies.cmake` scripts.
1414
* `CPM.cmake` script that downloads specified version of [CPM](https://github.com/cpm-cmake/CPM.cmake).
15-
* `dump()`, `dd()` and `fail_in_source_build()` utils functions, in `helpers.cmake`.
15+
* `dump()`, `dd()`, `fail_in_source_build()`, `extract_value()` and `safeguard_properties()` utils functions, in `helpers.cmake`.
1616
* `semver_parse()`, `write_version_file` and `version_from_file()` utils, in `version.cmake`.
1717
* `git_find_version_tag()` util, in `git.cmake`.
1818
* `VERSION` file.
1919
* Caching utilities, `cache.cmake`.
20+
* A "mini" testing framework for cmake modules and scripts, in `testing.cmake`.
21+
* `RSP_CMAKE_SCRIPTS_BUILD_TESTS` project option for building tests.
22+
* `tests.yaml` GitHub Actions workflow.
2023

2124
[Unreleased]: https://github.com/rsps/cmake-scripts/compare/develop

CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
cmake_minimum_required(VERSION 3.30)
66

7+
option(RSP_CMAKE_SCRIPTS_BUILD_TESTS "Build tests for the RSP CMake Scripts project" off)
8+
9+
# -------------------------------------------------------------------------------------------------------------- #
10+
# Setup
11+
# -------------------------------------------------------------------------------------------------------------- #
12+
713
# Append this package's cmake scripts in module path
814
list(FIND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" hasModulePath)
915
if(${hasModulePath} STREQUAL "-1")
@@ -59,6 +65,15 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
5965
include("dev-dependencies.cmake")
6066
endif()
6167

68+
# -------------------------------------------------------------------------------------------------------------- #
69+
# Tests
70+
# -------------------------------------------------------------------------------------------------------------- #
71+
72+
if (RSP_CMAKE_SCRIPTS_BUILD_TESTS)
73+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
74+
add_subdirectory("tests")
75+
endif ()
76+
6277
# -------------------------------------------------------------------------------------------------------------- #
6378
# Misc.
6479
# -------------------------------------------------------------------------------------------------------------- #

cmake/rsp/cache.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ if (NOT COMMAND "cache_set")
6666
string(TIMESTAMP now "%s")
6767
math(EXPR expires_at "${now} + ${INPUT_TTL}")
6868

69+
# Debug
70+
message(VERBOSE "Cache (${INPUT_KEY}) TTL set to ${INPUT_TTL} seconds. Now: ${now}, expires at: ${expires_at}")
71+
6972
set("${EXPIRES_AT_KEY}" "${expires_at}" CACHE STRING " Expiration timestamp for \"${INPUT_KEY}\" (via rsp/cache module)" FORCE)
7073
else ()
7174
# When no TTL has been specified, remove eventual previous stored TTl,

cmake/rsp/git.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ if (NOT COMMAND "git_find_version_tag")
6363
# And alternative could be "git tag --list --sort=-version:refname". Yet, a list of tags
6464
# would then have to be processed...
6565
COMMAND ${GIT_EXECUTABLE} describe --tags --match "${INPUT_MATCH_PATTERN}" --abbrev=0
66-
WORKING_DIRECTORY "${dir}"
66+
WORKING_DIRECTORY "${INPUT_WORKING_DIRECTORY}"
6767
RESULT_VARIABLE status
6868
OUTPUT_VARIABLE result
6969
ERROR_VARIABLE error

cmake/rsp/helpers.cmake

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,104 @@ if (NOT COMMAND "fail_in_source_build")
2323
endfunction()
2424
endif ()
2525

26+
if (NOT COMMAND "extract_value")
27+
28+
#! extract_value : Extracts variable value
29+
#
30+
# If given key is a value, then the value will be assigned
31+
# to the output variable.
32+
#
33+
# @param <variable> output The variable to assign extracted value to
34+
# @param <mixed> key The target key
35+
#
36+
# @return
37+
# output The extracted value
38+
#
39+
function(extract_value output key)
40+
41+
set("${output}" "${key}")
42+
43+
if (DEFINED ${key})
44+
set("${output}" "${${key}}")
45+
endif ()
46+
47+
return(PROPAGATE "${output}")
48+
endfunction()
49+
endif ()
50+
51+
if (NOT COMMAND "safeguard_properties")
52+
53+
#! safeguard_properties : Invoke a "risky" callback whilst "safeguarding" properties
54+
#
55+
# Function copies the values of the specified properties, invokes the callback, and
56+
# restores the properties' values.
57+
#
58+
# Caution: This function does NOT prevent properties from being force-cached.
59+
# Environment variables are NOT prevented changed.
60+
#
61+
# Alternatively, consider using cmake's `block()`.
62+
#
63+
# @see https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#variables
64+
# @see https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#environment-variables
65+
# @see https://cmake.org/cmake/help/latest/command/block.html#block
66+
#
67+
# @param [CALLBACK <command>] Risky command or macro to be invoked.
68+
# @param [PROPERTIES <variable>...] One or more properties to safeguard.
69+
#
70+
# @return
71+
# [PROPERTIES <variable>...] Restored properties
72+
#
73+
function(safeguard_properties)
74+
set(options "") # N/A
75+
set(oneValueArgs CALLBACK)
76+
set(multiValueArgs PROPERTIES)
77+
78+
cmake_parse_arguments(INPUT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
79+
80+
# Ensure required arguments are defined
81+
set(requiredArgs "CALLBACK;PROPERTIES")
82+
foreach (arg ${requiredArgs})
83+
if (NOT DEFINED INPUT_${arg})
84+
message(FATAL_ERROR "${arg} argument is missing, for ${CMAKE_CURRENT_FUNCTION}()")
85+
endif ()
86+
endforeach ()
87+
88+
# ---------------------------------------------------------------------------------------------- #
89+
90+
# Abort if callback not defined
91+
if (NOT COMMAND "${INPUT_CALLBACK}")
92+
message(FATAL_ERROR "Callback \"${INPUT_CALLBACK}()\" does not exist")
93+
endif ()
94+
95+
# ---------------------------------------------------------------------------------------------- #
96+
97+
set(prefix "original_")
98+
99+
# Copy each provided property
100+
foreach (prop ${INPUT_PROPERTIES})
101+
message(VERBOSE "Safeguarding: ${prop}, original value: ${${prop}}")
102+
103+
set("${prefix}${prop}" "${${prop}}")
104+
endforeach ()
105+
106+
# ---------------------------------------------------------------------------------------------- #
107+
108+
# Invoke the risky callback
109+
message(VERBOSE "Invoking risky callback: ${INPUT_CALLBACK}")
110+
cmake_language(CALL "${INPUT_CALLBACK}")
111+
112+
# ---------------------------------------------------------------------------------------------- #
113+
114+
# Restore each provided property
115+
foreach (prop ${INPUT_PROPERTIES})
116+
message(VERBOSE "Restoring: ${prop} from: ${${prop}}, to original value: ${${prefix}${prop}}")
117+
118+
# Ensure that property is set on parent scope
119+
set("${prop}" "${${prefix}${prop}}" PARENT_SCOPE)
120+
endforeach ()
121+
endfunction()
122+
endif ()
123+
26124
if (NOT COMMAND "dump")
27125

28126
#! dump : Outputs given variables' name and value

0 commit comments

Comments
 (0)