Commit 0546b65f authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 886fdce3
......@@ -493,10 +493,11 @@ type _testing_TB = testing.TB
type T struct {
_testing_TB
mu sync.Mutex
streamTab map[/*stream*/string]Chan // set to nil on test shutdown
routeEvent func(event interface{}) (stream string)
tracev []eventTrace // record of events as they happen
mu sync.Mutex
streamTab map[/*stream*/string]Chan // set to nil on test shutdown
routeEvent func(event interface{}) (stream string)
tracev []eventTrace // record of events as they happen
delayInjectTab map[/*stream*/string]*delayInjectState
nakq []nak // naks queued to be sent after Fatal
}
......@@ -508,6 +509,14 @@ type eventTrace struct {
event interface{}
}
// delayInjectState is used by delay-injector to find out for which event on a
// stream a delay should be injected.
type delayInjectState struct {
seqno int // current sequence number of event on this stream.
delayAt int // event with `seqno == delayAt` will be delayed
delayT time.Duration // by delayT time.
}
type nak struct {
msg *Msg
why string
......@@ -786,11 +795,15 @@ func (t *T) closeStreamTab() (nnak int) {
// Verify verifies a test system.
// XXX
func Verify(t testing.TB, f func(t *T)) {
tT := &T{_testing_TB: t, streamTab: make(map[string]Chan)}
// XXX
// XXX try back -> testing.TB? (but TB does not have .Run)
func Verify(t *testing.T, f func(t *T)) {
testf := func(t testing.TB, delayInjectTab map[string]*delayInjectState) *T {
tT := &T{
_testing_TB: t,
streamTab: make(map[string]Chan),
delayInjectTab: delayInjectTab,
}
func() {
// verify in the end that no events are left unchecked / unconsumed,
// e.g. sent to RxEvent, but not received. Nak them if they are and fail.
//
......@@ -804,14 +817,22 @@ func Verify(t testing.TB, f func(t *T)) {
}()
f(tT)
}()
return tT
}
tT0 := testf(t, nil)
// now, if f succeeds, verify f with injected delays.
if tT.Failed() {
// XXX explain with more text
if tT0.Failed() {
return
}
trace0 := tT0.tracev
if len(trace0) < 2 {
return
}
trace0 := tT.tracev
// sort trace0 by time just in case - events migth come from multiple
// CPUs simultaneously, and so for close events they might be added to
// tracev not in time order.
......@@ -819,8 +840,39 @@ func Verify(t testing.TB, f func(t *T)) {
return trace0[i].t.Before(trace0[j].t)
})
// find out max(δt) in between events
var δtMax time.Duration
for i := 1; i < len(trace0); i++ {
δt := trace0[i].t.Sub(trace0[i-1].t)
if δt > δtMax {
δtMax = δt
}
}
// retest f with 10·δtMax injected at i'th event
for i := 0; i < len(trace0); i++ {
// stream and on-stream sequence number for i'th global event
stream := trace0[i].stream
istream := -1
for j := 0; j <= i; j++ {
if trace0[j].stream == stream {
istream++
}
}
t.Run(fmt.Sprintf("delay@%d(=%s:%d)", i, stream, istream), func(t *testing.T) {
tT := testf(t, map[string]*delayInjectState{
stream: &delayInjectState{
delayAt: istream,
delayT: 10*δtMax, // XXX make sure it < deadTime
},
})
// XXX in the end: verify that streams are the same from run to run (if completed successfully).
// XXX in the end: verify that streams are the same from run to run (if completed successfully).
_ = tT
})
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment