• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 18822648545

26 Oct 2025 07:24PM UTC coverage: 79.831% (-0.4%) from 80.28%
18822648545

Pull #22809

github

web-flow
Merge 9401c4830 into 170094e99
Pull Request #22809: golang: fix Go SDK version check for coverage experiment

0 of 1 new or added line in 1 file covered. (0.0%)

439 existing lines in 25 files now uncovered.

77436 of 97000 relevant lines covered (79.83%)

3.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.67
/src/python/pants/backend/go/util_rules/assembly_integration_test.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
import os.path
1✔
7
import platform
1✔
8
import subprocess
1✔
9
from pathlib import Path
1✔
10
from textwrap import dedent
1✔
11

12
import pytest
1✔
13

14
from pants.backend.go import target_type_rules
1✔
15
from pants.backend.go.goals import package_binary
1✔
16
from pants.backend.go.goals.package_binary import GoBinaryFieldSet
1✔
17
from pants.backend.go.target_types import GoBinaryTarget, GoModTarget, GoPackageTarget
1✔
18
from pants.backend.go.util_rules import (
1✔
19
    assembly,
20
    build_pkg,
21
    build_pkg_target,
22
    first_party_pkg,
23
    go_mod,
24
    import_analysis,
25
    link,
26
    sdk,
27
    third_party_pkg,
28
)
29
from pants.backend.go.util_rules.build_opts import GoBuildOptions
1✔
30
from pants.backend.go.util_rules.build_pkg import BuildGoPackageRequest, FallibleBuiltGoPackage
1✔
31
from pants.core.goals.package import BuiltPackage
1✔
32
from pants.engine.addresses import Address
1✔
33
from pants.engine.rules import QueryRule
1✔
34
from pants.engine.target import Target
1✔
35
from pants.testutil.rule_runner import RuleRunner
1✔
36
from pants.util.contextutil import temporary_dir
1✔
37

38

39
@pytest.fixture()
1✔
40
def rule_runner() -> RuleRunner:
1✔
41
    rule_runner = RuleRunner(
1✔
42
        rules=[
43
            *assembly.rules(),
44
            *import_analysis.rules(),
45
            *package_binary.rules(),
46
            *build_pkg.rules(),
47
            *build_pkg_target.rules(),
48
            *first_party_pkg.rules(),
49
            *go_mod.rules(),
50
            *link.rules(),
51
            *target_type_rules.rules(),
52
            *third_party_pkg.rules(),
53
            *sdk.rules(),
54
            QueryRule(BuiltPackage, (GoBinaryFieldSet,)),
55
            QueryRule(FallibleBuiltGoPackage, (BuildGoPackageRequest,)),
56
        ],
57
        target_types=[
58
            GoBinaryTarget,
59
            GoModTarget,
60
            GoPackageTarget,
61
        ],
62
    )
63
    rule_runner.set_options([], env_inherit={"PATH"})
1✔
64
    return rule_runner
1✔
65

66

67
def build_package(rule_runner: RuleRunner, binary_target: Target) -> BuiltPackage:
1✔
68
    field_set = GoBinaryFieldSet.create(binary_target)
1✔
69
    result = rule_runner.request(BuiltPackage, [field_set])
1✔
UNCOV
70
    rule_runner.write_digest(result.digest)
×
UNCOV
71
    return result
×
72

73

74
def test_build_package_with_assembly(rule_runner: RuleRunner) -> None:
1✔
75
    rule_runner.write_files(
1✔
76
        {
77
            "go.mod": dedent(
78
                """\
79
                module example.com/assembly
80
                go 1.17
81
                """
82
            ),
83
            "main.go": dedent(
84
                """\
85
                package main
86

87
                import "fmt"
88

89
                func main() {
90
                    fmt.Println(add(1, 2))
91
                }
92
                """
93
            ),
94
            "add_amd64.go": "package main\nfunc add(x, y int64) int64",
95
            "add_arm64.go": "package main\nfunc add(x, y int64) int64",
96
            # Based on https://davidwong.fr/goasm/add.
97
            "add_amd64.s": dedent(
98
                """\
99
                TEXT ·add(SB),$0-24
100
                    MOVQ  x+0(FP), BX
101
                    MOVQ  y+8(FP), BP
102

103
                    ADDQ  BP, BX
104
                    MOVQ  BX, ret+16(FP)
105
                    RET
106
                """
107
            ),
108
            # Based on combining https://davidwong.fr/goasm/add and `go tool compile -S` to get
109
            # ARM instructions.
110
            "add_arm64.s": dedent(
111
                """\
112
                TEXT ·add(SB),$0-24
113
                    MOVD  x+0(FP), R0
114
                    MOVD  y+8(FP), R1
115

116
                    ADD   R1, R0, R0
117
                    MOVD  R0, ret+16(FP)
118
                    RET
119
                """
120
            ),
121
            "BUILD": dedent(
122
                """\
123
                go_mod(name="mod")
124
                go_package(name="pkg", sources=["*.go", "*.s"])
125
                go_binary(name="bin")
126
                """
127
            ),
128
        }
129
    )
130

131
    binary_tgt = rule_runner.get_target(Address("", target_name="bin"))
1✔
132
    built_package = build_package(rule_runner, binary_tgt)
1✔
UNCOV
133
    assert len(built_package.artifacts) == 1
×
UNCOV
134
    assert built_package.artifacts[0].relpath == "bin"
×
135

UNCOV
136
    result = subprocess.run([os.path.join(rule_runner.build_root, "bin")], stdout=subprocess.PIPE)
×
UNCOV
137
    assert result.returncode == 0
×
UNCOV
138
    assert result.stdout == b"3\n"
×
139

140

141
def test_build_invalid_package(rule_runner: RuleRunner) -> None:
1✔
142
    request = BuildGoPackageRequest(
1✔
143
        import_path="example.com/assembly",
144
        pkg_name="main",
145
        dir_path="",
146
        build_opts=GoBuildOptions(),
147
        go_files=("add_amd64.go", "add_arm64.go"),
148
        digest=rule_runner.make_snapshot(
149
            {
150
                "add_amd64.go": "package main\nfunc add(x, y int64) int64",
151
                "add_arm64.go": "package main\nfunc add(x, y int64) int64",
152
                "add_amd64.s": "INVALID!!!",
153
                "add_arm64.s": "INVALID!!!",
154
            }
155
        ).digest,
156
        s_files=("add_amd64.s", "add_arm64.s"),
157
        direct_dependencies=(),
158
        minimum_go_version=None,
159
    )
160
    result = rule_runner.request(FallibleBuiltGoPackage, [request])
1✔
UNCOV
161
    assert result.output is None
×
UNCOV
162
    assert result.exit_code == 1
×
UNCOV
163
    assert result.stdout == "add_amd64.s:1: unexpected EOF\nasm: assembly of add_amd64.s failed\n"
×
164

165

166
def test_build_package_with_prebuilt_object_files(rule_runner: RuleRunner) -> None:
1✔
167
    # Compile helper assembly into a prebuilt .syso object file.
168
    machine = platform.uname().machine
1✔
169
    if machine == "x86_64":
1✔
170
        assembly_text = dedent(
1✔
171
            """\
172
            /* Apple still insists on underscore prefixes for C function names. */
173
            #if defined(__APPLE__)
174
            #define EXT(s) _##s
175
            #else
176
            #define EXT(s) s
177
            #endif
178
            .align 4
179
            .globl EXT(fortytwo)
180
            EXT(fortytwo):
181
              movl $42, %eax
182
              ret
183
            """
184
        )
185
    elif machine == "arm64":
×
186
        assembly_text = dedent(
×
187
            """\
188
            /* Apple still insists on underscore prefixes for C function names. */
189
            #if defined(__APPLE__)
190
            #define EXT(s) _##s
191
            #else
192
            #define EXT(s) s
193
            #endif
194
            .align 4
195
            .globl EXT(fortytwo)
196
            EXT(fortytwo):
197
              mov x0, #42
198
              ret
199
        """
200
        )
201
    else:
202
        pytest.skip(f"Unsupported architecture for test: {machine}")
×
203

204
    with temporary_dir() as tempdir:
1✔
205
        source_path = Path(tempdir) / "fortytwo.S"
1✔
206
        source_path.write_text(assembly_text)
1✔
207
        output_path = source_path.with_suffix(".o")
1✔
208
        subprocess.check_call(["gcc", "-c", "-o", str(output_path), str(source_path)])
1✔
209
        object_bytes = output_path.read_bytes()
1✔
210

211
    rule_runner.write_files(
1✔
212
        {
213
            "go.mod": dedent(
214
                """\
215
                module example.com/syso_files
216
                go 1.17
217
                """
218
            ),
219
            "main.go": dedent(
220
                """\
221
                package main
222

223
                import "fmt"
224

225
                func main() {
226
                    fmt.Println(value())
227
                }
228
                """
229
            ),
230
            "value.go": dedent(
231
                """\
232
                package main
233
                // extern int fortytwo();
234
                import "C"
235
                func value() int {
236
                    return int(C.fortytwo())
237
                }
238
                """
239
            ),
240
            "value.syso": object_bytes,
241
            "BUILD": dedent(
242
                """\
243
                go_mod(name="mod")
244
                go_package(name="pkg", sources=["*.go", "*.syso"])
245
                go_binary(name="bin")
246
                """
247
            ),
248
        }
249
    )
250

251
    binary_tgt = rule_runner.get_target(Address("", target_name="bin"))
1✔
252
    built_package = build_package(rule_runner, binary_tgt)
1✔
UNCOV
253
    assert len(built_package.artifacts) == 1
×
UNCOV
254
    assert built_package.artifacts[0].relpath == "bin"
×
255

UNCOV
256
    result = subprocess.run([os.path.join(rule_runner.build_root, "bin")], stdout=subprocess.PIPE)
×
UNCOV
257
    assert result.returncode == 0
×
UNCOV
258
    assert result.stdout == b"42\n"
×
259

260

261
def test_build_package_using_api_metdata(rule_runner: RuleRunner) -> None:
1✔
262
    rule_runner.write_files(
1✔
263
        {
264
            "go.mod": dedent(
265
                """\
266
                module example.com/assembly
267
                go 1.17
268
                """
269
            ),
270
            "main.go": dedent(
271
                """\
272
                package main
273

274
                import "fmt"
275

276
                const MagicValueToBeUsedByAssembly int = 42
277

278
                func main() {
279
                    fmt.Println(add_magic(10))
280
                }
281
                """
282
            ),
283
            "add_amd64.go": "package main\nfunc add_magic(x int64) int64",
284
            "add_arm64.go": "package main\nfunc add_magic(x int64) int64",
285
            "add_amd64.s": dedent(
286
                """\
287
                #include "textflag.h"  // for NOSPLIT
288
                #include "go_asm.h"  // for const_MagicValueToBeUsedByAssembly
289
                TEXT ·add_magic(SB),NOSPLIT,$0
290
                    MOVQ  x+0(FP), BX
291
                    MOVQ  $const_MagicValueToBeUsedByAssembly, BP
292

293
                    ADDQ  BP, BX
294
                    MOVQ  BX, ret+8(FP)
295
                    RET
296
                """
297
            ),
298
            "add_arm64.s": dedent(
299
                """\
300
                #include "textflag.h"  // for NOSPLIT
301
                #include "go_asm.h"  // for const_MagicValueToBeUsedByAssembly
302
                TEXT ·add_magic(SB),NOSPLIT,$0
303
                    MOVD  x+0(FP), R0
304
                    MOVD  $const_MagicValueToBeUsedByAssembly, R1
305

306
                    ADD   R1, R0, R0
307
                    MOVD  R0, ret+8(FP)
308
                    RET
309
                """
310
            ),
311
            "BUILD": dedent(
312
                """\
313
                go_mod(name="mod")
314
                go_package(name="pkg", sources=["*.go", "*.s"])
315
                go_binary(name="bin")
316
                """
317
            ),
318
        }
319
    )
320

321
    binary_tgt = rule_runner.get_target(Address("", target_name="bin"))
1✔
322
    built_package = build_package(rule_runner, binary_tgt)
1✔
UNCOV
323
    assert len(built_package.artifacts) == 1
×
UNCOV
324
    assert built_package.artifacts[0].relpath == "bin"
×
325

UNCOV
326
    result = subprocess.run([os.path.join(rule_runner.build_root, "bin")], stdout=subprocess.PIPE)
×
UNCOV
327
    assert result.returncode == 0
×
UNCOV
328
    assert result.stdout == b"52\n"  # should be 10 + the 42 "magic" value
×
329

330

331
def test_build_package_with_copied_header(rule_runner: RuleRunner) -> None:
1✔
332
    rule_runner.write_files(
1✔
333
        {
334
            "go.mod": dedent(
335
                """\
336
                module example.com/assembly
337
                go 1.17
338
                """
339
            ),
340
            "constant_linux.h": dedent(
341
                """
342
                #define MAGIC_VALUE 42
343
                """
344
            ),
345
            "constant_darwin.h": dedent(
346
                """
347
                #define MAGIC_VALUE 42
348
                """
349
            ),
350
            "main.go": dedent(
351
                """\
352
                package main
353

354
                import "fmt"
355

356
                func main() {
357
                    fmt.Println(add_magic(10))
358
                }
359
                """
360
            ),
361
            "add_amd64.go": "package main\nfunc add_magic(x int64) int64",
362
            "add_arm64.go": "package main\nfunc add_magic(x int64) int64",
363
            "add_amd64.s": dedent(
364
                """\
365
                #include "textflag.h"  // for NOSPLIT
366
                #include "constant_GOOS.h"  // for MAGIC_VALUE
367
                TEXT ·add_magic(SB),NOSPLIT,$0
368
                    MOVQ  x+0(FP), BX
369
                    MOVQ  $MAGIC_VALUE, BP
370

371
                    ADDQ  BP, BX
372
                    MOVQ  BX, ret+8(FP)
373
                    RET
374
                """
375
            ),
376
            "add_arm64.s": dedent(
377
                """\
378
                #include "textflag.h"  // for NOSPLIT
379
                #include "constant_GOOS.h"  // for MAGIC_VALUE
380
                TEXT ·add_magic(SB),NOSPLIT,$0
381
                    MOVD  x+0(FP), R0
382
                    MOVD  $MAGIC_VALUE, R1
383

384
                    ADD   R1, R0, R0
385
                    MOVD  R0, ret+8(FP)
386
                    RET
387
                """
388
            ),
389
            "BUILD": dedent(
390
                """\
391
                go_mod(name="mod")
392
                go_package(name="pkg", sources=["*.go", "*.s", "*.h"])
393
                go_binary(name="bin")
394
                """
395
            ),
396
        }
397
    )
398

399
    binary_tgt = rule_runner.get_target(Address("", target_name="bin"))
1✔
400
    built_package = build_package(rule_runner, binary_tgt)
1✔
UNCOV
401
    assert len(built_package.artifacts) == 1
×
UNCOV
402
    assert built_package.artifacts[0].relpath == "bin"
×
403

UNCOV
404
    result = subprocess.run([os.path.join(rule_runner.build_root, "bin")], stdout=subprocess.PIPE)
×
UNCOV
405
    assert result.returncode == 0
×
UNCOV
406
    assert result.stdout == b"52\n"  # should be 10 + the 42 "magic" value
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc