packages feed

countable-1.0: test/Count.hs

module Main where
{
    import Prelude;
    import Data.Proxy;
    import Data.Word;
    import Test.Tasty;
    import Test.Tasty.HUnit;

    import Data.Empty;
    import Data.Searchable;
    import Data.Countable;

    import Show;
    import TypeName;
    import Three;
    import Golden;

    (@/=?) :: (Eq a,Show a) => a -> a -> Assertion;
    unexpected @/=? actual | unexpected /= actual = return ();
    _unexpected @/=? actual = assertFailure $ "got unexpected " ++ show actual;

    prevMaybeNext :: (Countable a,Show a) => Maybe a -> Assertion;
    prevMaybeNext ma = case countMaybeNext ma of
    {
        Just a' -> countPrevious a' @=? ma;
        Nothing -> return ();
    };

    countableTests' :: (Show a,Countable a) => a -> [TestTree];
    countableTests' a =
    [
        testCase "maybeNextDifferent" $ (Just a) @/=? countMaybeNext (Just a),
        testCase "prevDifferent" $ (Just a) @/=? (countPrevious a),
        testCase "maybeNextPrev" $ (Just a) @=? countMaybeNext (countPrevious a),
        testCase "prevMaybeNext" $ prevMaybeNext (Just a)
    ];

    findInNext :: (Countable a) => Int -> a -> TestTree;
    findInNext n a = testCase "findInNext" $ findInNext' n Nothing where
    {
        findInNext' 0 _ = assertFailure "failed";
        findInNext' _ (Just x) | x == a = return ();
        findInNext' n' mx = case countMaybeNext mx of
        {
            Nothing -> assertFailure "failed";
            mx' -> findInNext' (n' - 1) mx';
        };
    };

    countableTests :: (Show a,Countable a) => a -> [TestTree];
    countableTests a = (countableTests' a) ++ [findInNext 1000 a];

    nextIsMaybeNext :: (Show a,InfiniteCountable a) => Maybe a -> TestTree;
    nextIsMaybeNext ma = testCase "nextIsMaybeNext" $ (Just (countNext ma)) @=? (countMaybeNext ma);

    infiniteCountableTests :: (Show a,InfiniteCountable a) => a -> [TestTree];
    infiniteCountableTests a = (countableTests a) ++ [nextIsMaybeNext (Just a)];
    checkN :: (Show a,Countable a) => (String -> IO ()) -> Int -> Maybe a -> IO ();
    checkN _ 0 _ = return ();
    checkN write n ma = let
    {
        ma' = countMaybeNext ma;
    } in do
    {
        prevMaybeNext ma;
        write (show ma ++ "\n");
        case ma' of
        {
            Nothing -> return ();
            _ -> checkN write (n - 1) ma';
        };
    };

    testType :: forall a. (TypeName a,Show a) => (a -> [TestTree]) -> [a] -> TestTree;
    testType tests vals = testGroup (typeName (Proxy::Proxy a)) $ fmap (\a -> testGroup (show a) (tests a)) vals;

    -- This is to prevent overlapping Show function instance in Text.Show.Functions,
    -- which gets imported somehow with lts-5.
    newtype WrapFunction a b = MkWrapFunction (a -> b) deriving (Eq,Searchable,Countable,TypeName);
    instance (Show a,Finite a,Show b) => Show (WrapFunction a b) where
    {
        show (MkWrapFunction f) = showFunction f;
    };
    instance (Finite a,Finite b) => Finite (WrapFunction a b) where
    {
        allValues = fmap MkWrapFunction allValues;
        assemble wabfx = let
            foo abx (MkWrapFunction ab) = abx ab;
            in fmap foo $ assemble (wabfx . MkWrapFunction);
    };

    allTests :: TestTree;
    allTests = testGroup "countable"
        [
        testType countableTests (allValues :: [()]),
        testType countableTests (allValues :: [Bool]),
        testType countableTests ([0,3,255] :: [Word8]),
        testType countableTests (allValues :: [Maybe ()]),
        testType countableTests (allValues :: [Maybe Bool]),
        testType countableTests (allValues :: [Maybe (Maybe Bool)]),
        testType countableTests ([[],[0],[2],[-1,1],[0,0,0]] :: [[Integer]]),
        testType countableTests' ([[1,2,1],[-5,17,112]] :: [[Integer]]),
        testType countableTests ([[],[True,True]] :: [[Bool]]),
        testType infiniteCountableTests ([0,1,-1,3,-7] :: [Integer]),
        testType countableTests (allValues :: [WrapFunction Three Three]),
        testType countableTests (allValues :: [None]),
        testType countableTests ([[] :: [None]]),
        testGroup "list"
            [
            goldenVsWriteString "Bool"    "test/count.Bool.ref"    $ \write -> checkN write 40 (Nothing :: Maybe [Bool   ]),
            goldenVsWriteString "Word8"   "test/count.Word8.ref"   $ \write -> checkN write 40 (Nothing :: Maybe [Word8  ]),
            goldenVsWriteString "Integer" "test/count.Integer.ref" $ \write -> checkN write 40 (Nothing :: Maybe [Integer])
            ]
        ];

    main :: IO ();
    main = defaultMain allTests;
}