Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
#Requires -Version 5.1
|
||||
# Smoke test for the ast-grep skill on Windows (PowerShell 5.1+).
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$SkillDir = Split-Path -Parent $ScriptDir
|
||||
$Helper = Join-Path $SkillDir 'scripts/ast_grep_helper.py'
|
||||
$Python = if (Get-Command py -ErrorAction SilentlyContinue) { 'py' } else { 'python' }
|
||||
|
||||
$Output = Join-Path $env:TEMP ("ast-grep-skill-smoke-" + [guid]::NewGuid().ToString('N').Substring(0,8))
|
||||
New-Item -ItemType Directory -Path $Output -Force | Out-Null
|
||||
|
||||
function Pass([string]$msg) { Write-Host "PASS: $msg" }
|
||||
function Fail([string]$msg) { Write-Host "FAIL: $msg" -ForegroundColor Red; Remove-Item -Recurse -Force $Output -ErrorAction SilentlyContinue; exit 1 }
|
||||
|
||||
function Run([string[]]$Args) {
|
||||
$stdoutFile = Join-Path $Output ("out-" + [guid]::NewGuid().ToString('N').Substring(0,8) + ".txt")
|
||||
$proc = Start-Process -FilePath $Python -ArgumentList (@($Helper) + $Args) -NoNewWindow -PassThru -Wait -RedirectStandardOutput $stdoutFile -RedirectStandardError "$stdoutFile.err"
|
||||
$stdout = if (Test-Path $stdoutFile) { Get-Content $stdoutFile -Raw } else { '' }
|
||||
$stderr = if (Test-Path "$stdoutFile.err") { Get-Content "$stdoutFile.err" -Raw } else { '' }
|
||||
return [pscustomobject]@{
|
||||
ExitCode = $proc.ExitCode
|
||||
Stdout = $stdout
|
||||
Stderr = $stderr
|
||||
Combined = "$stdout`n$stderr"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
# 1. --version
|
||||
$r = Run @('--version')
|
||||
if ($r.Combined -notmatch 'ast-grep-helper') { Fail '--version output missing' }
|
||||
Pass '--version'
|
||||
|
||||
# 2. langs (must list >=25)
|
||||
$r = Run @('langs')
|
||||
$langCount = ($r.Stdout -split "`n" | Where-Object { $_ -match '^ [a-z]' }).Count
|
||||
if ($langCount -lt 25) { Fail "langs listed only $langCount (expected >=25)" }
|
||||
Pass 'langs lists at least 25 languages'
|
||||
|
||||
# 3. regex misuse: \w+
|
||||
$r = Run @('validate', '\w+', '--lang', 'ts')
|
||||
if ($r.ExitCode -ne 2) { Fail "validate '\w+' should exit 2, got $($r.ExitCode)" }
|
||||
if ($r.Combined -notmatch 'regex') { Fail "validate '\w+' should mention regex" }
|
||||
Pass 'validate detects \w regex misuse'
|
||||
|
||||
# 4. valid pattern
|
||||
$r = Run @('validate', 'console.log($MSG)', '--lang', 'ts')
|
||||
if ($r.ExitCode -ne 0) { Fail "validate 'console.log(`$MSG)' should exit 0, got $($r.ExitCode)" }
|
||||
Pass 'validate accepts plausible pattern'
|
||||
|
||||
# 5. Python trailing colon
|
||||
$r = Run @('validate', 'def $F($$$):', '--lang', 'py')
|
||||
if ($r.ExitCode -ne 2) { Fail "validate 'def `$F(`$`$`$):' should exit 2, got $($r.ExitCode)" }
|
||||
if ($r.Combined -notmatch 'colon|trailing') { Fail 'validate should mention trailing colon' }
|
||||
Pass 'validate detects Python trailing colon'
|
||||
|
||||
# 6. Incomplete TS function
|
||||
$r = Run @('validate', 'function $N', '--lang', 'ts')
|
||||
if ($r.ExitCode -ne 2) { Fail "validate 'function `$N' should exit 2, got $($r.ExitCode)" }
|
||||
if ($r.Combined -notmatch 'incomplete|params|body') { Fail 'validate should hint about params/body' }
|
||||
Pass 'validate detects incomplete TS function'
|
||||
|
||||
# 7. Alternation pipe
|
||||
$r = Run @('validate', 'foo|bar', '--lang', 'ts')
|
||||
if ($r.ExitCode -ne 2) { Fail "validate 'foo|bar' should exit 2, got $($r.ExitCode)" }
|
||||
if ($r.Combined -notmatch 'alternation|regex') { Fail 'validate should mention alternation' }
|
||||
Pass 'validate detects literal | alternation'
|
||||
|
||||
# 8. doctor
|
||||
$r = Run @('doctor')
|
||||
if ($r.Combined -notmatch 'ast-grep-helper') { Fail 'doctor missing helper version line' }
|
||||
Pass 'doctor produces output'
|
||||
|
||||
# 9. search w/o binary
|
||||
$r = Run @('-q', 'search', 'foo()', '--lang', 'ts', 'C:/nonexistent-path-xyzzy')
|
||||
switch ($r.ExitCode) {
|
||||
{ $_ -in 0,1,4 } { Pass "search runs (rc=$($r.ExitCode), ast-grep available)" }
|
||||
3 {
|
||||
if ($r.Combined -notmatch 'install') { Fail 'search rc=3 should print install hint' }
|
||||
Pass 'search without binary prints install hint'
|
||||
}
|
||||
default { Fail "search returned unexpected rc=$($r.ExitCode): $($r.Combined)" }
|
||||
}
|
||||
|
||||
# 10. install.ps1 syntax (parse-check via PowerShell tokenizer)
|
||||
$tokens = $null
|
||||
$errors = $null
|
||||
[System.Management.Automation.Language.Parser]::ParseFile(
|
||||
(Join-Path $SkillDir 'install.ps1'), [ref]$tokens, [ref]$errors) | Out-Null
|
||||
if ($errors -and $errors.Count -gt 0) { Fail "install.ps1 has parse errors: $($errors -join '; ')" }
|
||||
Pass 'install.ps1 parses cleanly'
|
||||
|
||||
# 11. SKILL.md frontmatter
|
||||
$skill = Get-Content (Join-Path $SkillDir 'SKILL.md') -Raw
|
||||
if (-not $skill.StartsWith("---`n") -and -not $skill.StartsWith("---`r`n")) {
|
||||
Fail 'SKILL.md must start with YAML frontmatter'
|
||||
}
|
||||
$endIdx = $skill.IndexOf("`n---`n", 4)
|
||||
if ($endIdx -lt 0) { $endIdx = $skill.IndexOf("`r`n---`r`n", 4) }
|
||||
if ($endIdx -lt 0) { Fail 'SKILL.md missing closing ---' }
|
||||
$fm = $skill.Substring(4, $endIdx - 4)
|
||||
if ($fm -notmatch '(?m)^name:\s*ast-grep\s*$') { Fail 'frontmatter missing name: ast-grep' }
|
||||
if ($fm -notmatch '(?m)^description:') { Fail 'frontmatter missing description' }
|
||||
Pass 'SKILL.md frontmatter shape'
|
||||
|
||||
# 12. All required reference files exist
|
||||
$required = @(
|
||||
'references/install.md', 'references/patterns.md', 'references/pitfalls.md',
|
||||
'references/recipes.md', 'references/cli.md', 'references/yaml-rules.md',
|
||||
'references/sgconfig.md'
|
||||
)
|
||||
foreach ($f in $required) {
|
||||
if (-not (Test-Path (Join-Path $SkillDir $f))) { Fail "missing $f" }
|
||||
}
|
||||
Pass 'all references present'
|
||||
|
||||
Write-Host ''
|
||||
Write-Host 'all smoke tests passed'
|
||||
}
|
||||
finally {
|
||||
Remove-Item -Recurse -Force $Output -ErrorAction SilentlyContinue
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke test for the ast-grep skill on POSIX (macOS / Linux / WSL / Git Bash).
|
||||
#
|
||||
# Tests:
|
||||
# 1. helper --version
|
||||
# 2. helper langs (lists 25 languages)
|
||||
# 3. helper validate '\w+' --lang ts (must exit 2 with hint)
|
||||
# 4. helper validate 'console.log($MSG)' (must exit 0 plausible)
|
||||
# 5. helper validate 'def $F($$$):' --lang py (must exit 2 - trailing colon)
|
||||
# 6. helper validate 'function $N' --lang ts (must exit 2 - incomplete)
|
||||
# 7. helper validate 'foo|bar' --lang ts (must exit 2 - alternation)
|
||||
# 8. helper doctor (informational; tolerates no-binary)
|
||||
# 9. helper search w/o binary => exit 3 with install hint
|
||||
# 10. install.sh --help (parses)
|
||||
# 11. SKILL.md frontmatter shape (canonical)
|
||||
#
|
||||
# Runs against the helper using ONLY stdlib python3 - no ast-grep needed.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
SKILL_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
HELPER="python3 $SKILL_DIR/scripts/ast_grep_helper.py"
|
||||
|
||||
OUTPUT_DIR="$(mktemp -d -t ast-grep-skill-smoke-XXXXXX)"
|
||||
trap 'rm -rf "$OUTPUT_DIR"' EXIT
|
||||
|
||||
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||
pass() { echo "PASS: $*"; }
|
||||
|
||||
omo_runtime_slug() {
|
||||
case "$(uname -s)" in
|
||||
Darwin) local os_slug="darwin" ;;
|
||||
MINGW*|MSYS*|CYGWIN*) local os_slug="win32" ;;
|
||||
*) local os_slug="linux" ;;
|
||||
esac
|
||||
|
||||
case "$(uname -m | tr '[:upper:]' '[:lower:]')" in
|
||||
arm64|aarch64) local arch_slug="arm64" ;;
|
||||
*) local arch_slug="x64" ;;
|
||||
esac
|
||||
|
||||
printf '%s-%s' "$os_slug" "$arch_slug"
|
||||
}
|
||||
|
||||
fake_sg() {
|
||||
local target="$1"
|
||||
mkdir -p "$(dirname "$target")"
|
||||
cat > "$target" <<'SH'
|
||||
#!/usr/bin/env bash
|
||||
if [ "${1:-}" = "--version" ]; then
|
||||
printf 'ast-grep 0.45.0 fake\n'
|
||||
else
|
||||
printf 'fake ast-grep\n'
|
||||
fi
|
||||
SH
|
||||
chmod +x "$target"
|
||||
}
|
||||
|
||||
# 1. --version
|
||||
$HELPER --version | grep -q "ast-grep-helper" || fail "--version output missing"
|
||||
pass "--version"
|
||||
|
||||
# 2. langs (must list 25)
|
||||
LANG_LINES=$($HELPER langs | grep -E '^ [a-z]' | wc -l | tr -d ' ')
|
||||
[ "$LANG_LINES" -ge 25 ] || fail "langs listed only $LANG_LINES (expected >=25)"
|
||||
pass "langs lists at least 25 languages"
|
||||
|
||||
# 3. regex misuse: \w+
|
||||
set +e
|
||||
$HELPER validate '\w+' --lang ts > "$OUTPUT_DIR/v1.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
[ $RC -eq 2 ] || fail "validate '\\w+' should exit 2, got $RC (output: $(cat $OUTPUT_DIR/v1.out))"
|
||||
grep -qi 'regex' "$OUTPUT_DIR/v1.out" || fail "validate '\\w+' should mention regex (output: $(cat $OUTPUT_DIR/v1.out))"
|
||||
pass "validate detects \\w regex misuse"
|
||||
|
||||
# 4. valid pattern
|
||||
set +e
|
||||
$HELPER validate 'console.log($MSG)' --lang ts > "$OUTPUT_DIR/v2.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
[ $RC -eq 0 ] || fail "validate 'console.log(\$MSG)' should exit 0, got $RC (output: $(cat $OUTPUT_DIR/v2.out))"
|
||||
pass "validate accepts plausible pattern"
|
||||
|
||||
# 5. Python trailing colon
|
||||
set +e
|
||||
$HELPER validate 'def $F($$$):' --lang py > "$OUTPUT_DIR/v3.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
[ $RC -eq 2 ] || fail "validate 'def \$F(\$\$\$):' should exit 2, got $RC"
|
||||
grep -qi 'colon\|trailing' "$OUTPUT_DIR/v3.out" || fail "validate should mention trailing colon"
|
||||
pass "validate detects Python trailing colon"
|
||||
|
||||
# 6. Incomplete TS function
|
||||
set +e
|
||||
$HELPER validate 'function $N' --lang ts > "$OUTPUT_DIR/v4.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
[ $RC -eq 2 ] || fail "validate 'function \$N' should exit 2, got $RC"
|
||||
grep -qi 'incomplete\|params\|body' "$OUTPUT_DIR/v4.out" || fail "validate should hint about params/body"
|
||||
pass "validate detects incomplete TS function"
|
||||
|
||||
# 7. Alternation pipe
|
||||
set +e
|
||||
$HELPER validate 'foo|bar' --lang ts > "$OUTPUT_DIR/v5.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
[ $RC -eq 2 ] || fail "validate 'foo|bar' should exit 2, got $RC"
|
||||
grep -qi 'alternation\|regex' "$OUTPUT_DIR/v5.out" || fail "validate should mention alternation"
|
||||
pass "validate detects literal | alternation"
|
||||
|
||||
# 8. doctor (informational)
|
||||
$HELPER doctor > "$OUTPUT_DIR/doc.out" 2>&1 || true
|
||||
grep -q "ast-grep-helper" "$OUTPUT_DIR/doc.out" || fail "doctor missing helper version line"
|
||||
pass "doctor produces output"
|
||||
|
||||
# Given OMO_AST_GREP_SG_PATH points at a fake executable.
|
||||
# When doctor resolves ast-grep, then it reports that exact path.
|
||||
FAKE_ENV_SG="$OUTPUT_DIR/fake-env/sg"
|
||||
fake_sg "$FAKE_ENV_SG"
|
||||
OMO_AST_GREP_SG_PATH="$FAKE_ENV_SG" $HELPER doctor > "$OUTPUT_DIR/omo-env.out" 2>&1
|
||||
grep -Fq "ast-grep binary: $FAKE_ENV_SG" "$OUTPUT_DIR/omo-env.out" || fail "OMO_AST_GREP_SG_PATH was not preferred: $(cat "$OUTPUT_DIR/omo-env.out")"
|
||||
pass "OMO_AST_GREP_SG_PATH resolves first"
|
||||
|
||||
# Given HOME has an OMO runtime sg executable.
|
||||
# When doctor resolves ast-grep, then it reports the HOME runtime path.
|
||||
RUNTIME_HOME="$OUTPUT_DIR/home"
|
||||
RUNTIME_SLUG="$(omo_runtime_slug)"
|
||||
RUNTIME_BIN="sg"
|
||||
case "$RUNTIME_SLUG" in
|
||||
win32-*) RUNTIME_BIN="sg.exe" ;;
|
||||
esac
|
||||
FAKE_RUNTIME_SG="$RUNTIME_HOME/.omo/runtime/ast-grep/$RUNTIME_SLUG/$RUNTIME_BIN"
|
||||
fake_sg "$FAKE_RUNTIME_SG"
|
||||
HOME="$RUNTIME_HOME" CODEX_HOME= OMO_AST_GREP_SG_PATH= $HELPER doctor > "$OUTPUT_DIR/omo-runtime.out" 2>&1
|
||||
grep -Fq "ast-grep binary: $FAKE_RUNTIME_SG" "$OUTPUT_DIR/omo-runtime.out" || fail "OMO HOME runtime was not resolved: $(cat "$OUTPUT_DIR/omo-runtime.out")"
|
||||
pass "OMO HOME runtime resolves before standalone fallback"
|
||||
|
||||
# 9. search w/o binary => either runs successfully (binary found) OR exits 3 with hint
|
||||
# The CI may or may not have ast-grep installed; both are valid.
|
||||
set +e
|
||||
$HELPER -q search 'foo()' --lang ts /nonexistent-path-xyzzy > "$OUTPUT_DIR/s1.out" 2>&1
|
||||
RC=$?
|
||||
set -e
|
||||
case "$RC" in
|
||||
0|1|4)
|
||||
# Binary present but no matches OR sg returned non-fatal error - both fine
|
||||
pass "search runs (rc=$RC, ast-grep available)"
|
||||
;;
|
||||
3)
|
||||
grep -qi 'install' "$OUTPUT_DIR/s1.out" || fail "search rc=3 should print install hint"
|
||||
pass "search without binary prints install hint"
|
||||
;;
|
||||
*)
|
||||
fail "search returned unexpected rc=$RC: $(cat $OUTPUT_DIR/s1.out)"
|
||||
;;
|
||||
esac
|
||||
|
||||
# 10. install.sh syntax check + --help
|
||||
bash -n "$SKILL_DIR/install.sh" || fail "install.sh has syntax errors"
|
||||
$SKILL_DIR/install.sh --help > "$OUTPUT_DIR/inst.out" 2>&1 || true
|
||||
grep -qi 'install' "$OUTPUT_DIR/inst.out" || fail "install.sh --help missing keyword 'install'"
|
||||
pass "install.sh syntax + --help"
|
||||
|
||||
# 11. SKILL.md frontmatter
|
||||
python3 - <<PY
|
||||
import re, sys
|
||||
src = open("$SKILL_DIR/SKILL.md").read()
|
||||
assert src.startswith("---\n"), "SKILL.md must start with YAML frontmatter"
|
||||
end = src.find("\n---\n", 4)
|
||||
assert end > 0, "SKILL.md missing closing ---"
|
||||
fm = src[4:end]
|
||||
assert re.search(r"^name:\s*ast-grep\s*$", fm, re.M), "frontmatter missing name: ast-grep"
|
||||
assert re.search(r"^description:", fm, re.M), "frontmatter missing description"
|
||||
PY
|
||||
pass "SKILL.md frontmatter shape"
|
||||
|
||||
# 12. All required reference files exist
|
||||
for f in references/install.md references/patterns.md references/pitfalls.md \
|
||||
references/recipes.md references/cli.md references/yaml-rules.md \
|
||||
references/sgconfig.md; do
|
||||
test -f "$SKILL_DIR/$f" || fail "missing $f"
|
||||
done
|
||||
pass "all references present"
|
||||
|
||||
python3 - "$SKILL_DIR" <<'PY' || fail "Korean characters found in skill content"
|
||||
import pathlib, re, sys
|
||||
root = pathlib.Path(sys.argv[1])
|
||||
hangul = re.compile(r"[\uac00-\ud7a3]")
|
||||
targets = [root / "SKILL.md", root / "README.md"]
|
||||
for d in ("references", "scripts", "tests", ".github"):
|
||||
targets.extend((root / d).rglob("*"))
|
||||
targets.extend([root / "install.sh", root / "install.ps1"])
|
||||
hits = 0
|
||||
for p in targets:
|
||||
if not p.is_file():
|
||||
continue
|
||||
try:
|
||||
text = p.read_text(encoding="utf-8")
|
||||
except (UnicodeDecodeError, OSError):
|
||||
continue
|
||||
for n, line in enumerate(text.splitlines(), 1):
|
||||
if hangul.search(line):
|
||||
print(f"{p}:{n}: {line.rstrip()}")
|
||||
hits += 1
|
||||
sys.exit(1 if hits else 0)
|
||||
PY
|
||||
pass "no Korean in skill content"
|
||||
|
||||
echo ""
|
||||
echo "all smoke tests passed"
|
||||
Reference in New Issue
Block a user