• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package sdk
16
17import (
18	"encoding/json"
19	"fmt"
20	"testing"
21
22	"android/soong/android"
23)
24
25// Tests for build_release.go
26
27var (
28	// Some additional test specific releases that are added after the currently supported ones and
29	// so are treated as being for future releases.
30	buildReleaseFuture1 = initBuildRelease("F1")
31	buildReleaseFuture2 = initBuildRelease("F2")
32)
33
34func TestNameToRelease(t *testing.T) {
35	t.Run("single release", func(t *testing.T) {
36		release, err := nameToRelease("S")
37		android.AssertDeepEquals(t, "errors", nil, err)
38		android.AssertDeepEquals(t, "release", buildReleaseS, release)
39	})
40	t.Run("invalid release", func(t *testing.T) {
41		release, err := nameToRelease("A")
42		android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release)
43		// Uses a wildcard in the error message to allow for additional build releases to be added to
44		// the supported set without breaking this test.
45		android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,T.*,F1,F2\]`, []error{err})
46	})
47}
48
49func TestParseBuildReleaseSet(t *testing.T) {
50	t.Run("single release", func(t *testing.T) {
51		set, err := parseBuildReleaseSet("S")
52		android.AssertDeepEquals(t, "errors", nil, err)
53		android.AssertStringEquals(t, "set", "[S]", set.String())
54	})
55	t.Run("open range", func(t *testing.T) {
56		set, err := parseBuildReleaseSet("F1+")
57		android.AssertDeepEquals(t, "errors", nil, err)
58		android.AssertStringEquals(t, "set", "[F1,F2]", set.String())
59	})
60	t.Run("closed range", func(t *testing.T) {
61		set, err := parseBuildReleaseSet("S-F1")
62		android.AssertDeepEquals(t, "errors", nil, err)
63		android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String())
64	})
65	invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
66	t.Run("invalid release", func(t *testing.T) {
67		set, err := parseBuildReleaseSet("A")
68		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
69		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
70	})
71	t.Run("invalid release in open range", func(t *testing.T) {
72		set, err := parseBuildReleaseSet("A+")
73		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
74		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
75	})
76	t.Run("invalid release in closed range start", func(t *testing.T) {
77		set, err := parseBuildReleaseSet("A-S")
78		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
79		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
80	})
81	t.Run("invalid release in closed range end", func(t *testing.T) {
82		set, err := parseBuildReleaseSet("Tiramisu-A")
83		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
84		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
85	})
86	t.Run("invalid closed range reversed", func(t *testing.T) {
87		set, err := parseBuildReleaseSet("F1-S")
88		android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
89		android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), `invalid closed range, start release "F1" is later than end release "S"`)
90	})
91}
92
93func TestBuildReleaseSetContains(t *testing.T) {
94	t.Run("contains", func(t *testing.T) {
95		set, _ := parseBuildReleaseSet("F1-F2")
96		android.AssertBoolEquals(t, "set contains F1", true, set.contains(buildReleaseFuture1))
97		android.AssertBoolEquals(t, "set does not contain S", false, set.contains(buildReleaseS))
98		android.AssertBoolEquals(t, "set contains F2", true, set.contains(buildReleaseFuture2))
99		android.AssertBoolEquals(t, "set does not contain T", false, set.contains(buildReleaseT))
100	})
101}
102
103func TestPropertyPrunerInvalidTag(t *testing.T) {
104	type brokenStruct struct {
105		Broken string `supported_build_releases:"A"`
106	}
107	type containingStruct struct {
108		Nested brokenStruct
109	}
110
111	t.Run("broken struct", func(t *testing.T) {
112		android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Broken of *sdk.brokenStruct: unknown release \"A\"", func() {
113			newPropertyPrunerByBuildRelease(&brokenStruct{}, buildReleaseS)
114		})
115	})
116
117	t.Run("nested broken struct", func(t *testing.T) {
118		android.AssertPanicMessageContains(t, "error", "invalid `supported_build_releases` tag on Nested.Broken of *sdk.containingStruct: unknown release \"A\"", func() {
119			newPropertyPrunerByBuildRelease(&containingStruct{}, buildReleaseS)
120		})
121	})
122}
123
124func TestPropertyPrunerByBuildRelease(t *testing.T) {
125	type nested struct {
126		F1_only string `supported_build_releases:"F1"`
127	}
128
129	type mapped struct {
130		Default string
131		T_only  string `supported_build_releases:"Tiramisu"`
132	}
133
134	type testBuildReleasePruner struct {
135		Default      string
136		S_and_T_only string `supported_build_releases:"S-Tiramisu"`
137		T_later      string `supported_build_releases:"Tiramisu+"`
138		Nested       nested
139		Mapped       map[string]*mapped
140	}
141
142	inputFactory := func() testBuildReleasePruner {
143		return testBuildReleasePruner{
144			Default:      "Default",
145			S_and_T_only: "S_and_T_only",
146			T_later:      "T_later",
147			Nested: nested{
148				F1_only: "F1_only",
149			},
150			Mapped: map[string]*mapped{
151				"one": {
152					Default: "one-default",
153					T_only:  "one-t-only",
154				},
155				"two": {
156					Default: "two-default",
157					T_only:  "two-t-only",
158				},
159			},
160		}
161	}
162
163	marshal := func(t interface{}) string {
164		bytes, err := json.MarshalIndent(t, "", "  ")
165		if err != nil {
166			panic(err)
167		}
168		return string(bytes)
169	}
170
171	assertJsonEquals := func(t *testing.T, expected, actual interface{}) {
172		t.Helper()
173		expectedJson := marshal(expected)
174		actualJson := marshal(actual)
175		if actualJson != expectedJson {
176			t.Errorf("test struct: expected:\n%s\n got:\n%s", expectedJson, actualJson)
177		}
178	}
179
180	t.Run("target S", func(t *testing.T) {
181		testStruct := inputFactory()
182		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseS)
183		pruner.pruneProperties(&testStruct)
184
185		expected := inputFactory()
186		expected.T_later = ""
187		expected.Nested.F1_only = ""
188		expected.Mapped["one"].T_only = ""
189		expected.Mapped["two"].T_only = ""
190		assertJsonEquals(t, expected, testStruct)
191	})
192
193	t.Run("target T", func(t *testing.T) {
194		testStruct := inputFactory()
195		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseT)
196		pruner.pruneProperties(&testStruct)
197
198		expected := inputFactory()
199		expected.Nested.F1_only = ""
200		assertJsonEquals(t, expected, testStruct)
201	})
202
203	t.Run("target F1", func(t *testing.T) {
204		testStruct := inputFactory()
205		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture1)
206		pruner.pruneProperties(&testStruct)
207
208		expected := inputFactory()
209		expected.S_and_T_only = ""
210		expected.Mapped["one"].T_only = ""
211		expected.Mapped["two"].T_only = ""
212		assertJsonEquals(t, expected, testStruct)
213	})
214
215	t.Run("target F2", func(t *testing.T) {
216		testStruct := inputFactory()
217		pruner := newPropertyPrunerByBuildRelease(&testStruct, buildReleaseFuture2)
218		pruner.pruneProperties(&testStruct)
219
220		expected := inputFactory()
221		expected.S_and_T_only = ""
222		expected.Nested.F1_only = ""
223		expected.Mapped["one"].T_only = ""
224		expected.Mapped["two"].T_only = ""
225		assertJsonEquals(t, expected, testStruct)
226	})
227}
228