[tor-commits] [snowflake/master] End-to-end Goconvey test for Broker passing SDP messages between concurrent client and proxy
arlo at torproject.org
arlo at torproject.org
Mon Feb 15 20:45:41 UTC 2016
commit 254223be0f7372669a5d42c6ed1bcf1cc559546b
Author: Serene Han <keroserene+git at gmail.com>
Date: Mon Feb 15 12:23:35 2016 -0800
End-to-end Goconvey test for Broker passing SDP messages between concurrent client and proxy
request handlers
---
broker/broker.go | 16 +++++-----
broker/snowflake-broker_test.go | 66 ++++++++++++++++++++++++++++++++++++-----
2 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/broker/broker.go b/broker/broker.go
index 7c14f63..69b8369 100644
--- a/broker/broker.go
+++ b/broker/broker.go
@@ -28,17 +28,17 @@ type BrokerContext struct {
snowflakes *SnowflakeHeap
// Map keeping track of snowflakeIDs required to match SDP answers from
// the second http POST.
- snowflakeMap map[string]*Snowflake
- createChan chan *ProxyRequest
+ snowflakeMap map[string]*Snowflake
+ createChannel chan *ProxyRequest
}
func NewBrokerContext() *BrokerContext {
snowflakes := new(SnowflakeHeap)
heap.Init(snowflakes)
return &BrokerContext{
- snowflakes: snowflakes,
- snowflakeMap: make(map[string]*Snowflake),
- createChan: make(chan *ProxyRequest),
+ snowflakes: snowflakes,
+ snowflakeMap: make(map[string]*Snowflake),
+ createChannel: make(chan *ProxyRequest),
}
}
@@ -72,7 +72,7 @@ func (sc *BrokerContext) AddSnowflake(id string) *Snowflake {
// func (ctx *BrokerContext) Broker(proxies <-chan *ProxyRequest) {
func (ctx *BrokerContext) Broker() {
// for p := range proxies {
- for p := range ctx.createChan {
+ for p := range ctx.createChannel {
snowflake := ctx.AddSnowflake(p.id)
// Wait for a client to avail an offer to the snowflake, or timeout
// and ask the snowflake to poll later.
@@ -131,7 +131,7 @@ func clientHandler(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Headers", "X-Session-ID")
// Find the most available snowflake proxy, and pass the offer to it.
- // TODO: Needs improvement - maybe shouldn'
+ // TODO: Needs improvement - maybe shouldn't immediately fail?
if ctx.snowflakes.Len() <= 0 {
log.Println("Client: No snowflake proxies available.")
w.WriteHeader(http.StatusServiceUnavailable)
@@ -178,7 +178,7 @@ func proxyHandler(ctx *BrokerContext, w http.ResponseWriter, r *http.Request) {
p := new(ProxyRequest)
p.id = id
p.offerChan = make(chan []byte)
- ctx.createChan <- p
+ ctx.createChannel <- p
// Wait for a client to avail an offer to the snowflake, or timeout
// and ask the snowflake to poll later.
diff --git a/broker/snowflake-broker_test.go b/broker/snowflake-broker_test.go
index 06d2316..ee984b0 100644
--- a/broker/snowflake-broker_test.go
+++ b/broker/snowflake-broker_test.go
@@ -7,7 +7,6 @@ import (
"net/http"
"net/http/httptest"
"testing"
- "fmt"
)
func TestBroker(t *testing.T) {
@@ -84,7 +83,7 @@ func TestBroker(t *testing.T) {
done <- true
}(ctx)
// Pass a fake client offer to this proxy
- p := <-ctx.createChan
+ p := <-ctx.createChannel
So(p.id, ShouldEqual, "test")
p.offerChan <- []byte("fake offer")
<-done
@@ -97,7 +96,7 @@ func TestBroker(t *testing.T) {
proxyHandler(ctx, w, r)
done <- true
}(ctx)
- p := <-ctx.createChan
+ p := <-ctx.createChannel
So(p.id, ShouldEqual, "test")
// nil means timeout
p.offerChan <- nil
@@ -107,10 +106,10 @@ func TestBroker(t *testing.T) {
})
})
- Convey("Responds to proxy answers...", func() {
+ Convey("Responds to proxy answers...", func() {
+ s := ctx.AddSnowflake("test")
w := httptest.NewRecorder()
data := bytes.NewReader([]byte("fake answer"))
- s := ctx.AddSnowflake("test")
Convey("by passing to the client if valid.", func() {
r, err := http.NewRequest("POST", "snowflake.broker/answer", data)
@@ -119,7 +118,7 @@ func TestBroker(t *testing.T) {
go func(ctx *BrokerContext) {
answerHandler(ctx, w, r)
}(ctx)
- answer := <- s.answerChannel
+ answer := <-s.answerChannel
So(w.Code, ShouldEqual, http.StatusOK)
So(answer, ShouldResemble, []byte("fake answer"))
})
@@ -130,7 +129,6 @@ func TestBroker(t *testing.T) {
r.Header.Set("X-Session-ID", "invalid")
answerHandler(ctx, w, r)
So(w.Code, ShouldEqual, http.StatusGone)
- fmt.Println("omg")
})
Convey("with error if the proxy gives invalid answer", func() {
@@ -141,9 +139,61 @@ func TestBroker(t *testing.T) {
answerHandler(ctx, w, r)
So(w.Code, ShouldEqual, http.StatusBadRequest)
})
-
})
+ })
+
+ Convey("End-To-End", t, func() {
+ done := make(chan bool)
+ polled := make(chan bool)
+ ctx := NewBrokerContext()
+ // Proxy polls with its ID first...
+ dataP := bytes.NewReader([]byte("test"))
+ wP := httptest.NewRecorder()
+ rP, err := http.NewRequest("POST", "snowflake.broker/proxy", dataP)
+ So(err, ShouldBeNil)
+ rP.Header.Set("X-Session-ID", "test")
+ go func() {
+ proxyHandler(ctx, wP, rP)
+ polled <- true
+ }()
+
+ // Manually do the Broker goroutine action here for full control.
+ p := <-ctx.createChannel
+ So(p.id, ShouldEqual, "test")
+ s := ctx.AddSnowflake(p.id)
+ go func() {
+ offer := <-s.offerChannel
+ p.offerChan <- offer
+ }()
+ So(ctx.snowflakeMap["test"], ShouldNotBeNil)
+
+ // Client request blocks until proxy answer arrives.
+ dataC := bytes.NewReader([]byte("fake offer"))
+ wC := httptest.NewRecorder()
+ rC, err := http.NewRequest("POST", "snowflake.broker/client", dataC)
+ So(err, ShouldBeNil)
+ go func() {
+ clientHandler(ctx, wC, rC)
+ done <- true
+ }()
+
+ <-polled
+ So(wP.Code, ShouldEqual, http.StatusOK)
+ So(wP.Body.String(), ShouldResemble, "fake offer")
+ So(ctx.snowflakeMap["test"], ShouldNotBeNil)
+ // Follow up with the answer request afterwards
+ wA := httptest.NewRecorder()
+ dataA := bytes.NewReader([]byte("fake answer"))
+ rA, err := http.NewRequest("POST", "snowflake.broker/proxy", dataA)
+ So(err, ShouldBeNil)
+ rA.Header.Set("X-Session-ID", "test")
+ answerHandler(ctx, wA, rA)
+ So(wA.Code, ShouldEqual, http.StatusOK)
+
+ <-done
+ So(wC.Code, ShouldEqual, http.StatusOK)
+ So(wC.Body.String(), ShouldEqual, "fake answer")
})
}
More information about the tor-commits
mailing list