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.

Code

395 commit(s) on main

update readme Keenan Nemetz · 36m ago 32290114
history blame raw 5.3 KiB
1package server_test
2
3import (
4 "net/http"
5 "strings"
6 "testing"
7 "time"
8
9 "rodent.software/vole/forge/config"
10 "rodent.software/vole/forge/repo"
11)
12
13func (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
23func TestAdminOverviewSummarizesTheInstance(t *testing.T) {
24 t.Parallel()
25 f := newFixture(t)
26 code, body := f.adminGet(t, "/-/admin")
27 if code != 200 {
28 t.Fatalf("status page = %d:\n%s", code, body)
29 }
30 for _, want := range []string{
31 "Overview", "Storage", "Runners", "Configuration", "Storage used", "Free space",
32 "Users", "Repositories", "Page views", "Today (UTC)",
33 "Recent admin activity", "Read the full audit log",
34 } {
35 if !strings.Contains(body, want) {
36 t.Fatalf("status overview does not show %q:\n%s", want, body)
37 }
38 }
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 } {
43 if strings.Contains(body, gone) {
44 t.Fatalf("status overview shows a section heading that belongs to another tab %q:\n%s", gone, body)
45 }
46 }
47}
48
49func TestAdminConfigurationShowsToAdmins(t *testing.T) {
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.
59 if resp, _ := f.browserGet(t, "/-/admin", ""); resp.StatusCode != http.StatusSeeOther || !strings.Contains(resp.Header.Get("Location"), "/-/login") {
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)
64 if resp, _ := f.browserGet(t, "/-/admin?tab=configuration", writerCookie); resp.StatusCode != http.StatusNotFound {
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)
72 resp, body := f.browserGet(t, "/-/admin?tab=configuration", cookie)
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
86func TestAdminPagesAreNotCountedAsPageViews(t *testing.T) {
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.
110 if code, _ := f.adminGet(t, "/-/admin"); code != 200 {
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
122func TestAdminTabsSplitTheSections(t *testing.T) {
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
132 code, storage := f.adminGet(t, "/-/admin?tab=storage")
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
142 code, runners := f.adminGet(t, "/-/admin?tab=runners")
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
150 code, config := f.adminGet(t, "/-/admin?tab=configuration")
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
159func 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}
167