package xturbo import ( "bytes" "encoding/binary" "errors" "os" "path/filepath" "testing" ) type authEntry struct { family uint16 addr, number, name string data []byte } func encodeAuth(entries ...authEntry) []byte { var b []byte str := func(s []byte) { b = binary.BigEndian.AppendUint16(b, uint16(len(s))) b = append(b, s...) } for _, e := range entries { b = binary.BigEndian.AppendUint16(b, e.family) str([]byte(e.addr)) str([]byte(e.number)) str([]byte(e.name)) str(e.data) } return b } func TestReadCookie(t *testing.T) { cookie := []byte("0123456789abcdef") other := []byte("fedcba9876543210") local := func(host, num string, data []byte) authEntry { return authEntry{familyLocal, host, num, authMagicCookie, data} } for _, tc := range []struct { name string file []byte want []byte wantErr error }{ {"match", encodeAuth(local("arch", "7", cookie)), cookie, nil}, {"first match wins", encodeAuth(local("other", "7", other), local("arch", "3", other), local("arch", "7", cookie), local("arch", "7", other)), cookie, nil}, {"wild family", encodeAuth(authEntry{familyWild, "", "7", authMagicCookie, cookie}), cookie, nil}, {"empty number matches any", encodeAuth(local("arch", "", cookie)), cookie, nil}, {"other host", encodeAuth(local("box", "7", cookie)), nil, nil}, {"other display", encodeAuth(local("arch", "70", cookie)), nil, nil}, {"other family", encodeAuth(authEntry{0, "arch", "7", authMagicCookie, cookie}), nil, nil}, {"other protocol", encodeAuth(authEntry{familyLocal, "arch", "7", "XDM-AUTHORIZATION-1", cookie}), nil, nil}, {"empty file", nil, nil, nil}, {"truncated family", []byte{1}, nil, ErrMalformed}, {"truncated field", encodeAuth(local("arch", "7", cookie))[:30], nil, ErrMalformed}, {"missing fields", encodeAuth(local("arch", "7", cookie))[:10], nil, ErrMalformed}, } { t.Run(tc.name, func(t *testing.T) { path := filepath.Join(t.TempDir(), "Xauthority") if err := os.WriteFile(path, tc.file, 0o600); err != nil { t.Fatal(err) } got, err := readCookie(path, "arch", 7) if !errors.Is(err, tc.wantErr) || (tc.wantErr == nil && err != nil) || !bytes.Equal(got, tc.want) { t.Fatalf("got %q, %v; want %q, %v", got, err, tc.want, tc.wantErr) } }) } if _, err := readCookie(filepath.Join(t.TempDir(), "missing"), "arch", 7); !errors.Is(err, os.ErrNotExist) { t.Fatal(err) } } func TestXauthorityPath(t *testing.T) { t.Setenv("XAUTHORITY", "/x/auth") if got := xauthorityPath(); got != "/x/auth" { t.Fatal(got) } t.Setenv("XAUTHORITY", "") t.Setenv("HOME", "/home/u") if got := xauthorityPath(); got != "/home/u/.Xauthority" { t.Fatal(got) } } func TestParseDisplay(t *testing.T) { for _, tc := range []struct { in string want int ok bool }{ {":0", 0, true}, {":12", 12, true}, {":3.1", 3, true}, {"unix:5", 5, true}, {"unix:5.0", 5, true}, {"", 0, false}, {"0", 0, false}, {":", 0, false}, {":x", 0, false}, {":1.", 0, false}, {":1.x", 0, false}, {":-1", 0, false}, {"localhost:0", 0, false}, {"host::0", 0, false}, {"::1:0", 0, false}, } { got, err := parseDisplay(tc.in) if (err == nil) != tc.ok || got != tc.want { t.Errorf("%q: %d, %v", tc.in, got, err) } } } func TestDialNoServer(t *testing.T) { // Display numbers above any real server: both abstract and path fail. if _, err := Dial(":2147483000"); err == nil { t.Fatal("Dial succeeded without a server") } if _, err := Dial("tcp/host:0"); err == nil { t.Fatal("remote DISPLAY accepted") } }