diff --git a/CMakeLists.txt b/CMakeLists.txt index 985f9dac11a..a0691c58ae6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.16...3.29) PROJECT(HTTPD C) +set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}../vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "toolchain") + INCLUDE(CheckSymbolExists) INCLUDE(CheckCSourceCompiles) INCLUDE("build/build-modules-c.cmake") @@ -133,6 +135,7 @@ SET(EXTRA_INCLUDES "" CACHE STRING "Extra inc SET(EXTRA_LIBS "" CACHE STRING "Extra libraries") SET(EXTRA_COMPILE_FLAGS "" CACHE STRING "Extra compile flags") + IF(NOT EXISTS "${APR_INCLUDE_DIR}/apr.h") MESSAGE(FATAL_ERROR "APR include directory ${APR_INCLUDE_DIR} is not correct.") ENDIF() @@ -428,7 +431,13 @@ SET(MODULE_LIST "modules/test/mod_optional_hook_import+O+example optional hook importer" "modules/test/mod_policy+I+HTTP protocol compliance filters" ) - +IF(BUILD_PYHTTPD_MODULES) + LIST(APPEND MODULE_LIST + "test/pyhttpd/mod_aptest/mod_aptest+A+Test module. Useful only for developers and testing purposes." + "test/modules/http1/mod_h1test/mod_h1test+A+Http/1 Test module. Useful only for developers and testing purposes." + "test/modules/http2/mod_h2test/mod_h2test+A+Http/2 Test module. Useful only for developers and testing purposes." + ) +ENDIF() # Track which modules actually built have APIs to link against. SET(installed_mod_libs_exps) @@ -918,6 +927,8 @@ TARGET_COMPILE_DEFINITIONS(httpd PRIVATE "ICON_FILE=${CMAKE_SOURCE_DIR}/build/win32/apache.ico" ) TARGET_COMPILE_OPTIONS(httpd PRIVATE "${EXTRA_COMPILE_FLAGS}") +add_compile_definitions(IF_WIN_OS_IS_UNICODE=1) + SET_TARGET_PROPERTIES(httpd PROPERTIES LINK_FLAGS "/stack:0x40000" ) @@ -1065,6 +1076,40 @@ INSTALL(TARGETS ${install_targets} INSTALL(TARGETS ${install_modules} RUNTIME DESTINATION modules ) +INSTALL(CODE [[ + SET(SERVER_ROOT "${CMAKE_INSTALL_PREFIX}") + + CONFIGURE_FILE( + "../support/apachectl.bat.in" + "${CMAKE_CURRENT_BINARY_DIR}/support/apachectl.bat" + @ONLY + ) +]]) +INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/support/apachectl.bat" + DESTINATION bin + ) + + INSTALL(CODE [[ + find_package(Git QUIET) + + if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} branch --show-current + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE HTTPD_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + endif() + + SET(SERVER_ROOT "${CMAKE_INSTALL_PREFIX}") + + CONFIGURE_FILE( + "../test/pyhttpd/config_win.ini.in" + "../test/pyhttpd/config.ini" + @ONLY + ) +]]) IF(INSTALL_PDB) INSTALL(FILES ${install_bin_pdb} diff --git a/build-win.bat b/build-win.bat new file mode 100644 index 00000000000..86939d74389 --- /dev/null +++ b/build-win.bat @@ -0,0 +1,110 @@ +@ECHO off +@REM + +@REM ------------------------------------- +@REM Variables used in this script +@REM ------------------------------------- +SET CWD=%CD% +SET "CWD=%CWD:\=/%" +@REM ------------------------------------- +SET ARCH="x64-windows" +SET BUILD_TYPE="Debug" +SET VCPKG_DIRECTORY="vcpkg\installed\x64-windows" +SET VCPKG_DIRECTORY_LIB=%VCPKG_DIRECTORY% +SET GENERATOR="NMake Makefiles" +@REM SET GENERATOR="Ninja" +SET CMAKE_VERSION="4.0" +SET HTTPD_INSTALL_DIRECTORY="C:/Users/%USERNAME%/Projects/http-debug/apache" +@REM ------------------------------------- + +@REM ------------------------------------- +@REM Installs via MS vcpkg manager all the +@REM packages needed to build httpd +@REM ------------------------------------- +if NOT EXIST vcpkg\ ( + echo "Adding...." + git submodule add --force https://github.com/microsoft/vcpkg.git vcpkg + PUSHD vcpkg\ + CALL bootstrap-vcpkg.bat +) else ( + echo "Updating...." + git submodule update --remote --merge vcpkg\ + PUSHD vcpkg\ +) + +SET VCPKG_ROOT=%CWD%\vcpkg +@REM For some reason using the manifest doesn't install the default-features +vcpkg.exe install --triplet x64-windows apr[private-headers] apr-util pcre2 openssl nghttp2 curl libxml2 jansson + +POPD + +@REM ------------------------------------- +@REM Setup build env using VS build 2022 +@REM It maybe installed somewhere else, if so, the path will need updating to find the batch file +@REM ------------------------------------- +call "C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Auxiliary\Build\vcvars64.bat" + +@REM ------------------------------------- +@REM Create a temp dir for cmake files +@REM ------------------------------------- +if not EXIST build-asf-win\ ( + mkdir build-asf-win\ +) + +PUSHD build-asf-win\ + +@REM ------------------------------------- +@REM Run cmake so that it configures the +@REM and creates the needed makefiles +@REM ------------------------------------- +cmake .. -B . ^ + -G %GENERATOR% ^ + -DCMAKE_BUILD_TYPE=%BUILD_TYPE% ^ + -DCMAKE_TOOLCHAIN_FILE=%CWD%/vcpkg/scripts/buildsystems/vcpkg.cmake ^ + -DVCPKG_TARGET_TRIPLET=%ARCH% ^ + -DNGHTTP2_INCLUDE_DIR=%CWD%/vcpkg/installed/x64-windows/include ^ + -DAPR_INCLUDE_DIR=%CWD%/vcpkg/installed/x64-windows/include ^ + -DJANSSON_INCLUDE_DIR=%CWD%/vcpkg/installed/x64-windows/include ^ + "-DAPR_LIBRARIES=%CWD%/vcpkg/installed/x64-windows/lib/libapr-1.lib;%CWD%/vcpkg/installed/x64-windows/lib/libaprutil-1.lib" ^ + -DNGHTTP2_LIBRARIES=%CWD%/vcpkg/installed/x64-windows/lib/nghttp2.lib ^ + -DJANSSON_LIBRARIES=%CWD%/vcpkg/installed/x64-windows/lib/jansson.lib ^ + -DBUILD_PYHTTPD_MODULES=true ^ + -DCMAKE_POLICY_VERSION_MINIMUM=%CMAKE_VERSION% ^ + --install-prefix %HTTPD_INSTALL_DIRECTORY% ^ + --fresh + +@REM ------------------------------------- +@REM Build httpd +@REM ------------------------------------- +cmake --build . + +@REM ------------------------------------- +@REM Install httpd only +@REM ------------------------------------- +cmake --install . --config %BUILD_TYPE% +POPD + +@REM ------------------------------------- +@REM Copy the dependencies. +@REM ------------------------------------- +if %BUILD_TYPE% == "Debug" ( + SET VCPKG_DIRECTORY_LIB=%VCPKG_DIRECTORY_LIB%\debug +) + +@REM ------------------------------------- +@REM Copy the libraries needed to run httpd +@REM ------------------------------------- +xcopy %VCPKG_DIRECTORY_LIB%\bin\* %HTTPD_INSTALL_DIRECTORY%\bin /y /f /i + +@REM ------------------------------------- +@REM Run the pyHttpd tests +@REM ------------------------------------- +PUSHD test\ +@REM python.exe -m pip install --upgrade pip +@REM python.exe -m venv .venv +@REM call .venv\Scripts\activate +@REM call python.exe -m pip install websockets filelock cryptography pyopenssl python-multipart pebble pytest-html pytest==8.4.2 cffi +@REM call python.exe -m pytest -vvv --ignore="modules/http2" -k "not test_cgi_003_01 and not test_800_websockets and not test_02_unix and not test_003_get and not test_004_post and not test_002_restarts and not test_005_trailers" --junitxml="reports/pytest-results.xml" --html="reports/Results" --self-contained-html +@REM deactivate + +POPD diff --git a/support/apachectl.bat.in b/support/apachectl.bat.in new file mode 100644 index 00000000000..fddfc14f7d9 --- /dev/null +++ b/support/apachectl.bat.in @@ -0,0 +1,71 @@ +echo off +SETLOCAL EnableDelayedExpansion +set "BIN_INSTALL_DIR=@SERVER_ROOT@/bin" + +:: ----------------------------------------------------------------------------- +:: Apache Control Script for Windows +:: By Paul Lodge +:: March 2026 +:: Version 0.0.1 +:: ----------------------------------------------------------------------------- + +set "APACHE24=Apache2.x" +set "HTTPD=%BIN_INSTALL_DIR%\httpd.exe" +set "ACMD=%~1" + +:: Check if a command was provided +if "%ACMD%"=="" goto DEFAULT + +:: Switch Logic +if /I "%ACMD%"=="install" goto INSTALL +if /I "%ACMD%"=="uninstall" goto UNINSTALL +if /I "%ACMD%"=="start" goto START +if /I "%ACMD%"=="stop" goto STOP +if /I "%ACMD%"=="restart" goto RESTART +if /I "%ACMD%"=="graceful" goto RESTART +if /I "%ACMD%"=="startssl" goto SSL_ERROR +if /I "%ACMD%"=="sslstart" goto SSL_ERROR +if /I "%ACMD%"=="start-SSL" goto SSL_ERROR +if /I "%ACMD%"=="configtest" goto NOT_SUPPORTED +if /I "%ACMD%"=="status" goto NOT_SUPPORTED +if /I "%ACMD%"=="fullstatus" goto NOT_SUPPORTED + +goto DEFAULT + +:INSTALL + "%HTTPD%" -k install + goto END + +:UNINSTALL + "%HTTPD%" -k uninstall -n %APACHE24% + goto END + +:START + net start %APACHE24% + goto END + +:STOP + net stop %APACHE24% + goto END + +:RESTART + net stop %APACHE24% + net start %APACHE24% + goto END + +:SSL_ERROR + echo The startssl option is no longer supported. + echo Please edit httpd.conf to include the SSL configuration settings + echo and then use 'apachectl start'. + goto END + +:NOT_SUPPORTED + echo Not supported! + goto END + +:DEFAULT + "%HTTPD%" %* + goto END + +:END +ENDLOCAL diff --git a/test/modules/core/htdocs/ssi/exec.shtml b/test/modules/core/htdocs/ssi/exec.shtml index e98afb15ddc..a5f987991be 100644 --- a/test/modules/core/htdocs/ssi/exec.shtml +++ b/test/modules/core/htdocs/ssi/exec.shtml @@ -1 +1,2 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/test/modules/core/htdocs/userdir/testuser/public_html/cgi-bin/test.cgi b/test/modules/core/htdocs/userdir/testuser/public_html/cgi-bin/test.cgi index 9c8c67c2093..9b7b795b935 100755 --- a/test/modules/core/htdocs/userdir/testuser/public_html/cgi-bin/test.cgi +++ b/test/modules/core/htdocs/userdir/testuser/public_html/cgi-bin/test.cgi @@ -1,4 +1,3 @@ -#!/bin/sh echo "Content-Type: text/plain" echo echo "OK" diff --git a/test/modules/core/test_002_restarts.py b/test/modules/core/test_002_restarts.py index cf203bc82db..2b4333d08ab 100644 --- a/test/modules/core/test_002_restarts.py +++ b/test/modules/core/test_002_restarts.py @@ -84,12 +84,11 @@ def _rtime(self, s: str) -> timedelta: delta = d - self._start return f"{delta.seconds:+02d}.{delta.microseconds:06d}" - - @pytest.mark.skipif(condition='STRESS_TEST' not in os.environ, reason="STRESS_TEST not set in env") -@pytest.mark.skipif(condition=not CoreTestEnv().h2load_is_at_least('1.41.0'), - reason="h2load unavailable or misses --connect-to option") +@pytest.mark.skipif(condition=CoreTestEnv().isWindows or not CoreTestEnv().h2load_is_at_least('1.41.0'), + reason="h2load unavailable or misses --connect-to option") + class TestRestarts: def test_core_002_01(self, env): diff --git a/test/modules/http1/env.py b/test/modules/http1/env.py index e2df1a561f2..728045e230b 100644 --- a/test/modules/http1/env.py +++ b/test/modules/http1/env.py @@ -24,19 +24,24 @@ def make(self): self._setup_data_1k_1m() def _add_h1test(self): - local_dir = os.path.dirname(inspect.getfile(H1TestSetup)) - p = subprocess.run([self.env.apxs, '-c', 'mod_h1test.c'], - capture_output=True, - cwd=os.path.join(local_dir, 'mod_h1test')) - rv = p.returncode - if rv != 0: - log.error(f"compiling md_h1test failed: {p.stderr}") - raise Exception(f"compiling md_h1test failed: {p.stderr}") + module_dir = self.env.test_modules_dir + if not self.env.isWindows: + local_dir = os.path.dirname(inspect.getfile(H1TestSetup)) + p = subprocess.run([self.env.apxs, '-c', 'mod_h1test.c'], + capture_output=True, + cwd=os.path.join(local_dir, 'mod_h1test')) + + rv = p.returncode + if rv != 0: + log.error(f"compiling md_h1test failed: {p.stderr}") + raise Exception(f"compiling md_h1test failed: {p.stderr}") + + module_dir = f"{local_dir}/mod_h1test/.libs" modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf') with open(modules_conf, 'a') as fd: # load our test module which is not installed - fd.write(f"LoadModule h1test_module \"{local_dir}/mod_h1test/.libs/mod_h1test.so\"\n") + fd.write(f"LoadModule h2test_module \"{module_dir}/mod_h2test.so\"\n") def _setup_data_1k_1m(self): s90 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n" diff --git a/test/modules/http2/env.py b/test/modules/http2/env.py index e2647616aaf..bdfcd8dd6ae 100644 --- a/test/modules/http2/env.py +++ b/test/modules/http2/env.py @@ -25,19 +25,24 @@ def make(self): self._setup_data_1k_1m() def _add_h2test(self): - local_dir = os.path.dirname(inspect.getfile(H2TestSetup)) - p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'], - capture_output=True, - cwd=os.path.join(local_dir, 'mod_h2test')) - rv = p.returncode - if rv != 0: - log.error(f"compiling md_h2test failed: {p.stderr}") - raise Exception(f"compiling md_h2test failed: {p.stderr}") + module_dir = self.env.test_modules_dir + if not self.env.isWindows: + local_dir = os.path.dirname(inspect.getfile(H2TestSetup)) + p = subprocess.run([self.env.apxs, '-c', 'mod_h2test.c'], + capture_output=True, + cwd=os.path.join(local_dir, 'mod_h2test')) + + rv = p.returncode + if rv != 0: + log.error(f"compiling md_h2test failed: {p.stderr}") + raise Exception(f"compiling md_h2test failed: {p.stderr}") + + module_dir = f"{local_dir}/mod_h1test/.libs" modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf') with open(modules_conf, 'a') as fd: # load our test module which is not installed - fd.write(f"LoadModule h2test_module \"{local_dir}/mod_h2test/.libs/mod_h2test.so\"\n") + fd.write(f"LoadModule h2test_module \"{module_dir}/mod_h2test.so\"\n") def _setup_data_1k_1m(self): s90 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678\n" diff --git a/test/modules/md/md_env.py b/test/modules/md/md_env.py index 7b5f0f9e561..9695b6eb8ea 100755 --- a/test/modules/md/md_env.py +++ b/test/modules/md/md_env.py @@ -132,8 +132,8 @@ def setup_httpd(self, setup: HttpdTestSetup = None): def set_store_dir_default(self): dirpath = "md" - if self.httpd_is_at_least("2.5.0"): - dirpath = os.path.join("state", dirpath) + # if self.httpd_is_at_least("2.5.0"): + # dirpath = os.path.join("state", dirpath) self.set_store_dir(dirpath) def set_store_dir(self, dirpath): @@ -280,7 +280,7 @@ def store_challenges(self): return os.path.join(self._store_dir, 'challenges') def store_domain_file(self, domain, filename): - return os.path.join(self.store_domains(), domain, filename) + return os.path.join(self.store_domains(), domain, filename).replace("\\", "/") def store_archived_file(self, domain, version, filename): return os.path.join(self.store_archives(), "%s.%d" % (domain, version), filename) diff --git a/test/pyhttpd/config_win.ini.in b/test/pyhttpd/config_win.ini.in new file mode 100644 index 00000000000..7164251778b --- /dev/null +++ b/test/pyhttpd/config_win.ini.in @@ -0,0 +1,34 @@ +[global] +prefix = @SERVER_ROOT@ +exec_prefix = ${prefix} +bindir = ${prefix}/bin +sbindir = ${exec_prefix}/sbin +libdir = ${exec_prefix}/lib +libexecdir = ${exec_prefix}/modules + +apr_bindir = ${prefix} +apxs = ${prefix}/bin/apxs +apachectl = ${exec_prefix}/bin/apachectl.bat + +curl_bin = curl.exe +nghttp = nghttp +h2load = h2load + +pre_built_test_binaries_dir = ${libexecdir} + +[httpd] +version = @HTTPD_VERSION@ +name = httpd +dso_modules = autht_jwt autht_core authn_file authn_dbm authn_anon authn_dbd authn_socache authn_core authz_host authz_groupfile authz_user authz_dbm authz_owner authz_dbd authz_core authnz_ldap access_compat auth_basic auth_bearer auth_form auth_digest allowmethods allowhandlers apreq file_cache cache cache_disk cache_socache socache_shmcb socache_dbm socache_memcache socache_redis watchdog macro dbd dumpio firehose echo buffer data ratelimit reqtimeout ext_filter request include filter reflector substitute sed charset_lite xml2enc proxy_html mime ldap syslog log_json log_config log_debug log_forensic logio env mime_magic expires headers usertrack unique_id setenvif version remoteip proxy proxy_connect proxy_ftp proxy_http proxy_fcgi proxy_scgi proxy_uwsgi proxy_fdpass proxy_wstunnel proxy_ajp proxy_balancer proxy_express proxy_hcheck session session_cookie session_crypto session_dbd slotmem_shm slotmem_plain ssl dialup http2 md lbmethod_byrequests lbmethod_bytraffic lbmethod_bybusyness lbmethod_heartbeat heartbeat heartmonitor dav status autoindex asis info dav_fs dav_lock vhost_alias negotiation dir actions speling userdir alias rewrite +mpm_modules = mpm_winnt + +[test] +gen_dir = @SERVER_ROOT@ +http_port = 5002 +https_port = 5001 +proxy_port = 5003 +http_port2 = 5004 +ws_port = 5100 +http_tld = tests.httpd.apache.org +test_dir = @ABS_SRCDIR@ +test_src_dir = @ABS_SRCDIR@ diff --git a/test/pyhttpd/env.py b/test/pyhttpd/env.py index e3cf1e72317..dc34360c607 100644 --- a/test/pyhttpd/env.py +++ b/test/pyhttpd/env.py @@ -8,6 +8,7 @@ import subprocess import sys import time +import platform from datetime import datetime, timedelta from string import Template from typing import List, Optional @@ -92,6 +93,7 @@ def make(self): self.add_modules([self.env.ssl_module]) self._make_modules_conf() self._make_htdocs() + self._add_aptest() self._build_clients() self.env.clear_curl_headerfiles() @@ -196,21 +198,27 @@ def _make_htdocs(self): os.chmod(py_file, st.st_mode | stat.S_IEXEC) def _add_aptest(self): - local_dir = os.path.dirname(inspect.getfile(HttpdTestSetup)) - p = subprocess.run([self.env.apxs, '-c', 'mod_aptest.c'], - capture_output=True, - cwd=os.path.join(local_dir, 'mod_aptest')) - rv = p.returncode - if rv != 0: - log.error(f"compiling mod_aptest failed: {p.stderr}") - raise Exception(f"compiling mod_aptest failed: {p.stderr}") + module_dir = self.env.test_modules_dir + if not self.env.isWindows: + local_dir = os.path.dirname(inspect.getfile(HttpdTestSetup)) + p = subprocess.run([self.env.apxs, '-c', 'mod_aptest.c'], + capture_output=True, + cwd=os.path.join(local_dir, 'mod_aptest')) + rv = p.returncode + if rv != 0: + log.error(f"compiling mod_aptest failed: {p.stderr}") + raise Exception(f"compiling mod_aptest failed: {p.stderr}") + + module_dir = f"{local_dir}/mod_aptest/.libs/" modules_conf = os.path.join(self.env.server_dir, 'conf/modules.conf') with open(modules_conf, 'a') as fd: - # load our test module which is not installed - fd.write(f"LoadModule aptest_module \"{local_dir}/mod_aptest/.libs/mod_aptest.so\"\n") + # load our test module + fd.write(f"LoadModule aptest_module \"{module_dir}/mod_aptest.so\"\n") def _build_clients(self): + if self.env.test_modules_dir: + return clients_dir = os.path.join( os.path.dirname(os.path.dirname(inspect.getfile(HttpdTestSetup))), 'clients') @@ -264,8 +272,15 @@ def __init__(self, pytestconfig=None): self._apxs = self.config.get('global', 'apxs') self._prefix = self.config.get('global', 'prefix') self._apachectl = self.config.get('global', 'apachectl') + + self._libexec_dir = self.config.get('global', 'libexecdir') + HttpdTestEnv.LIBEXEC_DIR = self._libexec_dir + if HttpdTestEnv.LIBEXEC_DIR is None: HttpdTestEnv.LIBEXEC_DIR = self._libexec_dir = self.get_apxs_var('LIBEXECDIR') + + self._httpd_ver = self.config.get('httpd', 'version') + self._curl = self.config.get('global', 'curl_bin') if 'CURL' in os.environ: self._curl = os.environ['CURL'] @@ -275,6 +290,8 @@ def __init__(self, pytestconfig=None): self._h2load = self.config.get('global', 'h2load') if self._h2load is None: self._h2load = 'h2load' + self._test_modules_dir = self.config.get('global', 'pre_built_test_binaries_dir', + fallback=None) self._http_port = int(self.config.get('test', 'http_port')) self._http_port2 = int(self.config.get('test', 'http_port2')) @@ -283,19 +300,28 @@ def __init__(self, pytestconfig=None): self._ws_port = int(self.config.get('test', 'ws_port')) self._http_tld = self.config.get('test', 'http_tld') self._test_dir = self.config.get('test', 'test_dir') + + # In cmake determining the test directory is a headache and this is a simple workaround + if not self._test_dir: + self._test_dir = os.getcwd() + "/pyhttpd" if "pyhttpd" not in os.getcwd() else os.getcwd() + self._clients_dir = os.path.join(os.path.dirname(self._test_dir), 'clients') self._gen_dir = self.config.get('test', 'gen_dir') + self._server_dir = os.path.join(self._gen_dir, 'apache') + self._server_dir = self._server_dir.replace("\\","/") self._server_conf_dir = os.path.join(self._server_dir, "conf") self._server_docs_dir = os.path.join(self._server_dir, "htdocs") self._server_logs_dir = os.path.join(self.server_dir, "logs") + self._server_run_dir = os.path.join(self.server_dir, "run") self._server_access_log = os.path.join(self._server_logs_dir, "access_log") - self._error_log = HttpdErrorLog(os.path.join(self._server_logs_dir, "error_log")) + error_log_sep = "." if self.isWindows else "_" + self._error_log = HttpdErrorLog(os.path.join(self._server_logs_dir, f"error{error_log_sep}log")) self._apachectl_stderr = None self._dso_modules = self.config.get('httpd', 'dso_modules').split(' ') self._mpm_modules = self.config.get('httpd', 'mpm_modules').split(' ') - self._mpm_module = f"mpm_{os.environ['MPM']}" if 'MPM' in os.environ else 'mpm_event' + self._mpm_module = f"mpm_{os.environ['MPM']}" if 'MPM' in os.environ else 'mpm_winnt' if self.isWindows else 'mpm_event' self._ssl_module = self.get_ssl_module() if len(self._ssl_module.strip()) == 0: self._ssl_module = None @@ -444,6 +470,10 @@ def server_dir(self) -> str: def server_logs_dir(self) -> str: return self._server_logs_dir + @property + def server_run_dir(self) -> str: + return self._server_run_dir + @property def libexec_dir(self) -> str: return HttpdTestEnv.LIBEXEC_DIR @@ -487,9 +517,17 @@ def set_current_test_name(self, val) -> None: self._current_test = val @property - def apachectl_stderr(self): + def apachectl_stderr(self) -> str: return self._apachectl_stderr + @property + def test_modules_dir(self) -> str: + return self._test_modules_dir + + @property + def isWindows(self) -> bool: + return platform.system().lower() == "windows" + def add_cert_specs(self, specs: List[CertificateSpec]): self._cert_specs.extend(specs) @@ -573,7 +611,7 @@ def get_apxs_var(self, name: str) -> str: return p.stdout.strip() def get_httpd_version(self) -> str: - return self.get_apxs_var("HTTPD_VERSION") + return self._httpd_ver def mkpath(self, path): if not os.path.exists(path):