vfs_test.go (3673B)
1 package vfs 2 3 import ( 4 "encoding/json" 5 "strings" 6 "testing" 7 "time" 8 9 appconfig "git.prime8.dev/moncheeta/prime8dev/internal/config" 10 ) 11 12 func testSource(user string) Source { 13 exp := appconfig.GetExperience() 14 projects := appconfig.GetProjects() 15 return Source{ 16 User: user, 17 About: appconfig.GetAbout(), 18 CurrentJob: appconfig.CurrentJob(exp), 19 Experience: exp, 20 Projects: projects, 21 Readmes: map[string]string{projects[0].ID: "# readme"}, 22 Now: time.Date(2026, 10, 21, 12, 0, 0, 0, time.UTC), 23 } 24 } 25 26 func TestBuildLayout(t *testing.T) { 27 src := testSource("visitor") 28 root := Build(src) 29 home := HomeDir("visitor") 30 for _, p := range []string{"bio", "about", "contact", "interests", "hobbies", "languages", "experience", "projects"} { 31 if root.Lookup(home+"/"+p) == nil { 32 t.Errorf("missing %s/%s", home, p) 33 } 34 } 35 first := src.Projects[0].ID 36 if n := root.Lookup(home + "/projects/" + first + "/README.md"); n == nil || n.Content != "# readme" { 37 t.Fatalf("readme override not used: %+v", n) 38 } 39 if n := root.Lookup(home + "/projects/" + first + "/info"); n == nil || !strings.Contains(n.Content, src.Projects[0].Name) { 40 t.Fatalf("info file: %+v", n) 41 } 42 for _, e := range src.Experience { 43 if root.Lookup(home+"/experience/"+Name(e.ID)) == nil { 44 t.Errorf("missing experience %s", e.ID) 45 } 46 } 47 if n := root.Lookup("/tmp"); n == nil || !n.Dir { 48 t.Error("missing /tmp") 49 } 50 } 51 52 func TestBuildDeterministicJSON(t *testing.T) { 53 a, _ := json.Marshal(Build(testSource("visitor"))) 54 b, _ := json.Marshal(Build(testSource("visitor"))) 55 if string(a) != string(b) { 56 t.Fatal("json output differs between builds") 57 } 58 if !strings.Contains(string(a), `"name":"visitor"`) { 59 t.Fatal("home dir not in json") 60 } 61 } 62 63 func TestNeverEscapesRoot(t *testing.T) { 64 root := Build(testSource("visitor")) 65 home := HomeDir("visitor") 66 for _, p := range []string{"/etc/passwd", "/root/.ssh/id_ed25519", "../../..", "/srv", "~/../../etc"} { 67 n := root.Lookup(Resolve(home, home, p)) 68 if n != nil && n != root { 69 t.Errorf("%s resolved to %q", p, n.Name) 70 } 71 } 72 if n := root.Lookup(Resolve(home, home, "../../..")); n != root { 73 t.Error(".. above / should stay at /") 74 } 75 } 76 77 func TestResolveAndDisplay(t *testing.T) { 78 home := "/home/visitor" 79 cases := map[string]string{ 80 "": home, 81 "~": home, 82 "~/projects": home + "/projects", 83 "projects/../": home, 84 "/tmp": "/tmp", 85 "..": "/home", 86 } 87 for in, want := range cases { 88 if got := Resolve(home, home, in); got != want { 89 t.Errorf("Resolve(%q) = %q, want %q", in, got, want) 90 } 91 } 92 if got := DisplayPath(home, home+"/projects/mos"); got != "~/projects/mos" { 93 t.Errorf("DisplayPath = %q", got) 94 } 95 if got := DisplayPath(home, "/tmp"); got != "/tmp" { 96 t.Errorf("DisplayPath = %q", got) 97 } 98 } 99 100 func TestName(t *testing.T) { 101 for in, want := range map[string]string{"Rally Cars": "rally-cars", "a/b": "a-b", ".": "", "..": ""} { 102 if got := Name(in); got != want { 103 t.Errorf("Name(%q) = %q, want %q", in, got, want) 104 } 105 } 106 } 107 108 func TestSanitizeUser(t *testing.T) { 109 for in, want := range map[string]string{ 110 "": "visitor", 111 " ": "visitor", 112 "Damian": "damian", 113 "moncheeta": "moncheeta", 114 "../../etc": "etc", 115 "..": "visitor", 116 "a/b c": "abc", 117 "j.doe_1-x": "j.doe_1-x", 118 "\x1b[31mred": "31mred", 119 "élan": "lan", 120 strings.Repeat("a", 50): strings.Repeat("a", 32), 121 } { 122 if got := SanitizeUser(in); got != want { 123 t.Errorf("SanitizeUser(%q) = %q, want %q", in, got, want) 124 } 125 } 126 }