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

package serial

import (
	"bufio"
	"bytes"
	"context"
	"crypto/rand"
	"io"
	"path/filepath"

	"io/ioutil"
	"net"
	"os"
	"testing"

	"go.fuchsia.dev/fuchsia/tools/lib/color"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"
)

var warningLogger = logger.NewLogger(logger.WarningLevel, color.NewColor(color.ColorNever), nil, nil, "test-serial")

func TestServerDrainsSerial(t *testing.T) {
	serial, device := serialAndDevice()

	s := NewServer(serial, ServerOptions{})

	ctx, cancel := context.WithCancel(context.Background())

	var serverErr error
	serverDone := make(chan struct{})
	go func() {
		l, _ := testListener(t)
		serverErr = s.Run(ctx, l)
		close(serverDone)
	}()

	// copy 1mb of random output to the server, if there were general IO problems
	// we'd likely block at around 64kb, this should shake out any common issues
	// with the normal copy pipeline
	_, err := io.CopyN(device, rand.Reader, 1024*1024)
	if err != nil {
		t.Fatal(err)
	}

	cancel()
	<-serverDone
	if serverErr != nil {
		t.Fatalf("unexpected server error: %s", serverErr)
	}
}

func TestServerAuxOutput(t *testing.T) {
	serial, device := serialAndDevice()
	aux := mkTempFile(t)

	s := NewServer(serial, ServerOptions{AuxiliaryOutput: aux})

	ctx, cancel := context.WithCancel(context.Background())

	var serverErr error
	serverDone := make(chan struct{})
	go func() {
		l, _ := testListener(t)
		serverErr = s.Run(ctx, l)
		close(serverDone)
	}()

	buf := make([]byte, 1024*1024)
	if _, err := io.ReadFull(rand.Reader, buf); err != nil {
		t.Fatal(err)
	}
	n, err := device.Write(buf)
	if err != nil || n != len(buf) {
		t.Fatalf("device write short or error: %s (%d/%d)", err, n, len(buf))
	}

	cancel()
	<-serverDone
	if serverErr != nil {
		t.Fatalf("unexpected server error: %s", serverErr)
	}
	if _, err := aux.Seek(0, io.SeekStart); err != nil {
		t.Fatal(err)
	}
	gotBuf, err := ioutil.ReadAll(aux)
	if err != nil {
		t.Fatal(err)
	}
	if !bytes.Equal(gotBuf, buf) {
		t.Fatalf("got\n%x\nwant\n%x", gotBuf, buf)
	}
}

func TestServerSocketOutput(t *testing.T) {
	serial, device := serialAndDevice()
	aux := mkTempFile(t)

	s := NewServer(serial, ServerOptions{AuxiliaryOutput: aux, Logger: warningLogger})

	ctx, cancel := context.WithCancel(context.Background())

	l, sockPath := testListener(t)

	var serverErr error
	serverDone := make(chan struct{})
	go func() {
		serverErr = s.Run(ctx, l)
		close(serverDone)
	}()

	c, err := net.DialUnix("unix", nil, &net.UnixAddr{Net: "unix", Name: sockPath})
	if err != nil {
		t.Fatal(err)
	}

	// A device writes things to serial, eventually writing a completion match the
	// reader was looking for
	go func() {
		for i := 0; i < 10000; i++ {
			if _, err := io.WriteString(device, "hello world\n"); err != nil {
				t.Fatal(err)
			}
		}
		if _, err := io.WriteString(device, "MAGIC!\n"); err != nil {
			t.Fatal(err)
		}
	}()

	// a client is tailing the log and tells the server it's done when it reads the magic:
	bio := bufio.NewReader(c)
	for {
		l, err := bio.ReadString('\n')
		if err != nil {
			t.Fatal(err)
		}
		if l == "MAGIC!\n" {
			break
		}
	}

	cancel()
	<-serverDone
	if serverErr != nil {
		t.Fatalf("unexpected server error: %s", serverErr)
	}
}

func TestServerSerialWrites(t *testing.T) {
	serial, device := serialAndDevice()
	aux := mkTempFile(t)

	s := NewServer(serial, ServerOptions{AuxiliaryOutput: aux, Logger: warningLogger})

	ctx, cancel := context.WithCancel(context.Background())

	l, sockPath := testListener(t)

	var serverErr error
	serverDone := make(chan struct{})
	go func() {
		serverErr = s.Run(ctx, l)
		close(serverDone)
	}()

	c, err := net.DialUnix("unix", nil, &net.UnixAddr{Net: "unix", Name: sockPath})
	if err != nil {
		t.Fatal(err)
	}

	var expectedCount = 10000
	// A test driver writes things to conn
	go func() {
		for i := 0; i < expectedCount-1; i++ {
			if _, err := io.WriteString(c, "hello world\n"); err != nil {
				t.Fatal(err)
			}
		}
		if _, err := io.WriteString(c, "MAGIC!\n"); err != nil {
			t.Fatal(err)
		}
	}()

	var count int
	// a device is receiving the input from the conn
	bio := bufio.NewReader(device)
	for {
		count++
		l, err := bio.ReadString('\n')
		if err != nil {
			t.Fatal(err)
		}
		if l == "MAGIC!\n" {
			break
		}
	}

	cancel()
	<-serverDone
	if serverErr != nil {
		t.Fatalf("unexpected server error: %s", serverErr)
	}

	if expectedCount != count {
		t.Fatalf("got %d, want %d", count, expectedCount)
	}
}

func TestServerSerialClosing(t *testing.T) {
	serial, _ := serialAndDevice()
	aux := mkTempFile(t)

	s := NewServer(serial, ServerOptions{AuxiliaryOutput: aux, Logger: warningLogger})

	ctx := context.Background()

	l, sockPath := testListener(t)

	var serverErr error
	serverDone := make(chan struct{})
	go func() {
		serverErr = s.Run(ctx, l)
		close(serverDone)
	}()

	c, err := net.DialUnix("unix", nil, &net.UnixAddr{Net: "unix", Name: sockPath})
	if err != nil {
		t.Fatal(err)
	}

	// serial goes away, say someone pulls the plug
	serial.Close()

	// the connection should get closed
	io.Copy(ioutil.Discard, c)

	// the server should exit cleanly
	<-serverDone
	// and it returns the underlying io error
	if serverErr == nil {
		t.Fatalf("server failed to return expected error")
	}
}

func TestIsErrNetClosing(t *testing.T) {
	// see golang issue 4373, this is the sad story from upstream, and the pattern
	// we follow is similar to that of the net/http and net/http2 package. There's
	// a variable stashed away in internal/poll, but it's not actually exported to
	// us for comparison.

	l, err := net.ListenUnix("unix", &net.UnixAddr{Net: "unix", Name: "foo.sock"})
	if err != nil {
		t.Fatal(err)
	}
	l.Close()
	_, err = l.Accept()

	if !IsErrNetClosing(err) {
		t.Fatalf("expected a wrapped errnetclosing, got: %#v", err)
	}
}

// Creates a "serial connection" in terms of its host- and device-side
// descriptors. They are implemented with synchronous in-memory pipes, so
// associated writes and reads will be one-to-one (with the usual caveats of
// io.Pipe).
func serialAndDevice() (io.ReadWriteCloser, io.ReadWriteCloser) {
	rs, wd := io.Pipe()
	rd, ws := io.Pipe()
	serial := &joinedPipeEnds{rs, ws}
	device := &joinedPipeEnds{rd, wd}
	return serial, device
}

func testListener(t *testing.T) (net.Listener, string) {
	t.Helper()

	name := filepath.Join(t.TempDir(), "test-serial-listener")
	l, err := net.ListenUnix("unix", &net.UnixAddr{Name: name, Net: "unix"})
	if err != nil {
		t.Fatal(err)
	}
	l.SetUnlinkOnClose(true)
	return l, name
}

type joinedPipeEnds struct {
	r *io.PipeReader
	w *io.PipeWriter
}

func (pe *joinedPipeEnds) Read(p []byte) (int, error) {
	return pe.r.Read(p)
}

func (pe *joinedPipeEnds) Write(p []byte) (int, error) {
	return pe.w.Write(p)
}

func (pe *joinedPipeEnds) Close() error {
	if err := pe.r.Close(); err != nil {
		pe.w.Close()
		return err
	}
	return pe.w.Close()
}

// mkTempFile returns a new temporary file that will be cleaned up
// automatically.
func mkTempFile(t *testing.T) *os.File {
	f, err := os.Create(filepath.Join(t.TempDir(), "serial-test"))
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() {
		if err := f.Close(); err != nil {
			t.Error(err)
		}
	})
	return f
}
