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
3f3635b056
commit
3059a16559
2
Makefile
2
Makefile
@ -13,7 +13,7 @@ generate:
|
|||||||
vet: fmt
|
vet: fmt
|
||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
||||||
test:
|
test: build
|
||||||
go test -count=1 -v ./...
|
go test -count=1 -v ./...
|
||||||
|
|
||||||
build: generate vet
|
build: generate vet
|
||||||
|
@ -2,6 +2,7 @@ package iowrappers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
@ -28,17 +29,16 @@ func NewChannelReadWriter(ctx context.Context, receiver <-chan []byte,
|
|||||||
func (rw *ChannelReadWriter) Read(p []byte) (n int, err error) {
|
func (rw *ChannelReadWriter) Read(p []byte) (n int, err error) {
|
||||||
nread := copy(p, rw.readBuf)
|
nread := copy(p, rw.readBuf)
|
||||||
if nread > 0 {
|
if nread > 0 {
|
||||||
|
log.Printf("Read %v bytes", nread)
|
||||||
rw.readBuf = rw.readBuf[nread:]
|
rw.readBuf = rw.readBuf[nread:]
|
||||||
return nread, nil
|
return nread, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-rw.ctx.Done():
|
case <-rw.ctx.Done():
|
||||||
log.Println("Context was canceled")
|
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
case data, ok := <-rw.receiver:
|
case data, ok := <-rw.receiver:
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Println("Channel closed")
|
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
}
|
}
|
||||||
nread = copy(p, data)
|
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) {
|
func (rw *ChannelReadWriter) Write(p []byte) (n int, err error) {
|
||||||
|
if rw.closed {
|
||||||
|
return 0, errors.New("Write on closed channel")
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-rw.ctx.Done():
|
case <-rw.ctx.Done():
|
||||||
|
rw.Close()
|
||||||
return 0, io.EOF
|
return 0, io.EOF
|
||||||
case rw.sender <- p:
|
case rw.sender <- p:
|
||||||
}
|
}
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *ChannelReadWriter) Close() error {
|
func (rw *ChannelReadWriter) Close() error {
|
||||||
if !rw.closed {
|
if !rw.closed {
|
||||||
close(rw.sender)
|
close(rw.sender)
|
||||||
|
@ -35,7 +35,6 @@ func (suite *ChannelReadWriterTestSuite) createChannel() {
|
|||||||
timeoutCancelFunc()
|
timeoutCancelFunc()
|
||||||
cancelFunc()
|
cancelFunc()
|
||||||
}
|
}
|
||||||
suite.cancelFunc = cancelFunc
|
|
||||||
suite.conn = NewChannelReadWriter(ctx, toChannel, fromChannel)
|
suite.conn = NewChannelReadWriter(ctx, toChannel, fromChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,47 +48,77 @@ func (suite *ChannelReadWriterTestSuite) TearDownTest() {
|
|||||||
|
|
||||||
type TestFunc func() any
|
type TestFunc func() any
|
||||||
|
|
||||||
func runAndWait(functions ...TestFunc) []any {
|
func (suite *ChannelReadWriterTestSuite) runAndWait(functions ...TestFunc) []any {
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(len(functions))
|
wg.Add(len(functions))
|
||||||
res := make([]any, len(functions))
|
res := make([]any, len(functions))
|
||||||
for i, function := range functions {
|
for i, function := range functions {
|
||||||
go func() {
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
res[i] = function()
|
res[i] = function()
|
||||||
wg.Done()
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ChannelReadWriterTestSuite) Test_SlicesLargeEnough() {
|
func (suite *ChannelReadWriterTestSuite) Test_SuccessfulCommunication() {
|
||||||
requires := suite.Require()
|
tests := []struct {
|
||||||
data := []byte("hello")
|
name string
|
||||||
|
data string
|
||||||
runAndWait(
|
chunkSizes []int
|
||||||
func() any {
|
chunks []string
|
||||||
suite.toChannel <- data
|
}{
|
||||||
log.Println("data sent")
|
{
|
||||||
return nil
|
name: "buffer_large_enough",
|
||||||
|
data: "hello",
|
||||||
|
chunkSizes: []int{10},
|
||||||
|
chunks: []string{"hello"},
|
||||||
},
|
},
|
||||||
func() any {
|
{
|
||||||
buf := make([]byte, len(data)*2)
|
name: "two_reads_required",
|
||||||
n, err := suite.conn.Read(buf)
|
data: "hello",
|
||||||
requires.Nil(err)
|
chunkSizes: []int{3, 10},
|
||||||
requires.Equal(n, len(data))
|
chunks: []string{"hel", "lo"},
|
||||||
requires.Equal(data, buf[:n])
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
)
|
{
|
||||||
}
|
name: "many_reads_required",
|
||||||
|
data: "hello",
|
||||||
|
chunkSizes: []int{1, 1, 1, 1, 1},
|
||||||
|
chunks: []string{"h", "e", "l", "l", "o"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *ChannelReadWriterTestSuite) Test_SliceTooSmallFullReadInTwoParts() {
|
for _, test := range tests {
|
||||||
suite.FailNow("todo")
|
suite.Run(test.name, func() {
|
||||||
}
|
suite.runAndWait(
|
||||||
|
func() any {
|
||||||
|
select {
|
||||||
|
case <-suite.ctx.Done():
|
||||||
|
suite.FailNow("deadline reached")
|
||||||
|
log.Println("Write deadline exceeded")
|
||||||
|
case suite.toChannel <- []byte(test.data):
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
func() any {
|
||||||
|
remainder := test.data
|
||||||
|
for i, chunkSize := range test.chunkSizes {
|
||||||
|
buf := make([]byte, chunkSize)
|
||||||
|
n, err := suite.conn.Read(buf)
|
||||||
|
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_SliceTooSmallFullREadInManyParts() {
|
|
||||||
suite.FailNow("todo")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ChannelReadWriterTestSuite) Test_Close() {
|
func (suite *ChannelReadWriterTestSuite) Test_Close() {
|
||||||
|
Loading…
Reference in New Issue
Block a user