// SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "errors" "git.stormux.org/storm/cthulhu/internal/atspi" "git.stormux.org/storm/cthulhu/internal/review" "git.stormux.org/storm/cthulhu/internal/wine" "testing" ) type reviewNativeSpy struct { calls []string ids []atspi.ObjectID } func (s *reviewNativeSpy) record(method string, id atspi.ObjectID) (*atspi.AccessibleTree, error) { s.calls = append(s.calls, method) s.ids = append(s.ids, id) return nil, nil } func (s *reviewNativeSpy) CaptureDesktop(context.Context) (*atspi.AccessibleTree, error) { return s.record("desktop", atspi.ObjectID{}) } func (s *reviewNativeSpy) CaptureReviewWindow(_ context.Context, id atspi.ObjectID) (*atspi.AccessibleTree, error) { return s.record("review", id) } func (s *reviewNativeSpy) CaptureDocument(_ context.Context, id atspi.ObjectID) (*atspi.AccessibleTree, error) { return s.record("document", id) } func (s *reviewNativeSpy) CaptureDocumentText(_ context.Context, id atspi.ObjectID) (*atspi.AccessibleTree, error) { return s.record("text", id) } type reviewWineSpy struct { calls int err error } func (s *reviewWineSpy) Capture(context.Context, atspi.ObjectID) (*atspi.AccessibleTree, error) { s.calls++ return nil, s.err } func TestReviewCaptureRouterNativeDelegation(t *testing.T) { native := &reviewNativeSpy{} r := &reviewCaptureRouter{native: native, wine: &reviewWineSpy{}} id := atspi.NewObjectID(":1.2", "/linux") r.CaptureDesktop(context.Background()) r.CaptureReviewWindow(context.Background(), id) r.CaptureDocument(context.Background(), id) r.CaptureDocumentText(context.Background(), id) if len(native.calls) != 4 || native.calls[0] != "desktop" || native.calls[1] != "review" || native.calls[2] != "document" || native.calls[3] != "text" || r.FreshReviewWindow(id) || r.NativeCapturerFor(id) != native { t.Fatal("native delegation changed") } for _, got := range native.ids[1:] { if got != id { t.Fatal("native identity changed") } } } func TestReviewCaptureRouterWineIDsNeverReachATSPINativeCalls(t *testing.T) { native := &reviewNativeSpy{} provider := &reviewWineSpy{err: wine.ErrReviewLimited} r := &reviewCaptureRouter{native: native, wine: provider} ids := []atspi.ObjectID{wine.ReviewID(":1.2", "instance", "window", "input"), atspi.NewObjectID(":1.2", "/wine/malformed"), atspi.NewObjectID(":1.2", "/wine")} for _, id := range ids { if !r.FreshReviewWindow(id) || r.NativeCapturerFor(id) != nil { t.Fatal("Wine optional native capability exposed") } if _, err := r.CaptureDocument(context.Background(), id); !errors.Is(err, wine.ErrReviewUnavailable) { t.Fatal(err) } if _, err := r.CaptureDocumentText(context.Background(), id); !errors.Is(err, wine.ErrReviewUnavailable) { t.Fatal(err) } _, err := r.CaptureReviewWindow(context.Background(), id) if wine.IsReviewID(id) && !errors.Is(err, review.ErrLimitedReview) { t.Fatal("limit message mapping lost") } } if len(native.calls) != 0 || provider.calls != 1 { t.Fatalf("native Wine calls: %+v", native.calls) } }