mirror of https://github.com/fluffle/goirc
Migrate to split event pkg.
This commit is contained in:
parent
4e4c4b6798
commit
907560b599
|
@ -3,7 +3,7 @@ package client
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"github.com/fluffle/goirc/event"
|
"github.com/fluffle/goevent/event"
|
||||||
"github.com/fluffle/golog/logging"
|
"github.com/fluffle/golog/logging"
|
||||||
"github.com/fluffle/goirc/state"
|
"github.com/fluffle/goirc/state"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
|
@ -2,7 +2,7 @@ package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"github.com/fluffle/goirc/event"
|
"github.com/fluffle/goevent/event"
|
||||||
"github.com/fluffle/golog/logging"
|
"github.com/fluffle/golog/logging"
|
||||||
"github.com/fluffle/goirc/state"
|
"github.com/fluffle/goirc/state"
|
||||||
"gomock.googlecode.com/hg/gomock"
|
"gomock.googlecode.com/hg/gomock"
|
||||||
|
|
|
@ -4,7 +4,7 @@ package client
|
||||||
// to manage tracking an irc connection etc.
|
// to manage tracking an irc connection etc.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fluffle/goirc/event"
|
"github.com/fluffle/goevent/event"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ package client
|
||||||
// to manage tracking state for an IRC connection
|
// to manage tracking state for an IRC connection
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fluffle/goirc/event"
|
"github.com/fluffle/goevent/event"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
// Automatically generated by MockGen. DO NOT EDIT!
|
|
||||||
// Source: registry.go
|
|
||||||
|
|
||||||
package event
|
|
||||||
|
|
||||||
import (
|
|
||||||
gomock "gomock.googlecode.com/hg/gomock"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Mock of Handler interface
|
|
||||||
type MockHandler struct {
|
|
||||||
ctrl *gomock.Controller
|
|
||||||
recorder *_MockHandlerRecorder
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recorder for MockHandler (not exported)
|
|
||||||
type _MockHandlerRecorder struct {
|
|
||||||
mock *MockHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMockHandler(ctrl *gomock.Controller) *MockHandler {
|
|
||||||
mock := &MockHandler{ctrl: ctrl}
|
|
||||||
mock.recorder = &_MockHandlerRecorder{mock}
|
|
||||||
return mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockHandler) EXPECT() *_MockHandlerRecorder {
|
|
||||||
return m.recorder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockHandler) Run(_param0 ...interface{}) {
|
|
||||||
m.ctrl.Call(m, "Run", _param0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockHandlerRecorder) Run(arg0 ...interface{}) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "Run", arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockHandler) Id() HandlerID {
|
|
||||||
ret := m.ctrl.Call(m, "Id")
|
|
||||||
ret0, _ := ret[0].(HandlerID)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockHandlerRecorder) Id() *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "Id")
|
|
||||||
}
|
|
||||||
// Mock of EventDispatcher interface
|
|
||||||
type MockEventDispatcher struct {
|
|
||||||
ctrl *gomock.Controller
|
|
||||||
recorder *_MockEventDispatcherRecorder
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recorder for MockEventDispatcher (not exported)
|
|
||||||
type _MockEventDispatcherRecorder struct {
|
|
||||||
mock *MockEventDispatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMockEventDispatcher(ctrl *gomock.Controller) *MockEventDispatcher {
|
|
||||||
mock := &MockEventDispatcher{ctrl: ctrl}
|
|
||||||
mock.recorder = &_MockEventDispatcherRecorder{mock}
|
|
||||||
return mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventDispatcher) EXPECT() *_MockEventDispatcherRecorder {
|
|
||||||
return m.recorder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventDispatcher) Dispatch(name string, ev ...interface{}) {
|
|
||||||
m.ctrl.Call(m, "Dispatch", name, ev)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockEventDispatcherRecorder) Dispatch(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "Dispatch", arg0, arg1)
|
|
||||||
}
|
|
||||||
// Mock of EventRegistry interface
|
|
||||||
type MockEventRegistry struct {
|
|
||||||
ctrl *gomock.Controller
|
|
||||||
recorder *_MockEventRegistryRecorder
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recorder for MockEventRegistry (not exported)
|
|
||||||
type _MockEventRegistryRecorder struct {
|
|
||||||
mock *MockEventRegistry
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMockEventRegistry(ctrl *gomock.Controller) *MockEventRegistry {
|
|
||||||
mock := &MockEventRegistry{ctrl: ctrl}
|
|
||||||
mock.recorder = &_MockEventRegistryRecorder{mock}
|
|
||||||
return mock
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventRegistry) EXPECT() *_MockEventRegistryRecorder {
|
|
||||||
return m.recorder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventRegistry) AddHandler(h Handler, names ...string) {
|
|
||||||
m.ctrl.Call(m, "AddHandler", h, names)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockEventRegistryRecorder) AddHandler(arg0 interface{}, arg1 ...string) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "AddHandler", arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventRegistry) DelHandler(h Handler, names ...string) {
|
|
||||||
m.ctrl.Call(m, "DelHandler", h, names)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockEventRegistryRecorder) DelHandler(arg0 interface{}, arg1 ...string) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "DelHandler", arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventRegistry) Dispatch(name string, ev ...interface{}) {
|
|
||||||
m.ctrl.Call(m, "Dispatch", name, ev)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockEventRegistryRecorder) Dispatch(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "Dispatch", arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockEventRegistry) ClearEvents(name string) {
|
|
||||||
m.ctrl.Call(m, "ClearEvents", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mr *_MockEventRegistryRecorder) ClearEvents(arg0 interface{}) *gomock.Call {
|
|
||||||
return mr.mock.ctrl.RecordCall(mr.mock, "ClearEvents", arg0)
|
|
||||||
}
|
|
|
@ -1,162 +0,0 @@
|
||||||
package event
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/list"
|
|
||||||
"strings"
|
|
||||||
"sync/atomic"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HandlerID uint32
|
|
||||||
|
|
||||||
var hidCounter uint32 = 0
|
|
||||||
|
|
||||||
func NewHandlerID() HandlerID {
|
|
||||||
return HandlerID(atomic.AddUint32(&hidCounter, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler interface {
|
|
||||||
Run(...interface{})
|
|
||||||
Id() HandlerID
|
|
||||||
}
|
|
||||||
|
|
||||||
type basicHandler struct {
|
|
||||||
fn func(...interface{})
|
|
||||||
id HandlerID
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *basicHandler) Run(ev ...interface{}) {
|
|
||||||
h.fn(ev...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *basicHandler) Id() HandlerID {
|
|
||||||
return h.id
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHandler(h func(...interface{})) Handler {
|
|
||||||
return &basicHandler{h, NewHandlerID()}
|
|
||||||
}
|
|
||||||
|
|
||||||
type EventDispatcher interface {
|
|
||||||
Dispatch(name string, ev ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type EventRegistry interface {
|
|
||||||
AddHandler(h Handler, names ...string)
|
|
||||||
DelHandler(h Handler, names ...string)
|
|
||||||
Dispatch(name string, ev ...interface{})
|
|
||||||
ClearEvents(name string)
|
|
||||||
}
|
|
||||||
|
|
||||||
type registry struct {
|
|
||||||
// Event registry as a lockable map of linked-lists
|
|
||||||
sync.RWMutex
|
|
||||||
events map[string]*list.List
|
|
||||||
dispatcher func(r *registry, name string, ev ...interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRegistry() *registry {
|
|
||||||
r := ®istry{events: make(map[string]*list.List)}
|
|
||||||
r.Parallel()
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) AddHandler(h Handler, names ...string) {
|
|
||||||
if len(names) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
r.Lock()
|
|
||||||
defer r.Unlock()
|
|
||||||
N: for _, name := range names {
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
if _, ok := r.events[name]; !ok {
|
|
||||||
r.events[name] = list.New()
|
|
||||||
}
|
|
||||||
for e := r.events[name].Front(); e != nil; e = e.Next() {
|
|
||||||
// Check we're not adding a duplicate handler to this event
|
|
||||||
if e.Value.(Handler).Id() == h.Id() {
|
|
||||||
continue N
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.events[name].PushBack(h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func _del(l *list.List, id HandlerID) bool {
|
|
||||||
for e := l.Front(); e != nil; e = e.Next() {
|
|
||||||
if e.Value.(Handler).Id() == id {
|
|
||||||
l.Remove(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return l.Len() == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) DelHandler(h Handler, names ...string) {
|
|
||||||
r.Lock()
|
|
||||||
defer r.Unlock()
|
|
||||||
if len(names) == 0 {
|
|
||||||
for name, l := range r.events {
|
|
||||||
if _del(l, h.Id()) {
|
|
||||||
r.events[name] = nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, name := range names {
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
if l, ok := r.events[name]; ok {
|
|
||||||
if _del(l, h.Id()) {
|
|
||||||
r.events[name] = nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) Dispatch(name string, ev ...interface{}) {
|
|
||||||
r.dispatcher(r, strings.ToLower(name), ev...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) ClearEvents(name string) {
|
|
||||||
name = strings.ToLower(name)
|
|
||||||
r.Lock()
|
|
||||||
defer r.Unlock()
|
|
||||||
if l, ok := r.events[name]; ok {
|
|
||||||
l.Init() // I hope this is enough to GC all list elements.
|
|
||||||
r.events[name] = nil, false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) Parallel() {
|
|
||||||
r.dispatcher = (*registry).parallelDispatch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) Serial() {
|
|
||||||
r.dispatcher = (*registry).serialDispatch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) parallelDispatch(name string, ev ...interface{}) {
|
|
||||||
r.RLock()
|
|
||||||
defer r.RUnlock()
|
|
||||||
if l, ok := r.events[name]; ok {
|
|
||||||
for e := l.Front(); e != nil; e = e.Next() {
|
|
||||||
h := e.Value.(Handler)
|
|
||||||
go h.Run(ev...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *registry) serialDispatch(name string, ev ...interface{}) {
|
|
||||||
r.RLock()
|
|
||||||
defer r.RUnlock()
|
|
||||||
if l, ok := r.events[name]; ok {
|
|
||||||
hlist := make([]Handler, l.Len())
|
|
||||||
for e, i := l.Front(), 0; e != nil; e, i = e.Next(), i+1 {
|
|
||||||
hlist[i] = e.Value.(Handler)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for _, h := range hlist {
|
|
||||||
h.Run(ev...)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,224 +0,0 @@
|
||||||
package event
|
|
||||||
|
|
||||||
// oh hey unit tests. or functionality tests, or something.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAddDelHandler(t *testing.T) {
|
|
||||||
r := NewRegistry()
|
|
||||||
|
|
||||||
if len(r.events) != 0 {
|
|
||||||
t.Errorf("New registry has non-zero-length event map.")
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 := NewHandler(func(ev ...interface{}) {})
|
|
||||||
h2 := NewHandler(func(ev ...interface{}) {})
|
|
||||||
|
|
||||||
// Ensure that a handler with no events to handle doesn't get added
|
|
||||||
r.AddHandler(h1)
|
|
||||||
if len(r.events) != 0 {
|
|
||||||
t.Errorf("Adding handler with no events succeded.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add h1 to a couple of events.
|
|
||||||
r.AddHandler(h1, "e1", "E2")
|
|
||||||
if len(r.events) != 2 {
|
|
||||||
t.Errorf("Adding handler h1 to events failed.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e1"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value != h1 {
|
|
||||||
t.Errorf("Handler h1 not added to event e1 correctly.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e2"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value != h1 {
|
|
||||||
t.Errorf("Handler h1 not added to event e2 correctly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add h2 to a couple of events.
|
|
||||||
r.AddHandler(h2, "e2", "E3")
|
|
||||||
if len(r.events) != 3 {
|
|
||||||
t.Errorf("Adding handler h2 to events failed.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e2"]; !ok || l.Len() != 2 ||
|
|
||||||
l.Front().Next().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Handler h2 not added to event e2 correctly.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e3"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Handler h2 not added to event e3 correctly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add h1 to some more events, which it may be in already.
|
|
||||||
r.AddHandler(h1, "e2", "e3", "e4", "e5")
|
|
||||||
if len(r.events) != 5 {
|
|
||||||
t.Errorf("Adding handler h1 to more events failed.")
|
|
||||||
println(len(r.events))
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e2"]; !ok || l.Len() != 2 {
|
|
||||||
t.Errorf("Handler h1 added twice to event e2.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e3"]; !ok || l.Len() != 2 ||
|
|
||||||
l.Front().Next().Value.(Handler) != h1 {
|
|
||||||
t.Errorf("Handler h1 not added to event e3 correctly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add h2 to a few more events, for testing delete
|
|
||||||
r.AddHandler(h2, "e5", "e6")
|
|
||||||
if len(r.events) != 6 {
|
|
||||||
t.Errorf("Adding handler h2 to more events failed.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently, we have the following handlers set up:
|
|
||||||
// h1: e1 e2 e3 e4 e5
|
|
||||||
// h2: e2 e3 e5 e6
|
|
||||||
// NOTE: for e3, h2 is first and h1 is second in the linked list
|
|
||||||
|
|
||||||
// Delete h1 from a few events. This should remove e4 completely.
|
|
||||||
r.DelHandler(h1, "e2", "E3", "e4")
|
|
||||||
if _, ok := r.events["e4"]; ok || len(r.events) != 5 {
|
|
||||||
t.Errorf("Deleting h1 from some events failed to remove e4.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e2"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Handler h1 not deleted from event e2 correctly.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e3"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Handler h1 not deleted from event e3 correctly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now, we have the following handlers set up:
|
|
||||||
// h1: e1 e5
|
|
||||||
// h2: e2 e3 e5 e6
|
|
||||||
|
|
||||||
// Delete h2 from a couple of events, removing e2 and e3.
|
|
||||||
// Deleting h2 from a handler it is not in should not cause problems.
|
|
||||||
r.DelHandler(h2, "e1", "e2", "e3")
|
|
||||||
if len(r.events) != 3 {
|
|
||||||
t.Errorf("Deleting h2 from some events failed to remove e{2,3}.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e1"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h1 {
|
|
||||||
t.Errorf("Handler h1 deleted from event e1 incorrectly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete h1 completely.
|
|
||||||
r.DelHandler(h1)
|
|
||||||
if _, ok := r.events["e1"]; ok || len(r.events) != 2 {
|
|
||||||
t.Errorf("Deleting h1 completely failed to remove e1.")
|
|
||||||
}
|
|
||||||
if l, ok := r.events["e5"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Handler h1 deleted from event e5 incorrectly.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear e5 completely
|
|
||||||
r.ClearEvents("e5")
|
|
||||||
if _, ok := r.events["e5"]; ok || len(r.events) != 1 {
|
|
||||||
t.Errorf("Deleting e5 completely failed to remove it.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// All that should be left is e6, with h2 as it's only handler.
|
|
||||||
if l, ok := r.events["e6"]; !ok || l.Len() != 1 ||
|
|
||||||
l.Front().Value.(Handler) != h2 {
|
|
||||||
t.Errorf("Remaining event and handler doesn't match expectations.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSimpleDispatch(t *testing.T) {
|
|
||||||
r := NewRegistry()
|
|
||||||
out := make(chan bool)
|
|
||||||
|
|
||||||
h := NewHandler(func(ev ...interface{}) {
|
|
||||||
out <- ev[0].(bool)
|
|
||||||
})
|
|
||||||
r.AddHandler(h, "send")
|
|
||||||
|
|
||||||
r.Dispatch("send", true)
|
|
||||||
if val := <-out; !val {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
|
|
||||||
r.Dispatch("send", false)
|
|
||||||
if val := <-out; val {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParallelDispatch(t *testing.T) {
|
|
||||||
r := NewRegistry()
|
|
||||||
// ensure we have enough of a buffer that all sends complete
|
|
||||||
out := make(chan int, 5)
|
|
||||||
// handler factory :-)
|
|
||||||
factory := func(t int) Handler {
|
|
||||||
return NewHandler(func(ev ...interface{}) {
|
|
||||||
// t * 10ms sleep
|
|
||||||
time.Sleep(int64(t * 1e7))
|
|
||||||
out <- t
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// create some handlers and send an event to them
|
|
||||||
for _, t := range []int{5, 11, 2, 15, 8} {
|
|
||||||
r.AddHandler(factory(t), "send")
|
|
||||||
}
|
|
||||||
r.Dispatch("send")
|
|
||||||
|
|
||||||
// If parallel dispatch is working, results from out should be in numerical order
|
|
||||||
if val := <-out; val != 2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 5 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 8 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 11 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 15 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSerialDispatch(t *testing.T) {
|
|
||||||
r := NewRegistry()
|
|
||||||
r.Serial()
|
|
||||||
// ensure we have enough of a buffer that all sends complete
|
|
||||||
out := make(chan int, 5)
|
|
||||||
// handler factory :-)
|
|
||||||
factory := func(t int) Handler {
|
|
||||||
return NewHandler(func(ev ...interface{}) {
|
|
||||||
// t * 10ms sleep
|
|
||||||
time.Sleep(int64(t * 1e7))
|
|
||||||
out <- t
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// create some handlers and send an event to them
|
|
||||||
for _, t := range []int{5, 11, 2, 15, 8} {
|
|
||||||
r.AddHandler(factory(t), "send")
|
|
||||||
}
|
|
||||||
r.Dispatch("send")
|
|
||||||
|
|
||||||
// If serial dispatch is working, results from out should be in handler order
|
|
||||||
if val := <-out; val != 5 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 11 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 2 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 15 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
if val := <-out; val != 8 {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue