Simplified and debugged the filter logic.
authorChris Jones <christian.jones@sri.com>
Mon, 09 Sep 2013 04:16:16 +0100
changeset 136 f35f853a52b6
parent 135 a4755a42af19
child 137 c94a7ce0f4fb
Simplified and debugged the filter logic.
xmpp/filter.go
xmpp/filter_test.go
--- a/xmpp/filter.go	Mon Sep 09 02:13:07 2013 +0100
+++ b/xmpp/filter.go	Mon Sep 09 04:16:16 2013 +0100
@@ -7,31 +7,21 @@
 // the top of the stack. Receive stanzas at the bottom of the stack on
 // input. Send stanzas out the top of the stack on output.
 func filterMgr(filterAdd <-chan Filter, input <-chan Stanza, output chan<- Stanza) {
-	botFiltIn := output
-	topFiltOut := input
-
-loop:
+	defer close(output)
 	for {
 		select {
 		case stan, ok := <-input:
 			if !ok {
-				break loop
-			}
-			botFiltIn <- stan
-
-		case stan, ok := <-topFiltOut:
-			if !ok {
-				break loop
+				return
 			}
 			output <- stan
 
 		case filt := <-filterAdd:
-			newTop := make(chan Stanza)
-			go filt(topFiltOut, newTop)
-			topFiltOut = newTop
+			ch := make(chan Stanza)
+			go filt(input, ch)
+			input = ch
 		}
 	}
-	close(botFiltIn)
 }
 
 // AddRecvFilter adds a new filter to the top of the stack through which
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmpp/filter_test.go	Mon Sep 09 04:16:16 2013 +0100
@@ -0,0 +1,67 @@
+package xmpp
+
+import (
+	"fmt"
+	"strconv"
+	"testing"
+)
+
+func TestCloseIn(t *testing.T) {
+	add := make(chan Filter)
+	in := make(chan Stanza)
+	out := make(chan Stanza)
+	go filterMgr(add, in, out)
+	close(in)
+	_, ok := <-out
+	if ok {
+		fmt.Errorf("out didn't close")
+	}
+}
+
+func passthru(in <-chan Stanza, out chan<- Stanza) {
+	defer close(out)
+	for stan := range in {
+		out <- stan
+	}
+}
+
+func TestFilters(t *testing.T) {
+	for n := 0; n < 10; n++ {
+		filterN(n, t)
+	}
+}
+
+func filterN(numFilts int, t *testing.T) {
+	add := make(chan Filter)
+	in := make(chan Stanza)
+	out := make(chan Stanza)
+	go filterMgr(add, in, out)
+	for i := 0; i < numFilts; i++ {
+		add <- passthru
+	}
+	go func() {
+		for i := 0; i < 100; i++ {
+			msg := Message{}
+			msg.Id = fmt.Sprintf("%d", i)
+			in <- &msg
+		}
+	}()
+	for i := 0; i < 100; i++ {
+		stan := <-out
+		msg, ok := stan.(*Message)
+		if !ok {
+			t.Errorf("N = %d: msg %d not a Message: %#v", numFilts,
+				i, stan)
+			continue
+		}
+		n, err := strconv.Atoi(msg.Header.Id)
+		if err != nil {
+			t.Errorf("N = %d: msg %d parsing ID '%s': %v", numFilts,
+				i, msg.Header.Id, err)
+			continue
+		}
+		if n != i {
+			t.Errorf("N = %d: msg %d wrong id %d", numFilts, i, n)
+		}
+	}
+}