Add tests to check for data race in broker

We had some data races in the broker that occur when proxies and clients
modify the heap/snowflake map at the same time. This test has a client
and proxy access the broker simultaneously to check for data races.
This commit is contained in:
Cecylia Bocovich 2019-11-25 14:00:54 -05:00
parent dccc15a6e9
commit 42e16021c4

View file

@ -191,58 +191,108 @@ func TestBroker(t *testing.T) {
}) })
}) })
}) })
Convey("End-To-End", t, func() { Convey("End-To-End", t, func() {
done := make(chan bool)
polled := make(chan bool)
ctx := NewBrokerContext(NullLogger()) ctx := NewBrokerContext(NullLogger())
// Proxy polls with its ID first... Convey("Check for client/proxy data race", func() {
dataP := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`)) proxy_done := make(chan bool)
wP := httptest.NewRecorder() client_done := make(chan bool)
rP, err := http.NewRequest("POST", "snowflake.broker/proxy", dataP)
So(err, ShouldBeNil)
go func() {
proxyPolls(ctx, wP, rP)
polled <- true
}()
// Manually do the Broker goroutine action here for full control. go ctx.Broker()
p := <-ctx.proxyPolls
So(p.id, ShouldEqual, "ymbcCMto7KHNGYlp")
s := ctx.AddSnowflake(p.id, "")
go func() {
offer := <-s.offerChannel
p.offerChannel <- offer
}()
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil)
// Client request blocks until proxy answer arrives. // Make proxy poll
dataC := bytes.NewReader([]byte("fake offer")) wp := httptest.NewRecorder()
wC := httptest.NewRecorder() datap := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
rC, err := http.NewRequest("POST", "snowflake.broker/client", dataC) rp, err := http.NewRequest("POST", "snowflake.broker/proxy", datap)
So(err, ShouldBeNil) So(err, ShouldBeNil)
go func() {
clientOffers(ctx, wC, rC)
done <- true
}()
<-polled go func(ctx *BrokerContext) {
So(wP.Code, ShouldEqual, http.StatusOK) proxyPolls(ctx, wp, rp)
So(wP.Body.String(), ShouldResemble, `{"Status":"client match","Offer":"fake offer"}`) proxy_done <- true
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil) }(ctx)
// Follow up with the answer request afterwards
wA := httptest.NewRecorder()
dataA := bytes.NewReader([]byte(`{"Version":"1.0","Sid":"ymbcCMto7KHNGYlp","Answer":"test"}`))
rA, err := http.NewRequest("POST", "snowflake.broker/answer", dataA)
So(err, ShouldBeNil)
proxyAnswers(ctx, wA, rA)
So(wA.Code, ShouldEqual, http.StatusOK)
<-done // Client offer
So(wC.Code, ShouldEqual, http.StatusOK) wc := httptest.NewRecorder()
So(wC.Body.String(), ShouldEqual, "test") datac := bytes.NewReader([]byte("test"))
rc, err := http.NewRequest("POST", "snowflake.broker/client", datac)
So(err, ShouldBeNil)
go func() {
clientOffers(ctx, wc, rc)
client_done <- true
}()
<-proxy_done
So(wp.Code, ShouldEqual, http.StatusOK)
// Proxy answers
wp = httptest.NewRecorder()
datap = bytes.NewReader([]byte(`{"Version":"1.0","Sid":"ymbcCMto7KHNGYlp","Answer":"test"}`))
rp, err = http.NewRequest("POST", "snowflake.broker/answer", datap)
So(err, ShouldBeNil)
go func(ctx *BrokerContext) {
proxyAnswers(ctx, wp, rp)
proxy_done <- true
}(ctx)
<-proxy_done
<-client_done
})
Convey("Ensure correct snowflake brokering", func() {
done := make(chan bool)
polled := make(chan bool)
// Proxy polls with its ID first...
dataP := bytes.NewReader([]byte(`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`))
wP := httptest.NewRecorder()
rP, err := http.NewRequest("POST", "snowflake.broker/proxy", dataP)
So(err, ShouldBeNil)
go func() {
proxyPolls(ctx, wP, rP)
polled <- true
}()
// Manually do the Broker goroutine action here for full control.
p := <-ctx.proxyPolls
So(p.id, ShouldEqual, "ymbcCMto7KHNGYlp")
s := ctx.AddSnowflake(p.id, "")
go func() {
offer := <-s.offerChannel
p.offerChannel <- offer
}()
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], 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() {
clientOffers(ctx, wC, rC)
done <- true
}()
<-polled
So(wP.Code, ShouldEqual, http.StatusOK)
So(wP.Body.String(), ShouldResemble, `{"Status":"client match","Offer":"fake offer"}`)
So(ctx.idToSnowflake["ymbcCMto7KHNGYlp"], ShouldNotBeNil)
// Follow up with the answer request afterwards
wA := httptest.NewRecorder()
dataA := bytes.NewReader([]byte(`{"Version":"1.0","Sid":"ymbcCMto7KHNGYlp","Answer":"test"}`))
rA, err := http.NewRequest("POST", "snowflake.broker/answer", dataA)
So(err, ShouldBeNil)
proxyAnswers(ctx, wA, rA)
So(wA.Code, ShouldEqual, http.StatusOK)
<-done
So(wC.Code, ShouldEqual, http.StatusOK)
So(wC.Body.String(), ShouldEqual, "test")
})
}) })
} }