Test that ALPN is preferred over NPN.

Change-Id: Ia9d10f672c8a83f507b46f75869b7c00fe1a4fda
Reviewed-on: https://boringssl-review.googlesource.com/1755
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 25e7626..7a87b91 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -97,6 +97,11 @@
 	dtls
 )
 
+const (
+	alpn = 1
+	npn  = 2
+)
+
 type testCase struct {
 	testType      testType
 	protocol      protocol
@@ -116,6 +121,9 @@
 	// expectedNextProto controls whether the connection should
 	// negotiate a next protocol via NPN or ALPN.
 	expectedNextProto string
+	// expectedNextProtoType, if non-zero, is the expected next
+	// protocol negotiation mechanism.
+	expectedNextProtoType int
 	// messageLen is the length, in bytes, of the test message that will be
 	// sent.
 	messageLen int
@@ -523,6 +531,12 @@
 		}
 	}
 
+	if test.expectedNextProtoType != 0 {
+		if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+			return fmt.Errorf("next proto type mismatch")
+		}
+	}
+
 	if test.shimWritesFirst {
 		var buf [5]byte
 		_, err := io.ReadFull(tlsConn, buf[:])
@@ -1143,8 +1157,9 @@
 					MaxHandshakeRecordLength: maxHandshakeRecordLength,
 				},
 			},
-			flags:             append(flags, "-select-next-proto", "foo"),
-			expectedNextProto: "foo",
+			flags:                 append(flags, "-select-next-proto", "foo"),
+			expectedNextProto:     "foo",
+			expectedNextProtoType: npn,
 		})
 		testCases = append(testCases, testCase{
 			protocol: protocol,
@@ -1159,7 +1174,8 @@
 			flags: append(flags,
 				"-advertise-npn", "\x03foo\x03bar\x03baz",
 				"-expect-next-proto", "bar"),
-			expectedNextProto: "bar",
+			expectedNextProto:     "bar",
+			expectedNextProtoType: npn,
 		})
 
 		// Client does False Start and negotiates NPN.
@@ -1446,8 +1462,9 @@
 			"-advertise-alpn", "\x03foo\x03bar\x03baz",
 			"-expect-alpn", "foo",
 		},
-		expectedNextProto: "foo",
-		resumeSession:     true,
+		expectedNextProto:     "foo",
+		expectedNextProtoType: alpn,
+		resumeSession:         true,
 	})
 	testCases = append(testCases, testCase{
 		testType: serverTest,
@@ -1459,8 +1476,43 @@
 			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
 			"-select-alpn", "foo",
 		},
-		expectedNextProto: "foo",
-		resumeSession:     true,
+		expectedNextProto:     "foo",
+		expectedNextProtoType: alpn,
+		resumeSession:         true,
+	})
+	// Test that the server prefers ALPN over NPN.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ALPNServer-Preferred",
+		config: Config{
+			NextProtos: []string{"foo", "bar", "baz"},
+		},
+		flags: []string{
+			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+			"-select-alpn", "foo",
+			"-advertise-npn", "\x03foo\x03bar\x03baz",
+		},
+		expectedNextProto:     "foo",
+		expectedNextProtoType: alpn,
+		resumeSession:         true,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ALPNServer-Preferred-Swapped",
+		config: Config{
+			NextProtos: []string{"foo", "bar", "baz"},
+			Bugs: ProtocolBugs{
+				SwapNPNAndALPN: true,
+			},
+		},
+		flags: []string{
+			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+			"-select-alpn", "foo",
+			"-advertise-npn", "\x03foo\x03bar\x03baz",
+		},
+		expectedNextProto:     "foo",
+		expectedNextProtoType: alpn,
+		resumeSession:         true,
 	})
 }