diff options
Diffstat (limited to 'test/testutil/basic_output.c')
-rw-r--r-- | test/testutil/basic_output.c | 204 |
1 files changed, 195 insertions, 9 deletions
diff --git a/test/testutil/basic_output.c b/test/testutil/basic_output.c index 92f3de9300cc..110cc252d4e8 100644 --- a/test/testutil/basic_output.c +++ b/test/testutil/basic_output.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -22,8 +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 @@ -38,8 +148,16 @@ void test_open_streams(void) BIO_set_prefix(bio_out, "# "); BIO_set_prefix(bio_err, "# "); +#if defined(OPENSSL_THREADS) + io_lock = CRYPTO_THREAD_lock_new(); +#endif + + OPENSSL_assert(ok); OPENSSL_assert(bio_out != NULL); OPENSSL_assert(bio_err != NULL); +#if defined(OPENSSL_THREADS) + OPENSSL_assert(io_lock != NULL); +#endif } void test_adjust_streams_tap_level(int level) @@ -59,44 +177,112 @@ 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 +} + +static ossl_inline void test_io_lock(void) +{ +#if defined(OPENSSL_THREADS) + OPENSSL_assert(CRYPTO_THREAD_write_lock(io_lock) > 0); +#endif +} + +static ossl_inline void test_io_unlock(void) +{ +#if defined(OPENSSL_THREADS) + CRYPTO_THREAD_unlock(io_lock); +#endif } int test_vprintf_stdout(const char *fmt, va_list ap) { - return BIO_vprintf(bio_out, fmt, ap); + int r; + + test_io_lock(); + r = BIO_vprintf(get_bio_out(), fmt, ap); + test_io_unlock(); + + return r; } int test_vprintf_stderr(const char *fmt, va_list ap) { - return BIO_vprintf(bio_err, fmt, ap); + int r; + + test_io_lock(); + r = BIO_vprintf(get_bio_err(), fmt, ap); + test_io_unlock(); + + return r; } int test_flush_stdout(void) { - return BIO_flush(bio_out); + int r; + + test_io_lock(); + r = BIO_flush(get_bio_out()); + test_io_unlock(); + + return r; } int test_flush_stderr(void) { - return BIO_flush(bio_err); + int r; + + test_io_lock(); + r = BIO_flush(get_bio_err()); + test_io_unlock(); + + return r; } int test_vprintf_tapout(const char *fmt, va_list ap) { - return BIO_vprintf(tap_out, fmt, ap); + int r; + + test_io_lock(); + r = BIO_vprintf(tap_out, fmt, ap); + test_io_unlock(); + + return r; } int test_vprintf_taperr(const char *fmt, va_list ap) { - return BIO_vprintf(tap_err, fmt, ap); + int r; + + test_io_lock(); + r = BIO_vprintf(tap_err, fmt, ap); + test_io_unlock(); + + return r; } int test_flush_tapout(void) { - return BIO_flush(tap_out); + int r; + + test_io_lock(); + r = BIO_flush(tap_out); + test_io_unlock(); + + return r; } int test_flush_taperr(void) { - return BIO_flush(tap_err); + int r; + + test_io_lock(); + r = BIO_flush(tap_err); + test_io_unlock(); + + return r; } |