Skip to content

Commit d2d0cb1

Browse files
author
Jon Poole
committed
Fix issue where we have duplicate packages in tests
1 parent 8c16dae commit d2d0cb1

File tree

4 files changed

+52
-19
lines changed

4 files changed

+52
-19
lines changed

build_defs/go.build_defs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -217,22 +217,28 @@ def go_stdlib(name:str, tags:list=CONFIG.GO.BUILD_TAGS, labels:list=[], visibili
217217
)
218218

219219

220-
def _pkg_sources(name: str, deps: list, test_only:bool):
220+
def _pkg_local_deps(name: str, deps: list, test_only:bool):
221221
"""
222-
This rule generates a list of go srcs for any rule in the deps list that is local to this package.
222+
Used by go_test to generate the deps for a non-external test lib.
223223

224-
This is how we avoid transitively depending on all sources for a target in order to compile non-external tests.
225-
Without this, we'd have to transitively pull in all third party sources for the rule which is very expensive,
226-
especially for remote execution.
224+
It works by finding any package-local dependencies, generating a filegroup that exports their sources, and filtering
225+
them out of the returned dependency list. The library then compiles against all sources it finds in the package
226+
directory, rather than just the srcs pass in via `srcs = []`.
227227
"""
228228
package_prefix = canonicalise(":all").removesuffix("all")
229-
return filegroup(
230-
name = name,
231-
tag = "pkg_srcs",
232-
exported_deps = [dep for dep in deps if canonicalise(dep).startswith(package_prefix)],
233-
requires = ["go_src"],
234-
test_only = test_only,
235-
)
229+
pkg_local_deps = [dep for dep in deps if canonicalise(dep).startswith(package_prefix)]
230+
deps = [dep for dep in deps if not canonicalise(dep).startswith(package_prefix)]
231+
232+
deps = deps + [
233+
filegroup(
234+
name = tag(name, "test_srcs"),
235+
tag = "pkg_srcs",
236+
exported_deps = pkg_local_deps,
237+
requires = ["go_src"],
238+
test_only = test_only,
239+
)
240+
]
241+
return deps
236242

237243
def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs:list=None, deps:list=[],
238244
visibility:list=None, test_only:bool&testonly=False, complete:bool=True,
@@ -307,7 +313,7 @@ def go_library(name:str, srcs:list, resources:list=[], asm_srcs:list=None, hdrs:
307313
# We could just depend on go_src for all our deps but that would mean bringing in srcs for targets outside this
308314
# package like third party sources which is especially slow on systems with slow syscall performance (macOS)
309315
if _all_srcs:
310-
deps += [_pkg_sources(name, deps, test_only)]
316+
deps = _pkg_local_deps(name, deps, test_only)
311317
if CONFIG.GO.STDLIB:
312318
deps += _stdlib()
313319

@@ -730,13 +736,12 @@ def go_test(name:str, srcs:list, resources:list=None, data:list|dict=None, deps:
730736
env (dict): Additional environment variables to set for the test
731737
"""
732738

733-
test_package = name + '_lib'
739+
test_package = name + '_lib' if external else None
734740
# Unfortunately we have to recompile this to build the test together with its library.
735741
lib_rule = go_library(
736742
name = f'_{name}#lib',
737743
srcs = srcs,
738744
resources = resources,
739-
package = test_package,
740745
deps = deps,
741746
_all_srcs=not external,
742747
labels = labels,
@@ -750,7 +755,7 @@ def go_test(name:str, srcs:list, resources:list=None, data:list|dict=None, deps:
750755
)
751756

752757
if cgo:
753-
archive_name = test_package + "_cgo"
758+
archive_name = f"_{name}#lib_cgo"
754759
lib_rule = merge_cgo_obj(
755760
name = name,
756761
tag='cgo',
@@ -762,12 +767,12 @@ def go_test(name:str, srcs:list, resources:list=None, data:list|dict=None, deps:
762767
package = archive_name,
763768
)
764769
else:
765-
archive_name = test_package
770+
archive_name = f"_{name}#lib"
766771

767772
import_config = build_rule(
768773
name=f'_{name}#lib_import_config',
769774
cmd = _write_import_config_cmd(archive_name, test_package),
770-
outs = [f'{test_package}.importconfig'],
775+
outs = [f'{name}_test_lib.importconfig'],
771776
visibility = visibility,
772777
test_only = True,
773778
labels = labels,
@@ -779,8 +784,8 @@ def go_test(name:str, srcs:list, resources:list=None, data:list|dict=None, deps:
779784
deps = deps,
780785
test_only = True,
781786
labels = labels,
782-
test_package = test_package,
783787
external = external,
788+
test_package = test_package,
784789
)
785790
modinfo = _go_modinfo(
786791
name = name,

test/normal_test/BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
subinclude("///go//build_defs:go")
2+
3+
go_library(
4+
name = "foo",
5+
srcs = ["foo.go"],
6+
)
7+
8+
go_test(
9+
name = "foo_test",
10+
srcs = ["foo_test.go"],
11+
deps = [":foo"],
12+
)

test/normal_test/foo.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package foo
2+
3+
func foo() string {
4+
return "foo"
5+
}

test/normal_test/foo_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package foo
2+
3+
import "testing"
4+
5+
func TestFoo(t *testing.T) {
6+
res := foo()
7+
8+
if res != "foo" {
9+
t.Fail()
10+
}
11+
}

0 commit comments

Comments
 (0)