effectful-tracing-0.1.0.0: test/Effectful/Tracing/IdGenSpec.hs
-- |
-- Module : Effectful.Tracing.IdGenSpec
-- Description : Tests for the id generators (newTraceId / newSpanId).
--
-- "Effectful.Tracing.IdsSpec" pins the codec and validity edges, and the
-- round-trip over arbitrary bytes lives in "Effectful.Tracing.PropertySpec".
-- Neither exercises the generators themselves, which draw real bytes from the
-- configured entropy source. This module does: it asserts that a freshly
-- generated id is valid, round-trips through hex, and that a large batch is
-- collision-free.
--
-- The same assertions run whichever byte source the library was built with, so
-- building the suite with the @secure-ids@ cabal flag turns this into coverage
-- of the @crypton@ system-entropy path (otherwise it covers the default
-- splitmix PRNG). The group label reflects which source is under test.
{-# LANGUAGE CPP #-}
module Effectful.Tracing.IdGenSpec
( tests
) where
import Control.Monad (replicateM)
import Data.Set qualified as Set
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertBool, testCase, (@?=))
import Effectful.Tracing
( isValidSpanId
, isValidTraceId
, newSpanId
, newTraceId
, spanIdFromHex
, spanIdToHex
, traceIdFromHex
, traceIdToHex
)
-- | Which entropy source these assertions are exercising, decided by the
-- @secure-ids@ cabal flag (which sets @-DSECURE_IDS@ on this suite).
sourceName :: String
#ifdef SECURE_IDS
sourceName = "crypton system entropy (secure-ids)"
#else
sourceName = "splitmix PRNG (default)"
#endif
-- | How many ids to mint when checking for collisions. Large enough that a
-- broken (constant or low-entropy) source would almost certainly repeat: even
-- the 8-byte span id has a birthday-collision probability here on the order of
-- 1e-12.
batchSize :: Int
batchSize = 10000
tests :: TestTree
tests =
testGroup
("Id generation: " <> sourceName)
[ testCase "a generated trace id is valid" $ do
tid <- newTraceId
assertBool "valid trace id" (isValidTraceId tid)
, testCase "a generated span id is valid" $ do
sid <- newSpanId
assertBool "valid span id" (isValidSpanId sid)
, testCase "a generated trace id round-trips through hex" $ do
tid <- newTraceId
traceIdFromHex (traceIdToHex tid) @?= Just tid
, testCase "a generated span id round-trips through hex" $ do
sid <- newSpanId
spanIdFromHex (spanIdToHex sid) @?= Just sid
, testCase (show batchSize <> " generated trace ids are all distinct") $ do
ids <- replicateM batchSize newTraceId
Set.size (Set.fromList ids) @?= batchSize
, testCase (show batchSize <> " generated span ids are all distinct") $ do
ids <- replicateM batchSize newSpanId
Set.size (Set.fromList ids) @?= batchSize
]