package diag import ( "bytes" "strings" "testing" ) // TestIndirectResolvesAtWriteTime:**关键性质**——Indirect 在写入时才去向, // 所以在它被交给子进程之后、再 SetWriter 重定向,后续写入仍会走新去向。 // // 这正是 MCP 子进程 stderr 的场景:子进程在 buildRuntime 里启动(那时 TUI 还没建 // 日志文件),日志文件的绑定必须晚一步生效,否则就钉死在 os.Stderr 上、打穿 alt-screen。 func TestIndirectResolvesAtWriteTime(t *testing.T) { before := Writer() defer SetWriter(before) // 别污染其他测试 var early, late bytes.Buffer if _, err := Indirect().Write([]byte("early\n")); err != nil { t.Fatal(err) } // 默认去向是 os.Stderr,这里只验证"能写不报错";重点在下面。 SetWriter(&early) w := Indirect() if _, err := w.Write([]byte("a\n")); err != nil { t.Fatal(err) } // 重定向之后:同一个 w 应当写到新去向 SetWriter(&late) if _, err := w.Write([]byte("b\n")); err != nil { t.Fatal(err) } if !strings.Contains(early.String(), "a") { t.Errorf("重定向前应写进第一个 sink,实际 %q", early.String()) } if !strings.Contains(late.String(), "b") { t.Errorf("重定向后同一个 writer 应写进新 sink,实际 %q", late.String()) } } // TestSetWriterNilDiscards:传 nil 表示丢弃(TUI 想彻底静音时用)。 func TestSetWriterNilDiscards(t *testing.T) { before := Writer() defer SetWriter(before) SetWriter(nil) if Writer() == nil { t.Fatal("nil 应被换成非 nil 的丢弃 writer") } Printf("这行不该 panic,也不该出现在任何地方\n") } // TestPrintfGoesToWriter:Printf 走当前去向。 func TestPrintfGoesToWriter(t *testing.T) { before := Writer() defer SetWriter(before) var buf bytes.Buffer SetWriter(&buf) Printf("hello %s\n", "autogo") if !strings.Contains(buf.String(), "hello autogo") { t.Errorf("Printf 没写到当前去向:%q", buf.String()) } }