Commit efb2325f authored by sof's avatar sof
Browse files

[project @ 1999-01-23 17:55:26 by sof]

More Enum regression tests than you can shake a stick at.
parent 3989806b
-- !!! Testing the Prelude's Enum instances.
module Main(main) where
import Exception
import Char
main = do
-- Enum Int
putStrLn "Testing Enum Int: "
testEnumInt
-- Enum Integer
putStrLn "Testing Enum Integer: "
testEnumInteger
-- Enum Char
putStrLn "Testing Enum Char: "
testEnumChar
-- Enum ()
putStrLn "Testing Enum (): "
testEnumUnit
-- Enum Ordering
putStrLn "Testing Enum Ordering (derived): "
testEnumOrdering
-- Enum Bool
putStrLn "Testing Enum Bool: "
testEnumBool
-- Enum Rational
putStrLn "Testing Enum Rational: "
testEnumRational
-- Enum (Ratio Int)
putStrLn "Testing Enum (Ratio Int): "
testEnumRatioInt
{-
Here's the properties that's supposed to
hold for arithmetic sequences over Int:
- [e1..] = [e1, (e1+1), (e1+2), ..., maxBound]
- [e1,e2..] = [e1, (e1+i), (e1+2*i), ... upper]
where
i = e2 - e1
upper
| i > 0 = maxBound
| i < 0 = minBound
| i == 0 = maxBound -- this really shouldn't matter (I feel.)
- [e1..e3] = [e1, (e1+i), (e1+2*i),..e3]
where
i
| e3 >= e1 = 1
| e3 < e1 = (-1)
- [e1,e2..e3] = res
where
i = e2 - e1
res
| i >= 0 && e3 < e1 = []
| i < 0 && e3 >= e1 = [] -- (*)
| otherwise = [e1, (e1+i), (e1 + 2*i), .. e3]
Note:
(*) - I think this instead should be (i < 0 && e3 > e1), since, as is,
[x,(x+1) ..x] = [x]
[x,(x-1) ..x] = []
which does not look right, symmetrically speaking.
The same properties hold for other Prelude types that
are instances of Enum as well as being Bounded.
For non-Bounded types (e.g., Float and Double), the properties are similar,
except that the boundary tests become slightly different, i.e., when an
element becomes greater than (e3 + i/2) (or less than (e3 + i/2) for negative
i.)
Q - does [(x::Double)..] have an upper bound? (ditto for Float.)
OK - on with the regression testing.
-}
#define printTest(x) (do{ putStr ( " " ++ "x" ++ " = " ) ; print (x) })
testEnumInt :: IO ()
testEnumInt = do
-- succ
printTest ((succ (0::Int)))
printTest ((succ (minBound::Int)))
mayBomb (printTest ((succ (maxBound::Int))))
-- pred
printTest (pred (1::Int))
printTest (pred (maxBound::Int))
mayBomb (printTest (pred (minBound::Int)))
-- toEnum
printTest ((map (toEnum::Int->Int) [1,minBound,maxBound]))
-- fromEnum
printTest ((map fromEnum [(1::Int),minBound,maxBound]))
-- [x..] aka enumFrom
printTest ((take 7 [(1::Int)..]))
printTest ((take 7 [((maxBound::Int)-5)..])) -- just in case it doesn't catch the upper bound..
-- [x,y..] aka enumFromThen
printTest ((take 7 [(1::Int),2..]))
printTest ((take 7 [(1::Int),7..]))
printTest ((take 7 [(1::Int),1..]))
printTest ((take 7 [(1::Int),0..]))
printTest ((take 7 [(5::Int),2..]))
let x = (minBound::Int) + 1
printTest ((take 7 [x, x-1 ..]))
let x = (minBound::Int) + 5
printTest ((take 7 [x, x-1 ..]))
let x = (maxBound::Int) - 5
printTest ((take 7 [x, (x+1) ..]))
-- [x..y] aka enumFromTo
printTest ((take 7 ([(1::Int) .. 5])))
printTest ((take 4 ([(1::Int) .. 1])))
printTest ((take 7 ([(1::Int) .. 0])))
printTest ((take 7 ([(5::Int) .. 0])))
printTest ((take 7 ([(maxBound-(5::Int)) .. maxBound])))
printTest ((take 7 ([(minBound+(5::Int)) .. minBound])))
-- [x,y..z] aka enumFromThenTo
printTest ((take 7 [(5::Int),4..1]))
printTest ((take 7 [(5::Int),3..1]))
printTest ((take 7 [(5::Int),3..2]))
printTest ((take 7 [(1::Int),2..1]))
printTest ((take 7 [(2::Int),1..2]))
printTest ((take 7 [(2::Int),1..1]))
printTest ((take 7 [(2::Int),3..1]))
let x = (maxBound::Int) - 4
printTest ((take 7 [x,(x+1)..maxBound]))
let x = (minBound::Int) + 5
printTest ((take 7 [x,(x-1)..minBound]))
testEnumChar :: IO ()
testEnumChar = do
-- succ
printTest ((succ 'a'))
printTest ((succ (minBound::Char)))
mayBomb (printTest ((succ (maxBound::Char))))
-- pred
printTest ((pred 'b'))
printTest (pred (maxBound::Char))
mayBomb (printTest (pred (minBound::Char)))
-- toEnum
printTest ((map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]))
mayBomb (printTest ((toEnum::Int->Char) (minBound::Int)))
-- fromEnum
printTest ((map fromEnum ['X',minBound,maxBound]))
-- [x..] aka enumFrom
printTest ((take 7 ['\NUL' .. ]))
printTest ((take 7 ['\250' .. ]))
-- [x,y..] aka enumFromThen
printTest ((take 7 ['a','b'..]))
printTest ((take 7 ['a','e'..]))
printTest ((take 7 ['a','a'..]))
printTest ((take 7 ['z','y'..]))
printTest ((take 7 ['z','v'..]))
let x = '\1'
printTest ((take 7 ['\1', '\0' ..]))
let x = '\5'
printTest ((take 7 ['\5', '\4' ..]))
let x = (maxBound::Int) - 5
printTest ((take 7 ['\250', '\251' ..]))
-- [x..y] aka enumFromTo
printTest ((take 7 (['a' .. 'e'])))
printTest ((take 4 (['a' .. 'a'])))
printTest ((take 7 (['b' .. 'a'])))
printTest ((take 7 (['e' .. 'a'])))
printTest ((take 7 (['\250' .. '\255'])))
printTest ((take 7 (['\5' .. '\0'])))
-- [x,y..z] aka enumFromThenTo
printTest ((take 7 ['f','e' .. 'b']))
printTest ((take 7 ['g','e' .. 'b']))
printTest ((take 7 ['g','d' .. 'c']))
printTest ((take 7 ['b','c' .. 'b']))
printTest ((take 7 ['c','b' .. 'c']))
printTest ((take 7 ['c','b' .. 'b']))
printTest ((take 7 ['c','d' .. 'b']))
printTest ((take 7 ['\251', '\252' .. maxBound]))
printTest ((take 7 ['\5', '\4' .. minBound]))
testEnumUnit :: IO ()
testEnumUnit = do
-- succ:
mayBomb (printTest ((succ ())))
mayBomb (printTest ((succ (minBound::()))))
mayBomb (printTest ((succ (maxBound::()))))
-- pred:
mayBomb (printTest ((pred ())))
mayBomb (printTest ((pred (minBound::()))))
mayBomb (printTest ((pred (maxBound::()))))
-- toEnum:
printTest ((toEnum 0)::())
mayBomb (printTest ((toEnum 1)::()))
-- fromEnum:
printTest ((fromEnum ()))
-- enumFrom:
printTest (([()..]))
-- enumFromThen:
printTest (([(),()..]))
-- enumFromTo
printTest (([()..()]))
-- enumFromThenTo
printTest (([(),()..()]))
testEnumOrdering :: IO ()
testEnumOrdering = do
-- succ:
printTest ((succ LT))
printTest ((succ (minBound::Ordering)))
mayBomb (printTest ((succ (maxBound::Ordering))))
-- pred:
printTest ((pred GT))
printTest ((pred (maxBound::Ordering)))
mayBomb (printTest ((pred (minBound::Ordering))))
-- toEnum:
printTest ((toEnum 0)::Ordering)
mayBomb (printTest ((toEnum 5)::Ordering))
-- fromEnum:
printTest ((fromEnum LT))
printTest ((fromEnum EQ))
printTest ((fromEnum GT))
-- enumFrom:
printTest (([LT ..]))
printTest (([EQ ..]))
printTest (([GT ..]))
-- enumFromThen:
printTest (([LT,EQ ..]))
printTest (([EQ,GT ..]))
printTest (([EQ,LT ..]))
printTest (([LT,GT ..]))
printTest (([GT,LT ..]))
printTest (take 7 (([GT,GT ..])))
printTest (take 7 (([LT,LT ..])))
-- enumFromTo
printTest (([LT .. GT]))
printTest (([LT .. EQ]))
printTest (([LT .. LT]))
printTest (([GT .. LT]))
printTest (([GT .. EQ]))
printTest (([GT .. GT]))
-- enumFromThenTo
printTest (([LT,EQ .. GT]))
printTest (([GT,EQ .. LT]))
printTest (([GT,EQ .. EQ]))
printTest (([GT,EQ .. GT]))
printTest (([GT,EQ .. LT]))
printTest (([LT,EQ .. LT]))
printTest (([LT,EQ .. GT]))
printTest (take 7 (([LT,LT .. GT])))
printTest (take 7 (([GT,GT .. LT])))
testEnumBool :: IO ()
testEnumBool = do
-- succ:
printTest ((succ False))
printTest ((succ (minBound::Bool)))
mayBomb (printTest ((succ (maxBound::Bool))))
-- pred:
printTest ((pred True))
printTest ((pred (maxBound::Bool)))
mayBomb (printTest ((pred (minBound::Bool))))
-- toEnum:
printTest ((toEnum 0)::Bool)
mayBomb (printTest ((toEnum 5)::Bool))
-- fromEnum:
printTest ((fromEnum False))
printTest ((fromEnum True))
-- enumFrom:
printTest (([False ..]))
printTest (([True ..]))
-- enumFromThen:
printTest (([False,True ..]))
printTest (([True,False ..]))
printTest ((take 7 ([False,False ..])))
printTest ((take 7 ([True,True ..])))
-- enumFromTo
printTest (([False .. True]))
printTest (([True .. False]))
-- enumFromThenTo
printTest (take 7 ([False,False .. False]))
printTest (take 7 ([False,False .. True]))
printTest (take 7 ([False,True .. False]))
printTest (take 7 ([False,True .. True]))
printTest (take 7 ([True,False .. False]))
printTest (take 7 ([True,False .. True]))
printTest (take 7 ([True,True .. False]))
printTest (take 7 ([True,True .. True]))
testEnumInteger :: IO ()
testEnumInteger = do
-- succ
printTest ((succ (0::Integer)))
printTest ((succ ((-1)::Integer)))
-- pred
printTest (pred (1::Integer))
printTest (pred (0::Integer))
-- toEnum
printTest ((map (toEnum::Int->Integer) [1,minBound,maxBound]))
-- fromEnum
printTest ((map fromEnum [(1::Integer),42,45]))
-- [x..] aka enumFrom
printTest ((take 7 [(1::Integer)..]))
printTest ((take 7 [(-5::Integer)..]))
-- [x,y..] aka enumFromThen
printTest ((take 7 [(1::Integer),2..]))
printTest ((take 7 [(1::Integer),7..]))
printTest ((take 7 [(1::Integer),1..]))
printTest ((take 7 [(1::Integer),0..]))
printTest ((take 7 [(5::Integer),2..]))
-- [x..y] aka enumFromTo
printTest ((take 7 ([(1::Integer) .. 5])))
printTest ((take 4 ([(1::Integer) .. 1])))
printTest ((take 7 ([(1::Integer) .. 0])))
printTest ((take 7 ([(5::Integer) .. 0])))
-- [x,y..z] aka enumFromThenTo
printTest ((take 7 [(5::Integer),4..1]))
printTest ((take 7 [(5::Integer),3..1]))
printTest ((take 7 [(5::Integer),3..2]))
printTest ((take 7 [(1::Integer),2..1]))
printTest ((take 7 [(2::Integer),1..2]))
printTest ((take 7 [(2::Integer),1..1]))
printTest ((take 7 [(2::Integer),3..1]))
testEnumRational :: IO ()
testEnumRational = do
-- succ
printTest ((succ (0::Rational)))
printTest ((succ ((-1)::Rational)))
-- pred
printTest (pred (1::Rational))
printTest (pred (0::Rational))
-- toEnum
printTest ((map (toEnum::Int->Rational) [1,minBound,maxBound]))
-- fromEnum
printTest ((map fromEnum [(1::Rational),42,45]))
-- [x..] aka enumFrom
printTest ((take 7 [(1::Rational)..]))
printTest ((take 7 [(-5::Rational)..]))
-- [x,y..] aka enumFromThen
printTest ((take 7 [(1::Rational),2..]))
printTest ((take 7 [(1::Rational),7..]))
printTest ((take 7 [(1::Rational),1..]))
printTest ((take 7 [(1::Rational),0..]))
printTest ((take 7 [(5::Rational),2..]))
-- [x..y] aka enumFromTo
printTest ((take 7 ([(1::Rational) .. 5])))
printTest ((take 4 ([(1::Rational) .. 1])))
printTest ((take 7 ([(1::Rational) .. 0])))
printTest ((take 7 ([(5::Rational) .. 0])))
-- [x,y..z] aka enumFromThenTo
printTest ((take 7 [(5::Rational),4..1]))
printTest ((take 7 [(5::Rational),3..1]))
printTest ((take 7 [(5::Rational),3..2]))
printTest ((take 7 [(1::Rational),2..1]))
printTest ((take 7 [(2::Rational),1..2]))
printTest ((take 7 [(2::Rational),1..1]))
printTest ((take 7 [(2::Rational),3..1]))
testEnumRatioInt :: IO ()
testEnumRatioInt = do
-- succ
printTest ((succ (0::Ratio Int)))
printTest ((succ ((-1)::Ratio Int)))
-- pred
printTest (pred (1::Ratio Int))
printTest (pred (0::Ratio Int))
-- toEnum
printTest ((map (toEnum::Int->Ratio Int) [1,minBound,maxBound]))
-- fromEnum
printTest ((map fromEnum [(1::Ratio Int),42,45]))
-- [x..] aka enumFrom
printTest ((take 7 [(1::Ratio Int)..]))
printTest ((take 7 [(-5::Ratio Int)..]))
printTest ((take 7 [((toEnum ((maxBound::Int)-5))::Ratio Int)..]))
-- [x,y..] aka enumFromThen
printTest ((take 7 [(1::Ratio Int),2..]))
printTest ((take 7 [(1::Ratio Int),7..]))
printTest ((take 7 [(1::Ratio Int),1..]))
printTest ((take 7 [(1::Ratio Int),0..]))
printTest ((take 7 [(5::Ratio Int),2..]))
let x = (toEnum ((minBound::Int) + 1))::Ratio Int
printTest ((take 7 [x, x-1 ..]))
let x = (toEnum ((minBound::Int) + 5))::Ratio Int
printTest ((take 7 [x, x-1 ..]))
let x = (toEnum ((maxBound::Int) - 5))::Ratio Int
printTest ((take 7 [x, (x+1) ..]))
-- [x..y] aka enumFromTo
printTest ((take 7 ([(1::Ratio Int) .. 5])))
printTest ((take 4 ([(1::Ratio Int) .. 1])))
printTest ((take 7 ([(1::Ratio Int) .. 0])))
printTest ((take 7 ([(5::Ratio Int) .. 0])))
let x = (toEnum (maxBound - (5::Int))) :: Ratio Int
let y = (toEnum (maxBound::Int)) :: Ratio Int
printTest ((take 7 ([x..y])))
let x = (toEnum (minBound + (5::Int))) :: Ratio Int
let y = (toEnum (minBound::Int)) :: Ratio Int
printTest ((take 7 ([x..y])))
-- [x,y..z] aka enumFromThenTo
printTest ((take 7 [(5::Ratio Int),4..1]))
printTest ((take 7 [(5::Ratio Int),3..1]))
printTest ((take 7 [(5::Ratio Int),3..2]))
printTest ((take 7 [(1::Ratio Int),2..1]))
printTest ((take 7 [(2::Ratio Int),1..2]))
printTest ((take 7 [(2::Ratio Int),1..1]))
printTest ((take 7 [(2::Ratio Int),3..1]))
let x = (toEnum ((maxBound::Int) - 4)) :: Ratio Int
let y = (toEnum (maxBound::Int)) :: Ratio Int
printTest ((take 7 [x,(x+1)..y]))
let x = (toEnum ((minBound::Int) + 5)) :: Ratio Int
let y = (toEnum (minBound::Int)) :: Ratio Int
printTest ((take 7 [x,(x-1)..y]))
--
--
-- Utils
--
--
mayBomb x = catchAllIO x errorHandler
errorHandler :: Exception -> IO ()
errorHandler e =
case justErrors e of
Just t -> putStrLn ("error " ++ show t)
_ -> return ()
test :: Show a => String -> String -> a -> IO ()
test test_nm expected val = do
putStr test_nm
if expected == got then
putStrLn ": SUCCEEDED"
else do
putStr ": FAILED"
putStrLn ("( expected: " ++ show expected ++ " , got: " ++ show got ++ " )")
where
got = show val
Testing Enum Int:
(succ (0::Int)) = 1
(succ (minBound::Int)) = -2147483647
(succ (maxBound::Int)) = error "Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"
pred (1::Int) = 0
pred (maxBound::Int) = 2147483646
pred (minBound::Int) = error "Prelude.Enum.pred{Int}: tried to take `pred' of minBound"
(map (toEnum::Int->Int) [1,minBound,maxBound]) = [1,-2147483648,2147483647]
(map fromEnum [(1::Int),minBound,maxBound]) = [1,-2147483648,2147483647]
(take 7 [(1::Int)..]) = [1,2,3,4,5,6,7]
(take 7 [((maxBound::Int)-5)..]) = [2147483642,2147483643,2147483644,2147483645,2147483646,2147483647]
(take 7 [(1::Int),2..]) = [1,2,3,4,5,6,7]
(take 7 [(1::Int),7..]) = [1,7,13,19,25,31,37]
(take 7 [(1::Int),1..]) = [1,1,1,1,1,1,1]
(take 7 [(1::Int),0..]) = [1,0,-1,-2,-3,-4,-5]
(take 7 [(5::Int),2..]) = [5,2,-1,-4,-7,-10,-13]
(take 7 [x, x-1 ..]) = [-2147483647,-2147483648]
(take 7 [x, x-1 ..]) = [-2147483643,-2147483644,-2147483645,-2147483646,-2147483647,-2147483648]
(take 7 [x, (x+1) ..]) = [2147483642,2147483643,2147483644,2147483645,2147483646,2147483647]
(take 7 ([(1::Int) .. 5])) = [1,2,3,4,5]
(take 4 ([(1::Int) .. 1])) = [1]
(take 7 ([(1::Int) .. 0])) = [1,0]
(take 7 ([(5::Int) .. 0])) = [5,4,3,2,1,0]
(take 7 ([(maxBound-(5::Int)) .. maxBound])) = [2147483642,2147483643,2147483644,2147483645,2147483646,2147483647]
(take 7 ([(minBound+(5::Int)) .. minBound])) = [-2147483643,-2147483644,-2147483645,-2147483646,-2147483647,-2147483648]
(take 7 [(5::Int),4..1]) = [5,4,3,2,1]
(take 7 [(5::Int),3..1]) = [5,3,1]
(take 7 [(5::Int),3..2]) = [5,3]
(take 7 [(1::Int),2..1]) = [1]
(take 7 [(2::Int),1..2]) = [2]
(take 7 [(2::Int),1..1]) = [2,1]
(take 7 [(2::Int),3..1]) = []
(take 7 [x,(x+1)..maxBound]) = [2147483643,2147483644,2147483645,2147483646,2147483647]
(take 7 [x,(x-1)..minBound]) = [-2147483643,-2147483644,-2147483645,-2147483646,-2147483647,-2147483648]
Testing Enum Integer:
(succ (0::Integer)) = 1
(succ ((-1)::Integer)) = 0
pred (1::Integer) = 0
pred (0::Integer) = -1
(map (toEnum::Int->Integer) [1,minBound,maxBound]) = [1,-2147483648,2147483647]
(map fromEnum [(1::Integer),42,45]) = [1,42,45]
(take 7 [(1::Integer)..]) = [1,2,3,4,5,6,7]
(take 7 [(-5::Integer)..]) = [-5,-4,-3,-2,-1,0,1]
(take 7 [(1::Integer),2..]) = [1,2,3,4,5,6,7]
(take 7 [(1::Integer),7..]) = [1,7,13,19,25,31,37]
(take 7 [(1::Integer),1..]) = [1,1,1,1,1,1,1]
(take 7 [(1::Integer),0..]) = [1,0,-1,-2,-3,-4,-5]
(take 7 [(5::Integer),2..]) = [5,2,-1,-4,-7,-10,-13]
(take 7 ([(1::Integer) .. 5])) = [1,2,3,4,5]
(take 4 ([(1::Integer) .. 1])) = [1]
(take 7 ([(1::Integer) .. 0])) = [1,0]
(take 7 ([(5::Integer) .. 0])) = [5,4,3,2,1,0]
(take 7 [(5::Integer),4..1]) = [5,4,3,2,1]
(take 7 [(5::Integer),3..1]) = [5,3,1]
(take 7 [(5::Integer),3..2]) = [5,3]
(take 7 [(1::Integer),2..1]) = [1]
(take 7 [(2::Integer),1..2]) = [2]
(take 7 [(2::Integer),1..1]) = [2,1]
(take 7 [(2::Integer),3..1]) = []
Testing Enum Char:
(succ 'a') = 'b'
(succ (minBound::Char)) = '\SOH'
(succ (maxBound::Char)) = error "Prelude.Enum.succ{Char}: tried to take `succ' of maxBound"
(pred 'b') = 'a'
pred (maxBound::Char) = '\254'
pred (minBound::Char) = error "Prelude.Enum.pred{Char}: tried to to take `pred' of minBound"
(map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\255"
(toEnum::Int->Char) (minBound::Int) = error "Prelude.Enum.toEnum{Char}: out of range: -2147483648"
(map fromEnum ['X',minBound,maxBound]) = [88,0,255]
(take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
(take 7 ['\250' .. ]) = "\250\251\252\253\254\255"
(take 7 ['a','b'..]) = "abcdefg"
(take 7 ['a','e'..]) = "aeimquy"
(take 7 ['a','a'..]) = "aaaaaaa"
(take 7 ['z','y'..]) = "zyxwvut"
(take 7 ['z','v'..]) = "zvrnjfb"
(take 7 ['\1', '\0' ..]) = "\SOH\NUL"
(take 7 ['\5', '\4' ..]) = "\ENQ\EOT\ETX\STX\SOH\NUL"
(take 7 ['\250', '\251' ..]) = "\250\251\252\253\254\255"
(take 7 (['a' .. 'e'])) = "abcde"
(take 4 (['a' .. 'a'])) = "a"
(take 7 (['b' .. 'a'])) = "ba"
(take 7 (['e' .. 'a'])) = "edcba"
(take 7 (['\250' .. '\255'])) = "\250\251\252\253\254\255"
(take 7 (['\5' .. '\0'])) = "\ENQ\EOT\ETX\STX\SOH\NUL"
(take 7 ['f','e' .. 'b']) = "fedcb"
(take 7 ['g','e' .. 'b']) = "gec"
(take 7 ['g','d' .. 'c']) = "gd"
(take 7 ['b','c' .. 'b']) = "b"
(take 7 ['c','b' .. 'c']) = "c"
(take 7 ['c','b' .. 'b']) = "cb"
(take 7 ['c','d' .. 'b']) = ""
(take 7 ['\251', '\252' .. maxBound]) = "\251\252\253\254\255"
(take 7 ['\5', '\4' .. minBound]) = "\ENQ\EOT\ETX\STX\SOH\NUL"
Testing Enum ():
(succ ()) = error "Prelude.Enum.succ{()}: not possible"
(succ (minBound::())) = error "Prelude.Enum.succ{()}: not possible"
(succ (maxBound::())) = error "Prelude.Enum.succ{()}: not possible"
(pred ()) = error "Prelude.Enum.pred{()}: not possible"