|
| 1 | +# Regression test for GitHub #45 — "Compilation error statically linking erpl-web extension". |
| 2 | +# |
| 3 | +# When erpl_web is consumed as a dependency (duckdb_extension_load / FetchContent), only the |
| 4 | +# extension source is fetched; the `duckdb` git submodule is NOT. But test/cpp includes |
| 5 | +# catch.hpp / core_functions_extension.hpp via paths relative to that submodule |
| 6 | +# (../../duckdb/...), so building the C++ test target in a consumer tree fails with |
| 7 | +# "catch.hpp file not found". DuckDB's BUILD_UNITTESTS does not distinguish the two cases |
| 8 | +# (it is TRUE in both our dev build and a consumer's main DuckDB build), so CMakeLists.txt |
| 9 | +# must gate add_subdirectory(test) on the in-tree submodule's presence. |
| 10 | +# |
| 11 | +# This is a pure-CMake script — no DuckDB configure required — so it runs identically on |
| 12 | +# Linux, macOS and Windows. |
| 13 | +# |
| 14 | +# Run with: cmake -DREPO_DIR=<repo root> -P test/cmake/test_cpp_tests_guard.cmake |
| 15 | + |
| 16 | +if(NOT DEFINED REPO_DIR) |
| 17 | + set(REPO_DIR "${CMAKE_CURRENT_LIST_DIR}/../..") |
| 18 | +endif() |
| 19 | +get_filename_component(REPO_DIR "${REPO_DIR}" ABSOLUTE) |
| 20 | + |
| 21 | +set(CMAKELISTS "${REPO_DIR}/CMakeLists.txt") |
| 22 | +if(NOT EXISTS "${CMAKELISTS}") |
| 23 | + message(FATAL_ERROR "Cannot find ${CMAKELISTS}") |
| 24 | +endif() |
| 25 | +file(READ "${CMAKELISTS}" CML) |
| 26 | + |
| 27 | +function(assert_contains needle why) |
| 28 | + string(FIND "${CML}" "${needle}" pos) |
| 29 | + if(pos EQUAL -1) |
| 30 | + message(FATAL_ERROR "GitHub #45 regression: ${why}\n Expected CMakeLists.txt to contain: ${needle}") |
| 31 | + endif() |
| 32 | +endfunction() |
| 33 | + |
| 34 | +function(assert_absent needle why) |
| 35 | + string(FIND "${CML}" "${needle}" pos) |
| 36 | + if(NOT pos EQUAL -1) |
| 37 | + message(FATAL_ERROR "GitHub #45 regression: ${why}\n Did not expect CMakeLists.txt to contain: ${needle}") |
| 38 | + endif() |
| 39 | +endfunction() |
| 40 | + |
| 41 | +# 1. The C++ tests must be gated on the duckdb submodule's catch.hpp, not built unconditionally. |
| 42 | +assert_contains("BUILD_UNITTESTS AND EXISTS" |
| 43 | + "add_subdirectory(test) is not gated on the in-tree duckdb submodule") |
| 44 | +assert_contains("duckdb/third_party/catch/catch.hpp" |
| 45 | + "the C++ test guard does not check for the duckdb submodule's catch.hpp") |
| 46 | +assert_contains("add_subdirectory(test)" |
| 47 | + "the C++ test subdirectory wiring is missing") |
| 48 | + |
| 49 | +# 2. erpl_web must NOT redeclare DuckDB core's BUILD_UNITTESTS option (it shadows the flag |
| 50 | +# DuckDB and embedders use to control test building). |
| 51 | +assert_absent("option(BUILD_UNITTESTS" |
| 52 | + "erpl_web redeclares DuckDB's BUILD_UNITTESTS option instead of honoring it") |
| 53 | + |
| 54 | +# 3. The guard is meaningful only because test/cpp really does depend on that submodule path. |
| 55 | +# Confirm the sources that triggered #45 are present and still include catch.hpp. |
| 56 | +foreach(need "test/cpp/CMakeLists.txt" "test/cpp/test_charset_converter.cpp") |
| 57 | + if(NOT EXISTS "${REPO_DIR}/${need}") |
| 58 | + message(FATAL_ERROR "Expected ${need} to exist (the GitHub #45 reproduction sources)") |
| 59 | + endif() |
| 60 | +endforeach() |
| 61 | +file(READ "${REPO_DIR}/test/cpp/test_charset_converter.cpp" CHARSET_TEST) |
| 62 | +string(FIND "${CHARSET_TEST}" "catch.hpp" charset_pos) |
| 63 | +if(charset_pos EQUAL -1) |
| 64 | + message(FATAL_ERROR "test/cpp/test_charset_converter.cpp no longer includes catch.hpp — " |
| 65 | + "the GitHub #45 guard rationale may be stale; revisit this test.") |
| 66 | +endif() |
| 67 | + |
| 68 | +# 4. Behavioral check of the guard condition, both ways: |
| 69 | +# (a) developer tree WITH the submodule -> condition is satisfied (tests build). |
| 70 | +if(NOT EXISTS "${REPO_DIR}/duckdb/third_party/catch/catch.hpp") |
| 71 | + message(FATAL_ERROR "Expected the duckdb submodule (catch.hpp) to be present in the dev tree; " |
| 72 | + "cannot validate the positive branch of the guard.") |
| 73 | +endif() |
| 74 | +# (b) a fake consumer tree WITHOUT the submodule -> condition is NOT satisfied (tests skipped). |
| 75 | +set(FAKE_CONSUMER "${REPO_DIR}/build/guard_check_fake_consumer") |
| 76 | +file(REMOVE_RECURSE "${FAKE_CONSUMER}") |
| 77 | +file(MAKE_DIRECTORY "${FAKE_CONSUMER}") |
| 78 | +if(EXISTS "${FAKE_CONSUMER}/duckdb/third_party/catch/catch.hpp") |
| 79 | + message(FATAL_ERROR "test bug: the fake consumer tree must not contain the duckdb submodule") |
| 80 | +endif() |
| 81 | +file(REMOVE_RECURSE "${FAKE_CONSUMER}") |
| 82 | + |
| 83 | +message(STATUS "PASS: GitHub #45 guard present and correct — erpl_web C++ unit tests are gated on the in-tree duckdb submodule and do not build for dependency consumers.") |
0 commit comments