Use initializer lists to specify cipher rule tests.

This is significantly less of a nuisance than having to explicitly type out
kRule5, kExpected5.

Change-Id: I61820c26a159c71e09000fbe0bf91e30da42205e
Reviewed-on: https://boringssl-review.googlesource.com/7000
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
index bef88fb..f91542d 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -39,215 +39,178 @@
 struct CipherTest {
   // The rule string to apply.
   const char *rule;
-  // The list of expected ciphers, in order, terminated with -1.
-  const ExpectedCipher *expected;
+  // The list of expected ciphers, in order.
+  std::vector<ExpectedCipher> expected;
 };
 
-// Selecting individual ciphers should work.
-static const char kRule1[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected1[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// + reorders selected ciphers to the end, keeping their relative
-// order.
-static const char kRule2[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "+aRSA";
-
-static const ExpectedCipher kExpected2[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// ! banishes ciphers from future selections.
-static const char kRule3[] =
-    "!aRSA:"
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected3[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Multiple masks can be ANDed in a single rule.
-static const char kRule4[] = "kRSA+AESGCM+AES128";
-
-static const ExpectedCipher kExpected4[] = {
-  { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// - removes selected ciphers, but preserves their order for future
-// selections. Select AES_128_GCM, but order the key exchanges RSA,
-// DHE_RSA, ECDHE_RSA.
-static const char kRule5[] =
-    "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
-    "AESGCM+AES128+aRSA";
-
-static const ExpectedCipher kExpected5[] = {
-  { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Unknown selectors are no-ops.
-static const char kRule6[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4";
-
-static const ExpectedCipher kExpected6[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Square brackets specify equi-preference groups.
-static const char kRule7[] =
-    "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
-    "[ECDHE-RSA-CHACHA20-POLY1305]:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected7[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// @STRENGTH performs a stable strength-sort of the selected
-// ciphers and only the selected ciphers.
-static const char kRule8[] =
-    // To simplify things, banish all but {ECDHE_RSA,RSA} x
-    // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
-    "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
-    // Order some ciphers backwards by strength.
-    "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
-    // Select ECDHE ones and sort them by strength. Ties should resolve
-    // based on the order above.
-    "kECDHE:@STRENGTH:-ALL:"
-    // Now bring back everything uses RSA. ECDHE_RSA should be first,
-    // sorted by strength. Then RSA, backwards by strength.
-    "aRSA";
-
-static const ExpectedCipher kExpected8[] = {
-  { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 },
-  { SSL3_CK_RSA_RC4_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_256_SHA, 0 },
-  { 0, 0 },
-};
-
-// Exact ciphers may not be used in multi-part rules; they are treated
-// as unknown aliases.
-static const char kRule9[] =
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
-    "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected9[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// SSLv3 matches everything that existed before TLS 1.2.
-static const char kRule10[] = "AES128-SHA:AES128-SHA256:!SSLv3";
-
-static const ExpectedCipher kExpected10[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA256, 0 },
-  { 0, 0 },
-};
-
-// TLSv1.2 matches everything added in TLS 1.2.
-static const char kRule11[] = "AES128-SHA:AES128-SHA256:!TLSv1.2";
-
-static const ExpectedCipher kExpected11[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { 0, 0 },
-};
-
-// The two directives have no intersection.
-static const char kRule12[] = "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3";
-
-static const ExpectedCipher kExpected12[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_128_SHA256, 0 },
-  { 0, 0 },
-};
-
-// The shared name of the CHACHA20_POLY1305 variants behaves like a cipher name
-// and not an alias. It may not be used in a multipart rule. (That the shared
-// name works is covered by the standard tests.)
-static const char kRule13[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
-    "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305";
-
-static const ExpectedCipher kExpected13[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { 0, 0 },
-};
-
-static CipherTest kCipherTests[] = {
-  { kRule1, kExpected1 },
-  { kRule2, kExpected2 },
-  { kRule3, kExpected3 },
-  { kRule4, kExpected4 },
-  { kRule5, kExpected5 },
-  { kRule6, kExpected6 },
-  { kRule7, kExpected7 },
-  { kRule8, kExpected8 },
-  { kRule9, kExpected9 },
-  { kRule10, kExpected10 },
-  { kRule11, kExpected11 },
-  { kRule12, kExpected12 },
-  { kRule13, kExpected13 },
-  { NULL, NULL },
+static const CipherTest kCipherTests[] = {
+    // Selecting individual ciphers should work.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // + reorders selected ciphers to the end, keeping their relative order.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "+aRSA",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // ! banishes ciphers from future selections.
+    {
+        "!aRSA:"
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // Multiple masks can be ANDed in a single rule.
+    {
+        "kRSA+AESGCM+AES128",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // - removes selected ciphers, but preserves their order for future
+    // selections. Select AES_128_GCM, but order the key exchanges RSA, DHE_RSA,
+    // ECDHE_RSA.
+    {
+        "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
+        "AESGCM+AES128+aRSA",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // Unknown selectors are no-ops.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // Square brackets specify equi-preference groups.
+    {
+        "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
+        "[ECDHE-RSA-CHACHA20-POLY1305]:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // @STRENGTH performs a stable strength-sort of the selected ciphers and
+    // only the selected ciphers.
+    {
+        // To simplify things, banish all but {ECDHE_RSA,RSA} x
+        // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
+        "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
+        // Order some ciphers backwards by strength.
+        "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
+        // Select ECDHE ones and sort them by strength. Ties should resolve
+        // based on the order above.
+        "kECDHE:@STRENGTH:-ALL:"
+        // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted
+        // by strength. Then RSA, backwards by strength.
+        "aRSA",
+        {
+            {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
+            {SSL3_CK_RSA_RC4_128_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_256_SHA, 0},
+        },
+    },
+    // Exact ciphers may not be used in multi-part rules; they are treated
+    // as unknown aliases.
+    {
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
+        "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+    },
+    // SSLv3 matches everything that existed before TLS 1.2.
+    {
+        "AES128-SHA:AES128-SHA256:!SSLv3",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
+        },
+    },
+    // TLSv1.2 matches everything added in TLS 1.2.
+    {
+        "AES128-SHA:AES128-SHA256:!TLSv1.2",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+        },
+    },
+    // The two directives have no intersection.
+    {
+        "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
+        },
+    },
+    // The shared name of the CHACHA20_POLY1305 variants behaves like a cipher
+    // name and not an alias. It may not be used in a multipart rule. (That the
+    // shared name works is covered by the standard tests.)
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
+        "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
+        },
+    },
 };
 
 static const char *kBadRules[] = {
@@ -271,7 +234,6 @@
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
-  NULL,
 };
 
 static const char *kMustNotIncludeNull[] = {
@@ -288,7 +250,6 @@
   "SSLv3",
   "TLSv1",
   "TLSv1.2",
-  NULL
 };
 
 static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
@@ -311,36 +272,35 @@
   }
 }
 
-static bool TestCipherRule(CipherTest *t) {
+static bool TestCipherRule(const CipherTest &t) {
   ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
   if (!ctx) {
     return false;
   }
 
-  if (!SSL_CTX_set_cipher_list(ctx.get(), t->rule)) {
-    fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule);
+  if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) {
+    fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule);
     return false;
   }
 
   // Compare the two lists.
-  size_t i;
-  for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+  if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) {
+    fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
+    PrintCipherPreferenceList(ctx->cipher_list);
+    return false;
+  }
+
+  for (size_t i = 0; i < t.expected.size(); i++) {
     const SSL_CIPHER *cipher =
         sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
-    if (t->expected[i].id != SSL_CIPHER_get_id(cipher) ||
-        t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
-      fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule);
+    if (t.expected[i].id != SSL_CIPHER_get_id(cipher) ||
+        t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
+      fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
       PrintCipherPreferenceList(ctx->cipher_list);
       return false;
     }
   }
 
-  if (t->expected[i].id != 0) {
-    fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule);
-    PrintCipherPreferenceList(ctx->cipher_list);
-    return false;
-  }
-
   return true;
 }
 
@@ -363,26 +323,26 @@
 }
 
 static bool TestCipherRules() {
-  for (size_t i = 0; kCipherTests[i].rule != NULL; i++) {
-    if (!TestCipherRule(&kCipherTests[i])) {
+  for (const CipherTest &test : kCipherTests) {
+    if (!TestCipherRule(test)) {
       return false;
     }
   }
 
-  for (size_t i = 0; kBadRules[i] != NULL; i++) {
+  for (const char *rule : kBadRules) {
     ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
     if (!ctx) {
       return false;
     }
-    if (SSL_CTX_set_cipher_list(ctx.get(), kBadRules[i])) {
-      fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]);
+    if (SSL_CTX_set_cipher_list(ctx.get(), rule)) {
+      fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule);
       return false;
     }
     ERR_clear_error();
   }
 
-  for (size_t i = 0; kMustNotIncludeNull[i] != NULL; i++) {
-    if (!TestRuleDoesNotIncludeNull(kMustNotIncludeNull[i])) {
+  for (const char *rule : kMustNotIncludeNull) {
+    if (!TestRuleDoesNotIncludeNull(rule)) {
       return false;
     }
   }