@@ -47,17 +47,7 @@ func TestShellVariableResolver_ResolveValue(t *testing.T) {
47 envVars: map[string]string{},
47 envVars: map[string]string{},
48 expectError: true,
48 expectError: true,
51− name: "shell command execution",
52− value: "$(echo hello)",
53− shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
54− if command == "echo hello" {
55− return "hello\n", "", nil
57− return "", "", errors.New("unexpected command")
62 name: "shell command with whitespace trimming",
52 name: "shell command with whitespace trimming",
63 value: "$(echo ' spaced ')",
53 value: "$(echo ' spaced ')",
@@ -104,6 +94,171 @@ func TestShellVariableResolver_ResolveValue(t *testing.T) {
97+func TestShellVariableResolver_EnhancedResolveValue(t *testing.T) {
101+ envVars map[string]string
102+ shellFunc func(ctx context.Context, command string) (stdout, stderr string, err error)
107+ name: "command substitution within string",
108+ value: "Bearer $(echo token123)",
109+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
110+ if command == "echo token123" {
111+ return "token123\n", "", nil
113+ return "", "", errors.New("unexpected command")
115+ expected: "Bearer token123",
118+ name: "environment variable within string",
119+ value: "Bearer $TOKEN",
120+ envVars: map[string]string{"TOKEN": "sk-ant-123"},
121+ expected: "Bearer sk-ant-123",
124+ name: "environment variable with braces within string",
125+ value: "Bearer ${TOKEN}",
126+ envVars: map[string]string{"TOKEN": "sk-ant-456"},
127+ expected: "Bearer sk-ant-456",
130+ name: "mixed command and environment substitution",
131+ value: "$USER-$(date +%Y)-$HOST",
132+ envVars: map[string]string{
134+ "HOST": "localhost",
136+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
137+ if command == "date +%Y" {
138+ return "2024\n", "", nil
140+ return "", "", errors.New("unexpected command")
142+ expected: "testuser-2024-localhost",
145+ name: "multiple command substitutions",
146+ value: "$(echo hello) $(echo world)",
147+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
150+ return "hello\n", "", nil
152+ return "world\n", "", nil
154+ return "", "", errors.New("unexpected command")
156+ expected: "hello world",
159+ name: "nested parentheses in command",
160+ value: "$(echo $(echo inner))",
161+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
162+ if command == "echo $(echo inner)" {
163+ return "nested\n", "", nil
165+ return "", "", errors.New("unexpected command")
170+ name: "lone dollar with non-variable chars",
171+ value: "prefix$123suffix", // Numbers can't start variable names
175+ name: "dollar with special chars",
176+ value: "a$@b$#c", // Special chars aren't valid in variable names
180+ name: "empty environment variable substitution",
181+ value: "Bearer $EMPTY_VAR",
182+ envVars: map[string]string{},
186+ name: "unmatched command substitution opening",
187+ value: "Bearer $(echo test",
191+ name: "unmatched environment variable braces",
192+ value: "Bearer ${TOKEN",
196+ name: "command substitution with error",
197+ value: "Bearer $(false)",
198+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
199+ return "", "", errors.New("command failed")
204+ name: "complex real-world example",
205+ value: "Bearer $(cat /tmp/token.txt | base64 -w 0)",
206+ shellFunc: func(ctx context.Context, command string) (stdout, stderr string, err error) {
207+ if command == "cat /tmp/token.txt | base64 -w 0" {
208+ return "c2stYW50LXRlc3Q=\n", "", nil
210+ return "", "", errors.New("unexpected command")
212+ expected: "Bearer c2stYW50LXRlc3Q=",
215+ name: "environment variable with underscores and numbers",
216+ value: "Bearer $API_KEY_V2",
217+ envVars: map[string]string{"API_KEY_V2": "sk-test-123"},
218+ expected: "Bearer sk-test-123",
221+ name: "no substitution needed",
222+ value: "Bearer sk-ant-static-token",
223+ expected: "Bearer sk-ant-static-token",
226+ name: "incomplete variable at end",
231+ name: "variable with invalid character",
232+ value: "Bearer $VAR-NAME", // Hyphen not allowed in variable names
236+ name: "multiple invalid variables",
242+ for _, tt := range tests {
243+ t.Run(tt.name, func(t *testing.T) {
244+ testEnv := env.NewFromMap(tt.envVars)
245+ resolver := &shellVariableResolver{
246+ shell: &mockShell{execFunc: tt.shellFunc},
250+ result, err := resolver.ResolveValue(tt.value)
253+ assert.Error(t, err)
255+ assert.NoError(t, err)
256+ assert.Equal(t, tt.expected, result)
107func TestEnvironmentVariableResolver_ResolveValue(t *testing.T) {
262func TestEnvironmentVariableResolver_ResolveValue(t *testing.T) {
108 tests := []struct {
263 tests := []struct {
109 name string
264 name string