| // 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,Tiramisu,UpsideDownCake,F1,F2,current\]`, []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,current]", 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,UpsideDownCake,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) |
| }) |
| } |