From df88173dd4605a95c6724110d800e081315b4818 Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Tue, 5 Sep 2023 15:19:21 +0100 Subject: [PATCH 01/37] Support adding a library as both a JNI library and a regular library. Bug: 299087066 Test: m nothing Change-Id: I6cafe23395b7306727a071ccefe3b189c56e928b Merged-In: I6cafe23395b7306727a071ccefe3b189c56e928b --- apex/apex.go | 3 +++ apex/apex_test.go | 25 +++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index fca09440f..1f2da5f1a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2217,6 +2217,9 @@ func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) { // If a module is directly included and also transitively depended on // consider it as directly included. e.transitiveDep = e.transitiveDep && f.transitiveDep + // If a module is added as both a JNI library and a regular shared library, consider it as a + // JNI library. + e.isJniLib = e.isJniLib || f.isJniLib encountered[dest] = e } } diff --git a/apex/apex_test.go b/apex/apex_test.go index 2eb359329..38d9106f6 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -7843,7 +7843,8 @@ func TestApexWithJniLibs(t *testing.T) { apex { name: "myapex", key: "myapex.key", - jni_libs: ["mylib", "libfoo.rust"], + binaries: ["mybin"], + jni_libs: ["mylib", "mylib3", "libfoo.rust"], updatable: false, } @@ -7870,6 +7871,24 @@ func TestApexWithJniLibs(t *testing.T) { apex_available: [ "myapex" ], } + // Used as both a JNI library and a regular shared library. + cc_library { + name: "mylib3", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + } + + cc_binary { + name: "mybin", + srcs: ["mybin.cpp"], + shared_libs: ["mylib3"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + } + rust_ffi_shared { name: "libfoo.rust", crate_name: "foo", @@ -7893,10 +7912,12 @@ func TestApexWithJniLibs(t *testing.T) { rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule") // Notice mylib2.so (transitive dep) is not added as a jni_lib - ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so") + ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so mylib3.so") ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{ + "bin/mybin", "lib64/mylib.so", "lib64/mylib2.so", + "lib64/mylib3.so", "lib64/libfoo.rust.so", "lib64/libc++.so", // auto-added to libfoo.rust by Soong "lib64/liblog.so", // auto-added to libfoo.rust by Soong From 57011173b387cd925f3cd7fbdd03bb625365a9e4 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Fri, 6 Oct 2023 19:54:58 +0000 Subject: [PATCH 02/37] Add proto for Test ownership metadata. This Cl adds a new rule to Soong to generate test spec metadata. Also, this CL adds a provider in various test module to provide test spec related data to the Soong rule. Will add providers and test code to other Module in the future changes. Provider added for the following test modules in this change: android_robolectric_test, android_test, bootclasspath_fragment_test, java_test, java_test_host, python_test, python_test_host, sh_test,and sh_test_host. Bug: 296873595 Change-Id: I5f89f72d5874bb7838ae357efdb8c6ca208e18a7 Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2774872 Change-Id: I23c09ed262915a5f68d6e7a4f21683e0389cd5f6 Merged-In: I5f89f72d5874bb7838ae357efdb8c6ca208e18a7 --- java/Android.bp | 1 + java/app.go | 2 + java/bootclasspath_fragment.go | 2 + java/java.go | 4 +- java/robolectric.go | 2 + python/Android.bp | 1 + python/test.go | 2 + sh/Android.bp | 1 + sh/sh_binary.go | 2 + testing/Android.bp | 19 ++ testing/init.go | 27 +++ testing/test_spec.go | 127 ++++++++++++ testing/test_spec_proto/Android.bp | 29 +++ testing/test_spec_proto/OWNERS | 4 + testing/test_spec_proto/go.mod | 2 + testing/test_spec_proto/regen.sh | 3 + testing/test_spec_proto/test_spec.pb.go | 244 ++++++++++++++++++++++++ testing/test_spec_proto/test_spec.proto | 33 ++++ 18 files changed, 504 insertions(+), 1 deletion(-) create mode 100644 testing/Android.bp create mode 100644 testing/init.go create mode 100644 testing/test_spec.go create mode 100644 testing/test_spec_proto/Android.bp create mode 100644 testing/test_spec_proto/OWNERS create mode 100644 testing/test_spec_proto/go.mod create mode 100644 testing/test_spec_proto/regen.sh create mode 100644 testing/test_spec_proto/test_spec.pb.go create mode 100644 testing/test_spec_proto/test_spec.proto diff --git a/java/Android.bp b/java/Android.bp index 4af2a14eb..043ab82fe 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -15,6 +15,7 @@ bootstrap_go_package { "soong-dexpreopt", "soong-genrule", "soong-java-config", + "soong-testing", "soong-provenance", "soong-python", "soong-remoteexec", diff --git a/java/app.go b/java/app.go index 254906d2e..e026feab5 100755 --- a/java/app.go +++ b/java/app.go @@ -21,6 +21,7 @@ import ( "path/filepath" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -1124,6 +1125,7 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.testConfig = a.FixTestConfig(ctx, testConfig) a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 108fdd483..f815954e4 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -23,6 +23,7 @@ import ( "android/soong/android" "android/soong/dexpreopt" + "android/soong/testing" "github.com/google/blueprint/proptools" @@ -564,6 +565,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo if ctx.Module() != ctx.FinalModule() { b.HideFromMake() } + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } // shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot diff --git a/java/java.go b/java/java.go index 9161b2253..c8817e1cb 100644 --- a/java/java.go +++ b/java/java.go @@ -26,7 +26,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" "android/soong/remoteexec" - + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -1199,10 +1199,12 @@ func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.Test.generateAndroidBuildActionsWithConfig(ctx, configs) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.generateAndroidBuildActionsWithConfig(ctx, nil) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) { diff --git a/java/robolectric.go b/java/robolectric.go index 008b8b1c9..f394006c4 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/java/config" + "android/soong/testing" "android/soong/tradefed" "github.com/google/blueprint/proptools" @@ -235,6 +236,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) } r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath, diff --git a/python/Android.bp b/python/Android.bp index 75786733a..87810c9ed 100644 --- a/python/Android.bp +++ b/python/Android.bp @@ -10,6 +10,7 @@ bootstrap_go_package { "soong-android", "soong-tradefed", "soong-cc", + "soong-testing", ], srcs: [ "binary.go", diff --git a/python/test.go b/python/test.go index 31da17e61..18da72a1d 100644 --- a/python/test.go +++ b/python/test.go @@ -17,6 +17,7 @@ package python import ( "fmt" + "android/soong/testing" "github.com/google/blueprint/proptools" "android/soong/android" @@ -159,6 +160,7 @@ func (p *PythonTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath}) } } + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/sh/Android.bp b/sh/Android.bp index f9198dc4f..2341a128b 100644 --- a/sh/Android.bp +++ b/sh/Android.bp @@ -10,6 +10,7 @@ bootstrap_go_package { "soong", "soong-android", "soong-cc", + "soong-testing", "soong-tradefed", ], srcs: [ diff --git a/sh/sh_binary.go b/sh/sh_binary.go index c921ca68a..d224fdfa4 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -20,6 +20,7 @@ import ( "sort" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -426,6 +427,7 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep)) } }) + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } func (s *ShTest) InstallInData() bool { diff --git a/testing/Android.bp b/testing/Android.bp new file mode 100644 index 000000000..26a7d9316 --- /dev/null +++ b/testing/Android.bp @@ -0,0 +1,19 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-testing", + pkgPath: "android/soong/testing", + deps: [ + "blueprint", + "soong-android", + "soong-testing-test_spec_proto", + + ], + srcs: [ + "test_spec.go", + "init.go", + ], + pluginFor: ["soong_build"], +} diff --git a/testing/init.go b/testing/init.go new file mode 100644 index 000000000..8820a6063 --- /dev/null +++ b/testing/init.go @@ -0,0 +1,27 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testing + +import ( + "android/soong/android" +) + +func init() { + RegisterBuildComponents(android.InitRegistrationContext) +} + +func RegisterBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("test_spec", TestSpecFactory) +} diff --git a/testing/test_spec.go b/testing/test_spec.go new file mode 100644 index 000000000..1ad276875 --- /dev/null +++ b/testing/test_spec.go @@ -0,0 +1,127 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testing + +import ( + "path/filepath" + "strconv" + + "android/soong/android" + "android/soong/testing/test_spec_proto" + "github.com/google/blueprint" + "google.golang.org/protobuf/proto" +) + +// ErrTestModuleDataNotFound is the error message for missing test module provider data. +const ErrTestModuleDataNotFound = "The module '%s' does not provide test specification data. Hint: This issue could arise if either the module is not a valid testing module or if it lacks the required 'TestModuleProviderKey' provider.\n" + +func TestSpecFactory() android.Module { + module := &TestSpecModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + + return module +} + +type TestSpecModule struct { + android.ModuleBase + android.DefaultableModuleBase + android.BazelModuleBase + + // Properties for "test_spec" + properties struct { + // Specifies the name of the test config. + Name string + // Specifies the team ID. + TeamId string + // Specifies the list of tests covered under this module. + Tests []string + } +} + +type testsDepTagType struct { + blueprint.BaseDependencyTag +} + +var testsDepTag = testsDepTagType{} + +func (module *TestSpecModule) DepsMutator(ctx android.BottomUpMutatorContext) { + // Validate Properties + if len(module.properties.TeamId) == 0 { + ctx.PropertyErrorf("TeamId", "Team Id not found in the test_spec module. Hint: Maybe the TeamId property hasn't been properly specified.") + } + if !isInt(module.properties.TeamId) { + ctx.PropertyErrorf("TeamId", "Invalid value for Team ID. The Team ID must be an integer.") + } + if len(module.properties.Tests) == 0 { + ctx.PropertyErrorf("Tests", "Expected to attribute some test but none found. Hint: Maybe the test property hasn't been properly specified.") + } + ctx.AddDependency(ctx.Module(), testsDepTag, module.properties.Tests...) +} +func isInt(s string) bool { + _, err := strconv.Atoi(s) + return err == nil +} + +// Provider published by TestSpec +type testSpecProviderData struct { + IntermediatePath android.WritablePath +} + +var testSpecProviderKey = blueprint.NewProvider(testSpecProviderData{}) + +type TestModuleProviderData struct { +} + +var TestModuleProviderKey = blueprint.NewProvider(TestModuleProviderData{}) + +func (module *TestSpecModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + for _, m := range ctx.GetDirectDepsWithTag(testsDepTag) { + if !ctx.OtherModuleHasProvider(m, TestModuleProviderKey) { + ctx.ModuleErrorf(ErrTestModuleDataNotFound, m.Name()) + } + } + bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile()) + metadataList := make( + []*test_spec_proto.TestSpec_OwnershipMetadata, 0, + len(module.properties.Tests), + ) + for _, test := range module.properties.Tests { + targetName := test + metadata := test_spec_proto.TestSpec_OwnershipMetadata{ + TrendyTeamId: &module.properties.TeamId, + TargetName: &targetName, + Path: &bpFilePath, + } + metadataList = append(metadataList, &metadata) + } + intermediatePath := android.PathForModuleOut( + ctx, "intermediateTestSpecMetadata.pb", + ) + testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList} + protoData, err := proto.Marshal(&testSpecMetadata) + if err != nil { + ctx.ModuleErrorf("Error: %s", err.Error()) + } + android.WriteFileRule(ctx, intermediatePath, string(protoData)) + + ctx.SetProvider( + testSpecProviderKey, testSpecProviderData{ + IntermediatePath: intermediatePath, + }, + ) +} diff --git a/testing/test_spec_proto/Android.bp b/testing/test_spec_proto/Android.bp new file mode 100644 index 000000000..1cac492f1 --- /dev/null +++ b/testing/test_spec_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-testing-test_spec_proto", + pkgPath: "android/soong/testing/test_spec_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "test_spec.pb.go", + ], +} diff --git a/testing/test_spec_proto/OWNERS b/testing/test_spec_proto/OWNERS new file mode 100644 index 000000000..03bcdf1c4 --- /dev/null +++ b/testing/test_spec_proto/OWNERS @@ -0,0 +1,4 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com diff --git a/testing/test_spec_proto/go.mod b/testing/test_spec_proto/go.mod new file mode 100644 index 000000000..482cdbbd1 --- /dev/null +++ b/testing/test_spec_proto/go.mod @@ -0,0 +1,2 @@ +module test_spec_proto +go 1.18 \ No newline at end of file diff --git a/testing/test_spec_proto/regen.sh b/testing/test_spec_proto/regen.sh new file mode 100644 index 000000000..2cf820375 --- /dev/null +++ b/testing/test_spec_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. test_spec.proto diff --git a/testing/test_spec_proto/test_spec.pb.go b/testing/test_spec_proto/test_spec.pb.go new file mode 100644 index 000000000..5cce60029 --- /dev/null +++ b/testing/test_spec_proto/test_spec.pb.go @@ -0,0 +1,244 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: test_spec.proto + +package test_spec_proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type TestSpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of all test targets and their metadata. + OwnershipMetadataList []*TestSpec_OwnershipMetadata `protobuf:"bytes,1,rep,name=ownership_metadata_list,json=ownershipMetadataList" json:"ownership_metadata_list,omitempty"` +} + +func (x *TestSpec) Reset() { + *x = TestSpec{} + if protoimpl.UnsafeEnabled { + mi := &file_test_spec_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestSpec) ProtoMessage() {} + +func (x *TestSpec) ProtoReflect() protoreflect.Message { + mi := &file_test_spec_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestSpec.ProtoReflect.Descriptor instead. +func (*TestSpec) Descriptor() ([]byte, []int) { + return file_test_spec_proto_rawDescGZIP(), []int{0} +} + +func (x *TestSpec) GetOwnershipMetadataList() []*TestSpec_OwnershipMetadata { + if x != nil { + return x.OwnershipMetadataList + } + return nil +} + +type TestSpec_OwnershipMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"` + Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"` +} + +func (x *TestSpec_OwnershipMetadata) Reset() { + *x = TestSpec_OwnershipMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_test_spec_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestSpec_OwnershipMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestSpec_OwnershipMetadata) ProtoMessage() {} + +func (x *TestSpec_OwnershipMetadata) ProtoReflect() protoreflect.Message { + mi := &file_test_spec_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestSpec_OwnershipMetadata.ProtoReflect.Descriptor instead. +func (*TestSpec_OwnershipMetadata) Descriptor() ([]byte, []int) { + return file_test_spec_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *TestSpec_OwnershipMetadata) GetTargetName() string { + if x != nil && x.TargetName != nil { + return *x.TargetName + } + return "" +} + +func (x *TestSpec_OwnershipMetadata) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *TestSpec_OwnershipMetadata) GetTrendyTeamId() string { + if x != nil && x.TrendyTeamId != nil { + return *x.TrendyTeamId + } + return "" +} + +var File_test_spec_proto protoreflect.FileDescriptor + +var file_test_spec_proto_rawDesc = []byte{ + 0x0a, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x12, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xdf, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12, + 0x63, 0x0a, 0x17, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4f, 0x77, 0x6e, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x15, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x6e, 0x0a, 0x11, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, + 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, + 0x61, 0x6d, 0x49, 0x64, 0x42, 0x27, 0x5a, 0x25, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, + 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x74, 0x65, + 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_test_spec_proto_rawDescOnce sync.Once + file_test_spec_proto_rawDescData = file_test_spec_proto_rawDesc +) + +func file_test_spec_proto_rawDescGZIP() []byte { + file_test_spec_proto_rawDescOnce.Do(func() { + file_test_spec_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_spec_proto_rawDescData) + }) + return file_test_spec_proto_rawDescData +} + +var file_test_spec_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_test_spec_proto_goTypes = []interface{}{ + (*TestSpec)(nil), // 0: test_spec_proto.TestSpec + (*TestSpec_OwnershipMetadata)(nil), // 1: test_spec_proto.TestSpec.OwnershipMetadata +} +var file_test_spec_proto_depIdxs = []int32{ + 1, // 0: test_spec_proto.TestSpec.ownership_metadata_list:type_name -> test_spec_proto.TestSpec.OwnershipMetadata + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_test_spec_proto_init() } +func file_test_spec_proto_init() { + if File_test_spec_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_test_spec_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_test_spec_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestSpec_OwnershipMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_test_spec_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_test_spec_proto_goTypes, + DependencyIndexes: file_test_spec_proto_depIdxs, + MessageInfos: file_test_spec_proto_msgTypes, + }.Build() + File_test_spec_proto = out.File + file_test_spec_proto_rawDesc = nil + file_test_spec_proto_goTypes = nil + file_test_spec_proto_depIdxs = nil +} diff --git a/testing/test_spec_proto/test_spec.proto b/testing/test_spec_proto/test_spec.proto new file mode 100644 index 000000000..86bc78954 --- /dev/null +++ b/testing/test_spec_proto/test_spec.proto @@ -0,0 +1,33 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; +package test_spec_proto; +option go_package = "android/soong/testing/test_spec_proto"; + +message TestSpec { + + message OwnershipMetadata { + // REQUIRED: Name of the build target + optional string target_name = 1; + + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + optional string path = 2; + + // REQUIRED: Team ID of the team that owns this target. + optional string trendy_team_id = 3; + } + + // List of all test targets and their metadata. + repeated OwnershipMetadata ownership_metadata_list = 1; +} From 5dfa963701eb73de5f55302aa5b5b46e3f3c10ab Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Fri, 17 Nov 2023 15:27:06 +0000 Subject: [PATCH 03/37] Add test spec provider to test modules. Provider added for the following test modules in this change: art_cc_test, cc_benchmark, cc_fuzz, cc_test, cc_test_host, rust_test,and rust_test_host. Bug: 296873595 Test: Manual test Change-Id: I815680529bcbecacb3a2bdb8f3746053afdee48c Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of: aosp/2836758 Change-Id: Ib9887d0546690355d40facdd3721d7905f5a55df Merged-In: I815680529bcbecacb3a2bdb8f3746053afdee48c --- cc/Android.bp | 1 + cc/cc.go | 11 ++++++++--- cc/fuzz.go | 1 + cc/test.go | 3 +++ rust/Android.bp | 1 + rust/rust.go | 9 +++++++-- rust/test.go | 2 ++ 7 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cc/Android.bp b/cc/Android.bp index f49dc1a9e..b12bdceff 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -18,6 +18,7 @@ bootstrap_go_package { "soong-genrule", "soong-multitree", "soong-snapshot", + "soong-testing", "soong-tradefed", ], srcs: [ diff --git a/cc/cc.go b/cc/cc.go index 307441d32..7c0b0c5d8 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -24,6 +24,7 @@ import ( "strconv" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -835,9 +836,10 @@ type Module struct { Properties BaseProperties // initialize before calling Init - hod android.HostOrDeviceSupported - multilib android.Multilib - bazelable bool + hod android.HostOrDeviceSupported + multilib android.Multilib + bazelable bool + testModule bool // Allowable SdkMemberTypes of this module type. sdkMemberTypes []android.SdkMemberType @@ -2104,6 +2106,9 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { } } } + if c.testModule { + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) + } c.maybeInstall(ctx, apexInfo) } diff --git a/cc/fuzz.go b/cc/fuzz.go index 7aa8b91c7..452cf356a 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -95,6 +95,7 @@ func fuzzMutatorDeps(mctx android.TopDownMutatorContext) { // your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree. func LibFuzzFactory() android.Module { module := NewFuzzer(android.HostAndDeviceSupported) + module.testModule = true return module.Init() } diff --git a/cc/test.go b/cc/test.go index 27de06b07..e2391335e 100644 --- a/cc/test.go +++ b/cc/test.go @@ -137,6 +137,7 @@ func init() { func TestFactory() android.Module { module := NewTest(android.HostAndDeviceSupported, true) module.bazelHandler = &ccTestBazelHandler{module: module} + module.testModule = true return module.Init() } @@ -154,12 +155,14 @@ func TestLibraryFactory() android.Module { // binary. func BenchmarkFactory() android.Module { module := NewBenchmark(android.HostAndDeviceSupported) + module.testModule = true return module.Init() } // cc_test_host compiles a test host binary. func TestHostFactory() android.Module { module := NewTest(android.HostSupported, true) + module.testModule = true return module.Init() } diff --git a/rust/Android.bp b/rust/Android.bp index b01a94ad0..c5b200019 100644 --- a/rust/Android.bp +++ b/rust/Android.bp @@ -12,6 +12,7 @@ bootstrap_go_package { "soong-cc", "soong-rust-config", "soong-snapshot", + "soong-testing", ], srcs: [ "afdo.go", diff --git a/rust/rust.go b/rust/rust.go index 7b520cdb0..77bb8b609 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -19,6 +19,7 @@ import ( "fmt" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -139,8 +140,9 @@ type Module struct { Properties BaseProperties - hod android.HostOrDeviceSupported - multilib android.Multilib + hod android.HostOrDeviceSupported + multilib android.Multilib + testModule bool makeLinkType string @@ -1007,6 +1009,9 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { ctx.Phony("rust", ctx.RustModule().OutputFile().Path()) } + if mod.testModule { + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) + } } func (mod *Module) deps(ctx DepsContext) Deps { diff --git a/rust/test.go b/rust/test.go index 4b5296e54..7ffc36767 100644 --- a/rust/test.go +++ b/rust/test.go @@ -222,11 +222,13 @@ func RustTestFactory() android.Module { // rustTestHostMultilib load hook to set MultilibFirst for the // host target. android.AddLoadHook(module, rustTestHostMultilib) + module.testModule = true return module.Init() } func RustTestHostFactory() android.Module { module, _ := NewRustTest(android.HostSupported) + module.testModule = true return module.Init() } From 02188d4da8eb7bd8a6831d7385d30e98115410f4 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Thu, 9 Nov 2023 20:07:52 +0000 Subject: [PATCH 04/37] Add Singleton class to collect and validate test spec metadata. Bug: 296873595 Test: Manual testing (Will add unit test case in the next change.) Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2824671 Change-Id: Ic4177c5f76602088d52a31ca8d9fbaa703855837 Merged-In: Ic4177c5f76602088d52a31ca8d9fbaa703855837 --- testing/Android.bp | 1 + testing/all_test_specs.go | 45 +++++++++++++++++++++++++++++++++++++++ testing/init.go | 6 ++++++ 3 files changed, 52 insertions(+) create mode 100644 testing/all_test_specs.go diff --git a/testing/Android.bp b/testing/Android.bp index 26a7d9316..85e6a8ba8 100644 --- a/testing/Android.bp +++ b/testing/Android.bp @@ -12,6 +12,7 @@ bootstrap_go_package { ], srcs: [ + "all_test_specs.go", "test_spec.go", "init.go", ], diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go new file mode 100644 index 000000000..2ecf15fa6 --- /dev/null +++ b/testing/all_test_specs.go @@ -0,0 +1,45 @@ +package testing + +import ( + "android/soong/android" +) + +const ownershipDirectory = "ownership" +const fileContainingFilePaths = "all_test_spec_paths.rsp" +const allTestSpecsFile = "all_test_specs.pb" + +func AllTestSpecsFactory() android.Singleton { + return &allTestSpecsSingleton{} +} + +type allTestSpecsSingleton struct { + // Path where the collected metadata is stored after successful validation. + outputPath android.OutputPath +} + +func (this *allTestSpecsSingleton) GenerateBuildActions(ctx android.SingletonContext) { + var intermediateMetadataPaths android.Paths + + ctx.VisitAllModules(func(module android.Module) { + if !ctx.ModuleHasProvider(module, testSpecProviderKey) { + return + } + intermediateMetadataPaths = append(intermediateMetadataPaths, ctx.ModuleProvider(module, testSpecProviderKey).(testSpecProviderData).IntermediatePath) + }) + + rspFile := android.PathForOutput(ctx, fileContainingFilePaths) + this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allTestSpecsFile) + + rule := android.NewRuleBuilder(pctx, ctx) + cmd := rule.Command(). + BuiltTool("metadata"). + FlagWithArg("-rule ", "test_spec"). + FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths) + cmd.FlagWithOutput("-outputFile ", this.outputPath) + rule.Build("all_test_specs_rule", "Generate all test specifications") + ctx.Phony("all_test_specs", this.outputPath) +} + +func (this *allTestSpecsSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.DistForGoal("test_specs", this.outputPath) +} diff --git a/testing/init.go b/testing/init.go index 8820a6063..1ab689215 100644 --- a/testing/init.go +++ b/testing/init.go @@ -18,10 +18,16 @@ import ( "android/soong/android" ) +var ( + pctx = android.NewPackageContext("android/soong/testing") +) + func init() { RegisterBuildComponents(android.InitRegistrationContext) + pctx.HostBinToolVariable("metadata", "metadata") } func RegisterBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("test_spec", TestSpecFactory) + ctx.RegisterSingletonType("all_test_specs", AllTestSpecsFactory) } From 6dded7b12a89c0e7a6d5d748e2122bbef699e82e Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Tue, 21 Nov 2023 15:38:37 +0000 Subject: [PATCH 05/37] Set testModule to true in cc.NewTest(). This Cl sets testModule field to True in cc.NewTest(). This will cover "cc_test", "cc_test_host" and "art_cc_test". Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2841416 Change-Id: I4a8db86835b195db34fd9f86560e7bf9321fbd7d Merged-In: I4a8db86835b195db34fd9f86560e7bf9321fbd7d --- cc/test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cc/test.go b/cc/test.go index e2391335e..db78d6c33 100644 --- a/cc/test.go +++ b/cc/test.go @@ -137,7 +137,6 @@ func init() { func TestFactory() android.Module { module := NewTest(android.HostAndDeviceSupported, true) module.bazelHandler = &ccTestBazelHandler{module: module} - module.testModule = true return module.Init() } @@ -162,7 +161,6 @@ func BenchmarkFactory() android.Module { // cc_test_host compiles a test host binary. func TestHostFactory() android.Module { module := NewTest(android.HostSupported, true) - module.testModule = true return module.Init() } @@ -485,6 +483,7 @@ func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module { module, binary := newBinary(hod, bazelable) module.bazelable = bazelable module.multilib = android.MultilibBoth + module.testModule = true binary.baseInstaller = NewTestInstaller() test := &testBinary{ From d860dd1b31d0056ca38d28560f6a64daae71cb38 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Fri, 17 Nov 2023 12:37:41 +0000 Subject: [PATCH 06/37] Add test for soong/testing/test_spec. This CL adds test for test_spec.go and all_test_specs.go (singleton). Bug: 296873595 Test: m nothing --no-skip-soong-tests -j96 Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2836072 Change-Id: I5010c68512e75d1b9a337c02da86faac15e376fe Merged-In: I5010c68512e75d1b9a337c02da86faac15e376fe --- java/Android.bp | 1 + java/test_spec_test.go | 132 ++++++++++++++++++++++++++++++++++++++ testing/Android.bp | 1 + testing/all_test_specs.go | 4 +- testing/test.go | 21 ++++++ testing/test_spec.go | 6 +- 6 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 java/test_spec_test.go create mode 100644 testing/test.go diff --git a/java/Android.bp b/java/Android.bp index 043ab82fe..2ad7a7a30 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -110,6 +110,7 @@ bootstrap_go_package { "sdk_library_test.go", "system_modules_test.go", "systemserver_classpath_fragment_test.go", + "test_spec_test.go", ], pluginFor: ["soong_build"], } diff --git a/java/test_spec_test.go b/java/test_spec_test.go new file mode 100644 index 000000000..22a8e60ee --- /dev/null +++ b/java/test_spec_test.go @@ -0,0 +1,132 @@ +package java + +import ( + "strings" + "testing" + + "android/soong/android" + soongTesting "android/soong/testing" + "android/soong/testing/test_spec_proto" + "google.golang.org/protobuf/proto" +) + +func TestTestSpec(t *testing.T) { + bp := `test_spec { + name: "module-name", + teamId: "12345", + tests: [ + "java-test-module-name-one", + "java-test-module-name-two" + ] + } + + java_test { + name: "java-test-module-name-one", + } + + java_test { + name: "java-test-module-name-two", + }` + result := runTest(t, android.FixtureExpectsNoErrors, bp) + + module := result.ModuleForTests( + "module-name", "", + ).Module().(*soongTesting.TestSpecModule) + + // Check that the provider has the right contents + data := result.ModuleProvider( + module, soongTesting.TestSpecProviderKey, + ).(soongTesting.TestSpecProviderData) + if !strings.HasSuffix( + data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb", + ) { + t.Errorf( + "Missing intermediates path in provider: %s", + data.IntermediatePath.String(), + ) + } + + buildParamsSlice := module.BuildParamsForTests() + var metadata = "" + for _, params := range buildParamsSlice { + if params.Rule.String() == "android/soong/android.writeFile" { + metadata = params.Args["content"] + } + } + + metadataList := make([]*test_spec_proto.TestSpec_OwnershipMetadata, 0, 2) + teamId := "12345" + bpFilePath := "Android.bp" + targetNames := []string{ + "java-test-module-name-one", "java-test-module-name-two", + } + + for _, test := range targetNames { + targetName := test + metadata := test_spec_proto.TestSpec_OwnershipMetadata{ + TrendyTeamId: &teamId, + TargetName: &targetName, + Path: &bpFilePath, + } + metadataList = append(metadataList, &metadata) + } + testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList} + protoData, _ := proto.Marshal(&testSpecMetadata) + rawData := string(protoData) + formattedData := strings.ReplaceAll(rawData, "\n", "\\n") + expectedMetadata := "'" + formattedData + "\\n'" + + if metadata != expectedMetadata { + t.Errorf( + "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata, + expectedMetadata, + ) + } + + // Tests for all_test_spec singleton. + singleton := result.SingletonForTests("all_test_specs") + rule := singleton.Rule("all_test_specs_rule") + expectedCmd := "out/soong/host/linux-x86/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb" + expectedOutputFile := "out/soong/ownership/all_test_specs.pb" + expectedInputFile := "out/soong/.intermediates/module-name/intermediateTestSpecMetadata.pb" + if !strings.Contains( + strings.TrimSpace(rule.Output.String()), + expectedOutputFile, + ) { + t.Errorf( + "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s", + rule.Output.String(), expectedOutputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.Inputs[0].String()), + expectedInputFile, + ) { + t.Errorf( + "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s", + rule.Inputs[0].String(), expectedInputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.RuleParams.Command), + expectedCmd, + ) { + t.Errorf( + "Retrieved cmd: %s is not equal to expectedCmd: %s", + rule.RuleParams.Command, expectedCmd, + ) + } +} + +func runTest( + t *testing.T, errorHandler android.FixtureErrorHandler, bp string, +) *android.TestResult { + return android.GroupFixturePreparers( + soongTesting.PrepareForTestWithTestSpecBuildComponents, + PrepareForIntegrationTestWithJava, + ). + ExtendWithErrorHandler(errorHandler). + RunTestWithBp(t, bp) +} diff --git a/testing/Android.bp b/testing/Android.bp index 85e6a8ba8..18dccb305 100644 --- a/testing/Android.bp +++ b/testing/Android.bp @@ -15,6 +15,7 @@ bootstrap_go_package { "all_test_specs.go", "test_spec.go", "init.go", + "test.go", ], pluginFor: ["soong_build"], } diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go index 2ecf15fa6..9d4645b37 100644 --- a/testing/all_test_specs.go +++ b/testing/all_test_specs.go @@ -21,10 +21,10 @@ func (this *allTestSpecsSingleton) GenerateBuildActions(ctx android.SingletonCon var intermediateMetadataPaths android.Paths ctx.VisitAllModules(func(module android.Module) { - if !ctx.ModuleHasProvider(module, testSpecProviderKey) { + if !ctx.ModuleHasProvider(module, TestSpecProviderKey) { return } - intermediateMetadataPaths = append(intermediateMetadataPaths, ctx.ModuleProvider(module, testSpecProviderKey).(testSpecProviderData).IntermediatePath) + intermediateMetadataPaths = append(intermediateMetadataPaths, ctx.ModuleProvider(module, TestSpecProviderKey).(TestSpecProviderData).IntermediatePath) }) rspFile := android.PathForOutput(ctx, fileContainingFilePaths) diff --git a/testing/test.go b/testing/test.go new file mode 100644 index 000000000..44824e4db --- /dev/null +++ b/testing/test.go @@ -0,0 +1,21 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testing + +import ( + "android/soong/android" +) + +var PrepareForTestWithTestSpecBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents) diff --git a/testing/test_spec.go b/testing/test_spec.go index 1ad276875..c370f7174 100644 --- a/testing/test_spec.go +++ b/testing/test_spec.go @@ -78,11 +78,11 @@ func isInt(s string) bool { } // Provider published by TestSpec -type testSpecProviderData struct { +type TestSpecProviderData struct { IntermediatePath android.WritablePath } -var testSpecProviderKey = blueprint.NewProvider(testSpecProviderData{}) +var TestSpecProviderKey = blueprint.NewProvider(TestSpecProviderData{}) type TestModuleProviderData struct { } @@ -120,7 +120,7 @@ func (module *TestSpecModule) GenerateAndroidBuildActions(ctx android.ModuleCont android.WriteFileRule(ctx, intermediatePath, string(protoData)) ctx.SetProvider( - testSpecProviderKey, testSpecProviderData{ + TestSpecProviderKey, TestSpecProviderData{ IntermediatePath: intermediatePath, }, ) From 5202fc918e723f3ddf0794c5cf3e38e7542ab9d6 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Tue, 21 Nov 2023 22:40:27 +0000 Subject: [PATCH 07/37] Use result.Config.PrebuiltOS() to get prebuiltHost in test_spec_test Bug: 312536783 Bug: 312536905 Test: m nothing --no-skip-soong-tests -j96 Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2836072 Change-Id: I1e12281927269d42ae796348b223030acfd6ecfa Merged-In: I1e12281927269d42ae796348b223030acfd6ecfa --- java/test_spec_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/test_spec_test.go b/java/test_spec_test.go index 22a8e60ee..39aff4cef 100644 --- a/java/test_spec_test.go +++ b/java/test_spec_test.go @@ -86,7 +86,8 @@ func TestTestSpec(t *testing.T) { // Tests for all_test_spec singleton. singleton := result.SingletonForTests("all_test_specs") rule := singleton.Rule("all_test_specs_rule") - expectedCmd := "out/soong/host/linux-x86/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb" + prebuiltOs := result.Config.PrebuiltOS() + expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb" expectedOutputFile := "out/soong/ownership/all_test_specs.pb" expectedInputFile := "out/soong/.intermediates/module-name/intermediateTestSpecMetadata.pb" if !strings.Contains( From 40c8da1d395a36f5c02dea663b13d9f7d88fee05 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Thu, 12 Oct 2023 19:40:17 +0000 Subject: [PATCH 08/37] Add Code Metadata rule to soong/testing. This Cl adds a new rule to Soong to generate code ownership metadata. Also, this CL adds a provider in the Java SDK library to provide generated source files to the Code_metadata rule. Will add providers to other libraries in the future changes. Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2786121 Bug: 296873595 Change-Id: Ic2e43aa9b161231fea4416d1f0d36b778361d7c5 Merged-In: Ic2e43aa9b161231fea4416d1f0d36b778361d7c5 --- android/Android.bp | 1 + android/source_file_provider.go | 11 + java/Android.bp | 1 + java/code_metadata_test.go | 125 ++++++++ java/sdk_library.go | 1 + java/test_spec_test.go | 10 +- testing/Android.bp | 3 + testing/OWNERS | 4 + testing/all_code_metadata.go | 51 ++++ testing/code_metadata.go | 139 +++++++++ .../code_metadata_internal_proto/Android.bp | 29 ++ testing/code_metadata_internal_proto/OWNERS | 4 + .../code_metadata_internal.pb.go | 277 ++++++++++++++++++ .../code_metadata_internal.proto | 40 +++ testing/code_metadata_internal_proto/go.mod | 3 + testing/code_metadata_internal_proto/regen.sh | 3 + testing/code_metadata_proto/Android.bp | 29 ++ testing/code_metadata_proto/OWNERS | 4 + .../code_metadata_proto/code_metadata.pb.go | 263 +++++++++++++++++ .../code_metadata_proto/code_metadata.proto | 37 +++ testing/code_metadata_proto/go.mod | 3 + testing/code_metadata_proto/regen.sh | 3 + testing/init.go | 2 + testing/test.go | 2 +- testing/test_spec_proto/go.mod | 5 +- 25 files changed, 1042 insertions(+), 8 deletions(-) create mode 100644 android/source_file_provider.go create mode 100644 java/code_metadata_test.go create mode 100644 testing/OWNERS create mode 100644 testing/all_code_metadata.go create mode 100644 testing/code_metadata.go create mode 100644 testing/code_metadata_internal_proto/Android.bp create mode 100644 testing/code_metadata_internal_proto/OWNERS create mode 100644 testing/code_metadata_internal_proto/code_metadata_internal.pb.go create mode 100644 testing/code_metadata_internal_proto/code_metadata_internal.proto create mode 100644 testing/code_metadata_internal_proto/go.mod create mode 100644 testing/code_metadata_internal_proto/regen.sh create mode 100644 testing/code_metadata_proto/Android.bp create mode 100644 testing/code_metadata_proto/OWNERS create mode 100644 testing/code_metadata_proto/code_metadata.pb.go create mode 100644 testing/code_metadata_proto/code_metadata.proto create mode 100644 testing/code_metadata_proto/go.mod create mode 100644 testing/code_metadata_proto/regen.sh diff --git a/android/Android.bp b/android/Android.bp index 641c438f1..35d5c19ca 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -88,6 +88,7 @@ bootstrap_go_package { "singleton.go", "singleton_module.go", "soong_config_modules.go", + "source_file_provider.go", "test_asserts.go", "test_suites.go", "testing.go", diff --git a/android/source_file_provider.go b/android/source_file_provider.go new file mode 100644 index 000000000..80bde2a50 --- /dev/null +++ b/android/source_file_provider.go @@ -0,0 +1,11 @@ +package android + +import ( + "github.com/google/blueprint" +) + +type SrcsFileProviderData struct { + SrcPaths Paths +} + +var SrcsFileProviderKey = blueprint.NewProvider(SrcsFileProviderData{}) diff --git a/java/Android.bp b/java/Android.bp index 2ad7a7a30..4d1e34e83 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -84,6 +84,7 @@ bootstrap_go_package { "app_import_test.go", "app_set_test.go", "app_test.go", + "code_metadata_test.go", "bootclasspath_fragment_test.go", "device_host_converter_test.go", "dex_test.go", diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go new file mode 100644 index 000000000..4b05d9ea6 --- /dev/null +++ b/java/code_metadata_test.go @@ -0,0 +1,125 @@ +package java + +import ( + "strings" + "testing" + + "android/soong/android" + soongTesting "android/soong/testing" + "android/soong/testing/code_metadata_internal_proto" + "google.golang.org/protobuf/proto" +) + +func TestCodeMetadata(t *testing.T) { + bp := `code_metadata { + name: "module-name", + teamId: "12345", + code: [ + "foo", + ] + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + }` + result := runCodeMetadataTest(t, android.FixtureExpectsNoErrors, bp) + + module := result.ModuleForTests( + "module-name", "", + ).Module().(*soongTesting.CodeMetadataModule) + + // Check that the provider has the right contents + data := result.ModuleProvider( + module, soongTesting.CodeMetadataProviderKey, + ).(soongTesting.CodeMetadataProviderData) + if !strings.HasSuffix( + data.IntermediatePath.String(), "/intermediateCodeMetadata.pb", + ) { + t.Errorf( + "Missing intermediates path in provider: %s", + data.IntermediatePath.String(), + ) + } + + buildParamsSlice := module.BuildParamsForTests() + var metadata = "" + for _, params := range buildParamsSlice { + if params.Rule.String() == "android/soong/android.writeFile" { + metadata = params.Args["content"] + } + } + + metadataList := make([]*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, 2) + teamId := "12345" + bpFilePath := "Android.bp" + targetName := "foo" + srcFile := []string{"a.java"} + expectedMetadataProto := code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ + TrendyTeamId: &teamId, + TargetName: &targetName, + Path: &bpFilePath, + SourceFiles: srcFile, + } + metadataList = append(metadataList, &expectedMetadataProto) + + CodeMetadataMetadata := code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList} + protoData, _ := proto.Marshal(&CodeMetadataMetadata) + rawData := string(protoData) + formattedData := strings.ReplaceAll(rawData, "\n", "\\n") + expectedMetadata := "'" + formattedData + "\\n'" + + if metadata != expectedMetadata { + t.Errorf( + "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata, + expectedMetadata, + ) + } + + // Tests for all_test_spec singleton. + singleton := result.SingletonForTests("all_code_metadata") + rule := singleton.Rule("all_code_metadata_rule") + prebuiltOs := result.Config.PrebuiltOS() + expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule code_metadata -inputFile out/soong/all_code_metadata_paths.rsp -outputFile out/soong/ownership/all_code_metadata.pb" + expectedOutputFile := "out/soong/ownership/all_code_metadata.pb" + expectedInputFile := "out/soong/.intermediates/module-name/intermediateCodeMetadata.pb" + if !strings.Contains( + strings.TrimSpace(rule.Output.String()), + expectedOutputFile, + ) { + t.Errorf( + "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s", + rule.Output.String(), expectedOutputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.Inputs[0].String()), + expectedInputFile, + ) { + t.Errorf( + "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s", + rule.Inputs[0].String(), expectedInputFile, + ) + } + + if !strings.Contains( + strings.TrimSpace(rule.RuleParams.Command), + expectedCmd, + ) { + t.Errorf( + "Retrieved cmd: %s doesn't contain expectedCmd: %s", + rule.RuleParams.Command, expectedCmd, + ) + } +} +func runCodeMetadataTest( + t *testing.T, errorHandler android.FixtureErrorHandler, bp string, +) *android.TestResult { + return android.GroupFixturePreparers( + soongTesting.PrepareForTestWithTestingBuildComponents, prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"), + ). + ExtendWithErrorHandler(errorHandler). + RunTestWithBp(t, bp) +} diff --git a/java/sdk_library.go b/java/sdk_library.go index 853792d20..01e69a2e7 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1404,6 +1404,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } } ctx.SetProvider(android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo}) + ctx.SetProvider(android.SrcsFileProviderKey, android.SrcsFileProviderData{SrcPaths: module.uniqueSrcFiles}) } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/java/test_spec_test.go b/java/test_spec_test.go index 39aff4cef..7f06785b0 100644 --- a/java/test_spec_test.go +++ b/java/test_spec_test.go @@ -27,7 +27,7 @@ func TestTestSpec(t *testing.T) { java_test { name: "java-test-module-name-two", }` - result := runTest(t, android.FixtureExpectsNoErrors, bp) + result := runTestSpecTest(t, android.FixtureExpectsNoErrors, bp) module := result.ModuleForTests( "module-name", "", @@ -78,7 +78,7 @@ func TestTestSpec(t *testing.T) { if metadata != expectedMetadata { t.Errorf( - "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata, + "Retrieved metadata: %s doesn't contain expectedMetadata: %s", metadata, expectedMetadata, ) } @@ -121,11 +121,11 @@ func TestTestSpec(t *testing.T) { } } -func runTest( - t *testing.T, errorHandler android.FixtureErrorHandler, bp string, +func runTestSpecTest( + t *testing.T, errorHandler android.FixtureErrorHandler, bp string, ) *android.TestResult { return android.GroupFixturePreparers( - soongTesting.PrepareForTestWithTestSpecBuildComponents, + soongTesting.PrepareForTestWithTestingBuildComponents, PrepareForIntegrationTestWithJava, ). ExtendWithErrorHandler(errorHandler). diff --git a/testing/Android.bp b/testing/Android.bp index 18dccb305..43040b0f9 100644 --- a/testing/Android.bp +++ b/testing/Android.bp @@ -8,11 +8,14 @@ bootstrap_go_package { deps: [ "blueprint", "soong-android", + "soong-testing-code_metadata_internal_proto", "soong-testing-test_spec_proto", ], srcs: [ + "all_code_metadata.go", "all_test_specs.go", + "code_metadata.go", "test_spec.go", "init.go", "test.go", diff --git a/testing/OWNERS b/testing/OWNERS new file mode 100644 index 000000000..03bcdf1c4 --- /dev/null +++ b/testing/OWNERS @@ -0,0 +1,4 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com diff --git a/testing/all_code_metadata.go b/testing/all_code_metadata.go new file mode 100644 index 000000000..16d7aae66 --- /dev/null +++ b/testing/all_code_metadata.go @@ -0,0 +1,51 @@ +package testing + +import ( + "android/soong/android" +) + +const fileContainingCodeMetadataFilePaths = "all_code_metadata_paths.rsp" +const allCodeMetadataFile = "all_code_metadata.pb" + +func AllCodeMetadataFactory() android.Singleton { + return &allCodeMetadataSingleton{} +} + +type allCodeMetadataSingleton struct { + // Path where the collected metadata is stored after successful validation. + outputPath android.OutputPath +} + +func (this *allCodeMetadataSingleton) GenerateBuildActions(ctx android.SingletonContext) { + var intermediateMetadataPaths android.Paths + + ctx.VisitAllModules( + func(module android.Module) { + if !ctx.ModuleHasProvider(module, CodeMetadataProviderKey) { + return + } + intermediateMetadataPaths = append( + intermediateMetadataPaths, ctx.ModuleProvider( + module, CodeMetadataProviderKey, + ).(CodeMetadataProviderData).IntermediatePath, + ) + }, + ) + + rspFile := android.PathForOutput(ctx, fileContainingCodeMetadataFilePaths) + this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allCodeMetadataFile) + + rule := android.NewRuleBuilder(pctx, ctx) + cmd := rule.Command(). + BuiltTool("metadata"). + FlagWithArg("-rule ", "code_metadata"). + FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths) + cmd.FlagWithOutput("-outputFile ", this.outputPath) + rule.Build("all_code_metadata_rule", "Generate all code metadata") + + ctx.Phony("all_code_metadata", this.outputPath) +} + +func (this *allCodeMetadataSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.DistForGoal("code_metadata", this.outputPath) +} diff --git a/testing/code_metadata.go b/testing/code_metadata.go new file mode 100644 index 000000000..926324dff --- /dev/null +++ b/testing/code_metadata.go @@ -0,0 +1,139 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package testing + +import ( + "path/filepath" + + "android/soong/android" + "android/soong/testing/code_metadata_internal_proto" + "github.com/google/blueprint" + "google.golang.org/protobuf/proto" +) + +func CodeMetadataFactory() android.Module { + module := &CodeMetadataModule{} + + android.InitAndroidModule(module) + android.InitDefaultableModule(module) + module.AddProperties(&module.properties) + + return module +} + +type CodeMetadataModule struct { + android.ModuleBase + android.DefaultableModuleBase + android.BazelModuleBase + + // Properties for "code_metadata" + properties struct { + // Specifies the name of the code_config. + Name string + // Specifies the team ID. + TeamId string + // Specifies the list of modules that this code_metadata covers. + Code []string + // An optional field to specify if multiple ownerships for source files is allowed. + MultiOwnership bool + } +} + +type codeDepTagType struct { + blueprint.BaseDependencyTag +} + +var codeDepTag = codeDepTagType{} + +func (module *CodeMetadataModule) DepsMutator(ctx android.BottomUpMutatorContext) { + // Validate Properties + if len(module.properties.TeamId) == 0 { + ctx.PropertyErrorf( + "TeamId", + "Team Id not found in the code_metadata module. Hint: Maybe the teamId property hasn't been properly specified.", + ) + } + if !isInt(module.properties.TeamId) { + ctx.PropertyErrorf( + "TeamId", "Invalid value for Team ID. The Team ID must be an integer.", + ) + } + if len(module.properties.Code) == 0 { + ctx.PropertyErrorf( + "Code", + "Targets to be attributed cannot be empty. Hint: Maybe the code property hasn't been properly specified.", + ) + } + ctx.AddDependency(ctx.Module(), codeDepTag, module.properties.Code...) +} + +// Provider published by CodeMetadata +type CodeMetadataProviderData struct { + IntermediatePath android.WritablePath +} + +var CodeMetadataProviderKey = blueprint.NewProvider(CodeMetadataProviderData{}) + +func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { + metadataList := make( + []*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, + len(module.properties.Code), + ) + bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile()) + + for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) { + targetName := m.Name() + var moduleSrcs android.Paths + if ctx.OtherModuleHasProvider(m, android.SrcsFileProviderKey) { + moduleSrcs = ctx.OtherModuleProvider( + m, android.SrcsFileProviderKey, + ).(android.SrcsFileProviderData).SrcPaths + } + if module.properties.MultiOwnership { + metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ + TargetName: &targetName, + TrendyTeamId: &module.properties.TeamId, + Path: &bpFilePath, + MultiOwnership: &module.properties.MultiOwnership, + SourceFiles: moduleSrcs.Strings(), + } + metadataList = append(metadataList, metadata) + } else { + metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ + TargetName: &targetName, + TrendyTeamId: &module.properties.TeamId, + Path: &bpFilePath, + SourceFiles: moduleSrcs.Strings(), + } + metadataList = append(metadataList, metadata) + } + + } + codeMetadata := &code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList} + protoData, err := proto.Marshal(codeMetadata) + if err != nil { + ctx.ModuleErrorf("Error marshaling code metadata: %s", err.Error()) + return + } + intermediatePath := android.PathForModuleOut( + ctx, "intermediateCodeMetadata.pb", + ) + android.WriteFileRule(ctx, intermediatePath, string(protoData)) + + ctx.SetProvider( + CodeMetadataProviderKey, + CodeMetadataProviderData{IntermediatePath: intermediatePath}, + ) +} diff --git a/testing/code_metadata_internal_proto/Android.bp b/testing/code_metadata_internal_proto/Android.bp new file mode 100644 index 000000000..a534cc20b --- /dev/null +++ b/testing/code_metadata_internal_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-testing-code_metadata_internal_proto", + pkgPath: "android/soong/testing/code_metadata_internal_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "code_metadata_internal.pb.go", + ], +} diff --git a/testing/code_metadata_internal_proto/OWNERS b/testing/code_metadata_internal_proto/OWNERS new file mode 100644 index 000000000..03bcdf1c4 --- /dev/null +++ b/testing/code_metadata_internal_proto/OWNERS @@ -0,0 +1,4 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.pb.go b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go new file mode 100644 index 000000000..ecb8b867a --- /dev/null +++ b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go @@ -0,0 +1,277 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: code_metadata_internal.proto + +package code_metadata_internal_proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CodeMetadataInternal struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of all code targets and their metadata. + TargetOwnershipList []*CodeMetadataInternal_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"` +} + +func (x *CodeMetadataInternal) Reset() { + *x = CodeMetadataInternal{} + if protoimpl.UnsafeEnabled { + mi := &file_code_metadata_internal_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeMetadataInternal) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeMetadataInternal) ProtoMessage() {} + +func (x *CodeMetadataInternal) ProtoReflect() protoreflect.Message { + mi := &file_code_metadata_internal_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeMetadataInternal.ProtoReflect.Descriptor instead. +func (*CodeMetadataInternal) Descriptor() ([]byte, []int) { + return file_code_metadata_internal_proto_rawDescGZIP(), []int{0} +} + +func (x *CodeMetadataInternal) GetTargetOwnershipList() []*CodeMetadataInternal_TargetOwnership { + if x != nil { + return x.TargetOwnershipList + } + return nil +} + +type CodeMetadataInternal_TargetOwnership struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // REQUIRED: Name of the build target + TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"` + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + // REQUIRED: Team ID of the team that owns this target. + TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"` + // OPTIONAL: The src files of the target. + // To be used to determine ownership of a file for ownership + SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"` + // OPTIONAL: Specify if multiple ownerships of the source files are allowed. + MultiOwnership *bool `protobuf:"varint,5,opt,name=multi_ownership,json=multiOwnership" json:"multi_ownership,omitempty"` +} + +func (x *CodeMetadataInternal_TargetOwnership) Reset() { + *x = CodeMetadataInternal_TargetOwnership{} + if protoimpl.UnsafeEnabled { + mi := &file_code_metadata_internal_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeMetadataInternal_TargetOwnership) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeMetadataInternal_TargetOwnership) ProtoMessage() {} + +func (x *CodeMetadataInternal_TargetOwnership) ProtoReflect() protoreflect.Message { + mi := &file_code_metadata_internal_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeMetadataInternal_TargetOwnership.ProtoReflect.Descriptor instead. +func (*CodeMetadataInternal_TargetOwnership) Descriptor() ([]byte, []int) { + return file_code_metadata_internal_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *CodeMetadataInternal_TargetOwnership) GetTargetName() string { + if x != nil && x.TargetName != nil { + return *x.TargetName + } + return "" +} + +func (x *CodeMetadataInternal_TargetOwnership) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *CodeMetadataInternal_TargetOwnership) GetTrendyTeamId() string { + if x != nil && x.TrendyTeamId != nil { + return *x.TrendyTeamId + } + return "" +} + +func (x *CodeMetadataInternal_TargetOwnership) GetSourceFiles() []string { + if x != nil { + return x.SourceFiles + } + return nil +} + +func (x *CodeMetadataInternal_TargetOwnership) GetMultiOwnership() bool { + if x != nil && x.MultiOwnership != nil { + return *x.MultiOwnership + } + return false +} + +var File_code_metadata_internal_proto protoreflect.FileDescriptor + +var file_code_metadata_internal_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, + 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x02, 0x0a, + 0x14, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x76, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0xb8, 0x01, + 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, + 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, + 0x27, 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x42, 0x34, 0x5a, 0x32, 0x61, 0x6e, 0x64, 0x72, + 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, + 0x67, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_code_metadata_internal_proto_rawDescOnce sync.Once + file_code_metadata_internal_proto_rawDescData = file_code_metadata_internal_proto_rawDesc +) + +func file_code_metadata_internal_proto_rawDescGZIP() []byte { + file_code_metadata_internal_proto_rawDescOnce.Do(func() { + file_code_metadata_internal_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_internal_proto_rawDescData) + }) + return file_code_metadata_internal_proto_rawDescData +} + +var file_code_metadata_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_code_metadata_internal_proto_goTypes = []interface{}{ + (*CodeMetadataInternal)(nil), // 0: code_metadata_internal_proto.CodeMetadataInternal + (*CodeMetadataInternal_TargetOwnership)(nil), // 1: code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership +} +var file_code_metadata_internal_proto_depIdxs = []int32{ + 1, // 0: code_metadata_internal_proto.CodeMetadataInternal.target_ownership_list:type_name -> code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_code_metadata_internal_proto_init() } +func file_code_metadata_internal_proto_init() { + if File_code_metadata_internal_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_code_metadata_internal_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CodeMetadataInternal); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_code_metadata_internal_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CodeMetadataInternal_TargetOwnership); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_code_metadata_internal_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_code_metadata_internal_proto_goTypes, + DependencyIndexes: file_code_metadata_internal_proto_depIdxs, + MessageInfos: file_code_metadata_internal_proto_msgTypes, + }.Build() + File_code_metadata_internal_proto = out.File + file_code_metadata_internal_proto_rawDesc = nil + file_code_metadata_internal_proto_goTypes = nil + file_code_metadata_internal_proto_depIdxs = nil +} diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.proto b/testing/code_metadata_internal_proto/code_metadata_internal.proto new file mode 100644 index 000000000..14edc0f9b --- /dev/null +++ b/testing/code_metadata_internal_proto/code_metadata_internal.proto @@ -0,0 +1,40 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; +package code_metadata_internal_proto; +option go_package = "android/soong/testing/code_metadata_internal_proto"; + +message CodeMetadataInternal { + + message TargetOwnership { + // REQUIRED: Name of the build target + optional string target_name = 1; + + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + optional string path = 2; + + // REQUIRED: Team ID of the team that owns this target. + optional string trendy_team_id = 3; + + // OPTIONAL: The src files of the target. + // To be used to determine ownership of a file for ownership + repeated string source_files = 4; + + // OPTIONAL: Specify if multiple ownerships of the source files are allowed. + optional bool multi_ownership = 5; + } + + // List of all code targets and their metadata. + repeated TargetOwnership target_ownership_list = 1; +} diff --git a/testing/code_metadata_internal_proto/go.mod b/testing/code_metadata_internal_proto/go.mod new file mode 100644 index 000000000..7e9129d57 --- /dev/null +++ b/testing/code_metadata_internal_proto/go.mod @@ -0,0 +1,3 @@ +module android/soong/testing/code_metadata_internal_proto + +go 1.18 diff --git a/testing/code_metadata_internal_proto/regen.sh b/testing/code_metadata_internal_proto/regen.sh new file mode 100644 index 000000000..f101a02b2 --- /dev/null +++ b/testing/code_metadata_internal_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. code_metadata_internal.proto diff --git a/testing/code_metadata_proto/Android.bp b/testing/code_metadata_proto/Android.bp new file mode 100644 index 000000000..8fcca1918 --- /dev/null +++ b/testing/code_metadata_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-testing-code_metadata_proto", + pkgPath: "android/soong/testing/code_metadata_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "code_metadata.pb.go", + ], +} diff --git a/testing/code_metadata_proto/OWNERS b/testing/code_metadata_proto/OWNERS new file mode 100644 index 000000000..03bcdf1c4 --- /dev/null +++ b/testing/code_metadata_proto/OWNERS @@ -0,0 +1,4 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com diff --git a/testing/code_metadata_proto/code_metadata.pb.go b/testing/code_metadata_proto/code_metadata.pb.go new file mode 100644 index 000000000..711bf7a82 --- /dev/null +++ b/testing/code_metadata_proto/code_metadata.pb.go @@ -0,0 +1,263 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: code_metadata.proto + +package code_metadata_proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type CodeMetadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of all code targets and their metadata. + TargetOwnershipList []*CodeMetadata_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"` +} + +func (x *CodeMetadata) Reset() { + *x = CodeMetadata{} + if protoimpl.UnsafeEnabled { + mi := &file_code_metadata_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeMetadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeMetadata) ProtoMessage() {} + +func (x *CodeMetadata) ProtoReflect() protoreflect.Message { + mi := &file_code_metadata_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeMetadata.ProtoReflect.Descriptor instead. +func (*CodeMetadata) Descriptor() ([]byte, []int) { + return file_code_metadata_proto_rawDescGZIP(), []int{0} +} + +func (x *CodeMetadata) GetTargetOwnershipList() []*CodeMetadata_TargetOwnership { + if x != nil { + return x.TargetOwnershipList + } + return nil +} + +type CodeMetadata_TargetOwnership struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // REQUIRED: Name of the build target + TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"` + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + // REQUIRED: Team ID of the team that owns this target. + TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"` + // OPTIONAL: The src files of the target. + // To be used to determine ownership of a file for ownership + SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"` +} + +func (x *CodeMetadata_TargetOwnership) Reset() { + *x = CodeMetadata_TargetOwnership{} + if protoimpl.UnsafeEnabled { + mi := &file_code_metadata_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CodeMetadata_TargetOwnership) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CodeMetadata_TargetOwnership) ProtoMessage() {} + +func (x *CodeMetadata_TargetOwnership) ProtoReflect() protoreflect.Message { + mi := &file_code_metadata_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CodeMetadata_TargetOwnership.ProtoReflect.Descriptor instead. +func (*CodeMetadata_TargetOwnership) Descriptor() ([]byte, []int) { + return file_code_metadata_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *CodeMetadata_TargetOwnership) GetTargetName() string { + if x != nil && x.TargetName != nil { + return *x.TargetName + } + return "" +} + +func (x *CodeMetadata_TargetOwnership) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *CodeMetadata_TargetOwnership) GetTrendyTeamId() string { + if x != nil && x.TrendyTeamId != nil { + return *x.TrendyTeamId + } + return "" +} + +func (x *CodeMetadata_TargetOwnership) GetSourceFiles() []string { + if x != nil { + return x.SourceFiles + } + return nil +} + +var File_code_metadata_proto protoreflect.FileDescriptor + +var file_code_metadata_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x02, 0x0a, 0x0c, 0x43, + 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, 0x15, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x64, + 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69, + 0x73, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, + 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, + 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, + 0x69, 0x6c, 0x65, 0x73, 0x42, 0x2b, 0x5a, 0x29, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, + 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f, + 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, +} + +var ( + file_code_metadata_proto_rawDescOnce sync.Once + file_code_metadata_proto_rawDescData = file_code_metadata_proto_rawDesc +) + +func file_code_metadata_proto_rawDescGZIP() []byte { + file_code_metadata_proto_rawDescOnce.Do(func() { + file_code_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_proto_rawDescData) + }) + return file_code_metadata_proto_rawDescData +} + +var file_code_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_code_metadata_proto_goTypes = []interface{}{ + (*CodeMetadata)(nil), // 0: code_metadata_proto.CodeMetadata + (*CodeMetadata_TargetOwnership)(nil), // 1: code_metadata_proto.CodeMetadata.TargetOwnership +} +var file_code_metadata_proto_depIdxs = []int32{ + 1, // 0: code_metadata_proto.CodeMetadata.target_ownership_list:type_name -> code_metadata_proto.CodeMetadata.TargetOwnership + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_code_metadata_proto_init() } +func file_code_metadata_proto_init() { + if File_code_metadata_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_code_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CodeMetadata); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_code_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CodeMetadata_TargetOwnership); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_code_metadata_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_code_metadata_proto_goTypes, + DependencyIndexes: file_code_metadata_proto_depIdxs, + MessageInfos: file_code_metadata_proto_msgTypes, + }.Build() + File_code_metadata_proto = out.File + file_code_metadata_proto_rawDesc = nil + file_code_metadata_proto_goTypes = nil + file_code_metadata_proto_depIdxs = nil +} diff --git a/testing/code_metadata_proto/code_metadata.proto b/testing/code_metadata_proto/code_metadata.proto new file mode 100644 index 000000000..254836300 --- /dev/null +++ b/testing/code_metadata_proto/code_metadata.proto @@ -0,0 +1,37 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; +package code_metadata_proto; +option go_package = "android/soong/testing/code_metadata_proto"; + +message CodeMetadata { + + message TargetOwnership { + // REQUIRED: Name of the build target + optional string target_name = 1; + + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + optional string path = 2; + + // REQUIRED: Team ID of the team that owns this target. + optional string trendy_team_id = 3; + + // OPTIONAL: The src files of the target. + // To be used to determine ownership of a file for ownership + repeated string source_files = 4; + } + + // List of all code targets and their metadata. + repeated TargetOwnership target_ownership_list = 1; +} diff --git a/testing/code_metadata_proto/go.mod b/testing/code_metadata_proto/go.mod new file mode 100644 index 000000000..ada241157 --- /dev/null +++ b/testing/code_metadata_proto/go.mod @@ -0,0 +1,3 @@ +module android/soong/testing/code_metadata_proto + +go 1.18 diff --git a/testing/code_metadata_proto/regen.sh b/testing/code_metadata_proto/regen.sh new file mode 100644 index 000000000..ffe06f7e2 --- /dev/null +++ b/testing/code_metadata_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. code_metadata.proto diff --git a/testing/init.go b/testing/init.go index 1ab689215..290efc6c3 100644 --- a/testing/init.go +++ b/testing/init.go @@ -28,6 +28,8 @@ func init() { } func RegisterBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("code_metadata", CodeMetadataFactory) ctx.RegisterModuleType("test_spec", TestSpecFactory) ctx.RegisterSingletonType("all_test_specs", AllTestSpecsFactory) + ctx.RegisterSingletonType("all_code_metadata", AllCodeMetadataFactory) } diff --git a/testing/test.go b/testing/test.go index 44824e4db..cd97a8fac 100644 --- a/testing/test.go +++ b/testing/test.go @@ -18,4 +18,4 @@ import ( "android/soong/android" ) -var PrepareForTestWithTestSpecBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents) +var PrepareForTestWithTestingBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents) diff --git a/testing/test_spec_proto/go.mod b/testing/test_spec_proto/go.mod index 482cdbbd1..b581aac30 100644 --- a/testing/test_spec_proto/go.mod +++ b/testing/test_spec_proto/go.mod @@ -1,2 +1,3 @@ -module test_spec_proto -go 1.18 \ No newline at end of file +module android/soong/testing/test_spec_proto + +go 1.18 From 95e2a3cbcd368d98578184020128e7038e2fb1a3 Mon Sep 17 00:00:00 2001 From: Aditya Choudhary Date: Wed, 29 Nov 2023 16:42:42 +0000 Subject: [PATCH 09/37] Add source file provider for genrule/srcs, python libraries and rust libraries. Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2786121 Change-Id: I2d7d4684a10c15aeecc27b8db800ab27a807d2e2 Merged-In: I2d7d4684a10c15aeecc27b8db800ab27a807d2e2 --- android/Android.bp | 1 - android/filegroup.go | 1 + android/source_file_provider.go | 11 ----------- bpf/bpf.go | 1 + cc/cc.go | 1 + genrule/genrule.go | 1 + java/base.go | 2 ++ java/sdk_library.go | 1 - python/python.go | 1 + rust/rust.go | 1 + sh/sh_binary.go | 1 + sysprop/sysprop_library.go | 7 ++++--- testing/code_metadata.go | 12 ++++++------ 13 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 android/source_file_provider.go diff --git a/android/Android.bp b/android/Android.bp index 35d5c19ca..641c438f1 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -88,7 +88,6 @@ bootstrap_go_package { "singleton.go", "singleton_module.go", "soong_config_modules.go", - "source_file_provider.go", "test_asserts.go", "test_suites.go", "testing.go", diff --git a/android/filegroup.go b/android/filegroup.go index 121368d7b..66aa15446 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -237,6 +237,7 @@ func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { if fg.properties.Path != nil { fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path)) } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()}) } func (fg *fileGroup) Srcs() Paths { diff --git a/android/source_file_provider.go b/android/source_file_provider.go deleted file mode 100644 index 80bde2a50..000000000 --- a/android/source_file_provider.go +++ /dev/null @@ -1,11 +0,0 @@ -package android - -import ( - "github.com/google/blueprint" -) - -type SrcsFileProviderData struct { - SrcPaths Paths -} - -var SrcsFileProviderKey = blueprint.NewProvider(SrcsFileProviderData{}) diff --git a/bpf/bpf.go b/bpf/bpf.go index d135d5f56..710d9cd67 100644 --- a/bpf/bpf.go +++ b/bpf/bpf.go @@ -208,6 +208,7 @@ func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()}) } func (bpf *bpf) AndroidMk() android.AndroidMkData { diff --git a/cc/cc.go b/cc/cc.go index 7c0b0c5d8..c40c5a66d 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -2109,6 +2109,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if c.testModule { ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()}) c.maybeInstall(ctx, apexInfo) } diff --git a/genrule/genrule.go b/genrule/genrule.go index 00adb7025..f532297f7 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -419,6 +419,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { addLocationLabel(in, inputLocation{paths}) } } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()}) var copyFrom android.Paths var outputFiles android.WritablePaths diff --git a/java/base.go b/java/base.go index 991132321..025fc7eec 100644 --- a/java/base.go +++ b/java/base.go @@ -22,6 +22,7 @@ import ( "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" + "github.com/google/blueprint" "android/soong/android" "android/soong/dexpreopt" @@ -1105,6 +1106,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...) uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...) j.uniqueSrcFiles = uniqueSrcFiles + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()}) // We don't currently run annotation processors in turbine, which means we can't use turbine // generated header jars when an annotation processor that generates API is enabled. One diff --git a/java/sdk_library.go b/java/sdk_library.go index 01e69a2e7..853792d20 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1404,7 +1404,6 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } } ctx.SetProvider(android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo}) - ctx.SetProvider(android.SrcsFileProviderKey, android.SrcsFileProviderData{SrcPaths: module.uniqueSrcFiles}) } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { diff --git a/python/python.go b/python/python.go index 1a129737a..353cc65ed 100644 --- a/python/python.go +++ b/python/python.go @@ -404,6 +404,7 @@ func (p *PythonLibraryModule) AddDepsOnPythonLauncherAndStdlib(ctx android.Botto // GenerateAndroidBuildActions performs build actions common to all Python modules func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs) + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: expandedSrcs.Strings()}) // expand data files from "data" property. expandedData := android.PathsForModuleSrc(ctx, p.properties.Data) diff --git a/rust/rust.go b/rust/rust.go index 77bb8b609..fdc7849aa 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -958,6 +958,7 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs()) } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()}) } if mod.compiler != nil && !mod.compiler.Disabled() { diff --git a/sh/sh_binary.go b/sh/sh_binary.go index d224fdfa4..d5e9d421a 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -261,6 +261,7 @@ func (s *ShBinary) generateAndroidBuildActions(ctx android.ModuleContext) { Output: s.outputFilePath, Input: s.sourceFilePath, }) + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: []string{s.sourceFilePath.String()}}) } func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) { diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index 0edbb7c37..61fabae2b 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -241,12 +241,13 @@ func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath { // generated java_library will depend on these API files. func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { baseModuleName := m.BaseModuleName() - - for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) { + srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs) + for _, syspropFile := range srcs { if syspropFile.Ext() != ".sysprop" { ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String()) } } + ctx.SetProvider(blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()}) if ctx.Failed() { return @@ -264,7 +265,7 @@ func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) rule.Command(). BuiltTool("sysprop_api_dump"). Output(m.dumpedApiFile). - Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs)) + Inputs(srcs) rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump") // check API rule diff --git a/testing/code_metadata.go b/testing/code_metadata.go index 926324dff..455028357 100644 --- a/testing/code_metadata.go +++ b/testing/code_metadata.go @@ -95,11 +95,11 @@ func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.Module for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) { targetName := m.Name() - var moduleSrcs android.Paths - if ctx.OtherModuleHasProvider(m, android.SrcsFileProviderKey) { + var moduleSrcs []string + if ctx.OtherModuleHasProvider(m, blueprint.SrcsFileProviderKey) { moduleSrcs = ctx.OtherModuleProvider( - m, android.SrcsFileProviderKey, - ).(android.SrcsFileProviderData).SrcPaths + m, blueprint.SrcsFileProviderKey, + ).(blueprint.SrcsFileProviderData).SrcPaths } if module.properties.MultiOwnership { metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ @@ -107,7 +107,7 @@ func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.Module TrendyTeamId: &module.properties.TeamId, Path: &bpFilePath, MultiOwnership: &module.properties.MultiOwnership, - SourceFiles: moduleSrcs.Strings(), + SourceFiles: moduleSrcs, } metadataList = append(metadataList, metadata) } else { @@ -115,7 +115,7 @@ func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.Module TargetName: &targetName, TrendyTeamId: &module.properties.TeamId, Path: &bpFilePath, - SourceFiles: moduleSrcs.Strings(), + SourceFiles: moduleSrcs, } metadataList = append(metadataList, metadata) } From 9f054b87a22cc7cac25d4b495b53663cc0c9def5 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 11 Dec 2023 18:59:20 -0800 Subject: [PATCH 10/37] Remove extra go.mod files Only the top level build/soong/go.mod file should exist, any extras breaks `go test ./...` in build/soong, and also breaks the kythe build that produces xrefs for code search. Bug: 315537199 Test: go test ./... Ignore-AOSP-First: CPing test_spec rule to udc-mainline-prod to support migration of test targets. Cherry pick of:aosp/2847033 Change-Id: Id5262550654ff1559cfb3fa1ecdae95c126109df Merged-In: Id5262550654ff1559cfb3fa1ecdae95c126109df --- testing/code_metadata_internal_proto/go.mod | 3 --- testing/code_metadata_proto/go.mod | 3 --- testing/test_spec_proto/go.mod | 3 --- 3 files changed, 9 deletions(-) delete mode 100644 testing/code_metadata_internal_proto/go.mod delete mode 100644 testing/code_metadata_proto/go.mod delete mode 100644 testing/test_spec_proto/go.mod diff --git a/testing/code_metadata_internal_proto/go.mod b/testing/code_metadata_internal_proto/go.mod deleted file mode 100644 index 7e9129d57..000000000 --- a/testing/code_metadata_internal_proto/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module android/soong/testing/code_metadata_internal_proto - -go 1.18 diff --git a/testing/code_metadata_proto/go.mod b/testing/code_metadata_proto/go.mod deleted file mode 100644 index ada241157..000000000 --- a/testing/code_metadata_proto/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module android/soong/testing/code_metadata_proto - -go 1.18 diff --git a/testing/test_spec_proto/go.mod b/testing/test_spec_proto/go.mod deleted file mode 100644 index b581aac30..000000000 --- a/testing/test_spec_proto/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module android/soong/testing/test_spec_proto - -go 1.18 From 028b94cdc5d89e3f5a84b25b39067f902ffa448a Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Tue, 16 Jan 2024 17:17:11 -0800 Subject: [PATCH 11/37] Promote the NewApi check to an error again Now that all existing cases have been baselined. Ignore-AOSP-First: Requires a LSC that is difficult to do across branches. Bug: 268261262 Test: m lint-check Change-Id: I413f86ff7a1f33564465f3ba9cd52924a4242901 --- java/lint.go | 7 +------ java/lint_test.go | 5 ++--- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/java/lint.go b/java/lint.go index c3d723b40..91e22a491 100644 --- a/java/lint.go +++ b/java/lint.go @@ -319,12 +319,7 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagWithInput("@", android.PathForSource(ctx, "build/soong/java/lint_defaults.txt")) - if l.compileSdkKind == android.SdkPublic { - cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors) - } else { - // TODO(b/268261262): Remove this branch. We're demoting NewApi to a warning due to pre-existing issues that need to be fixed. - cmd.FlagForEachArg("--warning_check ", l.extraMainlineLintErrors) - } + cmd.FlagForEachArg("--error_check ", l.extraMainlineLintErrors) cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks) cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks) cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) diff --git a/java/lint_test.go b/java/lint_test.go index b7e6aad8e..11c999cea 100644 --- a/java/lint_test.go +++ b/java/lint_test.go @@ -91,9 +91,8 @@ func TestJavaLintUsesCorrectBpConfig(t *testing.T) { t.Error("did not use the correct file for baseline") } - if !strings.Contains(*sboxProto.Commands[0].Command, "--warning_check NewApi") { - // TODO(b/268261262): Change this to check for --error_check - t.Error("should check NewApi warnings") + if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check NewApi") { + t.Error("should check NewApi errors") } if !strings.Contains(*sboxProto.Commands[0].Command, "--error_check SomeCheck") { From 62dc7cad5250547f131862597981de2b5ad3da0d Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Tue, 12 Dec 2023 17:14:22 -0800 Subject: [PATCH 12/37] Add sdk_genrule Some users want to repackage the results of an sdk module. Genrules have 3 variants: linux, android, and common_os. The common_os one produces a snapshot zip file that users want. In order to get access to it, we need a genrule in the same variant, so create an sdk_genrule for that. The sdk_genrule shouldn't have linux/android variants either, because those other variants would get errors when trying to depend on the sdk modules because the snapshot zip doesn't exist in those other variants. The code in arch.go needs to be tweaked to allow a common_os variant without the other variants. Bug: 315962165 Test: m dist out/dist/art_release.zip (cherry picked from https://android-review.googlesource.com/q/commit:8fc38f3761521cb489b7c25ac730ad4279ddb5c0) Merged-In: Idc9b3cae7a525d71aed6bafa0f8724a89f75a94b Change-Id: Idc9b3cae7a525d71aed6bafa0f8724a89f75a94b --- android/arch.go | 5 +++-- sdk/Android.bp | 2 ++ sdk/genrule.go | 44 ++++++++++++++++++++++++++++++++++++++ sdk/genrule_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++++ sdk/sdk.go | 12 +++++++++++ 5 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 sdk/genrule.go create mode 100644 sdk/genrule_test.go diff --git a/android/arch.go b/android/arch.go index 4b4691b3d..d3e7d2a3e 100644 --- a/android/arch.go +++ b/android/arch.go @@ -446,8 +446,10 @@ func osMutator(bpctx blueprint.BottomUpMutatorContext) { } } + createCommonOSVariant := base.commonProperties.CreateCommonOSVariant + // If there are no supported OSes then disable the module. - if len(moduleOSList) == 0 { + if len(moduleOSList) == 0 && !createCommonOSVariant { base.Disable() return } @@ -458,7 +460,6 @@ func osMutator(bpctx blueprint.BottomUpMutatorContext) { osNames[i] = os.String() } - createCommonOSVariant := base.commonProperties.CreateCommonOSVariant if createCommonOSVariant { // A CommonOS variant was requested so add it to the list of OS variants to // create. It needs to be added to the end because it needs to depend on the diff --git a/sdk/Android.bp b/sdk/Android.bp index f42b4787d..f436320df 100644 --- a/sdk/Android.bp +++ b/sdk/Android.bp @@ -18,6 +18,7 @@ bootstrap_go_package { "bp.go", "build_release.go", "exports.go", + "genrule.go", "member_trait.go", "member_type.go", "sdk.go", @@ -30,6 +31,7 @@ bootstrap_go_package { "cc_sdk_test.go", "compat_config_sdk_test.go", "exports_test.go", + "genrule_test.go", "java_sdk_test.go", "license_sdk_test.go", "member_trait_test.go", diff --git a/sdk/genrule.go b/sdk/genrule.go new file mode 100644 index 000000000..347ab0556 --- /dev/null +++ b/sdk/genrule.go @@ -0,0 +1,44 @@ +// Copyright 2023 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package sdk + +import ( + "android/soong/android" + "android/soong/genrule" +) + +func init() { + registerGenRuleBuildComponents(android.InitRegistrationContext) +} + +func registerGenRuleBuildComponents(ctx android.RegistrationContext) { + ctx.RegisterModuleType("sdk_genrule", SdkGenruleFactory) +} + +// sdk_genrule_host is a genrule that can depend on sdk and sdk_snapshot module types +// +// What this means is that it's a genrule with only the "common_os" variant. +// sdk modules have 3 variants: host, android, and common_os. The common_os one depends +// on the host/device ones and packages their result into a final snapshot zip. +// Genrules probably want access to this snapshot zip when they depend on an sdk module, +// which means they want to depend on the common_os variant and not the host/android +// variants. +func SdkGenruleFactory() android.Module { + module := genrule.NewGenRule() + + android.InitCommonOSAndroidMultiTargetsArchModule(module, android.NeitherHostNorDeviceSupported, android.MultilibCommon) + android.InitDefaultableModule(module) + + return module +} diff --git a/sdk/genrule_test.go b/sdk/genrule_test.go new file mode 100644 index 000000000..6e52a3db0 --- /dev/null +++ b/sdk/genrule_test.go @@ -0,0 +1,52 @@ +// Copyright 2018 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sdk + +import ( + "testing" + + "android/soong/android" + "android/soong/genrule" + "android/soong/java" +) + +func TestSdkGenrule(t *testing.T) { + // Test that an sdk_genrule can depend on an sdk, and that a genrule can depend on an sdk_genrule + bp := ` + sdk { + name: "my_sdk", + } + sdk_genrule { + name: "my_sdk_genrule", + tool_files: ["tool"], + cmd: "$(location tool) $(in) $(out)", + srcs: [":my_sdk"], + out: ["out"], + } + genrule { + name: "my_regular_genrule", + srcs: [":my_sdk_genrule"], + out: ["out"], + cmd: "cp $(in) $(out)", + } + ` + android.GroupFixturePreparers( + // if java components aren't registered, the sdk module doesn't create a snapshot for some reason. + java.PrepareForTestWithJavaBuildComponents, + genrule.PrepareForTestWithGenRuleBuildComponents, + PrepareForTestWithSdkBuildComponents, + android.FixtureRegisterWithContext(registerGenRuleBuildComponents), + ).RunTestWithBp(t, bp) +} diff --git a/sdk/sdk.go b/sdk/sdk.go index 4d4a2a2c4..fd16ab63f 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -222,6 +222,18 @@ func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries { }} } +func (s *sdk) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + if s.snapshotFile.Valid() { + return []android.Path{s.snapshotFile.Path()}, nil + } + return nil, fmt.Errorf("snapshot file not defined. This is most likely because this isn't the common_os variant of this module") + default: + return nil, fmt.Errorf("unknown tag %q", tag) + } +} + // gatherTraits gathers the traits from the dynamically generated trait specific properties. // // Returns a map from member name to the set of required traits. From 24e25c0499956d78fcbd2b8a9a9b00e773e6949f Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Fri, 19 Jan 2024 14:12:17 -0800 Subject: [PATCH 13/37] Re-enable strict updatability linting Now that all use cases where it would've errored on are removed. Ignore-AOSP-First: the properties were only removed in internal main to make the LSC smaller Bug: 320698986 Test: m nothing --no-skip-soong-tests, and also locally edited soong to add a quick build that runs all the strict updatability checks in the tree and ran that Change-Id: If9e23327a3c0944cc8c6849914fe51dc48bdb626 --- apex/apex_test.go | 372 +++++++++++++++++++++++----------------------- java/lint.go | 15 +- java/lint_test.go | 95 ++++++------ 3 files changed, 246 insertions(+), 236 deletions(-) diff --git a/apex/apex_test.go b/apex/apex_test.go index 7e67c0f9d..229175fbd 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -10273,188 +10273,196 @@ func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, mo } } -// TODO(b/193460475): Re-enable this test -//func TestApexStrictUpdtabilityLint(t *testing.T) { -// bpTemplate := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// java_libs: ["myjavalib"], -// updatable: %v, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// lint: { -// strict_updatability_linting: %v, -// }, -// sdk_version: "current", -// min_sdk_version: "29", -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// testCases := []struct { -// testCaseName string -// apexUpdatable bool -// javaStrictUpdtabilityLint bool -// lintFileExists bool -// disallowedFlagExpected bool -// }{ -// { -// testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", -// apexUpdatable: true, -// javaStrictUpdtabilityLint: true, -// lintFileExists: false, -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "non-updatable apex respects strict_updatability of javalib", -// apexUpdatable: false, -// javaStrictUpdtabilityLint: false, -// lintFileExists: true, -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "non-updatable apex respects strict updatability of javalib", -// apexUpdatable: false, -// javaStrictUpdtabilityLint: true, -// lintFileExists: true, -// disallowedFlagExpected: true, -// }, -// { -// testCaseName: "updatable apex sets strict updatability of javalib to true", -// apexUpdatable: true, -// javaStrictUpdtabilityLint: false, // will be set to true by mutator -// lintFileExists: true, -// disallowedFlagExpected: true, -// }, -// } -// -// for _, testCase := range testCases { -// bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint) -// fixtures := []android.FixturePreparer{} -// if testCase.lintFileExists { -// fixtures = append(fixtures, fs.AddToFixture()) -// } -// -// result := testApex(t, bp, fixtures...) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") -// -// if disallowedFlagActual != testCase.disallowedFlagExpected { -// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) -// } -// } -//} -// -//func TestUpdatabilityLintSkipLibcore(t *testing.T) { -// bp := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// java_libs: ["myjavalib"], -// updatable: true, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// sdk_version: "current", -// min_sdk_version: "29", -// } -// ` -// -// testCases := []struct { -// testCaseName string -// moduleDirectory string -// disallowedFlagExpected bool -// }{ -// { -// testCaseName: "lintable module defined outside libcore", -// moduleDirectory: "", -// disallowedFlagExpected: true, -// }, -// { -// testCaseName: "lintable module defined in libcore root directory", -// moduleDirectory: "libcore/", -// disallowedFlagExpected: false, -// }, -// { -// testCaseName: "lintable module defined in libcore child directory", -// moduleDirectory: "libcore/childdir/", -// disallowedFlagExpected: true, -// }, -// } -// -// for _, testCase := range testCases { -// lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "") -// bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp) -// result := testApex(t, "", lintFileCreator, bpFileCreator) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory) -// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags) -// -// if disallowedFlagActual != testCase.disallowedFlagExpected { -// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) -// } -// } -//} -// -//// checks transtive deps of an apex coming from bootclasspath_fragment -//func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { -// bp := ` -// apex { -// name: "myapex", -// key: "myapex.key", -// bootclasspath_fragments: ["mybootclasspathfragment"], -// updatable: true, -// min_sdk_version: "29", -// } -// apex_key { -// name: "myapex.key", -// } -// bootclasspath_fragment { -// name: "mybootclasspathfragment", -// contents: ["myjavalib"], -// apex_available: ["myapex"], -// hidden_api: { -// split_packages: ["*"], -// }, -// } -// java_library { -// name: "myjavalib", -// srcs: ["MyClass.java"], -// apex_available: [ "myapex" ], -// sdk_version: "current", -// min_sdk_version: "29", -// compile_dex: true, -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) -// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) -// } -//} +func TestApexStrictUpdtabilityLint(t *testing.T) { + bpTemplate := ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["myjavalib"], + updatable: %v, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + lint: { + strict_updatability_linting: %v, + %s + }, + sdk_version: "current", + min_sdk_version: "29", + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + testCases := []struct { + testCaseName string + apexUpdatable bool + javaStrictUpdtabilityLint bool + lintFileExists bool + disallowedFlagExpected bool + }{ + { + testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd", + apexUpdatable: true, + javaStrictUpdtabilityLint: true, + lintFileExists: false, + disallowedFlagExpected: false, + }, + { + testCaseName: "non-updatable apex respects strict_updatability of javalib", + apexUpdatable: false, + javaStrictUpdtabilityLint: false, + lintFileExists: true, + disallowedFlagExpected: false, + }, + { + testCaseName: "non-updatable apex respects strict updatability of javalib", + apexUpdatable: false, + javaStrictUpdtabilityLint: true, + lintFileExists: true, + disallowedFlagExpected: true, + }, + { + testCaseName: "updatable apex sets strict updatability of javalib to true", + apexUpdatable: true, + javaStrictUpdtabilityLint: false, // will be set to true by mutator + lintFileExists: true, + disallowedFlagExpected: true, + }, + } + + for _, testCase := range testCases { + fixtures := []android.FixturePreparer{} + baselineProperty := "" + if testCase.lintFileExists { + fixtures = append(fixtures, fs.AddToFixture()) + baselineProperty = "baseline_filename: \"lint-baseline.xml\"" + } + bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty) + + result := testApex(t, bp, fixtures...) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") + + if disallowedFlagActual != testCase.disallowedFlagExpected { + t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) + } + } +} + +func TestUpdatabilityLintSkipLibcore(t *testing.T) { + bp := ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["myjavalib"], + updatable: true, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + sdk_version: "current", + min_sdk_version: "29", + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + + testCases := []struct { + testCaseName string + moduleDirectory string + disallowedFlagExpected bool + }{ + { + testCaseName: "lintable module defined outside libcore", + moduleDirectory: "", + disallowedFlagExpected: true, + }, + { + testCaseName: "lintable module defined in libcore root directory", + moduleDirectory: "libcore/", + disallowedFlagExpected: false, + }, + { + testCaseName: "lintable module defined in libcore child directory", + moduleDirectory: "libcore/childdir/", + disallowedFlagExpected: true, + }, + } + + for _, testCase := range testCases { + lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "") + bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp) + result := testApex(t, "", lintFileCreator, bpFileCreator) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory) + disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags) + + if disallowedFlagActual != testCase.disallowedFlagExpected { + t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command) + } + } +} + +// checks transtive deps of an apex coming from bootclasspath_fragment +func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) { + bp := ` + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["mybootclasspathfragment"], + updatable: true, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + } + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: ["myjavalib"], + apex_available: ["myapex"], + hidden_api: { + split_packages: ["*"], + }, + } + java_library { + name: "myjavalib", + srcs: ["MyClass.java"], + apex_available: [ "myapex" ], + sdk_version: "current", + min_sdk_version: "29", + compile_dex: true, + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture()) + myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command) + } +} // updatable apexes should propagate updatable=true to its apps func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) { diff --git a/java/lint.go b/java/lint.go index 91e22a491..bd6c1bae6 100644 --- a/java/lint.go +++ b/java/lint.go @@ -325,14 +325,13 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.Ru cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) - // TODO(b/193460475): Re-enable strict updatability linting - //if l.GetStrictUpdatabilityLinting() { - // // Verify the module does not baseline issues that endanger safe updatability. - // if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() { - // cmd.FlagWithInput("--baseline ", baselinePath.Path()) - // cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) - // } - //} + if l.GetStrictUpdatabilityLinting() { + // Verify the module does not baseline issues that endanger safe updatability. + if l.properties.Lint.Baseline_filename != nil { + cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename)) + cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks) + } + } return lintPaths{ projectXML: projectXMLPath, diff --git a/java/lint_test.go b/java/lint_test.go index 11c999cea..6aee5946b 100644 --- a/java/lint_test.go +++ b/java/lint_test.go @@ -152,52 +152,55 @@ func TestJavaLintBypassUpdatableChecks(t *testing.T) { } } -// TODO(b/193460475): Re-enable this test -//func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { -// bp := ` -// java_library { -// name: "foo", -// srcs: [ -// "a.java", -// ], -// static_libs: ["bar"], -// min_sdk_version: "29", -// sdk_version: "current", -// lint: { -// strict_updatability_linting: true, -// }, -// } -// -// java_library { -// name: "bar", -// srcs: [ -// "a.java", -// ], -// min_sdk_version: "29", -// sdk_version: "current", -// } -// ` -// fs := android.MockFS{ -// "lint-baseline.xml": nil, -// } -// -// result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()). -// RunTestWithBp(t, bp) -// -// foo := result.ModuleForTests("foo", "android_common") -// sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, -// "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Error("did not restrict baselining NewApi") -// } -// -// bar := result.ModuleForTests("bar", "android_common") -// sboxProto = android.RuleBuilderSboxProtoForTests(t, bar.Output("lint.sbox.textproto")) -// if !strings.Contains(*sboxProto.Commands[0].Command, -// "--baseline lint-baseline.xml --disallowed_issues NewApi") { -// t.Error("did not restrict baselining NewApi") -// } -//} +func TestJavaLintStrictUpdatabilityLinting(t *testing.T) { + bp := ` + java_library { + name: "foo", + srcs: [ + "a.java", + ], + static_libs: ["bar"], + min_sdk_version: "29", + sdk_version: "current", + lint: { + strict_updatability_linting: true, + baseline_filename: "lint-baseline.xml", + }, + } + + java_library { + name: "bar", + srcs: [ + "a.java", + ], + min_sdk_version: "29", + sdk_version: "current", + lint: { + baseline_filename: "lint-baseline.xml", + } + } + ` + fs := android.MockFS{ + "lint-baseline.xml": nil, + } + + result := android.GroupFixturePreparers(PrepareForTestWithJavaDefaultModules, fs.AddToFixture()). + RunTestWithBp(t, bp) + + foo := result.ModuleForTests("foo", "android_common") + sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, + "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Error("did not restrict baselining NewApi") + } + + bar := result.ModuleForTests("bar", "android_common") + sboxProto = android.RuleBuilderSboxProtoForTests(t, result.TestContext, bar.Output("lint.sbox.textproto")) + if !strings.Contains(*sboxProto.Commands[0].Command, + "--baseline lint-baseline.xml --disallowed_issues NewApi") { + t.Error("did not restrict baselining NewApi") + } +} func TestJavaLintDatabaseSelectionFull(t *testing.T) { testCases := []struct { From 74965459c78384e0d29583939ce5962737f507eb Mon Sep 17 00:00:00 2001 From: Jihoon Kang Date: Tue, 23 Jan 2024 22:07:09 +0000 Subject: [PATCH 14/37] Introduce aconfig_declarations property in udc-mainline-prod Currently, Soong changes in aosp are not merged to udc-mainline-prod, while the mainline projects changes from aosp are merged. This leads to a conflicting build configuration issue for aosp-first projects, which want to maintain consistent bp module definition between aosp and main. In order to support specifying `aconfig_declaration` property in aosp for mainline projects, this change adds the property to the module definition while not performing any build actions, in order to resolve presubmit failures in udc-mainline-prod when specifying the property in aosp changes. Cherry-picking the aosp changes that introduces the property is not an option, as the flagging infra is not expected to be imported to udc-mainline-prod. Test: m nothing --no-skip-soong-tests Bug: 315027929 Merged-In: I37becd1b9dd9069d7ac4abed130906df30b3fdf4 Change-Id: Ie467c1dd4a36774f6268452fae8c054b9b3ad7d9 --- java/droidstubs.go | 4 ++++ java/sdk_library.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/java/droidstubs.go b/java/droidstubs.go index a9e20e03f..ea9305f51 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -152,6 +152,10 @@ type DroidstubsProperties struct { // API surface of this module. If set, the module contributes to an API surface. // For the full list of available API surfaces, refer to soong/android/sdk_version.go Api_surface *string + + // a list of aconfig_declarations module names that the stubs generated in this module + // depend on. + Aconfig_declarations []string } // Used by xsd_config diff --git a/java/sdk_library.go b/java/sdk_library.go index 853792d20..d461882c8 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -571,6 +571,10 @@ type sdkLibraryProperties struct { Enabled *bool } + // a list of aconfig_declarations module names that the stubs generated in this module + // depend on. + Aconfig_declarations []string + // TODO: determines whether to create HTML doc or not // Html_doc *bool } From 57f2349824a27cd7e83da1fd55a32281a88a40de Mon Sep 17 00:00:00 2001 From: Ronald Braunstein Date: Tue, 19 Dec 2023 10:24:47 -0800 Subject: [PATCH 15/37] Add team property to all modules. This allows vendors (like google) to specify which team owns the test module and code. Team is a commonProperty on modules and points to the designate "team" module. The DepsMutator adds the dependency on the "team" module and "GenerateBuildActions" write the team data to intermediate files. A new singleton rule, all_teams visits all modules and writes out the proto containing the team for each module. If a module doesn't have a team, then it finds the package in the blueprint file and parent directory blueprint files that have a default_team and uses that team. *** BRANCH DIFF *** *** BRANCH DIFF *** Some small diffs in writing proto file on udc-branch. i.e. write as textproto instead of binary and only write modules with teams or default teams from package, not all modules. This is because udc doesn't have the newer WriteFile rule from raw_files: https://source.corp.google.com/h/android/platform/build/soong/+/31a674571e53f12dffb97698e65b9eee6ae0ebbc *** BRANCH DIFF *** *** BRANCH DIFF *** Test: m all_teams Test: go test ./python ./java ./cc ./rust ./android Test: added team to HelloWorldHostTest and built the new asciiproto target Test: added package default_team and checkout output proto. Change-Id: I5c07bf489de460a04fc540f5fff0394f39f574a7 Merged-In: I5c07bf489de460a04fc540f5fff0394f39f574a7 --- android/Android.bp | 3 + android/all_teams.go | 151 ++++++++++++++++++++ android/all_teams_test.go | 208 ++++++++++++++++++++++++++++ android/module.go | 20 +++ android/mutator.go | 1 + android/package.go | 8 ++ android/team.go | 58 ++++++++ android/team_proto/Android.bp | 29 ++++ android/team_proto/OWNERS | 5 + android/team_proto/regen.sh | 3 + android/team_proto/team.pb.go | 253 ++++++++++++++++++++++++++++++++++ android/team_proto/team.proto | 34 +++++ android/team_test.go | 99 +++++++++++++ 13 files changed, 872 insertions(+) create mode 100644 android/all_teams.go create mode 100644 android/all_teams_test.go create mode 100644 android/team.go create mode 100644 android/team_proto/Android.bp create mode 100644 android/team_proto/OWNERS create mode 100755 android/team_proto/regen.sh create mode 100644 android/team_proto/team.pb.go create mode 100644 android/team_proto/team.proto create mode 100644 android/team_test.go diff --git a/android/Android.bp b/android/Android.bp index 641c438f1..b13d7cdb6 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -11,6 +11,7 @@ bootstrap_go_package { "blueprint-metrics", "sbox_proto", "soong", + "soong-android_team_proto", "soong-android-soongconfig", "soong-bazel", "soong-cquery", @@ -28,6 +29,7 @@ bootstrap_go_package { "androidmk-parser", ], srcs: [ + "all_teams.go", "androidmk.go", "apex.go", "api_domain.go", @@ -88,6 +90,7 @@ bootstrap_go_package { "singleton.go", "singleton_module.go", "soong_config_modules.go", + "team.go", "test_asserts.go", "test_suites.go", "testing.go", diff --git a/android/all_teams.go b/android/all_teams.go new file mode 100644 index 000000000..d061649da --- /dev/null +++ b/android/all_teams.go @@ -0,0 +1,151 @@ +package android + +import ( + "android/soong/android/team_proto" + "path/filepath" + + "github.com/google/blueprint/proptools" + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +const ownershipDirectory = "ownership" +const allTeamsFile = "all_teams.pb" + +func AllTeamsFactory() Singleton { + return &allTeamsSingleton{} +} + +func init() { + registerAllTeamBuildComponents(InitRegistrationContext) +} + +func registerAllTeamBuildComponents(ctx RegistrationContext) { + ctx.RegisterSingletonType("all_teams", AllTeamsFactory) +} + +// For each module, list the team or the bpFile the module is defined in. +type moduleTeamInfo struct { + teamName string + bpFile string +} + +type allTeamsSingleton struct { + // Path where the collected metadata is stored after successful validation. + outputPath OutputPath + + // Map of all package modules we visit during GenerateBuildActions + packages map[string]packageProperties + // Map of all team modules we visit during GenerateBuildActions + teams map[string]teamProperties + // Keeps track of team information or bp file for each module we visit. + teams_for_mods map[string]moduleTeamInfo +} + +// See if there is a package module for the given bpFilePath with a team defined, if so return the team. +// If not ascend up to the parent directory and do the same. +func (this *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) { + // return the Default_team listed in the package if is there. + if p, ok := this.packages[bpFilePath]; ok { + if t := p.Default_team; t != nil { + return this.teams[*p.Default_team], true + } + } + // Strip a directory and go up. + // Does android/paths.go basePath,SourcePath help? + current, base := filepath.Split(bpFilePath) + current = filepath.Clean(current) // removes trailing slash, convert "" -> "." + parent, _ := filepath.Split(current) + if current == "." { + return teamProperties{}, false + } + return this.lookupDefaultTeam(filepath.Join(parent, base)) +} + +// Create a rule to run a tool to collect all the intermediate files +// which list the team per module into one proto file. +func (this *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) { + this.packages = make(map[string]packageProperties) + this.teams = make(map[string]teamProperties) + this.teams_for_mods = make(map[string]moduleTeamInfo) + + ctx.VisitAllModules(func(module Module) { + if !module.Enabled() { + return + } + + bpFile := ctx.BlueprintFile(module) + + // Package Modules and Team Modules are stored in a map so we can look them up by name for + // modules without a team. + if pack, ok := module.(*packageModule); ok { + // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in this context. + pkgKey := bpFile + this.packages[pkgKey] = pack.properties + return + } + if team, ok := module.(*teamModule); ok { + this.teams[team.Name()] = team.properties + return + } + + // If a team name is given for a module, store it. + // Otherwise store the bpFile so we can do a package walk later. + if module.base().Team() != "" { + this.teams_for_mods[module.Name()] = moduleTeamInfo{teamName: module.base().Team(), bpFile: bpFile} + } else { + this.teams_for_mods[module.Name()] = moduleTeamInfo{bpFile: bpFile} + } + }) + + // Visit all modules again and lookup the team name in the package or parent package if the team + // isn't assignged at the module level. + allTeams := this.lookupTeamForAllModules() + + this.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile) + // udc branch diff, use textproto and encode it. + data, err := prototext.Marshal(allTeams) + if err != nil { + ctx.Errorf("Unable to marshal team data. %s", err) + } + + WriteFileRuleVerbatim(ctx, this.outputPath, proptools.NinjaEscape(string(data))) + ctx.Phony("all_teams", this.outputPath) +} + +func (this *allTeamsSingleton) MakeVars(ctx MakeVarsContext) { + ctx.DistForGoal("all_teams", this.outputPath) +} + +// Visit every (non-package, non-team) module and write out a proto containing +// either the declared team data for that module or the package default team data for that module. +func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams { + teamsProto := make([]*team_proto.Team, len(this.teams_for_mods)) + i := 0 + for moduleName, m := range this.teams_for_mods { + teamName := m.teamName + var teamProperties teamProperties + found := false + if teamName != "" { + teamProperties, found = this.teams[teamName] + } else { + teamProperties, found = this.lookupDefaultTeam(m.bpFile) + } + + // udc branch diff, only write modules with teams to keep ninja file smaller. + if found { + trendy_team_id := *teamProperties.Trendy_team_id + var files []string + teamData := new(team_proto.Team) + *teamData = team_proto.Team{ + TrendyTeamId: proto.String(trendy_team_id), + TargetName: proto.String(moduleName), + Path: proto.String(m.bpFile), + File: files, + } + teamsProto[i] = teamData + i++ + } + } + return &team_proto.AllTeams{Teams: teamsProto[:i]} +} diff --git a/android/all_teams_test.go b/android/all_teams_test.go new file mode 100644 index 000000000..6302d86ff --- /dev/null +++ b/android/all_teams_test.go @@ -0,0 +1,208 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package android + +import ( + "android/soong/android/team_proto" + "log" + "testing" + + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/proto" +) + +func TestAllTeams(t *testing.T) { + t.Parallel() + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + ctx.RegisterSingletonType("all_teams", AllTeamsFactory) + }), + ).RunTestWithBp(t, ` + fake { + name: "main_test", + team: "someteam", + } + team { + name: "someteam", + trendy_team_id: "cool_team", + } + + team { + name: "team2", + trendy_team_id: "22222", + } + + fake { + name: "tool", + team: "team2", + } + + fake { + name: "noteam", + } + `) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "main_test": proto.String("cool_team"), + "tool": proto.String("22222"), + } + + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} + +func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams { + teams := new(team_proto.AllTeams) + config := ctx.SingletonForTests("all_teams") + allOutputs := config.AllOutputs() + + protoPath := allOutputs[0] + + out := config.MaybeOutput(protoPath) + outProto := []byte(ContentFromFileRuleForTests(t, out)) + // udc diff + if err := prototext.Unmarshal(outProto, teams); err != nil { + log.Fatalln("Failed to parse teams proto:", err) + } + return teams +} + +// Android.bp +// +// team: team_top +// +// # dir1 has no modules with teams, +// # but has a dir with no Android.bp +// dir1/Android.bp +// +// module_dir1 +// +// # dirs without and Android.bp should be fine. +// dir1/dir2/dir3/Android.bp +// +// package {} +// module_dir123 +// +// teams_dir/Android.bp +// +// module_with_team1: team1 +// team1: 111 +// +// # team comes from upper package default +// teams_dir/deeper/Android.bp +// +// module2_with_team1: team1 +// +// package_defaults/Android.bp +// package_defaults/pd2/Android.bp +// +// package{ default_team: team_top} +// module_pd2 ## should get team_top +// +// package_defaults/pd2/pd3/Android.bp +// +// module_pd3 ## should get team_top +func TestPackageLookup(t *testing.T) { + t.Parallel() + rootBp := ` + team { + name: "team_top", + trendy_team_id: "trendy://team_top", + } ` + + dir1Bp := ` + fake { + name: "module_dir1", + } ` + dir3Bp := ` + package {} + fake { + name: "module_dir123", + } ` + teamsDirBp := ` + fake { + name: "module_with_team1", + team: "team1" + + } + team { + name: "team1", + trendy_team_id: "111", + } ` + teamsDirDeeper := ` + fake { + name: "module2_with_team1", + team: "team1" + } ` + // create an empty one. + packageDefaultsBp := "" + packageDefaultspd2 := ` + package { default_team: "team_top"} + fake { + name: "modulepd2", + } ` + + packageDefaultspd3 := ` + fake { + name: "modulepd3", + } + fake { + name: "modulepd3b", + team: "team1" + } ` + + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + ctx.RegisterSingletonType("all_teams", AllTeamsFactory) + }), + FixtureAddTextFile("Android.bp", rootBp), + FixtureAddTextFile("dir1/Android.bp", dir1Bp), + FixtureAddTextFile("dir1/dir2/dir3/Android.bp", dir3Bp), + FixtureAddTextFile("teams_dir/Android.bp", teamsDirBp), + FixtureAddTextFile("teams_dir/deeper/Android.bp", teamsDirDeeper), + FixtureAddTextFile("package_defaults/Android.bp", packageDefaultsBp), + FixtureAddTextFile("package_defaults/pd2/Android.bp", packageDefaultspd2), + FixtureAddTextFile("package_defaults/pd2/pd3/Android.bp", packageDefaultspd3), + ).RunTest(t) + + var teams *team_proto.AllTeams + teams = getTeamProtoOutput(t, ctx) + + // map of module name -> trendy team name. + actualTeams := make(map[string]*string) + for _, teamProto := range teams.Teams { + actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId + } + expectedTeams := map[string]*string{ + "module_with_team1": proto.String("111"), + "module2_with_team1": proto.String("111"), + "modulepd2": proto.String("trendy://team_top"), + "modulepd3": proto.String("trendy://team_top"), + "modulepd3b": proto.String("111"), + // udc diff, no nil teams + } + AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams) +} diff --git a/android/module.go b/android/module.go index 76b4e3d11..05f7682dc 100644 --- a/android/module.go +++ b/android/module.go @@ -953,6 +953,10 @@ type commonProperties struct { // Bazel conversion status BazelConversionStatus BazelConversionStatus `blueprint:"mutated"` + + // The team (defined by the owner/vendor) who owns the property. + Team *string `android:"path"` + } // CommonAttributes represents the common Bazel attributes from which properties @@ -995,6 +999,12 @@ type distProperties struct { Dists []Dist `android:"arch_variant"` } +type TeamDepTagType struct { + blueprint.BaseDependencyTag +} + +var teamDepTag = TeamDepTagType{} + // CommonTestOptions represents the common `test_options` properties in // Android.bp. type CommonTestOptions struct { @@ -1699,6 +1709,12 @@ func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {} func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {} +func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) { + if m.Team() != "" { + ctx.AddDependency(ctx.Module(), teamDepTag, m.Team()) + } +} + // AddProperties "registers" the provided props // each value in props MUST be a pointer to a struct func (m *ModuleBase) AddProperties(props ...interface{}) { @@ -2136,6 +2152,10 @@ func (m *ModuleBase) Owner() string { return String(m.commonProperties.Owner) } +func (m *ModuleBase) Team() string { + return String(m.commonProperties.Team) +} + func (m *ModuleBase) setImageVariation(variant string) { m.commonProperties.ImageVariation = variant } diff --git a/android/mutator.go b/android/mutator.go index 013fa77cf..0afa76717 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -681,6 +681,7 @@ func componentDepsMutator(ctx BottomUpMutatorContext) { func depsMutator(ctx BottomUpMutatorContext) { if m := ctx.Module(); m.Enabled() { + m.base().baseDepsMutator(ctx) m.DepsMutator(ctx) } } diff --git a/android/package.go b/android/package.go index 7fbc70041..682b35025 100644 --- a/android/package.go +++ b/android/package.go @@ -38,6 +38,7 @@ type packageProperties struct { Default_visibility []string // Specifies the default license terms for all modules defined in this package. Default_applicable_licenses []string + Default_team *string `android:"path"` } type bazelPackageAttributes struct { @@ -90,6 +91,13 @@ func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) { // Nothing to do. } +func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) { + // Add the dependency to do a validity check + if p.properties.Default_team != nil { + ctx.AddDependency(ctx.Module(), nil, *p.properties.Default_team) + } +} + func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) { // Nothing to do. } diff --git a/android/team.go b/android/team.go new file mode 100644 index 000000000..df61f4021 --- /dev/null +++ b/android/team.go @@ -0,0 +1,58 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +func init() { + RegisterTeamBuildComponents(InitRegistrationContext) +} + +func RegisterTeamBuildComponents(ctx RegistrationContext) { + ctx.RegisterModuleType("team", TeamFactory) +} + +var PrepareForTestWithTeamBuildComponents = GroupFixturePreparers( + FixtureRegisterWithContext(RegisterTeamBuildComponents), +) + +type teamProperties struct { + Trendy_team_id *string `json:"trendy_team_id"` +} + +type teamModule struct { + ModuleBase + DefaultableModuleBase + + properties teamProperties +} + +// Real work is done for the module that depends on us. +// If needed, the team can serialize the config to json/proto file as well. +func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {} + +func (t *teamModule) TrendyTeamId(ctx ModuleContext) string { + return *t.properties.Trendy_team_id +} + +func TeamFactory() Module { + module := &teamModule{} + + base := module.base() + module.AddProperties(&base.nameProperties, &module.properties) + + InitAndroidModule(module) + InitDefaultableModule(module) + + return module +} diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp new file mode 100644 index 000000000..061e77e03 --- /dev/null +++ b/android/team_proto/Android.bp @@ -0,0 +1,29 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +bootstrap_go_package { + name: "soong-android_team_proto", + pkgPath: "android/soong/android/team_proto", + deps: [ + "golang-protobuf-reflect-protoreflect", + "golang-protobuf-runtime-protoimpl", + ], + srcs: [ + "team.pb.go", + ], +} diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS new file mode 100644 index 000000000..2beb4f47d --- /dev/null +++ b/android/team_proto/OWNERS @@ -0,0 +1,5 @@ +dariofreni@google.com +joeo@google.com +ronish@google.com +caditya@google.com +rbraunstein@google.com diff --git a/android/team_proto/regen.sh b/android/team_proto/regen.sh new file mode 100755 index 000000000..63b2016e1 --- /dev/null +++ b/android/team_proto/regen.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +aprotoc --go_out=paths=source_relative:. team.proto diff --git a/android/team_proto/team.pb.go b/android/team_proto/team.pb.go new file mode 100644 index 000000000..61260cf78 --- /dev/null +++ b/android/team_proto/team.pb.go @@ -0,0 +1,253 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.21.12 +// source: team.proto + +package team_proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Team struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // REQUIRED: Name of the build target + TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"` + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"` + // REQUIRED: Team ID of the team that owns this target. + TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"` + // OPTIONAL: Files directly owned by this module. + File []string `protobuf:"bytes,4,rep,name=file" json:"file,omitempty"` +} + +func (x *Team) Reset() { + *x = Team{} + if protoimpl.UnsafeEnabled { + mi := &file_team_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Team) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Team) ProtoMessage() {} + +func (x *Team) ProtoReflect() protoreflect.Message { + mi := &file_team_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Team.ProtoReflect.Descriptor instead. +func (*Team) Descriptor() ([]byte, []int) { + return file_team_proto_rawDescGZIP(), []int{0} +} + +func (x *Team) GetTargetName() string { + if x != nil && x.TargetName != nil { + return *x.TargetName + } + return "" +} + +func (x *Team) GetPath() string { + if x != nil && x.Path != nil { + return *x.Path + } + return "" +} + +func (x *Team) GetTrendyTeamId() string { + if x != nil && x.TrendyTeamId != nil { + return *x.TrendyTeamId + } + return "" +} + +func (x *Team) GetFile() []string { + if x != nil { + return x.File + } + return nil +} + +type AllTeams struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Teams []*Team `protobuf:"bytes,1,rep,name=teams" json:"teams,omitempty"` +} + +func (x *AllTeams) Reset() { + *x = AllTeams{} + if protoimpl.UnsafeEnabled { + mi := &file_team_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AllTeams) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AllTeams) ProtoMessage() {} + +func (x *AllTeams) ProtoReflect() protoreflect.Message { + mi := &file_team_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AllTeams.ProtoReflect.Descriptor instead. +func (*AllTeams) Descriptor() ([]byte, []int) { + return file_team_proto_rawDescGZIP(), []int{1} +} + +func (x *AllTeams) GetTeams() []*Team { + if x != nil { + return x.Teams + } + return nil +} + +var File_team_proto protoreflect.FileDescriptor + +var file_team_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x74, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65, + 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d, + 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, + 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, + 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66, + 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, + 0x32, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74, + 0x65, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61, + 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65, + 0x61, 0x6d, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, + 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61, + 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, +} + +var ( + file_team_proto_rawDescOnce sync.Once + file_team_proto_rawDescData = file_team_proto_rawDesc +) + +func file_team_proto_rawDescGZIP() []byte { + file_team_proto_rawDescOnce.Do(func() { + file_team_proto_rawDescData = protoimpl.X.CompressGZIP(file_team_proto_rawDescData) + }) + return file_team_proto_rawDescData +} + +var file_team_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_team_proto_goTypes = []interface{}{ + (*Team)(nil), // 0: team_proto.Team + (*AllTeams)(nil), // 1: team_proto.AllTeams +} +var file_team_proto_depIdxs = []int32{ + 0, // 0: team_proto.AllTeams.teams:type_name -> team_proto.Team + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_team_proto_init() } +func file_team_proto_init() { + if File_team_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_team_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Team); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_team_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AllTeams); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_team_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_team_proto_goTypes, + DependencyIndexes: file_team_proto_depIdxs, + MessageInfos: file_team_proto_msgTypes, + }.Build() + File_team_proto = out.File + file_team_proto_rawDesc = nil + file_team_proto_goTypes = nil + file_team_proto_depIdxs = nil +} diff --git a/android/team_proto/team.proto b/android/team_proto/team.proto new file mode 100644 index 000000000..401eccc6e --- /dev/null +++ b/android/team_proto/team.proto @@ -0,0 +1,34 @@ +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto2"; +package team_proto; +option go_package = "android/soong/android/team_proto"; + +message Team { + // REQUIRED: Name of the build target + optional string target_name = 1; + + // REQUIRED: Code location of the target. + // To be used to support legacy/backup systems that use OWNERS file and is + // also required for our dashboard to support per code location basis UI + optional string path = 2; + + // REQUIRED: Team ID of the team that owns this target. + optional string trendy_team_id = 3; + + // OPTIONAL: Files directly owned by this module. + repeated string file = 4; +} + +message AllTeams { + repeated Team teams = 1; +} diff --git a/android/team_test.go b/android/team_test.go new file mode 100644 index 000000000..75b3e9fbb --- /dev/null +++ b/android/team_test.go @@ -0,0 +1,99 @@ +// Copyright 2024 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package android + +import ( + "testing" +) + +type fakeModuleForTests struct { + ModuleBase +} + +func fakeModuleFactory() Module { + module := &fakeModuleForTests{} + InitAndroidModule(module) + return module +} + +func (*fakeModuleForTests) GenerateAndroidBuildActions(ModuleContext) {} + +func TestTeam(t *testing.T) { + t.Parallel() + ctx := GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ).RunTestWithBp(t, ` + fake { + name: "main_test", + team: "someteam", + } + team { + name: "someteam", + trendy_team_id: "cool_team", + } + + team { + name: "team2", + trendy_team_id: "22222", + } + + fake { + name: "tool", + team: "team2", + } + `) + + // Assert the rule from GenerateAndroidBuildActions exists. + m := ctx.ModuleForTests("main_test", "") + AssertStringEquals(t, "msg", m.Module().base().Team(), "someteam") + m = ctx.ModuleForTests("tool", "") + AssertStringEquals(t, "msg", m.Module().base().Team(), "team2") +} + +func TestMissingTeamFails(t *testing.T) { + t.Parallel() + GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ). + ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")). + RunTestWithBp(t, ` + fake { + name: "you_cannot_pass", + team: "ring-bearer", + } + `) +} + +func TestPackageBadTeamNameFails(t *testing.T) { + t.Parallel() + GroupFixturePreparers( + PrepareForTestWithTeamBuildComponents, + PrepareForTestWithPackageModule, + FixtureRegisterWithContext(func(ctx RegistrationContext) { + ctx.RegisterModuleType("fake", fakeModuleFactory) + }), + ). + ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")). + RunTestWithBp(t, ` + package { + default_team: "ring-bearer", + } + `) +} From 5bde2e2ca9997982e8f787dfaeb23e56bbe01915 Mon Sep 17 00:00:00 2001 From: Dan Shi Date: Fri, 26 May 2023 04:21:44 +0000 Subject: [PATCH 16/37] Support test runnner option in auto generated test configs Bug: 284179405 Bug: 236980335 Test: unittest Change-Id: Ifae3d556ff79153ca6c3067347fc259b665fb2e1 Merged-In: Ifae3d556ff79153ca6c3067347fc259b665fb2e1 --- cc/test.go | 5 +++++ java/java.go | 5 +++++ java/java_test.go | 24 ++++++++++++++++++++++++ tradefed/autogen.go | 37 +++++++++++++++++++++++++------------ 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/cc/test.go b/cc/test.go index 27de06b07..3f5f71007 100644 --- a/cc/test.go +++ b/cc/test.go @@ -70,6 +70,10 @@ type TestOptions struct { // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an // integer value and the value is less than the min_vndk_version, skip this module. Min_vndk_version *int64 + + // Extra