Skip to content

Commit

Permalink
Rename and extend event sink operations
Browse files Browse the repository at this point in the history
Signed-off-by: Frank Mueller <[email protected]>
  • Loading branch information
Frank Mueller committed Apr 15, 2021
1 parent 0942cca commit ec43b3c
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 81 deletions.
4 changes: 2 additions & 2 deletions behaviors/combo.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ func (b *comboBehavior) Go(cell mesh.Cell, in mesh.Receptor, out mesh.Emitter) e
b.sink.Clear()
case CriterionKeep:
case CriterionDropFirst:
b.sink.PullFirst()
b.sink.Shift()
case CriterionDropLast:
b.sink.PullLast()
b.sink.Pop()
default:
return fmt.Errorf("invalid criterion matcher result: %v", matches)
}
Expand Down
79 changes: 46 additions & 33 deletions mesh/eventsink.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ type EventSinkReader interface {
Len() int

// PeekFirst returns the first of the collected events.
PeekFirst() (Event, bool)
First() (Event, bool)

// PeekLast returns the last of the collected event datas.
PeekLast() (Event, bool)
Last() (Event, bool)

// PeekAt returns an event at a given index and true if it
// exists, otherwise nil and false.
PeekAt(index int) (Event, bool)
Peek(index int) (Event, bool)

// Do iterates over all collected events.
Do(do EventSinkDoFunc) error
Expand Down Expand Up @@ -66,7 +66,7 @@ func NewEventSink(max int, evts ...Event) *EventSink {
return s
}

// Push adds a new event to the sink.
// Push adds an event to the end of the sink.
func (s *EventSink) Push(evt Event) int {
s.events = append(s.events, evt)
if s.max > 0 && len(s.events) > s.max {
Expand All @@ -75,63 +75,76 @@ func (s *EventSink) Push(evt Event) int {
return len(s.events)
}

// PullFirst returns and removed the first event of the sink.
func (s *EventSink) PullFirst() Event {
var evt Event
if len(s.events) > 0 {
evt = s.events[0]
s.events = s.events[1:]
// Pop retrieves and removes the last event from the sink
// and also returns the new length.
func (s *EventSink) Pop() (Event, int) {
if len(s.events) == 0 {
return nilEvent, 0
}
return evt
l := len(s.events) - 1
evt := s.events[l]
s.events = s.events[:l]
return evt, l
}

// PullLast returns and removed the last event of the sink.
func (s *EventSink) PullLast() Event {
var evt Event
if len(s.events) > 0 {
evt = s.events[len(s.events)-1]
// Unshift adds an event to the begin of the sink.
func (s *EventSink) Unshift(evt Event) int {
s.events = append([]Event{evt}, s.events...)
if s.max > 0 && len(s.events) > s.max {
s.events = s.events[:len(s.events)-1]
}
return evt
}

// Clear removes all collected events.
func (s *EventSink) Clear() {
s.events = nil
return len(s.events)
}

// Len returns the number of events in the sink.
func (s *EventSink) Len() int {
return len(s.events)
// Shift returns and removes the first event of the sink
// and also returns the new length.
func (s *EventSink) Shift() (Event, int) {
if len(s.events) == 0 {
return nilEvent, 0
}
l := len(s.events) - 1
evt := s.events[0]
s.events = s.events[1:]
return evt, l
}

// PeekFirst allows a look at the first event of the sink if it
// First allows a look at the first event of the sink if it
// exists. Otherwise nil and false will be returned.
func (s *EventSink) PeekFirst() (Event, bool) {
func (s *EventSink) First() (Event, bool) {
if len(s.events) < 1 {
return nilEvent, false
}
return s.events[0], true
}

// PeekFirst allows a look at the last event of the sink if it
// Last allows a look at the last event of the sink if it
// exists. Otherwise nil and false will be returned.
func (s *EventSink) PeekLast() (Event, bool) {
func (s *EventSink) Last() (Event, bool) {
if len(s.events) < 1 {
return nilEvent, false
}
return s.events[len(s.events)-1], true
}

// PeekFirst allows a look at the indexed event of the sink if it
// Peek allows a look at the indexed event of the sink if it
// exists. Otherwise nil and false will be returned.
func (s *EventSink) PeekAt(index int) (Event, bool) {
func (s *EventSink) Peek(index int) (Event, bool) {
if index < 0 || index > len(s.events)-1 {
return nilEvent, false
}
return s.events[index], true
}

// Clear removes all collected events.
func (s *EventSink) Clear() {
s.events = nil
}

// Len returns the number of events in the sink.
func (s *EventSink) Len() int {
return len(s.events)
}

// Do allows to iterate over all events of the sink and perform a
// function.
func (s *EventSink) Do(do EventSinkDoFunc) error {
Expand Down Expand Up @@ -205,8 +218,8 @@ func EventSinkFold(r EventSinkReader, inject Event, fold EventSinkFoldFunc) (Eve

// EventSinkDuration returns the duration between the first and the last event.
func EventSinkDuration(r EventSinkReader) time.Duration {
first, fok := r.PeekFirst()
last, lok := r.PeekLast()
first, fok := r.First()
last, lok := r.Last()
if fok == false || lok == false {
return 0
}
Expand Down
129 changes: 83 additions & 46 deletions mesh/eventsink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,63 +25,100 @@ import (
// TESTS
//--------------------

// TestEventSinkSimple verifies the standard functions of the event sink.
func TestEventSinkSimple(t *testing.T) {
// TestEventSinkPushPop verifies pushing and popping operations.
func TestEventSinkPushPop(t *testing.T) {
assert := asserts.NewTesting(t, asserts.FailStop)

// Empty limited sink.
max := 5
sink := mesh.NewEventSink(max)
assert.Length(sink, 0)
first, ok := sink.PeekFirst()
assert.True(mesh.IsNilEvent(first))
assert.False(ok)
last, ok := sink.PeekLast()
assert.True(mesh.IsNilEvent(last))
assert.False(ok)
at, ok := sink.PeekAt(-1)
assert.True(mesh.IsNilEvent(at))
assert.False(ok)
at, ok = sink.PeekAt(1337)
assert.True(mesh.IsNilEvent(at))
assert.False(ok)

// Fill empty sink.
evts := generateEvents(2 * max)
for _, evt := range evts {
evts := generateEvents(max)
for i, evt := range evts {
l := sink.Push(evt)
assert.True(l <= max)
assert.Equal(l, i+1)
}
assert.Length(sink, max)
first, ok = sink.PeekFirst()
assert.OK(ok)
assert.Equal(first, evts[len(evts)-max])
last, ok = sink.PeekLast()
assert.OK(ok)
assert.Equal(last, evts[len(evts)-1])

// Filled limited sink.
sink = mesh.NewEventSink(max, evts...)
evts = generateEvents(1)
evtA := evts[0]
l := sink.Push(evtA)
assert.Equal(l, max)
assert.Length(sink, max)

evtB, l := sink.Pop()
assert.Equal(evtA, evtB)
assert.Equal(l, max-1)

for i := max - 1; i > 0; i-- {
_, l = sink.Pop()
assert.Equal(l, i-1)
}
assert.Length(sink, 0)
}

// TestEventSinkUnshiftShift verifies unshifting and shifting operations.
func TestEventSinkUnshiftShift(t *testing.T) {
assert := asserts.NewTesting(t, asserts.FailStop)

max := 5
sink := mesh.NewEventSink(max)
assert.Length(sink, 0)

evts := generateEvents(max)
for i, evt := range evts {
l := sink.Unshift(evt)
assert.Equal(l, i+1)
}
assert.Length(sink, max)

evts = generateEvents(1)
evtA := evts[0]
l := sink.Unshift(evtA)
assert.Equal(l, max)
assert.Length(sink, max)

evtB, l := sink.Shift()
assert.Equal(evtA, evtB)
assert.Equal(l, max-1)

for i := max - 1; i > 0; i-- {
_, l = sink.Shift()
assert.Equal(l, i-1)
}
assert.Length(sink, 0)
}

// TestEventSinkFirstLastPeek verifies reading access to the sink.
func TestEventSinkFirstLastPeek(t *testing.T) {
assert := asserts.NewTesting(t, asserts.FailStop)

max := 5
sink := mesh.NewEventSink(max)
assert.Length(sink, 0)

evts := generateEvents(max)
evtFirst := evts[0]
evtLast := evts[max-1]
evtMid := evts[2]

for _, evt := range evts {
sink.Push(evt)
}
assert.Length(sink, max)

first, ok := sink.First()
assert.True(ok)
last, ok := sink.Last()
assert.True(ok)
mid, ok := sink.Peek(2)
assert.True(ok)

assert.Equal(first, evtFirst)
assert.Equal(last, evtLast)
assert.Equal(mid, evtMid)

assert.Length(sink, max)
first, ok = sink.PeekFirst()
assert.OK(ok)
assert.Equal(first, evts[len(evts)-max])
last, ok = sink.PeekLast()
assert.OK(ok)
assert.Equal(last, evts[len(evts)-1])
first = sink.PullFirst()
assert.Equal(first, evts[len(evts)-max])
assert.Length(sink, max-1)

// Filled unlimited sink.
sink = mesh.NewEventSink(0, evts...)
assert.Length(sink, len(evts))
first, ok = sink.PeekFirst()
assert.OK(ok)
assert.Equal(first, evts[0])
last, ok = sink.PeekLast()
assert.OK(ok)
assert.Equal(last, evts[len(evts)-1])
}

// TestEventSinkDo verifies the iterating over a sink.
Expand Down

0 comments on commit ec43b3c

Please sign in to comment.