Skip to content

Commit 9b0e1e0

Browse files
cmake with autotest (#350)
This idea is a different take on using cmake to build libdap4. The same build process is in place. I changed how the integration tests are run. Before, I made them use ctest and more completely integrated then with the cmake system. The problem was that about 1k lines of python were needed and the result was less useful than using autotest. I switched to using ctest/cmake for the unit tests but autotest for the integration tests. The downside is that developers need both systems (cmake and autoconf) on their machines. That seems like a small price to pay for better tests. --------- Co-authored-by: Hannah Robertson <hannahilea@users.noreply.github.com>
1 parent acc62ad commit 9b0e1e0

16 files changed

Lines changed: 334 additions & 1071 deletions

.github/workflows/cmake.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ jobs:
3030
name: macOS Intel
3131
# For a reason I don't entirely understand, with this build, some of the expr-tests fail.exclude:
3232
# Investigate on a clean OSX M4 machine. jhrg 4/2/26
33-
#- os: macos-15
34-
# name: macOS arm64
33+
- os: macos-15
34+
name: macOS arm64
3535
name: ${{ matrix.name }}
3636
runs-on: ${{ matrix.os }}
3737
env:
@@ -78,7 +78,7 @@ jobs:
7878
ccache \
7979
cppunit \
8080
flex \
81-
libtirpc
81+
autoconf
8282
8383
- name: Configure macOS build environment
8484
if: runner.os == 'macOS'

.vscode/jhrg/c_cpp_properties.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"version": 4,
3+
"configurations": [
4+
{
5+
"name": "macOS",
6+
"compilerPath": "/usr/bin/clang++",
7+
"cStandard": "c11",
8+
"cppStandard": "c++14",
9+
"intelliSenseMode": "macos-clang-arm64",
10+
"compileCommands": "${workspaceFolder}/compile_commands.json",
11+
"includePath": [
12+
"${workspaceFolder}",
13+
"${workspaceFolder}/**",
14+
"/Users/jhrg/src/hyrax/build/include",
15+
"/Users/jhrg/src/hyrax/build/deps/include",
16+
"/opt/homebrew/include/cppunit"
17+
],
18+
"defines": [],
19+
"macFrameworkPath": [
20+
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
21+
],
22+
"browse": {
23+
"path": ["${workspaceFolder}", "${workspaceFolder}/**"],
24+
"limitSymbolsToIncludedHeaders": true
25+
}
26+
}
27+
]
28+
}

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ These instructions apply to the entire `libdap4` repository.
1414

1515
- Prefer autotools for day-to-day work unless the task is explicitly CMake-focused.
1616
- Keep both autotools and CMake build paths healthy when changing shared build logic.
17+
- For all the builds the 'prefix' environment variable should be set.
18+
- $prefix is the full path to the 'build' directory in the directory above 'libdap4'.
19+
- The PATH env var should have $prefix/bin and $prefix/deps/bin prepended.
1720

1821
## Autotools Workflow (preferred)
1922

CMakePresets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"CMAKE_CXX_STANDARD": "14",
1616
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
1717
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
18-
"CMAKE_INSTALL_PREFIX": "$prefix",
18+
"CMAKE_INSTALL_PREFIX": "$env{prefix}",
1919
"BUILD_TESTING": "ON",
2020
"USE_CPP_11_REGEX": "ON",
2121
"USE_ASAN": "OFF",

config.h.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
/* Client version number */
5555
#define CVER "@LIBDAP_VERSION@"
5656
/* Client name and version combined */
57-
#define DVR "@PROJECT_NAME@/LIBDAP_VERSION@"
57+
#define DVR "@PROJECT_NAME@/@LIBDAP_VERSION@"
5858

5959
/* Install prefix for libdap */
6060
#define LIBDAP_ROOT "@LIBDAP_ROOT@"

docs/AGENTS.md

Lines changed: 0 additions & 109 deletions
This file was deleted.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
# CMake Autotest Integration Plan
2+
3+
Note: running the tests this was save ~1,000 lines of cmake code and requires
4+
no change to the existing autotest tests. jhrg 4/4/26
5+
6+
## Goal
7+
8+
Support CMake builds that run the existing autotools/autotest-based integration
9+
tests while keeping the current CMake CppUnit tests intact.
10+
11+
## Scope
12+
13+
- Keep the existing CMake CppUnit tests.
14+
- Modify the CMake test setup so it runs the autotest suites:
15+
- `DASTest`
16+
- `DDSTest`
17+
- `EXPRTest`
18+
- `DMRTest`
19+
- `getdapTest`
20+
- Add a minimal `tests/configure.ac` used only to configure the autotools test
21+
machinery.
22+
23+
## Plan
24+
25+
1. Audit the current CMake integration test modules and identify which
26+
generated/autotest inputs they duplicate from `tests/Makefile.am`
27+
(`DASTest.at`, `DDSTest.at`, `EXPRTest.at`, `DMRTest.at`, `getdapTest.at`,
28+
`atlocal.in`, `package.m4`).
29+
2. Add a minimal `tests/configure.ac` dedicated to the autotest suites, with
30+
only the package metadata and substitutions needed to generate `atconfig`,
31+
`atlocal`, and `package.m4` for the test scripts.
32+
3. Add CMake support in `tests/CMakeLists.txt` to find autotools tools
33+
(`autoconf`, `autom4te`, and `autoheader` if needed), configure the new
34+
test-only `configure.ac`, and generate the autotest driver scripts in the
35+
CMake build tree from the existing `*.at` files.
36+
4. Replace the current CMake per-test includes
37+
(`das-tests.cmake`, `dds-tests.cmake`, `expr-tests.cmake`,
38+
`dmr-tests.cmake`, `getdap-tests.cmake`) with a thinner registration layer
39+
that adds one CTest test per autotest suite and invokes `DASTest`,
40+
`DDSTest`, `EXPRTest`, `DMRTest`, and `getdapTest` with `TESTSUITEFLAGS`.
41+
5. Make the generated autotest environment point at the CMake-built executables
42+
(`das-test`, `dds-test`, `expr-test`, `dmr-test`, `getdap`) so the existing
43+
autotest cases run unchanged against the CMake artifacts.
44+
6. Preserve existing CMake CppUnit coverage and labels, and add sensible
45+
dependencies plus serial/parallel behavior for the autotest suite wrappers
46+
so `ctest` and the top-level `integration-test` and `check` targets
47+
continue to work.
48+
7. Fold the integration-test build artifacts into the default CMake `ALL`
49+
target so `cmake --build --preset <preset>` builds both the unit-test and
50+
integration-test executables plus the generated autotest suite drivers,
51+
without changing when tests are executed.
52+
8. Remove the now-unused hand-maintained CMake integration modules and any
53+
supporting `tests/CMakeLists.txt` logic that existed only for that older
54+
path.
55+
9. Validate with a focused CMake configure/build plus `ctest` over the
56+
integration label, then note any suites that still depend on autotools-era
57+
assumptions such as generated `package.m4`, working directory layout, or
58+
network access in `getdapTest`.
59+
60+
## Step 1 Audit
61+
62+
The current CMake integration layer in `tests/CMakeLists.txt` and
63+
`tests/cmake/*.cmake` does not generate or invoke the autotest suites from
64+
`tests/Makefile.am`. Instead, it re-expresses parts of those suites directly as
65+
CTest registrations and shell snippets.
66+
67+
| Autotest input from `tests/Makefile.am` | Current CMake duplication | Notes |
68+
| --------------------------------------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
69+
| `DASTest.at` | `tests/cmake/das-tests.cmake` | Partial duplication. CMake discovers `das-testsuite/*.das` with `file(GLOB ...)`, runs `das-test -p`, diffs against `*.base`, and stages baselines. This overlaps the `_AT_DAS_TEST` and `AT_DAS_RESPONSE_TEST` logic, but CMake derives the case list from the filesystem instead of the explicit autotest manifest. |
70+
| `DDSTest.at` | `tests/cmake/dds-tests.cmake` | Partial duplication. CMake discovers `dds-testsuite/*.dds`, runs `dds-test -p`, diffs against `*.base`, and stages baselines. This overlaps `_AT_DDS_TEST` and `AT_DDS_RESPONSE_TEST`, including the `xpass` cases for `test.24.dds`, `test.25.dds`, and `test.26.dds`, but not the autotest `--baselines` option. |
71+
| `EXPRTest.at` | `tests/cmake/expr-tests.cmake` | Substantial manual duplication. The CMake file enumerates the same expression and error cases one by one, recreates the `-w`/`-W` and `-bw`/`-bW` pairings, and duplicates the stdout/stderr combination behavior that the autotest macros implement. |
72+
| `DMRTest.at` | `tests/cmake/dmr-tests.cmake` | Substantial manual duplication. CMake reimplements large parts of the autotest macros with custom functions for parse, intern, translation, and CE/function cases, including byte-order-aware baseline selection and checksum filtering for universal baselines. |
73+
| `getdapTest.at` | `tests/cmake/getdap-tests.cmake` | Direct duplication for the single current case. CMake registers the same `getdap -d http://test.opendap.org/dap/data/nc/fnoc1.nc` check and baseline diff, plus a CMake-only baseline staging target. |
74+
| `atlocal.in` | None | Not duplicated today. The autotest-only `WORD_ORDER=@ac_word_order@` substitution is still provided only by autotools. CMake computes byte order independently inside `tests/cmake/dmr-tests.cmake` instead of generating `atlocal`. |
75+
| `package.m4` | None | Not duplicated today. `tests/Makefile.am` generates this from top-level package metadata, but the current CMake test flow never generates or consumes it because it does not invoke `autom4te` on the `*.at` files. |
76+
77+
### Audit summary
78+
79+
- `das-tests.cmake`, `dds-tests.cmake`, and `getdap-tests.cmake` are thin
80+
CTest rewrites of their corresponding autotest suites.
81+
- `expr-tests.cmake` and `dmr-tests.cmake` are larger hand-maintained ports of
82+
the autotest case matrices and macro behavior.
83+
- The current CMake path does not use the autotest support files from
84+
`tests/Makefile.am`; there is no CMake-generated `atconfig`, `atlocal`, or
85+
`package.m4`.
86+
- Step 2 should therefore add only the minimum autotools metadata needed to
87+
generate those support files and reuse the existing `*.at` sources instead of
88+
extending the current hand-ported CMake test definitions.
89+
90+
## Main Risks
91+
92+
- The autotest scripts assume autotools-generated files like `atconfig`,
93+
`atlocal`, and `package.m4`.
94+
- Some suites may assume a specific working directory layout under `tests/`.
95+
- `getdapTest` depends on network access and should stay clearly labeled as an
96+
integration test.
97+
98+
## Implementation Status
99+
100+
Steps 2 through 9 are now implemented in the CMake build:
101+
102+
- `tests/configure.ac` provides a minimal autotest-only configure input that
103+
computes `ac_word_order` and configures `atlocal` plus `package.m4`.
104+
- `tests/CMakeLists.txt` now finds `autoconf` and `autom4te`, generates the
105+
autotest support files in the CMake test build tree, and builds the
106+
`DASTest`, `DDSTest`, `EXPRTest`, `DMRTest`, and `getdapTest` drivers from
107+
the existing `*.at` sources.
108+
- The `tests` custom target is now part of the default `ALL` target, so a
109+
plain `cmake --build --preset <preset>` also builds the integration-test
110+
executables and generated autotest suite drivers.
111+
- The old hand-maintained per-case CMake integration modules have been removed,
112+
along with the unused `tests/CMakeLists.txt` setup that supported that older
113+
path; the CMake path now registers one CTest test per autotest suite.
114+
- The suite wrappers are labeled under `integration` and run serially at the
115+
CTest layer. Any desired intra-suite parallelism should be passed through
116+
`TESTSUITEFLAGS`, matching the autotools `make check` model.
117+
- The top-level CMake `integration-test` and `check` targets continue to work
118+
through the existing `tests` target dependency chain, while CMake CppUnit
119+
coverage and unit-test labels remain unchanged.
120+
121+
## Step 9 Validation
122+
123+
Validation was run with the repository-style environment:
124+
125+
```sh
126+
prefix=/Users/jimg/src/opendap/hyrax/build
127+
PATH=$prefix/bin:$prefix/deps/bin:$PATH
128+
```
129+
130+
Focused CMake validation used:
131+
132+
```sh
133+
cmake -S . -B /tmp/libdap4-cmake-autotest-build-prefix \
134+
-DCMAKE_INSTALL_PREFIX=$prefix -DBUILD_DEVELOPER=ON
135+
cmake --build /tmp/libdap4-cmake-autotest-build-prefix -j2
136+
ctest --test-dir /tmp/libdap4-cmake-autotest-build-prefix \
137+
--output-on-failure -L integration
138+
```
139+
140+
During the default build, CMake generated `tests/configure`, `atlocal`,
141+
`package.m4`, and the `DASTest`, `DDSTest`, `EXPRTest`, `DMRTest`, and
142+
`getdapTest` autotest driver scripts without requiring an explicit
143+
`--target tests`.
144+
145+
Observed suite results:
146+
147+
- `DASTest`: passed
148+
- `DDSTest`: passed
149+
- `DMRTest`: passed
150+
- `EXPRTest`: failed
151+
- `getdapTest`: failed
152+
153+
Current autotools-era assumptions or runtime issues still exposed by the CMake
154+
path:
155+
156+
- `EXPRTest` runs successfully as an autotest suite, but on this machine many
157+
`expr-test -w ...` cases fail while the matching `-W` cases pass. This now
158+
appears to be a runtime/behavior difference in `expr-test`, not a missing
159+
CMake/autotest integration input.
160+
- `getdapTest` still depends on network access and also hit a local HTTP cache
161+
locking failure in `HTTPCache.cc`, followed by a segmentation fault in
162+
`getdap`. This is likewise a runtime issue surfaced by the suite, not a
163+
driver-generation problem.
164+
- The generated suites expect to run from the CMake `tests/` build directory so
165+
that autotest can create its `*.dir` work areas relative to the configured
166+
`atconfig`/`atlocal` files.
167+
- `package.m4` is required by `autom4te` for all five suites and is now being
168+
generated in the CMake build tree rather than assumed from the autotools
169+
build.

0 commit comments

Comments
 (0)