Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Stefane Fermigier
neo
Commits
fc2f4a1a
Commit
fc2f4a1a
authored
7 years ago
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
c5f6dc77
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
56 deletions
+87
-56
go/neo/cluster_test.go
go/neo/cluster_test.go
+58
-52
go/xcommon/xtracing/tracetest/tracetest.go
go/xcommon/xtracing/tracetest/tracetest.go
+29
-4
No files found.
go/neo/cluster_test.go
View file @
fc2f4a1a
...
@@ -41,7 +41,7 @@ import (
...
@@ -41,7 +41,7 @@ import (
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/zodb"
"lab.nexedi.com/kirr/neo/go/xcommon/xtracing/t
sync
"
"lab.nexedi.com/kirr/neo/go/xcommon/xtracing/t
racetest
"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/exc"
"lab.nexedi.com/kirr/go123/tracing"
"lab.nexedi.com/kirr/go123/tracing"
...
@@ -116,14 +116,14 @@ func masterStartReady(where string, ready bool) *eventMStartReady {
...
@@ -116,14 +116,14 @@ func masterStartReady(where string, ready bool) *eventMStartReady {
type
EventRouter
struct
{
type
EventRouter
struct
{
mu
sync
.
Mutex
mu
sync
.
Mutex
defaultq
*
t
sync
.
SyncChan
defaultq
*
t
racetest
.
SyncChan
// events specific to particular node - e.g. node starts listening,
// events specific to particular node - e.g. node starts listening,
// state on that node changes, etc...
// state on that node changes, etc...
byNode
map
[
string
/*host*/
]
*
t
sync
.
SyncChan
byNode
map
[
string
/*host*/
]
*
t
racetest
.
SyncChan
// state on host changes. Takes precendece over byNode.
// state on host changes. Takes precendece over byNode.
byState
map
[
string
/*host*/
]
*
t
sync
.
SyncChan
byState
map
[
string
/*host*/
]
*
t
racetest
.
SyncChan
// event on a-b link
// event on a-b link
byLink
map
[
string
/*host-host*/
]
*
linkDst
byLink
map
[
string
/*host-host*/
]
*
linkDst
...
@@ -133,16 +133,16 @@ type EventRouter struct {
...
@@ -133,16 +133,16 @@ type EventRouter struct {
func
NewEventRouter
()
*
EventRouter
{
func
NewEventRouter
()
*
EventRouter
{
return
&
EventRouter
{
return
&
EventRouter
{
defaultq
:
t
sync
.
NewSyncChan
(
"default"
),
defaultq
:
t
racetest
.
NewSyncChan
(
"default"
),
byNode
:
make
(
map
[
string
]
*
t
sync
.
SyncChan
),
byNode
:
make
(
map
[
string
]
*
t
racetest
.
SyncChan
),
byState
:
make
(
map
[
string
]
*
t
sync
.
SyncChan
),
byState
:
make
(
map
[
string
]
*
t
racetest
.
SyncChan
),
byLink
:
make
(
map
[
string
]
*
linkDst
),
byLink
:
make
(
map
[
string
]
*
linkDst
),
connected
:
make
(
map
[
string
]
bool
),
connected
:
make
(
map
[
string
]
bool
),
}
}
}
}
func
(
r
*
EventRouter
)
AllRoutes
()
[]
*
t
sync
.
SyncChan
{
func
(
r
*
EventRouter
)
AllRoutes
()
[]
*
t
racetest
.
SyncChan
{
rtset
:=
map
[
*
t
sync
.
SyncChan
]
int
{}
rtset
:=
map
[
*
t
racetest
.
SyncChan
]
int
{}
rtset
[
r
.
defaultq
]
=
1
rtset
[
r
.
defaultq
]
=
1
for
_
,
dst
:=
range
r
.
byNode
{
for
_
,
dst
:=
range
r
.
byNode
{
rtset
[
dst
]
=
1
rtset
[
dst
]
=
1
...
@@ -155,7 +155,7 @@ func (r *EventRouter) AllRoutes() []*tsync.SyncChan {
...
@@ -155,7 +155,7 @@ func (r *EventRouter) AllRoutes() []*tsync.SyncChan {
rtset
[
ldst
.
b
]
=
1
rtset
[
ldst
.
b
]
=
1
}
}
var
rtv
[]
*
t
sync
.
SyncChan
var
rtv
[]
*
t
racetest
.
SyncChan
for
dst
:=
range
rtset
{
for
dst
:=
range
rtset
{
rtv
=
append
(
rtv
,
dst
)
rtv
=
append
(
rtv
,
dst
)
}
}
...
@@ -184,7 +184,7 @@ func host(addr string) string {
...
@@ -184,7 +184,7 @@ func host(addr string) string {
}
}
// Route routes events according to rules specified via Branch*()
// Route routes events according to rules specified via Branch*()
func
(
r
*
EventRouter
)
Route
(
event
interface
{})
(
dst
*
t
sync
.
SyncChan
)
{
func
(
r
*
EventRouter
)
Route
(
event
interface
{})
(
dst
*
t
racetest
.
SyncChan
)
{
r
.
mu
.
Lock
()
r
.
mu
.
Lock
()
defer
r
.
mu
.
Unlock
()
defer
r
.
mu
.
Unlock
()
...
@@ -258,7 +258,7 @@ func (r *EventRouter) Route(event interface{}) (dst *tsync.SyncChan) {
...
@@ -258,7 +258,7 @@ func (r *EventRouter) Route(event interface{}) (dst *tsync.SyncChan) {
}
}
// routeState routes event corresponding to state change on host
// routeState routes event corresponding to state change on host
func
(
r
*
EventRouter
)
routeState
(
host
string
)
(
dst
*
t
sync
.
SyncChan
)
{
func
(
r
*
EventRouter
)
routeState
(
host
string
)
(
dst
*
t
racetest
.
SyncChan
)
{
// lookup dst by state rules
// lookup dst by state rules
dst
=
r
.
byState
[
host
]
dst
=
r
.
byState
[
host
]
if
dst
!=
nil
{
if
dst
!=
nil
{
...
@@ -270,7 +270,7 @@ func (r *EventRouter) routeState(host string) (dst *tsync.SyncChan) {
...
@@ -270,7 +270,7 @@ func (r *EventRouter) routeState(host string) (dst *tsync.SyncChan) {
}
}
// BranchNode branches events corresponding to host.
// BranchNode branches events corresponding to host.
func
(
r
*
EventRouter
)
BranchNode
(
host
string
,
dst
*
t
sync
.
SyncChan
)
{
func
(
r
*
EventRouter
)
BranchNode
(
host
string
,
dst
*
t
racetest
.
SyncChan
)
{
r
.
mu
.
Lock
()
r
.
mu
.
Lock
()
defer
r
.
mu
.
Unlock
()
defer
r
.
mu
.
Unlock
()
...
@@ -282,7 +282,7 @@ func (r *EventRouter) BranchNode(host string, dst *tsync.SyncChan) {
...
@@ -282,7 +282,7 @@ func (r *EventRouter) BranchNode(host string, dst *tsync.SyncChan) {
}
}
// BranchState branches events corresponding to state changes on host.
// BranchState branches events corresponding to state changes on host.
func
(
r
*
EventRouter
)
BranchState
(
host
string
,
dst
*
t
sync
.
SyncChan
)
{
func
(
r
*
EventRouter
)
BranchState
(
host
string
,
dst
*
t
racetest
.
SyncChan
)
{
r
.
mu
.
Lock
()
r
.
mu
.
Lock
()
defer
r
.
mu
.
Unlock
()
defer
r
.
mu
.
Unlock
()
...
@@ -299,7 +299,7 @@ func (r *EventRouter) BranchState(host string, dst *tsync.SyncChan) {
...
@@ -299,7 +299,7 @@ func (r *EventRouter) BranchState(host string, dst *tsync.SyncChan) {
//
//
// Event with networking cause root coming from a go to dsta, and with
// Event with networking cause root coming from a go to dsta, and with
// networking cause root coming from b - go to dstb.
// networking cause root coming from b - go to dstb.
func
(
r
*
EventRouter
)
BranchLink
(
link
string
,
dsta
,
dstb
*
t
sync
.
SyncChan
)
{
func
(
r
*
EventRouter
)
BranchLink
(
link
string
,
dsta
,
dstb
*
t
racetest
.
SyncChan
)
{
r
.
mu
.
Lock
()
r
.
mu
.
Lock
()
defer
r
.
mu
.
Unlock
()
defer
r
.
mu
.
Unlock
()
...
@@ -313,8 +313,8 @@ func (r *EventRouter) BranchLink(link string, dsta, dstb *tsync.SyncChan) {
...
@@ -313,8 +313,8 @@ func (r *EventRouter) BranchLink(link string, dsta, dstb *tsync.SyncChan) {
}
}
type
linkDst
struct
{
type
linkDst
struct
{
a
*
t
sync
.
SyncChan
// net cause was on dialer
a
*
t
racetest
.
SyncChan
// net cause was on dialer
b
*
t
sync
.
SyncChan
// net cause was on listener
b
*
t
racetest
.
SyncChan
// net cause was on listener
}
}
// ---- trace probes, etc -> events -> dispatcher ----
// ---- trace probes, etc -> events -> dispatcher ----
...
@@ -322,14 +322,14 @@ type linkDst struct {
...
@@ -322,14 +322,14 @@ type linkDst struct {
// TraceCollector connects to NEO-specific trace points via probes and sends events to dispatcher.
// TraceCollector connects to NEO-specific trace points via probes and sends events to dispatcher.
type
TraceCollector
struct
{
type
TraceCollector
struct
{
pg
*
tracing
.
ProbeGroup
pg
*
tracing
.
ProbeGroup
d
*
tsync
.
EventDispatcher
d
interface
{
Dispatch
(
interface
{})
}
node2Name
map
[
*
NodeApp
]
string
node2Name
map
[
*
NodeApp
]
string
nodeTab2Owner
map
[
*
NodeTable
]
string
nodeTab2Owner
map
[
*
NodeTable
]
string
clusterState2Owner
map
[
*
proto
.
ClusterState
]
string
clusterState2Owner
map
[
*
proto
.
ClusterState
]
string
}
}
func
NewTraceCollector
(
dispatch
*
tsync
.
EventDispatcher
)
*
TraceCollector
{
func
NewTraceCollector
(
dispatch
interface
{
Dispatch
(
interface
{})
}
)
*
TraceCollector
{
return
&
TraceCollector
{
return
&
TraceCollector
{
pg
:
&
tracing
.
ProbeGroup
{},
pg
:
&
tracing
.
ProbeGroup
{},
d
:
dispatch
,
d
:
dispatch
,
...
@@ -415,7 +415,7 @@ func (t *TraceCollector) traceMasterStartReady(m *Master, ready bool) {
...
@@ -415,7 +415,7 @@ func (t *TraceCollector) traceMasterStartReady(m *Master, ready bool) {
// M drives cluster with 1 S & C through recovery -> verification -> service -> shutdown
// M drives cluster with 1 S & C through recovery -> verification -> service -> shutdown
func
TestMasterStorage
(
t
*
testing
.
T
)
{
func
TestMasterStorage
(
t
*
testing
.
T
)
{
rt
:=
NewEventRouter
()
rt
:=
NewEventRouter
()
dispatch
:=
t
sync
.
NewEventDispatcher
(
rt
)
dispatch
:=
t
racetest
.
NewEventDispatcher
(
rt
)
tracer
:=
NewTraceCollector
(
dispatch
)
tracer
:=
NewTraceCollector
(
dispatch
)
net
:=
pipenet
.
New
(
"testnet"
)
// test network
net
:=
pipenet
.
New
(
"testnet"
)
// test network
...
@@ -423,11 +423,6 @@ func TestMasterStorage(t *testing.T) {
...
@@ -423,11 +423,6 @@ func TestMasterStorage(t *testing.T) {
tracer
.
Attach
()
tracer
.
Attach
()
defer
tracer
.
Detach
()
defer
tracer
.
Detach
()
// by default events go to g
//g := tsync.NewEventChecker(t, dispatch, rt.defaultq)
// shortcut for addresses
// shortcut for addresses
xaddr
:=
func
(
addr
string
)
*
pipenet
.
Addr
{
xaddr
:=
func
(
addr
string
)
*
pipenet
.
Addr
{
a
,
err
:=
net
.
ParseAddr
(
addr
)
a
,
err
:=
net
.
ParseAddr
(
addr
)
...
@@ -483,23 +478,23 @@ func TestMasterStorage(t *testing.T) {
...
@@ -483,23 +478,23 @@ func TestMasterStorage(t *testing.T) {
Shost
:=
xnet
.
NetTrace
(
net
.
Host
(
"s"
),
tracer
)
Shost
:=
xnet
.
NetTrace
(
net
.
Host
(
"s"
),
tracer
)
Chost
:=
xnet
.
NetTrace
(
net
.
Host
(
"c"
),
tracer
)
Chost
:=
xnet
.
NetTrace
(
net
.
Host
(
"c"
),
tracer
)
cM
:=
t
sync
.
NewSyncChan
(
"m.main"
)
// trace of events local to M
cM
:=
t
racetest
.
NewSyncChan
(
"m.main"
)
// trace of events local to M
cS
:=
t
sync
.
NewSyncChan
(
"s.main"
)
// trace of events local to S XXX with cause root also on S
cS
:=
t
racetest
.
NewSyncChan
(
"s.main"
)
// trace of events local to S XXX with cause root also on S
// cC := t
sync
.NewSyncChan("c.main")
// cC := t
racetest
.NewSyncChan("c.main")
cMS
:=
t
sync
.
NewSyncChan
(
"m-s"
)
// trace of events with cause root being m -> s send
cMS
:=
t
racetest
.
NewSyncChan
(
"m-s"
)
// trace of events with cause root being m -> s send
cSM
:=
t
sync
.
NewSyncChan
(
"s-m"
)
// trace of events with cause root being s -> m send
cSM
:=
t
racetest
.
NewSyncChan
(
"s-m"
)
// trace of events with cause root being s -> m send
cMC
:=
t
sync
.
NewSyncChan
(
"m-c"
)
// ----//---- m -> c
cMC
:=
t
racetest
.
NewSyncChan
(
"m-c"
)
// ----//---- m -> c
cCM
:=
t
sync
.
NewSyncChan
(
"c-m"
)
// ----//---- c -> m
cCM
:=
t
racetest
.
NewSyncChan
(
"c-m"
)
// ----//---- c -> m
cCS
:=
t
sync
.
NewSyncChan
(
"c-s"
)
// ----//---- c -> s
cCS
:=
t
racetest
.
NewSyncChan
(
"c-s"
)
// ----//---- c -> s
tM
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cM
)
tM
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cM
)
tS
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cS
)
tS
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cS
)
// tC := t
sync
.NewEventChecker(t, dispatch, cC) // XXX no need
// tC := t
racetest
.NewEventChecker(t, dispatch, cC) // XXX no need
tMS
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cMS
)
tMS
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cMS
)
tSM
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cSM
)
tSM
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cSM
)
tMC
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cMC
)
tMC
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cMC
)
tCM
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cCM
)
tCM
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cCM
)
tCS
:=
t
sync
.
NewEventChecker
(
t
,
dispatch
,
cCS
)
tCS
:=
t
racetest
.
NewEventChecker
(
t
,
dispatch
,
cCS
)
rt
.
BranchNode
(
"m"
,
cM
)
rt
.
BranchNode
(
"m"
,
cM
)
...
@@ -910,7 +905,18 @@ func TestMasterStorage(t *testing.T) {
...
@@ -910,7 +905,18 @@ func TestMasterStorage(t *testing.T) {
}
}
/*
// dispatch1 dispatched directly to single output channel
//
// XXX hack - better we don't need it.
// XXX -> with testenv.MkCluster() we won't need it
type
tdispatch1
struct
{
outch
*
tracetest
.
SyncChan
}
func
(
d
tdispatch1
)
Dispatch
(
event
interface
{})
{
d
.
outch
.
Send
(
event
)
}
func
benchmarkGetObject
(
b
*
testing
.
B
,
Mnet
,
Snet
,
Cnet
xnet
.
Networker
,
benchit
func
(
xcload1
func
()))
{
func
benchmarkGetObject
(
b
*
testing
.
B
,
Mnet
,
Snet
,
Cnet
xnet
.
Networker
,
benchit
func
(
xcload1
func
()))
{
// create test cluster <- XXX factor to utility func
// create test cluster <- XXX factor to utility func
zstor
:=
xfs1stor
(
"../zodb/storage/fs1/testdata/1.fs"
)
zstor
:=
xfs1stor
(
"../zodb/storage/fs1/testdata/1.fs"
)
...
@@ -924,12 +930,13 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
...
@@ -924,12 +930,13 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
M
:=
NewMaster
(
"abc1"
,
""
,
Mnet
)
M
:=
NewMaster
(
"abc1"
,
""
,
Mnet
)
// XXX to wait for "M listens at ..." & "ready to start" -> XXX add something to M api?
// XXX to wait for "M listens at ..." & "ready to start" -> XXX add something to M api?
tracer := &TraceRouter{tsync.NewSyncChan()}
cG
:=
tracetest
.
NewSyncChan
(
"main"
)
tc := tsync.NewEventChecker(b, tracer.SyncChan)
tG
:=
tracetest
.
NewEventChecker
(
b
,
nil
/* XXX */
,
cG
)
pg := &tracing.ProbeGroup{}
tracer
:=
NewTraceCollector
(
tdispatch1
{
cG
})
tracing
.
Lock
()
tracing
.
Lock
()
pnode
:=
traceNodeChanged_Attach
(
nil
,
tracer
.
traceNode
)
pnode
:=
traceNodeChanged_Attach
(
nil
,
tracer
.
traceNode
)
traceMasterStartReady_Attach(pg, tracer.traceMasterStartReady)
traceMasterStartReady_Attach
(
tracer
.
pg
,
tracer
.
traceMasterStartReady
)
tracing
.
Unlock
()
tracing
.
Unlock
()
wg
.
Go
(
func
()
error
{
wg
.
Go
(
func
()
error
{
...
@@ -937,7 +944,7 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
...
@@ -937,7 +944,7 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
})
})
// determing M serving address XXX better with M api
// determing M serving address XXX better with M api
ev :=
tracer
.Recv()
ev
:=
cG
.
Recv
()
mnode
,
ok
:=
ev
.
Event
.
(
*
eventNodeTab
)
mnode
,
ok
:=
ev
.
Event
.
(
*
eventNodeTab
)
if
!
ok
{
if
!
ok
{
b
.
Fatal
(
"after M start: got %T ; want eventNodeTab"
,
ev
.
Event
)
b
.
Fatal
(
"after M start: got %T ; want eventNodeTab"
,
ev
.
Event
)
...
@@ -951,15 +958,15 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
...
@@ -951,15 +958,15 @@ func benchmarkGetObject(b *testing.B, Mnet, Snet, Cnet xnet.Networker, benchit f
// now after we know Maddr create S & C and start S serving
// now after we know Maddr create S & C and start S serving
S
:=
NewStorage
(
"abc1"
,
Maddr
,
""
,
Snet
,
zstor
)
S
:=
NewStorage
(
"abc1"
,
Maddr
,
""
,
Snet
,
zstor
)
C :=
client.
NewClient("abc1", Maddr, Cnet)
C
:=
NewClient
(
"abc1"
,
Maddr
,
Cnet
)
wg
.
Go
(
func
()
error
{
wg
.
Go
(
func
()
error
{
return
S
.
Run
(
ctx
)
return
S
.
Run
(
ctx
)
})
})
// command M to start
// command M to start
t
c.Expect(masterStartReady(M
, true)) // <- XXX better with M api
t
G
.
Expect
(
masterStartReady
(
"m"
,
true
))
// <- XXX better with M api
pg.Done
()
tracer
.
Detach
()
err
:=
M
.
Start
()
err
:=
M
.
Start
()
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -1043,4 +1050,3 @@ func BenchmarkGetObjectTCPloParallel(b *testing.B) {
...
@@ -1043,4 +1050,3 @@ func BenchmarkGetObjectTCPloParallel(b *testing.B) {
net
:=
xnet
.
NetPlain
(
"tcp"
)
net
:=
xnet
.
NetPlain
(
"tcp"
)
benchmarkGetObjectParallel
(
b
,
net
,
net
,
net
)
benchmarkGetObjectParallel
(
b
,
net
,
net
,
net
)
}
}
*/
This diff is collapsed.
Click to expand it.
go/xcommon/xtracing/t
sync/tsync
.go
→
go/xcommon/xtracing/t
racetest/tracetest
.go
View file @
fc2f4a1a
...
@@ -17,8 +17,8 @@
...
@@ -17,8 +17,8 @@
// 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.
// Package t
sync provides infrastructure for synchronous testing based on program tracing.
// Package t
racetest provides infrastructure for testing concurrent systems
//
XXX naming -> ttest? tracetest? synctest?
//
based on synchronous events tracing.
//
//
// A serial system can be verified by checking that its execution produces
// A serial system can be verified by checking that its execution produces
// expected serial stream of events. But concurrent systems cannot be verified
// expected serial stream of events. But concurrent systems cannot be verified
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
// However in a concurrent system one can decompose all events into serial
// However in a concurrent system one can decompose all events into serial
// streams in which events are strictly ordered by causality with respect to
// streams in which events are strictly ordered by causality with respect to
// each other. This decomposition in turn allows to verify that in every stream
// each other. This decomposition in turn allows to verify that in every stream
// events
were
as expected.
// events
happenned
as expected.
//
//
// Verification of events for all streams can be done by one *sequential*
// Verification of events for all streams can be done by one *sequential*
// process:
// process:
...
@@ -44,12 +44,37 @@
...
@@ -44,12 +44,37 @@
// 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:
//
// - implement tracer that will be synchronously collecting events from
// execution of your program. This can be done with package
// lab.nexedi.com/kirr/go123/tracing or by other similar means.
//
// the tracer have to output events to dispatcher (see below).
//
// - implement router that will be making decisions specific to your
// particular testing scenario on to which stream an event should belong.
//
// the router will be consulted by dispatcher (see below) for its working.
//
// - create Dispatcher. This is the central place where events are
// delivered from tracer and are further delivered in accordance to what
// router says.
//
// - for every serial stream of events create synchronous delivery channel
// (SyncChan) and event Checker. XXX
//
//
// XXX more text describing how to use the package.
// XXX more text describing how to use the package.
//
//
//
// XXX say that checker will detect deadlock if there is no event or it or
// another comes at different trace channel.
//
// XXX (if tested system is serial only there is no need to use Dispatcher and
// XXX (if tested system is serial only there is no need to use Dispatcher and
// routing - the collector can send output directly to the only SyncChan with
// routing - the collector can send output directly to the only SyncChan with
// only one EventChecker connected to it).
// only one EventChecker connected to it).
package
t
sync
package
t
racetest
import
(
import
(
"fmt"
"fmt"
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment