sauron-0.0.0.0: test/Test/Sauron/Top/Tweet.hs
module Test.Sauron.Top.Tweet (tweetSpec) where
import Data.Time.Calendar (fromGregorian)
import Data.Time.Clock (DiffTime, UTCTime (..), secondsToDiffTime)
import Data.Time.Format (defaultTimeLocale, parseTimeM)
import Hedgehog (Gen, forAll, tripping)
import Test.Hspec (Spec, describe, it, shouldBe, shouldReturn)
import Test.Hspec.Hedgehog (hedgehog)
import Sauron.Top.Tweet (Tweet (..), parseTime, showTime, subtractSecond)
import qualified Data.Aeson as Aeson
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
tweetSpec :: Spec
tweetSpec = describe "Tweet" $ do
it "parses the time" $ do
parseTime "2022-09-01T07:54:18.000Z" `shouldBe`
Just (UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:18"))
it "shows the time" $ do
showTime (UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:18"))
`shouldBe` "2022-09-01T07:54:18Z"
it "subtracts one second" $ do
subtractSecond (UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:18"))
`shouldBe` (UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:17"))
it "parses the example JSON tweet timeline" $
Aeson.eitherDecodeFileStrict "example.json" `shouldReturn` Right exampleTweets
it "decodeJSON . encodeJSON = id" $ hedgehog $ do
tweet <- forAll genTweet
tripping tweet Aeson.encode Aeson.eitherDecode
parseTod :: String -> DiffTime
parseTod
= fromMaybe (error "parsing time")
. parseTimeM True defaultTimeLocale "%H:%M:%S"
exampleTweets :: [Tweet]
exampleTweets =
[ Tweet
{ tweetId = "1565283709275803650"
, tweetText = "@klarkc In this particular case, laziness wasn't the problem. Something weirder was going on ๐ค"
, tweetLikeCount = 0
, tweetCreatedAt = UTCTime (fromGregorian 2022 9 1) (parseTod "10:21:32")
}
, Tweet
{ tweetId = "1565246658128056320"
, tweetText = "If you haven't finished your tea, I invite you to read one of my previous journeys into the wonders of the SQLite type system ๐บ๏ธ๐ซ๐\n\nhttps://t.co/4RElElHu0Z"
, tweetLikeCount = 1
, tweetCreatedAt = UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:18")
}
, Tweet
{ tweetId = "1565246655103995905"
, tweetText = "๐ฎ I still had some theories about the space leak. All the metrics show that it's not the Haskell process that leaks memory.\n\nI was even suspecting space leaks in SQLite itself as my setup was unusual. But I didn't have the time to verify my hypothesis so we'll never know..."
, tweetLikeCount = 1
, tweetCreatedAt = UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:18")
}
, Tweet
{ tweetId = "1565246652121767936"
, tweetText = "Are you still here? Do you still want to know how I solved this space leak? Very simple:\n\n๐๏ธ I left my job\n\nNow, it's no longer my problem and somebody else will continue what I've started ๐ถ"
, tweetLikeCount = 6
, tweetCreatedAt = UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:17")
}
, Tweet
{ tweetId = "1565246649185849344"
, tweetText = "๐บ๏ธ Now, real digging started. I had to use old Unix tools as my grandpa did in the good old times.\n\nI sampled the output of the /proc/rss values to check the real memory usage of my process. I've even looked at the diff between mmaped memory regions.\n\nStill, no results ๐
"
, tweetLikeCount = 1
, tweetCreatedAt = UTCTime (fromGregorian 2022 9 1) (parseTod "07:54:16")
}
]
genTweet :: Gen Tweet
genTweet = Tweet
<$> Gen.text (Range.linear 1 20) Gen.digit
<*> Gen.text (Range.linear 1 280) Gen.unicode
<*> Gen.int (Range.linear 0 100_000)
<*> genUTCTime
genUTCTime :: Gen UTCTime
genUTCTime = do
y <- toInteger <$> Gen.int (Range.constant 2000 2022)
m <- Gen.int (Range.constant 1 12)
d <- Gen.int (Range.constant 1 28)
let day = fromGregorian y m d
secs <- toInteger <$> Gen.int (Range.constant 0 86401)
let diff = secondsToDiffTime secs
pure $ UTCTime day diff