@@ -129,3 +129,301 @@ func TestParseHTTPToken(t *testing.T) {
129129 })
130130 }
131131}
132+
133+ func TestParseHost (t * testing.T ) {
134+ tests := []struct {
135+ name string
136+ input string
137+ expectedHost host
138+ expectedRest string
139+ expectError bool
140+ }{
141+ {
142+ name : "empty string" ,
143+ input : "" ,
144+ expectedHost : nil ,
145+ expectedRest : "" ,
146+ expectError : true ,
147+ },
148+ {
149+ name : "simple domain" ,
150+ input : "google.com" ,
151+ expectedHost : host {label ("google" ), label ("com" )},
152+ expectedRest : "" ,
153+ expectError : false ,
154+ },
155+ {
156+ name : "subdomain" ,
157+ input : "api.google.com" ,
158+ expectedHost : host {label ("api" ), label ("google" ), label ("com" )},
159+ expectedRest : "" ,
160+ expectError : false ,
161+ },
162+ {
163+ name : "single label" ,
164+ input : "localhost" ,
165+ expectedHost : host {label ("localhost" )},
166+ expectedRest : "" ,
167+ expectError : false ,
168+ },
169+ {
170+ name : "domain with trailing content" ,
171+ input : "example.org/path" ,
172+ expectedHost : host {label ("example" ), label ("org" )},
173+ expectedRest : "/path" ,
174+ expectError : false ,
175+ },
176+ {
177+ name : "domain with port" ,
178+ input : "localhost:8080" ,
179+ expectedHost : host {label ("localhost" )},
180+ expectedRest : ":8080" ,
181+ expectError : false ,
182+ },
183+ {
184+ name : "numeric labels" ,
185+ input : "192.168.1.1" ,
186+ expectedHost : host {label ("192" ), label ("168" ), label ("1" ), label ("1" )},
187+ expectedRest : "" ,
188+ expectError : false ,
189+ },
190+ {
191+ name : "hyphenated domain" ,
192+ input : "my-site.example-domain.co.uk" ,
193+ expectedHost : host {label ("my-site" ), label ("example-domain" ), label ("co" ), label ("uk" )},
194+ expectedRest : "" ,
195+ expectError : false ,
196+ },
197+ {
198+ name : "alphanumeric labels" ,
199+ input : "a1b2c3.test123.com" ,
200+ expectedHost : host {label ("a1b2c3" ), label ("test123" ), label ("com" )},
201+ expectedRest : "" ,
202+ expectError : false ,
203+ },
204+ {
205+ name : "starts with hyphen" ,
206+ input : "-invalid.com" ,
207+ expectedHost : nil ,
208+ expectedRest : "" ,
209+ expectError : true ,
210+ },
211+ {
212+ name : "ends with hyphen" ,
213+ input : "invalid-.com" ,
214+ expectedHost : nil ,
215+ expectedRest : "" ,
216+ expectError : true ,
217+ },
218+ {
219+ name : "label ends with hyphen" ,
220+ input : "test.invalid-.com" ,
221+ expectedHost : nil ,
222+ expectedRest : "" ,
223+ expectError : true ,
224+ },
225+ {
226+ name : "invalid character" ,
227+ 228+ expectedHost : host {label ("test" )},
229+ expectedRest : "@example.com" ,
230+ expectError : false ,
231+ },
232+ {
233+ name : "empty label" ,
234+ input : "test..com" ,
235+ expectedHost : nil ,
236+ expectedRest : "" ,
237+ expectError : true ,
238+ },
239+ {
240+ name : "trailing dot" ,
241+ input : "example.com." ,
242+ expectedHost : nil ,
243+ expectedRest : "" ,
244+ expectError : true ,
245+ },
246+ {
247+ name : "single character labels" ,
248+ input : "a.b.c" ,
249+ expectedHost : host {label ("a" ), label ("b" ), label ("c" )},
250+ expectedRest : "" ,
251+ expectError : false ,
252+ },
253+ {
254+ name : "mixed case" ,
255+ input : "Example.COM" ,
256+ expectedHost : host {label ("Example" ), label ("COM" )},
257+ expectedRest : "" ,
258+ expectError : false ,
259+ },
260+ }
261+
262+ for _ , tt := range tests {
263+ t .Run (tt .name , func (t * testing.T ) {
264+ hostResult , rest , err := parseHost (tt .input )
265+
266+ if tt .expectError {
267+ if err == nil {
268+ t .Errorf ("expected error but got none" )
269+ }
270+ return
271+ }
272+
273+ if err != nil {
274+ t .Errorf ("unexpected error: %v" , err )
275+ return
276+ }
277+
278+ if len (hostResult ) != len (tt .expectedHost ) {
279+ t .Errorf ("expected host length %d, got %d" , len (tt .expectedHost ), len (hostResult ))
280+ return
281+ }
282+
283+ for i , expectedLabel := range tt .expectedHost {
284+ if hostResult [i ] != expectedLabel {
285+ t .Errorf ("expected label[%d] %q, got %q" , i , expectedLabel , hostResult [i ])
286+ }
287+ }
288+
289+ if rest != tt .expectedRest {
290+ t .Errorf ("expected remaining %q, got %q" , tt .expectedRest , rest )
291+ }
292+ })
293+ }
294+ }
295+
296+ func TestParseLabel (t * testing.T ) {
297+ tests := []struct {
298+ name string
299+ input string
300+ expectedLabel label
301+ expectedRest string
302+ expectError bool
303+ }{
304+ {
305+ name : "empty string" ,
306+ input : "" ,
307+ expectedLabel : "" ,
308+ expectedRest : "" ,
309+ expectError : true ,
310+ },
311+ {
312+ name : "simple label" ,
313+ input : "test" ,
314+ expectedLabel : "test" ,
315+ expectedRest : "" ,
316+ expectError : false ,
317+ },
318+ {
319+ name : "label with dot" ,
320+ input : "test.com" ,
321+ expectedLabel : "test" ,
322+ expectedRest : ".com" ,
323+ expectError : false ,
324+ },
325+ {
326+ name : "label with hyphen" ,
327+ input : "my-site" ,
328+ expectedLabel : "my-site" ,
329+ expectedRest : "" ,
330+ expectError : false ,
331+ },
332+ {
333+ name : "alphanumeric label" ,
334+ input : "test123" ,
335+ expectedLabel : "test123" ,
336+ expectedRest : "" ,
337+ expectError : false ,
338+ },
339+ {
340+ name : "starts with hyphen" ,
341+ input : "-invalid" ,
342+ expectedLabel : "" ,
343+ expectedRest : "" ,
344+ expectError : true ,
345+ },
346+ {
347+ name : "ends with hyphen" ,
348+ input : "invalid-" ,
349+ expectedLabel : "" ,
350+ expectedRest : "" ,
351+ expectError : true ,
352+ },
353+ {
354+ name : "ends with hyphen followed by dot" ,
355+ input : "invalid-.com" ,
356+ expectedLabel : "" ,
357+ expectedRest : "" ,
358+ expectError : true ,
359+ },
360+ {
361+ name : "single character" ,
362+ input : "a" ,
363+ expectedLabel : "a" ,
364+ expectedRest : "" ,
365+ expectError : false ,
366+ },
367+ {
368+ name : "numeric label" ,
369+ input : "123" ,
370+ expectedLabel : "123" ,
371+ expectedRest : "" ,
372+ expectError : false ,
373+ },
374+ {
375+ name : "mixed case" ,
376+ input : "Test" ,
377+ expectedLabel : "Test" ,
378+ expectedRest : "" ,
379+ expectError : false ,
380+ },
381+ {
382+ name : "invalid character" ,
383+ input : "test@invalid" ,
384+ expectedLabel : "test" ,
385+ expectedRest : "@invalid" ,
386+ expectError : false ,
387+ },
388+ {
389+ name : "starts with number" ,
390+ input : "1test" ,
391+ expectedLabel : "1test" ,
392+ expectedRest : "" ,
393+ expectError : false ,
394+ },
395+ {
396+ name : "label with trailing slash" ,
397+ input : "api/path" ,
398+ expectedLabel : "api" ,
399+ expectedRest : "/path" ,
400+ expectError : false ,
401+ },
402+ }
403+
404+ for _ , tt := range tests {
405+ t .Run (tt .name , func (t * testing.T ) {
406+ labelResult , rest , err := parseLabel (tt .input )
407+
408+ if tt .expectError {
409+ if err == nil {
410+ t .Errorf ("expected error but got none" )
411+ }
412+ return
413+ }
414+
415+ if err != nil {
416+ t .Errorf ("unexpected error: %v" , err )
417+ return
418+ }
419+
420+ if labelResult != tt .expectedLabel {
421+ t .Errorf ("expected label %q, got %q" , tt .expectedLabel , labelResult )
422+ }
423+
424+ if rest != tt .expectedRest {
425+ t .Errorf ("expected remaining %q, got %q" , tt .expectedRest , rest )
426+ }
427+ })
428+ }
429+ }
0 commit comments