github.com/MontFerret/ferret@v0.18.0/pkg/drivers/cdp/events/stream_test.go (about)

     1  package events_test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/mafredri/cdp/rpcc"
     9  	"github.com/pkg/errors"
    10  	"github.com/stretchr/testify/mock"
    11  
    12  	events2 "github.com/MontFerret/ferret/pkg/drivers/cdp/events"
    13  	"github.com/MontFerret/ferret/pkg/runtime/core"
    14  	"github.com/MontFerret/ferret/pkg/runtime/events"
    15  	"github.com/MontFerret/ferret/pkg/runtime/values"
    16  
    17  	. "github.com/smartystreets/goconvey/convey"
    18  )
    19  
    20  type (
    21  	TestStream struct {
    22  		mock.Mock
    23  		ready   chan struct{}
    24  		message chan events.Message
    25  	}
    26  )
    27  
    28  func NewTestStream() *TestStream {
    29  	return NewBufferedTestStream(0)
    30  }
    31  
    32  func NewBufferedTestStream(buffer int) *TestStream {
    33  	es := new(TestStream)
    34  	es.ready = make(chan struct{}, buffer)
    35  	es.message = make(chan events.Message, buffer)
    36  	return es
    37  }
    38  
    39  func (ts *TestStream) Ready() <-chan struct{} {
    40  	return ts.ready
    41  }
    42  
    43  func (ts *TestStream) RecvMsg(m interface{}) error {
    44  	return nil
    45  }
    46  
    47  func (ts *TestStream) Close() error {
    48  	ts.Called()
    49  	close(ts.message)
    50  	close(ts.ready)
    51  	return nil
    52  }
    53  
    54  func (ts *TestStream) Emit(val core.Value) {
    55  	ts.ready <- struct{}{}
    56  	ts.message <- events.WithValue(val)
    57  }
    58  
    59  func (ts *TestStream) EmitError(err error) {
    60  	ts.ready <- struct{}{}
    61  	ts.message <- events.WithErr(err)
    62  }
    63  
    64  func (ts *TestStream) Recv() (core.Value, error) {
    65  	msg := <-ts.message
    66  
    67  	return msg.Value(), msg.Err()
    68  }
    69  
    70  func TestStreamReader(t *testing.T) {
    71  	Convey("StreamReader", t, func() {
    72  		Convey("Should read data from Stream", func() {
    73  			ctx, cancel := context.WithCancel(context.Background())
    74  
    75  			stream := NewTestStream()
    76  			stream.On("Close", mock.Anything).Maybe().Return(nil)
    77  
    78  			go func() {
    79  				stream.Emit(values.NewString("foo"))
    80  				stream.Emit(values.NewString("bar"))
    81  				stream.Emit(values.NewString("baz"))
    82  				cancel()
    83  			}()
    84  
    85  			data := make([]string, 0, 3)
    86  
    87  			es := events2.NewEventStream(stream, func(_ context.Context, stream rpcc.Stream) (core.Value, error) {
    88  				return stream.(*TestStream).Recv()
    89  			})
    90  
    91  			for evt := range es.Read(ctx) {
    92  				So(evt.Err(), ShouldBeNil)
    93  				So(evt.Value(), ShouldNotBeNil)
    94  
    95  				data = append(data, evt.Value().String())
    96  			}
    97  
    98  			So(data, ShouldResemble, []string{"foo", "bar", "baz"})
    99  
   100  			stream.AssertExpectations(t)
   101  
   102  			So(es.Close(context.Background()), ShouldBeNil)
   103  		})
   104  
   105  		Convey("Should handle error but do not close Stream", func() {
   106  			ctx := context.Background()
   107  
   108  			stream := NewTestStream()
   109  			stream.On("Close", mock.Anything).Maybe().Return(nil)
   110  
   111  			go func() {
   112  				stream.EmitError(errors.New("foo"))
   113  			}()
   114  
   115  			reader := events2.NewEventStream(stream, func(_ context.Context, stream rpcc.Stream) (core.Value, error) {
   116  				return stream.(*TestStream).Recv()
   117  			})
   118  
   119  			ch := reader.Read(ctx)
   120  			evt := <-ch
   121  			So(evt.Err(), ShouldNotBeNil)
   122  
   123  			time.Sleep(time.Duration(100) * time.Millisecond)
   124  
   125  			stream.AssertExpectations(t)
   126  		})
   127  
   128  		Convey("Should not close Stream when Context is cancelled", func() {
   129  			stream := NewTestStream()
   130  			stream.On("Close", mock.Anything).Maybe().Return(nil)
   131  
   132  			reader := events2.NewEventStream(stream, func(_ context.Context, stream rpcc.Stream) (core.Value, error) {
   133  				return values.EmptyArray(), nil
   134  			})
   135  
   136  			ctx, cancel := context.WithCancel(context.Background())
   137  
   138  			_ = reader.Read(ctx)
   139  
   140  			time.Sleep(time.Duration(100) * time.Millisecond)
   141  
   142  			cancel()
   143  
   144  			time.Sleep(time.Duration(100) * time.Millisecond)
   145  
   146  			stream.AssertExpectations(t)
   147  		})
   148  	})
   149  }