Documentation
¶
Overview ¶
Package testengine provides a way to write deterministic, repeatable, serializable, and analyzable tests. Tests are deterministic because all time is fake, there is only ever a single go routine executing, and all randomness is derived from a seed. Tests are repeatable because given the same configuration and random seed, the test actions are deterministic. Tests are serializable because the actions performed are all represented as protobuf messages. And finally, tests are analyzable because the serialized representation of the test actions may be analyzed in tooling after the test has executed. TODO, the above is the plan, but, nothing is implemented at this point.
Index ¶
- type ClientConfig
- type ClientMatching
- type CrashAndRestartAfterMangler
- type DelayMangler
- type DropMangler
- type DuplicateMangler
- type Event
- type EventClientProposal
- type EventInitialize
- type EventMsgReceived
- type EventProcessActions
- type EventProcessEvents
- type EventQueue
- func (l *EventQueue) ConsumeEvent() *Event
- func (l *EventQueue) InsertClientProposal(target, clientID, reqNo uint64, data []byte, fromNow int64)
- func (l *EventQueue) InsertEvent(event *Event)
- func (l *EventQueue) InsertInitialize(target uint64, initParms *state.EventInitialParameters, fromNow int64)
- func (l *EventQueue) InsertMsgReceived(target, source uint64, msg *msgs.Msg, fromNow int64)
- func (l *EventQueue) InsertProcessAppActions(target uint64, actions *statemachine.ActionList, fromNow int64)
- func (l *EventQueue) InsertProcessClientActions(target uint64, actions *statemachine.ActionList, fromNow int64)
- func (l *EventQueue) InsertProcessHashActions(target uint64, actions *statemachine.ActionList, fromNow int64)
- func (l *EventQueue) InsertProcessNetActions(target uint64, actions *statemachine.ActionList, fromNow int64)
- func (l *EventQueue) InsertProcessReqStoreEvents(target uint64, events *statemachine.EventList, fromNow int64)
- func (l *EventQueue) InsertProcessResultEvents(target uint64, events *statemachine.EventList, fromNow int64)
- func (l *EventQueue) InsertProcessWALActions(target uint64, actions *statemachine.ActionList, fromNow int64)
- func (l *EventQueue) InsertTickEvent(target uint64, fromNow int64)
- func (l *EventQueue) Status() string
- type EventTick
- type InlineMangler
- type InlineMatcher
- type JitterMangler
- type Link
- type MangleMatcher
- type MangleResult
- type Mangler
- type Mangling
- func (m *Mangling) CrashAndRestartAfter(delay int64, initParms *state.EventInitialParameters) Mangler
- func (m *Mangling) Delay(delay int) Mangler
- func (m *Mangling) Do(mangler Mangler) Mangler
- func (m *Mangling) Drop() Mangler
- func (m *Mangling) Duplicate(maxDelay int) Mangler
- func (m *Mangling) Jitter(maxDelay int) Mangler
- type MsgMatching
- type MsgTypeMatching
- type NamedLogger
- type Node
- type NodeConfig
- type NodeState
- type ReconfigPoint
- type Recorder
- type RecorderClient
- type Recording
- type ReqStore
- func (rs *ReqStore) GetAllocation(clientID, reqNo uint64) ([]byte, error)
- func (rs *ReqStore) GetRequest(ack *msgs.RequestAck) ([]byte, error)
- func (rs *ReqStore) PutAllocation(clientID, reqNo uint64, digest []byte) error
- func (rs *ReqStore) PutRequest(ack *msgs.RequestAck, data []byte) error
- func (rs *ReqStore) Sync() error
- type RuntimeParameters
- type Spec
- type StartupMatching
- type WAL
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ClientConfig ¶
type ClientMatching ¶
type ClientMatching struct { ToNode func(nodeID uint64) *ClientMatching ToNodes func(nodeIDs ...uint64) *ClientMatching AtPercent func(percent int) *ClientMatching FromClient func(clientId uint64) *ClientMatching // contains filtered or unexported fields }
func MatchClientProposal ¶
func MatchClientProposal() *ClientMatching
type CrashAndRestartAfterMangler ¶
type CrashAndRestartAfterMangler struct { InitParms *state.EventInitialParameters Delay int64 }
func (CrashAndRestartAfterMangler) Mangle ¶
func (cm CrashAndRestartAfterMangler) Mangle(random int, event *Event) []MangleResult
type DelayMangler ¶
type DelayMangler struct {
Delay int
}
DelayMangler will delay events a specified amount of time
func (*DelayMangler) Mangle ¶
func (dm *DelayMangler) Mangle(random int, event *Event) []MangleResult
type DropMangler ¶
type DropMangler struct{}
func (DropMangler) Mangle ¶
func (DropMangler) Mangle(random int, event *Event) []MangleResult
type DuplicateMangler ¶
type DuplicateMangler struct {
MaxDelay int
}
func (*DuplicateMangler) Mangle ¶
func (dm *DuplicateMangler) Mangle(random int, event *Event) []MangleResult
type Event ¶
type Event struct { Target uint64 Time int64 Initialize *EventInitialize MsgReceived *EventMsgReceived ClientProposal *EventClientProposal ProcessWALActions *statemachine.ActionList ProcessNetActions *statemachine.ActionList ProcessHashActions *statemachine.ActionList ProcessClientActions *statemachine.ActionList ProcessAppActions *statemachine.ActionList ProcessReqStoreEvents *statemachine.EventList ProcessResultEvents *statemachine.EventList Tick *EventTick }
type EventClientProposal ¶
type EventInitialize ¶
type EventInitialize struct {
InitParms *state.EventInitialParameters
}
type EventMsgReceived ¶
type EventProcessActions ¶
type EventProcessActions statemachine.ActionList
type EventProcessEvents ¶
type EventProcessEvents statemachine.EventList
type EventQueue ¶
type EventQueue struct { // List is a list of *Event messages, in order of time. List *list.List // FakeTime is the current 'time' according to this log. FakeTime int64 // Rand is a source of randomness for the manglers Rand *rand.Rand // Mangler is invoked on each event when it is first inserted Mangler Mangler // Mangled tracks which events have already been mangled to prevent loops Mangled map[*Event]struct{} }
func (*EventQueue) ConsumeEvent ¶
func (l *EventQueue) ConsumeEvent() *Event
func (*EventQueue) InsertClientProposal ¶
func (l *EventQueue) InsertClientProposal(target, clientID, reqNo uint64, data []byte, fromNow int64)
func (*EventQueue) InsertEvent ¶
func (l *EventQueue) InsertEvent(event *Event)
func (*EventQueue) InsertInitialize ¶
func (l *EventQueue) InsertInitialize(target uint64, initParms *state.EventInitialParameters, fromNow int64)
func (*EventQueue) InsertMsgReceived ¶
func (l *EventQueue) InsertMsgReceived(target, source uint64, msg *msgs.Msg, fromNow int64)
func (*EventQueue) InsertProcessAppActions ¶
func (l *EventQueue) InsertProcessAppActions(target uint64, actions *statemachine.ActionList, fromNow int64)
func (*EventQueue) InsertProcessClientActions ¶
func (l *EventQueue) InsertProcessClientActions(target uint64, actions *statemachine.ActionList, fromNow int64)
func (*EventQueue) InsertProcessHashActions ¶
func (l *EventQueue) InsertProcessHashActions(target uint64, actions *statemachine.ActionList, fromNow int64)
func (*EventQueue) InsertProcessNetActions ¶
func (l *EventQueue) InsertProcessNetActions(target uint64, actions *statemachine.ActionList, fromNow int64)
func (*EventQueue) InsertProcessReqStoreEvents ¶
func (l *EventQueue) InsertProcessReqStoreEvents(target uint64, events *statemachine.EventList, fromNow int64)
func (*EventQueue) InsertProcessResultEvents ¶
func (l *EventQueue) InsertProcessResultEvents(target uint64, events *statemachine.EventList, fromNow int64)
func (*EventQueue) InsertProcessWALActions ¶
func (l *EventQueue) InsertProcessWALActions(target uint64, actions *statemachine.ActionList, fromNow int64)
func (*EventQueue) InsertTickEvent ¶
func (l *EventQueue) InsertTickEvent(target uint64, fromNow int64)
func (*EventQueue) Status ¶
func (l *EventQueue) Status() string
type InlineMangler ¶
type InlineMangler func(random int, event *Event) []MangleResult
func (InlineMangler) Mangle ¶
func (im InlineMangler) Mangle(random int, event *Event) []MangleResult
type InlineMatcher ¶
type JitterMangler ¶
type JitterMangler struct {
MaxDelay int
}
JitterMangler will delay events a random amount of time, up to MaxDelay
func (*JitterMangler) Mangle ¶
func (jm *JitterMangler) Mangle(random int, event *Event) []MangleResult
type Link ¶
type Link struct { Source uint64 EventQueue *EventQueue Delay int64 }
type MangleMatcher ¶
type MangleResult ¶
type Mangler ¶
type Mangler interface {
Mangle(random int, event *Event) []MangleResult
}
type Mangling ¶
type Mangling struct {
Filter MangleMatcher
}
Mangling is usually constructed via For/After/Until and is used to conditionally apply a Mangler.
func After ¶
func After(matcher MangleMatcher) *Mangling
After is useful to begin a mangling after some action occurs. This is useful especially for allowing the network to get into a desired state before injecting a fault.
func For ¶
func For(matcher MangleMatcher) *Mangling
For is a simple way to apply a mangler whenever a condition is satisfied.
func Until ¶
func Until(matcher MangleMatcher) *Mangling
Until is useful to perform a mangling until some condition is complete. This is useful especially for delaying an event until after a condition occurs, or for fixing a fault after some period of time.
func (*Mangling) CrashAndRestartAfter ¶
func (m *Mangling) CrashAndRestartAfter(delay int64, initParms *state.EventInitialParameters) Mangler
type MsgMatching ¶
type MsgMatching struct { FromSelf func() *MsgMatching FromNode func(nodeID uint64) *MsgMatching FromNodes func(nodeIDs ...uint64) *MsgMatching ToNode func(nodeID uint64) *MsgMatching ToNodes func(nodeIDs ...uint64) *MsgMatching AtPercent func(percent int) *MsgMatching WithSequence func(seqNo uint64) *MsgMatching OfTypePreprepare func() *MsgTypeMatching OfTypePrepare func() *MsgTypeMatching OfTypeCommit func() *MsgTypeMatching OfTypeCheckpoint func() *MsgTypeMatching OfTypeSuspect func() *MsgTypeMatching OfTypeEpochChange func() *MsgTypeMatching OfTypeEpochChangeAck func() *MsgTypeMatching OfTypeNewEpoch func() *MsgTypeMatching OfTypeNewEpochEcho func() *MsgTypeMatching OfTypeNewEpochReady func() *MsgTypeMatching OfTypeFetchBatch func() *MsgTypeMatching OfTypeForwardBatch func() *MsgTypeMatching OfTypeRequestAck func() *MsgTypeMatching // contains filtered or unexported fields }
func MatchMsgs ¶
func MatchMsgs() *MsgMatching
type MsgTypeMatching ¶
type MsgTypeMatching struct { FromSelf func() *MsgTypeMatching FromNode func(nodeID uint64) *MsgTypeMatching FromNodes func(nodeIDs ...uint64) *MsgTypeMatching ToNode func(nodeID uint64) *MsgTypeMatching ToNodes func(nodeIDs ...uint64) *MsgTypeMatching AtPercent func(percent int) *MsgTypeMatching WithSequence func(seqNo uint64) *MsgTypeMatching WithEpoch func(epochNo uint64) *MsgTypeMatching // contains filtered or unexported fields }
type NamedLogger ¶
type NamedLogger struct { Level statemachine.LogLevel Name string Output io.Writer }
func (NamedLogger) Log ¶
func (nl NamedLogger) Log(level statemachine.LogLevel, msg string, args ...interface{})
type Node ¶
type Node struct { ID uint64 Config *NodeConfig WAL *WAL Link *Link Hasher processor.Hasher Interceptor processor.EventInterceptor ReqStore *ReqStore WorkItems *processor.WorkItems Clients *processor.Clients State *NodeState ProcessResultEventsPending bool ProcessReqStoreEventsPending bool ProcessWALActionsPending bool ProcessNetActionsPending bool ProcessHashActionsPending bool ProcessAppActionsPending bool ProcessClientActionsPending bool StateMachine *statemachine.StateMachine }
func (*Node) Initialize ¶
func (n *Node) Initialize(initParms *state.EventInitialParameters, logger statemachine.Logger) error
type NodeConfig ¶
type NodeConfig struct { InitParms *state.EventInitialParameters RuntimeParms *RuntimeParameters }
type NodeState ¶
type NodeState struct { Hasher processor.Hasher ActiveHash hash.Hash LastSeqNo uint64 ReconfigPoints []*ReconfigPoint PendingReconfigurations []*msgs.Reconfiguration ReqStore *ReqStore CheckpointSeqNo uint64 CheckpointHash []byte CheckpointState *msgs.NetworkState // The below vars are used for assertions on results, // but are not used directly in execution. StateTransfers []uint64 }
func (*NodeState) Snap ¶
func (ns *NodeState) Snap(networkConfig *msgs.NetworkState_Config, clientsState []*msgs.NetworkState_Client) ([]byte, []*msgs.Reconfiguration, error)
func (*NodeState) TransferTo ¶
type ReconfigPoint ¶
type ReconfigPoint struct { ClientID uint64 ReqNo uint64 Reconfiguration *msgs.Reconfiguration }
type Recorder ¶
type Recorder struct { NetworkState *msgs.NetworkState NodeConfigs []*NodeConfig ClientConfigs []*ClientConfig ReconfigPoints []*ReconfigPoint Mangler Mangler LogOutput io.Writer Hasher processor.Hasher RandomSeed int64 }
type RecorderClient ¶
type RecorderClient struct { Config *ClientConfig Hasher processor.Hasher }
func (*RecorderClient) RequestByReqNo ¶
func (rc *RecorderClient) RequestByReqNo(reqNo uint64) []byte
type Recording ¶
type Recording struct { Hasher processor.Hasher EventQueue *EventQueue Nodes []*Node Clients []*RecorderClient LogOutput io.Writer EventQueueOutput *gzip.Writer }
func (*Recording) DrainClients ¶
DrainClients will execute the recording until all client requests have committed. It will return with an error if the number of accumulated log entries exceeds timeout. If any step returns an error, this function returns that error.
type ReqStore ¶
type ReqStore struct {
// contains filtered or unexported fields
}
func NewReqStore ¶
func NewReqStore() *ReqStore
func (*ReqStore) GetAllocation ¶
func (*ReqStore) GetRequest ¶
func (rs *ReqStore) GetRequest(ack *msgs.RequestAck) ([]byte, error)
func (*ReqStore) PutAllocation ¶
func (*ReqStore) PutRequest ¶
func (rs *ReqStore) PutRequest(ack *msgs.RequestAck, data []byte) error
type RuntimeParameters ¶
type Spec ¶
type StartupMatching ¶
type StartupMatching struct { ForNode func(nodeID uint64) *StartupMatching ForNodes func(nodeIDs ...uint64) *StartupMatching // contains filtered or unexported fields }
func MatchNodeStartup ¶
func MatchNodeStartup() *StartupMatching