Skip to content

Commit aca5728

Browse files
committed
Variables testing: confirm space-containing values
The previous commit introduced a change to how the framework handled arguments, which necessitated some changes in the variables code. It got too complicated, too many places would need too much logic. Just accept that the test.run(arguments="...") will never be quite like the same arguments on the CLI, and just use lists to avoid things being broken on embedded spaces - those won't be split. Many tests arleady do this, so it's nothing new. Added a comment in TestCmd to make it more clear. Signed-off-by: Mats Wichmann <mats@linux.com>
1 parent 6cf21b8 commit aca5728

File tree

9 files changed

+69
-23
lines changed

9 files changed

+69
-23
lines changed

CHANGES.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
2121
From Mats Wichmann:
2222
- env.Dump() now considers the "key" positional argument to be a varargs
2323
type (zero, one or many). However called, it returns a serialized
24-
result that looks like a dict. Previously, only one "key" was
25-
accepted, and unlike the zero-args case, it was be serialized
26-
to a string containing the value (without the key). For example, if
24+
result that looks like a dict. Previously, only a single "key" was
25+
accepted, and unlike the zero-args case, it was serialized to a
26+
string containing just the value (without the key). For example, if
2727
"print(repr(env.Dump('CC'))" previously returned "'gcc'", it will now
2828
return "{'CC': 'gcc'}".
2929
- Add a timeout to test/ninja/default_targets.py - it's gotten stuck on

SCons/Variables/EnumVariableTests.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def valid(o, v) -> None:
159159
def invalid(o, v) -> None:
160160
with self.assertRaises(
161161
SCons.Errors.UserError,
162-
msg=f"did not catch expected UserError for o = {o.key}, v = {v}",
162+
msg=f"did not catch expected UserError for o = {o.key!r}, v = {v!r}",
163163
):
164164
o.validator('X', v, {})
165165
table = {
@@ -186,6 +186,22 @@ def invalid(o, v) -> None:
186186
expected[1](opt1, v)
187187
expected[2](opt2, v)
188188

189+
# make sure there are no problems with space-containing entries
190+
opts = SCons.Variables.Variables()
191+
opts.Add(
192+
SCons.Variables.EnumVariable(
193+
'test0',
194+
help='test option help',
195+
default='nospace',
196+
allowed_values=['nospace', 'with space'],
197+
map={},
198+
ignorecase=0,
199+
)
200+
)
201+
opt = opts.options[0]
202+
valid(opt, 'nospace')
203+
valid(opt, 'with space')
204+
189205

190206
if __name__ == "__main__":
191207
unittest.main()

SCons/Variables/ListVariable.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,6 @@ def _converter(val, allowedElems, mapdict) -> _ListVariable:
123123
Incoming values ``all`` and ``none`` are recognized and converted
124124
into their expanded form.
125125
"""
126-
val = val.replace('"', '') # trim any wrapping quotes
127-
val = val.replace("'", '')
128126
if val == 'none':
129127
val = []
130128
elif val == 'all':

test/Variables/EnumVariable.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def check(expect):
5252
allowed_values=('motif', 'gtk', 'kde'),
5353
map={}, ignorecase=1), # case insensitive
5454
EV('some', 'some option', 'xaver',
55-
allowed_values=('xaver', 'eins'),
56-
map={}, ignorecase=2), # make lowercase
55+
allowed_values=('xaver', 'eins', 'zwei wörter'),
56+
map={}, ignorecase=2), # case lowering
5757
)
5858
5959
_ = DefaultEnvironment(tools=[])
@@ -89,11 +89,14 @@ def check(expect):
8989
test.run(arguments='guilib=IrGeNdwas', stderr=expect_stderr, status=2)
9090

9191
expect_stderr = """
92-
scons: *** Invalid value for enum variable 'some': 'irgendwas'. Valid values are: ('xaver', 'eins')
92+
scons: *** Invalid value for enum variable 'some': 'irgendwas'. Valid values are: ('xaver', 'eins', 'zwei wörter')
9393
""" + test.python_file_line(SConstruct_path, 20)
9494

9595
test.run(arguments='some=IrGeNdwas', stderr=expect_stderr, status=2)
9696

97+
test.run(arguments=['some=zwei Wörter'])
98+
check(['no', 'gtk', 'zwei wörter']) # case-lowering converter
99+
97100
test.pass_test()
98101

99102
# Local Variables:

test/Variables/PackageVariable.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ def check(expect):
7070
test.run(arguments=['x11=%s' % test.workpath()])
7171
check([test.workpath()])
7272

73+
space_subdir = test.workpath('space subdir')
74+
test.subdir(space_subdir)
75+
test.run(arguments=[f'x11={space_subdir}'])
76+
check([space_subdir])
77+
7378
expect_stderr = """
7479
scons: *** Path does not exist for variable 'x11': '/non/existing/path/'
7580
""" + test.python_file_line(SConstruct_path, 13)

test/Variables/PathVariable.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,19 @@ def check(expect):
106106

107107
default_file = test.workpath('default_file')
108108
default_subdir = test.workpath('default_subdir')
109+
109110
existing_subdir = test.workpath('existing_subdir')
110111
test.subdir(existing_subdir)
111112

112113
existing_file = test.workpath('existing_file')
113114
test.write(existing_file, "existing_file\n")
114115

116+
space_subdir = test.workpath('space subdir')
117+
test.subdir(space_subdir)
118+
119+
space_file = test.workpath('space file')
120+
test.write(space_file, "space_file\n")
121+
115122
non_existing_subdir = test.workpath('non_existing_subdir')
116123
non_existing_file = test.workpath('non_existing_file')
117124

@@ -135,17 +142,22 @@ def check(expect):
135142
test.run(arguments=['X=%s' % existing_file])
136143
check([existing_file])
137144

138-
test.run(arguments=['X=%s' % non_existing_file])
139-
check([non_existing_file])
140-
141145
test.run(arguments=['X=%s' % existing_subdir])
142146
check([existing_subdir])
143147

148+
test.run(arguments=['X=%s' % space_file])
149+
check([space_file])
150+
151+
test.run(arguments=['X=%s' % space_subdir])
152+
check([space_subdir])
153+
144154
test.run(arguments=['X=%s' % non_existing_subdir])
145155
check([non_existing_subdir])
156+
test.must_not_exist(non_existing_subdir)
146157

158+
test.run(arguments=['X=%s' % non_existing_file])
159+
check([non_existing_file])
147160
test.must_not_exist(non_existing_file)
148-
test.must_not_exist(non_existing_subdir)
149161

150162
test.write(SConstruct_path, """\
151163
opts = Variables(args=ARGUMENTS)

testing/framework/TestCmd.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ def __init__(
10231023
interpreter=None,
10241024
workdir=None,
10251025
subdir=None,
1026-
verbose=None,
1026+
verbose: int = -1,
10271027
match=None,
10281028
match_stdout=None,
10291029
match_stderr=None,
@@ -1039,7 +1039,7 @@ def __init__(
10391039
self.description_set(description)
10401040
self.program_set(program)
10411041
self.interpreter_set(interpreter)
1042-
if verbose is None:
1042+
if verbose == -1:
10431043
try:
10441044
verbose = max(0, int(os.environ.get('TESTCMD_VERBOSE', 0)))
10451045
except ValueError:
@@ -1178,10 +1178,10 @@ def command_args(self, program=None, interpreter=None, arguments=None):
11781178
cmd.extend([f"{k}={v}" for k, v in arguments.items()])
11791179
return cmd
11801180
if isinstance(arguments, str):
1181-
# Split into a list for passing to SCons - don't lose
1182-
# quotes, and don't break apart quoted substring with space.
1183-
# str split() fails on the spaces, shlex.split() on the quotes.
1184-
arguments = re.findall(r"(?:\".*?\"|\S)+", arguments)
1181+
# Split into a list for passing to SCons. This *will*
1182+
# break if the string has embedded spaces as part of a substing -
1183+
# use a # list to pass those to avoid the problem.
1184+
arguments = arguments.split()
11851185
cmd.extend(arguments)
11861186
return cmd
11871187

testing/framework/TestCmdTests.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,13 +2239,13 @@ def test_command_args(self) -> None:
22392239
expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2']
22402240
self.assertEqual(expect, r)
22412241

2242-
r = test.command_args('prog', 'python', 'arg1 arg2="quoted"')
2243-
expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2="quoted"']
2242+
r = test.command_args('prog', 'python', 'arg1 arg2=value')
2243+
expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2=value']
22442244
with self.subTest():
22452245
self.assertEqual(expect, r)
22462246

2247-
r = test.command_args('prog', 'python', 'arg1 arg2="quoted with space"')
2248-
expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2="quoted with space"']
2247+
r = test.command_args('prog', 'python', ['arg1', 'arg2=with space'])
2248+
expect = ['python', run_env.workpath('prog'), 'arg1', 'arg2=with space']
22492249
with self.subTest():
22502250
self.assertEqual(expect, r)
22512251

testing/framework/test-framework.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,18 @@ or::
621621

622622
test.must_match(..., match=TestSCons.match_re, ...)
623623

624+
Often you want to supply arguments to SCons when it is invoked
625+
to run a test, which you can do using an *arguments* parameter::
626+
627+
test.run(arguments="-O -v FOO=BAR")
628+
629+
One caveat here: the way the parameter is processed is unavoidably
630+
different from typing on the command line - if you need it not to
631+
be split on spaces, pre-split it yourself, and pass the list, like::
632+
633+
test.run(arguments=["-f", "SConstruct2", "FOO=Two Words"])
634+
635+
624636
Avoiding tests based on tool existence
625637
======================================
626638

0 commit comments

Comments
 (0)