refactor(tests): CMake-based CDB, workspace fixture, test cleanup (#378)

## Summary

- **CMake-based CDB generation for module tests**: Replace hand-written
compile_commands.json with CMakeLists.txt (CMake 3.28 `FILE_SET
CXX_MODULES`) in all 26 `tests/data/modules/*/` directories. CDB is
generated on-the-fly via `cmake -G Ninja` during test setup.
- **`@pytest.mark.workspace()` decorator**: Introduce a marker + fixture
pattern so tests declare their workspace via decorator and receive a
resolved `workspace` path. The fixture auto-generates CDB when a
CMakeLists.txt is present.
- **`CliceClient` helper methods**: Add `initialize()`, `open()`,
`wait_diagnostics()`, and `open_and_wait()` to reduce boilerplate across
all test files.
- **Use `asyncio_mode = "auto"`**: Switch from `@pytest_asyncio.fixture`
+ `@pytest.mark.asyncio` to `@pytest.fixture` + auto mode for proper
Pylance type inference on fixtures.
- **Test cleanup**: Remove redundant section separators and docstrings,
delete `tests/pyproject.toml` (config moved to `pytest.ini`).
- **Format task**: Add `.cppm` to `format-cpp` glob pattern.
- **CI fix**: Disable `CMAKE_CXX_SCAN_FOR_MODULES` and prefer pixi
clang++ to fix macOS CI where CMake rejects module scanning.

## Test plan

- [x] All 26 module test directories have CMakeLists.txt with FILE_SET
CXX_MODULES
- [x] generate_cdb() produces valid compile_commands.json with module
flags
- [x] Integration tests pass locally
- [ ] CI passes on all platforms (Linux, macOS, Windows)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
* Unified fixtures and client workflow: new init/open/wait helpers,
workspace marker support, bounded diagnostics waiting, CMake-based
compilation-database generation, and directory-backed temp-file
workflows; enabled asyncio test mode.
* **Chores**
* Added many C++20 module test projects and test data; removed prior
test pyproject in favor of pytest config; updated formatter to include
.cppm files.
* **Style**
* Reformatted many module/source implementations to consistent
multi-line function bodies.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ykiko
2026-03-31 16:57:48 +08:00
committed by GitHub
parent 0a891d8b4a
commit bc04845293
93 changed files with 1009 additions and 970 deletions

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(chained_modules LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES mod_a.cppm mod_b.cppm
)

View File

@@ -1,2 +1,5 @@
export module A;
export int foo() { return 42; }
export int foo() {
return 42;
}

View File

@@ -1,3 +1,6 @@
export module B;
import A;
export int bar() { return foo() + 1; }
export int bar() {
return foo() + 1;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(circular_module_dependency LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES cycle_a.cppm cycle_b.cppm ok.cppm
)

View File

@@ -1,3 +1,6 @@
export module CycA;
import CycB;
export int a() { return 1; }
export int a() {
return 1;
}

View File

@@ -1,3 +1,6 @@
export module CycB;
import CycA;
export int b() { return 2; }
export int b() {
return 2;
}

View File

@@ -1,2 +1,5 @@
export module Ok;
export int ok() { return 42; }
export int ok() {
return 42;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(class_export_and_inheritance LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES shape.cppm circle.cppm
)

View File

@@ -1,8 +1,13 @@
export module Circle;
import Shape;
export class Circle : public Shape {
int r;
public:
Circle(int r) : r(r) {}
int area() const override { return 3 * r * r; }
int area() const override {
return 3 * r * r;
}
};

View File

@@ -1,4 +1,5 @@
export module Shape;
export class Shape {
public:
virtual ~Shape() = default;

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(consumer_imports_module LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES math.cppm
)
target_sources(test PRIVATE main.cpp)

View File

@@ -1,2 +1,5 @@
export module Math;
export int add(int a, int b) { return a + b; }
export int add(int a, int b) {
return a + b;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(deep_chain LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES m1.cppm m2.cppm m3.cppm m4.cppm m5.cppm
)

View File

@@ -1,2 +1,5 @@
export module M1;
export int f1() { return 1; }
export int f1() {
return 1;
}

View File

@@ -1,3 +1,6 @@
export module M2;
import M1;
export int f2() { return f1() + 1; }
export int f2() {
return f1() + 1;
}

View File

@@ -1,3 +1,6 @@
export module M3;
import M2;
export int f3() { return f2() + 1; }
export int f3() {
return f2() + 1;
}

View File

@@ -1,3 +1,6 @@
export module M4;
import M3;
export int f4() { return f3() + 1; }
export int f4() {
return f3() + 1;
}

View File

@@ -1,3 +1,6 @@
export module M5;
import M4;
export int f5() { return f4() + 1; }
export int f5() {
return f4() + 1;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(diamond_modules LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES base.cppm left.cppm right.cppm top.cppm
)

View File

@@ -1,2 +1,5 @@
export module Base;
export int base_val() { return 10; }
export int base_val() {
return 10;
}

View File

@@ -1,3 +1,6 @@
export module Left;
import Base;
export int left_val() { return base_val() + 1; }
export int left_val() {
return base_val() + 1;
}

View File

@@ -1,3 +1,6 @@
export module Right;
import Base;
export int right_val() { return base_val() + 2; }
export int right_val() {
return base_val() + 2;
}

View File

@@ -1,4 +1,7 @@
export module Top;
import Left;
import Right;
export int top_val() { return left_val() + right_val(); }
export int top_val() {
return left_val() + right_val();
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(dotted_module_name LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES io.cppm app.cppm
)

View File

@@ -1,3 +1,6 @@
export module my.app;
import my.io;
export void run() { print(); }
export void run() {
print();
}

View File

@@ -1,2 +1,3 @@
export module my.io;
export void print() {}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(export_block LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES block.cppm consumer.cppm
)

View File

@@ -1,8 +1,18 @@
export module Block;
export {
int alpha() { return 1; }
int beta() { return 2; }
namespace ns {
int gamma() { return 3; }
int alpha() {
return 1;
}
int beta() {
return 2;
}
namespace ns {
int gamma() {
return 3;
}
} // namespace ns
}

View File

@@ -1,3 +1,6 @@
export module Consumer;
import Block;
export int total() { return alpha() + beta() + ns::gamma(); }
export int total() {
return alpha() + beta() + ns::gamma();
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(export_namespace LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES ns.cppm calc.cppm
)

View File

@@ -1,3 +1,6 @@
export module Calc;
import NS;
export int compute() { return math::add(3, math::mul(4, 5)); }
export int compute() {
return math::add(3, math::mul(4, 5));
}

View File

@@ -1,5 +1,13 @@
export module NS;
export namespace math {
int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }
int add(int a, int b) {
return a + b;
}
int mul(int a, int b) {
return a * b;
}
} // namespace math

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(global_module_fragment LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES gmf.cppm
)
target_include_directories(test PRIVATE ${CMAKE_SOURCE_DIR})

View File

@@ -1,4 +1,7 @@
module;
#include "legacy.h"
export module GMF;
export int wrapped() { return legacy_fn(); }
export int wrapped() {
return legacy_fn();
}

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(gmf_with_import LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES base.cppm combined.cppm
)
target_include_directories(test PRIVATE ${CMAKE_SOURCE_DIR})

View File

@@ -1,2 +1,5 @@
export module Base;
export int base() { return 100; }
export int base() {
return 100;
}

View File

@@ -2,4 +2,7 @@ module;
#include "util.h"
export module Combined;
import Base;
export int combined() { return base() + util_helper(); }
export int combined() {
return base() + util_helper();
}

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(hover_on_imported_symbol LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES defs.cppm
)
target_sources(test PRIVATE use.cpp)

View File

@@ -1,2 +1,5 @@
export module Defs;
export int magic_number() { return 42; }
export int magic_number() {
return 42;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(independent_modules LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES x.cppm y.cppm
)

View File

@@ -1,2 +1,5 @@
export module X;
export int x() { return 1; }
export int x() {
return 1;
}

View File

@@ -1,2 +1,5 @@
export module Y;
export int y() { return 2; }
export int y() {
return 2;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(module_compile_error LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES good.cppm bad.cppm
)

View File

@@ -1,3 +1,6 @@
export module Bad;
import Good;
export int bad() { return UNDEFINED_SYMBOL; }
export int bad() {
return UNDEFINED_SYMBOL;
}

View File

@@ -1,2 +1,5 @@
export module Good;
export int good() { return 1; }
export int good() {
return 1;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(module_implementation_unit LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES greeter.cppm greeter_impl.cpp
)

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(module_partitions LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES part_a.cppm part_b.cppm lib.cppm
)

View File

@@ -1,4 +1,7 @@
export module Lib;
export import :A;
export import :B;
export int lib_fn() { return a_fn() + b_fn(); }
export int lib_fn() {
return a_fn() + b_fn();
}

View File

@@ -1,2 +1,5 @@
export module Lib:A;
export int a_fn() { return 1; }
export int a_fn() {
return 1;
}

View File

@@ -1,2 +1,5 @@
export module Lib:B;
export int b_fn() { return 2; }
export int b_fn() {
return 2;
}

View File

@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.28)
project(no_modules_plain_cpp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test STATIC plain.cpp)

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(partition_chain LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES types.cppm core.cppm sys.cppm
)

View File

@@ -1,3 +1,6 @@
export module Sys:Core;
import :Types;
export Config make_config() { return {42}; }
export Config make_config() {
return {42};
}

View File

@@ -1,2 +1,5 @@
export module Sys:Types;
export struct Config { int value = 0; };
export struct Config {
int value = 0;
};

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(partition_interface LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES part.cppm primary.cppm
)

View File

@@ -1,2 +1,5 @@
export module M:Part;
export int part_fn() { return 5; }
export int part_fn() {
return 5;
}

View File

@@ -1,3 +1,6 @@
export module M;
export import :Part;
export int primary_fn() { return part_fn() + 1; }
export int primary_fn() {
return part_fn() + 1;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(partition_with_external_import LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES ext.cppm part.cppm app.cppm
)

View File

@@ -1,2 +1,5 @@
export module Ext;
export int ext_val() { return 99; }
export int ext_val() {
return 99;
}

View File

@@ -1,3 +1,6 @@
export module App:Core;
import Ext;
export int core_fn() { return ext_val() + 1; }
export int core_fn() {
return ext_val() + 1;
}

View File

@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.28)
project(partition_with_gmf LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES part_cfg.cppm cfg.cppm
)
target_include_directories(test PRIVATE ${CMAKE_SOURCE_DIR})

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(private_module_fragment LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES priv.cppm
)

View File

@@ -1,5 +1,11 @@
export module Priv;
export int public_fn();
module : private;
int public_fn() { return 42; }
int private_helper() { return 7; }
module :private;
int public_fn() {
return 42;
}
int private_helper() {
return 7;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(re_export LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES core.cppm wrapper.cppm user.cppm
)

View File

@@ -1,2 +1,5 @@
export module Core;
export int core_fn() { return 1; }
export int core_fn() {
return 1;
}

View File

@@ -1,3 +1,6 @@
export module User;
import Wrapper;
export int use_fn() { return core_fn() + wrap_fn(); }
export int use_fn() {
return core_fn() + wrap_fn();
}

View File

@@ -1,3 +1,6 @@
export module Wrapper;
export import Core;
export int wrap_fn() { return core_fn() + 10; }
export int wrap_fn() {
return core_fn() + 10;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(save_recompile LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES leaf.cppm mid.cppm
)

View File

@@ -1,2 +1,5 @@
export module Leaf;
export int leaf() { return 1; }
export int leaf() {
return 1;
}

View File

@@ -1,3 +1,6 @@
export module Mid;
import Leaf;
export int mid() { return leaf() + 1; }
export int mid() {
return leaf() + 1;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(single_module_no_deps LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES mod_a.cppm
)

View File

@@ -1,2 +1,5 @@
export module A;
export int foo() { return 42; }
export int foo() {
return 42;
}

View File

@@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.28)
project(template_export LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(test)
target_sources(test
PUBLIC
FILE_SET CXX_MODULES
FILES tmpl.cppm use_tmpl.cppm
)

View File

@@ -1,5 +1,11 @@
export module Tmpl;
export template<typename T>
T identity(T x) { return x; }
export template<typename T, typename U>
auto pair_sum(T a, U b) { return a + b; }
export template <typename T>
T identity(T x) {
return x;
}
export template <typename T, typename U>
auto pair_sum(T a, U b) {
return a + b;
}

View File

@@ -1,3 +1,6 @@
export module UseTmpl;
import Tmpl;
export int test() { return identity(42) + pair_sum(1, 2); }
export int test() {
return identity(42) + pair_sum(1, 2);
}