clash-prelude-1.8.3: tests/Clash/Tests/Counter.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NumericUnderscores #-}
module Clash.Tests.Counter where
import qualified Prelude as P
import Clash.Class.Counter
import Clash.Prelude
import Data.Proxy
import Data.Typeable
import qualified Hedgehog as H
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Test.Tasty
import qualified Test.Tasty.Hedgehog.Extra as H
import Test.Tasty.HUnit
genUnsigned :: SNat n -> H.Gen (Unsigned n)
genUnsigned SNat = Gen.frequency
[ (80, Gen.integral (Range.linear minBound maxBound))
, (20, pure maxBound) ]
packTest2 ::
forall a b.
(KnownNat a, KnownNat b, KnownNat (a + b)) =>
(Unsigned (a + b) -> Unsigned (a + b)) ->
((Unsigned a, Unsigned b) -> (Unsigned a, Unsigned b)) ->
H.Property
packTest2 f1 f2 = H.property $ do
a <- H.forAll (genUnsigned (SNat @a))
b <- H.forAll (genUnsigned (SNat @b))
let ab = unpack @(Unsigned (a + b)) (pack (a, b))
f1 ab H.=== unpack (pack (f2 (a, b)))
packSuccTest2 ::
forall a b.
(KnownNat a, KnownNat b, KnownNat (a + b)) =>
Proxy a ->
Proxy b ->
H.Property
packSuccTest2 _ _ = packTest2 (satSucc SatWrap) (countSucc @(Unsigned a, Unsigned b))
packPredTest2 ::
forall a b.
(KnownNat a, KnownNat b, KnownNat (a + b)) =>
Proxy a ->
Proxy b ->
H.Property
packPredTest2 _ _ = packTest2 (satPred SatWrap) (countPred @(Unsigned a, Unsigned b))
-- | Counting /down/ from 'countMin' should yield 'countMin' at some point
predShouldWrapAround :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion
predShouldWrapAround Proxy =
let counter = P.take 100_0000 (P.drop 1 (P.iterate countPred countMin)) in
assertBool "Pred should wrap-around" (countMin @a `P.elem` counter)
-- | Counting /up/ from 'countMin' should yield 'countMin' at some point
succShouldWrapAround :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion
succShouldWrapAround Proxy =
let counter = P.take 100_000 (P.drop 1 (P.iterate countSucc countMin)) in
assertBool "Succ should wrap-around" (countMin @a `P.elem` counter)
-- | Counting /down/ from 'countMax' should yield 'countMin' at some point
predShouldSeeCountMin :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion
predShouldSeeCountMin Proxy =
let counter = P.take 100_0000 (P.drop 1 (P.iterate countPred countMax)) in
assertBool "Pred should see countMin" (countMin @a `P.elem` counter)
-- | Counting /up/ from 'countMin' should yield 'countMax' at some point
succShouldSeeCountMax :: forall a. (Eq a, Counter a, Show a) => Proxy a -> Assertion
succShouldSeeCountMax Proxy =
let counter = P.take 100_000 (P.drop 1 (P.iterate countSucc countMin)) in
assertBool "Succ should see countMax" (countMax @a `P.elem` counter)
quadTest :: forall a. (Eq a, Counter a, Typeable a, Show a) => Proxy a -> TestTree
quadTest proxy = testGroup (show (typeRep proxy))
[ testCase "succShouldWrapAround" (succShouldWrapAround proxy)
, testCase "predShouldWrapAround" (predShouldWrapAround proxy)
, testCase "succShouldSeeCountMax" (succShouldSeeCountMax proxy)
, testCase "predShouldSeeCountMin" (predShouldSeeCountMin proxy)
]
tests :: TestTree
tests = testGroup "All"
[ H.testPropertyXXX "packSuccTest @2 @2" (packSuccTest2 @2 @2 Proxy Proxy)
, H.testPropertyXXX "packSuccTest @3 @2" (packSuccTest2 @3 @2 Proxy Proxy)
, H.testPropertyXXX "packSuccTest2 @129 @5" (packSuccTest2 @129 @5 Proxy Proxy)
, H.testPropertyXXX "packPredTest @2 @2" (packPredTest2 @2 @2 Proxy Proxy)
, H.testPropertyXXX "packPredTest @3 @2" (packPredTest2 @3 @2 Proxy Proxy)
, H.testPropertyXXX "packPredTest2 @129 @5" (packPredTest2 @129 @5 Proxy Proxy)
, quadTest (Proxy @(Signed 5))
, quadTest (Proxy @(Signed 5, Signed 5))
, quadTest (Proxy @(Signed 2, Signed 2, Unsigned 7))
, quadTest (Proxy @(Either (Signed 5) (Index 5)))
]
-- Run with:
--
-- ./repld p:tests -T Clash.Tests.Counter.main
--
-- Add -W if you want to run tests in spite of warnings
--
main :: IO ()
main = defaultMain tests