Skip to content

Commit d4a1ebe

Browse files
committed
python runner
1 parent ecb7580 commit d4a1ebe

File tree

2 files changed

+861
-0
lines changed

2 files changed

+861
-0
lines changed

.github/workflows/test262-py.yml

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
name: test262
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
# 允許手動觸發,可以選擇跑哪些測試
8+
workflow_dispatch:
9+
inputs:
10+
test_pattern:
11+
description: 'Glob pattern for tests to run'
12+
required: false
13+
default: 'test/built-ins/**/*.js test/language/**/*.js'
14+
skip_features:
15+
description: 'Comma-separated features to skip'
16+
required: false
17+
default: ''
18+
19+
# 同一 PR 只保留最新一次 CI
20+
concurrency:
21+
group: ${{ github.workflow }}-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
env:
25+
CARGO_TERM_COLOR: always
26+
# ↓↓↓ 修改這裡:你的引擎 cargo package 名稱 ↓↓↓
27+
ENGINE_BIN_NAME: js
28+
29+
jobs:
30+
build-engine:
31+
name: Build Engine
32+
runs-on: ubuntu-latest
33+
steps:
34+
- name: Checkout engine
35+
uses: actions/checkout@v6
36+
37+
- name: Setup Rust toolchain
38+
uses: dtolnay/rust-toolchain@stable
39+
with:
40+
components: rustfmt, clippy
41+
42+
- name: Cache cargo
43+
uses: actions/cache@v4
44+
with:
45+
path: |
46+
~/.cargo/bin/
47+
~/.cargo/registry/index/
48+
~/.cargo/registry/cache/
49+
~/.cargo/git/db/
50+
target/
51+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
52+
restore-keys: ${{ runner.os }}-cargo-
53+
54+
- name: Build engine (release)
55+
run: cargo build --release -p ${{ env.ENGINE_BIN_NAME }}
56+
57+
- name: Stage artifacts
58+
run: |
59+
mkdir -p staging
60+
cp target/release/${{ env.ENGINE_BIN_NAME }} staging/
61+
cp run.py staging/
62+
63+
- name: Upload engine binary + runner
64+
uses: actions/upload-artifact@v4
65+
with:
66+
name: engine-binary
67+
path: staging/
68+
retention-days: 1
69+
70+
test262:
71+
name: test262
72+
needs: build-engine
73+
runs-on: ubuntu-latest
74+
# 不讓測試失敗阻擋整個 workflow,這樣能看到完整報告
75+
continue-on-error: true
76+
strategy:
77+
fail-fast: false
78+
matrix:
79+
# ── 按模組拆分並行跑,加速 CI ──
80+
suite:
81+
# language 拆成 4 個任務:2 個慢的 dstr 單獨跑,其餘分兩組
82+
- name: lang-expr-dstr
83+
pattern: "test/language/expressions/class/dstr/**/*.js"
84+
exclude: ""
85+
- name: lang-stmt-dstr
86+
pattern: "test/language/statements/class/dstr/**/*.js"
87+
exclude: ""
88+
- name: lang-expressions
89+
pattern: "test/language/expressions/**/*.js"
90+
exclude: "test/language/expressions/class/dstr/**/*.js"
91+
- name: lang-other
92+
pattern: "test/language/**/*.js"
93+
exclude: "test/language/expressions/**/*.js,test/language/statements/class/dstr/**/*.js"
94+
- name: built-ins-A-E
95+
pattern: "test/built-ins/[A-E]*/**/*.js"
96+
exclude: ""
97+
- name: built-ins-F-O
98+
pattern: "test/built-ins/[F-O]*/**/*.js"
99+
exclude: ""
100+
- name: built-ins-P-Z
101+
pattern: "test/built-ins/[P-Z]*/**/*.js"
102+
exclude: ""
103+
- name: annexB
104+
pattern: "test/annexB/**/*.js"
105+
exclude: ""
106+
107+
steps:
108+
- name: Download engine binary
109+
uses: actions/download-artifact@v4
110+
with:
111+
name: engine-binary
112+
path: ./engine
113+
114+
- name: Make engine executable
115+
run: chmod +x ./engine/${{ env.ENGINE_BIN_NAME }}
116+
117+
- name: Checkout test262
118+
uses: actions/checkout@v6
119+
with:
120+
repository: tc39/test262
121+
path: test262
122+
fetch-depth: 1
123+
124+
- name: Copy runner script
125+
run: cp ./engine/run.py test262/run.py
126+
127+
- name: Setup Python
128+
uses: actions/setup-python@v5
129+
with:
130+
python-version: '3.12'
131+
132+
- name: Install Python dependencies
133+
run: pip install pyyaml
134+
135+
- name: Run test262 — ${{ matrix.suite.name }}
136+
id: run-tests
137+
working-directory: test262
138+
env:
139+
# 你的引擎不支持的特性,在這裡跳過
140+
SKIP_FEATURES: >-
141+
Atomics,SharedArrayBuffer,
142+
IsHTMLDDA,
143+
resizable-arraybuffer,
144+
Temporal,
145+
import-defer,
146+
source-phase-imports,
147+
source-phase-imports-module-source,
148+
tail-call-optimization
149+
TEST_PATTERN: ${{ github.event.inputs.test_pattern || matrix.suite.pattern }}
150+
EXCLUDE_PATTERN: ${{ matrix.suite.exclude }}
151+
SKIP_OVERRIDE: ${{ github.event.inputs.skip_features }}
152+
run: |
153+
SKIP="${SKIP_OVERRIDE:-$SKIP_FEATURES}"
154+
EXCLUDE_ARG=""
155+
if [ -n "$EXCLUDE_PATTERN" ]; then
156+
EXCLUDE_ARG="--exclude $EXCLUDE_PATTERN"
157+
fi
158+
python3 run.py \
159+
--engine "${{ github.workspace }}/engine/${{ env.ENGINE_BIN_NAME }}" \
160+
--jobs 4 \
161+
--timeout 30 \
162+
--failures-only \
163+
--gh-annotations \
164+
--json results-${{ matrix.suite.name }}.json \
165+
--summary summary-${{ matrix.suite.name }}.md \
166+
--skip-features "$SKIP" \
167+
$EXCLUDE_ARG \
168+
"$TEST_PATTERN"
169+
# 即使測試失敗也繼續,這樣能上傳報告
170+
continue-on-error: true
171+
172+
- name: Write job summary
173+
if: always()
174+
working-directory: test262
175+
run: |
176+
if [ -f summary-${{ matrix.suite.name }}.md ]; then
177+
cat summary-${{ matrix.suite.name }}.md >> "$GITHUB_STEP_SUMMARY"
178+
fi
179+
180+
- name: Upload test results
181+
if: always()
182+
uses: actions/upload-artifact@v4
183+
with:
184+
name: test262-results-${{ matrix.suite.name }}
185+
path: |
186+
test262/results-*.json
187+
test262/summary-*.md
188+
retention-days: 30
189+
190+
# ── 匯總所有分片結果 ──
191+
report:
192+
name: Aggregate Results
193+
needs: test262
194+
if: always()
195+
runs-on: ubuntu-latest
196+
steps:
197+
- name: Download all results
198+
uses: actions/download-artifact@v4
199+
with:
200+
pattern: test262-results-*
201+
merge-multiple: true
202+
203+
- name: Aggregate and report
204+
run: |
205+
echo "## test262 Overall Results" >> "$GITHUB_STEP_SUMMARY"
206+
echo "" >> "$GITHUB_STEP_SUMMARY"
207+
208+
TOTAL_PASS=0
209+
TOTAL_FAIL=0
210+
TOTAL_SKIP=0
211+
TOTAL_TIMEOUT=0
212+
213+
for f in results-*.json; do
214+
if [ -f "$f" ]; then
215+
SUITE=$(basename "$f" .json | sed 's/results-//')
216+
PASS=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['pass'])")
217+
FAIL=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['fail'])")
218+
SKIP=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['skip'])")
219+
TMO=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['timeout'])")
220+
TOTAL_PASS=$((TOTAL_PASS + PASS))
221+
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
222+
TOTAL_SKIP=$((TOTAL_SKIP + SKIP))
223+
TOTAL_TIMEOUT=$((TOTAL_TIMEOUT + TMO))
224+
echo " $SUITE: $PASS pass, $FAIL fail, $SKIP skip, $TMO timeout"
225+
fi
226+
done
227+
228+
TOTAL=$((TOTAL_PASS + TOTAL_FAIL + TOTAL_SKIP + TOTAL_TIMEOUT))
229+
TESTED=$((TOTAL - TOTAL_SKIP))
230+
if [ "$TESTED" -gt 0 ]; then
231+
RATE=$(python3 -c "print(f'{$TOTAL_PASS/$TESTED*100:.1f}')")
232+
else
233+
RATE="N/A"
234+
fi
235+
236+
echo "" >> "$GITHUB_STEP_SUMMARY"
237+
echo "| | Count |" >> "$GITHUB_STEP_SUMMARY"
238+
echo "|---|---|" >> "$GITHUB_STEP_SUMMARY"
239+
echo "| :white_check_mark: Pass | $TOTAL_PASS |" >> "$GITHUB_STEP_SUMMARY"
240+
echo "| :x: Fail | $TOTAL_FAIL |" >> "$GITHUB_STEP_SUMMARY"
241+
echo "| :fast_forward: Skip | $TOTAL_SKIP |" >> "$GITHUB_STEP_SUMMARY"
242+
echo "| :hourglass: Timeout | $TOTAL_TIMEOUT |" >> "$GITHUB_STEP_SUMMARY"
243+
echo "| **Total** | **$TOTAL** |" >> "$GITHUB_STEP_SUMMARY"
244+
echo "" >> "$GITHUB_STEP_SUMMARY"
245+
echo "**Overall pass rate: ${RATE}%**" >> "$GITHUB_STEP_SUMMARY"
246+
247+
echo ""
248+
echo "============================="
249+
echo " PASS: $TOTAL_PASS"
250+
echo " FAIL: $TOTAL_FAIL"
251+
echo " SKIP: $TOTAL_SKIP"
252+
echo " TIMEOUT: $TOTAL_TIMEOUT"
253+
echo " Pass rate: ${RATE}%"
254+
echo "============================="
255+
256+
# 如果有失敗,設定 exit code
257+
if [ "$TOTAL_FAIL" -gt 0 ]; then
258+
echo "::warning::$TOTAL_FAIL test(s) failed"
259+
fi

0 commit comments

Comments
 (0)