internal/store/queues_test.go
118 lines · 3333 bytes
2 symbols in this file
1package store
2
3import (
4 "testing"
5 "time"
6)
7
8// Push is a worker queue like the others, and the one failure config
9// validation cannot catch — a key_id Apple did not issue — dead-letters
10// every row on its first attempt. Without a count and the rows here an
11// admin has no way to see that happening.
12func TestQueuesReportsPush(t *testing.T) {
13 s := open(t)
14 if err := s.MigrateUp(); err != nil {
15 t.Fatal(err)
16 }
17 uid, err := s.CreateUser("cmc", true)
18 if err != nil {
19 t.Fatal(err)
20 }
21 id, err := s.AddPushDevice(uid, "tok-a", "iphone")
22 if err != nil {
23 t.Fatal(err)
24 }
25 for i := 0; i < 3; i++ {
26 if err := s.EnqueuePush(uid, "krz/gitbay", "cmc opened issue #1", "krz/gitbay/issues/1"); err != nil {
27 t.Fatal(err)
28 }
29 }
30 due, err := s.DuePush(20)
31 if err != nil {
32 t.Fatal(err)
33 }
34 if len(due) != 3 {
35 t.Fatalf("queued %d, want 3", len(due))
36 }
37 next := time.Now().Add(time.Minute)
38 if err := s.MarkPushFailed(due[0].ID, "apns 503", &next); err != nil {
39 t.Fatal(err)
40 }
41 if err := s.MarkPushFailed(due[1].ID, "apns 403 InvalidProviderToken", nil); err != nil {
42 t.Fatal(err)
43 }
44
45 q, err := s.QueueStatus()
46 if err != nil {
47 t.Fatal(err)
48 }
49 if q.Push.Pending != 2 || q.Push.Retrying != 1 || q.Push.Failed != 1 {
50 t.Fatalf("counts: %+v", q.Push)
51 }
52 if q.Push.OldestPending == "" {
53 t.Fatalf("no oldest pending: %+v", q.Push)
54 }
55 // Retrying and dead-lettered rows, newest first, as the mail queue
56 // lists them.
57 if len(q.Push.Items) != 2 {
58 t.Fatalf("items: %+v", q.Push.Items)
59 }
60 if q.Push.Items[0].DeviceID != id || q.Push.Items[0].FailedAt == "" ||
61 q.Push.Items[0].LastError != "apns 403 InvalidProviderToken" {
62 t.Fatalf("dead-lettered row: %+v", q.Push.Items[0])
63 }
64 if q.Push.Items[1].Attempts != 1 || q.Push.Items[1].FailedAt != "" {
65 t.Fatalf("retrying row: %+v", q.Push.Items[1])
66 }
67 // A device token is never echoed, here included.
68 for _, it := range q.Push.Items {
69 if it.Title != "krz/gitbay" || it.CreatedAt == "" {
70 t.Fatalf("row: %+v", it)
71 }
72 }
73}
74
75// The build queue lists pending builds as well as running ones, so an
76// admin can see what no runner is claiming without walking every repo.
77func TestQueuesListsPendingBuilds(t *testing.T) {
78 s := open(t)
79 if err := s.MigrateUp(); err != nil {
80 t.Fatal(err)
81 }
82 uid, err := s.CreateUser("cmc", true)
83 if err != nil {
84 t.Fatal(err)
85 }
86 if _, err := s.CreateRepo("user", uid, "orgo", "public"); err != nil {
87 t.Fatal(err)
88 }
89 running, err := s.CreateBuild(1, "test", "abc123", "main", `["true"]`, "", "", true)
90 if err != nil {
91 t.Fatal(err)
92 }
93 pending, err := s.CreateBuild(1, "pages", "abc123", "main", `["true"]`, "", "", true)
94 if err != nil {
95 t.Fatal(err)
96 }
97 if _, ok, err := s.ClaimBuild(nil, false); err != nil || !ok {
98 t.Fatalf("claim: %v ok=%v", err, ok)
99 }
100
101 q, err := s.QueueStatus()
102 if err != nil {
103 t.Fatal(err)
104 }
105 if q.Builds.Pending != 1 || q.Builds.Running != 1 {
106 t.Fatalf("counts: %+v", q.Builds)
107 }
108 items := q.Builds.Items
109 if len(items) != 2 {
110 t.Fatalf("items: %+v", items)
111 }
112 if items[0].Number != running || items[0].Status != "running" || items[0].StartedAt == "" {
113 t.Fatalf("running row first: %+v", items[0])
114 }
115 if items[1].Number != pending || items[1].Status != "pending" || items[1].StartedAt != "" || items[1].CreatedAt == "" {
116 t.Fatalf("pending row after: %+v", items[1])
117 }
118}