CI / routing tests (ubuntu-latest) (push) Canceled after 0s
CI / routing tests (windows-latest) (push) Canceled after 0s
CI / shell script syntax check (push) Canceled after 0s
CI / field-journal leak scan (push) Canceled after 0s
CI / case contract test (ctf-demo) (push) Canceled after 0s
CI / version consistency (push) Canceled after 0s
134 lines
5.0 KiB
PowerShell
134 lines
5.0 KiB
PowerShell
#Requires -Version 5.1
|
|
param(
|
|
[string]$ScratchDir = ''
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$scriptDir = $PSScriptRoot
|
|
if ([string]::IsNullOrWhiteSpace($ScratchDir)) {
|
|
$ScratchDir = Join-Path ([System.IO.Path]::GetTempPath()) ('reverse-skill-codex-encoding-' + [guid]::NewGuid().ToString('N'))
|
|
}
|
|
New-Item -ItemType Directory -Path $ScratchDir -Force | Out-Null
|
|
|
|
. (Join-Path $scriptDir 'lib\ToolDiscovery.ps1')
|
|
|
|
# Load only the functions under test; do not execute bootstrap installation code.
|
|
$bootstrapPath = Join-Path $scriptDir 'bootstrap-reverse.ps1'
|
|
$tokens = $null
|
|
$errors = $null
|
|
$ast = [System.Management.Automation.Language.Parser]::ParseFile($bootstrapPath, [ref]$tokens, [ref]$errors)
|
|
if ($errors.Count -gt 0) {
|
|
throw "bootstrap-reverse.ps1 parse failed: $($errors[0].Message)"
|
|
}
|
|
foreach ($name in @('ConvertTo-TomlLiteral', 'Remove-CodexMcpServerBlocks', 'Set-CodexMcpServer')) {
|
|
$functionAst = $ast.Find({
|
|
param($node)
|
|
$node -is [System.Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -eq $name
|
|
}, $true)
|
|
if ($null -eq $functionAst) {
|
|
throw "Function not found: $name"
|
|
}
|
|
Invoke-Expression $functionAst.Extent.Text
|
|
}
|
|
|
|
function Assert-True {
|
|
param([bool]$Condition, [string]$Message)
|
|
if (-not $Condition) {
|
|
throw "ASSERTION FAILED: $Message"
|
|
}
|
|
Write-Host "[OK] $Message" -ForegroundColor Green
|
|
}
|
|
|
|
function Test-CodexConfigRoundTrip {
|
|
param(
|
|
[string]$Name,
|
|
[bool]$WithBom,
|
|
[string]$Newline
|
|
)
|
|
|
|
$path = Join-Path $ScratchDir "$Name.toml"
|
|
$original = @(
|
|
"[projects.'e:\codex目录\blender脚本管理器']",
|
|
'trust_level = "trusted"',
|
|
'',
|
|
'[mcp_servers.existing]',
|
|
'command = "existing"'
|
|
) -join $Newline
|
|
$original += $Newline
|
|
[System.IO.File]::WriteAllText($path, $original, [System.Text.UTF8Encoding]::new($WithBom))
|
|
|
|
$oldConfigPath = $env:CODEX_CONFIG_PATH
|
|
try {
|
|
$env:CODEX_CONFIG_PATH = $path
|
|
Set-CodexMcpServer -ServerName 'encoding-test' -ServerDefinition @{
|
|
type = 'stdio'
|
|
command = 'cmd'
|
|
args = @('/c', 'echo', '中文参数')
|
|
}
|
|
Set-CodexMcpServer -ServerName 'encoding-test' -ServerDefinition @{
|
|
type = 'stdio'
|
|
command = 'cmd'
|
|
args = @('/c', 'echo', '中文参数')
|
|
}
|
|
}
|
|
finally {
|
|
$env:CODEX_CONFIG_PATH = $oldConfigPath
|
|
}
|
|
|
|
$bytes = [System.IO.File]::ReadAllBytes($path)
|
|
$hasBom = $bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF
|
|
Assert-True ($hasBom -eq $WithBom) "$Name preserves UTF-8 BOM state"
|
|
|
|
$text = [System.Text.Encoding]::UTF8.GetString($bytes)
|
|
if ($text.Length -gt 0 -and $text[0] -eq [char]0xFEFF) {
|
|
$text = $text.Substring(1)
|
|
}
|
|
Assert-True ($text.Contains("[projects.'e:\codex目录\blender脚本管理器']")) "$Name preserves Chinese TOML path and closing quote"
|
|
Assert-True ($text.Contains('[mcp_servers.encoding-test]')) "$Name adds MCP server"
|
|
Assert-True (([regex]::Matches($text, '(?m)^\[mcp_servers\.encoding-test\]\r?$')).Count -eq 1) "$Name updates MCP server idempotently"
|
|
Assert-True ($text.Contains('中文参数')) "$Name preserves new Chinese values"
|
|
if ($Newline -eq "`r`n") {
|
|
Assert-True (-not ($text -replace "`r`n", '').Contains("`n")) "$Name preserves CRLF newlines"
|
|
}
|
|
}
|
|
|
|
Test-CodexConfigRoundTrip -Name 'utf8-no-bom-crlf' -WithBom $false -Newline "`r`n"
|
|
Test-CodexConfigRoundTrip -Name 'utf8-bom-lf' -WithBom $true -Newline "`n"
|
|
|
|
$newPath = Join-Path $ScratchDir 'new-config.toml'
|
|
$oldConfigPath = $env:CODEX_CONFIG_PATH
|
|
try {
|
|
$env:CODEX_CONFIG_PATH = $newPath
|
|
Set-CodexMcpServer -ServerName 'new-config-test' -ServerDefinition @{ command = '中文命令' }
|
|
}
|
|
finally {
|
|
$env:CODEX_CONFIG_PATH = $oldConfigPath
|
|
}
|
|
$newBytes = [System.IO.File]::ReadAllBytes($newPath)
|
|
$newHasBom = $newBytes.Length -ge 3 -and $newBytes[0] -eq 0xEF -and $newBytes[1] -eq 0xBB -and $newBytes[2] -eq 0xBF
|
|
Assert-True (-not $newHasBom) 'new config uses UTF-8 without BOM'
|
|
$newText = [System.Text.Encoding]::UTF8.GetString($newBytes)
|
|
Assert-True ($newText.Contains('[mcp_servers.new-config-test]')) 'new config contains MCP server block'
|
|
Assert-True ($newText.Contains('中文命令')) 'new config preserves Chinese values'
|
|
|
|
$invalidPath = Join-Path $ScratchDir 'invalid-utf8.toml'
|
|
[System.IO.File]::WriteAllBytes($invalidPath, [byte[]](0x5B, 0x80, 0x5D))
|
|
$oldConfigPath = $env:CODEX_CONFIG_PATH
|
|
$threw = $false
|
|
try {
|
|
$env:CODEX_CONFIG_PATH = $invalidPath
|
|
Set-CodexMcpServer -ServerName 'must-not-write' -ServerDefinition @{ command = 'x' }
|
|
}
|
|
catch [System.Text.DecoderFallbackException] {
|
|
$threw = $true
|
|
}
|
|
finally {
|
|
$env:CODEX_CONFIG_PATH = $oldConfigPath
|
|
}
|
|
Assert-True $threw 'invalid UTF-8 fails closed instead of rewriting the file'
|
|
$invalidBytes = [System.IO.File]::ReadAllBytes($invalidPath)
|
|
Assert-True ($invalidBytes.Length -eq 3 -and $invalidBytes[1] -eq 0x80) 'invalid UTF-8 file remains unchanged'
|
|
|
|
Write-Host 'OVERALL: ALL PASS' -ForegroundColor Green
|
|
|