packages feed

cybus-0.2.0.0: test/TestEnum.hs

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module TestEnum where

import Control.Arrow
import Cybus.Fin
import Cybus.FinMat
import Cybus.Mat
import Cybus.NatHelper
import Data.Foldable
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as N
import Data.Pos
import Primus.AsMaybe
import Primus.Enum
import Primus.Rep
import Test.Tasty
import Test.Tasty.HUnit

suite :: TestTree
suite =
  testGroup
    "TestEnum"
    [ testCase "toEnum" $
        toEnum @(Mat2 3 4 ()) 0
          @?= mat' @'[3, 4] (replicate 12 ())
    , testCase "toEnum" $
        toEnum @(Mat '[2, 3] ()) 0
          @?= mat' @'[2, 3] [(), (), (), (), (), ()]
    , testCase "toEnum" $
        left (const ()) (toEnumRep @(Mat '[2, 3]) @() 2)
          @?= Left ()
    , testCase "toenum" $
        toEnum @(Fin 10) 0
          @?= FinU _1P _10P
    , testCase "toenum" $
        toEnum @(Fin 10) 1
          @?= FinU _2P _10P
    , testCase "toenum" $
        toEnum @(Fin 10) 2
          @?= FinU _3P _10P
    , testCase "toenum" $
        toEnum @(Fin 2) 1
          @?= FinU _2P _2P
    , testCase "min" $
        minBound @(Fin 5)
          @?= FinU _1P _5P
    , testCase "max" $
        maxBound @(Fin 5)
          @?= FinU _5P _5P
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) (-2)
          @?= Left "calcNextEnum:not defined for negative numbers"
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) (-1)
          @?= Left "calcNextEnum:not defined for negative numbers"
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) 0
          @?= Right []
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) 1
          @?= Right [FinMatU 1 (_3P :| [_4P])]
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) 4
          @?= Right [FinMatU 4 (_3P :| [_4P])]
    , testCase "toEnumList" $
        toEnumList @(FinMat '[3, 4]) 5
          @?= Right [FinMatU 5 (_3P :| [_4P])]
    , testCase "toEnumList" $
        toEnumList @(FinMat '[1, 1, 1, 1]) (-2)
          @?= Left "calcNextEnum:not defined for negative numbers"
    , testCase "toEnumList" $
        toEnumList @(FinMat '[1, 1, 1, 1]) 0
          @?= Right []
    , testCase "toEnumList" $
        toEnumList @(FinMat '[1, 1, 1, 1]) 2
          @?= Left "calcNextEnum:not defined for positive numbers"
    , testCase "toEnumList" $
        toEnumList @(Fin 1) (-1)
          @?= Left "calcNextEnum:not defined for negative numbers"
    , testCase "toEnumList" $
        toEnumList @(Fin 1) 0
          @?= Right []
    , testCase "toEnumList" $
        toEnumList @(Fin 1) 1
          @?= Left "calcNextEnum:not defined for positive numbers"
    , testCase "toEnumList" $
        toEnumList @(Fin 2) (-10)
          @?= Left "calcNextEnum:not defined for negative numbers"
    , testCase "toEnumList" $
        toEnumList @(Fin 2) 0
          @?= Right []
    , testCase "toEnumList" $
        toEnumList @(Fin 2) 1
          @?= Right [FinU _2P _2P :: Fin 2]
    , testCase "toEnumList" $
        toEnumList @(Fin 2) 12
          @?= Right [FinU _2P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P :: Fin 2]
    , testCase "toEnumList" $
        toEnumList @(Fin 2) 100
          @?= Right [FinU _2P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P :: Fin 2]
    , testCase "universe1 fin" $
        universe1 @(Fin 5)
          @?= FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P]
    , testCase "universe1 nextfin" $
        iterateT1 succSafe (FinU _1P _5P)
          @?= FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P]
    , testCase "universe1 prevfin" $
        let f5 = FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P]
         in iterateT1 predSafe (N.last f5)
              @?= N.reverse f5
    , testCase "universe1 prevfin" $
        iterateT1 predSafe (FinU @5 _1P _5P)
          @?= FinU _1P _5P :| []
    , testCase "toEnumRep" $
        toEnumRep @(Mat '[4]) @Ordering 10
          @?= Right (mat' @'[4] [LT, EQ, LT, EQ])
    , testCase "toEnumRep" $
        toEnumRep @(Mat '[4]) @Ordering 0
          @?= Right (mat' @'[4] [LT, LT, LT, LT])
    , testCase "toEnumList" $
        toEnumList @(Vec 3 Ordering) 0
          @?= Right []
    , testCase "toEnumList" $
        toEnumList @(Vec 3 Ordering) 1
          @?= Right [mat' @'[3] [LT, LT, EQ]]
    , testCase "toEnumList" $
        toEnumList @(Vec 3 Ordering) 200
          @?= Right [mat' @'[3] [LT, GT, EQ], mat' @'[3] [EQ, LT, GT]]
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Ordering) 0
          @?= Right (mat' @'[3] [LT, LT, LT] :| [])
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Ordering) 1
          @?= Right (mat' @'[3] [LT, LT, EQ] :| [])
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Ordering) 26
          @?= Right (mat' @'[3] [GT, GT, GT] :| [])
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Ordering) 27
          @?= Right (mat' @'[3] [LT, LT, EQ] :| [mat' @'[3] [LT, LT, LT]])
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Ordering) 200
          @?= Right (mat' @'[3] [LT, GT, EQ] :| [mat' @'[3] [EQ, LT, GT]])
    , testCase "succTraversable" $
        universe1 @(Vec 3 Ordering)
          @?= iterateT1 succSafe minBound
    , testCase "toEnumList" $
        toEnumList @(Vec 3 ()) 1
          @?= Left "calcNextEnum:not defined for positive numbers"
    , testCase "toEnumList" $
        toEnumList @(Vec 3 ()) 0
          @?= Right []
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 ()) 0
          @?= Right ((() .: () .| ()) :| [])
    , testCase "toEnumList" $
        toEnumList @(Vec 3 Bool) 20
          @?= Right [False .: True .| False, True .: False .| False]
    , testCase "toEnumList1" $
        toEnumList1 @(Vec 3 Bool) 20
          @?= Right ((False .: True .| False) :| [True .: False .| False])
    , testCase "toEnumTraversable" $
        toEnumTraversable @Ordering (pure @(Mat '[6]) ()) 10
          @?= Right (LT .: LT .: LT .: EQ .: LT .| EQ)
    , testCase "toEnumRep" $
        toEnumRep @(Mat '[6]) @Ordering 10
          @?= Right (LT .: LT .: LT .: EQ .: LT .| EQ)
    , testCase "universe1" $
        universe1 @(FinMat (NN 123))
          @?= let ns = _1P :| [_2P, _3P]
               in FinMatU 0 ns :| [FinMatU 1 ns, FinMatU 2 ns, FinMatU 3 ns, FinMatU 4 ns, FinMatU 5 ns]
    , testCase "universeTraversable" $
        universeTraversable (pure @(Vec 2) GT)
          @?= Right ((LT .| LT) :| [LT .| EQ, LT .| GT, EQ .| LT, EQ .| EQ, EQ .| GT, GT .| LT, GT .| EQ, GT .| GT])
    , testCase "universeTraversable" $
        universeTraversable (replicate 2 (minBound @(Fin 5)))
          @?= let ff p n = FinU @5 p n
               in Right ([ff _1P _5P, ff _1P _5P] :| [[ff _1P _5P, ff _2P _5P], [ff _1P _5P, ff _3P _5P], [ff _1P _5P, ff _4P _5P], [ff _1P _5P, ff _5P _5P], [ff _2P _5P, ff _1P _5P], [ff _2P _5P, ff _2P _5P], [ff _2P _5P, ff _3P _5P], [ff _2P _5P, ff _4P _5P], [ff _2P _5P, ff _5P _5P], [ff _3P _5P, ff _1P _5P], [ff _3P _5P, ff _2P _5P], [ff _3P _5P, ff _3P _5P], [ff _3P _5P, ff _4P _5P], [ff _3P _5P, ff _5P _5P], [ff _4P _5P, ff _1P _5P], [ff _4P _5P, ff _2P _5P], [ff _4P _5P, ff _3P _5P], [ff _4P _5P, ff _4P _5P], [ff _4P _5P, ff _5P _5P], [ff _5P _5P, ff _1P _5P], [ff _5P _5P, ff _2P _5P], [ff _5P _5P, ff _3P _5P], [ff _5P _5P, ff _4P _5P], [ff _5P _5P, ff _5P _5P]])
    , testCase "universeTraversable" $
        universeTraversable (vec @2 (repeat (finMatC @'[1, 1] @'[2, 3])))
          @?= let ff i = FinMatU i (_2P :| [_3P])
               in Right ((ff 0 .| ff 0) :| [ff 0 .| ff 1, ff 0 .| ff 2, ff 0 .| ff 3, ff 0 .| ff 4, ff 0 .| ff 5, ff 1 .| ff 0, ff 1 .| ff 1, ff 1 .| ff 2, ff 1 .| ff 3, ff 1 .| ff 4, ff 1 .| ff 5, ff 2 .| ff 0, ff 2 .| ff 1, ff 2 .| ff 2, ff 2 .| ff 3, ff 2 .| ff 4, ff 2 .| ff 5, ff 3 .| ff 0, ff 3 .| ff 1, ff 3 .| ff 2, ff 3 .| ff 3, ff 3 .| ff 4, ff 3 .| ff 5, ff 4 .| ff 0, ff 4 .| ff 1, ff 4 .| ff 2, ff 4 .| ff 3, ff 4 .| ff 4, ff 4 .| ff 5, ff 5 .| ff 0, ff 5 .| ff 1, ff 5 .| ff 2, ff 5 .| ff 3, ff 5 .| ff 4, ff 5 .| ff 5])
    , testCase "capacity" $
        capacity @(FinMat '[2, 3]) (replicate 2 ())
          @?= Right (0, 35)
    , testCase "capacity" $
        capacity @(FinMat '[1, 3, 5, 6]) (replicate 7 ())
          @?= Right (0, 47829689999999)
    , testCase "iterateT1 succTraversable FinMat" $
        fmap (toList . fmap fmPos) (iterateT1 succTraversable (vec' @2 [finMatC @'[3, 3] @'[4, 3], finMatC @'[2, 1] @'[4, 3]]))
          @?= [8, 3] :| [[8, 4], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [8, 10], [8, 11], [9, 0], [9, 1], [9, 2], [9, 3], [9, 4], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9], [9, 10], [9, 11], [10, 0], [10, 1], [10, 2], [10, 3], [10, 4], [10, 5], [10, 6], [10, 7], [10, 8], [10, 9], [10, 10], [10, 11], [11, 0], [11, 1], [11, 2], [11, 3], [11, 4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9], [11, 10], [11, 11]]
    , testCase "iterateT1 succTraversable FinMat" $
        fmap (toList . fmap fmPos) (iterateT1 succTraversable [finMatC @'[3, 3] @'[3, 3], finMatC @'[2, 1], finMatC @'[3, 1]])
          @?= [8, 3, 6] :| [[8, 3, 7], [8, 3, 8], [8, 4, 0], [8, 4, 1], [8, 4, 2], [8, 4, 3], [8, 4, 4], [8, 4, 5], [8, 4, 6], [8, 4, 7], [8, 4, 8], [8, 5, 0], [8, 5, 1], [8, 5, 2], [8, 5, 3], [8, 5, 4], [8, 5, 5], [8, 5, 6], [8, 5, 7], [8, 5, 8], [8, 6, 0], [8, 6, 1], [8, 6, 2], [8, 6, 3], [8, 6, 4], [8, 6, 5], [8, 6, 6], [8, 6, 7], [8, 6, 8], [8, 7, 0], [8, 7, 1], [8, 7, 2], [8, 7, 3], [8, 7, 4], [8, 7, 5], [8, 7, 6], [8, 7, 7], [8, 7, 8], [8, 8, 0], [8, 8, 1], [8, 8, 2], [8, 8, 3], [8, 8, 4], [8, 8, 5], [8, 8, 6], [8, 8, 7], [8, 8, 8]]
    , testCase "iterateT1 succTraversable Fin" $
        fmap (toList . fmap fnPos) (iterateT1 succTraversable [finC @4 @5, finC @3, finC @2])
          @?= [_4P, _3P, _2P] :| [[_4P, _3P, _3P], [_4P, _3P, _4P], [_4P, _3P, _5P], [_4P, _4P, _1P], [_4P, _4P, _2P], [_4P, _4P, _3P], [_4P, _4P, _4P], [_4P, _4P, _5P], [_4P, _5P, _1P], [_4P, _5P, _2P], [_4P, _5P, _3P], [_4P, _5P, _4P], [_4P, _5P, _5P], [_5P, _1P, _1P], [_5P, _1P, _2P], [_5P, _1P, _3P], [_5P, _1P, _4P], [_5P, _1P, _5P], [_5P, _2P, _1P], [_5P, _2P, _2P], [_5P, _2P, _3P], [_5P, _2P, _4P], [_5P, _2P, _5P], [_5P, _3P, _1P], [_5P, _3P, _2P], [_5P, _3P, _3P], [_5P, _3P, _4P], [_5P, _3P, _5P], [_5P, _4P, _1P], [_5P, _4P, _2P], [_5P, _4P, _3P], [_5P, _4P, _4P], [_5P, _4P, _5P], [_5P, _5P, _1P], [_5P, _5P, _2P], [_5P, _5P, _3P], [_5P, _5P, _4P], [_5P, _5P, _5P]]
    , testCase "iterateT1 predTraversable Fin" $
        fmap (toList . fmap fnPos) (iterateT1 predTraversable [finC @4 @5, finC @3, finC @2])
          @?= [_4P, _3P, _2P] :| [[_4P, _3P, _1P], [_4P, _2P, _5P], [_4P, _2P, _4P], [_4P, _2P, _3P], [_4P, _2P, _2P], [_4P, _2P, _1P], [_4P, _1P, _5P], [_4P, _1P, _4P], [_4P, _1P, _3P], [_4P, _1P, _2P], [_4P, _1P, _1P], [_3P, _5P, _5P], [_3P, _5P, _4P], [_3P, _5P, _3P], [_3P, _5P, _2P], [_3P, _5P, _1P], [_3P, _4P, _5P], [_3P, _4P, _4P], [_3P, _4P, _3P], [_3P, _4P, _2P], [_3P, _4P, _1P], [_3P, _3P, _5P], [_3P, _3P, _4P], [_3P, _3P, _3P], [_3P, _3P, _2P], [_3P, _3P, _1P], [_3P, _2P, _5P], [_3P, _2P, _4P], [_3P, _2P, _3P], [_3P, _2P, _2P], [_3P, _2P, _1P], [_3P, _1P, _5P], [_3P, _1P, _4P], [_3P, _1P, _3P], [_3P, _1P, _2P], [_3P, _1P, _1P], [_2P, _5P, _5P], [_2P, _5P, _4P], [_2P, _5P, _3P], [_2P, _5P, _2P], [_2P, _5P, _1P], [_2P, _4P, _5P], [_2P, _4P, _4P], [_2P, _4P, _3P], [_2P, _4P, _2P], [_2P, _4P, _1P], [_2P, _3P, _5P], [_2P, _3P, _4P], [_2P, _3P, _3P], [_2P, _3P, _2P], [_2P, _3P, _1P], [_2P, _2P, _5P], [_2P, _2P, _4P], [_2P, _2P, _3P], [_2P, _2P, _2P], [_2P, _2P, _1P], [_2P, _1P, _5P], [_2P, _1P, _4P], [_2P, _1P, _3P], [_2P, _1P, _2P], [_2P, _1P, _1P], [_1P, _5P, _5P], [_1P, _5P, _4P], [_1P, _5P, _3P], [_1P, _5P, _2P], [_1P, _5P, _1P], [_1P, _4P, _5P], [_1P, _4P, _4P], [_1P, _4P, _3P], [_1P, _4P, _2P], [_1P, _4P, _1P], [_1P, _3P, _5P], [_1P, _3P, _4P], [_1P, _3P, _3P], [_1P, _3P, _2P], [_1P, _3P, _1P], [_1P, _2P, _5P], [_1P, _2P, _4P], [_1P, _2P, _3P], [_1P, _2P, _2P], [_1P, _2P, _1P], [_1P, _1P, _5P], [_1P, _1P, _4P], [_1P, _1P, _3P], [_1P, _1P, _2P], [_1P, _1P, _1P]]
    ]