This repository has no description
1package db
2
3import (
4 "context"
5 "encoding/json"
6 "path/filepath"
7 "slices"
8 "testing"
9 "time"
10
11 "tangled.org/core/api/tangled"
12)
13
14func newTestDB(t *testing.T) *DB {
15 t.Helper()
16 d, err := Make(context.Background(), filepath.Join(t.TempDir(), "spindle.db"))
17 if err != nil {
18 t.Fatalf("Make: %v", err)
19 }
20 t.Cleanup(func() { d.Close() })
21 return d
22}
23
24func seedPipelineEvent(t *testing.T, d *DB, rkey, repoDid, kind string, created int64) {
25 t.Helper()
26 repo := repoDid
27 tm := &tangled.Pipeline_TriggerMetadata{
28 Kind: kind,
29 Repo: &tangled.Pipeline_TriggerRepo{Knot: "knot.test", RepoDid: &repo, Did: repoDid},
30 }
31 switch kind {
32 case "push":
33 tm.Push = &tangled.Pipeline_PushTriggerData{NewSha: "sha-" + rkey, Ref: "refs/heads/main"}
34 case "pull_request":
35 tm.PullRequest = &tangled.Pipeline_PullRequestTriggerData{SourceSha: "sha-" + rkey, SourceBranch: "feature", TargetBranch: "main"}
36 case "manual":
37 tm.Manual = &tangled.Pipeline_ManualTriggerData{Sha: "sha-" + rkey}
38 }
39 raw := tangled.Pipeline{
40 TriggerMetadata: tm,
41 Workflows: []*tangled.Pipeline_Workflow{{Name: "ci.yml"}},
42 }
43 eventJson, err := json.Marshal(raw)
44 if err != nil {
45 t.Fatalf("marshal pipeline: %v", err)
46 }
47 if _, err := d.Exec(
48 `insert into events (rkey, nsid, event, created) values (?, 'sh.tangled.pipeline', ?, ?)`,
49 rkey, string(eventJson), created,
50 ); err != nil {
51 t.Fatalf("seed event %s: %v", rkey, err)
52 }
53}
54
55func TestQueryPipelines_FilterByKind(t *testing.T) {
56 d := newTestDB(t)
57 ctx := context.Background()
58 repo := "did:plc:boltless"
59 base := time.Now().UnixNano()
60
61 seedPipelineEvent(t, d, "p-push", repo, "push", base+1)
62 seedPipelineEvent(t, d, "p-pull", repo, "pull_request", base+2)
63 seedPipelineEvent(t, d, "p-manual", repo, "manual", base+3)
64
65 cases := []struct {
66 kinds []string
67 wantTotal int64
68 wantKinds []string
69 }{
70 {nil, 3, []string{"manual", "pull_request", "push"}},
71 {[]string{"push"}, 1, []string{"push"}},
72 {[]string{"pull_request"}, 1, []string{"pull_request"}},
73 {[]string{"manual"}, 1, []string{"manual"}},
74 {[]string{"push", "pull_request"}, 2, []string{"pull_request", "push"}},
75 }
76
77 for _, tc := range cases {
78 pipelines, _, total, err := d.QueryPipelines(ctx, repo, nil, "", tc.kinds, 30)
79 if err != nil {
80 t.Fatalf("kinds=%v: QueryPipelines: %v", tc.kinds, err)
81 }
82 if total != tc.wantTotal {
83 t.Errorf("kinds=%v: total = %d, want %d", tc.kinds, total, tc.wantTotal)
84 }
85 var gotKinds []string
86 for _, p := range pipelines {
87 gotKinds = append(gotKinds, triggerKindOf(p))
88 }
89 slices.Sort(gotKinds)
90 if !slices.Equal(gotKinds, tc.wantKinds) {
91 t.Errorf("kinds=%v: returned %v, want %v", tc.kinds, gotKinds, tc.wantKinds)
92 }
93 }
94}
95
96func TestQueryPipelines_KindScopedToRepo(t *testing.T) {
97 d := newTestDB(t)
98 ctx := context.Background()
99 base := time.Now().UnixNano()
100
101 seedPipelineEvent(t, d, "a-push", "did:plc:alice", "push", base+1)
102 seedPipelineEvent(t, d, "b-push", "did:plc:bob", "push", base+2)
103
104 pipelines, _, total, err := d.QueryPipelines(ctx, "did:plc:alice", nil, "", []string{"push"}, 30)
105 if err != nil {
106 t.Fatalf("QueryPipelines: %v", err)
107 }
108 if total != 1 || len(pipelines) != 1 {
109 t.Fatalf("total=%d len=%d, want exactly alice's single push pipeline", total, len(pipelines))
110 }
111 if pipelines[0].Repo == nil || *pipelines[0].Repo != "did:plc:alice" {
112 t.Errorf("returned pipeline repo = %v, want did:plc:alice", pipelines[0].Repo)
113 }
114}
115
116func triggerKindOf(p *tangled.CiPipeline) string {
117 if p.Trigger == nil {
118 return ""
119 }
120 switch {
121 case p.Trigger.CiTrigger_Push != nil:
122 return "push"
123 case p.Trigger.CiTrigger_PullRequest != nil:
124 return "pull_request"
125 case p.Trigger.CiTrigger_Manual != nil:
126 return "manual"
127 }
128 return ""
129}