;; 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)