~bigbes/ci-cacher

ref: 8851cb58dd2ccc5d3dd2cea8856d114fd69e1fff ci-cacher/internal/hash/hash_test.go -rw-r--r-- 3.4 KiB
8851cb58 — Eugene Blikh test.yml: install via install.sh, collapse cache_gomod to one dir download 11 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package hash

import (
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

// TestSingleFileMatchesSha256sumCutC116 asserts the central parity claim:
// Derive([f], 16) == `sha256sum f | cut -c1-16`. This is what the existing
// shell helper does (HASH=$(sha256sum docker/conformance.Dockerfile | cut -c1-16))
// and the new tool must produce the same key for the same input.
func TestSingleFileMatchesSha256sumCutC116(t *testing.T) {
	if _, err := exec.LookPath("sha256sum"); err != nil {
		t.Skip("sha256sum not on PATH; skipping shell parity check")
	}
	path := filepath.Join(t.TempDir(), "sample")
	if err := os.WriteFile(path, []byte("hello world\n"), 0o600); err != nil {
		t.Fatal(err)
	}
	out, err := exec.Command("sha256sum", path).Output()
	if err != nil {
		t.Fatalf("sha256sum: %v", err)
	}
	want := strings.Fields(string(out))[0][:16]

	got, err := Derive([]string{path}, 16)
	if err != nil {
		t.Fatalf("Derive: %v", err)
	}
	if got != want {
		t.Errorf("Derive=%q  want=%q", got, want)
	}
}

func TestDirHashIsStable(t *testing.T) {
	dir := t.TempDir()
	mustWrite := func(rel, body string) {
		p := filepath.Join(dir, rel)
		if err := os.MkdirAll(filepath.Dir(p), 0o700); err != nil {
			t.Fatal(err)
		}
		if err := os.WriteFile(p, []byte(body), 0o600); err != nil {
			t.Fatal(err)
		}
	}
	mustWrite("a/x", "x-body")
	mustWrite("b/y/z", "z-body")

	h1, err := Derive([]string{dir}, 32)
	if err != nil {
		t.Fatal(err)
	}
	h2, err := Derive([]string{dir}, 32)
	if err != nil {
		t.Fatal(err)
	}
	if h1 != h2 {
		t.Errorf("dir hash not stable: %q vs %q", h1, h2)
	}
}

func TestDirHashChangesOnContentChange(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, "f")
	_ = os.WriteFile(path, []byte("v1"), 0o600)
	h1, _ := Derive([]string{dir}, 32)
	_ = os.WriteFile(path, []byte("v2"), 0o600)
	h2, _ := Derive([]string{dir}, 32)
	if h1 == h2 {
		t.Error("dir hash unchanged after content change")
	}
}

func TestMultiPathCombines(t *testing.T) {
	dir := t.TempDir()
	a := filepath.Join(dir, "a")
	b := filepath.Join(dir, "b")
	_ = os.WriteFile(a, []byte("A"), 0o600)
	_ = os.WriteFile(b, []byte("B"), 0o600)

	ha, _ := Derive([]string{a}, 16)
	hab, _ := Derive([]string{a, b}, 16)
	hba, _ := Derive([]string{b, a}, 16)
	if ha == hab {
		t.Error("combining two paths produced same hash as single path")
	}
	if hab == hba {
		t.Error("order of --hash-from paths should matter")
	}
}

func TestApplyTemplateHashPlaceholder(t *testing.T) {
	got := ApplyTemplate("img/{hash}.tar.zst", "abcd1234", "linux", "amd64", false)
	if got != "img/abcd1234.tar.zst" {
		t.Errorf("ApplyTemplate placeholder = %q", got)
	}
}

func TestApplyTemplateNoPlaceholderAppends(t *testing.T) {
	got := ApplyTemplate("img/build.tar.zst", "abcd1234", "linux", "amd64", false)
	if got != "img/build-abcd1234.tar.zst" {
		t.Errorf("ApplyTemplate append = %q", got)
	}
}

func TestApplyTemplateArchSuffix(t *testing.T) {
	got := ApplyTemplate("img/build.tar.zst", "abcd", "linux", "amd64", true)
	if got != "img/build-abcd-linux-amd64.tar.zst" {
		t.Errorf("ApplyTemplate arch = %q", got)
	}
}

func TestApplyTemplateArchSuffixSimpleExt(t *testing.T) {
	got := ApplyTemplate("bin/cacher", "", "linux", "amd64", true)
	if got != "bin/cacher-linux-amd64" {
		t.Errorf("ApplyTemplate arch no-ext = %q", got)
	}
}

func TestDeriveRejectsEmpty(t *testing.T) {
	if _, err := Derive(nil, 16); err == nil {
		t.Error("expected error for empty paths")
	}
}