Files
navi/internal/core/manager_test.go
T
NavisandCursor 50f7f71393 Add site contacts/FAQ and accept AWG 2.0 / naive pastes in Add config.
ImportSubscription no longer requires only http(s): paste awg://, AWG .conf/JSON, or naive links; subscription parser also reads hosted AWG and Clash wireguard/naive. Site lists support emails and FAQ; Store listing texts/tools updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-02 15:40:13 +03:00

147 lines
3.9 KiB
Go

package core
import (
"io"
"net/http"
"net/http/httptest"
"path/filepath"
"strings"
"testing"
"vpnclient/internal/config"
)
func newTestManager(t *testing.T) *Manager {
t.Helper()
dir := t.TempDir()
cfgPath := filepath.Join(dir, "configs", "config.json")
cfg := config.Example()
if err := config.Save(cfgPath, cfg); err != nil {
t.Fatal(err)
}
loaded, err := config.Load(cfgPath)
if err != nil {
t.Fatal(err)
}
m, err := NewManager(cfgPath, loaded, io.Discard)
if err != nil {
t.Fatal(err)
}
return m
}
const testSubBody = "vless://7e1c0fbf-1758-4781-97f6-ae8715ed3f60@de.example.com:443?encryption=none&type=tcp&security=tls&sni=de.example.com#DE-1\n" +
"hysteria2://pass@nl.example.com:9000/?sni=nl.example.com#NL-1\n"
// A credential-less https URL pasted into the "add server link" field must be
// treated as a subscription URL and imported — never fail with
// "proxy URI missing username" (regression for the naive proxy-URI parser).
func TestSaveProfileRoutesSubscriptionURL(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, testSubBody)
}))
defer ts.Close()
m := newTestManager(t)
if err := m.SaveProfile("whatever", ts.URL+"/ZKszcVcC3xbWb8qj"); err != nil {
t.Fatalf("SaveProfile(subscription URL) failed: %v", err)
}
names := map[string]bool{}
for _, p := range m.Profiles() {
names[p.Name] = true
}
if !names["DE-1"] || !names["NL-1"] {
t.Fatalf("subscription profiles not imported, got %v", names)
}
if m.Config().SubscriptionURL == "" {
t.Fatal("subscription URL not persisted")
}
}
func TestSaveActiveProfileRoutesSubscriptionURL(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, testSubBody)
}))
defer ts.Close()
m := newTestManager(t)
if err := m.SaveActiveProfile("naive-main", ts.URL+"/short"); err != nil {
t.Fatalf("SaveActiveProfile(subscription URL) failed: %v", err)
}
if len(m.Profiles()) < 3 { // naive-main + 2 imported
t.Fatalf("expected imported profiles, got %d", len(m.Profiles()))
}
}
// A real naive share link (with credentials) must still be saved as a proxy.
func TestSaveProfileKeepsNaiveLink(t *testing.T) {
m := newTestManager(t)
if err := m.SaveProfile("naive-1", "https://user:pass@proxy.example.com:443"); err != nil {
t.Fatal(err)
}
p, err := m.Config().ActiveProfile()
if err != nil {
t.Fatal(err)
}
if p.Protocol != config.ProtocolNaive || !strings.Contains(p.Proxy, "user:pass@") {
t.Fatalf("naive profile broken: %+v", p)
}
}
// «Добавить конфигурацию» must accept pasted AWG 2.0 .conf / naive links,
// not only http(s) subscription URLs (regression: "нужен http(s) URL").
func TestImportSubscriptionDirectAWGAndNaive(t *testing.T) {
m := newTestManager(t)
awgBody := `[Interface]
PrivateKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
Address = 10.8.0.2/32
Jc = 4
Jmin = 40
Jmax = 70
H1 = 1
H2 = 2
H3 = 3
H4 = 4
[Peer]
PublicKey = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE=
Endpoint = 203.0.113.10:51820
AllowedIPs = 0.0.0.0/0
`
r, err := m.ImportSubscription(awgBody)
if err != nil {
t.Fatalf("AWG paste: %v", err)
}
if r.Imported < 1 {
t.Fatalf("AWG imported=%d", r.Imported)
}
foundAWG := false
for _, p := range m.Profiles() {
if config.Protocol(p.Protocol) == config.ProtocolAWG && strings.Contains(p.Proxy, "203.0.113.10:51820") {
foundAWG = true
break
}
}
if !foundAWG {
t.Fatal("AWG profile missing")
}
r2, err := m.ImportSubscription("https://user:secret@naive.example.com:443#NV")
if err != nil {
t.Fatalf("naive paste: %v", err)
}
if r2.Imported < 1 {
t.Fatalf("naive imported=%d", r2.Imported)
}
foundNaive := false
for _, p := range m.Profiles() {
if config.Protocol(p.Protocol) == config.ProtocolNaive && strings.Contains(p.Proxy, "naive.example.com") {
foundNaive = true
break
}
}
if !foundNaive {
t.Fatal("naive profile missing")
}
}