package bus import ( "bytes" "context" "errors" "fmt" "io" "log/slog" "net" "os" "path/filepath" "strings" "sync/atomic" "testing" "time" dwsevent "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/event" eventlock "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/event/lock" "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/event/runtimecred" "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/event/transport" ) var errBusInjected = errors.New("injected bus failure") func TestCrossPlatformCoverageMatcherConsumerAndCounterEdges(t *testing.T) { m, err := compileMatcher([]string{"", "*", "im.*", "prefix*", "exact"}, "^im", " sub ") if err != nil { t.Fatal(err) } if m.matches(nil) { t.Fatal("nil event matched") } for _, tc := range []struct { eventType, subscribe string want bool }{ {"exact", "sub", false}, {"im.message", "other", false}, {"im.message", "sub", true}, {"prefix-value", "sub", false}, } { if got := m.matches(&dwsevent.RawEvent{EventType: tc.eventType, SubscribeID: tc.subscribe}); got != tc.want { t.Fatalf("matches(%q,%q) = %v", tc.eventType, tc.subscribe, got) } } m, _ = compileMatcher([]string{"exact", "pre*"}, "", "") if !m.matches(&dwsevent.RawEvent{EventType: "exact"}) || !m.matches(&dwsevent.RawEvent{EventType: "prefix"}) { t.Fatal("exact/prefix matcher failed") } if m.matches(&dwsevent.RawEvent{EventType: "other"}) { t.Fatal("unexpected matcher hit") } re := &RegisterError{Err: errBusInjected} if !errors.Is(re, errBusInjected) || re.Error() == "" { t.Fatal("register error contract") } h := NewHub(0) h.Deliver(nil) c := &Consumer{SendCh: make(chan any), matcher: consumerMatcher{catchAll: true}} c.deliver(mkEvent("unbuffered", "1"), h.Counters()) if c.dropped.Load() != 1 { t.Fatalf("unbuffered dropped = %d", c.dropped.Load()) } if ok, evicted := c.tryPushOrDropOldestLocked("x"); ok || evicted { t.Fatalf("unbuffered = %v,%v", ok, evicted) } c.closed = true c.deliver(mkEvent("closed", "2"), h.Counters()) if c.enqueue("x") { t.Fatal("closed enqueue succeeded") } c.closeSend() buffered := &Consumer{SendCh: make(chan any, 1)} buffered.SendCh <- "old" if ok, evicted := buffered.tryPushOrDropOldestLocked("new"); !ok || !evicted { t.Fatalf("drop oldest = %v,%v", ok, evicted) } buffered.closeSend() buffered.closeSend() counters := NewPerTypeCounters() counters.row("zero") if got := counters.DropRatePercent("zero"); got != -1 { t.Fatalf("zero rate = %d", got) } origHook := counterRowMissHook t.Cleanup(func() { counterRowMissHook = origHook }) inserted := false counterRowMissHook = func() { if inserted { return } inserted = true counters.mu.Lock() counters.m["raced"] = &typeRow{} counters.mu.Unlock() } if counters.row("raced") == nil { t.Fatal("raced row missing") } } func TestCrossPlatformCoverageDropWarningScanEdges(t *testing.T) { origInterval := dropWarnTickInterval t.Cleanup(func() { dropWarnTickInterval = origInterval }) ctx, cancel := context.WithCancel(context.Background()) cancel() dropWarnWatcher(ctx, NewPerTypeCounters(), slog.Default(), 0) dropWarnWatcher(ctx, NewPerTypeCounters(), slog.Default(), 50) c := NewPerTypeCounters() c.AddReceived("healthy") c.AddReceived("warn") c.AddDropped("warn") state := map[string]int{"healthy": 90} var logs bytes.Buffer logger := slog.New(slog.NewTextHandler(&logs, nil)) scanDropWarnings(c, logger, 25, state) if _, ok := state["healthy"]; ok { t.Fatal("healthy warning state retained") } if state["warn"] == 0 || logs.Len() == 0 { t.Fatal("warning not emitted") } before := logs.Len() scanDropWarnings(c, logger, 25, state) if logs.Len() != before { t.Fatal("warning hysteresis failed") } for i := 0; i < 10; i++ { c.AddDropped("warn") } scanDropWarnings(c, logger, 25, state) if logs.Len() == before { t.Fatal("worsened warning not emitted") } dropWarnTickInterval = time.Millisecond ctx, cancel = context.WithTimeout(context.Background(), 4*time.Millisecond) defer cancel() dropWarnWatcher(ctx, c, logger, 25) } func TestCrossPlatformCoverageLockFailureInjection(t *testing.T) { origTry := busTryAcquire origSeek := busSeek origRead := busReadAll origAlive := busProcessAlive origTruncate := busTruncate origFprintf := busFprintf origSync := busSync t.Cleanup(func() { busTryAcquire = origTry busSeek = origSeek busReadAll = origRead busProcessAlive = origAlive busTruncate = origTruncate busFprintf = origFprintf busSync = origSync }) busTryAcquire = func(string) (*eventlock.File, error) { return nil, errBusInjected } if _, err := Acquire("x"); err == nil { t.Fatal("acquire error expected") } busTryAcquire = origTry newPath := func(name string) string { return filepath.Join(t.TempDir(), name) } busSeek = func(*os.File, int64, int) (int64, error) { return 0, errBusInjected } if _, err := Acquire(newPath("seek")); err == nil { t.Fatal("seek error expected") } busSeek = origSeek busReadAll = func(io.Reader) ([]byte, error) { return nil, errBusInjected } if _, err := Acquire(newPath("read")); err == nil { t.Fatal("read error expected") } busReadAll = origRead path := newPath("alive") if err := os.WriteFile(path, []byte("123\n"), 0o600); err != nil { t.Fatal(err) } busProcessAlive = func(int) bool { return true } if _, err := Acquire(path); !errors.Is(err, ErrStaleOwnerAlive) { t.Fatalf("alive error = %v", err) } busProcessAlive = origAlive busTruncate = func(*os.File, int64) error { return errBusInjected } if _, err := Acquire(newPath("write")); err == nil { t.Fatal("write PID error expected") } busTruncate = origTruncate lock, err := Acquire(newPath("held")) if err != nil { t.Fatal(err) } if lock.HoldsPath() == "" { t.Fatal("held path empty") } _ = lock.Close() if lock.HoldsPath() != "" { t.Fatal("closed path retained") } var nilLock *Lock if nilLock.HoldsPath() != "" || nilLock.Close() != nil { t.Fatal("nil lock contract") } f, err := os.CreateTemp(t.TempDir(), "pid") if err != nil { t.Fatal(err) } defer f.Close() busTruncate = func(*os.File, int64) error { return errBusInjected } if truncateAndWritePID(f, 1) == nil { t.Fatal("truncate failure expected") } busTruncate = func(*os.File, int64) error { return nil } busSeek = func(*os.File, int64, int) (int64, error) { return 0, errBusInjected } if truncateAndWritePID(f, 1) == nil { t.Fatal("PID seek failure expected") } busSeek = origSeek busFprintf = func(io.Writer, string, ...any) (int, error) { return 0, errBusInjected } if truncateAndWritePID(f, 1) == nil { t.Fatal("PID write failure expected") } busFprintf = origFprintf busSync = func(*os.File) error { return errBusInjected } if truncateAndWritePID(f, 0) == nil { t.Fatal("sync failure expected") } } func TestCrossPlatformCoverageMetaFailureInjection(t *testing.T) { origMarshal := metaMarshalIndent origWrite := metaWriteFile origRename := metaRename origRemove := metaRemove t.Cleanup(func() { metaMarshalIndent = origMarshal metaWriteFile = origWrite metaRename = origRename metaRemove = origRemove }) metaMarshalIndent = func(any, string, string) ([]byte, error) { return nil, errBusInjected } if WriteMeta(t.TempDir(), Meta{}) == nil { t.Fatal("marshal error expected") } metaMarshalIndent = origMarshal metaWriteFile = func(string, []byte, os.FileMode) error { return errBusInjected } if WriteMeta(t.TempDir(), Meta{}) == nil { t.Fatal("write error expected") } metaWriteFile = origWrite removed := false metaRename = func(string, string) error { return errBusInjected } metaRemove = func(string) error { removed = true; return nil } if WriteMeta(t.TempDir(), Meta{}) == nil || !removed { t.Fatal("rename cleanup error expected") } } type edgeSource struct { start func(context.Context, dwsevent.EmitFn) error } func (s edgeSource) Start(ctx context.Context, emit dwsevent.EmitFn) error { return s.start(ctx, emit) } func TestCrossPlatformCoverageRunStartupAndSourceEdges(t *testing.T) { if err := Run(context.Background(), Config{}); err == nil { t.Fatal("source validation expected") } origMkdir := daemonMkdirAll origAcquire := daemonAcquire origMeta := daemonWriteMeta origListen := daemonListen t.Cleanup(func() { daemonMkdirAll = origMkdir daemonAcquire = origAcquire daemonWriteMeta = origMeta daemonListen = origListen }) source := edgeSource{start: func(context.Context, dwsevent.EmitFn) error { return errBusInjected }} base := Config{WorkDir: t.TempDir(), IPCEndpoint: filepath.Join(t.TempDir(), "bus.sock"), Source: source} daemonMkdirAll = func(string, os.FileMode) error { return errBusInjected } if err := Run(context.Background(), base); err == nil { t.Fatal("mkdir error expected") } daemonMkdirAll = origMkdir daemonAcquire = func(string) (*Lock, error) { return nil, errBusInjected } if err := Run(context.Background(), base); err == nil { t.Fatal("lock error expected") } daemonAcquire = origAcquire daemonWriteMeta = func(string, Meta) error { return errBusInjected } if err := Run(context.Background(), base); err == nil { t.Fatal("meta error expected") } daemonWriteMeta = origMeta daemonListen = func(string) (transport.Listener, error) { return nil, errBusInjected } if err := Run(context.Background(), base); err == nil { t.Fatal("listen error expected") } daemonListen = origListen workDir := shortTempDir(t) base.WorkDir = workDir base.IPCEndpoint = dwsevent.IPCEndpoint( workDir, "open", dwsevent.SourceKindAppStream, dwsevent.IdentityHash(workDir), ) base.Logger = slog.New(slog.NewTextHandler(io.Discard, nil)) base.Source = edgeSource{start: func(_ context.Context, emit dwsevent.EmitFn) error { emit(nil) e := &dwsevent.RawEvent{EventID: "same", EventType: "type", ReceivedAt: time.Now()} emit(e) emit(e) return errBusInjected }} if err := Run(context.Background(), base); !errors.Is(err, errBusInjected) { t.Fatalf("source error = %v", err) } runtimeWorkDir := shortTempDir(t) base.WorkDir = runtimeWorkDir base.IPCEndpoint = dwsevent.IPCEndpoint( runtimeWorkDir, "open", dwsevent.SourceKindPersonalStream, dwsevent.IdentityHash(runtimeWorkDir), ) base.Source = edgeSource{start: func(context.Context, dwsevent.EmitFn) error { return runtimecred.ErrRuntimeTokenRejected }} if err := Run(context.Background(), base); !errors.Is(err, runtimecred.ErrRuntimeTokenRejected) { t.Fatalf("runtime source error = %v", err) } } type scriptedListener struct { accept func() (net.Conn, error) closed bool } func (l *scriptedListener) Accept() (net.Conn, error) { return l.accept() } func (l *scriptedListener) Close() error { l.closed = true; return nil } func (*scriptedListener) Endpoint() string { return "edge" } func TestCrossPlatformCoverageDaemonMethodEdges(t *testing.T) { logger := slog.New(slog.NewTextHandler(io.Discard, nil)) calls := 0 l := &scriptedListener{accept: func() (net.Conn, error) { calls++ if calls == 1 { return nil, errBusInjected } return nil, net.ErrClosed }} d := &daemon{listener: l, log: logger, hub: NewHub(1), idleStop: make(chan struct{}), stopReq: make(chan string, 1)} d.acceptLoop(context.Background()) d.shuttingDown.Store(true) d.acceptLoop(context.Background()) d.triggerShutdown("test") select { case reason := <-d.stopReq: if reason != "test" { t.Fatalf("stop reason = %q", reason) } default: t.Fatal("trigger did not notify lifecycle loop") } d = &daemon{listener: &scriptedListener{accept: func() (net.Conn, error) { return nil, net.ErrClosed }}, log: logger, hub: NewHub(1), idleStop: make(chan struct{})} d.idleWatch(context.Background()) ctx, cancel := context.WithCancel(context.Background()) d.cfg.IdleTimeout = time.Millisecond cancel() d.idleWatch(ctx) d = &daemon{cfg: Config{IdleTimeout: 4 * time.Millisecond}, log: logger, hub: NewHub(1), idleStop: make(chan struct{})} consumer, _ := d.hub.Register(transport.Hello{}) idleDone := make(chan struct{}) go func() { d.idleWatch(context.Background()); close(idleDone) }() time.Sleep(3 * time.Millisecond) d.hub.Unregister(consumer.ID) select { case <-idleDone: case <-time.After(50 * time.Millisecond): t.Fatal("idle watcher did not stop") } origTimeout := daemonShutdownTimeout t.Cleanup(func() { daemonShutdownTimeout = origTimeout }) daemonShutdownTimeout = time.Millisecond d.listener = &scriptedListener{accept: func() (net.Conn, error) { return nil, net.ErrClosed }} d.conns.Store("not-a-conn", struct{}{}) d.conns.Store(&queryConn{}, struct{}{}) d.consumerWG.Add(1) acceptDone := make(chan struct{}) close(acceptDone) d.shutdown(acceptDone) d.consumerWG.Done() d.shutdown(acceptDone) pr, pw, err := os.Pipe() if err != nil { t.Fatal(err) } want := errBusInjected if got := failReady(pw, want); !errors.Is(got, want) { t.Fatal(got) } b := make([]byte, 1) _, _ = pr.Read(b) _ = pr.Close() if b[0] != 'E' { t.Fatalf("fail ready byte = %q", b) } if failReady(nil, want) != want { t.Fatal("nil failReady changed error") } } func TestCrossPlatformCoverageHandleConnectionProtocolEdges(t *testing.T) { logger := slog.New(slog.NewTextHandler(io.Discard, nil)) newDaemon := func() *daemon { return &daemon{ cfg: Config{ClientID: "client", Edition: "open", IdleTimeout: time.Second}, log: logger, hub: NewHub(2), started: time.Now(), idleStop: make(chan struct{}), listener: &scriptedListener{accept: func() (net.Conn, error) { return nil, net.ErrClosed }}, } } run := func(d *daemon, action func(net.Conn)) { server, client := net.Pipe() done := make(chan struct{}) go func() { d.handleConnection(context.Background(), server); close(done) }() action(client) _ = client.Close() select { case <-done: case <-time.After(time.Second): t.Fatal("connection handler did not return") } } run(newDaemon(), func(c net.Conn) {}) run(newDaemon(), func(c net.Conn) { _ = transport.NewWriter(c).WriteJSON(transport.StatusReq{Type: transport.FrameTypeStatusReq}) }) run(newDaemon(), func(c net.Conn) { _ = transport.NewWriter(c).WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleStatus}) }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleStatus}) _ = w.WriteJSON(transport.StatusReq{Type: transport.FrameTypeStatusReq}) var resp transport.StatusResp if err := r.ReadJSON(&resp); err != nil { t.Fatal(err) } }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleStop}) var bye transport.Bye if err := r.ReadJSON(&bye); err != nil { t.Fatal(err) } }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleConsumerStop}) _ = w.WriteJSON(transport.StatusReq{Type: transport.FrameTypeStatusReq}) var resp transport.ConsumerStopResp if err := r.ReadJSON(&resp); err != nil { t.Fatal(err) } if resp.Type != transport.FrameTypeConsumerStopResp || !strings.Contains(resp.Error, "unexpected") { t.Fatalf("consumer stop protocol error = %#v", resp) } }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleConsumerStop}) _, _ = c.Write([]byte("{\n")) var resp transport.ConsumerStopResp if err := r.ReadJSON(&resp); err != nil { t.Fatal(err) } if resp.Type != transport.FrameTypeConsumerStopResp || resp.Error != "malformed consumer stop request" { t.Fatalf("malformed consumer stop response = %#v", resp) } }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Role: transport.HelloRoleConsumerStop}) _ = w.WriteJSON(transport.ConsumerStopReq{ Type: transport.FrameTypeConsumerStopReq, SubscribeIDs: []string{"", "missing", "missing"}, }) var resp transport.ConsumerStopResp if err := r.ReadJSON(&resp); err != nil { t.Fatal(err) } if len(resp.NotFound) != 1 || resp.NotFound[0] != "missing" { t.Fatalf("consumer stop response = %#v", resp) } }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello, Filter: "["}) var bye transport.Bye if err := r.ReadJSON(&bye); err != nil { t.Fatal(err) } }) run(newDaemon(), func(c net.Conn) { _ = transport.NewWriter(c).WriteJSON(transport.Hello{Type: transport.FrameTypeHello}) _ = c.Close() }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello}) var ack transport.HelloAck if err := r.ReadJSON(&ack); err != nil { t.Fatal(err) } _, _ = c.Write([]byte("{\n")) _ = w.WriteJSON(transport.StatusReq{Type: transport.FrameTypeStatusReq}) _ = w.WriteJSON(transport.Bye{Type: transport.FrameTypeBye}) }) run(newDaemon(), func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello}) var ack transport.HelloAck if err := r.ReadJSON(&ack); err != nil { t.Fatal(err) } payload := bytes.Repeat([]byte("x"), transport.MaxFrameBytes+1) _ = c.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) _, _ = c.Write(payload) }) d := newDaemon() run(d, func(c net.Conn) { w, r := transport.NewWriter(c), transport.NewReader(c) _ = w.WriteJSON(transport.Hello{Type: transport.FrameTypeHello}) var ack transport.HelloAck if err := r.ReadJSON(&ack); err != nil { t.Fatal(err) } d.hub.Broadcast(transport.Bye{Type: transport.FrameTypeBye}) time.Sleep(time.Millisecond) }) } func TestCrossPlatformCoverageHandleConnectionPrioritizesQueuedConsumerStop(t *testing.T) { d := &daemon{ cfg: Config{ClientID: "client", Edition: "open", IdleTimeout: time.Second}, log: slog.New(slog.NewTextHandler(io.Discard, nil)), hub: NewHub(2), started: time.Now(), idleStop: make(chan struct{}), } server, client := net.Pipe() countedServer := &countingCloseConn{Conn: server} done := make(chan struct{}) go func() { d.handleConnection(context.Background(), countedServer) close(done) }() w, r := transport.NewWriter(client), transport.NewReader(client) if err := w.WriteJSON(transport.Hello{ Type: transport.FrameTypeHello, SubscribeID: "sub-priority", }); err != nil { t.Fatal(err) } deadline := time.Now().Add(time.Second) for d.hub.Len() != 1 { if time.Now().After(deadline) { t.Fatal("consumer was not registered") } time.Sleep(time.Millisecond) } if stopped := d.hub.StopConsumers([]string{"sub-priority"}, "priority-stop"); len(stopped) != 1 { t.Fatalf("stopped = %#v", stopped) } var ack transport.HelloAck if err := r.ReadJSON(&ack); err != nil { t.Fatal(err) } var bye transport.Bye if err := r.ReadJSON(&bye); err != nil { t.Fatal(err) } if bye.Reason != "priority-stop" { t.Fatalf("bye = %#v", bye) } _ = client.Close() select { case <-done: case <-time.After(time.Second): t.Fatal("connection handler did not stop") } if got := countedServer.closeCount.Load(); got != 1 { t.Fatalf("underlying connection close count = %d, want 1", got) } } func TestCrossPlatformCoverageEnsureCloseOnceReusesWrapper(t *testing.T) { server, client := net.Pipe() defer client.Close() counted := &countingCloseConn{Conn: server} wrapped := ensureCloseOnce(counted) if got := ensureCloseOnce(wrapped); got != wrapped { t.Fatal("ensureCloseOnce wrapped an already managed connection") } if err := wrapped.Close(); err != nil { t.Fatal(err) } if err := wrapped.Close(); err != nil { t.Fatal(err) } if got := counted.closeCount.Load(); got != 1 { t.Fatalf("underlying connection close count = %d, want 1", got) } } type countingCloseConn struct { net.Conn closeCount atomic.Int32 } func (c *countingCloseConn) Close() error { c.closeCount.Add(1) return c.Conn.Close() } type queryConn struct{} func (*queryConn) Read([]byte) (int, error) { return 0, io.EOF } func (*queryConn) Write(p []byte) (int, error) { return len(p), nil } func (*queryConn) Close() error { return nil } func (*queryConn) LocalAddr() net.Addr { return edgeAddr("local") } func (*queryConn) RemoteAddr() net.Addr { return edgeAddr("remote") } func (*queryConn) SetDeadline(time.Time) error { return nil } func (*queryConn) SetReadDeadline(time.Time) error { return nil } func (*queryConn) SetWriteDeadline(time.Time) error { return nil } type edgeAddr string func (a edgeAddr) Network() string { return string(a) } func (a edgeAddr) String() string { return string(a) } var _ = fmt.Sprintf