scons_gd/scons/SCons/Variables/VariablesTests.py
2022-10-15 16:06:26 +02:00

696 lines
20 KiB
Python

# MIT License
#
# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import unittest
import TestSCons
import SCons.Variables
import SCons.Subst
import SCons.Warnings
from SCons.Util import cmp
class Environment:
def __init__(self):
self.dict = {}
def subst(self, x):
return SCons.Subst.scons_subst(x, self, gvars=self.dict)
def __setitem__(self, key, value):
self.dict[key] = value
def __getitem__(self, key):
return self.dict[key]
def __contains__(self, key):
return key in self.dict
def check(key, value, env):
assert int(value) == 6 * 9, "key %s = %s" % (key, repr(value))
# Check saved option file by executing and comparing against
# the expected dictionary
def checkSave(file, expected):
gdict = {}
ldict = {}
with open(file, 'r') as f:
exec(f.read(), gdict, ldict)
assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict)
class VariablesTestCase(unittest.TestCase):
def test_keys(self):
"""Test the Variables.keys() method"""
opts = SCons.Variables.Variables()
opts.Add('VAR1')
opts.Add('VAR2',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
keys = list(opts.keys())
assert keys == ['VAR1', 'VAR2'], keys
def test_Add(self):
"""Test adding to a Variables object"""
opts = SCons.Variables.Variables()
opts.Add('VAR')
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
o = opts.options[0]
assert o.key == 'VAR'
assert o.help == ''
assert o.default is None
assert o.validator is None
assert o.converter is None
o = opts.options[1]
assert o.key == 'ANSWER'
assert o.help == 'THE answer to THE question'
assert o.default == "42"
o.validator(o.key, o.converter(o.default), {})
def test_it(var, opts=opts):
exc_caught = None
try:
opts.Add(var)
except SCons.Errors.UserError:
exc_caught = 1
assert exc_caught, "did not catch UserError for '%s'" % var
test_it('foo/bar')
test_it('foo-bar')
test_it('foo.bar')
def test_AddVariables(self):
"""Test adding a list of options to a Variables object"""
opts = SCons.Variables.Variables()
opts.AddVariables(('VAR2',),
('ANSWER2',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12))
o = opts.options[0]
assert o.key == 'VAR2', o.key
assert o.help == '', o.help
assert o.default is None, o.default
assert o.validator is None, o.validator
assert o.converter is None, o.converter
o = opts.options[1]
assert o.key == 'ANSWER2', o.key
assert o.help == 'THE answer to THE question', o.help
assert o.default == "42", o.default
o.validator(o.key, o.converter(o.default), {})
def test_Update(self):
"""Test updating an Environment"""
# Test that a default value is validated correctly.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env)
assert env['ANSWER'] == 54
env = Environment()
opts.Update(env, {})
assert env['ANSWER'] == 54
# Test that a bad value from the file is used and
# validation fails correctly.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=54')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
env = Environment()
exc_caught = None
try:
opts.Update(env)
except AssertionError:
exc_caught = 1
assert exc_caught, "did not catch expected assertion"
env = Environment()
exc_caught = None
try:
opts.Update(env, {})
except AssertionError:
exc_caught = 1
assert exc_caught, "did not catch expected assertion"
# Test that a good value from the file is used and validated.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=42')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
'THE answer to THE question',
"10",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env)
assert env['ANSWER'] == 54
env = Environment()
opts.Update(env, {})
assert env['ANSWER'] == 54
# Test that a bad value from an args dictionary passed to
# Update() is used and validation fails correctly.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=10')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
'THE answer to THE question',
"12",
check,
lambda x: int(x) + 12)
env = Environment()
exc_caught = None
try:
opts.Update(env, {'ANSWER':'54'})
except AssertionError:
exc_caught = 1
assert exc_caught, "did not catch expected assertion"
# Test that a good value from an args dictionary
# passed to Update() is used and validated.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=10')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
'THE answer to THE question',
"12",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env, {'ANSWER':'42'})
assert env['ANSWER'] == 54
# Test against a former bug. If we supply a converter,
# but no default, the value should *not* appear in the
# Environment if no value is specified in the options file
# or args.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
help='THE answer to THE question',
converter=str)
env = Environment()
opts.Update(env, {})
assert 'ANSWER' not in env
# Test that a default value of None is all right.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
opts = SCons.Variables.Variables(file)
opts.Add('ANSWER',
"This is the answer",
None,
check)
env = Environment()
opts.Update(env, {})
assert 'ANSWER' not in env
def test_noaggregation(self):
"""Test that the 'files' and 'args' attributes of the Variables class
don't aggregate entries from one instance to another.
This used to be a bug in SCons version 2.4.1 and earlier.
"""
opts = SCons.Variables.Variables()
opts.files.append('custom.py')
opts.args['ANSWER'] = 54
nopts = SCons.Variables.Variables()
# Ensure that both attributes are initialized to
# an empty list and dict, respectively.
assert len(nopts.files) == 0
assert len(nopts.args) == 0
def test_args(self):
"""Test updating an Environment with arguments overridden"""
# Test that a bad (command-line) argument is used
# and the validation fails correctly.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=42')
opts = SCons.Variables.Variables(file, {'ANSWER':54})
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
env = Environment()
exc_caught = None
try:
opts.Update(env)
except AssertionError:
exc_caught = 1
assert exc_caught, "did not catch expected assertion"
# Test that a good (command-line) argument is used and validated.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=54')
opts = SCons.Variables.Variables(file, {'ANSWER':42})
opts.Add('ANSWER',
'THE answer to THE question',
"54",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env)
assert env['ANSWER'] == 54
# Test that a (command-line) argument is overridden by a dictionary
# supplied to Update() and the dictionary value is validated correctly.
test = TestSCons.TestSCons()
file = test.workpath('custom.py')
test.write('custom.py', 'ANSWER=54')
opts = SCons.Variables.Variables(file, {'ANSWER':54})
opts.Add('ANSWER',
'THE answer to THE question',
"54",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env, {'ANSWER':42})
assert env['ANSWER'] == 54
def test_Save(self):
"""Testing saving Variables"""
test = TestSCons.TestSCons()
cache_file = test.workpath('cached.options')
opts = SCons.Variables.Variables()
def bool_converter(val):
if val in [1, 'y']: val = 1
if val in [0, 'n']: val = 0
return val
# test saving out empty file
opts.Add('OPT_VAL',
'An option to test',
21,
None,
None)
opts.Add('OPT_VAL_2',
default='foo')
opts.Add('OPT_VAL_3',
default=1)
opts.Add('OPT_BOOL_0',
default='n',
converter=bool_converter)
opts.Add('OPT_BOOL_1',
default='y',
converter=bool_converter)
opts.Add('OPT_BOOL_2',
default=0,
converter=bool_converter)
env = Environment()
opts.Update(env, {'OPT_VAL_3' : 2})
assert env['OPT_VAL'] == 21, env['OPT_VAL']
assert env['OPT_VAL_2'] == 'foo', env['OPT_VAL_2']
assert env['OPT_VAL_3'] == 2, env['OPT_VAL_3']
assert env['OPT_BOOL_0'] == 0, env['OPT_BOOL_0']
assert env['OPT_BOOL_1'] == 1, env['OPT_BOOL_1']
assert env['OPT_BOOL_2'] == '0', env['OPT_BOOL_2']
env['OPT_VAL_2'] = 'bar'
env['OPT_BOOL_0'] = 0
env['OPT_BOOL_1'] = 1
env['OPT_BOOL_2'] = 2
opts.Save(cache_file, env)
checkSave(cache_file, { 'OPT_VAL_2' : 'bar',
'OPT_VAL_3' : 2,
'OPT_BOOL_2' : 2})
# Test against some old bugs
class Foo:
def __init__(self, x):
self.x = x
def __str__(self):
return self.x
test = TestSCons.TestSCons()
cache_file = test.workpath('cached.options')
opts = SCons.Variables.Variables()
opts.Add('THIS_USED_TO_BREAK',
'An option to test',
"Default")
opts.Add('THIS_ALSO_BROKE',
'An option to test',
"Default2")
opts.Add('THIS_SHOULD_WORK',
'An option to test',
Foo('bar'))
env = Environment()
opts.Update(env, { 'THIS_USED_TO_BREAK' : "Single'Quotes'In'String",
'THIS_ALSO_BROKE' : "\\Escape\nSequences\t",
'THIS_SHOULD_WORK' : Foo('baz') })
opts.Save(cache_file, env)
checkSave(cache_file, { 'THIS_USED_TO_BREAK' : "Single'Quotes'In'String",
'THIS_ALSO_BROKE' : "\\Escape\nSequences\t",
'THIS_SHOULD_WORK' : 'baz' })
def test_GenerateHelpText(self):
"""Test generating the default format help text"""
opts = SCons.Variables.Variables()
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
opts.Add('B',
'b - alpha test',
"42",
check,
lambda x: int(x) + 12)
opts.Add('A',
'a - alpha test',
"42",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env, {})
expect = """
ANSWER: THE answer to THE question
default: 42
actual: 54
B: b - alpha test
default: 42
actual: 54
A: a - alpha test
default: 42
actual: 54
"""
text = opts.GenerateHelpText(env)
assert text == expect, text
expectAlpha = """
A: a - alpha test
default: 42
actual: 54
ANSWER: THE answer to THE question
default: 42
actual: 54
B: b - alpha test
default: 42
actual: 54
"""
expectBackwards = """
B: b - alpha test
default: 42
actual: 54
ANSWER: THE answer to THE question
default: 42
actual: 54
A: a - alpha test
default: 42
actual: 54
"""
text = opts.GenerateHelpText(env, sort=cmp)
assert text == expectAlpha, text
textBool = opts.GenerateHelpText(env, sort=True)
assert text == expectAlpha, text
textBackwards = opts.GenerateHelpText(env, sort=lambda x, y: cmp(y, x))
assert textBackwards == expectBackwards, "Expected:\n%s\nGot:\n%s\n" % (
textBackwards,
expectBackwards,
)
def test_FormatVariableHelpText(self):
"""Test generating custom format help text"""
opts = SCons.Variables.Variables()
def my_format(env, opt, help, default, actual, aliases):
return '%s %s %s %s %s\n' % (opt, default, actual, help, aliases)
opts.FormatVariableHelpText = my_format
opts.Add('ANSWER',
'THE answer to THE question',
"42",
check,
lambda x: int(x) + 12)
opts.Add('B',
'b - alpha test',
"42",
check,
lambda x: int(x) + 12)
opts.Add('A',
'a - alpha test',
"42",
check,
lambda x: int(x) + 12)
env = Environment()
opts.Update(env, {})
expect = """\
ANSWER 42 54 THE answer to THE question ['ANSWER']
B 42 54 b - alpha test ['B']
A 42 54 a - alpha test ['A']
"""
text = opts.GenerateHelpText(env)
assert text == expect, text
expectAlpha = """\
A 42 54 a - alpha test ['A']
ANSWER 42 54 THE answer to THE question ['ANSWER']
B 42 54 b - alpha test ['B']
"""
text = opts.GenerateHelpText(env, sort=cmp)
assert text == expectAlpha, text
def test_Aliases(self):
"""Test option aliases"""
# test alias as a tuple
opts = SCons.Variables.Variables()
opts.AddVariables(
(('ANSWER', 'ANSWERALIAS'),
'THE answer to THE question',
"42"),
)
env = Environment()
opts.Update(env, {'ANSWER' : 'answer'})
assert 'ANSWER' in env
env = Environment()
opts.Update(env, {'ANSWERALIAS' : 'answer'})
assert 'ANSWER' in env and 'ANSWERALIAS' not in env
# test alias as a list
opts = SCons.Variables.Variables()
opts.AddVariables(
(['ANSWER', 'ANSWERALIAS'],
'THE answer to THE question',
"42"),
)
env = Environment()
opts.Update(env, {'ANSWER' : 'answer'})
assert 'ANSWER' in env
env = Environment()
opts.Update(env, {'ANSWERALIAS' : 'answer'})
assert 'ANSWER' in env and 'ANSWERALIAS' not in env
class UnknownVariablesTestCase(unittest.TestCase):
def test_unknown(self):
"""Test the UnknownVariables() method"""
opts = SCons.Variables.Variables()
opts.Add('ANSWER',
'THE answer to THE question',
"42")
args = {
'ANSWER' : 'answer',
'UNKNOWN' : 'unknown',
}
env = Environment()
opts.Update(env, args)
r = opts.UnknownVariables()
assert r == {'UNKNOWN' : 'unknown'}, r
assert env['ANSWER'] == 'answer', env['ANSWER']
def test_AddOptionUpdatesUnknown(self):
"""Test updating of the 'unknown' dict"""
opts = SCons.Variables.Variables()
opts.Add('A',
'A test variable',
"1")
args = {
'A' : 'a',
'ADDEDLATER' : 'notaddedyet',
}
env = Environment()
opts.Update(env,args)
r = opts.UnknownVariables()
assert r == {'ADDEDLATER' : 'notaddedyet'}, r
assert env['A'] == 'a', env['A']
opts.Add('ADDEDLATER',
'An option not present initially',
"1")
args = {
'A' : 'a',
'ADDEDLATER' : 'added',
}
opts.Update(env, args)
r = opts.UnknownVariables()
assert len(r) == 0, r
assert env['ADDEDLATER'] == 'added', env['ADDEDLATER']
def test_AddOptionWithAliasUpdatesUnknown(self):
"""Test updating of the 'unknown' dict (with aliases)"""
opts = SCons.Variables.Variables()
opts.Add('A',
'A test variable',
"1")
args = {
'A' : 'a',
'ADDEDLATERALIAS' : 'notaddedyet',
}
env = Environment()
opts.Update(env,args)
r = opts.UnknownVariables()
assert r == {'ADDEDLATERALIAS' : 'notaddedyet'}, r
assert env['A'] == 'a', env['A']
opts.AddVariables(
(('ADDEDLATER', 'ADDEDLATERALIAS'),
'An option not present initially',
"1"),
)
args['ADDEDLATERALIAS'] = 'added'
opts.Update(env, args)
r = opts.UnknownVariables()
assert len(r) == 0, r
assert env['ADDEDLATER'] == 'added', env['ADDEDLATER']
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4: