Skip to content

Commit 723af00

Browse files
Anchoring and tests for objectIDRegex (#342)
GitOrigin-RevId: 6a5d0aaacc8d9b03f44e290d117578389f97fa54
1 parent 95ff9c9 commit 723af00

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed

pkg/validate/id.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const (
1212
)
1313

1414
func IsObjectID(prefix, s string) bool {
15-
var objectIDRegex = regexp.MustCompile(fmt.Sprintf(`%s-[a-z0-9]{20}$`, prefix))
15+
var objectIDRegex = regexp.MustCompile(fmt.Sprintf(`^%s-[a-z0-9]{20}$`, prefix))
1616
return objectIDRegex.MatchString(s)
1717
}
1818

pkg/validate/id_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package validate_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/render-oss/cli/pkg/validate"
7+
)
8+
9+
func TestIsObjectID(t *testing.T) {
10+
tests := []struct {
11+
name string
12+
prefix string
13+
input string
14+
expected bool
15+
}{
16+
// Valid IDs
17+
{"valid service ID", "srv", "srv-12345678901234567890", true},
18+
{"valid postgres ID", "dpg", "dpg-12345678901234567890", true},
19+
20+
// Anchoring — the core regression test
21+
{"prefix suffix not matched (no ^ anchor regression)", "dpg", "xdpg-12345678901234567890", false},
22+
{"prefix suffix not matched with srv", "srv", "xsrv-12345678901234567890", false},
23+
{"valid ID embedded in longer string", "dpg", "dpg-12345678901234567890extra", false},
24+
25+
// Format violations
26+
{"uppercase letters rejected", "srv", "srv-1234567890ABCDEFGHIJ", false},
27+
{"too short", "srv", "srv-1234567890", false},
28+
{"too long", "srv", "srv-123456789012345678901", false},
29+
{"wrong prefix", "srv", "dpg-12345678901234567890", false},
30+
{"empty string", "srv", "", false},
31+
{"prefix only", "srv", "srv-", false},
32+
{"no prefix separator", "srv", "srv12345678901234567890", false},
33+
}
34+
35+
for _, tc := range tests {
36+
t.Run(tc.name, func(t *testing.T) {
37+
got := validate.IsObjectID(tc.prefix, tc.input)
38+
if got != tc.expected {
39+
t.Errorf("IsObjectID(%q, %q) = %v, want %v", tc.prefix, tc.input, got, tc.expected)
40+
}
41+
})
42+
}
43+
}
44+
45+
func TestIsServiceID(t *testing.T) {
46+
tests := []struct {
47+
name string
48+
input string
49+
expected bool
50+
}{
51+
{"valid service ID", "srv-12345678901234567890", true},
52+
{"service instance ID rejected", "srv-12345678901234567890-abc", false},
53+
{"postgres ID rejected", "dpg-12345678901234567890", false},
54+
{"suffix match rejected (anchor regression)", "xsrv-12345678901234567890", false},
55+
}
56+
57+
for _, tc := range tests {
58+
t.Run(tc.name, func(t *testing.T) {
59+
got := validate.IsServiceID(tc.input)
60+
if got != tc.expected {
61+
t.Errorf("IsServiceID(%q) = %v, want %v", tc.input, got, tc.expected)
62+
}
63+
})
64+
}
65+
}
66+
67+
func TestIsServiceInstanceID(t *testing.T) {
68+
tests := []struct {
69+
name string
70+
input string
71+
expected bool
72+
}{
73+
{"valid instance ID", "srv-12345678901234567890-abc", true},
74+
{"valid instance ID with longer suffix", "srv-12345678901234567890-abc123", true},
75+
{"bare service ID rejected", "srv-12345678901234567890", false},
76+
{"suffix match rejected", "xsrv-12345678901234567890-abc", false},
77+
}
78+
79+
for _, tc := range tests {
80+
t.Run(tc.name, func(t *testing.T) {
81+
got := validate.IsServiceInstanceID(tc.input)
82+
if got != tc.expected {
83+
t.Errorf("IsServiceInstanceID(%q) = %v, want %v", tc.input, got, tc.expected)
84+
}
85+
})
86+
}
87+
}
88+
89+
func TestExtractServiceIDFromInstanceID(t *testing.T) {
90+
tests := []struct {
91+
name string
92+
input string
93+
expected string
94+
}{
95+
{"extracts service ID from instance ID", "srv-12345678901234567890-abc", "srv-12345678901234567890"},
96+
{"returns empty for bare service ID", "srv-12345678901234567890", ""},
97+
{"returns empty for invalid input", "not-an-id", ""},
98+
}
99+
100+
for _, tc := range tests {
101+
t.Run(tc.name, func(t *testing.T) {
102+
got := validate.ExtractServiceIDFromInstanceID(tc.input)
103+
if got != tc.expected {
104+
t.Errorf("ExtractServiceIDFromInstanceID(%q) = %q, want %q", tc.input, got, tc.expected)
105+
}
106+
})
107+
}
108+
}

0 commit comments

Comments
 (0)