mirror of
https://github.com/Relintai/scons_gd.git
synced 2025-02-10 16:40:14 +01:00
696 lines
20 KiB
Python
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:
|