diff --git a/java/Android.bp b/java/Android.bp index 4450c4275..29c09570d 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 2271378a5..41848ce0b 100755 --- a/java/app.go +++ b/java/app.go @@ -22,6 +22,7 @@ import ( "path/filepath" "strings" + "android/soong/testing" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -1193,6 +1194,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 e92e6e68f..ea3fc9dbb 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" @@ -505,6 +506,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo if ctx.Module() != ctx.FinalModule() { b.HideFromMake() } + ctx.SetProvider(testing.TestModuleProviderKey, testing.TestModuleProviderData{}) } // getProfileProviderApex returns the name of the apex that provides a boot image profile, or an diff --git a/java/java.go b/java/java.go index dd0418894..0d90efc60 100644 --- a/java/java.go +++ b/java/java.go @@ -27,6 +27,7 @@ import ( "android/soong/bazel" "android/soong/bazel/cquery" "android/soong/remoteexec" + "android/soong/testing" "android/soong/ui/metrics/bp2build_metrics_proto" "github.com/google/blueprint" @@ -1228,10 +1229,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 af5633934..a8e6bfaff 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" @@ -253,6 +254,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 6e23a447f..cd7c73b5a 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" @@ -205,6 +206,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 1deedc731..930fcf54d 100644 --- a/sh/Android.bp +++ b/sh/Android.bp @@ -11,6 +11,7 @@ bootstrap_go_package { "soong-android", "soong-cc", "soong-java", + "soong-testing", "soong-tradefed", ], srcs: [ diff --git a/sh/sh_binary.go b/sh/sh_binary.go index 2e869f447..1bebc60be 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" @@ -452,6 +453,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; +}