mirror of
https://github.com/qdm12/gluetun.git
synced 2026-08-11 14:52:56 +02:00
207 lines
5.6 KiB
Go
207 lines
5.6 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
}
|