Files

240 lines
10 KiB
PowerShell
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 配置文件专项测试:验证 daili.ini 的生成、解析、覆盖与各项生效
# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File scripts\config-test.ps1
param(
[string]$Exe = '',
[string]$Work = '',
[string]$LanIp = ''
)
$Root = Split-Path -Parent $PSScriptRoot
if (-not $Exe) { $Exe = Join-Path $Root 'daili.exe' }
if (-not $Work) { $Work = Join-Path $Root 'config-run' }
$Evidence = Join-Path $Root 'test-evidence'
if (-not (Test-Path $Exe)) { throw "找不到被测程序:$Exe(先构建或已用 -Exe 指定)" }
$ErrorActionPreference = 'Continue'
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
Add-Type -AssemblyName System.Net.Http
$script:fail = 0
$script:results = @()
function Check {
param([string]$Id, [string]$Name, $Cond, [string]$Detail = '')
if ($Cond -eq $true) {
Write-Host (" [PASS] {0} {1}" -f $Id, $Name) -ForegroundColor Green
$script:results += "PASS|$Id|$Name|$Detail"
} else {
Write-Host (" [FAIL] {0} {1} {2}" -f $Id, $Name, $Detail) -ForegroundColor Red
$script:results += "FAIL|$Id|$Name|$Detail"
$script:fail++
}
}
function New-Client {
$h = New-Object System.Net.Http.HttpClientHandler
$h.UseCookies = $true
$h.AllowAutoRedirect = $true
$c = New-Object System.Net.Http.HttpClient($h)
$c.Timeout = [TimeSpan]::FromSeconds(10)
return $c
}
function Post-Form($client, $url, $kv) {
$pairs = New-Object 'System.Collections.Generic.List[System.Collections.Generic.KeyValuePair[string,string]]'
foreach ($k in $kv.Keys) {
$pairs.Add([System.Collections.Generic.KeyValuePair[string,string]]::new($k, [string]$kv[$k]))
}
return $client.PostAsync($url, [System.Net.Http.FormUrlEncodedContent]::new($pairs)).Result
}
function Get-Status($client, $url) {
try {
$r = $client.GetAsync($url).Result
return @{ Code = [int]$r.StatusCode; Path = $r.RequestMessage.RequestUri.AbsolutePath; Body = $r.Content.ReadAsStringAsync().Result }
} catch {
return @{ Code = 0; Path = ''; Body = '' }
}
}
function Wait-Up([int]$port, [int]$seconds = 15) {
$c = New-Client
for ($i = 0; $i -lt ($seconds * 4); $i++) {
$r = Get-Status $c "http://127.0.0.1:$port/healthz"
if ($r.Code -eq 200) { return $true }
Start-Sleep -Milliseconds 250
}
return $false
}
function Start-App([string]$dir, [string[]]$extra, [int]$port) {
$out = Join-Path $dir 'stdout.log'
$err = Join-Path $dir 'stderr.log'
$p = Start-Process -FilePath (Join-Path $dir 'daili.exe') -ArgumentList $extra -WorkingDirectory $dir `
-WindowStyle Hidden -PassThru -RedirectStandardOutput $out -RedirectStandardError $err
$ok = Wait-Up $port
return @{ Proc = $p; Out = $out; Err = $err; Up = $ok }
}
function Stop-App($h) {
if ($h -and $h.Proc) { Stop-Process -Id $h.Proc.Id -Force -ErrorAction SilentlyContinue }
Start-Sleep -Milliseconds 600
}
function New-CaseDir([string]$name) {
$dir = Join-Path $Work $name
Remove-Item -Recurse -Force $dir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $dir | Out-Null
Copy-Item $Exe (Join-Path $dir 'daili.exe') -Force
return $dir
}
function Write-Conf([string]$dir, [string]$text) {
[System.IO.File]::WriteAllText((Join-Path $dir 'daili.ini'), $text, (New-Object System.Text.UTF8Encoding($false)))
}
if (-not $LanIp) {
$LanIp = @(Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
Where-Object { $_.IPAddress -notlike '127.*' -and $_.IPAddress -notlike '169.254.*' -and $_.PrefixOrigin -ne 'WellKnown' } |
Select-Object -First 1 -ExpandProperty IPAddress)
}
if (-not $LanIp) { $LanIp = '192.168.1.1' }
Remove-Item -Recurse -Force $Work -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $Work | Out-Null
Write-Host "`n=== 配置文件专项测试(LAN IP: $LanIp) ===" -ForegroundColor Cyan
$c = New-Client
# ---------- CFG-01 / CFG-02:首启生成默认配置 + 默认端口 17777 ----------
Write-Host "`n-- CFG-01/02 首次启动生成默认配置 --" -ForegroundColor Cyan
$d1 = New-CaseDir 'default'
$h = Start-App $d1 @('-no-open') 17777
$ini = Join-Path $d1 'daili.ini'
Check 'CFG-01a' '首次启动自动生成 daili.ini' (Test-Path $ini)
$iniText = Get-Content $ini -Raw -Encoding UTF8
Check 'CFG-01b' '默认配置含注释与默认监听' (($iniText -match '代打台 配置文件') -and ($iniText -match 'listen_ip = 0\.0\.0\.0') -and ($iniText -match 'listen_port = 17777') -and ($iniText -match 'screen_public = true'))
$r = Get-Status $c 'http://127.0.0.1:17777/healthz'
Check 'CFG-02' '默认监听 17777 可用' ($h.Up -and $r.Code -eq 200) "health=$($r.Code)"
Stop-App $h
$logDir = Join-Path $d1 'logs'
$logs = @(Get-ChildItem $logDir -Filter 'daili-*.log' -ErrorAction SilentlyContinue)
$logText = ''
if ($logs.Count -ge 1) { $logText = Get-Content $logs[0].FullName -Raw -Encoding UTF8 }
Check 'CFG-07' '运行日志按天落盘' ($logs.Count -ge 1 -and $logText.Length -gt 20) "files=$($logs.Count) bytes=$($logText.Length)"
# ---------- CFG-03:只监听本机 ----------
Write-Host "`n-- CFG-03 仅本机监听 --" -ForegroundColor Cyan
$d2 = New-CaseDir 'loopback'
Write-Conf $d2 @"
listen_ip = 127.0.0.1
listen_port = 17901
open_browser = false
log_enabled = false
backup_enabled = false
"@
$h = Start-App $d2 @('-no-open') 17901
$local = (Test-NetConnection -ComputerName 127.0.0.1 -Port 17901 -InformationLevel Quiet -WarningAction SilentlyContinue)
$lan = (Test-NetConnection -ComputerName $LanIp -Port 17901 -InformationLevel Quiet -WarningAction SilentlyContinue)
Check 'CFG-03' '127.0.0.1 只开本机,局域网不可连' ($h.Up -and $local -and -not $lan) "local=$local lan=$lan"
$banner = Get-Content (Join-Path $d2 'stdout.log') -Raw -Encoding UTF8
Check 'CFG-03b' '横幅不再打印局域网地址' (-not ($banner -match '局域网')) ""
Stop-App $h
# ---------- CFG-04:非法配置报错退出且不改文件 ----------
Write-Host "`n-- CFG-04 非法配置 --" -ForegroundColor Cyan
$d3 = New-CaseDir 'invalid'
Write-Conf $d3 "# 故意写错`nlisten_ip = 0.0.0.0`nlisten_port = 99999`n"
$badIni = Join-Path $d3 'daili.ini'
$hashBefore = (Get-FileHash $badIni -Algorithm SHA256).Hash
$outText = & (Join-Path $d3 'daili.exe') -no-open 2>&1 | Out-String
$code = $LASTEXITCODE
$hashAfter = (Get-FileHash $badIni -Algorithm SHA256).Hash
Check 'CFG-04a' '非法配置退出码为 1' ($code -eq 1) "code=$code"
Check 'CFG-04b' '错误信息指出行号' ($outText -match '第 3 行' -and $outText -match '1-65535') ""
Check 'CFG-04c' '原配置文件未被改动' ($hashBefore -eq $hashAfter) ""
# ---------- CFG-05:命令行覆盖配置 ----------
Write-Host "`n-- CFG-05 命令行覆盖 --" -ForegroundColor Cyan
$d4 = New-CaseDir 'override'
Write-Conf $d4 @"
listen_ip = 127.0.0.1
listen_port = 17902
open_browser = false
log_enabled = false
backup_enabled = false
"@
$h = Start-App $d4 @('-no-open', '-addr', '127.0.0.1:17903') 17903
$p17902 = (Test-NetConnection -ComputerName 127.0.0.1 -Port 17902 -InformationLevel Quiet -WarningAction SilentlyContinue)
Check 'CFG-05' '-addr 覆盖配置文件端口' ($h.Up -and -not $p17902) "up17903=$($h.Up) up17902=$p17902"
Stop-App $h
# ---------- CFG-06:大屏鉴权开关 ----------
Write-Host "`n-- CFG-06 大屏访问控制 --" -ForegroundColor Cyan
$d5 = New-CaseDir 'screen-private'
Write-Conf $d5 @"
listen_ip = 127.0.0.1
listen_port = 17904
open_browser = false
screen_public = false
log_enabled = false
backup_enabled = false
"@
$h = Start-App $d5 @('-no-open') 17904
$anon = New-Client
$r = Get-Status $anon 'http://127.0.0.1:17904/screen'
Check 'CFG-06' 'screen_public=false 时大屏需登录' (($r.Path -like '/login*') -or ($r.Path -eq '/setup')) "path=$($r.Path)"
Stop-App $h
# ---------- CFG-08:备份目录与保留份数来自配置 ----------
Write-Host "`n-- CFG-08 备份目录与保留份数 --" -ForegroundColor Cyan
$d6 = New-CaseDir 'backup'
$bdir = Join-Path $d6 'my-backup'
Write-Conf $d6 @"
listen_ip = 127.0.0.1
listen_port = 17905
open_browser = false
log_enabled = false
backup_enabled = true
backup_dir = $bdir
backup_keep = 1
"@
$h = Start-App $d6 @('-no-open') 17905
$c6 = New-Client
Post-Form $c6 'http://127.0.0.1:17905/setup' @{ username = 'admin'; display_name = '老板'; password = 'daili123'; password2 = 'daili123' } | Out-Null
Post-Form $c6 'http://127.0.0.1:17905/packages' @{ name = '包月日常'; unit = 'day'; default_amount = '30'; color = '#2F5D50'; sort_order = '1' } | Out-Null
Post-Form $c6 'http://127.0.0.1:17905/customers' @{ tail = '3001'; name = '备份客户'; game_name = ''; game_server = ''; contact = ''; tags = ''; source = ''; note = '' } | Out-Null
Start-Sleep -Milliseconds 1200
Post-Form $c6 'http://127.0.0.1:17905/settings/backup' @{} | Out-Null
Start-Sleep -Milliseconds 1200
Post-Form $c6 'http://127.0.0.1:17905/settings/backup' @{} | Out-Null
$files = @(Get-ChildItem $bdir -Filter '*.db' -ErrorAction SilentlyContinue)
Check 'CFG-08a' '备份写入配置指定的目录' ($files.Count -ge 1) "dir=$bdir files=$($files.Count)"
Check 'CFG-08b' 'backup_keep=1 时只保留 1 份' ($files.Count -eq 1) "files=$($files.Count)"
Stop-App $h
# ---------- CFG-09:时区固定 ----------
Write-Host "`n-- CFG-09 时区固定 --" -ForegroundColor Cyan
$d7 = New-CaseDir 'timezone'
Write-Conf $d7 @"
listen_ip = 127.0.0.1
listen_port = 17906
open_browser = false
log_enabled = true
backup_enabled = false
timezone = Asia/Shanghai
"@
$h = Start-App $d7 @('-no-open') 17906
$errText = Get-Content (Join-Path $d7 'stderr.log') -Raw -Encoding UTF8
Check 'CFG-09' '时区固定为 Asia/Shanghai 生效' ($errText -match '时区已固定为 Asia/Shanghai') ""
Stop-App $h
# ---------- 汇总 ----------
$pass = @($script:results | Where-Object { $_ -like 'PASS|*' }).Count
$fail = @($script:results | Where-Object { $_ -like 'FAIL|*' }).Count
Write-Host "`n=== 汇总:通过 $pass 项,失败 $fail 项 ===" -ForegroundColor ($(if ($fail -eq 0) { 'Green' } else { 'Red' }))
New-Item -ItemType Directory -Force -Path $Evidence | Out-Null
$script:results | Set-Content (Join-Path $Evidence 'config-result.txt') -Encoding UTF8
Remove-Item -Recurse -Force $Work -ErrorAction SilentlyContinue
if ($fail -gt 0) { exit 1 }
exit 0