Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

156 lines
6.1 KiB
Go

package persistence
import (
"strings"
"testing"
"golang.org/x/text/unicode/norm"
)
// nfcDir / nfdDir are the precomposed and decomposed byte forms of the
// same accented repo path. They are derived in code with norm.NFC /
// norm.NFD from a single base so the two byte sequences are guaranteed
// distinct and deterministic — never dependent on how this source file
// happens to be saved. On macOS APFS a repo cloned into such a
// directory is reported in NFD by the OS, while the same path written
// into a config file or read on Linux is typically NFC; a snapshot
// keyed under one form must resolve to the same slot under the other.
//
// The non-ASCII characters in the base strings are written as explicit
// \u / \U escapes so this source file stays pure-ASCII.
var (
repoDirBase = "/home/dev/café/repo" // .../café/repo
nfcDir = norm.NFC.String(repoDirBase)
nfdDir = norm.NFD.String(repoDirBase)
)
const (
cjkBranch = "機能/日本語" // 機能/日本語
cyrBranch = "функция-ветка" // функция-ветка
asciiPath = "/home/dev/plain/repo"
asciiBr = "feat/some-branch"
commitHash = "0123456789abcdef0123456789abcdef01234567"
)
// TestCacheKey_NFCvsNFDPathSameSlot is the core round-trip guarantee:
// the same repo path supplied in decomposed and precomposed Unicode
// forms must hash to one snapshot slot. Without the NFC fold in
// CacheKey the two byte sequences hash differently and the daemon
// loses its cache across an OS / form boundary.
func TestCacheKey_NFCvsNFDPathSameSlot(t *testing.T) {
if nfcDir == nfdDir {
t.Fatal("test fixture invalid: NFC and NFD repo paths are byte-identical")
}
keyNFC := CacheKey(nfcDir, "main", commitHash)
keyNFD := CacheKey(nfdDir, "main", commitHash)
if keyNFC != keyNFD {
t.Fatalf("CacheKey not normalisation-stable for repo path:\n NFC -> %q\n NFD -> %q", keyNFC, keyNFD)
}
}
// TestCacheKey_NFCvsNFDBranchSameSlot guards the branch half of the
// key: a non-ASCII branch name in two Unicode forms must land in one
// slot, so the daemon does not split a single branch's snapshot in two.
func TestCacheKey_NFCvsNFDBranchSameSlot(t *testing.T) {
branchNFD := norm.NFD.String(cjkBranch)
branchNFC := norm.NFC.String(cjkBranch)
keyNFD := CacheKey(asciiPath, branchNFD, commitHash)
keyNFC := CacheKey(asciiPath, branchNFC, commitHash)
if keyNFD != keyNFC {
t.Fatalf("CacheKey not normalisation-stable for branch:\n NFD -> %q\n NFC -> %q", keyNFD, keyNFC)
}
}
// TestCacheKey_DistinctReposDistinctSlots confirms the fold does not
// over-collapse: two genuinely different non-ASCII repo paths must
// still get distinct slots.
func TestCacheKey_DistinctReposDistinctSlots(t *testing.T) {
a := CacheKey(nfcDir, "main", commitHash)
b := CacheKey(asciiPath, "main", commitHash)
if a == b {
t.Fatalf("CacheKey collided two different repos onto slot %q", a)
}
}
// TestCacheKey_DistinctBranchesDistinctSlots confirms two different
// non-ASCII branch names on the same repo do not collide — the
// collision-safety hash inside refSlug must survive normalisation.
func TestCacheKey_DistinctBranchesDistinctSlots(t *testing.T) {
a := CacheKey(asciiPath, cjkBranch, commitHash)
b := CacheKey(asciiPath, cyrBranch, commitHash)
if a == b {
t.Fatalf("CacheKey collided two different branches onto slot %q", a)
}
}
// TestCacheKey_FilesystemSafe checks the produced key is usable as a
// directory name: no path separators, no NUL, non-empty — true even
// when the branch is entirely non-ASCII (refSlug replaces every such
// rune, leaving the hash suffix to carry identity).
func TestCacheKey_FilesystemSafe(t *testing.T) {
for _, branch := range []string{cjkBranch, cyrBranch, "main", ""} {
key := CacheKey(nfdDir, branch, commitHash)
if key == "" {
t.Fatalf("CacheKey returned empty string for branch %q", branch)
}
if strings.ContainsAny(key, "/\\\x00") {
t.Fatalf("CacheKey %q for branch %q contains a path-unsafe byte", key, branch)
}
}
}
// TestCacheKey_ASCIIUnchangedByFold pins that the NFC fold is a no-op
// for the common all-ASCII case — the keys for ASCII inputs must not
// shift, so existing on-disk snapshot directories stay valid.
func TestCacheKey_ASCIIUnchangedByFold(t *testing.T) {
// Recomputed twice must be stable, and an ASCII path/branch must
// survive the fold byte-for-byte (the slug prefix is visible in
// the key, so a regression here would change the directory name).
key1 := CacheKey(asciiPath, asciiBr, commitHash)
key2 := CacheKey(asciiPath, asciiBr, commitHash)
if key1 != key2 {
t.Fatalf("CacheKey not deterministic for ASCII input: %q vs %q", key1, key2)
}
if !strings.Contains(key1, "feat-some-branch") {
t.Fatalf("CacheKey %q lost its readable ASCII branch slug", key1)
}
}
// TestCacheKey_DetachedHeadFallsBackToCommit checks the detached-HEAD
// path still works once the fold is in place: an empty branch keys by
// commit hash.
func TestCacheKey_DetachedHeadFallsBackToCommit(t *testing.T) {
withBranch := CacheKey(asciiPath, "main", commitHash)
detached := CacheKey(asciiPath, "", commitHash)
headLiteral := CacheKey(asciiPath, "HEAD", commitHash)
if detached == withBranch {
t.Fatal("detached-HEAD key collided with a real branch key")
}
if detached != headLiteral {
t.Fatalf("empty branch and literal HEAD must key alike: %q vs %q", detached, headLiteral)
}
}
// TestRepoCacheKey_NFCvsNFDSameSlot mirrors the CacheKey round-trip
// guarantee for the commit-independent feedback key.
func TestRepoCacheKey_NFCvsNFDSameSlot(t *testing.T) {
if nfcDir == nfdDir {
t.Fatal("test fixture invalid: NFC and NFD repo paths are byte-identical")
}
keyNFC := RepoCacheKey(nfcDir)
keyNFD := RepoCacheKey(nfdDir)
if keyNFC != keyNFD {
t.Fatalf("RepoCacheKey not normalisation-stable:\n NFC -> %q\n NFD -> %q", keyNFC, keyNFD)
}
}
// TestRepoCacheKey_DistinctReposDistinctSlots confirms the feedback
// key does not over-collapse distinct non-ASCII repos.
func TestRepoCacheKey_DistinctReposDistinctSlots(t *testing.T) {
a := RepoCacheKey(nfcDir)
b := RepoCacheKey(asciiPath)
if a == b {
t.Fatalf("RepoCacheKey collided two different repos onto slot %q", a)
}
}