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