mirror of
https://github.com/php/frankenphp.git
synced 2026-03-23 16:42:13 +01:00
Closes #83 #880 #1286. Working patch for Windows support. Supports linking to the [official PHP release (TS version)](https://www.php.net/downloads.php). Includes some work from #1286 (thanks @TenHian!!) This patch allows using Visual Studio to compile the cgo code. To do so, it must be compiled with Go 1.26 (RC) with the following setup: ```powershell winget install -e --id Microsoft.VisualStudio.2022.Community --override "--passive --wait --add Microsoft.VisualStudio.Workload.NativeDesktop --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --includeRecommended" winget install -e --id GoLang.Go $env:PATH += ';C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\bin' cd c:\ gh repo clone microsoft/vcpkg .\vcpkg\bootstrap-vcpkg.bat .\vcpkg\vcpkg install pthreads brotli # build watcher Invoke-WebRequest -Uri "https://github.com/e-dant/watcher/releases/download/0.14.3/x86_64-pc-windows-msvc.tar" -OutFile "$env:TEMP\watcher.tar" tar -xf "$env:TEMP\watcher.tar" -C C:\ Rename-Item -Path "C:\x86_64-pc-windows-msvc" -NewName "watcher-x86_64-pc-windows-msvc" Remove-Item "$env:TEMP\watcher.tar" # download php Invoke-WebRequest -Uri "https://downloads.php.net/~windows/releases/archives/php-8.5.1-Win32-vs17-x64.zip" -OutFile "$env:TEMP\php.zip" Expand-Archive -Path "$env:TEMP\php.zip" -DestinationPath "C:\" Remove-Item "$env:TEMP\php.zip" # download php development package Invoke-WebRequest -Uri "https://downloads.php.net/~windows/releases/archives/php-devel-pack-8.5.1-Win32-vs17-x64.zip" -OutFile "$env:TEMP\php-devel.zip" Expand-Archive -Path "$env:TEMP\php-devel.zip" -DestinationPath "C:\" Remove-Item "$env:TEMP\php-devel.zip" $env:GOTOOLCHAIN = 'go1.26rc1' $env:CC = 'clang' $env:CXX = 'clang++' $env:CGO_CFLAGS = "-I$env:C:\vcpkg\installed\x64-windows\include -IC:\watcher-x86_64-pc-windows-msvc -IC:\php-8.5.1-devel-vs17-x64\include -IC:\php-8.5.1-devel-vs17-x64\include\main -IC:\php-8.5.1-devel-vs17-x64\include\TSRM -IC:\php-8.5.1-devel-vs17-x64\include\Zend -IC:\php-8.5.1-devel-vs17-x64\include\ext" $env:CGO_LDFLAGS = '-LC:\vcpkg\installed\x64-windows\lib -lbrotlienc -LC:\watcher-x86_64-pc-windows-msvc -llibwatcher-c -LC:\php-8.5.1-Win32-vs17-x64 -LC:\php-8.5.1-devel-vs17-x64\lib -lphp8ts -lphp8embed' # clone frankenphp and build git clone -b windows https://github.com/php/frankenphp.git cd frankenphp\caddy\frankenphp go build -ldflags '-extldflags="-fuse-ld=lld"' -tags nowatcher,nobadger,nomysql,nopgx # Tests $env:PATH += ";$env:VCPKG_ROOT\installed\x64-windows\bin;C:\watcher-x86_64-pc-windows-msvc";C:\php-8.5.1-Win32-vs17-x64" "opcache.enable=0`r`nopcache.enable_cli=0" | Out-File -Encoding ascii php.ini $env:PHPRC = Get-Location go test -ldflags '-extldflags="-fuse-ld=lld"' -tags nowatcher,nobadger,nomysql,nopgx . ``` TODO: - [x] Fix remaining skipped tests (scaling and watcher) - [x] Test if the watcher mode works as expected - [x] Automate the build with GitHub Actions --------- Signed-off-by: Marc <m@pyc.ac> Co-authored-by: Kévin Dunglas <kevin@dunglas.dev> Co-authored-by: DubbleClick <m@pyc.ac>
71 lines
2.3 KiB
Go
71 lines
2.3 KiB
Go
//go:build !nowatcher
|
|
|
|
package frankenphp_test
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// we have to wait a few milliseconds for the watcher debounce to take effect
|
|
const pollingTime = 250
|
|
|
|
// in tests checking for no reload: we will poll 3x250ms = 0.75s
|
|
const minTimesToPollForChanges = 3
|
|
|
|
// in tests checking for a reload: we will poll a maximum of 60x250ms = 15s
|
|
const maxTimesToPollForChanges = 60
|
|
|
|
func TestWorkersShouldReloadOnMatchingPattern(t *testing.T) {
|
|
watch := []string{"./testdata/**/*.txt"}
|
|
|
|
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
|
requestBodyHasReset := pollForWorkerReset(t, handler, maxTimesToPollForChanges)
|
|
assert.True(t, requestBodyHasReset)
|
|
}, &testOptions{nbParallelRequests: 1, nbWorkers: 1, workerScript: "worker-with-counter.php", watch: watch})
|
|
}
|
|
|
|
func TestWorkersShouldNotReloadOnExcludingPattern(t *testing.T) {
|
|
watch := []string{"./testdata/**/*.php"}
|
|
|
|
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
|
|
requestBodyHasReset := pollForWorkerReset(t, handler, minTimesToPollForChanges)
|
|
assert.False(t, requestBodyHasReset)
|
|
}, &testOptions{nbParallelRequests: 1, nbWorkers: 1, workerScript: "worker-with-counter.php", watch: watch})
|
|
}
|
|
|
|
func pollForWorkerReset(t *testing.T, handler func(http.ResponseWriter, *http.Request), limit int) bool {
|
|
t.Helper()
|
|
|
|
// first we make an initial request to start the request counter
|
|
body, _ := testGet("http://example.com/worker-with-counter.php", handler, t)
|
|
assert.Equal(t, "requests:1", body)
|
|
|
|
// now we spam file updates and check if the request counter resets
|
|
for range limit {
|
|
updateTestFile(t, filepath.Join(".", "testdata", "files", "test.txt"), "updated")
|
|
time.Sleep(pollingTime * time.Millisecond)
|
|
body, _ := testGet("http://example.com/worker-with-counter.php", handler, t)
|
|
if body == "requests:1" {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func updateTestFile(t *testing.T, fileName, content string) {
|
|
absFileName, err := filepath.Abs(fileName)
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, os.MkdirAll(filepath.Dir(absFileName), 0700))
|
|
require.NoError(t, os.WriteFile(absFileName, []byte(content), 0644))
|
|
}
|