mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-14 05:11:19 -04:00
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:
parent
dccc15a6e9
commit
42e16021c4
1 changed files with 93 additions and 43 deletions
|
@ -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")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue