Documentation
¶
Index ¶
- Constants
- Variables
- func NewReportStore() *reportStore
- type Action
- type Condition
- func IsEventOf(replica types.ReplicaID) Condition
- func IsEventOfF(replicaFunc func(*types.Event, *Context) (types.ReplicaID, bool)) Condition
- func IsEventType(t string) Condition
- func IsMessageFrom(from types.ReplicaID) Condition
- func IsMessageFromF(replicaF func(*types.Event, *Context) (types.ReplicaID, bool)) Condition
- func IsMessageFromPart(partLabel string) Condition
- func IsMessageReceive() Condition
- func IsMessageSend() Condition
- func IsMessageTo(to types.ReplicaID) Condition
- func IsMessageToF(replicaF func(*types.Event, *Context) (types.ReplicaID, bool)) Condition
- func IsMessageType(t string) Condition
- func OnceCondition(c Condition) Condition
- type Context
- func (c *Context) Abort()
- func (c *Context) CreatePartition(sizes []int, labels []string)
- func (c *Context) EndTestCase()
- func (c *Context) GetMessage(e *types.Event) (*types.Message, bool)
- func (c *Context) Log(keyvals map[string]string)
- func (c *Context) Logger() *log.Logger
- func (c *Context) NewMessage(cur *types.Message, data []byte) *types.Message
- type CountWrapper
- func (c *CountWrapper) Eq(val int) Condition
- func (c *CountWrapper) EqF(val func(*types.Event, *Context) (int, bool)) Condition
- func (c *CountWrapper) Geq(val int) Condition
- func (c *CountWrapper) GeqF(val func(*types.Event, *Context) (int, bool)) Condition
- func (c *CountWrapper) Gt(val int) Condition
- func (c *CountWrapper) GtF(val func(*types.Event, *Context) (int, bool)) Condition
- func (c *CountWrapper) Incr() Action
- func (c *CountWrapper) Leq(val int) Condition
- func (c *CountWrapper) LeqF(val func(*types.Event, *Context) (int, bool)) Condition
- func (c *CountWrapper) Lt(val int) Condition
- func (c *CountWrapper) LtF(valF func(*types.Event, *Context) (int, bool)) Condition
- type Counter
- type FilterFunc
- type FilterSet
- type FilterSetOption
- type IfThenHandler
- type ReplicaPartition
- type SetWrapper
- type State
- type StateMachine
- type StateMachineBuilder
- type TestCase
- type TestCaseDriver
- type TestingServer
- type TimeoutDriver
- type VarSet
- func (v *VarSet) Exists(label string) bool
- func (v *VarSet) Get(label string) (interface{}, bool)
- func (v *VarSet) GetBool(label string) (bool, bool)
- func (v *VarSet) GetCounter(label string) (*Counter, bool)
- func (v *VarSet) GetInt(label string) (int, bool)
- func (v *VarSet) GetMessageSet(label string) (*types.MessageStore, bool)
- func (v *VarSet) GetString(label string) (string, bool)
- func (v *VarSet) NewMessageSet(label string)
- func (v *VarSet) Set(label string, value interface{})
- func (v *VarSet) SetCounter(label string)
Constants ¶
const ( // StartStateLabel is the start state label of a state machine StartStateLabel = "startState" // FailStateLabel is the failure state label FailStateLabel = "failState" // SuccessStateLabel is the state label of the success state SuccessStateLabel = "successState" )
Variables ¶
var ( ErrNotEnoughReplicas = errors.New("not enough replicas") ErrSizeLabelsMismatch = errors.New("sizes and labels are not of the same length") )
Functions ¶
func NewReportStore ¶
func NewReportStore() *reportStore
Types ¶
type Action ¶
Action is used to specify the consequence in the `If().Then()` handler
func DeliverMessage ¶
func DeliverMessage() Action
DeliverMessage returns the message if the event is a message send event
func OnceAction ¶ added in v0.1.1
func RecordMessageAs ¶
RecordMessageAs returns an action. If the event is a message send or receive, the message is recorded in context with the label as reference
type Condition ¶
Condition type to define predicates over the current event or the history of events
func IsEventOfF ¶ added in v0.1.1
func IsEventType ¶
IsEventType condition returns true if the event is GenericEventType with T == t
func IsMessageFrom ¶
IsMessageFrom condition returns true if the event is a message send or receive with message.From == from
func IsMessageFromF ¶
IsMessageFromF works the same as IsMessageFrom but the replica is fetched from the event and context
func IsMessageFromPart ¶ added in v0.1.1
func IsMessageReceive ¶
func IsMessageReceive() Condition
IsMessageReceive condition returns true if the event is a message receive event
func IsMessageSend ¶
func IsMessageSend() Condition
IsMessageSend condition returns true if the event is a message send event
func IsMessageTo ¶
IsMessageTo condition returns true if the event is a message send or receive with message.To == to
func IsMessageToF ¶
IsMessageToF works the same as IsMessageTo but the replica is fetched from the event and context
func IsMessageType ¶
IsMessageType condition returns true if the event is a message send or receive and the type of message is `t`
func OnceCondition ¶ added in v0.1.1
Once is a meta condition that allows the inner condition to be true only once
type Context ¶
type Context struct {
// MessagePool reference to an instance of the MessageStore
MessagePool *types.MessageStore
// Replicas reference to the replica store
Replicas *types.ReplicaStore
// EventDAG is the directed acyclic graph all prior events
EventDAG *types.EventDAG
// Vars is a generic key value store to facilate maintaining auxilliary information
// during the execution of a testcase
Vars *VarSet
// contains filtered or unexported fields
}
Context struct is passed to the calls of StateAction and Condition encapsulates all information needed by the StateAction and Condition to function
func (*Context) CreatePartition ¶ added in v0.1.1
func (*Context) EndTestCase ¶
func (c *Context) EndTestCase()
Ends the testcase without failing. The assertion will determine the success of the testcase
func (*Context) GetMessage ¶
GetMessage returns the `Message` struct from the Message pool if the event provided is a message send ot receive event
type CountWrapper ¶
CountWrapper encapsulates the function to fetch counter (CounterFunc) from state dynamically. CountWrapper is used to define actions and condition based on the counter.
func Count ¶
func Count(label string) *CountWrapper
Count returns a CountWrapper where the CounterFunc fetches the counter based on the label
func CountF ¶
CountF returns a CountWrapper where the label is also fetched based on the event and context
func CountTo ¶
func CountTo(label string) *CountWrapper
CountTo returns a CountWrapper where the counter label is `label` appended with message.To, if the event is a message send or receive
func (*CountWrapper) Eq ¶
func (c *CountWrapper) Eq(val int) Condition
Eq condition that returns true if the counter value is equal to the specified value.
func (*CountWrapper) EqF ¶
EqF condition that returns true if the counter value is equal to the specified value. The input is a function that obtains the value dynamically based on the event and context.
func (*CountWrapper) Geq ¶
func (c *CountWrapper) Geq(val int) Condition
Geq condition that returns true if the counter value is greater than or equal to the specified value.
func (*CountWrapper) GeqF ¶
GeqF condition that returns true if the counter value is greather than or equal to the specified value. The input is a function that obtains the value dynamically based on the event and context.
func (*CountWrapper) Gt ¶
func (c *CountWrapper) Gt(val int) Condition
Gt condition that returns true if the counter value is greater than the specified value.
func (*CountWrapper) GtF ¶
GtF condition that returns true if the counter value is greater than the specified value. The input is a function that obtains the value dynamically based on the event and context.
func (*CountWrapper) Incr ¶
func (c *CountWrapper) Incr() Action
Incr returns an action which increments the counter value
func (*CountWrapper) Leq ¶
func (c *CountWrapper) Leq(val int) Condition
Leq condition that returns true if the counter value is less than or equal to the specified value.
func (*CountWrapper) LeqF ¶
LeqF condition that returns true if the counter value is less than or equal to the specified value. The input is a function that obtains the value dynamically based on the event and context.
func (*CountWrapper) Lt ¶
func (c *CountWrapper) Lt(val int) Condition
Lt condition that returns true if the counter value is less than the specified value.
type Counter ¶
type Counter struct {
// contains filtered or unexported fields
}
Counter threadsafe counter
type FilterFunc ¶
FilterFunc type to define a conditional handler returns false in the second return value if the handler is not concerned about the event
func NewStateMachineHandler ¶
func NewStateMachineHandler(stateMachine *StateMachine) FilterFunc
NewStateMachineHandler returns a HandlerFunc that encodes the execution logic of the StateMachine For every invocation of the handler, internall a state machine step is executed which may or may not transition. If the StateMachine transitions to FailureState, the handler aborts the testcase
type FilterSet ¶
type FilterSet struct {
Filters []FilterFunc
DefaultFilter FilterFunc
}
FilterSet implements Handler Executes handlers in the specified order until the event is handled If no handler handles the event then the default handler is called
func NewFilterSet ¶
func NewFilterSet(opts ...FilterSetOption) *FilterSet
NewFilterSet creates a new cascade handler with the specified state machine and options
func (*FilterSet) AddFilter ¶
func (c *FilterSet) AddFilter(h FilterFunc)
AddFilter adds a handler to the cascade
type FilterSetOption ¶
type FilterSetOption func(*FilterSet)
FilterSetOption changes the parameters of the HandlerCascade
func WithDefault ¶
func WithDefault(d FilterFunc) FilterSetOption
WithDefault changes the HandlerCascade default handler
type IfThenHandler ¶
type IfThenHandler struct {
// contains filtered or unexported fields
}
IfThenHandler struct is used to wrap the attributes of the `If().Then()` handler
func If ¶
func If(cond Condition) *IfThenHandler
If creates a IfThenHandler with the specified condition
func (*IfThenHandler) Then ¶
func (i *IfThenHandler) Then(action Action, rest ...Action) FilterFunc
Then returns a HandlerFunc which encodes the `If().Then()` semantics. Accepts actions as arguments
type ReplicaPartition ¶ added in v0.1.1
type ReplicaPartition struct {
// contains filtered or unexported fields
}
func NewPartition ¶ added in v0.1.1
func NewPartition(replicas *types.ReplicaStore, sizes []int, labels []string) (*ReplicaPartition, error)
type SetWrapper ¶
SetWrapper encapsulates the mechanism to fetch a message set from the state. SetFunc should return a message set given the current event and context.
func Set ¶
func Set(label string) *SetWrapper
Set returns a SetWrapper where the set is fetched based on the label
func SetF ¶
SetF returns a SetWrapper where the label is determined dynamically by the event and context
func (*SetWrapper) Contains ¶
func (s *SetWrapper) Contains() Condition
Contains condition returns true if the event is a message send or receive and the message is apart of the message set.
func (*SetWrapper) Count ¶
func (s *SetWrapper) Count() *CountWrapper
Count returns a counter where the value is size of the message set
func (*SetWrapper) DeliverAll ¶
func (s *SetWrapper) DeliverAll() Action
DeliverAll returns an action which inturn returns all the messages in the message set and removes the messages from the set.
func (*SetWrapper) Store ¶
func (s *SetWrapper) Store() Action
Store returns an action. If the event is a message send or receive, the action adds the message to the message set
type State ¶
type State struct {
Label string `json:"label"`
Transitions map[string]Condition `json:"-"`
Success bool `json:"success"`
// contains filtered or unexported fields
}
State of the testcase state machine
func (*State) MarshalJSON ¶
type StateMachine ¶
type StateMachine struct {
// contains filtered or unexported fields
}
StateMachine is a deterministic transition system where the transitions are labelled by conditions
func NewStateMachine ¶
func NewStateMachine() *StateMachine
NewStateMachine instantiate a StateMachine
func (*StateMachine) Builder ¶
func (s *StateMachine) Builder() StateMachineBuilder
Builder retruns a StateMachineBuilder instance which provides a builder patter to construct the state machine
func (*StateMachine) CurState ¶
func (s *StateMachine) CurState() *State
CurState return the State that the StateMachine is currently in
func (*StateMachine) InState ¶
func (s *StateMachine) InState(state string) Condition
InState returns a condition which is true if the StateMachine is in a specific state. This can be used to define handler that access the state
func (*StateMachine) InSuccessState ¶
func (s *StateMachine) InSuccessState() bool
InSuccessState returns true if the current state of the state machine is a success state
func (*StateMachine) Transition ¶
func (s *StateMachine) Transition(to string)
Transition moves the current stat eof the StateMachine to the specified state
type StateMachineBuilder ¶
type StateMachineBuilder struct {
// contains filtered or unexported fields
}
StateMachineBuilder struct defines a builder pattern to create a state machine
func (StateMachineBuilder) MarkSuccess ¶
func (s StateMachineBuilder) MarkSuccess() StateMachineBuilder
MarkSuccess marks the current state of the builder as a success state
func (StateMachineBuilder) On ¶
func (s StateMachineBuilder) On(cond Condition, stateLabel string) StateMachineBuilder
On can be used to create a transition relation between states based on the specified condition
type TestCase ¶
type TestCase struct {
// Name name of the testcase
Name string
// Timeout maximum duration of the testcase execution
Timeout time.Duration
// Cascade instance of *HandlerCascade
Cascade *FilterSet
// StateMachine instance of *StateMachine to assert a property
StateMachine *StateMachine
// Logger to log information
Logger *log.Logger
// contains filtered or unexported fields
}
TestCase represents a unit test case
func NewTestCase ¶
func NewTestCase(name string, timeout time.Duration, sm *StateMachine, cascade *FilterSet) *TestCase
NewTestCase instantiates a TestCase based on the parameters specified The new testcase has three states by default. - Start state where the execution starts from - Fail state that can be used to fail the testcase - Success state that can be used to indicate a success of the testcase
type TestCaseDriver ¶ added in v0.1.1
type TestCaseDriver struct {
TestCase *TestCase
// contains filtered or unexported fields
}
func NewTestDriver ¶ added in v0.1.1
func NewTestDriver(ctx *context.RootContext, testcase *TestCase) *TestCaseDriver
type TestingServer ¶
type TestingServer struct {
*types.BaseService
// contains filtered or unexported fields
}
TestingServer is used to run the scheduler tool for unit testing
func NewTestingServer ¶
func NewTestingServer(config *config.Config, messageParser types.MessageParser, testcases []*TestCase) (*TestingServer, error)
NewTestingServer instantiates TestingServer testcases are passed as arguments
func (*TestingServer) Done ¶
func (srv *TestingServer) Done() chan string
Done returns the channel which will be closed once all testcases are run
func (*TestingServer) Name ¶
func (srv *TestingServer) Name() string
Name implements DashboardRouter
func (*TestingServer) SetupRouter ¶
func (srv *TestingServer) SetupRouter(router *gin.RouterGroup)
SetupRouter for setting up the dashboard routes implements DashboardRouter
func (*TestingServer) Start ¶
func (srv *TestingServer) Start()
Start starts the TestingServer and implements Service
func (*TestingServer) Stop ¶
func (srv *TestingServer) Stop()
Stop stops the TestingServer and implements Service
type TimeoutDriver ¶
type TimeoutDriver struct {
// contains filtered or unexported fields
}
Flow of execution
- Update the timeout context with the current event that is observed a. Keep track of pending timeouts b. Keep track of messages that have been delivered but not acknowledged
- Check delivery of messages that are currently intended to be delivered a. Easy to modify graph (mark nodes as clean and dirty) b. Check spuriousness (this can be configured explicitly) c. Easy algorithm to check spuriousness d. algorithm to order the timeouts that need to be fired.
- Update with additional timers that need to be fired a. Parameterized strategy to pick timeouts b. Ability for filters to mark certain timeouts to be fired earlier
func NewTimeoutDriver ¶
func NewTimeoutDriver(store *types.TimeoutStore) *TimeoutDriver
func (*TimeoutDriver) NewEvent ¶
func (t *TimeoutDriver) NewEvent(e *types.Event)
func (*TimeoutDriver) ToDispatch ¶
func (t *TimeoutDriver) ToDispatch() []*types.ReplicaTimeout
type VarSet ¶
type VarSet struct {
// contains filtered or unexported fields
}
VarSet is a dictionary for storing auxilliary state during the execution of the testcase VarSet is stored in the context passed to actions and conditions
func (*VarSet) Get ¶
Get returns the value stored of the specified label the second return argument is false if the label does not exist
func (*VarSet) GetBool ¶
GetBool casts the value at label (if it exists) into boolean and returns it
func (*VarSet) GetCounter ¶
GetCounter returns the counter at the label if it exists (nil, false) otherwise
func (*VarSet) GetMessageSet ¶
func (v *VarSet) GetMessageSet(label string) (*types.MessageStore, bool)
GetMessageSet returns the message set at label if one exists (nil, false) otherwise
func (*VarSet) GetString ¶
GetString casts the value at label (if it exists) into string and returns it
func (*VarSet) NewMessageSet ¶
NewMessageSet creates a message set at the specified label
func (*VarSet) SetCounter ¶
SetCounter sets a counter instance at the specified label with initial value 1