static int test_key_update_in_write(int tst)
{
    SSL_CTX *cctx = NULL, *sctx = NULL;
    SSL *clientssl = NULL, *serverssl = NULL;
    int testresult = 0;
    char buf[20];
    static char *mess = "A test message";
    BIO *bretry = BIO_new(bio_s_always_retry());
    BIO *tmp = NULL;
    SSL *peerupdate = NULL, *peerwrite = NULL;
    if (!TEST_ptr(bretry)
            || !TEST_true(create_ssl_ctx_pair(TLS_server_method(),
                                              TLS_client_method(),
                                              TLS1_3_VERSION,
                                              0,
                                              &sctx, &cctx, cert, privkey))
            || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
                                             NULL, NULL))
            || !TEST_true(create_ssl_connection(serverssl, clientssl,
                                                SSL_ERROR_NONE)))
        goto end;
    peerupdate = tst == 0 ? clientssl : serverssl;
    peerwrite = tst == 0 ? serverssl : clientssl;
    if (!TEST_true(SSL_key_update(peerupdate, SSL_KEY_UPDATE_REQUESTED))
            || !TEST_true(SSL_do_handshake(peerupdate)))
        goto end;
    tmp = SSL_get_wbio(peerwrite);
    if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {
        tmp = NULL;
        goto end;
    }
    SSL_set0_wbio(peerwrite, bretry);
    bretry = NULL;
    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1)
            || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE))
        goto end;
    SSL_set0_wbio(peerwrite, tmp);
    tmp = NULL;
    if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1)
            || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ))
        goto end;
    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))
            || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))
        goto end;
    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))
            || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))
        goto end;
    testresult = 1;
 end:
    SSL_free(serverssl);
    SSL_free(clientssl);
    SSL_CTX_free(sctx);
    SSL_CTX_free(cctx);
    BIO_free(bretry);
    BIO_free(tmp);
    return testresult;
}
['static int test_key_update_in_write(int tst)\n{\n    SSL_CTX *cctx = NULL, *sctx = NULL;\n    SSL *clientssl = NULL, *serverssl = NULL;\n    int testresult = 0;\n    char buf[20];\n    static char *mess = "A test message";\n    BIO *bretry = BIO_new(bio_s_always_retry());\n    BIO *tmp = NULL;\n    SSL *peerupdate = NULL, *peerwrite = NULL;\n    if (!TEST_ptr(bretry)\n            || !TEST_true(create_ssl_ctx_pair(TLS_server_method(),\n                                              TLS_client_method(),\n                                              TLS1_3_VERSION,\n                                              0,\n                                              &sctx, &cctx, cert, privkey))\n            || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,\n                                             NULL, NULL))\n            || !TEST_true(create_ssl_connection(serverssl, clientssl,\n                                                SSL_ERROR_NONE)))\n        goto end;\n    peerupdate = tst == 0 ? clientssl : serverssl;\n    peerwrite = tst == 0 ? serverssl : clientssl;\n    if (!TEST_true(SSL_key_update(peerupdate, SSL_KEY_UPDATE_REQUESTED))\n            || !TEST_true(SSL_do_handshake(peerupdate)))\n        goto end;\n    tmp = SSL_get_wbio(peerwrite);\n    if (!TEST_ptr(tmp) || !TEST_true(BIO_up_ref(tmp))) {\n        tmp = NULL;\n        goto end;\n    }\n    SSL_set0_wbio(peerwrite, bretry);\n    bretry = NULL;\n    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1)\n            || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE))\n        goto end;\n    SSL_set0_wbio(peerwrite, tmp);\n    tmp = NULL;\n    if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1)\n            || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ))\n        goto end;\n    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))\n            || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))\n        goto end;\n    if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), strlen(mess))\n            || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess)))\n        goto end;\n    testresult = 1;\n end:\n    SSL_free(serverssl);\n    SSL_free(clientssl);\n    SSL_CTX_free(sctx);\n    SSL_CTX_free(cctx);\n    BIO_free(bretry);\n    BIO_free(tmp);\n    return testresult;\n}', 'const BIO_METHOD *bio_s_always_retry(void)\n{\n    if (meth_always_retry == NULL) {\n        if (!TEST_ptr(meth_always_retry = BIO_meth_new(BIO_TYPE_ALWAYS_RETRY,\n                                                       "Always Retry"))\n            || !TEST_true(BIO_meth_set_write(meth_always_retry,\n                                             always_retry_write))\n            || !TEST_true(BIO_meth_set_read(meth_always_retry,\n                                            always_retry_read))\n            || !TEST_true(BIO_meth_set_puts(meth_always_retry,\n                                            always_retry_puts))\n            || !TEST_true(BIO_meth_set_gets(meth_always_retry,\n                                            always_retry_gets))\n            || !TEST_true(BIO_meth_set_ctrl(meth_always_retry,\n                                            always_retry_ctrl))\n            || !TEST_true(BIO_meth_set_create(meth_always_retry,\n                                              always_retry_new))\n            || !TEST_true(BIO_meth_set_destroy(meth_always_retry,\n                                               always_retry_free)))\n            return NULL;\n    }\n    return meth_always_retry;\n}', 'int test_ptr(const char *file, int line, const char *s, const void *p)\n{\n    if (p != NULL)\n        return 1;\n    test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);\n    return 0;\n}', 'int BIO_meth_set_write(BIO_METHOD *biom,\n                       int (*bwrite) (BIO *, const char *, int))\n{\n    biom->bwrite_old = bwrite;\n    biom->bwrite = bwrite_conv;\n    return 1;\n}', 'int test_true(const char *file, int line, const char *s, int b)\n{\n    if (b)\n        return 1;\n    test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");\n    return 0;\n}', 'int BIO_meth_set_read(BIO_METHOD *biom,\n                      int (*bread) (BIO *, char *, int))\n{\n    biom->bread_old = bread;\n    biom->bread = bread_conv;\n    return 1;\n}', 'int BIO_meth_set_puts(BIO_METHOD *biom,\n                      int (*bputs) (BIO *, const char *))\n{\n    biom->bputs = bputs;\n    return 1;\n}', 'int BIO_meth_set_gets(BIO_METHOD *biom,\n                      int (*bgets) (BIO *, char *, int))\n{\n    biom->bgets = bgets;\n    return 1;\n}', 'int BIO_meth_set_ctrl(BIO_METHOD *biom,\n                      long (*ctrl) (BIO *, int, long, void *))\n{\n    biom->ctrl = ctrl;\n    return 1;\n}', 'int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))\n{\n    biom->create = create;\n    return 1;\n}', 'int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))\n{\n    biom->destroy = destroy;\n    return 1;\n}', 'void SSL_CTX_free(SSL_CTX *a)\n{\n    int i;\n    if (a == NULL)\n        return;\n    CRYPTO_DOWN_REF(&a->references, &i, a->lock);\n    REF_PRINT_COUNT("SSL_CTX", a);\n    if (i > 0)\n        return;\n    REF_ASSERT_ISNT(i < 0);\n    X509_VERIFY_PARAM_free(a->param);\n    dane_ctx_final(&a->dane);\n    if (a->sessions != NULL)\n        SSL_CTX_flush_sessions(a, 0);\n    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);\n    lh_SSL_SESSION_free(a->sessions);\n    X509_STORE_free(a->cert_store);\n#ifndef OPENSSL_NO_CT\n    CTLOG_STORE_free(a->ctlog_store);\n#endif\n    sk_SSL_CIPHER_free(a->cipher_list);\n    sk_SSL_CIPHER_free(a->cipher_list_by_id);\n    sk_SSL_CIPHER_free(a->tls13_ciphersuites);\n    ssl_cert_free(a->cert);\n    sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free);\n    sk_X509_NAME_pop_free(a->client_ca_names, X509_NAME_free);\n    sk_X509_pop_free(a->extra_certs, X509_free);\n    a->comp_methods = NULL;\n#ifndef OPENSSL_NO_SRTP\n    sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);\n#endif\n#ifndef OPENSSL_NO_SRP\n    SSL_CTX_SRP_CTX_free(a);\n#endif\n#ifndef OPENSSL_NO_ENGINE\n    ENGINE_finish(a->client_cert_engine);\n#endif\n#ifndef OPENSSL_NO_EC\n    OPENSSL_free(a->ext.ecpointformats);\n    OPENSSL_free(a->ext.supportedgroups);\n#endif\n    OPENSSL_free(a->ext.alpn);\n    OPENSSL_secure_free(a->ext.secure);\n    CRYPTO_THREAD_lock_free(a->lock);\n    OPENSSL_free(a);\n}', 'static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock)\n{\n    *ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1;\n    if (*ret == 0)\n        atomic_thread_fence(memory_order_acquire);\n    return 1;\n}']