chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package outbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
func TestWorkerDefaultsAndRetryCap(t *testing.T) {
|
||||
worker := NewWorker(nil, discardLogger(), WorkerOptions{})
|
||||
if worker.options.PollInterval != 2*time.Second || worker.options.BatchSize != 20 || worker.options.MaxAttempts != 8 {
|
||||
t.Fatalf("unexpected worker defaults: %#v", worker.options)
|
||||
}
|
||||
worker.options.BaseRetry = time.Second
|
||||
worker.options.MaxRetry = 3 * time.Second
|
||||
delay := time.Until(worker.nextAttempt(10))
|
||||
if delay < 1400*time.Millisecond || delay > 3100*time.Millisecond {
|
||||
t.Fatalf("capped retry delay = %s", delay)
|
||||
}
|
||||
if !strings.HasPrefix(worker.workerID, "worker-") {
|
||||
t.Fatalf("unexpected worker id: %s", worker.workerID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreRejectsInvalidEventBeforeDatabaseAccess(t *testing.T) {
|
||||
store := NewStore(nil)
|
||||
if _, err := store.Enqueue(context.Background(), nil, NewEvent{}); err == nil {
|
||||
t.Fatal("empty event should be rejected")
|
||||
}
|
||||
if _, err := store.Enqueue(context.Background(), nil, NewEvent{
|
||||
AggregateType: "test", AggregateID: "id", EventType: "type", Payload: json.RawMessage(`not-json`),
|
||||
}); err == nil {
|
||||
t.Fatal("invalid JSON payload should be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashPayloadIsStable(t *testing.T) {
|
||||
first := hashPayload([]byte(`{"ok":true}`))
|
||||
if first != hashPayload([]byte(`{"ok":true}`)) || first == hashPayload([]byte(`{"ok":false}`)) {
|
||||
t.Fatal("payload hash is not stable")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetryableErrorAllowList(t *testing.T) {
|
||||
permanent := errors.New("malformed payload")
|
||||
if IsRetryable(permanent) {
|
||||
t.Fatal("ordinary errors must be permanent by default")
|
||||
}
|
||||
if !IsRetryable(Retryable(permanent)) || !errors.Is(Retryable(permanent), permanent) {
|
||||
t.Fatal("explicit retryable marker was not preserved")
|
||||
}
|
||||
if !IsRetryable(context.DeadlineExceeded) || !IsRetryable(&net.DNSError{IsTimeout: true}) {
|
||||
t.Fatal("timeouts must remain retryable")
|
||||
}
|
||||
if !IsRetryable(&pgconn.PgError{Code: "40001"}) || IsRetryable(&pgconn.PgError{Code: "23505"}) {
|
||||
t.Fatal("PostgreSQL transient and constraint errors were misclassified")
|
||||
}
|
||||
if Retryable(nil) != nil {
|
||||
t.Fatal("wrapping nil must return nil")
|
||||
}
|
||||
if !IsRetryable(fmt.Errorf("dependency: %w", Retryable(permanent))) {
|
||||
t.Fatal("wrapped marker must remain discoverable")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user