package dns

import (
	"bytes"
	"net"
	"testing"
	"time"
)

func TestPacketConnRoundTrip(t *testing.T) {
	serverPC, err := net.ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer serverPC.Close()

	clientPC, err := net.ListenPacket("udp", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer clientPC.Close()

	server := ServerConn(serverPC, DomainOption("tunnel.example."))
	client := ClientConn(clientPC, DomainOption("tunnel.example."))
	_ = server.SetDeadline(time.Now().Add(3 * time.Second))
	_ = client.SetDeadline(time.Now().Add(3 * time.Second))

	requestPayload := []byte("hello over dns")
	if n, err := client.WriteTo(requestPayload, server.LocalAddr()); err != nil {
		t.Fatal(err)
	} else if n != len(requestPayload) {
		t.Fatalf("client WriteTo wrote %d bytes, want %d", n, len(requestPayload))
	}

	buf := make([]byte, 1500)
	n, clientAddr, err := server.ReadFrom(buf)
	if err != nil {
		t.Fatal(err)
	}
	if got := buf[:n]; !bytes.Equal(got, requestPayload) {
		t.Fatalf("server ReadFrom got %q, want %q", got, requestPayload)
	}

	responsePayload := []byte("world over dns")
	if n, err := server.WriteTo(responsePayload, clientAddr); err != nil {
		t.Fatal(err)
	} else if n != len(responsePayload) {
		t.Fatalf("server WriteTo wrote %d bytes, want %d", n, len(responsePayload))
	}

	n, serverAddr, err := client.ReadFrom(buf)
	if err != nil {
		t.Fatal(err)
	}
	if serverAddr.String() != server.LocalAddr().String() {
		t.Fatalf("response addr = %v, want %v", serverAddr, server.LocalAddr())
	}
	if got := buf[:n]; !bytes.Equal(got, responsePayload) {
		t.Fatalf("client ReadFrom got %q, want %q", got, responsePayload)
	}
}
