package scheduler

import (
	"bytes"
	"io/ioutil"
	"local/firestormy/config"
	"local/logb"
	"local/storage"
	"os"
	"testing"
	"time"
)

func TestNewBashJobBadCron(t *testing.T) {
	_, err := newBashJob("1 1 1 ", "hostname")
	if err == nil {
		t.Fatal(err)
	}
}

func TestNewBashJobAndRun(t *testing.T) {
	config.Store = storage.NewMap()
	cases := []struct {
		sched string
		cmd   string
		out   string
	}{
		{
			sched: "1 1 1 1 1",
			cmd:   "hostname",
			out:   os.Getenv("HOSTNAME"),
		},
		{
			sched: "@hourly",
			cmd:   "hostname",
			out:   os.Getenv("HOSTNAME"),
		},
		{
			sched: "@hourly",
			cmd:   "exit 1",
		},
	}

	for _, c := range cases {
		b, clean := captureLog()
		defer clean()
		j, err := newBashJob(c.sched, c.cmd)
		if err != nil {
			t.Error(err)
			continue
		}
		j.Run()
		if !bytes.Contains(b.Bytes(), []byte(c.out)) {
			t.Errorf("(%s, %s) => %s", c.sched, c.cmd, b.Bytes())
		}
	}
}

func TestJobEncodeDecode(t *testing.T) {
	config.Store = storage.NewMap()
	buff, clean := captureLog()
	defer clean()

	j, err := newBashJob("1 1 1 1 1", "hostname")
	if err != nil {
		t.Fatal(err)
	}

	j.foo()
	if !bytes.Contains(buff.Bytes(), []byte(os.Getenv("HOSTNAME"))) {
		t.Errorf("%s", buff.Bytes())
	}
	buff.Reset()

	b, err := j.Encode()
	if err != nil {
		t.Fatal(err)
	}

	k := &Job{}
	if err := k.Decode(b); err != nil {
		t.Logf("decoded %+v", k)
		t.Fatal(err)
	}

	if k.Schedule != j.Schedule {
		t.Error(k.Schedule, "vs", j.Schedule)
	}
	if k.Name != j.Name {
		t.Error(k.Name, "vs", j.Name)
	}
	if diff := k.LastRun.Unix() - j.LastRun.Unix(); (diff > 0 && diff < int64(time.Hour)) || (diff < 0 && -1*diff < int64(time.Hour)) {
		t.Error(j.LastRun, "vs", k.LastRun)
	}
	if k.LastStatus != j.LastStatus {
		t.Error(j.LastStatus, "vs", k.LastStatus)
	}
	if k.LastRuntime != j.LastRuntime {
		t.Error(j.LastRuntime, "vs", k.LastRuntime)
	}
	if string(k.LastOutput) != string(j.LastOutput) {
		t.Error(j.LastOutput, "vs", k.LastOutput)
	}

	k.foo()
	if !bytes.Contains(buff.Bytes(), []byte(os.Getenv("HOSTNAME"))) {
		t.Errorf("%s", buff.Bytes())
	}
}

func captureLog() (*bytes.Buffer, func()) {
	was := logb.Writer()
	wase := os.Stderr
	f, _ := ioutil.TempFile(os.TempDir(), "test.newBashJobAndRun")
	os.Stderr = f
	b := bytes.NewBuffer(nil)
	logb.SetWriter(b)
	return b, func() {
		os.Remove(f.Name())
		logb.SetWriter(was)
		os.Stderr = wase
	}
}
