Skip to content

Commit 966e326

Browse files
committed
test(boost-family): 大测试成员 — 一个工程覆盖全部 23 个小依赖包
新增 tests/examples/boost-family/:消费 modular-boost 家族所有没有专属 成员的小包(align/bind/compat/container/container-hash/core/describe/ endian/intrusive/io/logic/move/mp11/optional/predef/preprocessor/ smart-ptr/static-string/system/type-index/utility/variant2/winapi), 按主题分 6 个 tests/*.cpp,每个组件都有可失败的行为断言: core-smart core(addressof/empty_value/ref) + smart-ptr + move containers container(vector) + intrusive(list) + optional + static-string meta mp11 + describe + preprocessor + type-index + predef system-errors system(error_code/system_error) + compat(invoke) + bind bytes-logic endian + container-hash + logic(tribool) + align io-platform io(ios_flags_saver) + utility(compressed_pair) + winapi 实测踩坑固化进注释:tribool 连 operator! 都返回 tribool(取 bool 走 explicit 转换/indeterminate());boost/winapi 头非 Windows 平台 #error (include 与断言均在 _WIN32 门控内,由 windows CI 腿真实覆盖); intrusive::list 析构前必须 clear(带链析构触发调试断言)。 mcpp 2026.8.27.2 本地冷验证:6/6 test result ok。
1 parent fd1dfe8 commit 966e326

10 files changed

Lines changed: 421 additions & 2 deletions

File tree

.agents/docs/2026-09-05-add-boost-beast-plan.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,18 @@ throw-exception);仓库 URL 与注释中保留上游仓原名 `container_has
127127
消费 TU;真实跑 `steady_timer` + `io_context::run`、post/defer、
128128
co_spawn/awaitable、tcp endpoint。`#include <boost/asio.hpp>` 单体头
129129
顺带验证 disable 宏守卫下单体 include 可用。
130-
- 两成员只消费 `compat` 命名空间,继承根 workspace 的 `[indices]`
130+
- `tests/examples/boost-family/`**大测试成员**,一次性消费全部 23 个没有
131+
专属成员的小依赖包(align/bind/compat/container/container-hash/core/
132+
describe/endian/intrusive/io/logic/move/mp11/optional/predef/preprocessor/
133+
smart-ptr/static-string/system/type-index/utility/variant2/winapi),
134+
按主题分 6 个 tests/*.cpp(core-smart / containers / meta /
135+
system-errors / bytes-logic / io-platform),每个组件都有可失败断言。
136+
实测踩坑三则已固化进测试注释:boost::logic::tribool 连 `operator!`
137+
返回 tribool(取 bool 只能 explicit 转换或 indeterminate());
138+
boost/winapi 头在非 Windows 平台 `#error`(include 与断言都在
139+
`#ifdef _WIN32` 内,由 windows CI 腿真实覆盖);intrusive::list 析构前
140+
必须 clear(调试断言 hook 不得带链析构)。
141+
- 三成员只消费 `compat` 命名空间,继承根 workspace 的 `[indices]`
131142
重定向,不声明自己的 indices。
132143
- 正向验证在 CI(linux/macos/windows 三平台);无 feature 需要负向验证
133144
(无源码门控),disable 宏的"负向"体现在:闭包树里根本没有

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@
2020
feature 携带 `BOOST_ASIO_DISABLE_BOOST_CONTEXT_FIBER` / `..._DATE_TIME`
2121
`BOOST_ASIO_HAS_THREADS`(llvm-on-Windows 无 `_MT`/`BOOST_HAS_THREADS`
2222
不钉定会静默退化为 null_thread 且 VERSION_TAG 跨 TU 漂移),保持家族
23-
header-only。新增 `boost-beast``boost-asio` 两个工作区成员。
23+
header-only。新增 `boost-beast``boost-asio``boost-family` 三个工作区
24+
成员;其中 `boost-family` 为大测试成员,一个工程 6 个测试文件覆盖全部
25+
23 个没有专属成员的小依赖包(core/smart-ptr、container/intrusive/
26+
optional/static-string、mp11/describe/preprocessor/type-index/predef、
27+
system/compat/bind、endian/container-hash/logic/align、io/utility/
28+
winapi)。
2429
- 收录 `gzj-creator.galay` 5.0.2 原生 Form-A 模块包,覆盖 `galay.utils`
2530
`galay.kernel` 默认模块,并加入 Unix 示例工程和索引文档。
2631

mcpp.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ members = [
1616
"tests/examples/boost-beast",
1717
"tests/examples/boost-config",
1818
"tests/examples/boost-ext.ut",
19+
"tests/examples/boost-family",
1920
"tests/examples/boost-throw-exception",
2021
"tests/examples/boost-type-traits",
2122
"tests/examples/boost-uuid",
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# compat boost 家族"大测试"成员:为每个没有专属成员的小依赖包提供行为断言。
2+
# 消费全部 23 个小包(boost-beast / boost-asio / 既有 uuid/config/assert/
3+
# throw-exception/type-traits 各有专属成员,不在其中),按主题分成 6 个
4+
# tests/*.cpp,每个组件都有可失败的有效断言。
5+
[package]
6+
name = "boost-family-tests"
7+
version = "0.1.0"
8+
9+
[dependencies.compat]
10+
boost-align = "1.92.0"
11+
boost-bind = "1.92.0"
12+
boost-compat = "1.92.0"
13+
boost-container = "1.92.0"
14+
boost-container-hash = "1.92.0"
15+
boost-core = "1.92.0"
16+
boost-describe = "1.92.0"
17+
boost-endian = "1.92.0"
18+
boost-intrusive = "1.92.0"
19+
boost-io = "1.92.0"
20+
boost-logic = "1.92.0"
21+
boost-move = "1.92.0"
22+
boost-mp11 = "1.92.0"
23+
boost-optional = "1.92.0"
24+
boost-predef = "1.92.0"
25+
boost-preprocessor = "1.92.0"
26+
boost-smart-ptr = "1.92.0"
27+
boost-static-string = "1.92.0"
28+
boost-system = "1.92.0"
29+
boost-type-index = "1.92.0"
30+
boost-utility = "1.92.0"
31+
boost-variant2 = "1.92.0"
32+
boost-winapi = "1.92.0"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// boost-endian (byte-order conversion), boost-container-hash (hashing),
2+
// boost-logic (tribool) and boost-align (pointer alignment helpers).
3+
#include <boost/align/align_down.hpp>
4+
#include <boost/align/align_up.hpp>
5+
#include <boost/align/is_aligned.hpp>
6+
#include <boost/container_hash/hash.hpp>
7+
#include <boost/endian/conversion.hpp>
8+
#include <boost/logic/tribool.hpp>
9+
10+
#include <cstdint>
11+
#include <vector>
12+
13+
int main() {
14+
bool ok = true;
15+
16+
// endian: reversing is an involution with byte-exact results.
17+
{
18+
std::uint32_t x = 0x01020304u;
19+
ok = ok && boost::endian::endian_reverse(x) == 0x04030201u;
20+
ok = ok &&
21+
boost::endian::endian_reverse(boost::endian::endian_reverse(x)) == x;
22+
}
23+
24+
// container-hash: deterministic within a process; combining is stable.
25+
{
26+
boost::hash<std::string> hs;
27+
ok = ok && hs("abc") == hs("abc");
28+
29+
const std::vector<int> v1{1, 2, 3}, v2{1, 2, 3};
30+
std::size_t seed = 0;
31+
boost::hash_range(seed, v1.begin(), v1.end());
32+
std::size_t seed2 = 0;
33+
boost::hash_range(seed2, v2.begin(), v2.end());
34+
ok = ok && seed == seed2 && seed != 0;
35+
}
36+
37+
// logic: three-valued truth table entry points used by beast::detect_ssl.
38+
// Every operator (including !) returns tribool; the explicit conversion
39+
// and the indeterminate() free function are the way back to bool.
40+
{
41+
using boost::logic::indeterminate;
42+
using boost::logic::tribool;
43+
tribool t = true, f = false, i = indeterminate;
44+
45+
ok = ok && static_cast<bool>(t) && !static_cast<bool>(f);
46+
ok = ok && indeterminate(i);
47+
ok = ok && indeterminate(t && i);
48+
ok = ok && static_cast<bool>(t || i); // true dominates OR
49+
ok = ok && !static_cast<bool>(f && i); // false dominates AND
50+
ok = ok && indeterminate(i || f) && indeterminate(i && t);
51+
}
52+
53+
// align: round-tripping through align_up lands on the boundary and
54+
// align_down undoes it.
55+
{
56+
alignas(64) char raw[128];
57+
ok = ok && boost::alignment::is_aligned(boost::alignment::align_up(raw, 64), 64);
58+
ok = ok && boost::alignment::align_down(
59+
boost::alignment::align_up(raw, 64), 64) ==
60+
boost::alignment::align_up(raw, 64);
61+
}
62+
63+
return ok ? 0 : 1;
64+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// boost-container (vector), boost-intrusive (list), boost-optional
2+
// and boost-static-string.
3+
#include <boost/container/vector.hpp>
4+
#include <boost/intrusive/list.hpp>
5+
#include <boost/optional.hpp>
6+
#include <boost/static_string/static_string.hpp>
7+
8+
int main() {
9+
bool ok = true;
10+
11+
// container: an STL-compatible vector that is not std::vector.
12+
{
13+
boost::container::vector<int> vec;
14+
for (int i = 0; i < 100; ++i) vec.push_back(i);
15+
ok = ok && vec.size() == 100 && vec.back() == 99 && vec[42] == 42;
16+
}
17+
18+
// intrusive: the list only links; ownership stays with the nodes.
19+
{
20+
namespace intr = boost::intrusive;
21+
struct Node : intr::list_base_hook<> {
22+
int v;
23+
explicit Node(int x) : v(x) {}
24+
};
25+
intr::list<Node> lst;
26+
Node a(1), b(2), c(3);
27+
lst.push_back(a);
28+
lst.push_back(b);
29+
lst.push_back(c);
30+
ok = ok && lst.size() == 3 && lst.front().v == 1 && lst.back().v == 3;
31+
32+
lst.pop_front();
33+
ok = ok && lst.front().v == 2 && a.v == 1; // a outlives its unlinking
34+
35+
lst.clear(); // unlink everything: hooks must not die while linked
36+
ok = ok && lst.empty();
37+
}
38+
39+
// optional: empty/engaged lifecycle and value_or fallback.
40+
{
41+
boost::optional<int> o;
42+
ok = ok && !o && o.value_or(-1) == -1;
43+
44+
o = 9;
45+
ok = ok && o && *o == 9 && o.value() == 9;
46+
47+
o.reset();
48+
ok = ok && !o;
49+
}
50+
51+
// static-string: fixed-capacity string with a compile-time bound.
52+
{
53+
boost::static_strings::static_string<8> s("abc");
54+
s += "def";
55+
ok = ok && s == "abcdef" && s.size() == 6;
56+
ok = ok && s.compare(0, 3, "abc") == 0;
57+
}
58+
59+
return ok ? 0 : 1;
60+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// boost-core (addressof / empty_value / ref), boost-smart-ptr
2+
// (shared_ptr/weak_ptr/make_shared) and boost-move (movelib::unique_ptr).
3+
#include <boost/core/addressof.hpp>
4+
#include <boost/core/empty_value.hpp>
5+
#include <boost/core/ref.hpp>
6+
#include <boost/make_shared.hpp>
7+
#include <boost/move/make_unique.hpp>
8+
#include <boost/move/unique_ptr.hpp>
9+
#include <boost/shared_ptr.hpp>
10+
#include <boost/weak_ptr.hpp>
11+
12+
int main() {
13+
bool ok = true;
14+
15+
// core: addressof survives overloaded operator&, ref wraps without copies.
16+
{
17+
struct Tricky {
18+
int v = 7;
19+
Tricky* operator&() const { return nullptr; }
20+
} tricky;
21+
ok = ok && boost::addressof(tricky) != nullptr;
22+
ok = ok && boost::addressof(tricky)->v == 7;
23+
24+
auto r = boost::cref(tricky.v);
25+
ok = ok && r.get() == 7;
26+
}
27+
28+
// core: empty_value with a non-empty payload stores and returns it.
29+
{
30+
boost::empty_value<int> ev(boost::empty_init_t(), 42);
31+
ok = ok && ev.get() == 42;
32+
}
33+
34+
// smart-ptr: reference counting across shared/weak.
35+
{
36+
boost::shared_ptr<int> sp = boost::make_shared<int>(5);
37+
boost::weak_ptr<int> wp = sp;
38+
ok = ok && sp.use_count() == 1 && *sp == 5 && !wp.expired();
39+
40+
sp.reset();
41+
ok = ok && wp.expired() && wp.lock() == boost::shared_ptr<int>();
42+
}
43+
44+
// move: movelib::unique_ptr transfers sole ownership.
45+
{
46+
boost::movelib::unique_ptr<int> up = boost::movelib::make_unique<int>(11);
47+
boost::movelib::unique_ptr<int> up2 = boost::move(up);
48+
ok = ok && !up && up2 && *up2 == 11;
49+
}
50+
51+
return ok ? 0 : 1;
52+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// boost-io (stream state savers), boost-utility (compressed_pair) and
2+
// boost-winapi (WinAPI type shims — compilable only where Win32 exists).
3+
#include <boost/compressed_pair.hpp>
4+
#include <boost/io/ios_state.hpp>
5+
6+
#include <sstream>
7+
#include <string>
8+
#include <type_traits>
9+
10+
#ifdef _WIN32
11+
#include <boost/winapi/basic_types.hpp>
12+
#endif
13+
14+
int main() {
15+
bool ok = true;
16+
17+
// io: RAII flag saver restores the stream's formatting state.
18+
{
19+
std::ostringstream os;
20+
os << 255;
21+
ok = ok && os.str() == "255";
22+
23+
os.str("");
24+
{
25+
boost::io::ios_flags_saver fs(os);
26+
os << std::hex << 255;
27+
ok = ok && os.str() == "ff";
28+
}
29+
30+
os.str("");
31+
os << 255;
32+
ok = ok && os.str() == "255"; // hex did not leak
33+
}
34+
35+
// utility: compressed_pair — empty-base-optimized pair with accessors.
36+
{
37+
boost::compressed_pair<int, std::string> cp(3, "three");
38+
ok = ok && cp.first() == 3 && cp.second() == "three";
39+
40+
// Both members empty: compiles and stays stateless in practice.
41+
struct Nothing {};
42+
boost::compressed_pair<Nothing, Nothing> empty_pair{};
43+
ok = ok && sizeof(empty_pair) <= sizeof(Nothing) * 2;
44+
}
45+
46+
// winapi: the shims declare the Win32 surface themselves, but the
47+
// headers are Windows-only to compile (they #error elsewhere), so real
48+
// assertions run under the Windows CI leg only.
49+
{
50+
#ifdef _WIN32
51+
ok = ok && std::is_pointer<boost::winapi::HANDLE_>::value;
52+
ok = ok && std::is_integral<boost::winapi::DWORD_>::value;
53+
ok = ok && sizeof(boost::winapi::DWORD_) >= 4;
54+
#endif
55+
}
56+
57+
return ok ? 0 : 1;
58+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// boost-mp11 (list metaprogramming), boost-describe (enum reflection),
2+
// boost-preprocessor (token repetition), boost-type-index (runtime type
3+
// identity) and boost-predef (platform/compiler detection).
4+
#include <boost/describe.hpp>
5+
#include <boost/mp11/algorithm.hpp>
6+
#include <boost/predef.h>
7+
#include <boost/preprocessor/cat.hpp>
8+
#include <boost/preprocessor/repetition/repeat.hpp>
9+
#include <boost/preprocessor/stringize.hpp>
10+
#include <boost/type_index.hpp>
11+
12+
#include <string>
13+
14+
// Enumerators must be visible at global scope for the describe macros.
15+
enum class Color { red = 1, green = 2, blue = 4 };
16+
BOOST_DESCRIBE_ENUM(Color, red, green, blue)
17+
18+
#define FAMILY_INC(z, n, d) + (n)
19+
20+
int main() {
21+
bool ok = true;
22+
23+
// mp11: list size and per-type iteration.
24+
{
25+
using L = boost::mp11::mp_list<int, long, char>;
26+
ok = ok && boost::mp11::mp_size<L>::value == 3;
27+
28+
int total = 0;
29+
boost::mp11::mp_for_each<L>([&](auto t) { total += sizeof(decltype(t)); });
30+
ok = ok && total > 0 && total >= 3;
31+
}
32+
33+
// describe: enumerate (name, value) pairs without RTTI tricks.
34+
{
35+
int count = 0;
36+
bool blueNamed = false;
37+
boost::mp11::mp_for_each<boost::describe::describe_enumerators<Color>>(
38+
[&](auto d) {
39+
++count;
40+
if (d.value == Color::blue)
41+
blueNamed = std::string(d.name) == "blue";
42+
});
43+
ok = ok && count == 3 && blueNamed;
44+
}
45+
46+
// preprocessor: stringize/cat composition and unrolled repetition.
47+
{
48+
ok = ok && std::string(BOOST_PP_STRINGIZE(BOOST_PP_CAT(fo, o))) == "foo";
49+
50+
int total = BOOST_PP_REPEAT(5, FAMILY_INC, 0); // + 0 + 1 + 2 + 3 + 4
51+
ok = ok && total == 10;
52+
}
53+
54+
// type-index: runtime type identity with a readable name.
55+
{
56+
namespace ti = boost::typeindex;
57+
ok = ok && ti::type_id<int>() == ti::type_id<int>();
58+
ok = ok && ti::type_id<int>() != ti::type_id<long>();
59+
ok = ok && std::string(ti::type_id<int>().pretty_name()).find("int") !=
60+
std::string::npos;
61+
}
62+
63+
// predef: the platform and compiler we run the index's CI on must be
64+
// detected (predef defines every macro, 0 when not detected).
65+
{
66+
ok = ok && (BOOST_OS_LINUX || BOOST_OS_MACOS || BOOST_OS_WINDOWS) != 0;
67+
ok = ok && (BOOST_COMP_CLANG || BOOST_COMP_GNUC || BOOST_COMP_MSVC) != 0;
68+
}
69+
70+
return ok ? 0 : 1;
71+
}

0 commit comments

Comments
 (0)