diff options
Diffstat (limited to 'tsweb/debug_test.go')
| -rw-r--r-- | tsweb/debug_test.go | 416 |
1 files changed, 208 insertions, 208 deletions
diff --git a/tsweb/debug_test.go b/tsweb/debug_test.go index 2a68ab6fb..504ec06ba 100644 --- a/tsweb/debug_test.go +++ b/tsweb/debug_test.go @@ -1,208 +1,208 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -package tsweb - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "runtime" - "strings" - "testing" -) - -func TestDebugger(t *testing.T) { - mux := http.NewServeMux() - - dbg1 := Debugger(mux) - if dbg1 == nil { - t.Fatal("didn't get a debugger from mux") - } - - dbg2 := Debugger(mux) - if dbg2 != dbg1 { - t.Fatal("Debugger returned different debuggers for the same mux") - } - - t.Run("cpu_pprof", func(t *testing.T) { - if testing.Short() { - t.Skip("skipping second long test") - } - switch runtime.GOOS { - case "linux", "darwin": - default: - t.Skipf("skipping test on %v", runtime.GOOS) - } - req := httptest.NewRequest("GET", "/debug/pprof/profile?seconds=1", nil) - req.RemoteAddr = "100.101.102.103:1234" - rec := httptest.NewRecorder() - mux.ServeHTTP(rec, req) - res := rec.Result() - if res.StatusCode != 200 { - t.Errorf("unexpected %v", res.Status) - } - }) -} - -func get(m http.Handler, path, srcIP string) (int, string) { - req := httptest.NewRequest("GET", path, nil) - req.RemoteAddr = srcIP + ":1234" - rec := httptest.NewRecorder() - m.ServeHTTP(rec, req) - return rec.Result().StatusCode, rec.Body.String() -} - -const ( - tsIP = "100.100.100.100" - pubIP = "8.8.8.8" -) - -func TestDebuggerKV(t *testing.T) { - mux := http.NewServeMux() - dbg := Debugger(mux) - dbg.KV("Donuts", 42) - dbg.KV("Secret code", "hunter2") - val := "red" - dbg.KVFunc("Condition", func() any { return val }) - - code, _ := get(mux, "/debug/", pubIP) - if code != 403 { - t.Fatalf("debug access wasn't denied, got %v", code) - } - - code, body := get(mux, "/debug/", tsIP) - if code != 200 { - t.Fatalf("debug access failed, got %v", code) - } - for _, want := range []string{"Donuts", "42", "Secret code", "hunter2", "Condition", "red"} { - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } - } - - val = "green" - code, body = get(mux, "/debug/", tsIP) - if code != 200 { - t.Fatalf("debug access failed, got %v", code) - } - for _, want := range []string{"Condition", "green"} { - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } - } -} - -func TestDebuggerURL(t *testing.T) { - mux := http.NewServeMux() - dbg := Debugger(mux) - dbg.URL("https://www.tailscale.com", "Homepage") - - code, body := get(mux, "/debug/", tsIP) - if code != 200 { - t.Fatalf("debug access failed, got %v", code) - } - for _, want := range []string{"https://www.tailscale.com", "Homepage"} { - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } - } -} - -func TestDebuggerSection(t *testing.T) { - mux := http.NewServeMux() - dbg := Debugger(mux) - dbg.Section(func(w io.Writer, r *http.Request) { - fmt.Fprintf(w, "Test output %v", r.RemoteAddr) - }) - - code, body := get(mux, "/debug/", tsIP) - if code != 200 { - t.Fatalf("debug access failed, got %v", code) - } - want := `Test output 100.100.100.100:1234` - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } -} - -func TestDebuggerHandle(t *testing.T) { - mux := http.NewServeMux() - dbg := Debugger(mux) - dbg.Handle("check", "Consistency check", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Test output %v", r.RemoteAddr) - })) - - code, body := get(mux, "/debug/", tsIP) - if code != 200 { - t.Fatalf("debug access failed, got %v", code) - } - for _, want := range []string{"/debug/check", "Consistency check"} { - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } - } - - code, _ = get(mux, "/debug/check", pubIP) - if code != 403 { - t.Fatal("/debug/check should be protected, but isn't") - } - - code, body = get(mux, "/debug/check", tsIP) - if code != 200 { - t.Fatal("/debug/check denied debug access") - } - want := "Test output " + tsIP - if !strings.Contains(body, want) { - t.Errorf("want %q in output, not found", want) - } -} - -func ExampleDebugHandler_Handle() { - mux := http.NewServeMux() - dbg := Debugger(mux) - // Registers /debug/flushcache with the given handler, and adds a - // link to /debug/ with the description "Flush caches". - dbg.Handle("flushcache", "Flush caches", http.HandlerFunc(http.NotFound)) -} - -func ExampleDebugHandler_KV() { - mux := http.NewServeMux() - dbg := Debugger(mux) - // Adds two list items to /debug/, showing that the condition is - // red and there are 42 donuts. - dbg.KV("Condition", "red") - dbg.KV("Donuts", 42) -} - -func ExampleDebugHandler_KVFunc() { - mux := http.NewServeMux() - dbg := Debugger(mux) - // Adds an count of page renders to /debug/. Note this example - // isn't concurrency-safe. - views := 0 - dbg.KVFunc("Debug pageviews", func() any { - views = views + 1 - return views - }) - dbg.KV("Donuts", 42) -} - -func ExampleDebugHandler_URL() { - mux := http.NewServeMux() - dbg := Debugger(mux) - // Links to the Tailscale website from /debug/. - dbg.URL("https://www.tailscale.com", "Homepage") -} - -func ExampleDebugHandler_Section() { - mux := http.NewServeMux() - dbg := Debugger(mux) - // Adds a section to /debug/ that dumps the HTTP request of the - // visitor. - dbg.Section(func(w io.Writer, r *http.Request) { - io.WriteString(w, "<h3>Dump of your HTTP request</h3>") - fmt.Fprintf(w, "<code>%#v</code>", r) - }) -} +// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package tsweb
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+func TestDebugger(t *testing.T) {
+ mux := http.NewServeMux()
+
+ dbg1 := Debugger(mux)
+ if dbg1 == nil {
+ t.Fatal("didn't get a debugger from mux")
+ }
+
+ dbg2 := Debugger(mux)
+ if dbg2 != dbg1 {
+ t.Fatal("Debugger returned different debuggers for the same mux")
+ }
+
+ t.Run("cpu_pprof", func(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping second long test")
+ }
+ switch runtime.GOOS {
+ case "linux", "darwin":
+ default:
+ t.Skipf("skipping test on %v", runtime.GOOS)
+ }
+ req := httptest.NewRequest("GET", "/debug/pprof/profile?seconds=1", nil)
+ req.RemoteAddr = "100.101.102.103:1234"
+ rec := httptest.NewRecorder()
+ mux.ServeHTTP(rec, req)
+ res := rec.Result()
+ if res.StatusCode != 200 {
+ t.Errorf("unexpected %v", res.Status)
+ }
+ })
+}
+
+func get(m http.Handler, path, srcIP string) (int, string) {
+ req := httptest.NewRequest("GET", path, nil)
+ req.RemoteAddr = srcIP + ":1234"
+ rec := httptest.NewRecorder()
+ m.ServeHTTP(rec, req)
+ return rec.Result().StatusCode, rec.Body.String()
+}
+
+const (
+ tsIP = "100.100.100.100"
+ pubIP = "8.8.8.8"
+)
+
+func TestDebuggerKV(t *testing.T) {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ dbg.KV("Donuts", 42)
+ dbg.KV("Secret code", "hunter2")
+ val := "red"
+ dbg.KVFunc("Condition", func() any { return val })
+
+ code, _ := get(mux, "/debug/", pubIP)
+ if code != 403 {
+ t.Fatalf("debug access wasn't denied, got %v", code)
+ }
+
+ code, body := get(mux, "/debug/", tsIP)
+ if code != 200 {
+ t.Fatalf("debug access failed, got %v", code)
+ }
+ for _, want := range []string{"Donuts", "42", "Secret code", "hunter2", "Condition", "red"} {
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+ }
+
+ val = "green"
+ code, body = get(mux, "/debug/", tsIP)
+ if code != 200 {
+ t.Fatalf("debug access failed, got %v", code)
+ }
+ for _, want := range []string{"Condition", "green"} {
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+ }
+}
+
+func TestDebuggerURL(t *testing.T) {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ dbg.URL("https://www.tailscale.com", "Homepage")
+
+ code, body := get(mux, "/debug/", tsIP)
+ if code != 200 {
+ t.Fatalf("debug access failed, got %v", code)
+ }
+ for _, want := range []string{"https://www.tailscale.com", "Homepage"} {
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+ }
+}
+
+func TestDebuggerSection(t *testing.T) {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ dbg.Section(func(w io.Writer, r *http.Request) {
+ fmt.Fprintf(w, "Test output %v", r.RemoteAddr)
+ })
+
+ code, body := get(mux, "/debug/", tsIP)
+ if code != 200 {
+ t.Fatalf("debug access failed, got %v", code)
+ }
+ want := `Test output 100.100.100.100:1234`
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+}
+
+func TestDebuggerHandle(t *testing.T) {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ dbg.Handle("check", "Consistency check", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Test output %v", r.RemoteAddr)
+ }))
+
+ code, body := get(mux, "/debug/", tsIP)
+ if code != 200 {
+ t.Fatalf("debug access failed, got %v", code)
+ }
+ for _, want := range []string{"/debug/check", "Consistency check"} {
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+ }
+
+ code, _ = get(mux, "/debug/check", pubIP)
+ if code != 403 {
+ t.Fatal("/debug/check should be protected, but isn't")
+ }
+
+ code, body = get(mux, "/debug/check", tsIP)
+ if code != 200 {
+ t.Fatal("/debug/check denied debug access")
+ }
+ want := "Test output " + tsIP
+ if !strings.Contains(body, want) {
+ t.Errorf("want %q in output, not found", want)
+ }
+}
+
+func ExampleDebugHandler_Handle() {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ // Registers /debug/flushcache with the given handler, and adds a
+ // link to /debug/ with the description "Flush caches".
+ dbg.Handle("flushcache", "Flush caches", http.HandlerFunc(http.NotFound))
+}
+
+func ExampleDebugHandler_KV() {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ // Adds two list items to /debug/, showing that the condition is
+ // red and there are 42 donuts.
+ dbg.KV("Condition", "red")
+ dbg.KV("Donuts", 42)
+}
+
+func ExampleDebugHandler_KVFunc() {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ // Adds an count of page renders to /debug/. Note this example
+ // isn't concurrency-safe.
+ views := 0
+ dbg.KVFunc("Debug pageviews", func() any {
+ views = views + 1
+ return views
+ })
+ dbg.KV("Donuts", 42)
+}
+
+func ExampleDebugHandler_URL() {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ // Links to the Tailscale website from /debug/.
+ dbg.URL("https://www.tailscale.com", "Homepage")
+}
+
+func ExampleDebugHandler_Section() {
+ mux := http.NewServeMux()
+ dbg := Debugger(mux)
+ // Adds a section to /debug/ that dumps the HTTP request of the
+ // visitor.
+ dbg.Section(func(w io.Writer, r *http.Request) {
+ io.WriteString(w, "<h3>Dump of your HTTP request</h3>")
+ fmt.Fprintf(w, "<code>%#v</code>", r)
+ })
+}
|
