1 1.1 christos /* 2 1.1 christos * Copyright 2017-2025 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos 10 1.1 christos #include "../testutil.h" 11 1.1 christos #include "output.h" 12 1.1 christos #include "tu_local.h" 13 1.1 christos 14 1.1 christos #include <openssl/crypto.h> 15 1.1 christos #include <openssl/bio.h> 16 1.1 christos 17 1.1 christos /* These are available for any test program */ 18 1.1 christos BIO *bio_out = NULL; 19 1.1 christos BIO *bio_err = NULL; 20 1.1 christos 21 1.1 christos /* These are available for TAP output only (internally) */ 22 1.1 christos static BIO *tap_out = NULL; 23 1.1 christos static BIO *tap_err = NULL; 24 1.1 christos 25 1.1 christos typedef struct local_test_data_st { 26 1.1 christos BIO *override_bio_out, *override_bio_err; 27 1.1 christos } LOCAL_TEST_DATA; 28 1.1 christos 29 1.1 christos #if defined(OPENSSL_THREADS) 30 1.1 christos static CRYPTO_THREAD_LOCAL local_test_data; /* (LOCAL_TEST_DATA *) */ 31 1.1 christos 32 1.1 christos static CRYPTO_RWLOCK *io_lock = NULL; 33 1.1 christos #endif 34 1.1 christos 35 1.1 christos #if defined(OPENSSL_THREADS) 36 1.1 christos static void cleanup_test_data(void *p) 37 1.1 christos { 38 1.1 christos OPENSSL_free(p); 39 1.1 christos } 40 1.1 christos #endif 41 1.1 christos 42 1.1 christos static int init_local_test_data(void) 43 1.1 christos { 44 1.1 christos #if defined(OPENSSL_THREADS) 45 1.1 christos if (!CRYPTO_THREAD_init_local(&local_test_data, cleanup_test_data)) 46 1.1 christos return 0; 47 1.1 christos #endif 48 1.1 christos 49 1.1 christos return 1; 50 1.1 christos } 51 1.1 christos 52 1.1 christos static LOCAL_TEST_DATA *get_local_test_data(void) 53 1.1 christos { 54 1.1 christos #if defined(OPENSSL_THREADS) 55 1.1 christos LOCAL_TEST_DATA *p; 56 1.1 christos 57 1.1 christos p = CRYPTO_THREAD_get_local(&local_test_data); 58 1.1 christos if (p != NULL) 59 1.1 christos return p; 60 1.1 christos 61 1.1 christos if ((p = OPENSSL_zalloc(sizeof(*p))) == NULL) 62 1.1 christos return NULL; 63 1.1 christos 64 1.1 christos if (!CRYPTO_THREAD_set_local(&local_test_data, p)) { 65 1.1 christos OPENSSL_free(p); 66 1.1 christos return NULL; 67 1.1 christos } 68 1.1 christos 69 1.1 christos return p; 70 1.1 christos #else 71 1.1 christos return NULL; 72 1.1 christos #endif 73 1.1 christos } 74 1.1 christos 75 1.1 christos static void cleanup_local_test_data(void) 76 1.1 christos { 77 1.1 christos #if defined(OPENSSL_THREADS) 78 1.1 christos LOCAL_TEST_DATA *p; 79 1.1 christos 80 1.1 christos p = CRYPTO_THREAD_get_local(&local_test_data); 81 1.1 christos if (p == NULL) 82 1.1 christos return; 83 1.1 christos 84 1.1 christos CRYPTO_THREAD_set_local(&local_test_data, NULL); 85 1.1 christos OPENSSL_free(p); 86 1.1 christos #endif 87 1.1 christos } 88 1.1 christos 89 1.1 christos int set_override_bio_out(BIO *bio) 90 1.1 christos { 91 1.1 christos LOCAL_TEST_DATA *data = get_local_test_data(); 92 1.1 christos 93 1.1 christos if (data == NULL) 94 1.1 christos return 0; 95 1.1 christos 96 1.1 christos data->override_bio_out = bio; 97 1.1 christos return 1; 98 1.1 christos } 99 1.1 christos 100 1.1 christos int set_override_bio_err(BIO *bio) 101 1.1 christos { 102 1.1 christos LOCAL_TEST_DATA *data = get_local_test_data(); 103 1.1 christos 104 1.1 christos if (data == NULL) 105 1.1 christos return 0; 106 1.1 christos 107 1.1 christos data->override_bio_err = bio; 108 1.1 christos return 1; 109 1.1 christos } 110 1.1 christos 111 1.1 christos static BIO *get_bio_out(void) 112 1.1 christos { 113 1.1 christos LOCAL_TEST_DATA *data = get_local_test_data(); 114 1.1 christos 115 1.1 christos if (data != NULL && data->override_bio_out != NULL) 116 1.1 christos return data->override_bio_out; 117 1.1 christos 118 1.1 christos return bio_out; 119 1.1 christos } 120 1.1 christos 121 1.1 christos static BIO *get_bio_err(void) 122 1.1 christos { 123 1.1 christos LOCAL_TEST_DATA *data = get_local_test_data(); 124 1.1 christos 125 1.1 christos if (data != NULL && data->override_bio_err != NULL) 126 1.1 christos return data->override_bio_err; 127 1.1 christos 128 1.1 christos return bio_err; 129 1.1 christos } 130 1.1 christos 131 1.1 christos void test_open_streams(void) 132 1.1 christos { 133 1.1 christos int ok; 134 1.1 christos 135 1.1 christos ok = init_local_test_data(); 136 1.1 christos 137 1.1 christos tap_out = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); 138 1.1 christos tap_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT); 139 1.1 christos #ifdef __VMS 140 1.1 christos tap_out = BIO_push(BIO_new(BIO_f_linebuffer()), tap_out); 141 1.1 christos tap_err = BIO_push(BIO_new(BIO_f_linebuffer()), tap_err); 142 1.1 christos #endif 143 1.1 christos tap_out = BIO_push(BIO_new(BIO_f_prefix()), tap_out); 144 1.1 christos tap_err = BIO_push(BIO_new(BIO_f_prefix()), tap_err); 145 1.1 christos 146 1.1 christos bio_out = BIO_push(BIO_new(BIO_f_prefix()), tap_out); 147 1.1 christos bio_err = BIO_push(BIO_new(BIO_f_prefix()), tap_err); 148 1.1 christos BIO_set_prefix(bio_out, "# "); 149 1.1 christos BIO_set_prefix(bio_err, "# "); 150 1.1 christos 151 1.1 christos #if defined(OPENSSL_THREADS) 152 1.1 christos io_lock = CRYPTO_THREAD_lock_new(); 153 1.1 christos #endif 154 1.1 christos 155 1.1 christos OPENSSL_assert(ok); 156 1.1 christos OPENSSL_assert(bio_out != NULL); 157 1.1 christos OPENSSL_assert(bio_err != NULL); 158 1.1 christos #if defined(OPENSSL_THREADS) 159 1.1 christos OPENSSL_assert(io_lock != NULL); 160 1.1 christos #endif 161 1.1 christos } 162 1.1 christos 163 1.1 christos void test_adjust_streams_tap_level(int level) 164 1.1 christos { 165 1.1 christos BIO_set_indent(tap_out, level); 166 1.1 christos BIO_set_indent(tap_err, level); 167 1.1 christos } 168 1.1 christos 169 1.1 christos void test_close_streams(void) 170 1.1 christos { 171 1.1 christos /* 172 1.1 christos * The rest of the chain is freed by the BIO_free_all() calls below, so 173 1.1 christos * we only need to free the last one in the bio_out and bio_err chains. 174 1.1 christos */ 175 1.1 christos BIO_free(bio_out); 176 1.1 christos BIO_free(bio_err); 177 1.1 christos 178 1.1 christos BIO_free_all(tap_out); 179 1.1 christos BIO_free_all(tap_err); 180 1.1 christos 181 1.1 christos cleanup_local_test_data(); 182 1.1 christos 183 1.1 christos #if defined(OPENSSL_THREADS) 184 1.1 christos CRYPTO_THREAD_lock_free(io_lock); 185 1.1 christos #endif 186 1.1 christos } 187 1.1 christos 188 1.1 christos static ossl_inline void test_io_lock(void) 189 1.1 christos { 190 1.1 christos #if defined(OPENSSL_THREADS) 191 1.1 christos OPENSSL_assert(CRYPTO_THREAD_write_lock(io_lock) > 0); 192 1.1 christos #endif 193 1.1 christos } 194 1.1 christos 195 1.1 christos static ossl_inline void test_io_unlock(void) 196 1.1 christos { 197 1.1 christos #if defined(OPENSSL_THREADS) 198 1.1 christos CRYPTO_THREAD_unlock(io_lock); 199 1.1 christos #endif 200 1.1 christos } 201 1.1 christos 202 1.1 christos int test_vprintf_stdout(const char *fmt, va_list ap) 203 1.1 christos { 204 1.1 christos int r; 205 1.1 christos 206 1.1 christos test_io_lock(); 207 1.1 christos r = BIO_vprintf(get_bio_out(), fmt, ap); 208 1.1 christos test_io_unlock(); 209 1.1 christos 210 1.1 christos return r; 211 1.1 christos } 212 1.1 christos 213 1.1 christos int test_vprintf_stderr(const char *fmt, va_list ap) 214 1.1 christos { 215 1.1 christos int r; 216 1.1 christos 217 1.1 christos test_io_lock(); 218 1.1 christos r = BIO_vprintf(get_bio_err(), fmt, ap); 219 1.1 christos test_io_unlock(); 220 1.1 christos 221 1.1 christos return r; 222 1.1 christos } 223 1.1 christos 224 1.1 christos int test_flush_stdout(void) 225 1.1 christos { 226 1.1 christos int r; 227 1.1 christos 228 1.1 christos test_io_lock(); 229 1.1 christos r = BIO_flush(get_bio_out()); 230 1.1 christos test_io_unlock(); 231 1.1 christos 232 1.1 christos return r; 233 1.1 christos } 234 1.1 christos 235 1.1 christos int test_flush_stderr(void) 236 1.1 christos { 237 1.1 christos int r; 238 1.1 christos 239 1.1 christos test_io_lock(); 240 1.1 christos r = BIO_flush(get_bio_err()); 241 1.1 christos test_io_unlock(); 242 1.1 christos 243 1.1 christos return r; 244 1.1 christos } 245 1.1 christos 246 1.1 christos int test_vprintf_tapout(const char *fmt, va_list ap) 247 1.1 christos { 248 1.1 christos int r; 249 1.1 christos 250 1.1 christos test_io_lock(); 251 1.1 christos r = BIO_vprintf(tap_out, fmt, ap); 252 1.1 christos test_io_unlock(); 253 1.1 christos 254 1.1 christos return r; 255 1.1 christos } 256 1.1 christos 257 1.1 christos int test_vprintf_taperr(const char *fmt, va_list ap) 258 1.1 christos { 259 1.1 christos int r; 260 1.1 christos 261 1.1 christos test_io_lock(); 262 1.1 christos r = BIO_vprintf(tap_err, fmt, ap); 263 1.1 christos test_io_unlock(); 264 1.1 christos 265 1.1 christos return r; 266 1.1 christos } 267 1.1 christos 268 1.1 christos int test_flush_tapout(void) 269 1.1 christos { 270 1.1 christos int r; 271 1.1 christos 272 1.1 christos test_io_lock(); 273 1.1 christos r = BIO_flush(tap_out); 274 1.1 christos test_io_unlock(); 275 1.1 christos 276 1.1 christos return r; 277 1.1 christos } 278 1.1 christos 279 1.1 christos int test_flush_taperr(void) 280 1.1 christos { 281 1.1 christos int r; 282 1.1 christos 283 1.1 christos test_io_lock(); 284 1.1 christos r = BIO_flush(tap_err); 285 1.1 christos test_io_unlock(); 286 1.1 christos 287 1.1 christos return r; 288 1.1 christos } 289