smalltalk: ANSI X3J20 validator subset + 62 tests -> 813/813
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"date": "2026-04-25T14:10:14Z",
|
||||
"date": "2026-04-25T14:44:32Z",
|
||||
"programs": [
|
||||
"eight-queens.st",
|
||||
"fibonacci.st",
|
||||
@@ -9,7 +9,7 @@
|
||||
],
|
||||
"program_count": 5,
|
||||
"program_tests_passed": 39,
|
||||
"all_tests_passed": 751,
|
||||
"all_tests_total": 751,
|
||||
"all_tests_passed": 813,
|
||||
"all_tests_total": 813,
|
||||
"exit_code": 0
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Smalltalk-on-SX Scoreboard
|
||||
|
||||
_Last run: 2026-04-25T14:10:14Z_
|
||||
_Last run: 2026-04-25T14:44:32Z_
|
||||
|
||||
## Totals
|
||||
|
||||
| Suite | Passing |
|
||||
|-------|---------|
|
||||
| All Smalltalk-on-SX tests | **751 / 751** |
|
||||
| All Smalltalk-on-SX tests | **813 / 813** |
|
||||
| Classic-corpus tests (`tests/programs.sx`) | **39** |
|
||||
|
||||
## Classic-corpus programs (`lib/smalltalk/tests/programs/`)
|
||||
@@ -22,6 +22,7 @@ _Last run: 2026-04-25T14:10:14Z_
|
||||
## Per-file test counts
|
||||
|
||||
```
|
||||
OK lib/smalltalk/tests/ansi.sx 62 passed
|
||||
OK lib/smalltalk/tests/blocks.sx 19 passed
|
||||
OK lib/smalltalk/tests/cannot_return.sx 5 passed
|
||||
OK lib/smalltalk/tests/collections.sx 29 passed
|
||||
|
||||
158
lib/smalltalk/tests/ansi.sx
Normal file
158
lib/smalltalk/tests/ansi.sx
Normal file
@@ -0,0 +1,158 @@
|
||||
;; ANSI X3J20 Smalltalk validator — stretch subset.
|
||||
;;
|
||||
;; Targets the mandatory protocols documented in the standard; one test
|
||||
;; case per ANSI §6.x category. Test methods are run through the SUnit
|
||||
;; framework; one st-test row per Smalltalk method (mirrors tests/pharo.sx).
|
||||
|
||||
(set! st-test-pass 0)
|
||||
(set! st-test-fail 0)
|
||||
(set! st-test-fails (list))
|
||||
|
||||
(define
|
||||
ansi-source
|
||||
"TestCase subclass: #AnsiObjectTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiObjectTest methodsFor: '6.10 Object'!
|
||||
testIdentity self assert: 42 == 42!
|
||||
testIdentityNotEq self deny: 'a' == 'b'!
|
||||
testEqualityIsAlsoIdentityOnInts self assert: 7 = 7!
|
||||
testNotEqual self assert: (1 ~= 2)!
|
||||
testIsNilOnNil self assert: nil isNil!
|
||||
testIsNilOnInt self deny: 1 isNil!
|
||||
testNotNil self assert: 42 notNil!
|
||||
testClass self assert: 42 class = SmallInteger!
|
||||
testYourself
|
||||
| x | x := 99.
|
||||
self assert: x yourself equals: 99! !
|
||||
|
||||
TestCase subclass: #AnsiBooleanTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiBooleanTest methodsFor: '6.11 Boolean'!
|
||||
testNot self assert: true not equals: false!
|
||||
testAndTT self assert: (true & true)!
|
||||
testAndTF self deny: (true & false)!
|
||||
testAndFT self deny: (false & true)!
|
||||
testAndFF self deny: (false & false)!
|
||||
testOrTT self assert: (true | true)!
|
||||
testOrTF self assert: (true | false)!
|
||||
testOrFT self assert: (false | true)!
|
||||
testOrFF self deny: (false | false)!
|
||||
testIfTrueTaken self assert: (true ifTrue: [1] ifFalse: [2]) equals: 1!
|
||||
testIfFalseTaken self assert: (false ifTrue: [1] ifFalse: [2]) equals: 2!
|
||||
testAndShort self assert: (false and: [1/0]) equals: false!
|
||||
testOrShort self assert: (true or: [1/0]) equals: true! !
|
||||
|
||||
TestCase subclass: #AnsiIntegerTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiIntegerTest methodsFor: '6.13 Integer'!
|
||||
testFactorial self assert: 6 factorial equals: 720!
|
||||
testGcd self assert: (12 gcd: 18) equals: 6!
|
||||
testLcm self assert: (4 lcm: 6) equals: 12!
|
||||
testEven self assert: 8 even!
|
||||
testOdd self assert: 9 odd!
|
||||
testNegated self assert: 5 negated equals: -5!
|
||||
testAbs self assert: -7 abs equals: 7! !
|
||||
|
||||
!AnsiIntegerTest methodsFor: '6.12 Number arithmetic'!
|
||||
testAdd self assert: 1 + 2 equals: 3!
|
||||
testSub self assert: 10 - 4 equals: 6!
|
||||
testMul self assert: 6 * 7 equals: 42!
|
||||
testMin self assert: (3 min: 7) equals: 3!
|
||||
testMax self assert: (3 max: 7) equals: 7!
|
||||
testBetween self assert: (5 between: 1 and: 10)! !
|
||||
|
||||
TestCase subclass: #AnsiStringTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiStringTest methodsFor: '6.17 String'!
|
||||
testSize self assert: 'abcdef' size equals: 6!
|
||||
testConcat self assert: ('foo' , 'bar') equals: 'foobar'!
|
||||
testAt self assert: ('abcd' at: 3) equals: 'c'!
|
||||
testCopyFromTo self assert: ('helloworld' copyFrom: 1 to: 5) equals: 'hello'!
|
||||
testAsSymbol self assert: 'foo' asSymbol == #foo!
|
||||
testIsEmpty self assert: '' isEmpty! !
|
||||
|
||||
TestCase subclass: #AnsiArrayTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiArrayTest methodsFor: '6.18 Array'!
|
||||
testSize self assert: #(1 2 3) size equals: 3!
|
||||
testAt self assert: (#(10 20 30) at: 2) equals: 20!
|
||||
testAtPut
|
||||
| a |
|
||||
a := Array new: 3.
|
||||
a at: 1 put: 100.
|
||||
self assert: (a at: 1) equals: 100!
|
||||
testDo
|
||||
| s |
|
||||
s := 0.
|
||||
#(1 2 3) do: [:e | s := s + e].
|
||||
self assert: s equals: 6!
|
||||
testCollect self assert: (#(1 2 3) collect: [:x | x + 10]) equals: #(11 12 13)!
|
||||
testSelect self assert: (#(1 2 3 4) select: [:x | x even]) equals: #(2 4)!
|
||||
testReject self assert: (#(1 2 3 4) reject: [:x | x even]) equals: #(1 3)!
|
||||
testInject self assert: (#(1 2 3 4 5) inject: 0 into: [:a :b | a + b]) equals: 15!
|
||||
testIncludes self assert: (#(1 2 3) includes: 2)!
|
||||
testFirst self assert: #(7 8 9) first equals: 7!
|
||||
testLast self assert: #(7 8 9) last equals: 9! !
|
||||
|
||||
TestCase subclass: #AnsiBlockTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiBlockTest methodsFor: '6.19 BlockContext'!
|
||||
testValue self assert: [42] value equals: 42!
|
||||
testValueOne self assert: ([:x | x * 2] value: 21) equals: 42!
|
||||
testValueTwo self assert: ([:a :b | a + b] value: 3 value: 4) equals: 7!
|
||||
testNumArgs self assert: [:a :b | a] numArgs equals: 2!
|
||||
testValueWithArguments
|
||||
self assert: ([:a :b | a , b] valueWithArguments: #('foo' 'bar')) equals: 'foobar'!
|
||||
testWhileTrue
|
||||
| n |
|
||||
n := 5.
|
||||
[n > 0] whileTrue: [n := n - 1].
|
||||
self assert: n equals: 0!
|
||||
testEnsureRunsOnNormal
|
||||
| log |
|
||||
log := Array new: 0.
|
||||
[log add: #body] ensure: [log add: #cleanup].
|
||||
self assert: log size equals: 2!
|
||||
testOnDoCatchesError
|
||||
| r |
|
||||
r := [Error signal: 'boom'] on: Error do: [:e | e messageText].
|
||||
self assert: r equals: 'boom'! !
|
||||
|
||||
TestCase subclass: #AnsiSymbolTest instanceVariableNames: ''!
|
||||
|
||||
!AnsiSymbolTest methodsFor: '6.16 Symbol'!
|
||||
testEqual self assert: #foo = #foo!
|
||||
testIdentity self assert: #bar == #bar!
|
||||
testNotEq self deny: #a == #b! !")
|
||||
|
||||
(smalltalk-load ansi-source)
|
||||
|
||||
(define
|
||||
pharo-test-class
|
||||
(fn
|
||||
(cls-name)
|
||||
(let ((selectors (sort (keys (get (st-class-get cls-name) :methods)))))
|
||||
(for-each
|
||||
(fn (sel)
|
||||
(when
|
||||
(and (>= (len sel) 4) (= (slice sel 0 4) "test"))
|
||||
(let
|
||||
((src (str "| s r | s := " cls-name " suiteForAll: #(#"
|
||||
sel "). r := s run.
|
||||
^ {(r passCount). (r failureCount). (r errorCount)}")))
|
||||
(let ((result (smalltalk-eval-program src)))
|
||||
(st-test
|
||||
(str cls-name " >> " sel)
|
||||
result
|
||||
(list 1 0 0))))))
|
||||
selectors))))
|
||||
|
||||
(pharo-test-class "AnsiObjectTest")
|
||||
(pharo-test-class "AnsiBooleanTest")
|
||||
(pharo-test-class "AnsiIntegerTest")
|
||||
(pharo-test-class "AnsiStringTest")
|
||||
(pharo-test-class "AnsiArrayTest")
|
||||
(pharo-test-class "AnsiBlockTest")
|
||||
(pharo-test-class "AnsiSymbolTest")
|
||||
|
||||
(list st-test-pass st-test-fail)
|
||||
@@ -97,7 +97,7 @@ Core mapping:
|
||||
- [x] Port SUnit (`lib/smalltalk/sunit.sx`). Written in Smalltalk source via `smalltalk-load`. Provides `TestCase` (with `setUp` / `tearDown` / `assert:` / `assert:description:` / `assert:equals:` / `deny:` / `should:raise:` / `shouldnt:raise:` / `runCase` / class-side `selector:` and `suiteForAll:`), `TestSuite` (`init`, `addTest:`, `addAll:`, `tests`, `run`, `runTest:result:`), `TestResult` (`passes`/`failures`/`errors`, counts, `allPassed`, `summary` using `String>>format:`), `TestFailure` (Error subclass raised by assertion failures and caught by the runner). 19 tests in `lib/smalltalk/tests/sunit.sx` exercise pass/fail counts, mixed suites, setUp threading, and should:raise:. test.sh now loads `lib/smalltalk/sunit.sx` in the bootstrap chain (nested SX `(load …)` from a test file does not reliably propagate top-level forms).
|
||||
- [x] Vendor a slice of Pharo `Kernel-Tests` and `Collections-Tests`. `lib/smalltalk/tests/pharo/kernel.st` (IntegerTest / StringTest / BooleanTest, ~50 methods) and `tests/pharo/collections.st` (ArrayTest / DictionaryTest / SetTest, ~35 methods) hold the canonical Smalltalk source. `lib/smalltalk/tests/pharo.sx` carries the same source as strings (the `(load …)`-from-tests-files limitation we hit during SUnit), runs each test method through SUnit, and emits one st-test row per Smalltalk method — 91 in total.
|
||||
- [x] Drive the scoreboard up: aim for 200+ green tests. **751 green** at this point — past the target by 3.7x.
|
||||
- [ ] Stretch: ANSI Smalltalk validator subset
|
||||
- [x] Stretch: ANSI Smalltalk validator subset (`lib/smalltalk/tests/ansi.sx`). 62 tests organised by ANSI X3J20 §6.10 Object, §6.11 Boolean, §6.12 Number, §6.13 Integer, §6.16 Symbol, §6.17 String, §6.18 Array, §6.19 BlockContext. Each test runs through SUnit and emits one st-test row, mirroring the Pharo-slice harness.
|
||||
|
||||
### Phase 7 — speed (optional)
|
||||
- [ ] Method-dictionary inline caching (already in CEK as a primitive; just wire selector cache)
|
||||
@@ -108,6 +108,7 @@ Core mapping:
|
||||
|
||||
_Newest first. Agent appends on every commit._
|
||||
|
||||
- 2026-04-25: ANSI X3J20 validator subset + 62 tests (`lib/smalltalk/tests/ansi.sx`). One TestCase subclass per ANSI §6.x protocol; runs through SUnit. **Phase 6 complete.** 813/813 total.
|
||||
- 2026-04-25: Pharo Kernel-Tests + Collections-Tests slice + 91 pharo-style tests (`tests/pharo/{kernel,collections}.st` + `tests/pharo.sx`). Each Smalltalk test method runs as its own SUnit case and counts as one st-test toward the scoreboard. 751/751 total — past the Phase 6 "200+ green tests" target.
|
||||
- 2026-04-25: SUnit port (`lib/smalltalk/sunit.sx`, `lib/smalltalk/tests/sunit.sx`) — TestCase/TestSuite/TestResult/TestFailure all written in Smalltalk source via `smalltalk-load`. Full assert family + should:raise: + setUp/tearDown threading. 19 tests verify the framework. test.sh now bootstraps SUnit alongside runtime/eval. 660/660 total.
|
||||
- 2026-04-25: String>>format: + universal printOn: + 18 tests (`lib/smalltalk/tests/printing.sx`). `format:` does Pharo {N}-substitution; `printOn:` routes through user `printString` and coerces to a String for iteration. Phase 5 complete. 638/638 total.
|
||||
|
||||
Reference in New Issue
Block a user