[project @ 1999-05-07 14:52:49 by simonm]
[ghc-hetmet.git] / ghc / tests / lib / should_run / enum01.hs
1 -- !!! Testing the Prelude's Enum instances.
2 module Main(main) where
3
4 import Exception
5 import Char
6 import Ratio
7
8 main = do
9    -- Enum Int
10   putStrLn "Testing Enum Int: "
11   testEnumInt
12    -- Enum Integer
13   putStrLn "Testing Enum Integer: "
14   testEnumInteger
15    -- Enum Char
16   putStrLn "Testing Enum Char: "
17   testEnumChar
18    -- Enum ()
19   putStrLn "Testing Enum (): "
20   testEnumUnit
21    -- Enum Ordering
22   putStrLn "Testing Enum Ordering (derived): "
23   testEnumOrdering
24    -- Enum Bool
25   putStrLn "Testing Enum Bool: "
26   testEnumBool
27    -- Enum Rational
28   putStrLn "Testing Enum Rational: "
29   testEnumRational
30    -- Enum (Ratio Int)
31   putStrLn "Testing Enum (Ratio Int): "
32   testEnumRatioInt
33
34 {- 
35   Here's the properties that's supposed to
36   hold for arithmetic sequences over Int:
37
38    - [e1..]    = [e1, (e1+1), (e1+2), ..., maxBound]
39
40    - [e1,e2..] = [e1, (e1+i), (e1+2*i), ... upper]
41                  where
42                   i = e2 - e1
43                   upper
44                    | i >  0 = maxBound
45                    | i <  0 = minBound
46                    | i == 0 = maxBound -- this really shouldn't matter (I feel.)
47    - [e1..e3] = [e1, (e1+i), (e1+2*i),..e3]
48                 where
49                  i
50                   | e3 >= e1 = 1
51                   | e3 <  e1 = (-1)
52     
53    - [e1,e2..e3] = res
54                    where
55                     i = e2 - e1
56                     
57                     res
58                      | i >= 0 && e3 <  e1 = []
59                      | i <  0 && e3 >= e1 = []  -- (*)
60                      | otherwise          = [e1, (e1+i), (e1 + 2*i), .. e3]
61
62    Note:
63      (*) - I think this instead should be (i < 0 && e3 > e1), since, as is,
64
65             [x,(x+1) ..x] = [x] 
66             [x,(x-1) ..x] = []
67
68            which does not look right, symmetrically speaking.
69
70
71    The same properties hold for other Prelude types that
72    are instances of Enum as well as being Bounded.
73    
74    For non-Bounded types (e.g., Float and Double), the properties are similar,
75    except that the boundary tests become slightly different, i.e., when an
76    element becomes greater than (e3 + i/2) (or less than (e3 + i/2) for negative
77    i.)
78
79   Q - does [(x::Double)..] have an upper bound? (ditto for Float.)
80
81   OK - on with the regression testing.
82 -}
83
84 #define printTest(x) (do{ putStr ( "    " ++ "x" ++ " = " ) ; print (x) })
85
86
87 testEnumInt :: IO ()
88 testEnumInt = do
89      -- succ
90   printTest ((succ (0::Int)))
91   printTest ((succ (minBound::Int)))
92   mayBomb   (printTest ((succ (maxBound::Int))))
93
94      -- pred
95   printTest (pred (1::Int))
96   printTest (pred (maxBound::Int))
97   mayBomb   (printTest (pred (minBound::Int))) 
98
99      -- toEnum
100   printTest ((map (toEnum::Int->Int) [1,minBound,maxBound]))
101
102      -- fromEnum
103   printTest ((map fromEnum [(1::Int),minBound,maxBound]))
104
105      -- [x..] aka enumFrom
106   printTest ((take 7 [(1::Int)..]))
107   printTest ((take 7 [((maxBound::Int)-5)..])) -- just in case it doesn't catch the upper bound..
108   
109      -- [x,y..] aka enumFromThen
110   printTest ((take 7 [(1::Int),2..]))
111   printTest ((take 7 [(1::Int),7..]))
112   printTest ((take 7 [(1::Int),1..]))
113   printTest ((take 7 [(1::Int),0..]))
114   printTest ((take 7 [(5::Int),2..]))
115   let x = (minBound::Int) + 1
116   printTest ((take 7 [x, x-1 ..]))
117   let x = (minBound::Int) + 5
118   printTest ((take 7 [x, x-1 ..]))
119   let x = (maxBound::Int) - 5
120   printTest ((take 7 [x, (x+1) ..]))
121
122      -- [x..y] aka enumFromTo
123   printTest ((take 7 ([(1::Int) .. 5])))
124   printTest ((take 4 ([(1::Int) .. 1])))
125   printTest ((take 7 ([(1::Int) .. 0])))
126   printTest ((take 7 ([(5::Int) .. 0])))
127   printTest ((take 7 ([(maxBound-(5::Int)) .. maxBound])))
128   printTest ((take 7 ([(minBound+(5::Int)) .. minBound])))
129
130      -- [x,y..z] aka enumFromThenTo
131   printTest ((take 7 [(5::Int),4..1]))
132   printTest ((take 7 [(5::Int),3..1]))
133   printTest ((take 7 [(5::Int),3..2]))
134   printTest ((take 7 [(1::Int),2..1]))
135   printTest ((take 7 [(2::Int),1..2]))
136   printTest ((take 7 [(2::Int),1..1]))
137   printTest ((take 7 [(2::Int),3..1]))
138
139   let x = (maxBound::Int) - 4
140   printTest ((take 7 [x,(x+1)..maxBound]))
141   let x = (minBound::Int) + 5
142   printTest ((take 7 [x,(x-1)..minBound]))
143
144 testEnumChar :: IO ()
145 testEnumChar = do
146      -- succ
147   printTest ((succ 'a'))
148   printTest ((succ (minBound::Char)))
149   mayBomb (printTest ((succ (maxBound::Char))))
150
151      -- pred
152   printTest ((pred 'b'))
153   printTest (pred (maxBound::Char))
154   mayBomb (printTest (pred (minBound::Char)))
155
156      -- toEnum
157   printTest ((map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]))
158   mayBomb (printTest ((toEnum::Int->Char) (minBound::Int)))
159
160      -- fromEnum
161   printTest ((map fromEnum ['X',minBound,maxBound]))
162
163      -- [x..] aka enumFrom
164   printTest ((take 7 ['\NUL' .. ]))
165   printTest ((take 7 ['\250' .. ]))
166   
167      -- [x,y..] aka enumFromThen
168   printTest ((take 7 ['a','b'..]))
169   printTest ((take 7 ['a','e'..]))
170   printTest ((take 7 ['a','a'..]))
171   printTest ((take 7 ['z','y'..]))
172   printTest ((take 7 ['z','v'..]))
173   let x = '\1'
174   printTest ((take 7 ['\1', '\0' ..]))
175   let x = '\5'
176   printTest ((take 7 ['\5', '\4' ..]))
177   let x = (maxBound::Int) - 5
178   printTest ((take 7 ['\250', '\251' ..]))
179
180      -- [x..y] aka enumFromTo
181   printTest ((take 7 (['a' .. 'e'])))
182   printTest ((take 4 (['a' .. 'a'])))
183   printTest ((take 7 (['b' .. 'a'])))
184   printTest ((take 7 (['e' .. 'a'])))
185   printTest ((take 7 (['\250' .. '\255'])))
186   printTest ((take 7 (['\5' .. '\0'])))
187
188      -- [x,y..z] aka enumFromThenTo
189   printTest ((take 7 ['f','e' .. 'b']))
190   printTest ((take 7 ['g','e' .. 'b']))
191   printTest ((take 7 ['g','d' .. 'c']))
192   printTest ((take 7 ['b','c' .. 'b']))
193   printTest ((take 7 ['c','b' .. 'c']))
194   printTest ((take 7 ['c','b' .. 'b']))
195   printTest ((take 7 ['c','d' .. 'b']))
196   printTest ((take 7 ['\251', '\252' .. maxBound]))
197   printTest ((take 7 ['\5', '\4' .. minBound]))
198
199
200 testEnumUnit :: IO ()
201 testEnumUnit = do
202    -- succ:
203   mayBomb (printTest ((succ ())))
204   mayBomb (printTest ((succ (minBound::()))))
205   mayBomb (printTest ((succ (maxBound::()))))
206        
207    -- pred:
208   mayBomb (printTest ((pred ())))
209   mayBomb (printTest ((pred (minBound::()))))
210   mayBomb (printTest ((pred (maxBound::()))))
211
212    -- toEnum:
213   printTest ((toEnum 0)::())
214   mayBomb   (printTest ((toEnum 1)::()))
215
216    -- fromEnum:
217   printTest ((fromEnum ()))
218
219    -- enumFrom:
220   printTest (([()..]))
221
222    -- enumFromThen:
223   printTest (([(),()..]))
224
225    -- enumFromTo
226   printTest (([()..()]))
227
228    -- enumFromThenTo
229   printTest (([(),()..()]))
230
231 testEnumOrdering :: IO ()
232 testEnumOrdering = do
233    -- succ:
234   printTest ((succ LT))
235   printTest ((succ (minBound::Ordering)))
236   mayBomb (printTest ((succ (maxBound::Ordering))))
237        
238    -- pred:
239   printTest ((pred GT))
240   printTest ((pred (maxBound::Ordering)))
241   mayBomb (printTest ((pred (minBound::Ordering))))
242
243    -- toEnum:
244   printTest ((toEnum 0)::Ordering)
245   mayBomb   (printTest ((toEnum 5)::Ordering))
246
247    -- fromEnum:
248   printTest ((fromEnum LT))
249   printTest ((fromEnum EQ))
250   printTest ((fromEnum GT))
251
252    -- enumFrom:
253   printTest (([LT ..]))
254   printTest (([EQ ..]))
255   printTest (([GT ..]))
256
257    -- enumFromThen:
258   printTest (([LT,EQ ..]))
259   printTest (([EQ,GT ..]))
260   printTest (([EQ,LT ..]))
261   printTest (([LT,GT ..]))
262   printTest (([GT,LT ..]))
263   printTest (take 7 (([GT,GT ..])))
264   printTest (take 7 (([LT,LT ..])))
265
266    -- enumFromTo
267   printTest (([LT .. GT]))
268   printTest (([LT .. EQ]))
269   printTest (([LT .. LT]))
270   printTest (([GT .. LT]))
271   printTest (([GT .. EQ]))
272   printTest (([GT .. GT]))
273
274    -- enumFromThenTo
275   printTest (([LT,EQ .. GT]))
276   printTest (([GT,EQ .. LT]))
277   printTest (([GT,EQ .. EQ]))
278   printTest (([GT,EQ .. GT]))
279   printTest (([GT,EQ .. LT]))
280   printTest (([LT,EQ .. LT]))
281   printTest (([LT,EQ .. GT]))
282   printTest (take 7 (([LT,LT .. GT])))
283   printTest (take 7 (([GT,GT .. LT])))
284
285 testEnumBool :: IO ()
286 testEnumBool = do
287    -- succ:
288   printTest ((succ False))
289   printTest ((succ (minBound::Bool)))
290   mayBomb (printTest ((succ (maxBound::Bool))))
291        
292    -- pred:
293   printTest ((pred True))
294   printTest ((pred (maxBound::Bool)))
295   mayBomb (printTest ((pred (minBound::Bool))))
296
297    -- toEnum:
298   printTest ((toEnum 0)::Bool)
299   mayBomb   (printTest ((toEnum 5)::Bool))
300
301    -- fromEnum:
302   printTest ((fromEnum False))
303   printTest ((fromEnum True))
304
305    -- enumFrom:
306   printTest (([False ..]))
307   printTest (([True ..]))
308
309    -- enumFromThen:
310   printTest (([False,True ..]))
311   printTest (([True,False ..]))
312   printTest ((take 7 ([False,False ..])))
313   printTest ((take 7 ([True,True ..])))
314
315    -- enumFromTo
316   printTest (([False .. True]))
317   printTest (([True .. False]))
318
319    -- enumFromThenTo
320   printTest (take 7 ([False,False .. False]))
321   printTest (take 7 ([False,False .. True]))
322   printTest (take 7 ([False,True .. False]))
323   printTest (take 7 ([False,True .. True]))
324   printTest (take 7 ([True,False .. False]))
325   printTest (take 7 ([True,False .. True]))
326   printTest (take 7 ([True,True ..  False]))
327   printTest (take 7 ([True,True ..  True]))
328
329
330 testEnumInteger :: IO ()
331 testEnumInteger = do
332      -- succ
333   printTest ((succ (0::Integer)))
334   printTest ((succ ((-1)::Integer)))
335
336      -- pred
337   printTest (pred (1::Integer))
338   printTest (pred (0::Integer))
339
340      -- toEnum
341   printTest ((map (toEnum::Int->Integer) [1,minBound,maxBound]))
342
343      -- fromEnum
344   printTest ((map fromEnum [(1::Integer),42,45]))
345
346      -- [x..] aka enumFrom
347   printTest ((take 7 [(1::Integer)..]))
348   printTest ((take 7 [(-5::Integer)..]))
349   
350      -- [x,y..] aka enumFromThen
351   printTest ((take 7 [(1::Integer),2..]))
352   printTest ((take 7 [(1::Integer),7..]))
353   printTest ((take 7 [(1::Integer),1..]))
354   printTest ((take 7 [(1::Integer),0..]))
355   printTest ((take 7 [(5::Integer),2..]))
356
357      -- [x..y] aka enumFromTo
358   printTest ((take 7 ([(1::Integer) .. 5])))
359   printTest ((take 4 ([(1::Integer) .. 1])))
360   printTest ((take 7 ([(1::Integer) .. 0])))
361   printTest ((take 7 ([(5::Integer) .. 0])))
362
363      -- [x,y..z] aka enumFromThenTo
364   printTest ((take 7 [(5::Integer),4..1]))
365   printTest ((take 7 [(5::Integer),3..1]))
366   printTest ((take 7 [(5::Integer),3..2]))
367   printTest ((take 7 [(1::Integer),2..1]))
368   printTest ((take 7 [(2::Integer),1..2]))
369   printTest ((take 7 [(2::Integer),1..1]))
370   printTest ((take 7 [(2::Integer),3..1]))
371
372 testEnumRational :: IO ()
373 testEnumRational = do
374      -- succ
375   printTest ((succ (0::Rational)))
376   printTest ((succ ((-1)::Rational)))
377
378      -- pred
379   printTest (pred (1::Rational))
380   printTest (pred (0::Rational))
381
382      -- toEnum
383   printTest ((map (toEnum::Int->Rational) [1,minBound,maxBound]))
384
385      -- fromEnum
386   printTest ((map fromEnum [(1::Rational),42,45]))
387
388      -- [x..] aka enumFrom
389   printTest ((take 7 [(1::Rational)..]))
390   printTest ((take 7 [(-5::Rational)..]))
391   
392      -- [x,y..] aka enumFromThen
393   printTest ((take 7 [(1::Rational),2..]))
394   printTest ((take 7 [(1::Rational),7..]))
395   printTest ((take 7 [(1::Rational),1..]))
396   printTest ((take 7 [(1::Rational),0..]))
397   printTest ((take 7 [(5::Rational),2..]))
398
399      -- [x..y] aka enumFromTo
400   printTest ((take 7 ([(1::Rational) .. 5])))
401   printTest ((take 4 ([(1::Rational) .. 1])))
402   printTest ((take 7 ([(1::Rational) .. 0])))
403   printTest ((take 7 ([(5::Rational) .. 0])))
404
405      -- [x,y..z] aka enumFromThenTo
406   printTest ((take 7 [(5::Rational),4..1]))
407   printTest ((take 7 [(5::Rational),3..1]))
408   printTest ((take 7 [(5::Rational),3..2]))
409   printTest ((take 7 [(1::Rational),2..1]))
410   printTest ((take 7 [(2::Rational),1..2]))
411   printTest ((take 7 [(2::Rational),1..1]))
412   printTest ((take 7 [(2::Rational),3..1]))
413
414 testEnumRatioInt :: IO ()
415 testEnumRatioInt = do
416      -- succ
417   printTest ((succ (0::Ratio Int)))
418   printTest ((succ ((-1)::Ratio Int)))
419
420      -- pred
421   printTest (pred (1::Ratio Int))
422   printTest (pred (0::Ratio Int))
423
424      -- toEnum
425   printTest ((map (toEnum::Int->Ratio Int) [1,minBound,maxBound]))
426
427      -- fromEnum
428   printTest ((map fromEnum [(1::Ratio Int),42,45]))
429
430      -- [x..] aka enumFrom
431   printTest ((take 7 [(1::Ratio Int)..]))
432   printTest ((take 7 [(-5::Ratio Int)..]))
433   printTest ((take 7 [((toEnum ((maxBound::Int)-5))::Ratio Int)..]))
434   
435      -- [x,y..] aka enumFromThen
436   printTest ((take 7 [(1::Ratio Int),2..]))
437   printTest ((take 7 [(1::Ratio Int),7..]))
438   printTest ((take 7 [(1::Ratio Int),1..]))
439   printTest ((take 7 [(1::Ratio Int),0..]))
440   printTest ((take 7 [(5::Ratio Int),2..]))
441   let x = (toEnum ((minBound::Int) + 1))::Ratio Int
442   printTest ((take 7 [x, x-1 ..]))
443   let x = (toEnum ((minBound::Int) + 5))::Ratio Int
444   printTest ((take 7 [x, x-1 ..]))
445   let x = (toEnum ((maxBound::Int) - 5))::Ratio Int
446   printTest ((take 7 [x, (x+1) ..]))
447
448      -- [x..y] aka enumFromTo
449   printTest ((take 7 ([(1::Ratio Int) .. 5])))
450   printTest ((take 4 ([(1::Ratio Int) .. 1])))
451   printTest ((take 7 ([(1::Ratio Int) .. 0])))
452   printTest ((take 7 ([(5::Ratio Int) .. 0])))
453   let x = (toEnum (maxBound - (5::Int))) :: Ratio Int
454   let y = (toEnum (maxBound::Int)) :: Ratio Int
455   printTest ((take 7 ([x..y])))
456   let x = (toEnum (minBound + (5::Int))) :: Ratio Int
457   let y = (toEnum (minBound::Int)) :: Ratio Int
458   printTest ((take 7 ([x..y])))
459
460      -- [x,y..z] aka enumFromThenTo
461   printTest ((take 7 [(5::Ratio Int),4..1]))
462   printTest ((take 7 [(5::Ratio Int),3..1]))
463   printTest ((take 7 [(5::Ratio Int),3..2]))
464   printTest ((take 7 [(1::Ratio Int),2..1]))
465   printTest ((take 7 [(2::Ratio Int),1..2]))
466   printTest ((take 7 [(2::Ratio Int),1..1]))
467   printTest ((take 7 [(2::Ratio Int),3..1]))
468
469   let x = (toEnum ((maxBound::Int) - 4)) :: Ratio Int
470   let y = (toEnum (maxBound::Int)) :: Ratio Int
471   printTest ((take 7 [x,(x+1)..y]))
472   let x = (toEnum ((minBound::Int) + 5)) :: Ratio Int
473   let y = (toEnum (minBound::Int)) :: Ratio Int
474   printTest ((take 7 [x,(x-1)..y]))
475
476 --
477 --
478 --  Utils
479 --
480 --
481
482
483 mayBomb x = catchAllIO x errorHandler
484
485 errorHandler :: Exception -> IO ()
486 errorHandler e =
487   case justErrors e of
488     Just t -> putStrLn ("error " ++ show t)
489     _      -> return ()
490  
491
492 test :: Show a => String -> String -> a -> IO ()
493 test test_nm expected val = do
494    putStr test_nm
495    if expected == got then
496       putStrLn ": SUCCEEDED"
497     else do
498       putStr   ": FAILED"
499       putStrLn ("( expected: " ++ show expected ++ " , got: " ++ show got ++ " )")
500   where
501    got = show val