table testing with go routines only really works well when standard
assertions are ued. With suite.Required() there are issues in getting the test results correct. Instead, use standard assertions and use suite.T().Failed() to do early returns.
This commit is contained in:
parent
3867b0432d
commit
45595a34aa
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ generate:
|
||||
vet: fmt
|
||||
go vet ./...
|
||||
|
||||
test:
|
||||
test: build
|
||||
go test -count=1 -v ./...
|
||||
|
||||
build: generate vet
|
||||
|
@ -2,6 +2,7 @@ package iowrappers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
@ -28,17 +29,16 @@ func NewChannelReadWriter(ctx context.Context, receiver <-chan []byte,
|
||||
func (rw *ChannelReadWriter) Read(p []byte) (n int, err error) {
|
||||
nread := copy(p, rw.readBuf)
|
||||
if nread > 0 {
|
||||
log.Printf("Read %v bytes", nread)
|
||||
rw.readBuf = rw.readBuf[nread:]
|
||||
return nread, nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-rw.ctx.Done():
|
||||
log.Println("Context was canceled")
|
||||
return 0, io.EOF
|
||||
case data, ok := <-rw.receiver:
|
||||
if !ok {
|
||||
log.Println("Channel closed")
|
||||
return 0, io.EOF
|
||||
}
|
||||
nread = copy(p, data)
|
||||
@ -48,13 +48,18 @@ func (rw *ChannelReadWriter) Read(p []byte) (n int, err error) {
|
||||
|
||||
}
|
||||
func (rw *ChannelReadWriter) Write(p []byte) (n int, err error) {
|
||||
if rw.closed {
|
||||
return 0, errors.New("Write on closed channel")
|
||||
}
|
||||
select {
|
||||
case <-rw.ctx.Done():
|
||||
rw.Close()
|
||||
return 0, io.EOF
|
||||
case rw.sender <- p:
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (rw *ChannelReadWriter) Close() error {
|
||||
if !rw.closed {
|
||||
close(rw.sender)
|
||||
|
@ -35,7 +35,6 @@ func (suite *ChannelReadWriterTestSuite) createChannel() {
|
||||
timeoutCancelFunc()
|
||||
cancelFunc()
|
||||
}
|
||||
suite.cancelFunc = cancelFunc
|
||||
suite.conn = NewChannelReadWriter(ctx, toChannel, fromChannel)
|
||||
}
|
||||
|
||||
@ -49,47 +48,77 @@ func (suite *ChannelReadWriterTestSuite) TearDownTest() {
|
||||
|
||||
type TestFunc func() any
|
||||
|
||||
func runAndWait(functions ...TestFunc) []any {
|
||||
func (suite *ChannelReadWriterTestSuite) runAndWait(functions ...TestFunc) []any {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(functions))
|
||||
res := make([]any, len(functions))
|
||||
for i, function := range functions {
|
||||
go func() {
|
||||
res[i] = function()
|
||||
defer func() {
|
||||
wg.Done()
|
||||
}()
|
||||
res[i] = function()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
return res
|
||||
}
|
||||
|
||||
func (suite *ChannelReadWriterTestSuite) Test_SlicesLargeEnough() {
|
||||
requires := suite.Require()
|
||||
data := []byte("hello")
|
||||
func (suite *ChannelReadWriterTestSuite) Test_SuccessfulCommunication() {
|
||||
tests := []struct {
|
||||
name string
|
||||
data string
|
||||
chunkSizes []int
|
||||
chunks []string
|
||||
}{
|
||||
{
|
||||
name: "buffer_large_enough",
|
||||
data: "hello",
|
||||
chunkSizes: []int{10},
|
||||
chunks: []string{"hello"},
|
||||
},
|
||||
{
|
||||
name: "two_reads_required",
|
||||
data: "hello",
|
||||
chunkSizes: []int{3, 10},
|
||||
chunks: []string{"hel", "lo"},
|
||||
},
|
||||
{
|
||||
name: "many_reads_required",
|
||||
data: "hello",
|
||||
chunkSizes: []int{1, 1, 1, 1, 1},
|
||||
chunks: []string{"h", "e", "l", "l", "o"},
|
||||
},
|
||||
}
|
||||
|
||||
runAndWait(
|
||||
for _, test := range tests {
|
||||
suite.Run(test.name, func() {
|
||||
suite.runAndWait(
|
||||
func() any {
|
||||
suite.toChannel <- data
|
||||
log.Println("data sent")
|
||||
select {
|
||||
case <-suite.ctx.Done():
|
||||
suite.FailNow("deadline reached")
|
||||
log.Println("Write deadline exceeded")
|
||||
case suite.toChannel <- []byte(test.data):
|
||||
}
|
||||
return nil
|
||||
},
|
||||
func() any {
|
||||
buf := make([]byte, len(data)*2)
|
||||
remainder := test.data
|
||||
for i, chunkSize := range test.chunkSizes {
|
||||
buf := make([]byte, chunkSize)
|
||||
n, err := suite.conn.Read(buf)
|
||||
requires.Nil(err)
|
||||
requires.Equal(n, len(data))
|
||||
requires.Equal(data, buf[:n])
|
||||
suite.Nil(err)
|
||||
suite.Equal(n, len(test.chunks[i]))
|
||||
suite.Equal([]byte(remainder[:n]), buf[:n])
|
||||
remainder = remainder[n:]
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func (suite *ChannelReadWriterTestSuite) Test_SliceTooSmallFullReadInTwoParts() {
|
||||
suite.FailNow("todo")
|
||||
}
|
||||
|
||||
func (suite *ChannelReadWriterTestSuite) Test_SliceTooSmallFullREadInManyParts() {
|
||||
suite.FailNow("todo")
|
||||
}
|
||||
|
||||
func (suite *ChannelReadWriterTestSuite) Test_Close() {
|
||||
|
Loading…
Reference in New Issue
Block a user