Skip to content

Commit 87d2c51

Browse files
committed
python runner
1 parent ecb7580 commit 87d2c51

File tree

2 files changed

+857
-0
lines changed

2 files changed

+857
-0
lines changed

.github/workflows/test262-py.yml

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
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: Upload engine binary + runner
58+
uses: actions/upload-artifact@v4
59+
with:
60+
name: engine-binary
61+
path: |
62+
target/release/${{ env.ENGINE_BIN_NAME }}
63+
run.py
64+
retention-days: 1
65+
66+
test262:
67+
name: test262
68+
needs: build-engine
69+
runs-on: ubuntu-latest
70+
# 不讓測試失敗阻擋整個 workflow,這樣能看到完整報告
71+
continue-on-error: true
72+
strategy:
73+
fail-fast: false
74+
matrix:
75+
# ── 按模組拆分並行跑,加速 CI ──
76+
suite:
77+
# language 拆成 4 個任務:2 個慢的 dstr 單獨跑,其餘分兩組
78+
- name: lang-expr-dstr
79+
pattern: "test/language/expressions/class/dstr/**/*.js"
80+
exclude: ""
81+
- name: lang-stmt-dstr
82+
pattern: "test/language/statements/class/dstr/**/*.js"
83+
exclude: ""
84+
- name: lang-expressions
85+
pattern: "test/language/expressions/**/*.js"
86+
exclude: "test/language/expressions/class/dstr/**/*.js"
87+
- name: lang-other
88+
pattern: "test/language/**/*.js"
89+
exclude: "test/language/expressions/**/*.js,test/language/statements/class/dstr/**/*.js"
90+
- name: built-ins-A-E
91+
pattern: "test/built-ins/[A-E]*/**/*.js"
92+
exclude: ""
93+
- name: built-ins-F-O
94+
pattern: "test/built-ins/[F-O]*/**/*.js"
95+
exclude: ""
96+
- name: built-ins-P-Z
97+
pattern: "test/built-ins/[P-Z]*/**/*.js"
98+
exclude: ""
99+
- name: annexB
100+
pattern: "test/annexB/**/*.js"
101+
exclude: ""
102+
103+
steps:
104+
- name: Download engine binary
105+
uses: actions/download-artifact@v4
106+
with:
107+
name: engine-binary
108+
path: ./engine
109+
110+
- name: Make engine executable
111+
run: chmod +x ./engine/${{ env.ENGINE_BIN_NAME }}
112+
113+
- name: Checkout test262
114+
uses: actions/checkout@v6
115+
with:
116+
repository: tc39/test262
117+
path: test262
118+
fetch-depth: 1
119+
120+
- name: Copy runner script
121+
run: cp ./engine/run.py test262/run.py
122+
123+
- name: Setup Python
124+
uses: actions/setup-python@v5
125+
with:
126+
python-version: '3.12'
127+
128+
- name: Install Python dependencies
129+
run: pip install pyyaml
130+
131+
- name: Run test262 — ${{ matrix.suite.name }}
132+
id: run-tests
133+
working-directory: test262
134+
env:
135+
# 你的引擎不支持的特性,在這裡跳過
136+
SKIP_FEATURES: >-
137+
Atomics,SharedArrayBuffer,
138+
IsHTMLDDA,
139+
resizable-arraybuffer,
140+
Temporal,
141+
import-defer,
142+
source-phase-imports,
143+
source-phase-imports-module-source,
144+
tail-call-optimization
145+
TEST_PATTERN: ${{ github.event.inputs.test_pattern || matrix.suite.pattern }}
146+
EXCLUDE_PATTERN: ${{ matrix.suite.exclude }}
147+
SKIP_OVERRIDE: ${{ github.event.inputs.skip_features }}
148+
run: |
149+
SKIP="${SKIP_OVERRIDE:-$SKIP_FEATURES}"
150+
EXCLUDE_ARG=""
151+
if [ -n "$EXCLUDE_PATTERN" ]; then
152+
EXCLUDE_ARG="--exclude $EXCLUDE_PATTERN"
153+
fi
154+
python3 run.py \
155+
--engine "${{ github.workspace }}/engine/${{ env.ENGINE_BIN_NAME }}" \
156+
--jobs 4 \
157+
--timeout 30 \
158+
--failures-only \
159+
--gh-annotations \
160+
--json results-${{ matrix.suite.name }}.json \
161+
--summary summary-${{ matrix.suite.name }}.md \
162+
--skip-features "$SKIP" \
163+
$EXCLUDE_ARG \
164+
"$TEST_PATTERN"
165+
# 即使測試失敗也繼續,這樣能上傳報告
166+
continue-on-error: true
167+
168+
- name: Write job summary
169+
if: always()
170+
working-directory: test262
171+
run: |
172+
if [ -f summary-${{ matrix.suite.name }}.md ]; then
173+
cat summary-${{ matrix.suite.name }}.md >> "$GITHUB_STEP_SUMMARY"
174+
fi
175+
176+
- name: Upload test results
177+
if: always()
178+
uses: actions/upload-artifact@v4
179+
with:
180+
name: test262-results-${{ matrix.suite.name }}
181+
path: |
182+
test262/results-*.json
183+
test262/summary-*.md
184+
retention-days: 30
185+
186+
# ── 匯總所有分片結果 ──
187+
report:
188+
name: Aggregate Results
189+
needs: test262
190+
if: always()
191+
runs-on: ubuntu-latest
192+
steps:
193+
- name: Download all results
194+
uses: actions/download-artifact@v4
195+
with:
196+
pattern: test262-results-*
197+
merge-multiple: true
198+
199+
- name: Aggregate and report
200+
run: |
201+
echo "## test262 Overall Results" >> "$GITHUB_STEP_SUMMARY"
202+
echo "" >> "$GITHUB_STEP_SUMMARY"
203+
204+
TOTAL_PASS=0
205+
TOTAL_FAIL=0
206+
TOTAL_SKIP=0
207+
TOTAL_TIMEOUT=0
208+
209+
for f in results-*.json; do
210+
if [ -f "$f" ]; then
211+
SUITE=$(basename "$f" .json | sed 's/results-//')
212+
PASS=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['pass'])")
213+
FAIL=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['fail'])")
214+
SKIP=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['skip'])")
215+
TMO=$(python3 -c "import json; d=json.load(open('$f')); print(d['summary']['timeout'])")
216+
TOTAL_PASS=$((TOTAL_PASS + PASS))
217+
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
218+
TOTAL_SKIP=$((TOTAL_SKIP + SKIP))
219+
TOTAL_TIMEOUT=$((TOTAL_TIMEOUT + TMO))
220+
echo " $SUITE: $PASS pass, $FAIL fail, $SKIP skip, $TMO timeout"
221+
fi
222+
done
223+
224+
TOTAL=$((TOTAL_PASS + TOTAL_FAIL + TOTAL_SKIP + TOTAL_TIMEOUT))
225+
TESTED=$((TOTAL - TOTAL_SKIP))
226+
if [ "$TESTED" -gt 0 ]; then
227+
RATE=$(python3 -c "print(f'{$TOTAL_PASS/$TESTED*100:.1f}')")
228+
else
229+
RATE="N/A"
230+
fi
231+
232+
echo "" >> "$GITHUB_STEP_SUMMARY"
233+
echo "| | Count |" >> "$GITHUB_STEP_SUMMARY"
234+
echo "|---|---|" >> "$GITHUB_STEP_SUMMARY"
235+
echo "| :white_check_mark: Pass | $TOTAL_PASS |" >> "$GITHUB_STEP_SUMMARY"
236+
echo "| :x: Fail | $TOTAL_FAIL |" >> "$GITHUB_STEP_SUMMARY"
237+
echo "| :fast_forward: Skip | $TOTAL_SKIP |" >> "$GITHUB_STEP_SUMMARY"
238+
echo "| :hourglass: Timeout | $TOTAL_TIMEOUT |" >> "$GITHUB_STEP_SUMMARY"
239+
echo "| **Total** | **$TOTAL** |" >> "$GITHUB_STEP_SUMMARY"
240+
echo "" >> "$GITHUB_STEP_SUMMARY"
241+
echo "**Overall pass rate: ${RATE}%**" >> "$GITHUB_STEP_SUMMARY"
242+
243+
echo ""
244+
echo "============================="
245+
echo " PASS: $TOTAL_PASS"
246+
echo " FAIL: $TOTAL_FAIL"
247+
echo " SKIP: $TOTAL_SKIP"
248+
echo " TIMEOUT: $TOTAL_TIMEOUT"
249+
echo " Pass rate: ${RATE}%"
250+
echo "============================="
251+
252+
# 如果有失敗,設定 exit code
253+
if [ "$TOTAL_FAIL" -gt 0 ]; then
254+
echo "::warning::$TOTAL_FAIL test(s) failed"
255+
fi

0 commit comments

Comments
 (0)