[ECH] test variations, e.g., retry
diff --git a/t/picotls.c b/t/picotls.c
index edb79b9..d89fe63 100644
--- a/t/picotls.c
+++ b/t/picotls.c
@@ -667,8 +667,16 @@
     return 0;
 }
 
-static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication,
-                           int ech)
+static int can_ech(ptls_context_t *ctx, int is_server)
+{
+    if (ctx->ech.kems == NULL || ctx->ech.ciphers == NULL)
+        return 0;
+    if (is_server && ctx->ech.create_opener == NULL)
+        return 0;
+    return 1;
+}
+
+static void test_handshake(ptls_iovec_t ticket, int mode, int expect_ticket, int check_ch, int require_client_authentication)
 {
     ptls_t *client, *server;
     ptls_handshake_properties_t client_hs_prop = {{{{NULL}, ticket}}}, server_hs_prop = {{{{NULL}}}};
@@ -697,7 +705,7 @@
         ptls_set_server_name(client, "test.example.com", 0);
     }
 
-    if (ech)
+    if (can_ech(ctx, 0))
         client_hs_prop.client.ech_config_list = ptls_iovec_init(ECH_CONFIG_LIST, sizeof(ECH_CONFIG_LIST) - 1);
 
     static ptls_on_extension_t cb = {on_extension_cb};
@@ -900,6 +908,14 @@
         decbuf.off = 0;
     }
 
+    if (can_ech(ctx_peer, 1) && can_ech(ctx, 0)) {
+        ok(ptls_is_ech_handshake(client));
+        ok(ptls_is_ech_handshake(server));
+    } else {
+        ok(!ptls_is_ech_handshake(client));
+        ok(!ptls_is_ech_handshake(server));
+    }
+
     ptls_buffer_dispose(&cbuf);
     ptls_buffer_dispose(&sbuf);
     ptls_buffer_dispose(&decbuf);
@@ -933,25 +949,25 @@
     return second_sc_orig->cb(second_sc_orig, tls, selected_algorithm, output, input, algorithms, num_algorithms);
 }
 
-static void test_full_handshake_impl(int require_client_authentication, int ech)
+static void test_full_handshake_impl(int require_client_authentication)
 {
     sc_callcnt = 0;
 
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, ech);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 2);
     } else {
         ok(sc_callcnt == 1);
     }
 
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication, ech);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 4);
     } else {
         ok(sc_callcnt == 2);
     }
 
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication, ech);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_1RTT, 0, 1, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 6);
     } else {
@@ -961,41 +977,30 @@
 
 static void test_full_handshake(void)
 {
-    test_full_handshake_impl(0, 0);
+    test_full_handshake_impl(0);
 }
 
 static void test_full_handshake_with_client_authentication(void)
 {
-    test_full_handshake_impl(1, 0);
-}
-
-static void test_full_handshake_ech(void)
-{
-    if (ctx->ech.kems == NULL || ctx->ech.kems[0] == NULL || ctx->ech.ciphers == NULL || ctx->ech.ciphers[0] == NULL ||
-        ctx_peer->ech.kems == NULL || ctx_peer->ech.kems[0] == NULL || ctx_peer->ech.ciphers == NULL ||
-        ctx_peer->ech.ciphers[0] == NULL) {
-        note("ech: does not have kems / ciphers");
-        return;
-    }
-    test_full_handshake_impl(0, 1);
+    test_full_handshake_impl(1);
 }
 
 static void test_key_update(void)
 {
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0, 0);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_KEY_UPDATE, 0, 0, 0);
 }
 
 static void test_hrr_handshake(void)
 {
     sc_callcnt = 0;
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0, 0);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR, 0, 0, 0);
     ok(sc_callcnt == 1);
 }
 
 static void test_hrr_stateless_handshake(void)
 {
     sc_callcnt = 0;
-    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0, 0);
+    test_handshake(ptls_iovec_init(NULL, 0), TEST_HANDSHAKE_HRR_STATELESS, 0, 0, 0);
     ok(sc_callcnt == 1);
 }
 
@@ -1048,12 +1053,12 @@
     ctx->save_ticket = &st;
 
     sc_callcnt = 0;
-    test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0, 0);
+    test_handshake(saved_ticket, different_preferred_key_share ? TEST_HANDSHAKE_2RTT : TEST_HANDSHAKE_1RTT, 1, 0, 0);
     ok(sc_callcnt == 1);
     ok(saved_ticket.base != NULL);
 
     /* psk using saved ticket */
-    test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, 0);
+    test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 3);
     } else {
@@ -1061,7 +1066,7 @@
     }
 
     /* 0-rtt psk using saved ticket */
-    test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, 0);
+    test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 5);
     } else {
@@ -1071,7 +1076,7 @@
     ctx->require_dhe_on_psk = 1;
 
     /* psk-dhe using saved ticket */
-    test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication, 0);
+    test_handshake(saved_ticket, TEST_HANDSHAKE_1RTT, 1, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 7);
     } else {
@@ -1079,7 +1084,7 @@
     }
 
     /* 0-rtt psk-dhe using saved ticket */
-    test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication, 0);
+    test_handshake(saved_ticket, TEST_HANDSHAKE_EARLY_DATA, 1, 0, require_client_authentication);
     if (require_client_authentication) {
         ok(sc_callcnt == 9);
     } else {
@@ -1541,6 +1546,24 @@
     ctx_peer->max_early_data_size = 0;
 }
 
+static void test_all_handshakes_core(void)
+{
+    subtest("full-handshake", test_full_handshake);
+    subtest("full-handshake+client-auth", test_full_handshake_with_client_authentication);
+    subtest("hrr-handshake", test_hrr_handshake);
+    subtest("resumption", test_resumption);
+    subtest("resumption-different-preferred-key-share", test_resumption_different_preferred_key_share);
+    subtest("resumption-with-client-authentication", test_resumption_with_client_authentication);
+    subtest("enforce-retry-stateful", test_enforce_retry_stateful);
+    if (!(can_ech(ctx_peer, 1) && can_ech(ctx, 0))) {
+        subtest("hrr-stateless-handshake", test_hrr_stateless_handshake);
+        subtest("enforce-retry-stateless", test_enforce_retry_stateless);
+        subtest("stateless-hrr-aad-change", test_stateless_hrr_aad_change);
+    }
+    subtest("key-update", test_key_update);
+    subtest("handshake-api", test_handshake_api);
+}
+
 static void test_all_handshakes(void)
 {
     ptls_sign_certificate_t server_sc = {sign_certificate};
@@ -1553,23 +1576,19 @@
         ctx->sign_certificate = &client_sc;
     }
 
-    subtest("full-handshake", test_full_handshake);
-    subtest("full-handshake-with-client-authentication", test_full_handshake_with_client_authentication);
-    subtest("full-handshake-ech", test_full_handshake_ech);
-    subtest("hrr-handshake", test_hrr_handshake);
-    subtest("hrr-stateless-handshake", test_hrr_stateless_handshake);
-    subtest("resumption", test_resumption);
-    subtest("resumption-different-preferred-key-share", test_resumption_different_preferred_key_share);
-    subtest("resumption-with-client-authentication", test_resumption_with_client_authentication);
+    struct {
+        ptls_hpke_kem_t **server, **client;
+    } orig_ech_kems = {ctx_peer->ech.kems, ctx->ech.kems};
 
-    subtest("enforce-retry-stateful", test_enforce_retry_stateful);
-    subtest("enforce-retry-stateless", test_enforce_retry_stateless);
+    /* first run tests wo. ECH */
+    ctx_peer->ech.kems = NULL;
+    ctx->ech.kems = NULL;
+    subtest("no-ech", test_all_handshakes_core);
+    ctx_peer->ech.kems = orig_ech_kems.server;
+    ctx->ech.kems = orig_ech_kems.client;
 
-    subtest("stateless-hrr-aad-change", test_stateless_hrr_aad_change);
-
-    subtest("key-update", test_key_update);
-
-    subtest("handshake-api", test_handshake_api);
+    if (can_ech(ctx_peer, 1) && can_ech(ctx, 0))
+        subtest("ech", test_all_handshakes_core);
 
     ctx_peer->sign_certificate = sc_orig;