packages feed

haskoin-core-0.15.0: test/Haskoin/UtilSpec.hs

module Haskoin.UtilSpec
    ( spec
    , customCerealID
    , readTestFile
    ) where

import           Data.Aeson             (FromJSON, ToJSON)
import qualified Data.Aeson             as A
import           Data.Aeson.Encoding    (encodingToLazyByteString)
import           Data.Aeson.Types       (Parser, parseMaybe)
import qualified Data.ByteString        as BS
import           Data.Either            (fromLeft, fromRight, isLeft, isRight)
import           Data.Foldable          (toList)
import           Data.List              (permutations)
import           Data.Map.Strict        (singleton)
import           Data.Maybe
import qualified Data.Sequence          as Seq
import           Data.Serialize         as S
import           Haskoin.Util
import           Haskoin.Util.Arbitrary
import           Test.Hspec
import           Test.Hspec.QuickCheck
import           Test.QuickCheck

spec :: Spec
spec =
    describe "utility functions" $ do
        prop "bsToInteger . integerToBS" getPutInteger
        prop "decodeHex . encodeHex" $ forAll arbitraryBS fromToHex
        prop "compare updateIndex with Data.Sequence" testUpdateIndex
        prop "matchTemplate" testMatchTemplate
        prop "testing matchTemplate with two lists" testMatchTemplateLen
        prop "test eitherToMaybe" testEitherToMaybe
        prop "test maybeToEither" testMaybeToEither

{- Various utilities -}

getPutInteger :: Integer -> Bool
getPutInteger i = bsToInteger (integerToBS $ abs i) == abs i

fromToHex :: BS.ByteString -> Bool
fromToHex bs = decodeHex (encodeHex bs) == Just bs

testUpdateIndex :: [Int] -> Int -> Int -> Bool
testUpdateIndex xs v i =
    updateIndex i xs (const v) == toList (Seq.update i v $ Seq.fromList xs)

testMatchTemplate :: [Int] -> Int -> Bool
testMatchTemplate as i = catMaybes res == bs
  where
    res = matchTemplate as bs (==)
    idx =
        if null as
            then 0
            else i `mod` length as
    bs = permutations as !! idx

testMatchTemplateLen :: [Int] -> [Int] -> Bool
testMatchTemplateLen as bs = length bs == length res
  where
    res = matchTemplate as bs (==)

testEitherToMaybe :: Either String Int -> Bool
testEitherToMaybe (Right v) = eitherToMaybe (Right v) == Just v
testEitherToMaybe e = isNothing (eitherToMaybe e)

testMaybeToEither :: Maybe Int -> String -> Bool
testMaybeToEither (Just v) str = maybeToEither str (Just v) == Right v
testMaybeToEither m str = maybeToEither str m == Left str

{-- Test Utilities --}

customCerealID :: Eq a => Get a -> Putter a -> a -> Bool
customCerealID g p a = runGet g (runPut (p a)) == Right a

readTestFile :: A.FromJSON a => FilePath -> IO a
readTestFile fp = do
    fileM <- A.decodeFileStrict $ "data/" <> fp
    maybe (error $ "Could not read test file " <> fp) return fileM