From acbae997b5ba9bd65a06cdaa89cdb5dbd9208bac Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Mon, 5 Feb 2024 17:35:33 +0000 Subject: testutil: Allow overriding output BIOs thread-locally Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23487) --- test/testutil.h | 4 ++ test/testutil/basic_output.c | 117 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 117 insertions(+), 4 deletions(-) diff --git a/test/testutil.h b/test/testutil.h index a247f55ed6..c23ad558c9 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -562,6 +562,10 @@ void test_perror(const char *s); extern BIO *bio_out; extern BIO *bio_err; +/* Thread local BIO overrides. */ +int set_override_bio_out(BIO *bio); +int set_override_bio_err(BIO *bio); + /* * Formatted output for strings, memory and bignums. */ diff --git a/test/testutil/basic_output.c b/test/testutil/basic_output.c index 5297b350e7..9637fee6ff 100644 --- a/test/testutil/basic_output.c +++ b/test/testutil/basic_output.c @@ -22,12 +22,118 @@ BIO *bio_err = NULL; static BIO *tap_out = NULL; static BIO *tap_err = NULL; +typedef struct local_test_data_st { + BIO *override_bio_out, *override_bio_err; +} LOCAL_TEST_DATA; + #if defined(OPENSSL_THREADS) +static CRYPTO_THREAD_LOCAL local_test_data; /* (LOCAL_TEST_DATA *) */ + static CRYPTO_RWLOCK *io_lock = NULL; #endif +#if defined(OPENSSL_THREADS) +static void cleanup_test_data(void *p) +{ + OPENSSL_free(p); +} +#endif + +static int init_local_test_data(void) +{ +#if defined(OPENSSL_THREADS) + if (!CRYPTO_THREAD_init_local(&local_test_data, cleanup_test_data)) + return 0; +#endif + + return 1; +} + +static LOCAL_TEST_DATA *get_local_test_data(void) +{ +#if defined(OPENSSL_THREADS) + LOCAL_TEST_DATA *p; + + p = CRYPTO_THREAD_get_local(&local_test_data); + if (p != NULL) + return p; + + if ((p = OPENSSL_zalloc(sizeof(*p))) == NULL) + return NULL; + + if (!CRYPTO_THREAD_set_local(&local_test_data, p)) { + OPENSSL_free(p); + return NULL; + } + + return p; +#else + return NULL; +#endif +} + +static void cleanup_local_test_data(void) +{ +#if defined(OPENSSL_THREADS) + LOCAL_TEST_DATA *p; + + p = CRYPTO_THREAD_get_local(&local_test_data); + if (p == NULL) + return; + + CRYPTO_THREAD_set_local(&local_test_data, NULL); + OPENSSL_free(p); +#endif +} + +int set_override_bio_out(BIO *bio) +{ + LOCAL_TEST_DATA *data = get_local_test_data(); + + if (data == NULL) + return 0; + + data->override_bio_out = bio; + return 1; +} + +int set_override_bio_err(BIO *bio) +{ + LOCAL_TEST_DATA *data = get_local_test_data(); + + if (data == NULL) + return 0; + + data->override_bio_err = bio; + return 1; +} + +static BIO *get_bio_out(void) +{ + LOCAL_TEST_DATA *data = get_local_test_data(); + + if (data != NULL && data->override_bio_out != NULL) + return data->override_bio_out; + + return bio_out; +} + +static BIO *get_bio_err(void) +{ + LOCAL_TEST_DATA *data = get_local_test_data(); + + if (data != NULL && data->override_bio_err != NULL) + return data->override_bio_err; + + return bio_err; +} + void test_open_streams(void) { + int ok; + + ok = init_local_test_data(); + tap_out = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); tap_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); #ifdef __VMS @@ -46,6 +152,7 @@ void test_open_streams(void) io_lock = CRYPTO_THREAD_lock_new(); #endif + OPENSSL_assert(ok); OPENSSL_assert(bio_out != NULL); OPENSSL_assert(bio_err != NULL); #if defined(OPENSSL_THREADS) @@ -71,6 +178,8 @@ void test_close_streams(void) BIO_free_all(tap_out); BIO_free_all(tap_err); + cleanup_local_test_data(); + #if defined(OPENSSL_THREADS) CRYPTO_THREAD_lock_free(io_lock); #endif @@ -95,7 +204,7 @@ int test_vprintf_stdout(const char *fmt, va_list ap) int r; test_io_lock(); - r = BIO_vprintf(bio_out, fmt, ap); + r = BIO_vprintf(get_bio_out(), fmt, ap); test_io_unlock(); return r; @@ -106,7 +215,7 @@ int test_vprintf_stderr(const char *fmt, va_list ap) int r; test_io_lock(); - r = BIO_vprintf(bio_err, fmt, ap); + r = BIO_vprintf(get_bio_err(), fmt, ap); test_io_unlock(); return r; @@ -117,7 +226,7 @@ int test_flush_stdout(void) int r; test_io_lock(); - r = BIO_flush(bio_out); + r = BIO_flush(get_bio_out()); test_io_unlock(); return r; @@ -128,7 +237,7 @@ int test_flush_stderr(void) int r; test_io_lock(); - r = BIO_flush(bio_err); + r = BIO_flush(get_bio_err()); test_io_unlock(); return r; -- cgit v1.2.3