blob: 972e86bc5de24e899787ade5ce30655af42801be [file] [log] [blame]
Ronald Braunsteina115e262024-04-09 18:07:38 -07001// Copyright 2024 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cc
16
17import (
18 "android/soong/android"
19 "android/soong/android/team_proto"
20 "log"
21 "strings"
22 "testing"
23
24 "github.com/google/blueprint"
25 "google.golang.org/protobuf/proto"
26)
27
28func TestTestOnlyProvider(t *testing.T) {
29 t.Parallel()
30 ctx := android.GroupFixturePreparers(
31 prepareForCcTest,
32 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
33 ctx.RegisterModuleType("cc_test_host", TestHostFactory)
34 }),
35 ).RunTestWithBp(t, `
36 // These should be test-only
37 cc_fuzz { name: "cc-fuzz" }
38 cc_test { name: "cc-test", gtest:false }
39 cc_benchmark { name: "cc-benchmark" }
40 cc_library { name: "cc-library-forced",
41 test_only: true }
42 cc_test_library {name: "cc-test-library", gtest: false}
43 cc_test_host {name: "cc-test-host", gtest: false}
44
45 // These should not be.
46 cc_genrule { name: "cc_genrule", cmd: "echo foo", out: ["out"] }
47 cc_library { name: "cc_library" }
48 cc_library { name: "cc_library_false", test_only: false }
49 cc_library_static { name: "cc_static" }
50 cc_library_shared { name: "cc_library_shared" }
51
52 cc_object { name: "cc-object" }
53 `)
54
55 // Visit all modules and ensure only the ones that should
56 // marked as test-only are marked as test-only.
57
58 actualTestOnly := []string{}
59 ctx.VisitAllModules(func(m blueprint.Module) {
60 if provider, ok := android.OtherModuleProvider(ctx.TestContext.OtherModuleProviderAdaptor(), m, android.TestOnlyProviderKey); ok {
61 if provider.TestOnly {
62 actualTestOnly = append(actualTestOnly, m.Name())
63 }
64 }
65 })
66 expectedTestOnlyModules := []string{
67 "cc-test",
68 "cc-library-forced",
69 "cc-fuzz",
70 "cc-benchmark",
71 "cc-test-library",
72 "cc-test-host",
73 }
74
75 notEqual, left, right := android.ListSetDifference(expectedTestOnlyModules, actualTestOnly)
76 if notEqual {
77 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
78 }
79}
80
Ronald Braunsteina115e262024-04-09 18:07:38 -070081func TestTestOnlyInTeamsProto(t *testing.T) {
82 t.Parallel()
83 ctx := android.GroupFixturePreparers(
84 android.PrepareForTestWithTeamBuildComponents,
85 prepareForCcTest,
86 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
87 ctx.RegisterParallelSingletonType("all_teams", android.AllTeamsFactory)
88 ctx.RegisterModuleType("cc_test_host", TestHostFactory)
89
90 }),
91 ).RunTestWithBp(t, `
92 package { default_team: "someteam"}
93
94 // These should be test-only
95 cc_fuzz { name: "cc-fuzz" }
96 cc_test { name: "cc-test", gtest:false }
97 cc_benchmark { name: "cc-benchmark" }
98 cc_library { name: "cc-library-forced",
99 test_only: true }
100 cc_test_library {name: "cc-test-library", gtest: false}
101 cc_test_host {name: "cc-test-host", gtest: false}
102
103 // These should not be.
104 cc_genrule { name: "cc_genrule", cmd: "echo foo", out: ["out"] }
105 cc_library { name: "cc_library" }
106 cc_library_static { name: "cc_static" }
107 cc_library_shared { name: "cc_library_shared" }
108
109 cc_object { name: "cc-object" }
110 team {
111 name: "someteam",
112 trendy_team_id: "cool_team",
113 }
114 `)
115
116 var teams *team_proto.AllTeams
117 teams = getTeamProtoOutput(t, ctx)
118
119 // map of module name -> trendy team name.
120 actualTrueModules := []string{}
121 for _, teamProto := range teams.Teams {
122 if Bool(teamProto.TestOnly) {
123 actualTrueModules = append(actualTrueModules, teamProto.GetTargetName())
124 }
125 }
126 expectedTestOnlyModules := []string{
127 "cc-test",
128 "cc-library-forced",
129 "cc-fuzz",
130 "cc-benchmark",
131 "cc-test-library",
132 "cc-test-host",
133 }
134
135 notEqual, left, right := android.ListSetDifference(expectedTestOnlyModules, actualTrueModules)
136 if notEqual {
137 t.Errorf("test-only: Expected but not found: %v, Found but not expected: %v", left, right)
138 }
139}
140
141// Don't allow setting test-only on things that are always tests or never tests.
142func TestInvalidTestOnlyTargets(t *testing.T) {
143 testCases := []string{
144 ` cc_test { name: "cc-test", test_only: true, gtest: false, srcs: ["foo.cc"], } `,
145 ` cc_binary { name: "cc-binary", test_only: true, srcs: ["foo.cc"], } `,
146 ` cc_test_library {name: "cc-test-library", test_only: true, gtest: false} `,
147 ` cc_test_host {name: "cc-test-host", test_only: true, gtest: false} `,
148 ` cc_defaults {name: "cc-defaults", test_only: true} `,
149 }
150
151 for i, bp := range testCases {
152 ctx := android.GroupFixturePreparers(
153 prepareForCcTest,
154 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
155 ctx.RegisterModuleType("cc_test_host", TestHostFactory)
156 })).
157 ExtendWithErrorHandler(android.FixtureIgnoreErrors).
158 RunTestWithBp(t, bp)
159 if len(ctx.Errs) == 0 {
160 t.Errorf("Expected err setting test_only in testcase #%d", i)
161 }
162 if len(ctx.Errs) > 1 {
163 t.Errorf("Too many errs: [%s] %v", bp, ctx.Errs)
164 }
165
166 if len(ctx.Errs) == 1 {
167 if !strings.Contains(ctx.Errs[0].Error(), "unrecognized property \"test_only\"") {
168 t.Errorf("ERR: %s bad bp: %s", ctx.Errs[0], bp)
169 }
170 }
171 }
172}
173
174func getTeamProtoOutput(t *testing.T, ctx *android.TestResult) *team_proto.AllTeams {
175 teams := new(team_proto.AllTeams)
176 config := ctx.SingletonForTests("all_teams")
177 allOutputs := config.AllOutputs()
178
179 protoPath := allOutputs[0]
180
181 out := config.MaybeOutput(protoPath)
182 outProto := []byte(android.ContentFromFileRuleForTests(t, ctx.TestContext, out))
183 if err := proto.Unmarshal(outProto, teams); err != nil {
184 log.Fatalln("Failed to parse teams proto:", err)
185 }
186 return teams
187}