opc-xml-da-client-0.1: quickcheck-util/OpcXmlDaClient/QuickCheckUtil/Gens.hs
module OpcXmlDaClient.QuickCheckUtil.Gens where
import qualified Data.Text as Text
import qualified Data.Time.Calendar.OrdinalDate as Time
import qualified Data.Time.LocalTime as Time
import Test.QuickCheck
import Prelude hiding (choose, optional)
-- * General
maybeOf :: Gen a -> Gen (Maybe a)
maybeOf gen =
oneof [pure Nothing, Just <$> gen]
onceIn :: Int -> Gen Bool
onceIn n =
(== 1) <$> chooseInt (1, n)
-- * Time
year :: Gen Integer
year = choose (-9999, 9999)
dayOfCommonYear :: Gen Int
dayOfCommonYear = choose (1, 365)
dayOfLeapYear :: Gen Int
dayOfLeapYear = choose (1, 366)
-- |
-- The arbitrary instance generates scarce values.
day :: Gen Day
day = do
_year <- year
_dayOfYear <- if Time.isLeapYear _year then dayOfLeapYear else dayOfCommonYear
return $ Time.fromOrdinalDate _year _dayOfYear
-- |
-- The arbitrary instance generates broken values.
-- This is an alternative to it.
timeZone :: Gen TimeZone
timeZone =
Time.hoursToTimeZone <$> choose (-24, 24)
utcTimeInRange :: UTCTime -> UTCTime -> Gen UTCTime
utcTimeInRange min max =
systemToUTCTime . flip MkSystemTime 0 <$> choose (minSec, maxSec)
where
MkSystemTime minSec _ = utcToSystemTime min
MkSystemTime maxSec _ = utcToSystemTime max
recentTime :: Gen UTCTime
recentTime =
utcTimeInRange (read "2020-01-01 00:00:00Z") (unsafePerformIO (getCurrentTime))
-- * Text
text :: Gen Text
text =
do
firstSentence <- sentence
otherSentences <- listOf $ do
doParagraph <- onceIn 5
let prefix = if doParagraph then "\n" else " "
(prefix <>) <$> sentence
return (mconcat (firstSentence : otherSentences))
sentence :: Gen Text
sentence =
do
firstWord <- Text.toTitle <$> word
extraWordsAmount <- chooseInt (0, 20)
extraWords <- replicateM extraWordsAmount $ do
prefix <- do
prependPunctuation <- (== 0) <$> chooseInt (0, 9)
if prependPunctuation
then elements [", ", ": ", " - "]
else pure " "
theWord <- do
titleCase <- (== 0) <$> chooseInt (0, 9)
(if titleCase then Text.toTitle else id) <$> word
return (prefix <> theWord)
return (firstWord <> mconcat extraWords)
word :: Gen Text
word =
elements
["foo", "bar", "qux", "quux", "quuz", "corge", "grault", "garply", "waldo", "fred", "plugh", "xyzzy", "thud"]