import Test.QuickCheck
import Test.Timing
import Control.Concurrent (threadDelay)
import System.IO.Unsafe (unsafePerformIO)


powers base exps = map (truncate . (base **))  exps


sleep t =
    threadDelay $ truncate (1000000.0 * t)


test = mapM timeM delays >>= return . zip ps
       where delays = map threadDelay ps
             ps = powers 10 [0..6]


test2 = mapM timeM delays >>= return . map (\(x,rx) -> realToFrac rx - fromIntegral x * 10.0 ** (-6.0)) . zip ps 
       where delays = map threadDelay ps
             ps = powers 10 [0..6]

-- Fail if the evaluation of sleep deviates by more than one percent
-- from the specified time.  The GHC runtime seems to be at least that
-- accurate in implementing a delay.  Any larger deviation presumably
-- means that the evaluation is being short circuited somehow.

prop_time t =
    reasonableTime t ==>
                       0.01 > (microseconds - unsafePerformIO (time (unsafePerformIO (threadDelay t))))
        where microseconds = fromIntegral t * 0.000001
              reasonableTime t = t >= 0 && t < 1000000

main = quickCheck prop_time
