@@ -85,6 +85,7 @@ func TestResolveEntry(t *testing.T) {
8585 hostname string
8686 pathType gatewayv1.PathMatchType
8787 path string
88+ nilPath bool // leave match.Path nil to exercise default-path handling
8889 wantBucket bucket
8990 wantKey maps.EntryKey
9091 }{
@@ -136,16 +137,45 @@ func TestResolveEntry(t *testing.T) {
136137 wantBucket : bucketRegex ,
137138 wantKey : maps.EntryKey {Hostname : `\.example\.com` , Path : "/foo" },
138139 },
140+ {
141+ // nil match.Path → defaults to path="/" and type=PathPrefix
142+ name : "nil path defaults to slash prefix exact-host" ,
143+ hostname : "example.com" ,
144+ nilPath : true ,
145+ wantBucket : bucketPrefix ,
146+ wantKey : maps.EntryKey {Hostname : "example.com" , Path : "/" },
147+ },
148+ {
149+ // regex path that starts with "^" — the caret must be stripped before sanitization
150+ name : "regex-path with leading caret exact-host" ,
151+ hostname : "example.com" ,
152+ pathType : gatewayv1 .PathMatchRegularExpression ,
153+ path : "^/foo" ,
154+ wantBucket : bucketRegex ,
155+ wantKey : maps.EntryKey {Hostname : `^example\.com` , Path : "/foo" },
156+ },
157+ {
158+ // root path "/" with prefix type and wildcard host → path becomes "/.*"
159+ name : "prefix-path root wildcard-host" ,
160+ hostname : "*.example.com" ,
161+ pathType : gatewayv1 .PathMatchPathPrefix ,
162+ path : "/" ,
163+ wantBucket : bucketRegex ,
164+ wantKey : maps.EntryKey {Hostname : `\.example\.com` , Path : "/.*" },
165+ },
139166 }
140167
141168 for _ , tt := range tests {
142169 t .Run (tt .name , func (t * testing.T ) {
143170 d := newDesiredBackendsMaps ()
144- match := gatewayv1.HTTPRouteMatch {
145- Path : & gatewayv1.HTTPPathMatch {
146- Type : ptr (tt .pathType ),
147- Value : strPtr (tt .path ),
148- },
171+ var match gatewayv1.HTTPRouteMatch
172+ if ! tt .nilPath {
173+ match = gatewayv1.HTTPRouteMatch {
174+ Path : & gatewayv1.HTTPPathMatch {
175+ Type : ptr (tt .pathType ),
176+ Value : strPtr (tt .path ),
177+ },
178+ }
149179 }
150180 innerMap , key := d .resolveEntry (tt .hostname , match )
151181
@@ -174,3 +204,28 @@ func TestResolveEntry(t *testing.T) {
174204 })
175205 }
176206}
207+
208+ // TestResolveEntryLazyInit verifies that two calls with the same hostname+match
209+ // return the same inner-map instance (lazy initialisation must not replace an
210+ // already-populated map).
211+ func TestResolveEntryLazyInit (t * testing.T ) {
212+ strPtr := func (s string ) * string { return & s }
213+ ptr := func (s gatewayv1.PathMatchType ) * gatewayv1.PathMatchType { return & s }
214+
215+ d := newDesiredBackendsMaps ()
216+ match := gatewayv1.HTTPRouteMatch {
217+ Path : & gatewayv1.HTTPPathMatch {
218+ Type : ptr (gatewayv1 .PathMatchPathPrefix ),
219+ Value : strPtr ("/bar" ),
220+ },
221+ }
222+
223+ m1 , _ := d .resolveEntry ("example.com" , match )
224+ w := int32 (100 )
225+ m1 ["backend-a" ] = & maps.WeightedValue {ValueName : "backend-a" , Weight : & w }
226+
227+ m2 , _ := d .resolveEntry ("example.com" , match )
228+ if m2 ["backend-a" ] == nil {
229+ t .Error ("second resolveEntry call returned a fresh map, wanted the same instance" )
230+ }
231+ }
0 commit comments