mirror of
https://github.com/qdm12/gluetun.git
synced 2026-08-11 14:52:56 +02:00
expressvpn wip
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
package updater
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func Test_parseServerListTable(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
htmlContent, err := os.ReadFile("testdata/index.html")
|
||||
require.NoError(t, err)
|
||||
|
||||
rootNode, err := html.Parse(strings.NewReader(string(htmlContent)))
|
||||
require.NoError(t, err)
|
||||
|
||||
servers, warnings := parseServerListTable(rootNode)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, warnings)
|
||||
// The ExpressVPN server list should have hundreds of servers
|
||||
assert.Greater(t, len(servers), 200,
|
||||
"expected at least 200 servers from the ExpressVPN server list, got %d", len(servers))
|
||||
|
||||
// Check that all servers have required fields
|
||||
for _, server := range servers {
|
||||
assert.NotEmpty(t, server.Country, "server country should not be empty")
|
||||
assert.True(t, server.TCP, "TCP should be enabled")
|
||||
assert.True(t, server.UDP, "UDP should be enabled")
|
||||
}
|
||||
|
||||
// Check some specific servers are found
|
||||
foundServers := make(map[string]models.Server)
|
||||
for _, server := range servers {
|
||||
key := server.Country
|
||||
if server.City != "" {
|
||||
key += " - " + server.City
|
||||
}
|
||||
foundServers[key] = server
|
||||
}
|
||||
|
||||
// Verify countries without cities
|
||||
assert.NotEmpty(t, foundServers["Albania"])
|
||||
assert.NotEmpty(t, foundServers["Singapore"])
|
||||
}
|
||||
|
||||
func Test_parseLocation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
input string
|
||||
country string
|
||||
city string
|
||||
number uint16
|
||||
}{
|
||||
"country only": {
|
||||
input: "Argentina",
|
||||
country: "Argentina",
|
||||
},
|
||||
"country with city": {
|
||||
input: "Australia - Adelaide",
|
||||
country: "Australia",
|
||||
city: "Adelaide",
|
||||
},
|
||||
"country with numbered location": {
|
||||
input: "Canada - Toronto - 2",
|
||||
country: "Canada",
|
||||
city: "Toronto",
|
||||
number: 2,
|
||||
},
|
||||
"virtual location": {
|
||||
input: "India (via Singapore)",
|
||||
country: "India (via Singapore)",
|
||||
},
|
||||
"country with multiple dashes in city": {
|
||||
input: "USA - Los Angeles - 1",
|
||||
country: "USA",
|
||||
city: "Los Angeles",
|
||||
number: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
country, city, number, err := parseLocation(testCase.input)
|
||||
assert.Equal(t, testCase.country, country)
|
||||
assert.Equal(t, testCase.city, city)
|
||||
assert.Equal(t, testCase.number, number)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_generateCandidateHostnames(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testCases := map[string]struct {
|
||||
input models.Server
|
||||
mustContain []string
|
||||
mustNotContain []string
|
||||
expectedCount int // exact count expected (0 if flexible)
|
||||
}{
|
||||
"simple country": {
|
||||
input: models.Server{Country: "Argentina"},
|
||||
mustContain: []string{
|
||||
"argentina-ca-version-2.expressnetw.com",
|
||||
"argentina1-ca-version-2.expressnetw.com",
|
||||
"argentina-1-ca-version-2.expressnetw.com",
|
||||
},
|
||||
},
|
||||
"country with city": {
|
||||
input: models.Server{Country: "USA", City: "New York"},
|
||||
mustContain: []string{
|
||||
"usa-newyork-ca-version-2.expressnetw.com",
|
||||
"us-newyork-ca-version-2.expressnetw.com", // alias
|
||||
"usa-newyork-1-ca-version-2.expressnetw.com",
|
||||
"usa-newyork1-ca-version-2.expressnetw.com",
|
||||
},
|
||||
},
|
||||
"North Macedonia abbreviation": {
|
||||
input: models.Server{Country: "North Macedonia"},
|
||||
mustContain: []string{
|
||||
"macedonia-ca-version-2.expressnetw.com",
|
||||
},
|
||||
expectedCount: 1, // single hardcoded hostname
|
||||
},
|
||||
"India via Singapore": {
|
||||
input: models.Server{Country: "India (via Singapore)"},
|
||||
mustContain: []string{
|
||||
"india-sg-ca-version-2.expressnetw.com",
|
||||
},
|
||||
expectedCount: 1, // single hardcoded hostname
|
||||
},
|
||||
"India via UK": {
|
||||
input: models.Server{Country: "India (via UK)"},
|
||||
mustContain: []string{
|
||||
"india-uk-ca-version-2.expressnetw.com",
|
||||
},
|
||||
expectedCount: 1, // single hardcoded hostname
|
||||
},
|
||||
"France Paris": {
|
||||
input: models.Server{Country: "France", City: "Paris"},
|
||||
mustContain: []string{
|
||||
"france-paris-ca-version-2.expressnetw.com",
|
||||
"france-paris-1-ca-version-2.expressnetw.com",
|
||||
"france-paris-2-ca-version-2.expressnetw.com",
|
||||
"france-paris1-ca-version-2.expressnetw.com",
|
||||
"france-paris2-ca-version-2.expressnetw.com",
|
||||
},
|
||||
},
|
||||
"UK with alias": {
|
||||
input: models.Server{Country: "UK", City: "London"},
|
||||
mustContain: []string{
|
||||
"uk-london-ca-version-2.expressnetw.com",
|
||||
"gb-london-ca-version-2.expressnetw.com", // alias
|
||||
},
|
||||
},
|
||||
"Germany": {
|
||||
input: models.Server{Country: "Germany"},
|
||||
mustContain: []string{
|
||||
"germany-ca-version-2.expressnetw.com",
|
||||
"de-ca-version-2.expressnetw.com", // alias
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
candidates, err := generateCandidateHostnames(testCase.input)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check exact count if specified
|
||||
if testCase.expectedCount > 0 {
|
||||
assert.Len(t, candidates, testCase.expectedCount,
|
||||
"expected exactly %d candidates", testCase.expectedCount)
|
||||
}
|
||||
|
||||
// Check required candidates exist
|
||||
for _, expected := range testCase.mustContain {
|
||||
assert.Contains(t, candidates, expected,
|
||||
"expected candidate %q in candidates", expected)
|
||||
}
|
||||
|
||||
// Check excluded candidates don't exist
|
||||
for _, excluded := range testCase.mustNotContain {
|
||||
assert.NotContains(t, candidates, excluded,
|
||||
"did not expect candidate %q in candidates", excluded)
|
||||
}
|
||||
|
||||
// All candidates should end with the expected suffix
|
||||
for _, candidate := range candidates {
|
||||
assert.True(t, strings.HasSuffix(candidate, hostnameSuffix),
|
||||
"candidate %q should end with %q", candidate, hostnameSuffix)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user