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