llsd-0.1.0.1: TestData.hs
{-# LANGUAGE TypeSynonymInstances #-}
-- |
-- Module : TestData - Part of the Test LLSD Utility
-- Copyright : (c) Linden Lab 2009
-- License : MIT
-- Maintainer : bos@lindenlab.com
-- Stability : provisional
-- Portability : portable
module TestData where
import Network.Format.LLSD
import Control.Monad
import Data.Maybe
import qualified Data.Map as M
import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import Data.UUID (UUID)
import Network.URI (URI, nullURI, parseURIReference)
import Test.QuickCheck
import System.Random
data LogItem =
LogIn { liAgent:: UUID, liTime:: UTCTime, liFirstTime:: Bool, liReferer:: URI }
| LogOut { liAgent:: UUID, liTime:: UTCTime, liAttachments:: Attachments }
| LogMisc { liAgent:: UUID, liTime:: UTCTime, liThis:: Int, liThat:: Double }
| LogError
deriving (Eq, Show)
instance SData LogItem where
toLLSD (LogIn a t ft r) = llsd `with` "event" .= "login"
`with` "agent" .= a
`with` "time" .= t
`with` "firsttime" .= ft
`with` "referer" .= r
toLLSD (LogOut a t ats) = llsd `with` "event" .= "logout"
`with` "agent" .= a
`with` "time" .= t
`with` "attachments" .= ats
toLLSD (LogMisc a t x y) = llsd `with` "event" .= "misc"
`with` "agent" .= a
`with` "time" .= t
`with` "this" .= x
`with` "that" .= y
toLLSD LogError = undef
fromLLSD l = case l `at` "event" of
"login" -> LogIn (l `at` "agent") (l `at` "time")
(l `at` "firsttime") (l `at` "referer")
"logout" -> LogOut (l `at` "agent") (l `at` "time")
(l `at` "attachments")
"misc" -> LogMisc (l `at` "agent") (l `at` "time")
(l `at` "this") (l `at` "that")
_ -> LogError
type Attachments = [(String, UUID)]
instance SData Attachments where
toLLSD = toLLSD . map entryToLLSD
where entryToLLSD (s, u) = llsd `with` "point" .= s
`with` "inv" .= u
fromLLSD = map entryFromLLSD . fromLLSD
where entryFromLLSD l = (l `at` "point", l `at` "inv")
data LogStats = LogStats {
lsCountIn, lsCountOut, lsCountMisc, lsCountError:: !Int,
lsAttachmentsHistogram:: !(M.Map Int Int)
}
deriving (Eq, Show)
zeroStats :: LogStats
zeroStats = LogStats 0 0 0 0 M.empty
note :: LogItem -> LogStats -> LogStats
note (LogIn _ _ _ _) s = s { lsCountIn = lsCountIn s + 1 }
note (LogOut _ _ ats) s =
s { lsCountOut = lsCountOut s + 1,
lsAttachmentsHistogram =
M.insertWith' (+) (length ats) 1 (lsAttachmentsHistogram s) }
-- must use the strict version of insertWith
note (LogMisc _ _ _ _) s = s { lsCountMisc = lsCountMisc s + 1 }
note LogError s = s { lsCountError = lsCountError s + 1 }
makeLogItems :: Int -> IO [LogItem]
makeLogItems n = getStdRandom makeEm
where makeEm g0 = let (g1, g2) = split g0 in
(generate n g1 (arbitraryItems n), g2)
arbitraryItems :: Int -> Gen [LogItem]
arbitraryItems n = replicateM n arbitraryItem
arbitraryItem, arbitraryIn, arbitraryOut, arbitraryMisc :: Gen LogItem
arbitraryItem = oneof [ arbitraryIn, arbitraryOut, arbitraryMisc ]
arbitraryIn =
liftM4 LogIn arbitraryUUID arbitraryTime arbitrary arbitraryURI
arbitraryOut =
liftM3 LogOut arbitraryUUID arbitraryTime arbitraryAttachements
arbitraryMisc =
liftM4 LogMisc arbitraryUUID arbitraryTime arbitrary arbitrary
arbitraryUUID :: Gen UUID
arbitraryUUID = (fst . random) `fmap` rand
arbitraryTime :: Gen UTCTime
arbitraryTime = (posixSecondsToUTCTime . realToFrac) `fmap` choose (0, century)
where century :: Integer
century = 50*365*24*60*60
arbitraryURI :: Gen URI
arbitraryURI = return $ fromMaybe nullURI
$ parseURIReference "http://example.com/"
arbitraryAttachements :: Gen Attachments
arbitraryAttachements = choose (0,22) >>= \n -> replicateM n arbAttach
where arbAttach = do
p <- elements points
u <- arbitraryUUID
return (p, u)
points = [ "head", "neck", "spine", "pelvis" ]
++ [ side ++ "-" ++ part |
side <- [ "left", "right" ],
part <- [ "shoulder", "arm", "hand", "leg", "foot" ]]