| 1 | package store |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | ) |
| 7 | |
| 8 | func TestRemoteWorkspaceSlug(t *testing.T) { |
| 9 | // The slug carries a readable stem plus a hash of the exact path. Assert the |
| 10 | // readable prefix and that a trailing slash is normalized to the same slug. |
| 11 | if got := RemoteWorkspaceSlug("/home/dev/projects/app"); !strings.HasPrefix(got, "home-dev-projects-app-") { |
| 12 | t.Errorf("slug = %q, want home-dev-projects-app-<hash> prefix", got) |
| 13 | } |
| 14 | if RemoteWorkspaceSlug("/home/dev/projects/app") != RemoteWorkspaceSlug("/home/dev/projects/app/") { |
| 15 | t.Error("trailing slash produced a different slug") |
| 16 | } |
| 17 | if got := RemoteWorkspaceSlug("/"); !strings.HasPrefix(got, "root-") { |
| 18 | t.Errorf("root slug = %q, want root-<hash>", got) |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | // TestRemoteWorkspaceSlugNoCollision is the reviewer's reproduction: distinct |
| 23 | // paths that reduce to the same separator-replaced stem must not share serve |
| 24 | // state files. |
| 25 | func TestRemoteWorkspaceSlugNoCollision(t *testing.T) { |
| 26 | a := RemoteWorkspaceSlug("/srv/a-b") |
| 27 | b := RemoteWorkspaceSlug("/srv/a/b") |
| 28 | if a == b { |
| 29 | t.Fatalf("/srv/a-b and /srv/a/b collided to the same slug %q", a) |
| 30 | } |
| 31 | // Same path (idempotent). |
| 32 | if RemoteWorkspaceSlug("/srv/a/b") != b { |
| 33 | t.Error("slug is not deterministic") |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | func TestRemoteWorkspaceSlugBoundsLongPaths(t *testing.T) { |
| 38 | long := "/data/" + strings.Repeat("verydeepdir/", 40) + "app" |
| 39 | slug := RemoteWorkspaceSlug(long) |
| 40 | if len(slug) > 200 { |
| 41 | t.Fatalf("slug length %d exceeds bound", len(slug)) |
| 42 | } |
| 43 | other := RemoteWorkspaceSlug(long + "2") |
| 44 | if slug == other { |
| 45 | t.Fatal("distinct long paths collapsed to one slug") |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | func TestRemoteServeFileNames(t *testing.T) { |
| 50 | slug := "home-dev-app" |
| 51 | if got := RemoteServeStateName(slug); got != "serve-home-dev-app.json" { |
| 52 | t.Fatalf("state name = %q", got) |
| 53 | } |
| 54 | if got := RemoteServeTokenName(slug); got != "serve-home-dev-app.token" { |
| 55 | t.Fatalf("token name = %q", got) |
| 56 | } |
| 57 | if got := RemoteServeLogName(slug); got != "serve-home-dev-app.log" { |
| 58 | t.Fatalf("log name = %q", got) |
| 59 | } |
| 60 | if got := RemoteServePortName(slug); got != "serve-home-dev-app.port" { |
| 61 | t.Fatalf("port name = %q", got) |
| 62 | } |
| 63 | if got := RemoteServePidName(slug); got != "serve-home-dev-app.pid" { |
| 64 | t.Fatalf("pid name = %q", got) |
| 65 | } |
| 66 | } |
| 67 |