2017-12-28 20:50:36 +00:00
|
|
|
package loop
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2018-02-08 13:03:04 +00:00
|
|
|
"sync/atomic"
|
2017-12-28 20:50:36 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/status-im/status-go/geth/jail/internal/vm"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
|
|
)
|
|
|
|
|
|
|
|
// DummyTask is something that satisfies the loop.Task interface for testing.
|
|
|
|
type DummyTask struct {
|
2018-02-08 13:03:04 +00:00
|
|
|
canceled int32
|
|
|
|
executed int32
|
2017-12-28 20:50:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (*DummyTask) SetID(int64) {}
|
|
|
|
func (*DummyTask) GetID() int64 { return 1 }
|
2018-02-08 13:03:04 +00:00
|
|
|
func (d *DummyTask) Cancel() { atomic.StoreInt32(&d.canceled, 1) }
|
2017-12-28 20:50:36 +00:00
|
|
|
func (d *DummyTask) Execute(*vm.VM, *Loop) error {
|
2018-02-08 13:03:04 +00:00
|
|
|
atomic.StoreInt32(&d.executed, 1)
|
2017-12-28 20:50:36 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-02-08 13:03:04 +00:00
|
|
|
func (d *DummyTask) Canceled() bool {
|
|
|
|
return atomic.LoadInt32(&d.canceled) == 1
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *DummyTask) Executed() bool {
|
|
|
|
return atomic.LoadInt32(&d.executed) == 1
|
|
|
|
}
|
|
|
|
|
2017-12-28 20:50:36 +00:00
|
|
|
func TestLoopSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(LoopSuite))
|
|
|
|
}
|
|
|
|
|
|
|
|
type LoopSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
|
|
|
|
loop *Loop
|
|
|
|
cancel context.CancelFunc
|
|
|
|
|
|
|
|
task *DummyTask
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LoopSuite) SetupTest() {
|
|
|
|
s.task = &DummyTask{}
|
|
|
|
|
|
|
|
vm := vm.New()
|
|
|
|
s.loop = New(vm)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
s.cancel = cancel
|
2018-02-12 11:16:06 +00:00
|
|
|
go func() {
|
2018-02-21 12:18:32 +00:00
|
|
|
a := s.Assertions // Cache assertions reference as otherwise we'd incur in a race condition
|
2018-02-12 11:16:06 +00:00
|
|
|
err := s.loop.Run(ctx)
|
2018-02-21 12:18:32 +00:00
|
|
|
a.Equal(context.Canceled, err)
|
2018-02-12 11:16:06 +00:00
|
|
|
}()
|
2017-12-28 20:50:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LoopSuite) TestAddAndReady() {
|
|
|
|
|
|
|
|
err := s.loop.Add(s.task)
|
|
|
|
s.NoError(err)
|
2018-02-08 13:03:04 +00:00
|
|
|
s.False(s.task.Canceled())
|
2017-12-28 20:50:36 +00:00
|
|
|
|
|
|
|
err = s.loop.Ready(s.task)
|
|
|
|
s.NoError(err)
|
|
|
|
|
|
|
|
// Wait to process task
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
2018-02-08 13:03:04 +00:00
|
|
|
s.True(s.task.Executed())
|
2017-12-28 20:50:36 +00:00
|
|
|
|
|
|
|
s.cancel()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LoopSuite) TestLoopErrorWhenClosed() {
|
|
|
|
s.cancel()
|
|
|
|
|
|
|
|
// Wait for the context to cancel and loop to close
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
err := s.loop.Add(s.task)
|
|
|
|
s.Error(err)
|
|
|
|
|
|
|
|
err = s.loop.Ready(s.task)
|
|
|
|
s.Error(err)
|
2018-02-08 13:03:04 +00:00
|
|
|
s.True(s.task.Canceled())
|
2017-12-28 20:50:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LoopSuite) TestImmediateExecution() {
|
|
|
|
err := s.loop.AddAndExecute(s.task)
|
|
|
|
|
|
|
|
// Wait for the task to execute
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
s.NoError(err)
|
2018-02-08 13:03:04 +00:00
|
|
|
s.True(s.task.Executed())
|
|
|
|
s.False(s.task.Canceled())
|
2017-12-28 20:50:36 +00:00
|
|
|
|
|
|
|
s.cancel()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *LoopSuite) TestImmediateExecutionErrorWhenClosed() {
|
|
|
|
s.cancel()
|
|
|
|
|
|
|
|
// Wait for the context to cancel and loop to close
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
|
|
|
|
err := s.loop.AddAndExecute(s.task)
|
|
|
|
|
|
|
|
s.Error(err)
|
2018-02-08 13:03:04 +00:00
|
|
|
s.False(s.task.Executed())
|
2017-12-28 20:50:36 +00:00
|
|
|
|
|
|
|
}
|