{-# LANGUAGE ExistentialQuantification #-}
import Control.DeepSeq (NFData, deepseq)
import Data.Ix (Ix(..))
import Test.Tasty.Bench (Benchmark, bgroup, bcompare, bench, nf, defaultMain)
import qualified Unicode.Char.Identifiers.Security as Security
import qualified Unicode.Internal.Char.Security.Confusables as Confusables
import qualified Unicode.Internal.Char.Security.IntentionalConfusables as Confusables
-- | A unit benchmark
data Bench = forall a. (NFData a) => Bench
{ _title :: !String -- ^ Name
, _func :: Char -> a -- ^ Function to benchmark
}
main :: IO ()
main = defaultMain
[ bgroup "Unicode.Char.Identifiers.Security"
[ bgroup "Identifier Status"
[ benchNF "isAllowedInIdentifier" (show . Security.isAllowedInIdentifier)
]
, bgroup "Identifier Types"
[ benchNF "identifierTypes" (show . Security.identifierTypes)
]
, bgroup "Confusables"
[ bgroup' "confusablePrototype"
[ Bench "CString" Confusables.confusablePrototype
, Bench "String" Security.confusablePrototype
]
-- , benchNF "prototype" Security.prototype
, bgroup' "intentionalConfusables"
[ Bench "CString" Confusables.intentionalConfusables
, Bench "String" Security.intentionalConfusables
]
, benchNF "isIntentionallyConfusable" Security.intentionalConfusables
]
]
]
where
bgroup' groupTitle bs = bgroup groupTitle
[ benchNF' groupTitle title f
| Bench title f <- bs
]
-- [NOTE] Works if groupTitle uniquely identifies the benchmark group.
benchNF' groupTitle title = case title of
"CString" -> benchNF title
_ ->
bcompare ("$NF == \"CString\" && $(NF-1) == \"" ++ groupTitle ++ "\"")
. benchNF title
benchNF :: forall a. (NFData a) => String -> (Char -> a) -> Benchmark
benchNF t f = bench t $ nf (fold_ f) (minBound, maxBound)
fold_ :: forall a. (NFData a) => (Char -> a) -> (Char, Char) -> ()
fold_ f = foldr (deepseq . f) () . range