Test that ALPS can be deferred to the ALPN callback.

This wasn't the cause of the bug, but I noticed we never tested it, so
fill that in.

Change-Id: Ib38bc08309e69f43c1995ba2a387643c0a7bae99
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44984
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 6f1f0ab..5dacff4 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -7008,6 +7008,38 @@
 				},
 			})
 
+			// Test that the server can defer its ALPS configuration to the ALPN
+			// selection callback.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "ALPS-Basic-Server-Defer-" + ver.name,
+				config: Config{
+					MaxVersion:          ver.version,
+					NextProtos:          []string{"proto"},
+					ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+				},
+				resumeConfig: &Config{
+					MaxVersion:          ver.version,
+					NextProtos:          []string{"proto"},
+					ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+				},
+				resumeSession: true,
+				expectations: connectionExpectations{
+					peerApplicationSettings: []byte("shim1"),
+				},
+				resumeExpectations: &connectionExpectations{
+					peerApplicationSettings: []byte("shim2"),
+				},
+				flags: []string{
+					"-select-alpn", "proto",
+					"-defer-alps",
+					"-on-initial-application-settings", "proto,shim1",
+					"-on-initial-expect-peer-application-settings", "runner1",
+					"-on-resume-application-settings", "proto,shim2",
+					"-on-resume-expect-peer-application-settings", "runner2",
+				},
+			})
+
 			// Test the client and server correctly handle empty settings.
 			testCases = append(testCases, testCase{
 				testType: clientTest,
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index e321ff3..eb863eb 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -74,6 +74,7 @@
     {"-expect-session-miss", &TestConfig::expect_session_miss},
     {"-decline-alpn", &TestConfig::decline_alpn},
     {"-select-empty-alpn", &TestConfig::select_empty_alpn},
+    {"-defer-alps", &TestConfig::defer_alps},
     {"-expect-extended-master-secret",
      &TestConfig::expect_extended_master_secret},
     {"-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling},
@@ -675,6 +676,19 @@
     exit(1);
   }
 
+  if (config->defer_alps) {
+    for (const auto &pair : config->application_settings) {
+      if (!SSL_add_application_settings(
+              ssl, reinterpret_cast<const uint8_t *>(pair.first.data()),
+              pair.first.size(),
+              reinterpret_cast<const uint8_t *>(pair.second.data()),
+              pair.second.size())) {
+        fprintf(stderr, "error configuring ALPS.\n");
+        exit(1);
+      }
+    }
+  }
+
   assert(config->select_alpn.empty() || !config->select_empty_alpn);
   *out = (const uint8_t *)config->select_alpn.data();
   *outlen = config->select_alpn.size();
@@ -1606,13 +1620,15 @@
           advertise_alpn.size()) != 0) {
     return nullptr;
   }
-  for (const auto &pair : application_settings) {
-    if (!SSL_add_application_settings(
-            ssl.get(), reinterpret_cast<const uint8_t *>(pair.first.data()),
-            pair.first.size(),
-            reinterpret_cast<const uint8_t *>(pair.second.data()),
-            pair.second.size())) {
-      return nullptr;
+  if (!defer_alps) {
+    for (const auto &pair : application_settings) {
+      if (!SSL_add_application_settings(
+              ssl.get(), reinterpret_cast<const uint8_t *>(pair.first.data()),
+              pair.first.size(),
+              reinterpret_cast<const uint8_t *>(pair.second.data()),
+              pair.second.size())) {
+        return nullptr;
+      }
     }
   }
   if (!psk.empty()) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 93aab24..67cab95 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -69,6 +69,7 @@
   std::string select_alpn;
   bool decline_alpn = false;
   bool select_empty_alpn = false;
+  bool defer_alps = false;
   std::vector<std::pair<std::string, std::string>> application_settings;
   std::unique_ptr<std::string> expect_peer_application_settings;
   std::string quic_transport_params;