first commit

This commit is contained in:
npc0-hue
2026-07-11 14:56:10 +08:00
commit 7e05d0a4e7
660 changed files with 78119 additions and 0 deletions
+145
View File
@@ -0,0 +1,145 @@
package repo
import (
"errors"
"path/filepath"
"strings"
"testing"
"browser.local/platform/domain"
)
func TestMemoryRepositoryRejectsDuplicateAndCopiesValues(t *testing.T) {
store := NewMemoryStore()
user := domain.User{
ID: "user-1",
DisplayName: "Mary",
Status: domain.UserStatusActive,
Roles: []string{"admin"},
}
if err := store.Users().Create(user); err != nil {
t.Fatalf("create user: %v", err)
}
if err := store.Users().Create(user); !errors.Is(err, ErrDuplicate) {
t.Fatalf("expected duplicate error, got %v", err)
}
got, err := store.Users().Get(user.ID)
if err != nil {
t.Fatalf("get user: %v", err)
}
got.Roles[0] = "mutated"
again, err := store.Users().Get(user.ID)
if err != nil {
t.Fatalf("get user again: %v", err)
}
if again.Roles[0] != "admin" {
t.Fatalf("expected stored roles to be isolated, got %+v", again.Roles)
}
}
func TestMemoryRepositoryListFiltersAndSorts(t *testing.T) {
store := NewMemoryStore()
users := []domain.User{
{ID: "user-c", DisplayName: "C", Status: domain.UserStatusDisabled},
{ID: "user-b", DisplayName: "B", Status: domain.UserStatusActive},
{ID: "user-a", DisplayName: "A", Status: domain.UserStatusActive},
}
for _, user := range users {
if err := store.Users().Create(user); err != nil {
t.Fatalf("create user %s: %v", user.ID, err)
}
}
active, err := store.Users().List(domain.UserFilter{Status: domain.UserStatusActive})
if err != nil {
t.Fatalf("list users: %v", err)
}
if len(active) != 2 || active[0].ID != "user-a" || active[1].ID != "user-b" {
t.Fatalf("expected sorted active users, got %+v", active)
}
}
func TestMemoryJobRepositoryFindsIdempotencyKey(t *testing.T) {
store := NewMemoryStore()
job := domain.Job{
ID: "job-1",
RunEndpointID: "run-local",
Capability: "process.start",
IdempotencyKey: "idem-1",
State: domain.JobStateQueued,
}
if err := store.Jobs().Create(job); err != nil {
t.Fatalf("create job: %v", err)
}
got, err := store.Jobs().GetByIdempotency("run-local", "idem-1")
if err != nil {
t.Fatalf("get by idempotency: %v", err)
}
if got.ID != job.ID {
t.Fatalf("expected job %q, got %q", job.ID, got.ID)
}
_, err = store.Jobs().GetByIdempotency("run-local", "missing")
if !errors.Is(err, ErrNotFound) {
t.Fatalf("expected not found for missing idempotency key, got %v", err)
}
}
func TestFileStorePersistsAndReloadsResources(t *testing.T) {
path := filepath.Join(t.TempDir(), "metadata.json")
store, err := NewFileStore(path)
if err != nil {
t.Fatalf("create file store: %v", err)
}
user := domain.User{
ID: "user-1",
DisplayName: "Durable User",
Status: domain.UserStatusActive,
Roles: []string{"platform-admin"},
}
if err := store.Users().Create(user); err != nil {
t.Fatalf("create user: %v", err)
}
job := domain.Job{
ID: "job-1",
RunEndpointID: "run-local",
ServerInstanceID: "server-1",
Capability: "process.start",
IdempotencyKey: "idem-1",
State: domain.JobStateQueued,
}
if err := store.Jobs().Create(job); err != nil {
t.Fatalf("create job: %v", err)
}
reloaded, err := NewFileStore(path)
if err != nil {
t.Fatalf("reload file store: %v", err)
}
got, err := reloaded.Users().Get("user-1")
if err != nil {
t.Fatalf("get reloaded user: %v", err)
}
if got.DisplayName != user.DisplayName || got.Roles[0] != "platform-admin" {
t.Fatalf("unexpected reloaded user: %+v", got)
}
gotJob, err := reloaded.Jobs().GetByIdempotency("run-local", "idem-1")
if err != nil {
t.Fatalf("get reloaded job by idempotency: %v", err)
}
if gotJob.ID != "job-1" || gotJob.ServerInstanceID != "server-1" {
t.Fatalf("unexpected reloaded job: %+v", gotJob)
}
}
func TestMySQLStoreRequiresDSN(t *testing.T) {
_, err := NewMySQLStore("")
if err == nil || !strings.Contains(err.Error(), "PLATFORM_MYSQL_DSN") {
t.Fatalf("expected missing MySQL DSN error, got %v", err)
}
}