mirror of
https://github.com/iritmaximus/haskell.git
synced 2026-10-12 19:13:39 +03:00
140 lines
5.1 KiB
Haskell
140 lines
5.1 KiB
Haskell
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
|
|
|
|
module Set11aTest where
|
|
|
|
import Mooc.Test
|
|
import Mooc.Th
|
|
|
|
import Control.Monad
|
|
import Data.List
|
|
import Data.IORef
|
|
import GHC.IO.Handle
|
|
import System.Directory
|
|
import System.IO
|
|
|
|
import Test.QuickCheck
|
|
import Test.QuickCheck.Monadic
|
|
|
|
import Set11b hiding (counter)
|
|
|
|
main = score tests
|
|
|
|
tests = [(1,"appendAll",[ex1])
|
|
,(2,"swapIORefs",[ex2])
|
|
,(3,"doubleCall",[ex3_doubleCall, ex3_doubleCall_2])
|
|
,(4,"composeIO",[ex4_composeIO_1, ex4_composeIO_2])
|
|
,(5,"hFetchLines",[ex5])
|
|
,(6,"hSelectLines",[ex6_hSelectLines])
|
|
,(7,"interact'",[ex7_interact_terminates, ex7_interact_example, ex7_interact_loop])]
|
|
|
|
-- -- -- -- --
|
|
|
|
word = listOf1 (choose ('a','z'))
|
|
|
|
ex1 = forAllBlind word $ \init ->
|
|
forAllBlind (listOf word) $ \ws ->
|
|
counterexample ("appendAll ref " ++ show ws) $
|
|
counterexample (" Initial value of ref was: " ++ show init) $
|
|
monadicIO $ do ref <- run $ newIORef init
|
|
run $ appendAll ref ws
|
|
out <- run $ readIORef ref
|
|
stop_ $ counterexample " Final value in ref" $ out ?== concat (init:ws)
|
|
|
|
ex2 = forAllBlind word $ \w1 ->
|
|
forAllBlind word $ \w2 ->
|
|
counterexample "swapIORefs r1 r2" $
|
|
counterexample (" Initial value of r1: "++show w1) $
|
|
counterexample (" Initial value of r2: "++show w2) $
|
|
monadicIO $ do r1 <- run $ newIORef w1
|
|
r2 <- run $ newIORef w2
|
|
run $ swapIORefs r1 r2
|
|
o1 <- run $ readIORef r1
|
|
o2 <- run $ readIORef r2
|
|
stop_ $ conjoin [counterexample " readIORef r1" $ o1 ?== w2
|
|
,counterexample " readIORef r2" $ o2 ?== w1]
|
|
|
|
ex3_doubleCall =
|
|
forAllBlind (choose (0,20::Int)) $ \i ->
|
|
counterexample ("doubleCall (return (return "++show i++"))") $
|
|
($ doubleCall (return (return i))) . withNoInput $
|
|
check (?=="") (?==i)
|
|
|
|
ex3_doubleCall_2 =
|
|
forAllBlind word $ \w1 ->
|
|
forAllBlind word $ \w2 ->
|
|
counterexample ("doubleCall (do putStrLn "++show w1++"; return (putStrLn "++show w2++"))") $
|
|
($ doubleCall (do putStrLn w1; return (putStrLn w2))) . withNoInput $
|
|
check (?==(w1++"\n"++w2++"\n")) (?==())
|
|
|
|
ex4_composeIO_1 =
|
|
forAllBlind word $ \w ->
|
|
forAllBlind word $ \v ->
|
|
counterexample ("compose putStrLn (\\x -> do putStrLn x; getLine) " ++ show w) $
|
|
($ compose putStrLn (\x -> do putStrLn x; getLine) w) . withInput (v++"\n") $
|
|
checkOutput (?==w++"\n"++v++"\n")
|
|
|
|
ex4_composeIO_2 =
|
|
forAll_ $ \(i::Int) ->
|
|
counterexample ("compose (\\x -> return (x*2)) (\\y -> return (y+1)) " ++ show i) $
|
|
($ compose (return . (*2)) (return . (+1)) i) . withNoInput $
|
|
checkResult (?== (i+1)*2)
|
|
|
|
ex5 = forAllBlind (listOf1 word) $ \lines ->
|
|
counterexample ("Contents of handle h:\n"++unlines lines) $
|
|
counterexample "hFetchLines h" $
|
|
monadicIO $ do
|
|
dir <- run $ getTemporaryDirectory
|
|
(_,h) <- run $ openTempFile dir "hSelectLines.in"
|
|
run $ hPutStr h $ unlines lines
|
|
run $ hSeek h AbsoluteSeek 0
|
|
outs <- run $ hFetchLines h
|
|
length outs `seq` do
|
|
run $ hClose h
|
|
stop_ $ outs ?== lines
|
|
|
|
ex6_hSelectLines =
|
|
forAllBlind (listOf1 word) $ \lines ->
|
|
forAllBlind (fmap (nub.sort) . listOf1 $ choose (1,length lines)) $ \inds ->
|
|
counterexample ("Contents of handle h:\n"++unlines lines) $
|
|
counterexample ("hSelectLines h "++show inds) $
|
|
monadicIO $ do
|
|
dir <- run $ getTemporaryDirectory
|
|
(path,h) <- run $ openTempFile dir "hSelectLines.in"
|
|
run $ hPutStr h $ unlines lines
|
|
run $ hSeek h AbsoluteSeek 0
|
|
outs <- run $ hSelectLines h inds
|
|
length outs `seq` do
|
|
run $ hClose h
|
|
stop_ $ counterexample (" was: "++show outs) $
|
|
conjoin [counterexample "Length of result" $ length outs ?== length inds
|
|
,conjoin [counterexample ("result!!"++show i) $ outs!!i ?== lines!!((inds!!i)-1)
|
|
| i <- [0..length inds-1]]]
|
|
|
|
counter :: (String,Integer) -> (Bool,String,Integer)
|
|
counter ("inc",n) = (True,"done",n+1)
|
|
counter ("print",n) = (True,show n,n)
|
|
counter ("quit",n) = (False,"bye bye",n)
|
|
|
|
ex7_interact_terminates =
|
|
forAllBlind word $ \w1 ->
|
|
forAllBlind word $ \w2 ->
|
|
forAllBlind (choose (0::Int,100)) $ \state ->
|
|
counterexample ("let f (input,state) = (False,input,state) in interact' f "++show state) $
|
|
($ let f (input,state) = (False,input,state) in interact' f state) . withInput (unlines [w1,w2]) $
|
|
check (?==(w1++"\n")) (?==state)
|
|
|
|
ex7_interact_example =
|
|
$(testing' [|interact' counter 1|]) . withInput (unlines ["print","inc","inc","print","quit"]) $
|
|
check (?==unlines ["1","done","done","3","bye bye"]) (?==3)
|
|
|
|
ex7_interact_loop =
|
|
forAllBlind (choose (0::Int,100)) $ \state ->
|
|
forAllBlind (choose (0::Int,5)) $ \steps ->
|
|
forAllBlind word $ \w ->
|
|
forAllBlind (word `suchThat` (/=w)) $ \end ->
|
|
let input = unlines $ replicate steps w ++ [end]
|
|
output = unlines $ map show [state..state+steps]
|
|
in counterexample ("let f (input,state) = (input=="++show w++",show state,state+1) in interact' f "++show state) $
|
|
($ let f (input,state) = (input==w,show state,state+1) in interact' f state) . withInput input $
|
|
check (?==output) (?==state+steps+1)
|