package persistence import ( "strings" "testing" ) func TestTrustlogStatus(t *testing.T) { tests := []struct { name string status TrustlogStatus expected string }{ {"not trustlogged", StatusNotTrustlogged, "NOT_TRUSTLOGGED"}, {"trustlogged", StatusTrustlogged, "TRUSTLOGGED"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if string(tt.status) != tt.expected { t.Errorf("expected %s, got %s", tt.expected, string(tt.status)) } }) } } func TestRetryStatus(t *testing.T) { tests := []struct { name string status RetryStatus expected string }{ {"pending", RetryStatusPending, "PENDING"}, {"retrying", RetryStatusRetrying, "RETRYING"}, {"dead letter", RetryStatusDeadLetter, "DEAD_LETTER"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if string(tt.status) != tt.expected { t.Errorf("expected %s, got %s", tt.expected, string(tt.status)) } }) } } func TestGetDialectDDL(t *testing.T) { tests := []struct { name string driverName string wantError bool checkFunc func(opDDL, cursorDDL, retryDDL string) error }{ { name: "postgres", driverName: "postgres", wantError: false, checkFunc: func(opDDL, cursorDDL, retryDDL string) error { if !strings.Contains(opDDL, "CREATE TABLE IF NOT EXISTS operation") { t.Error("postgres DDL should contain operation table") } if !strings.Contains(cursorDDL, "CREATE TABLE IF NOT EXISTS trustlog_cursor") { t.Error("postgres DDL should contain cursor table") } if !strings.Contains(retryDDL, "CREATE TABLE IF NOT EXISTS trustlog_retry") { t.Error("postgres DDL should contain retry table") } return nil }, }, { name: "mysql", driverName: "mysql", wantError: false, checkFunc: func(opDDL, cursorDDL, retryDDL string) error { if !strings.Contains(opDDL, "ENGINE=InnoDB") { t.Error("mysql DDL should contain ENGINE=InnoDB") } if !strings.Contains(opDDL, "DEFAULT CHARSET=utf8mb4") { t.Error("mysql DDL should contain DEFAULT CHARSET=utf8mb4") } return nil }, }, { name: "sqlite", driverName: "sqlite3", wantError: false, checkFunc: func(opDDL, cursorDDL, retryDDL string) error { if !strings.Contains(opDDL, "CREATE TABLE IF NOT EXISTS operation") { t.Error("sqlite DDL should contain operation table") } return nil }, }, { name: "unknown driver uses generic SQL", driverName: "unknown", wantError: false, checkFunc: func(opDDL, cursorDDL, retryDDL string) error { if !strings.Contains(opDDL, "CREATE TABLE IF NOT EXISTS operation") { t.Error("generic DDL should contain operation table") } return nil }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { opDDL, cursorDDL, retryDDL, err := GetDialectDDL(tt.driverName) if (err != nil) != tt.wantError { t.Errorf("GetDialectDDL() error = %v, wantError %v", err, tt.wantError) return } if !tt.wantError && tt.checkFunc != nil { if err := tt.checkFunc(opDDL, cursorDDL, retryDDL); err != nil { t.Errorf("DDL check failed: %v", err) } } }) } } func TestOperationTableDDL(t *testing.T) { requiredFields := []string{ "op_id", "op_actor", "doid", "producer_id", "request_body_hash", "response_body_hash", "sign", "op_source", "op_code", "do_prefix", "do_repository", "client_ip", "server_ip", "trustlog_status", "timestamp", } for _, field := range requiredFields { if !strings.Contains(OperationTableDDL, field) { t.Errorf("OperationTableDDL should contain field: %s", field) } } } func TestCursorTableDDL(t *testing.T) { requiredFields := []string{ "cursor_key", "cursor_value", "last_updated_at", } for _, field := range requiredFields { if !strings.Contains(CursorTableDDL, field) { t.Errorf("CursorTableDDL should contain field: %s", field) } } } func TestRetryTableDDL(t *testing.T) { requiredFields := []string{ "op_id", "retry_count", "retry_status", "last_retry_at", "next_retry_at", "error_message", } for _, field := range requiredFields { if !strings.Contains(RetryTableDDL, field) { t.Errorf("RetryTableDDL should contain field: %s", field) } } }