Clear sysproxy on core death; probe+reconnect; subscription prune; Best ignores soft UDP; Windows tray; Android protocol gate; CI workflows. Co-authored-by: Cursor <cursoragent@cursor.com>
107 lines
2.5 KiB
Go
107 lines
2.5 KiB
Go
package netcheck
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"vpnclient/internal/config"
|
|
)
|
|
|
|
func TestFriendlyDialError(t *testing.T) {
|
|
err := &netError{s: "dial tcp 1.2.3.4:22514: connectex: No connection could be made because the target machine actively refused it."}
|
|
got := friendlyDialError(err, true)
|
|
if got == "" || got == err.Error() {
|
|
t.Fatalf("got %q", got)
|
|
}
|
|
}
|
|
|
|
type netError struct{ s string }
|
|
|
|
func (e *netError) Error() string { return e.s }
|
|
func (e *netError) Timeout() bool { return false }
|
|
func (e *netError) Temporary() bool { return false }
|
|
|
|
func TestPingProfileEmpty(t *testing.T) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
defer cancel()
|
|
r := PingProfile(ctx, "x", config.ProtocolHysteria2, "")
|
|
if r.OK || r.Error == "" {
|
|
t.Fatalf("%+v", r)
|
|
}
|
|
}
|
|
|
|
func TestProbeUDPSoftOKWhenSilent(t *testing.T) {
|
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer pc.Close()
|
|
// Intentionally do not Read — mimics Hy2/AWG ignoring garbage probes.
|
|
_, port, err := net.SplitHostPort(pc.LocalAddr().String())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
start := time.Now()
|
|
rtt, soft, err := probeUDP(ctx, "127.0.0.1", port)
|
|
if err != nil {
|
|
t.Fatalf("expected soft-ok, got err=%v", err)
|
|
}
|
|
if !soft {
|
|
t.Fatal("expected soft=true")
|
|
}
|
|
if rtt <= 0 {
|
|
t.Fatalf("rtt=%v", rtt)
|
|
}
|
|
if time.Since(start) > 900*time.Millisecond {
|
|
t.Fatalf("soft-ok waited too long: %v (should not use long timeout)", time.Since(start))
|
|
}
|
|
|
|
res := PingProfile(ctx, "silent", config.ProtocolHysteria2, "hysteria2://x@127.0.0.1:"+port+"/")
|
|
if !res.OK || !res.Soft {
|
|
t.Fatalf("PingProfile soft-ok failed: %+v", res)
|
|
}
|
|
if res.Ms < 1 {
|
|
t.Fatalf("ms=%d", res.Ms)
|
|
}
|
|
if _, ok := BestOK([]Result{res}); ok {
|
|
t.Fatal("BestOK must ignore soft-up")
|
|
}
|
|
}
|
|
|
|
func TestProbeUDPReplyOK(t *testing.T) {
|
|
pc, err := net.ListenPacket("udp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer pc.Close()
|
|
go func() {
|
|
buf := make([]byte, 64)
|
|
n, addr, err := pc.ReadFrom(buf)
|
|
if err != nil || n == 0 {
|
|
return
|
|
}
|
|
_, _ = pc.WriteTo([]byte{1}, addr)
|
|
}()
|
|
_, port, err := net.SplitHostPort(pc.LocalAddr().String())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
|
defer cancel()
|
|
rtt, soft, err := probeUDP(ctx, "127.0.0.1", port)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if soft {
|
|
t.Fatal("reply should be hard-ok")
|
|
}
|
|
if rtt <= 0 {
|
|
t.Fatalf("rtt=%v", rtt)
|
|
}
|
|
}
|