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
 | 
					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