packages feed

hegel-0.1.0: conformance/TestHashmaps.hs

{-# LANGUAGE OverloadedStrings #-}

-- | Conformance binary: generates hash maps (dicts) and writes metrics.
module Main (main) where

import qualified Data.Aeson as Aeson
import Data.Aeson (Value (..))
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Maybe (fromMaybe, listToMaybe)
import qualified Data.Map.Strict as Map
import Data.Text (Text)
import Hegel
import System.Environment (getArgs)

parseParams :: IO (Map.Map String Value)
parseParams = do
  args <- getArgs
  pure $
    fromMaybe Map.empty $
      Aeson.decode . LBS.pack =<< listToMaybe args

getIntParam :: Map.Map String Value -> String -> Maybe Int
getIntParam m k = round <$> (getNumber =<< Map.lookup k m)
  where
    getNumber (Number n) = Just n
    getNumber _ = Nothing

getIntParamDefault :: Map.Map String Value -> String -> Int -> Int
getIntParamDefault m k defaultValue = fromMaybe defaultValue (getIntParam m k)

getTextParam :: Map.Map String Value -> String -> Maybe Text
getTextParam m k = getText =<< Map.lookup k m
  where
    getText (Aeson.String t) = Just t
    getText _ = Nothing

intOrNull :: Maybe Int -> String
intOrNull = maybe "null" show

main :: IO ()
main = do
  params <- parseParams
  let minSize = getIntParamDefault params "min_size" 0
  let maxSize = getIntParamDefault params "max_size" 10
  let keyType = fromMaybe "integer" (getTextParam params "key_type")
  let minKey = getIntParamDefault params "min_key" (-1000)
  let maxKey = getIntParamDefault params "max_key" 1000
  let minValBound = getIntParamDefault params "min_value" (-1000)
  let maxValBound = getIntParamDefault params "max_value" 1000
  testCases <- getTestCases
  if keyType == "string"
    then runHegelTest (\settings -> settings { settingsTestCases = testCases }) $ \tc -> do
      let keyGen = text def { rangeMin = Just 1, rangeMax = Just 10 }
      let valGen = integers def { rangeMin = Just minValBound, rangeMax = Just maxValBound }
      let mapGen = hashmaps keyGen valGen def { rangeMin = Just minSize, rangeMax = Just maxSize }
      pairs <- draw tc mapGen
      let len = length pairs
      let vals = map snd pairs
      let minVal = if null vals then Nothing else Just (minimum vals)
      let maxVal = if null vals then Nothing else Just (maximum vals)
      writeMetrics
        [ ("size", show len),
          ("min_key", "null"),
          ("max_key", "null"),
          ("min_value", intOrNull minVal),
          ("max_value", intOrNull maxVal)
        ]
    else runHegelTest (\settings -> settings { settingsTestCases = testCases }) $ \tc -> do
      let keyGen = integers def { rangeMin = Just minKey, rangeMax = Just maxKey }
      let valGen = integers def { rangeMin = Just minValBound, rangeMax = Just maxValBound }
      let mapGen = hashmaps keyGen valGen def { rangeMin = Just minSize, rangeMax = Just maxSize }
      pairs <- draw tc mapGen
      let len = length pairs
      let keys = map fst pairs
      let vals = map snd pairs
      let minKeyResult = if null keys then Nothing else Just (minimum keys)
      let maxKeyResult = if null keys then Nothing else Just (maximum keys)
      let minValResult = if null vals then Nothing else Just (minimum vals)
      let maxValResult = if null vals then Nothing else Just (maximum vals)
      writeMetrics
        [ ("size", show len),
          ("min_key", intOrNull minKeyResult),
          ("max_key", intOrNull maxKeyResult),
          ("min_value", intOrNull minValResult),
          ("max_value", intOrNull maxValResult)
        ]