]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/tls/tls_test.go
crypto/tls: use default cipher suites in BenchmarkThroughput
[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.Fatal(err)
299                         }
300                         serverConfig := testConfig.Clone()
301                         srv := Server(sconn, serverConfig)
302                         if err := srv.Handshake(); err != nil {
303                                 t.Fatal(err)
304                         }
305                         serverTLSUniques <- srv.ConnectionState().TLSUnique
306                 }
307         }()
308
309         clientConfig := testConfig.Clone()
310         clientConfig.ClientSessionCache = NewLRUClientSessionCache(1)
311         conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
312         if err != nil {
313                 t.Fatal(err)
314         }
315         if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
316                 t.Error("client and server channel bindings differ")
317         }
318         conn.Close()
319
320         conn, err = Dial("tcp", ln.Addr().String(), clientConfig)
321         if err != nil {
322                 t.Fatal(err)
323         }
324         defer conn.Close()
325         if !conn.ConnectionState().DidResume {
326                 t.Error("second session did not use resumption")
327         }
328         if !bytes.Equal(conn.ConnectionState().TLSUnique, <-serverTLSUniques) {
329                 t.Error("client and server channel bindings differ when session resumption is used")
330         }
331 }
332
333 func TestVerifyHostname(t *testing.T) {
334         testenv.MustHaveExternalNetwork(t)
335
336         c, err := Dial("tcp", "www.google.com:https", nil)
337         if err != nil {
338                 t.Fatal(err)
339         }
340         if err := c.VerifyHostname("www.google.com"); err != nil {
341                 t.Fatalf("verify www.google.com: %v", err)
342         }
343         if err := c.VerifyHostname("www.yahoo.com"); err == nil {
344                 t.Fatalf("verify www.yahoo.com succeeded")
345         }
346
347         c, err = Dial("tcp", "www.google.com:https", &Config{InsecureSkipVerify: true})
348         if err != nil {
349                 t.Fatal(err)
350         }
351         if err := c.VerifyHostname("www.google.com"); err == nil {
352                 t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
353         }
354         if err := c.VerifyHostname("www.yahoo.com"); err == nil {
355                 t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true")
356         }
357 }
358
359 func TestVerifyHostnameResumed(t *testing.T) {
360         testenv.MustHaveExternalNetwork(t)
361
362         config := &Config{
363                 ClientSessionCache: NewLRUClientSessionCache(32),
364         }
365         for i := 0; i < 2; i++ {
366                 c, err := Dial("tcp", "www.google.com:https", config)
367                 if err != nil {
368                         t.Fatalf("Dial #%d: %v", i, err)
369                 }
370                 cs := c.ConnectionState()
371                 if i > 0 && !cs.DidResume {
372                         t.Fatalf("Subsequent connection unexpectedly didn't resume")
373                 }
374                 if cs.VerifiedChains == nil {
375                         t.Fatalf("Dial #%d: cs.VerifiedChains == nil", i)
376                 }
377                 if err := c.VerifyHostname("www.google.com"); err != nil {
378                         t.Fatalf("verify www.google.com #%d: %v", i, err)
379                 }
380                 c.Close()
381         }
382 }
383
384 func TestConnCloseBreakingWrite(t *testing.T) {
385         ln := newLocalListener(t)
386         defer ln.Close()
387
388         srvCh := make(chan *Conn, 1)
389         var serr error
390         var sconn net.Conn
391         go func() {
392                 var err error
393                 sconn, err = ln.Accept()
394                 if err != nil {
395                         serr = err
396                         srvCh <- nil
397                         return
398                 }
399                 serverConfig := testConfig.Clone()
400                 srv := Server(sconn, serverConfig)
401                 if err := srv.Handshake(); err != nil {
402                         serr = fmt.Errorf("handshake: %v", err)
403                         srvCh <- nil
404                         return
405                 }
406                 srvCh <- srv
407         }()
408
409         cconn, err := net.Dial("tcp", ln.Addr().String())
410         if err != nil {
411                 t.Fatal(err)
412         }
413         defer cconn.Close()
414
415         conn := &changeImplConn{
416                 Conn: cconn,
417         }
418
419         clientConfig := testConfig.Clone()
420         tconn := Client(conn, clientConfig)
421         if err := tconn.Handshake(); err != nil {
422                 t.Fatal(err)
423         }
424
425         srv := <-srvCh
426         if srv == nil {
427                 t.Fatal(serr)
428         }
429         defer sconn.Close()
430
431         connClosed := make(chan struct{})
432         conn.closeFunc = func() error {
433                 close(connClosed)
434                 return nil
435         }
436
437         inWrite := make(chan bool, 1)
438         var errConnClosed = errors.New("conn closed for test")
439         conn.writeFunc = func(p []byte) (n int, err error) {
440                 inWrite <- true
441                 <-connClosed
442                 return 0, errConnClosed
443         }
444
445         closeReturned := make(chan bool, 1)
446         go func() {
447                 <-inWrite
448                 tconn.Close() // test that this doesn't block forever.
449                 closeReturned <- true
450         }()
451
452         _, err = tconn.Write([]byte("foo"))
453         if err != errConnClosed {
454                 t.Errorf("Write error = %v; want errConnClosed", err)
455         }
456
457         <-closeReturned
458         if err := tconn.Close(); err != errClosed {
459                 t.Errorf("Close error = %v; want errClosed", err)
460         }
461 }
462
463 func TestConnCloseWrite(t *testing.T) {
464         ln := newLocalListener(t)
465         defer ln.Close()
466
467         clientDoneChan := make(chan struct{})
468
469         serverCloseWrite := func() error {
470                 sconn, err := ln.Accept()
471                 if err != nil {
472                         return fmt.Errorf("accept: %v", err)
473                 }
474                 defer sconn.Close()
475
476                 serverConfig := testConfig.Clone()
477                 srv := Server(sconn, serverConfig)
478                 if err := srv.Handshake(); err != nil {
479                         return fmt.Errorf("handshake: %v", err)
480                 }
481                 defer srv.Close()
482
483                 data, err := ioutil.ReadAll(srv)
484                 if err != nil {
485                         return err
486                 }
487                 if len(data) > 0 {
488                         return fmt.Errorf("Read data = %q; want nothing", data)
489                 }
490
491                 if err := srv.CloseWrite(); err != nil {
492                         return fmt.Errorf("server CloseWrite: %v", err)
493                 }
494
495                 // Wait for clientCloseWrite to finish, so we know we
496                 // tested the CloseWrite before we defer the
497                 // sconn.Close above, which would also cause the
498                 // client to unblock like CloseWrite.
499                 <-clientDoneChan
500                 return nil
501         }
502
503         clientCloseWrite := func() error {
504                 defer close(clientDoneChan)
505
506                 clientConfig := testConfig.Clone()
507                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
508                 if err != nil {
509                         return err
510                 }
511                 if err := conn.Handshake(); err != nil {
512                         return err
513                 }
514                 defer conn.Close()
515
516                 if err := conn.CloseWrite(); err != nil {
517                         return fmt.Errorf("client CloseWrite: %v", err)
518                 }
519
520                 if _, err := conn.Write([]byte{0}); err != errShutdown {
521                         return fmt.Errorf("CloseWrite error = %v; want errShutdown", err)
522                 }
523
524                 data, err := ioutil.ReadAll(conn)
525                 if err != nil {
526                         return err
527                 }
528                 if len(data) > 0 {
529                         return fmt.Errorf("Read data = %q; want nothing", data)
530                 }
531                 return nil
532         }
533
534         errChan := make(chan error, 2)
535
536         go func() { errChan <- serverCloseWrite() }()
537         go func() { errChan <- clientCloseWrite() }()
538
539         for i := 0; i < 2; i++ {
540                 select {
541                 case err := <-errChan:
542                         if err != nil {
543                                 t.Fatal(err)
544                         }
545                 case <-time.After(10 * time.Second):
546                         t.Fatal("deadlock")
547                 }
548         }
549
550         // Also test CloseWrite being called before the handshake is
551         // finished:
552         {
553                 ln2 := newLocalListener(t)
554                 defer ln2.Close()
555
556                 netConn, err := net.Dial("tcp", ln2.Addr().String())
557                 if err != nil {
558                         t.Fatal(err)
559                 }
560                 defer netConn.Close()
561                 conn := Client(netConn, testConfig.Clone())
562
563                 if err := conn.CloseWrite(); err != errEarlyCloseWrite {
564                         t.Errorf("CloseWrite error = %v; want errEarlyCloseWrite", err)
565                 }
566         }
567 }
568
569 func TestClone(t *testing.T) {
570         var c1 Config
571         v := reflect.ValueOf(&c1).Elem()
572
573         rnd := rand.New(rand.NewSource(time.Now().Unix()))
574         typ := v.Type()
575         for i := 0; i < typ.NumField(); i++ {
576                 f := v.Field(i)
577                 if !f.CanSet() {
578                         // unexported field; not cloned.
579                         continue
580                 }
581
582                 // testing/quick can't handle functions or interfaces.
583                 fn := typ.Field(i).Name
584                 switch fn {
585                 case "Rand":
586                         f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
587                         continue
588                 case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate":
589                         // DeepEqual can't compare functions.
590                         continue
591                 case "Certificates":
592                         f.Set(reflect.ValueOf([]Certificate{
593                                 {Certificate: [][]byte{{'b'}}},
594                         }))
595                         continue
596                 case "NameToCertificate":
597                         f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
598                         continue
599                 case "RootCAs", "ClientCAs":
600                         f.Set(reflect.ValueOf(x509.NewCertPool()))
601                         continue
602                 case "ClientSessionCache":
603                         f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
604                         continue
605                 case "KeyLogWriter":
606                         f.Set(reflect.ValueOf(io.Writer(os.Stdout)))
607                         continue
608
609                 }
610
611                 q, ok := quick.Value(f.Type(), rnd)
612                 if !ok {
613                         t.Fatalf("quick.Value failed on field %s", fn)
614                 }
615                 f.Set(q)
616         }
617
618         c2 := c1.Clone()
619         // DeepEqual also compares unexported fields, thus c2 needs to have run
620         // serverInit in order to be DeepEqual to c1. Cloning it and discarding
621         // the result is sufficient.
622         c2.Clone()
623
624         if !reflect.DeepEqual(&c1, c2) {
625                 t.Errorf("clone failed to copy a field")
626         }
627 }
628
629 // changeImplConn is a net.Conn which can change its Write and Close
630 // methods.
631 type changeImplConn struct {
632         net.Conn
633         writeFunc func([]byte) (int, error)
634         closeFunc func() error
635 }
636
637 func (w *changeImplConn) Write(p []byte) (n int, err error) {
638         if w.writeFunc != nil {
639                 return w.writeFunc(p)
640         }
641         return w.Conn.Write(p)
642 }
643
644 func (w *changeImplConn) Close() error {
645         if w.closeFunc != nil {
646                 return w.closeFunc()
647         }
648         return w.Conn.Close()
649 }
650
651 func throughput(b *testing.B, totalBytes int64, dynamicRecordSizingDisabled bool) {
652         ln := newLocalListener(b)
653         defer ln.Close()
654
655         N := b.N
656
657         // Less than 64KB because Windows appears to use a TCP rwin < 64KB.
658         // See Issue #15899.
659         const bufsize = 32 << 10
660
661         go func() {
662                 buf := make([]byte, bufsize)
663                 for i := 0; i < N; i++ {
664                         sconn, err := ln.Accept()
665                         if err != nil {
666                                 // panic rather than synchronize to avoid benchmark overhead
667                                 // (cannot call b.Fatal in goroutine)
668                                 panic(fmt.Errorf("accept: %v", err))
669                         }
670                         serverConfig := testConfig.Clone()
671                         serverConfig.CipherSuites = nil // the defaults may prefer faster ciphers
672                         serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
673                         srv := Server(sconn, serverConfig)
674                         if err := srv.Handshake(); err != nil {
675                                 panic(fmt.Errorf("handshake: %v", err))
676                         }
677                         if _, err := io.CopyBuffer(srv, srv, buf); err != nil {
678                                 panic(fmt.Errorf("copy buffer: %v", err))
679                         }
680                 }
681         }()
682
683         b.SetBytes(totalBytes)
684         clientConfig := testConfig.Clone()
685         clientConfig.CipherSuites = nil // the defaults may prefer faster ciphers
686         clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
687
688         buf := make([]byte, bufsize)
689         chunks := int(math.Ceil(float64(totalBytes) / float64(len(buf))))
690         for i := 0; i < N; i++ {
691                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
692                 if err != nil {
693                         b.Fatal(err)
694                 }
695                 for j := 0; j < chunks; j++ {
696                         _, err := conn.Write(buf)
697                         if err != nil {
698                                 b.Fatal(err)
699                         }
700                         _, err = io.ReadFull(conn, buf)
701                         if err != nil {
702                                 b.Fatal(err)
703                         }
704                 }
705                 conn.Close()
706         }
707 }
708
709 func BenchmarkThroughput(b *testing.B) {
710         for _, mode := range []string{"Max", "Dynamic"} {
711                 for size := 1; size <= 64; size <<= 1 {
712                         name := fmt.Sprintf("%sPacket/%dMB", mode, size)
713                         b.Run(name, func(b *testing.B) {
714                                 throughput(b, int64(size<<20), mode == "Max")
715                         })
716                 }
717         }
718 }
719
720 type slowConn struct {
721         net.Conn
722         bps int
723 }
724
725 func (c *slowConn) Write(p []byte) (int, error) {
726         if c.bps == 0 {
727                 panic("too slow")
728         }
729         t0 := time.Now()
730         wrote := 0
731         for wrote < len(p) {
732                 time.Sleep(100 * time.Microsecond)
733                 allowed := int(time.Since(t0).Seconds()*float64(c.bps)) / 8
734                 if allowed > len(p) {
735                         allowed = len(p)
736                 }
737                 if wrote < allowed {
738                         n, err := c.Conn.Write(p[wrote:allowed])
739                         wrote += n
740                         if err != nil {
741                                 return wrote, err
742                         }
743                 }
744         }
745         return len(p), nil
746 }
747
748 func latency(b *testing.B, bps int, dynamicRecordSizingDisabled bool) {
749         ln := newLocalListener(b)
750         defer ln.Close()
751
752         N := b.N
753
754         go func() {
755                 for i := 0; i < N; i++ {
756                         sconn, err := ln.Accept()
757                         if err != nil {
758                                 // panic rather than synchronize to avoid benchmark overhead
759                                 // (cannot call b.Fatal in goroutine)
760                                 panic(fmt.Errorf("accept: %v", err))
761                         }
762                         serverConfig := testConfig.Clone()
763                         serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
764                         srv := Server(&slowConn{sconn, bps}, serverConfig)
765                         if err := srv.Handshake(); err != nil {
766                                 panic(fmt.Errorf("handshake: %v", err))
767                         }
768                         io.Copy(srv, srv)
769                 }
770         }()
771
772         clientConfig := testConfig.Clone()
773         clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled
774
775         buf := make([]byte, 16384)
776         peek := make([]byte, 1)
777
778         for i := 0; i < N; i++ {
779                 conn, err := Dial("tcp", ln.Addr().String(), clientConfig)
780                 if err != nil {
781                         b.Fatal(err)
782                 }
783                 // make sure we're connected and previous connection has stopped
784                 if _, err := conn.Write(buf[:1]); err != nil {
785                         b.Fatal(err)
786                 }
787                 if _, err := io.ReadFull(conn, peek); err != nil {
788                         b.Fatal(err)
789                 }
790                 if _, err := conn.Write(buf); err != nil {
791                         b.Fatal(err)
792                 }
793                 if _, err = io.ReadFull(conn, peek); err != nil {
794                         b.Fatal(err)
795                 }
796                 conn.Close()
797         }
798 }
799
800 func BenchmarkLatency(b *testing.B) {
801         for _, mode := range []string{"Max", "Dynamic"} {
802                 for _, kbps := range []int{200, 500, 1000, 2000, 5000} {
803                         name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps)
804                         b.Run(name, func(b *testing.B) {
805                                 latency(b, kbps*1000, mode == "Max")
806                         })
807                 }
808         }
809 }