param( [string]$Php = 'D:/phpstudy_pro/Extensions/php/php8.2.9nts/php.exe', [string]$MySqlRoot = 'D:/phpstudy_pro/Extensions/MySQL5.7.26' ) $ErrorActionPreference = 'Stop' $artifactRoot = [System.IO.Path]::GetFullPath($PSScriptRoot) $workspaceRoot = [System.IO.Path]::GetFullPath((Join-Path $artifactRoot '../..')) $runRoot = [System.IO.Path]::GetFullPath((Join-Path $artifactRoot ('mysql-test-' + [guid]::NewGuid().ToString('N')))) if (-not $runRoot.StartsWith($artifactRoot + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase)) { throw 'Disposable data directory escaped its artifact directory.' } $dataRoot = Join-Path $runRoot 'data' $mysqld = Join-Path $MySqlRoot 'bin/mysqld.exe' $mysqladmin = Join-Path $MySqlRoot 'bin/mysqladmin.exe' $listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Loopback, 0) $listener.Start() $port = $listener.LocalEndpoint.Port $listener.Stop() $mysqlProcess = $null $testExit = 1 $previousPort = $env:ZYT_WECOM_MEMBER_TEST_MYSQL_PORT try { New-Item -ItemType Directory -Path $dataRoot -Force | Out-Null $initArguments = @('--no-defaults', '--initialize-insecure', ('--basedir=' + $MySqlRoot), ('--datadir=' + $dataRoot)) $initProcess = Start-Process -FilePath $mysqld -ArgumentList $initArguments -WindowStyle Hidden -PassThru -Wait -RedirectStandardError (Join-Path $runRoot 'initialize.log') if ($initProcess.ExitCode -ne 0) { throw 'Disposable MySQL initialization failed.' } $startArguments = @('--no-defaults', ('--basedir=' + $MySqlRoot), ('--datadir=' + $dataRoot), ('--port=' + $port), '--bind-address=127.0.0.1', '--innodb-buffer-pool-size=32M') $mysqlProcess = Start-Process -FilePath $mysqld -ArgumentList $startArguments -WindowStyle Hidden -PassThru -RedirectStandardError (Join-Path $runRoot 'server.log') $ready = $false for ($attempt = 0; $attempt -lt 60; $attempt++) { if ($mysqlProcess.HasExited) { throw 'Disposable MySQL exited before becoming ready.' } $client = [System.Net.Sockets.TcpClient]::new() try { $client.Connect('127.0.0.1', $port) $ready = $true } catch { Start-Sleep -Milliseconds 250 } finally { $client.Dispose() } if ($ready) { break } } if (-not $ready) { throw 'Disposable MySQL did not become ready.' } $env:ZYT_WECOM_MEMBER_TEST_MYSQL_PORT = [string]$port & $Php (Join-Path $workspaceRoot 'server/tests/WecomPromotionMemberSyncTest.php') 2>&1 | Tee-Object -FilePath (Join-Path $artifactRoot 'backend-test-output.log') $testExit = $LASTEXITCODE } finally { $env:ZYT_WECOM_MEMBER_TEST_MYSQL_PORT = $previousPort if ($null -ne $mysqlProcess -and -not $mysqlProcess.HasExited) { & $mysqladmin --no-defaults --host=127.0.0.1 ('--port=' + $port) --user=root shutdown 2>$null $mysqlProcess.WaitForExit(10000) | Out-Null if (-not $mysqlProcess.HasExited) { Stop-Process -Id $mysqlProcess.Id -Force $mysqlProcess.WaitForExit(5000) | Out-Null } } $resolvedRunRoot = [System.IO.Path]::GetFullPath($runRoot) if (-not $resolvedRunRoot.StartsWith($artifactRoot + [System.IO.Path]::DirectorySeparatorChar, [System.StringComparison]::OrdinalIgnoreCase) -or (Split-Path $resolvedRunRoot -Leaf) -notmatch '^mysql-test-[a-f0-9]{32}$') { throw 'Refusing to remove an unverified temporary path.' } if (Test-Path -LiteralPath $resolvedRunRoot) { Remove-Item -LiteralPath $resolvedRunRoot -Recurse -Force } Write-Output 'Disposable MySQL stopped and its temporary data directory removed.' } exit $testExit