From a44599827ceb9cae19f843e13675d59a8e0eccd1 Mon Sep 17 00:00:00 2001 From: Edmond <1571649+edmonddantes@users.noreply.github.com> Date: Fri, 3 Jul 2026 16:12:58 +0000 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20built-in=20hot-reload=20triggers=20?= =?UTF-8?q?=E2=80=94=20enableHotReload=20(watcher)=20+=20enableReloadOnSig?= =?UTF-8?q?nal=20(SIGHUP)=20(#93)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HttpServerConfig::enableHotReload(watchPaths, extensions, debounceMs, maxHoldMs): the pool parent arms one recursive Async\FileSystemWatcher per path (engine-side debounce collapses change bursts); each delivered event invalidates the watched trees in opcache and rotates the pool via HttpServer::reload(). Config fields are parent-only, never snapshotted. - HttpServerConfig::enableReloadOnSignal(): a persistent SIGHUP event armed for the whole pool run (no unarmed window between deliveries), each delivery is one rotation. Throws on Windows. - Orchestrators are internal main-scope coroutines on the parent; teardown closes the watchers (ends their iterators) and notifies the signal waiter, which observes hot_reload_stopping and disposes its own event. - Logged through the parent's http_log: reload.watch armed/failed, reload.signal armed, reload.trigger source=watcher|sighup. - reload() now refuses under TRUE_ASYNC_SERVER_REACTOR_POOL=1: reactors route through worker inboxes registered for the pool's lifetime and there is no registry unregister yet — retiring workers under live reactors corrupted the heap (found by the new h3 test). Guard + test document the limit until inbox rotation lands (#80 follow-up). - tests: 053 watcher e2e (file edit -> new code served, no manual reload), 054 SIGHUP rotation, websocket/034 reload with a live WS connection (old conn retired, fresh cohort serves WS), h3/045 reactor-pool guard. Full sweep: 277 passed, 0 failed. --- include/php_http_server.h | 9 + src/http_server_class.c | 462 ++++++++++++++++++ src/http_server_config.c | 120 +++++ stubs/HttpServerConfig.php | 21 + stubs/HttpServerConfig.php_arginfo.h | 17 +- .../server/core/053-hot-reload-watcher.phpt | 77 +++ .../server/core/054-hot-reload-sighup.phpt | 79 +++ .../server/h3/045-h3-reload-reactor-pool.phpt | 90 ++++ tests/phpt/websocket/034-hot-reload-ws.phpt | 146 ++++++ 9 files changed, 1020 insertions(+), 1 deletion(-) create mode 100644 tests/phpt/server/core/053-hot-reload-watcher.phpt create mode 100644 tests/phpt/server/core/054-hot-reload-sighup.phpt create mode 100644 tests/phpt/server/h3/045-h3-reload-reactor-pool.phpt create mode 100644 tests/phpt/websocket/034-hot-reload-ws.phpt diff --git a/include/php_http_server.h b/include/php_http_server.h index 512747c..ae39b59 100644 --- a/include/php_http_server.h +++ b/include/php_http_server.h @@ -307,6 +307,15 @@ struct _http_server_config_t { zval log_stream; bool telemetry_enabled; + /* Hot-reload triggers (issue #93) — consumed by the pool parent only + * (the orchestrator coroutines run there), never snapshotted. + * hot_reload_paths IS_UNDEF = watcher trigger off. */ + zval hot_reload_paths; /* array of directories to watch */ + zval hot_reload_extensions; /* array of extensions; empty = all */ + uint32_t hot_reload_debounce_ms; + uint32_t hot_reload_max_hold_ms; + bool reload_on_sighup; + /* Frozen persistent snapshot — populated at lock time, shared refcounted * across threads. NULL until the owning HttpServer constructs (which calls * http_server_config_lock) or the Config is transferred directly via a diff --git a/src/http_server_class.c b/src/http_server_class.c index 867c689..52198f0 100644 --- a/src/http_server_class.c +++ b/src/http_server_class.c @@ -33,6 +33,10 @@ #include "core/worker_registry.h" #include "core/response_wire.h" #include "log/http_log.h" +#ifndef PHP_WIN32 +#include +#include +#endif #include "static/static_handler.h" #include "static/http_static_cache.h" #ifdef HAVE_HTTP_SERVER_HTTP3 @@ -479,6 +483,14 @@ struct http_server_object { bool reload_in_progress;/* parent: one rotation at a time */ void *pool_await_state; /* parent: st of the active pool run */ + /* Hot-reload triggers (issue #93), pool parent only. Watcher objects are + * closed and released by http_server_hot_reload_down; the SIGHUP event is + * owned by its orchestrator coroutine (the pointer here only lets teardown + * wake it). */ + zval hot_reload_watchers; /* array of Async\FileSystemWatcher */ + void *sighup_event; /* zend_async_signal_event_t* */ + bool hot_reload_stopping; /* orchestrators must exit */ + /* Transit sidecar — non-NULL only in the persistent shell created by * transfer_obj(TRANSFER). Holds pemalloc-copied closures so the LOAD * side can rebuild fcall_t entries in the destination thread's heap. @@ -576,6 +588,9 @@ typedef struct { } http_server_reload_shared_t; static void http_server_do_stop(http_server_object *server, const char *reason); +static void http_server_hot_reload_up(http_server_object *server, zval *this_zv, + http_server_config_t *cfg); +static void http_server_hot_reload_down(http_server_object *server); /* Runs on a fresh coroutine enqueued by the deadline tick: stop() disposes that * very tick timer, which must not happen from inside its own callback. */ @@ -2710,6 +2725,12 @@ static int http_server_start_pool(http_server_object *server, server->in_pool_mode = true; server->running = true; + /* Arm hot-reload triggers (issue #93) on the parent before it suspends. */ + if (boot_cfg != NULL + && (Z_TYPE(boot_cfg->hot_reload_paths) == IS_ARRAY || boot_cfg->reload_on_sighup)) { + http_server_hot_reload_up(server, this_zv, boot_cfg); + } + /* Suspend until all submitted workers report done. Skip the suspend * entirely when nothing got submitted — there is no callback to * notify all_done, so awaiting on it would deadlock. */ @@ -2741,6 +2762,9 @@ static int http_server_start_pool(http_server_object *server, server->worker_pool = NULL; server->pool_await_state = NULL; + /* Retire the hot-reload orchestrators before the pool machinery goes. */ + http_server_hot_reload_down(server); + /* Workers have quiesced (the suspend returned). Tear down the transport * reactor pool: this releases the H3 listeners the gated reactors own, * frees the worker registry, and stops the reactor loops. */ @@ -3630,6 +3654,17 @@ ZEND_METHOD(TrueAsync_HttpServer, reload) RETURN_THROWS(); } + /* The gated transport reactor pool (#80) routes requests through worker + * inboxes registered for the pool's lifetime; retiring a worker while the + * reactors are live would leave them posting into freed inboxes (there is + * no registry unregister yet). Refuse loudly instead of corrupting. */ + if (UNEXPECTED(http_server_reactor_pool_enabled())) { + zend_throw_exception(http_server_runtime_exception_ce, + "reload() is not yet supported with TRUE_ASYNC_SERVER_REACTOR_POOL=1 " + "(worker inbox rotation is not implemented, #93)", 0); + RETURN_THROWS(); + } + if (server->reload_in_progress) { RETURN_FALSE; /* one rotation at a time — call again after it returns */ } @@ -3743,6 +3778,433 @@ ZEND_METHOD(TrueAsync_HttpServer, reload) } /* }}} */ +/* ========================================================================== + * Hot-reload triggers (issue #93) — pool-parent orchestrators. + * ========================================================================== */ + +typedef struct { + zend_object *server_obj; /* addref'd parent HttpServer */ + zval watcher; /* owned Async\FileSystemWatcher */ +} hot_reload_watch_ctx_t; + +typedef struct { + zend_object *server_obj; +} hot_reload_sighup_ctx_t; + +static void hot_reload_watch_ctx_dispose(zend_coroutine_t *co) +{ + hot_reload_watch_ctx_t *ctx = co->extended_data; + + if (ctx == NULL) { + return; + } + + co->extended_data = NULL; + zval_ptr_dtor(&ctx->watcher); + OBJ_RELEASE(ctx->server_obj); + efree(ctx); +} + +static void hot_reload_sighup_ctx_dispose(zend_coroutine_t *co) +{ + hot_reload_sighup_ctx_t *ctx = co->extended_data; + + if (ctx == NULL) { + return; + } + + co->extended_data = NULL; + OBJ_RELEASE(ctx->server_obj); + efree(ctx); +} + +#ifndef PHP_WIN32 +/* Case-insensitive extension allow-list check; NULL/empty list = every file. */ +static bool hot_reload_ext_matches(const HashTable *exts, const char *name) +{ + if (exts == NULL || zend_hash_num_elements((HashTable *)exts) == 0) { + return true; + } + + const char *dot = strrchr(name, '.'); + + if (dot == NULL || dot[1] == '\0') { + return false; + } + + const zval *entry; + ZEND_HASH_FOREACH_VAL((HashTable *)exts, entry) + { + if (Z_TYPE_P(entry) != IS_STRING) { + continue; + } + + const char *e = Z_STRVAL_P(entry); + + if (e[0] == '.') { + e++; + } + + if (strcasecmp(dot + 1, e) == 0) { + return true; + } + } + ZEND_HASH_FOREACH_END(); + + return false; +} + +/* opcache_invalidate($file, true) for every matching file under `dir`. + * `fname` is the pre-resolved "opcache_invalidate" callable zval. */ +static void hot_reload_invalidate_tree(const char *dir, const HashTable *exts, + zval *fname, const int depth) +{ + if (depth > 16) { + return; + } + + DIR *d = opendir(dir); + + if (d == NULL) { + return; + } + + const struct dirent *ent; + + while ((ent = readdir(d)) != NULL) { + if (ent->d_name[0] == '.' + && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) { + continue; + } + + char full[MAXPATHLEN]; + + if ((size_t)snprintf(full, sizeof(full), "%s/%s", dir, ent->d_name) >= sizeof(full)) { + continue; + } + + struct stat st; + + if (lstat(full, &st) != 0) { + continue; + } + + if (S_ISDIR(st.st_mode)) { + hot_reload_invalidate_tree(full, exts, fname, depth + 1); + continue; + } + + if (!S_ISREG(st.st_mode) || !hot_reload_ext_matches(exts, ent->d_name)) { + continue; + } + + zval rv, params[2]; + ZVAL_UNDEF(&rv); + ZVAL_STRING(¶ms[0], full); + ZVAL_TRUE(¶ms[1]); + call_user_function(NULL, NULL, fname, &rv, 2, params); + zval_ptr_dtor(¶ms[0]); + zval_ptr_dtor(&rv); + + if (EG(exception)) { + zend_clear_exception(); + } + } + + closedir(d); +} +#endif /* !PHP_WIN32 */ + +/* One trigger firing: invalidate the watched trees in opcache (so replacement + * bootloaders recompile the changed files) and rotate via HttpServer::reload(). */ +static void http_server_hot_reload_fire(zend_object *server_obj, const char *trigger) +{ + http_server_object *server = http_server_from_obj(server_obj); + + if (server->hot_reload_stopping || !server->in_pool_mode) { + return; + } + + http_logf_info(&server->log_state, "reload.trigger source=%s", trigger); + +#ifndef PHP_WIN32 + http_server_config_t *cfg = http_server_get_config(server); + + if (cfg != NULL && Z_TYPE(cfg->hot_reload_paths) == IS_ARRAY) { + zval fname; + ZVAL_STRING(&fname, "opcache_invalidate"); + + if (zend_is_callable(&fname, 0, NULL)) { + const HashTable *exts = (Z_TYPE(cfg->hot_reload_extensions) == IS_ARRAY) + ? Z_ARRVAL(cfg->hot_reload_extensions) : NULL; + const zval *path; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(cfg->hot_reload_paths), path) + { + hot_reload_invalidate_tree(Z_STRVAL_P(path), exts, &fname, 0); + } + ZEND_HASH_FOREACH_END(); + } + + zval_ptr_dtor(&fname); + } +#endif + + zval rv; + ZVAL_UNDEF(&rv); + zend_call_method_with_0_params(server_obj, NULL, NULL, "reload", &rv); + zval_ptr_dtor(&rv); + + if (EG(exception)) { + http_logf_info(&server->log_state, "reload.trigger source=%s failed", trigger); + zend_clear_exception(); + } +} + +/* Coroutine: drive one watcher's iterator; every delivered (debounced) event + * is one reload. Ends when the watcher is closed by teardown. */ +static void http_server_hot_reload_watch_entry(void) +{ + zend_coroutine_t *co = ZEND_ASYNC_CURRENT_COROUTINE; + hot_reload_watch_ctx_t *ctx = co->extended_data; + http_server_object *server = http_server_from_obj(ctx->server_obj); + + zval iter; + ZVAL_UNDEF(&iter); + zend_call_method_with_0_params(Z_OBJ(ctx->watcher), NULL, NULL, "getIterator", &iter); + + if (EG(exception) || Z_TYPE(iter) != IS_OBJECT) { + zend_clear_exception(); + zval_ptr_dtor(&iter); + return; + } + + zval rv; + ZVAL_UNDEF(&rv); + zend_call_method_with_0_params(Z_OBJ(iter), NULL, NULL, "rewind", &rv); + zval_ptr_dtor(&rv); + + while (!EG(exception) && !server->hot_reload_stopping) { + zval valid; + ZVAL_UNDEF(&valid); + zend_call_method_with_0_params(Z_OBJ(iter), NULL, NULL, "valid", &valid); + + const bool go = !EG(exception) && zend_is_true(&valid); + zval_ptr_dtor(&valid); + + if (!go || server->hot_reload_stopping) { + break; + } + + http_server_hot_reload_fire(ctx->server_obj, "watcher"); + + if (server->hot_reload_stopping) { + break; + } + + ZVAL_UNDEF(&rv); + zend_call_method_with_0_params(Z_OBJ(iter), NULL, NULL, "next", &rv); + zval_ptr_dtor(&rv); + } + + if (EG(exception)) { + zend_clear_exception(); + } + + zval_ptr_dtor(&iter); +} + +#ifndef PHP_WIN32 +/* Coroutine: persistent SIGHUP handler — one signal event armed for the whole + * pool run (no unarmed window), each delivery is one reload. */ +static void http_server_hot_reload_sighup_entry(void) +{ + zend_coroutine_t *co = ZEND_ASYNC_CURRENT_COROUTINE; + hot_reload_sighup_ctx_t *ctx = co->extended_data; + http_server_object *server = http_server_from_obj(ctx->server_obj); + + zend_async_signal_event_t *sig = ZEND_ASYNC_NEW_SIGNAL_EVENT(SIGHUP); + + if (UNEXPECTED(sig == NULL)) { + zend_clear_exception(); + return; + } + + if (UNEXPECTED(!sig->base.start(&sig->base))) { + zend_clear_exception(); + sig->base.dispose(&sig->base); + return; + } + + server->sighup_event = sig; + http_logf_info(&server->log_state, "reload.signal armed signal=SIGHUP"); + + while (!server->hot_reload_stopping) { + zend_async_resume_when(co, &sig->base, false, zend_async_waker_callback_resolve, NULL); + ZEND_ASYNC_SUSPEND(); + ZEND_ASYNC_WAKER_DESTROY(co); + + if (EG(exception)) { + zend_clear_exception(); + break; + } + + if (server->hot_reload_stopping) { + break; + } + + http_server_hot_reload_fire(ctx->server_obj, "sighup"); + } + + server->sighup_event = NULL; + sig->base.stop(&sig->base); + sig->base.dispose(&sig->base); +} +#endif /* !PHP_WIN32 */ + +/* Arm the configured triggers on the pool parent (called from start_pool just + * before it suspends). Failures degrade to "trigger off" with a log line. */ +static void http_server_hot_reload_up(http_server_object *server, zval *this_zv, + http_server_config_t *cfg) +{ + server->hot_reload_stopping = false; + + if (Z_TYPE(cfg->hot_reload_paths) == IS_ARRAY) { + zend_string *cls = zend_string_init("Async\\FileSystemWatcher", + sizeof("Async\\FileSystemWatcher") - 1, 0); + zend_class_entry *ce = zend_lookup_class(cls); + zend_string_release(cls); + + if (UNEXPECTED(ce == NULL)) { + zend_clear_exception(); + http_logf_info(&server->log_state, + "reload.watch unavailable (Async\\FileSystemWatcher missing)"); + return; + } + + array_init(&server->hot_reload_watchers); + + const zval *path; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(cfg->hot_reload_paths), path) + { + zval watcher; + + if (object_init_ex(&watcher, ce) != SUCCESS) { + zend_clear_exception(); + continue; + } + + zval args[6], rv; + ZVAL_COPY(&args[0], path); + ZVAL_TRUE(&args[1]); /* recursive */ + ZVAL_TRUE(&args[2]); /* coalesce */ + ZVAL_LONG(&args[3], cfg->hot_reload_debounce_ms); + ZVAL_LONG(&args[4], cfg->hot_reload_max_hold_ms); + + if (Z_TYPE(cfg->hot_reload_extensions) == IS_ARRAY) { + ZVAL_COPY(&args[5], &cfg->hot_reload_extensions); + } else { + array_init(&args[5]); + } + + ZVAL_UNDEF(&rv); + zend_call_known_function(ce->constructor, Z_OBJ(watcher), ce, &rv, + 6, args, NULL); + zval_ptr_dtor(&rv); + zval_ptr_dtor(&args[0]); + zval_ptr_dtor(&args[5]); + + if (EG(exception)) { + http_logf_info(&server->log_state, "reload.watch failed path=%s", + Z_STRVAL_P(path)); + zend_clear_exception(); + zval_ptr_dtor(&watcher); + continue; + } + + hot_reload_watch_ctx_t *wctx = emalloc(sizeof(*wctx)); + wctx->server_obj = Z_OBJ_P(this_zv); + GC_ADDREF(wctx->server_obj); + ZVAL_COPY(&wctx->watcher, &watcher); + + zend_coroutine_t *co = ZEND_ASYNC_NEW_COROUTINE(ZEND_ASYNC_MAIN_SCOPE); + + if (UNEXPECTED(co == NULL)) { + zend_clear_exception(); + zval_ptr_dtor(&wctx->watcher); + OBJ_RELEASE(wctx->server_obj); + efree(wctx); + zval_ptr_dtor(&watcher); + continue; + } + + co->internal_entry = http_server_hot_reload_watch_entry; + co->extended_data = wctx; + co->extended_dispose = hot_reload_watch_ctx_dispose; + ZEND_ASYNC_ENQUEUE_COROUTINE(co); + + add_next_index_zval(&server->hot_reload_watchers, &watcher); + http_logf_info(&server->log_state, + "reload.watch armed path=%s debounce_ms=%u max_hold_ms=%u", + Z_STRVAL_P(path), cfg->hot_reload_debounce_ms, + cfg->hot_reload_max_hold_ms); + } + ZEND_HASH_FOREACH_END(); + } + +#ifndef PHP_WIN32 + if (cfg->reload_on_sighup) { + hot_reload_sighup_ctx_t *sctx = emalloc(sizeof(*sctx)); + sctx->server_obj = Z_OBJ_P(this_zv); + GC_ADDREF(sctx->server_obj); + + zend_coroutine_t *co = ZEND_ASYNC_NEW_COROUTINE(ZEND_ASYNC_MAIN_SCOPE); + + if (UNEXPECTED(co == NULL)) { + zend_clear_exception(); + OBJ_RELEASE(sctx->server_obj); + efree(sctx); + return; + } + + co->internal_entry = http_server_hot_reload_sighup_entry; + co->extended_data = sctx; + co->extended_dispose = hot_reload_sighup_ctx_dispose; + ZEND_ASYNC_ENQUEUE_COROUTINE(co); + } +#endif +} + +/* Retire the triggers: closing a watcher ends its iterator (the orchestrator + * sees valid()=false); notifying the signal event wakes its waiter, which + * observes hot_reload_stopping and disposes the event itself. */ +static void http_server_hot_reload_down(http_server_object *server) +{ + server->hot_reload_stopping = true; + + if (Z_TYPE(server->hot_reload_watchers) == IS_ARRAY) { + const zval *w; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL(server->hot_reload_watchers), w) + { + zval rv; + ZVAL_UNDEF(&rv); + zend_call_method_with_0_params(Z_OBJ_P(w), NULL, NULL, "close", &rv); + zval_ptr_dtor(&rv); + + if (EG(exception)) { + zend_clear_exception(); + } + } + ZEND_HASH_FOREACH_END(); + + zval_ptr_dtor(&server->hot_reload_watchers); + ZVAL_UNDEF(&server->hot_reload_watchers); + } + + if (server->sighup_event != NULL) { + ZEND_ASYNC_CALLBACKS_NOTIFY((zend_async_event_t *) server->sighup_event, NULL, NULL); + } +} + /* {{{ proto HttpServer::isRunning(): bool */ ZEND_METHOD(TrueAsync_HttpServer, isRunning) { diff --git a/src/http_server_config.c b/src/http_server_config.c index c668667..15a1e5a 100644 --- a/src/http_server_config.c +++ b/src/http_server_config.c @@ -411,6 +411,11 @@ ZEND_METHOD(TrueAsync_HttpServerConfig, __construct) config->stream_write_buffer_bytes = DEFAULT_STREAM_WRITE_BUFFER_BYTES; config->max_body_size = DEFAULT_MAX_BODY_SIZE; config->h2_static_budget_max = 0; /* 0 = auto from memory_limit */ + ZVAL_UNDEF(&config->hot_reload_paths); + ZVAL_UNDEF(&config->hot_reload_extensions); + config->hot_reload_debounce_ms = 300; + config->hot_reload_max_hold_ms = 2000; + config->reload_on_sighup = false; config->http3_idle_timeout_ms = DEFAULT_HTTP3_IDLE_TIMEOUT_MS; config->http3_stream_window_bytes = DEFAULT_HTTP3_STREAM_WINDOW_BYTES; config->http3_max_concurrent_streams = DEFAULT_HTTP3_MAX_CONCURRENT_STREAMS; @@ -727,6 +732,111 @@ ZEND_METHOD(TrueAsync_HttpServerConfig, getWorkers) } /* }}} */ +/* {{{ proto HttpServerConfig::enableHotReload(array $watchPaths, array $extensions = ['php'], int $debounceMs = 300, int $maxHoldMs = 2000): static + * + * Dev hot-reload trigger (issue #93), pool mode only. The pool parent spawns + * one recursive Async\FileSystemWatcher per path with the given debounce; a + * collapsed change event invalidates the watched trees in opcache and calls + * HttpServer::reload() — replacement workers re-run the bootloader. */ +ZEND_METHOD(TrueAsync_HttpServerConfig, enableHotReload) +{ + HashTable *paths; + HashTable *extensions = NULL; + zend_long debounce_ms = 300; + zend_long max_hold_ms = 2000; + + ZEND_PARSE_PARAMETERS_START(1, 4) + Z_PARAM_ARRAY_HT(paths) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT(extensions) + Z_PARAM_LONG(debounce_ms) + Z_PARAM_LONG(max_hold_ms) + ZEND_PARSE_PARAMETERS_END(); + + http_server_config_t *config = Z_HTTP_SERVER_CONFIG_P(ZEND_THIS); + + if (config_check_locked(config)) { + return; + } + + if (zend_hash_num_elements(paths) == 0) { + zend_throw_exception(http_server_invalid_argument_exception_ce, + "enableHotReload() requires at least one watch path", 0); + return; + } + + const zval *entry; + ZEND_HASH_FOREACH_VAL(paths, entry) + { + if (Z_TYPE_P(entry) != IS_STRING || Z_STRLEN_P(entry) == 0) { + zend_throw_exception(http_server_invalid_argument_exception_ce, + "enableHotReload() watch paths must be non-empty strings", 0); + return; + } + } + ZEND_HASH_FOREACH_END(); + + if (debounce_ms < 1 || debounce_ms > 600000 || max_hold_ms < 0 || max_hold_ms > 600000) { + zend_throw_exception(http_server_invalid_argument_exception_ce, + "enableHotReload() debounceMs must be 1..600000, maxHoldMs 0..600000", 0); + return; + } + + if (Z_TYPE(config->hot_reload_paths) != IS_UNDEF) { + zval_ptr_dtor(&config->hot_reload_paths); + } + + if (Z_TYPE(config->hot_reload_extensions) != IS_UNDEF) { + zval_ptr_dtor(&config->hot_reload_extensions); + ZVAL_UNDEF(&config->hot_reload_extensions); + } + + ZVAL_ARR(&config->hot_reload_paths, zend_array_dup(paths)); + + if (extensions != NULL && zend_hash_num_elements(extensions) > 0) { + ZVAL_ARR(&config->hot_reload_extensions, zend_array_dup(extensions)); + } + + config->hot_reload_debounce_ms = (uint32_t)debounce_ms; + config->hot_reload_max_hold_ms = (uint32_t)max_hold_ms; + + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); +} +/* }}} */ + +/* {{{ proto HttpServerConfig::enableReloadOnSignal(bool $enabled = true): static + * + * Prod hot-reload trigger (issue #93), pool mode only: the pool parent arms a + * persistent SIGHUP handler that calls HttpServer::reload(). */ +ZEND_METHOD(TrueAsync_HttpServerConfig, enableReloadOnSignal) +{ + bool enabled = true; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(enabled) + ZEND_PARSE_PARAMETERS_END(); + + http_server_config_t *config = Z_HTTP_SERVER_CONFIG_P(ZEND_THIS); + + if (config_check_locked(config)) { + return; + } + +#ifdef PHP_WIN32 + if (enabled) { + zend_throw_exception(http_server_invalid_argument_exception_ce, + "enableReloadOnSignal() is not supported on Windows (no SIGHUP)", 0); + return; + } +#endif + + config->reload_on_sighup = enabled; + + RETURN_OBJ_COPY(Z_OBJ_P(ZEND_THIS)); +} +/* }}} */ + /* {{{ proto HttpServerConfig::setBootloader(?Closure $bootloader): static * * Optional bootloader Closure handed to the built-in worker pool. The @@ -2802,6 +2912,16 @@ static void http_server_config_free(zend_object *obj) ZVAL_UNDEF(&config->log_stream); } + if (Z_TYPE(config->hot_reload_paths) != IS_UNDEF) { + zval_ptr_dtor(&config->hot_reload_paths); + ZVAL_UNDEF(&config->hot_reload_paths); + } + + if (Z_TYPE(config->hot_reload_extensions) != IS_UNDEF) { + zval_ptr_dtor(&config->hot_reload_extensions); + ZVAL_UNDEF(&config->hot_reload_extensions); + } + if (Z_TYPE(config->bootloader) != IS_UNDEF) { zval_ptr_dtor(&config->bootloader); ZVAL_UNDEF(&config->bootloader); diff --git a/stubs/HttpServerConfig.php b/stubs/HttpServerConfig.php index 5b0695d..2a960a5 100644 --- a/stubs/HttpServerConfig.php +++ b/stubs/HttpServerConfig.php @@ -138,6 +138,27 @@ public function getWorkers(): int {} */ public function setBootloader(?\Closure $bootloader): static {} + /** + * Dev hot-reload trigger (issue #93), pool mode only ({@see setWorkers()} > 1). + * The pool parent watches each path recursively (with the given debounce); + * a collapsed change event invalidates the watched trees in opcache and + * calls {@see HttpServer::reload()} — replacement workers re-run the + * bootloader with the changed code, on the same listen sockets. + * + * @param array $watchPaths Directories to watch (recursively). + * @param array $extensions Case-insensitive extension allow-list; empty = every file. + * @param int $debounceMs Quiet window before a burst of changes fires one reload. + * @param int $maxHoldMs Force a reload at most this long after the first change (0 = no cap). + */ + public function enableHotReload(array $watchPaths, array $extensions = ['php'], int $debounceMs = 300, int $maxHoldMs = 2000): static {} + + /** + * Prod hot-reload trigger (issue #93), pool mode only: the pool parent arms + * a persistent SIGHUP handler that calls {@see HttpServer::reload()}. + * Not supported on Windows. + */ + public function enableReloadOnSignal(bool $enabled = true): static {} + /** * Returns the bootloader previously set, or null. */ diff --git a/stubs/HttpServerConfig.php_arginfo.h b/stubs/HttpServerConfig.php_arginfo.h index 4280a97..b7d2f86 100644 --- a/stubs/HttpServerConfig.php_arginfo.h +++ b/stubs/HttpServerConfig.php_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit HttpServerConfig.php.stub.php instead. - * Stub hash: 3f74222f92482fa79cba17174f12fd9f023a317f */ + * Stub hash: 4d389377f8768c3f1faf3593872627ba44c80676 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_TrueAsync_HttpServerConfig___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, host, IS_STRING, 1, "null") @@ -43,6 +43,17 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_TrueAsync_HttpServerConfig ZEND_ARG_OBJ_INFO(0, bootloader, Closure, 1) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_TrueAsync_HttpServerConfig_enableHotReload, 0, 1, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO(0, watchPaths, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, extensions, IS_ARRAY, 0, "[\'php\']") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, debounceMs, IS_LONG, 0, "300") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, maxHoldMs, IS_LONG, 0, "2000") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_TrueAsync_HttpServerConfig_enableReloadOnSignal, 0, 0, IS_STATIC, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, enabled, _IS_BOOL, 0, "true") +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_TrueAsync_HttpServerConfig_getBootloader, 0, 0, Closure, 1) ZEND_END_ARG_INFO() @@ -289,6 +300,8 @@ ZEND_METHOD(TrueAsync_HttpServerConfig, setBacklog); ZEND_METHOD(TrueAsync_HttpServerConfig, setWorkers); ZEND_METHOD(TrueAsync_HttpServerConfig, getWorkers); ZEND_METHOD(TrueAsync_HttpServerConfig, setBootloader); +ZEND_METHOD(TrueAsync_HttpServerConfig, enableHotReload); +ZEND_METHOD(TrueAsync_HttpServerConfig, enableReloadOnSignal); ZEND_METHOD(TrueAsync_HttpServerConfig, getBootloader); ZEND_METHOD(TrueAsync_HttpServerConfig, getBacklog); ZEND_METHOD(TrueAsync_HttpServerConfig, setMaxConnections); @@ -404,6 +417,8 @@ static const zend_function_entry class_TrueAsync_HttpServerConfig_methods[] = { ZEND_ME(TrueAsync_HttpServerConfig, setWorkers, arginfo_class_TrueAsync_HttpServerConfig_setWorkers, ZEND_ACC_PUBLIC) ZEND_ME(TrueAsync_HttpServerConfig, getWorkers, arginfo_class_TrueAsync_HttpServerConfig_getWorkers, ZEND_ACC_PUBLIC) ZEND_ME(TrueAsync_HttpServerConfig, setBootloader, arginfo_class_TrueAsync_HttpServerConfig_setBootloader, ZEND_ACC_PUBLIC) + ZEND_ME(TrueAsync_HttpServerConfig, enableHotReload, arginfo_class_TrueAsync_HttpServerConfig_enableHotReload, ZEND_ACC_PUBLIC) + ZEND_ME(TrueAsync_HttpServerConfig, enableReloadOnSignal, arginfo_class_TrueAsync_HttpServerConfig_enableReloadOnSignal, ZEND_ACC_PUBLIC) ZEND_ME(TrueAsync_HttpServerConfig, getBootloader, arginfo_class_TrueAsync_HttpServerConfig_getBootloader, ZEND_ACC_PUBLIC) ZEND_ME(TrueAsync_HttpServerConfig, getBacklog, arginfo_class_TrueAsync_HttpServerConfig_getBacklog, ZEND_ACC_PUBLIC) ZEND_ME(TrueAsync_HttpServerConfig, setMaxConnections, arginfo_class_TrueAsync_HttpServerConfig_setMaxConnections, ZEND_ACC_PUBLIC) diff --git a/tests/phpt/server/core/053-hot-reload-watcher.phpt b/tests/phpt/server/core/053-hot-reload-watcher.phpt new file mode 100644 index 0000000..701453f --- /dev/null +++ b/tests/phpt/server/core/053-hot-reload-watcher.phpt @@ -0,0 +1,77 @@ +--TEST-- +HttpServerConfig::enableHotReload — file change triggers a pool rotation, new code served (#93) +--EXTENSIONS-- +true_async_server +true_async +--SKIPIF-- +/dev/null')) die('skip curl CLI not available'); +?> +--FILE-- +addListener('127.0.0.1', $port) + ->setReadTimeout(5) + ->setWriteTimeout(5) + ->setWorkers(2) + ->setBootloader(static function () use ($code): void { + define('APP_V', (string) include $code); + }) + ->enableHotReload([$dir], ['php'], 150, 1000); + +$server = new HttpServer($config); +$server->addHttpHandler(function ($req, $res) { + $res->setStatusCode(200)->setBody(APP_V); +}); + +spawn(function () use ($port, $code, $dir) { + $curl = static fn (): string => (string) shell_exec(sprintf( + 'curl -s --max-time 2 http://127.0.0.1:%d/ 2>/dev/null', $port)); + + $v1 = ''; + for ($i = 0; $i < 50 && $v1 !== 'v1'; $i++) { + usleep(200000); + $v1 = $curl(); + } + + echo "before=", $v1, "\n"; + + /* The only action: rewrite the watched file. */ + file_put_contents($code, "start(); +?> +--EXPECTF-- +before=v1 +%A +after=v2%A diff --git a/tests/phpt/server/core/054-hot-reload-sighup.phpt b/tests/phpt/server/core/054-hot-reload-sighup.phpt new file mode 100644 index 0000000..4625e06 --- /dev/null +++ b/tests/phpt/server/core/054-hot-reload-sighup.phpt @@ -0,0 +1,79 @@ +--TEST-- +HttpServerConfig::enableReloadOnSignal — SIGHUP rotates the pool, serving continues (#93) +--EXTENSIONS-- +true_async_server +true_async +--SKIPIF-- +/dev/null')) die('skip curl CLI not available'); +?> +--FILE-- +addListener('127.0.0.1', $port) + ->setReadTimeout(5) + ->setWriteTimeout(5) + ->setWorkers(2) + ->setBootloader(static function () use ($bfile): void { + file_put_contents($bfile, 'x', FILE_APPEND | LOCK_EX); + }) + ->enableReloadOnSignal(); + +$server = new HttpServer($config); +$server->addHttpHandler(function ($req, $res) { + $res->setStatusCode(200)->setBody('pong'); +}); + +spawn(function () use ($port, $bfile) { + $curl = static fn (): string => (string) shell_exec(sprintf( + 'curl -s --max-time 2 http://127.0.0.1:%d/ 2>/dev/null', $port)); + + $up = ''; + for ($i = 0; $i < 50 && $up !== 'pong'; $i++) { + usleep(200000); + $up = $curl(); + } + + echo "up=", $up, "\n"; + + posix_kill(getmypid(), SIGHUP); + + /* Rotation done when both replacements have re-run the bootloader. */ + $boots = 0; + for ($i = 0; $i < 100 && $boots < 4; $i++) { + usleep(200000); + $boots = strlen((string) @file_get_contents($bfile)); + } + + echo "boots=", $boots, "\n"; + + $again = ''; + for ($i = 0; $i < 50 && $again !== 'pong'; $i++) { + usleep(200000); + $again = $curl(); + } + + echo "served_after=", $again, "\n"; + + @unlink($bfile); + posix_kill(getmypid(), SIGKILL); +}); + +$server->start(); +?> +--EXPECTF-- +up=pong +%A +boots=4 +served_after=pong%A diff --git a/tests/phpt/server/h3/045-h3-reload-reactor-pool.phpt b/tests/phpt/server/h3/045-h3-reload-reactor-pool.phpt new file mode 100644 index 0000000..d9adfc5 --- /dev/null +++ b/tests/phpt/server/h3/045-h3-reload-reactor-pool.phpt @@ -0,0 +1,90 @@ +--TEST-- +HttpServer: reload() under the gated reactor pool is refused — inbox rotation not implemented (#93) +--EXTENSIONS-- +true_async_server +true_async +--SKIPIF-- + true, 'h3client' => true]); +?> +--ENV-- +TRUE_ASYNC_SERVER_REACTOR_POOL=1 +PHP_HTTP3_DISABLE_RETRY=1 +--FILE-- +addListener('127.0.0.1', $tcp_port) /* TCP listener required by start() */ + ->addHttp3Listener('127.0.0.1', $port) + ->enableTls(true)->setCertificate($cert)->setPrivateKey($key) + ->setWorkers(2); +$server = new HttpServer($config); +$server->addHttpHandler(function ($req, $res) { + $res->setStatusCode(201) + ->setHeader('content-type', 'text/plain; charset=utf-8') + ->setBody('echo:' . $req->getMethod() . ':' . $req->getUri()); +}); + +$client_bin = __DIR__ . '/../../../h3client/h3client'; + +spawn(function () use ($server, $port, $client_bin) { + usleep(600000); /* reactors + workers thread up and bind */ + + $get = static function (string $path) use ($client_bin, $port): string { + $cmd = sprintf('H3CLIENT_DEADLINE_MS=4000 %s 127.0.0.1 %d %s GET 2>&1', + escapeshellarg($client_bin), $port, $path); + $out = shell_exec($cmd) ?? ''; + $status = preg_match('/^STATUS=(\d+)$/m', $out, $m) ? (int)$m[1] : -1; + $body = trim((string) preg_replace('/^STATUS=\d+\n?/m', '', $out)); + return $status . ':' . $body; + }; + + echo "before=", $get('/one'), "\n"; + + try { + $server->reload(); + echo "reload=no-throw\n"; + } catch (\Throwable $e) { + echo "reload_refused=", + (int)(strpos($e->getMessage(), 'REACTOR_POOL') !== false), "\n"; + } + + /* The refusal must be side-effect free: H3 keeps serving. */ + echo "after=", $get('/two'), "\n"; + + posix_kill(getmypid(), SIGKILL); +}); + +$server->start(); +?> +--EXPECTF-- +%Abefore=201:echo:GET:/one +reload_refused=1 +after=201:echo:GET:/two +%A diff --git a/tests/phpt/websocket/034-hot-reload-ws.phpt b/tests/phpt/websocket/034-hot-reload-ws.phpt new file mode 100644 index 0000000..5a054e2 --- /dev/null +++ b/tests/phpt/websocket/034-hot-reload-ws.phpt @@ -0,0 +1,146 @@ +--TEST-- +WebSocket: pool reload with a live WS connection — old conn retired, fresh worker serves WS (#93) +--EXTENSIONS-- +true_async_server +true_async +--SKIPIF-- + +--FILE-- +addListener('127.0.0.1', $port) + ->setReadTimeout(5) + ->setWriteTimeout(5) + ->setShutdownTimeout(1) /* keep the drain grace short for the rotation */ + ->setWorkers(2); + +$server = new HttpServer($config); + +$server->addWebSocketHandler(function (WebSocket $ws, HttpRequest $req) { + while (($msg = $ws->recv()) !== null) { + $ws->send('echo: ' . $msg->data); + } +}); + +$server->addHttpHandler(function ($req, $resp) { + $resp->setStatusCode(404)->end(); +}); + +function ws_client_text_frame(string $payload): string { + $mask = "abcd"; + $masked = ''; + for ($i = 0, $n = strlen($payload); $i < $n; $i++) { + $masked .= chr(ord($payload[$i]) ^ ord($mask[$i & 3])); + } + return chr(0x81) . chr(0x80 | strlen($payload)) . $mask . $masked; +} + +function read_server_frame($fp): array { + $hdr = ''; + while (strlen($hdr) < 2) { + $c = fread($fp, 2 - strlen($hdr)); + if ($c === false || $c === '') return ['opcode' => -1, 'data' => '']; + $hdr .= $c; + } + $opcode = ord($hdr[0]) & 0x0f; + $len = ord($hdr[1]) & 0x7f; + if ($len === 126) { + $extra = fread($fp, 2); + $len = (ord($extra[0]) << 8) | ord($extra[1]); + } + $data = ''; + while (strlen($data) < $len) { + $c = fread($fp, $len - strlen($data)); + if ($c === false || $c === '') break; + $data .= $c; + } + return ['opcode' => $opcode, 'data' => $data]; +} + +function ws_connect(int $port) { + $fp = @stream_socket_client("tcp://127.0.0.1:$port", $errno, $errstr, 2); + if ($fp === false) return false; + stream_set_timeout($fp, 5); + fwrite($fp, + "GET / HTTP/1.1\r\nHost: x\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n" + . "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n"); + $hs = ''; + while (!str_contains($hs, "\r\n\r\n")) { + $c = fread($fp, 4096); + if ($c === false || $c === '') return false; + $hs .= $c; + } + return str_contains($hs, ' 101 ') ? $fp : false; +} + +spawn(function () use ($server, $port) { + usleep(400000); /* let the pool come up */ + + /* Live WS connection on the old cohort. */ + $fp = false; + for ($i = 0; $i < 25 && $fp === false; $i++) { + usleep(200000); + $fp = ws_connect($port); + } + + if ($fp === false) { + echo "pre_ws=fail\n"; + posix_kill(getmypid(), SIGKILL); + } + + fwrite($fp, ws_client_text_frame('one')); + $r1 = read_server_frame($fp); + echo "pre_echo=", $r1['data'], "\n"; + + /* Rotate while the connection is open. */ + $ok = $server->reload(); + echo "reload=", var_export($ok, true), "\n"; + + /* The retired worker must end our connection: close frame (8) or EOF (-1). */ + $r2 = read_server_frame($fp); + echo "old_conn_ended=", (int)($r2['opcode'] === 8 || $r2['opcode'] === -1), "\n"; + fclose($fp); + + /* Fresh cohort serves new WS connections on the same port. */ + $fp2 = false; + for ($i = 0; $i < 50 && $fp2 === false; $i++) { + usleep(200000); + $fp2 = ws_connect($port); + } + + if ($fp2 !== false) { + fwrite($fp2, ws_client_text_frame('two')); + $r3 = read_server_frame($fp2); + echo "post_echo=", $r3['data'], "\n"; + fclose($fp2); + } else { + echo "post_echo=fail\n"; + } + + posix_kill(getmypid(), SIGKILL); +}); + +$server->start(); +?> +--EXPECTF-- +pre_echo=echo: one +%A +reload=true +old_conn_ended=1 +post_echo=echo: two%A From 0f58b69b3334f0e8f98c237475c38f26dd4a8763 Mon Sep 17 00:00:00 2001 From: Edmond <1571649+edmonddantes@users.noreply.github.com> Date: Fri, 3 Jul 2026 16:27:39 +0000 Subject: [PATCH 2/2] =?UTF-8?q?test:=20migrate=20every=20phpt=20to=20kerne?= =?UTF-8?q?l-allocated=20ports=20=E2=80=94=20kill=20the=20port-collision?= =?UTF-8?q?=20flake=20class=20(#93)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 206 tests used 'BASE + getmypid() % N' with massively overlapping ranges (several %1000 spans, six tests sharing one literal base) while the server binds with SO_REUSEPORT — so under run-tests -j any two concurrent tests could silently share a port and split each other's traffic. That is the mechanism behind the h2/012 flake fixed in #98 and the websocket/024 backpressure flake seen on this PR's first CI round (its base 19790+%100 sits in the middle of the crowd). All 206 files now take tas_free_port(); tests that derive sibling ports as $port+N use the new tas_free_port_span(N+1), which holds the whole span before releasing it. Full suite at -j8, twice: 277 passed, 0 failed. --- tests/phpt/server/_free_port.inc | 28 +++++++++++++++++++ .../phpt/server/chaos/001-h2-rapid-reset.phpt | 3 +- .../chaos/002-h2-continuation-flood.phpt | 3 +- .../compression/010-h1-buffered-gzip.phpt | 3 +- .../compression/011-h1-buffered-skips.phpt | 3 +- .../compression/012-h1-streaming-gzip.phpt | 3 +- .../compression/020-h2-buffered-gzip.phpt | 3 +- .../compression/030-h1-request-gzip-in.phpt | 3 +- .../compression/040-h1-buffered-brotli.phpt | 3 +- .../compression/041-h1-streaming-brotli.phpt | 3 +- .../compression/050-h1-buffered-zstd.phpt | 3 +- .../compression/060-h1-request-malformed.phpt | 3 +- .../compression/070-encoder-pool-reuse.phpt | 3 +- .../server/core/004-server-start-stop.phpt | 3 +- .../server/core/005-server-e2e-simple.phpt | 3 +- .../007-server-transfer-handler-dispatch.phpt | 3 +- .../core/008-backpressure-telemetry.phpt | 3 +- .../core/009-http-exception-from-handler.phpt | 4 ++- .../core/012-drain-telemetry-reset.phpt | 3 +- .../core/014-log-emit-on-start-stop.phpt | 4 ++- .../server/core/015-log-multipart-debug.phpt | 4 ++- tests/phpt/server/core/016-log-tls-warn.phpt | 4 ++- .../server/core/018-log-off-no-overhead.phpt | 4 ++- .../server/core/019-parse-error-503-oom.phpt | 3 +- .../server/core/020-builtin-worker-pool.phpt | 4 ++- .../core/020-telemetry-trace-context.phpt | 3 +- tests/phpt/server/core/021-bootloader.phpt | 4 ++- .../server/core/021-response-headers-api.phpt | 3 +- .../server/core/022-response-status-api.phpt | 3 +- .../server/core/023-response-body-api.phpt | 3 +- .../server/core/024-response-helpers.phpt | 3 +- .../server/core/025-response-state-api.phpt | 3 +- .../core/026-response-trailers-api.phpt | 3 +- .../server/core/027-response-validation.phpt | 3 +- tests/phpt/server/core/030-response-json.phpt | 3 +- .../core/036-response-reason-phrases.phpt | 4 ++- .../core/037-http-methods-end-to-end.phpt | 4 ++- .../core/040-request-scope-isolation.phpt | 3 +- .../041-current-context-child-coroutines.phpt | 3 +- .../phpt/server/core/042-request-context.phpt | 3 +- ...-request-context-equals-scope-context.phpt | 3 +- .../core/044-worker-pool-bound-handler.phpt | 4 ++- .../server/core/045-request-context-h2.phpt | 3 +- .../core/045-shutdown-drains-inflight.phpt | 3 +- .../server/core/046-request-context-h3.phpt | 3 +- .../core/047-request-context-concurrent.phpt | 3 +- .../048-request-context-first-accessor.phpt | 3 +- .../server/core/049-request-scope-setter.phpt | 3 +- .../core/050-request-scope-workers.phpt | 3 +- tests/phpt/server/h1/001-pipelining.phpt | 3 +- tests/phpt/server/h1/002-parse-error-414.phpt | 3 +- tests/phpt/server/h1/003-parse-error-431.phpt | 4 ++- tests/phpt/server/h1/004-parse-error-400.phpt | 4 ++- .../h1/005-parse-error-mid-stream-body.phpt | 4 ++- tests/phpt/server/h1/006-smuggling-cl-te.phpt | 4 ++- .../phpt/server/h1/007-smuggling-dup-cl.phpt | 4 ++- .../server/h1/008-invalid-content-length.phpt | 4 ++- .../phpt/server/h1/009-obs-fold-rejected.phpt | 4 ++- .../server/h1/010-drain-proactive-age-h1.phpt | 3 +- .../h1/011-drain-reactive-hardcap-h1.phpt | 3 +- .../h1/012-drain-cooldown-blocks-refire.phpt | 3 +- .../phpt/server/h1/013-h1-chunked-basic.phpt | 3 +- tests/phpt/server/h1/014-h1-sse-pattern.phpt | 3 +- .../server/h1/015-h1-stream-edge-cases.phpt | 3 +- .../h1/016-h1-stream-after-send-many.phpt | 3 +- .../server/h1/017-admission-reject-h1.phpt | 3 +- .../phpt/server/h1/018-tcp-fragmentation.phpt | 3 +- tests/phpt/server/h1/019-host-validation.phpt | 4 ++- .../020-method-and-response-conformance.phpt | 4 ++- .../h1/021-request-target-hardening.phpt | 4 ++- tests/phpt/server/h1/022-h1-sse-api.phpt | 3 +- .../phpt/server/h1/023-h1-sse-validation.phpt | 3 +- tests/phpt/server/h1/024-h1-sse-misuse.phpt | 3 +- .../h1/025-h1-sse-client-disconnect.phpt | 3 +- .../server/h1/050-stream-request-body.phpt | 3 +- tests/phpt/server/h2/001-h2c-get.phpt | 3 +- tests/phpt/server/h2/002-h2c-post.phpt | 3 +- tests/phpt/server/h2/003-h2c-trailers.phpt | 3 +- tests/phpt/server/h2/004-h2-tls-get.phpt | 3 +- tests/phpt/server/h2/005-h2-tls-fallback.phpt | 3 +- tests/phpt/server/h2/006-h2c-multiplex.phpt | 3 +- .../server/h2/007-h2c-peer-reset-cancel.phpt | 3 +- .../h2/008-h2c-peer-reset-await-body.phpt | 3 +- tests/phpt/server/h2/009-h2-h2spec-gate.phpt | 4 +-- .../h2/010-drain-proactive-age-h2-goaway.phpt | 3 +- .../h2/011-drain-h2-multiplex-completes.phpt | 3 +- .../server/h2/013-h2-streaming-basic.phpt | 3 +- .../server/h2/014-h2-streaming-large.phpt | 3 +- .../h2/015-h2-streaming-backpressure.phpt | 3 +- .../server/h2/016-h2-streaming-telemetry.phpt | 3 +- .../server/h2/017-h2-streaming-cancel.phpt | 3 +- .../phpt/server/h2/018-h2-only-listener.phpt | 3 +- .../server/h2/019-h2-stream-telemetry.phpt | 3 +- .../server/h2/020-admission-reject-h2.phpt | 3 +- .../phpt/server/h2/021-h2-tls-multiplex.phpt | 4 ++- .../server/h2/022-h2-streaming-ring-full.phpt | 3 +- .../server/h2/023-h2-streaming-sendable.phpt | 3 +- .../phpt/server/h2/024-h2-tls-large-body.phpt | 4 ++- tests/phpt/server/h2/025-h2-sse-api.phpt | 3 +- .../server/h2/026-h2-sse-empty-start.phpt | 3 +- .../server/h2/050-stream-request-body.phpt | 3 +- tests/phpt/server/h3/001-h3-udp-recv.phpt | 3 +- tests/phpt/server/h3/002-h3-packet-parse.phpt | 3 +- .../server/h3/004-h3-start-without-cert.phpt | 3 +- .../h3/005-h3-repeat-initial-same-dcid.phpt | 3 +- .../h3/008-h3-stats-handshake-keys.phpt | 3 +- tests/phpt/server/h3/009-h3-e2e-get.phpt | 3 +- .../server/h3/010-h3-e2e-post-await-body.phpt | 3 +- .../server/h3/011-h3-e2e-streaming-send.phpt | 3 +- .../phpt/server/h3/012-h3-graceful-close.phpt | 3 +- .../server/h3/013-h3-stateless-reset.phpt | 3 +- .../server/h3/014-h3-drain-max-conn-age.phpt | 3 +- tests/phpt/server/h3/015-h3-idle-timeout.phpt | 3 +- .../server/h3/016-h3-per-peer-budget.phpt | 3 +- .../phpt/server/h3/017-h3-alt-svc-header.phpt | 4 ++- .../server/h3/018-h3-version-negotiation.phpt | 3 +- .../h3/022-h3-stats-error-counters.phpt | 3 +- .../server/h3/024-h3-config-setters-e2e.phpt | 3 +- tests/phpt/server/h3/025-h3-retry-token.phpt | 3 +- tests/phpt/server/h3/026-h3-static-file.phpt | 3 +- tests/phpt/server/h3/027-h3-static-mount.phpt | 3 +- tests/phpt/server/h3/028-h3-large-body.phpt | 4 +-- .../phpt/server/h3/029-h3-pacing-setter.phpt | 4 ++- .../031-h3-stats-nonzero-after-traffic.phpt | 3 +- .../h3/032-h3-connection-migration.phpt | 3 +- tests/phpt/server/h3/033-h3-head-request.phpt | 3 +- .../h3/034-h3-stateless-reset-clamps.phpt | 3 +- .../h3/035-h3-request-body-overflow.phpt | 3 +- .../server/h3/037-h3-reactor-pool-e2e.phpt | 3 +- .../server/h3/038-h3-reactor-pool-post.phpt | 3 +- .../server/h3/039-h3-reactor-pool-static.phpt | 3 +- .../h3/040-h3-reactor-pool-steering.phpt | 3 +- .../h3/041-h3-migration-storm-guard.phpt | 3 +- tests/phpt/server/h3/041-h3-sse-api.phpt | 3 +- .../h3/042-h3-newcid-dcid-rotation.phpt | 3 +- .../server/h3/042-h3-sse-empty-start.phpt | 3 +- .../h3/043-h3-newcid-multi-rotation.phpt | 3 +- tests/phpt/server/h3/044-hq-interop-file.phpt | 3 +- .../server/sendfile/001-sendfile-basic.phpt | 4 ++- .../server/sendfile/002-sendfile-options.phpt | 4 ++- .../server/sendfile/003-sendfile-sealed.phpt | 4 ++- .../server/sendfile/004-sendfile-errors.phpt | 4 ++- .../server/sendfile/005-sendfile-rfc5987.phpt | 4 ++- .../phpt/server/static/001-static-basic.phpt | 4 ++- .../002-static-dotfile-and-onmissing.phpt | 4 ++- .../server/static/003-static-security.phpt | 4 ++- .../server/static/004-static-workers.phpt | 4 ++- .../static/005-static-if-modified-since.phpt | 4 ++- .../006-static-zero-coroutine-counter.phpt | 4 ++- .../static/007-static-tls-streaming.phpt | 3 +- .../static/008-static-cache-counters.phpt | 4 ++- .../static/009-static-symlink-owner.phpt | 4 ++- .../static/010-static-precompressed.phpt | 4 ++- .../011-static-precompressed-cache-uaf.phpt | 4 ++- .../phpt/server/static/011-static-range.phpt | 4 ++- tests/phpt/server/static/012-static-h2.phpt | 4 ++- ...tic-precompressed-small-cache-headers.phpt | 4 ++- .../phpt/server/static/013-static-h2-tls.phpt | 3 +- .../server/static/014-static-body-cache.phpt | 4 ++- .../static/015-static-ims-date-formats.phpt | 4 ++- .../static/017-static-handler-locked.phpt | 4 ++- .../static/018-static-hide-index-mime.phpt | 4 ++- ...019-static-dotfile-ignore-and-noindex.phpt | 4 ++- .../020-static-extra-headers-and-mime.phpt | 4 ++- .../021-static-symlink-reject-nofollow.phpt | 4 ++- tests/phpt/server/tls/002-tls-config.phpt | 4 +-- tests/phpt/server/tls/003-tls-handshake.phpt | 3 +- tests/phpt/server/tls/004-tls-get.phpt | 3 +- tests/phpt/server/tls/005-tls-body.phpt | 3 +- tests/phpt/server/tls/006-tls-keepalive.phpt | 3 +- tests/phpt/server/tls/007-tls-pipelining.phpt | 3 +- tests/phpt/server/tls/008-tls-telemetry.phpt | 3 +- tests/phpt/server/tls/009-tls-resumption.phpt | 3 +- tests/phpt/server/tls/010-tls-ktls.phpt | 3 +- .../phpt/server/tls/011-tls-parse-error.phpt | 3 +- .../server/tls/012-tls-security-level.phpt | 4 ++- .../tls/013-tls-abrupt-and-plain-on-tls.phpt | 3 +- .../tls/014-tls-h2-large-body-bio-park.phpt | 4 ++- .../server/tls/015-tls-buffer-setter.phpt | 4 ++- tests/phpt/websocket/005-handshake-101.phpt | 3 +- tests/phpt/websocket/006-recv-text-frame.phpt | 3 +- tests/phpt/websocket/007-send-echo.phpt | 3 +- tests/phpt/websocket/008-close-handshake.phpt | 3 +- tests/phpt/websocket/009-binary-frames.phpt | 3 +- .../websocket/010-fragmented-message.phpt | 3 +- tests/phpt/websocket/011-concurrent-recv.phpt | 3 +- tests/phpt/websocket/012-upgrade-reject.phpt | 3 +- .../websocket/013-upgrade-subprotocol.phpt | 3 +- tests/phpt/websocket/015-keepalive-ping.phpt | 3 +- tests/phpt/websocket/016-auto-pong.phpt | 3 +- tests/phpt/websocket/017-remote-address.phpt | 3 +- tests/phpt/websocket/018-wss-echo.phpt | 3 +- .../websocket/019-h2-extended-connect.phpt | 3 +- .../020-permessage-deflate-echo.phpt | 3 +- .../021-permessage-deflate-bomb.phpt | 3 +- .../websocket/022-h2-permessage-deflate.phpt | 3 +- .../websocket/023-backpressure-trysend.phpt | 3 +- .../024-backpressure-send-blocks.phpt | 3 +- .../025-spawned-writer-teardown.phpt | 4 ++- .../websocket/026-pong-timeout-close.phpt | 3 +- .../websocket/027-handshake-bad-version.phpt | 3 +- .../websocket/028-handshake-missing-key.phpt | 3 +- .../websocket/029-handshake-bad-method.phpt | 3 +- .../websocket/030-utf8-failfast-teardown.phpt | 3 +- .../websocket/031-outbound-fragmentation.phpt | 3 +- .../websocket/032-closed-exception-code.phpt | 3 +- .../phpt/websocket/033-foreach-iterator.phpt | 3 +- 207 files changed, 493 insertions(+), 209 deletions(-) diff --git a/tests/phpt/server/_free_port.inc b/tests/phpt/server/_free_port.inc index 0579fc9..b48f8dc 100644 --- a/tests/phpt/server/_free_port.inc +++ b/tests/phpt/server/_free_port.inc @@ -24,3 +24,31 @@ function tas_free_port(): int return (int) substr($name, strrpos($name, ':') + 1); } + +/* A base port P such that P..P+$count-1 are all bindable — for tests that + * derive sibling ports as $port + N (e.g. a TCP listener next to the H3 UDP + * one). Retries with fresh kernel-assigned bases until a whole span fits. */ +function tas_free_port_span(int $count): int +{ + for ($try = 0; $try < 32; $try++) { + $base = tas_free_port(); + $held = []; + $ok = true; + + for ($i = 0; $i < $count; $i++) { + $h = @stream_socket_server("tcp://127.0.0.1:" . ($base + $i), $e, $m); + if ($h === false) { $ok = false; break; } + $held[] = $h; + } + + foreach ($held as $h) { + fclose($h); + } + + if ($ok) { + return $base; + } + } + + die('skip cannot allocate a free port span'); +} diff --git a/tests/phpt/server/chaos/001-h2-rapid-reset.phpt b/tests/phpt/server/chaos/001-h2-rapid-reset.phpt index 49f38d8..0ff5e53 100644 --- a/tests/phpt/server/chaos/001-h2-rapid-reset.phpt +++ b/tests/phpt/server/chaos/001-h2-rapid-reset.phpt @@ -26,8 +26,9 @@ use function Async\delay; require __DIR__ . '/../h2/_h2_client.inc'; -$port = 19870 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/chaos/002-h2-continuation-flood.phpt b/tests/phpt/server/chaos/002-h2-continuation-flood.phpt index 2f402f7..e7edf3c 100644 --- a/tests/phpt/server/chaos/002-h2-continuation-flood.phpt +++ b/tests/phpt/server/chaos/002-h2-continuation-flood.phpt @@ -27,8 +27,9 @@ use function Async\delay; require __DIR__ . '/../h2/_h2_client.inc'; -$port = 19872 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/compression/010-h1-buffered-gzip.phpt b/tests/phpt/server/compression/010-h1-buffered-gzip.phpt index 36e7322..01a7543 100644 --- a/tests/phpt/server/compression/010-h1-buffered-gzip.phpt +++ b/tests/phpt/server/compression/010-h1-buffered-gzip.phpt @@ -16,8 +16,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19200 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/011-h1-buffered-skips.phpt b/tests/phpt/server/compression/011-h1-buffered-skips.phpt index c5baae6..4a7ec4d 100644 --- a/tests/phpt/server/compression/011-h1-buffered-skips.phpt +++ b/tests/phpt/server/compression/011-h1-buffered-skips.phpt @@ -15,8 +15,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19250 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/012-h1-streaming-gzip.phpt b/tests/phpt/server/compression/012-h1-streaming-gzip.phpt index d4dfc8b..2fe8dba 100644 --- a/tests/phpt/server/compression/012-h1-streaming-gzip.phpt +++ b/tests/phpt/server/compression/012-h1-streaming-gzip.phpt @@ -16,8 +16,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19300 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/020-h2-buffered-gzip.phpt b/tests/phpt/server/compression/020-h2-buffered-gzip.phpt index 9f653e9..2edf48d 100644 --- a/tests/phpt/server/compression/020-h2-buffered-gzip.phpt +++ b/tests/phpt/server/compression/020-h2-buffered-gzip.phpt @@ -15,8 +15,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19350 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/030-h1-request-gzip-in.phpt b/tests/phpt/server/compression/030-h1-request-gzip-in.phpt index 51aea0f..da93377 100644 --- a/tests/phpt/server/compression/030-h1-request-gzip-in.phpt +++ b/tests/phpt/server/compression/030-h1-request-gzip-in.phpt @@ -16,8 +16,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19400 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/040-h1-buffered-brotli.phpt b/tests/phpt/server/compression/040-h1-buffered-brotli.phpt index 90e44bb..1f6cbef 100644 --- a/tests/phpt/server/compression/040-h1-buffered-brotli.phpt +++ b/tests/phpt/server/compression/040-h1-buffered-brotli.phpt @@ -18,8 +18,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19500 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/041-h1-streaming-brotli.phpt b/tests/phpt/server/compression/041-h1-streaming-brotli.phpt index 28d8dd7..7ba3d83 100644 --- a/tests/phpt/server/compression/041-h1-streaming-brotli.phpt +++ b/tests/phpt/server/compression/041-h1-streaming-brotli.phpt @@ -18,8 +18,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19700 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/050-h1-buffered-zstd.phpt b/tests/phpt/server/compression/050-h1-buffered-zstd.phpt index 185b7ba..98c9247 100644 --- a/tests/phpt/server/compression/050-h1-buffered-zstd.phpt +++ b/tests/phpt/server/compression/050-h1-buffered-zstd.phpt @@ -18,8 +18,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19600 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/060-h1-request-malformed.phpt b/tests/phpt/server/compression/060-h1-request-malformed.phpt index 9d154fd..e97fbcd 100644 --- a/tests/phpt/server/compression/060-h1-request-malformed.phpt +++ b/tests/phpt/server/compression/060-h1-request-malformed.phpt @@ -19,8 +19,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19800 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/compression/070-encoder-pool-reuse.phpt b/tests/phpt/server/compression/070-encoder-pool-reuse.phpt index d6c5b7d..ba2009f 100644 --- a/tests/phpt/server/compression/070-encoder-pool-reuse.phpt +++ b/tests/phpt/server/compression/070-encoder-pool-reuse.phpt @@ -16,8 +16,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19300 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/004-server-start-stop.phpt b/tests/phpt/server/core/004-server-start-stop.phpt index 4b90387..acd1cb1 100644 --- a/tests/phpt/server/core/004-server-start-stop.phpt +++ b/tests/phpt/server/core/004-server-start-stop.phpt @@ -9,8 +9,9 @@ use TrueAsync\HttpServer; use TrueAsync\HttpServerConfig; use function Async\spawn; -$port = 19900 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/005-server-e2e-simple.phpt b/tests/phpt/server/core/005-server-e2e-simple.phpt index 459c6f4..04b28d0 100644 --- a/tests/phpt/server/core/005-server-e2e-simple.phpt +++ b/tests/phpt/server/core/005-server-e2e-simple.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19800 + getmypid() % 1000; // Random-ish port to avoid conflicts +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/007-server-transfer-handler-dispatch.phpt b/tests/phpt/server/core/007-server-transfer-handler-dispatch.phpt index f7d1f87..846f2aa 100644 --- a/tests/phpt/server/core/007-server-transfer-handler-dispatch.phpt +++ b/tests/phpt/server/core/007-server-transfer-handler-dispatch.phpt @@ -33,8 +33,9 @@ use Async\ThreadPool; use function Async\spawn; use function Async\await; -$port = 19840 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $coro = spawn(function () use ($port) { $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/core/008-backpressure-telemetry.phpt b/tests/phpt/server/core/008-backpressure-telemetry.phpt index 4d6ef8c..795074f 100644 --- a/tests/phpt/server/core/008-backpressure-telemetry.phpt +++ b/tests/phpt/server/core/008-backpressure-telemetry.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19700 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/009-http-exception-from-handler.phpt b/tests/phpt/server/core/009-http-exception-from-handler.phpt index f54c089..df0ac98 100644 --- a/tests/phpt/server/core/009-http-exception-from-handler.phpt +++ b/tests/phpt/server/core/009-http-exception-from-handler.phpt @@ -11,7 +11,9 @@ use TrueAsync\HttpException; use function Async\spawn; use function Async\await; -$port = 19820 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); diff --git a/tests/phpt/server/core/012-drain-telemetry-reset.phpt b/tests/phpt/server/core/012-drain-telemetry-reset.phpt index 1a0a417..e5fbf49 100644 --- a/tests/phpt/server/core/012-drain-telemetry-reset.phpt +++ b/tests/phpt/server/core/012-drain-telemetry-reset.phpt @@ -16,8 +16,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19845 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/core/014-log-emit-on-start-stop.phpt b/tests/phpt/server/core/014-log-emit-on-start-stop.phpt index 6e05ff7..6718208 100644 --- a/tests/phpt/server/core/014-log-emit-on-start-stop.phpt +++ b/tests/phpt/server/core/014-log-emit-on-start-stop.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use TrueAsync\LogSeverity; use function Async\spawn; -$port = 19960 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port_span(2); $logfile = sys_get_temp_dir() . "/php-http-server-091-" . getmypid() . ".log"; @unlink($logfile); $logfh = fopen($logfile, "w+b"); diff --git a/tests/phpt/server/core/015-log-multipart-debug.phpt b/tests/phpt/server/core/015-log-multipart-debug.phpt index ebcea82..c94e6d4 100644 --- a/tests/phpt/server/core/015-log-multipart-debug.phpt +++ b/tests/phpt/server/core/015-log-multipart-debug.phpt @@ -11,7 +11,9 @@ use TrueAsync\LogSeverity; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port_span(2); $logfile = sys_get_temp_dir() . "/php-http-server-092-" . getmypid() . ".log"; @unlink($logfile); $logfh = fopen($logfile, "w+b"); diff --git a/tests/phpt/server/core/016-log-tls-warn.phpt b/tests/phpt/server/core/016-log-tls-warn.phpt index 8b45e28..e5f695e 100644 --- a/tests/phpt/server/core/016-log-tls-warn.phpt +++ b/tests/phpt/server/core/016-log-tls-warn.phpt @@ -23,7 +23,9 @@ $cert = $tmp . '/cert.pem'; $key = $tmp . '/key.pem'; if (!tls_gen_cert($key, $cert)) { echo "cert generation failed\n"; exit(1); } -$port = 19940 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $logfile = sys_get_temp_dir() . "/php-http-server-093-" . getmypid() . ".log"; @unlink($logfile); $logfh = fopen($logfile, "w+b"); diff --git a/tests/phpt/server/core/018-log-off-no-overhead.phpt b/tests/phpt/server/core/018-log-off-no-overhead.phpt index 218e385..87a1853 100644 --- a/tests/phpt/server/core/018-log-off-no-overhead.phpt +++ b/tests/phpt/server/core/018-log-off-no-overhead.phpt @@ -17,6 +17,8 @@ if (getenv('GITHUB_ACTIONS') !== false || getenv('SKIP_PERF_TESTS') !== false) { ?> --FILE-- addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/019-parse-error-503-oom.phpt b/tests/phpt/server/core/019-parse-error-503-oom.phpt index 2957f8a..bc903fc 100644 --- a/tests/phpt/server/core/019-parse-error-503-oom.phpt +++ b/tests/phpt/server/core/019-parse-error-503-oom.phpt @@ -22,8 +22,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19900 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setMaxBodySize(128 * 1024 * 1024) /* allow big bodies in principle */ diff --git a/tests/phpt/server/core/020-builtin-worker-pool.phpt b/tests/phpt/server/core/020-builtin-worker-pool.phpt index a5c8602..321064e 100644 --- a/tests/phpt/server/core/020-builtin-worker-pool.phpt +++ b/tests/phpt/server/core/020-builtin-worker-pool.phpt @@ -25,7 +25,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $workers = 2; $config = (new HttpServerConfig()) diff --git a/tests/phpt/server/core/020-telemetry-trace-context.phpt b/tests/phpt/server/core/020-telemetry-trace-context.phpt index 3250f26..56a6a45 100644 --- a/tests/phpt/server/core/020-telemetry-trace-context.phpt +++ b/tests/phpt/server/core/020-telemetry-trace-context.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19770 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/021-bootloader.phpt b/tests/phpt/server/core/021-bootloader.phpt index 2f10f1c..43e35b8 100644 --- a/tests/phpt/server/core/021-bootloader.phpt +++ b/tests/phpt/server/core/021-bootloader.phpt @@ -20,7 +20,9 @@ use TrueAsync\HttpServer; use TrueAsync\HttpServerConfig; use function Async\spawn; -$port = 19980 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $workers = 2; $config = (new HttpServerConfig()) diff --git a/tests/phpt/server/core/021-response-headers-api.phpt b/tests/phpt/server/core/021-response-headers-api.phpt index 0d27ce2..b5e432b 100644 --- a/tests/phpt/server/core/021-response-headers-api.phpt +++ b/tests/phpt/server/core/021-response-headers-api.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19200 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/022-response-status-api.phpt b/tests/phpt/server/core/022-response-status-api.phpt index 50f014e..ad326e2 100644 --- a/tests/phpt/server/core/022-response-status-api.phpt +++ b/tests/phpt/server/core/022-response-status-api.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19210 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/023-response-body-api.phpt b/tests/phpt/server/core/023-response-body-api.phpt index 2d48f75..56b9002 100644 --- a/tests/phpt/server/core/023-response-body-api.phpt +++ b/tests/phpt/server/core/023-response-body-api.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19220 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/024-response-helpers.phpt b/tests/phpt/server/core/024-response-helpers.phpt index 031109d..753def7 100644 --- a/tests/phpt/server/core/024-response-helpers.phpt +++ b/tests/phpt/server/core/024-response-helpers.phpt @@ -13,8 +13,9 @@ use function Async\await; // One server, three requests against three different paths — each path // triggers a different helper. Server stops after the third response. -$port = 19230 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/025-response-state-api.phpt b/tests/phpt/server/core/025-response-state-api.phpt index e77f4cd..b58c3f1 100644 --- a/tests/phpt/server/core/025-response-state-api.phpt +++ b/tests/phpt/server/core/025-response-state-api.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19240 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/026-response-trailers-api.phpt b/tests/phpt/server/core/026-response-trailers-api.phpt index 38ae4a3..64b65a5 100644 --- a/tests/phpt/server/core/026-response-trailers-api.phpt +++ b/tests/phpt/server/core/026-response-trailers-api.phpt @@ -14,8 +14,9 @@ use function Async\await; // drops trailers silently per the stub doc — no need for an H2 client // to verify the in-handler getters). -$port = 19250 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/027-response-validation.phpt b/tests/phpt/server/core/027-response-validation.phpt index b654d47..c3d2372 100644 --- a/tests/phpt/server/core/027-response-validation.phpt +++ b/tests/phpt/server/core/027-response-validation.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19260 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5)); diff --git a/tests/phpt/server/core/030-response-json.phpt b/tests/phpt/server/core/030-response-json.phpt index 3154f70..5cea3a6 100644 --- a/tests/phpt/server/core/030-response-json.phpt +++ b/tests/phpt/server/core/030-response-json.phpt @@ -15,8 +15,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19900 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/036-response-reason-phrases.phpt b/tests/phpt/server/core/036-response-reason-phrases.phpt index 9313a18..95b96df 100644 --- a/tests/phpt/server/core/036-response-reason-phrases.phpt +++ b/tests/phpt/server/core/036-response-reason-phrases.phpt @@ -55,7 +55,9 @@ $codes = [ 299 => 'Unknown', ]; -$port = 19920 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/core/037-http-methods-end-to-end.phpt b/tests/phpt/server/core/037-http-methods-end-to-end.phpt index 73b7e6d..0117674 100644 --- a/tests/phpt/server/core/037-http-methods-end-to-end.phpt +++ b/tests/phpt/server/core/037-http-methods-end-to-end.phpt @@ -15,7 +15,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20000 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/core/040-request-scope-isolation.phpt b/tests/phpt/server/core/040-request-scope-isolation.phpt index 421f200..a0e3b3b 100644 --- a/tests/phpt/server/core/040-request-scope-isolation.phpt +++ b/tests/phpt/server/core/040-request-scope-isolation.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20100 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/041-current-context-child-coroutines.phpt b/tests/phpt/server/core/041-current-context-child-coroutines.phpt index ef4f1b9..03d429e 100644 --- a/tests/phpt/server/core/041-current-context-child-coroutines.phpt +++ b/tests/phpt/server/core/041-current-context-child-coroutines.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20200 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/042-request-context.phpt b/tests/phpt/server/core/042-request-context.phpt index dbdba66..f518b3b 100644 --- a/tests/phpt/server/core/042-request-context.phpt +++ b/tests/phpt/server/core/042-request-context.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20300 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/043-request-context-equals-scope-context.phpt b/tests/phpt/server/core/043-request-context-equals-scope-context.phpt index accf1b8..a198419 100644 --- a/tests/phpt/server/core/043-request-context-equals-scope-context.phpt +++ b/tests/phpt/server/core/043-request-context-equals-scope-context.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20340 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/044-worker-pool-bound-handler.phpt b/tests/phpt/server/core/044-worker-pool-bound-handler.phpt index 652cbf6..082fd6d 100644 --- a/tests/phpt/server/core/044-worker-pool-bound-handler.phpt +++ b/tests/phpt/server/core/044-worker-pool-bound-handler.phpt @@ -42,7 +42,9 @@ PHP; eval($handlerClassSrc); // define BoundHandler in this (parent) thread -$port = 19840 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $workers = 2; $config = (new HttpServerConfig()) diff --git a/tests/phpt/server/core/045-request-context-h2.phpt b/tests/phpt/server/core/045-request-context-h2.phpt index b49f14c..1ab2612 100644 --- a/tests/phpt/server/core/045-request-context-h2.phpt +++ b/tests/phpt/server/core/045-request-context-h2.phpt @@ -30,8 +30,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19790 + getmypid() % 60; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/045-shutdown-drains-inflight.phpt b/tests/phpt/server/core/045-shutdown-drains-inflight.phpt index 0398f56..5a10cb4 100644 --- a/tests/phpt/server/core/045-shutdown-drains-inflight.phpt +++ b/tests/phpt/server/core/045-shutdown-drains-inflight.phpt @@ -15,8 +15,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20180 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/core/046-request-context-h3.phpt b/tests/phpt/server/core/046-request-context-h3.phpt index bca8f84..d098189 100644 --- a/tests/phpt/server/core/046-request-context-h3.phpt +++ b/tests/phpt/server/core/046-request-context-h3.phpt @@ -37,8 +37,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20360 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/core/047-request-context-concurrent.phpt b/tests/phpt/server/core/047-request-context-concurrent.phpt index 51822fe..ba1033e 100644 --- a/tests/phpt/server/core/047-request-context-concurrent.phpt +++ b/tests/phpt/server/core/047-request-context-concurrent.phpt @@ -26,8 +26,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 20120 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/048-request-context-first-accessor.phpt b/tests/phpt/server/core/048-request-context-first-accessor.phpt index cf7629c..e9e31c0 100644 --- a/tests/phpt/server/core/048-request-context-first-accessor.phpt +++ b/tests/phpt/server/core/048-request-context-first-accessor.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 20340 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/core/049-request-scope-setter.phpt b/tests/phpt/server/core/049-request-scope-setter.phpt index 3f20196..497b092 100644 --- a/tests/phpt/server/core/049-request-scope-setter.phpt +++ b/tests/phpt/server/core/049-request-scope-setter.phpt @@ -25,7 +25,8 @@ echo "set true -> " . (int)$c->setRequestScope(true)->isRequestScope() . "\n"; echo "chainable=" . (int)($c->setRequestScope(false) instanceof HttpServerConfig) . "\n"; /* 1 */ /* === Part B: locked after the config is handed to a server === */ -$port = 19965 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $cfg = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setRequestScope(false) /* serve with the per-request scope OFF */ diff --git a/tests/phpt/server/core/050-request-scope-workers.phpt b/tests/phpt/server/core/050-request-scope-workers.phpt index 9ebb2bb..b8dfa82 100644 --- a/tests/phpt/server/core/050-request-scope-workers.phpt +++ b/tests/phpt/server/core/050-request-scope-workers.phpt @@ -23,8 +23,9 @@ use TrueAsync\HttpServer; use TrueAsync\HttpServerConfig; use function Async\spawn; -$port = 19985 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h1/001-pipelining.phpt b/tests/phpt/server/h1/001-pipelining.phpt index dd980e0..aa88f42 100644 --- a/tests/phpt/server/h1/001-pipelining.phpt +++ b/tests/phpt/server/h1/001-pipelining.phpt @@ -18,8 +18,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19650 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h1/002-parse-error-414.phpt b/tests/phpt/server/h1/002-parse-error-414.phpt index 7093083..3cedd88 100644 --- a/tests/phpt/server/h1/002-parse-error-414.phpt +++ b/tests/phpt/server/h1/002-parse-error-414.phpt @@ -10,8 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19817 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h1/003-parse-error-431.phpt b/tests/phpt/server/h1/003-parse-error-431.phpt index 849a18c..d1e54e0 100644 --- a/tests/phpt/server/h1/003-parse-error-431.phpt +++ b/tests/phpt/server/h1/003-parse-error-431.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19818 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/004-parse-error-400.phpt b/tests/phpt/server/h1/004-parse-error-400.phpt index 064373c..2682749 100644 --- a/tests/phpt/server/h1/004-parse-error-400.phpt +++ b/tests/phpt/server/h1/004-parse-error-400.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19819 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/005-parse-error-mid-stream-body.phpt b/tests/phpt/server/h1/005-parse-error-mid-stream-body.phpt index 161c443..58852eb 100644 --- a/tests/phpt/server/h1/005-parse-error-mid-stream-body.phpt +++ b/tests/phpt/server/h1/005-parse-error-mid-stream-body.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19821 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10)->setWriteTimeout(10); diff --git a/tests/phpt/server/h1/006-smuggling-cl-te.phpt b/tests/phpt/server/h1/006-smuggling-cl-te.phpt index 57cf406..5d17341 100644 --- a/tests/phpt/server/h1/006-smuggling-cl-te.phpt +++ b/tests/phpt/server/h1/006-smuggling-cl-te.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19822 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/007-smuggling-dup-cl.phpt b/tests/phpt/server/h1/007-smuggling-dup-cl.phpt index efd8911..635e651 100644 --- a/tests/phpt/server/h1/007-smuggling-dup-cl.phpt +++ b/tests/phpt/server/h1/007-smuggling-dup-cl.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19823 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/008-invalid-content-length.phpt b/tests/phpt/server/h1/008-invalid-content-length.phpt index 033f96a..6160a31 100644 --- a/tests/phpt/server/h1/008-invalid-content-length.phpt +++ b/tests/phpt/server/h1/008-invalid-content-length.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19824 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/009-obs-fold-rejected.phpt b/tests/phpt/server/h1/009-obs-fold-rejected.phpt index 1f29cc1..92f5a9b 100644 --- a/tests/phpt/server/h1/009-obs-fold-rejected.phpt +++ b/tests/phpt/server/h1/009-obs-fold-rejected.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19825 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/010-drain-proactive-age-h1.phpt b/tests/phpt/server/h1/010-drain-proactive-age-h1.phpt index 792ece8..e98d6d1 100644 --- a/tests/phpt/server/h1/010-drain-proactive-age-h1.phpt +++ b/tests/phpt/server/h1/010-drain-proactive-age-h1.phpt @@ -16,8 +16,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19840 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h1/011-drain-reactive-hardcap-h1.phpt b/tests/phpt/server/h1/011-drain-reactive-hardcap-h1.phpt index 4253017..06724ef 100644 --- a/tests/phpt/server/h1/011-drain-reactive-hardcap-h1.phpt +++ b/tests/phpt/server/h1/011-drain-reactive-hardcap-h1.phpt @@ -16,8 +16,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19841 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h1/012-drain-cooldown-blocks-refire.phpt b/tests/phpt/server/h1/012-drain-cooldown-blocks-refire.phpt index f55e0a4..2ff1fee 100644 --- a/tests/phpt/server/h1/012-drain-cooldown-blocks-refire.phpt +++ b/tests/phpt/server/h1/012-drain-cooldown-blocks-refire.phpt @@ -16,8 +16,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19846 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h1/013-h1-chunked-basic.phpt b/tests/phpt/server/h1/013-h1-chunked-basic.phpt index e2e00a3..c261d83 100644 --- a/tests/phpt/server/h1/013-h1-chunked-basic.phpt +++ b/tests/phpt/server/h1/013-h1-chunked-basic.phpt @@ -14,8 +14,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19820 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/014-h1-sse-pattern.phpt b/tests/phpt/server/h1/014-h1-sse-pattern.phpt index 305ac13..60e28ac 100644 --- a/tests/phpt/server/h1/014-h1-sse-pattern.phpt +++ b/tests/phpt/server/h1/014-h1-sse-pattern.phpt @@ -14,8 +14,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19840 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/015-h1-stream-edge-cases.phpt b/tests/phpt/server/h1/015-h1-stream-edge-cases.phpt index ac56ea1..cbc7a43 100644 --- a/tests/phpt/server/h1/015-h1-stream-edge-cases.phpt +++ b/tests/phpt/server/h1/015-h1-stream-edge-cases.phpt @@ -14,8 +14,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19340 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10)->setWriteTimeout(10)); diff --git a/tests/phpt/server/h1/016-h1-stream-after-send-many.phpt b/tests/phpt/server/h1/016-h1-stream-after-send-many.phpt index b945ed7..465b07f 100644 --- a/tests/phpt/server/h1/016-h1-stream-after-send-many.phpt +++ b/tests/phpt/server/h1/016-h1-stream-after-send-many.phpt @@ -14,8 +14,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19350 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10)->setWriteTimeout(10)); diff --git a/tests/phpt/server/h1/017-admission-reject-h1.phpt b/tests/phpt/server/h1/017-admission-reject-h1.phpt index a16599b..1d450eb 100644 --- a/tests/phpt/server/h1/017-admission-reject-h1.phpt +++ b/tests/phpt/server/h1/017-admission-reject-h1.phpt @@ -23,8 +23,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19910 + getmypid() % 80; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setMaxConnections(32) diff --git a/tests/phpt/server/h1/018-tcp-fragmentation.phpt b/tests/phpt/server/h1/018-tcp-fragmentation.phpt index 07b96ca..3bac072 100644 --- a/tests/phpt/server/h1/018-tcp-fragmentation.phpt +++ b/tests/phpt/server/h1/018-tcp-fragmentation.phpt @@ -24,8 +24,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19850 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h1/019-host-validation.phpt b/tests/phpt/server/h1/019-host-validation.phpt index 0a7c929..b0fbe31 100644 --- a/tests/phpt/server/h1/019-host-validation.phpt +++ b/tests/phpt/server/h1/019-host-validation.phpt @@ -22,7 +22,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19824 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/server/h1/020-method-and-response-conformance.phpt b/tests/phpt/server/h1/020-method-and-response-conformance.phpt index 4650b2c..a8f2c01 100644 --- a/tests/phpt/server/h1/020-method-and-response-conformance.phpt +++ b/tests/phpt/server/h1/020-method-and-response-conformance.phpt @@ -21,7 +21,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19825 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5)); $server->addHttpHandler(function ($req, $res) { diff --git a/tests/phpt/server/h1/021-request-target-hardening.phpt b/tests/phpt/server/h1/021-request-target-hardening.phpt index 7793db3..4808d57 100644 --- a/tests/phpt/server/h1/021-request-target-hardening.phpt +++ b/tests/phpt/server/h1/021-request-target-hardening.phpt @@ -22,7 +22,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19826 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port)->setReadTimeout(5)->setWriteTimeout(5)); $server->addHttpHandler(function ($req, $res) { diff --git a/tests/phpt/server/h1/022-h1-sse-api.phpt b/tests/phpt/server/h1/022-h1-sse-api.phpt index c735100..92c0e73 100644 --- a/tests/phpt/server/h1/022-h1-sse-api.phpt +++ b/tests/phpt/server/h1/022-h1-sse-api.phpt @@ -24,8 +24,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/023-h1-sse-validation.phpt b/tests/phpt/server/h1/023-h1-sse-validation.phpt index 9c1e657..4e4f5fb 100644 --- a/tests/phpt/server/h1/023-h1-sse-validation.phpt +++ b/tests/phpt/server/h1/023-h1-sse-validation.phpt @@ -20,8 +20,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19680 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/024-h1-sse-misuse.phpt b/tests/phpt/server/h1/024-h1-sse-misuse.phpt index 88b946e..9f57e12 100644 --- a/tests/phpt/server/h1/024-h1-sse-misuse.phpt +++ b/tests/phpt/server/h1/024-h1-sse-misuse.phpt @@ -23,8 +23,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19700 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/025-h1-sse-client-disconnect.phpt b/tests/phpt/server/h1/025-h1-sse-client-disconnect.phpt index 83bd4c6..ab8f001 100644 --- a/tests/phpt/server/h1/025-h1-sse-client-disconnect.phpt +++ b/tests/phpt/server/h1/025-h1-sse-client-disconnect.phpt @@ -22,8 +22,9 @@ use TrueAsync\HttpException; use function Async\spawn; use function Async\await; -$port = 19780 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h1/050-stream-request-body.phpt b/tests/phpt/server/h1/050-stream-request-body.phpt index 1c4a0a3..fe95017 100644 --- a/tests/phpt/server/h1/050-stream-request-body.phpt +++ b/tests/phpt/server/h1/050-stream-request-body.phpt @@ -14,8 +14,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19920 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h2/001-h2c-get.phpt b/tests/phpt/server/h2/001-h2c-get.phpt index cc433a8..5b44e76 100644 --- a/tests/phpt/server/h2/001-h2c-get.phpt +++ b/tests/phpt/server/h2/001-h2c-get.phpt @@ -24,8 +24,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19700 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h2/002-h2c-post.phpt b/tests/phpt/server/h2/002-h2c-post.phpt index 4b3ec49..4d3aef1 100644 --- a/tests/phpt/server/h2/002-h2c-post.phpt +++ b/tests/phpt/server/h2/002-h2c-post.phpt @@ -21,8 +21,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19710 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h2/003-h2c-trailers.phpt b/tests/phpt/server/h2/003-h2c-trailers.phpt index f0db5cd..aadf7de 100644 --- a/tests/phpt/server/h2/003-h2c-trailers.phpt +++ b/tests/phpt/server/h2/003-h2c-trailers.phpt @@ -21,8 +21,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19720 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h2/004-h2-tls-get.phpt b/tests/phpt/server/h2/004-h2-tls-get.phpt index dbf5a6a..21fc9be 100644 --- a/tests/phpt/server/h2/004-h2-tls-get.phpt +++ b/tests/phpt/server/h2/004-h2-tls-get.phpt @@ -29,8 +29,9 @@ $cert = $tmp_dir . '/cert.pem'; $key = $tmp_dir . '/key.pem'; if (!h2_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } -$port = 19970 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/h2/005-h2-tls-fallback.phpt b/tests/phpt/server/h2/005-h2-tls-fallback.phpt index cf1b578..b2178bb 100644 --- a/tests/phpt/server/h2/005-h2-tls-fallback.phpt +++ b/tests/phpt/server/h2/005-h2-tls-fallback.phpt @@ -29,8 +29,9 @@ $cert = $tmp_dir . '/cert.pem'; $key = $tmp_dir . '/key.pem'; if (!h2_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } -$port = 19990 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/h2/006-h2c-multiplex.phpt b/tests/phpt/server/h2/006-h2c-multiplex.phpt index c3e49ca..2e11142 100644 --- a/tests/phpt/server/h2/006-h2c-multiplex.phpt +++ b/tests/phpt/server/h2/006-h2c-multiplex.phpt @@ -26,8 +26,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19730 + getmypid() % 60; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/server/h2/007-h2c-peer-reset-cancel.phpt b/tests/phpt/server/h2/007-h2c-peer-reset-cancel.phpt index f6e99e9..36e21aa 100644 --- a/tests/phpt/server/h2/007-h2c-peer-reset-cancel.phpt +++ b/tests/phpt/server/h2/007-h2c-peer-reset-cancel.phpt @@ -31,8 +31,9 @@ use function Async\delay; require __DIR__ . '/_h2_client.inc'; -$port = 19830 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/008-h2c-peer-reset-await-body.phpt b/tests/phpt/server/h2/008-h2c-peer-reset-await-body.phpt index f6b7ddd..5bbe3ff 100644 --- a/tests/phpt/server/h2/008-h2c-peer-reset-await-body.phpt +++ b/tests/phpt/server/h2/008-h2c-peer-reset-await-body.phpt @@ -29,8 +29,9 @@ use function Async\delay; require __DIR__ . '/_h2_client.inc'; -$port = 19831 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/009-h2-h2spec-gate.phpt b/tests/phpt/server/h2/009-h2-h2spec-gate.phpt index 00b4435..45575c6 100644 --- a/tests/phpt/server/h2/009-h2-h2spec-gate.phpt +++ b/tests/phpt/server/h2/009-h2-h2spec-gate.phpt @@ -41,9 +41,9 @@ if ($h2spec === '' && is_executable($home = (string)getenv('HOME') . '/.local/bi $h2spec = $home; } -$port = 19500 + getmypid() % 200; +require_once __DIR__ . '/../_free_port.inc'; -// PHP_BINARY would re-enter THIS test under the phpt runner; use its +$port = tas_free_port(); // caller chain via posix or fall back to reading /proc/self/exe. $php = PHP_BINARY; diff --git a/tests/phpt/server/h2/010-drain-proactive-age-h2-goaway.phpt b/tests/phpt/server/h2/010-drain-proactive-age-h2-goaway.phpt index e93afef..8ba43ee 100644 --- a/tests/phpt/server/h2/010-drain-proactive-age-h2-goaway.phpt +++ b/tests/phpt/server/h2/010-drain-proactive-age-h2-goaway.phpt @@ -22,8 +22,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19842 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/011-drain-h2-multiplex-completes.phpt b/tests/phpt/server/h2/011-drain-h2-multiplex-completes.phpt index a71e8ef..c8dc030 100644 --- a/tests/phpt/server/h2/011-drain-h2-multiplex-completes.phpt +++ b/tests/phpt/server/h2/011-drain-h2-multiplex-completes.phpt @@ -21,8 +21,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19843 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/013-h2-streaming-basic.phpt b/tests/phpt/server/h2/013-h2-streaming-basic.phpt index 609c145..b7fc636 100644 --- a/tests/phpt/server/h2/013-h2-streaming-basic.phpt +++ b/tests/phpt/server/h2/013-h2-streaming-basic.phpt @@ -23,8 +23,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19850 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/014-h2-streaming-large.phpt b/tests/phpt/server/h2/014-h2-streaming-large.phpt index b38229f..278c4af 100644 --- a/tests/phpt/server/h2/014-h2-streaming-large.phpt +++ b/tests/phpt/server/h2/014-h2-streaming-large.phpt @@ -21,8 +21,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19851 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/015-h2-streaming-backpressure.phpt b/tests/phpt/server/h2/015-h2-streaming-backpressure.phpt index 0343b2a..7bbaf60 100644 --- a/tests/phpt/server/h2/015-h2-streaming-backpressure.phpt +++ b/tests/phpt/server/h2/015-h2-streaming-backpressure.phpt @@ -25,8 +25,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19870 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(15) diff --git a/tests/phpt/server/h2/016-h2-streaming-telemetry.phpt b/tests/phpt/server/h2/016-h2-streaming-telemetry.phpt index 15b453c..17f763a 100644 --- a/tests/phpt/server/h2/016-h2-streaming-telemetry.phpt +++ b/tests/phpt/server/h2/016-h2-streaming-telemetry.phpt @@ -20,8 +20,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19910 + getmypid() % 80; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h2/017-h2-streaming-cancel.phpt b/tests/phpt/server/h2/017-h2-streaming-cancel.phpt index f45d890..46a413a 100644 --- a/tests/phpt/server/h2/017-h2-streaming-cancel.phpt +++ b/tests/phpt/server/h2/017-h2-streaming-cancel.phpt @@ -32,8 +32,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19860 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h2/018-h2-only-listener.phpt b/tests/phpt/server/h2/018-h2-only-listener.phpt index ae79752..0118a1c 100644 --- a/tests/phpt/server/h2/018-h2-only-listener.phpt +++ b/tests/phpt/server/h2/018-h2-only-listener.phpt @@ -26,8 +26,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h2/019-h2-stream-telemetry.phpt b/tests/phpt/server/h2/019-h2-stream-telemetry.phpt index 2f3ecff..d514743 100644 --- a/tests/phpt/server/h2/019-h2-stream-telemetry.phpt +++ b/tests/phpt/server/h2/019-h2-stream-telemetry.phpt @@ -16,8 +16,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19900 + getmypid() % 80; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h2/020-admission-reject-h2.phpt b/tests/phpt/server/h2/020-admission-reject-h2.phpt index 924167e..9e35172 100644 --- a/tests/phpt/server/h2/020-admission-reject-h2.phpt +++ b/tests/phpt/server/h2/020-admission-reject-h2.phpt @@ -33,8 +33,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19980 + getmypid() % 10; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setMaxConnections(32) diff --git a/tests/phpt/server/h2/021-h2-tls-multiplex.phpt b/tests/phpt/server/h2/021-h2-tls-multiplex.phpt index 85d0250..4bfc4bf 100644 --- a/tests/phpt/server/h2/021-h2-tls-multiplex.phpt +++ b/tests/phpt/server/h2/021-h2-tls-multiplex.phpt @@ -46,7 +46,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19800 + getmypid() % 200; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $body_bytes = 256 * 1024; $config = (new HttpServerConfig()) diff --git a/tests/phpt/server/h2/022-h2-streaming-ring-full.phpt b/tests/phpt/server/h2/022-h2-streaming-ring-full.phpt index f350982..6646960 100644 --- a/tests/phpt/server/h2/022-h2-streaming-ring-full.phpt +++ b/tests/phpt/server/h2/022-h2-streaming-ring-full.phpt @@ -30,8 +30,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19890 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $CHUNK_SZ = 8192; $N_CHUNKS = 64; diff --git a/tests/phpt/server/h2/023-h2-streaming-sendable.phpt b/tests/phpt/server/h2/023-h2-streaming-sendable.phpt index b1bb8db..d7f7478 100644 --- a/tests/phpt/server/h2/023-h2-streaming-sendable.phpt +++ b/tests/phpt/server/h2/023-h2-streaming-sendable.phpt @@ -25,8 +25,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19920 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $CHUNK_SZ = 8192; $N_CHUNKS = 48; diff --git a/tests/phpt/server/h2/024-h2-tls-large-body.phpt b/tests/phpt/server/h2/024-h2-tls-large-body.phpt index ea4d9a8..bb5720b 100644 --- a/tests/phpt/server/h2/024-h2-tls-large-body.phpt +++ b/tests/phpt/server/h2/024-h2-tls-large-body.phpt @@ -28,7 +28,9 @@ $cert = $tmp_dir . '/cert.pem'; $key = $tmp_dir . '/key.pem'; if (!h2_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } -$port = 19890 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $size = 256 * 1024; $body = str_repeat('A', $size); diff --git a/tests/phpt/server/h2/025-h2-sse-api.phpt b/tests/phpt/server/h2/025-h2-sse-api.phpt index e26d196..0dc450c 100644 --- a/tests/phpt/server/h2/025-h2-sse-api.phpt +++ b/tests/phpt/server/h2/025-h2-sse-api.phpt @@ -20,8 +20,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19890 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/026-h2-sse-empty-start.phpt b/tests/phpt/server/h2/026-h2-sse-empty-start.phpt index cc405c2..9e78d84 100644 --- a/tests/phpt/server/h2/026-h2-sse-empty-start.phpt +++ b/tests/phpt/server/h2/026-h2-sse-empty-start.phpt @@ -23,8 +23,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19910 + getmypid() % 80; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/server/h2/050-stream-request-body.phpt b/tests/phpt/server/h2/050-stream-request-body.phpt index a0783fe..d682e7f 100644 --- a/tests/phpt/server/h2/050-stream-request-body.phpt +++ b/tests/phpt/server/h2/050-stream-request-body.phpt @@ -15,8 +15,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 19950 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer( (new HttpServerConfig()) ->addListener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/001-h3-udp-recv.phpt b/tests/phpt/server/h3/001-h3-udp-recv.phpt index d6a69f5..5aa936e 100644 --- a/tests/phpt/server/h3/001-h3-udp-recv.phpt +++ b/tests/phpt/server/h3/001-h3-udp-recv.phpt @@ -30,8 +30,9 @@ $cert_path = $tmp_dir . '/cert.pem'; $key_path = $tmp_dir . '/key.pem'; if (!h3_gen_cert($key_path, $cert_path)) { echo "cert gen failed\n"; exit(1); } -$port = 19900 + getmypid() % 100; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) /* dummy TCP so start() has >=1 listener pre-H3 */ ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/002-h3-packet-parse.phpt b/tests/phpt/server/h3/002-h3-packet-parse.phpt index 2a703e8..9f0c960 100644 --- a/tests/phpt/server/h3/002-h3-packet-parse.phpt +++ b/tests/phpt/server/h3/002-h3-packet-parse.phpt @@ -39,8 +39,9 @@ $cert_path = $tmp_dir . '/cert.pem'; $key_path = $tmp_dir . '/key.pem'; if (!h3_gen_cert($key_path, $cert_path)) { echo "cert gen failed\n"; exit(1); } -$port = 19950 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/004-h3-start-without-cert.phpt b/tests/phpt/server/h3/004-h3-start-without-cert.phpt index 9917b67..4244c9f 100644 --- a/tests/phpt/server/h3/004-h3-start-without-cert.phpt +++ b/tests/phpt/server/h3/004-h3-start-without-cert.phpt @@ -18,8 +18,9 @@ if (!class_exists('TrueAsync\HttpServer')) die('skip http_server not loaded'); use TrueAsync\HttpServer; use TrueAsync\HttpServerConfig; -$port = 20100 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addHttp3Listener('127.0.0.1', $port) ->setReadTimeout(2); diff --git a/tests/phpt/server/h3/005-h3-repeat-initial-same-dcid.phpt b/tests/phpt/server/h3/005-h3-repeat-initial-same-dcid.phpt index 58b2c74..10ea722 100644 --- a/tests/phpt/server/h3/005-h3-repeat-initial-same-dcid.phpt +++ b/tests/phpt/server/h3/005-h3-repeat-initial-same-dcid.phpt @@ -32,8 +32,9 @@ $cert_path = $tmp_dir . '/cert.pem'; $key_path = $tmp_dir . '/key.pem'; if (!h3_gen_cert($key_path, $cert_path)) { echo "cert gen failed\n"; exit(1); } -$port = 20150 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/008-h3-stats-handshake-keys.phpt b/tests/phpt/server/h3/008-h3-stats-handshake-keys.phpt index f36d1da..e606a7d 100644 --- a/tests/phpt/server/h3/008-h3-stats-handshake-keys.phpt +++ b/tests/phpt/server/h3/008-h3-stats-handshake-keys.phpt @@ -33,8 +33,9 @@ $cert_path = $tmp_dir . '/cert.pem'; $key_path = $tmp_dir . '/key.pem'; if (!h3_gen_cert($key_path, $cert_path)) { echo "cert gen failed\n"; exit(1); } -$port = 20250 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/009-h3-e2e-get.phpt b/tests/phpt/server/h3/009-h3-e2e-get.phpt index 1d4ccbf..0dd444e 100644 --- a/tests/phpt/server/h3/009-h3-e2e-get.phpt +++ b/tests/phpt/server/h3/009-h3-e2e-get.phpt @@ -40,8 +40,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20300 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) /* TCP listener required by start() */ ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/010-h3-e2e-post-await-body.phpt b/tests/phpt/server/h3/010-h3-e2e-post-await-body.phpt index 25c3ecf..c046b19 100644 --- a/tests/phpt/server/h3/010-h3-e2e-post-await-body.phpt +++ b/tests/phpt/server/h3/010-h3-e2e-post-await-body.phpt @@ -38,8 +38,9 @@ file_put_contents($body_path, $body); $expected = sprintf("len=%d sha1=%s method=POST", strlen($body), sha1($body)); -$port = 20400 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/011-h3-e2e-streaming-send.phpt b/tests/phpt/server/h3/011-h3-e2e-streaming-send.phpt index 2a10613..1beecd1 100644 --- a/tests/phpt/server/h3/011-h3-e2e-streaming-send.phpt +++ b/tests/phpt/server/h3/011-h3-e2e-streaming-send.phpt @@ -47,8 +47,9 @@ $expected_body = implode('', $chunks); $expected_sha1 = sha1($expected_body); $expected_len = strlen($expected_body); -$port = 20500 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/012-h3-graceful-close.phpt b/tests/phpt/server/h3/012-h3-graceful-close.phpt index 31b5bc0..0c59db0 100644 --- a/tests/phpt/server/h3/012-h3-graceful-close.phpt +++ b/tests/phpt/server/h3/012-h3-graceful-close.phpt @@ -33,8 +33,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20400 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/013-h3-stateless-reset.phpt b/tests/phpt/server/h3/013-h3-stateless-reset.phpt index d3b8500..47e8a8c 100644 --- a/tests/phpt/server/h3/013-h3-stateless-reset.phpt +++ b/tests/phpt/server/h3/013-h3-stateless-reset.phpt @@ -33,8 +33,9 @@ $cert = $tmp . '/cert.pem'; $key = $tmp . '/key.pem'; if (!h3_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } -$port = 20500 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/014-h3-drain-max-conn-age.phpt b/tests/phpt/server/h3/014-h3-drain-max-conn-age.phpt index 46261b9..1322fa9 100644 --- a/tests/phpt/server/h3/014-h3-drain-max-conn-age.phpt +++ b/tests/phpt/server/h3/014-h3-drain-max-conn-age.phpt @@ -33,8 +33,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20600 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/015-h3-idle-timeout.phpt b/tests/phpt/server/h3/015-h3-idle-timeout.phpt index 1608023..4e318db 100644 --- a/tests/phpt/server/h3/015-h3-idle-timeout.phpt +++ b/tests/phpt/server/h3/015-h3-idle-timeout.phpt @@ -37,8 +37,9 @@ if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } putenv('PHP_HTTP3_IDLE_TIMEOUT_MS=500'); -$port = 20700 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/016-h3-per-peer-budget.phpt b/tests/phpt/server/h3/016-h3-per-peer-budget.phpt index bdc8696..efc05a5 100644 --- a/tests/phpt/server/h3/016-h3-per-peer-budget.phpt +++ b/tests/phpt/server/h3/016-h3-per-peer-budget.phpt @@ -38,8 +38,9 @@ if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } putenv('PHP_HTTP3_PEER_BUDGET=1'); -$port = 20800 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/017-h3-alt-svc-header.phpt b/tests/phpt/server/h3/017-h3-alt-svc-header.phpt index 67ddf04..3525c76 100644 --- a/tests/phpt/server/h3/017-h3-alt-svc-header.phpt +++ b/tests/phpt/server/h3/017-h3-alt-svc-header.phpt @@ -63,7 +63,9 @@ function run_server(int $tcp_port, int $udp_port, string $cert, string $key, boo return $captured; } -$port_tcp = 20900 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; + +$port_tcp = tas_free_port_span(11); $port_udp = $port_tcp + 1; $out = run_server($port_tcp, $port_udp, $cert, $key, /* disable */ false); diff --git a/tests/phpt/server/h3/018-h3-version-negotiation.phpt b/tests/phpt/server/h3/018-h3-version-negotiation.phpt index 6d3cdc0..10457b6 100644 --- a/tests/phpt/server/h3/018-h3-version-negotiation.phpt +++ b/tests/phpt/server/h3/018-h3-version-negotiation.phpt @@ -31,8 +31,9 @@ $cert = $tmp . '/cert.pem'; $key = $tmp . '/key.pem'; if (!h3_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } -$port = 21000 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1, true) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/022-h3-stats-error-counters.phpt b/tests/phpt/server/h3/022-h3-stats-error-counters.phpt index 5975c3d..b749955 100644 --- a/tests/phpt/server/h3/022-h3-stats-error-counters.phpt +++ b/tests/phpt/server/h3/022-h3-stats-error-counters.phpt @@ -29,8 +29,9 @@ $cert_path = $tmp_dir . '/cert.pem'; $key_path = $tmp_dir . '/key.pem'; if (!h3_gen_cert($key_path, $cert_path)) { echo "cert gen failed\n"; exit(1); } -$port = 20300 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/024-h3-config-setters-e2e.phpt b/tests/phpt/server/h3/024-h3-config-setters-e2e.phpt index 8bec6ec..9977c0d 100644 --- a/tests/phpt/server/h3/024-h3-config-setters-e2e.phpt +++ b/tests/phpt/server/h3/024-h3-config-setters-e2e.phpt @@ -38,8 +38,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20920 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/025-h3-retry-token.phpt b/tests/phpt/server/h3/025-h3-retry-token.phpt index 9415c7a..3467f16 100644 --- a/tests/phpt/server/h3/025-h3-retry-token.phpt +++ b/tests/phpt/server/h3/025-h3-retry-token.phpt @@ -25,8 +25,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20420 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/026-h3-static-file.phpt b/tests/phpt/server/h3/026-h3-static-file.phpt index e392e60..f5852f1 100644 --- a/tests/phpt/server/h3/026-h3-static-file.phpt +++ b/tests/phpt/server/h3/026-h3-static-file.phpt @@ -55,8 +55,9 @@ register_shutdown_function(function () use ($tmp, $root, $sizes) { @rmdir($root); @rmdir($tmp); }); -$port = 20360 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/027-h3-static-mount.phpt b/tests/phpt/server/h3/027-h3-static-mount.phpt index 10c1d6c..162ac93 100644 --- a/tests/phpt/server/h3/027-h3-static-mount.phpt +++ b/tests/phpt/server/h3/027-h3-static-mount.phpt @@ -58,8 +58,9 @@ register_shutdown_function(function () use ($tmp, $root, $sizes) { @rmdir($root); @rmdir($tmp); }); -$port = 20400 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/028-h3-large-body.phpt b/tests/phpt/server/h3/028-h3-large-body.phpt index 9a5b6cf..f680b7c 100644 --- a/tests/phpt/server/h3/028-h3-large-body.phpt +++ b/tests/phpt/server/h3/028-h3-large-body.phpt @@ -38,9 +38,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 20440 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; -/* Position-varying content so a reorder/truncation shows as a sha1 miss. */ +$port = tas_free_port_span(2); $size = 2 * 1024 * 1024; $body = str_repeat("\0", $size); for ($i = 0; $i < $size; $i++) { $body[$i] = chr(($i * 31 + 7) & 0xff); } diff --git a/tests/phpt/server/h3/029-h3-pacing-setter.phpt b/tests/phpt/server/h3/029-h3-pacing-setter.phpt index 93e6fb1..424e67a 100644 --- a/tests/phpt/server/h3/029-h3-pacing-setter.phpt +++ b/tests/phpt/server/h3/029-h3-pacing-setter.phpt @@ -42,7 +42,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 20460 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port_span(2); $size = 256 * 1024; $body = str_repeat("\0", $size); for ($i = 0; $i < $size; $i++) { $body[$i] = chr(($i * 31 + 7) & 0xff); } diff --git a/tests/phpt/server/h3/031-h3-stats-nonzero-after-traffic.phpt b/tests/phpt/server/h3/031-h3-stats-nonzero-after-traffic.phpt index f854ab7..d601178 100644 --- a/tests/phpt/server/h3/031-h3-stats-nonzero-after-traffic.phpt +++ b/tests/phpt/server/h3/031-h3-stats-nonzero-after-traffic.phpt @@ -33,8 +33,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 20560 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/032-h3-connection-migration.phpt b/tests/phpt/server/h3/032-h3-connection-migration.phpt index bce1a11..6ee050d 100644 --- a/tests/phpt/server/h3/032-h3-connection-migration.phpt +++ b/tests/phpt/server/h3/032-h3-connection-migration.phpt @@ -39,8 +39,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21100 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/033-h3-head-request.phpt b/tests/phpt/server/h3/033-h3-head-request.phpt index 2348421..0e77191 100644 --- a/tests/phpt/server/h3/033-h3-head-request.phpt +++ b/tests/phpt/server/h3/033-h3-head-request.phpt @@ -31,8 +31,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 20760 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/034-h3-stateless-reset-clamps.phpt b/tests/phpt/server/h3/034-h3-stateless-reset-clamps.phpt index 3d3ddd0..b6ab2b6 100644 --- a/tests/phpt/server/h3/034-h3-stateless-reset-clamps.phpt +++ b/tests/phpt/server/h3/034-h3-stateless-reset-clamps.phpt @@ -35,8 +35,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 20680 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/035-h3-request-body-overflow.phpt b/tests/phpt/server/h3/035-h3-request-body-overflow.phpt index e7aee21..5e4e76a 100644 --- a/tests/phpt/server/h3/035-h3-request-body-overflow.phpt +++ b/tests/phpt/server/h3/035-h3-request-body-overflow.phpt @@ -39,8 +39,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key, $big) { @unlink($cert); @unlink($key); @unlink($big); @rmdir($tmp); }); -$port = 20720 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/037-h3-reactor-pool-e2e.phpt b/tests/phpt/server/h3/037-h3-reactor-pool-e2e.phpt index 7e5fa64..e96be10 100644 --- a/tests/phpt/server/h3/037-h3-reactor-pool-e2e.phpt +++ b/tests/phpt/server/h3/037-h3-reactor-pool-e2e.phpt @@ -45,8 +45,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21300 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) /* TCP listener required by start() */ ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/038-h3-reactor-pool-post.phpt b/tests/phpt/server/h3/038-h3-reactor-pool-post.phpt index e83133f..2a3bba9 100644 --- a/tests/phpt/server/h3/038-h3-reactor-pool-post.phpt +++ b/tests/phpt/server/h3/038-h3-reactor-pool-post.phpt @@ -49,8 +49,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key, $body_path) { @unlink($cert); @unlink($key); @unlink($body_path); @rmdir($tmp); }); -$port = 21380 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/039-h3-reactor-pool-static.phpt b/tests/phpt/server/h3/039-h3-reactor-pool-static.phpt index 90c7392..d2e55de 100644 --- a/tests/phpt/server/h3/039-h3-reactor-pool-static.phpt +++ b/tests/phpt/server/h3/039-h3-reactor-pool-static.phpt @@ -52,8 +52,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key, $root) { @rmdir($root); @rmdir($tmp); }); -$port = 21420 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/040-h3-reactor-pool-steering.phpt b/tests/phpt/server/h3/040-h3-reactor-pool-steering.phpt index 94876ae..0f25e29 100644 --- a/tests/phpt/server/h3/040-h3-reactor-pool-steering.phpt +++ b/tests/phpt/server/h3/040-h3-reactor-pool-steering.phpt @@ -55,8 +55,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21340 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) /* TCP listener required by start() */ ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/041-h3-migration-storm-guard.phpt b/tests/phpt/server/h3/041-h3-migration-storm-guard.phpt index 15c0ea3..5917d21 100644 --- a/tests/phpt/server/h3/041-h3-migration-storm-guard.phpt +++ b/tests/phpt/server/h3/041-h3-migration-storm-guard.phpt @@ -55,8 +55,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21380 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) /* TCP listener required by start() */ ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/041-h3-sse-api.phpt b/tests/phpt/server/h3/041-h3-sse-api.phpt index e240d9d..5a52ae2 100644 --- a/tests/phpt/server/h3/041-h3-sse-api.phpt +++ b/tests/phpt/server/h3/041-h3-sse-api.phpt @@ -36,8 +36,9 @@ $expected_body = "data: multi\ndata: line\n\n" . "id: 7\nevent: ping\ndata: named\n\n"; -$port = 20560 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/042-h3-newcid-dcid-rotation.phpt b/tests/phpt/server/h3/042-h3-newcid-dcid-rotation.phpt index 3fc45c6..f923b66 100644 --- a/tests/phpt/server/h3/042-h3-newcid-dcid-rotation.phpt +++ b/tests/phpt/server/h3/042-h3-newcid-dcid-rotation.phpt @@ -41,8 +41,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21420 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/042-h3-sse-empty-start.phpt b/tests/phpt/server/h3/042-h3-sse-empty-start.phpt index 046e8b7..8902df1 100644 --- a/tests/phpt/server/h3/042-h3-sse-empty-start.phpt +++ b/tests/phpt/server/h3/042-h3-sse-empty-start.phpt @@ -32,8 +32,9 @@ exec(sprintf('openssl req -x509 -newkey rsa:2048 -sha256 -days 1 -nodes ' escapeshellarg($key), escapeshellarg($cert)), $_, $rc); if ($rc !== 0) { echo "cert gen failed\n"; exit(1); } -$port = 20600 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/043-h3-newcid-multi-rotation.phpt b/tests/phpt/server/h3/043-h3-newcid-multi-rotation.phpt index c24417e..2b5e28b 100644 --- a/tests/phpt/server/h3/043-h3-newcid-multi-rotation.phpt +++ b/tests/phpt/server/h3/043-h3-newcid-multi-rotation.phpt @@ -36,8 +36,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 21460 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/h3/044-hq-interop-file.phpt b/tests/phpt/server/h3/044-hq-interop-file.phpt index ca36d2f..d35790c 100644 --- a/tests/phpt/server/h3/044-hq-interop-file.phpt +++ b/tests/phpt/server/h3/044-hq-interop-file.phpt @@ -55,8 +55,9 @@ register_shutdown_function(function () use ($tmp, $root, $sizes) { @rmdir($root); @rmdir($tmp); }); -$port = 20460 + getmypid() % 40; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port + 1) ->addHttp3Listener('127.0.0.1', $port) diff --git a/tests/phpt/server/sendfile/001-sendfile-basic.phpt b/tests/phpt/server/sendfile/001-sendfile-basic.phpt index 3f8f02d..c21626a 100644 --- a/tests/phpt/server/sendfile/001-sendfile-basic.phpt +++ b/tests/phpt/server/sendfile/001-sendfile-basic.phpt @@ -17,7 +17,9 @@ file_put_contents($tmp, "body{margin:0}"); register_shutdown_function(function() use ($tmp) { @unlink($tmp); }); -$port = 28310 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addHttpHandler(function ($req, $res) use ($tmp) { diff --git a/tests/phpt/server/sendfile/002-sendfile-options.phpt b/tests/phpt/server/sendfile/002-sendfile-options.phpt index 855195b..299e5d3 100644 --- a/tests/phpt/server/sendfile/002-sendfile-options.phpt +++ b/tests/phpt/server/sendfile/002-sendfile-options.phpt @@ -17,7 +17,9 @@ file_put_contents($tmp, "abcdef"); register_shutdown_function(function() use ($tmp) { @unlink($tmp); }); -$port = 28320 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addHttpHandler(function ($req, $res) use ($tmp) { diff --git a/tests/phpt/server/sendfile/003-sendfile-sealed.phpt b/tests/phpt/server/sendfile/003-sendfile-sealed.phpt index 373fee7..d580d5f 100644 --- a/tests/phpt/server/sendfile/003-sendfile-sealed.phpt +++ b/tests/phpt/server/sendfile/003-sendfile-sealed.phpt @@ -16,7 +16,9 @@ file_put_contents($tmp, "ZZZZZ"); register_shutdown_function(function() use ($tmp) { @unlink($tmp); }); -$port = 28330 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addHttpHandler(function ($req, $res) use ($tmp) { diff --git a/tests/phpt/server/sendfile/004-sendfile-errors.phpt b/tests/phpt/server/sendfile/004-sendfile-errors.phpt index b3f6781..7c1b036 100644 --- a/tests/phpt/server/sendfile/004-sendfile-errors.phpt +++ b/tests/phpt/server/sendfile/004-sendfile-errors.phpt @@ -10,7 +10,9 @@ use TrueAsync\HttpServerConfig; use function Async\spawn; use function Async\await; -$port = 28340 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addHttpHandler(function ($req, $res) { diff --git a/tests/phpt/server/sendfile/005-sendfile-rfc5987.phpt b/tests/phpt/server/sendfile/005-sendfile-rfc5987.phpt index c13f9d2..0b8c4eb 100644 --- a/tests/phpt/server/sendfile/005-sendfile-rfc5987.phpt +++ b/tests/phpt/server/sendfile/005-sendfile-rfc5987.phpt @@ -31,7 +31,9 @@ $cases = [ "attachment; filename*=UTF-8''a%22b.txt"], ]; -$port = 28430 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addHttpHandler(function ($req, $res) use ($tmp, $cases) { diff --git a/tests/phpt/server/static/001-static-basic.phpt b/tests/phpt/server/static/001-static-basic.phpt index 9606e1c..0cb1499 100644 --- a/tests/phpt/server/static/001-static-basic.phpt +++ b/tests/phpt/server/static/001-static-basic.phpt @@ -27,7 +27,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19817 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $h = (new StaticHandler('/static/', $root))->setIndexFiles('index.html'); diff --git a/tests/phpt/server/static/002-static-dotfile-and-onmissing.phpt b/tests/phpt/server/static/002-static-dotfile-and-onmissing.phpt index 8ff376b..f1ffc1f 100644 --- a/tests/phpt/server/static/002-static-dotfile-and-onmissing.phpt +++ b/tests/phpt/server/static/002-static-dotfile-and-onmissing.phpt @@ -25,7 +25,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19817 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/static/003-static-security.phpt b/tests/phpt/server/static/003-static-security.phpt index 4b86e44..3bf2310 100644 --- a/tests/phpt/server/static/003-static-security.phpt +++ b/tests/phpt/server/static/003-static-security.phpt @@ -49,7 +49,9 @@ register_shutdown_function(function() use ($base, $forbidden) { $rm($base); }); -$port = 19817 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $h = new StaticHandler('/static/', $root); diff --git a/tests/phpt/server/static/004-static-workers.phpt b/tests/phpt/server/static/004-static-workers.phpt index c70ed1d..27ba548 100644 --- a/tests/phpt/server/static/004-static-workers.phpt +++ b/tests/phpt/server/static/004-static-workers.phpt @@ -30,7 +30,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19940 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $workers = 2; $config = (new HttpServerConfig()) diff --git a/tests/phpt/server/static/005-static-if-modified-since.phpt b/tests/phpt/server/static/005-static-if-modified-since.phpt index 7dfc88a..c4e858f 100644 --- a/tests/phpt/server/static/005-static-if-modified-since.phpt +++ b/tests/phpt/server/static/005-static-if-modified-since.phpt @@ -30,7 +30,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19960 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler(new StaticHandler('/static/', $root)); diff --git a/tests/phpt/server/static/006-static-zero-coroutine-counter.phpt b/tests/phpt/server/static/006-static-zero-coroutine-counter.phpt index c87666e..b7cc35b 100644 --- a/tests/phpt/server/static/006-static-zero-coroutine-counter.phpt +++ b/tests/phpt/server/static/006-static-zero-coroutine-counter.phpt @@ -27,7 +27,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19990 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler((new StaticHandler('/static/', $root))->disableIndex()); diff --git a/tests/phpt/server/static/007-static-tls-streaming.phpt b/tests/phpt/server/static/007-static-tls-streaming.phpt index 7d72461..935526d 100644 --- a/tests/phpt/server/static/007-static-tls-streaming.phpt +++ b/tests/phpt/server/static/007-static-tls-streaming.phpt @@ -38,8 +38,9 @@ register_shutdown_function(function() use ($root, $tmp) { @rmdir($tmp); }); -$port = 19960 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/static/008-static-cache-counters.phpt b/tests/phpt/server/static/008-static-cache-counters.phpt index bc60a3a..ad80673 100644 --- a/tests/phpt/server/static/008-static-cache-counters.phpt +++ b/tests/phpt/server/static/008-static-cache-counters.phpt @@ -28,7 +28,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19940 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/009-static-symlink-owner.phpt b/tests/phpt/server/static/009-static-symlink-owner.phpt index d27cbca..91189c9 100644 --- a/tests/phpt/server/static/009-static-symlink-owner.phpt +++ b/tests/phpt/server/static/009-static-symlink-owner.phpt @@ -45,7 +45,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19960 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/static/010-static-precompressed.phpt b/tests/phpt/server/static/010-static-precompressed.phpt index bca15c0..d803be5 100644 --- a/tests/phpt/server/static/010-static-precompressed.phpt +++ b/tests/phpt/server/static/010-static-precompressed.phpt @@ -38,7 +38,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19930 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/011-static-precompressed-cache-uaf.phpt b/tests/phpt/server/static/011-static-precompressed-cache-uaf.phpt index 87aef55..71c6e1a 100644 --- a/tests/phpt/server/static/011-static-precompressed-cache-uaf.phpt +++ b/tests/phpt/server/static/011-static-precompressed-cache-uaf.phpt @@ -41,7 +41,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19460 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/011-static-range.phpt b/tests/phpt/server/static/011-static-range.phpt index ab13e1d..857c192 100644 --- a/tests/phpt/server/static/011-static-range.phpt +++ b/tests/phpt/server/static/011-static-range.phpt @@ -28,7 +28,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19920 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler((new StaticHandler('/r/', $root))->disableIndex()); diff --git a/tests/phpt/server/static/012-static-h2.phpt b/tests/phpt/server/static/012-static-h2.phpt index 58927d7..d9e8196 100644 --- a/tests/phpt/server/static/012-static-h2.phpt +++ b/tests/phpt/server/static/012-static-h2.phpt @@ -38,7 +38,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19940 + getmypid() % 50; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/012-static-precompressed-small-cache-headers.phpt b/tests/phpt/server/static/012-static-precompressed-small-cache-headers.phpt index 318165a..9109dc4 100644 --- a/tests/phpt/server/static/012-static-precompressed-small-cache-headers.phpt +++ b/tests/phpt/server/static/012-static-precompressed-small-cache-headers.phpt @@ -43,7 +43,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19480 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/013-static-h2-tls.phpt b/tests/phpt/server/static/013-static-h2-tls.phpt index e4a0dd1..9e3e753 100644 --- a/tests/phpt/server/static/013-static-h2-tls.phpt +++ b/tests/phpt/server/static/013-static-h2-tls.phpt @@ -49,8 +49,9 @@ register_shutdown_function(function() use ($root, $tmp) { @rmdir($tmp); }); -$port = 19980 + getmypid() % 15; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/static/014-static-body-cache.phpt b/tests/phpt/server/static/014-static-body-cache.phpt index 7cfd39a..5dfa33a 100644 --- a/tests/phpt/server/static/014-static-body-cache.phpt +++ b/tests/phpt/server/static/014-static-body-cache.phpt @@ -27,7 +27,9 @@ register_shutdown_function(function () use ($root) { @rmdir($root); }); -$port = 19960 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/static/015-static-ims-date-formats.phpt b/tests/phpt/server/static/015-static-ims-date-formats.phpt index c0fdb2f..cc1c891 100644 --- a/tests/phpt/server/static/015-static-ims-date-formats.phpt +++ b/tests/phpt/server/static/015-static-ims-date-formats.phpt @@ -27,7 +27,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 20040 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler(new StaticHandler('/s/', $root)); diff --git a/tests/phpt/server/static/017-static-handler-locked.phpt b/tests/phpt/server/static/017-static-handler-locked.phpt index 458344c..617b8af 100644 --- a/tests/phpt/server/static/017-static-handler-locked.phpt +++ b/tests/phpt/server/static/017-static-handler-locked.phpt @@ -21,7 +21,9 @@ $root = sys_get_temp_dir() . '/sh-lock-' . getmypid() . '-' . bin2hex(random_byt mkdir($root, 0700, true); register_shutdown_function(fn() => @rmdir($root)); -$port = 28560 + getmypid() % 1000; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $sh = new StaticHandler('/s/', $root); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/static/018-static-hide-index-mime.phpt b/tests/phpt/server/static/018-static-hide-index-mime.phpt index bab913e..0784339 100644 --- a/tests/phpt/server/static/018-static-hide-index-mime.phpt +++ b/tests/phpt/server/static/018-static-hide-index-mime.phpt @@ -38,7 +38,9 @@ register_shutdown_function(function() use ($root1, $root2) { @rmdir("$root1/sub"); @rmdir($root1); @rmdir($root2); }); -$port = 19880 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/static/019-static-dotfile-ignore-and-noindex.phpt b/tests/phpt/server/static/019-static-dotfile-ignore-and-noindex.phpt index e07613d..932f70a 100644 --- a/tests/phpt/server/static/019-static-dotfile-ignore-and-noindex.phpt +++ b/tests/phpt/server/static/019-static-dotfile-ignore-and-noindex.phpt @@ -35,7 +35,9 @@ register_shutdown_function(function() use ($root) { @rmdir($root); }); -$port = 19960 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); diff --git a/tests/phpt/server/static/020-static-extra-headers-and-mime.phpt b/tests/phpt/server/static/020-static-extra-headers-and-mime.phpt index 6fa3cbf..d0e0137 100644 --- a/tests/phpt/server/static/020-static-extra-headers-and-mime.phpt +++ b/tests/phpt/server/static/020-static-extra-headers-and-mime.phpt @@ -27,7 +27,9 @@ register_shutdown_function(function() use ($root) { @unlink("$root/page.mdx"); @rmdir($root); }); -$port = 20040 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $h = (new StaticHandler('/s/', $root)) diff --git a/tests/phpt/server/static/021-static-symlink-reject-nofollow.phpt b/tests/phpt/server/static/021-static-symlink-reject-nofollow.phpt index b2569cc..d95174e 100644 --- a/tests/phpt/server/static/021-static-symlink-reject-nofollow.phpt +++ b/tests/phpt/server/static/021-static-symlink-reject-nofollow.phpt @@ -46,7 +46,9 @@ register_shutdown_function(function() use ($root, $secret) { @unlink($secret); }); -$port = 19970 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port); $server = new HttpServer($config); $server->addStaticHandler( diff --git a/tests/phpt/server/tls/002-tls-config.phpt b/tests/phpt/server/tls/002-tls-config.phpt index eef50d6..fe6dce8 100644 --- a/tests/phpt/server/tls/002-tls-config.phpt +++ b/tests/phpt/server/tls/002-tls-config.phpt @@ -29,9 +29,9 @@ if (!tls_gen_cert($key_path, $cert_path)) { exit(1); } -$port = 19960 + getmypid() % 30; +require_once __DIR__ . '/../_free_port.inc'; -// --- Case 1: TLS listener with valid cert/key starts and stops cleanly. +$port = tas_free_port_span(2); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) // tls=true ->enableTls(true) diff --git a/tests/phpt/server/tls/003-tls-handshake.phpt b/tests/phpt/server/tls/003-tls-handshake.phpt index 81b2979..cf169f2 100644 --- a/tests/phpt/server/tls/003-tls-handshake.phpt +++ b/tests/phpt/server/tls/003-tls-handshake.phpt @@ -29,8 +29,9 @@ if (!tls_gen_cert($key_path, $cert_path)) { exit(1); } -$port = 19970 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) // tls=true ->enableTls(true) diff --git a/tests/phpt/server/tls/004-tls-get.phpt b/tests/phpt/server/tls/004-tls-get.phpt index 3e221db..5ddd7cc 100644 --- a/tests/phpt/server/tls/004-tls-get.phpt +++ b/tests/phpt/server/tls/004-tls-get.phpt @@ -26,8 +26,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19940 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/005-tls-body.phpt b/tests/phpt/server/tls/005-tls-body.phpt index 447fa3e..0e55d43 100644 --- a/tests/phpt/server/tls/005-tls-body.phpt +++ b/tests/phpt/server/tls/005-tls-body.phpt @@ -40,8 +40,9 @@ $buf = substr($buf, 0, $size); file_put_contents($payload, $buf); $expected_sha1 = sha1($buf); -$port = 19920 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/006-tls-keepalive.phpt b/tests/phpt/server/tls/006-tls-keepalive.phpt index 21171ac..01bd5d4 100644 --- a/tests/phpt/server/tls/006-tls-keepalive.phpt +++ b/tests/phpt/server/tls/006-tls-keepalive.phpt @@ -25,8 +25,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19880 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/007-tls-pipelining.phpt b/tests/phpt/server/tls/007-tls-pipelining.phpt index 00ac443..eda0ef6 100644 --- a/tests/phpt/server/tls/007-tls-pipelining.phpt +++ b/tests/phpt/server/tls/007-tls-pipelining.phpt @@ -34,8 +34,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19860 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/008-tls-telemetry.phpt b/tests/phpt/server/tls/008-tls-telemetry.phpt index 5d5ac4a..156af92 100644 --- a/tests/phpt/server/tls/008-tls-telemetry.phpt +++ b/tests/phpt/server/tls/008-tls-telemetry.phpt @@ -25,8 +25,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19820 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/009-tls-resumption.phpt b/tests/phpt/server/tls/009-tls-resumption.phpt index acd90c4..c243d13 100644 --- a/tests/phpt/server/tls/009-tls-resumption.phpt +++ b/tests/phpt/server/tls/009-tls-resumption.phpt @@ -32,8 +32,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19800 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/010-tls-ktls.phpt b/tests/phpt/server/tls/010-tls-ktls.phpt index 2b42e35..ca911ed 100644 --- a/tests/phpt/server/tls/010-tls-ktls.phpt +++ b/tests/phpt/server/tls/010-tls-ktls.phpt @@ -25,8 +25,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19780 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/011-tls-parse-error.phpt b/tests/phpt/server/tls/011-tls-parse-error.phpt index 32b5aec..196e87f 100644 --- a/tests/phpt/server/tls/011-tls-parse-error.phpt +++ b/tests/phpt/server/tls/011-tls-parse-error.phpt @@ -26,8 +26,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19960 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/012-tls-security-level.phpt b/tests/phpt/server/tls/012-tls-security-level.phpt index 90b28ca..490fd72 100644 --- a/tests/phpt/server/tls/012-tls-security-level.phpt +++ b/tests/phpt/server/tls/012-tls-security-level.phpt @@ -27,7 +27,9 @@ if (!tls_gen_cert($key_path, $cert_path, 1024, 'sha1')) { exit(1); } -$port = 19990 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/013-tls-abrupt-and-plain-on-tls.phpt b/tests/phpt/server/tls/013-tls-abrupt-and-plain-on-tls.phpt index d4b2b33..f0398f8 100644 --- a/tests/phpt/server/tls/013-tls-abrupt-and-plain-on-tls.phpt +++ b/tests/phpt/server/tls/013-tls-abrupt-and-plain-on-tls.phpt @@ -26,8 +26,9 @@ if (!tls_gen_cert($key, $cert)) { exit(1); } -$port = 19990 + getmypid() % 9; +require_once __DIR__ . '/../_free_port.inc'; +$port = tas_free_port(); $server = new HttpServer((new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/server/tls/014-tls-h2-large-body-bio-park.phpt b/tests/phpt/server/tls/014-tls-h2-large-body-bio-park.phpt index 2f076c9..97ae49b 100644 --- a/tests/phpt/server/tls/014-tls-h2-large-body-bio-park.phpt +++ b/tests/phpt/server/tls/014-tls-h2-large-body-bio-park.phpt @@ -48,7 +48,9 @@ register_shutdown_function(function () use ($tmp, $cert, $key) { @unlink($cert); @unlink($key); @rmdir($tmp); }); -$port = 19930 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $size = 256 * 1024; /* 8x the 32 KiB gather cap */ $body = str_repeat("\0", $size); for ($i = 0; $i < $size; $i++) { $body[$i] = chr(($i * 31 + 7) & 0xff); } diff --git a/tests/phpt/server/tls/015-tls-buffer-setter.phpt b/tests/phpt/server/tls/015-tls-buffer-setter.phpt index 5a0d72d..b28ff4a 100644 --- a/tests/phpt/server/tls/015-tls-buffer-setter.phpt +++ b/tests/phpt/server/tls/015-tls-buffer-setter.phpt @@ -47,7 +47,9 @@ $key = sys_get_temp_dir() . '/tls015-' . getmypid() . '.key'; if (!tls_gen_cert($key, $cert)) { echo "cert gen failed\n"; exit(1); } register_shutdown_function(function () use ($cert, $key) { @unlink($cert); @unlink($key); }); -$port = 19945 + getmypid() % 20; +require_once __DIR__ . '/../_free_port.inc'; + +$port = tas_free_port(); $size = 200000; /* > one record → exercises park path */ $body = str_repeat("\0", $size); for ($i = 0; $i < $size; $i++) { $body[$i] = chr(($i * 31 + 7) & 0xff); } diff --git a/tests/phpt/websocket/005-handshake-101.phpt b/tests/phpt/websocket/005-handshake-101.phpt index 26358cb..ad4f67f 100644 --- a/tests/phpt/websocket/005-handshake-101.phpt +++ b/tests/phpt/websocket/005-handshake-101.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19850 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/006-recv-text-frame.phpt b/tests/phpt/websocket/006-recv-text-frame.phpt index 007737b..cd3bee7 100644 --- a/tests/phpt/websocket/006-recv-text-frame.phpt +++ b/tests/phpt/websocket/006-recv-text-frame.phpt @@ -13,8 +13,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19860 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/007-send-echo.phpt b/tests/phpt/websocket/007-send-echo.phpt index 6386cc7..aee822c 100644 --- a/tests/phpt/websocket/007-send-echo.phpt +++ b/tests/phpt/websocket/007-send-echo.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19870 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/008-close-handshake.phpt b/tests/phpt/websocket/008-close-handshake.phpt index 2e75b85..2ea9373 100644 --- a/tests/phpt/websocket/008-close-handshake.phpt +++ b/tests/phpt/websocket/008-close-handshake.phpt @@ -13,8 +13,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/009-binary-frames.phpt b/tests/phpt/websocket/009-binary-frames.phpt index 14d5b0b..2a66d02 100644 --- a/tests/phpt/websocket/009-binary-frames.phpt +++ b/tests/phpt/websocket/009-binary-frames.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19890 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/010-fragmented-message.phpt b/tests/phpt/websocket/010-fragmented-message.phpt index fc562e8..a2946c8 100644 --- a/tests/phpt/websocket/010-fragmented-message.phpt +++ b/tests/phpt/websocket/010-fragmented-message.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19900 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/011-concurrent-recv.phpt b/tests/phpt/websocket/011-concurrent-recv.phpt index 5e2f66d..0e36db2 100644 --- a/tests/phpt/websocket/011-concurrent-recv.phpt +++ b/tests/phpt/websocket/011-concurrent-recv.phpt @@ -14,8 +14,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19910 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/012-upgrade-reject.phpt b/tests/phpt/websocket/012-upgrade-reject.phpt index 4da5301..16a0500 100644 --- a/tests/phpt/websocket/012-upgrade-reject.phpt +++ b/tests/phpt/websocket/012-upgrade-reject.phpt @@ -13,8 +13,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19920 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/013-upgrade-subprotocol.phpt b/tests/phpt/websocket/013-upgrade-subprotocol.phpt index 96dc8c7..bf601f2 100644 --- a/tests/phpt/websocket/013-upgrade-subprotocol.phpt +++ b/tests/phpt/websocket/013-upgrade-subprotocol.phpt @@ -13,8 +13,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19930 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/015-keepalive-ping.phpt b/tests/phpt/websocket/015-keepalive-ping.phpt index a1bc423..86c41e8 100644 --- a/tests/phpt/websocket/015-keepalive-ping.phpt +++ b/tests/phpt/websocket/015-keepalive-ping.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19940 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/016-auto-pong.phpt b/tests/phpt/websocket/016-auto-pong.phpt index b60b705..bc6d596 100644 --- a/tests/phpt/websocket/016-auto-pong.phpt +++ b/tests/phpt/websocket/016-auto-pong.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19960 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/017-remote-address.phpt b/tests/phpt/websocket/017-remote-address.phpt index 1c440a8..a137e09 100644 --- a/tests/phpt/websocket/017-remote-address.phpt +++ b/tests/phpt/websocket/017-remote-address.phpt @@ -12,8 +12,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19980 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/018-wss-echo.phpt b/tests/phpt/websocket/018-wss-echo.phpt index b74d660..4bfe666 100644 --- a/tests/phpt/websocket/018-wss-echo.phpt +++ b/tests/phpt/websocket/018-wss-echo.phpt @@ -52,8 +52,9 @@ echo "$status op=0x", dechex($op), " payload=$p\n"; CLIENT ); -$port = 19920 + getmypid() % 30; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port, true) ->enableTls(true) diff --git a/tests/phpt/websocket/019-h2-extended-connect.phpt b/tests/phpt/websocket/019-h2-extended-connect.phpt index edddc02..59be653 100644 --- a/tests/phpt/websocket/019-h2-extended-connect.phpt +++ b/tests/phpt/websocket/019-h2-extended-connect.phpt @@ -13,8 +13,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19890 + getmypid() % 50; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/websocket/020-permessage-deflate-echo.phpt b/tests/phpt/websocket/020-permessage-deflate-echo.phpt index 932f883..21a0a31 100644 --- a/tests/phpt/websocket/020-permessage-deflate-echo.phpt +++ b/tests/phpt/websocket/020-permessage-deflate-echo.phpt @@ -21,8 +21,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19880 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/021-permessage-deflate-bomb.phpt b/tests/phpt/websocket/021-permessage-deflate-bomb.phpt index 866a03f..a91a06e 100644 --- a/tests/phpt/websocket/021-permessage-deflate-bomb.phpt +++ b/tests/phpt/websocket/021-permessage-deflate-bomb.phpt @@ -21,8 +21,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19890 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/022-h2-permessage-deflate.phpt b/tests/phpt/websocket/022-h2-permessage-deflate.phpt index 6877d03..3b15c50 100644 --- a/tests/phpt/websocket/022-h2-permessage-deflate.phpt +++ b/tests/phpt/websocket/022-h2-permessage-deflate.phpt @@ -22,8 +22,9 @@ use TrueAsync\HttpRequest; use function Async\spawn; use function Async\await; -$port = 19940 + getmypid() % 50; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(10) diff --git a/tests/phpt/websocket/023-backpressure-trysend.phpt b/tests/phpt/websocket/023-backpressure-trysend.phpt index b716279..fd0d03f 100644 --- a/tests/phpt/websocket/023-backpressure-trysend.phpt +++ b/tests/phpt/websocket/023-backpressure-trysend.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19990 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/024-backpressure-send-blocks.phpt b/tests/phpt/websocket/024-backpressure-send-blocks.phpt index ee004cb..2ac6dac 100644 --- a/tests/phpt/websocket/024-backpressure-send-blocks.phpt +++ b/tests/phpt/websocket/024-backpressure-send-blocks.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19790 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/025-spawned-writer-teardown.phpt b/tests/phpt/websocket/025-spawned-writer-teardown.phpt index 2e5cd18..607189e 100644 --- a/tests/phpt/websocket/025-spawned-writer-teardown.phpt +++ b/tests/phpt/websocket/025-spawned-writer-teardown.phpt @@ -32,7 +32,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19680 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; + +$port = tas_free_port(); $N = 4; $config = (new HttpServerConfig()) diff --git a/tests/phpt/websocket/026-pong-timeout-close.phpt b/tests/phpt/websocket/026-pong-timeout-close.phpt index 67839fc..e815de5 100644 --- a/tests/phpt/websocket/026-pong-timeout-close.phpt +++ b/tests/phpt/websocket/026-pong-timeout-close.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19960 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig()) ->addListener('127.0.0.1', $port) ->setReadTimeout(5) diff --git a/tests/phpt/websocket/027-handshake-bad-version.phpt b/tests/phpt/websocket/027-handshake-bad-version.phpt index 9f71462..287d9a9 100644 --- a/tests/phpt/websocket/027-handshake-bad-version.phpt +++ b/tests/phpt/websocket/027-handshake-bad-version.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19970 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/028-handshake-missing-key.phpt b/tests/phpt/websocket/028-handshake-missing-key.phpt index eea590b..62f99d4 100644 --- a/tests/phpt/websocket/028-handshake-missing-key.phpt +++ b/tests/phpt/websocket/028-handshake-missing-key.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19980 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/029-handshake-bad-method.phpt b/tests/phpt/websocket/029-handshake-bad-method.phpt index 645aa65..81c4d3c 100644 --- a/tests/phpt/websocket/029-handshake-bad-method.phpt +++ b/tests/phpt/websocket/029-handshake-bad-method.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19990 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/030-utf8-failfast-teardown.phpt b/tests/phpt/websocket/030-utf8-failfast-teardown.phpt index 1ac7883..a0461b5 100644 --- a/tests/phpt/websocket/030-utf8-failfast-teardown.phpt +++ b/tests/phpt/websocket/030-utf8-failfast-teardown.phpt @@ -19,8 +19,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19730 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/031-outbound-fragmentation.phpt b/tests/phpt/websocket/031-outbound-fragmentation.phpt index 42d9f64..f15aef5 100644 --- a/tests/phpt/websocket/031-outbound-fragmentation.phpt +++ b/tests/phpt/websocket/031-outbound-fragmentation.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19740 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5) ->setWsMaxFrameSize(128); // cap each frame at 128 bytes (setter minimum) diff --git a/tests/phpt/websocket/032-closed-exception-code.phpt b/tests/phpt/websocket/032-closed-exception-code.phpt index 48e3aaa..d06a098 100644 --- a/tests/phpt/websocket/032-closed-exception-code.phpt +++ b/tests/phpt/websocket/032-closed-exception-code.phpt @@ -14,8 +14,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19750 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config); diff --git a/tests/phpt/websocket/033-foreach-iterator.phpt b/tests/phpt/websocket/033-foreach-iterator.phpt index 1d4b01f..52676e9 100644 --- a/tests/phpt/websocket/033-foreach-iterator.phpt +++ b/tests/phpt/websocket/033-foreach-iterator.phpt @@ -13,8 +13,9 @@ use function Async\spawn; use function Async\await; use function Async\delay; -$port = 19760 + getmypid() % 100; +require_once __DIR__ . '/../server/_free_port.inc'; +$port = tas_free_port(); $config = (new HttpServerConfig())->addListener('127.0.0.1', $port) ->setReadTimeout(5)->setWriteTimeout(5); $server = new HttpServer($config);