Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Blame · server/status_test.go

Line attribution on main · 166 line(s)

09b15120
Keenan Nemetz
15d ago
1 package server_test
2
3 import (
4506a4d3
Keenan Nemetz
14d ago
4 "net/http"
09b15120
Keenan Nemetz
15d ago
5 "strings"
6 "testing"
4506a4d3
Keenan Nemetz
14d ago
7 "time"
8
d37d301f
Keenan Nemetz
19h ago
9 "rodent.software/vole/forge/config"
10 "rodent.software/vole/forge/repo"
09b15120
Keenan Nemetz
15d ago
11 )
12
4506a4d3
Keenan Nemetz
14d ago
13 func (f *fixture) adminGet(t *testing.T, path string) (int, string) {
14 t.Helper()
15 if _, err := f.srv.Identity.SetAdmin(f.ownerID, true, "test"); err != nil {
16 t.Fatal(err)
17 }
18 _, cookie := f.browserSession(t, f.ownerID)
19 resp, body := f.browserGet(t, path, cookie)
20 return resp.StatusCode, body
21 }
22
43e681d8
Keenan Nemetz
4d ago
23 func TestAdminOverviewSummarizesTheInstance(t *testing.T) {
09b15120
Keenan Nemetz
15d ago
24 t.Parallel()
25 f := newFixture(t)
ed03b3d1
Keenan Nemetz
6h ago
26 code, body := f.adminGet(t, "/-/admin")
4506a4d3
Keenan Nemetz
14d ago
27 if code != 200 {
09b15120
Keenan Nemetz
15d ago
28 t.Fatalf("status page = %d:\n%s", code, body)
29 }
0db980ee
Keenan Nemetz
4d ago
30 for _, want := range []string{
31 "Overview", "Storage", "Runners", "Configuration", "Storage used", "Free space",
9a2a270b
Keenan Nemetz
4d ago
32 "Users", "Repositories", "Page views", "Today (UTC)",
33 "Recent admin activity", "Read the full audit log",
0db980ee
Keenan Nemetz
4d ago
34 } {
09b15120
Keenan Nemetz
15d ago
35 if !strings.Contains(body, want) {
4506a4d3
Keenan Nemetz
14d ago
36 t.Fatalf("status overview does not show %q:\n%s", want, body)
37 }
38 }
9a2a270b
Keenan Nemetz
4d ago
39 for _, gone := range []string{
40 "Service health", "All core services are responding", "Runners and queue",
41 "Instance and access", "LFS objects", "Active people", "Instance admins", "Retired",
42 } {
4506a4d3
Keenan Nemetz
14d ago
43 if strings.Contains(body, gone) {
0db980ee
Keenan Nemetz
4d ago
44 t.Fatalf("status overview shows a section heading that belongs to another tab %q:\n%s", gone, body)
09b15120
Keenan Nemetz
15d ago
45 }
46 }
47 }
4506a4d3
Keenan Nemetz
14d ago
48
43e681d8
Keenan Nemetz
4d ago
49 func TestAdminConfigurationShowsToAdmins(t *testing.T) {
4506a4d3
Keenan Nemetz
14d ago
50 t.Parallel()
51 f := newFixtureWith(t, func(c *config.Config) {
52 c.InstanceName = "Acme Forge"
53 c.PagesDomain = "pages.example.com"
54 c.MaxBlobBytes = 1234
55 })
56
57 // The page is instance-admin only: anonymous goes to login, and a signed-in
58 // non-admin gets the same 404 as a missing page.
ed03b3d1
Keenan Nemetz
6h ago
59 if resp, _ := f.browserGet(t, "/-/admin", ""); resp.StatusCode != http.StatusSeeOther || !strings.Contains(resp.Header.Get("Location"), "/-/login") {
4506a4d3
Keenan Nemetz
14d ago
60 t.Fatalf("anonymous status page = %d %q", resp.StatusCode, resp.Header.Get("Location"))
61 }
62 f.addWriter(t)
63 _, writerCookie := f.browserSession(t, f.writerID)
ed03b3d1
Keenan Nemetz
6h ago
64 if resp, _ := f.browserGet(t, "/-/admin?tab=configuration", writerCookie); resp.StatusCode != http.StatusNotFound {
4506a4d3
Keenan Nemetz
14d ago
65 t.Fatalf("non-admin status page = %d, want 404", resp.StatusCode)
66 }
67
68 if _, err := f.srv.Identity.SetAdmin(f.ownerID, true, "test"); err != nil {
69 t.Fatal(err)
70 }
71 _, cookie := f.browserSession(t, f.ownerID)
ed03b3d1
Keenan Nemetz
6h ago
72 resp, body := f.browserGet(t, "/-/admin?tab=configuration", cookie)
4506a4d3
Keenan Nemetz
14d ago
73 if resp.StatusCode != 200 {
74 t.Fatalf("admin status page = %d:\n%s", resp.StatusCode, body)
75 }
76 for _, want := range []string{
77 "Configuration", "Instance and access", "Acme Forge", "pages.example.com",
78 "max_blob_bytes", "1.2 KiB (1234 bytes)", "built-in defaults",
79 } {
80 if !strings.Contains(body, want) {
81 t.Fatalf("admin status page does not show %q:\n%s", want, body)
82 }
83 }
84 }
85
43e681d8
Keenan Nemetz
4d ago
86 func TestAdminPagesAreNotCountedAsPageViews(t *testing.T) {
4506a4d3
Keenan Nemetz
14d ago
87 t.Parallel()
88 f := newFixture(t)
89
90 for i := 0; i < 3; i++ {
91 if code, _ := f.get("/"); code != 200 {
92 t.Fatalf("anonymous page %d = %d", i, code)
93 }
94 }
95 _, cookie := f.browserSession(t, f.ownerID)
96 if resp, _ := f.browserGet(t, "/", cookie); resp.StatusCode != 200 {
97 t.Fatalf("signed-in page = %d", resp.StatusCode)
98 }
99
100 stats, err := f.srv.Web.PageViews.Stats(time.Now().UTC())
101 if err != nil {
102 t.Fatal(err)
103 }
104 if stats.Today.Views != 4 || stats.Today.Users != 1 {
105 t.Fatalf("today = %+v, want 4 views and 1 signed-in user", stats.Today)
106 }
107
108 // The status page must not count itself, or a monitor turns the metric into
109 // a measure of polling.
ed03b3d1
Keenan Nemetz
6h ago
110 if code, _ := f.adminGet(t, "/-/admin"); code != 200 {
4506a4d3
Keenan Nemetz
14d ago
111 t.Fatalf("status = %d", code)
112 }
113 stats, err = f.srv.Web.PageViews.Stats(time.Now().UTC())
114 if err != nil {
115 t.Fatal(err)
116 }
117 if stats.Today.Views != 4 {
118 t.Fatalf("status page changed the view count to %d", stats.Today.Views)
119 }
120 }
121
43e681d8
Keenan Nemetz
4d ago
122 func TestAdminTabsSplitTheSections(t *testing.T) {
4506a4d3
Keenan Nemetz
14d ago
123 t.Parallel()
124 f := newFixture(t)
125 if _, err := f.srv.Repos.Create("private", f.ownerID, "private example"); err != nil {
126 t.Fatal(err)
127 }
128 if err := f.srv.Index.Upsert(mustRepoNamed(t, f, "private")); err != nil {
129 t.Fatal(err)
130 }
131
ed03b3d1
Keenan Nemetz
6h ago
132 code, storage := f.adminGet(t, "/-/admin?tab=storage")
4506a4d3
Keenan Nemetz
14d ago
133 if code != 200 || !strings.Contains(storage, "Repositories") || !strings.Contains(storage, "LFS and build objects") {
134 t.Fatalf("storage tab = %d:\n%s", code, storage)
135 }
136 for _, gone := range []string{"Page views", "Runners and queue", "Instance and access"} {
137 if strings.Contains(storage, gone) {
138 t.Fatalf("storage tab shows %q:", gone)
139 }
140 }
141
ed03b3d1
Keenan Nemetz
6h ago
142 code, runners := f.adminGet(t, "/-/admin?tab=runners")
4506a4d3
Keenan Nemetz
14d ago
143 if code != 200 || !strings.Contains(runners, "Runners and queue") || !strings.Contains(runners, "Queue") {
144 t.Fatalf("runners tab = %d:\n%s", code, runners)
145 }
146 if strings.Contains(runners, "Storage used") || strings.Contains(runners, "Page views") {
147 t.Fatalf("runners tab shows overview content:\n%s", runners)
148 }
149
ed03b3d1
Keenan Nemetz
6h ago
150 code, config := f.adminGet(t, "/-/admin?tab=configuration")
4506a4d3
Keenan Nemetz
14d ago
151 if code != 200 || !strings.Contains(config, "Configuration") || !strings.Contains(config, "Instance and access") {
152 t.Fatalf("configuration tab = %d:\n%s", code, config)
153 }
154 if strings.Contains(config, "Storage used") || strings.Contains(config, "Runners and queue") {
155 t.Fatalf("configuration tab shows another tab's content:\n%s", config)
156 }
157 }
158
159 func mustRepoNamed(t *testing.T, f *fixture, name string) *repo.Meta {
160 t.Helper()
161 m, err := f.srv.Repos.Open(name)
162 if err != nil {
163 t.Fatal(err)
164 }
165 return m
166 }