730373cc75
We recently started moving core data structures inside of the internal/model package as detailed in https://github.com/ooni/probe/issues/1885. The chief reason to do that is to have a set of fundamental shared data types to help us rationalize the codebase. This specific diff moves internal/netx/archival's core data types inside the internal/model package. While there, it also refactors the existing tests to improve their quality. Additionally, we also added an extra test to ensure `ArchivalHTTPBody` is an alias for `ArchivalMaybeBinaryData`, which is required to ensure the custom JSON serialization process works for it. We're doing that because both internal/netx/archival and internal/measurex define their own archival data structures. We developed measurex using its own structures because it allowed to iterate more quickly. Now that we have sketched out measurex, the time has come to consolidate. My overall aim is to spend a few more hours this week on engineering measurex. This work is preliminary work before we finish up both measurex and websteps. We described this cleanup in https://github.com/ooni/probe/issues/1957.
709 lines
17 KiB
Go
709 lines
17 KiB
Go
package archival_test
|
|
|
|
import (
|
|
"context"
|
|
"crypto/x509"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/gorilla/websocket"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
|
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
)
|
|
|
|
func TestNewTCPConnectList(t *testing.T) {
|
|
begin := time.Now()
|
|
type args struct {
|
|
begin time.Time
|
|
events []trace.Event
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []archival.TCPConnectEntry
|
|
}{{
|
|
name: "empty run",
|
|
args: args{
|
|
begin: begin,
|
|
events: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "realistic run",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
|
Hostname: "dns.google.com",
|
|
Name: "resolve_done",
|
|
Time: begin.Add(100 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Duration: 30 * time.Millisecond,
|
|
Name: netxlite.ConnectOperation,
|
|
Proto: "tcp",
|
|
Time: begin.Add(130 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Duration: 55 * time.Millisecond,
|
|
Name: netxlite.ConnectOperation,
|
|
Proto: "udp",
|
|
Time: begin.Add(130 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.4.4:53",
|
|
Duration: 50 * time.Millisecond,
|
|
Err: io.EOF,
|
|
Name: netxlite.ConnectOperation,
|
|
Proto: "tcp",
|
|
Time: begin.Add(180 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.TCPConnectEntry{{
|
|
IP: "8.8.8.8",
|
|
Port: 853,
|
|
Status: archival.TCPConnectStatus{
|
|
Success: true,
|
|
},
|
|
T: 0.13,
|
|
}, {
|
|
IP: "8.8.4.4",
|
|
Port: 53,
|
|
Status: archival.TCPConnectStatus{
|
|
Failure: archival.NewFailure(io.EOF),
|
|
Success: false,
|
|
},
|
|
T: 0.18,
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := archival.NewTCPConnectList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
|
t.Error(cmp.Diff(got, tt.want))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewRequestList(t *testing.T) {
|
|
begin := time.Now()
|
|
type args struct {
|
|
begin time.Time
|
|
events []trace.Event
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []archival.RequestEntry
|
|
}{{
|
|
name: "empty run",
|
|
args: args{
|
|
begin: begin,
|
|
events: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "realistic run",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Name: "http_transaction_start",
|
|
Time: begin.Add(10 * time.Millisecond),
|
|
}, {
|
|
Name: "http_request_body_snapshot",
|
|
Data: []byte("deadbeef"),
|
|
DataIsTruncated: false,
|
|
}, {
|
|
Name: "http_request_metadata",
|
|
HTTPHeaders: http.Header{
|
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
|
},
|
|
HTTPMethod: "POST",
|
|
HTTPURL: "https://www.example.com/submit",
|
|
}, {
|
|
Name: "http_response_metadata",
|
|
HTTPHeaders: http.Header{
|
|
"Server": []string{"miniooni/0.1.0-dev"},
|
|
},
|
|
HTTPStatusCode: 200,
|
|
}, {
|
|
Name: "http_response_body_snapshot",
|
|
Data: []byte("{}"),
|
|
DataIsTruncated: false,
|
|
}, {
|
|
Name: "http_transaction_done",
|
|
}, {
|
|
Name: "http_transaction_start",
|
|
Time: begin.Add(20 * time.Millisecond),
|
|
}, {
|
|
Name: "http_request_metadata",
|
|
HTTPHeaders: http.Header{
|
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
|
},
|
|
HTTPMethod: "GET",
|
|
HTTPURL: "https://www.example.com/result",
|
|
}, {
|
|
Name: "http_transaction_done",
|
|
Err: io.EOF,
|
|
}},
|
|
},
|
|
want: []archival.RequestEntry{{
|
|
Failure: archival.NewFailure(io.EOF),
|
|
Request: archival.HTTPRequest{
|
|
HeadersList: []archival.HTTPHeader{{
|
|
Key: "User-Agent",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "miniooni/0.1.0-dev",
|
|
},
|
|
}},
|
|
Headers: map[string]archival.MaybeBinaryValue{
|
|
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
|
},
|
|
Method: "GET",
|
|
URL: "https://www.example.com/result",
|
|
},
|
|
T: 0.02,
|
|
}, {
|
|
Request: archival.HTTPRequest{
|
|
Body: archival.MaybeBinaryValue{
|
|
Value: "deadbeef",
|
|
},
|
|
HeadersList: []archival.HTTPHeader{{
|
|
Key: "User-Agent",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "miniooni/0.1.0-dev",
|
|
},
|
|
}},
|
|
Headers: map[string]archival.MaybeBinaryValue{
|
|
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
|
},
|
|
Method: "POST",
|
|
URL: "https://www.example.com/submit",
|
|
},
|
|
Response: archival.HTTPResponse{
|
|
Body: archival.MaybeBinaryValue{
|
|
Value: "{}",
|
|
},
|
|
Code: 200,
|
|
HeadersList: []archival.HTTPHeader{{
|
|
Key: "Server",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "miniooni/0.1.0-dev",
|
|
},
|
|
}},
|
|
Headers: map[string]archival.MaybeBinaryValue{
|
|
"Server": {Value: "miniooni/0.1.0-dev"},
|
|
},
|
|
Locations: nil,
|
|
},
|
|
T: 0.01,
|
|
}},
|
|
}, {
|
|
// for an example of why we need to sort headers, see
|
|
// https://github.com/ooni/probe-engine/pull/751/checks?check_run_id=853562310
|
|
name: "run with redirect and headers to sort",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Name: "http_transaction_start",
|
|
Time: begin.Add(10 * time.Millisecond),
|
|
}, {
|
|
Name: "http_request_metadata",
|
|
HTTPHeaders: http.Header{
|
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
|
},
|
|
HTTPMethod: "GET",
|
|
HTTPURL: "https://www.example.com/",
|
|
}, {
|
|
Name: "http_response_metadata",
|
|
HTTPHeaders: http.Header{
|
|
"Server": []string{"miniooni/0.1.0-dev"},
|
|
"Location": []string{"https://x.example.com", "https://y.example.com"},
|
|
},
|
|
HTTPStatusCode: 302,
|
|
}, {
|
|
Name: "http_transaction_done",
|
|
}},
|
|
},
|
|
want: []archival.RequestEntry{{
|
|
Request: archival.HTTPRequest{
|
|
HeadersList: []archival.HTTPHeader{{
|
|
Key: "User-Agent",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "miniooni/0.1.0-dev",
|
|
},
|
|
}},
|
|
Headers: map[string]archival.MaybeBinaryValue{
|
|
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
|
},
|
|
Method: "GET",
|
|
URL: "https://www.example.com/",
|
|
},
|
|
Response: archival.HTTPResponse{
|
|
Code: 302,
|
|
HeadersList: []archival.HTTPHeader{{
|
|
Key: "Location",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "https://x.example.com",
|
|
},
|
|
}, {
|
|
Key: "Location",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "https://y.example.com",
|
|
},
|
|
}, {
|
|
Key: "Server",
|
|
Value: archival.MaybeBinaryValue{
|
|
Value: "miniooni/0.1.0-dev",
|
|
},
|
|
}},
|
|
Headers: map[string]archival.MaybeBinaryValue{
|
|
"Server": {Value: "miniooni/0.1.0-dev"},
|
|
"Location": {Value: "https://x.example.com"},
|
|
},
|
|
Locations: []string{
|
|
"https://x.example.com", "https://y.example.com",
|
|
},
|
|
},
|
|
T: 0.01,
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := archival.NewRequestList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
|
t.Error(cmp.Diff(got, tt.want))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewDNSQueriesList(t *testing.T) {
|
|
begin := time.Now()
|
|
type args struct {
|
|
begin time.Time
|
|
events []trace.Event
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []archival.DNSQueryEntry
|
|
}{{
|
|
name: "empty run",
|
|
args: args{
|
|
begin: begin,
|
|
events: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "realistic run",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Address: "1.1.1.1:853",
|
|
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
|
Hostname: "dns.google.com",
|
|
Name: "resolve_done",
|
|
Proto: "dot",
|
|
Time: begin.Add(100 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Duration: 30 * time.Millisecond,
|
|
Name: netxlite.ConnectOperation,
|
|
Proto: "tcp",
|
|
Time: begin.Add(130 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.4.4:53",
|
|
Duration: 50 * time.Millisecond,
|
|
Err: io.EOF,
|
|
Name: netxlite.ConnectOperation,
|
|
Proto: "tcp",
|
|
Time: begin.Add(180 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.DNSQueryEntry{{
|
|
Answers: []archival.DNSAnswerEntry{{
|
|
ASN: 15169,
|
|
ASOrgName: "Google LLC",
|
|
AnswerType: "A",
|
|
IPv4: "8.8.8.8",
|
|
}, {
|
|
ASN: 15169,
|
|
ASOrgName: "Google LLC",
|
|
AnswerType: "A",
|
|
IPv4: "8.8.4.4",
|
|
}},
|
|
Engine: "dot",
|
|
Hostname: "dns.google.com",
|
|
QueryType: "A",
|
|
ResolverAddress: "1.1.1.1:853",
|
|
T: 0.1,
|
|
}},
|
|
}, {
|
|
name: "run with IPv6 results",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Addresses: []string{"2001:4860:4860::8888"},
|
|
Hostname: "dns.google.com",
|
|
Name: "resolve_done",
|
|
Time: begin.Add(200 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.DNSQueryEntry{{
|
|
Answers: []archival.DNSAnswerEntry{{
|
|
ASN: 15169,
|
|
ASOrgName: "Google LLC",
|
|
AnswerType: "AAAA",
|
|
IPv6: "2001:4860:4860::8888",
|
|
}},
|
|
Hostname: "dns.google.com",
|
|
QueryType: "AAAA",
|
|
T: 0.2,
|
|
}},
|
|
}, {
|
|
name: "run with errors",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Err: &netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError},
|
|
Hostname: "dns.google.com",
|
|
Name: "resolve_done",
|
|
Time: begin.Add(200 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.DNSQueryEntry{{
|
|
Answers: nil,
|
|
Failure: archival.NewFailure(
|
|
&netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError}),
|
|
Hostname: "dns.google.com",
|
|
QueryType: "A",
|
|
T: 0.2,
|
|
}, {
|
|
Answers: nil,
|
|
Failure: archival.NewFailure(
|
|
&netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError}),
|
|
Hostname: "dns.google.com",
|
|
QueryType: "AAAA",
|
|
T: 0.2,
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := archival.NewDNSQueriesList(tt.args.begin, tt.args.events)
|
|
if diff := cmp.Diff(tt.want, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewNetworkEventsList(t *testing.T) {
|
|
begin := time.Now()
|
|
type args struct {
|
|
begin time.Time
|
|
events []trace.Event
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []archival.NetworkEvent
|
|
}{{
|
|
name: "empty run",
|
|
args: args{
|
|
begin: begin,
|
|
events: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "realistic run",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Name: netxlite.ConnectOperation,
|
|
Address: "8.8.8.8:853",
|
|
Err: io.EOF,
|
|
Proto: "tcp",
|
|
Time: begin.Add(7 * time.Millisecond),
|
|
}, {
|
|
Name: netxlite.ReadOperation,
|
|
Err: context.Canceled,
|
|
NumBytes: 7117,
|
|
Time: begin.Add(11 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Name: netxlite.ReadFromOperation,
|
|
Err: context.Canceled,
|
|
NumBytes: 7117,
|
|
Time: begin.Add(11 * time.Millisecond),
|
|
}, {
|
|
Name: netxlite.WriteOperation,
|
|
Err: websocket.ErrBadHandshake,
|
|
NumBytes: 4114,
|
|
Time: begin.Add(14 * time.Millisecond),
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Name: netxlite.WriteToOperation,
|
|
Err: websocket.ErrBadHandshake,
|
|
NumBytes: 4114,
|
|
Time: begin.Add(14 * time.Millisecond),
|
|
}, {
|
|
Name: netxlite.CloseOperation,
|
|
Err: websocket.ErrReadLimit,
|
|
Time: begin.Add(17 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.NetworkEvent{{
|
|
Address: "8.8.8.8:853",
|
|
Failure: archival.NewFailure(io.EOF),
|
|
Operation: netxlite.ConnectOperation,
|
|
Proto: "tcp",
|
|
T: 0.007,
|
|
}, {
|
|
Failure: archival.NewFailure(context.Canceled),
|
|
NumBytes: 7117,
|
|
Operation: netxlite.ReadOperation,
|
|
T: 0.011,
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Failure: archival.NewFailure(context.Canceled),
|
|
NumBytes: 7117,
|
|
Operation: netxlite.ReadFromOperation,
|
|
T: 0.011,
|
|
}, {
|
|
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
|
NumBytes: 4114,
|
|
Operation: netxlite.WriteOperation,
|
|
T: 0.014,
|
|
}, {
|
|
Address: "8.8.8.8:853",
|
|
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
|
NumBytes: 4114,
|
|
Operation: netxlite.WriteToOperation,
|
|
T: 0.014,
|
|
}, {
|
|
Failure: archival.NewFailure(websocket.ErrReadLimit),
|
|
Operation: netxlite.CloseOperation,
|
|
T: 0.017,
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := archival.NewNetworkEventsList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
|
t.Error(cmp.Diff(got, tt.want))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewTLSHandshakesList(t *testing.T) {
|
|
begin := time.Now()
|
|
type args struct {
|
|
begin time.Time
|
|
events []trace.Event
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want []archival.TLSHandshake
|
|
}{{
|
|
name: "empty run",
|
|
args: args{
|
|
begin: begin,
|
|
events: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "realistic run",
|
|
args: args{
|
|
begin: begin,
|
|
events: []trace.Event{{
|
|
Name: netxlite.CloseOperation,
|
|
Err: websocket.ErrReadLimit,
|
|
Time: begin.Add(17 * time.Millisecond),
|
|
}, {
|
|
Name: "tls_handshake_done",
|
|
Err: io.EOF,
|
|
NoTLSVerify: false,
|
|
TLSCipherSuite: "SUITE",
|
|
TLSNegotiatedProto: "h2",
|
|
TLSPeerCerts: []*x509.Certificate{{
|
|
Raw: []byte("deadbeef"),
|
|
}, {
|
|
Raw: []byte("abad1dea"),
|
|
}},
|
|
TLSServerName: "x.org",
|
|
TLSVersion: "TLSv1.3",
|
|
Time: begin.Add(55 * time.Millisecond),
|
|
}},
|
|
},
|
|
want: []archival.TLSHandshake{{
|
|
CipherSuite: "SUITE",
|
|
Failure: archival.NewFailure(io.EOF),
|
|
NegotiatedProtocol: "h2",
|
|
NoTLSVerify: false,
|
|
PeerCertificates: []archival.MaybeBinaryValue{{
|
|
Value: "deadbeef",
|
|
}, {
|
|
Value: "abad1dea",
|
|
}},
|
|
ServerName: "x.org",
|
|
T: 0.055,
|
|
TLSVersion: "TLSv1.3",
|
|
}},
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := archival.NewTLSHandshakesList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
|
t.Error(cmp.Diff(got, tt.want))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewFailure(t *testing.T) {
|
|
type args struct {
|
|
err error
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *string
|
|
}{{
|
|
name: "when error is nil",
|
|
args: args{
|
|
err: nil,
|
|
},
|
|
want: nil,
|
|
}, {
|
|
name: "when error is wrapped and failure meaningful",
|
|
args: args{
|
|
err: &netxlite.ErrWrapper{
|
|
Failure: netxlite.FailureConnectionRefused,
|
|
},
|
|
},
|
|
want: func() *string {
|
|
s := netxlite.FailureConnectionRefused
|
|
return &s
|
|
}(),
|
|
}, {
|
|
name: "when error is wrapped and failure is not meaningful",
|
|
args: args{
|
|
err: &netxlite.ErrWrapper{},
|
|
},
|
|
want: func() *string {
|
|
s := "unknown_failure: errWrapper.Failure is empty"
|
|
return &s
|
|
}(),
|
|
}, {
|
|
name: "when error is not wrapped but wrappable",
|
|
args: args{err: io.EOF},
|
|
want: func() *string {
|
|
s := "eof_error"
|
|
return &s
|
|
}(),
|
|
}, {
|
|
name: "when the error is not wrapped and not wrappable",
|
|
args: args{
|
|
err: errors.New("use of closed socket 127.0.0.1:8080->10.0.0.1:22"),
|
|
},
|
|
want: func() *string {
|
|
s := "unknown_failure: use of closed socket [scrubbed]->[scrubbed]"
|
|
return &s
|
|
}(),
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := archival.NewFailure(tt.args.err)
|
|
if tt.want == nil && got == nil {
|
|
return
|
|
}
|
|
if tt.want == nil && got != nil {
|
|
t.Errorf("NewFailure: want %+v, got %s", tt.want, *got)
|
|
return
|
|
}
|
|
if tt.want != nil && got == nil {
|
|
t.Errorf("NewFailure: want %s, got %+v", *tt.want, got)
|
|
return
|
|
}
|
|
if *tt.want != *got {
|
|
t.Errorf("NewFailure: want %s, got %s", *tt.want, *got)
|
|
return
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestNewFailedOperation(t *testing.T) {
|
|
type args struct {
|
|
err error
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *string
|
|
}{{
|
|
name: "With no error",
|
|
args: args{
|
|
err: nil, // explicit
|
|
},
|
|
want: nil, // explicit
|
|
}, {
|
|
name: "With wrapped error and non-empty operation",
|
|
args: args{
|
|
err: &netxlite.ErrWrapper{
|
|
Failure: netxlite.FailureConnectionRefused,
|
|
Operation: netxlite.ConnectOperation,
|
|
},
|
|
},
|
|
want: (func() *string {
|
|
s := netxlite.ConnectOperation
|
|
return &s
|
|
})(),
|
|
}, {
|
|
name: "With wrapped error and empty operation",
|
|
args: args{
|
|
err: &netxlite.ErrWrapper{
|
|
Failure: netxlite.FailureConnectionRefused,
|
|
},
|
|
},
|
|
want: (func() *string {
|
|
s := netxlite.UnknownOperation
|
|
return &s
|
|
})(),
|
|
}, {
|
|
name: "With non wrapped error",
|
|
args: args{
|
|
err: io.EOF,
|
|
},
|
|
want: (func() *string {
|
|
s := netxlite.UnknownOperation
|
|
return &s
|
|
})(),
|
|
}}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := archival.NewFailedOperation(tt.args.err)
|
|
if got == nil && tt.want == nil {
|
|
return
|
|
}
|
|
if got == nil && tt.want != nil {
|
|
t.Errorf("NewFailedOperation() = %v, want %v", got, tt.want)
|
|
return
|
|
}
|
|
if got != nil && tt.want == nil {
|
|
t.Errorf("NewFailedOperation() = %v, want %v", got, tt.want)
|
|
return
|
|
}
|
|
if got != nil && tt.want != nil && *got != *tt.want {
|
|
t.Errorf("NewFailedOperation() = %v, want %v", got, tt.want)
|
|
return
|
|
}
|
|
})
|
|
}
|
|
}
|