// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build darwin || dragonfly || freebsd || netbsd || openbsd

package unix

import (
	"reflect"
	"strings"
	"testing"
	"unsafe"
)

func Test_anyToSockaddr(t *testing.T) {
	tests := []struct {
		name string
		rsa  *RawSockaddrAny
		sa   Sockaddr
		err  error
	}{
		{
			name: "AF_UNIX zero length",
			rsa: sockaddrUnixToAny(RawSockaddrUnix{
				Family: AF_UNIX,
			}),
			err: EINVAL,
		},
		{
			name: "AF_UNIX unnamed",
			rsa: sockaddrUnixToAny(RawSockaddrUnix{
				Len:    2, // family (uint16)
				Family: AF_UNIX,
			}),
			sa: &SockaddrUnix{},
		},
		{
			name: "AF_UNIX named",
			rsa: sockaddrUnixToAny(RawSockaddrUnix{
				Len:    uint8(2 + len("gopher")), // family (uint16) + len(gopher)
				Family: AF_UNIX,
				Path:   [104]int8{'g', 'o', 'p', 'h', 'e', 'r'},
			}),
			sa: &SockaddrUnix{
				Name: "gopher",
			},
		},
		{
			name: "AF_UNIX named",
			rsa: sockaddrUnixToAny(RawSockaddrUnix{
				Len:    uint8(2 + len("go")),
				Family: AF_UNIX,
				Path:   [104]int8{'g', 'o', 'p', 'h', 'e', 'r'},
			}),
			sa: &SockaddrUnix{
				Name: "go",
			},
		},
		{
			name: "AF_MAX EAFNOSUPPORT",
			rsa: &RawSockaddrAny{
				Addr: RawSockaddr{
					Family: AF_MAX,
				},
			},
			err: EAFNOSUPPORT,
		},
		// TODO: expand to support other families.
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			fd := int(0)
			sa, err := anyToSockaddr(fd, tt.rsa)
			if err != tt.err {
				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
			}

			if !reflect.DeepEqual(sa, tt.sa) {
				t.Fatalf("unexpected Sockaddr:\n got: %#v\nwant: %#v", sa, tt.sa)
			}
		})
	}
}

func TestSockaddrUnix_sockaddr(t *testing.T) {
	tests := []struct {
		name string
		sa   *SockaddrUnix
		raw  *RawSockaddrUnix
		err  error
	}{
		{
			name: "unnamed",
			sa:   &SockaddrUnix{},
			raw: &RawSockaddrUnix{
				Family: AF_UNIX,
			},
			err: EINVAL,
		},
		{
			name: "named",
			sa: &SockaddrUnix{
				Name: "gopher",
			},
			raw: &RawSockaddrUnix{
				Len:    uint8(2 + len("gopher") + 1), // family (uint16) + len(gopher) + '\0'
				Family: AF_UNIX,
				Path:   [104]int8{'g', 'o', 'p', 'h', 'e', 'r'},
			},
		},
		{
			name: "named too long",
			sa: &SockaddrUnix{
				Name: strings.Repeat("A", 104),
			},
			err: EINVAL,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			out, _, err := tt.sa.sockaddr()
			if err != tt.err {
				t.Fatalf("unexpected error: %v, want: %v", err, tt.err)
			}

			if out == nil {
				// No pointer to cast, return early.
				return
			}

			raw := (*RawSockaddrUnix)(out)
			if !reflect.DeepEqual(raw, tt.raw) {
				t.Fatalf("unexpected RawSockaddrUnix:\n got: %#v\nwant: %#v", raw, tt.raw)
			}
		})
	}
}

func sockaddrUnixToAny(in RawSockaddrUnix) *RawSockaddrAny {
	var out RawSockaddrAny

	// Explicitly copy the contents of in into out to produce the correct
	// sockaddr structure, without relying on unsafe casting to a type of a
	// larger size.
	copy(
		(*(*[SizeofSockaddrAny]byte)(unsafe.Pointer(&out)))[:],
		(*(*[SizeofSockaddrUnix]byte)(unsafe.Pointer(&in)))[:],
	)

	return &out
}
