Files
cgalo5758 88db730fcc Add dual licensing and SPDX headers
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.
2026-09-06 02:29:42 -05:00

58 lines
2.3 KiB
Go

// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
package workflows
import (
"errors"
"fmt"
"testing"
"go.temporal.io/api/serviceerror"
"go.temporal.io/sdk/temporal"
)
// TestIsScheduleNotFound verifies that only Temporal's *serviceerror.NotFound is
// classified as "schedule absent". Any other error — including a different
// serviceerror type — is not, so EnsureSyncSchedule surfaces it instead of
// misrouting to Create.
func TestIsScheduleNotFound(t *testing.T) {
tests := []struct {
name string
err error
want bool
}{
{"not found", serviceerror.NewNotFound("schedule not found"), true},
{"wrapped not found", fmt.Errorf("describe: %w", serviceerror.NewNotFound("schedule not found")), true},
{"generic error", errors.New("connection reset"), false},
{"other serviceerror", serviceerror.NewUnavailable("temporal degraded"), false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := isScheduleNotFound(tt.err); got != tt.want {
t.Errorf("isScheduleNotFound(%v) = %v, want %v", tt.err, got, tt.want)
}
})
}
}
// TestCreateRaceClassification pins the sentinel that gates EnsureSyncSchedule's
// create-race fallback. EnsureSyncSchedule itself is not exercised end-to-end
// here: it needs a live client.ScheduleClient(), which the local
// go.temporal.io/sdk/testsuite package does not fake (testsuite covers
// workflow/activity execution, not the Schedule API). The reachable, meaningful
// unit is the errors.Is match on temporal.ErrScheduleAlreadyRunning.
func TestCreateRaceClassification(t *testing.T) {
if !errors.Is(temporal.ErrScheduleAlreadyRunning, temporal.ErrScheduleAlreadyRunning) {
t.Fatal("ErrScheduleAlreadyRunning should match itself under errors.Is")
}
if errors.Is(errors.New("some other error"), temporal.ErrScheduleAlreadyRunning) {
t.Fatal("unrelated error must not match ErrScheduleAlreadyRunning")
}
// A wrapped sentinel still matches, mirroring how Create's error is inspected
// through fmt.Errorf wrapping before the fallback fires.
if !errors.Is(fmt.Errorf("create: %w", temporal.ErrScheduleAlreadyRunning), temporal.ErrScheduleAlreadyRunning) {
t.Fatal("wrapped ErrScheduleAlreadyRunning should match under errors.Is")
}
}