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.
58 lines
2.3 KiB
Go
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")
|
|
}
|
|
}
|