Skip to content

Commit d1d2eb9

Browse files
committed
io-sim: debug mode
1 parent 7eac27c commit d1d2eb9

File tree

2 files changed

+58
-17
lines changed

2 files changed

+58
-17
lines changed

io-sim/src/Control/Monad/IOSim.hs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE BangPatterns #-}
2+
{-# LANGUAGE LambdaCase #-}
23
{-# LANGUAGE ExplicitNamespaces #-}
34
{-# LANGUAGE NamedFieldPuns #-}
45
{-# LANGUAGE RankNTypes #-}
@@ -89,14 +90,17 @@ module Control.Monad.IOSim
8990
import Prelude
9091

9192
import Data.Bifoldable
93+
import Data.Bifunctor (first)
9294
import Data.Dynamic (fromDynamic)
95+
import Data.Functor (void)
9396
import Data.List (intercalate)
9497
import Data.Maybe (catMaybes)
9598
import Data.Set (Set)
9699
import qualified Data.Set as Set
97100
import Data.Typeable (Typeable)
98101

99102
import Data.List.Trace (Trace (..))
103+
import qualified Data.List.Trace as Trace
100104

101105
import Control.Exception (throw)
102106

@@ -107,13 +111,13 @@ import Control.Monad.Class.MonadThrow as MonadThrow
107111

108112
import Control.Monad.IOSim.Internal (runSimTraceST)
109113
import Control.Monad.IOSim.Types
110-
import Control.Monad.IOSimPOR.Internal (controlSimTraceST)
114+
import qualified Control.Monad.IOSimPOR.Internal as IOSimPOR (controlSimTraceST)
111115
import Control.Monad.IOSimPOR.QuickCheckUtils
112116

113117
import Test.QuickCheck
114118

115-
116119
import System.IO.Unsafe
120+
import qualified Debug.Trace as Debug
117121

118122

119123
selectTraceEvents
@@ -497,11 +501,12 @@ exploreSimTrace optsf mainAction k =
497501
-> Int -- branching factor
498502
-> ScheduleControl -> Maybe (SimTrace a) -> ST s Property
499503
explore cacheRef n m control passingTrace = do
500-
traceWithRaces <- controlSimTraceST (explorationStepTimelimit opts) control mainAction
504+
traceWithRaces <- IOSimPOR.controlSimTraceST (explorationStepTimelimit opts) control mainAction
501505
(readRaces, trace0) <- detachTraceRacesST traceWithRaces
502506
(readSleeperST, trace) <- compareTracesST passingTrace trace0
503507
conjoinNoCatchST
504508
[ do sleeper <- readSleeperST
509+
() <- traceDebugLog (explorationDebugLevel opts) traceWithRaces
505510
return $ counterexample ("Schedule control: " ++ show control)
506511
$ counterexample
507512
(case sleeper of
@@ -520,15 +525,13 @@ exploreSimTrace optsf mainAction k =
520525
-- node.
521526
races <- catMaybes
522527
<$> (readRaces >>= traverse (cachedST cacheRef) . take limit)
528+
() <- traceDebugLog (explorationDebugLevel opts) traceWithRaces
523529
let branching = length races
524530
-- tabulate "Races explored" (map show races) $
525531
tabulate "Branching factor" [bucket branching]
526532
. tabulate "Race reversals per schedule" [bucket (raceReversals control)]
527533
<$> conjoinParST
528-
[ --Debug.trace "New schedule:" $
529-
--Debug.trace (" "++show r) $
530-
--counterexample ("Schedule control: " ++ show r) $
531-
explore cacheRef n' ((m-1) `max` 1) r (Just trace0)
534+
[ explore cacheRef n' ((m-1) `max` 1) r (Just trace0)
532535
| (r,n') <- zip races (divide (n-branching) branching) ]
533536
]
534537

@@ -546,8 +549,8 @@ exploreSimTrace optsf mainAction k =
546549

547550
showThread :: (ThreadId,Maybe ThreadLabel) -> String
548551
showThread (tid,lab) =
549-
show tid ++ (case lab of Nothing -> ""
550-
Just l -> " ("++l++")")
552+
ppIOSimThreadId tid ++ (case lab of Nothing -> ""
553+
Just l -> " ("++l++")")
551554

552555
-- insert a schedule into the cache
553556
cachedST :: STRef s (Set ScheduleControl) -> ScheduleControl -> ST s (Maybe ScheduleControl)
@@ -562,8 +565,6 @@ exploreSimTrace optsf mainAction k =
562565
-- Caching in ST monad
563566
--
564567

565-
-- TODO: Use STRef!
566-
567568
-- It is possible for the same control to be generated several times.
568569
-- To avoid exploring them twice, we keep a cache of explored schedules.
569570
createCacheST :: ST s (STRef s (Set ScheduleControl))
@@ -578,6 +579,17 @@ exploreSimTrace optsf mainAction k =
578579
cacheSizeST = fmap Set.size . readSTRef
579580

580581

582+
-- | Trace `SimTrace` to `stderr`.
583+
--
584+
traceDebugLog :: Int -> SimTrace a -> ST s ()
585+
traceDebugLog logLevel _trace | logLevel <= 0 = pure ()
586+
traceDebugLog 1 trace = Debug.traceM $ "Simulation trace with discovered schedules:\n"
587+
++ Trace.ppTrace show (ppSimEvent 0 0 0) (ignoreRaces $ void `first` trace)
588+
traceDebugLog _ trace = Debug.traceM $ "Simulation trace with discovered schedules:\n"
589+
++ Trace.ppTrace show (ppSimEvent 0 0 0) (void `first` trace)
590+
591+
592+
581593
-- | A specialised version of `controlSimTrace'.
582594
--
583595
-- An internal function.
@@ -593,8 +605,10 @@ replaySimTrace :: forall a test. (Testable test)
593605
-- will not contain any race events
594606
-> Property
595607
replaySimTrace opts mainAction control k =
596-
let trace = runST $ fmap snd $ detachTraceRacesST =<<
597-
controlSimTraceST (explorationStepTimelimit opts) control mainAction
608+
let trace = runST $ do
609+
(_readRaces, trace) <- IOSimPOR.controlSimTraceST (explorationStepTimelimit opts) control mainAction
610+
>>= detachTraceRacesST
611+
return (ignoreRaces trace)
598612
in property (k trace)
599613

600614
-- | Run a simulation using a given schedule. This is useful to reproduce
@@ -611,8 +625,22 @@ controlSimTrace :: forall a.
611625
-> (forall s. IOSim s a)
612626
-- ^ a simulation to run
613627
-> SimTrace a
614-
controlSimTrace limit control mainAction =
615-
runST (controlSimTraceST limit control mainAction)
628+
controlSimTrace limit control main =
629+
runST (controlSimTraceST limit control main)
630+
631+
controlSimTraceST :: Maybe Int -> ScheduleControl -> IOSim s a -> ST s (SimTrace a)
632+
controlSimTraceST limit control main =
633+
ignoreRaces <$> IOSimPOR.controlSimTraceST limit control main
634+
635+
636+
--
637+
-- Utils
638+
--
639+
640+
ignoreRaces :: SimTrace a -> SimTrace a
641+
ignoreRaces = Trace.filter (\a -> case a of
642+
SimPOREvent { seType = EventRaces {} } -> False
643+
_ -> True)
616644

617645
raceReversals :: ScheduleControl -> Int
618646
raceReversals ControlDefault = 0
@@ -629,6 +657,7 @@ raceReversals ControlFollow{} = error "Impossible: raceReversals ControlFoll
629657
-- this far, then we collect its identity only if it is reached using
630658
-- unsafePerformIO.
631659

660+
-- TODO: return StepId
632661
compareTracesST :: forall a b s.
633662
Maybe (SimTrace a) -- ^ passing
634663
-> SimTrace b -- ^ failing

io-sim/src/Control/Monad/IOSim/Types.hs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,10 +1146,21 @@ data ExplorationOptions = ExplorationOptions{
11461146
-- catching infinite loops etc.
11471147
--
11481148
-- The default value is `Nothing`.
1149-
explorationReplay :: Maybe ScheduleControl
1149+
explorationReplay :: Maybe ScheduleControl,
11501150
-- ^ A schedule to replay.
11511151
--
11521152
-- The default value is `Nothing`.
1153+
explorationDebugLevel :: Int
1154+
-- ^ Log detailed trace to stderr containing information on discovered
1155+
-- races. The trace does not contain the result of the simulation, unless
1156+
-- one will do that explicitly inside the simulation.
1157+
--
1158+
-- level 0: don't show any output,
1159+
-- level 1: show simulation trace with discovered schedules
1160+
-- level 2: show simulation trace with discovered schedules and races
1161+
--
1162+
-- NOTE: discovered schedules & races are not exposed to the user in the
1163+
-- callback of `exploreSimTrace` or in the output of `controlSimTrace`.
11531164
}
11541165
deriving Show
11551166

@@ -1158,7 +1169,8 @@ stdExplorationOptions = ExplorationOptions{
11581169
explorationScheduleBound = 100,
11591170
explorationBranching = 3,
11601171
explorationStepTimelimit = Nothing,
1161-
explorationReplay = Nothing
1172+
explorationReplay = Nothing,
1173+
explorationDebugLevel = 0
11621174
}
11631175

11641176
type ExplorationSpec = ExplorationOptions -> ExplorationOptions

0 commit comments

Comments
 (0)