@marcel91200 / caddy Mirror · read-only
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 10, 22:30 UTC

master
go 840 lines 19.5 KB
Raw
1 // Copyright 2015 Matthew Holt and The Caddy Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package caddy
16
17 import (
18 "context"
19 "crypto/tls"
20 "net"
21 "reflect"
22 "strings"
23 "testing"
24
25 "github.com/caddyserver/caddy/v2/internal"
26 )
27
28 func TestSplitNetworkAddress(t *testing.T) {
29 for i, tc := range []struct {
30 input string
31 expectNetwork string
32 expectHost string
33 expectPort string
34 expectErr bool
35 }{
36 {
37 input: "",
38 expectHost: "",
39 },
40 {
41 input: "foo",
42 expectHost: "foo",
43 },
44 {
45 input: ":", // empty host & empty port
46 },
47 {
48 input: "::",
49 expectHost: "::",
50 },
51 {
52 input: "[::]",
53 expectHost: "::",
54 },
55 {
56 input: ":1234",
57 expectPort: "1234",
58 },
59 {
60 input: "foo:1234",
61 expectHost: "foo",
62 expectPort: "1234",
63 },
64 {
65 input: "foo:1234-5678",
66 expectHost: "foo",
67 expectPort: "1234-5678",
68 },
69 {
70 input: "udp/foo:1234",
71 expectNetwork: "udp",
72 expectHost: "foo",
73 expectPort: "1234",
74 },
75 {
76 input: "tcp6/foo:1234-5678",
77 expectNetwork: "tcp6",
78 expectHost: "foo",
79 expectPort: "1234-5678",
80 },
81 {
82 input: "udp/",
83 expectNetwork: "udp",
84 expectHost: "",
85 },
86 {
87 input: "unix//foo/bar",
88 expectNetwork: "unix",
89 expectHost: "/foo/bar",
90 },
91 {
92 input: "unixgram//foo/bar",
93 expectNetwork: "unixgram",
94 expectHost: "/foo/bar",
95 },
96 {
97 input: "unixpacket//foo/bar",
98 expectNetwork: "unixpacket",
99 expectHost: "/foo/bar",
100 },
101 } {
102 actualNetwork, actualHost, actualPort, err := SplitNetworkAddress(tc.input)
103 if tc.expectErr && err == nil {
104 t.Errorf("Test %d: Expected error but got %v", i, err)
105 }
106 if !tc.expectErr && err != nil {
107 t.Errorf("Test %d: Expected no error but got %v", i, err)
108 }
109 if actualNetwork != tc.expectNetwork {
110 t.Errorf("Test %d: Expected network '%s' but got '%s'", i, tc.expectNetwork, actualNetwork)
111 }
112 if actualHost != tc.expectHost {
113 t.Errorf("Test %d: Expected host '%s' but got '%s'", i, tc.expectHost, actualHost)
114 }
115 if actualPort != tc.expectPort {
116 t.Errorf("Test %d: Expected port '%s' but got '%s'", i, tc.expectPort, actualPort)
117 }
118 }
119 }
120
121 func TestJoinNetworkAddress(t *testing.T) {
122 for i, tc := range []struct {
123 network, host, port string
124 expect string
125 }{
126 {
127 network: "", host: "", port: "",
128 expect: "",
129 },
130 {
131 network: "tcp", host: "", port: "",
132 expect: "tcp/",
133 },
134 {
135 network: "", host: "foo", port: "",
136 expect: "foo",
137 },
138 {
139 network: "", host: "", port: "1234",
140 expect: ":1234",
141 },
142 {
143 network: "", host: "", port: "1234-5678",
144 expect: ":1234-5678",
145 },
146 {
147 network: "", host: "foo", port: "1234",
148 expect: "foo:1234",
149 },
150 {
151 network: "udp", host: "foo", port: "1234",
152 expect: "udp/foo:1234",
153 },
154 {
155 network: "udp", host: "", port: "1234",
156 expect: "udp/:1234",
157 },
158 {
159 network: "unix", host: "/foo/bar", port: "",
160 expect: "unix//foo/bar",
161 },
162 {
163 network: "unix", host: "/foo/bar", port: "0",
164 expect: "unix//foo/bar",
165 },
166 {
167 network: "unix", host: "/foo/bar", port: "1234",
168 expect: "unix//foo/bar",
169 },
170 {
171 network: "", host: "::1", port: "1234",
172 expect: "[::1]:1234",
173 },
174 } {
175 actual := JoinNetworkAddress(tc.network, tc.host, tc.port)
176 if actual != tc.expect {
177 t.Errorf("Test %d: Expected '%s' but got '%s'", i, tc.expect, actual)
178 }
179 }
180 }
181
182 func TestSharedQUICStateGetEncryptedClientHelloKeys(t *testing.T) {
183 hello := &tls.ClientHelloInfo{ServerName: "example.com"}
184 initialKeys := []tls.EncryptedClientHelloKey{{Config: []byte("initial"), PrivateKey: []byte("initial-key")}}
185 updatedKeys := []tls.EncryptedClientHelloKey{{Config: []byte("updated"), PrivateKey: []byte("updated-key")}}
186
187 initialConfig := &tls.Config{
188 GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
189 return nil, nil
190 },
191 GetEncryptedClientHelloKeys: func(*tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
192 return initialKeys, nil
193 },
194 }
195
196 sqs := newSharedQUICState(initialConfig)
197
198 keys, err := sqs.getEncryptedClientHelloKeys(hello)
199 if err != nil {
200 t.Fatalf("getting initial ECH keys: %v", err)
201 }
202 if !reflect.DeepEqual(keys, initialKeys) {
203 t.Fatalf("unexpected initial ECH keys: got %#v, want %#v", keys, initialKeys)
204 }
205
206 updatedConfig := &tls.Config{
207 GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
208 return nil, nil
209 },
210 GetEncryptedClientHelloKeys: func(*tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
211 return updatedKeys, nil
212 },
213 }
214
215 _, cancel := sqs.addState(updatedConfig)
216 sqs.rmu.Lock()
217 sqs.activeTlsConf = updatedConfig
218 sqs.rmu.Unlock()
219
220 keys, err = sqs.getEncryptedClientHelloKeys(hello)
221 if err != nil {
222 t.Fatalf("getting updated ECH keys: %v", err)
223 }
224 if !reflect.DeepEqual(keys, updatedKeys) {
225 t.Fatalf("unexpected updated ECH keys: got %#v, want %#v", keys, updatedKeys)
226 }
227
228 cancel(nil)
229
230 keys, err = sqs.getEncryptedClientHelloKeys(hello)
231 if err != nil {
232 t.Fatalf("getting restored ECH keys: %v", err)
233 }
234 if !reflect.DeepEqual(keys, initialKeys) {
235 t.Fatalf("unexpected restored ECH keys: got %#v, want %#v", keys, initialKeys)
236 }
237 }
238
239 func TestParseNetworkAddress(t *testing.T) {
240 for i, tc := range []struct {
241 input string
242 defaultNetwork string
243 defaultPort uint
244 expectAddr NetworkAddress
245 expectErr bool
246 }{
247 {
248 input: "",
249 expectAddr: NetworkAddress{},
250 },
251 {
252 input: ":",
253 defaultNetwork: "udp",
254 expectAddr: NetworkAddress{
255 Network: "udp",
256 },
257 },
258 {
259 input: "[::]",
260 defaultNetwork: "udp",
261 defaultPort: 53,
262 expectAddr: NetworkAddress{
263 Network: "udp",
264 Host: "::",
265 StartPort: 53,
266 EndPort: 53,
267 },
268 },
269 {
270 input: ":1234",
271 defaultNetwork: "udp",
272 expectAddr: NetworkAddress{
273 Network: "udp",
274 Host: "",
275 StartPort: 1234,
276 EndPort: 1234,
277 },
278 },
279 {
280 input: "udp/:1234",
281 defaultNetwork: "udp",
282 expectAddr: NetworkAddress{
283 Network: "udp",
284 Host: "",
285 StartPort: 1234,
286 EndPort: 1234,
287 },
288 },
289 {
290 input: "tcp6/:1234",
291 defaultNetwork: "tcp",
292 expectAddr: NetworkAddress{
293 Network: "tcp6",
294 Host: "",
295 StartPort: 1234,
296 EndPort: 1234,
297 },
298 },
299 {
300 input: "tcp4/localhost:1234",
301 defaultNetwork: "tcp",
302 expectAddr: NetworkAddress{
303 Network: "tcp4",
304 Host: "localhost",
305 StartPort: 1234,
306 EndPort: 1234,
307 },
308 },
309 {
310 input: "unix//foo/bar",
311 defaultNetwork: "tcp",
312 expectAddr: NetworkAddress{
313 Network: "unix",
314 Host: "/foo/bar",
315 },
316 },
317 {
318 input: "localhost:1234-1234",
319 defaultNetwork: "tcp",
320 expectAddr: NetworkAddress{
321 Network: "tcp",
322 Host: "localhost",
323 StartPort: 1234,
324 EndPort: 1234,
325 },
326 },
327 {
328 input: "localhost:2-1",
329 defaultNetwork: "tcp",
330 expectErr: true,
331 },
332 {
333 input: "localhost:0",
334 defaultNetwork: "tcp",
335 expectAddr: NetworkAddress{
336 Network: "tcp",
337 Host: "localhost",
338 StartPort: 0,
339 EndPort: 0,
340 },
341 },
342 {
343 input: "localhost:1-999999999999",
344 defaultNetwork: "tcp",
345 expectErr: true,
346 },
347 {
348 input: "localhost:65535-65535",
349 defaultNetwork: "tcp",
350 expectAddr: NetworkAddress{
351 Network: "tcp",
352 Host: "localhost",
353 StartPort: 65535,
354 EndPort: 65535,
355 },
356 },
357 {
358 input: "localhost:000000000080",
359 defaultNetwork: "tcp",
360 expectErr: true,
361 },
362 } {
363 actualAddr, err := ParseNetworkAddressWithDefaults(tc.input, tc.defaultNetwork, tc.defaultPort)
364 if tc.expectErr && err == nil {
365 t.Errorf("Test %d: Expected error but got: %v", i, err)
366 }
367 if !tc.expectErr && err != nil {
368 t.Errorf("Test %d: Expected no error but got: %v", i, err)
369 }
370
371 if actualAddr.Network != tc.expectAddr.Network {
372 t.Errorf("Test %d: Expected network '%v' but got '%v'", i, tc.expectAddr, actualAddr)
373 }
374 if !reflect.DeepEqual(tc.expectAddr, actualAddr) {
375 t.Errorf("Test %d: Expected addresses %v but got %v", i, tc.expectAddr, actualAddr)
376 }
377 }
378 }
379
380 // A very long port should fail with a short error (issue #8229).
381 func TestParseNetworkAddressLongPort(t *testing.T) {
382 junk := strings.Repeat("\x7f", 1<<20)
383 for i, input := range []string{
384 ":" + junk,
385 ":80-" + junk,
386 ":" + junk + "-80",
387 "localhost:" + strings.Repeat("9", 1<<20),
388 } {
389 _, err := ParseNetworkAddress(input)
390 if err == nil {
391 t.Errorf("Test %d: expected error but got none", i)
392 continue
393 }
394 if len(err.Error()) > 100 {
395 t.Errorf("Test %d: error message is %d bytes, expected at most 100", i, len(err.Error()))
396 }
397 }
398 }
399
400 func TestParseNetworkAddressWithDefaults(t *testing.T) {
401 for i, tc := range []struct {
402 input string
403 defaultNetwork string
404 defaultPort uint
405 expectAddr NetworkAddress
406 expectErr bool
407 }{
408 {
409 input: "",
410 expectAddr: NetworkAddress{},
411 },
412 {
413 input: ":",
414 defaultNetwork: "udp",
415 expectAddr: NetworkAddress{
416 Network: "udp",
417 },
418 },
419 {
420 input: "[::]",
421 defaultNetwork: "udp",
422 defaultPort: 53,
423 expectAddr: NetworkAddress{
424 Network: "udp",
425 Host: "::",
426 StartPort: 53,
427 EndPort: 53,
428 },
429 },
430 {
431 input: ":1234",
432 defaultNetwork: "udp",
433 expectAddr: NetworkAddress{
434 Network: "udp",
435 Host: "",
436 StartPort: 1234,
437 EndPort: 1234,
438 },
439 },
440 {
441 input: "udp/:1234",
442 defaultNetwork: "udp",
443 expectAddr: NetworkAddress{
444 Network: "udp",
445 Host: "",
446 StartPort: 1234,
447 EndPort: 1234,
448 },
449 },
450 {
451 input: "tcp6/:1234",
452 defaultNetwork: "tcp",
453 expectAddr: NetworkAddress{
454 Network: "tcp6",
455 Host: "",
456 StartPort: 1234,
457 EndPort: 1234,
458 },
459 },
460 {
461 input: "tcp4/localhost:1234",
462 defaultNetwork: "tcp",
463 expectAddr: NetworkAddress{
464 Network: "tcp4",
465 Host: "localhost",
466 StartPort: 1234,
467 EndPort: 1234,
468 },
469 },
470 {
471 input: "unix//foo/bar",
472 defaultNetwork: "tcp",
473 expectAddr: NetworkAddress{
474 Network: "unix",
475 Host: "/foo/bar",
476 },
477 },
478 {
479 input: "localhost:1234-1234",
480 defaultNetwork: "tcp",
481 expectAddr: NetworkAddress{
482 Network: "tcp",
483 Host: "localhost",
484 StartPort: 1234,
485 EndPort: 1234,
486 },
487 },
488 {
489 input: "localhost:2-1",
490 defaultNetwork: "tcp",
491 expectErr: true,
492 },
493 {
494 input: "localhost:0",
495 defaultNetwork: "tcp",
496 expectAddr: NetworkAddress{
497 Network: "tcp",
498 Host: "localhost",
499 StartPort: 0,
500 EndPort: 0,
501 },
502 },
503 {
504 input: "localhost:1-999999999999",
505 defaultNetwork: "tcp",
506 expectErr: true,
507 },
508 } {
509 actualAddr, err := ParseNetworkAddressWithDefaults(tc.input, tc.defaultNetwork, tc.defaultPort)
510 if tc.expectErr && err == nil {
511 t.Errorf("Test %d: Expected error but got: %v", i, err)
512 }
513 if !tc.expectErr && err != nil {
514 t.Errorf("Test %d: Expected no error but got: %v", i, err)
515 }
516
517 if actualAddr.Network != tc.expectAddr.Network {
518 t.Errorf("Test %d: Expected network '%v' but got '%v'", i, tc.expectAddr, actualAddr)
519 }
520 if !reflect.DeepEqual(tc.expectAddr, actualAddr) {
521 t.Errorf("Test %d: Expected addresses %v but got %v", i, tc.expectAddr, actualAddr)
522 }
523 }
524 }
525
526 func TestJoinHostPort(t *testing.T) {
527 for i, tc := range []struct {
528 pa NetworkAddress
529 offset uint
530 expect string
531 }{
532 {
533 pa: NetworkAddress{
534 Network: "tcp",
535 Host: "localhost",
536 StartPort: 1234,
537 EndPort: 1234,
538 },
539 expect: "localhost:1234",
540 },
541 {
542 pa: NetworkAddress{
543 Network: "tcp",
544 Host: "localhost",
545 StartPort: 1234,
546 EndPort: 1235,
547 },
548 expect: "localhost:1234",
549 },
550 {
551 pa: NetworkAddress{
552 Network: "tcp",
553 Host: "localhost",
554 StartPort: 1234,
555 EndPort: 1235,
556 },
557 offset: 1,
558 expect: "localhost:1235",
559 },
560 {
561 pa: NetworkAddress{
562 Network: "unix",
563 Host: "/run/php/php7.3-fpm.sock",
564 },
565 expect: "/run/php/php7.3-fpm.sock",
566 },
567 } {
568 actual := tc.pa.JoinHostPort(tc.offset)
569 if actual != tc.expect {
570 t.Errorf("Test %d: Expected '%s' but got '%s'", i, tc.expect, actual)
571 }
572 }
573 }
574
575 func TestExpand(t *testing.T) {
576 for i, tc := range []struct {
577 input NetworkAddress
578 expect []NetworkAddress
579 }{
580 {
581 input: NetworkAddress{
582 Network: "tcp",
583 Host: "localhost",
584 StartPort: 2000,
585 EndPort: 2000,
586 },
587 expect: []NetworkAddress{
588 {
589 Network: "tcp",
590 Host: "localhost",
591 StartPort: 2000,
592 EndPort: 2000,
593 },
594 },
595 },
596 {
597 input: NetworkAddress{
598 Network: "tcp",
599 Host: "localhost",
600 StartPort: 2000,
601 EndPort: 2002,
602 },
603 expect: []NetworkAddress{
604 {
605 Network: "tcp",
606 Host: "localhost",
607 StartPort: 2000,
608 EndPort: 2000,
609 },
610 {
611 Network: "tcp",
612 Host: "localhost",
613 StartPort: 2001,
614 EndPort: 2001,
615 },
616 {
617 Network: "tcp",
618 Host: "localhost",
619 StartPort: 2002,
620 EndPort: 2002,
621 },
622 },
623 },
624 {
625 input: NetworkAddress{
626 Network: "tcp",
627 Host: "localhost",
628 StartPort: 2000,
629 EndPort: 1999,
630 },
631 expect: []NetworkAddress{},
632 },
633 {
634 input: NetworkAddress{
635 Network: "unix",
636 Host: "/foo/bar",
637 StartPort: 0,
638 EndPort: 0,
639 },
640 expect: []NetworkAddress{
641 {
642 Network: "unix",
643 Host: "/foo/bar",
644 StartPort: 0,
645 EndPort: 0,
646 },
647 },
648 },
649 } {
650 actual := tc.input.Expand()
651 if !reflect.DeepEqual(actual, tc.expect) {
652 t.Errorf("Test %d: Expected %+v but got %+v", i, tc.expect, actual)
653 }
654 }
655 }
656
657 func TestSplitUnixSocketPermissionsBits(t *testing.T) {
658 for i, tc := range []struct {
659 input string
660 expectNetwork string
661 expectPath string
662 expectFileMode string
663 expectErr bool
664 }{
665 {
666 input: "./foo.socket",
667 expectPath: "./foo.socket",
668 expectFileMode: "--w-------",
669 },
670 {
671 input: `.\relative\path.socket`,
672 expectPath: `.\relative\path.socket`,
673 expectFileMode: "--w-------",
674 },
675 {
676 // literal colon in resulting address
677 // and defaulting to 0200 bits
678 input: "./foo.socket:0666",
679 expectPath: "./foo.socket:0666",
680 expectFileMode: "--w-------",
681 },
682 {
683 input: "./foo.socket|0220",
684 expectPath: "./foo.socket",
685 expectFileMode: "--w--w----",
686 },
687 {
688 input: "/var/run/foo|222",
689 expectPath: "/var/run/foo",
690 expectFileMode: "--w--w--w-",
691 },
692 {
693 input: "./foo.socket|0660",
694 expectPath: "./foo.socket",
695 expectFileMode: "-rw-rw----",
696 },
697 {
698 input: "./foo.socket|0666",
699 expectPath: "./foo.socket",
700 expectFileMode: "-rw-rw-rw-",
701 },
702 {
703 input: "/var/run/foo|666",
704 expectPath: "/var/run/foo",
705 expectFileMode: "-rw-rw-rw-",
706 },
707 {
708 input: `c:\absolute\path.socket|220`,
709 expectPath: `c:\absolute\path.socket`,
710 expectFileMode: "--w--w----",
711 },
712 {
713 // symbolic permission representation is not supported for now
714 input: "./foo.socket|u=rw,g=rw,o=rw",
715 expectErr: true,
716 },
717 {
718 // octal (base-8) permission representation has to be between
719 // `0` for no read, no write, no exec (`---`) and
720 // `7` for read (4), write (2), exec (1) (`rwx` => `4+2+1 = 7`)
721 input: "./foo.socket|888",
722 expectErr: true,
723 },
724 {
725 // too many colons in address
726 input: "./foo.socket|123456|0660",
727 expectErr: true,
728 },
729 {
730 // owner is missing write perms
731 input: "./foo.socket|0522",
732 expectErr: true,
733 },
734 } {
735 actualPath, actualFileMode, err := internal.SplitUnixSocketPermissionsBits(tc.input)
736 if tc.expectErr && err == nil {
737 t.Errorf("Test %d: Expected error but got: %v", i, err)
738 }
739 if !tc.expectErr && err != nil {
740 t.Errorf("Test %d: Expected no error but got: %v", i, err)
741 }
742 if actualPath != tc.expectPath {
743 t.Errorf("Test %d: Expected path '%s' but got '%s'", i, tc.expectPath, actualPath)
744 }
745 // fileMode.Perm().String() parses 0 to "----------"
746 if !tc.expectErr && actualFileMode.Perm().String() != tc.expectFileMode {
747 t.Errorf("Test %d: Expected perms '%s' but got '%s'", i, tc.expectFileMode, actualFileMode.Perm().String())
748 }
749 }
750 }
751
752 // TestListenQUICOptions_ZeroValueAllows0RTT checks that ListenQUIC accepts a
753 // zero-value options struct (historical default: 0-RTT allowed) and that the
754 // returned listener is released by closing it twice, per ListenQUIC's contract.
755 func TestListenQUICOptions_ZeroValueAllows0RTT(t *testing.T) {
756 na, err := ParseNetworkAddress("udp/127.0.0.1:0")
757 if err != nil {
758 t.Fatalf("ParseNetworkAddress: %v", err)
759 }
760
761 ln, err := na.ListenQUIC(context.Background(), 0, net.ListenConfig{}, ListenQUICOptions{
762 TLSConfig: &tls.Config{}, //nolint:gosec // test listener; no client handshake
763 })
764 if err != nil {
765 t.Fatalf("ListenQUIC: %v", err)
766 }
767 if err := ln.Close(); err != nil {
768 t.Errorf("first Close: %v", err)
769 }
770 if err := ln.Close(); err != nil {
771 t.Errorf("second Close: %v", err)
772 }
773 }
774
775 // TestListenQUICWebTransportCapability verifies that WebTransport QUIC
776 // capabilities are fixed by the first creator of a pooled QUIC listener.
777 func TestListenQUICWebTransportCapability(t *testing.T) {
778 closeTwice := func(t *testing.T, ln interface{ Close() error }) {
779 t.Helper()
780 if err := ln.Close(); err != nil {
781 t.Errorf("first Close: %v", err)
782 }
783 if err := ln.Close(); err != nil {
784 t.Errorf("second Close: %v", err)
785 }
786 }
787 supportsWT := func(t *testing.T, ln any) bool {
788 t.Helper()
789 wt, ok := ln.(interface{ SupportsWebTransport() bool })
790 if !ok {
791 t.Fatal("listener does not implement SupportsWebTransport()")
792 }
793 return wt.SupportsWebTransport()
794 }
795
796 for _, tc := range []struct {
797 name string
798 first, want bool
799 }{
800 {name: "off-then-on", first: false, want: false},
801 {name: "on-then-off", first: true, want: true},
802 } {
803 t.Run(tc.name, func(t *testing.T) {
804 probe, err := net.ListenPacket("udp", "127.0.0.1:0")
805 if err != nil {
806 t.Fatalf("ListenPacket probe: %v", err)
807 }
808 port := uint(probe.LocalAddr().(*net.UDPAddr).Port)
809 _ = probe.Close()
810
811 na := NetworkAddress{Network: "udp", Host: "127.0.0.1", StartPort: port, EndPort: port}
812 tlsConf := &tls.Config{}
813 listen := func(enable bool) (interface{ Close() error }, error) {
814 return na.ListenQUIC(context.Background(), 0, net.ListenConfig{}, ListenQUICOptions{
815 TLSConfig: tlsConf,
816 EnableWebTransport: enable,
817 })
818 }
819
820 ln1, err := listen(tc.first)
821 if err != nil {
822 t.Fatalf("first ListenQUIC: %v", err)
823 }
824 ln2, err := listen(!tc.first)
825 if err != nil {
826 closeTwice(t, ln1)
827 t.Fatalf("second ListenQUIC: %v", err)
828 }
829 defer closeTwice(t, ln1)
830 defer closeTwice(t, ln2)
831
832 if got := supportsWT(t, ln1); got != tc.want {
833 t.Errorf("first listener SupportsWebTransport() = %v, want %v", got, tc.want)
834 }
835 if got := supportsWT(t, ln2); got != tc.want {
836 t.Errorf("second listener SupportsWebTransport() = %v, want %v (pool reuses first creator's config)", got, tc.want)
837 }
838 })
839 }
840 }