xref: /aosp_15_r20/build/soong/aconfig/aconfig_declarations_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2018 Google Inc. All rights reserved.
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 aconfig
16
17import (
18	"slices"
19	"strings"
20	"testing"
21
22	"android/soong/android"
23)
24
25func TestAconfigDeclarations(t *testing.T) {
26	bp := `
27		aconfig_declarations {
28			name: "module_name",
29			package: "com.example.package",
30			container: "com.android.foo",
31			exportable: true,
32			srcs: [
33				"foo.aconfig",
34				"bar.aconfig",
35			],
36		}
37	`
38	result := runTest(t, android.FixtureExpectsNoErrors, bp)
39
40	module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
41
42	// Check that the provider has the right contents
43	depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
44	android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
45	android.AssertStringEquals(t, "container", depData.Container, "com.android.foo")
46	android.AssertBoolEquals(t, "exportable", depData.Exportable, true)
47	if !strings.HasSuffix(depData.IntermediateCacheOutputPath.String(), "/intermediate.pb") {
48		t.Errorf("Missing intermediates proto path in provider: %s", depData.IntermediateCacheOutputPath.String())
49	}
50	if !strings.HasSuffix(depData.IntermediateDumpOutputPath.String(), "/intermediate.txt") {
51		t.Errorf("Missing intermediates text path in provider: %s", depData.IntermediateDumpOutputPath.String())
52	}
53}
54
55func TestAconfigDeclarationsWithExportableUnset(t *testing.T) {
56	bp := `
57		aconfig_declarations {
58			name: "module_name",
59			package: "com.example.package",
60			container: "com.android.foo",
61			srcs: [
62				"foo.aconfig",
63				"bar.aconfig",
64			],
65		}
66	`
67	result := runTest(t, android.FixtureExpectsNoErrors, bp)
68
69	module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
70	depData, _ := android.OtherModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
71	android.AssertBoolEquals(t, "exportable", depData.Exportable, false)
72}
73
74func TestAconfigDeclarationsWithContainer(t *testing.T) {
75	bp := `
76		aconfig_declarations {
77			name: "module_name",
78			package: "com.example.package",
79			container: "com.android.foo",
80			srcs: [
81				"foo.aconfig",
82			],
83		}
84	`
85	result := runTest(t, android.FixtureExpectsNoErrors, bp)
86
87	module := result.ModuleForTests("module_name", "")
88	rule := module.Rule("aconfig")
89	android.AssertStringEquals(t, "rule must contain container", rule.Args["container"], "--container com.android.foo")
90}
91
92func TestMandatoryProperties(t *testing.T) {
93	testCases := []struct {
94		name          string
95		expectedError string
96		bp            string
97	}{
98		{
99			name: "Srcs missing from aconfig_declarations",
100			bp: `
101				aconfig_declarations {
102					name: "my_aconfig_declarations_foo",
103					package: "com.example.package",
104					container: "otherapex",
105				}`,
106			expectedError: `missing source files`,
107		},
108		{
109			name: "Package missing from aconfig_declarations",
110			bp: `
111				aconfig_declarations {
112					name: "my_aconfig_declarations_foo",
113					container: "otherapex",
114					srcs: ["foo.aconfig"],
115				}`,
116			expectedError: `missing package property`,
117		},
118		{
119			name: "Container missing from aconfig_declarations",
120			bp: `
121				aconfig_declarations {
122					name: "my_aconfig_declarations_foo",
123					package: "com.example.package",
124					srcs: ["foo.aconfig"],
125				}`,
126			expectedError: `missing container property`,
127		},
128	}
129	for _, test := range testCases {
130		t.Run(test.name, func(t *testing.T) {
131			errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
132			android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
133				ExtendWithErrorHandler(errorHandler).
134				RunTestWithBp(t, test.bp)
135		})
136	}
137}
138
139func TestAssembleFileName(t *testing.T) {
140	testCases := []struct {
141		name          string
142		releaseConfig string
143		path          string
144		expectedValue string
145	}{
146		{
147			name:          "active release config",
148			path:          "file.path",
149			expectedValue: "file.path",
150		},
151		{
152			name:          "release config FOO",
153			releaseConfig: "FOO",
154			path:          "file.path",
155			expectedValue: "file-FOO.path",
156		},
157	}
158	for _, test := range testCases {
159		actualValue := assembleFileName(test.releaseConfig, test.path)
160		if actualValue != test.expectedValue {
161			t.Errorf("Expected %q found %q", test.expectedValue, actualValue)
162		}
163	}
164}
165
166func TestGenerateAndroidBuildActions(t *testing.T) {
167	testCases := []struct {
168		name         string
169		buildFlags   map[string]string
170		bp           string
171		errorHandler android.FixtureErrorHandler
172	}{
173		{
174			name: "generate extra",
175			buildFlags: map[string]string{
176				"RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS": "config2",
177				"RELEASE_ACONFIG_VALUE_SETS":            "aconfig_value_set-config1",
178				"RELEASE_ACONFIG_VALUE_SETS_config2":    "aconfig_value_set-config2",
179			},
180			bp: `
181				aconfig_declarations {
182					name: "module_name",
183					package: "com.example.package",
184					container: "com.android.foo",
185					srcs: [
186						"foo.aconfig",
187						"bar.aconfig",
188					],
189				}
190				aconfig_value_set {
191					name: "aconfig_value_set-config1",
192					values: []
193				}
194				aconfig_value_set {
195					name: "aconfig_value_set-config2",
196					values: []
197				}
198			`,
199		},
200	}
201	for _, test := range testCases {
202		fixture := PrepareForTest(t, addBuildFlagsForTest(test.buildFlags))
203		if test.errorHandler != nil {
204			fixture = fixture.ExtendWithErrorHandler(test.errorHandler)
205		}
206		result := fixture.RunTestWithBp(t, test.bp)
207		module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
208		depData, _ := android.OtherModuleProvider(result, module, android.AconfigReleaseDeclarationsProviderKey)
209		expectedKeys := []string{""}
210		for _, rc := range strings.Split(test.buildFlags["RELEASE_ACONFIG_EXTRA_RELEASE_CONFIGS"], " ") {
211			expectedKeys = append(expectedKeys, rc)
212		}
213		slices.Sort(expectedKeys)
214		actualKeys := []string{}
215		for rc := range depData {
216			actualKeys = append(actualKeys, rc)
217		}
218		slices.Sort(actualKeys)
219		android.AssertStringEquals(t, "provider keys", strings.Join(expectedKeys, " "), strings.Join(actualKeys, " "))
220		for _, rc := range actualKeys {
221			if !strings.HasSuffix(depData[rc].IntermediateCacheOutputPath.String(), assembleFileName(rc, "/intermediate.pb")) {
222				t.Errorf("Incorrect intermediates proto path in provider for release config %s: %s", rc, depData[rc].IntermediateCacheOutputPath.String())
223			}
224			if !strings.HasSuffix(depData[rc].IntermediateDumpOutputPath.String(), assembleFileName(rc, "/intermediate.txt")) {
225				t.Errorf("Incorrect intermediates text path in provider for release config %s: %s", rc, depData[rc].IntermediateDumpOutputPath.String())
226			}
227		}
228	}
229}
230