Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

248 lines
6.2 KiB
Go

package devicelink
import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"strings"
"testing"
"time"
)
func TestQUICEndpointCloseClosesOwnedUDPSocket(t *testing.T) {
conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
if err != nil {
t.Fatal(err)
}
endpoint, err := NewQUICEndpoint(conn)
if err != nil {
t.Fatal(err)
}
if err := endpoint.Close(); err != nil {
t.Fatalf("Close() error = %v", err)
}
if err := conn.SetReadDeadline(time.Now()); !errors.Is(err, net.ErrClosed) {
t.Fatalf("owned UDP socket deadline error = %v, want net.ErrClosed", err)
}
}
func TestDefaultQUICLiveness(t *testing.T) {
config := defaultQUICConfig()
if config.KeepAlivePeriod != 5*time.Second {
t.Fatalf("KeepAlivePeriod = %s, want 5s", config.KeepAlivePeriod)
}
if config.MaxIdleTimeout != 15*time.Second {
t.Fatalf("MaxIdleTimeout = %s, want 15s", config.MaxIdleTimeout)
}
}
func TestGlobalIPv6FromAddr(t *testing.T) {
tests := []struct {
name string
addr string
ok bool
}{
{name: "global", addr: "2001:db8::10/64", ok: true},
{name: "ula", addr: "fd00::10/64", ok: false},
{name: "link local", addr: "fe80::10%en0/64", ok: false},
{name: "ipv4", addr: "192.0.2.10/24", ok: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, ok := globalIPv6FromAddr(testAddr(tt.addr))
if ok != tt.ok {
t.Fatalf("globalIPv6FromAddr(%q) ok = %v, want %v", tt.addr, ok, tt.ok)
}
})
}
}
func TestListenGlobalIPv6CurrentHost(t *testing.T) {
if os.Getenv("TUTTI_TEST_GLOBAL_IPV6") != "1" {
t.Skip("set TUTTI_TEST_GLOBAL_IPV6=1 to probe physical IPv6 candidates")
}
endpoints, err := ListenGlobalIPv6(context.Background())
if err != nil {
t.Fatalf("ListenGlobalIPv6() error = %v", err)
}
defer func() {
for _, endpoint := range endpoints {
_ = endpoint.Close()
}
}()
for _, endpoint := range endpoints {
if strings.HasPrefix(strings.ToLower(endpoint.Candidate.InterfaceName), "utun") {
t.Fatalf("ListenGlobalIPv6() returned TUN candidate on %q", endpoint.Candidate.InterfaceName)
}
}
}
func TestQUICMutualPinningAndStreamRoundTrip(t *testing.T) {
callerUDP := listenLoopbackUDP6(t)
ownerUDP := listenLoopbackUDP6(t)
runQUICRoundTrip(t, context.Background(), callerUDP, ownerUDP, nil, nil, ALPN)
}
func TestQUICRollingALPNCompatibility(t *testing.T) {
legacy := "tsh-device-link-p2p/2"
tests := []struct {
name string
callerProtocols []string
ownerProtocols []string
}{
{name: "new caller old owner", callerProtocols: []string{ALPN, legacy}, ownerProtocols: []string{legacy}},
{name: "old caller new owner", callerProtocols: []string{legacy}, ownerProtocols: []string{ALPN, legacy}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
runQUICRoundTrip(
t,
context.Background(),
listenLoopbackUDP6(t),
listenLoopbackUDP6(t),
tt.callerProtocols,
tt.ownerProtocols,
legacy,
)
})
}
}
func runQUICRoundTrip(
t *testing.T,
parent context.Context,
callerUDP, ownerUDP *net.UDPConn,
callerProtocols, ownerProtocols []string,
expectedProtocol string,
) {
t.Helper()
callerEndpoint, err := NewQUICEndpoint(callerUDP)
if err != nil {
t.Fatal(err)
}
defer callerEndpoint.Close()
ownerEndpoint, err := NewQUICEndpoint(ownerUDP)
if err != nil {
t.Fatal(err)
}
defer ownerEndpoint.Close()
callerIdentity, err := NewEphemeralIdentity(time.Now())
if err != nil {
t.Fatal(err)
}
ownerIdentity, err := NewEphemeralIdentity(time.Now())
if err != nil {
t.Fatal(err)
}
serverTLS, err := ownerIdentity.ServerTLSConfigForProtocols(callerIdentity.Fingerprint, ownerProtocols)
if err != nil {
t.Fatal(err)
}
clientTLS, err := callerIdentity.ClientTLSConfigForProtocols(ownerIdentity.Fingerprint, callerProtocols)
if err != nil {
t.Fatal(err)
}
listener, err := ownerEndpoint.Listen(serverTLS)
if err != nil {
t.Fatal(err)
}
defer listener.Close()
ctx, cancel := context.WithTimeout(parent, 5*time.Second)
defer cancel()
serverDone := make(chan error, 1)
go func() {
session, err := listener.Accept(ctx)
if err != nil {
serverDone <- err
return
}
defer session.Close()
if got := session.NegotiatedProtocol(); got != expectedProtocol {
serverDone <- fmt.Errorf("server negotiated protocol = %q, want %q", got, expectedProtocol)
return
}
stream, err := session.AcceptStream(ctx)
if err != nil {
serverDone <- err
return
}
defer stream.Close()
_, err = io.Copy(stream, stream)
serverDone <- err
}()
clientSession, err := callerEndpoint.Dial(ctx, ownerUDP.LocalAddr().(*net.UDPAddr), clientTLS)
if err != nil {
t.Fatal(err)
}
if got := clientSession.NegotiatedProtocol(); got != expectedProtocol {
t.Fatalf("negotiated protocol = %q, want %q", got, expectedProtocol)
}
stream, err := clientSession.OpenStream(ctx)
if err != nil {
t.Fatal(err)
}
payload := []byte("device-link-quic-round-trip")
if _, err := stream.Write(payload); err != nil {
t.Fatal(err)
}
got := make([]byte, len(payload))
if _, err := io.ReadFull(stream, got); err != nil {
t.Fatal(err)
}
if string(got) != string(payload) {
t.Fatalf("round trip = %q, want %q", got, payload)
}
_ = stream.Close()
select {
case err := <-serverDone:
if err != nil && err != io.EOF {
t.Fatalf("server error = %v", err)
}
case <-time.After(time.Second):
t.Fatal("server did not finish")
}
_ = clientSession.Close()
}
func TestQUICRejectsWrongPeerFingerprint(t *testing.T) {
identity, err := NewEphemeralIdentity(time.Now())
if err != nil {
t.Fatal(err)
}
other, err := NewEphemeralIdentity(time.Now())
if err != nil {
t.Fatal(err)
}
wrong, err := NewEphemeralIdentity(time.Now())
if err != nil {
t.Fatal(err)
}
config, err := identity.ClientTLSConfig(other.Fingerprint)
if err != nil {
t.Fatal(err)
}
if err := config.VerifyPeerCertificate(wrong.Certificate.Certificate, nil); err == nil {
t.Fatal("VerifyPeerCertificate() accepted wrong fingerprint")
}
}
func listenLoopbackUDP6(t *testing.T) *net.UDPConn {
t.Helper()
conn, err := net.ListenUDP("udp6", &net.UDPAddr{IP: net.ParseIP("::1")})
if err != nil {
t.Fatalf("ListenUDP() error = %v", err)
}
return conn
}
type testAddr string
func (testAddr) Network() string { return "test" }
func (a testAddr) String() string { return string(a) }