Files
navi/internal/subscription/fetch_test.go
T
M4andCursor 7ceb3a5148
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run
Release 3.8.2.13: iOS Packet Tunnel client and Clash URL subscriptions.
Add SwiftUI + Network Extension (LibXray/hev), parse Clash Meta YAML from subscription URLs into vless/trojan/hy2 share links, keep the selected server on connect, and ship Navis-3.8.2.13.ipa with versioned changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-01 22:46:32 +03:00

145 lines
3.5 KiB
Go

package subscription
import (
"encoding/base64"
"os"
"path/filepath"
"strings"
"testing"
)
func TestParseBodyPlain(t *testing.T) {
body := `# comment
hysteria2://pass@ex.com:443/?sni=ex.com&obfs=salamander&obfs-password=x#EU
naive+https://u:p@n.example.com#naive1
`
items, err := ParseBody(body)
if err != nil {
t.Fatal(err)
}
if len(items) != 2 {
t.Fatalf("got %d items", len(items))
}
}
func TestParseBodyBase64(t *testing.T) {
plain := "hysteria2://secret@host.example:443/?sni=host.example#HY\nhttps://user:pass@naive.example.com#NV\n"
body := base64.StdEncoding.EncodeToString([]byte(plain))
items, err := ParseBody(body)
if err != nil {
t.Fatal(err)
}
if len(items) != 2 {
t.Fatalf("got %d items: %+v", len(items), items)
}
}
func TestParseBodyClashYAML(t *testing.T) {
body := `
proxies:
- name: "DE HY2"
type: hysteria2
server: de.example.com
port: 443
password: secret
sni: de.example.com
obfs: salamander
obfs-password: obfspass
- name: CZ Vless
type: vless
server: cz.example.com
port: 443
uuid: 7e1c0fbf-1758-4781-97f6-ae8715ed3f60
network: xhttp
tls: true
servername: cz.example.com
alpn:
- h2
- http/1.1
xhttp-opts:
path: /xhttp
host: cz.example.com
mode: auto
client-fingerprint: chrome
- name: CZ Trojan
type: trojan
server: cz.example.com
port: 20000
password: secretpass
network: ws
tls: true
sni: cz.example.com
ws-opts:
path: /ws
proxy-groups:
- name: Auto
icon: https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Proxy.png
type: select
`
items, err := ParseBody(body)
if err != nil {
t.Fatal(err)
}
if len(items) != 3 {
t.Fatalf("got %d items: %+v", len(items), items)
}
byProto := map[string]int{}
var vlessURI string
for _, it := range items {
byProto[string(it.Protocol)]++
if it.Protocol == "naive" {
t.Fatalf("unexpected naive: %s %s", it.Name, it.URI)
}
if it.Protocol == "vless" {
vlessURI = it.URI
}
}
if byProto["hysteria2"] != 1 || byProto["vless"] != 1 || byProto["trojan"] != 1 {
t.Fatalf("protos %+v", byProto)
}
if !strings.Contains(items[0].URI+items[1].URI+items[2].URI, "de.example.com:443") {
t.Fatalf("missing hy2 host in %+v", items)
}
if !strings.Contains(vlessURI, "alpn=h2") {
t.Fatalf("alpn list broken in %s", vlessURI)
}
if strings.Contains(vlessURI, "alpn=-") {
t.Fatalf("alpn bled list marker in %s", vlessURI)
}
if !strings.Contains(vlessURI, "mode=auto") {
t.Fatalf("xhttp mode missing in %s", vlessURI)
}
}
func TestNaiveAuthIgnoresPathAt(t *testing.T) {
if naiveLinkHasAuth("https://cdn.jsdelivr.net/gh/Koolson/Qure@master/IconSet/Color/Proxy.png") {
t.Fatal("path @master must not count as auth")
}
if !naiveLinkHasAuth("https://user:pass@naive.example.com") {
t.Fatal("real auth required")
}
}
func TestParseBodyRealClashSubscriptionFile(t *testing.T) {
path := filepath.Join("testdata", "evilfox_clash.yaml")
raw, err := os.ReadFile(path)
if err != nil {
t.Skip("optional fixture missing:", path)
}
items, err := ParseBody(string(raw))
if err != nil {
t.Fatal(err)
}
if len(items) < 80 {
t.Fatalf("expected ~89 proxies, got %d", len(items))
}
for _, it := range items {
if it.Protocol == "naive" {
t.Fatalf("naive noise: %s %s", it.Name, it.URI)
}
if strings.EqualFold(it.Name, "master") || strings.HasPrefix(strings.ToLower(it.Name), "master-") {
t.Fatalf("icon false-positive name: %s", it.Name)
}
}
}