[CmdletBinding()] param( [string]$PostgresBin = 'D:\pgsql17\bin', [int]$PostgresPort = 55462, [int]$BellPort = 18092, [string]$Database = 'bell_62' ) $ErrorActionPreference = 'Stop' $serverProcess = $null $testRoot = Join-Path ([System.IO.Path]::GetTempPath()) 'yovision-bell-62-smoke' $serverExe = Join-Path $testRoot 'bell-server.exe' $stdout = Join-Path $testRoot 'bell-server.out.log' $stderr = Join-Path $testRoot 'bell-server.err.log' $serverRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\server')).Path $dropDb = Join-Path $PostgresBin 'dropdb.exe' $createDb = Join-Path $PostgresBin 'createdb.exe' $psql = Join-Path $PostgresBin 'psql.exe' New-Item -ItemType Directory -Path $testRoot -Force | Out-Null try { & $dropDb -h 127.0.0.1 -p $PostgresPort -U postgres --if-exists $Database if ($LASTEXITCODE -ne 0) { throw 'dropdb failed' } & $createDb -h 127.0.0.1 -p $PostgresPort -U postgres $Database if ($LASTEXITCODE -ne 0) { throw 'createdb failed' } $smokePassword = [guid]::NewGuid().ToString('N') $env:GOTOOLCHAIN = 'go1.26.5' $env:BELL_DATABASE_URL = "host=127.0.0.1 port=$PostgresPort user=postgres dbname=$Database sslmode=disable" $env:BELL_JWT_SECRET = [guid]::NewGuid().ToString('N') + [guid]::NewGuid().ToString('N') $env:BELL_BOOTSTRAP_USERNAME = 'bell_smoke_admin' $env:BELL_BOOTSTRAP_PASSWORD = $smokePassword $env:BELL_HOST = '127.0.0.1' $env:BELL_PORT = $BellPort.ToString() Push-Location $serverRoot try { go run . migrate -c config/settings.demo.yml *> (Join-Path $testRoot 'bell-migrate.log') if ($LASTEXITCODE -ne 0) { throw 'Bell migration failed' } go build -o $serverExe . if ($LASTEXITCODE -ne 0) { throw 'Bell server build failed' } } finally { Pop-Location } $serverProcess = Start-Process -FilePath $serverExe -ArgumentList @('server', '-c', 'config/settings.demo.yml') -WorkingDirectory $serverRoot -RedirectStandardOutput $stdout -RedirectStandardError $stderr -WindowStyle Hidden -PassThru $deadline = (Get-Date).AddSeconds(30) $health = $null do { try { $health = Invoke-RestMethod -Uri "http://127.0.0.1:$BellPort/healthz" -TimeoutSec 2 -NoProxy break } catch { Start-Sleep -Milliseconds 300 } } while ((Get-Date) -lt $deadline) if ($null -eq $health -or $health.service -ne 'bell') { throw 'Bell health check failed' } $loginBody = @{ username = 'bell_smoke_admin'; password = $smokePassword; code = '0'; uuid = '0' } | ConvertTo-Json -Compress $login = Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:$BellPort/api/v1/login" -ContentType 'application/json' -Body $loginBody -TimeoutSec 5 -NoProxy if ($login.code -ne 200 -or [string]::IsNullOrWhiteSpace($login.token)) { throw "Bell login failed with code $($login.code)" } $headers = @{ Authorization = "Bearer $($login.token)" } $menus = Invoke-RestMethod -Uri "http://127.0.0.1:$BellPort/api/v1/menurole" -Headers $headers -TimeoutSec 5 -NoProxy if ($menus.code -ne 200) { throw "menu request failed with code $($menus.code)" } $unauth = Invoke-WebRequest -Uri "http://127.0.0.1:$BellPort/api/v1/sys-user" -SkipHttpErrorCheck -TimeoutSec 5 -NoProxy $disabled = Invoke-WebRequest -Uri "http://127.0.0.1:$BellPort/api/v1/server-monitor" -Headers $headers -SkipHttpErrorCheck -TimeoutSec 5 -NoProxy $disabledAdmin = Invoke-WebRequest -Uri "http://127.0.0.1:$BellPort/api/v1/dept" -Headers $headers -SkipHttpErrorCheck -TimeoutSec 5 -NoProxy if ($unauth.Content -notmatch '401') { throw 'RBAC unauthenticated request was not rejected' } if ($disabled.StatusCode -ne 404) { throw "disabled route status was $($disabled.StatusCode)" } if ($disabledAdmin.StatusCode -ne 404) { throw "disabled admin route status was $($disabledAdmin.StatusCode)" } $dbEvidence = & $psql -h 127.0.0.1 -p $PostgresPort -U postgres -d $Database -Atc "select count(*) from sys_migration; select count(*) from sys_user where username='bell_smoke_admin'; select count(*) from sys_menu where visible='0' and menu_id in (2,3,51,52); select count(*) from sys_menu where visible='1' and menu_id in (56,57,58,59,60,62,211,212,216,261,262,264,269,459,460,471,528,537,540);" Write-Output "SMOKE health=$($health.status) login=$($login.code) unauth_rejected=true disabled_routes=$($disabled.StatusCode)/$($disabledAdmin.StatusCode) db_evidence=$($dbEvidence -join ',')" } finally { if ($null -ne $serverProcess -and -not $serverProcess.HasExited) { Stop-Process -Id $serverProcess.Id -Force } Remove-Item Env:BELL_BOOTSTRAP_PASSWORD -ErrorAction SilentlyContinue Remove-Item Env:BELL_JWT_SECRET -ErrorAction SilentlyContinue }