diff --git a/eventer.go b/eventer.go index 8d314720c..c1e1ae643 100644 --- a/eventer.go +++ b/eventer.go @@ -18,20 +18,27 @@ type eventer struct { type Eventer interface { // Events returns the map of valid Event names. Events() (eventnames map[string]string) + // Event returns an Event string from map of valid Event names. // Mostly used to validate that an Event name is valid. Event(name string) string + // AddEvent registers a new Event name. AddEvent(name string) + // DeleteEvent removes a previously registered Event name. DeleteEvent(name string) - // Publish new events to anyone listening + + // Publish new events to anyone that is subscribed Publish(name string, data interface{}) + // Subscribe to any events from this eventer Subscribe() (events eventChannel) + // Event handler On(name string, f func(s interface{})) (err error) - // Event handler, only exectues one time + + // Event handler, only executes one time Once(name string, f func(s interface{})) (err error) } @@ -43,7 +50,7 @@ func NewEventer() Eventer { outs: make([]eventChannel, 1), } - // goroutine to cascade in events to all out event channels + // goroutine to cascade "in" events to all "out" event channels go func() { for { select { @@ -58,35 +65,41 @@ func NewEventer() Eventer { return evtr } +// Events returns the map of valid Event names. func (e *eventer) Events() map[string]string { return e.eventnames } +// Event returns an Event string from map of valid Event names. +// Mostly used to validate that an Event name is valid. func (e *eventer) Event(name string) string { return e.eventnames[name] } +// AddEvent registers a new Event name. func (e *eventer) AddEvent(name string) { e.eventnames[name] = name } +// DeleteEvent removes a previously registered Event name. func (e *eventer) DeleteEvent(name string) { delete(e.eventnames, name) } +// Publish new events to anyone that is subscribed func (e *eventer) Publish(name string, data interface{}) { evt := NewEvent(name, data) e.in <- evt } +// Subscribe to any events from this eventer func (e *eventer) Subscribe() eventChannel { out := make(eventChannel) e.outs = append(e.outs, out) return out } -// On executes f when e is Published to. Returns ErrUnknownEvent if Event -// does not exist. +// On executes the event handler f when e is Published to. func (e *eventer) On(n string, f func(s interface{})) (err error) { out := e.Subscribe() go func() { @@ -103,17 +116,17 @@ func (e *eventer) On(n string, f func(s interface{})) (err error) { return } -// Once is similar to On except that it only executes f one time. Returns -//ErrUnknownEvent if Event does not exist. +// Once is similar to On except that it only executes f one time. func (e *eventer) Once(n string, f func(s interface{})) (err error) { out := e.Subscribe() go func() { + ProcessEvents: for { select { case evt := <-out: if evt.Name == n { f(evt.Data) - break + break ProcessEvents } } } diff --git a/eventer_test.go b/eventer_test.go index 28abcb06e..659003dac 100644 --- a/eventer_test.go +++ b/eventer_test.go @@ -2,6 +2,7 @@ package gobot import ( "testing" + "time" ) func TestEventerAddEvent(t *testing.T) { @@ -22,3 +23,53 @@ func TestEventerDeleteEvent(t *testing.T) { t.Errorf("Could not add delete event from list of Event names") } } + +func TestEventerOn(t *testing.T) { + e := NewEventer() + e.AddEvent("test") + + sem := make(chan bool) + e.On("test", func(data interface{}) { + sem <- true + }) + + go func() { + e.Publish("test", true) + }() + + select { + case <-sem: + case <-time.After(10 * time.Millisecond): + t.Errorf("On was not called") + } +} + +func TestEventerOnce(t *testing.T) { + e := NewEventer() + e.AddEvent("test") + + sem := make(chan bool) + e.Once("test", func(data interface{}) { + sem <- true + }) + + go func() { + e.Publish("test", true) + }() + + select { + case <-sem: + case <-time.After(10 * time.Millisecond): + t.Errorf("Once was not called") + } + + go func() { + e.Publish("test", true) + }() + + select { + case <-sem: + t.Errorf("Once was called twice") + case <-time.After(10 * time.Millisecond): + } +}