summaryrefslogtreecommitdiff
path: root/internal/llm/provider_more_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-10 23:59:21 +0300
committerPaul Buetow <paul@buetow.org>2026-06-10 23:59:21 +0300
commit72ac39cb2bac5c176dd1277c9482334d0441286f (patch)
tree91c68a1f03f0da64a6380f90643dc108e133f8de /internal/llm/provider_more_test.go
parentb9f90b4ffa8260cc906fa1b195ed0ba4aaa211df (diff)
Replace panics with returned errors in llm.RegisterProvider
RegisterProvider now returns an error for an empty name, a nil factory, or a duplicate registration instead of panicking, making registration composable and testable without recover(). RegisterAllProviders caches the one-time registration error (sync.Once cannot return a value) and returns it to every caller. Updated all call sites: hexailsp, hexaicli and hexaiaction propagate the error with context; test TestMains fail fast via panic. Added unit tests covering empty name, nil factory, duplicate, success and idempotent re-registration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'internal/llm/provider_more_test.go')
-rw-r--r--internal/llm/provider_more_test.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/internal/llm/provider_more_test.go b/internal/llm/provider_more_test.go
index 18cd49a..407c684 100644
--- a/internal/llm/provider_more_test.go
+++ b/internal/llm/provider_more_test.go
@@ -13,6 +13,48 @@ func TestWithOptions_Apply(t *testing.T) {
}
}
+func TestRegisterProvider_EmptyName(t *testing.T) {
+ // An empty (or whitespace-only) name must be rejected with an error
+ // instead of panicking, and must not mutate the registry.
+ if err := RegisterProvider(" ", func(Config, ProviderKeys) (Client, error) { return nil, nil }); err == nil {
+ t.Fatalf("expected error for empty provider name, got nil")
+ }
+}
+
+func TestRegisterProvider_NilFactory(t *testing.T) {
+ // A nil factory is a programming error and must surface as an error.
+ if err := RegisterProvider("with-nil-factory", nil); err == nil {
+ t.Fatalf("expected error for nil factory, got nil")
+ }
+}
+
+func TestRegisterProvider_Duplicate(t *testing.T) {
+ // "openai" is registered by RegisterAllProviders in TestMain, so a second
+ // registration under the same normalized name must return an error.
+ if err := RegisterProvider("OpenAI", func(Config, ProviderKeys) (Client, error) { return nil, nil }); err == nil {
+ t.Fatalf("expected error for duplicate provider, got nil")
+ }
+}
+
+func TestRegisterProvider_Success(t *testing.T) {
+ // A fresh, valid registration succeeds and is then resolvable.
+ name := "test-register-success"
+ if err := RegisterProvider(name, func(Config, ProviderKeys) (Client, error) { return nil, nil }); err != nil {
+ t.Fatalf("unexpected error registering provider: %v", err)
+ }
+ if _, ok := lookupProviderFactory(name); !ok {
+ t.Fatalf("provider %q not found after successful registration", name)
+ }
+}
+
+func TestRegisterAllProviders_Idempotent(t *testing.T) {
+ // RegisterAllProviders ran in TestMain; calling it again must return the
+ // same cached (nil) error without re-registering and tripping a duplicate.
+ if err := RegisterAllProviders(); err != nil {
+ t.Fatalf("RegisterAllProviders returned error on repeat call: %v", err)
+ }
+}
+
func TestNewFromConfig_Success_OpenAI(t *testing.T) {
// OpenAI success
oc := Config{Provider: "openai", OpenAIBaseURL: "http://x", OpenAIModel: "gpt"}