refactor(netxlite/iox): group tests and avoid races (#484)

Part of https://github.com/ooni/probe/issues/1591
This commit is contained in:
Simone Basso 2021-09-07 22:41:34 +02:00 committed by GitHub
parent 1472f7530b
commit 9e82e37ab8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,13 +5,14 @@ import (
"errors"
"io"
"strings"
"sync"
"testing"
"time"
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
)
func TestReadAllContextCommonCase(t *testing.T) {
func TestReadAllContext(t *testing.T) {
t.Run("with success and background context", func(t *testing.T) {
r := strings.NewReader("deadbeef")
ctx := context.Background()
out, err := ReadAllContext(ctx, r)
@ -21,9 +22,9 @@ func TestReadAllContextCommonCase(t *testing.T) {
if len(out) != 8 {
t.Fatal("not the expected number of bytes")
}
}
})
func TestReadAllContextWithError(t *testing.T) {
t.Run("with failure and background context", func(t *testing.T) {
expected := errors.New("mocked error")
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
@ -38,10 +39,26 @@ func TestReadAllContextWithError(t *testing.T) {
if len(out) != 0 {
t.Fatal("not the expected number of bytes")
}
}
})
func TestReadAllContextWithCancelledContext(t *testing.T) {
r := strings.NewReader("deadbeef")
t.Run("with success and cancelled context", func(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
sigch := make(chan interface{})
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
defer wg.Done()
<-sigch
// "When Read encounters an error or end-of-file condition
// after successfully reading n > 0 bytes, it returns
// the number of bytes read. It may return the (non-nil)
// error from the same call or return the error (and n == 0)
// from a subsequent call.""
//
// See https://pkg.go.dev/io#Reader
return len(b), io.EOF
},
}
ctx, cancel := context.WithCancel(context.Background())
cancel() // fail immediately
out, err := ReadAllContext(ctx, r)
@ -51,13 +68,19 @@ func TestReadAllContextWithCancelledContext(t *testing.T) {
if len(out) != 0 {
t.Fatal("not the expected number of bytes")
}
}
close(sigch)
wg.Wait()
})
func TestReadAllContextWithErrorAndCancelledContext(t *testing.T) {
t.Run("with failure and cancelled context", func(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
sigch := make(chan interface{})
expected := errors.New("mocked error")
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
time.Sleep(time.Millisecond)
defer wg.Done()
<-sigch
return 0, expected
},
}
@ -70,9 +93,13 @@ func TestReadAllContextWithErrorAndCancelledContext(t *testing.T) {
if len(out) != 0 {
t.Fatal("not the expected number of bytes")
}
close(sigch)
wg.Wait()
})
}
func TestCopyContextCommonCase(t *testing.T) {
func TestCopyContext(t *testing.T) {
t.Run("with success and background context", func(t *testing.T) {
r := strings.NewReader("deadbeef")
ctx := context.Background()
out, err := CopyContext(ctx, io.Discard, r)
@ -82,9 +109,9 @@ func TestCopyContextCommonCase(t *testing.T) {
if out != 8 {
t.Fatal("not the expected number of bytes")
}
}
})
func TestCopyContextWithError(t *testing.T) {
t.Run("with failure and background context", func(t *testing.T) {
expected := errors.New("mocked error")
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
@ -99,10 +126,26 @@ func TestCopyContextWithError(t *testing.T) {
if out != 0 {
t.Fatal("not the expected number of bytes")
}
}
})
func TestCopyContextWithCancelledContext(t *testing.T) {
r := strings.NewReader("deadbeef")
t.Run("with success and cancelled context", func(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
sigch := make(chan interface{})
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
defer wg.Done()
<-sigch
// "When Read encounters an error or end-of-file condition
// after successfully reading n > 0 bytes, it returns
// the number of bytes read. It may return the (non-nil)
// error from the same call or return the error (and n == 0)
// from a subsequent call.""
//
// See https://pkg.go.dev/io#Reader
return len(b), io.EOF
},
}
ctx, cancel := context.WithCancel(context.Background())
cancel() // fail immediately
out, err := CopyContext(ctx, io.Discard, r)
@ -112,13 +155,19 @@ func TestCopyContextWithCancelledContext(t *testing.T) {
if out != 0 {
t.Fatal("not the expected number of bytes")
}
}
close(sigch)
wg.Wait()
})
func TestCopyContextWithErrorAndCancelledContext(t *testing.T) {
t.Run("with failure and cancelled context", func(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(1)
sigch := make(chan interface{})
expected := errors.New("mocked error")
r := &mocks.Reader{
MockRead: func(b []byte) (int, error) {
time.Sleep(time.Millisecond)
defer wg.Done()
<-sigch
return 0, expected
},
}
@ -131,4 +180,7 @@ func TestCopyContextWithErrorAndCancelledContext(t *testing.T) {
if out != 0 {
t.Fatal("not the expected number of bytes")
}
close(sigch)
wg.Wait()
})
}