{-# LANGUAGE DerivingVia, TypeApplications, OverloadedLists #-} module Main where import Control.Exception import Control.Monad import Data.Array.Byte import Data.Bits import Data.Either import Data.List (tails) import Data.Ord import Data.Semigroup import GHC.Exts (IsList(..)) newtype Tricky = Tricky Int deriving (Eq, Num, Real, Enum, Integral) via Int deriving Ord via Down Int smallArrs :: [ByteArray] -- 40 arrays, of total length 600 smallArrs = [[], [3,8,1], [0], [255], [1,6,1,8,2]] ++ map fromList (replicate 29 0 : tails [0..32]) shouldError :: a -> IO () -> IO () shouldError val ifNoError = do res <- try @ErrorCall (evaluate val) when (isRight res) ifNoError testConcat :: [ByteArray] -> IO () testConcat arrs = do let lis = map toList arrs expected = mconcat lis actual = toList (mconcat arrs) when (expected /= actual) $ putStrLn $ unwords ["mconcat", show lis, "/=", show actual] main :: IO () main = do when (toList @ByteArray mempty /= []) $ putStrLn "mempty /= []" -- test <> forM_ smallArrs $ \x -> do let xli = toList x forM_ smallArrs $ \y -> do let yli = toList y expected = xli <> yli actual = toList (x <> y) when (expected /= actual) $ putStrLn $ unwords [show xli, "<>", show yli, "/=", show actual] -- test stimes forM_ smallArrs $ \x -> do let xli = toList x shouldError (stimes (-1 :: Integer) x) $ putStrLn $ unwords ["stimes (-1 :: Integer)", show xli, "didn't fail??"] shouldError (stimes (-1 :: Tricky) x) $ putStrLn $ unwords ["stimes (-1 :: Tricky)", show xli, "didn't fail??"] when (length xli > 1) $ shouldError (stimes (maxBound @Int) x) $ putStrLn $ unwords ["stimes (maxBound @Int)", show xli, "didn't fail??"] forM_ (10000 : [0 :: Int .. 32]) $ \n -> do let expected = stimes n xli actual = toList (stimes n x) when (expected /= actual) $ putStrLn $ unwords ["stimes", show n, show xli, "/=", show actual] evaluate $ stimes @ByteArray @Int maxBound [] evaluate $ stimes @ByteArray @Integer (10^100) [] -- test mconcat testConcat [] forM_ smallArrs $ \x -> do testConcat [x] forM_ smallArrs $ \y -> do testConcat [x, y] forM_ smallArrs $ \z -> do -- OK, 40^3 = 64K testConcat [x, y, z] -- test mconcat's overflow-handling let bigArr = stimes (bit 18 :: Int) [0] :: ByteArray when (finiteBitSize @Int 0 == 32) $ shouldError (mconcat $ replicate (bit 14) bigArr) $ putStrLn "Impossible mconcat succeeded???"