Documentation
¶
Overview ¶
Package detsim is a deterministic simulation testing library: a virtual-time event kernel, a fault-injectable network, and a fault-injectable storage layer. See the rt and rewrite packages for running ordinary goroutine-based code deterministically instead.
Example ¶
package main
import (
"fmt"
detsim "github.com/arshnah/detsim"
)
func main() {
sim := detsim.New(1)
net := detsim.NewNetwork(sim)
net.Register("a", func(from detsim.NodeID, msg any) {
fmt.Println("a received:", msg, "from", from)
})
net.Register("b", func(from detsim.NodeID, msg any) {
fmt.Println("b received:", msg, "from", from)
net.Send("b", "a", "pong")
})
net.Send("a", "b", "ping")
sim.RunFor(100)
}
Output:
Index ¶
- Variables
- type FaultProfile
- type FaultyStorage
- func (f *FaultyStorage) Crash()
- func (f *FaultyStorage) ReadAt(p []byte, offset int64) (n int, err error)
- func (f *FaultyStorage) SeedRaw(data []byte)
- func (f *FaultyStorage) Size() int64
- func (f *FaultyStorage) Sync() error
- func (f *FaultyStorage) WriteAt(data []byte, offset int64) (n int, err error)
- type Network
- func (n *Network) Heal(a, b NodeID)
- func (n *Network) HealAll()
- func (n *Network) Partition(groupA, groupB []NodeID)
- func (n *Network) Register(id NodeID, handler func(from NodeID, msg any))
- func (n *Network) Send(from, to NodeID, msg any)
- func (n *Network) SetDelayRange(min, max VirtualTime)
- func (n *Network) SetDropRate(rate float64)
- type NodeID
- type Sim
- func (s *Sim) After(d VirtualTime, fn func(*Sim))
- func (s *Sim) At(t VirtualTime, fn func(*Sim))
- func (s *Sim) Immediately(fn func(*Sim))
- func (s *Sim) Now() VirtualTime
- func (s *Sim) Run() (steps int, ranToCompletion bool)
- func (s *Sim) RunFor(d VirtualTime) (steps int)
- func (s *Sim) RunUntil(t VirtualTime) (steps int)
- func (s *Sim) SetMaxSteps(n int)
- type VirtualTime
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrDiskFull = errors.New("detsim: disk full")
ErrDiskFull is returned by FaultyStorage.WriteAt when MaxSize would be exceeded.
Functions ¶
This section is empty.
Types ¶
type FaultProfile ¶
type FaultProfile struct {
TornWriteRate float64
CorruptByteRate float64
SkipSyncRate float64
ReorderRate float64
MaxSize int64
}
FaultProfile controls which faults FaultyStorage injects and how often.
type FaultyStorage ¶
type FaultyStorage struct {
// contains filtered or unexported fields
}
FaultyStorage is a byte-addressable virtual disk that injects torn writes, corruption, dropped syncs, and reordered commits.
Example ¶
package main
import (
"fmt"
detsim "github.com/arshnah/detsim"
)
func main() {
profile := detsim.FaultProfile{TornWriteRate: 0.3, CorruptByteRate: 0.4}
for seed := int64(1); seed <= 5; seed++ {
fs := detsim.NewFaultyStorage(seed, profile)
fs.WriteAt([]byte("hello world"), 0)
fs.Sync()
got := make([]byte, 11)
fs.ReadAt(got, 0)
if string(got) == "hello world" {
fmt.Printf("seed %d: clean\n", seed)
} else {
fmt.Printf("seed %d: corrupted\n", seed)
}
}
}
Output:
func NewFaultyStorage ¶
func NewFaultyStorage(seed int64, profile FaultProfile) *FaultyStorage
NewFaultyStorage builds a FaultyStorage seeded for reproducible fault injection.
func (*FaultyStorage) Crash ¶
func (f *FaultyStorage) Crash()
Crash discards anything staged but not yet synced.
func (*FaultyStorage) ReadAt ¶
func (f *FaultyStorage) ReadAt(p []byte, offset int64) (n int, err error)
ReadAt reads from the current materialized view, committed data plus any pending writes. It follows the io.ReaderAt contract: io.EOF is returned when fewer than len(p) bytes are available, and (0, io.EOF) at or past the end.
func (*FaultyStorage) SeedRaw ¶ added in v1.0.0
func (f *FaultyStorage) SeedRaw(data []byte)
SeedRaw replaces the committed buffer wholesale and clears anything staged.
func (*FaultyStorage) Size ¶ added in v1.0.0
func (f *FaultyStorage) Size() int64
Size returns the length of the current materialized view.
func (*FaultyStorage) Sync ¶
func (f *FaultyStorage) Sync() error
Sync commits pending writes, subject to SkipSyncRate and ReorderRate.
type Network ¶
type Network struct {
// contains filtered or unexported fields
}
Network is a fault-injectable network on top of a Sim.
func NewNetwork ¶
NewNetwork builds a Network driven by s's clock and Rand.
func (*Network) Heal ¶ added in v1.0.0
Heal clears the specific partition between a and b (both directions).
func (*Network) HealAll ¶
func (n *Network) HealAll()
HealAll clears every partition set by Partition.
func (*Network) Partition ¶
Partition blocks delivery between every node in groupA and every node in groupB.
func (*Network) Send ¶
Send delivers msg from from to to after a random delay, subject to drops and partitions.
func (*Network) SetDelayRange ¶
func (n *Network) SetDelayRange(min, max VirtualTime)
SetDelayRange sets the range delivery delay is drawn from.
func (*Network) SetDropRate ¶
SetDropRate sets the probability a send or delivery is dropped.
type Sim ¶
Sim is the deterministic event kernel.
func (*Sim) After ¶
func (s *Sim) After(d VirtualTime, fn func(*Sim))
After schedules fn to run d after the current virtual time. A negative d is clamped to zero. fn must not be nil; scheduling one panics immediately instead of mid-Run.
func (*Sim) At ¶
func (s *Sim) At(t VirtualTime, fn func(*Sim))
At schedules fn to run at absolute virtual time t. A t earlier than the current time is clamped to Now so virtual time never moves backwards.
func (*Sim) Immediately ¶
Immediately schedules fn as the next event.
func (*Sim) RunFor ¶ added in v1.0.0
func (s *Sim) RunFor(d VirtualTime) (steps int)
RunFor runs d more virtual time from the highest horizon requested so far, not from Now.
func (*Sim) RunUntil ¶
func (s *Sim) RunUntil(t VirtualTime) (steps int)
RunUntil runs events up to and including virtual time t.
func (*Sim) SetMaxSteps ¶
SetMaxSteps overrides the step budget Run enforces.
type VirtualTime ¶
VirtualTime is simulated time, an alias for time.Duration.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
detsim
command
|
|
|
detsim-rewrite
command
|
|
|
detsim-test
command
|
|
|
detsim-trace
command
Command detsim-trace reads the trace files detsim-test and rt.DumpTraceOnFailure write, and renders them for humans: an annotated timeline of every scheduling decision, per-goroutine stats, and a keep/drop diff between an original and a minimized trace.
|
Command detsim-trace reads the trace files detsim-test and rt.DumpTraceOnFailure write, and renders them for humans: an annotated timeline of every scheduling decision, per-goroutine stats, and a keep/drop diff between an original and a minimized trace. |
|
examples
|
|
|
Package minimize implements delta-debugging (ddmin) over a scheduler decision trace, shrinking a failing seed's trace down to a minimal one that still reproduces the failure.
|
Package minimize implements delta-debugging (ddmin) over a scheduler decision trace, shrinking a failing seed's trace down to a minimal one that still reproduces the failure. |
|
Package rewrite source-rewrites a Go package's goroutines, channels, sync locals, and a subset of time/rand/os/net calls to run on the rt package's deterministic scheduler, via a go build overlay rather than touching files on disk.
|
Package rewrite source-rewrites a Go package's goroutines, channels, sync locals, and a subset of time/rand/os/net calls to run on the rt package's deterministic scheduler, via a go build overlay rather than touching files on disk. |
|
Package rt is a cooperative, single-stepping scheduler for real Go goroutines.
|
Package rt is a cooperative, single-stepping scheduler for real Go goroutines. |
|
Package traceview renders rt traces for humans: an annotated timeline of the scheduler's decisions, per-goroutine stats, and a keep/drop diff showing exactly which decisions a minimized trace kept.
|
Package traceview renders rt traces for humans: an annotated timeline of the scheduler's decisions, per-goroutine stats, and a keep/drop diff showing exactly which decisions a minimized trace kept. |