1// Copyright (C) 2019 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 sysprop
16
17import (
18	"os"
19	"strings"
20	"testing"
21
22	"android/soong/android"
23	"android/soong/cc"
24	"android/soong/java"
25	"android/soong/rust"
26
27	"github.com/google/blueprint/proptools"
28)
29
30func TestMain(m *testing.M) {
31	os.Exit(m.Run())
32}
33
34func test(t *testing.T, bp string) *android.TestResult {
35	t.Helper()
36
37	bp += `
38		cc_library {
39			name: "libbase",
40			host_supported: true,
41		}
42
43		cc_library_headers {
44			name: "libbase_headers",
45			vendor_available: true,
46			product_available: true,
47			recovery_available: true,
48		}
49
50		java_library {
51			name: "sysprop-library-stub-platform",
52			sdk_version: "core_current",
53		}
54
55		java_library {
56			name: "sysprop-library-stub-vendor",
57			soc_specific: true,
58			sdk_version: "core_current",
59		}
60
61		java_library {
62			name: "sysprop-library-stub-product",
63			product_specific: true,
64			sdk_version: "core_current",
65		}
66
67		rust_library {
68			name: "librustutils",
69			crate_name: "rustutils",
70			srcs: ["librustutils/lib.rs"],
71			product_available: true,
72			vendor_available: true,
73			min_sdk_version: "29",
74		}
75
76		rust_library {
77			name: "liblog_rust",
78			crate_name: "log",
79			srcs: ["log/src/lib.rs"],
80			product_available: true,
81			vendor_available: true,
82			min_sdk_version: "29",
83		}
84	`
85
86	mockFS := android.MockFS{
87		"a.java":                           nil,
88		"b.java":                           nil,
89		"c.java":                           nil,
90		"d.cpp":                            nil,
91		"api/sysprop-platform-current.txt": nil,
92		"api/sysprop-platform-latest.txt":  nil,
93		"api/sysprop-platform-on-product-current.txt": nil,
94		"api/sysprop-platform-on-product-latest.txt":  nil,
95		"api/sysprop-vendor-current.txt":              nil,
96		"api/sysprop-vendor-latest.txt":               nil,
97		"api/sysprop-vendor-on-product-current.txt":   nil,
98		"api/sysprop-vendor-on-product-latest.txt":    nil,
99		"api/sysprop-odm-current.txt":                 nil,
100		"api/sysprop-odm-latest.txt":                  nil,
101		"framework/aidl/a.aidl":                       nil,
102
103		// For framework-res, which is an implicit dependency for framework
104		"AndroidManifest.xml":                        nil,
105		"build/make/target/product/security/testkey": nil,
106
107		"build/soong/scripts/jar-wrapper.sh": nil,
108
109		"jdk8/jre/lib/jce.jar": nil,
110		"jdk8/jre/lib/rt.jar":  nil,
111		"jdk8/lib/tools.jar":   nil,
112
113		"bar-doc/a.java":                 nil,
114		"bar-doc/b.java":                 nil,
115		"bar-doc/IFoo.aidl":              nil,
116		"bar-doc/known_oj_tags.txt":      nil,
117		"external/doclava/templates-sdk": nil,
118
119		"cert/new_cert.x509.pem": nil,
120		"cert/new_cert.pk8":      nil,
121
122		"android/sysprop/PlatformProperties.sysprop": nil,
123		"com/android/VendorProperties.sysprop":       nil,
124		"com/android2/OdmProperties.sysprop":         nil,
125
126		"librustutils/lib.rs": nil,
127		"log/src/lib.rs":      nil,
128	}
129
130	result := android.GroupFixturePreparers(
131		cc.PrepareForTestWithCcDefaultModules,
132		java.PrepareForTestWithJavaDefaultModules,
133		rust.PrepareForTestWithRustDefaultModules,
134		PrepareForTestWithSyspropBuildComponents,
135		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
136			variables.DeviceSystemSdkVersions = []string{"28"}
137			variables.DeviceCurrentApiLevelForVendorModules = proptools.StringPtr("28")
138		}),
139		java.FixtureWithPrebuiltApis(map[string][]string{
140			"28": {},
141			"29": {},
142			"30": {},
143		}),
144		mockFS.AddToFixture(),
145		android.FixtureWithRootAndroidBp(bp),
146	).RunTest(t)
147
148	return result
149}
150
151func TestSyspropLibrary(t *testing.T) {
152	result := test(t, `
153		sysprop_library {
154			name: "sysprop-platform",
155			apex_available: ["//apex_available:platform"],
156			srcs: ["android/sysprop/PlatformProperties.sysprop"],
157			api_packages: ["android.sysprop"],
158			property_owner: "Platform",
159			vendor_available: true,
160			host_supported: true,
161		}
162
163		sysprop_library {
164			name: "sysprop-platform-on-product",
165			srcs: ["android/sysprop/PlatformProperties.sysprop"],
166			api_packages: ["android.sysprop"],
167			property_owner: "Platform",
168			product_specific: true,
169		}
170
171		sysprop_library {
172			name: "sysprop-vendor",
173			srcs: ["com/android/VendorProperties.sysprop"],
174			api_packages: ["com.android"],
175			property_owner: "Vendor",
176			vendor: true,
177		}
178
179		sysprop_library {
180			name: "sysprop-vendor-on-product",
181			srcs: ["com/android/VendorProperties.sysprop"],
182			api_packages: ["com.android"],
183			property_owner: "Vendor",
184			product_specific: true,
185		}
186
187		sysprop_library {
188			name: "sysprop-odm",
189			srcs: ["com/android2/OdmProperties.sysprop"],
190			api_packages: ["com.android2"],
191			property_owner: "Odm",
192			device_specific: true,
193		}
194
195		java_library {
196			name: "java-platform",
197			srcs: ["c.java"],
198			sdk_version: "system_current",
199			libs: ["sysprop-platform"],
200		}
201
202		java_library {
203			name: "java-platform-private",
204			srcs: ["c.java"],
205			platform_apis: true,
206			libs: ["sysprop-platform"],
207		}
208
209		java_library {
210			name: "java-product",
211			srcs: ["c.java"],
212			sdk_version: "system_current",
213			product_specific: true,
214			libs: ["sysprop-platform", "sysprop-vendor-on-product"],
215		}
216
217		java_library {
218			name: "java-vendor",
219			srcs: ["c.java"],
220			sdk_version: "system_current",
221			soc_specific: true,
222			libs: ["sysprop-platform", "sysprop-vendor"],
223		}
224
225		cc_library {
226			name: "cc-client-platform",
227			srcs: ["d.cpp"],
228			static_libs: ["libsysprop-platform"],
229		}
230
231		cc_library_static {
232			name: "cc-client-platform-static",
233			srcs: ["d.cpp"],
234			whole_static_libs: ["libsysprop-platform"],
235		}
236
237		cc_library {
238			name: "cc-client-product",
239			srcs: ["d.cpp"],
240			product_specific: true,
241			static_libs: ["libsysprop-platform-on-product", "libsysprop-vendor-on-product"],
242		}
243
244		cc_library {
245			name: "cc-client-vendor",
246			srcs: ["d.cpp"],
247			soc_specific: true,
248			static_libs: ["libsysprop-platform", "libsysprop-vendor"],
249		}
250
251		cc_binary_host {
252			name: "hostbin",
253			static_libs: ["libsysprop-platform"],
254		}
255	`)
256
257	// Check for generated cc_library
258	for _, variant := range []string{
259		"android_vendor_arm_armv7-a-neon_shared",
260		"android_vendor_arm_armv7-a-neon_static",
261		"android_vendor_arm64_armv8-a_shared",
262		"android_vendor_arm64_armv8-a_static",
263	} {
264		result.ModuleForTests("libsysprop-platform", variant)
265		result.ModuleForTests("libsysprop-vendor", variant)
266		result.ModuleForTests("libsysprop-odm", variant)
267	}
268
269	// product variant of vendor-owned sysprop_library
270	for _, variant := range []string{
271		"android_product_arm_armv7-a-neon_shared",
272		"android_product_arm_armv7-a-neon_static",
273		"android_product_arm64_armv8-a_shared",
274		"android_product_arm64_armv8-a_static",
275	} {
276		result.ModuleForTests("libsysprop-vendor-on-product", variant)
277	}
278
279	for _, variant := range []string{
280		"android_arm_armv7-a-neon_shared",
281		"android_arm_armv7-a-neon_static",
282		"android_arm64_armv8-a_shared",
283		"android_arm64_armv8-a_static",
284	} {
285		library := result.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
286		expectedApexAvailableOnLibrary := []string{"//apex_available:platform"}
287		android.AssertDeepEquals(t, "apex available property on libsysprop-platform", expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
288	}
289
290	result.ModuleForTests("sysprop-platform", "android_common")
291	result.ModuleForTests("sysprop-platform_public", "android_common")
292	result.ModuleForTests("sysprop-vendor", "android_common")
293	result.ModuleForTests("sysprop-vendor-on-product", "android_common")
294
295	// Check for exported includes
296	coreVariant := "android_arm64_armv8-a_static"
297	vendorVariant := "android_vendor_arm64_armv8-a_static"
298	productVariant := "android_product_arm64_armv8-a_static"
299
300	platformInternalPath := "libsysprop-platform/android_arm64_armv8-a_static/gen/sysprop/include"
301	platformPublicVendorPath := "libsysprop-platform/android_vendor_arm64_armv8-a_static/gen/sysprop/public/include"
302
303	platformOnProductPath := "libsysprop-platform-on-product/android_product_arm64_armv8-a_static/gen/sysprop/public/include"
304
305	vendorInternalPath := "libsysprop-vendor/android_vendor_arm64_armv8-a_static/gen/sysprop/include"
306	vendorOnProductPath := "libsysprop-vendor-on-product/android_product_arm64_armv8-a_static/gen/sysprop/public/include"
307
308	platformClient := result.ModuleForTests("cc-client-platform", coreVariant)
309	platformFlags := platformClient.Rule("cc").Args["cFlags"]
310
311	// platform should use platform's internal header
312	android.AssertStringDoesContain(t, "flags for platform", platformFlags, platformInternalPath)
313
314	platformStaticClient := result.ModuleForTests("cc-client-platform-static", coreVariant)
315	platformStaticFlags := platformStaticClient.Rule("cc").Args["cFlags"]
316
317	// platform-static should use platform's internal header
318	android.AssertStringDoesContain(t, "flags for platform-static", platformStaticFlags, platformInternalPath)
319
320	productClient := result.ModuleForTests("cc-client-product", productVariant)
321	productFlags := productClient.Rule("cc").Args["cFlags"]
322
323	// Product should use platform's and vendor's public headers
324	if !strings.Contains(productFlags, platformOnProductPath) ||
325		!strings.Contains(productFlags, vendorOnProductPath) {
326		t.Errorf("flags for product must contain %#v and %#v, but was %#v.",
327			platformOnProductPath, vendorOnProductPath, productFlags)
328	}
329
330	vendorClient := result.ModuleForTests("cc-client-vendor", vendorVariant)
331	vendorFlags := vendorClient.Rule("cc").Args["cFlags"]
332
333	// Vendor should use platform's public header and vendor's internal header
334	if !strings.Contains(vendorFlags, platformPublicVendorPath) ||
335		!strings.Contains(vendorFlags, vendorInternalPath) {
336		t.Errorf("flags for vendor must contain %#v and %#v, but was %#v.",
337			platformPublicVendorPath, vendorInternalPath, vendorFlags)
338	}
339
340	// Java modules linking against system API should use public stub
341	javaSystemApiClient := result.ModuleForTests("java-platform", "android_common").Rule("javac")
342	syspropPlatformPublic := result.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
343	if g, w := javaSystemApiClient.Implicits.Strings(), syspropPlatformPublic.Output.String(); !android.InList(w, g) {
344		t.Errorf("system api client should use public stub %q, got %q", w, g)
345	}
346}
347
348func TestApexAvailabilityIsForwarded(t *testing.T) {
349	result := test(t, `
350		sysprop_library {
351			name: "sysprop-platform",
352			apex_available: ["//apex_available:platform"],
353			srcs: ["android/sysprop/PlatformProperties.sysprop"],
354			api_packages: ["android.sysprop"],
355			property_owner: "Platform",
356		}
357	`)
358
359	expected := []string{"//apex_available:platform"}
360
361	ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
362	propFromCc := ccModule.ApexProperties.Apex_available
363	android.AssertDeepEquals(t, "apex_available forwarding to cc module", expected, propFromCc)
364
365	javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
366	propFromJava := javaModule.ApexProperties.Apex_available
367	android.AssertDeepEquals(t, "apex_available forwarding to java module", expected, propFromJava)
368
369	rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
370	propFromRust := rustModule.ApexProperties.Apex_available
371	android.AssertDeepEquals(t, "apex_available forwarding to rust module", expected, propFromRust)
372}
373
374func TestMinSdkVersionIsForwarded(t *testing.T) {
375	result := test(t, `
376		sysprop_library {
377			name: "sysprop-platform",
378			srcs: ["android/sysprop/PlatformProperties.sysprop"],
379			api_packages: ["android.sysprop"],
380			property_owner: "Platform",
381			cpp: {
382				min_sdk_version: "29",
383			},
384			java: {
385				min_sdk_version: "30",
386			},
387			rust: {
388				min_sdk_version: "29",
389			}
390		}
391	`)
392
393	ccModule := result.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
394	propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
395	android.AssertStringEquals(t, "min_sdk_version forwarding to cc module", "29", propFromCc)
396
397	javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
398	propFromJava := javaModule.MinSdkVersionString()
399	android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
400
401	rustModule := result.ModuleForTests("libsysprop_platform_rust", "android_arm64_armv8-a_rlib_rlib-std").Module().(*rust.Module)
402	propFromRust := proptools.String(rustModule.Properties.Min_sdk_version)
403	android.AssertStringEquals(t, "min_sdk_version forwarding to rust module", "29", propFromRust)
404}
405