Skip to content

Commit 051fac1

Browse files
authored
Fix/windows ci compat (#6189)
1 parent a281145 commit 051fac1

114 files changed

Lines changed: 1872 additions & 504 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/windows-phpt.ps1

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
param(
2+
[Parameter(Mandatory = $true)]
3+
[string[]] $Path,
4+
[int] $Offset = 0,
5+
[int] $Count = [int]::MaxValue,
6+
[int] $TimeoutSeconds = 12
7+
)
8+
9+
$ErrorActionPreference = 'Stop'
10+
$env:PHPT = '1'
11+
$env:TEST_PHP_EXECUTABLE = 'php'
12+
$env:SKIP_ONLINE_TESTS = '1'
13+
$env:NO_INTERACTION = '1'
14+
15+
$tests = foreach ($entry in $Path) {
16+
$item = Get-Item -LiteralPath $entry -ErrorAction SilentlyContinue
17+
if ($item -and $item.PSIsContainer) {
18+
Get-ChildItem -LiteralPath $item.FullName -Recurse -Filter *.phpt -File
19+
} elseif ($item) {
20+
$item
21+
} else {
22+
Get-ChildItem -Path $entry -Filter *.phpt -File
23+
}
24+
}
25+
26+
$tests = @(
27+
$tests |
28+
Sort-Object FullName -Unique |
29+
Select-Object -Skip $Offset -First $Count
30+
)
31+
32+
if ($tests.Count -eq 0) {
33+
throw "No PHPT files matched: $($Path -join ', ')"
34+
}
35+
36+
$innerTimeout = [Math]::Max(1, $TimeoutSeconds - 2)
37+
$options = @(
38+
'tests\run-tests',
39+
'-P',
40+
'-q',
41+
'-d', 'extension=php_swoole',
42+
'-d', 'swoole.use_shortname=On',
43+
'--show-diff',
44+
'-g', 'PASS,FAIL,BORK,LEAK,XLEAK',
45+
'--show-slow', '1000',
46+
'--set-timeout', $innerTimeout
47+
)
48+
49+
$failures = [System.Collections.Generic.List[string]]::new()
50+
$timeouts = [System.Collections.Generic.List[string]]::new()
51+
52+
foreach ($test in $tests) {
53+
$relativePath = Resolve-Path -Relative $test.FullName
54+
Write-Host "::group::PHPT $relativePath"
55+
try {
56+
$process = Start-Process -FilePath php -ArgumentList ($options + $test.FullName) -NoNewWindow -PassThru
57+
# Windows PowerShell 5 loses ExitCode for -NoNewWindow processes when
58+
# the native handle is first requested after the child has exited.
59+
# Cache it while the process is still alive (PowerShell #5421).
60+
$null = $process.Handle
61+
if (-not $process.WaitForExit($TimeoutSeconds * 1000)) {
62+
$timeouts.Add($relativePath)
63+
$failures.Add($relativePath)
64+
Write-Error "PHPT exceeded ${TimeoutSeconds}s: $relativePath" -ErrorAction Continue
65+
& taskkill.exe /PID $process.Id /T /F 2>$null | Out-Null
66+
$process.WaitForExit()
67+
} else {
68+
$process.WaitForExit()
69+
$process.Refresh()
70+
$exitCode = $process.ExitCode
71+
if ($exitCode -ne 0) {
72+
$failures.Add($relativePath)
73+
Write-Error "PHPT failed with exit code ${exitCode}: $relativePath" -ErrorAction Continue
74+
}
75+
}
76+
} finally {
77+
Write-Host '::endgroup::'
78+
}
79+
}
80+
81+
Write-Host "Windows PHPT summary: $($tests.Count - $failures.Count) passed/skipped, $($failures.Count) failed, $($timeouts.Count) timed out"
82+
if ($failures.Count -gt 0) {
83+
Write-Host "Failed PHPT: $($failures -join ', ')"
84+
exit 1
85+
}

.github/workflows/windows.yml

Lines changed: 151 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ jobs:
55
windows-tests:
66
name: Unit Test on Windows
77
runs-on: windows-2022
8+
timeout-minutes: 20
89
if: "!contains(github.event.head_commit.message, '--filter=') || contains(github.event.head_commit.message, '[win-unit]')"
910
strategy:
1011
fail-fast: false
@@ -49,7 +50,7 @@ jobs:
4950
with:
5051
ext-path: .
5152
tools-path: C:\tools\phpdev
52-
conf-args: --enable-swoole-curl --enable-swoole-thread
53+
conf-args: --enable-swoole-curl --enable-swoole-thread --enable-php-sockets
5354
staging-deps: '1'
5455
deps: openssl,libcurl,libssh2,zlib,nghttp2,libzstd,brotli
5556

@@ -65,11 +66,158 @@ jobs:
6566
php composer-setup.php --quiet
6667
php composer.phar install --working-dir=tests\include\lib --no-interaction
6768
68-
- name: Run unit tests
69+
- name: Run IOCP cURL cancellation test
70+
id: iocp-curl-cancel
71+
continue-on-error: true
72+
timeout-minutes: 1
6973
shell: cmd
7074
run: |
7175
set PHPT=1
7276
set TEST_PHP_EXECUTABLE=php
7377
set SKIP_ONLINE_TESTS=1
7478
set NO_INTERACTION=1
75-
php tests\run-tests -P -q -d extension=php_swoole -d swoole.use_shortname=On --show-diff -g FAIL,BORK,LEAK,XLEAK --show-slow 1000 --set-timeout 300 tests\swoole_windows tests\swoole_function
79+
php tests\run-tests -P -q -d extension=php_swoole -d swoole.use_shortname=On --show-diff -g PASS,FAIL,BORK,LEAK,XLEAK --show-slow 1000 --set-timeout 10 tests\swoole_windows\iocp_curl_cancel.phpt
80+
81+
- name: Run core Windows IOCP tests
82+
id: windows-core
83+
continue-on-error: true
84+
timeout-minutes: 2
85+
shell: powershell
86+
run: |
87+
$tests = @(
88+
'tests\swoole_windows\atomic_compat.phpt',
89+
'tests\swoole_windows\bootstrap.phpt',
90+
'tests\swoole_windows\iocp_cancel.phpt',
91+
'tests\swoole_windows\iocp_curl.phpt',
92+
'tests\swoole_windows\iocp_curl_multi.phpt',
93+
'tests\swoole_windows\iocp_file.phpt',
94+
'tests\swoole_windows\iocp_shutdown.phpt',
95+
'tests\swoole_windows\iocp_socket.phpt',
96+
'tests\swoole_windows\local_ip.phpt',
97+
'tests\swoole_windows\local_mac.phpt'
98+
)
99+
& .github\workflows\windows-phpt.ps1 -Path $tests -TimeoutSeconds 12
100+
101+
- name: Run Windows function and atomic tests
102+
id: function-atomic
103+
continue-on-error: true
104+
timeout-minutes: 1
105+
shell: cmd
106+
run: |
107+
set PHPT=1
108+
set TEST_PHP_EXECUTABLE=php
109+
set SKIP_ONLINE_TESTS=1
110+
set NO_INTERACTION=1
111+
php tests\run-tests -P -q -d extension=php_swoole -d swoole.use_shortname=On --show-diff -g PASS,FAIL,BORK,LEAK,XLEAK --show-slow 1000 --set-timeout 10 tests\swoole_function tests\swoole_atomic\atomic.phpt tests\swoole_atomic\wait_and_wakeup.phpt
112+
113+
- name: Run Windows channel and lock tests
114+
id: channel-lock
115+
continue-on-error: true
116+
timeout-minutes: 2
117+
shell: cmd
118+
run: |
119+
set PHPT=1
120+
set TEST_PHP_EXECUTABLE=php
121+
set SKIP_ONLINE_TESTS=1
122+
set NO_INTERACTION=1
123+
php tests\run-tests -P -q -d extension=php_swoole -d swoole.use_shortname=On --show-diff -g PASS,FAIL,BORK,LEAK,XLEAK --show-slow 1000 --set-timeout 10 tests\swoole_channel_coro tests\swoole_coroutine_lock tests\swoole_coroutine_wait_group
124+
125+
- name: Run Windows scheduler tests
126+
id: scheduler
127+
continue-on-error: true
128+
timeout-minutes: 3
129+
shell: powershell
130+
run: |
131+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_coroutine_scheduler -TimeoutSeconds 12
132+
133+
- name: Run Windows coroutine utility tests
134+
id: coroutine-util
135+
continue-on-error: true
136+
timeout-minutes: 2
137+
shell: powershell
138+
run: |
139+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_coroutine_util -TimeoutSeconds 12
140+
141+
- name: Run Windows coroutine system tests
142+
id: coroutine-system
143+
continue-on-error: true
144+
timeout-minutes: 2
145+
shell: powershell
146+
run: |
147+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_coroutine_system -TimeoutSeconds 12
148+
149+
- name: Run Windows timer and event tests
150+
id: timer-event
151+
continue-on-error: true
152+
timeout-minutes: 2
153+
shell: cmd
154+
run: |
155+
set PHPT=1
156+
set TEST_PHP_EXECUTABLE=php
157+
set SKIP_ONLINE_TESTS=1
158+
set NO_INTERACTION=1
159+
php tests\run-tests -P -q -d extension=php_swoole -d swoole.use_shortname=On --show-diff -g PASS,FAIL,BORK,LEAK,XLEAK --show-slow 1000 --set-timeout 10 tests\swoole_timer tests\swoole_event
160+
161+
- name: Run Windows IOCP socket tests (1/4)
162+
id: iocp-socket-1
163+
continue-on-error: true
164+
timeout-minutes: 2
165+
shell: powershell
166+
run: |
167+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_socket_coro -Count 16 -TimeoutSeconds 12
168+
169+
- name: Run Windows IOCP socket tests (2/4)
170+
id: iocp-socket-2
171+
continue-on-error: true
172+
timeout-minutes: 2
173+
shell: powershell
174+
run: |
175+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_socket_coro -Offset 16 -Count 16 -TimeoutSeconds 12
176+
177+
- name: Run Windows IOCP socket tests (3/4)
178+
id: iocp-socket-3
179+
continue-on-error: true
180+
timeout-minutes: 2
181+
shell: powershell
182+
run: |
183+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_socket_coro -Offset 32 -Count 16 -TimeoutSeconds 12
184+
185+
- name: Run Windows IOCP socket tests (4/4)
186+
id: iocp-socket-4
187+
continue-on-error: true
188+
timeout-minutes: 2
189+
shell: powershell
190+
run: |
191+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_socket_coro -Offset 48 -Count 16 -TimeoutSeconds 12
192+
193+
- name: Run Windows thread tests
194+
id: thread
195+
continue-on-error: true
196+
timeout-minutes: 4
197+
shell: powershell
198+
run: |
199+
& .github\workflows\windows-phpt.ps1 -Path tests\swoole_thread\*.phpt -TimeoutSeconds 20
200+
201+
- name: Check Windows test results
202+
if: always()
203+
shell: powershell
204+
run: |
205+
$outcomes = @(
206+
'${{ steps.iocp-curl-cancel.outcome }}',
207+
'${{ steps.windows-core.outcome }}',
208+
'${{ steps.function-atomic.outcome }}',
209+
'${{ steps.channel-lock.outcome }}',
210+
'${{ steps.scheduler.outcome }}',
211+
'${{ steps.coroutine-util.outcome }}',
212+
'${{ steps.coroutine-system.outcome }}',
213+
'${{ steps.timer-event.outcome }}',
214+
'${{ steps.iocp-socket-1.outcome }}',
215+
'${{ steps.iocp-socket-2.outcome }}',
216+
'${{ steps.iocp-socket-3.outcome }}',
217+
'${{ steps.iocp-socket-4.outcome }}',
218+
'${{ steps.thread.outcome }}'
219+
)
220+
if ($outcomes -contains 'failure' -or $outcomes -contains 'cancelled') {
221+
Write-Error "One or more Windows PHPT suites failed: $($outcomes -join ', ')"
222+
exit 1
223+
}

.github/workflows/winext/install.ps1

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ if ($dumpbinPath) {
8585
$notFound = @()
8686
foreach ($dll in $imports) {
8787
if ($dll | IsSystemDll) { continue }
88-
if (Test-Path "$phppath\$dll") { continue }
88+
# PHP extensions normally live in extension_dir, and extension DLLs
89+
# imported by another extension are resolvable from there as well.
90+
if ((Test-Path "$phppath\$dll") -or (Test-Path "$extdir\$dll")) { continue }
8991
if ($dllIndex.ContainsKey($dll)) {
9092
info "Copy dep DLL: $dll -> $phppath"
9193
Copy-Item $dllIndex[$dll] $phppath
@@ -103,7 +105,9 @@ if ($dumpbinPath) {
103105
} else {
104106
warn "dumpbin not available, copying all non-system DLLs from index"
105107
foreach ($kv in $dllIndex.GetEnumerator()) {
106-
if (($kv.Key | IsSystemDll) -or (Test-Path "$phppath\$($kv.Key)")) { continue }
108+
if (($kv.Key | IsSystemDll) -or
109+
(Test-Path "$phppath\$($kv.Key)") -or
110+
(Test-Path "$extdir\$($kv.Key)")) { continue }
107111
info "Copy dep DLL: $($kv.Key) -> $phppath"
108112
Copy-Item $kv.Value $phppath
109113
$copiedCount++
@@ -147,15 +151,16 @@ if ($dumpbinPath) {
147151
$missingDlls = @()
148152
foreach ($dll in $allImports) {
149153
if ($dll | IsSystemDll) { continue }
150-
if (-not (Test-Path "$phppath\$dll")) {
154+
if ((-not (Test-Path "$phppath\$dll")) -and
155+
(-not (Test-Path "$extdir\$dll"))) {
151156
$missingDlls += $dll
152157
}
153158
}
154159

155160
if ($missingDlls.Count) {
156161
Write-Host "`nMISSING DLLs:" -ForegroundColor Red
157162
$missingDlls | ForEach-Object { Write-Host " $_" -ForegroundColor Red }
158-
err "Cannot load swoole: $($missingDlls.Count) DLL(s) not found in $phppath"
163+
err "Cannot load swoole: $($missingDlls.Count) DLL(s) not found in $phppath or $extdir"
159164
$checkOk = $false
160165
} else {
161166
Write-Host "`nAll $($allImports.Count) dependency DLLs resolved" -ForegroundColor Green

config.w32

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ if (PHP_SWOOLE != "no") {
206206
// Check for required libraries and headers
207207
var swoole_ok = true;
208208

209+
AC_DEFINE("HAVE_CPU_AFFINITY", 1, "CPU affinity support");
209210
AC_DEFINE("SW_USE_OPENSSL", 1, "Enable OpenSSL support");
210211
AC_DEFINE("SW_HAVE_ZLIB", 1, "Have zlib");
211212
AC_DEFINE("SW_HAVE_BROTLI", 1, "Have Brotli");
@@ -324,7 +325,7 @@ if (PHP_SWOOLE != "no") {
324325
AC_DEFINE("SW_CORO_TIME", 1, "Calculate coroutine execution time");
325326
}
326327

327-
if (PHP_SOCKETS == "yes") {
328+
if (PHP_PHP_SOCKETS == "yes") {
328329
AC_DEFINE("SW_SOCKETS", 1, "Enable sockets support");
329330
AC_DEFINE("HAVE_SOCKETS", 1, "Whether sockets extension is enabled");
330331
}
@@ -349,6 +350,10 @@ if (PHP_SWOOLE != "no") {
349350
ADD_EXTENSION_DEP("swoole", "curl");
350351
}
351352

353+
if (PHP_PHP_SOCKETS == "yes") {
354+
ADD_EXTENSION_DEP("swoole", "sockets");
355+
}
356+
352357
if (PHP_SWOOLE_SQLITE == "yes") {
353358
ADD_EXTENSION_DEP("swoole", "pdo");
354359
}

ext-src/php_swoole_cxx.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,44 @@ zend_refcounted *sw_get_refcount_ptr(zval *value) {
1616
return (sw_refcount_ptr = value->value.counted);
1717
}
1818

19+
#ifdef HAVE_CPU_AFFINITY
20+
bool php_swoole_array_to_cpu_set(const zval *array, cpu_set_t *cpu_set) {
21+
if (php_swoole_array_length(array) == 0) {
22+
return false;
23+
}
24+
25+
const zend_long cpu_num = SW_MIN((zend_long) SW_CPU_NUM, (zend_long) CPU_SETSIZE);
26+
if ((zend_long) php_swoole_array_length(array) > cpu_num) {
27+
php_swoole_fatal_error(E_WARNING, "More than the number of CPU");
28+
return false;
29+
}
30+
31+
zval *value = nullptr;
32+
CPU_ZERO(cpu_set);
33+
34+
SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(array), value)
35+
if (zval_get_long(value) < 0 || zval_get_long(value) >= cpu_num) {
36+
php_swoole_fatal_error(E_WARNING, "invalid cpu id [%d]", (int) Z_LVAL_P(value));
37+
return false;
38+
}
39+
CPU_SET(Z_LVAL_P(value), cpu_set);
40+
SW_HASHTABLE_FOREACH_END();
41+
42+
return true;
43+
}
44+
45+
void php_swoole_cpu_set_to_array(zval *array, cpu_set_t *cpu_set) {
46+
array_init(array);
47+
48+
int cpu_n = SW_MIN(SW_CPU_NUM, CPU_SETSIZE);
49+
SW_LOOP_N(cpu_n) {
50+
if (CPU_ISSET(i, cpu_set)) {
51+
add_next_index_long(array, i);
52+
}
53+
}
54+
}
55+
#endif
56+
1957
//----------------------------------known string------------------------------------
2058
namespace zend {
2159
void known_strings_init() {

0 commit comments

Comments
 (0)