scheme_handler_systemviews_test.go RawHistoryFolder
1package cef
2
3import (
4 "net/url"
5 "testing"
6
7 "github.com/bnema/dumber/assets"
8)
9
10func TestResolveAssetPath_SystemviewsRootsUseSystemviewsShell(t *testing.T) {
11 t.Parallel()
12
13 tests := []struct {
14 name string
15 raw string
16 wantDir string
17 wantRel string
18 }{
19 {name: "history host", raw: "https://dumber.invalid/history", wantDir: "systemviews", wantRel: indexHTML},
20 {name: "favorites host", raw: "https://dumber.invalid/favorites", wantDir: "systemviews", wantRel: indexHTML},
21 {name: "config host", raw: "https://dumber.invalid/config", wantDir: "systemviews", wantRel: indexHTML},
22 {name: "root wasm exec", raw: "https://dumber.invalid/wasm_exec.js", wantDir: "systemviews", wantRel: "wasm_exec.js"},
23 {name: "root wasm asset", raw: "https://dumber.invalid/systemviews.wasm", wantDir: "systemviews", wantRel: "systemviews.wasm"},
24 {name: "root css asset", raw: "https://dumber.invalid/systemviews.css", wantDir: "systemviews", wantRel: "systemviews.css"},
25 {name: "history opaque", raw: "dumb:history", wantDir: "systemviews", wantRel: indexHTML},
26 {name: "history sub-asset", raw: "https://dumber.invalid/history/wasm_exec.js", wantDir: "systemviews", wantRel: "wasm_exec.js"},
27 {name: "history css asset", raw: "https://dumber.invalid/history/systemviews.css", wantDir: "systemviews", wantRel: "systemviews.css"},
28 }
29
30 for _, tt := range tests {
31 t.Run(tt.name, func(t *testing.T) {
32 t.Parallel()
33 u := mustParseURL(t, tt.raw)
34 gotDir, gotRel, ok := resolveAssetPath(u)
35 if !ok {
36 t.Fatalf("resolveAssetPath(%q) = not ok", tt.raw)
37 }
38 if gotDir != tt.wantDir || gotRel != tt.wantRel {
39 t.Fatalf("resolveAssetPath(%q) = (%q, %q), want (%q, %q)", tt.raw, gotDir, gotRel, tt.wantDir, tt.wantRel)
40 }
41 })
42 }
43}
44
45func TestReadAssetWithEncoding_DecompressesEmbeddedBrotliWASM(t *testing.T) {
46 t.Parallel()
47
48 data, err := readAssetWithEncoding(assets.WebUIAssets, "systemviews/systemviews.wasm", "systemviews.wasm")
49 if err != nil {
50 t.Fatalf("readAssetWithEncoding() error = %v", err)
51 }
52 if len(data) < 4 {
53 t.Fatalf("decompressed wasm too short: got %d bytes", len(data))
54 }
55 if string(data[:4]) != "\x00asm" {
56 t.Fatalf("decompressed wasm magic = %q, want \\x00asm", data[:4])
57 }
58}
59
60func mustParseURL(t *testing.T, raw string) *url.URL {
61 t.Helper()
62 u, err := url.Parse(raw)
63 if err != nil {
64 t.Fatalf("url.Parse(%q) error = %v", raw, err)
65 }
66 return u
67}
68
69func TestSafeSystemviewsAssetPathRejectsTraversal(t *testing.T) {
70 t.Parallel()
71
72 fullPath, relPath, ok := safeSystemviewsAssetPath(systemviewsAssetDir, "nested/../systemviews.css")
73 if !ok {
74 t.Fatal("safeSystemviewsAssetPath() rejected safe cleaned path")
75 }
76 if fullPath != "systemviews/systemviews.css" || relPath != "systemviews.css" {
77 t.Fatalf("safeSystemviewsAssetPath() = (%q, %q), want (systemviews/systemviews.css, systemviews.css)", fullPath, relPath)
78 }
79
80 invalid := []struct {
81 name string
82 assetDir string
83 relPath string
84 }{
85 {name: "parent escape", assetDir: systemviewsAssetDir, relPath: "../logo.svg"},
86 {name: "nested parent escape", assetDir: systemviewsAssetDir, relPath: "nested/../../logo.svg"},
87 {name: "absolute parent escape", assetDir: systemviewsAssetDir, relPath: "/../logo.svg"},
88 {name: "null byte", assetDir: systemviewsAssetDir, relPath: "systemviews.css\x00"},
89 {name: "wrong asset dir", assetDir: "logos", relPath: "logo.svg"},
90 }
91 for _, tt := range invalid {
92 t.Run(tt.name, func(t *testing.T) {
93 t.Parallel()
94 if fullPath, relPath, ok := safeSystemviewsAssetPath(tt.assetDir, tt.relPath); ok {
95 t.Fatalf("safeSystemviewsAssetPath(%q, %q) = (%q, %q, true), want rejected", tt.assetDir, tt.relPath, fullPath, relPath)
96 }
97 })
98 }
99}