expect-pty 0.5.3 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +28 -19
  4. data/docs/API.md +88 -0
  5. data/docs/MIGRATION.md +15 -0
  6. data/lib/expect/cleanup.rb +33 -0
  7. data/lib/expect/configuration.rb +87 -66
  8. data/lib/expect/interaction.rb +226 -209
  9. data/lib/expect/logging.rb +157 -156
  10. data/lib/expect/matcher.rb +30 -29
  11. data/lib/expect/pattern.rb +8 -2
  12. data/lib/expect/pattern_list.rb +35 -5
  13. data/lib/expect/redactor.rb +11 -4
  14. data/lib/expect/relay.rb +97 -73
  15. data/lib/expect/relay_writer.rb +2 -1
  16. data/lib/expect/result.rb +32 -8
  17. data/lib/expect/session.rb +508 -0
  18. data/lib/expect/session_resources.rb +10 -2
  19. data/lib/expect/terminal.rb +78 -78
  20. data/lib/expect/version.rb +1 -1
  21. data/lib/expect.rb +333 -520
  22. data/sig/expect.rbs +355 -0
  23. metadata +13 -106
  24. data/.rubocop.yml +0 -66
  25. data/CONTRIBUTING.md +0 -29
  26. data/Gemfile +0 -28
  27. data/Rakefile +0 -38
  28. data/benchmark/matching.rb +0 -98
  29. data/benchmark/redactor.rb +0 -64
  30. data/benchmark/relay.rb +0 -48
  31. data/benchmark/scaling.rb +0 -70
  32. data/benchmark/send_slow.rb +0 -41
  33. data/benchmark/support.rb +0 -114
  34. data/docs/COMPATIBILITY.md +0 -98
  35. data/docs/INTERNAL_CONTRACTS.md +0 -154
  36. data/docs/PERFORMANCE.md +0 -165
  37. data/docs/RELEASING.md +0 -84
  38. data/docs/VERIFICATION.md +0 -456
  39. data/examples/dialogue.rb +0 -30
  40. data/examples/kibitz/README.md +0 -81
  41. data/examples/kibitz/kibitz.rb +0 -142
  42. data/examples/kibitz/test_kibitz.rb +0 -37
  43. data/examples/ssh_auto.rb +0 -94
  44. data/examples/ssh_interact.rb +0 -159
  45. data/examples/ssh_login.rb +0 -64
  46. data/expect-pty.gemspec +0 -33
  47. data/script/ci +0 -121
  48. data/script/release.rb +0 -319
  49. data/test/buffer_accounting_test.rb +0 -83
  50. data/test/cleanup_test.rb +0 -251
  51. data/test/compare_upstream.rb +0 -157
  52. data/test/configuration_test.rb +0 -133
  53. data/test/deadline_test.rb +0 -237
  54. data/test/diagnostics_test.rb +0 -353
  55. data/test/edge_case_test.rb +0 -262
  56. data/test/fixtures/ssh_scripts/01_identity.sh +0 -4
  57. data/test/fixtures/ssh_scripts/02_output.sh +0 -5
  58. data/test/fixtures/ssh_scripts/03_delayed.sh +0 -6
  59. data/test/fixtures/ssh_scripts/04_failure.sh +0 -2
  60. data/test/fixtures/ssh_scripts/05_recovery.sh +0 -3
  61. data/test/initialization_failure_test.rb +0 -92
  62. data/test/integration/README.md +0 -109
  63. data/test/integration/ssh_scripts.rb +0 -94
  64. data/test/interact_test.rb +0 -253
  65. data/test/interconnect_test.rb +0 -425
  66. data/test/io_test.rb +0 -321
  67. data/test/kibitz_test.rb +0 -45
  68. data/test/lifecycle_contract_test.rb +0 -71
  69. data/test/literal_scan_test.rb +0 -97
  70. data/test/matching_test.rb +0 -211
  71. data/test/multi_session_test.rb +0 -66
  72. data/test/ownership_sequence_test.rb +0 -208
  73. data/test/pattern_offset_test.rb +0 -43
  74. data/test/process_interruption_test.rb +0 -296
  75. data/test/process_test.rb +0 -291
  76. data/test/redactor_test.rb +0 -183
  77. data/test/relay_recovery_test.rb +0 -451
  78. data/test/relay_reentrancy_test.rb +0 -159
  79. data/test/release_test.rb +0 -375
  80. data/test/ruby_api_test.rb +0 -515
  81. data/test/scan_reuse_test.rb +0 -109
  82. data/test/script_logging_test.rb +0 -124
  83. data/test/support/interact_probe.rb +0 -125
  84. data/test/support/kibitz_probe.rb +0 -177
  85. data/test/support/script_probe.rb +0 -158
  86. data/test/terminal_cleanup_test.rb +0 -349
  87. data/test/test_helper.rb +0 -58
  88. data/test/timeout_test.rb +0 -289
  89. data/test/write_contract_test.rb +0 -105
data/docs/VERIFICATION.md DELETED
@@ -1,456 +0,0 @@
1
- # 验证记录
2
-
3
- ## v0.5.2 改进计划 T00–T07(2026-09-27,本地实施阶段)
4
-
5
- 以下是版本归档前的本地验证记录,对应改动随后归入 0.5.3。发布状态以 GitHub Release、对应 CI 和 RubyGems 为准。
6
-
7
- 基线为 `ac583532b5f4c946856e79ecd7350eb298019081`,开始时主工作区干净且 HEAD 等于本地 v0.5.2 标签。
8
- 本轮保留同步 IO、匹配优先级、默认 nil 期限、二进制缓冲及现有运行时依赖。版本仍为 0.5.2,变更记入 Unreleased;
9
- 没有提交、推送、创建标签、调用发布接口或登录真实 SSH。
10
-
11
- T00 在 macOS 26.6.2 arm64、Ruby 4.0.6、Bundler 4.0.17、Minitest 5.27.0 上执行原始 `bundle exec rake`:
12
- 61 个文件 lint 通过,346 项 / 6,604 断言,退出码 0,无失败、错误或跳过。
13
- 系统默认 Ruby 为 2.6.10,因此下列本机命令统一使用 Homebrew Ruby,不改全局配置:
14
-
15
- ```sh
16
- export PATH="/opt/homebrew/opt/ruby/bin:$PATH"
17
- export BUNDLER_VERSION=4.0.17
18
- bundle exec rake
19
- bundle exec rake test TESTOPTS='--seed=20260927'
20
- bundle exec rake test TESTOPTS='--seed=1'
21
- bundle exec rake test TESTOPTS='--seed=42'
22
- script/ci
23
- ```
24
-
25
- 计划中的 `TESTOPTS='--seed 20260927'` 在锁定的 Rake 13.4.2 上实际失败:加载器把独立的数字参数当作文件。
26
- 同一 `rake test` 入口改用 `--seed=...` 后,输出确认采用指定 seed;未修改加载器、依赖或测试门槛。
27
-
28
- ### 按任务核对红灯与绿灯
29
-
30
- 从基线建立独立 detached worktree `tmp/improvement-052/baseline`,只复制对应的新回归测试,逐文件重放旧行为。
31
- 下表红灯为该基线的真实失败,绿灯为修复后同一测试文件的独立运行;全部使用 seed 20260927。
32
-
33
- | 任务 | 修改与回归文件 | 旧版失败证据 | 修复后结果(测试 / 断言) |
34
- | --- | --- | --- | --- |
35
- | T01 / F01 | `lib/expect.rb`、`session_resources.rb`、`test/initialization_failure_test.rb` | 6 项失败:PTY 未关闭、open 用 NoMethodError 覆盖原中断 | 6 / 39,通过 |
36
- | T02 / F02 | 上述生命周期文件、`test/process_interruption_test.rb` | 3 项失败、4 项错误:EINTR 提前终止 wait/close,finalizer 未 detach,归属变化后仍 detach | 12 / 56,通过 |
37
- | T03 / F03 | `lib/expect.rb`、`interaction.rb`、`relay.rb`、`test/relay_reentrancy_test.rb` | 5 项失败:`abc` 变为 `abcabc`、重叠来源未拒绝、准备异常丢失缓冲 | 8 / 47,通过 |
38
- | T04 / F04 | `script/release.rb`、发布 workflow、`test/release_test.rb` | 2 项失败:中文说明在 US-ASCII 下无法解析,非法 UTF-8 缺少明确诊断 | 21 / 124,通过(含原有发布拒绝条件) |
39
- | T05 / C01–C02 | `lib/expect.rb`、`test/write_contract_test.rb` | 2 项失败:零计数依赖 watchdog 才退出,超出当前 chunk 的计数未拒绝 | 6 / 39,通过 |
40
- | T06 | `test/ownership_sequence_test.rb` | 组合回归,非新增独立缺陷 | 6 / 161,通过 |
41
- | T07 | README、内部契约、CHANGELOG、本记录 | 保留所有原测试及原有 CI 门禁 | 见下方完整验证 |
42
-
43
- F01 使用真实 IO/PTY 并注入构造与 close 故障;F02 包含真实孩子的 waitpid 中断、真实 fork 非创建者检查,
44
- 连续中断和 GC 路径另外使用受控时钟与全部系统调用替身。假 PID 不进入真实信号或回收调用。
45
- F03 使用公开 API、真实管道和自定义 writer 自然复现;F04 使用真实 CLI 子进程和中文文件。
46
- C02 是非法 IO 适配返回值注入,不能推断正常 Ruby IO 会返回这些值。C01 的持续成功短写特征在旧版及新版均通过。
47
-
48
- T06 的字节与多目标序列使用固定 seeds 20260927、1、42,核对各目标的完整内容、已确认计数、未处理缓冲、
49
- 转义消费、日志唯一性及原目标续发。真实 pipe EOF 与仍活跃孩子组合验证 IO/PID 相互独立,soft_close 只发 TERM,
50
- hard_close 后读取真实状态并确认 ECHILD。测试时钟与系统调用替身在 ensure 中恢复,watchdog 仅用于测试防挂起。
51
-
52
- ### 完整验证与发布预演
53
-
54
- 新增 40 项测试,最终本机 `bundle exec rake`:66 个文件 lint 通过,**386 项 / 6,965 断言**,退出码 0。
55
- 三个固定 seed 的默认套件也各为 386 / 6,965,退出码均为 0,无失败、错误或跳过。
56
- 原有 cleanup/process/terminal_cleanup、relay/interact/diagnostics、io/timeout/deadline 定向组合也全部通过。
57
-
58
- | 环境 | 完整 `script/ci` |
59
- | --- | --- |
60
- | macOS 26.6.2 arm64,Ruby 4.0.6 | 退出 0;386 / 6,965;66 文件 lint 通过 |
61
- | Linux aarch64,Ruby 3.2.11,`ruby:3.2` | 退出 0;386 / 6,965;66 文件 lint 通过 |
62
- | Linux aarch64,Ruby 3.3.12,`ruby:3.3` | 退出 0;386 / 6,965;66 文件 lint 通过 |
63
- | Linux aarch64,Ruby 3.4.10,`ruby:3.4-slim` | 退出 0;386 / 6,965;66 文件 lint 通过 |
64
- | Linux aarch64,Ruby 4.0.6,`ruby:4.0` | 退出 0;386 / 6,965;66 文件 lint 通过 |
65
-
66
- Linux 验证以只读源目录挂载到临时容器,复制到独立 `/work` 后,使用同一 Gemfile.lock、Bundler 4.0.17 与
67
- `BUNDLE_FROZEN=true` 执行原始 `script/ci`。3.4 slim 的 git 和构建工具仅安装在该临时容器。
68
- 完整脚本包含 dialogue 示例、matching/relay/send_slow/scaling/redactor 五组 smoke、Gem 构建、
69
- 普通 RubyGems 与最小 Bundler 消费方的隔离 PTY/核心契约/运行时依赖检查;所有这些步骤保留并执行。
70
-
71
- 在添加本轮 Unreleased 条目前,用本地完整源码构建的同一个 Gem 实际执行:
72
-
73
- ```sh
74
- LC_ALL=C LANG=C ruby -EUS-ASCII script/release.rb --dry-run --artifact tmp/improvement-052/expect-pty-0.5.2.gem
75
- LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ruby -EUTF-8 script/release.rb --dry-run --artifact tmp/improvement-052/expect-pty-0.5.2.gem
76
- ```
77
-
78
- 两次退出 0、验证相同 Gem 字节,生成的中文 release-notes 逐字节相同。该候选只是中途本地验证物,不是可发布版本。
79
- 新增 CLI 测试另覆盖独立 fixture 项目的非法 UTF-8 拒绝,以及 C/UTF-8 两种外部编码;不会访问发布服务。
80
- 当前 Unreleased 保留本轮变更,正式发布前仍需维护者自行归档并选择版本,原有拒绝条件不绕过。
81
- 最后对当前工作区再次执行 C locale dry-run,按预期退出 1 并提示 `Move Unreleased changes into the versioned changelog before releasing`。
82
-
83
- ### 同类检查、兼容性与剩余范围
84
-
85
- - 构造所有权:核对 new/open/spawn/stty 四条入口。new/open 补账本之前的兜底;spawn 继续委托 new,stty 保留已有独立兜底。
86
- - 进程回收:核对主会话、finalizer、stty 正常等待与异常回收。主会话/GC 修复 EINTR;stty 继续使用自身阶段策略,不合并账本。
87
- - 写入进度:核对直接 write、RelayWriter、logging.emit 三处。后两者已有计数验证,仅补直接 write。
88
- - 发布文本:本地入口与 workflow 共用 UTF-8 读取,notes 显式 UTF-8 写出;ASCII 校验和与 Git/Gem 二进制比较保持原状。
89
- - 内部命名:统一为 `cleanup(failed:)`、`close_resources`、`close_child`、`mark_eof`;库、测试和文档无旧私有入口调用或别名。
90
- - 兼容性:同源活跃 Relay 现在明确报 `ReentrancyError`,异常适配计数报 IOError;普通顺序恢复、嵌套 Matcher、匹配顺序和期限默认值不变。
91
-
92
- G1–G6 由上述红绿回归与实际 locale dry-run 覆盖;G7–G8 由默认套件及原始 CI 脚本覆盖;G9–G10 由契约回归、
93
- 聚焦 diff 和本记录覆盖。日志位于被忽略的 `tmp/improvement-052/`,含基线、逐项红绿、固定 seed、容器和 dry-run 输出。
94
- 测试迭代中修正了测试 helper 与 Minitest 同名方法/嵌套 stub 的冲突,以及 CLI fixture 必须随脚本根目录复制的问题;
95
- 这些测试支架错误不计入产品红灯证据,表中证据来自修正后的独立基线重放。
96
-
97
- 未执行 macOS Ruby 3.2/3.3/3.4、远端 GitHub Actions 的 ubuntu-24.04/macos-15 矩阵、真实 SSH 或发布。
98
- 本地 Linux arm64 容器不能替代该远端矩阵。T08 的长期压力、高水位及性能对照按计划留作后续测量;
99
- 本轮 smoke 不证明吞吐提升、峰值内存下降或任意系统故障下保证回收成功。
100
-
101
- ## 0.5.0 公共字节过滤器发布前复核(2026-09-27)
102
-
103
- 基线为已发布的 `5a219f7`(0.4.0)。本轮公开 `Expect::Redactor`,新增 11 项回归,覆盖独立加载不引入 PTY、完整文本与流尾部策略、跨分片与重叠秘密、自定义替换标记、空规则、输入复制、无效更新原子性及安全摘要;现有会话日志与诊断继续复用该过滤器。
104
-
105
- 从基线建立独立检出,仅带入本轮改动。macOS arm64、Ruby 4.0.6、Bundler 4.0.17 下执行 `ruby script/release.rb --dry-run`,330 项测试、1,894 条断言全部通过,无失败、错误或跳过;RuboCop 检查 59 个文件无违规。四组基准 smoke、Gem 构建、普通 RubyGems 与最小 Bundler 应用的隔离安装均通过,安装后实际调用公共完整文本和分块过滤接口。
106
-
107
- 此处记录本地发布预演;远端 Linux/macOS 与 Ruby 3.2/3.3/3.4/4.0 矩阵、标签及下载包校验,以 0.5.0 发布提交对应的 GitHub Actions 与 Release 为准。
108
-
109
- ## 0.4.0 发布前复核(2026-09-27)
110
-
111
- 发布前新增七项回归:总期限在文本回调后到达时,已知 EOF 先于剩余活跃来源的超时派发;覆盖日志路径前交付旧尾部,冲刷失败不能提前截断新文件;嵌套诊断等待保留外层匹配结果;日志回调轮换目标时正确交接所有权;诊断回调新建或再次写入另一方向时,尾部仍交给旧目标。各项均先复现失败,再验证修复,纯相对超时行为保持不变。
112
-
113
- 从 `b5e9159` 建立独立检出,只带入本轮 30 个功能、测试、文档和版本文件,排除主工作区的其他格式化改动。macOS arm64、Ruby 4.0.6、Bundler 4.0.17 下执行 `ruby script/release.rb --dry-run`,319 项测试、1,820 条断言全部通过,RuboCop 检查 58 个文件无违规;四组基准 smoke、Gem 构建、两种隔离安装和新增接口检查均通过。
114
-
115
- 此处记录本地发布预演,远端矩阵、标签和发布产物以 0.4.0 对应提交的 GitHub Actions 与 Release 为准;下节保留改进阶段的双平台验证结果。
116
-
117
- ## 底层引擎补齐与模块注释(2026-09-27)
118
-
119
- 基线为已发布的 `b5e9159`(0.3.3),本节记录 0.4.0 发布准备前的底层改进验证。范围限于底层 Expect:裁剪计数、生命周期及错误契约、等待总期限、诊断目标、按字节流脱敏、增量字面扫描及多来源基准。未引入厂商实现、SSH 编排或新的 Reactor。
120
-
121
- 新增 43 项回归,覆盖外部回收、借用 IO、关闭重试、缓冲裁剪与正常消费、绝对期限限制各类重置、已知 EOF、EINTR、分片与重叠秘密、二进制诊断、流尾部交付,以及字面缓存与全量扫描的操作序列对照。
122
-
123
- | 当前环境 | 完整 `bash script/ci` |
124
- | --- | --- |
125
- | macOS arm64,Ruby 4.0.6,Bundler 4.0.17 | 312 项 / 1,784 条断言,0 失败、错误、跳过;RuboCop 58 文件无违规 |
126
- | Linux aarch64,Ruby 3.2.11,Bundler 4.0.17,当前源码独立容器副本 | 同上;容器使用冻结锁文件及独立 Linux 依赖 |
127
-
128
- 两套检查均通过对话示例、四组基准 smoke、Gem 构建、普通 RubyGems 和最小 Bundler 应用的隔离安装。安装后检查新增总期限、裁剪计数、内部过滤器和结构化诊断实际工作,并确认 Logger 等开发依赖没有泄漏到运行时。macOS 构建存在宿主 RDoc 7/8 重复常量警告,命令退出状态为 0。
129
-
130
- 审阅 `lib/expect` 全部 14 个模块,补齐其中 12 个模块的中文职责、方法及复杂流程注释;加载入口和版本文件保留现有充分说明。以注释编辑开始时的源码快照对照,15 个库文件的 Ripper 语法树(忽略位置)完全相同,逐行差异也仅为注释或空白。工作区其他 Ruby 格式化修正同样核对语法树等价。
131
-
132
- 另通过 14 个文档 Ruby 片段语法解析、工作流 actionlint(未启用 shellcheck)和 `git diff --check`。两轮同机匹配性能对照、真实管道来源容量与阻塞目标检查见 [性能基准](PERFORMANCE.md#持续字面扫描验证2026-09-27);1,000 管道来源只证明该受控场景,不代表真实设备吞吐或长期运行。
133
-
134
- 本轮未运行远端 CI、Ruby 3.3/3.4 或真实 SSH/设备测试,未提交、推送或发布。以下历史记录不作为本轮验收结果。
135
-
136
- ## 模块审查、资源清理与正则输入复用(2026-09-27)
137
-
138
- 基线为 `b9fc077`,以下为 0.3.3
139
- 发布准备前的源码审查记录。覆盖会话、配置、模式声明与定位、匹配结果及期限、资源所有权、日志、终端、人工接管、转接恢复、示例、发布和打包模块。修复工厂/构造失败后的子进程回收、部分句柄清理、原始异常保留、EOF
140
- 继续期限和发布包提交来源验证;新行为均有先失败后通过的回归。EOF 补充多源同时结束和重置期限用例,保留已知 EOF 的派发顺序。
141
-
142
- 日志与终端方法拆入独立能力文件,公共入口保持 `expect/pty`;打包检查确认两文件随 Gem
143
- 分发。正则输入复用通过冻结输入、编码分片、二进制、字节偏移及匹配/转接回归,实测数据见 [性能基准](PERFORMANCE.md#正则输入复用验证2026-09-27)。
144
-
145
- | 当前运行环境 | 完整 `bash script/ci` |
146
- |----------------------------------------------------------|----------------------------------------------------------------|
147
- | macOS arm64,Ruby 4.0.6,Bundler 4.0.17,原工作区 | 269 项 / 1,356 断言,0 失败、错误、跳过;RuboCop 51 文件无违规 |
148
- | macOS arm64,同一运行时,隔离 worktree | 同上;从基线加本轮补丁及新增文件重建 |
149
- | Linux aarch64,Ruby 3.2.11,Bundler 4.0.17,独立容器副本 | 同上;冻结开发锁文件,容器独立安装依赖 |
150
-
151
- 三次均完成对话示例、三组基准 smoke、Gem 构建、普通 RubyGems 与最小 Bundler 应用的隔离安装及真实 PTY 对话。另检查包内 69
152
- 个文件及新增模块,无构建目录或日志;工作流 actionlint 通过(未启用 shellcheck),发布与示例 `--help` 正常。macOS 构建仍有宿主
153
- RDoc 7/8 重复常量警告,退出状态为 0。
154
-
155
- 发布测试使用临时 Git 仓库,验证合法包通过,忽略文件、`assume-unchanged` 隐藏内容、忽略执行权限变化及主页元数据不一致均被拒绝,未连接发布服务。审查时版本仍为
156
- 0.3.2,改动位于 `Unreleased`,这些本地检查不代替发布验证;当时未运行真实 SSH、远端 CI 或 Ruby 3.3/3.4,也未提交、推送或发布。0.3.3
157
- 的远端平台结果以发布提交对应的 GitHub Actions 为准,以下历史结果不作为本轮验证证据。
158
-
159
- ## 配置并发与模块审查改进(2026-09-26)
160
-
161
- 当前工作树在既有未提交的匹配、转接和清理改动上,增加 `configure` 的串行读改写与回归测试:旧实现的并发用例先失败,修复后通过;嵌套调用显式抛出
162
- `ThreadError`,不会陷入死锁或发布部分配置。`read_available` 的裁剪选择改为显式参数,转接调用明确禁止裁剪其待处理缓冲。RuboCop
163
- 对生产代码启用分支复杂度检查,既有状态机只在对应方法局部豁免;补充内部调用契约、贡献指南、issue/PR 模板与安全说明。
164
-
165
- macOS arm64、Ruby 4.0.6、Bundler 4.0.17 下执行 `bash script/ci`:249 项测试、1,242 条断言,0 失败、错误或跳过;RuboCop 检查 49
166
- 个文件无违规。对话示例、三组基准 smoke、Gem 构建、普通 RubyGems 与 Bundler 隔离安装及真实 PTY 对话均通过。构建时本机 RDoc 7/8
167
- 重复常量警告仍存在,但命令成功完成。
168
-
169
- 本轮未运行 Linux/Ruby 3.2、远端 CI 或真实 SSH;未提交、推送或发布。下文历史结果不作为本轮检查证据。
170
-
171
- ## 0.3.0 发布前复核(2026-09-26)
172
-
173
- 以 0.2.0 为基线导入源码更新,发布前增加 8 项回归,覆盖退出正则切换、同规则跨次匹配、待发送恢复、跨次
174
- CRLF、转义回调内匹配与异常尾部恢复、嵌套写入超时进度。新用例先在修复前失败,再验证修复;仅内部转义处理器的两项测试随职责调整更新调用方式。
175
-
176
- macOS arm64、Ruby 4.0.6、Bundler 4.0.17 下执行 `BUNDLER_VERSION=4.0.17 bash script/ci`:225 项测试、903 条断言,0
177
- 失败、错误或跳过;RuboCop 检查 42 个文件无违规,对话示例、Gem 构建、隔离安装及 PTY 对话全部通过。连续 1,000 次使用同一输入调用
178
- `interact`,仅保留一个输入包装器,关闭会话不关闭借用 IO。
179
-
180
- 真实 IO 的已有 Ruby 写缓冲可能让 `write_nonblock` 先阻塞刷新,已在 README 明确首次写入前设置 `sync`
181
- 或交接前排空缓冲的要求;未通过绕过缓冲改变字节顺序。真实 SSH 与完整上游差分不在本次验证范围。远端平台矩阵以发布提交对应的
182
- GitHub Actions 结果为准,以下记录属于各自历史时点。
183
-
184
- ## 转接期限、交付恢复与输入接续(2026-09-26)
185
-
186
- 继续引用审查中的 R1–R5,在原有未提交改动上修复;基线为 194 项测试 / 737 条断言全部通过。新增 `test/relay_recovery_test.rb`
187
- 的前 8 个用例先在未修复实现运行,得到 5 个失败、3 个错误,分别确认阻塞超时、部分发送重放、监听器失败重放、短写入丢后缀、原始输入
188
- IO 接续、背压读取 EINTR、写超时进度和 EOF 截断编码问题。修复后这 8 项通过,再扩展到 23 项恢复与边界用例。
189
-
190
- 根因与修复:
191
-
192
- - `interconnect` 的期限原先只约束读取循环,同步 `target.write` 可以无限阻塞;`Relay` 现统一 select
193
- 读写并保留总期限,超时后的前缀刷新也只尝试非阻塞写入。
194
- - 原先只有单次 `write` 的局部偏移,转发失败后重新发送整个源缓冲;`RelayWriter` 现按目标保留游标,成功目标不重放,短写入继续后缀,flush
195
- 异常只重试 flush。转义回调等待前缀交付,剩余输入与待发送数据分别保留。
196
- - `interact` 原先每次新建输入包装器;现由连接持有并按原始 IO 身份复用,关闭连接时不等键盘 EOF、不关闭借用
197
- IO。关闭路径也先通过有界测试复现等待,再修复并复验。
198
- - 背压读取的 `EINTR` 纳入原写期限重试;直接写超时异常提供 `bytes_written`。编码检查感知 EOF,固定 UTF-8 正则对截断字符抛出
199
- `EncodingError`,匹配缓冲保留原字节。
200
-
201
- 同类路径复核覆盖直接写入、转接的常规/转义/EOF/超时发送、日志及普通监听器的 `emit`、匹配和转义两处正则定位。共同 `emit`
202
- 同样补齐短写入检查;匹配和转义都传入 EOF 状态。日志、回调、普通匹配的监听器以及自定义写入对象仍同步运行,文档明确这些操作不受
203
- IO 等待期限强制中断;自定义对象必须准确返回已接受的字节数。R6 使用 Ruby 已有的正则实例
204
- timeout,新增测试验证异常透传、缓冲保留及全局配置不变,未增加进程全局设置。
205
-
206
- | 环境 | 完整 `script/ci` | 打包及运行 |
207
- |----------------------------|--------------------------------------------------------------|-------------------------------------------------|
208
- | macOS arm64,Ruby 4.0.7 | 217 项 / 857 断言,0 失败、错误、跳过;RuboCop 42 文件无违规 | 对话示例、Gem 构建、隔离安装及真实 PTY 对话通过 |
209
- | Linux aarch64,Ruby 3.2.11 | 217 项 / 857 断言,0 失败、错误、跳过;RuboCop 42 文件无违规 | 对话示例、Gem 构建、隔离安装及真实 PTY 对话通过 |
210
-
211
- Linux 从 gemspec 文件白名单及锁文件构造独立源码快照,只读挂载后复制到容器,使用 Bundler 4.0.20、锁定依赖及
212
- `BUNDLE_FROZEN=true`;未读取或分发工作区设备日志。检查构建包包含 `relay.rb`、转接写入器(现名 `relay_writer.rb`
213
- )、原有重命名模块和新增回归测试,不含 `tmp/` 或 `.git/`。macOS 构建时存在本机 RDoc 多版本重复常量警告,命令成功退出,隔离安装与
214
- PTY 验证通过。工作区原有 16 处样式问题只作相应格式修正。
215
-
216
- Linux 首轮新增用例误把 0.1 秒转接超时当作发送完成:`pending_output? == false` 时,`buffer`
217
- 仍可能含尚未排入队列的输入。探针证实该状态存在;用例改为关闭源写端并等待转接返回该 EOF 来源,明确验证缓冲已空后再断言回复,避免依赖机器吞吐量。
218
-
219
- `git diff --check` 通过。未运行 Ruby 3.3/3.4、远端 CI 或真实
220
- SSH;未提交、推送或发布。新增源码仍需随现有重构文件一起纳入后续提交。性能窗口、完整输出存储等建议已补充使用说明,未改变默认缓冲上限或任意正则的匹配语义。
221
-
222
- ## Tcl 对照与全项目复核(2026-09-26)
223
-
224
- 基于 `e6fc883` 及当前全部未提交改动,复核库源码、测试、示例、打包和发布脚本。保留既有 `Matcher`、`SessionResources` 和
225
- `interaction.rb` 职责命名,不新增兼容别名。本轮补充四项回归测试,修复三处问题:
226
-
227
- - Ruby 编码转换器识别非法 UTF-8 前缀,避免将过长编码、代理区或越界码点误判为等待更多字节;合法分片继续等待,原字节保留。
228
- - 转接读取先存入转接缓冲,再调用日志;日志异常后输入归还会话,可继续匹配。
229
- - 新建日志使用 `0600` 权限;追加和覆盖已有文件均保留其权限。
230
-
231
- 三项缺陷均先运行回归测试确认旧实现失败,再修改实现并复验。合法分片用例覆盖二、三、四字节字符的每个截断位置。
232
-
233
- | 环境 | 完整 `script/ci` | 打包验证 |
234
- |----------------------------|--------------------------------------------------------------|---------------------------------------------|
235
- | macOS arm64,Ruby 4.0.7 | 191 项 / 728 断言,0 失败、错误、跳过;RuboCop 39 文件无违规 | 对话示例、构建、隔离安装与真实 PTY 对话通过 |
236
- | Linux aarch64,Ruby 3.2.11 | 191 项 / 728 断言,0 失败、错误、跳过;RuboCop 39 文件无违规 | 对话示例、构建、隔离安装与真实 PTY 对话通过 |
237
-
238
- macOS 验证目录从 `git archive HEAD`、全部工作区补丁及未跟踪源码重建,包含本地开发锁文件;隔离的 GEM_HOME 安装 Bundler
239
- 4.0.17,并以 `BUNDLE_FROZEN=true bash script/ci` 验证,未依赖本机损坏的 Bundler 启动器。Linux 使用 `ruby:3.2-bookworm`
240
- ,源码只读挂载并复制到容器临时目录,同样安装锁定依赖;完整测试包含 `release_test.rb`。
241
-
242
- 核对 Tcl 官方 `expect.c` 的匹配、缓冲消费和继续计时流程,以及 `exp_inter.c` 的部分模式匹配和终端恢复;另在 Tcl Expect
243
- 5.45.4 与本库中分别实跑缓冲消费、保留、EOF 和 wait
244
- 场景,均通过。功能差异和未实现能力见 [接口说明](COMPATIBILITY.md#tcl-expect-语义边界),不代表完整 Tcl 差分验收。
245
-
246
- 本轮未重跑真实 SSH、Ruby 3.3/3.4 或远端 CI,也未提交、推送或发布。以下记录保留各自验证时点,不作为本轮执行证据。
247
-
248
- ## 当前工作区:交互、匹配与 IO 修复(2026-09-24)
249
-
250
- 本轮检查并修复固定 UTF-8 正则在末尾字符未收齐时提前匹配、正则转义历史窗口截断到 UTF-8 续字节,以及就绪查询、写入和转接中的
251
- `EINTR`。新增回归覆盖分片字符、历史窗口和 select/read/write 中断。
252
-
253
- | 环境 | 测试结果 | 其他检查 |
254
- |---------------------------|---------------------------------------|--------------------------------------------------------|
255
- | macOS arm64,Ruby 4.0.7 | 187 项 / 692 断言,无失败、错误、跳过 | RuboCop 39 个文件无违规;对话示例通过 |
256
- | Linux aarch64,Ruby 4.0.6 | 176 项 / 658 断言,无失败、错误、跳过 | 只读挂载源码;排除依赖本机打包环境的 `release_test.rb` |
257
-
258
- `git diff --check` 通过。本轮未在 Ruby 3.2 重新运行完整测试,也未运行远端 CI;下节的 Ruby 3.2 结果属于 2026-09-12
259
- 的历史验证,不能代表当前工作区。
260
-
261
- ## Ruby 原生接口与关闭策略(2026-09-12)
262
-
263
- 此次重构以 144 项测试 / 526 个断言为基线。原有交互场景全部迁移到新接口,新增 18 项回归,三个环境均通过 `bundle exec rake`
264
- (RuboCop 和完整测试)及 `ruby examples/dialogue.rb`:
265
-
266
- | 环境 | 测试结果 | RuboCop |
267
- |----------------------------|---------------------------------------|-------------------|
268
- | macOS arm64,Ruby 4.0.6 | 162 项 / 618 断言,无失败、错误、跳过 | 37 个文件,无违规 |
269
- | Linux aarch64,Ruby 3.2.11 | 162 项 / 618 断言,无失败、错误、跳过 | 37 个文件,无违规 |
270
- | Linux aarch64,Ruby 4.0.6 | 162 项 / 618 断言,无失败、错误、跳过 | 37 个文件,无违规 |
271
-
272
- 新增检查覆盖配置发布的原子性、冻结与会话隔离、子类覆盖、无效赋值保留状态、Ruby
273
- 真值、字面模式标志、全部活跃会话的超时回调、重复超时注册、日志所有权。真实子进程验证软关闭收集尾部、响应 TERM、绝不发送
274
- KILL、保留存活 PID、后续硬关闭和重复回收,以及自动清理、日志异常和无效关闭期限。模拟 EINTR 检查重复 select 中断不能延长期限、读取中断不丢输入。
275
-
276
- 最终会话输出接口统一为 `puts`、`write` 和 `send_slow(..., delay:)`,移除会话 `print` 和 `write_slow`。`lib/expect/` 的 9
277
- 个模块文件及主入口均补充中文注释,说明方法用途、匹配状态机、编码分片、转接缓冲、日志所有权和进程关闭;词法检查确认注释增补没有改变可执行代码。
278
-
279
- 原有 PTY、控制终端、信号、中文/二进制、背压、捕获组、匹配优先级、多会话、日志、interact 和 GC
280
- 测试继续全量运行。模块设置已收敛到配置对象;旧方法、位置超时、数组回调和 Perl 正则模式解析已移除,测试使用新 API。10 个文档
281
- Ruby 示例块均通过语法检查。
282
-
283
- macOS 的独立 `bundle exec rake test:kibitz` 也通过全部 6 个场景,报告位于
284
- `tmp/kibitz/20260911T232907Z-20260912-9935-te8xfa/report.json`。本轮在 Linux Ruby 3.2 容器中重新运行
285
- `test/compare_upstream.rb`, **11 组共同交互行为对照通过**;适配脚本使用新 Ruby API,显式转换错误标记及可读会话索引,原版
286
- Perl fixture 未修改。
287
-
288
- 关闭策略另核对上游 `lib/Expect.pm` 的 `soft_close`、`hard_close` 和 `DESTROY`:软关闭最多 TERM,硬关闭可 KILL,销毁可先软后硬。Ruby
289
- 以 `graceful_close` / `close(graceful:)` 表达默认策略,以关键字配置等待期限;显式关闭返回 `Process::Status`,通用 `close`
290
- 返回 `nil`。
291
-
292
- Linux 源码以只读方式挂载,使用 `BUNDLE_FROZEN=true` 和独立容器依赖目录;镜像摘要仍为下文记录的 `ruby:3.2` 与 `ruby:4.0`
293
- 。Gemfile 和锁文件未改动,锁文件 SHA-256 为 `b1186a77057fba44bb79c440ffb6921042c16c1b88d213fabaa6548befb38d57`。macOS 复用了
294
- `/tmp/expect-pty-gems` 的隔离依赖环境。
295
-
296
- 本轮没有重新连接真实 SSH 或运行远端 CI。`pkg/` 的 0.1.0 / 0.1.1 构建与记录仍代表历史版本;当前源码的接口见 README 和
297
- COMPATIBILITY。以下各节保留其原验证时间、接口和范围,不作为当前接口的使用说明。
298
-
299
- ## 历史验证记录
300
-
301
- 验证日期:2026-09-11。上游参考版本 Expect.pm 1.38,提交 `2ea0e4ce20a896c95cb4c94e781f1b1f3145150d`。
302
-
303
- ## 自动测试
304
-
305
- 完整测试集包含 76 项测试,全部通过,无跳过:
306
-
307
- | 环境 | 结果 |
308
- |----------------------------|-----------|
309
- | macOS arm64,Ruby 4.0.6 | 76 项通过 |
310
- | Linux aarch64,Ruby 3.2.11 | 76 项通过 |
311
- | Linux aarch64,Ruby 4.0.6 | 76 项通过 |
312
-
313
- Linux 使用官方 Docker 镜像:
314
-
315
- - `ruby:3.2`:`sha256:d3bcbd845d26ae1efafcc987f641aa9ac796267b9b857e0f196a2b05070c8330`
316
- - `ruby:4.0`:`sha256:8dc3950712ad2078bdd275b890419ba2fd3aab5a0653b291a7325f0d8a24ca05`
317
-
318
- 测试范围包含真实 PTY 的控制终端、stdin/stdout/stderr、raw/noecho、终端尺寸、Ctrl-C 前台信号、退出码、TERM/KILL 回收、GC
319
- 兜底;模式优先级、捕获组、中文分片、二进制、缓冲上限;回调、事件、绝对/接收重置超时;多会话、日志、管道和 socket、大块双向
320
- IO、写入背压;人工交互、跨读取转义序列、异常和超时后终端恢复;与 Ruby 标准库 IO#expect 共存。
321
-
322
- macOS 改变终端设置后内核可能设置 PENDIN 临时状态位。终端恢复测试屏蔽这一状态位,比较其余完整配置;没有忽略真实的
323
- echo、canonical、输入/输出、信号或控制字符设置变化。
324
-
325
- 复现:
326
-
327
- ```sh
328
- bundle install
329
- bundle exec rake test
330
- ```
331
-
332
- 本机全局 RubyGems/Bundler 安装存在版本混用,验证使用了临时 GEM_HOME 中的独立 Bundler 4.0.16、Rake 和 Minitest;未修改项目对
333
- Bundler 的通常用法或用户的全局 gem。
334
-
335
- ## 上游差分验证
336
-
337
- `test/compare_upstream.rb` 对同一输入分别运行原始 Perl 模块与本 Ruby
338
- 实现:字面模式、数组正则、跨行锚点、模式优先级、notransfer、缓冲上限、超时保留缓冲、连续回调、真实 PTY 对话。 **9 组对照通过**。
339
-
340
- 对照在 Linux Ruby 3.2 容器内执行,Perl 依赖 IO::Pty / IO::Stty 仅安装到该临时容器。正则捕获及错误访问的 Perl
341
- 对象模型差异见兼容性说明;没有将它们伪装为一致行为。
342
-
343
- ```sh
344
- # 此项是可选验证,需要 Perl 及 IO::Pty / IO::Stty。
345
- ruby test/compare_upstream.rb /path/to/expect.pm
346
- ```
347
-
348
- 没有把这 9 项差分测试等同于运行完整 Perl 上游测试套件;功能覆盖同时依赖 Ruby 的 76 项测试和源码/API 对照。
349
-
350
- ## 真实 SSH
351
-
352
- 使用用户授权的 `crate@127.0.0.1` 完成真实 OpenSSH 密码认证,进入远端交互 shell 和 PTY。校验随机输出标记、`id -un` 返回
353
- `crate`、`tty` 返回 `/dev/...`,随后 `exit`,SSH 退出码为 0。
354
-
355
- 测试随机标记由远端拼接,排除了仅匹配命令回显的误判。密码由隐藏输入读取或从进程环境取出,只保留在验证进程内,未写入源码、测试、文档和日志。临时
356
- known_hosts 在退出后删除。
357
-
358
- ```sh
359
- SSH_USER=crate SSH_HOST=127.0.0.1 ruby examples/ssh_login.rb
360
- ```
361
-
362
- ## 打包和范围
363
-
364
- 提供 `expect-pty.gemspec`、MIT LICENSE、中文 README、API 兼容性表、对话和 SSH 示例,以及 macOS/Linux 的 Ruby 3.2/3.3/3.4/4.0
365
- CI 配置。CI 文件已进行 YAML 解析检查,远端 GitHub Actions 尚未运行。
366
-
367
- 初始构建物为 `expect-pty-0.1.0.gem`,补充后的交付版本为 `expect-pty-0.1.1.gem`,包含可运行的测试和 fixtures。安装验证在独立
368
- GEM_HOME 中、从项目目录外运行 `require "expect/pty"` 和真实 PTY 对话,避免依赖源码目录的加载路径。
369
-
370
- 原生 Windows、其他 Unix、真实外部设备/外部 SSH 服务未实测。没有发布 gem、推送仓库或创建远端 Release;本次交付为本地源码和安装包。
371
-
372
- ## 补充验证:登录后多脚本与日志(2026-09-11)
373
-
374
- 新增 `test/script_logging_test.rb` 的 8 项真实 PTY 测试,及可单独运行的 `test/integration/ssh_scripts.rb`。自动测试总计从
375
- 76 项增至 84 项。新增测试共享 5 个 `.sh` fixture,覆盖多脚本日志文件、回调和借用 File、日志出错、异常退出码、输出不符、引号和中文传输,以及超时后的日志连续性。
376
-
377
- 最终全量回归:macOS Ruby 4.0.6 为 84 项 / 283 断言,Linux Ruby 3.2.11 为 84 项 / 283 断言,Linux Ruby 4.0.6 为 84 项 / 289
378
- 断言,均无失败、错误或跳过。Rake 的 `test:ssh` 入口已注册,Ruby 脚本和 5 个 shell fixture 的语法检查通过。
379
-
380
- 真实 SSH `crate@127.0.0.1` 已通过同一会话内的 7 项执行(5 个文件脚本,加日志关闭/恢复用例)及 11 项日志检查。第 4 个 fixture
381
- 故意返回 7,第 5 个仍执行成功;最终 SSH 退出码为 0。日志读取验证包含执行期间即时 flush、逐条顺序、无重复、覆盖/暂停/追加,以及
382
- `soft_close` 收集最终延迟输出。
383
-
384
- 实际通过的日志和 JSON 报告保存在 `tmp/ssh-logs/20260911T124918Z-20260911-97383-lka948/`。目录被 Git
385
- 忽略,每次重跑生成新目录,失败时保留失败报告。
386
-
387
- 该成功会话日志共 1633 字节,SHA-256 为 `6b8abf4df93e1c40dec21a2b89c359bf4e2a9f9636791a83713150af5796672c`,与 JSON
388
- 报告的摘要一致;日志和报告均为 0600 权限。`pkg/` 中保留 0.1.0 作为初始构建记录,后续修正和测试脚本随 0.1.1 打包。
389
-
390
- ## 完整性复核与 0.1.1
391
-
392
- 复核上游实际代码后,补充 `test_handles(timeout, *sessions)` 等待语义,以及 `set_seq` 正则序列和跨读取回调,差分用例从 9
393
- 组扩展到 11 组。新增回归也覆盖从 `expect` 切换到 `interconnect` 再返回时的日志唯一性、转义后的原始日志,以及日志目标抛 IO
394
- 错误时保留输入并正确报告错误。
395
-
396
- 0.1.1 包含库源码、中文文档、完整测试与 5 个 `.sh` fixtures、Gemfile、gemspec 和 Rakefile。具体构建摘要和安装后的验证结果记录在构建物旁的
397
- `pkg/VERIFICATION-0.1.1.txt`,避免文档与包自身摘要循环依赖。
398
-
399
- SSH 首轮测试曾准确报告中文脚本退出 127;根据日志定位到测试 helper 的逐字节转义与远端 shell 行编辑相互影响。已改为完整脚本单引号传输,并禁用交互
400
- shell 的 emacs/vi 编辑;重跑后中文、标准输出和错误输出逐字节匹配通过。
401
-
402
- ## 补充验证:interact 与本地 Kibitz(2026-09-11)
403
-
404
- 当前源码全量测试为 **109 项**,无失败、错误或跳过:macOS arm64 Ruby 4.0.6 为 380 断言,Linux aarch64 Ruby 3.2.11 为 380
405
- 断言,Linux aarch64 Ruby 4.0.6 为 386 断言。Linux 仍使用上文记录的两个镜像。这些新增内容记在 Unreleased,已有 0.1.1
406
- 构建记录保持为该包的历史验证结果。
407
-
408
- 新增 7 项 `test/interact_test.rb` 测试覆盖真实 PTY 接管、输入即时回显、远端 Ctrl-C、两次 Ctrl-]
409
- 返回、恢复自动化、超时/EOF/回调和输出异常后的终端恢复。另补 1 项 CRLF 输出分帧回归,检查空输出、无末尾换行和多个末尾换行。人工交互启用远端
410
- echo,回到自动化时关闭 echo;自动脚本的无回显设置保留。TTY 身份探测的换行匹配不参与输出截取,不存在同一分帧问题。
411
-
412
- 实际 SSH `crate@127.0.0.1` 通过的三条路径,均记录 SSH 退出码 0,日志与报告权限 0600:
413
-
414
- | 路径 | 结果 | 报告所在目录 |
415
- |-------------------|------------------------------------------------------------|-----------------------------------------------------------|
416
- | 自动 PTY 交互 | 4 项命令、13 项交互/日志检查 | `tmp/ssh-interact/20260911T131311Z-20260911-367-hkxq5z/` |
417
- | 人工输入后 Ctrl-] | 回车前可见 `printf` 输入,执行结果正确,返回后自动命令成功 | `tmp/ssh-interact/20260911T131343Z-20260911-423-7pgq5m/` |
418
- | 人工直接 exit | 远端 EOF、终端恢复、正常退出,不执行自动化恢复命令 | `tmp/ssh-interact/20260911T132040Z-20260911-1777-qi6yry/` |
419
-
420
- 参考上游 `examples/kibitz` 源码的连接图,新增 `examples/kibitz/kibitz.rb` 和 `test_kibitz.rb`。本地示例通过 Unix socket
421
- 连接两份 CLI,各自运行于独立真实 PTY;共享模式启动真实 shell。`test/kibitz_test.rb` 新增 7
422
- 项测试,覆盖共享状态、输入回显、双向广播、中文/stderr、Ctrl-C、无子进程互传、自定义分片转义、禁用转义、非零退出、连接与转接超时、日志唯一性以及终端恢复和
423
- socket 清理。
424
-
425
- 测试捕获并修正了就绪提示先于本地 raw/noecho 设置的启动时序问题;现在两端的就绪提示均在终端设置完成后发送。分片转义检查先确认普通前缀已到达对端,再发送转义的剩余部分,确保确实覆盖跨读取路径。
426
-
427
- `bundle exec rake test:kibitz` 独立执行 6 个场景并全部通过,报告保存于
428
- `tmp/kibitz/20260911T132223Z-20260911-2081-1poaup/report.json`,每个场景有独立 `session.log`
429
- 。此验证参考并重现上游的本地交互行为,不代表移植或运行了上游的用户邀请、跨主机 rlogin 和转义菜单。
430
-
431
- ## Ruby API 与编码规范重构(2026-09-12)
432
-
433
- 本轮基线为 109 项测试 / 380 断言。新增 `test/ruby_api_test.rb` 的 35 项测试 / 146 断言,最终三种环境均通过完整的
434
- `bundle exec rake` 和 `ruby examples/dialogue.rb`:
435
-
436
- | 环境 | 完整测试 | RuboCop |
437
- |----------------------------|---------------------------------------|-------------------|
438
- | macOS arm64,Ruby 4.0.6 | 144 项 / 526 断言,无失败、错误、跳过 | 35 个文件,无违规 |
439
- | Linux aarch64,Ruby 3.2.11 | 144 项 / 526 断言,无失败、错误、跳过 | 35 个文件,无违规 |
440
- | Linux aarch64,Ruby 4.0.6 | 144 项 / 526 断言,无失败、错误、跳过 | 35 个文件,无违规 |
441
-
442
- 新增验证覆盖简洁 `expect(10) { on(...) ... }`、显式块参数保留调用方 `self`、闭包、可选块参数、注册时异常和 `break`
443
- 不消费输入、关键字与位置超时校验、EOF / 超时 / 多会话回调、继续等待及原期限;也覆盖借用和接管 IO 的块清理、初始化失败、缓冲和监听列表副本、日志块、原生
444
- `puts` 的空参数/嵌套/递归数组、对象写入与链式追加。
445
-
446
- `Result` 转换验证直接对照七个 Struct 字段,包括 `to_a`、`Array(result)`、`to_h`、位置/键模式解构及显式多重赋值;确认不再响应
447
- `to_ary`。另验证 `session.send(:buffer)` 等 Ruby 反射调用和实际字节写入分离。原有 PTY、二进制、超时、进程回收、日志、interact、Kibitz
448
- 测试继续全量运行。
449
-
450
- 开发依赖固定在 Ruby 3.2 可运行的范围:RuboCop 1.89.0、parallel 1.28.0、Minitest 5.27.0、Rake 13.4.2,锁文件已补齐校验和。Linux
451
- 验证以只读方式挂载源码,使用 `BUNDLE_FROZEN=true` 安装同一锁文件;镜像仍为本文记录的 `ruby:3.2` 和 `ruby:4.0`。macOS 使用
452
- `/tmp/expect-pty-gems` 中的独立 Bundler 4.0.16。
453
-
454
- 调用与迁移说明已同步至 README、兼容性表和示例;`send(data)` 需改为 `write(data)`,多重赋值需显式使用 `result.to_a`,`puts`
455
- 返回 `nil`。不冲突的 Expect.pm 入口继续作为兼容入口保留。本轮未重新连接真实 SSH、运行 Perl 上游差分或触发远端
456
- CI;历史验证记录不作为这些路径本轮实测的证明。
data/examples/dialogue.rb DELETED
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "../lib/expect/pty"
4
- require "rbconfig"
5
-
6
- program = <<~'RUBY'
7
- STDOUT.sync = true
8
- print "Name: "
9
- name = STDIN.gets.strip
10
- print "Code: "
11
- code = STDIN.gets.strip
12
- puts "Hello #{name}, code=#{code}"
13
- RUBY
14
-
15
- Expect.spawn(RbConfig.ruby, "-e", program, raw_pty: true, log_stdout: false) do |session|
16
- matched = session.expect(timeout: 3) do
17
- on("Name: ") do |connection|
18
- connection.puts("Ruby")
19
- connection.continue
20
- end
21
- on("Code: ") do |connection|
22
- connection.puts("1234")
23
- connection.continue
24
- end
25
- on(/Hello (\w+), code=(\d+)/)
26
- end
27
- abort(session.error) unless matched
28
- puts session.match
29
- session.soft_close(timeout: 1)
30
- end
@@ -1,81 +0,0 @@
1
- # 本地 Kibitz 示例与测试
2
-
3
- 参考 [Expect.pm 的 kibitz](https://github.com/jacoby/expect.pm/tree/master/examples/kibitz),使用本项目的 `Expect.open`
4
- 块、`listeners=`、`on_sequence` 和 `Expect.interconnect` 连接两端输入与同一个交互进程。参考源码为上游提交
5
- `2ea0e4ce20a896c95cb4c94e781f1b1f3145150d`。
6
-
7
- 需要 Ruby 3.2+ 和 macOS/Linux。示例和自动脚本只依赖标准库,不需要 SSH 服务或密码。
8
-
9
- ## 两个终端手工运行
10
-
11
- 在第一个终端运行:
12
-
13
- ```sh
14
- ruby examples/kibitz/kibitz.rb -- /bin/sh -i
15
- ```
16
-
17
- 程序打印一条完整的 `--join /tmp/expect-kibitz-.../peer.sock` 命令。在本机、同一账户的第二个终端执行这条命令,两端即可操作同一个
18
- shell。输入和输出在两端都可见,例如:
19
-
20
- ```sh
21
- # 第一个终端设置 shell 变量
22
- shared_value=42
23
- # 第二个终端读取同一个变量
24
- printf '%s\n' "$shared_value"
25
- ```
26
-
27
- 任一端输入 `exit` 结束共享 shell;Ctrl-C 发给共享进程的前台任务。任一端按 Ctrl-] 结束自己的转接并断开连接,另一端随 EOF
28
- 结束。终端配置在退出时恢复。可以通过 `-- program args...` 运行其他交互程序;不传程序时使用 `$SHELL`,缺省 `/bin/sh`。
29
-
30
- ## 无子进程互传和可选参数
31
-
32
- ```sh
33
- # 输入只传给另一端,没有本地回显
34
- ruby examples/kibitz/kibitz.rb --noproc
35
-
36
- # 自定义本端转义键(第二端可在自己的加入命令中独立设置)
37
- ruby examples/kibitz/kibitz.rb --escape '^X' -- /bin/sh -i
38
-
39
- # 禁用本端转义,Ctrl-] 也作为普通数据转发
40
- ruby examples/kibitz/kibitz.rb --noescape -- /bin/sh -i
41
-
42
- # 等待加入最多 30 秒,加入后转接也最多 30 秒;日志文件必须尚不存在
43
- ruby examples/kibitz/kibitz.rb --timeout 30 --log /tmp/my-kibitz-session.log -- /bin/sh -i
44
- ```
45
-
46
- 共享进程模式的日志记录该进程实际返回的字节,包括终端回显;无子进程模式记录对端返回的字节。日志使用 0600
47
- 权限。进程正常结束时,发起端返回该进程的退出码;转义或对端 EOF 返回 0,超时或连接失败返回非零。加入端只能观察连接结束,不取得共享进程的退出码。
48
-
49
- 这是同账户本地示例:连接使用 0700 临时目录内的 0600 Unix socket,接受一位加入者后移除 socket,退出时清理目录。原例的用户邀请、跨主机
50
- rlogin、FIFO 以及转义菜单没有移植;双方终端初始尺寸由发起端决定,未实现运行期间的窗口尺寸同步。
51
-
52
- ## 自动运行同样的两个终端流程
53
-
54
- ```sh
55
- ruby examples/kibitz/test_kibitz.rb
56
- # 或
57
- bundle exec rake test:kibitz
58
- ```
59
-
60
- 脚本真正启动两份 `kibitz.rb`,通过两个独立 PTY 模拟两位用户,并执行打印出的 Unix socket 加入流程。共享模式运行真实
61
- `/bin/sh -i`,没有 mock 转发逻辑。
62
-
63
- | 场景 | 检查 |
64
- |-------------------|-------------------------------------------------------------------------|
65
- | 共享 shell | 输入回显、双方命令、共享变量、两端输出、中文、stderr、失败后继续执行 |
66
- | Ctrl-C 与进程 EOF | 第二端中断第一端启动的前台任务,最终输出到达两端,进程退出 |
67
- | `--noproc` | 双向字节互传,发送端无本地回显 |
68
- | 自定义转义 | `STOP` 分两次发送,前缀不泄漏,转义和尾部不进入对端 |
69
- | 加入端转义 | Ctrl-] 关闭加入端,发起端响应 EOF |
70
- | `--noescape` | Ctrl-] 字节被完整转发 |
71
- | 非零退出 | 共享 shell 返回 7,发起程序也返回 7 |
72
- | 超时 | 转接到期返回失败,另一端结束 |
73
- | 每个场景 | 就绪时已关闭本地回显,退出后两端终端配置恢复,socket 清理、日志权限正确 |
74
-
75
- 每轮结果写入 `tmp/kibitz/` 的独立目录,可用 `EXPECT_LOG_DIR` 指定其他目录。`report.json` 包含各场景检查项与整体 `passed`
76
- ,各场景子目录保留 `session.log`。只有全部检查通过才返回 0。默认测试集还覆盖没有第二端加入时的超时清理:
77
-
78
- ```sh
79
- bundle exec ruby -Itest test/kibitz_test.rb
80
- bundle exec rake test
81
- ```