Add a test for renegotiation on busy write buffer.

The write path for TLS is going to need some work. There are some fiddly
cases when there is a write in progress. Start adding tests to cover
this logic.

Later I'm hoping we can extend this flag so it drains the unfinished
write and thus test the interaction of read/write paths in 0-RTT. (We
may discover 1-RTT keys while we're in the middle of writing data.)

Change-Id: Iac2c417e4b5e84794fb699dd7cbba26a883b64ef
Reviewed-on: https://boringssl-review.googlesource.com/13049
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 418b9f0..d46a027 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -1760,6 +1760,19 @@
       }
     }
   } else {
+    if (config->read_with_unfinished_write) {
+      if (!config->async) {
+        fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
+        return false;
+      }
+
+      int write_ret = SSL_write(ssl.get(),
+                          reinterpret_cast<const uint8_t *>("unfinished"), 10);
+      if (SSL_get_error(ssl.get(), write_ret) != SSL_ERROR_WANT_WRITE) {
+        fprintf(stderr, "Failed to leave unfinished write.\n");
+        return false;
+      }
+    }
     if (config->shim_writes_first) {
       if (WriteAll(ssl.get(), reinterpret_cast<const uint8_t *>("hello"),
                    5) < 0) {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index a71a9cc..56026b2 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -6262,6 +6262,24 @@
 		expectedLocalError: "remote error: no renegotiation",
 	})
 
+	// Renegotiation is not allowed when there is an unfinished write.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-UnfinishedWrite",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-async",
+			"-renegotiate-freely",
+			"-read-with-unfinished-write",
+		},
+		shouldFail:    true,
+		expectedError: ":NO_RENEGOTIATION:",
+		// We do not successfully send the no_renegotiation alert in
+		// this case. https://crbug.com/boringssl/130
+	})
+
 	// Stray HelloRequests during the handshake are ignored in TLS 1.2.
 	testCases = append(testCases, testCase{
 		name: "StrayHelloRequest",
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 0b11169..22e4c9c 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -116,6 +116,7 @@
   { "-expect-sha256-client-cert-resume",
     &TestConfig::expect_sha256_client_cert_resume },
   { "-enable-short-header", &TestConfig::enable_short_header },
+  { "-read-with-unfinished-write", &TestConfig::read_with_unfinished_write },
 };
 
 const Flag<std::string> kStringFlags[] = {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 9f3fbec..882cddc 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -124,6 +124,7 @@
   bool expect_sha256_client_cert_initial = false;
   bool expect_sha256_client_cert_resume = false;
   bool enable_short_header = false;
+  bool read_with_unfinished_write = false;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);