# End-to-end smoke test: # start proxy -> run chat cases -> wait batch flush -> verify ClickHouse -> stop proxy. param( [string]$Model = "gpt-5.4-mini", [string]$ApiKey = $env:NEWAPI_KEY, [string]$ProxyBase = "http://127.0.0.1:8080" ) if (-not $ApiKey) { throw "NEWAPI_KEY not set" } $ErrorActionPreference = "Stop" function Section($name) { Write-Host "" Write-Host ("=" * 70) -ForegroundColor Cyan Write-Host $name -ForegroundColor Cyan Write-Host ("=" * 70) -ForegroundColor Cyan } Section "Start proxy" if (Test-Path proxy.log) { Remove-Item proxy.log -Force } if (Test-Path proxy.err.log) { Remove-Item proxy.err.log -Force } $proxy = Start-Process -FilePath .\TokenThief.exe -PassThru -RedirectStandardOutput proxy.log -RedirectStandardError proxy.err.log -WindowStyle Hidden Write-Host "proxy pid=$($proxy.Id)" Start-Sleep -Seconds 2 $health = & curl.exe -s -o NUL -w "%{http_code}" "$ProxyBase/healthz" Write-Host "healthz: $health" if ($health -ne "200") { Get-Content proxy.log -Tail 30 | Write-Host Get-Content proxy.err.log -Tail 30 | Write-Host throw "proxy did not start" } $results = @{} function CallChat { param([string]$Url, [string]$JsonBody) $bodyTmp = New-TemporaryFile $headTmp = New-TemporaryFile $outTmp = New-TemporaryFile # PowerShell 5.1 Set-Content -Encoding UTF8 writes a BOM; newapi rejects BOM-prefixed JSON. $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($bodyTmp.FullName, $JsonBody, $utf8NoBom) $code = & curl.exe -s -X POST $Url ` -H "Content-Type: application/json" ` -H "Authorization: Bearer $ApiKey" ` -D $headTmp.FullName ` -o $outTmp.FullName ` --data-binary "@$($bodyTmp.FullName)" ` -w "%{http_code}" $rid = "" foreach ($line in Get-Content $headTmp.FullName) { if ($line -match '^X-Request-Id:\s*(.+)$') { $rid = $matches[1].Trim() break } } $body = Get-Content $outTmp.FullName -Raw -ErrorAction SilentlyContinue if (-not $body) { $body = "" } Remove-Item $bodyTmp.FullName, $headTmp.FullName, $outTmp.FullName -Force -ErrorAction SilentlyContinue return @{ StatusCode = $code; RequestID = $rid; Body = $body } } try { Section "T1: non-stream chat completions" $t1Body = '{"model":"' + $Model + '","messages":[{"role":"user","content":"Say hello in one short sentence."}],"stream":false}' $r = CallChat "$ProxyBase/v1/chat/completions" $t1Body Write-Host " status=$($r.StatusCode) rid=$($r.RequestID)" $preview = if ($r.Body.Length -gt 200) { $r.Body.Substring(0, 200) } else { $r.Body } Write-Host " body(first 200): $preview" $results.T1 = $r Section "T2: stream chat completions" $t2Body = '{"model":"' + $Model + '","messages":[{"role":"user","content":"Say exactly: one two three four five"}],"stream":true}' $r = CallChat "$ProxyBase/v1/chat/completions" $t2Body Write-Host " status=$($r.StatusCode) rid=$($r.RequestID)" $chunkCount = ([regex]::Matches($r.Body, "^data:", "Multiline")).Count $hasDone = $r.Body.Contains("[DONE]") Write-Host " SSE chunk lines=$chunkCount contains [DONE]=$hasDone body_len=$($r.Body.Length)" $results.T2 = $r Section "T3: large body (request_truncated should be true)" $bigContent = "x" * (12 * 1024 * 1024) $t3Body = '{"model":"' + $Model + '","messages":[{"role":"user","content":"' + $bigContent + '"}],"stream":false,"max_tokens":5}' Write-Host " request body size: $($t3Body.Length) bytes" $r = CallChat "$ProxyBase/v1/chat/completions" $t3Body Write-Host " status=$($r.StatusCode) rid=$($r.RequestID)" $preview = if ($r.Body.Length -gt 200) { $r.Body.Substring(0, 200) } else { $r.Body } Write-Host " body(first 200): $preview" $results.T3 = $r Section "T4: nonexistent model (upstream error response should be logged)" $t4Body = '{"model":"definitely-not-a-real-model-xyz","messages":[{"role":"user","content":"hi"}]}' $r = CallChat "$ProxyBase/v1/chat/completions" $t4Body Write-Host " status=$($r.StatusCode) rid=$($r.RequestID)" $preview = if ($r.Body.Length -gt 200) { $r.Body.Substring(0, 200) } else { $r.Body } Write-Host " body(first 200): $preview" $results.T4 = $r Section "T5: healthz (should not be logged)" $code = & curl.exe -s -o NUL -w "%{http_code}" "$ProxyBase/healthz" Write-Host " /healthz status=$code" Section "Wait batch flush (4s)" Start-Sleep -Seconds 4 Section "T6: ClickHouse verification" $rids = @() foreach ($k in @("T1","T2","T3","T4")) { if ($results[$k].RequestID) { $rids += $results[$k].RequestID } } Write-Host " request_ids: $($rids -join ', ')" $env:CHECK_RIDS = ($rids | ConvertTo-Json -Compress) if ($rids.Count -eq 1) { $env:CHECK_RIDS = "[`"$($rids[0])`"]" } & go run .\tests\scripts\dbcheck\main.go Remove-Item Env:CHECK_RIDS -ErrorAction SilentlyContinue } finally { Section "Stop proxy" Stop-Process -Id $proxy.Id -Force Write-Host "tail proxy.log:" Get-Content proxy.log -Tail 30 | Write-Host if (Test-Path proxy.err.log) { $err = Get-Content proxy.err.log -ErrorAction SilentlyContinue if ($err) { Write-Host "proxy.err.log:" $err | Write-Host } } }