{-# LANGUAGE Arrows #-} {-# LANGUAGE CPP #-} -- | -- Description : Test cases for signal functions working with events -- Copyright : (c) Antony Courtney and Henrik Nilsson, Yale University, 2003-2004 -- Authors : Antony Courtney, Henrik Nilsson -- Notes pertaining to regression tests: -- - Add test cases for Yampa. There should be at least one test case for each -- "non-trivial" entity exported from Yampa. -- -- - Make tests cases for after and repeatedly more robust. Must not -- fail due to small discrepancies in floating point implementation. -- -- 01-May-2002: evsrc_t7 currently fails in hugs. module Test.FRP.Yampa.EventS ( tests ) where #if __GLASGOW_HASKELL__ < 710 import Control.Applicative ((<*>)) import Data.Functor ((<$>)) #endif import Test.QuickCheck hiding (once, sample) import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck (testProperty) import FRP.Yampa as Yampa import FRP.Yampa.EventS (snap, sampleWindow, recur, andThen, snapAfter, sample) import FRP.Yampa.Stream import FRP.Yampa.QuickCheck import FRP.Yampa.LTLFuture import TestsCommon tests :: TestTree tests = testGroup "Regression tests for FRP.Yampa.EventS" [ testProperty "never (0, fixed)" (property $ evsrc_t0 ~= evsrc_t0r) , testProperty "Events > No event" prop_event_noevent , testProperty "eventS (1, fixed)" (property $ evsrc_t1 ~= evsrc_t1r) , testProperty "Events > Now" prop_event_now , testProperty "eventS (2, fixed)" (property $ evsrc_t2 ~= evsrc_t2r) , testProperty "Events > After 0.0" prop_event_after_0 , testProperty "eventS (3, fixed)" (property $ evsrc_t3 ~= evsrc_t3r) , testProperty "eventS (4, fixed)" (property $ evsrc_t4 ~= evsrc_t4r) , testProperty "eventS (5, fixed)" (property $ evsrc_t5 ~= evsrc_t5r) , testProperty "eventS (6, fixed)" (property $ evsrc_t6 ~= evsrc_t6r) , testProperty "eventS (7, fixed)" (property $ evsrc_t7 ~= evsrc_t7r) , testProperty "eventS (8, fixed)" (property $ evsrc_t8 ~= evsrc_t8r) , testProperty "eventS (9, fixed)" (property $ evsrc_t9 ~= evsrc_t9r) , testProperty "eventS (10, fixed)" (property $ evsrc_t10 ~= evsrc_t10r) , testProperty "eventS (11, fixed)" (property $ evsrc_t11 ~= evsrc_t11r) , testProperty "eventS (28, fixed)" (property $ evsrc_t28 ~= evsrc_t28r) , testProperty "delayEvent (0, fixed)" (property $ evsrc_t30 ~= evsrc_t30r) , testProperty "delayEvent (1, qc)" propDelayEvent , testProperty "delayEventCat (0, fixed)" (property $ evsrc_t29 ~= evsrc_t29r) , testProperty "eventS (12, fixed)" (property $ evsrc_t12 ~= evsrc_t12r) , testProperty "eventS (13, fixed)" (property $ evsrc_t13 ~= evsrc_t13r) , testProperty "iEdge (0, qc)" propIEdge , testProperty "edgeTag (0, qc)" propEdgeTag , testProperty "edgeJust (0, qc)" propEdgeJust , testProperty "eventS (14, fixed)" (property $ evsrc_t14 ~= evsrc_t14r) , testProperty "eventS (15, fixed)" (property $ evsrc_t15 ~= evsrc_t15r) , testProperty "eventS (16, fixed)" (property $ evsrc_t16 ~= evsrc_t16r) , testProperty "notYet (0, qc)" propNotYet , testProperty "eventS (17, fixed)" (property $ evsrc_t17 ~= evsrc_t17r) , testProperty "eventS (18, fixed)" (property $ evsrc_t18 ~= evsrc_t18r) , testProperty "eventS (19, fixed)" (property $ evsrc_t19 ~= evsrc_t19r) , testProperty "eventS (20, fixed)" (property $ evsrc_t20 ~= evsrc_t20r) , testProperty "eventS (21, fixed)" (property $ evsrc_t21 ~= evsrc_t21r) , testProperty "eventS (22, fixed)" (property $ evsrc_t22 ~= evsrc_t22r) , testProperty "eventS (23, fixed)" (property $ evsrc_t23 ~= evsrc_t23r) , testProperty "eventS (24, fixed)" (property $ evsrc_t24 ~= evsrc_t24r) , testProperty "eventS (25, fixed)" (property $ evsrc_t25 ~= evsrc_t25r) , testProperty "eventS (26, fixed)" (property $ evsrc_t26 ~= evsrc_t26r) , testProperty "eventS (27, fixed)" (property $ evsrc_t27 ~= evsrc_t27r) , testProperty "snap (fixed)" (property $ utils_t10 ~= utils_t10r) , testProperty "snapAfter (fixed)" (property $ utils_t11 ~= utils_t11r) , testProperty "sample (fixed)" (property $ utils_t12 ~= utils_t12r) , testProperty "sampleWindow (0, fixed)" (property $ utils_t15 ~= utils_t15r) , testProperty "sampleWindow (1, fixed)" (property $ utils_t16 ~= utils_t16r) , testProperty "after (0, fixed)" (property $ utils_t13 ~= utils_t13r) , testProperty "after (1, fixed)" (property $ utils_t14 ~= utils_t14r) ] -- * Basic event sources evsrc_t0 :: [Event ()] evsrc_t0 = testSF1 never evsrc_t0r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] prop_event_noevent = forAll myStream $ evalT $ Always $ prop (sfNever, const (== noEvent)) where myStream :: Gen (SignalSampleStream Float) myStream = uniDistStream sfNever :: SF Float (Event Float) sfNever = never evsrc_t1 :: [Event Int] evsrc_t1 = testSF1 (now 42) evsrc_t1r :: [Event Int] evsrc_t1r = [ Event 42, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] prop_event_now = forAll myStream $ evalT $ -- (sf, p0) /\ O [] (sf, pn) And (prop (sf, p0)) -- Initially (Next $ Always $ prop (sf, pn)) -- After first sample where sf = Yampa.now 42.0 p0 x y = y == Event 42.0 pn x y = y == noEvent myStream :: Gen (SignalSampleStream Float) myStream = uniDistStream evsrc_t2 :: [Event Int] evsrc_t2 = testSF1 (after 0.0 42) evsrc_t2r :: [Event Int] evsrc_t2r = [ Event 42, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] prop_event_after_0 = forAll myStream $ evalT $ -- (sf, p0) /\ O [] (sf, pn) And (prop (sf, p0)) -- Initially (Next $ Always $ prop (sf, pn)) -- After first sample where sf = after 0.0 42.0 p0 x y = y == Event 42.0 pn x y = y == noEvent myStream :: Gen (SignalSampleStream Float) myStream = uniDistStream evsrc_t3 :: [Event Int] evsrc_t3 = testSF1 (after 3.0 42) evsrc_t3r :: [Event Int] evsrc_t3r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , Event 42, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t4 :: [Event Int] evsrc_t4 = testSF1 (after 3.01 42) evsrc_t4r :: [Event Int] evsrc_t4r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, Event 42, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t5 :: [Event Int] evsrc_t5 = testSF1 (repeatedly 0.795 42) evsrc_t5r :: [Event Int] evsrc_t5r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 1.0 s , NoEvent, NoEvent, Event 42, NoEvent -- 2.0 s , NoEvent, Event 42, NoEvent, NoEvent -- 3.0 s , Event 42, NoEvent, NoEvent, NoEvent -- 4.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 5.0 s , NoEvent ] evsrc_t6 :: [Event Int] evsrc_t6 = testSF1 (repeatedly 0.29999 42) evsrc_t6r :: [Event Int] evsrc_t6r = [ NoEvent, NoEvent, Event 42, Event 42 -- 0.0 s , Event 42, Event 42, Event 42, NoEvent -- 1.0 s , Event 42, Event 42, Event 42, Event 42 -- 2.0 s , Event 42, NoEvent, Event 42, Event 42 -- 3.0 s , Event 42, Event 42, Event 42, NoEvent -- 4.0 s , Event 42, Event 42, Event 42, Event 42 -- 5.0 s , Event 42 ] evsrc_t7 :: [Event Int] evsrc_t7 = testSF1 (repeatedly 0.24 42) evsrc_t7r :: [Event Int] evsrc_t7r = [ NoEvent, Event 42, Event 42, Event 42 -- 0.0 s , Event 42, Event 42, Event 42, Event 42 -- 1.0 s , Event 42, Event 42, Event 42, Event 42 -- 2.0 s , Event 42, Event 42, Event 42, Event 42 -- 3.0 s , Event 42, Event 42, Event 42, Event 42 -- 4.0 s , Event 42, Event 42, Event 42, Event 42 -- 5.0 s , Event 42 ] evsrc_t8 :: [Event Int] evsrc_t8 = testSF1 (afterEach [ (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4) , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8) , (0.10, 9), (2.00, 10) ] ) evsrc_t8r :: [Event Int] evsrc_t8r = [ Event 1, Event 3, Event 5, NoEvent -- 0.0 s , NoEvent, Event 6, Event 9, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, Event 10, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t9 :: [Event Int] evsrc_t9 = testSF1 (afterEach [ (2.03, 0) , (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4) , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8) , (0.10, 9), (2.00, 10), (0.00, 11), (0.00, 12) ] ) evsrc_t9r :: [Event Int] evsrc_t9r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, Event 0, Event 4, NoEvent -- 2.0 s , NoEvent, Event 6, Event 9, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, Event 10, NoEvent -- 5.0 s , NoEvent ] evsrc_t10 :: [Event [Int]] evsrc_t10 = testSF1 (afterEachCat [ (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4) , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8) , (0.10, 9), (2.00, 10) ] ) evsrc_t10r :: [Event [Int]] evsrc_t10r = [ Event [1,2], Event [3,4], Event [5], NoEvent -- 0.0 s , NoEvent, Event [6,7,8], Event [9], NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, Event [10], NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t11 :: [Event [Int]] evsrc_t11 = testSF1 (afterEachCat [ (2.03, 0) , (0.00, 1), (0.00, 2), (0.01, 3), (0.23, 4) , (0.02, 5), (0.75, 6), (0.10, 7), (0.10, 8) , (0.10, 9), (2.00, 10) ] ) evsrc_t11r :: [Event [Int]] evsrc_t11r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, Event [0,1,2,3], Event [4,5], NoEvent -- 2.0 s , NoEvent, Event [6,7,8], Event [9], NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, Event [10], NoEvent -- 5.0 s , NoEvent ] propDelayEvent :: Property propDelayEvent = forAll delayFactorG $ \delayFactor -> forAll myStream $ evalT $ Always $ SP $ (==) <$> originalSF delayFactor <*> sfModelDelayEvent delayFactor where -- SF under test originalSF :: Int -> SF () (Event ()) originalSF factor = time >>> arr cos >>> arr (< 0) >>> edge >>> delayEvent (fromIntegral factor * delay) -- Model SF that applies the delay internally sfModelDelayEvent :: Int -> SF () (Event ()) sfModelDelayEvent factor = time >>> arr (\x -> x - (fromIntegral factor * delay)) >>> arr cos >>> arr (< 0) >>> edge -- Generator: Factor by which the signal is delayed delayFactorG :: Gen Int delayFactorG = getPositive <$> arbitrary -- Generator: Random input stream. Delays and values are fixed but the -- length is not. myStream :: Gen (SignalSampleStream ()) myStream = fixedDelayStream delay -- Constant: Max delay delay :: DTime delay = 0.01 evsrc_t28 :: [(Event Int, Event Int)] evsrc_t28 = embed (repeatedly 0.5 () >>> accumBy (\n _ -> n + 1) 0 >>> identity &&& delayEvent 2.0) (deltaEncode 0.125 (replicate 50 ())) evsrc_t28r = [ (NoEvent,NoEvent), (NoEvent,NoEvent) -- 0.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 1,NoEvent), (NoEvent,NoEvent) -- 0.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 2,NoEvent), (NoEvent,NoEvent) -- 1.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 3,NoEvent), (NoEvent,NoEvent) -- 1.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 4,NoEvent), (NoEvent,NoEvent) -- 2.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 5,Event 1), (NoEvent,NoEvent) -- 2.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 6,Event 2), (NoEvent,NoEvent) -- 3.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 7,Event 3), (NoEvent,NoEvent) -- 3.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 8,Event 4), (NoEvent,NoEvent) -- 4.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 9,Event 5), (NoEvent,NoEvent) -- 4.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 10,Event 6), (NoEvent,NoEvent) -- 5.0 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 11,Event 7), (NoEvent,NoEvent) -- 5.5 s , (NoEvent,NoEvent), (NoEvent,NoEvent) , (Event 12,Event 8), (NoEvent,NoEvent) -- 6.0 s ] -- "delayEvent" in a feedback loop. Should work like "repeatedly". evsrc_t30 :: [(Event ())] evsrc_t30 = embed (now () >>> (loop $ arr (uncurry lMerge) >>> delayEvent 1.0 >>> arr dup)) (deltaEncode 0.125 (replicate 50 ())) evsrc_t30r :: [(Event ())] evsrc_t30r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 0.5 s , Event (), NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.5 s , Event (), NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.5 s , Event (), NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.5 s , Event (), NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.5 s , Event (), NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.5 s , Event (), NoEvent -- 6.0 s ] evsrc_t29 :: [Event [Double]] evsrc_t29 = embed (time &&& repeatedly 0.5001 () >>> arr (\(t,e) -> e `tag` t) >>> delayEventCat 3.0) input where dts = replicate 40 0.1 ++ [2.0] ++ replicate 40 0.1 input = ((), [(dt, Just ()) | dt <- dts]) {- Resulting input to the delay for reference: [ NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, Event 0.6, NoEvent, NoEvent, NoEvent -- 0.5 s , NoEvent, Event 1.1, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, Event 1.6, NoEvent, NoEvent, NoEvent -- 1.5 s , NoEvent, Event 2.1, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, Event 2.6, NoEvent, NoEvent, NoEvent -- 2.5 s , NoEvent, Event 3.1, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, Event 3.6, NoEvent, NoEvent, NoEvent -- 3.5 s , NoEvent -- 4.0 s , Event 6.0, Event 6.1, NoEvent, NoEvent, NoEvent -- 6.0 s , NoEvent, Event 6.6, NoEvent, NoEvent, NoEvent -- 6.5 s , NoEvent, Event 7.1, NoEvent, NoEvent, NoEvent -- 7.0 s , NoEvent, Event 7.6, NoEvent, NoEvent, NoEvent -- 7.5 s , NoEvent, Event 8.1, NoEvent, NoEvent, NoEvent -- 8.0 s , NoEvent, Event 8.6, NoEvent, NoEvent, NoEvent -- 8.5 s , NoEvent, Event 9.1, NoEvent, NoEvent, NoEvent -- 9.0 s , NoEvent, Event 9.6, NoEvent, NoEvent, NoEvent -- 9.5 s , NoEvent -- 10.0 s ] -} evsrc_t29r = [ NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 0.5 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 1.5 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 2.5 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, Event [0.6], NoEvent, NoEvent, NoEvent -- 3.5 s , NoEvent -- 4.0 s , Event [1.1, 1.6, 2.1, 2.6] -- 6.0 s , NoEvent, Event [3.1], NoEvent, NoEvent , NoEvent, NoEvent, Event [3.6], NoEvent, NoEvent -- 6.5 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 7.0 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 7.5 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 8.0 s , NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 8.5 s , NoEvent, Event [6.0], Event [6.1], NoEvent, NoEvent -- 9.0 s , NoEvent, NoEvent, Event [6.6], NoEvent, NoEvent -- 9.5 s , NoEvent -- 10.0 s ] evsrc_t12 :: [Event ()] evsrc_t12 = testSF1 (localTime >>> arr (>=0) >>> edge) evsrc_t12r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t13 :: [Event ()] evsrc_t13 = testSF1 (localTime >>> arr (>=4.26) >>> edge) evsrc_t13r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, Event (), NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] propIEdge :: Property propIEdge = forAll initialValG $ \initialVal -> forAll myStream $ evalT $ Always $ SP $ (==) <$> originalSF initialVal <*> modelSF initialVal where -- SF under test originalSF :: Bool -> SF Bool (Event ()) originalSF = iEdge -- Model SF that behaves like edge except for the initial sample modelSF :: Bool -> SF Bool (Event ()) modelSF k = proc (x) -> do t <- time -< () e <- edge -< x let result | t == 0 && not k && x = Event () | t == 0 && k = NoEvent | otherwise = e returnA -< result -- Generator: Initialization value for iEdge initialValG :: Gen Bool initialValG = arbitrary -- Generator: Random input stream. myStream :: Gen (SignalSampleStream Bool) myStream = uniDistStream propEdgeTag :: Property propEdgeTag = forAll paramValG $ \paramVal -> forAll myStream $ evalT $ Always $ SP $ (==) <$> originalSF paramVal <*> modelSF paramVal where -- SF under test originalSF :: Int -> SF Bool (Event Int) originalSF = edgeTag -- Model SF that tags the value in the event, after applying edge modelSF :: Int -> SF Bool (Event Int) modelSF k = edge >>^ arr (tagWith k) -- Generator: Tagging value paramValG :: Gen Int paramValG = arbitrary -- Generator: Random input stream. myStream :: Gen (SignalSampleStream Bool) myStream = uniDistStream propEdgeJust :: Property propEdgeJust = forAll myStream $ evalT $ Always $ SP $ (==) <$> originalSF <*> modelSF where -- SF under test originalSF :: SF (Maybe Int) (Event Int) originalSF = edgeJust -- Model SF modelSF :: SF (Maybe Int) (Event Int) modelSF = loopPre (Just 0) $ arr $ \v@(n, _) -> case v of (Just x, Nothing) -> (Event x, n) _ -> (NoEvent, n) -- Generator: Random input stream. myStream :: Gen (SignalSampleStream (Maybe Int)) myStream = uniDistStream -- Raising edge detector. evsrc_isEdge False False = Nothing evsrc_isEdge False True = Just () evsrc_isEdge True True = Nothing evsrc_isEdge True False = Nothing evsrc_t14 :: [Event ()] evsrc_t14 = testSF1 (localTime >>> arr (>=0) >>> edgeBy evsrc_isEdge False) evsrc_t14r = [ Event (), NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t15 :: [Event ()] evsrc_t15 = testSF1 (localTime >>> arr (>=4.26) >>> edgeBy evsrc_isEdge False) evsrc_t15r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, Event (), NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] -- Raising and falling edge detector. evsrc_isEdge2 False False = Nothing evsrc_isEdge2 False True = Just True evsrc_isEdge2 True True = Nothing evsrc_isEdge2 True False = Just False evsrc_t16 :: [Event Bool] evsrc_t16 = testSF1 (localTime >>> arr (\t -> t >=2.01 && t <= 4.51) >>> edgeBy evsrc_isEdge2 True) evsrc_t16r = [ Event False, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, Event True, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, Event False -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] -- * Stateful event suppression propNotYet :: Property propNotYet = forAll myStream $ evalT $ Always $ SP $ (==) <$> originalSF <*> modelSF where -- SF under test originalSF :: SF (Event Int) (Event Int) originalSF = notYet -- Model SF that sets the initial value of an Event signal to noEvent modelSF :: SF (Event Int) (Event Int) modelSF = const noEvent -=> identity -- Generator: Random input stream. myStream :: Gen (SignalSampleStream (Event Int)) myStream = uniDistStream evsrc_t17 :: [Event Int] evsrc_t17 = testSF1 (now 17 &&& repeatedly 0.795 42 >>> arr (uncurry merge) >>> notYet) evsrc_t17r :: [Event Int] evsrc_t17r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 1.0 s , NoEvent, NoEvent, Event 42, NoEvent -- 2.0 s , NoEvent, Event 42, NoEvent, NoEvent -- 3.0 s , Event 42, NoEvent, NoEvent, NoEvent -- 4.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 5.0 s , NoEvent ] evsrc_t18 :: [Event Int] evsrc_t18 = testSF1 (now 42 >>> once) evsrc_t18r :: [Event Int] evsrc_t18r = [ Event 42, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t19 :: [Event Int] evsrc_t19 = testSF1 (repeatedly 0.8 42 >>> once) evsrc_t19r :: [Event Int] evsrc_t19r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 42, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t20 :: [Event Int] evsrc_t20 = testSF1 (now 42 >>> takeEvents 0) evsrc_t20r :: [Event Int] evsrc_t20r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t21 :: [Event Int] evsrc_t21 = testSF1 (now 42 >>> takeEvents 1) evsrc_t21r :: [Event Int] evsrc_t21r = [ Event 42, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t22 :: [Event Int] evsrc_t22 = testSF1 (repeatedly 0.8 42 >>> takeEvents 4) evsrc_t22r :: [Event Int] evsrc_t22r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 1.0 s , NoEvent, NoEvent, Event 42, NoEvent -- 2.0 s , NoEvent, Event 42, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t23 :: [Event Int] evsrc_t23 = testSF1 (repeatedly 0.2 42 >>> takeEvents 4) evsrc_t23r :: [Event Int] evsrc_t23r = [ NoEvent, Event 42, Event 42, Event 42 -- 0.0 s , Event 42, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t24 :: [Event Int] evsrc_t24 = testSF1 (now 42 >>> dropEvents 0) evsrc_t24r :: [Event Int] evsrc_t24r = [ Event 42, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t25 :: [Event Int] evsrc_t25 = testSF1 (now 42 >>> dropEvents 1) evsrc_t25r :: [Event Int] evsrc_t25r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] evsrc_t26 :: [Event Int] -- Drop 5 events to get rid of the event at 4.0 s which may or may not happen -- exactly there. evsrc_t26 = testSF1 (repeatedly 0.8 42 >>> dropEvents 5) evsrc_t26r :: [Event Int] evsrc_t26r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , Event 42, NoEvent, NoEvent, Event 42 -- 5.0 s , NoEvent ] evsrc_t27 :: [Event Int] evsrc_t27 = testSF1 (repeatedly 0.2 42 >>> dropEvents 4) evsrc_t27r :: [Event Int] evsrc_t27r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, Event 42, Event 42, Event 42 -- 1.0 s , Event 42, Event 42, Event 42, Event 42 -- 2.0 s , Event 42, Event 42, Event 42, Event 42 -- 3.0 s , Event 42, Event 42, Event 42, Event 42 -- 4.0 s , Event 42, Event 42, Event 42, Event 42 -- 5.0 s , Event 42 ] -- ** Hybrid continuous-to-discrete SF combinators. utils_t10 :: [Event Double] utils_t10 = testSF1 snap utils_t10r = [ Event 0.0, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] utils_t11 :: [Event Double] utils_t11 = testSF1 (snapAfter 2.6) utils_t11r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, Event 11.0 -- 2.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] utils_t12 :: [Event Double] utils_t12 = testSF1 (sample 0.99) utils_t12r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 4.0, NoEvent, NoEvent, NoEvent -- 1.0 s , Event 8.0, NoEvent, NoEvent, NoEvent -- 2.0 s , Event 12.0, NoEvent, NoEvent, NoEvent -- 3.0 s , Event 16.0, NoEvent, NoEvent, NoEvent -- 4.0 s , Event 20.0, NoEvent, NoEvent, NoEvent -- 5.0 s , Event 24.0 ] utils_t15 = take 50 (embed (time >>> sampleWindow 5 0.5) (deltaEncode 0.125 (repeat ()))) utils_t15r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event [0.5], NoEvent, NoEvent, NoEvent -- 0.5 s , Event [0.5,1.0], NoEvent, NoEvent, NoEvent -- 1.0 s , Event [0.5,1.0,1.5], NoEvent, NoEvent, NoEvent -- 1.5 s , Event [0.5,1.0,1.5,2.0], NoEvent, NoEvent, NoEvent -- 2.0 s , Event [0.5,1.0,1.5,2.0,2.5], NoEvent, NoEvent, NoEvent -- 2.5 s , Event [1.0,1.5,2.0,2.5,3.0], NoEvent, NoEvent, NoEvent -- 3.0 s , Event [1.5,2.0,2.5,3.0,3.5], NoEvent, NoEvent, NoEvent -- 3.5 s , Event [2.0,2.5,3.0,3.5,4.0], NoEvent, NoEvent, NoEvent -- 4.0 s , Event [2.5,3.0,3.5,4.0,4.5], NoEvent, NoEvent, NoEvent -- 4.5 s , Event [3.0,3.5,4.0,4.5,5.0], NoEvent, NoEvent, NoEvent -- 5.0 s , Event [3.5,4.0,4.5,5.0,5.5], NoEvent, NoEvent, NoEvent -- 5.5 s , Event [4.0,4.5,5.0,5.5,6.0], NoEvent -- 6.0 s ] {- -- Not robust utils_t16 = take 50 (embed (time >>> sampleWindow 5 0.5) input) where input = ((), [(dt, Just ()) | dt <- dts]) dts = replicate 15 0.1 ++ [1.0, 1.0] ++ replicate 15 0.1 ++ [2.0] ++ replicate 10 0.1 utils_t16r = [ NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 , NoEvent, Event [0.6], NoEvent, NoEvent, NoEvent -- 0.5 , NoEvent, Event [0.6, 1.1], NoEvent, NoEvent, NoEvent -- 1.0 , NoEvent -- 1.5 , Event [0.6,1.1,2.5,2.5,2.5] -- 2.5 , Event [2.5,2.5,2.5,3.5,3.5], NoEvent, NoEvent, NoEvent, NoEvent -- 3.5 , NoEvent, Event [2.5,2.5,3.5,3.5,4.1], NoEvent, NoEvent, NoEvent -- 4.0 , NoEvent, Event [2.5,3.5,3.5,4.1,4.6], NoEvent, NoEvent, NoEvent -- 4.5 , NoEvent -- 5.0 , Event [7.0,7.0,7.0,7.0,7.0], NoEvent, NoEvent, NoEvent, NoEvent -- 7.0 , NoEvent, Event [7.0,7.0,7.0,7.0,7.6], NoEvent, NoEvent, NoEvent -- 7.5 , NoEvent -- 8.0 ] -} utils_t16 = take 50 (embed (time >>> sampleWindow 5 0.4999) input) where input = ((), [(dt, Just ()) | dt <- dts]) dts = replicate 15 0.1 ++ [1.0, 1.0] ++ replicate 15 0.1 ++ [2.0] ++ replicate 10 0.1 utils_t16r = [ NoEvent, NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 , Event [0.5], NoEvent, NoEvent, NoEvent, NoEvent -- 0.5 , Event [0.5, 1.0], NoEvent, NoEvent, NoEvent, NoEvent -- 1.0 , Event [0.5, 1.0, 1.5] -- 1.5 , Event [0.5, 1.0, 1.5, 2.5, 2.5] -- 2.5 , Event [1.5, 2.5, 2.5, 3.5, 3.5], NoEvent, NoEvent, NoEvent -- 3.5 , NoEvent , Event [2.5, 2.5, 3.5, 3.5, 4.0], NoEvent, NoEvent, NoEvent -- 4.0 , NoEvent , Event [2.5, 3.5, 3.5, 4.0, 4.5], NoEvent, NoEvent, NoEvent -- 4.5 , NoEvent , Event [3.5, 3.5, 4.0, 4.5, 5.0] -- 5.0 , Event [5.0, 7.0, 7.0, 7.0, 7.0], NoEvent, NoEvent, NoEvent -- 7.0 , NoEvent , Event [7.0, 7.0, 7.0, 7.0, 7.5], NoEvent, NoEvent, NoEvent -- 7.5 , NoEvent , Event [7.0, 7.0, 7.0, 7.5, 8.0] -- 8.0 ] -- * Repetition and switching utils_t13 :: [Event ()] utils_t13 = testSF1 (recur (after 0.99 ())) utils_t13r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event (), NoEvent, NoEvent, NoEvent -- 1.0 s , Event (), NoEvent, NoEvent, NoEvent -- 2.0 s , Event (), NoEvent, NoEvent, NoEvent -- 3.0 s , Event (), NoEvent, NoEvent, NoEvent -- 4.0 s , Event (), NoEvent, NoEvent, NoEvent -- 5.0 s , Event () ] utils_t14 :: [Event Int] utils_t14 = testSF1 (after 1.0 1 `andThen` now 2 `andThen` after 2.0 3) utils_t14r = [ NoEvent, NoEvent, NoEvent, NoEvent -- 0.0 s , Event 1, NoEvent, NoEvent, NoEvent -- 1.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 2.0 s , Event 3, NoEvent, NoEvent, NoEvent -- 3.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 4.0 s , NoEvent, NoEvent, NoEvent, NoEvent -- 5.0 s , NoEvent ] -- * Auxiliary -- prop :: SF a b -> (a -> b -> prop (a,b) = SP ((identity &&& a) >>^ uncurry b) -- * Arbitrary value generation instance Arbitrary a => Arbitrary (Event a) where arbitrary = oneof [ return NoEvent , do x <- arbitrary return $ Event x ]