Commit 99977ccd authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent decaff6f
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
// See COPYING file for full licensing terms. // See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options. // See https://www.nexedi.com/licensing for rationale and options.
// XXX explain // Package tracetest_test demonstrates how to use package tracetest.
package tracetest_test package tracetest_test
//go:generate gotrace gen . //go:generate gotrace gen .
...@@ -49,72 +49,70 @@ func hello(who string) { ...@@ -49,72 +49,70 @@ func hello(who string) {
// TestTracetestExample demonstrates how to use tracetest to verify concurrent system with 2 threads. // TestTracetestExample demonstrates how to use tracetest to verify concurrent system with 2 threads.
func TestTracetestExample(t *testing.T) { func TestTracetestExample(t *testing.T) {
tracetest.Verify(t, testTracetestExample)
}
func testTracetestExample(t *tracetest.T) {
type eventHi string type eventHi string
type eventHello string type eventHello string
testf := func(t *tracetest.T) { // setup tracing to deliver trace events to t.
// setup tracing to deliver trace events to t XXX not to t, but to something dedicated? pg := &tracing.ProbeGroup{}
pg := &tracing.ProbeGroup{} tracing.Lock()
tracing.Lock() traceHi_Attach(pg, func(who string) {
traceHi_Attach(pg, func(who string) { t.RxEvent(eventHi(who))
// XXX NewEvent? IncomingEvent? })
t.RxEvent(eventHi(who)) // XXX -> t.OnEvent? not via t? traceHello_Attach(pg, func(who string) {
}) t.RxEvent(eventHello(who))
traceHello_Attach(pg, func(who string) { })
t.RxEvent(eventHello(who)) tracing.Unlock()
}) defer pg.Done()
tracing.Unlock()
defer pg.Done() // tell tracetest to which stream an event should go.
t.SetEventRouter(func(event interface{}) (stream string) {
// tell tracetest to which stream an event should go. // it can be only eventHi and eventHello.
t.SetEventRouter(func(event interface{}) (stream string) { // in this test the convention is that who comes as <threadID>·...
// it can be only eventHi and eventHello. // we used threadID as stream.
// in this test the convention is that who comes as <threadID>·... who := ""
// we used threadID as stream. switch ev := event.(type) {
who := "" default:
switch ev := event.(type) { panic(fmt.Sprintf("unexpected event type %T", event))
default: case eventHi:
panic(fmt.Sprintf("unexpected event type %T", event)) who = string(ev)
case eventHi: case eventHello:
who = string(ev) who = string(ev)
case eventHello: }
who = string(ev)
} i := strings.Index(who, "·")
if i == -1 {
i := strings.Index(who, "·") panic(fmt.Sprintf("who does not have threadID: %q", who))
if i == -1 { }
panic(fmt.Sprintf("who does not have threadID: %q", who))
} return strings.ToLower(who[:i])
})
return strings.ToLower(who[:i])
}) // run the workload
var wg sync.WaitGroup
// run the workload defer wg.Wait()
var wg sync.WaitGroup wg.Add(2)
defer wg.Wait()
wg.Add(2) go func() { // thread1
defer wg.Done()
go func() { // thread1 hi("T1·A")
defer wg.Done() hello("T1·B")
hi("T1·A") }()
hello("T1·B")
}() go func() { // thread2
defer wg.Done()
go func() { // thread2 hi("T2·C")
defer wg.Done() }()
hi("T2·C")
}() // assert that events come as expected
t.Expect("t2", eventHi("T2·C"))
// assert that events come as expected t.Expect("t1", eventHi("T1·A"))
t.Expect("t2", eventHi("T2·C")) t.Expect("t1", eventHello("T1·B"))
t.Expect("t1", eventHi("T1·A"))
t.Expect("t1", eventHello("T1·B")) // XXX also t.Recv, t.ExpectNoAck ?
// XXX also t.Recv, t.ExpectNoAck ? //t1 := t.OnStream("t1")
//t1.Expect(eventHi("X·A"))
//t1 := t.OnStream("t1")
//t1.Expect(eventHi("X·A"))
}
tracetest.Verify(t, testf)
} }
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
// causality (i.e. there is some happens-before relation for them) the // causality (i.e. there is some happens-before relation for them) the
// sequence of checking should represent that ordering relation. // sequence of checking should represent that ordering relation.
// //
// The package should be used as follows: // The package should be used as follows: XXX rework
// //
// XXX tracer -> trace collector? // XXX tracer -> trace collector?
// - implement tracer that will be synchronously collecting events from // - implement tracer that will be synchronously collecting events from
...@@ -528,6 +528,8 @@ func (t *T) SetEventRouter(routeEvent func(event interface{}) (stream string)) { ...@@ -528,6 +528,8 @@ func (t *T) SetEventRouter(routeEvent func(event interface{}) (stream string)) {
} }
// XXX doc; naming // XXX doc; naming
// XXX NewEvent? IncomingEvent? OnEvent?
// XXX pass events in not via t (via something dedicated)?
func (t *T) RxEvent(event interface{}) { func (t *T) RxEvent(event interface{}) {
t0 := time.Now() t0 := time.Now()
stream := "default" stream := "default"
...@@ -603,6 +605,7 @@ func (t *T) Expect(stream string, eventOK interface{}) { ...@@ -603,6 +605,7 @@ func (t *T) Expect(stream string, eventOK interface{}) {
// XXX ExpectNoACK // XXX ExpectNoACK
// XXX Recv // XXX Recv
// XXX Select? (e.g. Select("a", "b") to fetch from either "a" or "b")
// expect1 receives next event on stream and verifies it to be equal to eventOK (both type and value). // expect1 receives next event on stream and verifies it to be equal to eventOK (both type and value).
// //
...@@ -798,6 +801,17 @@ func Verify(t testing.TB, f func(t *T)) { ...@@ -798,6 +801,17 @@ func Verify(t testing.TB, f func(t *T)) {
f(tT) f(tT)
/*
// now verify f with injected delays.
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.
sort.Slice(trace0, func(i, j int) bool {
return trace0[i].t.Before(trace[j].t)
}
*/
// 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).
} }
......
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