blob: 0b210cd6f54052e6089da39fe51e05bdf66c5582 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001package main
2
3import (
4 "bytes"
5 "flag"
6 "fmt"
7 "io"
8 "net"
9 "os"
10 "os/exec"
11 "strings"
12 "sync"
13 "syscall"
14)
15
16var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
17
David Benjamin025b3d32014-07-01 19:53:04 -040018const (
19 rsaCertificateFile = "cert.pem"
20 ecdsaCertificateFile = "ecdsa_cert.pem"
21)
22
23const (
24 rsaKeyFile = "key.pem"
25 ecdsaKeyFile = "ecdsa_key.pem"
26)
27
Adam Langley95c29f32014-06-20 12:00:00 -070028var rsaCertificate, ecdsaCertificate Certificate
29
30func initCertificates() {
31 var err error
David Benjamin025b3d32014-07-01 19:53:04 -040032 rsaCertificate, err = LoadX509KeyPair(rsaCertificateFile, rsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070033 if err != nil {
34 panic(err)
35 }
36
David Benjamin025b3d32014-07-01 19:53:04 -040037 ecdsaCertificate, err = LoadX509KeyPair(ecdsaCertificateFile, ecdsaKeyFile)
Adam Langley95c29f32014-06-20 12:00:00 -070038 if err != nil {
39 panic(err)
40 }
41}
42
43var certificateOnce sync.Once
44
45func getRSACertificate() Certificate {
46 certificateOnce.Do(initCertificates)
47 return rsaCertificate
48}
49
50func getECDSACertificate() Certificate {
51 certificateOnce.Do(initCertificates)
52 return ecdsaCertificate
53}
54
David Benjamin025b3d32014-07-01 19:53:04 -040055type testType int
56
57const (
58 clientTest testType = iota
59 serverTest
60)
61
Adam Langley95c29f32014-06-20 12:00:00 -070062type testCase struct {
David Benjamin025b3d32014-07-01 19:53:04 -040063 testType testType
Adam Langley95c29f32014-06-20 12:00:00 -070064 name string
65 config Config
66 shouldFail bool
67 expectedError string
Adam Langleyac61fa32014-06-23 12:03:11 -070068 // expectedLocalError, if not empty, contains a substring that must be
69 // found in the local error.
70 expectedLocalError string
Adam Langley80842bd2014-06-20 12:00:00 -070071 // messageLen is the length, in bytes, of the test message that will be
72 // sent.
73 messageLen int
David Benjamin025b3d32014-07-01 19:53:04 -040074 // certFile is the path to the certificate to use for the server.
75 certFile string
76 // keyFile is the path to the private key to use for the server.
77 keyFile string
David Benjamin325b5c32014-07-01 19:40:31 -040078 // flags, if not empty, contains a list of command-line flags that will
79 // be passed to the shim program.
80 flags []string
Adam Langley95c29f32014-06-20 12:00:00 -070081}
82
David Benjamin025b3d32014-07-01 19:53:04 -040083var testCases = []testCase{
Adam Langley95c29f32014-06-20 12:00:00 -070084 {
85 name: "BadRSASignature",
86 config: Config{
87 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
88 Bugs: ProtocolBugs{
89 InvalidSKXSignature: true,
90 },
91 },
92 shouldFail: true,
93 expectedError: ":BAD_SIGNATURE:",
94 },
95 {
96 name: "BadECDSASignature",
97 config: Config{
98 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
99 Bugs: ProtocolBugs{
100 InvalidSKXSignature: true,
101 },
102 Certificates: []Certificate{getECDSACertificate()},
103 },
104 shouldFail: true,
105 expectedError: ":BAD_SIGNATURE:",
106 },
107 {
108 name: "BadECDSACurve",
109 config: Config{
110 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
111 Bugs: ProtocolBugs{
112 InvalidSKXCurve: true,
113 },
114 Certificates: []Certificate{getECDSACertificate()},
115 },
116 shouldFail: true,
117 expectedError: ":WRONG_CURVE:",
118 },
Adam Langleyac61fa32014-06-23 12:03:11 -0700119 {
David Benjamin325b5c32014-07-01 19:40:31 -0400120 name: "NoFallbackSCSV",
Adam Langleyac61fa32014-06-23 12:03:11 -0700121 config: Config{
122 Bugs: ProtocolBugs{
123 FailIfNotFallbackSCSV: true,
124 },
125 },
126 shouldFail: true,
127 expectedLocalError: "no fallback SCSV found",
128 },
David Benjamin325b5c32014-07-01 19:40:31 -0400129 {
130 name: "FallbackSCSV",
131 config: Config{
132 Bugs: ProtocolBugs{
133 FailIfNotFallbackSCSV: true,
134 },
135 },
136 flags: []string{"-fallback-scsv"},
137 },
David Benjamin197b3ab2014-07-02 18:37:33 -0400138 {
139 testType: serverTest,
David Benjamin35a7a442014-07-05 00:23:20 -0400140 name: "ServerNameExtension",
David Benjamin197b3ab2014-07-02 18:37:33 -0400141 config: Config{
142 ServerName: "example.com",
143 },
144 flags: []string{"-expect-server-name", "example.com"},
145 },
David Benjamin35a7a442014-07-05 00:23:20 -0400146 {
147 testType: clientTest,
148 name: "DuplicateExtensionClient",
149 config: Config{
150 Bugs: ProtocolBugs{
151 DuplicateExtension: true,
152 },
153 },
154 shouldFail: true,
155 expectedLocalError: "remote error: error decoding message",
156 },
157 {
158 testType: serverTest,
159 name: "DuplicateExtensionServer",
160 config: Config{
161 Bugs: ProtocolBugs{
162 DuplicateExtension: true,
163 },
164 },
165 shouldFail: true,
166 expectedLocalError: "remote error: error decoding message",
167 },
David Benjamin7b030512014-07-08 17:30:11 -0400168 {
169 name: "ClientCertificateTypes",
170 config: Config{
171 ClientAuth: RequestClientCert,
172 ClientCertificateTypes: []byte{
173 CertTypeDSSSign,
174 CertTypeRSASign,
175 CertTypeECDSASign,
176 },
177 },
178 flags: []string{"-expect-certificate-types", string([]byte{
179 CertTypeDSSSign,
180 CertTypeRSASign,
181 CertTypeECDSASign,
182 })},
183 },
David Benjamin636293b2014-07-08 17:59:18 -0400184 {
185 name: "NoClientCertificate",
186 config: Config{
187 ClientAuth: RequireAnyClientCert,
188 },
189 shouldFail: true,
190 expectedLocalError: "client didn't provide a certificate",
191 },
David Benjamin1c375dd2014-07-12 00:48:23 -0400192 {
193 name: "UnauthenticatedECDH",
194 config: Config{
195 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
196 Bugs: ProtocolBugs{
197 UnauthenticatedECDH: true,
198 },
199 },
200 shouldFail: true,
201 expectedError: ":MISSING_RSA_SIGNING_CERT:",
202 },
Adam Langley95c29f32014-06-20 12:00:00 -0700203}
204
Adam Langley80842bd2014-06-20 12:00:00 -0700205func doExchange(tlsConn *Conn, messageLen int) error {
Adam Langley95c29f32014-06-20 12:00:00 -0700206 if err := tlsConn.Handshake(); err != nil {
207 return err
208 }
Adam Langley80842bd2014-06-20 12:00:00 -0700209 if messageLen == 0 {
210 messageLen = 32
211 }
212 testMessage := make([]byte, messageLen)
213 for i := range testMessage {
214 testMessage[i] = 0x42
215 }
Adam Langley95c29f32014-06-20 12:00:00 -0700216 tlsConn.Write(testMessage)
217
218 buf := make([]byte, len(testMessage))
219 _, err := io.ReadFull(tlsConn, buf)
220 if err != nil {
221 return err
222 }
223
224 for i, v := range buf {
225 if v != testMessage[i]^0xff {
226 return fmt.Errorf("bad reply contents at byte %d", i)
227 }
228 }
229
230 return nil
231}
232
David Benjamin325b5c32014-07-01 19:40:31 -0400233func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
234 valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
Adam Langley95c29f32014-06-20 12:00:00 -0700235 if dbAttach {
David Benjamin325b5c32014-07-01 19:40:31 -0400236 valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
Adam Langley95c29f32014-06-20 12:00:00 -0700237 }
David Benjamin325b5c32014-07-01 19:40:31 -0400238 valgrindArgs = append(valgrindArgs, path)
239 valgrindArgs = append(valgrindArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700240
David Benjamin325b5c32014-07-01 19:40:31 -0400241 return exec.Command("valgrind", valgrindArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700242}
243
David Benjamin325b5c32014-07-01 19:40:31 -0400244func gdbOf(path string, args ...string) *exec.Cmd {
245 xtermArgs := []string{"-e", "gdb", "--args"}
246 xtermArgs = append(xtermArgs, path)
247 xtermArgs = append(xtermArgs, args...)
Adam Langley95c29f32014-06-20 12:00:00 -0700248
David Benjamin325b5c32014-07-01 19:40:31 -0400249 return exec.Command("xterm", xtermArgs...)
Adam Langley95c29f32014-06-20 12:00:00 -0700250}
251
252func runTest(test *testCase) error {
253 socks, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)
254 if err != nil {
255 panic(err)
256 }
257
258 syscall.CloseOnExec(socks[0])
259 syscall.CloseOnExec(socks[1])
David Benjamin025b3d32014-07-01 19:53:04 -0400260 shimEnd := os.NewFile(uintptr(socks[0]), "shim end")
Adam Langley95c29f32014-06-20 12:00:00 -0700261 connFile := os.NewFile(uintptr(socks[1]), "our end")
262 conn, err := net.FileConn(connFile)
263 connFile.Close()
264 if err != nil {
265 panic(err)
266 }
267
David Benjamin025b3d32014-07-01 19:53:04 -0400268 const shim_path = "../../../build/ssl/test/bssl_shim"
269 flags := []string{}
270 if test.testType == clientTest {
271 flags = append(flags, "client")
Adam Langley95c29f32014-06-20 12:00:00 -0700272 } else {
David Benjamin025b3d32014-07-01 19:53:04 -0400273 flags = append(flags, "server")
Adam Langley95c29f32014-06-20 12:00:00 -0700274
David Benjamin025b3d32014-07-01 19:53:04 -0400275 flags = append(flags, "-key-file")
276 if test.keyFile == "" {
277 flags = append(flags, rsaKeyFile)
278 } else {
279 flags = append(flags, test.keyFile)
280 }
281
282 flags = append(flags, "-cert-file")
283 if test.certFile == "" {
284 flags = append(flags, rsaCertificateFile)
285 } else {
286 flags = append(flags, test.certFile)
287 }
288 }
289 flags = append(flags, test.flags...)
290
291 var shim *exec.Cmd
292 if *useValgrind {
293 shim = valgrindOf(false, shim_path, flags...)
294 } else {
295 shim = exec.Command(shim_path, flags...)
296 }
297 // shim = gdbOf(shim_path, flags...)
298 shim.ExtraFiles = []*os.File{shimEnd}
299 shim.Stdin = os.Stdin
300 var stdoutBuf, stderrBuf bytes.Buffer
301 shim.Stdout = &stdoutBuf
302 shim.Stderr = &stderrBuf
303
304 if err := shim.Start(); err != nil {
Adam Langley95c29f32014-06-20 12:00:00 -0700305 panic(err)
306 }
David Benjamin025b3d32014-07-01 19:53:04 -0400307 shimEnd.Close()
Adam Langley95c29f32014-06-20 12:00:00 -0700308
309 config := test.config
Adam Langley95c29f32014-06-20 12:00:00 -0700310
David Benjamin025b3d32014-07-01 19:53:04 -0400311 var tlsConn *Conn
312 if test.testType == clientTest {
313 if len(config.Certificates) == 0 {
314 config.Certificates = []Certificate{getRSACertificate()}
315 }
316 tlsConn = Server(conn, &config)
317 } else {
318 config.InsecureSkipVerify = true
319 tlsConn = Client(conn, &config)
320 }
Adam Langley80842bd2014-06-20 12:00:00 -0700321 err = doExchange(tlsConn, test.messageLen)
Adam Langley95c29f32014-06-20 12:00:00 -0700322
323 conn.Close()
David Benjamin025b3d32014-07-01 19:53:04 -0400324 childErr := shim.Wait()
Adam Langley95c29f32014-06-20 12:00:00 -0700325
326 stdout := string(stdoutBuf.Bytes())
327 stderr := string(stderrBuf.Bytes())
328 failed := err != nil || childErr != nil
329 correctFailure := len(test.expectedError) == 0 || strings.Contains(stdout, test.expectedError)
Adam Langleyac61fa32014-06-23 12:03:11 -0700330 localError := "none"
331 if err != nil {
332 localError = err.Error()
333 }
334 if len(test.expectedLocalError) != 0 {
335 correctFailure = correctFailure && strings.Contains(localError, test.expectedLocalError)
336 }
Adam Langley95c29f32014-06-20 12:00:00 -0700337
338 if failed != test.shouldFail || failed && !correctFailure {
Adam Langley95c29f32014-06-20 12:00:00 -0700339 childError := "none"
Adam Langley95c29f32014-06-20 12:00:00 -0700340 if childErr != nil {
341 childError = childErr.Error()
342 }
343
344 var msg string
345 switch {
346 case failed && !test.shouldFail:
347 msg = "unexpected failure"
348 case !failed && test.shouldFail:
349 msg = "unexpected success"
350 case failed && !correctFailure:
Adam Langleyac61fa32014-06-23 12:03:11 -0700351 msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
Adam Langley95c29f32014-06-20 12:00:00 -0700352 default:
353 panic("internal error")
354 }
355
356 return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, string(stdoutBuf.Bytes()), stderr)
357 }
358
359 if !*useValgrind && len(stderr) > 0 {
360 println(stderr)
361 }
362
363 return nil
364}
365
366var tlsVersions = []struct {
367 name string
368 version uint16
369}{
370 {"SSL3", VersionSSL30},
371 {"TLS1", VersionTLS10},
372 {"TLS11", VersionTLS11},
373 {"TLS12", VersionTLS12},
374}
375
376var testCipherSuites = []struct {
377 name string
378 id uint16
379}{
380 {"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
381 {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
382 {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
383 {"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
384 {"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
385 {"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
386 {"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
387 {"ECDHE-RSA-3DES-SHA", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA},
388 {"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
389 {"ECDHE-RSA-AES256-GCM", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
390 {"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
391 {"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
392 {"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
393 {"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
394 {"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
395}
396
397func addCipherSuiteTests() {
398 for _, suite := range testCipherSuites {
399 var cert Certificate
David Benjamin025b3d32014-07-01 19:53:04 -0400400 var certFile string
401 var keyFile string
Adam Langley95c29f32014-06-20 12:00:00 -0700402 if strings.Contains(suite.name, "ECDSA") {
403 cert = getECDSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400404 certFile = ecdsaCertificateFile
405 keyFile = ecdsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700406 } else {
407 cert = getRSACertificate()
David Benjamin025b3d32014-07-01 19:53:04 -0400408 certFile = rsaCertificateFile
409 keyFile = rsaKeyFile
Adam Langley95c29f32014-06-20 12:00:00 -0700410 }
411
412 for _, ver := range tlsVersions {
413 if ver.version != VersionTLS12 && strings.HasSuffix(suite.name, "-GCM") {
414 continue
415 }
416
David Benjamin025b3d32014-07-01 19:53:04 -0400417 testCases = append(testCases, testCase{
418 testType: clientTest,
419 name: ver.name + "-" + suite.name + "-client",
Adam Langley95c29f32014-06-20 12:00:00 -0700420 config: Config{
421 MinVersion: ver.version,
422 MaxVersion: ver.version,
423 CipherSuites: []uint16{suite.id},
424 Certificates: []Certificate{cert},
425 },
426 })
David Benjamin025b3d32014-07-01 19:53:04 -0400427
428 // Go's TLS implementation implements SSLv3 as a server,
429 // but not as a client.
430 //
431 // TODO(davidben): Implement SSLv3 as a client too to
432 // exercise that code.
433 if ver.version != VersionSSL30 {
434 testCases = append(testCases, testCase{
435 testType: serverTest,
436 name: ver.name + "-" + suite.name + "-server",
437 config: Config{
438 MinVersion: ver.version,
439 MaxVersion: ver.version,
440 CipherSuites: []uint16{suite.id},
441 Certificates: []Certificate{cert},
442 },
443 certFile: certFile,
444 keyFile: keyFile,
445 })
446 }
Adam Langley95c29f32014-06-20 12:00:00 -0700447 }
448 }
449}
450
451func addBadECDSASignatureTests() {
452 for badR := BadValue(1); badR < NumBadValues; badR++ {
453 for badS := BadValue(1); badS < NumBadValues; badS++ {
David Benjamin025b3d32014-07-01 19:53:04 -0400454 testCases = append(testCases, testCase{
Adam Langley95c29f32014-06-20 12:00:00 -0700455 name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
456 config: Config{
457 CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
458 Certificates: []Certificate{getECDSACertificate()},
459 Bugs: ProtocolBugs{
460 BadECDSAR: badR,
461 BadECDSAS: badS,
462 },
463 },
464 shouldFail: true,
465 expectedError: "SIGNATURE",
466 })
467 }
468 }
469}
470
Adam Langley80842bd2014-06-20 12:00:00 -0700471func addCBCPaddingTests() {
David Benjamin025b3d32014-07-01 19:53:04 -0400472 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700473 name: "MaxCBCPadding",
474 config: Config{
475 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
476 Bugs: ProtocolBugs{
477 MaxPadding: true,
478 },
479 },
480 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
481 })
David Benjamin025b3d32014-07-01 19:53:04 -0400482 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700483 name: "BadCBCPadding",
484 config: Config{
485 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
486 Bugs: ProtocolBugs{
487 PaddingFirstByteBad: true,
488 },
489 },
490 shouldFail: true,
491 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
492 })
493 // OpenSSL previously had an issue where the first byte of padding in
494 // 255 bytes of padding wasn't checked.
David Benjamin025b3d32014-07-01 19:53:04 -0400495 testCases = append(testCases, testCase{
Adam Langley80842bd2014-06-20 12:00:00 -0700496 name: "BadCBCPadding255",
497 config: Config{
498 CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
499 Bugs: ProtocolBugs{
500 MaxPadding: true,
501 PaddingFirstByteBadIf255: true,
502 },
503 },
504 messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
505 shouldFail: true,
506 expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
507 })
508}
509
David Benjamin636293b2014-07-08 17:59:18 -0400510func addClientAuthTests() {
511 for _, ver := range tlsVersions {
512 if ver.version == VersionSSL30 {
513 // TODO(davidben): The Go implementation does not
514 // correctly compute CertificateVerify hashes for SSLv3.
515 continue
516 }
517
518 var cipherSuites []uint16
519 if ver.version >= VersionTLS12 {
520 // Pick a SHA-256 cipher suite. The Go implementation
521 // does not correctly handle client auth with a SHA-384
522 // cipher suite.
523 cipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
524 }
525
526 testCases = append(testCases, testCase{
527 testType: clientTest,
528 name: ver.name + "-ClientAuth-RSA",
529 config: Config{
530 MinVersion: ver.version,
531 MaxVersion: ver.version,
532 CipherSuites: cipherSuites,
533 ClientAuth: RequireAnyClientCert,
534 },
535 flags: []string{
536 "-cert-file", rsaCertificateFile,
537 "-key-file", rsaKeyFile,
538 },
539 })
540 testCases = append(testCases, testCase{
541 testType: clientTest,
542 name: ver.name + "-ClientAuth-ECDSA",
543 config: Config{
544 MinVersion: ver.version,
545 MaxVersion: ver.version,
546 CipherSuites: cipherSuites,
547 ClientAuth: RequireAnyClientCert,
548 },
549 flags: []string{
550 "-cert-file", ecdsaCertificateFile,
551 "-key-file", ecdsaKeyFile,
552 },
553 })
554 }
555}
556
Adam Langley95c29f32014-06-20 12:00:00 -0700557func worker(statusChan chan statusMsg, c chan *testCase, wg *sync.WaitGroup) {
558 defer wg.Done()
559
560 for test := range c {
561 statusChan <- statusMsg{test: test, started: true}
562 err := runTest(test)
563 statusChan <- statusMsg{test: test, err: err}
564 }
565}
566
567type statusMsg struct {
568 test *testCase
569 started bool
570 err error
571}
572
573func statusPrinter(doneChan chan struct{}, statusChan chan statusMsg, total int) {
574 var started, done, failed, lineLen int
575 defer close(doneChan)
576
577 for msg := range statusChan {
578 if msg.started {
579 started++
580 } else {
581 done++
582 }
583
584 fmt.Printf("\x1b[%dD\x1b[K", lineLen)
585
586 if msg.err != nil {
587 fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
588 failed++
589 }
590 line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
591 lineLen = len(line)
592 os.Stdout.WriteString(line)
593 }
594}
595
596func main() {
597 var flagTest *string = flag.String("test", "", "The name of a test to run, or empty to run all tests")
598
599 flag.Parse()
600
601 addCipherSuiteTests()
602 addBadECDSASignatureTests()
Adam Langley80842bd2014-06-20 12:00:00 -0700603 addCBCPaddingTests()
David Benjamin636293b2014-07-08 17:59:18 -0400604 addClientAuthTests()
Adam Langley95c29f32014-06-20 12:00:00 -0700605
606 var wg sync.WaitGroup
607
608 const numWorkers = 64
609
610 statusChan := make(chan statusMsg, numWorkers)
611 testChan := make(chan *testCase, numWorkers)
612 doneChan := make(chan struct{})
613
David Benjamin025b3d32014-07-01 19:53:04 -0400614 go statusPrinter(doneChan, statusChan, len(testCases))
Adam Langley95c29f32014-06-20 12:00:00 -0700615
616 for i := 0; i < numWorkers; i++ {
617 wg.Add(1)
618 go worker(statusChan, testChan, &wg)
619 }
620
David Benjamin025b3d32014-07-01 19:53:04 -0400621 for i := range testCases {
622 if len(*flagTest) == 0 || *flagTest == testCases[i].name {
623 testChan <- &testCases[i]
Adam Langley95c29f32014-06-20 12:00:00 -0700624 }
625 }
626
627 close(testChan)
628 wg.Wait()
629 close(statusChan)
630 <-doneChan
631
632 fmt.Printf("\n")
633}