130 lines
3.1 KiB
Go
130 lines
3.1 KiB
Go
package lockfile
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func readFile(t *testing.T, path string) string {
|
||
|
|
t.Helper()
|
||
|
|
data, err := os.ReadFile(path)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
return string(data)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMarshalDeterministic(t *testing.T) {
|
||
|
|
l1 := New()
|
||
|
|
l1.Sources["beta"] = &Source{
|
||
|
|
URL: "https://example.com/beta.git", Ref: "main", Rev: "cafe123",
|
||
|
|
Selection: Selection{Mode: ModeAll},
|
||
|
|
Renames: map[string]string{"zeta": "beta-zeta"},
|
||
|
|
Inventory: map[string][]string{TypeSkill: {"a", "zeta"}},
|
||
|
|
Warnings: []string{"a-warning", "b-warning"},
|
||
|
|
}
|
||
|
|
l1.Sources["alpha"] = &Source{
|
||
|
|
URL: "https://example.com/alpha.git", Ref: "v1.0", Rev: "abcd00",
|
||
|
|
Selection: Selection{Mode: ModeInclude, Include: []string{"a", "x"}},
|
||
|
|
}
|
||
|
|
|
||
|
|
l2 := New()
|
||
|
|
l2.Sources["alpha"] = l1.Sources["alpha"]
|
||
|
|
l2.Sources["beta"] = l1.Sources["beta"]
|
||
|
|
|
||
|
|
b1, err := Marshal(l1)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
b2, err := Marshal(l2)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if string(b1) != string(b2) {
|
||
|
|
t.Fatalf("marshal not deterministic:\n%s\n--- vs ---\n%s", b1, b2)
|
||
|
|
}
|
||
|
|
if b1[len(b1)-1] != '\n' {
|
||
|
|
t.Error("missing trailing newline")
|
||
|
|
}
|
||
|
|
|
||
|
|
l1.Save(filepath.Join(t.TempDir(), FileName))
|
||
|
|
b3, err := Marshal(l1)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if string(b1) != string(b3) {
|
||
|
|
t.Fatalf("save mutated already-canonical bytes:\n%s\n--- vs ---\n%s", b1, b3)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSaveCanonicalizesUnsortedInput(t *testing.T) {
|
||
|
|
l := New()
|
||
|
|
l.Sources["s"] = &Source{
|
||
|
|
URL: "u", Ref: "r", Rev: "rev",
|
||
|
|
Selection: Selection{Mode: ModeInclude, Include: []string{"z", "a"}},
|
||
|
|
Warnings: []string{"w2", "w1"},
|
||
|
|
Inventory: map[string][]string{TypeSkill: {"z", "a"}},
|
||
|
|
}
|
||
|
|
path := filepath.Join(t.TempDir(), FileName)
|
||
|
|
if err := l.Save(path); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
got, err := Load(path)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
src := got.Sources["s"]
|
||
|
|
wantInclude := []string{"a", "z"}
|
||
|
|
if !slicesEqual(src.Selection.Include, wantInclude) {
|
||
|
|
t.Errorf("include = %v, want %v", src.Selection.Include, wantInclude)
|
||
|
|
}
|
||
|
|
wantWarnings := []string{"w1", "w2"}
|
||
|
|
if !slicesEqual(src.Warnings, wantWarnings) {
|
||
|
|
t.Errorf("warnings = %v, want %v", src.Warnings, wantWarnings)
|
||
|
|
}
|
||
|
|
wantInv := []string{"a", "z"}
|
||
|
|
if !slicesEqual(src.Inventory[TypeSkill], wantInv) {
|
||
|
|
t.Errorf("inventory = %v, want %v", src.Inventory[TypeSkill], wantInv)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func slicesEqual(a, b []string) bool {
|
||
|
|
if len(a) != len(b) {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
for i := range a {
|
||
|
|
if a[i] != b[i] {
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoadRoundTrip(t *testing.T) {
|
||
|
|
dir := t.TempDir()
|
||
|
|
path := filepath.Join(dir, FileName)
|
||
|
|
l := New()
|
||
|
|
l.Sources["s"] = &Source{URL: "u", Ref: "r", Rev: "rev1", Selection: Selection{Mode: ModeAll}}
|
||
|
|
if err := l.Save(path); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
got, err := Load(path)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if got.Version != Version || got.Sources["s"].Rev != "rev1" {
|
||
|
|
t.Fatalf("round trip lost data: %+v", got)
|
||
|
|
}
|
||
|
|
|
||
|
|
if _, err := Load(filepath.Join(dir, "missing.json")); err != ErrNotExist {
|
||
|
|
t.Fatalf("want ErrNotExist, got %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
os.WriteFile(path, []byte(`{"version": 1, "sources": {}}`), 0o644)
|
||
|
|
if _, err := Load(path); err == nil {
|
||
|
|
t.Fatal("version 1 lockfile must be rejected")
|
||
|
|
}
|
||
|
|
}
|