detached 985c8e4

test(container): add sanitization and collision detection tests

Add comprehensive tests for container name sanitization including collision detection between domains like git.example.com and git-example.com. Verify that dot, colon, and hyphen separators produce distinct outputs to prevent name conflicts.
commit
985c8e41cd2fe7301d136cfa285f0b11034fd798
author
bnema · · 2026-01-31 22:20 UTC
parent
db67927
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +60 -0
M internal/usecase/container/service_test.go +60 -0
@@ -1153,3 +1153,63 @@ func TestService_StripRegistryPrefix(t *testing.T) {
11531153 })
11541154 }
11551155 }
1156+
1157+func TestSanitizeName(t *testing.T) {
1158+ tests := []struct {
1159+ domain string
1160+ expected string
1161+ description string
1162+ }{
1163+ {
1164+ domain: "git.example.com",
1165+ expected: "git__example__com",
1166+ description: "Dots become double underscores",
1167+ },
1168+ {
1169+ domain: "git-example.com",
1170+ expected: "git-example__com",
1171+ description: "Hyphens preserved, dots become underscores",
1172+ },
1173+ {
1174+ domain: "app:8080.example.com",
1175+ expected: "app-_8080__example__com",
1176+ description: "Colons become hyphen-underscore",
1177+ },
1178+ {
1179+ domain: "git.example.com:3000",
1180+ expected: "git__example__com-_3000",
1181+ description: "Multiple separators handled distinctly",
1182+ },
1183+ {
1184+ domain: "simple.com",
1185+ expected: "simple__com",
1186+ description: "Simple domain",
1187+ },
1188+ }
1189+
1190+ for _, tt := range tests {
1191+ t.Run(tt.domain, func(t *testing.T) {
1192+ result := sanitizeName(tt.domain)
1193+ assert.Equal(t, tt.expected, result, "sanitization should match expected")
1194+ })
1195+ }
1196+
1197+ // Verify no collisions between potentially conflicting domains
1198+ t.Run("NoCollisions", func(t *testing.T) {
1199+ domains := []string{
1200+ "git.example.com",
1201+ "git-example.com",
1202+ "app:8080.example.com",
1203+ "app-8080-example.com",
1204+ }
1205+
1206+ results := make(map[string]string)
1207+ for _, d := range domains {
1208+ result := sanitizeName(d)
1209+ if original, exists := results[result]; exists {
1210+ t.Errorf("COLLISION: %q and %q both sanitize to %q", original, d, result)
1211+ }
1212+ results[result] = d
1213+ }
1214+ })
1215+}
@@ -1153,3 +1153,63 @@ func TestService_StripRegistryPrefix(t *testing.T) {
1153 })1153 })
1154 }1154 }
1155 }1155 }
1156+
1157+func TestSanitizeName(t *testing.T) {
1158+ tests := []struct {
1159+ domain string
1160+ expected string
1161+ description string
1162+ }{
1163+ {
1164+ domain: "git.example.com",
1165+ expected: "git__example__com",
1166+ description: "Dots become double underscores",
1167+ },
1168+ {
1169+ domain: "git-example.com",
1170+ expected: "git-example__com",
1171+ description: "Hyphens preserved, dots become underscores",
1172+ },
1173+ {
1174+ domain: "app:8080.example.com",
1175+ expected: "app-_8080__example__com",
1176+ description: "Colons become hyphen-underscore",
1177+ },
1178+ {
1179+ domain: "git.example.com:3000",
1180+ expected: "git__example__com-_3000",
1181+ description: "Multiple separators handled distinctly",
1182+ },
1183+ {
1184+ domain: "simple.com",
1185+ expected: "simple__com",
1186+ description: "Simple domain",
1187+ },
1188+ }
1189+
1190+ for _, tt := range tests {
1191+ t.Run(tt.domain, func(t *testing.T) {
1192+ result := sanitizeName(tt.domain)
1193+ assert.Equal(t, tt.expected, result, "sanitization should match expected")
1194+ })
1195+ }
1196+
1197+ // Verify no collisions between potentially conflicting domains
1198+ t.Run("NoCollisions", func(t *testing.T) {
1199+ domains := []string{
1200+ "git.example.com",
1201+ "git-example.com",
1202+ "app:8080.example.com",
1203+ "app-8080-example.com",
1204+ }
1205+
1206+ results := make(map[string]string)
1207+ for _, d := range domains {
1208+ result := sanitizeName(d)
1209+ if original, exists := results[result]; exists {
1210+ t.Errorf("COLLISION: %q and %q both sanitize to %q", original, d, result)
1211+ }
1212+ results[result] = d
1213+ }
1214+ })
1215+}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close