@@ -7,7 +7,9 @@ module Main where
77
88import Common
99import Control.Comonad.Cofree (Cofree ((:<) ))
10+ import Control.Monad (unless )
1011import Data.Bifunctor (second )
12+ import Data.List (isInfixOf )
1113import Data.Ratio
1214import PrettyPrint
1315import qualified System.IO.Strict as Strict
@@ -74,12 +76,24 @@ assertExpr :: String -> String -> Assertion
7476assertExpr input expected = do
7577 res <- evalExprString input
7678 case res of
77- Left err -> assertFailure $ " Evaluation failed: " <> err
79+ Left err -> unless (expected `isInfixOf` err) . assertFailure $ " Evaluation failed: " <> err
7880 Right val -> val @?= expected
7981
8082rationalToString :: Ratio Integer -> String
8183rationalToString r = " (" <> show (numerator r) <> " ," <> show (denominator r) <> " )"
8284
85+ genInt :: Gen Int
86+ genInt = choose (0 , 100 )
87+
88+ genInt2 :: Gen Int
89+ genInt2 = choose (0 , 85 )
90+
91+ genInt3 :: Gen Int
92+ genInt3 = choose (0 , 16 )
93+
94+ genInt4 :: Gen Int
95+ genInt4 = choose (0 , 6 )
96+
8397-----------------
8498------ Unit Tests
8599-----------------
@@ -88,19 +102,23 @@ unitTestsNatArithmetic :: TestTree
88102unitTestsNatArithmetic = testGroup " Unit tests on natural arithmetic expresions"
89103 [ testCase " test addition" $ assertExpr " dPlus 1 2" (show (1 + 2 ))
90104 , testCase " test subtraction" $ assertExpr " dMinus 5 3" (show (5 - 3 ))
105+ , testCase " test substraction lower limit" $ assertExpr " dMinus 0 1" " 0"
91106 , testCase " test multiplication" $ assertExpr " dTimes 3 4" (show (3 * 4 ))
92107 , testCase " test division" $ assertExpr " dDiv 8 2" (show (8 `div` 2 ))
108+ , testCase " test division by zero" $ assertExpr " dDiv 1 0" " abort:"
109+ , testCase " test equality" $ assertExpr " dEqual 3 3" " 1"
110+ , testCase " test inequality" $ assertExpr " dEqual 3 4" " 0"
93111 , testCase " test modulo" $ assertExpr " dMod 10 3" (show (10 `mod` 3 ))
94112 , testCase " test gcd" $ assertExpr " gcd 48 18" (show (gcd 48 18 ))
95113 , testCase " test lcm" $ assertExpr " lcm 12 15" (show (lcm 12 15 ))
96114 , testCase " test exponentiation" $ assertExpr " dPow 2 3" (show (2 ^ 3 ))
115+ , testCase " test exponentiation with zero exponent" $ assertExpr " dPow 5 0" " 1"
116+ , testCase " test raise zero to the zero power" $ assertExpr " dPow 0 0" " 1"
97117 , testCase " test factorial" $ assertExpr " dFactorial 5" (show (product [1 .. 5 ]))
98- , testCase " test equality" $ assertExpr " dEqual 3 3" (show 1 )
99- , testCase " test inequality" $ assertExpr " dEqual 3 4" (show 0 )
100118 ]
101119
102120unitTestsRatArithmetic :: TestTree
103- unitTestsRatArithmetic = testGroup " Unit tests on natural arithmetic expresions"
121+ unitTestsRatArithmetic = testGroup " Unit tests on rational arithmetic expresions"
104122 [ testCase " test addition" $ do
105123 let exp = rationalToString (1 % 2 + 1 % 2 )
106124 assertExpr " right (rPlus (fromRational 1 2) (fromRational 1 2))" exp
@@ -113,14 +131,72 @@ unitTestsRatArithmetic = testGroup "Unit tests on natural arithmetic expresions"
113131 , testCase " test division" $ do
114132 let exp = rationalToString ((1 % 2 ) / (1 % 2 ))
115133 assertExpr " right (rDiv (fromRational 1 2) (fromRational 1 2))" exp
134+ , testCase " test division by zero" $ assertExpr " rDiv (fromRational 1 2) (fromRational 0 1)" " abort:"
116135 ]
117136
118137---------------------
119138------ Property Tests
120139---------------------
121140
122141qcPropsNatArithmetic = testGroup " Property tests on natural arithmetic expressions (QuickCheck)"
123- [
142+ [ QC. testProperty " Commutative Additive" $
143+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
144+ x <- generate genInt
145+ y <- generate genInt
146+ res <- evalExprString
147+ ( " dEqual (dPlus " <> show x <> " " <> show y <>
148+ " ) (dPlus " <> show y <> " " <> show x <> " )" )
149+ pure $ case res of
150+ Left err -> err === " 1"
151+ Right val -> val === " 1"
152+ , QC. testProperty " Associative Additive" $
153+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
154+ x <- generate genInt2
155+ y <- generate genInt2
156+ z <- generate genInt2
157+ res <- evalExprString
158+ ( " dEqual (dPlus (dPlus " <> show x <> " " <> show y
159+ <> " )" <> show z <> " ) (dPlus " <> show x <> " (dPlus "
160+ <> show y <> " " <> show z <> " ))" )
161+ pure $ case res of
162+ Left err -> err === " 1"
163+ Right val -> val === " 1"
164+ , QC. testProperty " Neutral Additive" $
165+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
166+ x <- generate genInt
167+ res <- evalExprString (" dPlus " <> show x <> " 0" )
168+ pure $ case res of
169+ Left err -> err === show x
170+ Right val -> val === show x
171+ , QC. testProperty " Commutative Multiplicative" $
172+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
173+ x <- generate genInt3
174+ y <- generate genInt3
175+ res <- evalExprString
176+ ( " dEqual (dTimes " <> show x <> " " <> show y <>
177+ " ) (dTimes " <> show y <> " " <> show x <> " )" )
178+ pure $ case res of
179+ Left err -> err === " 1"
180+ Right val -> val === " 1"
181+ , QC. testProperty " Associative Multiplicative" $
182+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
183+ x <- generate genInt4
184+ y <- generate genInt4
185+ z <- generate genInt4
186+ res <- evalExprString
187+ ( " dEqual (dTimes (dTimes " <> show x <> " " <> show y
188+ <> " )" <> show z <> " ) (dTimes " <> show x <> " (dTimes "
189+ <> show y <> " " <> show z <> " ))" )
190+ pure $ case res of
191+ Left err -> err === " 1"
192+ Right val -> val === " 1"
193+ , QC. testProperty " Neutral Multiplicative" $
194+ \ () -> withMaxSuccess 16 . QC. idempotentIOProperty $ do
195+ x <- generate genInt
196+ res <- evalExprString (" dTimes " <> show x <> " 1" )
197+ pure $ case res of
198+ Left err -> err === show x
199+ Right val -> val === show x
124200 ]
125201
126202qcPropsRatArithmetic = testGroup " Property tests on rational arithmetic expressions (QuickCheck)"
0 commit comments