// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package provisioner

import (
	"context"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"testing"

	"cos.googlesource.com/cos/tools.git/src/pkg/fakes"
	"golang.org/x/sys/unix"
)

const trueExecutable = "#!/bin/bash\ntrue"

func testDataDir(t *testing.T) string {
	t.Helper()
	path, err := filepath.Abs("testdata")
	if err != nil {
		t.Fatal(err)
	}
	return path
}

func stubMount() {
	mountFunc = func(a1, a2, a3 string, a4 uintptr, a5 string) error {
		return nil
	}
	unmountFunc = func(a1 string, a2 int) error {
		return nil
	}
}

func restoreMount() {
	mountFunc = unix.Mount
	unmountFunc = unix.Unmount
}

func stubMountInfo(filePath, mountPoint string) error {
	if err := os.MkdirAll(filepath.Dir(filePath), 0755); err != nil {
		return err
	}
	return ioutil.WriteFile(filePath, []byte(fmt.Sprintf("0 0 0 / %s ro\n", mountPoint)), 0644)
}

func TestStateExists(t *testing.T) {
	ctx := context.Background()
	dir, err := ioutil.TempDir("", "provisioner-test-")
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { os.RemoveAll(dir) })
	if err := ioutil.WriteFile(filepath.Join(dir, "state.json"), []byte("{}"), 0660); err != nil {
		t.Fatal(err)
	}
	deps := Deps{
		GCSClient:           nil,
		TarCmd:              "",
		SystemctlCmd:        "",
		DockerCredentialGCR: []byte(trueExecutable),
		VeritySetupImage:    []byte(trueExecutable),
		HandleDiskLayoutBin: []byte(trueExecutable),
	}
	config := Config{}
	if err := Run(ctx, deps, dir, config); err != errStateAlreadyExists {
		t.Fatalf("Run(ctx, %+v, %q, %+v) = %v; want %v", deps, dir, config, err, errStateAlreadyExists)
	}
}

func TestRunInvalidArgs(t *testing.T) {
	stubMount()
	t.Cleanup(restoreMount)
	tests := []struct {
		name   string
		config Config
	}{
		{
			name: "RunScript",
			config: Config{
				Steps: []StepConfig{
					{
						Type: "RunScript",
						Args: []byte("{}"),
					},
				},
			},
		},
	}
	for _, test := range tests {
		test := test
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			ctx := context.Background()
			tempDir, err := ioutil.TempDir("", "provisioner-test-")
			if err != nil {
				t.Fatal(err)
			}
			defer os.RemoveAll(tempDir)
			gcs := fakes.GCSForTest(t)
			deps := Deps{
				GCSClient:           gcs.Client,
				TarCmd:              "tar",
				SystemctlCmd:        "/bin/true",
				RootDir:             tempDir,
				DockerCredentialGCR: []byte(trueExecutable),
				VeritySetupImage:    []byte(trueExecutable),
				HandleDiskLayoutBin: []byte(trueExecutable),
			}
			stateDir := filepath.Join(tempDir, "var", "lib", ".cos-customizer")
			if err := stubMountInfo(filepath.Join(tempDir, "proc", "self", "mountinfo"), filepath.Join(stateDir, "bin")); err != nil {
				t.Fatal(err)
			}
			funcCall := fmt.Sprintf("Run(ctx, %+v, %q, %+v)", deps, stateDir, test.config)
			if err := Run(ctx, deps, stateDir, test.config); err == nil {
				t.Fatalf("%s = nil; want invalid args", funcCall)
			}
		})
	}
}

func TestRunFailure(t *testing.T) {
	stubMount()
	t.Cleanup(restoreMount)
	testData := testDataDir(t)
	buildCtxDir, err := ioutil.TempDir("", "provisioner-test-")
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { os.RemoveAll(buildCtxDir) })
	buildCtx := filepath.Join(buildCtxDir, "test.tar")
	if err := exec.Command("tar", "cf", buildCtx, "-C", filepath.Join(testData, "test_ctx"), ".").Run(); err != nil {
		t.Fatal(err)
	}
	tests := []struct {
		name       string
		gcsObjects map[string]string
		config     Config
	}{
		{
			name: "RunScript",
			gcsObjects: map[string]string{
				"/test/test.tar": buildCtx,
			},
			config: Config{
				BuildContexts: map[string]string{
					"bc": "gs://test/test.tar",
				},
				Steps: []StepConfig{
					{
						Type: "RunScript",
						Args: []byte(`{"BuildContext": "bc", "Path": "run_env.sh"}`),
					},
				},
			},
		},
	}
	for _, test := range tests {
		test := test
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			ctx := context.Background()
			tempDir, err := ioutil.TempDir("", "provisioner-test-")
			if err != nil {
				t.Fatal(err)
			}
			defer os.RemoveAll(tempDir)
			gcs := fakes.GCSForTest(t)
			for name, path := range test.gcsObjects {
				data, err := ioutil.ReadFile(path)
				if err != nil {
					t.Fatal(err)
				}
				gcs.Objects[name] = data
			}
			deps := Deps{
				GCSClient:           gcs.Client,
				TarCmd:              "tar",
				SystemctlCmd:        "/bin/true",
				RootDir:             tempDir,
				DockerCredentialGCR: []byte(trueExecutable),
				VeritySetupImage:    []byte(trueExecutable),
				HandleDiskLayoutBin: []byte(trueExecutable),
			}
			stateDir := filepath.Join(tempDir, "var", "lib", ".cos-customizer")
			if err := stubMountInfo(filepath.Join(tempDir, "proc", "self", "mountinfo"), filepath.Join(stateDir, "bin")); err != nil {
				t.Fatal(err)
			}
			funcCall := fmt.Sprintf("Run(ctx, %+v, %q, %+v)", deps, stateDir, test.config)
			if err := Run(ctx, deps, stateDir, test.config); err == nil {
				t.Fatalf("%s = nil; want err", funcCall)
			}
		})
	}
}

func TestRunSuccess(t *testing.T) {
	stubMount()
	t.Cleanup(restoreMount)
	testData := testDataDir(t)
	buildCtxDir, err := ioutil.TempDir("", "provisioner-test-")
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(func() { os.RemoveAll(buildCtxDir) })
	buildCtx := filepath.Join(buildCtxDir, "test.tar")
	if err := exec.Command("tar", "cf", buildCtx, "-C", filepath.Join(testData, "test_ctx"), ".").Run(); err != nil {
		t.Fatal(err)
	}
	tests := []struct {
		name       string
		gcsObjects map[string]string
		config     Config
	}{
		{
			name:   "EmptyConfig",
			config: Config{},
		},
		{
			name: "RunScript",
			gcsObjects: map[string]string{
				"/test/test.tar": buildCtx,
			},
			config: Config{
				BuildContexts: map[string]string{
					"bc": "gs://test/test.tar",
				},
				Steps: []StepConfig{
					{
						Type: "RunScript",
						Args: []byte(`{"BuildContext": "bc", "Path": "run.sh"}`),
					},
					{
						Type: "RunScript",
						Args: []byte(`{"BuildContext": "bc", "Path": "run_env.sh", "Env": "TEST=t"}`),
					},
				},
			},
		},
	}
	for _, test := range tests {
		test := test
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			ctx := context.Background()
			tempDir, err := ioutil.TempDir("", "provisioner-test-")
			if err != nil {
				t.Fatal(err)
			}
			defer os.RemoveAll(tempDir)
			gcs := fakes.GCSForTest(t)
			for name, path := range test.gcsObjects {
				data, err := ioutil.ReadFile(path)
				if err != nil {
					t.Fatal(err)
				}
				gcs.Objects[name] = data
			}
			deps := Deps{
				GCSClient:           gcs.Client,
				TarCmd:              "tar",
				SystemctlCmd:        "/bin/true",
				RootDir:             tempDir,
				DockerCredentialGCR: []byte(trueExecutable),
				VeritySetupImage:    []byte(trueExecutable),
				HandleDiskLayoutBin: []byte(trueExecutable),
			}
			stateDir := filepath.Join(tempDir, "var", "lib", ".cos-customizer")
			if err := stubMountInfo(filepath.Join(tempDir, "proc", "self", "mountinfo"), filepath.Join(stateDir, "bin")); err != nil {
				t.Fatal(err)
			}
			funcCall := fmt.Sprintf("Run(ctx, %+v, %q, %+v)", deps, stateDir, test.config)
			if err := Run(ctx, deps, stateDir, test.config); err != nil {
				t.Fatalf("%s = %v; want nil", funcCall, err)
			}
		})
	}
}
