Table of Contents

Core 故障注入面使用指南——IO 缝(FaultInjectingFileSystem)与时钟缝(FakeTimeProvider)

对应设计:docs/design/fault-injection-surface-design.md(件一时钟缝 / 件三 IO 缝扩展)。 哲学锚:注入脸只建在真实失败边界上,且是常设面非测试代码泄漏(spec-12 §9.2 传输面先例)。

0. 快速开始(30 秒上手)

// IO 缝——错误/腐败/慢/挂/乱序六族规则,装饰任意 IFileSystem
using var fi = new FaultInjectingFileSystem(TierFs.New("memory:"));
fi.AddRule("*", "Write", IOError.DiskFull, failAtCallIndex: 1);        // 第 1 次写 DiskFull
fi.AddCorruptRule("data", "Write", offset: 8, mask: new byte[] { 0xFF }); // 静默腐败
using var dev = new StorageEngineOptions("eng").Builder(fi).Start();   // 注入引擎根 fs

// 时钟缝——假钟快进驱动一切 provider 时间语义
var clock = new FakeTimeProvider();
var kv = await TierKvOfLongLong.CreateAsync(fs, TierKvOptions.Default.WithKvName("kv").WithClock(clock));
clock.Advance(TimeSpan.FromSeconds(61));   // TTL 过期判定即刻生效——零真实睡等

1. IO 缝:FaultInjectingFileSystem(TC.Tier.Core.IO.Testing,internal——测试经 IVT 可见)

装饰器形态:持有内层 IFileSystem,句柄包装为 FaultInjectingFileHandle。规则 = 「路径 × 操作 × 命中仲裁」三维: 路径/操作匹配是精确名或 "*";命中仲裁 = 概率(seeded Random——可复现)或第 N 次(failAtCallIndex,1 起, 两者都设时确定性优先)。每条规则暴露 MatchCount(命中记账,可观测)。

六族规则(可叠加,各管各的注入维度)

API 注入点 语义
错误(类型化) AddRule(path, op, IOError, probability, failAtCallIndex, detail) 前置 FileIOException(语义码透传)
错误(自定义异常) AddExceptionRule(path, op, Func<Exception>, …) 前置 非致命异常传播边界
延迟 AddDelayRule(path, op, TimeSpan, …) 前置 同步 Thread.Sleep / 异步 Task.Delay(ct 可取消)——watchdog/有界等待触发器
挂起 AddHangRule(path, op, detail) 前置 操作永不到达内层;异步路径 ct 取消即出(有界等待路径);ClearRules/Dispose 释放门仅供拆除
乱序 AddReorderRule(path, op, TimeSpan holdDelay, …) 前置(仅异步写族:WriteAsync/AppendAsync/WriteVectorAsync) 命中操作延后 hold 再提交——与其后并发到达操作形成受控乱序;同步操作永不命中
腐败 AddCorruptRule(path, op, long offset, ReadOnlyMemory<byte> mask, …) 后置(写族转发成功后) 对介质 [offset, offset+mask.Length) 现存字节按 mask[i % Length] 循环 XOR(读-XOR-写回,静默不抛)——读自愈/CRC 判废/MagicLocator 恢复扫描的对抗抓手

注入链与注入点全集

  • 同步入口链:错误(抛)→ 延迟(睡)→ 挂起(阻塞)。fs 级操作(Open/Delete/CreateFile/Stat/Enumerate*/…)与 句柄同步数据面(Write/Read/Append/Flush/PunchHole/CopyRange/…)共用同链。
  • 异步入口链:错误 → 延迟(异步等)→ 挂起(WaitAsync(ct))→(写族)乱序裁决 → 转发 →(写族)腐败评估。 异步注入点:WriteAsync / ReadAsync / AppendAsync / WriteVectorAsync / ReadVectorAsync。
  • 腐败后置评估点:Write / Append / WriteVector / CopyRange / CloneRange 及其异步版。
  • ClearRules():六族全清 + 释放挂起门;Dispose() 同样先放行挂起线程再转发内层。

反模式(禁忌)

  1. 挂起规则不设拆除外置——挂点在故障语义下永不放行,测试必须以被测方超时/取消路径先行处置; 依赖 ClearRules/Dispose 放行当"正常路径"= 测试假绿。
  2. 乱序规则打同步操作——永不命中(乱序需要异步解耦);静默不命中是设计契约,不是缺陷。
  3. 腐败规则按"当前写负载"寻址——腐败以介质绝对偏移寻址,翻转的是落盘现存字节(可能来自更早的写)。
  4. 真实乱序/掉电时序拿 mem 卷当真——mem 卷保序前提下的受控乱序只服务恢复协议确定性测试; 真盘乱序归云上形态(二者互补,见 VALIDATIONS.md 各 V 项"本地注入形态/云上形态")。

2. 时钟缝:FakeTimeProvider(TC.Tier.Core.Testing,public——零外部依赖替身)

BCL TimeProvider 自建测试替身(不用 Microsoft.Extensions.TimeProvider.Testing)。双钟模型:

读数 API 注入 语义
单调钟 GetTimestamp()(ms 域,TimestampFrequency=1000——与 Environment.TickCount64 同域) Advance(delta) 快进 停走/倒流免疫;墙钟跳变不污染
墙钟 GetUtcNow() Advance(按走速)/ SetWallClock(跳变)/ SetDrift(rate)(走速) TTL/租约消费点;跳变建模 NTP 校时
  • Advance 同步推进双钟并按到期序同步触发到期定时器(周期定时器在大跨度 Advance 内连发;回调异常原样 冒泡不吞);Advance(TimeSpan.Zero) = 冲刷已到期定时器;due ≤ 0 的定时器"创建即到期"(下次 Advance 触发)。
  • CreateTimer 返回完整 ITimer(DueTime/Period 可读写、Change 可重挂、Dispose 解除挂载)。
  • 缺省零变化TimeProvider.System 下一切落点行为逐字节同现状;单调戳经 TimeProviderExtensions.GetMsTimestamp()(System 快路径直读 TickCount64),延迟经 TimeProviderExtensions.Delay()(System 直通 Task.Delay)。
  • 消费侧统一供给源:组件 Options 以 TimeProvider Clock { get; init; } = TimeProvider.System; 形态注入 (RaftOptions.WithClock / TierKvOptions.WithClock / TierQueueOptions.WithClock / DistributedLock 锁组状态机与客户端构造参 / DeadlineRegistry(clock:))。

反模式(禁忌)

  1. 假钟不配同钟节拍注册表——raft 侧注入假钟时不显式传 registry 即自动新建同钟注册表; 自行混搭(假钟 options + Shared 注册表)= deadline 判定错乱。
  2. 对墙钟消费点断言"倒流后复活"——TTL 观测点带单调水位守卫(TierKv.NowUtcTicks),已判过期项不复活; 测试应断言不复活(§1.3 矩阵倒流行)。
  3. 等待循环用真实 Thread.Sleep 判定假钟推进——假钟语义下用 Advance 驱动;raft 节拍线程为真实线程 (同钟注册表,100ms 封顶扫描粒度),快进后到 Role 收敛允许 ≤ 数百 ms 真实延迟。
  4. TimeSpan.FromMilliseconds(-1) 当负延迟用——它是 Timeout.InfiniteTimeSpan 哨兵(永不完成)。

3. 指路

  • 引擎缝(IStorageEngineFaultInjector):见 src/TC.Tier.Runtime/docs/storage-engine.md §故障注入面。
  • 本地注入形态 / 云上形态落账:scripts/cloud/VALIDATIONS.md 各 V 项。
  • 设计定案:docs/design/fault-injection-surface-design.md(内部)。