Skip to content

Commit a3f6cb8

Browse files
authored
fix(scenarios): Fix the regex that locates variables to override (#202)
This PR updates the regex used to find exported variables in a scenario that have more complex declarations (I.E. variables that get values from sub-shells, variables that are defined on the same line as another, etc). This PR fixes #199 and tests have been added to ensure that this issue doesn't arise again.
1 parent 2f1f50d commit a3f6cb8

File tree

3 files changed

+139
-3
lines changed

3 files changed

+139
-3
lines changed

internal/engine/scenario.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func downloadScenarioMarkdown(url string) ([]byte, error) {
6868
return body, nil
6969
}
7070

71-
// Given either a local or remote path to a markdown file, resolve the path to
71+
// Given either a local or remote path to a markdown file, resolve the path to
7272
// the markdown file and return the contents of the file.
7373
func resolveMarkdownSource(path string) ([]byte, error) {
7474
if strings.HasPrefix(path, "https://") || strings.HasPrefix(path, "http://") {
@@ -128,8 +128,9 @@ func CreateScenarioFromMarkdown(
128128

129129
varsToExport := lib.CopyMap(environmentVariableOverrides)
130130
for key, value := range environmentVariableOverrides {
131+
environmentVariables[key] = value
131132
logging.GlobalLogger.Debugf("Attempting to override %s with %s", key, value)
132-
exportRegex := regexp.MustCompile(fmt.Sprintf(`export %s=["']?([a-z-A-Z0-9_]+)["']?`, key))
133+
exportRegex := regexp.MustCompile(fmt.Sprintf(`(?m)export %s\s*=\s*(.*?)(;|&&|$)`, key))
133134

134135
for index, codeBlock := range codeBlocks {
135136
matches := exportRegex.FindAllStringSubmatch(codeBlock.Content, -1)
@@ -150,7 +151,7 @@ func CreateScenarioFromMarkdown(
150151
oldValue := match[1]
151152

152153
// Replace the old export with the new export statement
153-
newLine := strings.Replace(oldLine, oldValue, value, 1)
154+
newLine := strings.Replace(oldLine, oldValue, value+" ", 1)
154155
logging.GlobalLogger.Debugf("Replacing '%s' with '%s'", oldLine, newLine)
155156

156157
// Update the code block with the new export statement

internal/engine/scenario_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"os"
88
"strings"
99
"testing"
10+
11+
"github.com/stretchr/testify/assert"
1012
)
1113

1214
// Mock HTTP server for testing downloading markdown from URL
@@ -76,3 +78,99 @@ func TestResolveMarkdownSource(t *testing.T) {
7678
}
7779
})
7880
}
81+
82+
func TestVariableOverrides(t *testing.T) {
83+
// Test overriding environment variables
84+
t.Run("Override a standard variable declaration", func(t *testing.T) {
85+
scenario, err := CreateScenarioFromMarkdown(
86+
"../../scenarios/testing/variables.md",
87+
[]string{"bash"},
88+
map[string]string{
89+
"MY_VAR": "my_value",
90+
},
91+
)
92+
93+
assert.NoError(t, err)
94+
assert.Equal(t, "my_value", scenario.Environment["MY_VAR"])
95+
assert.Contains(t, scenario.Steps[0].CodeBlocks[0].Content, "export MY_VAR=my_value")
96+
})
97+
98+
t.Run(
99+
"Override a variable that is declared on the same line as another variable, separated by &&",
100+
func(t *testing.T) {
101+
scenario, err := CreateScenarioFromMarkdown(
102+
"../../scenarios/testing/variables.md",
103+
[]string{"bash"},
104+
map[string]string{
105+
"NEXT_VAR": "next_value",
106+
},
107+
)
108+
109+
assert.NoError(t, err)
110+
assert.Equal(t, "next_value", scenario.Environment["NEXT_VAR"])
111+
assert.Contains(
112+
t,
113+
scenario.Steps[1].CodeBlocks[0].Content,
114+
`export NEXT_VAR=next_value && export OTHER_VAR="Hello, World!"`,
115+
)
116+
},
117+
)
118+
119+
t.Run(
120+
"Override a variable that is declared on the same line as another variable, separated by ;",
121+
func(t *testing.T) {
122+
scenario, err := CreateScenarioFromMarkdown(
123+
"../../scenarios/testing/variables.md",
124+
[]string{"bash"},
125+
map[string]string{
126+
"THIS_VAR": "this_value",
127+
"THAT_VAR": "that_value",
128+
},
129+
)
130+
131+
assert.NoError(t, err)
132+
assert.Equal(t, "this_value", scenario.Environment["THIS_VAR"])
133+
assert.Equal(t, "that_value", scenario.Environment["THAT_VAR"])
134+
assert.Contains(
135+
t,
136+
scenario.Steps[2].CodeBlocks[0].Content,
137+
`export THIS_VAR=this_value ; export THAT_VAR=that_value`,
138+
)
139+
})
140+
141+
t.Run("Override a variable that has a subshell command as it's value", func(t *testing.T) {
142+
scenario, err := CreateScenarioFromMarkdown(
143+
"../../scenarios/testing/variables.md",
144+
[]string{"bash"},
145+
map[string]string{
146+
"SUBSHELL_VARIABLE": "subshell_value",
147+
},
148+
)
149+
150+
assert.NoError(t, err)
151+
assert.Equal(t, "subshell_value", scenario.Environment["SUBSHELL_VARIABLE"])
152+
assert.Contains(
153+
t,
154+
scenario.Steps[3].CodeBlocks[0].Content,
155+
`export SUBSHELL_VARIABLE=subshell_value`,
156+
)
157+
})
158+
159+
t.Run("Override a variable that references another variable", func(t *testing.T) {
160+
scenario, err := CreateScenarioFromMarkdown(
161+
"../../scenarios/testing/variables.md",
162+
[]string{"bash"},
163+
map[string]string{
164+
"VAR2": "var2_value",
165+
},
166+
)
167+
168+
assert.NoError(t, err)
169+
assert.Equal(t, "var2_value", scenario.Environment["VAR2"])
170+
assert.Contains(
171+
t,
172+
scenario.Steps[4].CodeBlocks[0].Content,
173+
`export VAR2=var2_value`,
174+
)
175+
})
176+
}

scenarios/testing/variables.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Variable declaration and usage
2+
3+
## Simple declaration
4+
5+
```bash
6+
export MY_VAR="Hello, World!"
7+
echo $MY_VAR
8+
```
9+
10+
## Double variable declaration
11+
12+
```bash
13+
export NEXT_VAR="Hello" && export OTHER_VAR="Hello, World!"
14+
echo $NEXT_VAR
15+
```
16+
17+
## Double declaration with semicolon
18+
19+
```bash
20+
export THIS_VAR="Hello"; export THAT_VAR="Hello, World!"
21+
echo $OTHER_VAR
22+
```
23+
24+
## Declaration with subshell value
25+
26+
```bash
27+
export SUBSHELL_VARIABLE=$(echo "Hello, World!")
28+
echo $SUBSHELL_VARIABLE
29+
```
30+
31+
## Declaration with other variable in value
32+
33+
```bash
34+
export VAR1="Hello"
35+
export VAR2="$VAR1, World!"
36+
echo $VAR2
37+
```

0 commit comments

Comments
 (0)