diff --git a/internal/provider/cyberghost/connection.go b/internal/provider/cyberghost/connection.go index c6467e5f..961610c6 100644 --- a/internal/provider/cyberghost/connection.go +++ b/internal/provider/cyberghost/connection.go @@ -15,7 +15,7 @@ func (c *Cyberghost) GetConnection(selection settings.ServerSelection) ( protocol = constants.TCP } - servers, err := c.filterServers(selection) + servers, err := utils.FilterServers(c.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/cyberghost/filter.go b/internal/provider/cyberghost/filter.go deleted file mode 100644 index 57ffb7e8..00000000 --- a/internal/provider/cyberghost/filter.go +++ /dev/null @@ -1,31 +0,0 @@ -package cyberghost - -import ( - "errors" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -var ErrGroupMismatchesProtocol = errors.New("server group does not match protocol") - -func (c *Cyberghost) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range c.servers { - switch { - case - utils.FilterByProtocol(selection, server.TCP, server.UDP), - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/cyberghost/filter_test.go b/internal/provider/cyberghost/filter_test.go deleted file mode 100644 index 6d36169e..00000000 --- a/internal/provider/cyberghost/filter_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package cyberghost - -import ( - "errors" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/constants/providers" - "github.com/qdm12/gluetun/internal/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Cyberghost_filterServers(t *testing.T) { - t.Parallel() - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filteredServers []models.Server - err error - }{ - "no server": { - selection: settings.ServerSelection{}.WithDefaults(providers.Cyberghost), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "servers without filter defaults to UDP": { - servers: []models.Server{ - {Country: "a", TCP: true}, - {Country: "b", TCP: true}, - {Country: "c", UDP: true}, - {Country: "d", UDP: true}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Cyberghost), - filteredServers: []models.Server{ - {Country: "c", UDP: true}, - {Country: "d", UDP: true}, - }, - }, - "servers with TCP selection": { - servers: []models.Server{ - {Country: "a", TCP: true}, - {Country: "b", TCP: true}, - {Country: "c", UDP: true}, - {Country: "d", UDP: true}, - }, - selection: settings.ServerSelection{ - OpenVPN: settings.OpenVPNSelection{ - TCP: boolPtr(true), - }, - }.WithDefaults(providers.Cyberghost), - filteredServers: []models.Server{ - {Country: "a", TCP: true}, - {Country: "b", TCP: true}, - }, - }, - "servers with regions filter": { - servers: []models.Server{ - {Country: "a", UDP: true}, - {Country: "b", UDP: true}, - {Country: "c", UDP: true}, - {Country: "d", UDP: true}, - }, - selection: settings.ServerSelection{ - Countries: []string{"a", "c"}, - }.WithDefaults(providers.Cyberghost), - filteredServers: []models.Server{ - {Country: "a", UDP: true}, - {Country: "c", UDP: true}, - }, - }, - "servers with hostnames filter": { - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - selection: settings.ServerSelection{ - Hostnames: []string{"a", "c"}, - }.WithDefaults(providers.Cyberghost), - filteredServers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "c", UDP: true}, - }, - }, - } - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - c := &Cyberghost{servers: testCase.servers} - filteredServers, err := c.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filteredServers, filteredServers) - }) - } -} diff --git a/internal/provider/expressvpn/connection.go b/internal/provider/expressvpn/connection.go index f9a13514..56b85604 100644 --- a/internal/provider/expressvpn/connection.go +++ b/internal/provider/expressvpn/connection.go @@ -11,7 +11,7 @@ func (p *Provider) GetConnection(selection settings.ServerSelection) ( port := getPort(selection) protocol := utils.GetProtocol(selection) - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/expressvpn/connection_test.go b/internal/provider/expressvpn/connection_test.go index f53d6a7a..78a68bda 100644 --- a/internal/provider/expressvpn/connection_test.go +++ b/internal/provider/expressvpn/connection_test.go @@ -1,7 +1,6 @@ package expressvpn import ( - "errors" "math/rand" "net" "testing" @@ -11,8 +10,8 @@ import ( "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider/utils" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func Test_Provider_GetConnection(t *testing.T) { @@ -22,17 +21,19 @@ func Test_Provider_GetConnection(t *testing.T) { servers []models.Server selection settings.ServerSelection connection models.Connection - err error + errWrapped error + errMessage string }{ "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), + selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), + errWrapped: utils.ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", }, "no filter": { servers: []models.Server{ - {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), connection: models.Connection{ @@ -47,9 +48,9 @@ func Test_Provider_GetConnection(t *testing.T) { TargetIP: net.IPv4(2, 2, 2, 2), }.WithDefaults(providers.Expressvpn), servers: []models.Server{ - {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -63,9 +64,9 @@ func Test_Provider_GetConnection(t *testing.T) { Hostnames: []string{"b"}, }.WithDefaults(providers.Expressvpn), servers: []models.Server{ - {Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -88,11 +89,9 @@ func Test_Provider_GetConnection(t *testing.T) { connection, err := m.GetConnection(testCase.selection) - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) } assert.Equal(t, testCase.connection, connection) diff --git a/internal/provider/expressvpn/filter.go b/internal/provider/expressvpn/filter.go deleted file mode 100644 index 94ca0a23..00000000 --- a/internal/provider/expressvpn/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package expressvpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Provider) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/expressvpn/filter_test.go b/internal/provider/expressvpn/filter_test.go deleted file mode 100644 index 4e4e6b7a..00000000 --- a/internal/provider/expressvpn/filter_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package expressvpn - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/constants/providers" - "github.com/qdm12/gluetun/internal/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Expressvpn_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Expressvpn), - filtered: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - }, - "filter by country": { - selection: settings.ServerSelection{ - Countries: []string{"b"}, - }.WithDefaults(providers.Expressvpn), - servers: []models.Server{ - {Country: "a", UDP: true}, - {Country: "b", UDP: true}, - {Country: "c", UDP: true}, - }, - filtered: []models.Server{ - {Country: "b", UDP: true}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Expressvpn), - servers: []models.Server{ - {City: "a", UDP: true}, - {City: "b", UDP: true}, - {City: "c", UDP: true}, - }, - filtered: []models.Server{ - {City: "b", UDP: true}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Expressvpn), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", UDP: true}, - }, - }, - "filter by protocol": { - selection: settings.ServerSelection{ - OpenVPN: settings.OpenVPNSelection{ - TCP: boolPtr(true), - }, - }.WithDefaults(providers.Expressvpn), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true, TCP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", UDP: true, TCP: true}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - m := New(testCase.servers, randSource) - - servers, err := m.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -} diff --git a/internal/provider/fastestvpn/connection.go b/internal/provider/fastestvpn/connection.go index bcd240e8..92379be9 100644 --- a/internal/provider/fastestvpn/connection.go +++ b/internal/provider/fastestvpn/connection.go @@ -15,7 +15,7 @@ func (f *Fastestvpn) GetConnection(selection settings.ServerSelection) ( protocol = constants.TCP } - servers, err := f.filterServers(selection) + servers, err := utils.FilterServers(f.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/fastestvpn/filter.go b/internal/provider/fastestvpn/filter.go deleted file mode 100644 index 6f635449..00000000 --- a/internal/provider/fastestvpn/filter.go +++ /dev/null @@ -1,27 +0,0 @@ -package fastestvpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (f *Fastestvpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range f.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/hidemyass/connection.go b/internal/provider/hidemyass/connection.go index 6844f4c0..4c9c2004 100644 --- a/internal/provider/hidemyass/connection.go +++ b/internal/provider/hidemyass/connection.go @@ -20,7 +20,7 @@ func (h *HideMyAss) GetConnection(selection settings.ServerSelection) ( port = *selection.OpenVPN.CustomPort } - servers, err := h.filterServers(selection) + servers, err := utils.FilterServers(h.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/hidemyass/filter.go b/internal/provider/hidemyass/filter.go deleted file mode 100644 index ccb24304..00000000 --- a/internal/provider/hidemyass/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package hidemyass - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (h *HideMyAss) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range h.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/ipvanish/connection.go b/internal/provider/ipvanish/connection.go index 5133c4ec..871be42c 100644 --- a/internal/provider/ipvanish/connection.go +++ b/internal/provider/ipvanish/connection.go @@ -12,7 +12,7 @@ func (i *Ipvanish) GetConnection(selection settings.ServerSelection) ( const port = 443 const protocol = constants.UDP - servers, err := i.filterServers(selection) + servers, err := utils.FilterServers(i.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/ipvanish/filter.go b/internal/provider/ipvanish/filter.go deleted file mode 100644 index 99353d8a..00000000 --- a/internal/provider/ipvanish/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package ipvanish - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (i *Ipvanish) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range i.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/ivpn/connection.go b/internal/provider/ivpn/connection.go index d50fd2ee..cee40761 100644 --- a/internal/provider/ivpn/connection.go +++ b/internal/provider/ivpn/connection.go @@ -11,7 +11,7 @@ func (i *Ivpn) GetConnection(selection settings.ServerSelection) ( port := getPort(selection) protocol := utils.GetProtocol(selection) - servers, err := i.filterServers(selection) + servers, err := utils.FilterServers(i.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/ivpn/connection_test.go b/internal/provider/ivpn/connection_test.go index 6e6bf813..66974df0 100644 --- a/internal/provider/ivpn/connection_test.go +++ b/internal/provider/ivpn/connection_test.go @@ -1,7 +1,6 @@ package ivpn import ( - "errors" "math/rand" "net" "testing" @@ -11,8 +10,8 @@ import ( "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider/utils" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func Test_Ivpn_GetConnection(t *testing.T) { @@ -22,17 +21,19 @@ func Test_Ivpn_GetConnection(t *testing.T) { servers []models.Server selection settings.ServerSelection connection models.Connection - err error + errWrapped error + errMessage string }{ "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), + selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), + errWrapped: utils.ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", }, "no filter": { servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), connection: models.Connection{ @@ -47,9 +48,9 @@ func Test_Ivpn_GetConnection(t *testing.T) { TargetIP: net.IPv4(2, 2, 2, 2), }.WithDefaults(providers.Ivpn), servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -63,9 +64,9 @@ func Test_Ivpn_GetConnection(t *testing.T) { Hostnames: []string{"b"}, }.WithDefaults(providers.Ivpn), servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -88,11 +89,9 @@ func Test_Ivpn_GetConnection(t *testing.T) { connection, err := m.GetConnection(testCase.selection) - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) } assert.Equal(t, testCase.connection, connection) diff --git a/internal/provider/ivpn/filter.go b/internal/provider/ivpn/filter.go deleted file mode 100644 index 29a33536..00000000 --- a/internal/provider/ivpn/filter.go +++ /dev/null @@ -1,30 +0,0 @@ -package ivpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (i *Ivpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range i.servers { - switch { - case - server.VPN != selection.VPN, - utils.FilterByPossibilities(server.ISP, selection.ISPs), - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/ivpn/filter_test.go b/internal/provider/ivpn/filter_test.go deleted file mode 100644 index b6f6088b..00000000 --- a/internal/provider/ivpn/filter_test.go +++ /dev/null @@ -1,134 +0,0 @@ -package ivpn - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "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" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Ivpn_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Ivpn), - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, - }, - }, - "filter by country": { - selection: settings.ServerSelection{ - Countries: []string{"b"}, - }.WithDefaults(providers.Ivpn), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Country: "a", UDP: true}, - {VPN: vpn.OpenVPN, Country: "b", UDP: true}, - {VPN: vpn.OpenVPN, Country: "c", UDP: true}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Country: "b", UDP: true}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Ivpn), - servers: []models.Server{ - {VPN: vpn.OpenVPN, City: "a", UDP: true}, - {VPN: vpn.OpenVPN, City: "b", UDP: true}, - {VPN: vpn.OpenVPN, City: "c", UDP: true}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, City: "b", UDP: true}, - }, - }, - "filter by ISP": { - selection: settings.ServerSelection{ - ISPs: []string{"b"}, - }.WithDefaults(providers.Ivpn), - servers: []models.Server{ - {VPN: vpn.OpenVPN, ISP: "a", UDP: true}, - {VPN: vpn.OpenVPN, ISP: "b", UDP: true}, - {VPN: vpn.OpenVPN, ISP: "c", UDP: true}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, ISP: "b", UDP: true}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Ivpn), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, - }, - }, - "filter by protocol": { - selection: settings.ServerSelection{ - OpenVPN: settings.OpenVPNSelection{ - TCP: boolPtr(true), - }, - }.WithDefaults(providers.Ivpn), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true, TCP: true}, - {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "b", UDP: true, TCP: true}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - m := New(testCase.servers, randSource) - - servers, err := m.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -} diff --git a/internal/provider/mullvad/connection.go b/internal/provider/mullvad/connection.go index 43be4241..17ff0d57 100644 --- a/internal/provider/mullvad/connection.go +++ b/internal/provider/mullvad/connection.go @@ -11,7 +11,7 @@ func (m *Mullvad) GetConnection(selection settings.ServerSelection) ( port := getPort(selection) protocol := utils.GetProtocol(selection) - servers, err := m.filterServers(selection) + servers, err := utils.FilterServers(m.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/mullvad/connection_test.go b/internal/provider/mullvad/connection_test.go index d90c9fab..44bd9e77 100644 --- a/internal/provider/mullvad/connection_test.go +++ b/internal/provider/mullvad/connection_test.go @@ -1,7 +1,6 @@ package mullvad import ( - "errors" "math/rand" "net" "testing" @@ -11,8 +10,8 @@ import ( "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider/utils" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func Test_Mullvad_GetConnection(t *testing.T) { @@ -22,17 +21,19 @@ func Test_Mullvad_GetConnection(t *testing.T) { servers []models.Server selection settings.ServerSelection connection models.Connection - err error + errWrapped error + errMessage string }{ "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), - err: errors.New("no server found: for VPN openvpn; protocol udp"), + selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), + errWrapped: utils.ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", }, "no filter": { servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, }, selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), connection: models.Connection{ @@ -47,9 +48,9 @@ func Test_Mullvad_GetConnection(t *testing.T) { TargetIP: net.IPv4(2, 2, 2, 2), }.WithDefaults(providers.Mullvad), servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -63,9 +64,9 @@ func Test_Mullvad_GetConnection(t *testing.T) { Hostnames: []string{"b"}, }.WithDefaults(providers.Mullvad), servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {VPN: vpn.OpenVPN, UDP: true, Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, + {VPN: vpn.OpenVPN, UDP: true, Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, + {VPN: vpn.OpenVPN, UDP: true, Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -87,11 +88,9 @@ func Test_Mullvad_GetConnection(t *testing.T) { connection, err := m.GetConnection(testCase.selection) - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) } assert.Equal(t, testCase.connection, connection) diff --git a/internal/provider/mullvad/filter.go b/internal/provider/mullvad/filter.go deleted file mode 100644 index 511d5baf..00000000 --- a/internal/provider/mullvad/filter.go +++ /dev/null @@ -1,30 +0,0 @@ -package mullvad - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (m *Mullvad) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range m.servers { - switch { - case - server.VPN != selection.VPN, - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.ISP, selection.ISPs), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - *selection.OwnedOnly && !server.Owned: - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/mullvad/filter_test.go b/internal/provider/mullvad/filter_test.go deleted file mode 100644 index f63ddb27..00000000 --- a/internal/provider/mullvad/filter_test.go +++ /dev/null @@ -1,145 +0,0 @@ -package mullvad - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "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" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Mullvad_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - }, - "filter OpenVPN out": { - selection: settings.ServerSelection{ - VPN: vpn.Wireguard, - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.Wireguard, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.Wireguard, Hostname: "b"}, - }, - }, - "filter by country": { - selection: settings.ServerSelection{ - Countries: []string{"b"}, - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Country: "a"}, - {VPN: vpn.OpenVPN, Country: "b"}, - {VPN: vpn.OpenVPN, Country: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Country: "b"}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, City: "a"}, - {VPN: vpn.OpenVPN, City: "b"}, - {VPN: vpn.OpenVPN, City: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, City: "b"}, - }, - }, - "filter by ISP": { - selection: settings.ServerSelection{ - ISPs: []string{"b"}, - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, ISP: "a"}, - {VPN: vpn.OpenVPN, ISP: "b"}, - {VPN: vpn.OpenVPN, ISP: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, ISP: "b"}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "b"}, - }, - }, - "filter by owned": { - selection: settings.ServerSelection{ - OwnedOnly: boolPtr(true), - }.WithDefaults(providers.Mullvad), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b", Owned: true}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "b", Owned: true}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - m := New(testCase.servers, randSource) - - servers, err := m.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -} diff --git a/internal/provider/nordvpn/connection.go b/internal/provider/nordvpn/connection.go index e969ce5e..fc21bf6b 100644 --- a/internal/provider/nordvpn/connection.go +++ b/internal/provider/nordvpn/connection.go @@ -16,7 +16,7 @@ func (n *Nordvpn) GetConnection(selection settings.ServerSelection) ( protocol = constants.TCP } - servers, err := n.filterServers(selection) + servers, err := utils.FilterServers(n.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/nordvpn/filter.go b/internal/provider/nordvpn/filter.go deleted file mode 100644 index a27bdc4e..00000000 --- a/internal/provider/nordvpn/filter.go +++ /dev/null @@ -1,36 +0,0 @@ -package nordvpn - -import ( - "strconv" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (n *Nordvpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - selectedNumbers := make([]string, len(selection.Numbers)) - for i := range selection.Numbers { - selectedNumbers[i] = strconv.Itoa(int(selection.Numbers[i])) - } - - for _, server := range n.servers { - serverNumber := strconv.Itoa(int(server.Number)) - switch { - case - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByPossibilities(serverNumber, selectedNumbers), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/perfectprivacy/connection.go b/internal/provider/perfectprivacy/connection.go index b2a59aea..da571d04 100644 --- a/internal/provider/perfectprivacy/connection.go +++ b/internal/provider/perfectprivacy/connection.go @@ -15,7 +15,7 @@ func (p *Perfectprivacy) GetConnection(selection settings.ServerSelection) ( } protocol := utils.GetProtocol(selection) - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/perfectprivacy/filter.go b/internal/provider/perfectprivacy/filter.go deleted file mode 100644 index 1c5b2c30..00000000 --- a/internal/provider/perfectprivacy/filter.go +++ /dev/null @@ -1,26 +0,0 @@ -package perfectprivacy - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Perfectprivacy) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/privado/connection.go b/internal/provider/privado/connection.go index 65d158b4..f84b4e70 100644 --- a/internal/provider/privado/connection.go +++ b/internal/provider/privado/connection.go @@ -12,7 +12,7 @@ func (p *Privado) GetConnection(selection settings.ServerSelection) ( const port = 1194 const protocol = constants.UDP - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/privado/filter.go b/internal/provider/privado/filter.go deleted file mode 100644 index 5d3a30e9..00000000 --- a/internal/provider/privado/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package privado - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Privado) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/privateinternetaccess/connection.go b/internal/provider/privateinternetaccess/connection.go index fc465080..567a8017 100644 --- a/internal/provider/privateinternetaccess/connection.go +++ b/internal/provider/privateinternetaccess/connection.go @@ -19,7 +19,7 @@ func (p *PIA) GetConnection(selection settings.ServerSelection) ( return connection, err } - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/privateinternetaccess/filter.go b/internal/provider/privateinternetaccess/filter.go deleted file mode 100644 index 82f0c786..00000000 --- a/internal/provider/privateinternetaccess/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package privateinternetaccess - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *PIA) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByPossibilities(server.ServerName, selection.Names), // TODO remove in v4 - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/privatevpn/connection.go b/internal/provider/privatevpn/connection.go index 05857eba..d6efa89d 100644 --- a/internal/provider/privatevpn/connection.go +++ b/internal/provider/privatevpn/connection.go @@ -19,7 +19,7 @@ func (p *Privatevpn) GetConnection(selection settings.ServerSelection) ( port = *selection.OpenVPN.CustomPort } - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/privatevpn/filter.go b/internal/provider/privatevpn/filter.go deleted file mode 100644 index de1e1309..00000000 --- a/internal/provider/privatevpn/filter.go +++ /dev/null @@ -1,27 +0,0 @@ -package privatevpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Privatevpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/protonvpn/connection.go b/internal/provider/protonvpn/connection.go index 9259be79..727505e0 100644 --- a/internal/provider/protonvpn/connection.go +++ b/internal/provider/protonvpn/connection.go @@ -19,7 +19,7 @@ func (p *Protonvpn) GetConnection(selection settings.ServerSelection) ( return connection, err } - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/protonvpn/filter.go b/internal/provider/protonvpn/filter.go deleted file mode 100644 index 9f23b163..00000000 --- a/internal/provider/protonvpn/filter.go +++ /dev/null @@ -1,32 +0,0 @@ -package protonvpn - -import ( - "strings" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Protonvpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByPossibilities(server.ServerName, selection.Names), // TODO remove in v4 - *selection.FreeOnly && !strings.Contains(strings.ToLower(server.ServerName), "free"): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/purevpn/connection.go b/internal/provider/purevpn/connection.go index f1350f0a..e84e2c51 100644 --- a/internal/provider/purevpn/connection.go +++ b/internal/provider/purevpn/connection.go @@ -16,7 +16,7 @@ func (p *Purevpn) GetConnection(selection settings.ServerSelection) ( port = 80 } - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/purevpn/filter.go b/internal/provider/purevpn/filter.go deleted file mode 100644 index 58c7a344..00000000 --- a/internal/provider/purevpn/filter.go +++ /dev/null @@ -1,29 +0,0 @@ -package purevpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Purevpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/surfshark/connection.go b/internal/provider/surfshark/connection.go index 2947d6f6..f1ea078f 100644 --- a/internal/provider/surfshark/connection.go +++ b/internal/provider/surfshark/connection.go @@ -16,7 +16,7 @@ func (s *Surfshark) GetConnection(selection settings.ServerSelection) ( port = 1443 } - servers, err := s.filterServers(selection) + servers, err := utils.FilterServers(s.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/surfshark/filter.go b/internal/provider/surfshark/filter.go deleted file mode 100644 index c4e8e0c3..00000000 --- a/internal/provider/surfshark/filter.go +++ /dev/null @@ -1,30 +0,0 @@ -package surfshark - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (s *Surfshark) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range s.servers { - switch { - case - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP), - *selection.MultiHopOnly && !server.MultiHop: - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/surfshark/filter_test.go b/internal/provider/surfshark/filter_test.go deleted file mode 100644 index ad24e271..00000000 --- a/internal/provider/surfshark/filter_test.go +++ /dev/null @@ -1,146 +0,0 @@ -package surfshark - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/constants/providers" - "github.com/qdm12/gluetun/internal/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Surfshark_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Surfshark), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Surfshark), - filtered: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - }, - "filter by region": { - selection: settings.ServerSelection{ - Regions: []string{"b"}, - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {Region: "a", UDP: true}, - {Region: "b", UDP: true}, - {Region: "c", UDP: true}, - }, - filtered: []models.Server{ - {Region: "b", UDP: true}, - }, - }, - "filter by country": { - selection: settings.ServerSelection{ - Countries: []string{"b"}, - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {Country: "a", UDP: true}, - {Country: "b", UDP: true}, - {Country: "c", UDP: true}, - }, - filtered: []models.Server{ - {Country: "b", UDP: true}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {City: "a", UDP: true}, - {City: "b", UDP: true}, - {City: "c", UDP: true}, - }, - filtered: []models.Server{ - {City: "b", UDP: true}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", UDP: true}, - }, - }, - "filter by protocol": { - selection: settings.ServerSelection{ - OpenVPN: settings.OpenVPNSelection{ - TCP: boolPtr(true), - }, - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true, TCP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", UDP: true, TCP: true}, - }, - }, - "filter by multihop only": { - selection: settings.ServerSelection{ - MultiHopOnly: boolPtr(true), - }.WithDefaults(providers.Surfshark), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", MultiHop: true, UDP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", MultiHop: true, UDP: true}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - s := New(testCase.servers, randSource) - - servers, err := s.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -} diff --git a/internal/provider/torguard/connection.go b/internal/provider/torguard/connection.go index 01365d62..3202b408 100644 --- a/internal/provider/torguard/connection.go +++ b/internal/provider/torguard/connection.go @@ -19,7 +19,7 @@ func (t *Torguard) GetConnection(selection settings.ServerSelection) ( port = *selection.OpenVPN.CustomPort } - servers, err := t.filterServers(selection) + servers, err := utils.FilterServers(t.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/torguard/filter.go b/internal/provider/torguard/filter.go deleted file mode 100644 index 2b793364..00000000 --- a/internal/provider/torguard/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package torguard - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (t *Torguard) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range t.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/utils/filtering.go b/internal/provider/utils/filtering.go index 268536b2..a992c60a 100644 --- a/internal/provider/utils/filtering.go +++ b/internal/provider/utils/filtering.go @@ -1,8 +1,93 @@ package utils -import "strings" +import ( + "strings" -func FilterByPossibilities(value string, possibilities []string) (filtered bool) { + "github.com/qdm12/gluetun/internal/configuration/settings" + "github.com/qdm12/gluetun/internal/models" +) + +func FilterServers(servers []models.Server, + selection settings.ServerSelection) ( + filtered []models.Server, err error, +) { + for _, server := range servers { + if filterServer(server, selection) { + continue + } + + filtered = append(filtered, server) + } + + if len(filtered) == 0 { + return nil, NoServerFoundError(selection) + } + + return filtered, nil +} + +func filterServer(server models.Server, + selection settings.ServerSelection) (filtered bool) { + // Note each condition is split to make sure + // we have full testing coverage. + if server.VPN != selection.VPN { + return true + } + + if FilterByProtocol(selection, server.TCP, server.UDP) { + return true + } + + if *selection.MultiHopOnly && !server.MultiHop { + return true + } + + if *selection.FreeOnly && !server.Free { + return true + } + + if *selection.StreamOnly && !server.Stream { + return true + } + + if *selection.OwnedOnly && !server.Owned { + return true + } + + if filterByPossibilities(server.Country, selection.Countries) { + return true + } + + if filterByPossibilities(server.Region, selection.Regions) { + return true + } + + if filterByPossibilities(server.City, selection.Cities) { + return true + } + + if filterByPossibilities(server.ISP, selection.ISPs) { + return true + } + + if filterByPossibilitiesUint16(server.Number, selection.Numbers) { + return true + } + + if filterByPossibilities(server.ServerName, selection.Names) { + return true + } + + if filterByPossibilities(server.Hostname, selection.Hostnames) { + return true + } + + // TODO filter port forward server for PIA + + return false +} + +func filterByPossibilities(value string, possibilities []string) (filtered bool) { if len(possibilities) == 0 { return false } @@ -13,3 +98,16 @@ func FilterByPossibilities(value string, possibilities []string) (filtered bool) } return true } + +// TODO merge with filterByPossibilities with generics in Go 1.18. +func filterByPossibilitiesUint16(value uint16, possibilities []uint16) (filtered bool) { + if len(possibilities) == 0 { + return false + } + for _, possibility := range possibilities { + if value == possibility { + return false + } + } + return true +} diff --git a/internal/provider/utils/filtering_test.go b/internal/provider/utils/filtering_test.go index 1f74cfde..5247caf5 100644 --- a/internal/provider/utils/filtering_test.go +++ b/internal/provider/utils/filtering_test.go @@ -3,10 +3,232 @@ package utils import ( "testing" + "github.com/qdm12/gluetun/internal/configuration/settings" + "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_FilterByPossibilities(t *testing.T) { +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 + }{ + "no server available": { + selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), + errMessage: "no server found: for VPN openvpn; protocol udp", + errWrapped: ErrNoServerFound, + }, + "no filter": { + servers: []models.Server{ + {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, + {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, + {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, + }, + selection: settings.ServerSelection{}.WithDefaults(providers.Mullvad), + filtered: []models.Server{ + {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, + {VPN: vpn.OpenVPN, Hostname: "b", UDP: true}, + {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, + }, + }, + "filter by VPN protocol": { + selection: settings.ServerSelection{ + VPN: vpn.Wireguard, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {VPN: vpn.OpenVPN, Hostname: "a", UDP: true}, + {VPN: vpn.Wireguard, Hostname: "b", UDP: true}, + {VPN: vpn.OpenVPN, Hostname: "c", UDP: true}, + }, + filtered: []models.Server{ + {VPN: vpn.Wireguard, Hostname: "b", UDP: true}, + }, + }, + "filter by network protocol": { + selection: settings.ServerSelection{ + OpenVPN: settings.OpenVPNSelection{ + TCP: boolPtr(true), + }, + }.WithDefaults(providers.Ivpn), + servers: []models.Server{ + {UDP: true, Hostname: "a", VPN: vpn.OpenVPN}, + {UDP: true, TCP: true, Hostname: "b", VPN: vpn.OpenVPN}, + {UDP: true, Hostname: "c", VPN: vpn.OpenVPN}, + }, + filtered: []models.Server{ + {UDP: true, TCP: true, Hostname: "b", VPN: vpn.OpenVPN}, + }, + }, + "filter by multihop only": { + selection: settings.ServerSelection{ + MultiHopOnly: boolPtr(true), + }.WithDefaults(providers.Surfshark), + servers: []models.Server{ + {MultiHop: false, VPN: vpn.OpenVPN, UDP: true}, + {MultiHop: true, VPN: vpn.OpenVPN, UDP: true}, + {MultiHop: false, VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {MultiHop: true, VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by free only": { + selection: settings.ServerSelection{ + FreeOnly: boolPtr(true), + }.WithDefaults(providers.Surfshark), + servers: []models.Server{ + {Free: false, VPN: vpn.OpenVPN, UDP: true}, + {Free: true, VPN: vpn.OpenVPN, UDP: true}, + {Free: false, VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Free: true, VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by stream only": { + selection: settings.ServerSelection{ + StreamOnly: boolPtr(true), + }.WithDefaults(providers.Surfshark), + servers: []models.Server{ + {Stream: false, VPN: vpn.OpenVPN, UDP: true}, + {Stream: true, VPN: vpn.OpenVPN, UDP: true}, + {Stream: false, VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Stream: true, VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by owned": { + selection: settings.ServerSelection{ + OwnedOnly: boolPtr(true), + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {Owned: false, VPN: vpn.OpenVPN, UDP: true}, + {Owned: true, VPN: vpn.OpenVPN, UDP: true}, + {Owned: false, VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Owned: true, VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by country": { + selection: settings.ServerSelection{ + Countries: []string{"b"}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {Country: "a", VPN: vpn.OpenVPN, UDP: true}, + {Country: "b", VPN: vpn.OpenVPN, UDP: true}, + {Country: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Country: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by region": { + selection: settings.ServerSelection{ + Regions: []string{"b"}, + }.WithDefaults(providers.Surfshark), + servers: []models.Server{ + {Region: "a", VPN: vpn.OpenVPN, UDP: true}, + {Region: "b", VPN: vpn.OpenVPN, UDP: true}, + {Region: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Region: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by city": { + selection: settings.ServerSelection{ + Cities: []string{"b"}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {City: "a", VPN: vpn.OpenVPN, UDP: true}, + {City: "b", VPN: vpn.OpenVPN, UDP: true}, + {City: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {City: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by ISP": { + selection: settings.ServerSelection{ + ISPs: []string{"b"}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {ISP: "a", VPN: vpn.OpenVPN, UDP: true}, + {ISP: "b", VPN: vpn.OpenVPN, UDP: true}, + {ISP: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {ISP: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by number": { + selection: settings.ServerSelection{ + Numbers: []uint16{1}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {Number: 0, VPN: vpn.OpenVPN, UDP: true}, + {Number: 1, VPN: vpn.OpenVPN, UDP: true}, + {Number: 2, VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Number: 1, VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by server name": { + selection: settings.ServerSelection{ + Names: []string{"b"}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {ServerName: "a", VPN: vpn.OpenVPN, UDP: true}, + {ServerName: "b", VPN: vpn.OpenVPN, UDP: true}, + {ServerName: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {ServerName: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + "filter by hostname": { + selection: settings.ServerSelection{ + Hostnames: []string{"b"}, + }.WithDefaults(providers.Mullvad), + servers: []models.Server{ + {Hostname: "a", VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "b", VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "c", VPN: vpn.OpenVPN, UDP: true}, + }, + filtered: []models.Server{ + {Hostname: "b", VPN: vpn.OpenVPN, UDP: true}, + }, + }, + } + + for name, testCase := range testCases { + testCase := testCase + 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) + } + + assert.Equal(t, testCase.filtered, filtered) + }) + } +} + +func Test_filterByPossibilities(t *testing.T) { t.Parallel() testCases := map[string]struct { value string @@ -29,7 +251,7 @@ func Test_FilterByPossibilities(t *testing.T) { testCase := testCase t.Run(name, func(t *testing.T) { t.Parallel() - filtered := FilterByPossibilities(testCase.value, testCase.possibilities) + filtered := filterByPossibilities(testCase.value, testCase.possibilities) assert.Equal(t, testCase.filtered, filtered) }) } diff --git a/internal/provider/vpnunlimited/connection.go b/internal/provider/vpnunlimited/connection.go index 1e8933cf..d9b691d2 100644 --- a/internal/provider/vpnunlimited/connection.go +++ b/internal/provider/vpnunlimited/connection.go @@ -12,7 +12,7 @@ func (p *Provider) GetConnection(selection settings.ServerSelection) ( const port = 1194 const protocol = constants.UDP - servers, err := p.filterServers(selection) + servers, err := utils.FilterServers(p.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/vpnunlimited/filter.go b/internal/provider/vpnunlimited/filter.go deleted file mode 100644 index e7408729..00000000 --- a/internal/provider/vpnunlimited/filter.go +++ /dev/null @@ -1,30 +0,0 @@ -package vpnunlimited - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (p *Provider) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range p.servers { - switch { - case - utils.FilterByPossibilities(server.Country, selection.Countries), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - *selection.FreeOnly && !server.Free, - *selection.StreamOnly && !server.Stream, - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/vyprvpn/connection.go b/internal/provider/vyprvpn/connection.go index 867642d1..a5ec441f 100644 --- a/internal/provider/vyprvpn/connection.go +++ b/internal/provider/vyprvpn/connection.go @@ -12,7 +12,7 @@ func (v *Vyprvpn) GetConnection(selection settings.ServerSelection) ( const port = 443 const protocol = constants.UDP - servers, err := v.filterServers(selection) + servers, err := utils.FilterServers(v.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/vyprvpn/filter.go b/internal/provider/vyprvpn/filter.go deleted file mode 100644 index 8251d7da..00000000 --- a/internal/provider/vyprvpn/filter.go +++ /dev/null @@ -1,27 +0,0 @@ -package vyprvpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (v *Vyprvpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range v.servers { - switch { - case - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames), - utils.FilterByProtocol(selection, server.TCP, server.UDP): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/wevpn/connection.go b/internal/provider/wevpn/connection.go index b3445df2..3f009823 100644 --- a/internal/provider/wevpn/connection.go +++ b/internal/provider/wevpn/connection.go @@ -11,7 +11,7 @@ func (w *Wevpn) GetConnection(selection settings.ServerSelection) ( port := getPort(selection) protocol := utils.GetProtocol(selection) - servers, err := w.filterServers(selection) + servers, err := utils.FilterServers(w.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/wevpn/connection_test.go b/internal/provider/wevpn/connection_test.go index 25042389..b60c45f1 100644 --- a/internal/provider/wevpn/connection_test.go +++ b/internal/provider/wevpn/connection_test.go @@ -1,7 +1,6 @@ package wevpn import ( - "errors" "math/rand" "net" "testing" @@ -11,8 +10,8 @@ import ( "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider/utils" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func Test_Wevpn_GetConnection(t *testing.T) { @@ -22,19 +21,21 @@ func Test_Wevpn_GetConnection(t *testing.T) { servers []models.Server selection settings.ServerSelection connection models.Connection - err error + errWrapped error + errMessage string }{ "no server available": { selection: settings.ServerSelection{ VPN: vpn.OpenVPN, }.WithDefaults(providers.Wevpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), + errWrapped: utils.ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", }, "no filter": { servers: []models.Server{ - {UDP: true, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {UDP: true, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {UDP: true, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, selection: settings.ServerSelection{}.WithDefaults(providers.Wevpn), connection: models.Connection{ @@ -49,9 +50,9 @@ func Test_Wevpn_GetConnection(t *testing.T) { TargetIP: net.IPv4(2, 2, 2, 2), }.WithDefaults(providers.Wevpn), servers: []models.Server{ - {UDP: true, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {UDP: true, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {UDP: true, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -65,9 +66,9 @@ func Test_Wevpn_GetConnection(t *testing.T) { Hostnames: []string{"b"}, }.WithDefaults(providers.Wevpn), servers: []models.Server{ - {UDP: true, Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {UDP: true, Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {UDP: true, Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -89,11 +90,9 @@ func Test_Wevpn_GetConnection(t *testing.T) { connection, err := m.GetConnection(testCase.selection) - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) } assert.Equal(t, testCase.connection, connection) diff --git a/internal/provider/wevpn/filter.go b/internal/provider/wevpn/filter.go deleted file mode 100644 index 1d99ea18..00000000 --- a/internal/provider/wevpn/filter.go +++ /dev/null @@ -1,27 +0,0 @@ -package wevpn - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (w *Wevpn) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range w.servers { - switch { - case - utils.FilterByProtocol(selection, server.TCP, server.UDP), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/wevpn/filter_test.go b/internal/provider/wevpn/filter_test.go deleted file mode 100644 index d959eb40..00000000 --- a/internal/provider/wevpn/filter_test.go +++ /dev/null @@ -1,105 +0,0 @@ -package wevpn - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/constants/providers" - "github.com/qdm12/gluetun/internal/models" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func boolPtr(b bool) *bool { return &b } - -func Test_Wevpn_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Wevpn), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Wevpn), - filtered: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - }, - "filter by protocol": { - selection: settings.ServerSelection{ - OpenVPN: settings.OpenVPNSelection{TCP: boolPtr(true)}, - }.WithDefaults(providers.Wevpn), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", TCP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", TCP: true}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Wevpn), - servers: []models.Server{ - {City: "a", UDP: true}, - {City: "b", UDP: true}, - {City: "c", UDP: true}, - }, - filtered: []models.Server{ - {City: "b", UDP: true}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Wevpn), - servers: []models.Server{ - {Hostname: "a", UDP: true}, - {Hostname: "b", UDP: true}, - {Hostname: "c", UDP: true}, - }, - filtered: []models.Server{ - {Hostname: "b", UDP: true}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - w := New(testCase.servers, randSource) - - servers, err := w.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -} diff --git a/internal/provider/windscribe/connection.go b/internal/provider/windscribe/connection.go index 2ef1fe11..2ce148a3 100644 --- a/internal/provider/windscribe/connection.go +++ b/internal/provider/windscribe/connection.go @@ -11,7 +11,7 @@ func (w *Windscribe) GetConnection(selection settings.ServerSelection) ( port := getPort(selection) protocol := utils.GetProtocol(selection) - servers, err := w.filterServers(selection) + servers, err := utils.FilterServers(w.servers, selection) if err != nil { return connection, err } diff --git a/internal/provider/windscribe/connection_test.go b/internal/provider/windscribe/connection_test.go index ced6dd89..b37a8a70 100644 --- a/internal/provider/windscribe/connection_test.go +++ b/internal/provider/windscribe/connection_test.go @@ -1,7 +1,6 @@ package windscribe import ( - "errors" "math/rand" "net" "testing" @@ -11,8 +10,8 @@ import ( "github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/models" + "github.com/qdm12/gluetun/internal/provider/utils" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func Test_Windscribe_GetConnection(t *testing.T) { @@ -22,17 +21,19 @@ func Test_Windscribe_GetConnection(t *testing.T) { servers []models.Server selection settings.ServerSelection connection models.Connection - err error + errWrapped error + errMessage string }{ "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), - err: errors.New("no server found: for VPN openvpn; protocol udp"), + selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), + errWrapped: utils.ErrNoServerFound, + errMessage: "no server found: for VPN openvpn; protocol udp", }, "no filter": { servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, + {VPN: vpn.OpenVPN, UDP: true, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, }, selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), connection: models.Connection{ @@ -47,9 +48,9 @@ func Test_Windscribe_GetConnection(t *testing.T) { TargetIP: net.IPv4(2, 2, 2, 2), }.WithDefaults(providers.Windscribe), servers: []models.Server{ - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -63,9 +64,9 @@ func Test_Windscribe_GetConnection(t *testing.T) { Hostnames: []string{"b"}, }.WithDefaults(providers.Windscribe), servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}}, - {VPN: vpn.OpenVPN, Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}}, - {VPN: vpn.OpenVPN, Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}}, + {Hostname: "a", IPs: []net.IP{net.IPv4(1, 1, 1, 1)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "b", IPs: []net.IP{net.IPv4(2, 2, 2, 2)}, VPN: vpn.OpenVPN, UDP: true}, + {Hostname: "a", IPs: []net.IP{net.IPv4(3, 3, 3, 3)}, VPN: vpn.OpenVPN, UDP: true}, }, connection: models.Connection{ Type: vpn.OpenVPN, @@ -83,17 +84,14 @@ func Test_Windscribe_GetConnection(t *testing.T) { randSource := rand.NewSource(0) - m := New(testCase.servers, randSource) + provider := New(testCase.servers, randSource) - connection, err := m.GetConnection(testCase.selection) + connection, err := provider.GetConnection(testCase.selection) - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) + assert.ErrorIs(t, err, testCase.errWrapped) + if testCase.errWrapped != nil { + assert.EqualError(t, err, testCase.errMessage) } - assert.Equal(t, testCase.connection, connection) }) } diff --git a/internal/provider/windscribe/filter.go b/internal/provider/windscribe/filter.go deleted file mode 100644 index d3614032..00000000 --- a/internal/provider/windscribe/filter.go +++ /dev/null @@ -1,28 +0,0 @@ -package windscribe - -import ( - "github.com/qdm12/gluetun/internal/configuration/settings" - "github.com/qdm12/gluetun/internal/models" - "github.com/qdm12/gluetun/internal/provider/utils" -) - -func (w *Windscribe) filterServers(selection settings.ServerSelection) ( - servers []models.Server, err error) { - for _, server := range w.servers { - switch { - case - server.VPN != selection.VPN, - utils.FilterByPossibilities(server.Region, selection.Regions), - utils.FilterByPossibilities(server.City, selection.Cities), - utils.FilterByPossibilities(server.Hostname, selection.Hostnames): - default: - servers = append(servers, server) - } - } - - if len(servers) == 0 { - return nil, utils.NoServerFoundError(selection) - } - - return servers, nil -} diff --git a/internal/provider/windscribe/filter_test.go b/internal/provider/windscribe/filter_test.go deleted file mode 100644 index dbb836db..00000000 --- a/internal/provider/windscribe/filter_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package windscribe - -import ( - "errors" - "math/rand" - "testing" - - "github.com/qdm12/gluetun/internal/configuration/settings" - "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" - "github.com/stretchr/testify/require" -) - -func Test_Windscribe_filterServers(t *testing.T) { - t.Parallel() - - testCases := map[string]struct { - servers []models.Server - selection settings.ServerSelection - filtered []models.Server - err error - }{ - "no server available": { - selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), - err: errors.New("no server found: for VPN openvpn; protocol udp"), - }, - "no filter": { - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - selection: settings.ServerSelection{}.WithDefaults(providers.Windscribe), - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - }, - "filter OpenVPN out": { - selection: settings.ServerSelection{ - VPN: vpn.Wireguard, - }.WithDefaults(providers.Windscribe), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.Wireguard, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.Wireguard, Hostname: "b"}, - }, - }, - "filter by region": { - selection: settings.ServerSelection{ - Regions: []string{"b"}, - }.WithDefaults(providers.Windscribe), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Region: "a"}, - {VPN: vpn.OpenVPN, Region: "b"}, - {VPN: vpn.OpenVPN, Region: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Region: "b"}, - }, - }, - "filter by city": { - selection: settings.ServerSelection{ - Cities: []string{"b"}, - }.WithDefaults(providers.Windscribe), - servers: []models.Server{ - {VPN: vpn.OpenVPN, City: "a"}, - {VPN: vpn.OpenVPN, City: "b"}, - {VPN: vpn.OpenVPN, City: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, City: "b"}, - }, - }, - "filter by hostname": { - selection: settings.ServerSelection{ - Hostnames: []string{"b"}, - }.WithDefaults(providers.Windscribe), - servers: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "a"}, - {VPN: vpn.OpenVPN, Hostname: "b"}, - {VPN: vpn.OpenVPN, Hostname: "c"}, - }, - filtered: []models.Server{ - {VPN: vpn.OpenVPN, Hostname: "b"}, - }, - }, - } - - for name, testCase := range testCases { - testCase := testCase - t.Run(name, func(t *testing.T) { - t.Parallel() - - randSource := rand.NewSource(0) - - m := New(testCase.servers, randSource) - - servers, err := m.filterServers(testCase.selection) - - if testCase.err != nil { - require.Error(t, err) - assert.Equal(t, testCase.err.Error(), err.Error()) - } else { - assert.NoError(t, err) - } - - assert.Equal(t, testCase.filtered, servers) - }) - } -}