mirror of
https://github.com/cloudflare/cloudflared.git
synced 2026-06-23 04:10:20 +00:00
4494eee13d
Adding integration tests for cloudflared pre-checks. This tests pre-check functionality to ensure it is working as expected.
596 lines
18 KiB
Go
596 lines
18 KiB
Go
package prechecks
|
|
|
|
import (
|
|
"context"
|
|
"crypto/tls"
|
|
"errors"
|
|
"net"
|
|
"testing"
|
|
|
|
"github.com/quic-go/quic-go"
|
|
"github.com/rs/zerolog"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/mock/gomock"
|
|
|
|
"github.com/cloudflare/cloudflared/edgediscovery/allregions"
|
|
"github.com/cloudflare/cloudflared/mocks"
|
|
)
|
|
|
|
// Test constants for repeated string values.
|
|
const (
|
|
testRegion1Global = region1Global
|
|
testRegion2Global = region2Global
|
|
testRegion1US = region1US
|
|
testRegion2US = region2US
|
|
testRegion1Fed = region1Fed
|
|
testRegion2Fed = region2Fed
|
|
|
|
testEdgePort = 7844
|
|
)
|
|
|
|
// testTLSConfig is a minimal *tls.Config for tests. Mock dialers never
|
|
// perform a real TLS handshake, so an empty config is sufficient.
|
|
var testTLSConfig = &tls.Config{} //nolint:gosec
|
|
|
|
// mockQuicConnection is a minimal test double for quic.Connection.
|
|
type mockQuicConnection struct {
|
|
closeErr error
|
|
}
|
|
|
|
func (m *mockQuicConnection) AcceptStream(_ context.Context) (quic.Stream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) AcceptUniStream(_ context.Context) (quic.ReceiveStream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) OpenStream() (quic.Stream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) OpenStreamSync(_ context.Context) (quic.Stream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) OpenUniStream() (quic.SendStream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) OpenUniStreamSync(_ context.Context) (quic.SendStream, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) LocalAddr() net.Addr {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) RemoteAddr() net.Addr {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) CloseWithError(_ quic.ApplicationErrorCode, _ string) error {
|
|
return m.closeErr
|
|
}
|
|
|
|
func (m *mockQuicConnection) Context() context.Context {
|
|
return context.Background()
|
|
}
|
|
|
|
func (m *mockQuicConnection) ConnectionState() quic.ConnectionState {
|
|
return quic.ConnectionState{}
|
|
}
|
|
|
|
func (m *mockQuicConnection) SendDatagram(_ []byte) error {
|
|
return nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) ReceiveDatagram(_ context.Context) ([]byte, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (m *mockQuicConnection) AddPath(*quic.Transport) (*quic.Path, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Helper to create test edge addresses.
|
|
func createTestEdgeAddr(ip string, port int, version allregions.EdgeIPVersion) *allregions.EdgeAddr {
|
|
parsedIP := net.ParseIP(ip)
|
|
return &allregions.EdgeAddr{
|
|
TCP: &net.TCPAddr{IP: parsedIP, Port: port},
|
|
UDP: &net.UDPAddr{IP: parsedIP, Port: port},
|
|
IPVersion: version,
|
|
}
|
|
}
|
|
|
|
// probeDNS tests.
|
|
|
|
func TestProbeDNS_Success(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
v4Addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
v6Addr := createTestEdgeAddr("2001:db8::1", testEdgePort, allregions.V6)
|
|
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("").Return([][]*allregions.EdgeAddr{{v4Addr, v6Addr}}, nil)
|
|
|
|
targets := probeDNS(resolver, "")
|
|
|
|
require.Len(t, targets, 1)
|
|
assert.NotEmpty(t, targets[0].Addrs)
|
|
assert.Equal(t, ProbeTypeDNS, targets[0].DNSResult.Type)
|
|
assert.Equal(t, testRegion1Global, targets[0].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[0].DNSResult.ProbeStatus)
|
|
assert.Equal(t, dnsResolvedSuccessfully, targets[0].DNSResult.Details)
|
|
}
|
|
|
|
func TestProbeDNS_MultipleRegions(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
v4Addr1 := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
v4Addr2 := createTestEdgeAddr("192.0.2.2", testEdgePort, allregions.V4)
|
|
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("").Return([][]*allregions.EdgeAddr{{v4Addr1}, {v4Addr2}}, nil)
|
|
|
|
targets := probeDNS(resolver, "")
|
|
|
|
require.Len(t, targets, 2)
|
|
|
|
assert.Equal(t, testRegion1Global, targets[0].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[0].DNSResult.ProbeStatus)
|
|
assert.NotEmpty(t, targets[0].Addrs)
|
|
|
|
assert.Equal(t, testRegion2Global, targets[1].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[1].DNSResult.ProbeStatus)
|
|
assert.NotEmpty(t, targets[1].Addrs)
|
|
}
|
|
|
|
func TestProbeDNS_ResolverError(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("").Return(nil, errors.New("DNS lookup failed"))
|
|
|
|
targets := probeDNS(resolver, "")
|
|
|
|
require.Len(t, targets, 2)
|
|
assert.Empty(t, targets[0].Addrs)
|
|
assert.Equal(t, Fail, targets[0].DNSResult.ProbeStatus)
|
|
assert.Equal(t, "DNS lookup failed", targets[0].DNSResult.Details)
|
|
assert.Contains(t, targets[0].DNSResult.Action, testRegion1Global)
|
|
assert.Empty(t, targets[1].Addrs)
|
|
assert.Equal(t, Fail, targets[1].DNSResult.ProbeStatus)
|
|
assert.Contains(t, targets[1].DNSResult.Action, testRegion2Global)
|
|
}
|
|
|
|
func TestProbeDNS_EmptyResults(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("").Return([][]*allregions.EdgeAddr{}, nil)
|
|
|
|
targets := probeDNS(resolver, "")
|
|
|
|
require.Len(t, targets, 2)
|
|
assert.Empty(t, targets[0].Addrs)
|
|
assert.Equal(t, Fail, targets[0].DNSResult.ProbeStatus)
|
|
assert.Equal(t, dnsNoAddressesReturned, targets[0].DNSResult.Details)
|
|
}
|
|
|
|
func TestProbeDNS_EmptyGroup(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("").Return([][]*allregions.EdgeAddr{{}}, nil)
|
|
|
|
targets := probeDNS(resolver, "")
|
|
|
|
require.Len(t, targets, 1)
|
|
assert.Empty(t, targets[0].Addrs)
|
|
assert.Equal(t, Fail, targets[0].DNSResult.ProbeStatus)
|
|
assert.Equal(t, dnsNoAddressesReturned, targets[0].DNSResult.Details)
|
|
}
|
|
|
|
func TestProbeDNS_RegionFlag(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
v4Addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
resolver := mocks.NewMockDNSResolver(ctrl)
|
|
resolver.EXPECT().Resolve("us").Return([][]*allregions.EdgeAddr{{v4Addr}}, nil)
|
|
|
|
targets := probeDNS(resolver, "us")
|
|
|
|
require.Len(t, targets, 1)
|
|
assert.Equal(t, testRegion1US, targets[0].DNSResult.Target)
|
|
}
|
|
|
|
// probeQUIC tests.
|
|
|
|
func TestProbeQUIC_Success(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
mockConn := &mockQuicConnection{}
|
|
dialer := mocks.NewMockQUICDialer(ctrl)
|
|
dialer.EXPECT().DialQuic(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(mockConn, nil)
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
logger := zerolog.New(nil)
|
|
|
|
result := probeQUIC(context.Background(), testTLSConfig, dialer, addr, &logger)
|
|
|
|
assert.Equal(t, ProbeTypeQUIC, result.Type)
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
assert.Equal(t, detailsQUICHandshakeSuccessful, result.Details)
|
|
}
|
|
|
|
func TestProbeQUIC_DialError(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockQUICDialer(ctrl)
|
|
dialer.EXPECT().DialQuic(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("connection refused"))
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
logger := zerolog.New(nil)
|
|
|
|
result := probeQUIC(context.Background(), testTLSConfig, dialer, addr, &logger)
|
|
|
|
assert.Equal(t, ProbeTypeQUIC, result.Type)
|
|
assert.Equal(t, Fail, result.ProbeStatus)
|
|
assert.Equal(t, detailsQUICHandshakeFailed, result.Details)
|
|
assert.Equal(t, actionQUICBlocked, result.Action)
|
|
}
|
|
|
|
func TestProbeQUIC_CloseErrorDoesNotAffectResult(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
mockConn := &mockQuicConnection{closeErr: errors.New("close failed")}
|
|
dialer := mocks.NewMockQUICDialer(ctrl)
|
|
dialer.EXPECT().DialQuic(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(mockConn, nil)
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
logger := zerolog.New(nil)
|
|
|
|
result := probeQUIC(context.Background(), testTLSConfig, dialer, addr, &logger)
|
|
|
|
assert.Equal(t, ProbeTypeQUIC, result.Type)
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
assert.Equal(t, detailsQUICHandshakeSuccessful, result.Details)
|
|
}
|
|
|
|
func TestProbeQUIC_ContextTimeout(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockQUICDialer(ctrl)
|
|
dialer.EXPECT().DialQuic(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, context.DeadlineExceeded)
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
logger := zerolog.New(nil)
|
|
|
|
result := probeQUIC(context.Background(), testTLSConfig, dialer, addr, &logger)
|
|
|
|
assert.Equal(t, Fail, result.ProbeStatus)
|
|
assert.Equal(t, detailsQUICHandshakeFailed, result.Details)
|
|
}
|
|
|
|
// probeHTTP2 tests.
|
|
|
|
func TestProbeHTTP2_Success(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockTCPDialer(ctrl)
|
|
dialer.EXPECT().DialEdge(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&net.TCPConn{}, nil)
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
|
|
result := probeHTTP2(context.Background(), testTLSConfig, dialer, addr)
|
|
|
|
assert.Equal(t, ProbeTypeHTTP2, result.Type)
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
assert.Equal(t, detailsHTTP2HandshakeSuccessful, result.Details)
|
|
}
|
|
|
|
func TestProbeHTTP2_DialError(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockTCPDialer(ctrl)
|
|
dialer.EXPECT().DialEdge(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("connection refused"))
|
|
|
|
addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
|
|
result := probeHTTP2(context.Background(), testTLSConfig, dialer, addr)
|
|
|
|
assert.Equal(t, ProbeTypeHTTP2, result.Type)
|
|
assert.Equal(t, Fail, result.ProbeStatus)
|
|
assert.Equal(t, detailsHTTP2BlockedOrUnreachable, result.Details)
|
|
assert.Equal(t, actionHTTP2Blocked, result.Action)
|
|
}
|
|
|
|
// probeManagementAPI tests.
|
|
|
|
func TestProbeManagementAPI_Success(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockManagementDialer(ctrl)
|
|
dialer.EXPECT().DialContext(gomock.Any(), "tcp", "api.cloudflare.com:443").Return(&net.TCPConn{}, nil)
|
|
|
|
result := probeManagementAPI(context.Background(), dialer)
|
|
|
|
assert.Equal(t, ProbeTypeManagementAPI, result.Type)
|
|
assert.Equal(t, "Cloudflare API", result.Component)
|
|
assert.Equal(t, "api.cloudflare.com:443", result.Target)
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
assert.Equal(t, detailsApiReachable, result.Details)
|
|
}
|
|
|
|
func TestProbeManagementAPI_DialError(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockManagementDialer(ctrl)
|
|
dialer.EXPECT().DialContext(gomock.Any(), "tcp", "api.cloudflare.com:443").Return(nil, errors.New("connection refused"))
|
|
|
|
result := probeManagementAPI(context.Background(), dialer)
|
|
|
|
assert.Equal(t, ProbeTypeManagementAPI, result.Type)
|
|
assert.Equal(t, Fail, result.ProbeStatus)
|
|
assert.Equal(t, detailsAPIConnectionFailed, result.Details)
|
|
assert.Equal(t, actionAPIUnreachable, result.Action)
|
|
}
|
|
|
|
// skipResult tests.
|
|
|
|
func TestSkipResult(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
result := skipResult(ProbeTypeQUIC, "UDP Connectivity", "Port 7844 (QUIC)", detailsDNSPrerequisiteFailed)
|
|
|
|
assert.Equal(t, ProbeTypeQUIC, result.Type)
|
|
assert.Equal(t, "UDP Connectivity", result.Component)
|
|
assert.Equal(t, "Port 7844 (QUIC)", result.Target)
|
|
assert.Equal(t, Skip, result.ProbeStatus)
|
|
assert.Equal(t, detailsDNSPrerequisiteFailed, result.Details)
|
|
}
|
|
|
|
// regionTargets tests.
|
|
|
|
func TestRegionTargets(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
region string
|
|
wantRegion1 string
|
|
wantRegion2 string
|
|
description string
|
|
}{
|
|
{
|
|
name: "empty region returns global hostnames",
|
|
region: "",
|
|
wantRegion1: testRegion1Global,
|
|
wantRegion2: testRegion2Global,
|
|
},
|
|
{
|
|
name: "us region returns US hostnames",
|
|
region: "us",
|
|
wantRegion1: testRegion1US,
|
|
wantRegion2: testRegion2US,
|
|
},
|
|
{
|
|
name: "fed region returns fed hostnames",
|
|
region: "fed",
|
|
wantRegion1: testRegion1Fed,
|
|
wantRegion2: testRegion2Fed,
|
|
},
|
|
{
|
|
name: "unknown region defaults to global hostnames",
|
|
region: "eu",
|
|
wantRegion1: testRegion1Global,
|
|
wantRegion2: testRegion2Global,
|
|
description: "Unknown regions should default to global hostnames",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
gotR1, gotR2 := regionTargets(tt.region)
|
|
assert.Equal(t, tt.wantRegion1, gotR1)
|
|
assert.Equal(t, tt.wantRegion2, gotR2)
|
|
})
|
|
}
|
|
}
|
|
|
|
// addrsByFamily tests.
|
|
|
|
func TestAddrsByFamily(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
v4Addr := createTestEdgeAddr("192.0.2.1", testEdgePort, allregions.V4)
|
|
v6Addr := createTestEdgeAddr("2001:db8::1", testEdgePort, allregions.V6)
|
|
|
|
tests := []struct {
|
|
name string
|
|
group []*allregions.EdgeAddr
|
|
ipVersion allregions.ConfigIPVersion
|
|
wantV4 bool
|
|
wantV6 bool
|
|
}{
|
|
{
|
|
name: "auto returns both v4 and v6",
|
|
group: []*allregions.EdgeAddr{v4Addr, v6Addr},
|
|
ipVersion: allregions.Auto,
|
|
wantV4: true,
|
|
wantV6: true,
|
|
},
|
|
{
|
|
name: "ipv4 only returns v4 and nil v6",
|
|
group: []*allregions.EdgeAddr{v4Addr, v6Addr},
|
|
ipVersion: allregions.IPv4Only,
|
|
wantV4: true,
|
|
wantV6: false,
|
|
},
|
|
{
|
|
name: "ipv6 only returns nil v4 and v6",
|
|
group: []*allregions.EdgeAddr{v4Addr, v6Addr},
|
|
ipVersion: allregions.IPv6Only,
|
|
wantV4: false,
|
|
wantV6: true,
|
|
},
|
|
{
|
|
name: "empty group returns nil for both",
|
|
group: []*allregions.EdgeAddr{},
|
|
ipVersion: allregions.Auto,
|
|
wantV4: false,
|
|
wantV6: false,
|
|
},
|
|
{
|
|
name: "only v4 available returns v4 and nil v6",
|
|
group: []*allregions.EdgeAddr{v4Addr},
|
|
ipVersion: allregions.Auto,
|
|
wantV4: true,
|
|
wantV6: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
gotV4, gotV6 := addrsByFamily(tt.group, tt.ipVersion)
|
|
if tt.wantV4 {
|
|
assert.NotNil(t, gotV4)
|
|
} else {
|
|
assert.Nil(t, gotV4)
|
|
}
|
|
if tt.wantV6 {
|
|
assert.NotNil(t, gotV6)
|
|
} else {
|
|
assert.Nil(t, gotV6)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// IPv6 address tests for probeQUIC.
|
|
|
|
func TestProbeQUIC_IPv6Address(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
mockConn := &mockQuicConnection{}
|
|
dialer := mocks.NewMockQUICDialer(ctrl)
|
|
dialer.EXPECT().DialQuic(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(mockConn, nil)
|
|
|
|
addr := createTestEdgeAddr("2001:db8::1", testEdgePort, allregions.V6)
|
|
logger := zerolog.New(nil)
|
|
|
|
result := probeQUIC(context.Background(), testTLSConfig, dialer, addr, &logger)
|
|
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
assert.Equal(t, detailsQUICHandshakeSuccessful, result.Details)
|
|
}
|
|
|
|
// IPv6 address tests for probeHTTP2.
|
|
|
|
func TestProbeHTTP2_IPv6Address(t *testing.T) {
|
|
t.Parallel()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
dialer := mocks.NewMockTCPDialer(ctrl)
|
|
dialer.EXPECT().DialEdge(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&net.TCPConn{}, nil)
|
|
|
|
addr := createTestEdgeAddr("2001:db8::1", testEdgePort, allregions.V6)
|
|
|
|
result := probeHTTP2(context.Background(), testTLSConfig, dialer, addr)
|
|
|
|
assert.Equal(t, Pass, result.ProbeStatus)
|
|
}
|
|
|
|
// resolveStaticEdge tests.
|
|
|
|
// TestResolveStaticEdge_SingleAddr verifies that a single resolvable --edge
|
|
// addr produces one group labeled with the original addr string.
|
|
func TestResolveStaticEdge_SingleAddr(t *testing.T) {
|
|
t.Parallel()
|
|
logger := zerolog.Nop()
|
|
targets := resolveStaticEdge([]string{"127.0.0.1:7844"}, &logger)
|
|
require.Len(t, targets, 1)
|
|
assert.Equal(t, "127.0.0.1:7844", targets[0].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[0].DNSResult.ProbeStatus)
|
|
assert.NotEmpty(t, targets[0].Addrs)
|
|
}
|
|
|
|
// TestResolveStaticEdge_MultipleAddrs verifies that multiple --edge addrs each
|
|
// produce their own ResolvedTarget, preserving per-addr structure and label order.
|
|
func TestResolveStaticEdge_MultipleAddrs(t *testing.T) {
|
|
t.Parallel()
|
|
logger := zerolog.Nop()
|
|
targets := resolveStaticEdge([]string{"127.0.0.1:7844", "127.0.0.2:7844"}, &logger)
|
|
require.Len(t, targets, 2)
|
|
assert.Equal(t, "127.0.0.1:7844", targets[0].DNSResult.Target)
|
|
assert.Equal(t, "127.0.0.2:7844", targets[1].DNSResult.Target)
|
|
}
|
|
|
|
// TestResolveStaticEdge_InvalidAddr verifies that an unresolvable addr is
|
|
// silently skipped and does not appear in the output.
|
|
func TestResolveStaticEdge_InvalidAddr(t *testing.T) {
|
|
t.Parallel()
|
|
logger := zerolog.Nop()
|
|
// "not-a-valid-addr" has no port — ResolveTCPAddr will fail.
|
|
targets := resolveStaticEdge([]string{"not-a-valid-addr"}, &logger)
|
|
require.Len(t, targets, 1)
|
|
assert.Equal(t, "not-a-valid-addr", targets[0].DNSResult.Target)
|
|
assert.Equal(t, Fail, targets[0].DNSResult.ProbeStatus)
|
|
assert.Equal(t, dnsNoAddressesReturned, targets[0].DNSResult.Details)
|
|
assert.Empty(t, targets[0].Addrs)
|
|
}
|
|
|
|
// TestResolveStaticEdge_PartiallyValid verifies that a mix of valid and invalid
|
|
// addrs produces one ResolvedTarget per addr — valid ones with Addrs and a Skip
|
|
// DNSResult, invalid ones with nil Addrs and a Fail DNSResult.
|
|
func TestResolveStaticEdge_PartiallyValid(t *testing.T) {
|
|
t.Parallel()
|
|
logger := zerolog.Nop()
|
|
targets := resolveStaticEdge([]string{"127.0.0.1:7844", "not-a-valid-addr", "127.0.0.2:7844"}, &logger)
|
|
require.Len(t, targets, 3)
|
|
assert.Equal(t, "127.0.0.1:7844", targets[0].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[0].DNSResult.ProbeStatus)
|
|
assert.NotEmpty(t, targets[0].Addrs)
|
|
assert.Equal(t, "not-a-valid-addr", targets[1].DNSResult.Target)
|
|
assert.Equal(t, Fail, targets[1].DNSResult.ProbeStatus)
|
|
assert.Empty(t, targets[1].Addrs)
|
|
assert.Equal(t, "127.0.0.2:7844", targets[2].DNSResult.Target)
|
|
assert.Equal(t, Pass, targets[2].DNSResult.ProbeStatus)
|
|
assert.NotEmpty(t, targets[2].Addrs)
|
|
}
|