]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/tls/tls_test.go
all: don't call t.Fatal from a goroutine
[gostls13.git] / src / crypto / tls / tls_test.go
1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package tls
6
7 import (
8         "bytes"
9         "crypto/x509"
10         "errors"
11         "fmt"
12         "internal/testenv"
13         "io"
14         "io/ioutil"
15         "math"
16         "math/rand"
17         "net"
18         "os"
19         "reflect"
20         "strings"
21         "testing"
22         "testing/quick"
23         "time"
24 )
25
26 var rsaCertPEM = `-----BEGIN CERTIFICATE-----
27 MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
28 BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
29 aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
30 MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
31 ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
32 hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
33 rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
34 zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
35 MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
36 r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
37 -----END CERTIFICATE-----
38 `
39
40 var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
41 MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
42 k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
43 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
44 MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
45 SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
46 xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
47 D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
48 -----END RSA PRIVATE KEY-----
49 `
50
51 // keyPEM is the same as rsaKeyPEM, but declares itself as just
52 // "PRIVATE KEY", not "RSA PRIVATE KEY".  https://golang.org/issue/4477
53 var keyPEM = `-----BEGIN PRIVATE KEY-----
54 MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
55 k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
56 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
57 MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
58 SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
59 xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
60 D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
61 -----END PRIVATE KEY-----
62 `
63
64 var ecdsaCertPEM = `-----BEGIN CERTIFICATE-----
65 MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw
66 EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
67 eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG
68 EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk
69 Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR
70 lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl
71 01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8
72 XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo
73 A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb
74 H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1
75 +jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA==
76 -----END CERTIFICATE-----
77 `
78
79 var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS-----
80 BgUrgQQAIw==
81 -----END EC PARAMETERS-----
82 -----BEGIN EC PRIVATE KEY-----
83 MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0
84 NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL
85 06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz
86 VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q
87 kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ==
88 -----END EC PRIVATE KEY-----
89 `
90
91 var keyPairTests = []struct {
92         algo string
93         cert string
94         key  string
95 }{
96         {"ECDSA", ecdsaCertPEM, ecdsaKeyPEM},
97         {"RSA", rsaCertPEM, rsaKeyPEM},
98         {"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477
99 }
100
101 func TestX509KeyPair(t *testing.T) {
102         t.Parallel()
103         var pem []byte
104         for _, test := range keyPairTests {
105                 pem = []byte(test.cert + test.key)
106                 if _, err := X509KeyPair(pem, pem); err != nil {
107                         t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err)
108                 }
109                 pem = []byte(test.key + test.cert)
110                 if _, err := X509KeyPair(pem, pem); err != nil {
111                         t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err)
112                 }
113         }
114 }
115
116 func TestX509KeyPairErrors(t *testing.T) {
117         _, err := X509KeyPair([]byte(rsaKeyPEM), []byte(rsaCertPEM))
118         if err == nil {
119                 t.Fatalf("X509KeyPair didn't return an error when arguments were switched")
120         }
121         if subStr := "been switched"; !strings.Contains(err.Error(), subStr) {
122                 t.Fatalf("Expected %q in the error when switching arguments to X509KeyPair, but the error was %q", subStr, err)
123         }
124
125         _, err = X509KeyPair([]byte(rsaCertPEM), []byte(rsaCertPEM))
126         if err == nil {
127                 t.Fatalf("X509KeyPair didn't return an error when both arguments were certificates")
128         }
129         if subStr := "certificate"; !strings.Contains(err.Error(), subStr) {
130                 t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were certificates, but the error was %q", subStr, err)
131         }
132
133         const nonsensePEM = `
134 -----BEGIN NONSENSE-----
135 Zm9vZm9vZm9v
136 -----END NONSENSE-----
137 `
138
139         _, err = X509KeyPair([]byte(nonsensePEM), []byte(nonsensePEM))
140         if err == nil {
141                 t.Fatalf("X509KeyPair didn't return an error when both arguments were nonsense")
142         }
143         if subStr := "NONSENSE"; !strings.Contains(err.Error(), subStr) {
144                 t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were nonsense, but the error was %q", subStr, err)
145         }
146 }
147
148 func TestX509MixedKeyPair(t *testing.T) {
149         if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
150                 t.Error("Load of RSA certificate succeeded with ECDSA private key")
151         }
152         if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil {
153                 t.Error("Load of ECDSA certificate succeeded with RSA private key")
154         }
155 }
156
157 func newLocalListener(t testing.TB) net.Listener {
158         ln, err := net.Listen("tcp", "127.0.0.1:0")
159         if err != nil {
160                 ln, err = net.Listen("tcp6", "[::1]:0")
161         }
162         if err != nil {
163                 t.Fatal(err)
164         }
165         return ln
166 }
167
168 func TestDialTimeout(t *testing.T) {
169         if testing.Short() {
170                 t.Skip("skipping in short mode")
171         }
172         listener := newLocalListener(t)
173
174         addr := listener.Addr().String()
175         defer listener.Close()
176
177         complete := make(chan bool)
178         defer close(complete)
179
180         go func() {
181                 conn, err := listener.Accept()
182                 if err != nil {
183                         t.Error(err)
184                         return
185                 }
186                 <-complete
187                 conn.Close()
188         }()
189
190         dialer := &net.Dialer{
191                 Timeout: 10 * time.Millisecond,
192         }
193
194         var err error
195         if _, err = DialWithDialer(dialer, "tcp", addr, nil); err == nil {
196                 t.Fatal("DialWithTimeout completed successfully")
197         }
198
199         if !isTimeoutError(err) {
200                 t.Errorf("resulting error not a timeout: %v\nType %T: %#v", err, err, err)
201         }
202 }
203
204 func isTimeoutError(err error) bool {
205         if ne, ok := err.(net.Error); ok {
206                 return ne.Timeout()
207         }
208         return false
209 }
210
211 // tests that Conn.Read returns (non-zero, io.EOF) instead of
212 // (non-zero, nil) when a Close (alertCloseNotify) is sitting right
213 // behind the application data in the buffer.
214 func TestConnReadNonzeroAndEOF(t *testing.T) {
215         // This test is racy: it assumes that after a write to a
216         // localhost TCP connection, the peer TCP connection can
217         // immediately read it. Because it's racy, we skip this test
218         // in short mode, and then retry it several times with an
219         // increasing sleep in between our final write (via srv.Close
220         // below) and the following read.
221         if testing.Short() {
222                 t.Skip("skipping in short mode")
223         }
224         var err error
225         for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 {
226                 if err = testConnReadNonzeroAndEOF(t, delay); err == nil {
227                         return
228                 }
229         }
230         t.Error(err)
231 }
232
233 func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error {
234         ln := newLocalListener(t)
235         defer ln.Close()
236
237         srvCh := make(chan *Conn, 1)
238         var serr error
239         go func() {
240                 sconn, err := ln.Accept()
241                 if err != nil {
242                         serr = err
243                         srvCh <- nil
244                         return
245                 }
246                 serverConfig := testConfig.Clone()
247                 srv := Server(sconn, serverConfig)
248                 if err := srv.Handshake(); err != nil {
249                         serr = fmt.Errorf("handshake: %v", err)
250                         srvCh <- nil
251                         return
252                 }
253                 srvCh <- srv
254         }()
255
256         clientConfig := testConfig.Clone()
257         conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
258         if err != nil {
259                 t.Fatal(err)
260         }
261         defer conn.Close()
262
263         srv := <-srvCh
264         if srv == nil {
265                 return serr
266         }
267
268         buf := make([]byte, 6)
269
270         srv.Write([]byte("foobar"))
271         n, err := conn.Read(buf)
272         if n != 6 || err != nil || string(buf) != "foobar" {
273                 return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf)
274         }
275
276         srv.Write([]byte("abcdef"))
277         srv.Close()
278         time.Sleep(delay)
279         n, err = conn.Read(buf)
280         if n != 6 || string(buf) != "abcdef" {
281                 return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf)
282         }
283         if err != io.EOF {
284                 return fmt.Errorf("Second Read error = %v; want io.EOF", err)
285         }
286         return nil
287 }
288
289 func TestTLSUniqueMatches(t *testing.T) {
290         ln := newLocalListener(t)
291         defer ln.Close()
292
293         serverTLSUniques := make(chan []byte)
294         go func() {
295                 for i := 0; i < 2; i++ {
296                         sconn, err := ln.Accept()
297                         if err != nil {
298                                 t.Error(err)
299                                 return
300                         }
301                         serverConfig := testConfig.Clone()
302                         srv := Server(sconn, serverConfig)
303                         if err := srv.Handshake(); err != nil {
304                                 t.Error(err)
305                                 return
306                         }
307                         serverTLSUniques <- srv.ConnectionState().TLSUnique
308                 }
309         }()
310
311         clientConfig := testConfig.Clone()
312         clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
313         conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
314         if err != nil {
315                 t.Fatal(err)
316         }
317         if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
318                 t.Error("client and server channel bindings differ")
319         }
320         conn.Close()
321
322         conn, err = Dial("tcp", ln.Addr().String(), clientConfig)
323         if err != nil {
324                 t.Fatal(err)
325         }
326         defer conn.Close()
327         if !conn.ConnectionState().DidResume {
328                 t.Error("second session did not use resumption")
329         }
330         if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
331                 t.Error("client and server channel bindings differ when session resumption is used")
332         }
333 }
334
335 func TestVerifyHostname(t *testing.T) {
336         testenv.MustHaveExternalNetwork(t)
337
338         c, err := Dial("tcp", "www.google.com:https", nil)
339         if err != nil {
340                 t.Fatal(err)
341         }
342         if err := c.VerifyHostname("www.google.com"); err != nil {
343                 t.Fatalf("verify www.google.com: %v", err)
344         }
345         if err := c.VerifyHostname("www.yahoo.com"); err == nil {
346                 t.Fatalf("verify www.yahoo.com succeeded")
347         }
348
349         c, err = Dial("tcp", "www.google.com:https", &Config{InsecureSkipVerify: true})
350         if err != nil {
351                 t.Fatal(err)
352         }
353         if err := c.VerifyHostname("www.google.com"); err == nil {
354                 t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
355         }
356         if err := c.VerifyHostname("www.yahoo.com"); err == nil {
357                 t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
358         }
359 }
360
361 func TestVerifyHostnameResumed(t *testing.T) {
362         testenv.MustHaveExternalNetwork(t)
363
364         config := &Config{
365                 ClientSessionCache: NewLRUClientSessionCache(32),
366         }
367         for i := 0; i < 2; i++ {
368                 c, err := Dial("tcp", "www.google.com:https", config)
369                 if err != nil {
370                         t.Fatalf("Dial #%d: %v", i, err)
371                 }
372                 cs := c.ConnectionState()
373                 if i > 0 && !cs.DidResume {
374                         t.Fatalf("Subsequent connection unexpectedly didn't resume")
375                 }
376                 if cs.VerifiedChains == nil {
377                         t.Fatalf("Dial #%d: cs.VerifiedChains == nil", i)
378                 }
379                 if err := c.VerifyHostname("www.google.com"); err != nil {
380                         t.Fatalf("verify www.google.com #%d: %v", i, err)
381                 }
382                 c.Close()
383         }
384 }
385
386 func TestConnCloseBreakingWrite(t *testing.T) {
387         ln := newLocalListener(t)
388         defer ln.Close()
389
390         srvCh := make(chan *Conn, 1)
391         var serr error
392         var sconn net.Conn
393         go func() {
394                 var err error
395                 sconn, err = ln.Accept()
396                 if err != nil {
397                         serr = err
398                         srvCh <- nil
399                         return
400                 }
401                 serverConfig := testConfig.Clone()
402                 srv := Server(sconn, serverConfig)
403                 if err := srv.Handshake(); err != nil {
404                         serr = fmt.Errorf("handshake: %v", err)
405                         srvCh <- nil
406                         return
407                 }
408                 srvCh <- srv
409         }()
410
411         cconn, err := net.Dial("tcp", ln.Addr().String())
412         if err != nil {
413                 t.Fatal(err)
414         }
415         defer cconn.Close()
416
417         conn := &changeImplConn{
418                 Conn: cconn,
419         }
420
421         clientConfig := testConfig.Clone()
422         tconn := Client(conn, clientConfig)
423         if err := tconn.Handshake(); err != nil {
424                 t.Fatal(err)
425         }
426
427         srv := <-srvCh
428         if srv == nil {
429                 t.Fatal(serr)
430         }
431         defer sconn.Close()
432
433         connClosed := make(chan struct{})
434         conn.closeFunc = func() error {
435                 close(connClosed)
436                 return nil
437         }
438
439         inWrite := make(chan bool, 1)
440         var errConnClosed = errors.New("conn closed for test")
441         conn.writeFunc = func(p []byte) (n int, err error) {
442                 inWrite <- true
443                 <-connClosed
444                 return 0, errConnClosed
445         }
446
447         closeReturned := make(chan bool, 1)
448         go func() {
449                 <-inWrite
450                 tconn.Close() // test that this doesn't block forever.
451                 closeReturned <- true
452         }()
453
454         _, err = tconn.Write([]byte("foo"))
455         if err != errConnClosed {
456                 t.Errorf("Write error = %v; want errConnClosed", err)
457         }
458
459         <-closeReturned
460         if err := tconn.Close(); err != errClosed {
461                 t.Errorf("Close error = %v; want errClosed", err)
462         }
463 }
464
465 func TestConnCloseWrite(t *testing.T) {
466         ln := newLocalListener(t)
467         defer ln.Close()
468
469         clientDoneChan := make(chan struct{})
470
471         serverCloseWrite := func() error {
472                 sconn, err := ln.Accept()
473                 if err != nil {
474                         return fmt.Errorf("accept: %v", err)
475                 }
476                 defer sconn.Close()
477
478                 serverConfig := testConfig.Clone()
479                 srv := Server(sconn, serverConfig)
480                 if err := srv.Handshake(); err != nil {
481                         return fmt.Errorf("handshake: %v", err)
482                 }
483                 defer srv.Close()
484
485                 data, err := ioutil.ReadAll(srv)
486                 if err != nil {
487                         return err
488                 }
489                 if len(data) > 0 {
490                         return fmt.Errorf("Read data = %q; want nothing", data)
491                 }
492
493                 if err := srv.CloseWrite(); err != nil {
494                         return fmt.Errorf("server CloseWrite: %v", err)
495                 }
496
497                 // Wait for clientCloseWrite to finish, so we know we
498                 // tested the CloseWrite before we defer the
499                 // sconn.Close above, which would also cause the
500                 // client to unblock like CloseWrite.
501                 <-clientDoneChan
502                 return nil
503         }
504
505         clientCloseWrite := func() error {
506                 defer close(clientDoneChan)
507
508                 clientConfig := testConfig.Clone()
509                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
510                 if err != nil {
511                         return err
512                 }
513                 if err := conn.Handshake(); err != nil {
514                         return err
515                 }
516                 defer conn.Close()
517
518                 if err := conn.CloseWrite(); err != nil {
519                         return fmt.Errorf("client CloseWrite: %v", err)
520                 }
521
522                 if _, err := conn.Write([]byte{0}); err != errShutdown {
523                         return fmt.Errorf("CloseWrite error = %v; want errShutdown", err)
524                 }
525
526                 data, err := ioutil.ReadAll(conn)
527                 if err != nil {
528                         return err
529                 }
530                 if len(data) > 0 {
531                         return fmt.Errorf("Read data = %q; want nothing", data)
532                 }
533                 return nil
534         }
535
536         errChan := make(chan error, 2)
537
538         go func() { errChan <- serverCloseWrite() }()
539         go func() { errChan <- clientCloseWrite() }()
540
541         for i := 0; i < 2; i++ {
542                 select {
543                 case err := <-errChan:
544                         if err != nil {
545                                 t.Fatal(err)
546                         }
547                 case <-time.After(10 * time.Second):
548                         t.Fatal("deadlock")
549                 }
550         }
551
552         // Also test CloseWrite being called before the handshake is
553         // finished:
554         {
555                 ln2 := newLocalListener(t)
556                 defer ln2.Close()
557
558                 netConn, err := net.Dial("tcp", ln2.Addr().String())
559                 if err != nil {
560                         t.Fatal(err)
561                 }
562                 defer netConn.Close()
563                 conn := Client(netConn, testConfig.Clone())
564
565                 if err := conn.CloseWrite(); err != errEarlyCloseWrite {
566                         t.Errorf("CloseWrite error = %v; want errEarlyCloseWrite", err)
567                 }
568         }
569 }
570
571 func TestClone(t *testing.T) {
572         var c1 Config
573         v := reflect.ValueOf(&c1).Elem()
574
575         rnd := rand.New(rand.NewSource(time.Now().Unix()))
576         typ := v.Type()
577         for i := 0; i < typ.NumField(); i++ {
578                 f := v.Field(i)
579                 if !f.CanSet() {
580                         // unexported field; not cloned.
581                         continue
582                 }
583
584                 // testing/quick can't handle functions or interfaces.
585                 fn := typ.Field(i).Name
586                 switch fn {
587                 case "Rand":
588                         f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
589                         continue
590                 case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate":
591                         // DeepEqual can't compare functions.
592                         continue
593                 case "Certificates":
594                         f.Set(reflect.ValueOf([]Certificate{
595                                 {Certificate: [][]byte{{'b'}}},
596                         }))
597                         continue
598                 case "NameToCertificate":
599                         f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
600                         continue
601                 case "RootCAs", "ClientCAs":
602                         f.Set(reflect.ValueOf(x509.NewCertPool()))
603                         continue
604                 case "ClientSessionCache":
605                         f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
606                         continue
607                 case "KeyLogWriter":
608                         f.Set(reflect.ValueOf(io.Writer(os.Stdout)))
609                         continue
610
611                 }
612
613                 q, ok := quick.Value(f.Type(), rnd)
614                 if !ok {
615                         t.Fatalf("quick.Value failed on field %s", fn)
616                 }
617                 f.Set(q)
618         }
619
620         c2 := c1.Clone()
621         // DeepEqual also compares unexported fields, thus c2 needs to have run
622         // serverInit in order to be DeepEqual to c1. Cloning it and discarding
623         // the result is sufficient.
624         c2.Clone()
625
626         if !reflect.DeepEqual(&c1, c2) {
627                 t.Errorf("clone failed to copy a field")
628         }
629 }
630
631 // changeImplConn is a net.Conn which can change its Write and Close
632 // methods.
633 type changeImplConn struct {
634         net.Conn
635         writeFunc func([]byte) (int, error)
636         closeFunc func() error
637 }
638
639 func (w *changeImplConn) Write(p []byte) (n int, err error) {
640         if w.writeFunc != nil {
641                 return w.writeFunc(p)
642         }
643         return w.Conn.Write(p)
644 }
645
646 func (w *changeImplConn) Close() error {
647         if w.closeFunc != nil {
648                 return w.closeFunc()
649         }
650         return w.Conn.Close()
651 }
652
653 func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool) {
654         ln := newLocalListener(b)
655         defer ln.Close()
656
657         N := b.N
658
659         // Less than 64KB because Windows appears to use a TCP rwin < 64KB.
660         // See Issue #15899.
661         const bufsize = 32 << 10
662
663         go func() {
664                 buf := make([]byte, bufsize)
665                 for i := 0; i < N; i++ {
666                         sconn, err := ln.Accept()
667                         if err != nil {
668                                 // panic rather than synchronize to avoid benchmark overhead
669                                 // (cannot call b.Fatal in goroutine)
670                                 panic(fmt.Errorf("accept: %v", err))
671                         }
672                         serverConfig := testConfig.Clone()
673                         serverConfig.CipherSuites = nil // the defaults may prefer faster ciphers
674                         serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
675                         srv := Server(sconn, serverConfig)
676                         if err := srv.Handshake(); err != nil {
677                                 panic(fmt.Errorf("handshake: %v", err))
678                         }
679                         if _, err := io.CopyBuffer(srv, srv, buf); err != nil {
680                                 panic(fmt.Errorf("copy buffer: %v", err))
681                         }
682                 }
683         }()
684
685         b.SetBytes(totalBytes)
686         clientConfig := testConfig.Clone()
687         clientConfig.CipherSuites = nil // the defaults may prefer faster ciphers
688         clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
689
690         buf := make([]byte, bufsize)
691         chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
692         for i := 0; i < N; i++ {
693                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
694                 if err != nil {
695                         b.Fatal(err)
696                 }
697                 for j := 0; j < chunks; j++ {
698                         _, err := conn.Write(buf)
699                         if err != nil {
700                                 b.Fatal(err)
701                         }
702                         _, err = io.ReadFull(conn, buf)
703                         if err != nil {
704                                 b.Fatal(err)
705                         }
706                 }
707                 conn.Close()
708         }
709 }
710
711 func BenchmarkThroughput(b *testing.B) {
712         for _, mode := range []string{"Max", "Dynamic"} {
713                 for size := 1; size <= 64; size <<= 1 {
714                         name := fmt.Sprintf("%sPacket/%dMB", mode, size)
715                         b.Run(name, func(b *testing.B) {
716                                 throughput(b, int64(size<<20), mode == "Max")
717                         })
718                 }
719         }
720 }
721
722 type slowConn struct {
723         net.Conn
724         bps int
725 }
726
727 func (c *slowConn) Write(p []byte) (int, error) {
728         if c.bps == 0 {
729                 panic("too slow")
730         }
731         t0 := time.Now()
732         wrote := 0
733         for wrote < len(p) {
734                 time.Sleep(100 * time.Microsecond)
735                 allowed := int(time.Since(t0).Seconds()*float64(c.bps)) / 8
736                 if allowed > len(p) {
737                         allowed = len(p)
738                 }
739                 if wrote < allowed {
740                         n, err := c.Conn.Write(p[wrote:allowed])
741                         wrote += n
742                         if err != nil {
743                                 return wrote, err
744                         }
745                 }
746         }
747         return len(p), nil
748 }
749
750 func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
751         ln := newLocalListener(b)
752         defer ln.Close()
753
754         N := b.N
755
756         go func() {
757                 for i := 0; i < N; i++ {
758                         sconn, err := ln.Accept()
759                         if err != nil {
760                                 // panic rather than synchronize to avoid benchmark overhead
761                                 // (cannot call b.Fatal in goroutine)
762                                 panic(fmt.Errorf("accept: %v", err))
763                         }
764                         serverConfig := testConfig.Clone()
765                         serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
766                         srv := Server(&slowConn{sconn, bps}, serverConfig)
767                         if err := srv.Handshake(); err != nil {
768                                 panic(fmt.Errorf("handshake: %v", err))
769                         }
770                         io.Copy(srv, srv)
771                 }
772         }()
773
774         clientConfig := testConfig.Clone()
775         clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
776
777         buf := make([]byte, 16384)
778         peek := make([]byte, 1)
779
780         for i := 0; i < N; i++ {
781                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
782                 if err != nil {
783                         b.Fatal(err)
784                 }
785                 // make sure we're connected and previous connection has stopped
786                 if _, err := conn.Write(buf[:1]); err != nil {
787                         b.Fatal(err)
788                 }
789                 if _, err := io.ReadFull(conn, peek); err != nil {
790                         b.Fatal(err)
791                 }
792                 if _, err := conn.Write(buf); err != nil {
793                         b.Fatal(err)
794                 }
795                 if _, err = io.ReadFull(conn, peek); err != nil {
796                         b.Fatal(err)
797                 }
798                 conn.Close()
799         }
800 }
801
802 func BenchmarkLatency(b *testing.B) {
803         for _, mode := range []string{"Max", "Dynamic"} {
804                 for _, kbps := range []int{200, 500, 1000, 2000, 5000} {
805                         name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps)
806                         b.Run(name, func(b *testing.B) {
807                                 latency(b, kbps*1000, mode == "Max")
808                         })
809                 }
810         }
811 }