Establish the project foundation with three packages: - core: shared types (Header, Metadata, Value, ObjectType, UUID generation) - db: SQLite migration framework, connection management (WAL, FK, busy timeout), transaction helpers (StartTX/EndTX), time conversion - config: runtime configuration (DB path, blob store, Minio, gRPC addr) Includes initial schema migration (001_initial.sql) with 13 tables covering shared infrastructure, bibliographic data, and artifact repository. Full test coverage for all packages, strict linting (.golangci.yaml), and Makefile. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
107 lines
2.4 KiB
Go
107 lines
2.4 KiB
Go
package core
|
|
|
|
import (
|
|
"sort"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNewUUID(t *testing.T) {
|
|
id1 := NewUUID()
|
|
id2 := NewUUID()
|
|
if id1 == "" {
|
|
t.Fatal("NewUUID returned empty string")
|
|
}
|
|
if id1 == id2 {
|
|
t.Fatal("NewUUID returned duplicate UUIDs")
|
|
}
|
|
}
|
|
|
|
func TestVal(t *testing.T) {
|
|
v := Val("hello")
|
|
if v.Contents != "hello" {
|
|
t.Fatalf("expected contents 'hello', got %q", v.Contents)
|
|
}
|
|
if v.Type != ValueTypeUnspecified {
|
|
t.Fatalf("expected type %q, got %q", ValueTypeUnspecified, v.Type)
|
|
}
|
|
}
|
|
|
|
func TestVals(t *testing.T) {
|
|
v := Vals("world")
|
|
if v.Contents != "world" {
|
|
t.Fatalf("expected contents 'world', got %q", v.Contents)
|
|
}
|
|
if v.Type != ValueTypeString {
|
|
t.Fatalf("expected type %q, got %q", ValueTypeString, v.Type)
|
|
}
|
|
}
|
|
|
|
func TestNewHeader(t *testing.T) {
|
|
before := time.Now().UTC().Unix()
|
|
h := NewHeader(ObjectTypeArtifact)
|
|
after := time.Now().UTC().Unix()
|
|
|
|
if h.ID == "" {
|
|
t.Fatal("header ID is empty")
|
|
}
|
|
if h.Type != ObjectTypeArtifact {
|
|
t.Fatalf("expected type %q, got %q", ObjectTypeArtifact, h.Type)
|
|
}
|
|
if h.Created < before || h.Created > after {
|
|
t.Fatalf("Created timestamp %d not in range [%d, %d]", h.Created, before, after)
|
|
}
|
|
if h.Modified != h.Created {
|
|
t.Fatalf("Modified (%d) should equal Created (%d)", h.Modified, h.Created)
|
|
}
|
|
if h.Meta == nil {
|
|
t.Fatal("Meta should not be nil")
|
|
}
|
|
}
|
|
|
|
func TestHeaderTouch(t *testing.T) {
|
|
h := NewHeader(ObjectTypeNode)
|
|
original := h.Modified
|
|
// Ensure at least 1 second passes for timestamp change.
|
|
time.Sleep(10 * time.Millisecond)
|
|
h.Touch()
|
|
if h.Modified < original {
|
|
t.Fatalf("Touch should not decrease Modified: was %d, now %d", original, h.Modified)
|
|
}
|
|
}
|
|
|
|
func TestMapFromList(t *testing.T) {
|
|
list := []string{"alpha", "beta", "gamma"}
|
|
m := MapFromList(list)
|
|
if len(m) != 3 {
|
|
t.Fatalf("expected 3 entries, got %d", len(m))
|
|
}
|
|
for _, s := range list {
|
|
if !m[s] {
|
|
t.Fatalf("expected %q in map", s)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestListFromMap(t *testing.T) {
|
|
m := map[string]bool{"z": true, "a": true, "m": true}
|
|
list := ListFromMap(m)
|
|
if len(list) != 3 {
|
|
t.Fatalf("expected 3 entries, got %d", len(list))
|
|
}
|
|
sort.Strings(list)
|
|
expected := []string{"a", "m", "z"}
|
|
for i, v := range list {
|
|
if v != expected[i] {
|
|
t.Fatalf("index %d: expected %q, got %q", i, expected[i], v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMapFromListEmpty(t *testing.T) {
|
|
m := MapFromList(nil)
|
|
if len(m) != 0 {
|
|
t.Fatalf("expected empty map, got %d entries", len(m))
|
|
}
|
|
}
|