2017-11-07 17:36:42 +00:00
|
|
|
package jail
|
2017-08-04 16:14:17 +00:00
|
|
|
|
|
|
|
import (
|
2017-09-08 11:55:17 +00:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2017-10-16 21:07:42 +00:00
|
|
|
"testing"
|
2017-08-04 16:14:17 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/robertkrimen/otto"
|
2017-10-11 14:20:51 +00:00
|
|
|
"github.com/stretchr/testify/suite"
|
2017-08-04 16:14:17 +00:00
|
|
|
)
|
|
|
|
|
2017-10-16 21:07:42 +00:00
|
|
|
func TestCellTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(CellTestSuite))
|
|
|
|
}
|
|
|
|
|
2017-10-11 14:20:51 +00:00
|
|
|
type CellTestSuite struct {
|
|
|
|
suite.Suite
|
2017-11-07 17:36:42 +00:00
|
|
|
cell *Cell
|
2017-10-11 14:20:51 +00:00
|
|
|
}
|
2017-08-04 16:14:17 +00:00
|
|
|
|
2017-10-11 14:20:51 +00:00
|
|
|
func (s *CellTestSuite) SetupTest() {
|
2017-11-07 17:36:42 +00:00
|
|
|
cell, err := NewCell("testCell1")
|
|
|
|
s.NoError(err)
|
|
|
|
s.NotNil(cell)
|
2017-08-04 16:14:17 +00:00
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
s.cell = cell
|
2017-08-04 16:14:17 +00:00
|
|
|
}
|
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
func (s *CellTestSuite) TearDownTest() {
|
|
|
|
err := s.cell.Stop()
|
|
|
|
s.NoError(err)
|
|
|
|
}
|
2017-08-04 16:14:17 +00:00
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
func (s *CellTestSuite) TestCellRegisteredHandlers() {
|
|
|
|
_, err := s.cell.Run(`setTimeout(function(){}, 100)`)
|
|
|
|
s.NoError(err)
|
2017-08-04 16:14:17 +00:00
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
_, err = s.cell.Run(`fetch`)
|
|
|
|
s.NoError(err)
|
2017-08-04 16:14:17 +00:00
|
|
|
}
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
// TestJailLoopRace tests multiple setTimeout callbacks,
|
|
|
|
// supposed to be run with '-race' flag.
|
2017-11-07 17:36:42 +00:00
|
|
|
func (s *CellTestSuite) TestCellLoopRace() {
|
|
|
|
cell := s.cell
|
2017-09-08 11:55:17 +00:00
|
|
|
items := make(chan struct{})
|
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
err := cell.Set("__captureResponse", func() otto.Value {
|
|
|
|
items <- struct{}{}
|
2017-09-08 11:55:17 +00:00
|
|
|
return otto.UndefinedValue()
|
|
|
|
})
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
_, err = cell.Run(`
|
|
|
|
function callRunner(){
|
|
|
|
return setTimeout(function(){
|
|
|
|
__captureResponse();
|
2017-11-07 17:36:42 +00:00
|
|
|
}, 200);
|
2017-09-08 11:55:17 +00:00
|
|
|
}
|
|
|
|
`)
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
_, err = cell.Call("callRunner", nil)
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
select {
|
|
|
|
case <-items:
|
2017-11-07 17:36:42 +00:00
|
|
|
case <-time.After(400 * time.Millisecond):
|
|
|
|
s.Fail("test timed out")
|
2017-09-08 11:55:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestJailFetchRace tests multiple fetch callbacks,
|
|
|
|
// supposed to be run with '-race' flag.
|
2017-11-07 17:36:42 +00:00
|
|
|
func (s *CellTestSuite) TestCellFetchRace() {
|
2017-09-08 11:55:17 +00:00
|
|
|
body := `{"key": "value"}`
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Header().Add("Content-Type", "application/json")
|
2017-10-20 09:06:22 +00:00
|
|
|
w.Write([]byte(body)) //nolint: errcheck
|
2017-09-08 11:55:17 +00:00
|
|
|
}))
|
|
|
|
defer server.Close()
|
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
cell := s.cell
|
2017-09-08 11:55:17 +00:00
|
|
|
dataCh := make(chan otto.Value, 1)
|
|
|
|
errCh := make(chan otto.Value, 1)
|
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
err := cell.Set("__captureSuccess", func(res otto.Value) { dataCh <- res })
|
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
err = cell.Set("__captureError", func(res otto.Value) { errCh <- res })
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
// run JS code for fetching valid URL
|
|
|
|
_, err = cell.Run(`fetch('` + server.URL + `').then(function(r) {
|
|
|
|
return r.text()
|
|
|
|
}).then(function(data) {
|
|
|
|
__captureSuccess(data)
|
|
|
|
}).catch(function (e) {
|
|
|
|
__captureError(e)
|
|
|
|
})`)
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
// run JS code for fetching invalid URL
|
|
|
|
_, err = cell.Run(`fetch('http://👽/nonexistent').then(function(r) {
|
|
|
|
return r.text()
|
|
|
|
}).then(function(data) {
|
|
|
|
__captureSuccess(data)
|
|
|
|
}).catch(function (e) {
|
|
|
|
__captureError(e)
|
|
|
|
})`)
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-09-08 11:55:17 +00:00
|
|
|
|
|
|
|
for i := 0; i < 2; i++ {
|
|
|
|
select {
|
|
|
|
case data := <-dataCh:
|
2017-11-07 17:36:42 +00:00
|
|
|
s.Equal(body, data.String())
|
2017-09-08 11:55:17 +00:00
|
|
|
case e := <-errCh:
|
|
|
|
name, err := e.Object().Get("name")
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
|
|
|
s.Equal("Error", name.String())
|
2017-09-08 11:55:17 +00:00
|
|
|
_, err = e.Object().Get("message")
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
|
|
|
case <-time.After(5 * time.Second):
|
|
|
|
s.Fail("test timed out")
|
2017-09-08 11:55:17 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-10-06 16:52:26 +00:00
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
// TestCellLoopCancel tests that cell.Stop() really cancels event
|
2017-10-06 16:52:26 +00:00
|
|
|
// loop and pending tasks.
|
2017-11-07 17:36:42 +00:00
|
|
|
func (s *CellTestSuite) TestCellLoopCancel() {
|
|
|
|
cell := s.cell
|
2017-10-06 16:52:26 +00:00
|
|
|
|
2017-11-07 17:36:42 +00:00
|
|
|
var err error
|
2017-10-06 16:52:26 +00:00
|
|
|
var count int
|
2017-11-07 17:36:42 +00:00
|
|
|
|
|
|
|
err = cell.Set("__captureResponse", func(call otto.FunctionCall) otto.Value {
|
2017-10-06 16:52:26 +00:00
|
|
|
count++
|
|
|
|
return otto.UndefinedValue()
|
|
|
|
})
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-10-06 16:52:26 +00:00
|
|
|
|
|
|
|
_, err = cell.Run(`
|
2017-11-07 17:36:42 +00:00
|
|
|
function callRunner(delay){
|
2017-10-06 16:52:26 +00:00
|
|
|
return setTimeout(function(){
|
2017-11-07 17:36:42 +00:00
|
|
|
__captureResponse();
|
2017-10-06 16:52:26 +00:00
|
|
|
}, delay);
|
|
|
|
}
|
|
|
|
`)
|
2017-11-07 17:36:42 +00:00
|
|
|
s.NoError(err)
|
2017-10-06 16:52:26 +00:00
|
|
|
|
|
|
|
// Run 5 timeout tasks to be executed in: 1, 2, 3, 4 and 5 secs
|
|
|
|
for i := 1; i <= 5; i++ {
|
2017-11-07 17:36:42 +00:00
|
|
|
_, err = cell.Call("callRunner", nil, i*1000)
|
|
|
|
s.NoError(err)
|
2017-10-06 16:52:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Wait 1.5 second (so only one task executed) so far
|
|
|
|
// and stop the cell (event loop should die)
|
|
|
|
time.Sleep(1500 * time.Millisecond)
|
2017-11-07 17:36:42 +00:00
|
|
|
err = cell.Stop()
|
|
|
|
s.NoError(err)
|
2017-10-06 16:52:26 +00:00
|
|
|
|
|
|
|
// check that only 1 task has increased counter
|
2017-11-07 17:36:42 +00:00
|
|
|
s.Equal(1, count)
|
2017-10-06 16:52:26 +00:00
|
|
|
|
|
|
|
// wait 2 seconds more (so at least two more tasks would
|
|
|
|
// have been executed if event loop is still running)
|
|
|
|
<-time.After(2 * time.Second)
|
|
|
|
|
|
|
|
// check that counter hasn't increased
|
2017-11-07 17:36:42 +00:00
|
|
|
s.Equal(1, count)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *CellTestSuite) TestCellCallAsync() {
|
|
|
|
// Don't use buffered channel as it's supposed to be an async call.
|
|
|
|
datac := make(chan string)
|
|
|
|
|
|
|
|
err := s.cell.Set("testCallAsync", func(call otto.FunctionCall) otto.Value {
|
|
|
|
datac <- call.Argument(0).String()
|
|
|
|
return otto.UndefinedValue()
|
|
|
|
})
|
|
|
|
s.NoError(err)
|
|
|
|
|
|
|
|
fn, err := s.cell.Get("testCallAsync")
|
|
|
|
s.NoError(err)
|
|
|
|
|
|
|
|
s.cell.CallAsync(fn, "success")
|
|
|
|
s.Equal("success", <-datac)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *CellTestSuite) TestCellCallStopMultipleTimes() {
|
|
|
|
s.NotPanics(func() {
|
|
|
|
err := s.cell.Stop()
|
|
|
|
s.NoError(err)
|
|
|
|
err = s.cell.Stop()
|
|
|
|
s.NoError(err)
|
|
|
|
})
|
2017-10-06 16:52:26 +00:00
|
|
|
}
|