refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
package netxlite
|
2021-02-02 12:05:47 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"net"
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
"strings"
|
2021-02-02 12:05:47 +01:00
|
|
|
"testing"
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
"time"
|
2021-02-02 12:05:47 +01:00
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
"github.com/apex/log"
|
2021-09-07 19:56:42 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite/errorsx"
|
2021-09-05 14:49:38 +02:00
|
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite/mocks"
|
2021-02-02 12:05:47 +01:00
|
|
|
)
|
|
|
|
|
2021-09-05 19:55:28 +02:00
|
|
|
func TestDialerSystemCloseIdleConnections(t *testing.T) {
|
|
|
|
d := &dialerSystem{}
|
|
|
|
d.CloseIdleConnections() // should not crash
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverNoPort(t *testing.T) {
|
2021-09-05 19:55:28 +02:00
|
|
|
dialer := &dialerResolver{Dialer: defaultDialer, Resolver: DefaultResolver}
|
2021-06-23 17:00:44 +02:00
|
|
|
conn, err := dialer.DialContext(context.Background(), "tcp", "ooni.nu")
|
|
|
|
if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") {
|
|
|
|
t.Fatal("not the error we expected", err)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected a nil conn here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverLookupHostAddress(t *testing.T) {
|
2021-09-05 19:55:28 +02:00
|
|
|
dialer := &dialerResolver{Dialer: defaultDialer, Resolver: &mocks.Resolver{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
|
|
|
return nil, errors.New("we should not call this function")
|
|
|
|
},
|
2021-02-02 12:05:47 +01:00
|
|
|
}}
|
2021-06-09 09:42:31 +02:00
|
|
|
addrs, err := dialer.lookupHost(context.Background(), "1.1.1.1")
|
2021-02-02 12:05:47 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(addrs) != 1 || addrs[0] != "1.1.1.1" {
|
|
|
|
t.Fatal("not the result we expected")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverLookupHostFailure(t *testing.T) {
|
2021-02-02 12:05:47 +01:00
|
|
|
expected := errors.New("mocked error")
|
2021-09-05 19:55:28 +02:00
|
|
|
dialer := &dialerResolver{Dialer: defaultDialer, Resolver: &mocks.Resolver{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
|
|
|
return nil, expected
|
|
|
|
},
|
2021-02-02 12:05:47 +01:00
|
|
|
}}
|
2021-06-23 17:00:44 +02:00
|
|
|
ctx := context.Background()
|
|
|
|
conn, err := dialer.DialContext(ctx, "tcp", "dns.google.com:853")
|
2021-02-02 12:05:47 +01:00
|
|
|
if !errors.Is(err, expected) {
|
2021-06-23 17:00:44 +02:00
|
|
|
t.Fatal("not the error we expected", err)
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverDialForSingleIPFails(t *testing.T) {
|
2021-09-05 14:49:38 +02:00
|
|
|
dialer := &dialerResolver{Dialer: &mocks.Dialer{
|
2021-06-08 23:59:30 +02:00
|
|
|
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
|
|
|
return nil, io.EOF
|
|
|
|
},
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
}, Resolver: DefaultResolver}
|
2021-02-02 12:05:47 +01:00
|
|
|
conn, err := dialer.DialContext(context.Background(), "tcp", "1.1.1.1:853")
|
|
|
|
if !errors.Is(err, io.EOF) {
|
|
|
|
t.Fatal("not the error we expected")
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverDialForManyIPFails(t *testing.T) {
|
2021-09-05 14:49:38 +02:00
|
|
|
dialer := &dialerResolver{
|
|
|
|
Dialer: &mocks.Dialer{
|
2021-06-08 23:59:30 +02:00
|
|
|
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
|
|
|
return nil, io.EOF
|
|
|
|
},
|
2021-09-05 14:49:38 +02:00
|
|
|
}, Resolver: &mocks.Resolver{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
|
|
|
return []string{"1.1.1.1", "8.8.8.8"}, nil
|
|
|
|
},
|
2021-06-08 23:59:30 +02:00
|
|
|
}}
|
2021-02-02 12:05:47 +01:00
|
|
|
conn, err := dialer.DialContext(context.Background(), "tcp", "dot.dns:853")
|
|
|
|
if !errors.Is(err, io.EOF) {
|
|
|
|
t.Fatal("not the error we expected")
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
func TestDialerResolverDialForManyIPSuccess(t *testing.T) {
|
2021-09-05 14:49:38 +02:00
|
|
|
dialer := &dialerResolver{Dialer: &mocks.Dialer{
|
2021-06-08 23:59:30 +02:00
|
|
|
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
2021-09-05 14:49:38 +02:00
|
|
|
return &mocks.Conn{
|
2021-06-08 23:59:30 +02:00
|
|
|
MockClose: func() error {
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
},
|
2021-09-05 14:49:38 +02:00
|
|
|
}, Resolver: &mocks.Resolver{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
|
|
|
return []string{"1.1.1.1", "8.8.8.8"}, nil
|
|
|
|
},
|
2021-02-02 12:05:47 +01:00
|
|
|
}}
|
|
|
|
conn, err := dialer.DialContext(context.Background(), "tcp", "dot.dns:853")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("expected nil error here")
|
|
|
|
}
|
|
|
|
if conn == nil {
|
|
|
|
t.Fatal("expected non-nil conn")
|
|
|
|
}
|
|
|
|
conn.Close()
|
|
|
|
}
|
|
|
|
|
2021-09-05 19:55:28 +02:00
|
|
|
func TestDialerResolverCloseIdleConnections(t *testing.T) {
|
|
|
|
var (
|
|
|
|
calledDialer bool
|
|
|
|
calledResolver bool
|
|
|
|
)
|
|
|
|
d := &dialerResolver{
|
|
|
|
Dialer: &mocks.Dialer{
|
|
|
|
MockCloseIdleConnections: func() {
|
|
|
|
calledDialer = true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Resolver: &mocks.Resolver{
|
|
|
|
MockCloseIdleConnections: func() {
|
|
|
|
calledResolver = true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
d.CloseIdleConnections()
|
|
|
|
if !calledDialer || !calledResolver {
|
|
|
|
t.Fatal("not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 17:00:44 +02:00
|
|
|
func TestDialerLoggerSuccess(t *testing.T) {
|
2021-09-05 14:49:38 +02:00
|
|
|
d := &dialerLogger{
|
|
|
|
Dialer: &mocks.Dialer{
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
2021-09-05 14:49:38 +02:00
|
|
|
return &mocks.Conn{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockClose: func() error {
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}, nil
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Logger: log.Log,
|
|
|
|
}
|
|
|
|
conn, err := d.DialContext(context.Background(), "tcp", "www.google.com:443")
|
2021-06-23 17:00:44 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
}
|
2021-06-23 17:00:44 +02:00
|
|
|
if conn == nil {
|
|
|
|
t.Fatal("expected non-nil conn here")
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
}
|
2021-06-23 17:00:44 +02:00
|
|
|
conn.Close()
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2021-06-23 17:00:44 +02:00
|
|
|
func TestDialerLoggerFailure(t *testing.T) {
|
2021-09-05 14:49:38 +02:00
|
|
|
d := &dialerLogger{
|
|
|
|
Dialer: &mocks.Dialer{
|
2021-06-23 17:00:44 +02:00
|
|
|
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
|
|
|
return nil, io.EOF
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Logger: log.Log,
|
|
|
|
}
|
|
|
|
conn, err := d.DialContext(context.Background(), "tcp", "www.google.com:443")
|
|
|
|
if !errors.Is(err, io.EOF) {
|
|
|
|
t.Fatal("not the error we expected")
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn here")
|
|
|
|
}
|
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
|
2021-09-05 19:55:28 +02:00
|
|
|
func TestDialerLoggerCloseIdleConnections(t *testing.T) {
|
|
|
|
var (
|
|
|
|
calledDialer bool
|
|
|
|
)
|
|
|
|
d := &dialerLogger{
|
|
|
|
Dialer: &mocks.Dialer{
|
|
|
|
MockCloseIdleConnections: func() {
|
|
|
|
calledDialer = true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
d.CloseIdleConnections()
|
|
|
|
if !calledDialer {
|
|
|
|
t.Fatal("not called")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnderlyingDialerHasTimeout(t *testing.T) {
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
expected := 15 * time.Second
|
2021-09-05 19:55:28 +02:00
|
|
|
if underlyingDialer.Timeout != expected {
|
refactor: start pivoting netx (#396)
What do I mean by pivoting? Netx is currently organized by row:
```
| dialer | quicdialer | resolver | ...
saving | | | | ...
errorwrapping | | | | ...
logging | | | | ...
mocking/sys | | | | ...
```
Every row needs to implement saving, errorwrapping, logging, mocking (or
adapting to the system or to some underlying library).
This causes cross package dependencies and, in turn, complexity. For
example, we need the `trace` package for supporting saving.
And `dialer`, `quickdialer`, et al. need to depend on such a package.
The same goes for errorwrapping.
This arrangement further complicates testing. For example, I am
currently working on https://github.com/ooni/probe/issues/1505 and
I realize it need to repeat integration tests in multiple places.
Let's say instead we pivot the above matrix as follows:
```
| saving | errorwrapping | logging | ...
dialer | | | | ...
quicdialer | | | | ...
logging | | | | ...
mocking/sys | | | | ...
...
```
In this way, now every row contains everything related to a specific
action to perform. We can now share code without relying on extra
support packages. What's more, we can write tests and, judding from
the way in which things are made, it seems we only need integration
testing in `errorwrapping` because it's where data quality matters
whereas, in all other cases, unit testing is fine.
I am going, therefore, to proceed with these changes and "pivot"
`netx`. Hopefully, it won't be too painful.
2021-06-23 15:53:12 +02:00
|
|
|
t.Fatal("unexpected timeout value")
|
|
|
|
}
|
2021-02-02 12:05:47 +01:00
|
|
|
}
|
2021-09-05 20:41:46 +02:00
|
|
|
|
|
|
|
func TestNewDialerWithoutResolverChain(t *testing.T) {
|
|
|
|
dlr := NewDialerWithoutResolver(log.Log)
|
|
|
|
dlog, okay := dlr.(*dialerLogger)
|
|
|
|
if !okay {
|
|
|
|
t.Fatal("invalid type")
|
|
|
|
}
|
|
|
|
if dlog.Logger != log.Log {
|
|
|
|
t.Fatal("invalid logger")
|
|
|
|
}
|
|
|
|
dreso, okay := dlog.Dialer.(*dialerResolver)
|
|
|
|
if !okay {
|
|
|
|
t.Fatal("invalid type")
|
|
|
|
}
|
|
|
|
if _, okay := dreso.Resolver.(*nullResolver); !okay {
|
|
|
|
t.Fatal("invalid Resolver type")
|
|
|
|
}
|
|
|
|
dlog, okay = dreso.Dialer.(*dialerLogger)
|
|
|
|
if !okay {
|
|
|
|
t.Fatal("invalid type")
|
|
|
|
}
|
|
|
|
if dlog.Logger != log.Log {
|
|
|
|
t.Fatal("invalid logger")
|
|
|
|
}
|
2021-09-07 19:56:42 +02:00
|
|
|
dew, okay := dlog.Dialer.(*dialerErrWrapper)
|
|
|
|
if !okay {
|
|
|
|
t.Fatal("invalid type")
|
|
|
|
}
|
|
|
|
if _, okay := dew.Dialer.(*dialerSystem); !okay {
|
2021-09-05 20:41:46 +02:00
|
|
|
t.Fatal("invalid type")
|
|
|
|
}
|
|
|
|
}
|
2021-09-06 14:12:30 +02:00
|
|
|
|
|
|
|
func TestNewSingleUseDialerWorksAsIntended(t *testing.T) {
|
|
|
|
conn := &mocks.Conn{}
|
|
|
|
d := NewSingleUseDialer(conn)
|
|
|
|
outconn, err := d.DialContext(context.Background(), "", "")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if conn != outconn {
|
|
|
|
t.Fatal("invalid outconn")
|
|
|
|
}
|
|
|
|
for i := 0; i < 4; i++ {
|
|
|
|
outconn, err = d.DialContext(context.Background(), "", "")
|
|
|
|
if !errors.Is(err, ErrNoConnReuse) {
|
|
|
|
t.Fatal("not the error we expected", err)
|
|
|
|
}
|
|
|
|
if outconn != nil {
|
|
|
|
t.Fatal("expected nil outconn here")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-07 19:56:42 +02:00
|
|
|
|
|
|
|
func TestDialerErrWrapper(t *testing.T) {
|
|
|
|
t.Run("DialContext on success", func(t *testing.T) {
|
|
|
|
t.Run("on success", func(t *testing.T) {
|
|
|
|
expectedConn := &mocks.Conn{}
|
|
|
|
d := &dialerErrWrapper{
|
|
|
|
Dialer: &mocks.Dialer{
|
|
|
|
MockDialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
|
|
return expectedConn, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
conn, err := d.DialContext(ctx, "", "")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
errWrapperConn := conn.(*dialerErrWrapperConn)
|
|
|
|
if errWrapperConn.Conn != expectedConn {
|
|
|
|
t.Fatal("unexpected conn")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("on failure", func(t *testing.T) {
|
|
|
|
expectedErr := io.EOF
|
|
|
|
d := &dialerErrWrapper{
|
|
|
|
Dialer: &mocks.Dialer{
|
|
|
|
MockDialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
|
|
return nil, expectedErr
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
conn, err := d.DialContext(ctx, "", "")
|
|
|
|
if err == nil || err.Error() != errorsx.FailureEOFError {
|
|
|
|
t.Fatal("unexpected err", err)
|
|
|
|
}
|
|
|
|
if conn != nil {
|
|
|
|
t.Fatal("expected nil conn")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("CloseIdleConnections", func(t *testing.T) {
|
|
|
|
var called bool
|
|
|
|
d := &dialerErrWrapper{
|
|
|
|
Dialer: &mocks.Dialer{
|
|
|
|
MockCloseIdleConnections: func() {
|
|
|
|
called = true
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
d.CloseIdleConnections()
|
|
|
|
if !called {
|
|
|
|
t.Fatal("not called")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDialerErrWrapperConn(t *testing.T) {
|
|
|
|
t.Run("Read", func(t *testing.T) {
|
|
|
|
t.Run("on success", func(t *testing.T) {
|
|
|
|
b := make([]byte, 128)
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockRead: func(b []byte) (int, error) {
|
|
|
|
return len(b), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
count, err := conn.Read(b)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if count != len(b) {
|
|
|
|
t.Fatal("unexpected count")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("on failure", func(t *testing.T) {
|
|
|
|
b := make([]byte, 128)
|
|
|
|
expectedErr := io.EOF
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockRead: func(b []byte) (int, error) {
|
|
|
|
return 0, expectedErr
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
count, err := conn.Read(b)
|
|
|
|
if err == nil || err.Error() != errorsx.FailureEOFError {
|
|
|
|
t.Fatal("unexpected err", err)
|
|
|
|
}
|
|
|
|
if count != 0 {
|
|
|
|
t.Fatal("unexpected count")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Write", func(t *testing.T) {
|
|
|
|
t.Run("on success", func(t *testing.T) {
|
|
|
|
b := make([]byte, 128)
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockWrite: func(b []byte) (int, error) {
|
|
|
|
return len(b), nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
count, err := conn.Write(b)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if count != len(b) {
|
|
|
|
t.Fatal("unexpected count")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("on failure", func(t *testing.T) {
|
|
|
|
b := make([]byte, 128)
|
|
|
|
expectedErr := io.EOF
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockWrite: func(b []byte) (int, error) {
|
|
|
|
return 0, expectedErr
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
count, err := conn.Write(b)
|
|
|
|
if err == nil || err.Error() != errorsx.FailureEOFError {
|
|
|
|
t.Fatal("unexpected err", err)
|
|
|
|
}
|
|
|
|
if count != 0 {
|
|
|
|
t.Fatal("unexpected count")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("Close", func(t *testing.T) {
|
|
|
|
t.Run("on success", func(t *testing.T) {
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockClose: func() error {
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
err := conn.Close()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("on failure", func(t *testing.T) {
|
|
|
|
expectedErr := io.EOF
|
|
|
|
conn := &dialerErrWrapperConn{
|
|
|
|
Conn: &mocks.Conn{
|
|
|
|
MockClose: func() error {
|
|
|
|
return expectedErr
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
err := conn.Close()
|
|
|
|
if err == nil || err.Error() != errorsx.FailureEOFError {
|
|
|
|
t.Fatal("unexpected err", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|