diff --git a/internal/provider/expressvpn/connection_test.go b/internal/provider/expressvpn/connection_test.go index ecd3b884..d0e71413 100644 --- a/internal/provider/expressvpn/connection_test.go +++ b/internal/provider/expressvpn/connection_test.go @@ -24,10 +24,10 @@ func Test_Provider_GetConnection(t *testing.T) { errWrapped error errMessage string }{ - "no server available": { + "no server": { selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), - errWrapped: utils.ErrNoServerFound, - errMessage: "cannot filter servers: no server found: for VPN openvpn; protocol udp", + errWrapped: utils.ErrNoServer, + errMessage: "no server", }, "no filter": { servers: []models.Server{ diff --git a/internal/provider/ivpn/connection_test.go b/internal/provider/ivpn/connection_test.go index 451cda4b..0b0a830d 100644 --- a/internal/provider/ivpn/connection_test.go +++ b/internal/provider/ivpn/connection_test.go @@ -26,8 +26,8 @@ func Test_Ivpn_GetConnection(t *testing.T) { }{ "no server available": { selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), - errWrapped: utils.ErrNoServerFound, - errMessage: "cannot filter servers: no server found: for VPN openvpn; protocol udp", + errWrapped: utils.ErrNoServer, + errMessage: "no server", }, "no filter": { servers: []models.Server{ diff --git a/internal/provider/mullvad/connection_test.go b/internal/provider/mullvad/connection_test.go index 15c35650..0cf202e5 100644 --- a/internal/provider/mullvad/connection_test.go +++ b/internal/provider/mullvad/connection_test.go @@ -26,8 +26,8 @@ func Test_Mullvad_GetConnection(t *testing.T) { }{ "no server available": { selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), - errWrapped: utils.ErrNoServerFound, - errMessage: "cannot filter servers: no server found: for VPN openvpn; protocol udp", + errWrapped: utils.ErrNoServer, + errMessage: "no server", }, "no filter": { servers: []models.Server{ diff --git a/internal/provider/utils/connection.go b/internal/provider/utils/connection.go index 6244c144..140e4e19 100644 --- a/internal/provider/utils/connection.go +++ b/internal/provider/utils/connection.go @@ -1,7 +1,7 @@ package utils import ( - "fmt" + "errors" "math/rand" "github.com/qdm12/gluetun/internal/configuration/settings" @@ -24,14 +24,20 @@ func NewConnectionDefaults(openvpnTCPPort, openvpnUDPPort, } } +var ErrNoServer = errors.New("no server") + func GetConnection(servers []models.Server, selection settings.ServerSelection, defaults ConnectionDefaults, randSource rand.Source) ( connection models.Connection, err error) { - servers, err = FilterServers(servers, selection) - if err != nil { - return connection, fmt.Errorf("cannot filter servers: %w", err) + if len(servers) == 0 { + return connection, ErrNoServer + } + + servers = FilterServers(servers, selection) + if len(servers) == 0 { + return connection, NoServerFoundError(selection) } protocol := getProtocol(selection) diff --git a/internal/provider/utils/connection_test.go b/internal/provider/utils/connection_test.go index 4e08758c..937fa7fa 100644 --- a/internal/provider/utils/connection_test.go +++ b/internal/provider/utils/connection_test.go @@ -1,9 +1,184 @@ package utils -import "testing" +import ( + "math/rand" + "net" + "testing" + + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/constants" + "github.com/qdm12/gluetun/internal/constants/providers" + "github.com/qdm12/gluetun/internal/constants/vpn" + "github.com/qdm12/gluetun/internal/models" + "github.com/stretchr/testify/assert" +) func Test_GetConnection(t *testing.T) { t.Parallel() - // testCases := map[string]struct{}{} + testCases := map[string]struct { + servers []models.Server + serverSelection settings.ServerSelection + defaults ConnectionDefaults + randSource rand.Source + connection models.Connection + errWrapped error + errMessage string + }{ + "no server": { + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + errWrapped: ErrNoServer, + errMessage: "no server", + }, + "all servers filtered": { + servers: []models.Server{ + {VPN: vpn.Wireguard}, + {VPN: vpn.Wireguard}, + }, + serverSelection: settings.ServerSelection{ + VPN: vpn.OpenVPN, + }.WithDefaults(providers.Mullvad), + errWrapped: ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", + }, + "server without IPs": { + servers: []models.Server{ + {VPN: vpn.OpenVPN, UDP: true}, + {VPN: vpn.OpenVPN, UDP: true}, + }, + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + defaults: ConnectionDefaults{ + OpenVPNTCPPort: 1, + OpenVPNUDPPort: 1, + WireguardPort: 1, + }, + errWrapped: ErrNoConnectionToPickFrom, + errMessage: "no connection to pick from", + }, + "OpenVPN server with hostname": { + servers: []models.Server{ + { + VPN: vpn.OpenVPN, + UDP: true, + IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, + Hostname: "name", + }, + }, + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + defaults: NewConnectionDefaults(443, 1194, 58820), + randSource: rand.NewSource(0), + connection: models.Connection{ + Type: vpn.OpenVPN, + IP: net.IPv4(1, 1, 1, 1), + Protocol: constants.UDP, + Port: 1194, + Hostname: "name", + }, + }, + "OpenVPN server with x509": { + servers: []models.Server{ + { + VPN: vpn.OpenVPN, + UDP: true, + IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, + Hostname: "hostname", + OvpnX509: "x509", + }, + }, + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + defaults: NewConnectionDefaults(443, 1194, 58820), + randSource: rand.NewSource(0), + connection: models.Connection{ + Type: vpn.OpenVPN, + IP: net.IPv4(1, 1, 1, 1), + Protocol: constants.UDP, + Port: 1194, + Hostname: "x509", + }, + }, + "server with IPv4 and IPv6": { + servers: []models.Server{ + { + VPN: vpn.OpenVPN, + UDP: true, + IPs: []net.IP{ + net.IPv4(1, 1, 1, 1), + // All IPv6 is ignored + net.IPv6zero, + net.IPv6zero, + net.IPv6zero, + net.IPv6zero, + net.IPv6zero, + }, + }, + }, + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + defaults: NewConnectionDefaults(443, 1194, 58820), + randSource: rand.NewSource(0), + connection: models.Connection{ + Type: vpn.OpenVPN, + IP: net.IPv4(1, 1, 1, 1), + Protocol: constants.UDP, + Port: 1194, + }, + }, + "mixed servers": { + servers: []models.Server{ + { + VPN: vpn.OpenVPN, + UDP: true, + IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, + OvpnX509: "ovpnx509", + }, + { + VPN: vpn.Wireguard, + UDP: true, + IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, + OvpnX509: "ovpnx509", + }, + { + VPN: vpn.OpenVPN, + UDP: true, + IPs: []net.IP{ + net.IPv4(3, 3, 3, 3), + {1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, // ipv6 ignored + }, + Hostname: "hostname", + }, + }, + serverSelection: settings.ServerSelection{}. + WithDefaults(providers.Mullvad), + defaults: NewConnectionDefaults(443, 1194, 58820), + randSource: rand.NewSource(0), + connection: models.Connection{ + Type: vpn.OpenVPN, + IP: net.IPv4(1, 1, 1, 1), + Protocol: constants.UDP, + Port: 1194, + Hostname: "ovpnx509", + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + t.Run(name, func(t *testing.T) { + t.Parallel() + + connection, err := GetConnection(testCase.servers, + testCase.serverSelection, testCase.defaults, + testCase.randSource) + + assert.Equal(t, testCase.connection, connection) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) + } + }) + } } diff --git a/internal/provider/utils/filtering.go b/internal/provider/utils/filtering.go index 2d455d9a..b6648d16 100644 --- a/internal/provider/utils/filtering.go +++ b/internal/provider/utils/filtering.go @@ -8,9 +8,7 @@ import ( ) func FilterServers(servers []models.Server, - selection settings.ServerSelection) ( - filtered []models.Server, err error, -) { + selection settings.ServerSelection) (filtered []models.Server) { for _, server := range servers { if filterServer(server, selection) { continue @@ -19,11 +17,7 @@ func FilterServers(servers []models.Server, filtered = append(filtered, server) } - if len(filtered) == 0 { - return nil, NoServerFoundError(selection) - } - - return filtered, nil + return filtered } func filterServer(server models.Server, diff --git a/internal/provider/utils/filtering_test.go b/internal/provider/utils/filtering_test.go index 5247caf5..5fd6c4de 100644 --- a/internal/provider/utils/filtering_test.go +++ b/internal/provider/utils/filtering_test.go @@ -14,16 +14,12 @@ func Test_FilterServers(t *testing.T) { t.Parallel() testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - errMessage string - errWrapped error + servers []models.Server + selection settings.ServerSelection + filtered []models.Server }{ "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), - errMessage: "no server found: for VPN openvpn; protocol udp", - errWrapped: ErrNoServerFound, + selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), }, "no filter": { servers: []models.Server{ @@ -216,12 +212,7 @@ func Test_FilterServers(t *testing.T) { t.Run(name, func(t *testing.T) { t.Parallel() - filtered, err := FilterServers(testCase.servers, testCase.selection) - - assert.ErrorIs(t, err, testCase.errWrapped) - if testCase.errWrapped != nil { - assert.EqualError(t, err, testCase.errMessage) - } + filtered := FilterServers(testCase.servers, testCase.selection) assert.Equal(t, testCase.filtered, filtered) }) diff --git a/internal/provider/wevpn/connection_test.go b/internal/provider/wevpn/connection_test.go index 709d2421..f04be81a 100644 --- a/internal/provider/wevpn/connection_test.go +++ b/internal/provider/wevpn/connection_test.go @@ -28,8 +28,8 @@ func Test_Wevpn_GetConnection(t *testing.T) { selection: settings.ServerSelection{ VPN: vpn.OpenVPN, }.WithDefaults(providers.Wevpn), - errWrapped: utils.ErrNoServerFound, - errMessage: "cannot filter servers: no server found: for VPN openvpn; protocol udp", + errWrapped: utils.ErrNoServer, + errMessage: "no server", }, "no filter": { servers: []models.Server{ diff --git a/internal/provider/windscribe/connection_test.go b/internal/provider/windscribe/connection_test.go index 6ff61ec6..baed3081 100644 --- a/internal/provider/windscribe/connection_test.go +++ b/internal/provider/windscribe/connection_test.go @@ -26,8 +26,8 @@ func Test_Windscribe_GetConnection(t *testing.T) { }{ "no server available": { selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), - errWrapped: utils.ErrNoServerFound, - errMessage: "cannot filter servers: no server found: for VPN openvpn; protocol udp", + errWrapped: utils.ErrNoServer, + errMessage: "no server", }, "no filter": { servers: []models.Server{