refactor(tracex): convert to unit testing (#781)

The exercise already allowed me to notice issues such as fields not
being properly initialized by savers.

This is one of the last steps before moving tracex away from the
internal/netx package and into the internal package.

See https://github.com/ooni/probe/issues/2121
This commit is contained in:
Simone Basso 2022-06-01 23:15:47 +02:00 committed by GitHub
commit d397036073
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 1674 additions and 1111 deletions

View file

@ -12,127 +12,268 @@ import (
"github.com/ooni/probe-cli/v3/internal/netxlite"
)
func TestSaverDialerFailure(t *testing.T) {
expected := errors.New("mocked error")
func TestDialerConnectObserver(t *testing.T) {
saver := &Saver{}
dlr := &SaverDialer{
Dialer: &mocks.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return nil, expected
},
},
Saver: saver,
obs := &dialerConnectObserver{
saver: saver,
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if !errors.Is(err, expected) {
t.Fatal("expected another error here")
dialer := &mocks.Dialer{}
out := obs.WrapDialer(dialer)
dialSaver := out.(*DialerSaver)
if dialSaver.Dialer != dialer {
t.Fatal("invalid dialer")
}
if conn != nil {
t.Fatal("expected nil conn here")
}
ev := saver.Read()
if len(ev) != 1 {
t.Fatal("expected a single event here")
}
if ev[0].Value().Address != "www.google.com:443" {
t.Fatal("unexpected Address")
}
if ev[0].Value().Duration <= 0 {
t.Fatal("unexpected Duration")
}
if !errors.Is(ev[0].Value().Err, expected) {
t.Fatal("unexpected Err")
}
if ev[0].Name() != netxlite.ConnectOperation {
t.Fatal("unexpected Name")
}
if ev[0].Value().Proto != "tcp" {
t.Fatal("unexpected Proto")
}
if !ev[0].Value().Time.Before(time.Now()) {
t.Fatal("unexpected Time")
if dialSaver.Saver != saver {
t.Fatal("invalid saver")
}
}
func TestSaverConnDialerFailure(t *testing.T) {
expected := errors.New("mocked error")
saver := &Saver{}
dlr := &SaverConnDialer{
Dialer: &mocks.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return nil, expected
},
},
Saver: saver,
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
}
if conn != nil {
t.Fatal("expected nil conn here")
}
}
func TestSaverConnDialerSuccess(t *testing.T) {
saver := &Saver{}
dlr := &SaverConnDialer{
Dialer: &SaverDialer{
func TestDialerSaver(t *testing.T) {
t.Run("on failure", func(t *testing.T) {
expected := errors.New("mocked error")
saver := &Saver{}
dlr := &DialerSaver{
Dialer: &mocks.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return &mocks.Conn{
MockRead: func(b []byte) (int, error) {
return 0, io.EOF
},
MockWrite: func(b []byte) (int, error) {
return 0, io.EOF
},
MockClose: func() error {
return io.EOF
},
MockLocalAddr: func() net.Addr {
return &net.TCPAddr{Port: 12345}
},
}, nil
return nil, expected
},
},
Saver: saver,
},
Saver: saver,
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if err != nil {
t.Fatal("not the error we expected", err)
}
conn.Read(nil)
conn.Write(nil)
conn.Close()
events := saver.Read()
if len(events) != 3 {
t.Fatal("unexpected number of events saved", len(events))
}
if events[0].Name() != "connect" {
t.Fatal("expected a connect event")
}
saverCheckConnectEvent(t, &events[0])
if events[1].Name() != "read" {
t.Fatal("expected a read event")
}
saverCheckReadEvent(t, &events[1])
if events[2].Name() != "write" {
t.Fatal("expected a write event")
}
saverCheckWriteEvent(t, &events[2])
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if !errors.Is(err, expected) {
t.Fatal("expected another error here")
}
if conn != nil {
t.Fatal("expected nil conn here")
}
ev := saver.Read()
if len(ev) != 1 {
t.Fatal("expected a single event here")
}
if ev[0].Value().Address != "www.google.com:443" {
t.Fatal("unexpected Address")
}
if ev[0].Value().Duration <= 0 {
t.Fatal("unexpected Duration")
}
if !errors.Is(ev[0].Value().Err, expected) {
t.Fatal("unexpected Err")
}
if ev[0].Name() != netxlite.ConnectOperation {
t.Fatal("unexpected Name")
}
if ev[0].Value().Proto != "tcp" {
t.Fatal("unexpected Proto")
}
if !ev[0].Value().Time.Before(time.Now()) {
t.Fatal("unexpected Time")
}
})
t.Run("CloseIdleConnections", func(t *testing.T) {
var called bool
child := &mocks.Dialer{
MockCloseIdleConnections: func() {
called = true
},
}
dialer := &DialerSaver{
Dialer: child,
Saver: &Saver{},
}
dialer.CloseIdleConnections()
if !called {
t.Fatal("not called")
}
})
}
func saverCheckConnectEvent(t *testing.T, ev *Event) {
// TODO(bassosimone): implement
func TestDialerReadWriteObserver(t *testing.T) {
saver := &Saver{}
obs := &dialerReadWriteObserver{
saver: saver,
}
dialer := &mocks.Dialer{}
out := obs.WrapDialer(dialer)
dialSaver := out.(*DialerConnSaver)
if dialSaver.Dialer != dialer {
t.Fatal("invalid dialer")
}
if dialSaver.Saver != saver {
t.Fatal("invalid saver")
}
}
func saverCheckReadEvent(t *testing.T, ev *Event) {
// TODO(bassosimone): implement
func TestDialerConnSaver(t *testing.T) {
t.Run("DialContext", func(t *testing.T) {
t.Run("on failure", func(t *testing.T) {
expected := errors.New("mocked error")
saver := &Saver{}
dlr := &DialerConnSaver{
Dialer: &mocks.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return nil, expected
},
},
Saver: saver,
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if !errors.Is(err, expected) {
t.Fatal("not the error we expected")
}
if conn != nil {
t.Fatal("expected nil conn here")
}
})
t.Run("on success", func(t *testing.T) {
origConn := &mocks.Conn{}
saver := &Saver{}
dlr := &DialerConnSaver{
Dialer: &DialerSaver{
Dialer: &mocks.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return origConn, nil
},
},
Saver: saver,
},
Saver: saver,
}
conn, err := dlr.DialContext(context.Background(), "tcp", "www.google.com:443")
if err != nil {
t.Fatal("not the error we expected", err)
}
cw := conn.(*dialerConnWrapper)
if cw.Conn != origConn {
t.Fatal("unexpected conn")
}
})
})
t.Run("CloseIdleConnections", func(t *testing.T) {
var called bool
child := &mocks.Dialer{
MockCloseIdleConnections: func() {
called = true
},
}
dialer := &DialerConnSaver{
Dialer: child,
Saver: &Saver{},
}
dialer.CloseIdleConnections()
if !called {
t.Fatal("not called")
}
})
}
func saverCheckWriteEvent(t *testing.T, ev *Event) {
// TODO(bassosimone): implement
func TestDialerConnWrapper(t *testing.T) {
t.Run("Read", func(t *testing.T) {
baseConn := &mocks.Conn{
MockRead: func(b []byte) (int, error) {
return 0, io.EOF
},
MockRemoteAddr: func() net.Addr {
return &mocks.Addr{
MockString: func() string {
return "www.google.com:443"
},
MockNetwork: func() string {
return "tcp"
},
}
},
}
saver := &Saver{}
conn := &dialerConnWrapper{
Conn: baseConn,
saver: saver,
}
data := make([]byte, 155)
count, err := conn.Read(data)
if !errors.Is(err, io.EOF) {
t.Fatal("unexpected err", err)
}
if count != 0 {
t.Fatal("unexpected count")
}
ev := saver.Read()
if len(ev) != 1 {
t.Fatal("expected a single event here")
}
if ev[0].Value().Address != "www.google.com:443" {
t.Fatal("unexpected Address")
}
if ev[0].Value().Duration <= 0 {
t.Fatal("unexpected Duration")
}
if !errors.Is(ev[0].Value().Err, io.EOF) {
t.Fatal("unexpected Err")
}
if ev[0].Name() != netxlite.ReadOperation {
t.Fatal("unexpected Name")
}
if ev[0].Value().Proto != "tcp" {
t.Fatal("unexpected Proto")
}
if !ev[0].Value().Time.Before(time.Now()) {
t.Fatal("unexpected Time")
}
})
t.Run("Write", func(t *testing.T) {
baseConn := &mocks.Conn{
MockWrite: func(b []byte) (int, error) {
return 0, io.EOF
},
MockRemoteAddr: func() net.Addr {
return &mocks.Addr{
MockString: func() string {
return "www.google.com:443"
},
MockNetwork: func() string {
return "tcp"
},
}
},
}
saver := &Saver{}
conn := &dialerConnWrapper{
Conn: baseConn,
saver: saver,
}
data := make([]byte, 155)
count, err := conn.Write(data)
if !errors.Is(err, io.EOF) {
t.Fatal("unexpected err", err)
}
if count != 0 {
t.Fatal("unexpected count")
}
ev := saver.Read()
if len(ev) != 1 {
t.Fatal("expected a single event here")
}
if ev[0].Value().Address != "www.google.com:443" {
t.Fatal("unexpected Address")
}
if ev[0].Value().Duration <= 0 {
t.Fatal("unexpected Duration")
}
if !errors.Is(ev[0].Value().Err, io.EOF) {
t.Fatal("unexpected Err")
}
if ev[0].Name() != netxlite.WriteOperation {
t.Fatal("unexpected Name")
}
if ev[0].Value().Proto != "tcp" {
t.Fatal("unexpected Proto")
}
if !ev[0].Value().Time.Before(time.Now()) {
t.Fatal("unexpected Time")
}
})
}