testengine

package
v0.0.0-...-f247ec5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 15, 2021 License: Apache-2.0 Imports: 20 Imported by: 0

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

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClientConfig

type ClientConfig struct {
	ID          uint64
	MaxInFlight int
	Total       uint64

	// IgnoreNodes may be set to cause the client not to send requests
	// to a particular set of nodes.  This is useful for testing request
	// forwarding behavior.
	IgnoreNodes []uint64
}

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

func (ClientMatching) Matches

func (m ClientMatching) Matches(random int, event *Event) bool

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 EventClientProposal struct {
	ClientID uint64
	ReqNo    uint64
	Data     []byte
}

type EventInitialize

type EventInitialize struct {
	InitParms *state.EventInitialParameters
}

type EventMsgReceived

type EventMsgReceived struct {
	Source uint64
	Msg    *msgs.Msg
}

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 EventTick

type EventTick struct{}

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 InlineMatcher func(random int, event *Event) bool

func (InlineMatcher) Matches

func (im InlineMatcher) Matches(random int, event *Event) bool

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 struct {
	Source     uint64
	EventQueue *EventQueue
	Delay      int64
}

func (*Link) Send

func (l *Link) Send(dest uint64, msg *msgs.Msg)

type MangleMatcher

type MangleMatcher interface {
	Matches(random int, event *Event) bool
}

type MangleResult

type MangleResult struct {
	Event    *Event
	Remangle bool
}

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

func (*Mangling) Delay

func (m *Mangling) Delay(delay int) Mangler

func (*Mangling) Do

func (m *Mangling) Do(mangler Mangler) Mangler

func (*Mangling) Drop

func (m *Mangling) Drop() Mangler

func (*Mangling) Duplicate

func (m *Mangling) Duplicate(maxDelay int) Mangler

func (*Mangling) Jitter

func (m *Mangling) Jitter(maxDelay int) 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

func (MsgMatching) Matches

func (m MsgMatching) Matches(random int, event *Event) bool

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
}

func (MsgTypeMatching) Matches

func (m MsgTypeMatching) Matches(random int, event *Event) bool

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) Apply

func (ns *NodeState) Apply(batch *msgs.QEntry) error

func (*NodeState) Snap

func (ns *NodeState) Snap(networkConfig *msgs.NetworkState_Config, clientsState []*msgs.NetworkState_Client) ([]byte, []*msgs.Reconfiguration, error)

func (*NodeState) TransferTo

func (ns *NodeState) TransferTo(seqNo uint64, snap []byte) (*msgs.NetworkState, error)

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
}

func (*Recorder) Recording

func (r *Recorder) Recording(output *gzip.Writer) (*Recording, error)

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

func (r *Recording) DrainClients(timeout int) (count int, err error)

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.

func (*Recording) Step

func (r *Recording) Step() error

type ReqStore

type ReqStore struct {
	// contains filtered or unexported fields
}

func NewReqStore

func NewReqStore() *ReqStore

func (*ReqStore) GetAllocation

func (rs *ReqStore) GetAllocation(clientID, reqNo uint64) ([]byte, error)

func (*ReqStore) GetRequest

func (rs *ReqStore) GetRequest(ack *msgs.RequestAck) ([]byte, error)

func (*ReqStore) PutAllocation

func (rs *ReqStore) PutAllocation(clientID, reqNo uint64, digest []byte) error

func (*ReqStore) PutRequest

func (rs *ReqStore) PutRequest(ack *msgs.RequestAck, data []byte) error

func (*ReqStore) Sync

func (rs *ReqStore) Sync() error

type RuntimeParameters

type RuntimeParameters struct {
	TickInterval int
	LinkLatency  int

	ProcessWALLatency      int
	ProcessNetLatency      int
	ProcessHashLatency     int
	ProcessClientLatency   int
	ProcessAppLatency      int
	ProcessReqStoreLatency int
	ProcessEventsLatency   int
}

type Spec

type Spec struct {
	NodeCount     int
	ClientCount   int
	ReqsPerClient uint64
	BatchSize     uint32
	ClientsIgnore []uint64
	TweakRecorder func(r *Recorder)
}

func (*Spec) Recorder

func (s *Spec) Recorder() *Recorder

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

func (StartupMatching) Matches

func (m StartupMatching) Matches(random int, event *Event) bool

type WAL

type WAL struct {
	LowIndex uint64
	List     *list.List
}

func NewWAL

func NewWAL(initialState *msgs.NetworkState, initialCP []byte) *WAL

func (*WAL) LoadAll

func (wal *WAL) LoadAll(iter func(index uint64, p *msgs.Persistent)) error

TODO, deal with this in the processor

func (*WAL) Sync

func (wal *WAL) Sync() error

func (*WAL) Truncate

func (wal *WAL) Truncate(index uint64) error

func (*WAL) Write

func (wal *WAL) Write(index uint64, p *msgs.Persistent) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL