yampa-test-0.14.1: tests/Test/FRP/Yampa/EventS.hs
{-# 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
]