packages feed

unicode-data-security-0.1.0: bench/Main.hs

{-# 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