tinyrelayfile
tinyrelay/internal/daemon/git_live_test.go/

internal/daemon/git_live_test.go raw
1package daemon
2
3import (
4 "context"
5 "strings"
6 "testing"
7 "time"
8
9 "github.com/FelineStateMachine/tinyrelay/internal/event"
10 gitrelay "github.com/FelineStateMachine/tinyrelay/tinygit"
11)
12
13func TestGitLiveEnabledRequiresGRASP02(t *testing.T) {
14 _, tenant := testTenant(t)
15 p := tenant.Policy()
16 p.Features.Grasp = true
17 p.Features.Grasp02 = false
18 if err := tenant.applyPolicy(context.Background(), p); err != nil {
19 t.Fatal(err)
20 }
21 if tenant.gitLiveEnabled() {
22 t.Fatal("live synchronization enabled without GRASP-02")
23 }
24 p.Features.Grasp02 = true
25 if err := tenant.applyPolicy(context.Background(), p); err != nil {
26 t.Fatal(err)
27 }
28 if !tenant.gitLiveEnabled() {
29 t.Fatal("live synchronization disabled with GRASP-02")
30 }
31}
32
33func TestGitLivePrivateTargetRequiresConfiguredPeer(t *testing.T) {
34 _, tenant := testTenant(t)
35 repo := gitrelay.Repository{Private: true}
36 if tenant.gitLiveAuthorized(repo, "wss://peer.example") {
37 t.Fatal("unconfigured private target was authorized")
38 }
39 p := tenant.Policy()
40 p.Features.Grasp, p.Features.Grasp02, p.Features.Grasp08 = true, true, true
41 p.Reads = "members"
42 p.PrivatePeers = []string{"wss://peer.example"}
43 if err := tenant.applyPolicy(context.Background(), p); err != nil {
44 t.Fatal(err)
45 }
46 if !tenant.gitLiveAuthorized(repo, "wss://peer.example") {
47 t.Fatal("configured private target was rejected")
48 }
49 if tenant.gitLiveAuthorized(repo, "wss://other.example") {
50 t.Fatal("different private target was authorized")
51 }
52}
53
54func TestGitLiveFiltersIncludeConversationRootsAndReplies(t *testing.T) {
55 repo := gitrelay.Repository{Owner: strings.Repeat("a", 64), Identifier: "repo"}
56 root := event.Event{Kind: event.KIND_GIT_ISSUE, ID: strings.Repeat("b", 64)}
57 filters := gitLiveFiltersForRoots(repo, []event.Event{root})
58 if len(filters) != 5 {
59 t.Fatalf("got %d filters, want metadata, conversation and two reply filters", len(filters))
60 }
61 for _, key := range []string{"e", "E"} {
62 found := false
63 for _, filter := range filters {
64 if len(filter.Tags[key]) == 1 && filter.Tags[key][0] == root.ID {
65 found = true
66 }
67 }
68 if !found {
69 t.Fatalf("missing reply filter for %s", key)
70 }
71 }
72}
73
74func TestGitLiveCohortRespectsSocketCapAndRotates(t *testing.T) {
75 keys := make([]string, maxGitLivePeers+7)
76 for i := range keys {
77 keys[i] = strings.Repeat("a", i+1)
78 }
79 first := gitLiveCohort(keys, 0)
80 second := gitLiveCohort(keys, maxGitLivePeers)
81 if len(first) != maxGitLivePeers || len(second) != maxGitLivePeers {
82 t.Fatalf("cohort sizes = %d, %d; want %d", len(first), len(second), maxGitLivePeers)
83 }
84 _, firstHas := first[keys[maxGitLivePeers-1]]
85 _, secondHas := second[keys[maxGitLivePeers-1]]
86 if firstHas == secondHas {
87 t.Fatal("live cohort did not rotate")
88 }
89}
90
91func TestRotateGitAuthorsUsesDurableOffset(t *testing.T) {
92 authors := []string{"a", "b", "c"}
93 got := rotateGitAuthors(authors, 1)
94 if strings.Join(got, ",") != "b,c,a" {
95 t.Fatalf("rotated authors = %v", got)
96 }
97}
98
99func TestStopGitLiveWorkersCancelsAndWaits(t *testing.T) {
100 done := make(chan struct{})
101 canceled := make(chan struct{})
102 workers := map[string]gitLiveWorker{"peer": {
103 cancel: func() { close(canceled); close(done) },
104 done: done,
105 }}
106 finished := make(chan struct{})
107 go func() {
108 stopGitLiveWorkers(workers)
109 close(finished)
110 }()
111 select {
112 case <-canceled:
113 case <-time.After(time.Second):
114 t.Fatal("worker was not canceled")
115 }
116 select {
117 case <-finished:
118 case <-time.After(time.Second):
119 t.Fatal("stop returned before worker completion")
120 }
121 if len(workers) != 0 {
122 t.Fatal("stopped workers remain in the registry")
123 }
124}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs