// Copyright 2018 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 testsharder

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"sort"
	"testing"

	"go.fuchsia.dev/tools/build"
)

var qemuPlatform = DimensionSet{
	DeviceType: "QEMU",
}

var nucPlatform = DimensionSet{
	DeviceType: "NUC",
}

var linuxPlatform = DimensionSet{
	OS: "Linux",
}

var macPlatform = DimensionSet{
	OS: "Mac",
}

var qemuEnv = Environment{
	Dimensions: qemuPlatform,
}

var nucEnv = Environment{
	Dimensions: nucPlatform,
}

var linuxEnv = Environment{
	Dimensions: linuxPlatform,
}

var macEnv = Environment{
	Dimensions: macPlatform,
}

var specFoo1 = TestSpec{
	Test: Test{
		Name:    "//obsidian/bin/foo:foo_unittests",
		Path:    "/system/test/foo_unittests",
		OS:      Fuchsia,
		Command: []string{"/system/test/foo_unittests", "bar", "baz"},
	},
	Envs: []Environment{qemuEnv},
}

var specFoo2 = TestSpec{
	Test: Test{
		Name: "//obsidian/bin/foo:foo_integration_tests",
		Path: "/system/test/foo_integration_tests",
		OS:   Fuchsia,
	},
	Envs: []Environment{qemuEnv, nucEnv},
}

var specBar = TestSpec{
	Test: Test{
		Name: "//obsidian/lib/bar:bar_tests",
		Path: "/system/test/bar_tests",
		OS:   Fuchsia,
	},
	Envs: []Environment{qemuEnv},
}

var specBaz = TestSpec{
	Test: Test{
		Name: "//obsidian/public/lib/baz:baz_host_tests",
		Path: "/$root_build_dir/baz_host_tests",
		OS:   Linux,
	},
	Envs: []Environment{linuxEnv, macEnv},
}

func TestLoadTestSpecs(t *testing.T) {
	areEqual := func(a, b []TestSpec) bool {
		stringify := func(spec TestSpec) string {
			return fmt.Sprintf("%#v", spec)
		}
		sort := func(list []TestSpec) {
			sort.Slice(list[:], func(i, j int) bool {
				return stringify(list[i]) < stringify(list[j])
			})
		}
		sort(a)
		sort(b)
		return reflect.DeepEqual(a, b)
	}

	tmpDir, err := ioutil.TempDir("", "test-spec")
	if err != nil {
		t.Fatalf("failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	deps := []string{"path/to/first/dep", "path/to/second"}
	depsFilepath := filepath.Join(tmpDir, "deps.json")
	df, err := os.Create(depsFilepath)
	if err != nil {
		t.Fatal(err)
	}
	defer df.Close()
	if err := json.NewEncoder(df).Encode(&deps); err != nil {
		t.Fatalf("failed to create JSON encoder: %v", err)
	}

	specBazIn := specBaz
	specBazIn.DepsFile = "deps.json"
	initial := []TestSpec{specBar, specBazIn}

	manifest := filepath.Join(tmpDir, build.TestSpecManifestName)
	m, err := os.Create(manifest)
	if err != nil {
		t.Fatal(err)
	}
	defer m.Close()
	if err := json.NewEncoder(m).Encode(&initial); err != nil {
		t.Fatal(err)
	}

	actual, err := LoadTestSpecs(tmpDir)
	if err != nil {
		t.Fatalf("failed to load test specs: %v", err)
	}

	specBazOut := specBaz
	specBazOut.Deps = deps
	expected := []TestSpec{specBar, specBazOut}

	if !areEqual(expected, actual) {
		t.Fatalf("test specs not properly loaded:\nexpected:\n%+v\nactual:\n%+v", expected, actual)
	}
}

func TestValidateTestSpecs(t *testing.T) {
	noTestNameSpec := TestSpec{
		Test: Test{
			Path: "/system/test/baz_tests",
			OS:   Linux,
		},
		Envs: []Environment{qemuEnv},
	}
	noTestPathSpec := TestSpec{
		Test: Test{
			Name: "//obsidian/public/lib/baz:baz_tests",
			OS:   Linux,
		},
		Envs: []Environment{qemuEnv},
	}
	noOSSpec := TestSpec{
		Test: Test{
			Name: "//obsidian/bin/foo:foo_unittests",
			Path: "/system/test/foo_unittests",
		},
	}
	badEnvSpec := TestSpec{
		Test: Test{
			Name: "//obsidian/public/lib/baz:baz_tests",
			Path: "/system/test/baz_tests",
			OS:   Linux,
		},
		Envs: []Environment{
			Environment{
				Dimensions: DimensionSet{
					DeviceType: "NON-EXISTENT-DEVICE",
				},
			},
		},
	}
	platforms := []DimensionSet{qemuPlatform, nucPlatform}

	t.Run("valid specs are validated", func(t *testing.T) {
		validSpecLists := [][]TestSpec{
			{specFoo1}, {specFoo2}, {specBar},
			{specFoo1, specFoo2}, {specFoo1, specBar}, {specFoo2, specBar},
			{specFoo1, specFoo2, specBar},
		}
		for _, list := range validSpecLists {
			if err := ValidateTestSpecs(list, platforms); err != nil {
				t.Fatalf("valid specs marked as invalid: %+v: %v", list, err)
			}
		}
	})

	t.Run("invalid specs are invalidated", func(t *testing.T) {
		invalidSpecLists := [][]TestSpec{
			{noOSSpec}, {noTestNameSpec}, {noTestPathSpec}, {badEnvSpec},
			{noTestNameSpec, noTestPathSpec}, {noTestNameSpec, badEnvSpec},
			{noTestPathSpec, badEnvSpec},
			{noTestNameSpec, noTestPathSpec, badEnvSpec},
		}
		for _, list := range invalidSpecLists {
			if err := ValidateTestSpecs(list, platforms); err == nil {
				t.Fatalf("invalid specs marked as valid: %+v", list)
			}
		}
	})
}
