yampa-test 0.13.5 → 0.13.6
raw patch · 5 files changed
+282/−17 lines, 5 filesdep ~YampaPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: Yampa
API changes (from Hackage documentation)
Files
- CHANGELOG +6/−0
- tests/Test/FRP/Yampa/Basic.hs +177/−12
- tests/Test/FRP/Yampa/Conditional.hs +54/−1
- tests/Test/FRP/Yampa/Delays.hs +43/−2
- yampa-test.cabal +2/−2
CHANGELOG view
@@ -1,3 +1,9 @@+2022-08-07 Ivan Perez <ivan.perez@haskell.sexy>+ * yampa-test.cabal: Version bump (0.13.6) (#232).+ * tests/: Complete unit tests for FRP.Yampa.Basic (#219), complete unit+ tests for FRP.Yampa.Conditional (#225), complete unit tests for+ FRP.Yampa.Delays (#226).+ 2022-06-07 Ivan Perez <ivan.perez@haskell.sexy> * yampa-test.cabal: Version bump (0.13.5) (#220), fix broken link in description (#204), enable all warnings (#206), rename flag (#208),
tests/Test/FRP/Yampa/Basic.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} -- | -- Description : Test cases for basic signal functions -- Copyright : Yale University, 2003@@ -7,6 +8,10 @@ ) where +#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<*>))+import Data.Functor ((<$>))+#endif import Test.QuickCheck import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck (testProperty)@@ -25,12 +30,19 @@ , testProperty "identity (qc)" prop_basic_identity_2 , testProperty "constant (fixed)" (property $ basicsf_t1 ~= basicsf_t1r) , testProperty "constant (qc)" prop_basic_constant+ , testProperty "--> (qc)" propInsert+ , testProperty "-:> (qc)" propAlterFirstOutput+ , testProperty ">-- (qc)" propInputInit+ , testProperty "-=> (qc)" propModFirstOutput+ , testProperty ">=- (qc)" propModFirstInput , testProperty "initially (fixed)" (property $ basicsf_t4 ~= basicsf_t4r) , testProperty "initially (qc)" prop_basic_initially ] -- * Basic signal functions +-- ** identity+ basicsf_t0 :: [Double] basicsf_t0 = testSF1 identity basicsf_t0r =@@ -52,6 +64,8 @@ where myStream :: Gen (SignalSampleStream Float) myStream = uniDistStream +-- ** constant+ basicsf_t1 :: [Double] basicsf_t1 = testSF1 (constant 42.0) basicsf_t1r =@@ -70,24 +84,175 @@ -- * Initialization -prop_insert =+-- ** @(-->)@++-- | Test that @initialValue --> integral@, when applied to any signal, is+-- initially equal to @constant initialValue@, and, in the future, always equal+-- to @integral@.+--+-- Note that it is important to understand that integral is "turned on" at time+-- zero, and its value discarded. This is not the same as using the constant SF+-- at time zero and turning @integral@ on at the next time (e.g., with+-- @switch@).+propInsert :: Property+propInsert = forAll initialValueG $ \initialValue ->- forAll finalValueG $ \finalValue -> forAll myStream $ evalT $- let sfStep = initialValue --> constant finalValue - in And (prop (sfStep, const (== initialValue)))- (Next $ Always $- (prop (sfStep, const (== finalValue))))+ -- SF that uses the actual function being tested+ let sfStep :: SF Float Float+ sfStep = initialValue --> integral - where myStream :: Gen (SignalSampleStream Float)- myStream = uniDistStream+ -- Expected behavior+ in And+ -- Currently equal to initialValue+ (SP $ (==) <$> sfStep <*> constant initialValue) - initialValueG :: Gen Float- initialValueG = arbitrary+ -- In the future, always equal to integral+ (Next $ Always $ SP $ (==) <$> sfStep <*> integral) - finalValueG :: Gen Float- finalValueG = arbitrary+ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++-- ** @(-:>)@++-- | Test that @initialValue -:> sf@, when applied to any signal, is initially+-- equal to @constant initialValue@, and, after that, the output is the same as+-- @sf@ (starting from that point).+propAlterFirstOutput :: Property+propAlterFirstOutput =+ forAll initialValueG $ \initialValue ->+ forAll myStream $ evalT $++ -- SF that uses the actual function being tested.+ --+ -- We pick a point-wise function for the test because we have no (easy)+ -- way of dropping a sample when we "turn of" the second sf in the+ -- comparison for future samples. For example, if we had picked integral,+ -- then the integral would start from the second sample (with the delay+ -- applied), but the temporal Next operator starts the SF now and waits+ -- until the next sample to check the property.+ let sfStep :: SF Float Float+ sfStep = (initialValue -:> arr (* 2)) >>> arr (^ 2)++ -- Expected behavior+ in And+ -- Currently equal to initialValue. In tis case it is safe to+ -- compare floating point numbers with (==) because the output HAS+ -- to be exactly the same. Note that, in the efinition of sfStep,+ -- the number initialValue should reach (arr (^ 2)) unchanged, and+ -- arr is just function application.+ (SP $ (==) <$> sfStep <*> constant (initialValue ^ 2))++ -- In the future, always equal to (arr ((^ 2) . (* 2)))). Note that+ -- we ignore initialValue completely.+ (Next $ Always $ SP $ (==) <$> sfStep <*> arr ((^ 2) . (* 2)))++ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++-- ** @(>--)@++-- | Test that @initialValue >-- sf@, when applied to any signal, is initially+-- equal to @initialValue@, and, in the future, always equal to @sf@.+propInputInit :: Property+propInputInit =+ forAll initialValueG $ \initialValue ->+ forAll myStream $ evalT $++ -- SF that uses the actual function being tested+ let sfStep :: SF Float Float+ sfStep = initialValue --> arr (* 2)++ -- Expected behavior+ in And+ -- Currently equal to initialValue+ (SP $ (==) <$> sfStep <*> constant initialValue)++ -- In the future, always equal to arr (* 2)+ (Next $ Always $ SP $ (==) <$> sfStep <*> arr (* 2))++ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++-- ** (-=>)++-- | Test that @(-=>)@ applies a transformation to the first output.+--+-- We test with the specific function @(* 4) -=> arr (^ 2)@.+propModFirstOutput :: Property+propModFirstOutput =+ forAll myStream $ evalT $++ -- SF that uses the actual function being tested.+ --+ -- We specifically pick transformations that do not commute, so that we+ -- test that transformations are applied in the expected order.+ let sfStep :: SF Float Float+ sfStep = (* 4) -=> arr (^ 2)++ -- Expected behavior+ in And+ -- Initially, both transformations are applied. Note that the+ -- difference between this comparison and the one for (>=-) is the+ -- order in which the two transformations are applied.+ (SP $ (==) <$> sfStep <*> arr ((* 4) . (^ 2)))++ -- In the future, only the second transformation is applied+ (Next $ Always $ SP $ (==) <$> sfStep <*> arr (^ 2))++ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++-- ** @(>=-)@++-- | Test that @f -=> arr (^ 2)@, when applied to any signal, is initially+-- equal to initialValue, and, in the future, always equal to @arr (^ 2)@.+propModFirstInput :: Property+propModFirstInput =+ forAll myStream $ evalT $++ -- SF that uses the actual function being tested.+ --+ -- We specifically pick transformations that do not commute, so that we+ -- test that transformations are applied in the expected order.+ let sfStep :: SF Float Float+ sfStep = (* 2) >=- arr (^ 2)++ -- Expected behavior+ in And+ -- Initially, both transformations are applied. Note that the+ -- difference between this comparison and the one for (-=>) is the+ -- order in which the two transformations are applied.+ (SP $ (==) <$> sfStep <*> arr ((^ 2) . (* 2)))++ -- In the future, only the second transformation is applied+ (Next $ Always $ SP $ (==) <$> sfStep <*> arr (^ 2))++ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++-- ** initially basicsf_t4 :: [Double] basicsf_t4 = testSF1 (initially 42.0)
tests/Test/FRP/Yampa/Conditional.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE Arrows #-}+{-# LANGUAGE CPP #-} -- | -- Description : Test cases for FRP.Yampa.Conditional -- Copyright : Yale University, 2003@@ -7,12 +9,19 @@ ) where +#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<*>))+import Data.Functor ((<$>))+#endif import Test.QuickCheck import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck (testProperty) import FRP.Yampa as Yampa-import FRP.Yampa.Conditional (provided)+import FRP.Yampa.Conditional (pause, provided)+import FRP.Yampa.LTLFuture (TPred (Always, SP), evalT)+import FRP.Yampa.QuickCheck (uniDistStream)+import FRP.Yampa.Stream (SignalSampleStream) import TestsCommon @@ -20,6 +29,7 @@ tests = testGroup "Regression tests for FRP.Yampa.Conditional" [ testProperty "provided (1, fixed)" (property $ utils_t8 ~= utils_t8r) , testProperty "provided (2, fixed)" (property $ utils_t9 ~= utils_t9r)+ , testProperty "pause (qc)" propPause ] -- * Guards and automata-oriented combinators@@ -59,3 +69,46 @@ , -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0 , 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 ]++propPause :: Property+propPause =+ forAll initialValueG $ \initialValue ->+ forAll myStream $ evalT $+ -- The behavior of pause is always the same as some ideal behavior+ -- implemented by modelPause below. We give these auxiliary definitions+ -- names and pass initialValue as argument to facilitate debugging.+ Always $ SP $ (==) <$> sfPause initialValue <*> sfModelPause initialValue+ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++ -- SF that uses the actual function being tested+ sfPause :: Float -> SF Float Float+ sfPause initialValue = pause initialValue (arr (odd . round)) integral++ -- Model SF that uses the actual function being tested+ sfModelPause :: Float -> SF Float Float+ sfModelPause initialValue =+ modelPause initialValue (arr (odd . round)) integral++ -- Model implementation of pause.+ modelPause :: b -> SF a Bool -> SF a b -> SF a b+ modelPause acc0 sf1 sf2 = proc (a) -> do+ rec c <- sf1 -< a++ -- Accumulator that is updated only when then condition is false.+ acc <- hold acc0 -< e++ -- When the condition is false, sf2 is turned on and executed,+ -- producing a new Event. Note that we need to put this in an+ -- ArrowCase block, we can't just run both and the decide whether we+ -- want to output the value or not based on the condition, because,+ -- in that case, the argument sf2 would still be executed and+ -- accumulate state.+ e <- if c then returnA -< NoEvent+ else Event ^<< sf2 -< a++ returnA -< acc
tests/Test/FRP/Yampa/Delays.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} -- | -- Description : Test cases for FRP.Yampa.Delays -- Copyright : Yale University, 2003@@ -7,11 +8,16 @@ ) where +#if __GLASGOW_HASKELL__ < 710+import Control.Applicative ((<*>))+import Data.Functor ((<$>))+#endif import Test.QuickCheck import Test.Tasty (TestTree, testGroup) import Test.Tasty.QuickCheck (testProperty) import FRP.Yampa as Yampa+import FRP.Yampa.Delays (fby) import FRP.Yampa.Stream import FRP.Yampa.QuickCheck import FRP.Yampa.LTLFuture@@ -20,7 +26,8 @@ tests :: TestTree tests = testGroup "Regression tests for FRP.Yampa.Delays"- [ testProperty "iPre (0, fixed)" (property $ pre_t0 ~= pre_t0r)+ [ testProperty "pre (qc)" propPre+ , testProperty "iPre (0, fixed)" (property $ pre_t0 ~= pre_t0r) , testProperty "iPre (1, fixed)" (property $ pre_t1 ~= pre_t1r) , testProperty "iPre (2, fixed)" (property $ pre_t2 ~= pre_t2r) , testProperty "iPre (3, fixed)" (property $ pre_t3 == pre_t3r)@@ -29,6 +36,7 @@ , testProperty "iPre (6, fixed)" (property $ pre_t6 == pre_t6r) , testProperty "iPre (7, fixed)" (property $ pre_t7 == pre_t7r) , testProperty "iPre (8, fixed)" (property $ pre_t8 == pre_t8r)+ , testProperty "fby (qc)" propFby , testProperty "delay (0, fixed)" (property $ delay_t0 ~= delay_t0r) , testProperty "delay (1, fixed)" (property $ delay_t1 ~= delay_t1r) , testProperty "delay (2, fixed)" (property $ delay_t2 ~= delay_t2r)@@ -39,8 +47,22 @@ , testProperty "delay (small delay, qc)" prop_delay_2 ] --- * Delays+-- * Basic delays +propPre :: Property+propPre =+ forAll initialValueG $ \initialValue ->+ forAll myStream $ evalT $+ -- The behavior of pre is always the same as iPre after the first sample.+ -- The value at time zero is undefined, so we don't need to test it.+ Next $ Always $ SP $ (==) <$> pre <*> iPre initialValue+ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary+ pre_t0 = testSF1 (iPre 17) pre_t0r = [ 17.0,0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0@@ -211,6 +233,25 @@ , 10,10,10,10 -- 11s , 10,10 -- 12s ]++propFby :: Property+propFby =+ forAll initialValueG $ \initialValue ->+ forAll myStream $ evalT $+ -- fby is just a convenience function for iPre with composition+ Always $ SP $ (==) <$> fby initialValue sf <*> (sf >>> iPre initialValue)+ where+ myStream :: Gen (SignalSampleStream Float)+ myStream = uniDistStream++ initialValueG :: Gen Float+ initialValueG = arbitrary++ -- We pick the integral because it exploits the case where the SF has to be+ -- turned off sooner or later (it would produce different results if turned+ -- on at inconsistent times between fby and >>> iPre).+ sf :: SF Float Float+ sf = integral -- * Timed delays
yampa-test.cabal view
@@ -31,7 +31,7 @@ build-type: Simple name: yampa-test-version: 0.13.5+version: 0.13.6 author: Ivan Perez maintainer: ivan.perez@keera.co.uk homepage: http://github.com/ivanperez-keera/Yampa@@ -84,7 +84,7 @@ base >= 4 && < 5 , normaldistribution , QuickCheck- , Yampa >= 0.13.5 && < 0.14+ , Yampa >= 0.13.6 && < 0.14 default-language: Haskell2010