package signals

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"testing"
	"time"

	"v.io/core/veyron2"
	"v.io/core/veyron2/context"
	"v.io/core/veyron2/ipc"
	"v.io/core/veyron2/mgmt"
	"v.io/core/veyron2/naming"
	"v.io/core/veyron2/rt"
	"v.io/core/veyron2/services/mgmt/appcycle"

	"v.io/core/veyron/lib/expect"
	"v.io/core/veyron/lib/flags/consts"
	"v.io/core/veyron/lib/modules"
	"v.io/core/veyron/lib/testutil"
	"v.io/core/veyron/lib/testutil/security"
	"v.io/core/veyron/profiles"
	vflag "v.io/core/veyron/security/flag"
	"v.io/core/veyron/services/mgmt/device"
)

// TestHelperProcess is boilerplate for the modules setup.
func TestHelperProcess(t *testing.T) {
	modules.DispatchInTest()
}

func init() {
	testutil.Init()
	modules.RegisterChild("handleDefaults", "", handleDefaults)
	modules.RegisterChild("handleCustom", "", handleCustom)
	modules.RegisterChild("handleCustomWithStop", "", handleCustomWithStop)
	modules.RegisterChild("handleDefaultsIgnoreChan", "", handleDefaultsIgnoreChan)
}

func stopLoop(ctx *context.T, stdin io.Reader, ch chan<- struct{}) {
	scanner := bufio.NewScanner(stdin)
	for scanner.Scan() {
		switch scanner.Text() {
		case "close":
			close(ch)
			return
		case "stop":
			veyron2.GetAppCycle(ctx).Stop()
		}
	}
}

func program(stdin io.Reader, stdout io.Writer, signals ...os.Signal) {
	runtime, err := rt.New()
	if err != nil {
		panic(err)
	}

	ctx := runtime.NewContext()

	closeStopLoop := make(chan struct{})
	go stopLoop(ctx, stdin, closeStopLoop)
	wait := ShutdownOnSignals(ctx, signals...)
	fmt.Fprintf(stdout, "ready\n")
	fmt.Fprintf(stdout, "received signal %s\n", <-wait)
	runtime.Cleanup()
	<-closeStopLoop
}

func handleDefaults(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	program(stdin, stdout)
	return nil
}

func handleCustom(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	program(stdin, stdout, syscall.SIGABRT)
	return nil
}

func handleCustomWithStop(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	program(stdin, stdout, STOP, syscall.SIGABRT, syscall.SIGHUP)
	return nil
}

func handleDefaultsIgnoreChan(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	runtime, err := rt.New()
	if err != nil {
		panic(err)
	}
	defer runtime.Cleanup()

	ctx := runtime.NewContext()

	closeStopLoop := make(chan struct{})
	go stopLoop(ctx, stdin, closeStopLoop)
	ShutdownOnSignals(ctx)
	fmt.Fprintf(stdout, "ready\n")
	<-closeStopLoop
	return nil
}

func isSignalInSet(sig os.Signal, set []os.Signal) bool {
	for _, s := range set {
		if sig == s {
			return true
		}
	}
	return false
}

func checkSignalIsDefault(t *testing.T, sig os.Signal) {
	if !isSignalInSet(sig, defaultSignals()) {
		t.Errorf("signal %s not in default signal set, as expected", sig)
	}
}

func checkSignalIsNotDefault(t *testing.T, sig os.Signal) {
	if isSignalInSet(sig, defaultSignals()) {
		t.Errorf("signal %s unexpectedly in default signal set", sig)
	}
}

func newShell(t *testing.T, command string) (*modules.Shell, modules.Handle, *expect.Session) {
	sh, err := modules.NewShell(nil)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	handle, err := sh.Start(command, nil)
	if err != nil {
		sh.Cleanup(os.Stderr, os.Stderr)
		t.Fatalf("unexpected error: %s", err)
		return nil, nil, nil
	}
	session := expect.NewSession(t, handle.Stdout(), time.Minute)
	return sh, handle, session
}

// TestCleanShutdownSignal verifies that sending a signal to a child that
// handles it by default causes the child to shut down cleanly.
func TestCleanShutdownSignal(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	checkSignalIsDefault(t, syscall.SIGINT)
	syscall.Kill(h.Pid(), syscall.SIGINT)
	s.Expectf("received signal %s", syscall.SIGINT)
	fmt.Fprintf(h.Stdin(), "close\n")
	s.ExpectEOF()
}

// TestCleanShutdownStop verifies that sending a stop comamnd to a child that
// handles stop commands by default causes the child to shut down cleanly.
func TestCleanShutdownStop(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	fmt.Fprintf(h.Stdin(), "stop\n")
	s.Expectf("received signal %s", veyron2.LocalStop)
	fmt.Fprintf(h.Stdin(), "close\n")
	s.ExpectEOF()

}

// TestCleanShutdownStopCustom verifies that sending a stop comamnd to a child
// that handles stop command as part of a custom set of signals handled, causes
// the child to shut down cleanly.
func TestCleanShutdownStopCustom(t *testing.T) {
	sh, h, s := newShell(t, "handleCustomWithStop")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	fmt.Fprintf(h.Stdin(), "stop\n")
	s.Expectf("received signal %s", veyron2.LocalStop)
	fmt.Fprintf(h.Stdin(), "close\n")
	s.ExpectEOF()
}

func testExitStatus(t *testing.T, h modules.Handle, s *expect.Session, code int) {
	s.ExpectEOF()
	_, file, line, _ := runtime.Caller(1)
	file = filepath.Base(file)
	if got, want := h.Shutdown(os.Stdout, os.Stderr), fmt.Errorf("exit status %d", code); got.Error() != want.Error() {
		t.Errorf("%s:%d: got %q, want %q", file, line, got, want)
	}
}

// TestStopNoHandler verifies that sending a stop command to a child that does
// not handle stop commands causes the child to exit immediately.
func TestStopNoHandler(t *testing.T) {
	sh, h, s := newShell(t, "handleCustom")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	fmt.Fprintf(h.Stdin(), "stop\n")
	testExitStatus(t, h, s, veyron2.UnhandledStopExitCode)
}

// TestDoubleSignal verifies that sending a succession of two signals to a child
// that handles these signals by default causes the child to exit immediately
// upon receiving the second signal.
func TestDoubleSignal(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	checkSignalIsDefault(t, syscall.SIGTERM)
	syscall.Kill(h.Pid(), syscall.SIGTERM)
	s.Expectf("received signal %s", syscall.SIGTERM)
	checkSignalIsDefault(t, syscall.SIGINT)
	syscall.Kill(h.Pid(), syscall.SIGINT)
	testExitStatus(t, h, s, DoubleStopExitCode)
}

// TestSignalAndStop verifies that sending a signal followed by a stop command
// to a child that handles these by default causes the child to exit immediately
// upon receiving the stop command.
func TestSignalAndStop(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	checkSignalIsDefault(t, syscall.SIGTERM)
	syscall.Kill(h.Pid(), syscall.SIGTERM)
	s.Expectf("received signal %s", syscall.SIGTERM)
	fmt.Fprintf(h.Stdin(), "stop\n")
	testExitStatus(t, h, s, DoubleStopExitCode)
}

// TestDoubleStop verifies that sending a succession of stop commands to a child
// that handles stop commands by default causes the child to exit immediately
// upon receiving the second stop command.
func TestDoubleStop(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	fmt.Fprintf(h.Stdin(), "stop\n")
	s.Expectf("received signal %s", veyron2.LocalStop)
	fmt.Fprintf(h.Stdin(), "stop\n")
	testExitStatus(t, h, s, DoubleStopExitCode)
}

// TestSendUnhandledSignal verifies that sending a signal that the child does
// not handle causes the child to exit as per the signal being sent.
func TestSendUnhandledSignal(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaults")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	checkSignalIsNotDefault(t, syscall.SIGABRT)
	syscall.Kill(h.Pid(), syscall.SIGABRT)
	testExitStatus(t, h, s, 2)
}

// TestDoubleSignalIgnoreChan verifies that, even if we ignore the channel that
// ShutdownOnSignals returns, sending two signals should still cause the
// process to exit (ensures that there is no dependency in ShutdownOnSignals
// on having a goroutine read from the returned channel).
func TestDoubleSignalIgnoreChan(t *testing.T) {
	sh, h, s := newShell(t, "handleDefaultsIgnoreChan")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	// Even if we ignore the channel that ShutdownOnSignals returns,
	// sending two signals should still cause the process to exit.
	checkSignalIsDefault(t, syscall.SIGTERM)
	syscall.Kill(h.Pid(), syscall.SIGTERM)
	checkSignalIsDefault(t, syscall.SIGINT)
	syscall.Kill(h.Pid(), syscall.SIGINT)
	testExitStatus(t, h, s, DoubleStopExitCode)
}

// TestHandlerCustomSignal verifies that sending a non-default signal to a
// server that listens for that signal causes the server to shut down cleanly.
func TestHandlerCustomSignal(t *testing.T) {
	sh, h, s := newShell(t, "handleCustom")
	defer sh.Cleanup(os.Stderr, os.Stderr)
	s.Expect("ready")
	checkSignalIsNotDefault(t, syscall.SIGABRT)
	syscall.Kill(h.Pid(), syscall.SIGABRT)
	s.Expectf("received signal %s", syscall.SIGABRT)
	fmt.Fprintf(h.Stdin(), "stop\n")
	s.ExpectEOF()
}

// TestHandlerCustomSignalWithStop verifies that sending a custom stop signal
// to a server that listens for that signal causes the server to shut down
// cleanly, even when a STOP signal is also among the handled signals.
func TestHandlerCustomSignalWithStop(t *testing.T) {
	for _, signal := range []syscall.Signal{syscall.SIGABRT, syscall.SIGHUP} {
		sh, h, s := newShell(t, "handleCustomWithStop")
		s.Expect("ready")
		checkSignalIsNotDefault(t, signal)
		syscall.Kill(h.Pid(), signal)
		s.Expectf("received signal %s", signal)
		fmt.Fprintf(h.Stdin(), "close\n")
		s.ExpectEOF()
		sh.Cleanup(os.Stderr, os.Stderr)
	}
}

// TestParseSignalsList verifies that ShutdownOnSignals correctly interprets
// the input list of signals.
func TestParseSignalsList(t *testing.T) {
	list := []os.Signal{STOP, syscall.SIGTERM}
	ShutdownOnSignals(nil, list...)
	if !isSignalInSet(syscall.SIGTERM, list) {
		t.Errorf("signal %s not in signal set, as expected: %v", syscall.SIGTERM, list)
	}
	if !isSignalInSet(STOP, list) {
		t.Errorf("signal %s not in signal set, as expected: %v", STOP, list)
	}
}

type configServer struct {
	ch chan<- string
}

func (c *configServer) Set(_ ipc.ServerContext, key, value string) error {
	if key != mgmt.AppCycleManagerConfigKey {
		return fmt.Errorf("Unexpected key: %v", key)
	}
	c.ch <- value
	return nil

}

func createConfigServer(t *testing.T, ctx *context.T) (ipc.Server, string, <-chan string) {
	server, err := veyron2.NewServer(ctx)
	if err != nil {
		t.Fatalf("Got error: %v", err)
	}
	ch := make(chan string)
	var ep []naming.Endpoint
	if ep, err = server.Listen(profiles.LocalListenSpec); err != nil {
		t.Fatalf("Got error: %v", err)
	}
	if err := server.Serve("", device.ConfigServer(&configServer{ch}), vflag.NewAuthorizerOrDie()); err != nil {
		t.Fatalf("Got error: %v", err)
	}
	return server, ep[0].Name(), ch

}

// TestCleanRemoteShutdown verifies that remote shutdown works correctly.
func TestCleanRemoteShutdown(t *testing.T) {
	runtime, err := rt.New()
	if err != nil {
		panic(err)
	}
	defer runtime.Cleanup()
	ctx := runtime.NewContext()

	sh, err := modules.NewShell(nil)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	defer sh.Cleanup(os.Stderr, os.Stderr)

	// Set the child process up with a blessing from the parent so that
	// the default authorization works for RPCs between the two.
	principal := veyron2.GetPrincipal(ctx)
	childcreds, _ := security.ForkCredentials(principal, "child")
	defer os.RemoveAll(childcreds)
	configServer, configServiceName, ch := createConfigServer(t, ctx)
	defer configServer.Stop()
	sh.SetVar(consts.VeyronCredentials, childcreds)
	sh.SetConfigKey(mgmt.ParentNameConfigKey, configServiceName)
	sh.SetConfigKey(mgmt.ProtocolConfigKey, "tcp")
	sh.SetConfigKey(mgmt.AddressConfigKey, "127.0.0.1:0")
	h, err := sh.Start("handleDefaults", nil)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	s := expect.NewSession(t, h.Stdout(), time.Minute)
	appCycleName := <-ch
	s.Expect("ready")
	appCycle := appcycle.AppCycleClient(appCycleName)
	stream, err := appCycle.Stop(ctx)
	if err != nil {
		t.Fatalf("Got error: %v", err)
	}
	rStream := stream.RecvStream()
	if rStream.Advance() || rStream.Err() != nil {
		t.Errorf("Expected EOF, got (%v, %v) instead: ", rStream.Value(), rStream.Err())
	}
	if err := stream.Finish(); err != nil {
		t.Fatalf("Got error: %v", err)
	}
	s.Expectf("received signal %s", veyron2.RemoteStop)
	fmt.Fprintf(h.Stdin(), "close\n")
	s.ExpectEOF()
}
