Add tests for packed handshake records in TLS.

I'm surprised we'd never tested this. In addition to splitting handshake
records up, one may pack multiple handshakes into a single record, as
they fit. Generalize the DTLS handshake flush hook to do this in TLS as
well.

Change-Id: Ia546d18c7c56ba45e50f489c5b53e1fcd6404f51
Reviewed-on: https://boringssl-review.googlesource.com/8650
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 7596485..b8f7088 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -2918,10 +2918,39 @@
 	}
 }
 
+type stateMachineTestConfig struct {
+	protocol                            protocol
+	async                               bool
+	splitHandshake, packHandshakeFlight bool
+}
+
 // Adds tests that try to cover the range of the handshake state machine, under
 // various conditions. Some of these are redundant with other tests, but they
 // only cover the synchronous case.
-func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
+func addAllStateMachineCoverageTests() {
+	for _, async := range []bool{false, true} {
+		for _, protocol := range []protocol{tls, dtls} {
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol: protocol,
+				async:    async,
+			})
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol:       protocol,
+				async:          async,
+				splitHandshake: true,
+			})
+			if protocol == tls {
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:            protocol,
+					async:               async,
+					packHandshakeFlight: true,
+				})
+			}
+		}
+	}
+}
+
+func addStateMachineCoverageTests(config stateMachineTestConfig) {
 	var tests []testCase
 
 	// Basic handshake, with resumption. Client and server,
@@ -3024,7 +3053,7 @@
 		// Setting SSL_VERIFY_PEER allows anonymous clients.
 		flags: []string{"-verify-peer"},
 	})
-	if protocol == tls {
+	if config.protocol == tls {
 		tests = append(tests, testCase{
 			testType: clientTest,
 			name:     "ClientAuth-NoCertificate-Client-SSL3",
@@ -3247,7 +3276,7 @@
 		},
 	})
 
-	if protocol == tls {
+	if config.protocol == tls {
 		tests = append(tests, testCase{
 			name: "Renegotiate-Client",
 			config: Config{
@@ -3486,24 +3515,28 @@
 	}
 
 	for _, test := range tests {
-		test.protocol = protocol
-		if protocol == dtls {
+		test.protocol = config.protocol
+		if config.protocol == dtls {
 			test.name += "-DTLS"
 		}
-		if async {
+		if config.async {
 			test.name += "-Async"
 			test.flags = append(test.flags, "-async")
 		} else {
 			test.name += "-Sync"
 		}
-		if splitHandshake {
+		if config.splitHandshake {
 			test.name += "-SplitHandshakeRecords"
 			test.config.Bugs.MaxHandshakeRecordLength = 1
-			if protocol == dtls {
+			if config.protocol == dtls {
 				test.config.Bugs.MaxPacketLength = 256
 				test.flags = append(test.flags, "-mtu", "256")
 			}
 		}
+		if config.packHandshakeFlight {
+			test.name += "-PackHandshakeFlight"
+			test.config.Bugs.PackHandshakeFlight = true
+		}
 		testCases = append(testCases, test)
 	}
 }
@@ -5856,13 +5889,7 @@
 	addCECPQ1Tests()
 	addKeyExchangeInfoTests()
 	addTLS13RecordTests()
-	for _, async := range []bool{false, true} {
-		for _, splitHandshake := range []bool{false, true} {
-			for _, protocol := range []protocol{tls, dtls} {
-				addStateMachineCoverageTests(async, splitHandshake, protocol)
-			}
-		}
-	}
+	addAllStateMachineCoverageTests()
 
 	var wg sync.WaitGroup