mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-27 02:26:21 +09:00
c3d771e23e
Keeps the interlocked pins current and reports what it could not move. Areas apply, gate and commit one at a time, so a dependency that breaks the build costs one commit rather than the whole pull request.
120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"golang.org/x/mod/modfile"
|
|
)
|
|
|
|
// The lockstep notes in go.mod are load-bearing prose: they are the only record
|
|
// of why the pairs exist. `go mod tidy` re-sorts requires and can leave a note
|
|
// stranded above the wrong line, which reads fine in a diff and is wrong.
|
|
func TestNoteAttached(t *testing.T) {
|
|
const attached = `module example.com/x
|
|
|
|
go 1.27.0
|
|
|
|
require (
|
|
// NOTE: modernc sqlite has a fragile dependency chain:
|
|
// https://github.com/juanfont/headscale/issues/2188
|
|
modernc.org/sqlite v1.52.0
|
|
pgregory.net/rapid v1.3.0
|
|
)
|
|
`
|
|
|
|
// The note is still in the file, but now documents the wrong module.
|
|
const detached = `module example.com/x
|
|
|
|
go 1.27.0
|
|
|
|
require (
|
|
// NOTE: modernc sqlite has a fragile dependency chain:
|
|
// https://github.com/juanfont/headscale/issues/2188
|
|
pgregory.net/rapid v1.3.0
|
|
|
|
modernc.org/sqlite v1.52.0
|
|
)
|
|
`
|
|
|
|
tests := []struct {
|
|
name string
|
|
content string
|
|
want bool
|
|
}{
|
|
{name: "attached", content: attached, want: true},
|
|
{name: "detached", content: detached, want: false},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
f, err := modfile.Parse("go.mod", []byte(test.content), nil)
|
|
if err != nil {
|
|
t.Fatalf("parsing fixture: %v", err)
|
|
}
|
|
|
|
if got := noteAttached(f, "modernc.org/sqlite", "issues/2188"); got != test.want {
|
|
t.Errorf("noteAttached = %v, want %v", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRequiredVersion(t *testing.T) {
|
|
const goMod = `module modernc.org/sqlite
|
|
|
|
go 1.25.0
|
|
|
|
require (
|
|
modernc.org/libc v1.75.6
|
|
modernc.org/mathutil v1.7.1
|
|
)
|
|
`
|
|
|
|
f, err := modfile.Parse("go.mod", []byte(goMod), nil)
|
|
if err != nil {
|
|
t.Fatalf("parsing fixture: %v", err)
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
dep string
|
|
want string
|
|
found bool
|
|
}{
|
|
{name: "present", dep: "modernc.org/libc", want: "v1.75.6", found: true},
|
|
{name: "absent", dep: "gvisor.dev/gvisor", found: false},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
got, ok := requiredVersion(f, test.dep)
|
|
if ok != test.found {
|
|
t.Fatalf("requiredVersion found = %v, want %v", ok, test.found)
|
|
}
|
|
|
|
if got != test.want {
|
|
t.Errorf("requiredVersion = %q, want %q", got, test.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// The repository's own go.mod is the case that actually matters: the notes must
|
|
// survive whatever the last tidy did to the require blocks.
|
|
func TestRepoLockstepNotesAttached(t *testing.T) {
|
|
b, err := modfile.Parse("../../go.mod", mustRead(t, "../../go.mod"), nil)
|
|
if err != nil {
|
|
t.Fatalf("parsing go.mod: %v", err)
|
|
}
|
|
|
|
for _, note := range lockstepNotes {
|
|
if !noteAttached(b, note.module, note.needle) {
|
|
t.Errorf("go.mod: note %q is not attached to %s", note.needle, note.module)
|
|
}
|
|
}
|
|
|
|
if len(b.Tool) == 0 {
|
|
t.Error("go.mod: tool block is missing")
|
|
}
|
|
}
|