Add a test to ensure False Start occurs.

This adds the missing test coverage for
7e3305eebd7fb06d57e7f25b3bbf9c10d526f7d5.

Change-Id: I8c9f1dc998afa9bb1f6fb2a7872a651037bb4844
Reviewed-on: https://boringssl-review.googlesource.com/1610
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 8c1e75e..8955324 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -470,6 +470,12 @@
       }
     }
   } else {
+    if (config->shim_writes_first) {
+      int w;
+      do {
+        w = SSL_write(ssl, "hello", 5);
+      } while (config->async && retry_async(ssl, w, bio));
+    }
     for (;;) {
       uint8_t buf[512];
       int n;
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index daeeb5e..0dcb084 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -434,6 +434,12 @@
 	// SkipHelloVerifyRequest causes a DTLS server to skip the
 	// HelloVerifyRequest message.
 	SkipHelloVerifyRequest bool
+
+	// ExpectFalseStart causes the server to, on full handshakes,
+	// expect the peer to False Start; the server Finished message
+	// isn't sent until we receive an application data record
+	// from the peer.
+	ExpectFalseStart bool
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 2c5e920..47b6e61 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -660,7 +660,7 @@
 			return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
 		}
 	case recordTypeApplicationData:
-		if !c.handshakeComplete {
+		if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart {
 			c.sendAlert(alertInternalError)
 			return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
 		}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 40e1b88..72fa502 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -87,6 +87,11 @@
 		if err := hs.readFinished(isResume); err != nil {
 			return err
 		}
+		if c.config.Bugs.ExpectFalseStart {
+			if err := c.readRecord(recordTypeApplicationData); err != nil {
+				return err
+			}
+		}
 		if err := hs.sendSessionTicket(); err != nil {
 			return err
 		}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 72e8cce..9645f70 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -126,6 +126,9 @@
 	// sendPrefix sends a prefix on the socket before actually performing a
 	// handshake.
 	sendPrefix string
+	// shimWritesFirst controls whether the shim sends an initial "hello"
+	// message before doing a roundtrip with the runner.
+	shimWritesFirst bool
 	// flags, if not empty, contains a list of command-line flags that will
 	// be passed to the shim program.
 	flags []string
@@ -529,6 +532,17 @@
 		}
 	}
 
+	if test.shimWritesFirst {
+		var buf [5]byte
+		_, err := io.ReadFull(tlsConn, buf[:])
+		if err != nil {
+			return err
+		}
+		if string(buf[:]) != "hello" {
+			return fmt.Errorf("bad initial message")
+		}
+	}
+
 	if messageLen < 0 {
 		if test.protocol == dtls {
 			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
@@ -646,6 +660,10 @@
 		flags = append(flags, "-resume")
 	}
 
+	if test.shimWritesFirst {
+		flags = append(flags, "-shim-writes-first")
+	}
+
 	flags = append(flags, test.flags...)
 
 	var shim *exec.Cmd
@@ -1156,13 +1174,15 @@
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
+					ExpectFalseStart:         true,
 					MaxHandshakeRecordLength: maxHandshakeRecordLength,
 				},
 			},
 			flags: append(flags,
 				"-false-start",
 				"-select-next-proto", "foo"),
-			resumeSession: true,
+			shimWritesFirst: true,
+			resumeSession:   true,
 		})
 
 		// False Start without session tickets.
@@ -1173,6 +1193,7 @@
 				NextProtos:             []string{"foo"},
 				SessionTicketsDisabled: true,
 				Bugs: ProtocolBugs{
+					ExpectFalseStart:         true,
 					MaxHandshakeRecordLength: maxHandshakeRecordLength,
 				},
 			},
@@ -1180,6 +1201,7 @@
 				"-false-start",
 				"-select-next-proto", "foo",
 			),
+			shimWritesFirst: true,
 		})
 
 		// Server parses a V2ClientHello.
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index cf0d0af..9d1ffc9 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -53,6 +53,7 @@
   { "-no-tls1", &TestConfig::no_tls1 },
   { "-no-ssl3", &TestConfig::no_ssl3 },
   { "-cookie-exchange", &TestConfig::cookie_exchange },
+  { "-shim-writes-first", &TestConfig::shim_writes_first },
 };
 
 const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
@@ -93,7 +94,8 @@
       no_tls11(false),
       no_tls1(false),
       no_ssl3(false),
-      cookie_exchange(false) {
+      cookie_exchange(false),
+      shim_writes_first(false) {
 }
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index dc5e8d3..d79b7f4 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -45,6 +45,7 @@
   bool cookie_exchange;
   std::string expected_channel_id;
   std::string send_channel_id;
+  bool shim_writes_first;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);