Skip to content

Commit 7d48630

Browse files
chore: appease linter and add test case
Appease the linter and make a test case for `safeAgentName`.
1 parent 0660cba commit 7d48630

File tree

2 files changed

+201
-11
lines changed

2 files changed

+201
-11
lines changed

agent/agentcontainers/api.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"sync"
1616
"sync/atomic"
1717
"time"
18-
"unicode"
1918

2019
"github.com/fsnotify/fsnotify"
2120
"github.com/go-chi/chi/v5"
@@ -639,28 +638,24 @@ var consecutiveHyphenRegex = regexp.MustCompile("-+")
639638
// of a folder name, falling back to a safe version
640639
// of the container name if unable to create a name.
641640
func safeAgentName(name string, friendlyName string) string {
642-
// Keep only letters and digits, replacing everything
641+
// Keep only ASCII letters and digits, replacing everything
643642
// else with a hyphen.
644643
var sb strings.Builder
645644
for _, r := range strings.ToLower(name) {
646-
if unicode.IsLetter(r) || unicode.IsDigit(r) {
647-
sb.WriteRune(r)
645+
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') {
646+
_, _ = sb.WriteRune(r)
648647
} else {
649-
sb.WriteRune('-')
648+
_, _ = sb.WriteRune('-')
650649
}
651650
}
652651

653-
// Remove any consecutive hyphens, and then trim and leading
652+
// Remove any consecutive hyphens, and then trim any leading
654653
// and trailing hyphens.
655654
name = consecutiveHyphenRegex.ReplaceAllString(sb.String(), "-")
656655
name = strings.Trim(name, "-")
657656

658-
name = strings.ToLower(name)
659-
name = strings.ReplaceAll(name, " ", "-")
660-
name = strings.ReplaceAll(name, "_", "-")
661-
662657
if name == "" {
663-
return safeFriendlyName(name)
658+
return safeFriendlyName(friendlyName)
664659
}
665660

666661
return name
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package agentcontainers
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/coder/coder/v2/provisioner"
9+
)
10+
11+
func TestSafeAgentName(t *testing.T) {
12+
t.Parallel()
13+
14+
tests := []struct {
15+
name string
16+
folderName string
17+
expected string
18+
}{
19+
// Basic valid names
20+
{
21+
folderName: "simple",
22+
expected: "simple",
23+
},
24+
{
25+
folderName: "with-hyphens",
26+
expected: "with-hyphens",
27+
},
28+
{
29+
folderName: "123numbers",
30+
expected: "123numbers",
31+
},
32+
{
33+
folderName: "mixed123",
34+
expected: "mixed123",
35+
},
36+
37+
// Names that need transformation
38+
{
39+
folderName: "With_Underscores",
40+
expected: "with-underscores",
41+
},
42+
{
43+
folderName: "With Spaces",
44+
expected: "with-spaces",
45+
},
46+
{
47+
folderName: "UPPERCASE",
48+
expected: "uppercase",
49+
},
50+
{
51+
folderName: "Mixed_Case-Name",
52+
expected: "mixed-case-name",
53+
},
54+
55+
// Names with special characters that get replaced
56+
{
57+
folderName: "special@#$chars",
58+
expected: "special-chars",
59+
},
60+
{
61+
folderName: "dots.and.more",
62+
expected: "dots-and-more",
63+
},
64+
{
65+
folderName: "multiple___underscores",
66+
expected: "multiple-underscores",
67+
},
68+
{
69+
folderName: "multiple---hyphens",
70+
expected: "multiple-hyphens",
71+
},
72+
73+
// Edge cases with leading/trailing special chars
74+
{
75+
folderName: "-leading-hyphen",
76+
expected: "leading-hyphen",
77+
},
78+
{
79+
folderName: "trailing-hyphen-",
80+
expected: "trailing-hyphen",
81+
},
82+
{
83+
folderName: "_leading_underscore",
84+
expected: "leading-underscore",
85+
},
86+
{
87+
folderName: "trailing_underscore_",
88+
expected: "trailing-underscore",
89+
},
90+
{
91+
folderName: "---multiple-leading",
92+
expected: "multiple-leading",
93+
},
94+
{
95+
folderName: "trailing-multiple---",
96+
expected: "trailing-multiple",
97+
},
98+
99+
// Complex transformation cases
100+
{
101+
folderName: "___very---complex@@@name___",
102+
expected: "very-complex-name",
103+
},
104+
{
105+
folderName: "my.project-folder_v2",
106+
expected: "my-project-folder-v2",
107+
},
108+
109+
// Empty and fallback cases - now correctly uses friendlyName fallback
110+
{
111+
folderName: "",
112+
expected: "friendly-fallback",
113+
},
114+
{
115+
folderName: "---",
116+
expected: "friendly-fallback",
117+
},
118+
{
119+
folderName: "___",
120+
expected: "friendly-fallback",
121+
},
122+
{
123+
folderName: "@#$",
124+
expected: "friendly-fallback",
125+
},
126+
127+
// Additional edge cases
128+
{
129+
folderName: "a",
130+
expected: "a",
131+
},
132+
{
133+
folderName: "1",
134+
expected: "1",
135+
},
136+
{
137+
folderName: "a1b2c3",
138+
expected: "a1b2c3",
139+
},
140+
{
141+
folderName: "CamelCase",
142+
expected: "camelcase",
143+
},
144+
{
145+
folderName: "snake_case_name",
146+
expected: "snake-case-name",
147+
},
148+
{
149+
folderName: "kebab-case-name",
150+
expected: "kebab-case-name",
151+
},
152+
{
153+
folderName: "mix3d_C4s3-N4m3",
154+
expected: "mix3d-c4s3-n4m3",
155+
},
156+
{
157+
folderName: "123-456-789",
158+
expected: "123-456-789",
159+
},
160+
{
161+
folderName: "abc123def456",
162+
expected: "abc123def456",
163+
},
164+
{
165+
folderName: " spaces everywhere ",
166+
expected: "spaces-everywhere",
167+
},
168+
{
169+
folderName: "unicode-café-naïve",
170+
expected: "unicode-caf-na-ve",
171+
},
172+
{
173+
folderName: "path/with/slashes",
174+
expected: "path-with-slashes",
175+
},
176+
{
177+
folderName: "file.tar.gz",
178+
expected: "file-tar-gz",
179+
},
180+
{
181+
folderName: "version-1.2.3-alpha",
182+
expected: "version-1-2-3-alpha",
183+
},
184+
}
185+
186+
for _, tt := range tests {
187+
t.Run(tt.folderName, func(t *testing.T) {
188+
t.Parallel()
189+
name := safeAgentName(tt.folderName, "friendly-fallback")
190+
191+
assert.Equal(t, tt.expected, name)
192+
assert.True(t, provisioner.AgentNameRegex.Match([]byte(name)))
193+
})
194+
}
195+
}

0 commit comments

Comments
 (0)