packages feed

bech32-th-1.0.2: test/Codec/Binary/Bech32/THSpec.hs

module Codec.Binary.Bech32.THSpec
    ( spec
    ) where

import Prelude

import Codec.Binary.Bech32
    ( CharPosition (..)
    , HumanReadablePartError (..)
    , humanReadableCharMaxBound
    , humanReadableCharMinBound
    , humanReadablePartMaxLength
    , humanReadablePartMinLength
    )
import Codec.Binary.Bech32.TH
    ( humanReadablePart )
import Control.Monad
    ( forM_ )
import Language.Haskell.TH.Quote
    ( QuasiQuoter (quoteExp) )
import Language.Haskell.TH.Syntax
    ( Exp (..), runQ )
import Test.Hspec
    ( Spec, describe, it, shouldSatisfy, shouldThrow )

spec :: Spec
spec =
    describe "Quasi-Quotations" $

        describe "Human-Readable Prefixes" $ do
            let mkHumanReadablePartExp = runQ . quoteExp humanReadablePart

            describe "Parsing valid human-readable prefixes should succeed." $
                forM_ validHumanReadableParts $ \hrp ->
                    it (show hrp) $
                        mkHumanReadablePartExp hrp >>=
                            (`shouldSatisfy` isAppE)

            describe "Parsing invalid human-readable prefixes should fail." $
                forM_ invalidHumanReadableParts $ \(hrp, expectedError) ->
                    it (show hrp) $
                        mkHumanReadablePartExp hrp
                            `shouldThrow` (== expectedError)

-- | Matches only function application expressions.
--
isAppE :: Exp -> Bool
isAppE AppE {} = True
isAppE _       = False

-- | A selection of valid human-readable prefixes, that when parsed with the
--   'humanReadablePart' quasiquoter should not result in an exception.
--
-- Note that this is not by any means intended to be an exhaustive list.
-- The underlying parsing logic, provided by `humanReadablePartFromText`,
-- is already tested in the `bech32` package.
--
validHumanReadableParts :: [String]
validHumanReadableParts =
    [ replicate humanReadablePartMinLength humanReadableCharMinBound
    , replicate humanReadablePartMaxLength humanReadableCharMaxBound
    , "addr"
    ]

-- | A selection of invalid human-readable prefixes, along with the errors that
--   we expect to see if we attempt to parse them with the 'humanReadablePart'
--   quasi-quoter.
--
-- Note that this is not by any means intended to be an exhaustive list.
-- The underlying parsing logic, provided by `humanReadablePartFromText`,
-- is already tested in the `bech32` package.
--
invalidHumanReadableParts :: [(String, HumanReadablePartError)]
invalidHumanReadableParts =
    [ ( replicate (pred minLen) minChar
      , HumanReadablePartTooShort
      )
    , ( replicate (succ maxLen) maxChar
      , HumanReadablePartTooLong
      )
    , ( replicate (succ minLen) (pred minChar)
      , HumanReadablePartContainsInvalidChars (CharPosition <$> [0 .. minLen])
      )
    , ( replicate (succ minLen) (succ maxChar)
      , HumanReadablePartContainsInvalidChars (CharPosition <$> [0 .. minLen])
      )
    ]
  where
    minChar = humanReadableCharMinBound
    maxChar = humanReadableCharMaxBound
    minLen = humanReadablePartMinLength
    maxLen = humanReadablePartMaxLength