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