From 3fbb34988227c8b1a3faea0a784966ec73ecc009 Mon Sep 17 00:00:00 2001 From: Ankitsinghsisodya Date: Mon, 25 May 2026 23:22:53 +0530 Subject: [PATCH 1/2] Implement extension parsing in invokeConfig with validation tests - Added `extensionsMap` method to `invokeConfig` to parse key=value extensions and return a map. - Introduced error handling for malformed extension entries. - Created unit tests `TestInvokeExtensionsMapValid` and `TestInvokeExtensionsMapMalformed` to validate the parsing logic and error conditions. This enhances the robustness of the extension handling in the invoke command. --- cmd/invoke.go | 17 +++++++++++------ cmd/invoke_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/cmd/invoke.go b/cmd/invoke.go index 9ff96d37fa..4ec0a4d20d 100644 --- a/cmd/invoke.go +++ b/cmd/invoke.go @@ -186,6 +186,10 @@ func runInvoke(cmd *cobra.Command, _ []string, newClient ClientFactory) (err err // Message to send the running function built from parameters gathered // from the user (or defaults) + exts, err := cfg.extensionsMap() + if err != nil { + return err + } m := fn.InvokeMessage{ ID: cfg.ID, Source: cfg.Source, @@ -194,7 +198,7 @@ func runInvoke(cmd *cobra.Command, _ []string, newClient ClientFactory) (err err RequestType: strings.ToUpper(cfg.RequestType), Data: cfg.Data, Format: cfg.Format, - Extensions: cfg.extensionsMap(), + Extensions: exts, } // If --file was specified, use its content for message data @@ -315,15 +319,16 @@ func newInvokeConfig() (cfg invokeConfig, err error) { return } -func (c invokeConfig) extensionsMap() map[string]string { - extensionsMap := make(map[string]string) +func (c invokeConfig) extensionsMap() (map[string]string, error) { + result := make(map[string]string) for _, ext := range c.Extensions { parts := strings.SplitN(ext, "=", 2) - if len(parts) == 2 { - extensionsMap[parts[0]] = parts[1] + if len(parts) != 2 { + return nil, fmt.Errorf("invalid --extension %q: must be in key=value format", ext) } + result[parts[0]] = parts[1] } - return extensionsMap + return result, nil } func (c invokeConfig) prompt() (invokeConfig, error) { diff --git a/cmd/invoke_test.go b/cmd/invoke_test.go index 7feae43f03..129511ca4c 100644 --- a/cmd/invoke_test.go +++ b/cmd/invoke_test.go @@ -78,3 +78,29 @@ func TestInvoke(t *testing.T) { t.Fatal("function was not invoked") } } + +// TestInvokeExtensionsMapValid ensures well-formed key=value extensions are +// parsed correctly, including values that themselves contain '='. +func TestInvokeExtensionsMapValid(t *testing.T) { + c := invokeConfig{Extensions: []string{"key=value", "foo=bar=baz"}} + m, err := c.extensionsMap() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if m["key"] != "value" { + t.Fatalf("expected key=value, got %q", m["key"]) + } + if m["foo"] != "bar=baz" { + t.Fatalf("expected foo=bar=baz, got %q", m["foo"]) + } +} + +// TestInvokeExtensionsMapMalformed ensures that an extension entry missing '=' +// returns an error rather than being silently dropped. +func TestInvokeExtensionsMapMalformed(t *testing.T) { + c := invokeConfig{Extensions: []string{"valid=ok", "badformat"}} + _, err := c.extensionsMap() + if err == nil { + t.Fatal("expected error for malformed extension entry, got nil") + } +} From c806ceb0e379714c08a91e6e72544a1c690529f5 Mon Sep 17 00:00:00 2001 From: Ankitsinghsisodya Date: Mon, 25 May 2026 23:28:37 +0530 Subject: [PATCH 2/2] Refactor extension handling in invokeConfig with improved validation - Renamed `extensionsMap` method to `parseExtensions` for clarity. - Enhanced validation to check for empty keys in extension entries. - Updated unit tests to cover cases for missing '=' and empty keys in extensions. This change improves the robustness and clarity of extension parsing in the invoke command. --- cmd/invoke.go | 6 +++--- cmd/invoke_test.go | 25 ++++++++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/cmd/invoke.go b/cmd/invoke.go index 4ec0a4d20d..206dc27dd4 100644 --- a/cmd/invoke.go +++ b/cmd/invoke.go @@ -186,7 +186,7 @@ func runInvoke(cmd *cobra.Command, _ []string, newClient ClientFactory) (err err // Message to send the running function built from parameters gathered // from the user (or defaults) - exts, err := cfg.extensionsMap() + exts, err := cfg.parseExtensions() if err != nil { return err } @@ -319,11 +319,11 @@ func newInvokeConfig() (cfg invokeConfig, err error) { return } -func (c invokeConfig) extensionsMap() (map[string]string, error) { +func (c invokeConfig) parseExtensions() (map[string]string, error) { result := make(map[string]string) for _, ext := range c.Extensions { parts := strings.SplitN(ext, "=", 2) - if len(parts) != 2 { + if len(parts) != 2 || strings.TrimSpace(parts[0]) == "" { return nil, fmt.Errorf("invalid --extension %q: must be in key=value format", ext) } result[parts[0]] = parts[1] diff --git a/cmd/invoke_test.go b/cmd/invoke_test.go index 129511ca4c..ce4fbb3f3c 100644 --- a/cmd/invoke_test.go +++ b/cmd/invoke_test.go @@ -83,7 +83,7 @@ func TestInvoke(t *testing.T) { // parsed correctly, including values that themselves contain '='. func TestInvokeExtensionsMapValid(t *testing.T) { c := invokeConfig{Extensions: []string{"key=value", "foo=bar=baz"}} - m, err := c.extensionsMap() + m, err := c.parseExtensions() if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -95,12 +95,23 @@ func TestInvokeExtensionsMapValid(t *testing.T) { } } -// TestInvokeExtensionsMapMalformed ensures that an extension entry missing '=' -// returns an error rather than being silently dropped. +// TestInvokeExtensionsMapMalformed ensures that extension entries missing '=' +// or with an empty key return an error rather than being silently dropped. func TestInvokeExtensionsMapMalformed(t *testing.T) { - c := invokeConfig{Extensions: []string{"valid=ok", "badformat"}} - _, err := c.extensionsMap() - if err == nil { - t.Fatal("expected error for malformed extension entry, got nil") + cases := []struct { + name string + exts []string + }{ + {"missing equals", []string{"valid=ok", "badformat"}}, + {"empty key", []string{"valid=ok", "=nokey"}}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + c := invokeConfig{Extensions: tc.exts} + _, err := c.parseExtensions() + if err == nil { + t.Fatalf("expected error for %v, got nil", tc.exts) + } + }) } }