200 lines
5.0 KiB
Go
200 lines
5.0 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"gcy_hpc_server/internal/model"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
func setupBlobTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.FileBlob{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func TestBlobStore_Create(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
blob := &model.FileBlob{
|
|
SHA256: "abc123",
|
|
MinioKey: "files/abc123",
|
|
FileSize: 1024,
|
|
MimeType: "application/octet-stream",
|
|
RefCount: 0,
|
|
}
|
|
if err := store.Create(ctx, blob); err != nil {
|
|
t.Fatalf("Create() error = %v", err)
|
|
}
|
|
if blob.ID == 0 {
|
|
t.Error("Create() did not set ID")
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_GetBySHA256(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
store.Create(ctx, &model.FileBlob{SHA256: "abc", MinioKey: "files/abc", FileSize: 100, RefCount: 0})
|
|
|
|
blob, err := store.GetBySHA256(ctx, "abc")
|
|
if err != nil {
|
|
t.Fatalf("GetBySHA256() error = %v", err)
|
|
}
|
|
if blob == nil {
|
|
t.Fatal("GetBySHA256() returned nil")
|
|
}
|
|
if blob.SHA256 != "abc" {
|
|
t.Errorf("SHA256 = %q, want %q", blob.SHA256, "abc")
|
|
}
|
|
if blob.RefCount != 0 {
|
|
t.Errorf("RefCount = %d, want 0", blob.RefCount)
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_GetBySHA256_NotFound(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
blob, err := store.GetBySHA256(ctx, "nonexistent")
|
|
if err != nil {
|
|
t.Fatalf("GetBySHA256() error = %v", err)
|
|
}
|
|
if blob != nil {
|
|
t.Error("GetBySHA256() should return nil for not found")
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_IncrementDecrementRef(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
store.Create(ctx, &model.FileBlob{SHA256: "abc", MinioKey: "files/abc", FileSize: 100, RefCount: 0})
|
|
|
|
if err := store.IncrementRef(ctx, "abc"); err != nil {
|
|
t.Fatalf("IncrementRef() error = %v", err)
|
|
}
|
|
blob, _ := store.GetBySHA256(ctx, "abc")
|
|
if blob.RefCount != 1 {
|
|
t.Errorf("RefCount after 1st increment = %d, want 1", blob.RefCount)
|
|
}
|
|
|
|
store.IncrementRef(ctx, "abc")
|
|
blob, _ = store.GetBySHA256(ctx, "abc")
|
|
if blob.RefCount != 2 {
|
|
t.Errorf("RefCount after 2nd increment = %d, want 2", blob.RefCount)
|
|
}
|
|
|
|
refCount, err := store.DecrementRef(ctx, "abc")
|
|
if err != nil {
|
|
t.Fatalf("DecrementRef() error = %v", err)
|
|
}
|
|
if refCount != 1 {
|
|
t.Errorf("DecrementRef() returned %d, want 1", refCount)
|
|
}
|
|
|
|
refCount, _ = store.DecrementRef(ctx, "abc")
|
|
if refCount != 0 {
|
|
t.Errorf("DecrementRef() returned %d, want 0", refCount)
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_Delete(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
store.Create(ctx, &model.FileBlob{SHA256: "abc", MinioKey: "files/abc", FileSize: 100, RefCount: 0})
|
|
|
|
if err := store.Delete(ctx, "abc"); err != nil {
|
|
t.Fatalf("Delete() error = %v", err)
|
|
}
|
|
|
|
blob, _ := store.GetBySHA256(ctx, "abc")
|
|
if blob != nil {
|
|
t.Error("Delete() did not remove blob")
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_GetBySHA256s(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
store.Create(ctx, &model.FileBlob{SHA256: "h1", MinioKey: "files/h1", FileSize: 100})
|
|
store.Create(ctx, &model.FileBlob{SHA256: "h2", MinioKey: "files/h2", FileSize: 200})
|
|
store.Create(ctx, &model.FileBlob{SHA256: "h3", MinioKey: "files/h3", FileSize: 300})
|
|
|
|
blobs, err := store.GetBySHA256s(ctx, []string{"h1", "h3"})
|
|
if err != nil {
|
|
t.Fatalf("GetBySHA256s() error = %v", err)
|
|
}
|
|
if len(blobs) != 2 {
|
|
t.Fatalf("len(blobs) = %d, want 2", len(blobs))
|
|
}
|
|
keys := map[string]bool{}
|
|
for _, b := range blobs {
|
|
keys[b.SHA256] = true
|
|
}
|
|
if !keys["h1"] || !keys["h3"] {
|
|
t.Errorf("expected h1 and h3, got %v", blobs)
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_GetBySHA256s_Empty(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
blobs, err := store.GetBySHA256s(ctx, []string{})
|
|
if err != nil {
|
|
t.Fatalf("GetBySHA256s() error = %v", err)
|
|
}
|
|
if len(blobs) != 0 {
|
|
t.Errorf("len(blobs) = %d, want 0", len(blobs))
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_GetBySHA256s_NotFound(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
blobs, err := store.GetBySHA256s(ctx, []string{"nonexistent"})
|
|
if err != nil {
|
|
t.Fatalf("GetBySHA256s() error = %v", err)
|
|
}
|
|
if len(blobs) != 0 {
|
|
t.Errorf("len(blobs) = %d, want 0 for non-existent SHA256s", len(blobs))
|
|
}
|
|
}
|
|
|
|
func TestBlobStore_SHA256_UniqueConstraint(t *testing.T) {
|
|
db := setupBlobTestDB(t)
|
|
store := NewBlobStore(db)
|
|
ctx := context.Background()
|
|
|
|
store.Create(ctx, &model.FileBlob{SHA256: "dup", MinioKey: "files/dup1", FileSize: 100})
|
|
err := store.Create(ctx, &model.FileBlob{SHA256: "dup", MinioKey: "files/dup2", FileSize: 200})
|
|
if err == nil {
|
|
t.Error("expected error for duplicate SHA256, got nil")
|
|
}
|
|
}
|