verstak/internal/core/sync/blob_test.go

208 lines
4.8 KiB
Go

package sync
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestBlobDir(t *testing.T) {
got := BlobDir("/tmp/vault")
want := "/tmp/vault/.verstak/blobs"
if got != want {
t.Errorf("BlobDir() = %q, want %q", got, want)
}
}
func TestBlobPath(t *testing.T) {
sha := "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
got := BlobPath("/tmp/blobs", sha)
want := "/tmp/blobs/ab/cd/abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"
if got != want {
t.Errorf("BlobPath() = %q, want %q", got, want)
}
}
func TestHashBytes(t *testing.T) {
got := HashBytes([]byte("hello"))
// SHA-256 of "hello"
want := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
if got != want {
t.Errorf("HashBytes() = %q, want %q", got, want)
}
gotEmpty := HashBytes([]byte{})
wantEmpty := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
if gotEmpty != wantEmpty {
t.Errorf("HashBytes(empty) = %q, want %q", gotEmpty, wantEmpty)
}
}
func TestHashFile(t *testing.T) {
dir := t.TempDir()
// Write a test file.
path := filepath.Join(dir, "test.txt")
if err := os.WriteFile(path, []byte("hello"), 0644); err != nil {
t.Fatal(err)
}
got, err := HashFile(path)
if err != nil {
t.Fatal(err)
}
want := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
if got != want {
t.Errorf("HashFile() = %q, want %q", got, want)
}
// Hash a non-existent file.
_, err = HashFile(filepath.Join(dir, "nonexistent"))
if err == nil {
t.Error("HashFile() expected error for non-existent file")
}
}
func TestStoreBlob(t *testing.T) {
dir := t.TempDir()
blobsDir := BlobDir(dir)
srcDir := t.TempDir()
// Write source file.
srcPath := filepath.Join(srcDir, "data.bin")
if err := os.WriteFile(srcPath, []byte("hello world"), 0644); err != nil {
t.Fatal(err)
}
// Store the blob.
sha, err := StoreBlob(blobsDir, srcPath)
if err != nil {
t.Fatal(err)
}
wantSHA := "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
if sha != wantSHA {
t.Errorf("StoreBlob() sha = %q, want %q", sha, wantSHA)
}
// Verify file exists at the expected path.
blobPath := BlobPath(blobsDir, sha)
if _, err := os.Stat(blobPath); err != nil {
t.Errorf("blob file not created at %s: %v", blobPath, err)
}
// Verify content.
data, err := os.ReadFile(blobPath)
if err != nil {
t.Fatal(err)
}
if string(data) != "hello world" {
t.Errorf("blob content = %q, want %q", string(data), "hello world")
}
}
func TestStoreBlob_Deduplicate(t *testing.T) {
dir := t.TempDir()
blobsDir := BlobDir(dir)
srcDir := t.TempDir()
// Create two files with the same content.
src1 := filepath.Join(srcDir, "a.txt")
src2 := filepath.Join(srcDir, "b.txt")
if err := os.WriteFile(src1, []byte("same content"), 0644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(src2, []byte("same content"), 0644); err != nil {
t.Fatal(err)
}
sha1, err := StoreBlob(blobsDir, src1)
if err != nil {
t.Fatal(err)
}
sha2, err := StoreBlob(blobsDir, src2)
if err != nil {
t.Fatal(err)
}
if sha1 != sha2 {
t.Errorf("StoreBlob() deduplication failed: sha1=%q sha2=%q", sha1, sha2)
}
// Count files in the blob store — should only be 1.
var count int
filepath.Walk(blobsDir, func(p string, fi os.FileInfo, err error) error {
if err == nil && !fi.IsDir() {
count++
}
return nil
})
if count != 1 {
t.Errorf("expected 1 blob file, got %d", count)
}
}
func TestStoreBlob_LargeFile(t *testing.T) {
dir := t.TempDir()
blobsDir := BlobDir(dir)
srcDir := t.TempDir()
// Create a 1MB file.
srcPath := filepath.Join(srcDir, "large.bin")
data := make([]byte, 1024*1024)
for i := range data {
data[i] = byte(i % 256)
}
if err := os.WriteFile(srcPath, data, 0644); err != nil {
t.Fatal(err)
}
sha, err := StoreBlob(blobsDir, srcPath)
if err != nil {
t.Fatal(err)
}
if len(sha) != 64 {
t.Errorf("expected 64-char SHA-256, got %d chars", len(sha))
}
blobPath := BlobPath(blobsDir, sha)
stored, err := os.ReadFile(blobPath)
if err != nil {
t.Fatal(err)
}
if len(stored) != len(data) {
t.Errorf("stored blob size = %d, want %d", len(stored), len(data))
}
}
func TestReadBlob(t *testing.T) {
dir := t.TempDir()
blobsDir := BlobDir(dir)
srcDir := t.TempDir()
srcPath := filepath.Join(srcDir, "data.txt")
if err := os.WriteFile(srcPath, []byte("read test"), 0644); err != nil {
t.Fatal(err)
}
sha, err := StoreBlob(blobsDir, srcPath)
if err != nil {
t.Fatal(err)
}
data, err := ReadBlob(blobsDir, sha)
if err != nil {
t.Fatal(err)
}
if string(data) != "read test" {
t.Errorf("ReadBlob() = %q, want %q", string(data), "read test")
}
// Read non-existent blob.
_, err = ReadBlob(blobsDir, strings.Repeat("a", 64))
if err == nil {
t.Error("ReadBlob() expected error for non-existent blob")
}
}