organize tests
diff --git a/t/fusion.c b/t/fusion.c
index f9ebd2d..8adc21b 100644
--- a/t/fusion.c
+++ b/t/fusion.c
@@ -46,114 +46,40 @@
     return buf;
 }
 
-int main(int argc, char **argv)
+static const uint8_t zero[16384] = {};
+
+static void ecb(void)
 {
-    if (!ptls_fusion_is_supported_by_cpu()) {
-        note("CPU does have the necessary features (avx2, aes, pclmul)\n");
-        return done_testing();
-    }
+    ptls_fusion_aesecb_context_t ecb;
+    uint8_t encrypted[16];
 
-    static const uint8_t zero[16384] = {}, one[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+    ptls_fusion_aesecb_init(&ecb, 1, zero, 16);
+    ptls_fusion_aesecb_encrypt(&ecb, encrypted, "hello world!!!!!");
+    ptls_fusion_aesecb_dispose(&ecb);
+    ok(strcmp(tostr(encrypted, 16), "172afecb50b5f1237814b2f7cb51d0f7") == 0);
 
-    {
-        ptls_fusion_aesecb_context_t ecb;
-        uint8_t encrypted[16];
+    ptls_fusion_aesecb_init(&ecb, 1, zero, 32);
+    ptls_fusion_aesecb_encrypt(&ecb, encrypted, "hello world!!!!!");
+    ptls_fusion_aesecb_dispose(&ecb);
+    ok(strcmp(tostr(encrypted, 16), "2a033f0627b3554aa4fe5786550736ff") == 0);
+}
 
-        ptls_fusion_aesecb_init(&ecb, 1, zero, 16);
-        ptls_fusion_aesecb_encrypt(&ecb, encrypted, "hello world!!!!!");
-        ptls_fusion_aesecb_dispose(&ecb);
-        ok(strcmp(tostr(encrypted, 16), "172afecb50b5f1237814b2f7cb51d0f7") == 0);
-
-        ptls_fusion_aesecb_init(&ecb, 1, zero, 32);
-        ptls_fusion_aesecb_encrypt(&ecb, encrypted, "hello world!!!!!");
-        ptls_fusion_aesecb_dispose(&ecb);
-        ok(strcmp(tostr(encrypted, 16), "2a033f0627b3554aa4fe5786550736ff") == 0);
-    }
-
+static void gcm_basic(void)
+{
     {
         static const uint8_t expected[] = {0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2,
                                            0xb9, 0x71, 0xb2, 0xfe, 0x78, 0x97, 0x3f, 0xbc, 0xa6, 0x54, 0x77,
                                            0xbf, 0x47, 0x85, 0xb0, 0xd5, 0x61, 0xf7, 0xe3, 0xfd, 0x6c};
         ptls_fusion_aesgcm_context_t *ctx = ptls_fusion_aesgcm_new(zero, PTLS_AES128_KEY_SIZE, 5 + 16);
         uint8_t encrypted[sizeof(expected)], decrypted[sizeof(expected) - 16];
-
         ptls_fusion_aesgcm_encrypt(ctx, encrypted, zero, 16, _mm_setzero_si128(), "hello", 5, NULL);
         ok(memcmp(expected, encrypted, sizeof(expected)) == 0);
-
         memset(decrypted, 0x55, sizeof(decrypted));
         ok(ptls_fusion_aesgcm_decrypt(ctx, decrypted, expected, 16, _mm_setzero_si128(), "hello", 5, expected + 16));
         ok(memcmp(decrypted, zero, sizeof(decrypted)) == 0);
-
         ptls_fusion_aesgcm_free(ctx);
     }
 
-    { /* test capacity */
-        static const uint8_t expected[17] = {0x5b, 0x27, 0x21, 0x5e, 0xd8, 0x1a, 0x70, 0x2e, 0x39,
-                                             0x41, 0xc8, 0x05, 0x77, 0xd5, 0x2f, 0xcb, 0x57};
-        ptls_fusion_aesgcm_context_t *ctx = ptls_fusion_aesgcm_new(zero, PTLS_AES128_KEY_SIZE, 2);
-        uint8_t encrypted[17], decrypted[1] = {0x55};
-        ptls_fusion_aesgcm_encrypt(ctx, encrypted, "X", 1, _mm_setzero_si128(), "a", 1, NULL);
-        ok(memcmp(expected, encrypted, 17) == 0);
-        ok(ptls_fusion_aesgcm_decrypt(ctx, decrypted, expected, 1, _mm_setzero_si128(), "a", 1, expected + 1));
-        ok('X' == decrypted[0]);
-        ptls_fusion_aesgcm_free(ctx);
-    }
-
-    {
-        ptls_fusion_aesgcm_context_t *aead = ptls_fusion_aesgcm_new(zero, PTLS_AES128_KEY_SIZE, sizeof(zero));
-        ptls_aead_supplementary_encryption_t *supp = NULL;
-
-        for (int i = 0; i < 2; ++i) {
-            uint8_t encrypted[sizeof(zero) + 16], decrypted[sizeof(zero)];
-#define DOIT(aad, aadlen, ptlen, expected_tag, expected_supp)                                                                      \
-    do {                                                                                                                           \
-        memset(encrypted, 0xcc, sizeof(encrypted));                                                                                \
-        ptls_fusion_aesgcm_encrypt(aead, encrypted, zero, ptlen, _mm_setzero_si128(), aad, aadlen, supp);                          \
-        printf("%s\n", tostr(encrypted + ptlen, 16));                                                                              \
-        ok(strcmp(tostr(encrypted + ptlen, 16), expected_tag) == 0);                                                               \
-        if (supp != NULL)                                                                                                          \
-            ok(strcmp(tostr(supp->output, sizeof(supp->output)), expected_supp) == 0);                                             \
-        memset(decrypted, 0x55, sizeof(decrypted));                                                                                \
-        ok(ptls_fusion_aesgcm_decrypt(aead, decrypted, encrypted, ptlen, _mm_setzero_si128(), aad, aadlen, encrypted + ptlen));    \
-        ok(memcmp(decrypted, zero, ptlen) == 0);                                                                                   \
-    } while (0)
-
-            DOIT(zero, 13, 17, "1b4e515384e8aa5bb781ee12549a2ccf", "4576f18ef3ae9dfd37cf72c4592da874");
-            DOIT(zero, 13, 32, "84030586f55adf8ac3c145913c6fd0f8", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 64, "66165d39739c50c90727e7d49127146b", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 65, "eb3b75e1d4431e1bb67da46f6a1a0edd", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 79, "8f4a96c7390c26bb15b68865e6a861b9", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 80, "5cc2554857b19e7a9e18d015feac61fd", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 81, "5a65f0d4db36c981bf7babd11691fe78", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 95, "6a8a51152efe928999a610d8a7b1df9d", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 96, "6b9c468e24ed96010687f3880a044d42", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 13, 97, "1b4eb785b884a7d4fdebaff81c1c12e8", "a062016e90dcc316d061fde5424cf34f");
-
-            DOIT(zero, 22, 1328, "0507baaece8d573774c94e8103821316", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 21, 1329, "dd70d59030eadb6313e778046540a253", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 20, 1330, "f1b456b955afde7603188af0124a32ef", "a062016e90dcc316d061fde5424cf34f");
-
-            DOIT(zero, 13, 1337, "a22deec51250a7eb1f4384dea5f2e890", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 12, 1338, "42102b0a499b2efa89702ece4b0c5789", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 11, 1339, "9827f0b34252160d0365ffaa9364bedc", "a062016e90dcc316d061fde5424cf34f");
-
-            DOIT(zero, 0, 80, "98885a3a22bd4742fe7b72172193b163", "a062016e90dcc316d061fde5424cf34f");
-            DOIT(zero, 0, 96, "afd649fc51e14f3966e4518ad53b9ddc", "a062016e90dcc316d061fde5424cf34f");
-
-            DOIT(zero, 20, 85, "afe8b727057c804a0525c2914ef856b0", "a062016e90dcc316d061fde5424cf34f");
-
-#undef DOIT
-
-            supp = malloc(sizeof(*supp));
-            supp->ctx = ptls_cipher_new(&ptls_fusion_aes128ctr, 1, one);
-            supp->input = encrypted + 2;
-        }
-
-        ptls_cipher_free(supp->ctx);
-        free(supp);
-        ptls_fusion_aesgcm_free(aead);
-    }
-
     {
         static const uint8_t key[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
                                         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
@@ -177,6 +103,88 @@
         ok(memcmp(decrypted, plaintext, sizeof(plaintext)) == 0);
         ptls_aead_free(aead);
     }
+}
+
+static void gcm_capacity(void)
+{
+    static const uint8_t expected[17] = {0x5b, 0x27, 0x21, 0x5e, 0xd8, 0x1a, 0x70, 0x2e, 0x39,
+                                         0x41, 0xc8, 0x05, 0x77, 0xd5, 0x2f, 0xcb, 0x57};
+    ptls_fusion_aesgcm_context_t *ctx = ptls_fusion_aesgcm_new(zero, PTLS_AES128_KEY_SIZE, 2);
+    uint8_t encrypted[17], decrypted[1] = {0x55};
+    ptls_fusion_aesgcm_encrypt(ctx, encrypted, "X", 1, _mm_setzero_si128(), "a", 1, NULL);
+    ok(memcmp(expected, encrypted, 17) == 0);
+    ok(ptls_fusion_aesgcm_decrypt(ctx, decrypted, expected, 1, _mm_setzero_si128(), "a", 1, expected + 1));
+    ok('X' == decrypted[0]);
+    ptls_fusion_aesgcm_free(ctx);
+}
+
+static void gcm_test_vectors(void)
+{
+    static const uint8_t one[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+    ptls_fusion_aesgcm_context_t *aead = ptls_fusion_aesgcm_new(zero, PTLS_AES128_KEY_SIZE, sizeof(zero));
+    ptls_aead_supplementary_encryption_t *supp = NULL;
+
+    for (int i = 0; i < 2; ++i) {
+        uint8_t encrypted[sizeof(zero) + 16], decrypted[sizeof(zero)];
+#define DOIT(aad, aadlen, ptlen, expected_tag, expected_supp)                                                                      \
+    do {                                                                                                                           \
+        memset(encrypted, 0xcc, sizeof(encrypted));                                                                                \
+        ptls_fusion_aesgcm_encrypt(aead, encrypted, zero, ptlen, _mm_setzero_si128(), aad, aadlen, supp);                          \
+        ok(strcmp(tostr(encrypted + ptlen, 16), expected_tag) == 0);                                                               \
+        if (supp != NULL)                                                                                                          \
+            ok(strcmp(tostr(supp->output, sizeof(supp->output)), expected_supp) == 0);                                             \
+        memset(decrypted, 0x55, sizeof(decrypted));                                                                                \
+        ok(ptls_fusion_aesgcm_decrypt(aead, decrypted, encrypted, ptlen, _mm_setzero_si128(), aad, aadlen, encrypted + ptlen));    \
+        ok(memcmp(decrypted, zero, ptlen) == 0);                                                                                   \
+    } while (0)
+
+        DOIT(zero, 13, 17, "1b4e515384e8aa5bb781ee12549a2ccf", "4576f18ef3ae9dfd37cf72c4592da874");
+        DOIT(zero, 13, 32, "84030586f55adf8ac3c145913c6fd0f8", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 64, "66165d39739c50c90727e7d49127146b", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 65, "eb3b75e1d4431e1bb67da46f6a1a0edd", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 79, "8f4a96c7390c26bb15b68865e6a861b9", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 80, "5cc2554857b19e7a9e18d015feac61fd", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 81, "5a65f0d4db36c981bf7babd11691fe78", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 95, "6a8a51152efe928999a610d8a7b1df9d", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 96, "6b9c468e24ed96010687f3880a044d42", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 13, 97, "1b4eb785b884a7d4fdebaff81c1c12e8", "a062016e90dcc316d061fde5424cf34f");
+
+        DOIT(zero, 22, 1328, "0507baaece8d573774c94e8103821316", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 21, 1329, "dd70d59030eadb6313e778046540a253", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 20, 1330, "f1b456b955afde7603188af0124a32ef", "a062016e90dcc316d061fde5424cf34f");
+
+        DOIT(zero, 13, 1337, "a22deec51250a7eb1f4384dea5f2e890", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 12, 1338, "42102b0a499b2efa89702ece4b0c5789", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 11, 1339, "9827f0b34252160d0365ffaa9364bedc", "a062016e90dcc316d061fde5424cf34f");
+
+        DOIT(zero, 0, 80, "98885a3a22bd4742fe7b72172193b163", "a062016e90dcc316d061fde5424cf34f");
+        DOIT(zero, 0, 96, "afd649fc51e14f3966e4518ad53b9ddc", "a062016e90dcc316d061fde5424cf34f");
+
+        DOIT(zero, 20, 85, "afe8b727057c804a0525c2914ef856b0", "a062016e90dcc316d061fde5424cf34f");
+
+#undef DOIT
+
+        supp = malloc(sizeof(*supp));
+        supp->ctx = ptls_cipher_new(&ptls_fusion_aes128ctr, 1, one);
+        supp->input = encrypted + 2;
+    }
+
+    ptls_cipher_free(supp->ctx);
+    free(supp);
+    ptls_fusion_aesgcm_free(aead);
+}
+
+int main(int argc, char **argv)
+{
+    if (!ptls_fusion_is_supported_by_cpu()) {
+        note("CPU does have the necessary features (avx2, aes, pclmul)\n");
+        return done_testing();
+    }
+
+    subtest("ecb", ecb);
+    subtest("gcm-basic", gcm_basic);
+    subtest("gcm-capacity", gcm_capacity);
+    subtest("gcm-test-vectors", gcm_test_vectors);
 
     return done_testing();
 }