// Copyright (C) 2021 The Android Open Source Project
//
// 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 sdk

import (
	"encoding/json"
	"fmt"
	"testing"

	"android/soong/android"
)

// Tests for build_release.go

var (
	// Some additional test specific releases that are added after the currently supported ones and
	// so are treated as being for future releases.
	buildReleaseFuture1 = initBuildRelease("F1")
	buildReleaseFuture2 = initBuildRelease("F2")
)

func TestNameToRelease(t *testing.T) {
	t.Run("single release", func(t *testing.T) {
		release, err := nameToRelease("S")
		android.AssertDeepEquals(t, "errors", nil, err)
		android.AssertDeepEquals(t, "release", buildReleaseS, release)
	})
	t.Run("invalid release", func(t *testing.T) {
		release, err := nameToRelease("A")
		android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release)
		// Uses a wildcard in the error message to allow for additional build releases to be added to
		// the supported set without breaking this test.
		android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,T.*,F1,F2\]`, []error{err})
	})
}

func TestParseBuildReleaseSet(t *testing.T) {
	t.Run("single release", func(t *testing.T) {
		set, err := parseBuildReleaseSet("S")
		android.AssertDeepEquals(t, "errors", nil, err)
		android.AssertStringEquals(t, "set", "[S]", set.String())
	})
	t.Run("open range", func(t *testing.T) {
		set, err := parseBuildReleaseSet("F1+")
		android.AssertDeepEquals(t, "errors", nil, err)
		android.AssertStringEquals(t, "set", "[F1,F2]", set.String())
	})
	t.Run("closed range", func(t *testing.T) {
		set, err := parseBuildReleaseSet("S-F1")
		android.AssertDeepEquals(t, "errors", nil, err)
		android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String())
	})
	invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
	t.Run("invalid release", func(t *testing.T) {
		set, err := parseBuildReleaseSet("A")
		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
	})
	t.Run("invalid release in open range", func(t *testing.T) {
		set, err := parseBuildReleaseSet("A+")
		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
	})
	t.Run("invalid release in closed range start", func(t *testing.T) {
		set, err := parseBuildReleaseSet("A-S")
		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
	})
	t.Run("invalid release in closed range end", func(t *testing.T) {
		set, err := parseBuildReleaseSet("Tiramisu-A")
		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
	})
	t.Run("invalid closed range reversed", func(t *testing.T) {
		set, err := parseBuildReleaseSet("F1-S")
		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), `invalid closed range, start release "F1" is later than end release "S"`)
	})
}

func TestBuildReleaseSetContains(t *testing.T) {
	t.Run("contains", func(t *testing.T) {
		set, _ := parseBuildReleaseSet("F1-F2")
		android.AssertBoolEquals(t, "set contains F1", true, set.contains(buildReleaseFuture1))
		android.AssertBoolEquals(t, "set does not contain S", false, set.contains(buildReleaseS))
		android.AssertBoolEquals(t, "set contains F2", true, set.contains(buildReleaseFuture2))
		android.AssertBoolEquals(t, "set does not contain T", false, set.contains(buildReleaseT))
	})
}

func TestPropertyPrunerInvalidTag(t *testing.T) {
	type brokenStruct struct {
		Broken string `supported_build_releases:"A"`
	}
	type containingStruct struct {
		Nested brokenStruct
	}

	t.Run("broken struct", func(t *testing.T) {
		android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Broken of *sdk.brokenStruct: unknown release \"A\"", func() {
			newPropertyPrunerByBuildRelease(&brokenStruct{}, buildReleaseS)
		})
	})

	t.Run("nested broken struct", func(t *testing.T) {
		android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Nested.Broken of *sdk.containingStruct: unknown release \"A\"", func() {
			newPropertyPrunerByBuildRelease(&containingStruct{}, buildReleaseS)
		})
	})
}

func TestPropertyPrunerByBuildRelease(t *testing.T) {
	type nested struct {
		F1_only string `supported_build_releases:"F1"`
	}

	type mapped struct {
		Default string
		T_only  string `supported_build_releases:"Tiramisu"`
	}

	type testBuildReleasePruner struct {
		Default      string
		S_and_T_only string `supported_build_releases:"S-Tiramisu"`
		T_later      string `supported_build_releases:"Tiramisu+"`
		Nested       nested
		Mapped       map[string]*mapped
	}

	inputFactory := func() testBuildReleasePruner {
		return testBuildReleasePruner{
			Default:      "Default",
			S_and_T_only: "S_and_T_only",
			T_later:      "T_later",
			Nested: nested{
				F1_only: "F1_only",
			},
			Mapped: map[string]*mapped{
				"one": {
					Default: "one-default",
					T_only:  "one-t-only",
				},
				"two": {
					Default: "two-default",
					T_only:  "two-t-only",
				},
			},
		}
	}

	marshal := func(t interface{}) string {
		bytes, err := json.MarshalIndent(t, "", "  ")
		if err != nil {
			panic(err)
		}
		return string(bytes)
	}

	assertJsonEquals := func(t *testing.T, expected, actual interface{}) {
		t.Helper()
		expectedJson := marshal(expected)
		actualJson := marshal(actual)
		if actualJson != expectedJson {
			t.Errorf("test struct: expected:\n%s\n got:\n%s", expectedJson, actualJson)
		}
	}

	t.Run("target S", func(t *testing.T) {
		testStruct := inputFactory()
		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseS)
		pruner.pruneProperties(&testStruct)

		expected := inputFactory()
		expected.T_later = ""
		expected.Nested.F1_only = ""
		expected.Mapped["one"].T_only = ""
		expected.Mapped["two"].T_only = ""
		assertJsonEquals(t, expected, testStruct)
	})

	t.Run("target T", func(t *testing.T) {
		testStruct := inputFactory()
		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseT)
		pruner.pruneProperties(&testStruct)

		expected := inputFactory()
		expected.Nested.F1_only = ""
		assertJsonEquals(t, expected, testStruct)
	})

	t.Run("target F1", func(t *testing.T) {
		testStruct := inputFactory()
		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture1)
		pruner.pruneProperties(&testStruct)

		expected := inputFactory()
		expected.S_and_T_only = ""
		expected.Mapped["one"].T_only = ""
		expected.Mapped["two"].T_only = ""
		assertJsonEquals(t, expected, testStruct)
	})

	t.Run("target F2", func(t *testing.T) {
		testStruct := inputFactory()
		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture2)
		pruner.pruneProperties(&testStruct)

		expected := inputFactory()
		expected.S_and_T_only = ""
		expected.Nested.F1_only = ""
		expected.Mapped["one"].T_only = ""
		expected.Mapped["two"].T_only = ""
		assertJsonEquals(t, expected, testStruct)
	})
}
