1# Copyright 2023 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://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, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14"""Tests for the pw_build.gn_target module.""" 15 16import unittest 17 18from pw_build.bazel_query import BazelRule 19from pw_build.gn_target import GnTarget 20from pw_build.gn_utils import GnLabel, MalformedGnError 21 22 23class TestGnTarget(unittest.TestCase): 24 """Tests for gn_target.GnTarget.""" 25 26 def setUp(self): 27 self.rule = BazelRule('//my-package:my-target', 'cc_library') 28 29 def test_from_bazel_rule_label(self): 30 """Tests the GN target name and package derived from a Bazel rule.""" 31 target = GnTarget('$build', '$src', bazel=self.rule) 32 self.assertEqual(target.name(), 'my-target') 33 self.assertEqual(target.package(), 'my-package') 34 35 def test_from_bazel_rule_type_source_set(self): 36 """Tests creating a `pw_source_set` from a Bazel rule.""" 37 target = GnTarget('$build', '$src', bazel=self.rule) 38 self.assertEqual(target.type(), 'pw_source_set') 39 40 def test_from_bazel_rule_type_static_lib(self): 41 """Tests creating a `pw_static_library` from a Bazel rule.""" 42 self.rule.set_attr('linkstatic', True) 43 target = GnTarget('$build', '$src', bazel=self.rule) 44 self.assertEqual(target.type(), 'pw_static_library') 45 46 def test_from_bazel_rule_type_invalid(self): 47 """Tests creating an invalid type from a Bazel rule.""" 48 with self.assertRaises(MalformedGnError): 49 rule = BazelRule('//my-package:my-target', 'custom_type') 50 GnTarget('$build', '$src', bazel=rule) 51 52 def test_from_bazel_rule_visibility(self): 53 """Tests getting the GN visibility from a Bazel rule.""" 54 self.rule.set_attr( 55 'visibility', 56 [ 57 '//foo:__subpackages__', 58 '//foo/bar:__pkg__', 59 '//baz:__pkg__', 60 ], 61 ) 62 target = GnTarget('$build', '$src', bazel=self.rule) 63 self.assertEqual( 64 {str(scope) for scope in target.visibility}, 65 { 66 '$build/my-package:*', 67 '$build/foo/*', 68 '$build/baz:*', 69 }, 70 ) 71 72 def test_from_bazel_rule_visibility_public(self): 73 """Tests that 'public' overrides any other visibility""" 74 self.rule.set_attr( 75 'visibility', 76 [ 77 '//visibility:private', 78 '//visibility:public', 79 ], 80 ) 81 target = GnTarget('$build', '$src', bazel=self.rule) 82 self.assertEqual({str(scope) for scope in target.visibility}, {'//*'}) 83 84 def test_from_bazel_rule_visibility_invalid(self): 85 """Tests that and invalid visibility raises an error.""" 86 self.rule.set_attr('visibility', ['invalid']) 87 with self.assertRaises(MalformedGnError): 88 GnTarget('$build', '$src', bazel=self.rule) 89 90 def test_from_bazel_rule_testonly_unset(self): 91 """Tests that omitting `testonly` defaults it to False.""" 92 target = GnTarget('$build', '$src', bazel=self.rule) 93 self.assertFalse(target.testonly) 94 95 def test_from_bazel_rule_testonly_false(self): 96 """Tests setting `testonly` to False.""" 97 self.rule.set_attr('testonly', False) 98 target = GnTarget('$build', '$src', bazel=self.rule) 99 self.assertFalse(target.testonly) 100 101 def test_from_bazel_rule_testonly_true(self): 102 """Tests setting `testonly` to True.""" 103 self.rule.set_attr('testonly', True) 104 target = GnTarget('$build', '$src', bazel=self.rule) 105 self.assertTrue(target.testonly) 106 107 def test_from_bazel_rule_public(self): 108 """Tests getting the GN public headers from a Bazel rule.""" 109 self.rule.set_attr('hdrs', ['//foo:bar.h', '//:baz.h']) 110 target = GnTarget('$build', '$src', bazel=self.rule) 111 self.assertEqual( 112 {str(path) for path in target.public}, 113 { 114 '$src/foo/bar.h', 115 '$src/baz.h', 116 }, 117 ) 118 119 def test_from_bazel_rule_sources(self): 120 """Tests getting the GN source files from a Bazel rule.""" 121 self.rule.set_attr('srcs', ['//foo:bar.cc', '//:baz.cc']) 122 target = GnTarget('$build', '$src', bazel=self.rule) 123 self.assertEqual( 124 {str(path) for path in target.sources}, 125 { 126 '$src/foo/bar.cc', 127 '$src/baz.cc', 128 }, 129 ) 130 131 def test_from_bazel_rule_inputs(self): 132 """Tests getting the GN input files from a Bazel rule.""" 133 self.rule.set_attr( 134 'additional_linker_inputs', ['//foo:bar.data', '//:baz.data'] 135 ) 136 target = GnTarget('$build', '$src', bazel=self.rule) 137 self.assertEqual( 138 {str(path) for path in target.inputs}, 139 { 140 '$src/foo/bar.data', 141 '$src/baz.data', 142 }, 143 ) 144 145 def test_from_bazel_rule_include_dirs(self): 146 """Tests getting the GN include directories from a Bazel rule.""" 147 self.rule.set_attr('includes', ['//foo']) 148 target = GnTarget('$build', '$src', bazel=self.rule) 149 self.assertEqual( 150 set(target.config.get('include_dirs')), 151 { 152 '$src', 153 '$src/foo', 154 }, 155 ) 156 157 def test_from_bazel_rule_configs(self): 158 """Tests getting the GN config flags from a Bazel rule.""" 159 self.rule.set_attr('defines', ['KEY1=VAL1']) 160 self.rule.set_attr('copts', ['-frobinator']) 161 self.rule.set_attr('linkopts', ['-fizzbuzzer']) 162 self.rule.set_attr('local_defines', ['KEY2=VAL2', 'KEY3=VAL3']) 163 target = GnTarget('$build', '$src', bazel=self.rule) 164 self.assertEqual( 165 set(target.config.get('public_defines')), {'KEY1=VAL1'} 166 ) 167 self.assertEqual(set(target.config.get('cflags')), {'-frobinator'}) 168 self.assertEqual(set(target.config.get('ldflags')), {'-fizzbuzzer'}) 169 self.assertEqual( 170 set(target.config.get('defines')), {'KEY2=VAL2', 'KEY3=VAL3'} 171 ) 172 173 def test_from_bazel_rule_deps(self): 174 """Tests getting the GN dependencies from a Bazel rule.""" 175 self.rule.set_attr( 176 'deps', ['//my-package:foo', '@com_corp_project//bar'] 177 ) 178 self.rule.set_attr( 179 'implementation_deps', 180 [ 181 '//other-pkg/subdir', 182 '@com_corp_project//:top-level', 183 ], 184 ) 185 target = GnTarget('$build', '$src', bazel=self.rule) 186 self.assertEqual( 187 {str(label) for label in target.public_deps}, 188 { 189 '$build/my-package:foo', 190 '$repo/bar', 191 }, 192 ) 193 self.assertEqual( 194 {str(label) for label in target.deps}, 195 { 196 '$build/other-pkg/subdir', 197 '$repo:top-level', 198 }, 199 ) 200 201 def test_make_relative_adjacent(self): 202 """Tests rebasing labels for a target.""" 203 target = GnTarget('$build/pkg', '$src') 204 label = target.make_relative(GnLabel('$build/pkg:adjacent-config')) 205 self.assertEqual(label, ":adjacent-config") 206 207 def test_make_relative_absolute(self): 208 """Tests rebasing labels for a target.""" 209 target = GnTarget('$build/pkg', '$src') 210 label = target.make_relative(GnLabel('//absolute:config')) 211 self.assertEqual(label, "//absolute:config") 212 213 def test_make_relative_descend(self): 214 """Tests rebasing labels for a target.""" 215 target = GnTarget('$build/pkg', '$src') 216 label = target.make_relative(GnLabel('$build/pkg/relative:dep')) 217 self.assertEqual(label, "relative:dep") 218 219 def test_make_relative_ascend(self): 220 """Tests rebasing labels for a target.""" 221 target = GnTarget('$build/pkg', '$src') 222 label = target.make_relative(GnLabel('$build/dotdot/relative')) 223 self.assertEqual(label, "../dotdot/relative") 224 225 226if __name__ == '__main__': 227 unittest.main() 228