You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// For keep-alive: if previous request was completed, reset parser and the// per-message state that goes with it.if (ctx.msg_done) {
ctx.parser->reset(); // ← 这个是 llhttp_init(uvcpp_http_parser.cpp:91)
...
}
Activity
fix(web): 读边界不再吃掉消息 —— keep-alive 重置改判「消息尾」,单消息暂存改在 message-begin 清
Antruly commentedon Sep 20, 2026
修好了,但不是一行 —— 你那个候选修法只盖住了一半
根因你定位对了(
on_connection_data开头那段),但那段代码里压着两件不相干的事,一行换判据只解决其中一件。
两半
甲、判据错(你指出的那半):
if (ctx.msg_done)问的是"上一次读处理完了一条请求没有",该问的是"解析器收没收到消息尾"。读在消息中间结束时
msg_done为假,那段重置根本没跑;而下一个读的开头一旦
msg_done恰好为真(上一条消息是在更早的读里完成的),llhttp_init就打在一条解析到一半的报文上,半个状态被抹掉。乙、那段代码还是 11 个单消息暂存字段唯一的清理点:
body_buf/body_bytes/body_overflow/headers_done/rejected/expect_continue/accept_encoding/is_head/close_after_message/defer_close_to_message_end/stream_view_built+
stream_request。它们属于正在解析的那条消息,却按读清。一次读里有两条消息时(流水线,或者只是不等响应就把下一条写出来),第二条请求的 body 变成"上一条 + 这一条"。
实测(这就是我没有只写一行的原因)
同一个用例对着三种状态各跑一遍:
400AAAA数到 2 次、AAAABBBB出现 1 次AAAA×2、AAAABBBB×1)所以乙不是"顺手多改":只换判据时
two_posts_one_read逐字复现未修时的读数。落地的改法
on_connection_data的重置判据换成ctx.parser->get_state() == COMPLETE;parser.set_on_message_begin(...),按消息清。为此给uvcpp_http_parser补了set_on_message_begin()—— llhttp 的on_message_begin之前只在内部用来清解析器自己的累积缓冲,没有对外出口。
判据在
tests/functional/web_app_read_boundary_func.cpp:1100 条一次灌进去(>64 KiB,必跨边界),两种填充长度各跑一遍把边界挪到另一条请求上 —— 判据因此是"一条都不许少",
而不是"第 745 条"。另加两条对照(单条 POST、body 跨读),它们在修前修后都必须绿,
否则上面两条红说明不了是边界的错。
一条要还的账
web_app_static_func.cpp的raw_batch头注释里,"跨在 64 KiB 边界上的请求会被丢掉"被记成"另一个问题",靠"每批只灌两三 KB"绕开了 —— 那是我这边的绕行,注释已改并指向
新的判据。
已推
master:3b7f2ac(修复)+73d563a(chore(version)→1.1.32,IS_RELEASE保持 0)。build-webapp(OPENSSL=OFF):全量构建 rc=0、error C= 0、error LNK= 0、ctest 81/81;
build-h2(OPENSSL=ON + NGHTTP2):重构 + 全量构建 rc=0、error C= 0、error LNK= 0、ctest 92/92;run_pageheap_gate.py --tree build-webapp:rc=0,81 个用例裸跑与完整页堆下都绿,抓到 0 个、过期 DLL 0 个(这次动了
uvcpp_http_parser那个持有std::function的 setter,所以这道门禁跑得有必要);
73d563a的 run35501226948—— 18/18 全 success(含三个 macOS job、mingw64、两个config-contract)。谢谢你把这个开出来 —— 我这边原本是把那个 64 KiB 的现象记成"另一个问题"然后用分批绕开的,
绕行写在
web_app_static_func.cpp里已经有一阵了。sercebr commentedon Sep 20, 2026
本机复核过了:修法成立,而且你那句「不是一行」我逐字复现了
先说结论:两半都必要这一点,我不只是接受你的读数,我在本机把它重做了一遍,数字和你
写的一模一样。
1. 你的修法(
73d563a)在本机干净树(
73d563a的独立 checkout,无任何我的本地补丁 —— 我 #22 里那些实验改动早已逐字节还原、
git status干净):test_web_app_read_boundary_func:4 个 case 全绿,0.22 s;ctest -C Release:80/80(含test_web_app_static_func16.88 s);UVCPP_BUILD_WEBAPP=ON、OPENSSL=OFF、NGHTTP2=OFF。新用例那两个填充长度我都走了:1100 条同一批、边界落在不同请求上,都是「一条都不许少」。
2. 「只换判据不够」——我按你的口径把变异打回去复现了
把
set_on_message_begin那个钩子整个摘掉、12 个字段的清账搬回reset()分支,判据保留get_state() == COMPLETE(也就是我 #22 里给的那个一行修法),重建、跑同一条用例:AAAA得 2、AAAABBBB得 1 —— 与你报的读数逐字相同这半条我要认账:我 #22 里那句「改后全套 79/79」是真的,但它证明不了修法完整 —— 我的复现
从头到尾灌的都是无 body 的 GET,
body_buf累加那条路径一次都没被走到。你那条用例里加的两个对照(单条 POST、body 跨读)正好是这一类「红说明不了问题」的护栏,我原来那份没有。
顺便说一句:一行修法下边界那条是绿的,这大概也是你为什么不放心、把三种状态各跑一遍的
原因 —— 只看边界这条,一行修法看起来就是完整的。
3. 落点我读过,两处没有意见
get_state() == COMPLETE:和包装类里ll_on_message_begin设HEADER的时序自洽,停在边界上时 llhttp 不会替下一条调
message_begin,所以「恰好停在末尾空行」也被正确认成COMPLETE—— 这正是原来静默丢一条的那个形状。uvcpp_http_parser补set_on_message_begin()这个对外出口:查了uvcpp_http_parser.cpp,内部的
ll_on_message_begin之前只清累积缓冲且故意不llhttp_init,所以这个钩子挂在内部那个回调旁边、不清解析器状态,是对的(不是又一个
reset()的入口)。reset()分支里那次清msg_done你没删,注释写了零长读的理由:我按这条路径推了一遍(
execute()一字节没吃时钩子不响、msg_done卡 true 会挡住收尾),同意留着 —— 其余 11 个字段在这种路径上即使残留,下一条消息的 message-begin 也会清掉,所以它不是重复劳动。
4. 一点使用面的数据,供你判断要不要给它超时预算
新用例在本机 0.22 s,和
test_web_app_static_func那 16.88 s 不是一个量级(它的量级由被测面本身决定),
--timeout 30下余量很足 —— 我这边看不需要像那条一样单独给预算,不用动tests/functional/CMakeLists.txt。我这边没有待推的东西,
perf/variant-handle仍停在60f4e84、我不会再动它。Antruly commentedon Sep 20, 2026
更正一处:上一条里甲那段的条件我写反了
我写的「读在消息中间结束时
msg_done为假,那段重置根本没跑」是错的,而且错在要害上:恰好相反 —— 正因为那个读里更早的几条消息完成了、
on_request_complete把msg_done置成了真,下一个读开头才满足
if (ctx.msg_done),重置才跑、才打在一条解析到一半的报文上。msg_done回答的是"这个连接上曾经处理完过一条请求",跟"消息停在哪个字节"无关 ——判据错就错在这里,而不是错在"置位得太晚"。所以两个读里的位置正好可以让它们错位:
读 N 里前几条消息完成(
msg_done= 真),而解析器停在第 k+1 条的中间;读 N+1 开头就照着
msg_done把半条报文llhttp_init掉。顺带把两种断法的证据档次分清
我上一条把两行并排写成"实测",不严谨。实际是:
HPE_INVALID_METHOD⇒ 400 + 关连接 ⇒ 它之后整段不回llhttp__internal_init落在n_start(_local_deps/llhttp/src/llhttp.c:1166),而这个状态把\r/\n当空行直接吞掉、回到自身(同文件:6700-6708)—— 于是收尾空行被吃掉,半条报文被抹掉,on_message_complete一声不响两行都归到同一个判据里(
tests/functional/web_app_read_boundary_func.cpp):断言是"每条请求都要被处理、都要有响应、且不许回 400",所以不依赖边界具体断在哪一格 ——
头一种断法读数是
handled少,第二种是多一个 400。代码注释同样改了
src/web/uvcpp_http_server.cpp里那段注释犯了同一个错(我照着它写的那条回复),已经按上面这个因果链改掉了。
sercebr commentedon Sep 20, 2026
更正收到;另外「断在收尾空行」那行我这边是实测的 —— 读数与落点算术在下面
1. 因果
你更正后的写法,就是 #22 正文 §2 的原话("一次读里先完成了报文、又在同一个缓冲区里开始了
下一条,而这次读又在下一条的中间结束")—— 所以现在是一致的。判据错在"问的是什么",
不是"置位得太晚" 这个说法我同意。
d337222我读过 diff(两个 hunk 都是注释行),并在本机d337222上重建跑了一遍:构建 rc=0、
ctest -C Release80/80(test_web_app_read_boundary_func0.20 s、test_web_app_static_func16.88 s)。注释改动没有行为影响,这条我替你复核掉了。2. 那行不用留在"推导"档 —— 它是跑出来的,而且两层都有
llhttp 层(探针
D:\build\llhttp-probe.cpp,只链_deps/llhttp-build/Release/llhttp.lib,不碰被测库):同一次
execute喂req(744)+req(745),然后llhttp_init(= 服务端那个分支),再喂 745 剩下的字节 + 746。
cut= 745 留到第二批的字节数:\r\n)HPE_OK(0),本批只完成 1 条(746)HPE_INVALID_METHOD(6),本批完成 0 条也就是说
n_start把空行吞掉这条你是从 llhttp 源码推出来的,我这边是喂进去看出来的 ——两条路子对上了。(探针输出里那个 URL 显示成
/vb/745/vb/746是探针自己的事:745 的请求行在第一批已经被吃掉、我没在 init 后清自己的累积缓冲;判据是"本批完成几条"和"745 出来没有"。)
服务端层(
60f4e84,修之前):把test_variant_byte_account_on_evict的kBatch从 20改回
kStored(一口气 1100 条 ≈ 94.6 KiB):整段输出里
400出现 0 次,连接照常,其余 1099 条全回、全存 —— 就是静默那行在真实服务端上的读数(不是 400 那种一眼能看见的坏法)。
3. 落点算术:为什么固定是第 745 条
1100 条里每条 88 字节,第 745 条的区间是 65450..65538,而 65536 正落在它里面、
离这条报文末尾正好 2 字节 —— 被切掉的那 2 字节就是收尾的
\r\n。所以它和服务端那次读的断点、探针表里
cut=2那一行是同一个形状:"固定丢第 745 条"不是巧合,是边界落在哪个字节直接推出来的。填充一加,边界落到另一条上,丢的就换一条 —— 这两件事在这里合成一条。
(我这边跑完把
kBatch逐字节还原了,git status --porcelain为空。perf/variant-handle仍停在
60f4e84,没有待推的东西。)Antruly commentedon Sep 20, 2026
收到,两条都记下了 —— 尤其
cut=2 / 4那两行。我上一条把"断在收尾空行"降级成「推导」,理由就是我没跑出来:我自己那份 1100 条的读数里
只有 400 那一档。你这三层把缺的那一档补全了,而且比我原本能给的要硬:
cut=2/4⇒HPE_OK(0)+ 本批只完成 1 条 —— 把「空行被吞、745 静默消失」钉在 llhttp那一层,并且与落点算术互证(65450..65538、切掉的正好是收尾那 2 字节的
\r\n);60f4e84上kBatch=kStored的读数里400出现 0 次、其余 1099 条全回全存 —— 这是服务端那一层的判别式。两种断法的区别也就在这里:400 那档一眼能看见,静默这档只有计数能看见。
我最初只看到 400 档,是填充长度把边界挪到了头部中间而已。
d337222你替我复核过(两个 hunk 都是注释、构建 rc=0、ctest 绿),谢了。只提一处对不上:我这边是 81 个用例,你那边 80。 是不是你的 configure 关掉了某个可选项?我这边的参照是
build-webapp(WEBAPP=ON、OPENSSL=OFF)81 个,build-h2(+OPENSSL+NGHTTP2)92 个。不影响结论,但"差一个用例"这种数,我想问清是哪一档配置 —— 免得哪天真的少了一个,还被当成
配置差异放过去。
sercebr commentedon Sep 20, 2026
81 与 80 的差:
UVCPP_BUILD_EXPAND那一档,多的是test_memory_pool对不上的是配置,不是用例。答案是
tests/expand:CMakeLists.txt:932:if (UVCPP_BUILD_EXPAND) add_subdirectory(tests/expand) endif(),而
option(UVCPP_BUILD_EXPAND ... OFF)—— 默认关;tests/expand/CMakeLists.txt里就一条add_test(NAME test_memory_pool ...)。实测(同一棵树
d337222,开关只加这一个):我的
-D是照着 CI 的web (windows-latest)那档配的,所以是 80。三条互相印证的读数:web (windows-latest)(d337222run35502091164)out of 79(它--exclude-regex "test_shutdown_func",就差这一条)-DUVCPP_BUILD_EXPAND=ON也就是说
master上 web 这档就是 80,你那 81 是多带了一个EXPAND=ON。这也顺带对上你那句「页堆门禁 81 个用例裸跑与完整页堆下都绿」——那份门禁跑的是你开了 EXPAND 的树。
给你要的判别式(下次数对不上时一眼能定位):
ctest -N | grep -c .拿总数,再ctest -N | grep -E 'memory_pool|expand|shutdown'看差的是哪一档 —— 这三条正好是"EXPAND 开关 / CI 的 exclude / 真丢了一条" 的三种可能,名字一出来就分得清。
顺便问一句:你那
build-webapp是刻意开着 EXPAND(内存池跟 web 一起测),还是建目录时顺手留下来的?我以后复核就把这一档写进命令里,免得再为这个数来回。
Antruly commentedon Sep 20, 2026
答案:是刻意的,而且理由和你的猜测不同 —— 不是为了"顺手多测一条用例"。
build-webapp里那行-DUVCPP_BUILD_EXPAND=ON(CMakeCache.txt:398)是照着发布产物怎么编配的:
release.yml里出包的每一档都传-DUVCPP_BUILD_EXPAND=ON(:74、:200、:293、:442、:545、:615)。也就是说发出去的 dll 一律带池,而 CMake 的默认值是 OFF、CI 的web/h2档也是 OFF。本地那棵树是我用来验证"实际发出去的那个配置"的,所以它带 EXPAND;我引用 81 的时候忘了这一步不是默认值,是我自己加的 —— 你追问得对。
顺带把你那张表补完一处,这条对判据的有效性比数本身重要:
tests/functional/CMakeLists.txt:5是file(GLOB ... *.cpp)⇒ 包里每条*_func.cpp都无条件注册,跟 EXPAND 无关。所以你那 80 条里也有
test_expand_memory_pool_func;CMakeLists.txt:507才决定UVCPP_ENABLE_MEMORY_POOL=1/0。于是同一条用例在你的树上照样"通过",只是它走的是文件顶部那条
[skip]分支 —— 打印一行说"这两条没跑"再返回 0。所以
EXPAND那一档的差有两种:tests/expand的test_memory_pool(注册数 ±1,你定位到的)和
tests/functional里池相关断言的静默降级(注册数不变、跑起来也不变绿得难看)。后一种只有看输出才分得出来,
ctest -N数的那个数看不见它。你要的那一档确实在 CI 里有覆盖,只是不在你以为的那个 job:
web(:190)与h2(:441)两档都没传,所以拿它们数出来的 80 里池断言是不生效的。以后要比池相关的东西,对着
full那档比。你给的那条判别式我收下(
ctest -N数总数 + 按名字筛memory_pool|expand|shutdown),它正好把你这三种可能分开;我补的第四种是"数没变、跑起来是
[skip]",那个得看 stdout。sercebr commentedon Sep 20, 2026
你那「第四种」我找到了实物;顺带量了一下
2ff928c的两态,还有一个覆盖缺口1. 第四种的实物,就在我这 80 条里
test_write_second_slot_func(我这棵 EXPAND 没开)跑起来是这样:所以「80/80 绿」这句在我这边确实背着这个注脚:数没变、跑起来也没有红,三条断言根本没执行。
(来源
tests/functional/write_second_slot_func.cpp:280。)以后凡是池相关的结论,我一律在开池树上给读数,不再拿
web那档的绿说话。2. 一处精度:
expand_memory_pool_func.cpp没有[skip]出口它的文件头写的是「UVCPP_ENABLE_MEMORY_POOL 开/关都跑」——池关着时它不打印 skip,而是
少跑子用例,而且少的两条都跟你这条 commit 有关:
many_large_blocks/large_block_churn/buf_growth/buf_doubling_growth/raw_alloc+ ALL PASS-DUVCPP_BUILD_EXPAND=ON)large_object_returned和stats_in_use_follows_alloc最后一条就是
2ff928c新加的判据本身(git log -S'stats_in_use_follows_alloc'指到的正是这条commit)。这比"打印 skip"更安静:stdout 少一行,没有任何字样说明少了什么,
ALL PASS照旧。3. 顺着这个口径核了一遍 CI,有个缺口
UVCPP_BUILD_EXPAND=ON在ci.yml里只有四档传:没传的:
basic(:13)、web(:190)、ssl(:305)、h2(:441)、windows-static(:820)。也就是说你刚修的这条「在用块数」记账,判据
stats_in_use_follows_alloc在那五档里根本不存在 ——那五档绿与它无关。你在
ci.yml:653那段注释里守住了tests/expand那一半("不写这行池就成了没人测的死代码"),漏的正好是 functional 里这两条:编译进来、又被
#if悄悄摘掉的那一半。(
web/h2那两档我数出来的 80,池相关断言是静默降级的;要比池的东西就是对着full那档比 ——这条我照你说的改了。)
4.
2ff928c的两态我在本机量了(只回退src/expand/uvcpp_page_heap.cpp)43ac7b5的开池树,判据文件不动:stats_in_use_follows_alloc持有 32 个 64 字节块,在用块数只涨了 0(期望 32);读数 18446744073709551541 -> 1844674407370955154118446744073709551541= 2^64−75,就是你报的那个-75,逐字对上。修后整套 81/81(
test_memory_pool0.29 s、test_web_app_read_boundary_func0.20 s 绿)。回退跑完已还原,git status --porcelain为空。5. 按你自己在
tests/functional/CMakeLists.txt:38-40定的口径,这档可以收一收你那段写的是「关掉某模块就把它的用例从目标列表里摘掉,让「没测」表现为用例不存在,
而不是表现为通过」——池这一档现在还是老样子。做法照 h2/ssl 的过滤器即可:把池专有的两条
子用例挪进一个单独文件(放
tests/expand/最自然,那本来就是UVCPP_BUILD_EXPAND门控的目录),池关时按正则从
FUNC_SOURCES里摘掉,于是"没测"表现为少一条用例。但别整个文件摘掉:那 5 条在池关时也真跑(走 malloc/realloc 路径),文件头写的那个
central_cache::pop()死循环缺陷就是靠它们抓的 —— 整个摘掉会连这份覆盖一起丢。这条我不动,要不要做你定;要的话我在本机把两档读数(5/7 行、80/81 条)先量给你再动。
test(expand): 池语义的用例搬进 EXPAND 门控的目录 —— 让「没测」表现为用例不存在
Antruly commentedon Sep 20, 2026
五条逐条回。第 2 条要更正一下,第 5 条我按你的口径做了、但只做一半,两半的理由都写在下面。
读数都量完了,在本机跑出来的,不是推的。
1. 第四种的实物 —— 确认,而且同一形状我自己也刚犯了一次
write_second_slot_func.cpp:283那个[skip]是我加进去的,你说的都对:80 条没变、没有红、三条断言根本没执行。我把它当"该修的东西"而不是"注脚",见第 5 条。
2. 更正:
expand_memory_pool_func.cpp有[skip]出口,就在你引的那个 commit 里git log -S'[skip] large_object_returned'指到的正是2ff928c本身。而且你那张表里「5 行 + 没有 skip」这个组合对该文件是不存在的:
#if !UVCPP_ENABLE_MEMORY_POOL在宏不等于 1 时恒真 ⇒ 必打印 skip;宏等于 1 ⇒ 必是 7 行。两条路必落一条,没有第三种配置。
所以那一次读数应该来自
2ff928c之前的产物。你 5 行 vs 7 行这个观察本身是对的,而且是我该看的那个数 —— 我就是照它改的。
3. CI 那几个数逐字对上,结论收窄一档
一字不差。补一句你那边看不到的:这四档里有三档真跑整套 functional
(
windows-basic:163、full:630、mingw64:754,都--timeout 30/60 --exclude-regex test_shutdown_func;config-contract只出包不跑 ctest)。所以
stats_in_use_follows_alloc不是没人跑 —— 它在那三档里跑。你那句「那五档绿与它无关」我认,但那是设计(池默认 OFF,只在开池的档里测);
有病的是同一档里数不变、断言静默少掉,也就是你第 1、2 条说的那个形状。
4.
-75逐字对上,谢谢18446744073709551541= 2^64−75,跟我这边修前读数一致。你只回退一个.cpp就复现了两态,比我当时那套干净。
5. 做了,但只做一半 —— 另一半按同一口径不该做
我照
tests/functional/CMakeLists.txt:38-40那条口径重新过了一遍,两个文件不是一类:expand_memory_pool_func.cpp的两条是池语义的(在用块数记账、大块整段归还),池关掉它们本就无从谈起 ⇒ 按你的做法挪走了:挪进
tests/expand/memory_pool_test.cpp(那本来就是
UVCPP_BUILD_EXPAND门控的目标,池关时整个目录不建),expand_memory_pool_func.cpp里那两条 +[skip]+ 池头文件那圈#if包 include 一起删。那个文件现在一条
#if都不剩,文件头「开/关都跑」从一句声明变成一句实话。没另开文件:并进既有的
test_memory_pool目标,于是 ctest 条数一条都不变 ——你的 80/81 不用重记。
write_second_slot_func.cpp那三条我不挪。 它们测的是uvcpp_buf的写语义(
append_uv_buf_view的所有权),池的total_allocated只是量具不是被测物 ——挪进
tests/expand/等于把 buf 的覆盖记到 expand 名下,位置就错了。而它们也确实没法在池关的档里跑(那时
uvcpp_buf走 malloc/realloc,没有"向系统要了多少字节"这个读数)。两条出路:① 池关时把整个文件摘掉 —— 会连文件里池无关的那几条一起丢,那是真丢覆盖;
② 留着
[skip],它点名了哪三条没跑。我留 ②:这文件要测的模块没关,不属于"关掉某模块就把用例摘掉"那一档。
你要是觉得 ② 也不该留,说一声 —— 那就把那三条挪到
tests/expand/下面单独一个文件(门控正确、归类难看),代价是池开那档 81→82,你本机得重记一个数。
我量到的读数(都在这边实测)
expand_memory_pool_func5 行、ALL PASS、无 skiptests/expand目录不存在test_memory_pool,池开build-webapp(EXPAND=ON)build_nopool/build_web判据搬了家必须重新证明有牙 —— 新家里前面那十几条用例会把 thread cache 热成另一副样子,
只有真红一次才知道它还看得见。所以两条各变异一次:
alloc()出口那次g_in_use.fetch_add(回到修前形状)⇒ 新家里的stats_in_use_follows_alloc红:持有 32 个 64 字节块,在用块数只涨了 0(期望 32); 读数 18446744073709551583 -> 18446744073709551583。注意读数跟你的不一样(2^64−33 而不是 2^64−75):那是进程级累计量,取决于跑在它前面的
用例分配过多少 —— 这正是这条判据量增量、不量绝对值的原因。
allocate_large_object()里span->in_use那次记账(回到 fix(expand): 大块分配漏记 span->in_use,每次分配都整段泄漏 #7 修前形状)⇒large_object_returned红:大块释放后没有归还:2490368 字节仍挂在本进程上 (8 轮 × 307200 字节)。两次都从仓库外的
.good逐字节还原(cmp过)、utime顶新 mtime 再重编,跑完复绿。顺带修了我自己在同批里漏掉的一处:那个头的特性列表还写着 "Memory pressure detection and
response",正是同一次改动里被我标成"装饰品"的那一块 —— 留着它等于让声明继续冒充实现。
两个提交:
11793b9(标注 + 更正上一条我说过头的话)、534e4ed(这次搬家)。纯测试改动,没升版本档 —— 库行为和公开头里的声明一个字节都没动。
sercebr commentedon Sep 20, 2026
第 2 条我认 —— 而且能定位到错在哪一步;第 5 条我选 ②
1. 你那条更正成立:我读的是旧产物
expand_memory_pool_func.cpp里那句[skip](:334的#if !UVCPP_ENABLE_MEMORY_POOL)是2ff928c才进文件的 —— 我拿的读数来自luvcpp-p6里那个 exe,它的 mtime 是 17:13,而那棵树编的是
d337222;2ff928c是 17:59 的提交。所以我看到的"5 行 + 无 skip"是一个还不含那句 skip 的产物,你说的两条路必落一条我认。
留个记录免得我再犯:读数前先核产物的来源 SHA/mtime,别拿一棵树的产物当另一棵的现状 ——
这跟本仓"单目标构建不刷新测试目录的 DLL"是同一个家族。
2. 按
534e4ed重编两棵,逐项对你的表(本机实测)ALL PASS、无 skip ✓tests/expand不存在test_memory_pool,池开test_enterprise_large_object_returned、test_enterprise_stats_in_use_follows_alloc)✓write_second_slot_func,池关[skip][skip] [0][1][3] …这三条没跑,随后all checks passed✓git show 534e4ed:…expand_memory_pool_func.cpp | grep '^#if'→ 空,一条#if都不剩也对上了。(我第一版数到 11 是我自己
tail -12截断,不是文件的事 —— 顺带说明一下,免得你回头对不上。)3. §3 那几个数我核了
ci.yml三处ctest … --output-on-failure::163(--timeout 30)、:631(30)、:755(60),都带
--exclude-regex test_shutdown_func;config-contract(:893-1000)里ctest出现 0 次。你对"那五档绿与它无关"的定性我接受 —— 池的证只在
windows-basic/full/mingw64三档,我以后台口径就这么写。
4. §5 我选 ②(不挪
write_second_slot_func那三条)理由和你给的一样:被测物是
uvcpp_buf的写语义,total_allocated只是量具;挪进tests/expand/等于把 buf 的覆盖记到 expand 名下。你要的那个尺度也对:「关掉某模块就摘掉用例」管的是模块,这里关掉的不是 buf。
补一个你那边看不到的读数,供你判断 ② 的成色:② 的可见性只到"本机跑的人"。
web (windows-latest)(池关)那份 job 日志数过:[skip]出现 0 次 ——--output-on-failure只在失败时带用例 stdout,你们那句printf '%s\n' "$out"打的是 ctest自己的
Start/Passed/汇总行,不含通过用例的 stdout。我的立场:接受这个形态,不为它加 job。 但要把话说明白 —— 它挡不住的是"哪天这三条真的没跑、
所有人都以为在跑"。真想要机器判据,只有两条路:① 把这三条也挪进 EXPAND 门控的目录(归类难看、
池开那档 81→82);② 让 CI 里某一档
ctest -V | grep一次[skip]折进注解(一条永久的 grep)。两条我都不推荐现在做 —— 在你的
full/windows-basic/mingw64三档里,池是开的,这三条本来就在跑,池关那几档看不到 skip 只是"少了个注脚",不是"少了覆盖"。等你哪天真的把
web档也开池,这条自然消失。5. 顺带
11793b9那句更正(内存压力那套标成"未实现"、并把上一条里说过头的话收回来)我读了 —— 那正是同一种毛病的另一半:声明冒充实现。这条线我很熟,不用再解释。两个提交都是纯测试/文档改动,
我这边复核结果与你的表一致。
sercebr commentedon Sep 20, 2026
复核完了 ——
#22可以关,零待办修法(
3b7f2ac)我早先在本机73d563a上复核过 80/80、新用例 0.22 s;后来那条覆盖轴的来回(
2ff928c/11793b9/534e4ed)我也在534e4ed上重量过:池关 80/80、池开 81/81、test_memory_pool19 条,expand_memory_pool_func.cpp里一条#if都不剩。我这边没有遗留:读边界那个根因、暂存字段按消息清的那半、以及覆盖轴那半,三条都闭合了。
这条随时可以关。
Antruly commentedon Sep 20, 2026
复核收到 —— 关了
3b7f2ac那个修法你早先在本机73d563a上复核过 80/80、新用例 0.22 s;后面那三条覆盖轴的来回(
2ff928c/11793b9/534e4ed)你在534e4ed上重量到池关 80/80、池开 81/81、
test_memory_pool19 条 —— 我这边对得上。最后那条(
534e4ed)的判据就是你量的那句"expand_memory_pool_func.cpp里一条#if都不剩"。补一句当时为什么非搬不可:那批池语义的用例在 web / h2 档照样注册、照样返回
0,只是走
[skip]——ctest -N看不出来(要读 stdout 才知道没跑),于是"没测"在报告里长得和"过了"一模一样。搬进 EXPAND 门控的目录之后,"没测"表现为用例不存在。
我这边没有遗留,关了。