Introduce a commercial license option alongside AGPL-3.0-only, require a CLA for contributors, and document the terms in COMMERCIAL.md and NOTICE. Add a script to stamp SPDX headers on Go files and apply it across the tree.
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package workflows
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.temporal.io/sdk/client"
|
|
)
|
|
|
|
// TestDialWithRetry_SucceedsAfterTransientFailures models the cold-start JWKS
|
|
// race: the first attempts fail with an "unauthorized" error, then the server's
|
|
// key cache refreshes and the dial succeeds.
|
|
func TestDialWithRetry_SucceedsAfterTransientFailures(t *testing.T) {
|
|
calls := 0
|
|
dial := func() (client.Client, error) {
|
|
calls++
|
|
if calls < 3 {
|
|
return nil, errors.New("failed reaching server: Request unauthorized.")
|
|
}
|
|
return nil, nil
|
|
}
|
|
c, err := dialWithRetry(context.Background(), dial, time.Second, time.Millisecond, 5*time.Millisecond, nil)
|
|
if err != nil {
|
|
t.Fatalf("expected success after retries, got: %v", err)
|
|
}
|
|
if c != nil {
|
|
t.Fatalf("expected the stub's nil client, got non-nil")
|
|
}
|
|
if calls != 3 {
|
|
t.Fatalf("expected 3 dial attempts, got %d", calls)
|
|
}
|
|
}
|
|
|
|
// TestDialWithRetry_ExhaustsBudget asserts a persistently failing dial returns the
|
|
// last error (wrapped) once the budget elapses.
|
|
func TestDialWithRetry_ExhaustsBudget(t *testing.T) {
|
|
calls := 0
|
|
wantErr := errors.New("failed reaching server: Request unauthorized.")
|
|
dial := func() (client.Client, error) {
|
|
calls++
|
|
return nil, wantErr
|
|
}
|
|
_, err := dialWithRetry(context.Background(), dial, 20*time.Millisecond, time.Millisecond, 5*time.Millisecond, nil)
|
|
if err == nil {
|
|
t.Fatal("expected an error after exhausting the budget")
|
|
}
|
|
if !errors.Is(err, wantErr) {
|
|
t.Fatalf("expected the wrapped last error, got: %v", err)
|
|
}
|
|
if calls < 2 {
|
|
t.Fatalf("expected multiple attempts within the budget, got %d", calls)
|
|
}
|
|
}
|
|
|
|
// TestDialWithRetry_HealthySucceedsFirstTry asserts a healthy server connects on
|
|
// the first attempt with no backoff delay.
|
|
func TestDialWithRetry_HealthySucceedsFirstTry(t *testing.T) {
|
|
calls := 0
|
|
dial := func() (client.Client, error) {
|
|
calls++
|
|
return nil, nil
|
|
}
|
|
start := time.Now()
|
|
if _, err := dialWithRetry(context.Background(), dial, time.Second, 50*time.Millisecond, time.Second, nil); err != nil {
|
|
t.Fatalf("expected immediate success, got: %v", err)
|
|
}
|
|
if calls != 1 {
|
|
t.Fatalf("expected exactly 1 attempt, got %d", calls)
|
|
}
|
|
if elapsed := time.Since(start); elapsed > 20*time.Millisecond {
|
|
t.Fatalf("expected no backoff delay on first-try success, took %s", elapsed)
|
|
}
|
|
}
|
|
|
|
// TestDialWithRetry_RespectsContextCancellation asserts a canceled context aborts
|
|
// the retry loop promptly.
|
|
func TestDialWithRetry_RespectsContextCancellation(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
calls := 0
|
|
dial := func() (client.Client, error) {
|
|
calls++
|
|
if calls == 1 {
|
|
cancel() // cancel before the first backoff sleep
|
|
}
|
|
return nil, errors.New("still starting")
|
|
}
|
|
_, err := dialWithRetry(ctx, dial, 5*time.Second, 50*time.Millisecond, time.Second, nil)
|
|
if err == nil {
|
|
t.Fatal("expected a cancellation error")
|
|
}
|
|
if !errors.Is(err, context.Canceled) {
|
|
t.Fatalf("expected context.Canceled, got: %v", err)
|
|
}
|
|
}
|