"{ Package: 'stx:goodies/regression' }"
"{ NameSpace: RegressionTests }"
TestCase subclass:#NumberTest
instanceVariableNames:'a b'
classVariableNames:''
poolDictionaries:''
category:'tests-Regression-Numbers'
!
!NumberTest methodsFor:'accessing'!
a
^ a
!
a:something
a := something.
!
b
^ b
!
b:something
b := something.
! !
!NumberTest methodsFor:'initialize / release'!
tearDown
Class withoutUpdatingChangesDo:[
self class removeSelector:#testEQ
].
! !
!NumberTest methodsFor:'tests-comparing'!
test_minMax
self assert:(0.5 min:1) = 0.5.
self assert:(1.5 min:1) = 1.
self assert:(2 min:1) = 1.
self assert:(-1 min:1) = -1.
self assert:(0.5 max:1) = 1.
self assert:(1.5 max:1) = 1.5.
self assert:(1.5 max:2) = 2.
self assert:(2 max:1) = 2.
self assert:(-1 max:1) = 1.
self assert:(0.5 min:1 max:0) = 0.5.
self assert:(1 min:1 max:0) = 1.
self assert:(1.5 min:1 max:0) = 1.
self assert:(2 min:1 max:0) = 1.
self assert:(0 min:1 max:0) = 0.
self assert:(0.0 min:1 max:0) = 0.
self assert:(-1 min:1 max:0) = 0.
! !
!NumberTest methodsFor:'tests-concrete bugs'!
test_eqNumberBug
"reported 09-09-2004;
stc generated wrong code for some inlined = - compare (shame)."
self
skipIf:ExternalAddress pointerSize = 8
description:'Compile does not work under 64bit'.
false "(Helper
isStcCompiledMethod:#test_eqNumberBug
in:self
)" ifTrue:[
self
skipIf:true
description:'#compile is not available in stand alone apps'.
].
Class withoutUpdatingChangesDo:[
self class
compile:
'testEQ
a = b ifTrue:[^ false].
^ true.
'
classified:'temporary'.
].
self assert: (
(self
a:0;
b:0) testEQ ) == false.
self assert: (
(self
a:0;
b:0.0) testEQ ) == false.
self assert: (
(self
a:0.0;
b:0) testEQ ) == false.
self assert: (
(self
a:0.0;
b:0.0) testEQ ) == false.
Class withoutUpdatingChangesDo:[
Compiler stcCompileMethod:(self class compiledMethodAt:#testEQ).
].
self assert: (
(self
a:0;
b:0) testEQ ) == false.
self assert: (
(self
a:0;
b:0.0) testEQ ) == false.
self assert: (
(self
a:0.0;
b:0) testEQ ) == false.
self assert: (
(self
a:0.0;
b:0.0) testEQ ) == false.
Class withoutUpdatingChangesDo:[
self class removeSelector:#testEQ
].
"
self new test_eqNumberBug
"
"Modified (format): / 06-05-2019 / 14:12:55 / Claus Gittinger"
"Modified: / 21-05-2019 / 16:20:50 / Stefan Reise"
! !
!NumberTest methodsFor:'tests-conversion-rounding'!
test_conversion
"reported as Bug 388
Current implementation neither truncate nor round to nearest Floating point
value, it just accumulate round off errors."
self assert: 16r1FFFFFFFFFFFF0801 asDouble ~= 16r1FFFFFFFFFFFF0800 asDouble.
"this test is on 65 bits"
self assert: 16r1FFFFFFFFFFFF0802 asDouble ~= 16r1FFFFFFFFFFFF0800 asDouble.
"this test is on 64 bits"
self assert: 16r1FFFFFFFFFFF1F800 asDouble = 16r1FFFFFFFFFFF20000 asDouble.
"nearest even is higher"
self assert: 16r1FFFFFFFFFFFF0800 asDouble = 16r1FFFFFFFFFFFF0000 asDouble.
"nearest even is lower"
self assert: 16r1FFFFFFFFFFF1F800 asLongFloat ~= 16r1FFFFFFFFFFF20000 asLongFloat.
self assert: 16r1FFFFFFFFFFFF0800 asLongFloat ~= 16r1FFFFFFFFFFFF0000 asLongFloat.
"Created: / 24-10-2006 / 15:31:20 / cg"
! !
!NumberTest methodsFor:'tests-printing'!
testPrintf_FixedPoint
"/ FixedPoint
|pi|
pi := FixedPoint pi.
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.141593' ).
"/ too small
self assert:( (pi printfPrintString:'%4Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%5Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%6Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%7Lf') = '3.141593' ).
"/ fit
self assert:( (pi printfPrintString:'%8Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%4.2Lf') = '3.14' ).
"/ left filled
self assert:( (pi printfPrintString:'%9Lf') = ' 3.141593' ).
"/ right filled
self assert:( (pi printfPrintString:'%-9Lf') = '3.141593 ' ).
"Created: / 10-10-2017 / 12:36:21 / cg"
"Modified: / 10-10-2017 / 16:29:20 / cg"
!
testPrintf_Float
"/ Float
|pi|
pi := Float pi.
self assert:( (PrintfScanf printf:'%.0f' argument:pi) = '3' ).
self assert:( (PrintfScanf printf:'%#.0f' argument:pi) = '3.0' ). "/ hash forces print of '.0'
self assert:( (PrintfScanf printf:'%.1f' argument:pi) = '3.1' ).
self assert:( (PrintfScanf printf:'%#.1f' argument:pi) = '3.1' ).
self assert:( (PrintfScanf printf:'%.2f' argument:pi) = '3.14' ).
self assert:( (PrintfScanf printf:'%.3f' argument:pi) = '3.142' ).
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.141593' ).
self assert:( (PrintfScanf printf:'%4f' argument:pi) = '3.141593' ).
"/ too small
self assert:( (pi printfPrintString:'%4f') = '3.141593' ).
self assert:( (pi printfPrintString:'%5f') = '3.141593' ).
self assert:( (pi printfPrintString:'%6f') = '3.141593' ).
self assert:( (pi printfPrintString:'%7f') = '3.141593' ).
"/ fit
self assert:( (pi printfPrintString:'%8f') = '3.141593' ).
self assert:( (pi printfPrintString:'%4.2f') = '3.14' ).
"/ left filled
self assert:( (pi printfPrintString:'%9f') = ' 3.141593' ).
self assert:( (pi printfPrintString:'%8.4f') = ' 3.1416' ).
"/ right filled
self assert:( (pi printfPrintString:'%-9f') = '3.141593 ' ).
false ifTrue:[
#(
'%.3f' 1.0 '1.0'
) inGroupsOf:3 do:[:fmt :val :expected|
|printfGenerated stxGenerated|
printfGenerated := val printfPrintString:fmt.
stxGenerated := PrintfScanf printf:fmt argument:val.
self assert:(stxGenerated = printfGenerated).
self assert:(printfGenerated = expected).
].
].
self assert:( (1.0 printfPrintString:'%4f') = '1.000000' ).
self assert:( (1.0 printfPrintString:'%5f') = '1.000000' ).
self assert:( (1.0 printfPrintString:'%6f') = '1.000000' ).
self assert:( (1.0 printfPrintString:'%7f') = '1.000000' ).
self assert:( (1.0 printfPrintString:'%.0f') = '1' ).
self assert:( (1.0 printfPrintString:'%#.0f') = '1.' ).
self assert:( (1.0 printfPrintString:'%#.0g') = '1.' ).
self assert:( (1.0 printfPrintString:'%#.1f') = '1.0' ).
self assert:( (1.0 printfPrintString:'%#.1g') = '1.' ).
self assert:( (1.0 printfPrintString:'%.1f') = '1.0' ).
self assert:( (1.0 printfPrintString:'%.2f') = '1.00' ).
self assert:( (1.0 printfPrintString:'%.3f') = '1.000' ).
self assert:( (1.0 printfPrintString:'%.4f') = '1.0000' ).
self assert:( (1.0 printfPrintString:'%.5f') = '1.00000' ).
self assert:( (1.0 printfPrintString:'%.6f') = '1.000000' ).
self assert:( (1.0 printfPrintString:'%.7f') = '1.0000000' ).
self assert:( (PrintfScanf printf:'%.0f' argument:1.0) = '1' ).
false ifTrue:[
self assert:( (PrintfScanf printf:'%#.0f' argument:1.0) = '3.0' ). "/ hash forces print of '.0'
].
self assert:( (PrintfScanf printf:'%.1f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%#.1f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%.2f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%.3f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%.4f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%.8f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%f' argument:1.0) = '1.0' ).
self assert:( (PrintfScanf printf:'%4f' argument:1.0) = ' 1.0' ).
"Created: / 10-10-2017 / 12:34:51 / cg"
"Modified: / 10-10-2017 / 16:32:01 / cg"
!
testPrintf_Fraction
"/ Fraction
|pi|
pi := Fraction pi.
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.141593' ).
"/ too small
self assert:( (pi printfPrintString:'%4Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%5Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%6Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%7Lf') = '3.141593' ).
"/ fit
self assert:( (pi printfPrintString:'%8Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%4.2Lf') = '3.14' ).
"/ left filled
self assert:( (pi printfPrintString:'%9Lf') = ' 3.141593' ).
"/ right filled
self assert:( (pi printfPrintString:'%-9Lf') = '3.141593 ' ).
"Created: / 10-10-2017 / 12:37:25 / cg"
"Modified: / 10-10-2017 / 16:29:27 / cg"
!
testPrintf_Integer
|skipB systemIsWin32Bit|
systemIsWin32Bit := OperatingSystem isMSWINDOWSlike and:[ ExternalAddress pointerSize == 4 ].
"/ Integers
"/ verify that our printf generates the same string as the system-printf.
"/ Checks of printfPrintString: are here to make sure, that the system's printf is doing it right...)
self assert:( (20 printfPrintString:'%d') = '20' ).
self assert:( (20 printfPrintString:'% d') = ' 20' ).
self assert:( (-20 printfPrintString:'% d') = '-20' ).
self assert:( (20 printfPrintString:'%#d') = '20' ).
self assert:( (20 printfPrintString:'%#5d') = ' 20' ).
self assert:( (20 printfPrintString:'% -#5d') = ' 20 ' ).
self assert:( (20 printfPrintString:'%- #5d') = ' 20 ' ).
self assert:( (20 printfPrintString:'%-# 5d') = ' 20 ' ).
self assert:( (20 printfPrintString:'%-#5d') = '20 ' ).
self assert:( (20 printfPrintString:'%-#05d') = '20 ' ). "/ NOTICE
self assert:( (20 printfPrintString:'%-0#5d') = '20 ' ). "/ NOTICE
"/ borland printf is wrong here
(OperatingSystem isMSWINDOWSlike and:[ ExternalAddress pointerSize == 4]) ifTrue:[
"/ skip
] ifFalse:[
self assert:( (20 printfPrintString:'%0-#5d') = '20 ' ). "/ NOTICE - some printf's dont do this correctly
self assert:( (20 printfPrintString:'%0#-5d') = '20 ' ). "/ NOTICE
].
self assert:( (20 printfPrintString:'%#05d') = '00020' ).
self assert:( (20 printfPrintString:'%+ 5d') = ' +20' ).
self assert:( (20 printfPrintString:'%- 5d') = ' 20 ' ).
self assert:( (-20 printfPrintString:'%- 5d') = '-20 ' ).
self assert:( ( 20 printfPrintString:'%-+ 5d') = '+20 ' ).
self assert:( (-20 printfPrintString:'%-+ 5d') = '-20 ' ).
self assert:( ( 20 printfPrintString:'%+ 5d') = ' +20' ).
self assert:( (-20 printfPrintString:'%+ 5d') = ' -20' ).
self assert:( ( 0 printfPrintString:'%+ 5d') = ' +0' ).
self assert:( ( 0 printfPrintString:'%-+ 5d') = '+0 ' ).
self assert:( (20 printfPrintString:'%# 5d') = ' 20' ).
"/ skip with borland (that printf is wrong):
skipB := #(
('%D' nil) "/ not supported at all
('%#x' 0 ) "/ printf is wrong: always prepending 0x - even for 0 value
('%#o' 0 ) "/ printf is wrong: always prepending 0 - even for 0 value
).
#(
'%d' 20 '20'
'%d' -20 '-20'
"/ '%D' 20 '20' "/ works in ST/X and OSX-print, but not Win32-printf
"/ '%D' -20 '-20' "/ works in ST/X and OSX-print, but not Win32-printf
'%ld' 20 '20'
'%ld' -20 '-20'
'%lld' 20 '20'
'%lld' -20 '-20'
'%hd' 20 '20'
'%hd' -20 '-20'
'%hhd' 20 '20'
'%hhd' -20 '-20'
'%lhd' 20 '20'
'%hld' -20 '-20'
'% d' 20 ' 20'
'% d' -20 '-20'
'%#d' 20 '20'
'%#d' -20 '-20'
'%5d' 20 ' 20'
'%5d' -20 ' -20'
'%-5d' 20 '20 '
'%-5d' -20 '-20 '
'%05d' 20 '00020'
'%05d' -20 '-0020'
'%-05d' 20 '20 '
'%-05d' -20 '-20 '
'% 5d' 20 ' 20'
'% 5d' -20 ' -20'
'%- 5d' 20 ' 20 '
'%- 5d' -20 '-20 '
'%.0d' 20 '20'
'%.0d' -20 '-20'
'%.0d' 0 ''
'%x' 20 '14'
'%x' 255 'ff'
'%X' 255 'FF'
'%#x' 255 '0xff'
'%#X' 255 '0XFF' "/ printf also uppercases the 'x'
'%x' 0 '0'
'%#x' 0 '0' "/ with zero, no 0x should be prepended
'%#x' 20 '0x14'
'%5x' 20 ' 14'
'%-5x' 20 '14 '
'%#5x' 20 ' 0x14'
'%-#5x' 20 '0x14 '
'%#-5x' 20 '0x14 '
'%#-5X' 20 '0X14 '
"/ '%x' -20 '-14'
'%o' 20 '24'
'%o' 0 '0'
'%#o' 20 '024'
'%#o' 0 '0' "/ with zero, no 0 should be prepended
'%5o' 20 ' 24'
'%-5o' 20 '24 '
'%#5o' 20 ' 024'
'%-#5o' 20 '024 '
'%#-5o' 20 '024 '
'%-#05o' 20 '024 '
'%#05o' 20 '00024'
'%2d' 1234 '1234'
"/ '%2.2d' 1234 '1234'
'%2x' 10 ' a'
'%2X' 10 ' A'
'%02x' 10 '0a'
'%02X' 10 '0A'
"/ '%o' -20 '-24'
'%#5d' 20 ' 20'
'%-#5d' -20 '-20 '
'%-#5d' -20 '-20 '
'%-#05d' -20 '-20 '
'%#05d' -20 '-0020'
'%-#5d' 20 '20 '
'%-#5d' 20 '20 '
'%-#05d' 20 '20 '
'%-#05x' 20 '0x14 '
'%#05x' 20 '0x014'
'%.3x' 0xAFFE 'affe' "/ max length ignored for numbers
) inGroupsOf:3 do:[:fmt :val :expected|
|skip printfGenerated stxGenerated|
skip := false.
systemIsWin32Bit ifTrue:[
skip := skipB contains:[:pair | (pair first = fmt) and:[(pair second ? val) = val]].
].
skip ifTrue:[
Transcript showCR:'skipped check for %1 (borland printf does not handle it correctly)' with:fmt
] ifFalse:[
printfGenerated := val printfPrintString:fmt.
stxGenerated := PrintfScanf printf:fmt argument:val.
self assert:(stxGenerated = printfGenerated).
self assert:(printfGenerated = expected).
]
].
"/ hex
self assert:( (PrintfScanf printf:'%x' argument:-20) = '-14' ).
self assert:( (PrintfScanf printf:'%#x' argument:-20) = '-0x14' ).
self assert:( (PrintfScanf printf:'%#7x' argument:-20) = ' -0x14' ).
self assert:( (PrintfScanf printf:'%-#7x' argument:-20) = '-0x14 ' ).
self assert:( (PrintfScanf printf:'%-#07x' argument:-20) = '-0x14 ' ).
self assert:( (PrintfScanf printf:'%#07x' argument:-20) = '-0x0014' ).
"/ octal
self assert:( (PrintfScanf printf:'%o' argument:-20) = '-24' ).
self assert:( (PrintfScanf printf:'%#o' argument:-20) = '-024' ).
self assert:( (PrintfScanf printf:'%#5o' argument:-20) = ' -024' ).
self assert:( (PrintfScanf printf:'%-#5o' argument:-20) = '-024 ' ).
self assert:( (PrintfScanf printf:'%-#05o' argument:-20) = '-024 ' ).
self assert:( (PrintfScanf printf:'%#05o' argument:-20) = '-0024' ).
!
testPrintf_LargeFloat
"/ LargeFloat- unfinished
|lf pi|
pi := LargeFloat pi.
self
skipIf:(Smalltalk isSmalltalkDevelopmentSystem not)
description:'work in progress'.
self
skipIf:(Smalltalk at:#LargeFloat) isNil
description:'LargeFloat is not loaded'.
self assert:(pi printString) = '3.141592653590' "'3.141592653589793238462643383280'".
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
"/ disabled, as we currently get different results on different machines
"/ 0.0000000000000000000000033832795028841888829163053742377087
"/ self assert:( (PrintfScanf printf:'%f' argument:pi-(LargeFloat readFrom:'3.14159265358979323846264')) = '0.0000000000000000000000033832795028841973206112925254274159' "'0.00000000000000000000000338328'" ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.14159265359' "'3.141592653589793238462643383280'" ).
"/ too small
self assert:( (pi printfPrintString:'%4Lf') = '3.14159265359' "'3.141592653589793238462643383280'" ).
self assert:( (pi printfPrintString:'%5Lf') = '3.14159265359' "'3.141592653589793238462643383280'" ).
self assert:( (pi printfPrintString:'%6Lf') = '3.14159265359' "'3.141592653589793238462643383280'" ).
self assert:( (pi printfPrintString:'%7Lf') = '3.14159265359' "'3.141592653589793238462643383280'" ).
"/ fit
self assert:( (pi printfPrintString:'%8Lf') = '3.14159265359' "'3.141592653589793238462643383280'" ).
self assert:( (pi printfPrintString:'%4.2Lf') = '3.14' ).
self assert:( (pi printfPrintString:'%4.3Lf') = '3.142' ).
self assert:( (pi printfPrintString:'%4.4Lf') = '3.1416' ).
self assert:( (pi printfPrintString:'%4.5Lf') = '3.14159' ).
self assert:( (pi printfPrintString:'%4.6Lf') = '3.141593' ).
"/ left filled
self assert:( (pi printfPrintString:'%9Lf') = '3.14159265359' "' 3.141593'" ).
"/ right filled
self assert:( (pi printfPrintString:'%-9Lf') = '3.14159265359' "'3.141593 '" ).
"/ exact (to 130 digits) value is:
"/ 3.1415926535 8979323846 2643383279 5028841971 6939937510 5820974944 5923078164 0628620899 8628034825 3421170679 8214808651 3282306647
"/ ((LargeFloat fromString:'3.141592653589793238462643383279') printfPrintString:'%4.20Lf')
lf := 1 asLargeFloat.
self assert:( (lf printfPrintString:'%4.20Lf') = ' 1.0' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = ' 0.1' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.01' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.00001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.00000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.00000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.00000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.00000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.000000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.0000000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.21Lf') = '0.00000000000000000001' ).
lf := lf / 10.
self assert:( (lf printfPrintString:'%4.22Lf') = '0.000000000000000000001' ).
lf := pi.
self assert:( (lf printString) = '3.141592653590' ).
self assert:( (lf printfPrintString:'%4.20Lf') = '3.14159265358979323846' ).
lf := lf - 3.
self assert:( (lf printfPrintString:'%4.20Lf') = '0.14159265358979323846' ).
"Created: / 10-10-2017 / 16:25:25 / cg"
"Modified: / 05-06-2019 / 20:15:13 / Claus Gittinger"
"Modified (comment): / 22-07-2019 / 19:40:10 / Claus Gittinger"
!
testPrintf_LongFloat
"/ LongFloat
|pi|
pi := LongFloat pi.
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.14159265' ).
"/ LongFloat
"/ too small
self assert:( (pi printfPrintString:'%4Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%5Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%6Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%7Lf') = '3.141593' ).
"/ fit
self assert:( (pi printfPrintString:'%8Lf') = '3.141593' ).
self assert:( (pi printfPrintString:'%4.2Lf') = '3.14' ).
"/ left filled
self assert:( (pi printfPrintString:'%9Lf') = ' 3.141593' ).
"/ right filled
self assert:( (pi printfPrintString:'%-9Lf') = '3.141593 ' ).
"Created: / 10-10-2017 / 12:35:40 / cg"
"Modified: / 10-10-2017 / 16:29:56 / cg"
!
testPrintf_Misc
"/ verify that our printf generates the same string as the system-printf.
"/ Checks of printfPrintString: are here to make sure, that the system's printf is doing it right...)
self assert:( (20 printfPrintString:'%%%d') = '%20' ).
self assert:( (20 printfPrintString:'%d%%') = '20%' ).
"/ borland is wrong here
(OperatingSystem isMSWINDOWSlike and:[ExternalAddress pointerSize == 4]) ifFalse:[
self assert:( (20 printfPrintString:'%d%') = '20' ).
].
self assert:( PrintfScanf printf:'%d%' argument:20 ) = '20' .
self assert:( (20 printfPrintString:'%%') = '%' ).
"/ nobody knows what should happen...
"/ self assert:( (20 printfPrintString:'\%\') = '\' ).
"/ self assert:( (20 printfPrintString:'\%') = '%' ).
{
'%f' . Float NaN . 'nan' .
'%F' . Float NaN . 'NAN' .
'%f' . Float infinity . 'inf' .
'%F' . Float infinity . 'INF' .
'%f' . Float negativeInfinity . '-inf' .
'%F' . Float negativeInfinity . '-INF' .
'%+f' . Float NaN . 'nan' .
'%+F' . Float NaN . 'NAN' .
'%+f' . Float NaN negated . 'nan' .
'%+F' . Float NaN negated . 'NAN' .
'%+f' . Float infinity . '+inf' .
'%+F' . Float infinity . '+INF' .
'%+f' . Float negativeInfinity . '-inf' .
'%+F' . Float negativeInfinity . '-INF' .
'% f' . Float NaN . 'nan' . "/ not sure if that is reasonable (but printf does the same)
'% F' . Float NaN . 'NAN' . "/ not sure if that is reasonable (but printf does the same)
'% f' . Float infinity . ' inf' .
'% F' . Float infinity . ' INF' .
'% f' . Float negativeInfinity . '-inf' .
'% F' . Float negativeInfinity . '-INF' .
} inGroupsOf:3 do:[:fmt :val :expected|
|printfGenerated stxGenerated|
printfGenerated := val printfPrintString:fmt.
stxGenerated := PrintfScanf printf:fmt argument:val.
self assert:(stxGenerated = expected).
"/ borland printf generates uppercase 'NAN' for %f
((fmt = '%f') and:[ stxGenerated = printfGenerated asLowercase]) ifFalse:[
"/ borland printf does not handle %F
((fmt = '%F') and:[ printfGenerated = '%F']) ifFalse:[
"/ borland printf is completely wrong with %+f
((fmt = '%+f') and:[ printfGenerated = '++NAN']) ifFalse:[
self assert:(stxGenerated = printfGenerated).
].
].
].
].
#(
'%r' 1234 'r'
'%3r' 1234 ' r'
'%-3r' 1234 'r '
'%#r' 1234 'r'
"/ '%v' 1234 'v'
'%Id' 1234 'Id'
'%%%d' 20 '%20'
'%d%%' 20 '20%'
'%d%' 20 '20'
'%%a%%' 20 '%a%'
) inGroupsOf:3 do:[:fmt :val :expected|
|printfGenerated stxGenerated|
printfGenerated := val printfPrintString:fmt.
stxGenerated := PrintfScanf printf:fmt argument:val.
self assert:(stxGenerated = printfGenerated).
self assert:(printfGenerated = expected).
].
"/ more examples from "Secretes of printf"
self assert:( (0 printfPrintString:'%d') = '0' ).
self assert:( (-7 printfPrintString:'%d') = '-7' ).
self assert:( (1560133635 printfPrintString:'%d') = '1560133635' ).
self assert:( (-2035065302 printfPrintString:'%d') = '-2035065302' ).
!
testPrintf_More2
"/ additional test patterns from secrets of printf
"/ https://www.cypress.com/file/54441/download
{
'%d' . 0 . '0' .
'%d' . -7 . '-7' .
'%d' . 1560133635 . '1560133635' .
'%d' . -2035065302 . '-2035065302' .
'%5d' . 0 . ' 0' .
'%5d' . -7 . ' -7' .
'%5d' . 1560133635 . '1560133635' .
'%5d' . -2035065302 . '-2035065302' .
'%-5d' . 0 . '0 ' .
'%-5d' . -7 . '-7 ' .
'%-5d' . 1560133635 . '1560133635' .
'%-5d' . -2035065302 . '-2035065302' .
'%05d' . 0 . '00000' .
'%05d' . -7 . '-0007' .
'%05d' . 1560133635 . '1560133635' .
'%05d' . -2035065302 . '-2035065302' .
'%+5d' . 0 . ' +0' .
'%+5d' . -7 . ' -7' .
'%+5d' . 1560133635 . '+1560133635' .
'%+5d' . -2035065302 . '-2035065302' .
'%+-5d' . 0 . '+0 ' .
'%+-5d' . -7 . '-7 ' .
'%+-5d' . 1560133635 . '+1560133635' .
'%+-5d' . -2035065302 . '-2035065302' .
'% -5d' . 0 . ' 0 ' .
'% -5d' . -7 . '-7 ' .
'% -5d' . 1560133635 . ' 1560133635' .
'% -5d' . -2035065302 . '-2035065302' .
'% 05d' . 0 . ' 0000' .
'% 05d' . -7 . '-0007' .
'% 05d' . 1560133635 . ' 1560133635' .
'% 05d' . -2035065302 . '-2035065302' .
'%+05d' . 0 . '+0000' .
'%+05d' . -7 . '-0007' .
'%+05d' . 1560133635 . '+1560133635' .
'%+05d' . -2035065302 . '-2035065302' .
} inGroupsOf:3 do:[:fmt :val :expected|
|printfGenerated stxGenerated|
printfGenerated := val printfPrintString:fmt.
stxGenerated := PrintfScanf printf:fmt argument:val.
self assert:(stxGenerated = printfGenerated).
self assert:(printfGenerated = expected).
].
!
testPrintf_QDouble
"/ QDouble
|pi|
pi := QDouble pi.
self
skipIf:(OperatingSystem isUNIXlike and:[ExternalAddress pointerSize = 4])
description:'Fails under Linux32'.
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%.8f' argument:pi) = '3.14159265' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.1415926536' ).
self assert:( (pi printfPrintString:'%4Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%5Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%6Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%7Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%10Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%11Lf') = '3.1415926536' ).
self assert:( (pi printfPrintString:'%12Lf') = '3.1415926536' ).
"/ left filled
self assert:( (pi printfPrintString:'%13Lf') = ' 3.1415926536' ).
self assert:( (pi printfPrintString:'%18Lf') = ' 3.1415926536' ).
self assert:( (pi printfPrintString:'%19Lf') = ' 3.1415926536' ).
self assert:( (pi printfPrintString:'%20Lf') = ' 3.1415926536' ).
self assert:( (pi printfPrintString:'%21Lf') = ' 3.1415926536' ).
self assert:( (pi printfPrintString:'%4.2Lf') = '3.14' ).
"/ right filled
self assert:( (pi printfPrintString:'%-20Lf') = '3.1415926536 ' ).
"Created: / 10-10-2017 / 12:24:22 / cg"
"Modified: / 10-10-2017 / 16:28:51 / cg"
!
testPrintf_ShortFloat
|pi|
pi := ShortFloat pi.
self assert:( (PrintfScanf printf:'%.4f' argument:pi) = '3.1416' ).
self assert:( (PrintfScanf printf:'%f' argument:pi) = '3.14159' ).
"/ ShortFloat
"/ too small
self assert:( (pi printfPrintString:'%4f') = '3.141593' ).
self assert:( (pi printfPrintString:'%5f') = '3.141593' ).
self assert:( (pi printfPrintString:'%6f') = '3.141593' ).
self assert:( (pi printfPrintString:'%7f') = '3.141593' ).
"/ fit
self assert:( (pi printfPrintString:'%8f') = '3.141593' ).
self assert:( (pi printfPrintString:'%4.2f') = '3.14' ).
"/ left filled
self assert:( (pi printfPrintString:'%9f') = ' 3.141593' ).
self assert:( (pi printfPrintString:'%8.4f') = ' 3.1416' ).
"/ right filled
self assert:( (pi printfPrintString:'%-9f') = '3.141593 ' ).
self assert:( (pi printfPrintString:'%-8.4f') = '3.1416 ' ).
"Created: / 10-10-2017 / 12:35:12 / cg"
"Modified: / 10-10-2017 / 16:32:31 / cg"
! !
!NumberTest methodsFor:'tests-reading'!
testReadFrom
self assert: 1.0e-14 = (Number readFrom: '1.0e-14').
#(
'0.8' 0.8 '0.8'
'0' 0 '0'
'-0' 0 '0'
'00' 0 '0'
'000' 0 '0'
'0x0' 0 '0'
'0b0' 0 '0'
'16r0' 0 '0'
'4865804016353280000' 4865804016353280000 '4865804016353280000'
) inGroupsOf:3 do:[:str :expected :expectedPrintString|
|gotVal|
self assert:(gotVal := Number readFrom:str) = expected.
self assert:expected printString = expectedPrintString.
].
self assert: ('1' asNumber = 1).
self assert: ('10' asNumber = 10).
self assert: ('-1' asNumber = -1).
self assert: ('-10' asNumber = -10).
self assert: ('1e' asNumber = 1).
self assert: ('1e1' asNumber = 10).
self assert: ('1e10' asNumber = 10000000000).
self assert: ('-1e' asNumber = -1).
self assert: ('-1e1' asNumber = -10).
self assert: ('-1e10' asNumber = -10000000000).
self assert: ('1.0e' asNumber = 1.0).
self assert: ('1.0e1' asNumber = 10.0).
self assert: ('1.0e10' asNumber = 10000000000.0).
self assert: ('-1.0e' asNumber = -1.0).
self assert: ('-1.0e1' asNumber = -10.0).
self assert: ('-1.0e10' asNumber = -10000000000.0).
self assert: ('22.2' asNumber = 22.2).
self assert: ('-22.2' asNumber = -22.2).
self assert: ((Number readFrom:'0xaffe') = 45054).
self assert: ((Number readFrom:'0b1010') = 10).
self assert: ((Number readFrom:'0o177') = 127).
self assert: ((Number readFrom:'0Xaffe') = 45054).
self assert: ((Number readFrom:'0B1010') = 10).
self assert: ((Number readFrom:'0O177') = 127).
self assert: ((Number readFrom:'-0xaffe') = -45054).
self assert: ((Number readFrom:'-0b1010') = -10).
self assert: ((Number readFrom:'-0o177') = -127).
self assert: ((Number readFrom:'-0Xaffe') = -45054).
self assert: ((Number readFrom:'-0B1010') = -10).
self assert: ((Number readFrom:'-0O177') = -127).
self assert: ((Integer readFrom:'0x-affe') = -45054).
self should: [ Number readFrom:'0x-affe' ] raise:Error.
self should: [ Number readFrom:'0b-1010' ] raise:Error.
self should: [ Number readFrom:'0o-177' ] raise:Error.
self should: [ Number readFrom:'0X-affe' ] raise:Error.
self should: [ Number readFrom:'0B-1010' ] raise:Error.
self should: [ Number readFrom:'0O-177' ] raise:Error.
Smalltalk isSmalltalkX ifTrue:[
"/ st/x requires this:
self assert: ((Number readSmalltalkSyntaxFrom:'10r5.5') = 5.5).
self assert: ((Number readSmalltalkSyntaxFrom:'16r5.5') = 5.3125).
self assert: ((Number readSmalltalkSyntaxFrom:'3r1.1e2') = 12).
self assert: ((Number readSmalltalkSyntaxFrom:'3r1.1e10') = 78732.0).
self assert: ((Number readSmalltalkSyntaxFrom:'16r10.1e10') = 16.117431640625).
self assert: ((Number readSmalltalkSyntaxFrom:'10r22.2') = 22.2).
self assert: ((Number readSmalltalkSyntaxFrom:'10r22.2s5') = 22.2).
self assert: ((Number readSmalltalkSyntaxFrom:'10r-22.2') = -22.2).
self assert: ((Number readSmalltalkSyntaxFrom:'10r-22.2s5') = -22.2).
self assert: ((Number readSmalltalkSyntaxFrom:'0xaffe') = 45054).
"/ test fails when stc code, byte code works
(Helper
isStcCompiledMethod:#'testReadFrom'
in:self) ifTrue:[
self logSkipped:'2r1e26 is not valid in stc code -> debugger doesNotUnderstand: #e26'.
] ifFalse:[
self assert: 2r1e26 = (Number readSmalltalkSyntaxFrom: '2r1e26').
].
self assert: ('-1q' asNumber = -1).
self assert: ('-1q' asNumber class == LongFloat).
self assert: ('-1q1' asNumber = -10).
self assert: ('-1q10' asNumber = -10000000000).
] ifFalse:[
"/ squeak allows this:
self assert: 2r1e26 = (Number readFrom: '2r1e26').
self assert: ('10r22.2' asNumber = 22.2).
self assert: ('10r22.2s5' asNumber = 22.2).
self assert: ('10r-22.2' asNumber = -22.2).
self assert: ('10r-22.2s5' asNumber = -22.2).
].
"Modified: / 20-06-2017 / 14:05:37 / cg"
"Modified: / 17-12-2019 / 14:39:17 / Stefan Reise"
!
testReadFrom2
|n|
n := Number readFrom:(ReadStream on:'54.32e-01') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 5.432).
n := Number readFrom:(ReadStream on:'12345') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345).
n := Number readFrom:(ReadStream on:'12345.0') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.0f') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.0e') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.0q') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.0d') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.0s') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345.01s') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.01).
n := Float readFrom:(ReadStream on:'12345') decimalPointCharacters:'.' onError:[self halt].
self assert:(n = 12345.0).
n := Number readFrom:(ReadStream on:'12345678901234567890').
self assert:(n = 12345678901234567890).
n := Number readFrom:(ReadStream on:'12345678901234567890.0').
self assert:(n = 12345678901234567890.0).
n := Number readFrom:(ReadStream on:'12345678901234567890.012345678901234567890').
self assert:(n closeTo: 12345678901234567890.012345678901234567890).
n := Number readFrom:(ReadStream on:'16rAAAAFFFFAAAAFFFF').
self assert:(n = 16rAAAAFFFFAAAAFFFF).
n := Number readFrom:'16rAAAAFFFFAAAAFFFF'.
self assert:(n = 16rAAAAFFFFAAAAFFFF).
n := Number readFrom:'16r100A'.
self assert:(n = 16r100A).
n := Number readFrom:'16r100a'.
self assert:(n = 16r100A).
n := Number readFrom:'16r-100A'.
self assert:(n = -16r100A).
n := Number readFrom:'-16r100A'.
self assert:(n = -16r100A).
n := Number readFrom:'0x100A'.
self assert:(n = 16r100A).
n := Number readFrom:'-0x100A'.
self assert:(n = -16r100A).
self should:[ n := Number readFrom:'0x-100A' ] raise:Error.
n := Number readFrom:'0.000001'.
n := '+00000123.45' asNumber.
n := Number readFrom:'(1/3)'.
n := Number readFrom:'(-1/3)'.
n := Number readFrom:'(1/-3)'.
n := Number readFrom:'-(1/3)'.
n := Number readFrom:'-(-1/3)'.
self should:[ n := Number readFrom:'(-1/3' ] raise:Error.
n := Number readFrom:'99s'.
n := Number readFrom:'99.00s'.
n := Number readFrom:'99.0000000s'.
n := Number readFrom:'.0000000s'.
n := Number readFrom:'.0000000q'.
n := Number readFrom:'.0000000f'.
n := Number readFrom:'.0000000e'.
n := Number readFrom:'.0000000s1'.
n := Number readFrom:'.0000000q1'.
n := Number readFrom:'.0000000f1'.
n := Number readFrom:'.0000000e1'.
n := LongFloat readFrom:'.00000001'.
n := Number readFrom:'.00000000000001'.
n := Number readFrom:'.001'.
n := ShortFloat readFrom:'.001'.
n := Number readFrom:'123garbage'. "/ -> returns 123
self should:[ n := Number fromString:'123garbage'] raise:Error.
n := Number readFrom:'99,00' decimalPointCharacters:#( $. $, ).
n := Number readFrom:'99,00' decimalPointCharacters:#( $. ).
! !
!NumberTest class methodsFor:'documentation'!
version
^ '$Header$'
!
version_CVS
^ '$Header$'
! !