Removed the tests from scons.

This commit is contained in:
Relintai 2022-03-20 00:46:57 +01:00
parent d93618c84e
commit 6a36452181
42 changed files with 4 additions and 26827 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,369 +0,0 @@
# 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 os.path
import shutil
import sys
import unittest
import tempfile
import stat
from TestCmd import TestCmd
import SCons.CacheDir
built_it = None
class Action:
def __call__(self, targets, sources, env, **kw):
global built_it
if kw.get('execute', 1):
built_it = 1
return 0
def genstring(self, target, source, env):
return str(self)
def get_contents(self, target, source, env):
return bytearray('','utf-8')
class Builder:
def __init__(self, environment, action):
self.env = environment
self.action = action
self.overrides = {}
self.source_scanner = None
self.target_scanner = None
class Environment:
def __init__(self, cachedir):
self.cachedir = cachedir
def Override(self, overrides):
return self
def get_CacheDir(self):
return self.cachedir
class BaseTestCase(unittest.TestCase):
"""
Base fixtures common to our other unittest classes.
"""
def setUp(self):
self.test = TestCmd(workdir='')
import SCons.Node.FS
self.fs = SCons.Node.FS.FS()
self._CacheDir = SCons.CacheDir.CacheDir('cache')
def File(self, name, bsig=None, action=Action()):
node = self.fs.File(name)
node.builder_set(Builder(Environment(self._CacheDir), action))
if bsig:
node.cachesig = bsig
#node.binfo = node.BuildInfo(node)
#node.binfo.ninfo.bsig = bsig
return node
def tearDown(self):
os.remove(os.path.join(self._CacheDir.path, 'config'))
os.rmdir(self._CacheDir.path)
# Should that be shutil.rmtree?
class CacheDirTestCase(BaseTestCase):
"""
Test calling CacheDir code directly.
"""
def test_cachepath(self):
"""Test the cachepath() method"""
# Verify how the cachepath() method determines the name
# of the file in cache.
def my_collect(list, hash_format=None):
return list[0]
save_collect = SCons.Util.hash_collect
SCons.Util.hash_collect = my_collect
try:
name = 'a_fake_bsig'
f5 = self.File("cd.f5", name)
result = self._CacheDir.cachepath(f5)
len = self._CacheDir.config['prefix_len']
dirname = os.path.join('cache', name.upper()[:len])
filename = os.path.join(dirname, name)
assert result == (dirname, filename), result
finally:
SCons.Util.hash_collect = save_collect
class ExceptionTestCase(unittest.TestCase):
"""Test that the correct exceptions are thrown by CacheDir."""
# Don't inherit from BaseTestCase, we're by definition trying to
# break things so we really want a clean slate for each test.
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self._CacheDir = SCons.CacheDir.CacheDir(self.tmpdir)
def tearDown(self):
shutil.rmtree(self.tmpdir)
@unittest.skipIf(sys.platform.startswith("win"), "This fixture will not trigger an OSError on Windows")
def test_throws_correct_on_OSError(self):
"""Test that the correct error is thrown when cache directory cannot be created."""
privileged_dir = os.path.join(self.tmpdir, "privileged")
try:
os.mkdir(privileged_dir)
os.chmod(privileged_dir, stat.S_IREAD)
cd = SCons.CacheDir.CacheDir(os.path.join(privileged_dir, "cache"))
assert False, "Should have raised exception and did not"
except SCons.Errors.SConsEnvironmentError as e:
assert str(e) == "Failed to create cache directory {}".format(os.path.join(privileged_dir, "cache"))
finally:
os.chmod(privileged_dir, stat.S_IWRITE | stat.S_IEXEC | stat.S_IREAD)
shutil.rmtree(privileged_dir)
def test_throws_correct_when_failed_to_write_configfile(self):
class Unserializable:
"""A class which the JSON should not be able to serialize"""
def __init__(self, oldconfig):
self.something = 1 # Make the object unserializable
# Pretend to be the old config just enough
self.__dict__["prefix_len"] = oldconfig["prefix_len"]
def __getitem__(self, name, default=None):
if name == "prefix_len":
return self.__dict__["prefix_len"]
else:
return None
def __setitem__(self, name, value):
self.__dict__[name] = value
oldconfig = self._CacheDir.config
self._CacheDir.config = Unserializable(oldconfig)
# Remove the config file that got created on object creation
# so that _readconfig* will try to rewrite it
old_config = os.path.join(self._CacheDir.path, "config")
os.remove(old_config)
try:
self._CacheDir._readconfig(self._CacheDir.path)
assert False, "Should have raised exception and did not"
except SCons.Errors.SConsEnvironmentError as e:
assert str(e) == "Failed to write cache configuration for {}".format(self._CacheDir.path)
def test_raise_environment_error_on_invalid_json(self):
config_file = os.path.join(self._CacheDir.path, "config")
with open(config_file, "r") as cfg:
content = cfg.read()
# This will make JSON load raise a ValueError
content += "{}"
with open(config_file, "w") as cfg:
cfg.write(content)
try:
# Construct a new cache dir that will try to read the invalid config
new_cache_dir = SCons.CacheDir.CacheDir(self._CacheDir.path)
assert False, "Should have raised exception and did not"
except SCons.Errors.SConsEnvironmentError as e:
assert str(e) == "Failed to read cache configuration for {}".format(self._CacheDir.path)
class FileTestCase(BaseTestCase):
"""
Test calling CacheDir code through Node.FS.File interfaces.
"""
# These tests were originally in Nodes/FSTests.py and got moved
# when the CacheDir support was refactored into its own module.
# Look in the history for Node/FSTests.py if any of this needs
# to be re-examined.
def retrieve_succeed(self, target, source, env, execute=1):
self.retrieved.append(target)
return 0
def retrieve_fail(self, target, source, env, execute=1):
self.retrieved.append(target)
return 1
def push(self, target, source, env):
self.pushed.append(target)
return 0
def test_CacheRetrieve(self):
"""Test the CacheRetrieve() function"""
save_CacheRetrieve = SCons.CacheDir.CacheRetrieve
self.retrieved = []
f1 = self.File("cd.f1")
try:
SCons.CacheDir.CacheRetrieve = self.retrieve_succeed
self.retrieved = []
built_it = None
r = f1.retrieve_from_cache()
assert r == 1, r
assert self.retrieved == [f1], self.retrieved
assert built_it is None, built_it
SCons.CacheDir.CacheRetrieve = self.retrieve_fail
self.retrieved = []
built_it = None
r = f1.retrieve_from_cache()
assert not r, r
assert self.retrieved == [f1], self.retrieved
assert built_it is None, built_it
finally:
SCons.CacheDir.CacheRetrieve = save_CacheRetrieve
def test_CacheRetrieveSilent(self):
"""Test the CacheRetrieveSilent() function"""
save_CacheRetrieveSilent = SCons.CacheDir.CacheRetrieveSilent
SCons.CacheDir.cache_show = 1
f2 = self.File("cd.f2", 'f2_bsig')
try:
SCons.CacheDir.CacheRetrieveSilent = self.retrieve_succeed
self.retrieved = []
built_it = None
r = f2.retrieve_from_cache()
assert r == 1, r
assert self.retrieved == [f2], self.retrieved
assert built_it is None, built_it
SCons.CacheDir.CacheRetrieveSilent = self.retrieve_fail
self.retrieved = []
built_it = None
r = f2.retrieve_from_cache()
assert r is False, r
assert self.retrieved == [f2], self.retrieved
assert built_it is None, built_it
finally:
SCons.CacheDir.CacheRetrieveSilent = save_CacheRetrieveSilent
def test_CachePush(self):
"""Test the CachePush() function"""
save_CachePush = SCons.CacheDir.CachePush
SCons.CacheDir.CachePush = self.push
try:
self.pushed = []
cd_f3 = self.test.workpath("cd.f3")
f3 = self.File(cd_f3)
f3.push_to_cache()
assert self.pushed == [], self.pushed
self.test.write(cd_f3, "cd.f3\n")
f3.push_to_cache()
assert self.pushed == [f3], self.pushed
self.pushed = []
cd_f4 = self.test.workpath("cd.f4")
f4 = self.File(cd_f4)
f4.visited()
assert self.pushed == [], self.pushed
self.test.write(cd_f4, "cd.f4\n")
f4.clear()
f4.visited()
assert self.pushed == [], self.pushed
SCons.CacheDir.cache_force = 1
f4.clear()
f4.visited()
assert self.pushed == [f4], self.pushed
finally:
SCons.CacheDir.CachePush = save_CachePush
def test_warning(self):
"""Test raising a warning if we can't copy a file to cache."""
test = TestCmd(workdir='')
save_copy2 = shutil.copy2
def copy2(src, dst):
raise OSError
shutil.copy2 = copy2
save_mkdir = os.mkdir
def mkdir(dir, mode=0):
pass
os.mkdir = mkdir
old_warn_exceptions = SCons.Warnings.warningAsException(1)
SCons.Warnings.enableWarningClass(SCons.Warnings.CacheWriteErrorWarning)
try:
cd_f7 = self.test.workpath("cd.f7")
self.test.write(cd_f7, "cd.f7\n")
f7 = self.File(cd_f7, 'f7_bsig')
warn_caught = 0
try:
f7.push_to_cache()
except SCons.Errors.BuildError as e:
assert e.exc_info[0] == SCons.Warnings.CacheWriteErrorWarning
warn_caught = 1
assert warn_caught
finally:
shutil.copy2 = save_copy2
os.mkdir = save_mkdir
SCons.Warnings.warningAsException(old_warn_exceptions)
SCons.Warnings.suppressWarningClass(SCons.Warnings.CacheWriteErrorWarning)
def test_no_strfunction(self):
"""Test handling no strfunction() for an action."""
save_CacheRetrieveSilent = SCons.CacheDir.CacheRetrieveSilent
f8 = self.File("cd.f8", 'f8_bsig')
try:
SCons.CacheDir.CacheRetrieveSilent = self.retrieve_succeed
self.retrieved = []
built_it = None
r = f8.retrieve_from_cache()
assert r == 1, r
assert self.retrieved == [f8], self.retrieved
assert built_it is None, built_it
SCons.CacheDir.CacheRetrieveSilent = self.retrieve_fail
self.retrieved = []
built_it = None
r = f8.retrieve_from_cache()
assert r is False, r
assert self.retrieved == [f8], self.retrieved
assert built_it is None, built_it
finally:
SCons.CacheDir.CacheRetrieveSilent = save_CacheRetrieveSilent
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,76 +0,0 @@
# 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 os
import unittest
import TestCmd
from SCons.Defaults import mkdir_func
class DefaultsTestCase(unittest.TestCase):
def test_mkdir_func0(self):
test = TestCmd.TestCmd(workdir = '')
test.subdir('sub')
subdir2 = test.workpath('sub', 'dir1', 'dir2')
# Simple smoke test
mkdir_func(subdir2)
mkdir_func(subdir2) # 2nd time should be OK too
def test_mkdir_func1(self):
test = TestCmd.TestCmd(workdir = '')
test.subdir('sub')
subdir1 = test.workpath('sub', 'dir1')
subdir2 = test.workpath('sub', 'dir1', 'dir2')
# No error if asked to create existing dir
os.makedirs(subdir2)
mkdir_func(subdir2)
mkdir_func(subdir1)
def test_mkdir_func2(self):
test = TestCmd.TestCmd(workdir = '')
test.subdir('sub')
subdir1 = test.workpath('sub', 'dir1')
subdir2 = test.workpath('sub', 'dir1', 'dir2')
file = test.workpath('sub', 'dir1', 'dir2', 'file')
# make sure it does error if asked to create a dir
# where there's already a file
os.makedirs(subdir2)
test.write(file, "test\n")
try:
mkdir_func(file)
except OSError as e:
pass
else:
self.fail("expected OSError")
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
# 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
from SCons.EnvironmentValues import EnvironmentValues
class MyTestCase(unittest.TestCase):
def test_simple_environmentValues(self):
"""Test comparing SubstitutionEnvironments
"""
env1 = EnvironmentValues(XXX='x')
env2 = EnvironmentValues(XXX='x',XX="$X", X1="${X}", X2="$($X$)")
if __name__ == '__main__':
unittest.main()

View File

@ -1,128 +0,0 @@
# 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 SCons.Errors
class ErrorsTestCase(unittest.TestCase):
def test_BuildError(self):
"""Test the BuildError exception."""
try:
raise SCons.Errors.BuildError(
errstr = "foo", status=57, filename="file", exc_info=(1,2,3),
node = "n", executor="e", action="a", command="c")
except SCons.Errors.BuildError as e:
assert e.errstr == "foo"
assert e.status == 57
assert e.exitstatus == 2, e.exitstatus
assert e.filename == "file"
assert e.exc_info == (1,2,3)
assert e.node == "n"
assert e.executor == "e"
assert e.action == "a"
assert e.command == "c"
try:
raise SCons.Errors.BuildError("n", "foo", 57, 3, "file",
"e", "a", "c", (1,2,3))
except SCons.Errors.BuildError as e:
assert e.errstr == "foo", e.errstr
assert e.status == 57, e.status
assert e.exitstatus == 3, e.exitstatus
assert e.filename == "file", e.filename
assert e.exc_info == (1,2,3), e.exc_info
assert e.node == "n"
assert e.executor == "e"
assert e.action == "a"
assert e.command == "c"
try:
raise SCons.Errors.BuildError()
except SCons.Errors.BuildError as e:
assert e.errstr == "Unknown error"
assert e.status == 2
assert e.exitstatus == 2
assert e.filename is None
assert e.exc_info == (None, None, None)
assert e.node is None
assert e.executor is None
assert e.action is None
assert e.command is None
def test_InternalError(self):
"""Test the InternalError exception."""
try:
raise SCons.Errors.InternalError("test internal error")
except SCons.Errors.InternalError as e:
assert e.args == ("test internal error",)
def test_UserError(self):
"""Test the UserError exception."""
try:
raise SCons.Errors.UserError("test user error")
except SCons.Errors.UserError as e:
assert e.args == ("test user error",)
def test_ExplicitExit(self):
"""Test the ExplicitExit exception."""
try:
raise SCons.Errors.ExplicitExit("node")
except SCons.Errors.ExplicitExit as e:
assert e.node == "node"
def test_convert_EnvironmentError_to_BuildError(self):
"""Test the convert_to_BuildError function on SConsEnvironmentError
exceptions.
"""
ee = SCons.Errors.SConsEnvironmentError("test env error")
be = SCons.Errors.convert_to_BuildError(ee)
assert be.errstr == "test env error"
assert be.status == 2
assert be.exitstatus == 2
assert be.filename is None
def test_convert_OSError_to_BuildError(self):
"""Test the convert_to_BuildError function on OSError
exceptions.
"""
ose = OSError(7, 'test oserror')
be = SCons.Errors.convert_to_BuildError(ose)
assert be.errstr == 'test oserror'
assert be.status == 7
assert be.exitstatus == 2
assert be.filename is None
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,487 +0,0 @@
# 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 SCons.Executor
class MyEnvironment:
def __init__(self, **kw):
self._dict = {}
self._dict.update(kw)
def __getitem__(self, key):
return self._dict[key]
def Override(self, overrides):
d = self._dict.copy()
d.update(overrides)
return MyEnvironment(**d)
def _update(self, dict):
self._dict.update(dict)
class MyAction:
def __init__(self, actions=['action1', 'action2']):
self.actions = actions
def __call__(self, target, source, env, **kw):
for action in self.actions:
action(target, source, env, **kw)
def genstring(self, target, source, env):
return ' '.join(['GENSTRING'] + list(map(str, self.actions)) + target + source)
def get_contents(self, target, source, env):
return b' '.join(
[SCons.Util.to_bytes(aa) for aa in self.actions] +
[SCons.Util.to_bytes(tt) for tt in target] +
[SCons.Util.to_bytes(ss) for ss in source]
)
def get_implicit_deps(self, target, source, env):
return []
class MyBuilder:
def __init__(self, env, overrides):
self.env = env
self.overrides = overrides
self.action = MyAction()
class MyNode:
def __init__(self, name=None, pre=[], post=[]):
self.name = name
self.implicit = []
self.pre_actions = pre
self.post_actions = post
self.missing_val = None
self.always_build = False
self.up_to_date = False
def __str__(self):
return self.name
def build(self):
executor = SCons.Executor.Executor(MyAction(self.pre_actions +
[self.builder.action] +
self.post_actions),
self.builder.env,
[],
[self],
['s1', 's2'])
executor(self)
def get_env_scanner(self, env, kw):
return MyScanner('dep-')
def get_implicit_deps(self, env, scanner, path, kw={}):
if not scanner:
scanner = self.get_env_scanner(env, kw)
return [scanner.prefix + str(self)]
def add_to_implicit(self, deps):
self.implicit.extend(deps)
def missing(self):
return self.missing_val
def calc_signature(self, calc):
return 'cs-'+calc+'-'+self.name
def disambiguate(self):
return self
def is_up_to_date(self):
return self.up_to_date
class MyScanner:
def __init__(self, prefix):
self.prefix = prefix
def path(self, env, cwd, target, source):
return ()
def select(self, node):
return self
class ExecutorTestCase(unittest.TestCase):
def test__init__(self):
"""Test creating an Executor"""
source_list = ['s1', 's2']
x = SCons.Executor.Executor('a', 'e', ['o'], 't', source_list)
assert x.action_list == ['a'], x.action_list
assert x.env == 'e', x.env
assert x.overridelist == ['o'], x.overridelist
targets = x.get_all_targets()
assert targets == ['t'], targets
source_list.append('s3')
sources = x.get_all_sources()
assert sources == ['s1', 's2'], sources
try:
x = SCons.Executor.Executor(None, 'e', ['o'], 't', source_list)
except SCons.Errors.UserError:
pass
else:
raise Exception("Did not catch expected UserError")
def test__action_list(self):
"""Test the {get,set}_action_list() methods"""
x = SCons.Executor.Executor('a', 'e', 'o', 't', ['s1', 's2'])
l = x.get_action_list()
assert l == ['a'], l
x.add_pre_action('pre')
x.add_post_action('post')
l = x.get_action_list()
assert l == ['pre', 'a', 'post'], l
x.set_action_list('b')
l = x.get_action_list()
assert l == ['pre', 'b', 'post'], l
x.set_action_list(['c'])
l = x.get_action_list()
assert l == ['pre', 'c', 'post'], l
def test_get_build_env(self):
"""Test fetching and generating a build environment"""
x = SCons.Executor.Executor(MyAction(), MyEnvironment(e=1), [],
't', ['s1', 's2'])
x.env = MyEnvironment(eee=1)
be = x.get_build_env()
assert be['eee'] == 1, be
env = MyEnvironment(X='xxx')
x = SCons.Executor.Executor(MyAction(),
env,
[{'O':'o2'}],
't',
['s1', 's2'])
be = x.get_build_env()
assert be['O'] == 'o2', be['O']
assert be['X'] == 'xxx', be['X']
env = MyEnvironment(Y='yyy')
overrides = [{'O':'ob3'}, {'O':'oo3'}]
x = SCons.Executor.Executor(MyAction(), env, overrides, ['t'], ['s'])
be = x.get_build_env()
assert be['O'] == 'oo3', be['O']
assert be['Y'] == 'yyy', be['Y']
overrides = [{'O':'ob3'}]
x = SCons.Executor.Executor(MyAction(), env, overrides, ['t'], ['s'])
be = x.get_build_env()
assert be['O'] == 'ob3', be['O']
assert be['Y'] == 'yyy', be['Y']
def test_get_build_scanner_path(self):
"""Test fetching the path for the specified scanner."""
t = MyNode('t')
t.cwd = 'here'
x = SCons.Executor.Executor(MyAction(),
MyEnvironment(SCANNERVAL='sss'),
[],
[t],
['s1', 's2'])
class LocalScanner:
def path(self, env, dir, target, source):
target = list(map(str, target))
source = list(map(str, source))
return "scanner: %s, %s, %s, %s" % (env['SCANNERVAL'], dir, target, source)
s = LocalScanner()
p = x.get_build_scanner_path(s)
assert p == "scanner: sss, here, ['t'], ['s1', 's2']", p
def test_get_kw(self):
"""Test the get_kw() method"""
t = MyNode('t')
x = SCons.Executor.Executor(MyAction(),
MyEnvironment(),
[],
[t],
['s1', 's2'],
builder_kw={'X':1, 'Y':2})
kw = x.get_kw()
assert kw == {'X':1, 'Y':2, 'executor':x}, kw
kw = x.get_kw({'Z':3})
assert kw == {'X':1, 'Y':2, 'Z':3, 'executor':x}, kw
kw = x.get_kw({'X':4})
assert kw == {'X':4, 'Y':2, 'executor':x}, kw
def test__call__(self):
"""Test calling an Executor"""
result = []
def pre(target, source, env, result=result, **kw):
result.append('pre')
def action1(target, source, env, result=result, **kw):
result.append('action1')
def action2(target, source, env, result=result, **kw):
result.append('action2')
def post(target, source, env, result=result, **kw):
result.append('post')
env = MyEnvironment()
a = MyAction([action1, action2])
t = MyNode('t')
x = SCons.Executor.Executor(a, env, [], [t], ['s1', 's2'])
x.add_pre_action(pre)
x.add_post_action(post)
x(t)
assert result == ['pre', 'action1', 'action2', 'post'], result
del result[:]
def pre_err(target, source, env, result=result, **kw):
result.append('pre_err')
return 1
x = SCons.Executor.Executor(a, env, [], [t], ['s1', 's2'])
x.add_pre_action(pre_err)
x.add_post_action(post)
try:
x(t)
except SCons.Errors.BuildError:
pass
else:
raise Exception("Did not catch expected BuildError")
assert result == ['pre_err'], result
del result[:]
def test_cleanup(self):
"""Test cleaning up an Executor"""
orig_env = MyEnvironment(e=1)
x = SCons.Executor.Executor('b', orig_env, [{'o':1}],
't', ['s1', 's2'])
be = x.get_build_env()
assert be['e'] == 1, be['e']
x.cleanup()
x.env = MyEnvironment(eee=1)
be = x.get_build_env()
assert be['eee'] == 1, be['eee']
x.cleanup()
be = x.get_build_env()
assert be['eee'] == 1, be['eee']
def test_add_sources(self):
"""Test adding sources to an Executor"""
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
sources = x.get_all_sources()
assert sources == ['s1', 's2'], sources
x.add_sources(['s1', 's2'])
sources = x.get_all_sources()
assert sources == ['s1', 's2'], sources
x.add_sources(['s3', 's1', 's4'])
sources = x.get_all_sources()
assert sources == ['s1', 's2', 's3', 's4'], sources
def test_get_sources(self):
"""Test getting sources from an Executor"""
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
sources = x.get_sources()
assert sources == ['s1', 's2'], sources
x.add_sources(['s1', 's2'])
sources = x.get_sources()
assert sources == ['s1', 's2'], sources
x.add_sources(['s3', 's1', 's4'])
sources = x.get_sources()
assert sources == ['s1', 's2', 's3', 's4'], sources
def test_prepare(self):
"""Test the Executor's prepare() method"""
env = MyEnvironment()
t1 = MyNode('t1')
s1 = MyNode('s1')
s2 = MyNode('s2')
s3 = MyNode('s3')
x = SCons.Executor.Executor('b', env, [{}], [t1], [s1, s2, s3])
s2.missing_val = True
try:
r = x.prepare()
except SCons.Errors.StopError as e:
assert str(e) == "Source `s2' not found, needed by target `t1'.", e
else:
raise AssertionError("did not catch expected StopError: %s" % r)
def test_add_pre_action(self):
"""Test adding pre-actions to an Executor"""
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
x.add_pre_action('a1')
assert x.pre_actions == ['a1']
x.add_pre_action('a2')
assert x.pre_actions == ['a1', 'a2']
def test_add_post_action(self):
"""Test adding post-actions to an Executor"""
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
x.add_post_action('a1')
assert x.post_actions == ['a1']
x.add_post_action('a2')
assert x.post_actions == ['a1', 'a2']
def test___str__(self):
"""Test the __str__() method"""
env = MyEnvironment(S='string')
x = SCons.Executor.Executor(MyAction(), env, [], ['t'], ['s'])
c = str(x)
assert c == 'GENSTRING action1 action2 t s', c
x = SCons.Executor.Executor(MyAction(), env, [], ['t'], ['s'])
x.add_pre_action(MyAction(['pre']))
x.add_post_action(MyAction(['post']))
c = str(x)
expect = 'GENSTRING pre t s\n' + \
'GENSTRING action1 action2 t s\n' + \
'GENSTRING post t s'
assert c == expect, c
def test_nullify(self):
"""Test the nullify() method"""
env = MyEnvironment(S='string')
result = []
def action1(target, source, env, result=result, **kw):
result.append('action1')
env = MyEnvironment()
a = MyAction([action1])
x = SCons.Executor.Executor(a, env, [], ['t1', 't2'], ['s1', 's2'])
x(MyNode('', [], []))
assert result == ['action1'], result
s = str(x)
assert s[:10] == 'GENSTRING ', s
del result[:]
x.nullify()
assert result == [], result
x(MyNode('', [], []))
assert result == [], result
s = str(x)
assert s == '', s
def test_get_contents(self):
"""Test fetching the signatures contents"""
env = MyEnvironment(C='contents')
x = SCons.Executor.Executor(MyAction(), env, [], ['t'], ['s'])
c = x.get_contents()
assert c == b'action1 action2 t s', c
x = SCons.Executor.Executor(MyAction(actions=['grow']), env, [],
['t'], ['s'])
x.add_pre_action(MyAction(['pre']))
x.add_post_action(MyAction(['post']))
c = x.get_contents()
assert c == b'pre t sgrow t spost t s', c
def test_get_timestamp(self):
"""Test fetching the "timestamp" """
x = SCons.Executor.Executor('b', 'e', 'o', 't', ['s1', 's2'])
ts = x.get_timestamp()
assert ts == 0, ts
def test_scan_targets(self):
"""Test scanning the targets for implicit dependencies"""
env = MyEnvironment(S='string')
t1 = MyNode('t1')
t2 = MyNode('t2')
sources = [MyNode('s1'), MyNode('s2')]
x = SCons.Executor.Executor(MyAction(), env, [{}], [t1, t2], sources)
deps = x.scan_targets(None)
assert t1.implicit == ['dep-t1', 'dep-t2'], t1.implicit
assert t2.implicit == ['dep-t1', 'dep-t2'], t2.implicit
t1.implicit = []
t2.implicit = []
deps = x.scan_targets(MyScanner('scanner-'))
assert t1.implicit == ['scanner-t1', 'scanner-t2'], t1.implicit
assert t2.implicit == ['scanner-t1', 'scanner-t2'], t2.implicit
def test_scan_sources(self):
"""Test scanning the sources for implicit dependencies"""
env = MyEnvironment(S='string')
t1 = MyNode('t1')
t2 = MyNode('t2')
sources = [MyNode('s1'), MyNode('s2')]
x = SCons.Executor.Executor(MyAction(), env, [{}], [t1, t2], sources)
deps = x.scan_sources(None)
assert t1.implicit == ['dep-s1', 'dep-s2'], t1.implicit
assert t2.implicit == ['dep-s1', 'dep-s2'], t2.implicit
t1.implicit = []
t2.implicit = []
deps = x.scan_sources(MyScanner('scanner-'))
assert t1.implicit == ['scanner-s1', 'scanner-s2'], t1.implicit
assert t2.implicit == ['scanner-s1', 'scanner-s2'], t2.implicit
def test_get_unignored_sources(self):
"""Test fetching the unignored source list"""
env = MyEnvironment()
s1 = MyNode('s1')
s2 = MyNode('s2')
s3 = MyNode('s3')
x = SCons.Executor.Executor('b', env, [{}], [], [s1, s2, s3])
r = x.get_unignored_sources(None, [])
assert r == [s1, s2, s3], list(map(str, r))
r = x.get_unignored_sources(None, [s2])
assert r == [s1, s3], list(map(str, r))
r = x.get_unignored_sources(None, [s1, s3])
assert r == [s2], list(map(str, r))
def test_changed_sources_for_alwaysBuild(self):
"""
Ensure if a target is marked always build that the sources are always marked changed sources
:return:
"""
env = MyEnvironment()
s1 = MyNode('s1')
s2 = MyNode('s2')
t1 = MyNode('t1')
t1.up_to_date = True
t1.always_build = True
x = SCons.Executor.Executor('b', env, [{}], [t1], [s1, s2])
changed_sources = x._get_changed_sources()
assert changed_sources == [s1, s2], "If target marked AlwaysBuild sources should always be marked changed"
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,169 +0,0 @@
# 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 SCons.Memoize
# Enable memoization counting
SCons.Memoize.EnableMemoization()
class FakeObject:
def __init__(self):
self._memo = {}
def _dict_key(self, argument):
return argument
@SCons.Memoize.CountDictCall(_dict_key)
def dict(self, argument):
memo_key = argument
try:
memo_dict = self._memo['dict']
except KeyError:
memo_dict = {}
self._memo['dict'] = memo_dict
else:
try:
return memo_dict[memo_key]
except KeyError:
pass
result = self.compute_dict(argument)
memo_dict[memo_key] = result
return result
@SCons.Memoize.CountMethodCall
def value(self):
try:
return self._memo['value']
except KeyError:
pass
result = self.compute_value()
self._memo['value'] = result
return result
def get_memoizer_counter(self, name):
return SCons.Memoize.CounterList.get(self.__class__.__name__+'.'+name, None)
class Returner:
def __init__(self, result):
self.result = result
self.calls = 0
def __call__(self, *args, **kw):
self.calls = self.calls + 1
return self.result
class CountDictTestCase(unittest.TestCase):
def test___call__(self):
"""Calling a Memoized dict method
"""
obj = FakeObject()
called = []
fd1 = Returner(1)
fd2 = Returner(2)
obj.compute_dict = fd1
r = obj.dict(11)
assert r == 1, r
obj.compute_dict = fd2
r = obj.dict(12)
assert r == 2, r
r = obj.dict(11)
assert r == 1, r
obj.compute_dict = fd1
r = obj.dict(11)
assert r == 1, r
r = obj.dict(12)
assert r == 2, r
assert fd1.calls == 1, fd1.calls
assert fd2.calls == 1, fd2.calls
c = obj.get_memoizer_counter('dict')
assert c.hit == 3, c.hit
assert c.miss == 2, c.miss
class CountValueTestCase(unittest.TestCase):
def test___call__(self):
"""Calling a Memoized value method
"""
obj = FakeObject()
called = []
fv1 = Returner(1)
fv2 = Returner(2)
obj.compute_value = fv1
r = obj.value()
assert r == 1, r
r = obj.value()
assert r == 1, r
obj.compute_value = fv2
r = obj.value()
assert r == 1, r
r = obj.value()
assert r == 1, r
assert fv1.calls == 1, fv1.calls
assert fv2.calls == 0, fv2.calls
c = obj.get_memoizer_counter('value')
assert c.hit == 3, c.hit
assert c.miss == 1, c.miss
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,117 +0,0 @@
# 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 SCons.Errors
import SCons.Node.Alias
class AliasTestCase(unittest.TestCase):
def test_AliasNameSpace(self):
"""Test creating an Alias name space
"""
ans = SCons.Node.Alias.AliasNameSpace()
assert ans is not None, ans
def test_ANS_Alias(self):
"""Test the Alias() factory
"""
ans = SCons.Node.Alias.AliasNameSpace()
a1 = ans.Alias('a1')
assert a1.name == 'a1', a1.name
a2 = ans.Alias('a1')
assert a1 is a2, (a1, a2)
def test_get_contents(self):
"""Test the get_contents() method
"""
class DummyNode:
def __init__(self, contents):
self.contents = contents
def get_csig(self):
return self.contents
def get_contents(self):
return self.contents
ans = SCons.Node.Alias.AliasNameSpace()
ans.Alias('a1')
a = ans.lookup('a1')
a.sources = [ DummyNode('one'), DummyNode('two'), DummyNode('three') ]
c = a.get_contents()
assert c == 'onetwothree', c
def test_lookup(self):
"""Test the lookup() method
"""
ans = SCons.Node.Alias.AliasNameSpace()
ans.Alias('a1')
a = ans.lookup('a1')
assert a.name == 'a1', a.name
a1 = ans.lookup('a1')
assert a is a1, a1
a = ans.lookup('a2')
assert a is None, a
def test_Alias(self):
"""Test creating an Alias() object
"""
a1 = SCons.Node.Alias.Alias('a')
assert a1.name == 'a', a1.name
a2 = SCons.Node.Alias.Alias('a')
assert a2.name == 'a', a2.name
assert a1 is not a2
assert a1.name == a2.name
class AliasNodeInfoTestCase(unittest.TestCase):
def test___init__(self):
"""Test AliasNodeInfo initialization"""
ans = SCons.Node.Alias.AliasNameSpace()
aaa = ans.Alias('aaa')
ni = SCons.Node.Alias.AliasNodeInfo()
class AliasBuildInfoTestCase(unittest.TestCase):
def test___init__(self):
"""Test AliasBuildInfo initialization"""
ans = SCons.Node.Alias.AliasNameSpace()
aaa = ans.Alias('aaa')
bi = SCons.Node.Alias.AliasBuildInfo()
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +0,0 @@
# 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 SCons.Errors
import SCons.Node.Python
class ValueTestCase(unittest.TestCase):
def test_Value(self):
"""Test creating a Value() object
"""
v1 = SCons.Node.Python.Value('a')
assert v1.value == 'a', v1.value
value2 = 'a'
v2 = SCons.Node.Python.Value(value2)
assert v2.value == value2, v2.value
assert v2.value is value2, v2.value
assert v1 is not v2
assert v1.value == v2.value
v3 = SCons.Node.Python.Value('c', 'cb')
assert v3.built_value == 'cb'
def test_build(self):
"""Test "building" a Value Node
"""
class fake_executor:
def __call__(self, node):
node.write('faked')
v1 = SCons.Node.Python.Value('b', 'built')
v1.executor = fake_executor()
v1.build()
assert v1.built_value == 'built', v1.built_value
v2 = SCons.Node.Python.Value('b')
v2.executor = fake_executor()
v2.build()
assert v2.built_value == 'faked', v2.built_value
v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name')
v3.executor = fake_executor()
v3.build()
assert v3.name == 'name', v3.name
assert v3.built_value == 'faked', v3.built_value
def test_read(self):
"""Test the Value.read() method
"""
v1 = SCons.Node.Python.Value('a')
x = v1.read()
assert x == 'a', x
def test_write(self):
"""Test the Value.write() method
"""
v1 = SCons.Node.Python.Value('a')
assert v1.value == 'a', v1.value
assert not hasattr(v1, 'built_value')
v1.write('new')
assert v1.value == 'a', v1.value
assert v1.built_value == 'new', v1.built_value
def test_get_csig(self):
"""Test calculating the content signature of a Value() object
"""
v1 = SCons.Node.Python.Value('aaa')
csig = v1.get_csig(None)
assert csig == 'aaa', csig
v2 = SCons.Node.Python.Value(7)
csig = v2.get_csig(None)
assert csig == '7', csig
v3 = SCons.Node.Python.Value(None)
csig = v3.get_csig(None)
assert csig == 'None', csig
class ValueNodeInfoTestCase(unittest.TestCase):
def test___init__(self):
"""Test ValueNodeInfo initialization"""
vvv = SCons.Node.Python.Value('vvv')
ni = SCons.Node.Python.ValueNodeInfo()
class ValueBuildInfoTestCase(unittest.TestCase):
def test___init__(self):
"""Test ValueBuildInfo initialization"""
vvv = SCons.Node.Python.Value('vvv')
bi = SCons.Node.Python.ValueBuildInfo()
class ValueChildTestCase(unittest.TestCase):
def test___init__(self):
"""Test support for a Value() being an implicit dependency of a Node"""
value = SCons.Node.Python.Value('v')
node = SCons.Node.Node()
node._func_get_contents = 2 # Pretend to be a Dir.
node.add_to_implicit([value])
contents = node.get_contents()
expected_contents = '%s %s\n' % (value.get_csig(), value.name)
assert contents == expected_contents
class ValueMemoTestCase(unittest.TestCase):
def test_memo(self):
"""Test memoization"""
# First confirm that ValueWithMemo does memoization.
value1 = SCons.Node.Python.ValueWithMemo('vvv')
value2 = SCons.Node.Python.ValueWithMemo('vvv')
assert value1 is value2
# Next confirm that ValueNodeInfo.str_to_node does memoization using
# the same cache as ValueWithMemo.
ni = SCons.Node.Python.ValueNodeInfo()
value3 = ni.str_to_node('vvv')
assert value1 is value3
def test_built_value(self):
"""Confirm that built values are not memoized."""
v1 = SCons.Node.Python.ValueWithMemo('c', 'ca')
v2 = SCons.Node.Python.ValueWithMemo('c', 'ca')
assert v1 is not v2
def test_non_primitive_values(self):
"""Confirm that non-primitive values are not memoized."""
d = {'a': 1}
v1 = SCons.Node.Python.ValueWithMemo(d)
v2 = SCons.Node.Python.ValueWithMemo(d)
assert v1 is not v2
a = [1]
v3 = SCons.Node.Python.ValueWithMemo(a)
v4 = SCons.Node.Python.ValueWithMemo(a)
assert v3 is not v4
def test_value_set_name(self):
""" Confirm setting name and caching takes the name into account """
v1 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name')
v2 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name2')
v3 = SCons.Node.Python.ValueWithMemo('Jibberish')
self.assertEqual(v1.name,'name', msg=v1.name)
self.assertEqual(v2.name,'name2', msg=v2.name)
self.assertEqual(v3.name,'Jibberish', msg=v3.name)
self.assertTrue(v1 is not v2, msg="v1 and v2 should be different as they have different names but same values")
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,193 +0,0 @@
# 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 SCons.PathList
class subst_pathTestCase(unittest.TestCase):
def setUp(self):
class FakeEnvironment:
def __init__(self, **kw):
self.kw = kw
def subst(self, s, target=None, source=None, conv=lambda x: x):
if s[0] == '$':
s = s[1:]
if s == 'target':
s = target
elif s == 'source':
s = source
else:
s = self.kw[s]
return s
self.env = FakeEnvironment(AAA = 'aaa', NULL = '')
from SCons.Environment import Environment
self.env = Environment(AAA = 'aaa', NULL = '')
def test_node(self):
"""Test the subst_path() method on a Node
"""
import SCons.Node
class A:
pass
n = SCons.Node.Node()
pl = SCons.PathList.PathList((n,))
result = pl.subst_path(self.env, 'y', 'z')
assert result == (n,), result
def test_object(self):
"""Test the subst_path() method on a non-Node object
"""
class A:
def __str__(self):
return '<object A>'
a = A()
pl = SCons.PathList.PathList((a,))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('<object A>',), result
def test_object_get(self):
"""Test the subst_path() method on an object with a get() method
"""
class B:
def get(self):
return 'b'
b = B()
pl = SCons.PathList.PathList((b,))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('b',), result
def test_string(self):
"""Test the subst_path() method on a non-substitution string
"""
self.env.subst = lambda s, target, source, conv: 'NOT THIS STRING'
pl = SCons.PathList.PathList(('x',))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('x',), result
def test_subst(self):
"""Test the subst_path() method on substitution strings
"""
pl = SCons.PathList.PathList(('$AAA', '$NULL'))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('aaa',), result
def test_list_of_lists(self):
"""Test the subst_path() method on substitution of nested lists.
"""
pl = SCons.PathList.PathList((['$AAA', '$AAA'], '$NULL'))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('aaa', 'aaa'), result
def test_subst_nested(self):
"""Test the subst_path() method on nested substitution of strings.
"""
self.env.Append(L1 = ['a', 'b'],
L2 = ['c', 'd'],
L3 = ['$L2'])
pl = SCons.PathList.PathList(['$L1'])
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('a', 'b'), result
self.env.Append(L1 = ['$L2'])
pl = SCons.PathList.PathList(['$L1'])
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('a', 'b', 'c', 'd'), result
self.env.Append(L1 = ['$L3'])
pl = SCons.PathList.PathList(['$L1'])
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('a', 'b', 'c', 'd', 'c', 'd'), result
def test_another_env(self):
"""Test the subst_path does lazy evaluation.
"""
pl = SCons.PathList.PathList(('$AAA', '$NULL'))
result = pl.subst_path(self.env, 'y', 'z')
assert result == ('aaa',), result
e = self.env.Clone(AAA = 'bbb')
result = pl.subst_path(e, 'y', 'z')
assert result == ('bbb',), result
class PathListCacheTestCase(unittest.TestCase):
def test_no_PathListCache(self):
"""Make sure the PathListCache class is not visible
"""
try:
SCons.PathList.PathListCache
except AttributeError:
pass
else:
self.fail("Found PathListCache unexpectedly\n")
class PathListTestCase(unittest.TestCase):
def test_PathList(self):
"""Test the PathList() entry point
"""
x1 = SCons.PathList.PathList(('x',))
x2 = SCons.PathList.PathList(['x',])
assert x1 is x2, (x1, x2)
x3 = SCons.PathList.PathList('x')
assert x1 is not x3, (x1, x3)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,330 +0,0 @@
# 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 collections
import unittest
import os
import SCons.compat
import SCons.Errors
import SCons.Platform
import SCons.Environment
import SCons.Action
class Environment(collections.UserDict):
def Detect(self, cmd):
return cmd
def AppendENVPath(self, key, value):
pass
class PlatformTestCase(unittest.TestCase):
def test_Platform(self):
"""Test the Platform() function"""
p = SCons.Platform.Platform('cygwin')
assert str(p) == 'cygwin', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '.exe', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'cygwin', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('os2')
assert str(p) == 'os2', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '.exe', env
assert env['LIBSUFFIX'] == '.lib', env
assert env['HOST_OS'] == 'os2', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('posix')
assert str(p) == 'posix', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'posix', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('irix')
assert str(p) == 'irix', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'irix', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('aix')
assert str(p) == 'aix', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'aix', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('sunos')
assert str(p) == 'sunos', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'sunos', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('hpux')
assert str(p) == 'hpux', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '', env
assert env['LIBSUFFIX'] == '.a', env
assert env['SHELL'] == 'sh', env
assert env['HOST_OS'] == 'hpux', env
assert env['HOST_ARCH'] != '', env
p = SCons.Platform.Platform('win32')
assert str(p) == 'win32', p
env = Environment()
p(env)
assert env['PROGSUFFIX'] == '.exe', env
assert env['LIBSUFFIX'] == '.lib', env
assert env['HOST_OS'] == 'win32', env
assert env['HOST_ARCH'] != '', env
exc_caught = None
try:
p = SCons.Platform.Platform('_does_not_exist_')
except SCons.Errors.UserError:
exc_caught = 1
assert exc_caught, "did not catch expected UserError"
env = Environment()
SCons.Platform.Platform()(env)
assert env != {}, env
def test_win32_no_arch_shell_variables(self):
"""
Test that a usable HOST_ARCH is available when
neither: PROCESSOR_ARCHITEW6432 nor PROCESSOR_ARCHITECTURE
is set for SCons.Platform.win32.get_architecture()
"""
# Save values if defined
PA_6432 = os.environ.get('PROCESSOR_ARCHITEW6432')
PA = os.environ.get('PROCESSOR_ARCHITECTURE')
if PA_6432:
del(os.environ['PROCESSOR_ARCHITEW6432'])
if PA:
del(os.environ['PROCESSOR_ARCHITECTURE'])
p = SCons.Platform.win32.get_architecture()
# restore values
if PA_6432:
os.environ['PROCESSOR_ARCHITEW6432']=PA_6432
if PA:
os.environ['PROCESSOR_ARCHITECTURE']=PA
assert p.arch != '', 'SCons.Platform.win32.get_architecture() not setting arch'
assert p.synonyms != '', 'SCons.Platform.win32.get_architecture() not setting synonyms'
class TempFileMungeTestCase(unittest.TestCase):
def test_MAXLINELENGTH(self):
""" Test different values for MAXLINELENGTH with the same
size command string to ensure that the temp file mechanism
kicks in only at MAXLINELENGTH+1, or higher
"""
# Init class with cmd, such that the fully expanded
# string reads "a test command line".
# Note, how we're using a command string here that is
# actually longer than the substituted one. This is to ensure
# that the TempFileMunge class internally really takes the
# length of the expanded string into account.
defined_cmd = "a $VERY $OVERSIMPLIFIED line"
t = SCons.Platform.TempFileMunge(defined_cmd)
env = SCons.Environment.SubstitutionEnvironment(tools=[])
# Setting the line length high enough...
env['MAXLINELENGTH'] = 1024
env['VERY'] = 'test'
env['OVERSIMPLIFIED'] = 'command'
expanded_cmd = env.subst(defined_cmd)
# Call the tempfile munger
cmd = t(None, None, env, 0)
assert cmd == defined_cmd, cmd
# Let MAXLINELENGTH equal the string's length
env['MAXLINELENGTH'] = len(expanded_cmd)
cmd = t(None, None, env, 0)
assert cmd == defined_cmd, cmd
# Finally, let the actual tempfile mechanism kick in
# Disable printing of actions...
old_actions = SCons.Action.print_actions
SCons.Action.print_actions = 0
env['MAXLINELENGTH'] = len(expanded_cmd)-1
cmd = t(None, None, env, 0)
# ...and restoring its setting.
SCons.Action.print_actions = old_actions
assert cmd != defined_cmd, cmd
def test_TEMPFILEARGJOINBYTE(self):
"""
Test argument join byte TEMPFILEARGJOINBYTE
"""
# Init class with cmd, such that the fully expanded
# string reads "a test command line".
# Note, how we're using a command string here that is
# actually longer than the substituted one. This is to ensure
# that the TempFileMunge class internally really takes the
# length of the expanded string into account.
defined_cmd = "a $VERY $OVERSIMPLIFIED line"
t = SCons.Platform.TempFileMunge(defined_cmd)
env = SCons.Environment.SubstitutionEnvironment(tools=[])
# Setting the line length high enough...
env['MAXLINELENGTH'] = 1024
env['VERY'] = 'test'
env['OVERSIMPLIFIED'] = 'command'
env['TEMPFILEARGJOINBYTE'] = os.linesep
expanded_cmd = env.subst(defined_cmd)
# For tempfilemunge to operate.
old_actions = SCons.Action.print_actions
SCons.Action.print_actions = 0
env['MAXLINELENGTH'] = len(expanded_cmd)-1
cmd = t(None, None, env, 0)
# print("CMD is:%s"%cmd)
with open(cmd[-1],'rb') as f:
file_content = f.read()
# print("Content is:[%s]"%file_content)
# ...and restoring its setting.
SCons.Action.print_actions = old_actions
assert file_content != env['TEMPFILEARGJOINBYTE'].join(['test','command','line'])
def test_TEMPFILEARGESCFUNC(self):
"""
Test a custom TEMPFILEARGESCFUNC
"""
def _tempfile_arg_esc_func(arg):
return str(arg).replace("line", "newarg")
defined_cmd = "a $VERY $OVERSIMPLIFIED line"
t = SCons.Platform.TempFileMunge(defined_cmd)
env = SCons.Environment.SubstitutionEnvironment(tools=[])
# Setting the line length high enough...
env['MAXLINELENGTH'] = 5
env['VERY'] = 'test'
env['OVERSIMPLIFIED'] = 'command'
# For tempfilemunge to operate.
old_actions = SCons.Action.print_actions
SCons.Action.print_actions = 0
env['TEMPFILEARGESCFUNC'] = _tempfile_arg_esc_func
cmd = t(None, None, env, 0)
# print("CMD is: %s"%cmd)
with open(cmd[-1], 'rb') as f:
file_content = f.read()
# print("Content is:[%s]"%file_content)
# # ...and restoring its setting.
SCons.Action.print_actions = old_actions
assert b"newarg" in file_content
def test_tempfilecreation_once(self):
"""
Init class with cmd, such that the fully expanded
string reads "a test command line".
Note, how we're using a command string here that is
actually longer than the substituted one. This is to ensure
that the TempFileMunge class internally really takes the
length of the expanded string into account.
"""
defined_cmd = "a $VERY $OVERSIMPLIFIED line"
t = SCons.Platform.TempFileMunge(defined_cmd)
env = SCons.Environment.SubstitutionEnvironment(tools=[])
# Setting the line length high enough...
env['VERY'] = 'test'
env['OVERSIMPLIFIED'] = 'command'
expanded_cmd = env.subst(defined_cmd)
env['MAXLINELENGTH'] = len(expanded_cmd)-1
# Disable printing of actions...
old_actions = SCons.Action.print_actions
SCons.Action.print_actions = 0
# Create an instance of object derived class to allow setattrb
class Node:
class Attrs:
pass
def __init__(self):
self.attributes = self.Attrs()
target = [Node()]
cmd = t(target, None, env, 0)
# ...and restoring its setting.
SCons.Action.print_actions = old_actions
assert cmd != defined_cmd, cmd
assert cmd == target[0].attributes.tempfile_cmdlist[defined_cmd]
class PlatformEscapeTestCase(unittest.TestCase):
def test_posix_escape(self):
""" Check that paths with parens are escaped properly
"""
import SCons.Platform.posix
test_string = "/my (really) great code/main.cpp"
output = SCons.Platform.posix.escape(test_string)
# We expect the escape function to wrap the string
# in quotes, but not escape any internal characters
# in the test_string. (Parens doesn't require shell
# escaping if their quoted)
assert output[1:-1] == test_string
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,240 +0,0 @@
# 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 collections
import unittest
import os
import sys
import SCons.compat
import SCons.Platform.virtualenv
import SCons.Util
class Environment(collections.UserDict):
def Detect(self, cmd):
return cmd
def AppendENVPath(self, key, value):
if SCons.Util.is_List(value):
value = os.path.pathsep.join(value)
if 'ENV' not in self:
self['ENV'] = {}
current = self['ENV'].get(key)
if not current:
self['ENV'][key] = value
else:
self['ENV'][key] = os.path.pathsep.join([current, value])
def PrependENVPath(self, key, value):
if SCons.Util.is_List(value):
value = os.path.pathsep.join(value)
if 'ENV' not in self:
self['ENV'] = {}
current = self['ENV'].get(key)
if not current:
self['ENV'][key] = value
else:
self['ENV'][key] = os.path.pathsep.join([value, current])
class SysPrefixes:
"""Used to temporarily mock sys.prefix, sys.real_prefix and sys.base_prefix"""
def __init__(self, prefix, real_prefix=None, base_prefix=None):
self._prefix = prefix
self._real_prefix = real_prefix
self._base_prefix = base_prefix
def start(self):
self._store()
sys.prefix = self._prefix
if self._real_prefix is None:
if hasattr(sys, 'real_prefix'):
del sys.real_prefix
else:
sys.real_prefix = self._real_prefix
if self._base_prefix is None:
if hasattr(sys, 'base_prefix'):
del sys.base_prefix
else:
sys.base_prefix = self._base_prefix
def stop(self):
self._restore()
def __enter__(self):
self.start()
attrs = ('prefix', 'real_prefix', 'base_prefix')
return {k: getattr(sys, k) for k in attrs if hasattr(sys, k)}
def __exit__(self, *args):
self.stop()
def _store(self):
s = dict()
if hasattr(sys, 'real_prefix'):
s['real_prefix'] = sys.real_prefix
if hasattr(sys, 'base_prefix'):
s['base_prefix'] = sys.base_prefix
s['prefix'] = sys.prefix
self._stored = s
def _restore(self):
s = self._stored
if 'real_prefix' in s:
sys.real_prefix = s['real_prefix']
if 'base_prefix' in s:
sys.base_prefix = s['base_prefix']
if 'prefix' in s:
sys.prefix = s['prefix']
del self._stored
def _p(p):
"""Converts path string **p** from posix format to os-specific format."""
drive = []
if p.startswith('/') and sys.platform == 'win32':
drive = ['C:']
pieces = p.split('/')
return os.path.sep.join(drive + pieces)
class _is_path_in_TestCase(unittest.TestCase):
def test_false(self):
for args in [ ('',''),
('', _p('/foo/bar')),
(_p('/foo/bar'), ''),
(_p('/foo/bar'), _p('/foo/bar')),
(_p('/foo/bar'), _p('/foo/bar/geez')),
(_p('/'), _p('/foo')),
(_p('foo'), _p('foo/bar')) ]:
assert SCons.Platform.virtualenv._is_path_in(*args) is False, "_is_path_in(%r, %r) should be False" % args
def test__true(self):
for args in [ (_p('/foo'), _p('/')),
(_p('/foo/bar'), _p('/foo')),
(_p('/foo/bar/geez'), _p('/foo/bar')),
(_p('/foo//bar//geez'), _p('/foo/bar')),
(_p('/foo/bar/geez'), _p('/foo//bar')),
(_p('/foo/bar/geez'), _p('//foo//bar')) ]:
assert SCons.Platform.virtualenv._is_path_in(*args) is True, "_is_path_in(%r, %r) should be True" % args
class IsInVirtualenvTestCase(unittest.TestCase):
def test_false(self):
# "without wirtualenv" - always false
with SysPrefixes(_p('/prefix')):
for p in [ _p(''),
_p('/foo'),
_p('/prefix'),
_p('/prefix/foo') ]:
assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p
# "with virtualenv"
with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')):
for p in [ _p(''),
_p('/real/prefix/foo'),
_p('/virtualenv/prefix'),
_p('/virtualenv/prefix/bar/..'),
_p('/virtualenv/prefix/bar/../../bleah'),
_p('/virtualenv/bleah') ]:
assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p
# "with venv"
with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')):
for p in [ _p(''),
_p('/base/prefix/foo'),
_p('/virtualenv/prefix'),
_p('/virtualenv/prefix/bar/..'),
_p('/virtualenv/prefix/bar/../../bleah'),
_p('/virtualenv/bleah') ]:
assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p
def test_true(self):
# "with virtualenv"
with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')):
for p in [ _p('/virtualenv/prefix/foo'),
_p('/virtualenv/prefix/foo/bar') ]:
assert SCons.Platform.virtualenv.IsInVirtualenv(p) is True, "IsInVirtualenv(%r) should be True" % p
# "with venv"
with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')):
for p in [ _p('/virtualenv/prefix/foo'),
_p('/virtualenv/prefix/foo/bar') ]:
assert SCons.Platform.virtualenv.IsInVirtualenv(p) is True, "IsInVirtualenv(%r) should be True" % p
class _inject_venv_pathTestCase(unittest.TestCase):
def path_list(self):
return [
_p('/virtualenv/prefix/bin'),
_p('/virtualenv/prefix'),
_p('/virtualenv/prefix/../bar'),
_p('/home/user/.local/bin'),
_p('/usr/bin'),
_p('/opt/bin')
]
def test_with_path_string(self):
env = Environment()
path_string = os.path.pathsep.join(self.path_list())
with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')):
SCons.Platform.virtualenv._inject_venv_path(env, path_string)
assert env['ENV']['PATH'] == _p('/virtualenv/prefix/bin'), env['ENV']['PATH']
def test_with_path_list(self):
env = Environment()
with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')):
SCons.Platform.virtualenv._inject_venv_path(env, self.path_list())
assert env['ENV']['PATH'] == _p('/virtualenv/prefix/bin'), env['ENV']['PATH']
class VirtualenvTestCase(unittest.TestCase):
def test_none(self):
def _msg(given):
return "Virtualenv() should be None, not %s" % repr(given)
with SysPrefixes(_p('/prefix')):
ve = SCons.Platform.virtualenv.Virtualenv()
assert ve is None , _msg(ve)
with SysPrefixes(_p('/base/prefix'), base_prefix=_p('/base/prefix')):
ve = SCons.Platform.virtualenv.Virtualenv()
assert ve is None, _msg(ve)
def test_not_none(self):
def _msg(expected, given):
return "Virtualenv() should == %r, not %s" % (_p(expected), repr(given))
with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')):
ve = SCons.Platform.virtualenv.Virtualenv()
assert ve == _p('/virtualenv/prefix'), _msg('/virtualenv/prefix', ve)
with SysPrefixes(_p('/same/prefix'), real_prefix=_p('/same/prefix')):
ve = SCons.Platform.virtualenv.Virtualenv()
assert ve == _p('/same/prefix'), _msg('/same/prefix', ve)
with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')):
ve = SCons.Platform.virtualenv.Virtualenv()
assert ve == _p('/virtualenv/prefix'), _msg('/virtualenv/prefix', ve)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,783 +0,0 @@
# 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 io
import os
import re
import sys
from types import ModuleType
import unittest
import TestCmd
sys.stdout = io.StringIO()
if sys.platform == 'win32':
existing_lib = "msvcrt"
else:
existing_lib = "m"
class SConfTestCase(unittest.TestCase):
def setUp(self):
# we always want to start with a clean directory
self.save_cwd = os.getcwd()
self.test = TestCmd.TestCmd(workdir = '')
os.chdir(self.test.workpath(''))
def tearDown(self):
self.test.cleanup()
import SCons.SConsign
SCons.SConsign.Reset()
os.chdir(self.save_cwd)
def _resetSConfState(self):
# Ok, this is tricky, and i do not know, if everything is sane.
# We try to reset scons' state (including all global variables)
import SCons.SConsign
SCons.SConsign.write() # simulate normal scons-finish
for n in list(sys.modules.keys()):
if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat':
m = sys.modules[n]
if isinstance(m, ModuleType):
# if this is really a scons module, clear its namespace
del sys.modules[n]
m.__dict__.clear()
# we only use SCons.Environment and SCons.SConf for these tests.
import SCons.Environment
import SCons.SConf
self.Environment = SCons.Environment
self.SConf = SCons.SConf
# and we need a new environment, cause references may point to
# old modules (well, at least this is safe ...)
self.scons_env = self.Environment.Environment()
self.scons_env.AppendENVPath('PATH', os.environ['PATH'])
# we want to do some autodetection here
# this stuff works with
# - cygwin on Windows (using cmd.exe, not bash)
# - posix
# - msvc on Windows (hopefully)
if (not self.scons_env.Detect( self.scons_env.subst('$CXX') ) or
not self.scons_env.Detect( self.scons_env.subst('$CC') ) or
not self.scons_env.Detect( self.scons_env.subst('$LINK') )):
raise Exception("This test needs an installed compiler!")
if self.scons_env['CXX'] == 'g++':
global existing_lib
existing_lib = 'm'
def _baseTryXXX(self, TryFunc):
# TryCompile and TryLink are much the same, so we can test them
# in one method, we pass the function as a string ('TryCompile',
# 'TryLink'), so we are aware of reloading modules.
def checks(self, sconf, TryFuncString):
TryFunc = self.SConf.SConfBase.__dict__[TryFuncString]
res1 = TryFunc( sconf, "int main(void) { return 0; }\n", ".c" )
res2 = TryFunc( sconf,
'#include "no_std_header.h"\nint main(void) {return 0; }\n',
'.c' )
return (res1,res2)
# 1. test initial behaviour (check ok / failed)
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
res = checks( self, sconf, TryFunc )
assert res[0] and not res[1], res
finally:
sconf.Finish()
# 2.1 test the error caching mechanism (no dependencies have changed)
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
res = checks( self, sconf, TryFunc )
assert res[0] and not res[1], res
finally:
sconf.Finish()
# we should have exactly one one error cached
log = str(self.test.read( self.test.workpath('config.log') ))
expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
firstOcc = expr.match( log )
assert firstOcc is not None, log
secondOcc = expr.match( log, firstOcc.end(0) )
assert secondOcc is None, log
# 2.2 test the error caching mechanism (dependencies have changed)
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
no_std_header_h = self.test.workpath('config.tests', 'no_std_header.h')
test_h = self.test.write( no_std_header_h,
"/* we are changing a dependency now */\n" )
try:
res = checks( self, sconf, TryFunc )
log = self.test.read( self.test.workpath('config.log') )
assert res[0] and res[1], res
finally:
sconf.Finish()
def test_TryBuild(self):
"""Test SConf.TryBuild
"""
# 1 test that we can try a builder that returns a list of nodes
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
import SCons.Builder
import SCons.Node
class MyAction:
def get_contents(self, target, source, env):
return 'MyBuilder-MyAction $SOURCE $TARGET'
class Attrs:
__slots__ = ('shared', '__dict__')
class MyBuilder(SCons.Builder.BuilderBase):
def __init__(self):
self.prefix = ''
self.suffix = ''
# need action because temporary file name uses hash of actions get_contents()
self.action = MyAction()
def __call__(self, env, target, source, *args, **kw):
class MyNode:
def __init__(self, name):
self.name = name
self.state = SCons.Node.no_state
self.waiting_parents = set()
self.side_effects = []
self.builder = None
self.prerequisites = None
self.attributes = Attrs()
def disambiguate(self):
return self
def has_builder(self):
return 1
def add_pre_action(self, *actions):
pass
def add_post_action(self, *actions):
pass
def children(self, scan = 1):
return []
def get_state(self):
return self.state
def set_state(self, state):
self.state = state
def alter_targets(self):
return [], None
def depends_on(self, nodes):
return None
def postprocess(self):
pass
def clear(self):
pass
def is_up_to_date(self):
return None
def prepare(self):
pass
def push_to_cache(self):
pass
def retrieve_from_cache(self):
return 0
def build(self, **kw):
return
def built(self):
pass
def get_stored_info(self):
pass
def get_executor(self):
class Executor:
def __init__(self, targets):
self.targets = targets
def get_all_targets(self):
return self.targets
return Executor([self])
return [MyNode('n1'), MyNode('n2')]
try:
self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
sconf.TryBuild(self.scons_env.SConfActionBuilder)
finally:
sconf.Finish()
def test_TryCompile(self):
"""Test SConf.TryCompile
"""
self._baseTryXXX( "TryCompile" ) #self.SConf.SConf.TryCompile )
def test_TryLink(self):
"""Test SConf.TryLink
"""
self._baseTryXXX( "TryLink" ) #self.SConf.SConf.TryLink )
def test_TryRun(self):
"""Test SConf.TryRun
"""
def checks(sconf):
prog = """
#include <stdio.h>
int main(void) {
printf( "Hello" );
return 0;
}
"""
res1 = sconf.TryRun( prog, ".c" )
res2 = sconf.TryRun( "not a c program\n", ".c" )
return (res1, res2)
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
res = checks(sconf)
assert res[0][0] and res[0][1] == "Hello", res
assert not res[1][0] and res[1][1] == "", res
finally:
sconf.Finish()
log = self.test.read( self.test.workpath('config.log') )
# test the caching mechanism
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
res = checks(sconf)
assert res[0][0] and res[0][1] == "Hello", res
assert not res[1][0] and res[1][1] == "", res
finally:
sconf.Finish()
# we should have exactly one error cached
# creating string here because it's bytes by default on py3
log = str(self.test.read( self.test.workpath('config.log') ))
expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
firstOcc = expr.match( log )
assert firstOcc is not None, log
secondOcc = expr.match( log, firstOcc.end(0) )
assert secondOcc is None, log
def test_TryAction(self):
"""Test SConf.TryAction
"""
def actionOK(target, source, env):
with open(str(target[0]), "w") as f:
f.write("RUN OK\n")
return None
def actionFAIL(target, source, env):
return 1
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
(ret, output) = sconf.TryAction(action=actionOK)
assert ret and output.encode('utf-8') == bytearray("RUN OK"+os.linesep, 'utf-8'), (ret, output)
(ret, output) = sconf.TryAction(action=actionFAIL)
assert not ret and output == "", (ret, output)
finally:
sconf.Finish()
def _test_check_compilers(self, comp, func, name):
"""This is the implementation for CheckCC and CheckCXX tests."""
from copy import deepcopy
# Check that Check* works
r = func()
assert r, "could not find %s ?" % comp
# Check that Check* does fail if comp is not available in env
oldcomp = deepcopy(self.scons_env[comp])
del self.scons_env[comp]
r = func()
assert not r, "%s worked wo comp ?" % name
# Check that Check* does fail if comp is set but empty
self.scons_env[comp] = ''
r = func()
assert not r, "%s worked with comp = '' ?" % name
# Check that Check* does fail if comp is set to buggy executable
self.scons_env[comp] = 'thiscccompilerdoesnotexist'
r = func()
assert not r, "%s worked with comp = thiscompilerdoesnotexist ?" % name
# Check that Check* does fail if CFLAGS is buggy
self.scons_env[comp] = oldcomp
self.scons_env['%sFLAGS' % comp] = '/WX qwertyuiop.c'
r = func()
assert not r, "%s worked with %sFLAGS = qwertyuiop ?" % (name, comp)
def test_CheckCC(self):
"""Test SConf.CheckCC()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
try:
self._test_check_compilers('CC', sconf.CheckCC, 'CheckCC')
except AssertionError:
sys.stderr.write(self.test.read('config.log', mode='r'))
raise
finally:
sconf.Finish()
def test_CheckSHCC(self):
"""Test SConf.CheckSHCC()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
try:
self._test_check_compilers('SHCC', sconf.CheckSHCC, 'CheckSHCC')
except AssertionError:
sys.stderr.write(self.test.read('config.log', mode='r'))
raise
finally:
sconf.Finish()
def test_CheckCXX(self):
"""Test SConf.CheckCXX()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
try:
self._test_check_compilers('CXX', sconf.CheckCXX, 'CheckCXX')
except AssertionError:
sys.stderr.write(self.test.read('config.log', mode='r'))
raise
finally:
sconf.Finish()
def test_CheckSHCXX(self):
"""Test SConf.CheckSHCXX()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
try:
self._test_check_compilers('SHCXX', sconf.CheckSHCXX, 'CheckSHCXX')
except AssertionError:
sys.stderr.write(self.test.read('config.log', mode='r'))
raise
finally:
sconf.Finish()
def test_CheckHeader(self):
"""Test SConf.CheckHeader()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckHeader()
r = sconf.CheckHeader( "stdio.h", include_quotes="<>", language="C" )
assert r, "did not find stdio.h"
r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C" )
assert not r, "unexpectedly found HopefullyNoHeader.noh"
r = sconf.CheckHeader( "vector", include_quotes="<>", language="C++" )
assert r, "did not find vector"
r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C++" )
assert not r, "unexpectedly found HopefullyNoHeader.noh"
finally:
sconf.Finish()
def test_CheckCHeader(self):
"""Test SConf.CheckCHeader()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckCHeader()
r = sconf.CheckCHeader( "stdio.h", include_quotes="<>" )
assert r, "did not find stdio.h"
r = sconf.CheckCHeader( ["math.h", "stdio.h"], include_quotes="<>" )
assert r, "did not find stdio.h, #include math.h first"
r = sconf.CheckCHeader( "HopefullyNoCHeader.noh" )
assert not r, "unexpectedly found HopefullyNoCHeader.noh"
finally:
sconf.Finish()
def test_CheckCXXHeader(self):
"""Test SConf.CheckCXXHeader()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckCXXHeader()
r = sconf.CheckCXXHeader( "vector", include_quotes="<>" )
assert r, "did not find vector"
r = sconf.CheckCXXHeader( ["stdio.h", "vector"], include_quotes="<>" )
assert r, "did not find vector, #include stdio.h first"
r = sconf.CheckCXXHeader( "HopefullyNoCXXHeader.noh" )
assert not r, "unexpectedly found HopefullyNoCXXHeader.noh"
finally:
sconf.Finish()
def test_CheckLib(self):
"""Test SConf.CheckLib()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckLib()
r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
assert r, "did not find %s" % existing_lib
r = sconf.CheckLib( "hopefullynolib", "main", autoadd=0 )
assert not r, "unexpectedly found hopefullynolib"
# CheckLib() with list of libs
r = sconf.CheckLib( [existing_lib], "main", autoadd=0 )
assert r, "did not find %s" % existing_lib
r = sconf.CheckLib( ["hopefullynolib"], "main", autoadd=0 )
assert not r, "unexpectedly found hopefullynolib"
# This is a check that a null list doesn't find functions
# that are in libraries that must be explicitly named.
# This works on POSIX systems where you have to -lm to
# get the math functions, but it fails on Visual Studio
# where you apparently get all those functions for free.
# Comment out this check until someone who understands
# Visual Studio better can come up with a corresponding
# test (if that ever really becomes necessary).
#r = sconf.CheckLib( [], "sin", autoadd=0 )
#assert not r, "unexpectedly found nonexistent library"
r = sconf.CheckLib( [existing_lib,"hopefullynolib"], "main", autoadd=0 )
assert r, "did not find %s,%s " % (existing_lib,r)
r = sconf.CheckLib( ["hopefullynolib",existing_lib], "main", autoadd=0 )
assert r, "did not find %s " % existing_lib
# CheckLib() with autoadd
def libs(env):
return env.get('LIBS', [])
env = sconf.env.Clone()
try:
r = sconf.CheckLib( existing_lib, "main", autoadd=1 )
assert r, "did not find main in %s" % existing_lib
expect = libs(env) + [existing_lib]
got = libs(sconf.env)
assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
sconf.env = env.Clone()
r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
assert r, "did not find main in %s" % existing_lib
expect = libs(env)
got = libs(sconf.env)
assert got == expect, "before and after LIBS were not the same"
finally:
sconf.env = env
finally:
sconf.Finish()
def test_CheckLibWithHeader(self):
"""Test SConf.CheckLibWithHeader()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckLibWithHeader()
r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
assert r, "did not find %s" % existing_lib
r = sconf.CheckLibWithHeader( existing_lib, ["stdio.h", "math.h"], "C", autoadd=0 )
assert r, "did not find %s, #include stdio.h first" % existing_lib
r = sconf.CheckLibWithHeader( "hopefullynolib", "math.h", "C", autoadd=0 )
assert not r, "unexpectedly found hopefullynolib"
# CheckLibWithHeader() with lists of libs
r = sconf.CheckLibWithHeader( [existing_lib], "math.h", "C", autoadd=0 )
assert r, "did not find %s" % existing_lib
r = sconf.CheckLibWithHeader( [existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
assert r, "did not find %s, #include stdio.h first" % existing_lib
# This is a check that a null list doesn't find functions
# that are in libraries that must be explicitly named.
# This works on POSIX systems where you have to -lm to
# get the math functions, but it fails on Visual Studio
# where you apparently get all those functions for free.
# Comment out this check until someone who understands
# Visual Studio better can come up with a corresponding
# test (if that ever really becomes necessary).
#r = sconf.CheckLibWithHeader( [], "math.h", "C", call="sin(3);", autoadd=0 )
#assert not r, "unexpectedly found non-existent library"
r = sconf.CheckLibWithHeader( ["hopefullynolib"], "math.h", "C", autoadd=0 )
assert not r, "unexpectedly found hopefullynolib"
r = sconf.CheckLibWithHeader( ["hopefullynolib",existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
assert r, "did not find %s, #include stdio.h first" % existing_lib
r = sconf.CheckLibWithHeader( [existing_lib,"hopefullynolib"], ["stdio.h", "math.h"], "C", autoadd=0 )
assert r, "did not find %s, #include stdio.h first" % existing_lib
# CheckLibWithHeader with autoadd
def libs(env):
return env.get('LIBS', [])
env = sconf.env.Clone()
try:
r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
assert r, "did not find math.h with %s" % existing_lib
expect = libs(env) + [existing_lib]
got = libs(sconf.env)
assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
sconf.env = env.Clone()
r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
assert r, "did not find math.h with %s" % existing_lib
expect = libs(env)
got = libs(sconf.env)
assert got == expect, "before and after LIBS were not the same"
finally:
sconf.env = env
finally:
sconf.Finish()
def test_CheckFunc(self):
"""Test SConf.CheckFunc()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckFunc()
r = sconf.CheckFunc('strcpy')
assert r, "did not find strcpy"
r = sconf.CheckFunc('strcpy', '/* header */ char strcpy();')
assert r, "did not find strcpy"
r = sconf.CheckFunc('hopefullynofunction')
assert not r, "unexpectedly found hopefullynofunction"
finally:
sconf.Finish()
def test_CheckProg(self):
"""Test SConf.CheckProg()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
if os.name != 'nt':
r = sconf.CheckProg('sh')
assert r, "/bin/sh"
else:
r = sconf.CheckProg('cmd.exe')
self.assertIn('cmd.exe',r)
r = sconf.CheckProg('hopefully-not-a-program')
assert r is None
finally:
sconf.Finish()
def test_Define(self):
"""Test SConf.Define()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'),
config_h = self.test.workpath('config.h'))
try:
# XXX: we test the generated config.h string. This is not so good,
# ideally, we would like to test if the generated file included in
# a test program does what we want.
# Test defining one symbol wo value
sconf.config_h_text = ''
sconf.Define('YOP')
assert sconf.config_h_text == '#define YOP\n'
# Test defining one symbol with integer value
sconf.config_h_text = ''
sconf.Define('YOP', 1)
assert sconf.config_h_text == '#define YOP 1\n'
# Test defining one symbol with string value
sconf.config_h_text = ''
sconf.Define('YOP', '"YIP"')
assert sconf.config_h_text == '#define YOP "YIP"\n'
# Test defining one symbol with string value
sconf.config_h_text = ''
sconf.Define('YOP', "YIP")
assert sconf.config_h_text == '#define YOP YIP\n'
finally:
sconf.Finish()
def test_CheckTypeSize(self):
"""Test SConf.CheckTypeSize()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckTypeSize()
# In ANSI C, sizeof(char) == 1.
r = sconf.CheckTypeSize('char', expect = 1)
assert r == 1, "sizeof(char) != 1 ??"
r = sconf.CheckTypeSize('char', expect = 0)
assert r == 0, "sizeof(char) == 0 ??"
r = sconf.CheckTypeSize('char', expect = 2)
assert r == 0, "sizeof(char) == 2 ??"
r = sconf.CheckTypeSize('char')
assert r == 1, "sizeof(char) != 1 ??"
r = sconf.CheckTypeSize('const unsigned char')
assert r == 1, "sizeof(const unsigned char) != 1 ??"
# Checking C++
r = sconf.CheckTypeSize('const unsigned char', language = 'C++')
assert r == 1, "sizeof(const unsigned char) != 1 ??"
# Checking Non-existing type
r = sconf.CheckTypeSize('thistypedefhasnotchancetosexist_scons')
assert r == 0, \
"Checking size of thistypedefhasnotchancetosexist_scons succeeded ?"
finally:
sconf.Finish()
def test_CheckDeclaration(self):
"""Test SConf.CheckDeclaration()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# In ANSI C, malloc should be available in stdlib
r = sconf.CheckDeclaration('malloc', includes = "#include <stdlib.h>")
assert r, "malloc not declared ??"
# For C++, __cplusplus should be declared
r = sconf.CheckDeclaration('__cplusplus', language = 'C++')
assert r, "__cplusplus not declared in C++ ??"
r = sconf.CheckDeclaration('__cplusplus', language = 'C')
assert not r, "__cplusplus declared in C ??"
r = sconf.CheckDeclaration('unknown', language = 'Unknown')
assert not r, "unknown language was supported ??"
finally:
sconf.Finish()
def test_(self):
"""Test SConf.CheckType()
"""
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
# CheckType()
r = sconf.CheckType('off_t', '#include <sys/types.h>\n')
assert r, "did not find off_t"
r = sconf.CheckType('hopefullynotypedef_not')
assert not r, "unexpectedly found hopefullynotypedef_not"
finally:
sconf.Finish()
def test_CustomChecks(self):
"""Test Custom Checks
"""
def CheckCustom(test):
test.Message( "Checking UserTest ... " )
prog = """
#include <stdio.h>
int main(void) {
printf( "Hello" );
return 0;
}
"""
(ret, output) = test.TryRun( prog, ".c" )
test.Result( ret )
assert ret and output == "Hello", (ret, output)
return ret
self._resetSConfState()
sconf = self.SConf.SConf(self.scons_env,
custom_tests={'CheckCustom': CheckCustom},
conf_dir=self.test.workpath('config.tests'),
log_file=self.test.workpath('config.log'))
try:
ret = sconf.CheckCustom()
assert ret, ret
finally:
sconf.Finish()
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,390 +0,0 @@
# 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 os
import unittest
import TestCmd
import SCons.dblite
import SCons.SConsign
from SCons.Util import get_hash_format, get_current_hash_algorithm_used
class BuildInfo:
def merge(self, object):
pass
class DummySConsignEntry:
def __init__(self, name):
self.name = name
self.binfo = BuildInfo()
def convert_to_sconsign(self):
self.c_to_s = 1
def convert_from_sconsign(self, dir, name):
self.c_from_s = 1
class FS:
def __init__(self, top):
self.Top = top
self.Top.repositories = []
class DummyNode:
def __init__(self, path='not_a_valid_path', binfo=None):
self.path = path
self.tpath = path
self.fs = FS(self)
self.binfo = binfo
def get_stored_info(self):
return self.binfo
def get_binfo(self):
return self.binfo
def get_internal_path(self):
return self.path
def get_tpath(self):
return self.tpath
class SConsignTestCase(unittest.TestCase):
def setUp(self):
self.save_cwd = os.getcwd()
self.test = TestCmd.TestCmd(workdir = '')
os.chdir(self.test.workpath(''))
def tearDown(self):
self.test.cleanup()
SCons.SConsign.Reset()
os.chdir(self.save_cwd)
class BaseTestCase(SConsignTestCase):
def test_Base(self):
aaa = DummySConsignEntry('aaa')
bbb = DummySConsignEntry('bbb')
bbb.arg1 = 'bbb arg1'
ccc = DummySConsignEntry('ccc')
ccc.arg2 = 'ccc arg2'
f = SCons.SConsign.Base()
f.set_entry('aaa', aaa)
f.set_entry('bbb', bbb)
#f.merge()
e = f.get_entry('aaa')
assert e == aaa, e
assert e.name == 'aaa', e.name
e = f.get_entry('bbb')
assert e == bbb, e
assert e.name == 'bbb', e.name
assert e.arg1 == 'bbb arg1', e.arg1
assert not hasattr(e, 'arg2'), e
f.set_entry('bbb', ccc)
e = f.get_entry('bbb')
assert e.name == 'ccc', e.name
assert not hasattr(e, 'arg1'), e
assert e.arg2 == 'ccc arg2', e.arg1
ddd = DummySConsignEntry('ddd')
eee = DummySConsignEntry('eee')
fff = DummySConsignEntry('fff')
fff.arg = 'fff arg'
f = SCons.SConsign.Base()
f.set_entry('ddd', ddd)
f.set_entry('eee', eee)
e = f.get_entry('ddd')
assert e == ddd, e
assert e.name == 'ddd', e.name
e = f.get_entry('eee')
assert e == eee, e
assert e.name == 'eee', e.name
assert not hasattr(e, 'arg'), e
f.set_entry('eee', fff)
e = f.get_entry('eee')
assert e.name == 'fff', e.name
assert e.arg == 'fff arg', e.arg
def test_store_info(self):
aaa = DummySConsignEntry('aaa')
bbb = DummySConsignEntry('bbb')
bbb.arg1 = 'bbb arg1'
ccc = DummySConsignEntry('ccc')
ccc.arg2 = 'ccc arg2'
f = SCons.SConsign.Base()
f.store_info('aaa', DummyNode('aaa', aaa))
f.store_info('bbb', DummyNode('bbb', bbb))
try:
e = f.get_entry('aaa')
except KeyError:
pass
else:
raise Exception("unexpected entry %s" % e)
try:
e = f.get_entry('bbb')
except KeyError:
pass
else:
raise Exception("unexpected entry %s" % e)
f.merge()
e = f.get_entry('aaa')
assert e == aaa, "aaa = %s, e = %s" % (aaa, e)
assert e.name == 'aaa', e.name
e = f.get_entry('bbb')
assert e == bbb, "bbb = %s, e = %s" % (bbb, e)
assert e.name == 'bbb', e.name
assert e.arg1 == 'bbb arg1', e.arg1
assert not hasattr(e, 'arg2'), e
f.store_info('bbb', DummyNode('bbb', ccc))
e = f.get_entry('bbb')
assert e == bbb, e
assert e.name == 'bbb', e.name
assert e.arg1 == 'bbb arg1', e.arg1
assert not hasattr(e, 'arg2'), e
f.merge()
e = f.get_entry('bbb')
assert e.name == 'ccc', e.name
assert not hasattr(e, 'arg1'), e
assert e.arg2 == 'ccc arg2', e.arg1
ddd = DummySConsignEntry('ddd')
eee = DummySConsignEntry('eee')
fff = DummySConsignEntry('fff')
fff.arg = 'fff arg'
f = SCons.SConsign.Base()
f.store_info('ddd', DummyNode('ddd', ddd))
f.store_info('eee', DummyNode('eee', eee))
f.merge()
e = f.get_entry('ddd')
assert e == ddd, e
assert e.name == 'ddd', e.name
e = f.get_entry('eee')
assert e == eee, e
assert e.name == 'eee', e.name
assert not hasattr(e, 'arg'), e
f.store_info('eee', DummyNode('eee', fff))
e = f.get_entry('eee')
assert e == eee, e
assert e.name == 'eee', e.name
assert not hasattr(e, 'arg'), e
f.merge()
e = f.get_entry('eee')
assert e.name == 'fff', e.name
assert e.arg == 'fff arg', e.arg
class SConsignDBTestCase(SConsignTestCase):
def test_SConsignDB(self):
save_DataBase = SCons.SConsign.DataBase
SCons.SConsign.DataBase = {}
try:
d1 = SCons.SConsign.DB(DummyNode('dir1'))
d1.set_entry('aaa', DummySConsignEntry('aaa name'))
d1.set_entry('bbb', DummySConsignEntry('bbb name'))
aaa = d1.get_entry('aaa')
assert aaa.name == 'aaa name'
bbb = d1.get_entry('bbb')
assert bbb.name == 'bbb name'
d2 = SCons.SConsign.DB(DummyNode('dir2'))
d2.set_entry('ccc', DummySConsignEntry('ccc name'))
d2.set_entry('ddd', DummySConsignEntry('ddd name'))
ccc = d2.get_entry('ccc')
assert ccc.name == 'ccc name'
ddd = d2.get_entry('ddd')
assert ddd.name == 'ddd name'
d31 = SCons.SConsign.DB(DummyNode('dir3/sub1'))
d31.set_entry('eee', DummySConsignEntry('eee name'))
d31.set_entry('fff', DummySConsignEntry('fff name'))
eee = d31.get_entry('eee')
assert eee.name == 'eee name'
fff = d31.get_entry('fff')
assert fff.name == 'fff name'
d32 = SCons.SConsign.DB(DummyNode('dir3%ssub2' % os.sep))
d32.set_entry('ggg', DummySConsignEntry('ggg name'))
d32.set_entry('hhh', DummySConsignEntry('hhh name'))
ggg = d32.get_entry('ggg')
assert ggg.name == 'ggg name'
hhh = d32.get_entry('hhh')
assert hhh.name == 'hhh name'
finally:
SCons.SConsign.DataBase = save_DataBase
class SConsignDirFileTestCase(SConsignTestCase):
def test_SConsignDirFile(self):
bi_foo = DummySConsignEntry('foo')
bi_bar = DummySConsignEntry('bar')
f = SCons.SConsign.DirFile(DummyNode())
f.set_entry('foo', bi_foo)
f.set_entry('bar', bi_bar)
e = f.get_entry('foo')
assert e == bi_foo, e
assert e.name == 'foo', e.name
e = f.get_entry('bar')
assert e == bi_bar, e
assert e.name == 'bar', e.name
assert not hasattr(e, 'arg'), e
bbb = DummySConsignEntry('bbb')
bbb.arg = 'bbb arg'
f.set_entry('bar', bbb)
e = f.get_entry('bar')
assert e.name == 'bbb', e.name
assert e.arg == 'bbb arg', e.arg
class SConsignFileTestCase(SConsignTestCase):
def test_SConsignFile(self):
test = self.test
file = test.workpath('sconsign_file')
assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase
if get_hash_format() is None and get_current_hash_algorithm_used() == 'md5':
assert SCons.SConsign.DB_Name == ".sconsign", SCons.SConsign.DB_Name
else:
assert SCons.SConsign.DB_Name == ".sconsign_{}".format(get_current_hash_algorithm_used()), SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
SCons.SConsign.File(file)
assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase
assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is SCons.dblite, SCons.SConsign.DB_Module
SCons.SConsign.File(None)
assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase
assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is None, SCons.SConsign.DB_Module
class Fake_DBM:
def open(self, name, mode):
self.name = name
self.mode = mode
return self
def __getitem__(self, key):
pass
def __setitem__(self, key, value):
pass
fake_dbm = Fake_DBM()
SCons.SConsign.File(file, fake_dbm)
assert SCons.SConsign.DataBase == {}, SCons.SConsign.DataBase
assert SCons.SConsign.DB_Name is file, SCons.SConsign.DB_Name
assert SCons.SConsign.DB_Module is fake_dbm, SCons.SConsign.DB_Module
assert not hasattr(fake_dbm, 'name'), fake_dbm
assert not hasattr(fake_dbm, 'mode'), fake_dbm
SCons.SConsign.ForDirectory(DummyNode(test.workpath('dir')))
assert SCons.SConsign.DataBase is not None, SCons.SConsign.DataBase
assert fake_dbm.name == file, fake_dbm.name
assert fake_dbm.mode == "c", fake_dbm.mode
class writeTestCase(SConsignTestCase):
def test_write(self):
test = self.test
file = test.workpath('sconsign_file')
class Fake_DBM:
def __getitem__(self, key):
return None
def __setitem__(self, key, value):
pass
def open(self, name, mode):
self.sync_count = 0
return self
def sync(self):
self.sync_count = self.sync_count + 1
fake_dbm = Fake_DBM()
SCons.SConsign.DataBase = {}
SCons.SConsign.File(file, fake_dbm)
f = SCons.SConsign.DB(DummyNode())
bi_foo = DummySConsignEntry('foo')
bi_bar = DummySConsignEntry('bar')
f.set_entry('foo', bi_foo)
f.set_entry('bar', bi_bar)
SCons.SConsign.write()
assert bi_foo.c_to_s, bi_foo.c_to_s
assert bi_bar.c_to_s, bi_bar.c_to_s
assert fake_dbm.sync_count == 1, fake_dbm.sync_count
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,534 +0,0 @@
# 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 collections
import os
import unittest
import TestCmd
import TestUnit
import SCons.compat
import SCons.Node.FS
import SCons.Warnings
import SCons.Scanner.C
test = TestCmd.TestCmd(workdir = '')
os.chdir(test.workpath(''))
# create some source files and headers:
test.write('f1.cpp',"""
#ifdef INCLUDE_F2 /* multi-line comment */
#include <f2.h>
#else
#include \"f1.h\"
#endif
int main(void)
{
return 0;
}
""")
test.write('f2.cpp',"""
#include \"d1/f1.h\"
#if 5UL < 10 && !defined(DUMMY_MACRO) // some comment
#if NESTED_CONDITION
#include <d2/f1.h>
#endif
#else
#include \"f1.h\"
#endif
#import <f4.h>
int main(void)
{
return 0;
}
""")
test.write('f3.cpp',"""
#include \t "f1.h"
\t #include "f2.h"
# \t include "f3-test.h"
#include \t <d1/f1.h>
\t #include <d1/f2.h>
# \t include <d1/f3-test.h>
// #include "never.h"
const char* x = "#include <never.h>"
int main(void)
{
return 0;
}
""")
# for Emacs -> "
test.subdir('d1', ['d1', 'd2'])
headers = ['f1.h','f2.h', 'f3-test.h', 'fi.h', 'fj.h', 'never.h',
'd1/f1.h', 'd1/f2.h', 'd1/f3-test.h', 'd1/fi.h', 'd1/fj.h',
'd1/d2/f1.h', 'd1/d2/f2.h', 'd1/d2/f3-test.h',
'd1/d2/f4.h', 'd1/d2/fi.h', 'd1/d2/fj.h']
for h in headers:
test.write(h, " ")
test.write('f2.h',"""
#include "fi.h"
""")
test.write('f3-test.h',"""
#include <fj.h>
""")
test.subdir('include', 'subdir', ['subdir', 'include'])
test.write('fa.cpp',"""
#include \"fa.h\"
#include <fb.h>
int main(void)
{
return 0;
}
""")
test.write(['include', 'fa.h'], "\n")
test.write(['include', 'fb.h'], "\n")
test.write(['subdir', 'include', 'fa.h'], "\n")
test.write(['subdir', 'include', 'fb.h'], "\n")
test.subdir('repository', ['repository', 'include'],
['repository', 'src' ])
test.subdir('work', ['work', 'src'])
test.write(['repository', 'include', 'iii.h'], "\n")
test.write(['work', 'src', 'fff.c'], """
#include <iii.h>
#include <jjj.h>
int main(void)
{
return 0;
}
""")
test.write([ 'work', 'src', 'aaa.c'], """
#include "bbb.h"
int main(void)
{
return 0;
}
""")
test.write([ 'work', 'src', 'bbb.h'], "\n")
test.write([ 'repository', 'src', 'ccc.c'], """
#include "ddd.h"
int main(void)
{
return 0;
}
""")
test.write([ 'repository', 'src', 'ddd.h'], "\n")
test.write('f5.c', """\
#include\"f5a.h\"
#include<f5b.h>
""")
test.write("f5a.h", "\n")
test.write("f5b.h", "\n")
# define some helpers:
class DummyEnvironment(collections.UserDict):
def __init__(self, **kwargs):
super().__init__()
self.data.update(kwargs)
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
return self.data
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_list(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return [self.data[strSubst[1:]]]
return [[strSubst]]
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
else:
my_normpath = os.path.normpath
def deps_match(self, deps, headers):
global my_normpath
scanned = list(map(my_normpath, list(map(str, deps))))
expect = list(map(my_normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
# define some tests:
class CScannerTestCase1(unittest.TestCase):
def runTest(self):
"""Find local files with no CPPPATH"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f1.cpp'), env, path)
headers = ['f1.h', 'f2.h']
deps_match(self, deps, headers)
class CScannerTestCase2(unittest.TestCase):
def runTest(self):
"""Find a file in a CPPPATH directory"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1")])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f1.cpp'), env, path)
headers = ['f1.h', 'd1/f2.h']
deps_match(self, deps, headers)
class CScannerTestCase3(unittest.TestCase):
def runTest(self):
"""Find files in explicit subdirectories, ignore missing file"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1")])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f2.cpp'), env, path)
headers = ['d1/f1.h', 'f1.h', 'd1/d2/f1.h']
deps_match(self, deps, headers)
class CScannerTestCase4(unittest.TestCase):
def runTest(self):
"""Find files in explicit subdirectories"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1"), test.workpath("d1/d2")])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f2.cpp'), env, path)
headers = ['d1/f1.h', 'f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h']
deps_match(self, deps, headers)
class CScannerTestCase5(unittest.TestCase):
def runTest(self):
"""Make sure files in repositories will get scanned"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
n = env.File('f3.cpp')
def my_rexists(s):
s.Tag('rexists_called', 1)
return SCons.Node._rexists_map[s.GetTag('old_rexists')](s)
n.Tag('old_rexists', n._func_rexists)
SCons.Node._rexists_map[3] = my_rexists
n._func_rexists = 3
deps = s(n, env, path)
# Make sure rexists() got called on the file node being
# scanned, essential for cooperation with VariantDir functionality.
assert n.GetTag('rexists_called')
headers = ['f1.h', 'f2.h', 'f3-test.h',
'd1/f1.h', 'd1/f2.h', 'd1/f3-test.h']
deps_match(self, deps, headers)
class CScannerTestCase6(unittest.TestCase):
def runTest(self):
"""Find a same-named file in different directories when CPPPATH changes"""
env1 = DummyEnvironment(CPPPATH=[test.workpath("d1")])
env2 = DummyEnvironment(CPPPATH=[test.workpath("d1/d2")])
s = SCons.Scanner.C.CScanner()
path1 = s.path(env1)
path2 = s.path(env2)
deps1 = s(env1.File('f1.cpp'), env1, path1)
deps2 = s(env2.File('f1.cpp'), env2, path2)
headers1 = ['f1.h', 'd1/f2.h']
headers2 = ['f1.h', 'd1/d2/f2.h']
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
class CScannerTestCase8(unittest.TestCase):
def runTest(self):
"""Find files in a subdirectory relative to the current directory"""
env = DummyEnvironment(CPPPATH=["include"])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps1 = s(env.File('fa.cpp'), env, path)
env.fs.chdir(env.Dir('subdir'))
dir = env.fs.getcwd()
env.fs.chdir(env.Dir(''))
path = s.path(env, dir)
deps2 = s(env.File('#fa.cpp'), env, path)
headers1 = list(map(test.workpath, ['include/fa.h', 'include/fb.h']))
headers2 = ['include/fa.h', 'include/fb.h']
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
class CScannerTestCase9(unittest.TestCase):
def runTest(self):
"""Generate a warning when we can't find a #included file"""
SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
class TestOut:
def __call__(self, x):
self.out = x
to = TestOut()
to.out = None
SCons.Warnings._warningOut = to
test.write('fa.h','\n')
fs = SCons.Node.FS.FS(test.workpath(''))
env = DummyEnvironment(CPPPATH=[])
env.fs = fs
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(fs.File('fa.cpp'), env, path)
# Did we catch the warning associated with not finding fb.h?
assert to.out
deps_match(self, deps, [ 'fa.h' ])
test.unlink('fa.h')
class CScannerTestCase10(unittest.TestCase):
def runTest(self):
"""Find files in the local directory when the scanned file is elsewhere"""
fs = SCons.Node.FS.FS(test.workpath(''))
fs.chdir(fs.Dir('include'))
env = DummyEnvironment(CPPPATH=[])
env.fs = fs
s = SCons.Scanner.C.CScanner()
path = s.path(env)
test.write('include/fa.cpp', test.read('fa.cpp'))
fs.chdir(fs.Dir('..'))
deps = s(fs.File('#include/fa.cpp'), env, path)
deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ])
test.unlink('include/fa.cpp')
class CScannerTestCase11(unittest.TestCase):
def runTest(self):
"""Handle dependencies on a derived .h file in a non-existent directory"""
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.Repository(test.workpath('repository'))
# Create a derived file in a directory that does not exist yet.
# This was a bug at one time.
f1=fs.File('include2/jjj.h')
f1.builder=1
env = DummyEnvironment(CPPPATH=['include', 'include2'])
env.fs = fs
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(fs.File('src/fff.c'), env, path)
deps_match(self, deps, [ test.workpath('repository/include/iii.h'),
'include2/jjj.h' ])
os.chdir(test.workpath(''))
class CScannerTestCase12(unittest.TestCase):
def runTest(self):
"""Find files in VariantDir() directories"""
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.VariantDir('build1', 'src', 1)
fs.VariantDir('build2', 'src', 0)
fs.Repository(test.workpath('repository'))
env = DummyEnvironment(CPPPATH=[])
env.fs = fs
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps1 = s(fs.File('build1/aaa.c'), env, path)
deps_match(self, deps1, [ 'build1/bbb.h' ])
deps2 = s(fs.File('build2/aaa.c'), env, path)
deps_match(self, deps2, [ 'src/bbb.h' ])
deps3 = s(fs.File('build1/ccc.c'), env, path)
deps_match(self, deps3, [ 'build1/ddd.h' ])
deps4 = s(fs.File('build2/ccc.c'), env, path)
deps_match(self, deps4, [ test.workpath('repository/src/ddd.h') ])
os.chdir(test.workpath(''))
class CScannerTestCase13(unittest.TestCase):
def runTest(self):
"""Find files in directories named in a substituted environment variable"""
class SubstEnvironment(DummyEnvironment):
def subst(self, arg, target=None, source=None, conv=None, test=test):
if arg == "$blah":
return test.workpath("d1")
else:
return arg
env = SubstEnvironment(CPPPATH=["$blah"])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f1.cpp'), env, path)
headers = ['f1.h', 'd1/f2.h']
deps_match(self, deps, headers)
class CScannerTestCase14(unittest.TestCase):
def runTest(self):
"""Find files when there's no space between "#include" and the name"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
path = s.path(env)
deps = s(env.File('f5.c'), env, path)
headers = ['f5a.h', 'f5b.h']
deps_match(self, deps, headers)
class CScannerTestCase15(unittest.TestCase):
def runTest(self):
"""Verify scanner initialization with the suffixes in $CPPSUFFIXES"""
suffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
".h", ".H", ".hxx", ".hpp", ".hh",
".F", ".fpp", ".FPP",
".S", ".spp", ".SPP"]
env = DummyEnvironment(CPPSUFFIXES = suffixes)
s = SCons.Scanner.C.CScanner()
for suffix in suffixes:
assert suffix in s.get_skeys(env), "%s not in skeys" % suffix
class CConditionalScannerTestCase1(unittest.TestCase):
def runTest(self):
"""Find local files with no CPPPATH"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CConditionalScanner()
path = s.path(env)
deps = s(env.File('f1.cpp'), env, path)
headers = ['f1.h']
deps_match(self, deps, headers)
class CConditionalScannerTestCase2(unittest.TestCase):
def runTest(self):
"""Find local files with no CPPPATH based on #ifdef"""
env = DummyEnvironment(CPPPATH=[], CPPDEFINES=["INCLUDE_F2"])
s = SCons.Scanner.C.CConditionalScanner()
path = s.path(env)
deps = s(env.File('f1.cpp'), env, path)
headers = ['f2.h', 'fi.h']
deps_match(self, deps, headers)
class CConditionalScannerTestCase3(unittest.TestCase):
def runTest(self):
"""Find files in explicit subdirectories, ignore missing file"""
env = DummyEnvironment(
CPPPATH=[test.workpath("d1")],
CPPDEFINES=[("NESTED_CONDITION", 1)]
)
s = SCons.Scanner.C.CConditionalScanner()
deps = s(env.File('f2.cpp'), env, s.path(env))
headers = ['d1/f1.h', 'd1/d2/f1.h']
deps_match(self, deps, headers)
# disable nested conditions
env = DummyEnvironment(
CPPPATH=[test.workpath("d1")],
CPPDEFINES=[("NESTED_CONDITION", 0)]
)
s = SCons.Scanner.C.CConditionalScanner()
deps = s(env.File('f2.cpp'), env, s.path(env))
headers = ['d1/f1.h']
deps_match(self, deps, headers)
class dictify_CPPDEFINESTestCase(unittest.TestCase):
def runTest(self):
"""Make sure single-item tuples convert correctly.
This is a regression test: AppendUnique turns sequences into
lists of tuples, and dictify could gack on these.
"""
env = DummyEnvironment(CPPDEFINES=(("VALUED_DEFINE", 1), ("UNVALUED_DEFINE", )))
d = SCons.Scanner.C.dictify_CPPDEFINES(env)
expect = {'VALUED_DEFINE': 1, 'UNVALUED_DEFINE': None}
assert d == expect
def suite():
suite = unittest.TestSuite()
suite.addTest(CScannerTestCase1())
suite.addTest(CScannerTestCase2())
suite.addTest(CScannerTestCase3())
suite.addTest(CScannerTestCase4())
suite.addTest(CScannerTestCase5())
suite.addTest(CScannerTestCase6())
suite.addTest(CScannerTestCase8())
suite.addTest(CScannerTestCase9())
suite.addTest(CScannerTestCase10())
suite.addTest(CScannerTestCase11())
suite.addTest(CScannerTestCase12())
suite.addTest(CScannerTestCase13())
suite.addTest(CScannerTestCase14())
suite.addTest(CScannerTestCase15())
suite.addTest(CConditionalScannerTestCase1())
suite.addTest(CConditionalScannerTestCase2())
suite.addTest(CConditionalScannerTestCase3())
suite.addTest(dictify_CPPDEFINESTestCase())
return suite
if __name__ == "__main__":
TestUnit.run(suite())
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,272 +0,0 @@
# 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 collections
import os
import unittest
import TestCmd
import SCons.Scanner.D
test = TestCmd.TestCmd(workdir = '')
class DummyEnvironment(collections.UserDict):
def __init__(self, **kwargs):
super().__init__()
self.data.update(kwargs)
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
return self.data
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_list(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return [self.data[strSubst[1:]]]
return [[strSubst]]
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
else:
my_normpath = os.path.normpath
def deps_match(self, deps, headers):
global my_normpath
scanned = list(map(my_normpath, list(map(str, deps))))
expect = list(map(my_normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
"""
Examples from https://dlang.org/spec/module.html
D Language: 2.071.1
Accessed: 11 August 2016
"""
# Regular import
test.write('basic.d',"""
import A;
void main() {}
""")
# Static import
test.write('static.d',"""
static import A;
void main()
{
std.stdio.writeln("hello!"); // ok, writeln is fully qualified
}
""")
# Public import
test.write('public.d',"""
public import A;
void main() {}
""")
# Renamed import
test.write('rename.d',"""
import B = A;
void main()
{
io.writeln("hello!"); // ok, calls std.stdio.writeln
}
""")
# Selective import
test.write('selective.d',"""
import A : B, C;
void main()
{
writeln("hello!"); // ok, writeln bound into current namespace
foo("world"); // ok, calls std.stdio.write()
}
""")
# Renamed and Selective import
test.write('renameAndSelective.d',"""
import B = A : C = D;
void main()
{
}
""")
# Scoped import
test.write('scoped.d',"""
void main()
{
import A;
}
""")
# Combinatorial import
test.write('combinatorial.d',"""
import A, B, CCC = C, DDD = D : EEE = FFF;
void main()
{
}
""")
# Subdirs import
test.write('subdirs.d',"""
import X.Y, X.Z, X.X.X;
void main() {}
""")
# Multiple import
test.write('multiple.d',"""
public import B;
static import C;
import X = X.Y : Q, R, S, T = U;
void main()
{
import A;
}
""")
# Multiline import
test.write('multiline.d',"""
import
A;
void main() {}
""")
test.write('A.d',"""
module A;
void main() {}
""")
test.write('B.d',"""
module B;
void main() {}
""")
test.write('C.d',"""
module C;
void main() {}
""")
test.write('D.d',"""
module D;
void main() {}
""")
test.subdir('X', os.path.join('X','X'))
test.write(os.path.join('X','Y.d'),"""
module Y;
void main() {}
""")
test.write(os.path.join('X','Z.d'),"""
module Z;
void main() {}
""")
test.write(os.path.join('X','X','X.d'),"""
module X;
void main() {}
""")
class DScannerTestCase(unittest.TestCase):
def helper(self, filename, headers):
env = DummyEnvironment()
s = SCons.Scanner.D.DScanner()
path = s.path(env)
deps = s(env.File(filename), env, path)
deps_match(self, deps, headers)
def test_BasicImport(self):
self.helper('basic.d', ['A.d'])
def test_StaticImport(self):
self.helper('static.d', ['A.d'])
def test_publicImport(self):
self.helper('public.d', ['A.d'])
def test_RenameImport(self):
self.helper('rename.d', ['A.d'])
def test_SelectiveImport(self):
self.helper('selective.d', ['A.d'])
def test_RenameAndSelectiveImport(self):
self.helper('renameAndSelective.d', ['A.d'])
def test_ScopedImport(self):
self.helper('scoped.d', ['A.d'])
def test_CombinatorialImport(self):
self.helper('combinatorial.d', ['A.d', 'B.d', 'C.d', 'D.d'])
def test_SubdirsImport(self):
self.helper('subdirs.d', [os.path.join('X','X','X.d'), os.path.join('X','Y.d'), os.path.join('X','Z.d')])
def test_MultipleImport(self):
self.helper('multiple.d', ['A.d', 'B.d', 'C.d', os.path.join('X','Y.d')])
def test_MultilineImport(self):
self.helper('multiline.d', ['A.d'])
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,130 +0,0 @@
# 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 os.path
import unittest
import TestCmd
import SCons.Node.FS
import SCons.Scanner.Dir
from SCons.SConsign import current_sconsign_filename
#class DummyNode:
# def __init__(self, name, fs):
# self.name = name
# self.abspath = test.workpath(name)
# self.fs = fs
# def __str__(self):
# return self.name
# def Entry(self, name):
# return self.fs.Entry(name)
class DummyEnvironment:
def __init__(self, root):
self.fs = SCons.Node.FS.FS(root)
def Dir(self, name):
return self.fs.Dir(name)
def Entry(self, name):
return self.fs.Entry(name)
def File(self, name):
return self.fs.File(name)
def get_factory(self, factory):
return factory or self.fs.Entry
class DirScannerTestBase(unittest.TestCase):
def setUp(self):
self.test = TestCmd.TestCmd(workdir = '')
self.test.subdir('dir', ['dir', 'sub'])
sconsign = current_sconsign_filename()
self.test.write(['dir', 'f1'], "dir/f1\n")
self.test.write(['dir', 'f2'], "dir/f2\n")
self.test.write(['dir', '{}'.format(sconsign)], "dir/{}\n".format(sconsign))
self.test.write(['dir', '{}.bak'.format(sconsign)], "dir/{}.bak\n".format(sconsign))
self.test.write(['dir', '{}.dat'.format(sconsign)], "dir/{}.dat\n".format(sconsign))
self.test.write(['dir', '{}.db'.format(sconsign)], "dir/{}.db\n".format(sconsign))
self.test.write(['dir', '{}.dblite'.format(sconsign)], "dir/{}.dblite\n".format(sconsign))
self.test.write(['dir', '{}.dir'.format(sconsign)], "dir/{}.dir\n".format(sconsign))
self.test.write(['dir', '{}.pag'.format(sconsign)], "dir/{}.pag\n".format(sconsign))
self.test.write(['dir', 'sub', 'f3'], "dir/sub/f3\n")
self.test.write(['dir', 'sub', 'f4'], "dir/sub/f4\n")
self.test.write(['dir', 'sub', '{}'.format(sconsign)], "dir/{}\n".format(sconsign))
self.test.write(['dir', 'sub', '{}.bak'.format(sconsign)], "dir/{}.bak\n".format(sconsign))
self.test.write(['dir', 'sub', '{}.dat'.format(sconsign)], "dir/{}.dat\n".format(sconsign))
self.test.write(['dir', 'sub', '{}.dblite'.format(sconsign)], "dir/{}.dblite\n".format(sconsign))
self.test.write(['dir', 'sub', '{}.dir'.format(sconsign)], "dir/{}.dir\n".format(sconsign))
self.test.write(['dir', 'sub', '{}.pag'.format(sconsign)], "dir/{}.pag\n".format(sconsign))
class DirScannerTestCase(DirScannerTestBase):
def runTest(self):
env = DummyEnvironment(self.test.workpath())
s = SCons.Scanner.Dir.DirScanner()
expect = [
os.path.join('dir', 'f1'),
os.path.join('dir', 'f2'),
os.path.join('dir', 'sub'),
]
deps = s(env.Dir('dir'), env, ())
sss = list(map(str, deps))
assert sss == expect, "Found {}, expected {}".format(sss, expect)
expect = [
os.path.join('dir', 'sub', 'f3'),
os.path.join('dir', 'sub', 'f4'),
]
deps = s(env.Dir('dir/sub'), env, ())
sss = list(map(str, deps))
assert sss == expect, "Found {}, expected {}".format(sss, expect)
class DirEntryScannerTestCase(DirScannerTestBase):
def runTest(self):
env = DummyEnvironment(self.test.workpath())
s = SCons.Scanner.Dir.DirEntryScanner()
deps = s(env.Dir('dir'), env, ())
sss = list(map(str, deps))
assert sss == [], "Found {}, expected {}".format(sss, [])
deps = s(env.Dir('dir/sub'), env, ())
sss = list(map(str, deps))
assert sss == [], "Found {}, expected {}".format(sss, [])
# Make sure we don't blow up if handed a non-Dir node.
deps = s(env.File('dir/f1'), env, ())
sss = list(map(str, deps))
assert sss == [], "Found {}, expected {}".format(sss, [])
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,538 +0,0 @@
# 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 os
import unittest
import SCons.Scanner.Fortran
import SCons.Node.FS
import SCons.Warnings
import TestCmd
original = os.getcwd()
test = TestCmd.TestCmd(workdir='')
os.chdir(test.workpath(''))
# create some source files and headers:
test.write('fff1.f', """
PROGRAM FOO
INCLUDE 'f1.f'
include 'f2.f'
STOP
END
""")
test.write('fff2.f', """
PROGRAM FOO
INCLUDE 'f2.f'
include 'd1/f2.f'
INCLUDE 'd2/f2.f'
STOP
END
""")
test.write('fff3.f', """
PROGRAM FOO
INCLUDE 'f3.f' ; INCLUDE\t'd1/f3.f'
STOP
END
""")
# for Emacs -> "
test.subdir('d1', ['d1', 'd2'])
test_headers = ['fi.f', 'never.f',
'd1/f1.f', 'd1/f2.f', 'd1/f3.f', 'd1/fi.f',
'd1/d2/f1.f', 'd1/d2/f2.f', 'd1/d2/f3.f',
'd1/d2/f4.f', 'd1/d2/fi.f']
for h in test_headers:
test.write(h, "\n")
test.subdir('include', 'subdir', ['subdir', 'include'])
test.write('fff4.f', """
PROGRAM FOO
INCLUDE 'f4.f'
STOP
END
""")
test.write('include/f4.f', "\n")
test.write('subdir/include/f4.f', "\n")
test.write('fff5.f', """
PROGRAM FOO
INCLUDE 'f5.f'
INCLUDE 'not_there.f'
STOP
END
""")
test.write('f5.f', "\n")
test.subdir('repository', ['repository', 'include'],
['repository', 'src'])
test.subdir('work', ['work', 'src'])
test.write(['repository', 'include', 'iii.f'], "\n")
test.write(['work', 'src', 'fff.f'], """
PROGRAM FOO
INCLUDE 'iii.f'
INCLUDE 'jjj.f'
STOP
END
""")
test.write(['work', 'src', 'aaa.f'], """
PROGRAM FOO
INCLUDE 'bbb.f'
STOP
END
""")
test.write(['work', 'src', 'bbb.f'], "\n")
test.write(['repository', 'src', 'ccc.f'], """
PROGRAM FOO
INCLUDE 'ddd.f'
STOP
END
""")
test.write(['repository', 'src', 'ddd.f'], "\n")
test.write('fff90a.f90', """
PROGRAM FOO
! Test comments - these includes should NOT be picked up
C INCLUDE 'fi.f'
# INCLUDE 'fi.f'
! INCLUDE 'fi.f'
INCLUDE 'f1.f' ! in-line comments are valid syntax
INCLUDE"fi.f" ! space is significant - this should be ignored
INCLUDE <f2.f> ! Absoft compiler allows greater than/less than delimiters
!
! Allow kind type parameters
INCLUDE kindType_"f3.f"
INCLUDE kind_Type_"f4.f"
!
! Test multiple statements per line - use various spacings between semicolons
incLUDE 'f5.f';include "f6.f" ; include <f7.f>; include 'f8.f' ;include kindType_'f9.f'
!
! Test various USE statement syntaxes
!
USE Mod01
use mod02
use use
USE mOD03, ONLY : someVar
USE MOD04 ,only:someVar
USE Mod05 , ONLY: someVar ! in-line comment
USE Mod06,ONLY :someVar,someOtherVar
USE mod07;USE mod08; USE mod09 ;USE mod10 ; USE mod11 ! Test various semicolon placements
use mod12 ;use mod13! Test comment at end of line
! USE modi
! USE modia ; use modib ! Scanner regexp will only ignore the first - this is a deficiency in the regexp
! USE modic ; ! use modid ! Scanner regexp should ignore both modules
USE mod14 !; USE modi ! Only ignore the second
USE mod15!;USE modi
USE mod16 ! ; USE modi
! Test semicolon syntax - use various spacings
USE :: mod17
USE::mod18
USE ::mod19 ; USE:: mod20
use, non_intrinsic :: mod21, ONLY : someVar ; use,intrinsic:: mod22
USE, NON_INTRINSIC::mod23 ; USE ,INTRINSIC ::mod24
USE mod25 ! Test USE statement at the beginning of line
; USE modi ! Scanner should ignore this since it isn't valid syntax
USEmodi ! No space in between USE and module name - ignore it
USE mod01 ! This one is a duplicate - there should only be one dependency to it.
STOP
END
""")
test_modules = ['mod01.mod', 'mod02.mod', 'mod03.mod', 'mod04.mod', 'mod05.mod',
'mod06.mod', 'mod07.mod', 'mod08.mod', 'mod09.mod', 'mod10.mod',
'mod11.mod', 'mod12.mod', 'mod13.mod', 'mod14.mod', 'mod15.mod',
'mod16.mod', 'mod17.mod', 'mod18.mod', 'mod19.mod', 'mod20.mod',
'mod21.mod', 'mod22.mod', 'mod23.mod', 'mod24.mod', 'mod25.mod']
for m in test_modules:
test.write(m, "\n")
test.subdir('modules')
test.write(['modules', 'use.mod'], "\n")
# define some helpers:
class DummyEnvironment:
def __init__(self, listCppPath):
self.path = listCppPath
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
if not args:
return {'FORTRANPATH': self.path, 'FORTRANMODSUFFIX': ".mod"}
elif len(args) == 1 and args[0] == 'FORTRANPATH':
return self.path
else:
raise KeyError("Dummy environment only has FORTRANPATH attribute.")
def __contains__(self, key):
return key in self.Dictionary()
def __getitem__(self, key):
return self.Dictionary()[key]
def __setitem__(self, key, value):
self.Dictionary()[key] = value
def __delitem__(self, key):
del self.Dictionary()[key]
def subst(self, arg, target=None, source=None, conv=None):
if arg[0] == '$':
return self[arg[1:]]
return arg
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
def deps_match(self, deps, headers):
scanned = list(map(os.path.normpath, list(map(str, deps))))
expect = list(map(os.path.normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
# define some tests:
class FortranScannerTestCase1(unittest.TestCase):
def runTest(self):
test.write('f1.f', "\n")
test.write('f2.f', " INCLUDE 'fi.f'\n")
env = DummyEnvironment([])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff1.f'), env, path)
headers = ['f1.f', 'f2.f']
deps_match(self, deps, headers)
test.unlink('f1.f')
test.unlink('f2.f')
class FortranScannerTestCase2(unittest.TestCase):
def runTest(self):
test.write('f1.f', "\n")
test.write('f2.f', " INCLUDE 'fi.f'\n")
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff1.f'), env, path)
headers = ['f1.f', 'f2.f']
deps_match(self, deps, headers)
test.unlink('f1.f')
test.unlink('f2.f')
class FortranScannerTestCase3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff1.f'), env, path)
headers = ['d1/f1.f', 'd1/f2.f']
deps_match(self, deps, headers)
class FortranScannerTestCase4(unittest.TestCase):
def runTest(self):
test.write(['d1', 'f2.f'], " INCLUDE 'fi.f'\n")
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff1.f'), env, path)
headers = ['d1/f1.f', 'd1/f2.f']
deps_match(self, deps, headers)
test.write(['d1', 'f2.f'], "\n")
class FortranScannerTestCase5(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff2.f'), env, path)
headers = ['d1/f2.f', 'd1/d2/f2.f', 'd1/f2.f']
deps_match(self, deps, headers)
class FortranScannerTestCase6(unittest.TestCase):
def runTest(self):
test.write('f2.f', "\n")
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff2.f'), env, path)
headers = ['d1/f2.f', 'd1/d2/f2.f', 'f2.f']
deps_match(self, deps, headers)
test.unlink('f2.f')
class FortranScannerTestCase7(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1/d2"), test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff2.f'), env, path)
headers = ['d1/f2.f', 'd1/d2/f2.f', 'd1/d2/f2.f']
deps_match(self, deps, headers)
class FortranScannerTestCase8(unittest.TestCase):
def runTest(self):
test.write('f2.f', "\n")
env = DummyEnvironment([test.workpath("d1/d2"), test.workpath("d1")])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff2.f'), env, path)
headers = ['d1/f2.f', 'd1/d2/f2.f', 'f2.f']
deps_match(self, deps, headers)
test.unlink('f2.f')
class FortranScannerTestCase9(unittest.TestCase):
def runTest(self):
test.write('f3.f', "\n")
env = DummyEnvironment([])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
n = env.File('fff3.f')
def my_rexists(s):
s.Tag('rexists_called', 1)
return SCons.Node._rexists_map[s.GetTag('old_rexists')](s)
n.Tag('old_rexists', n._func_rexists)
SCons.Node._rexists_map[3] = my_rexists
n._func_rexists = 3
deps = s(n, env, path)
# Make sure rexists() got called on the file node being
# scanned, essential for cooperation with VariantDir functionality.
assert n.GetTag('rexists_called')
headers = ['d1/f3.f', 'f3.f']
deps_match(self, deps, headers)
test.unlink('f3.f')
class FortranScannerTestCase10(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(["include"])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps1 = s(env.File('fff4.f'), env, path)
env.fs.chdir(env.Dir('subdir'))
test_dir = env.fs.getcwd()
env.fs.chdir(env.Dir(''))
path = s.path(env, test_dir)
deps2 = s(env.File('#fff4.f'), env, path)
headers1 = [test.workpath(f) for f in ['include/f4.f']]
headers2 = ['include/f4.f']
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
class FortranScannerTestCase11(unittest.TestCase):
def runTest(self):
SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
class TestOut:
def __call__(self, x):
self.out = x
to = TestOut()
to.out = None
SCons.Warnings._warningOut = to
env = DummyEnvironment([])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff5.f'), env, path)
# Did we catch the warning from not finding not_there.f?
assert to.out
deps_match(self, deps, ['f5.f'])
class FortranScannerTestCase12(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
env.fs.chdir(env.Dir('include'))
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
test.write('include/fff4.f', test.read('fff4.f'))
deps = s(env.File('#include/fff4.f'), env, path)
env.fs.chdir(env.Dir(''))
deps_match(self, deps, ['f4.f'])
test.unlink('include/fff4.f')
class FortranScannerTestCase13(unittest.TestCase):
def runTest(self):
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.Repository(test.workpath('repository'))
# Create a derived file in a directory that does not exist yet.
# This was a bug at one time.
f1 = fs.File('include2/jjj.f')
f1.builder = 1
env = DummyEnvironment(['include', 'include2'])
env.fs = fs
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(fs.File('src/fff.f'), env, path)
deps_match(self, deps, [test.workpath('repository/include/iii.f'), 'include2/jjj.f'])
os.chdir(test.workpath(''))
class FortranScannerTestCase14(unittest.TestCase):
def runTest(self):
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.VariantDir('build1', 'src', 1)
fs.VariantDir('build2', 'src', 0)
fs.Repository(test.workpath('repository'))
env = DummyEnvironment([])
env.fs = fs
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps1 = s(fs.File('build1/aaa.f'), env, path)
deps_match(self, deps1, ['build1/bbb.f'])
deps2 = s(fs.File('build2/aaa.f'), env, path)
deps_match(self, deps2, ['src/bbb.f'])
deps3 = s(fs.File('build1/ccc.f'), env, path)
deps_match(self, deps3, ['build1/ddd.f'])
deps4 = s(fs.File('build2/ccc.f'), env, path)
deps_match(self, deps4, [test.workpath('repository/src/ddd.f')])
os.chdir(test.workpath(''))
class FortranScannerTestCase15(unittest.TestCase):
def runTest(self):
class SubstEnvironment(DummyEnvironment):
def subst(self, arg, target=None, source=None, conv=None, test=test):
if arg == "$junk":
return test.workpath("d1")
else:
return arg
test.write(['d1', 'f2.f'], " INCLUDE 'fi.f'\n")
env = SubstEnvironment(["$junk"])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff1.f'), env, path)
headers = ['d1/f1.f', 'd1/f2.f']
deps_match(self, deps, headers)
test.write(['d1', 'f2.f'], "\n")
class FortranScannerTestCase16(unittest.TestCase):
def runTest(self):
test.write('f1.f', "\n")
test.write('f2.f', "\n")
test.write('f3.f', "\n")
test.write('f4.f', "\n")
test.write('f5.f', "\n")
test.write('f6.f', "\n")
test.write('f7.f', "\n")
test.write('f8.f', "\n")
test.write('f9.f', "\n")
test.write('f10.f', "\n")
env = DummyEnvironment([test.workpath('modules')])
s = SCons.Scanner.Fortran.FortranScan()
path = s.path(env)
deps = s(env.File('fff90a.f90'), env, path)
headers = ['f1.f', 'f2.f', 'f3.f', 'f4.f', 'f5.f', 'f6.f', 'f7.f', 'f8.f', 'f9.f']
modules = ['mod01.mod', 'mod02.mod', 'mod03.mod', 'mod04.mod', 'mod05.mod',
'mod06.mod', 'mod07.mod', 'mod08.mod', 'mod09.mod', 'mod10.mod',
'mod11.mod', 'mod12.mod', 'mod13.mod', 'mod14.mod', 'mod15.mod',
'mod16.mod', 'mod17.mod', 'mod18.mod', 'mod19.mod', 'mod20.mod',
'mod21.mod', 'mod22.mod', 'mod23.mod', 'mod24.mod', 'mod25.mod', 'modules/use.mod']
deps_expected = headers + modules
deps_match(self, deps, deps_expected)
test.unlink('f1.f')
test.unlink('f2.f')
test.unlink('f3.f')
test.unlink('f4.f')
test.unlink('f5.f')
test.unlink('f6.f')
test.unlink('f7.f')
test.unlink('f8.f')
test.unlink('f9.f')
test.unlink('f10.f')
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,451 +0,0 @@
# 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 os
import os.path
import TestCmd
import TestUnit
import SCons.Scanner.IDL
import SCons.Node.FS
import SCons.Warnings
test = TestCmd.TestCmd(workdir = '')
os.chdir(test.workpath(''))
# create some source files and headers:
test.write('t1.idl','''
#include "f1.idl"
#include <f2.idl>
import "f3.idl";
[
object,
uuid(22995106-CE26-4561-AF1B-C71C6934B840),
dual,
helpstring("IBarObject Interface"),
pointer_default(unique)
]
interface IBarObject : IDispatch
{
};
''')
test.write('t2.idl',"""
#include \"d1/f1.idl\"
#include <d2/f1.idl>
#include \"f1.idl\"
import <f3.idl>;
[
object,
uuid(22995106-CE26-4561-AF1B-C71C6934B840),
dual,
helpstring(\"IBarObject Interface\"),
pointer_default(unique)
]
interface IBarObject : IDispatch
{
};
""")
test.write('t3.idl',"""
#include \t \"f1.idl\"
\t #include \"f2.idl\"
# \t include \"f3-test.idl\"
#include \t <d1/f1.idl>
\t #include <d1/f2.idl>
# \t include <d1/f3-test.idl>
import \t \"d1/f1.idl\"
\t import \"d1/f2.idl\"
include \t \"never.idl\"
\t include \"never.idl\"
// #include \"never.idl\"
const char* x = \"#include <never.idl>\"
[
object,
uuid(22995106-CE26-4561-AF1B-C71C6934B840),
dual,
helpstring(\"IBarObject Interface\"),
pointer_default(unique)
]
interface IBarObject : IDispatch
{
};
""")
test.subdir('d1', ['d1', 'd2'])
headers = ['f1.idl','f2.idl', 'f3.idl', 'f3-test.idl', 'fi.idl', 'fj.idl', 'never.idl',
'd1/f1.idl', 'd1/f2.idl', 'd1/f3-test.idl', 'd1/fi.idl', 'd1/fj.idl',
'd1/d2/f1.idl', 'd1/d2/f2.idl', 'd1/d2/f3-test.idl',
'd1/d2/f4.idl', 'd1/d2/fi.idl', 'd1/d2/fj.idl']
for h in headers:
test.write(h, " ")
test.write('f2.idl',"""
#include "fi.idl"
""")
test.write('f3-test.idl',"""
#include <fj.idl>
""")
test.subdir('include', 'subdir', ['subdir', 'include'])
test.write('t4.idl',"""
#include \"fa.idl\"
#include <fb.idl>
[
object,
uuid(22995106-CE26-4561-AF1B-C71C6934B840),
dual,
helpstring(\"IBarObject Interface\"),
pointer_default(unique)
]
interface IBarObject : IDispatch
{
};
""")
test.write(['include', 'fa.idl'], "\n")
test.write(['include', 'fb.idl'], "\n")
test.write(['subdir', 'include', 'fa.idl'], "\n")
test.write(['subdir', 'include', 'fb.idl'], "\n")
test.subdir('repository', ['repository', 'include'],
['repository', 'src' ])
test.subdir('work', ['work', 'src'])
test.write(['repository', 'include', 'iii.idl'], "\n")
test.write(['work', 'src', 'fff.c'], """
#include <iii.idl>
#include <jjj.idl>
int main(void)
{
return 0;
}
""")
test.write([ 'work', 'src', 'aaa.c'], """
#include "bbb.idl"
int main(void)
{
return 0;
}
""")
test.write([ 'work', 'src', 'bbb.idl'], "\n")
test.write([ 'repository', 'src', 'ccc.c'], """
#include "ddd.idl"
int main(void)
{
return 0;
}
""")
test.write([ 'repository', 'src', 'ddd.idl'], "\n")
# define some helpers:
class DummyEnvironment:
def __init__(self, listCppPath):
self.path = listCppPath
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
if not args:
return { 'CPPPATH': self.path }
elif len(args) == 1 and args[0] == 'CPPPATH':
return self.path
else:
raise KeyError("Dummy environment only has CPPPATH attribute.")
def subst(self, arg, target=None, source=None, conv=None):
return arg
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def __contains__(self, key):
return key in self.Dictionary()
def __getitem__(self,key):
return self.Dictionary()[key]
def __setitem__(self,key,value):
self.Dictionary()[key] = value
def __delitem__(self,key):
del self.Dictionary()[key]
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
global my_normpath
my_normpath = os.path.normpath
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
def deps_match(self, deps, headers):
scanned = list(map(my_normpath, list(map(str, deps))))
expect = list(map(my_normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
# define some tests:
class IDLScannerTestCase1(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t1.idl'), env, path)
headers = ['f1.idl', 'f3.idl', 'f2.idl']
deps_match(self, deps, headers)
class IDLScannerTestCase2(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t1.idl'), env, path)
headers = ['f1.idl', 'f3.idl', 'd1/f2.idl']
deps_match(self, deps, headers)
class IDLScannerTestCase3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1")])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t2.idl'), env, path)
headers = ['d1/f1.idl', 'f1.idl', 'd1/d2/f1.idl', 'f3.idl']
deps_match(self, deps, headers)
class IDLScannerTestCase4(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t2.idl'), env, path)
headers = ['d1/f1.idl', 'f1.idl', 'd1/d2/f1.idl', 'f3.idl']
deps_match(self, deps, headers)
class IDLScannerTestCase5(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
n = env.File('t3.idl')
def my_rexists(s):
s.Tag('rexists_called', 1)
return SCons.Node._rexists_map[s.GetTag('old_rexists')](s)
n.Tag('old_rexists', n._func_rexists)
SCons.Node._rexists_map[3] = my_rexists
n._func_rexists = 3
deps = s(n, env, path)
# Make sure rexists() got called on the file node being
# scanned, essential for cooperation with VariantDir functionality.
assert n.GetTag('rexists_called')
headers = ['d1/f1.idl', 'd1/f2.idl',
'f1.idl', 'f2.idl', 'f3-test.idl',
'd1/f1.idl', 'd1/f2.idl', 'd1/f3-test.idl']
deps_match(self, deps, headers)
class IDLScannerTestCase6(unittest.TestCase):
def runTest(self):
env1 = DummyEnvironment([test.workpath("d1")])
env2 = DummyEnvironment([test.workpath("d1/d2")])
s = SCons.Scanner.IDL.IDLScan()
path1 = s.path(env1)
path2 = s.path(env2)
deps1 = s(env1.File('t1.idl'), env1, path1)
deps2 = s(env2.File('t1.idl'), env2, path2)
headers1 = ['f1.idl', 'f3.idl', 'd1/f2.idl']
headers2 = ['f1.idl', 'f3.idl', 'd1/d2/f2.idl']
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
class IDLScannerTestCase7(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(["include"])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps1 = s(env.File('t4.idl'), env, path)
env.fs.chdir(env.Dir('subdir'))
dir = env.fs.getcwd()
env.fs.chdir(env.Dir(''))
path = s.path(env, dir)
deps2 = s(env.File('#t4.idl'), env, path)
headers1 = list(map(test.workpath, ['include/fa.idl', 'include/fb.idl']))
headers2 = ['include/fa.idl', 'include/fb.idl']
deps_match(self, deps1, headers1)
deps_match(self, deps2, headers2)
class IDLScannerTestCase8(unittest.TestCase):
def runTest(self):
SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
class TestOut:
def __call__(self, x):
self.out = x
to = TestOut()
to.out = None
SCons.Warnings._warningOut = to
test.write('fa.idl','\n')
env = DummyEnvironment([])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t4.idl'), env, path)
# Did we catch the warning associated with not finding fb.idl?
assert to.out
deps_match(self, deps, [ 'fa.idl' ])
test.unlink('fa.idl')
class IDLScannerTestCase9(unittest.TestCase):
def runTest(self):
env = DummyEnvironment([])
env.fs.chdir(env.Dir('include'))
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
test.write('include/t4.idl', test.read('t4.idl'))
deps = s(env.File('#include/t4.idl'), env, path)
env.fs.chdir(env.Dir(''))
deps_match(self, deps, [ 'fa.idl', 'fb.idl' ])
test.unlink('include/t4.idl')
class IDLScannerTestCase10(unittest.TestCase):
def runTest(self):
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.Repository(test.workpath('repository'))
# Create a derived file in a directory that does not exist yet.
# This was a bug at one time.
env = DummyEnvironment(['include', 'include2'])
env.fs = fs
f1 = fs.File('include2/jjj.idl')
f1.builder = 1
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(fs.File('src/fff.c'), env, path)
deps_match(self, deps, [ test.workpath('repository/include/iii.idl'),
'include2/jjj.idl' ])
os.chdir(test.workpath(''))
class IDLScannerTestCase11(unittest.TestCase):
def runTest(self):
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
fs.VariantDir('build1', 'src', 1)
fs.VariantDir('build2', 'src', 0)
fs.Repository(test.workpath('repository'))
env = DummyEnvironment([])
env.fs = fs
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps1 = s(fs.File('build1/aaa.c'), env, path)
deps_match(self, deps1, [ 'build1/bbb.idl' ])
deps2 = s(fs.File('build2/aaa.c'), env, path)
deps_match(self, deps2, [ 'src/bbb.idl' ])
deps3 = s(fs.File('build1/ccc.c'), env, path)
deps_match(self, deps3, [ 'build1/ddd.idl' ])
deps4 = s(fs.File('build2/ccc.c'), env, path)
deps_match(self, deps4, [ test.workpath('repository/src/ddd.idl') ])
os.chdir(test.workpath(''))
class IDLScannerTestCase12(unittest.TestCase):
def runTest(self):
class SubstEnvironment(DummyEnvironment):
def subst(self, arg, target=None, source=None, conv=None, test=test):
if arg == "$blah":
return test.workpath("d1")
else:
return arg
env = SubstEnvironment(["$blah"])
s = SCons.Scanner.IDL.IDLScan()
path = s.path(env)
deps = s(env.File('t1.idl'), env, path)
headers = ['f1.idl', 'f3.idl', 'd1/f2.idl']
deps_match(self, deps, headers)
def suite():
suite = unittest.TestSuite()
suite.addTest(IDLScannerTestCase1())
suite.addTest(IDLScannerTestCase2())
suite.addTest(IDLScannerTestCase3())
suite.addTest(IDLScannerTestCase4())
suite.addTest(IDLScannerTestCase5())
suite.addTest(IDLScannerTestCase6())
suite.addTest(IDLScannerTestCase7())
suite.addTest(IDLScannerTestCase8())
suite.addTest(IDLScannerTestCase9())
suite.addTest(IDLScannerTestCase10())
suite.addTest(IDLScannerTestCase11())
suite.addTest(IDLScannerTestCase12())
return suite
if __name__ == "__main__":
TestUnit.run(suite())
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,177 +0,0 @@
# 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 collections
import os
import unittest
import TestCmd
import SCons.compat
import SCons.Node.FS
import SCons.Scanner.LaTeX
test = TestCmd.TestCmd(workdir = '')
test.write('test1.latex',r"""
\include{inc1}
\input{inc2}
include{incNO}
%\include{incNO}
xyzzy \include{inc6}
\subimport{subdir}{inc3}
\import{subdir}{inc3a}
\includefrom{subdir}{inc3b}
\subincludefrom{subdir}{inc3c}
\inputfrom{subdir}{inc3d}
\subinputfrom{subdir}{inc3e}
""")
test.write('test2.latex',r"""
\include{inc1}
\include{inc3}
""")
test.write('test3.latex',r"""
\includegraphics{inc4.eps}
\includegraphics[width=60mm]{inc5.xyz}
""")
test.write('test4.latex',r"""
\include{inc1}\include{inc2}
\only<1>{\includegraphics{inc5.xyz}}%
\only<2>{\includegraphics{inc7.png}}
""")
test.subdir('subdir')
test.write('inc1.tex',"\n")
test.write('inc2.tex',"\n")
test.write(['subdir', 'inc3.tex'], "\n")
for suffix in 'abcde':
test.write(['subdir', 'inc3%s.tex' % suffix], "\n")
test.write(['subdir', 'inc3b.tex'], "\n")
test.write(['subdir', 'inc3c.tex'], "\n")
test.write(['subdir', 'inc4.eps'], "\n")
test.write('inc5.xyz', "\n")
test.write('inc6.tex', "\n")
test.write('inc7.png', "\n")
test.write('incNO.tex', "\n")
# define some helpers:
# copied from CTest.py
class DummyEnvironment(collections.UserDict):
def __init__(self, **kw):
super().__init__()
self.data.update(kw)
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
return self.data
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_list(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return [self.data[strSubst[1:]]]
return [[strSubst]]
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
else:
my_normpath = os.path.normpath
def deps_match(self, deps, headers):
global my_normpath
scanned = list(map(my_normpath, list(map(str, deps))))
expect = list(map(my_normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
class LaTeXScannerTestCase1(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LATEXSUFFIXES = [".tex", ".ltx", ".latex"])
s = SCons.Scanner.LaTeX.LaTeXScanner()
path = s.path(env)
deps = s(env.File('test1.latex'), env, path)
headers = ['inc1.tex', 'inc2.tex', 'inc6.tex',
'subdir/inc3.tex', 'subdir/inc3a.tex',
'subdir/inc3b.tex', 'subdir/inc3c.tex',
'subdir/inc3d.tex', 'subdir/inc3e.tex']
deps_match(self, deps, headers)
class LaTeXScannerTestCase2(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(TEXINPUTS=[test.workpath("subdir")],LATEXSUFFIXES = [".tex", ".ltx", ".latex"])
s = SCons.Scanner.LaTeX.LaTeXScanner()
path = s.path(env)
deps = s(env.File('test2.latex'), env, path)
headers = ['inc1.tex', 'subdir/inc3.tex']
deps_match(self, deps, headers)
class LaTeXScannerTestCase3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(TEXINPUTS=[test.workpath("subdir")],LATEXSUFFIXES = [".tex", ".ltx", ".latex"])
s = SCons.Scanner.LaTeX.LaTeXScanner()
path = s.path(env)
deps = s(env.File('test3.latex'), env, path)
files = ['inc5.xyz', 'subdir/inc4.eps']
deps_match(self, deps, files)
class LaTeXScannerTestCase4(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(TEXINPUTS=[test.workpath("subdir")],LATEXSUFFIXES = [".tex", ".ltx", ".latex"])
s = SCons.Scanner.LaTeX.LaTeXScanner()
path = s.path(env)
deps = s(env.File('test4.latex'), env, path)
files = ['inc1.tex', 'inc2.tex', 'inc5.xyz', 'inc7.png']
deps_match(self, deps, files)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,264 +0,0 @@
# 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 os.path
import unittest
import TestCmd
import SCons.Node.FS
import SCons.Scanner.Prog
import SCons.Subst
test = TestCmd.TestCmd(workdir = '')
test.subdir('d1', ['d1', 'd2'], 'dir', ['dir', 'sub'])
libs = [ 'l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib',
'dir/libfoo.a', 'dir/sub/libbar.a', 'dir/libxyz.other']
for h in libs:
test.write(h, "\n")
# define some helpers:
class DummyEnvironment:
def __init__(self, **kw):
self._dict = {'LIBSUFFIXES' : '.lib'}
self._dict.update(kw)
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
if not args:
return self._dict
elif len(args) == 1:
return self._dict[args[0]]
else:
return [self._dict[x] for x in args]
def __contains__(self, key):
return key in self.Dictionary()
def __getitem__(self,key):
return self.Dictionary()[key]
def __setitem__(self,key,value):
self.Dictionary()[key] = value
def __delitem__(self,key):
del self.Dictionary()[key]
def subst(self, s, target=None, source=None, conv=None):
return SCons.Subst.scons_subst(s, self, gvars=self._dict, lvars=self._dict)
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(test.workpath(filename))
def File(self, filename):
return self.fs.File(test.workpath(filename))
class DummyNode:
def __init__(self, name):
self.name = name
def rexists(self):
return 1
def __str__(self):
return self.name
def deps_match(deps, libs):
deps=sorted(map(str, deps))
libs.sort()
return list(map(os.path.normpath, deps)) == list(map(os.path.normpath, libs))
# define some tests:
class ProgramScannerTestCase1(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[ test.workpath("") ],
LIBS=[ 'l1', 'l2', 'l3' ])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['l1.lib']), list(map(str, deps))
env = DummyEnvironment(LIBPATH=[ test.workpath("") ],
LIBS='l1')
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['l1.lib']), list(map(str, deps))
f1 = env.fs.File(test.workpath('f1'))
env = DummyEnvironment(LIBPATH=[ test.workpath("") ],
LIBS=[f1])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps[0] is f1, deps
f2 = env.fs.File(test.workpath('f1'))
env = DummyEnvironment(LIBPATH=[ test.workpath("") ],
LIBS=f2)
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps[0] is f2, deps
class ProgramScannerTestCase2(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=list(map(test.workpath,
["", "d1", "d1/d2" ])),
LIBS=[ 'l1', 'l2', 'l3' ])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib' ]), list(map(str, deps))
class ProgramScannerTestCase3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[test.workpath("d1/d2"),
test.workpath("d1")],
LIBS='l2 l3'.split())
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), list(map(str, deps))
class ProgramScannerTestCase5(unittest.TestCase):
def runTest(self):
class SubstEnvironment(DummyEnvironment):
def subst(self, arg, target=None, source=None, conv=None, path=test.workpath("d1")):
if arg == "$blah":
return test.workpath("d1")
else:
return arg
env = SubstEnvironment(LIBPATH=[ "$blah" ],
LIBS='l2 l3'.split())
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, [ 'd1/l2.lib' ]), list(map(str, deps))
class ProgramScannerTestCase6(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=['foo', 'sub/libbar', 'xyz.other'],
LIBPREFIXES=['lib'],
LIBSUFFIXES=['.a'])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['dir/libfoo.a', 'dir/sub/libbar.a', 'dir/libxyz.other']), list(map(str, deps))
class ProgramScannerTestCase7(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=['foo', '$LIBBAR', '$XYZ'],
LIBPREFIXES=['lib'],
LIBSUFFIXES=['.a'],
LIBBAR='sub/libbar',
XYZ='xyz.other')
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['dir/libfoo.a', 'dir/sub/libbar.a', 'dir/libxyz.other']), list(map(str, deps))
class ProgramScannerTestCase8(unittest.TestCase):
def runTest(self):
n1 = DummyNode('n1')
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=[n1],
LIBPREFIXES=['p1-', 'p2-'],
LIBSUFFIXES=['.1', '2'])
s = SCons.Scanner.Prog.ProgramScanner(node_class = DummyNode)
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps == [n1], deps
n2 = DummyNode('n2')
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=[n1, [n2]],
LIBPREFIXES=['p1-', 'p2-'],
LIBSUFFIXES=['.1', '2'])
s = SCons.Scanner.Prog.ProgramScanner(node_class = DummyNode)
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps == [n1, n2], deps
class ProgramScannerTestCase9(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=['foo', '$LIBBAR'],
LIBPREFIXES=['lib'],
LIBSUFFIXES=['.a'],
LIBBAR=['sub/libbar', 'xyz.other'])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['dir/libfoo.a', 'dir/sub/libbar.a', 'dir/libxyz.other']), list(map(str, deps))
class ProgramScannerTestCase10(unittest.TestCase):
def runTest(self):
env = DummyEnvironment(LIBPATH=[ test.workpath("dir") ],
LIBS=['foo', '$LIBBAR'],
LIBPREFIXES=['lib'],
LIBSUFFIXES=['.a'],
LIBBAR='sub/libbar $LIBBAR2',
LIBBAR2=['xyz.other'])
s = SCons.Scanner.Prog.ProgramScanner()
path = s.path(env)
deps = s(DummyNode('dummy'), env, path)
assert deps_match(deps, ['dir/libfoo.a', 'dir/sub/libbar.a', 'dir/libxyz.other']), list(map(str, deps))
def suite():
suite = unittest.TestSuite()
suite.addTest(ProgramScannerTestCase1())
suite.addTest(ProgramScannerTestCase2())
suite.addTest(ProgramScannerTestCase3())
suite.addTest(ProgramScannerTestCase5())
suite.addTest(ProgramScannerTestCase6())
suite.addTest(ProgramScannerTestCase7())
suite.addTest(ProgramScannerTestCase8())
suite.addTest(ProgramScannerTestCase9())
suite.addTest(ProgramScannerTestCase10())
return suite
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,331 +0,0 @@
# 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.
"""
Unit tests for the Python scanner. These tests validate proper working of the
Python scanner by confirming that the results of the scan match expectations.
The absolute path tests have strongly-defined behavior in that there is no real
ambiguity to what they should result in. For example, if you import package x,
you expect to get x/__init__.py as a dependency.
The relative path tests that reach into ancestor directories do have some
ambiguity in whether to depend upon __init__.py in those referenced ancestor
directories. Python only allows these kinds of relative imports if the file is
part of a package, in which case those ancestor directories' __init__.py files
have already been imported.
"""
import SCons.compat
import collections
import os
import unittest
import TestCmd
import SCons.Node.FS
import SCons.Scanner.Python
test = TestCmd.TestCmd(workdir='')
test.dir_fixture('python_scanner')
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
else:
my_normpath = os.path.normpath
def deps_match(self, deps, headers):
global my_normpath
scanned = list(map(my_normpath, list(map(str, deps))))
expect = list(map(my_normpath, headers))
self.assertTrue(scanned == expect,
"expect %s != scanned %s" % (expect, scanned))
# Copied from LaTeXTests.py.
class DummyEnvironment(collections.UserDict):
def __init__(self, **kwargs):
super().__init__()
self.data.update(kwargs)
self.fs = SCons.Node.FS.FS(test.workpath(''))
self['ENV'] = {}
def Dictionary(self, *args):
return self.data
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_list(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return [self.data[strSubst[1:]]]
return [[strSubst]]
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
class PythonScannerTestPythonPath(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
env['ENV']['PYTHONPATH'] = test.workpath('')
path = s.path(env)
deps = s(env.File('imports_simple_package.py'), env, path)
files = ['simple_package/__init__.py']
deps_match(self, deps, files)
class PythonScannerTestPythonCallablePath(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
env['ENV']['PYTHONPATH'] = test.workpath('')
deps = s(env.File('imports_simple_package.py'), env,
lambda : s.path(env))
files = ['simple_package/__init__.py']
deps_match(self, deps, files)
class PythonScannerTestImportSimplePackage(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('imports_simple_package.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py']
deps_match(self, deps, files)
# Repeat the test in case there are any issues caching includes.
deps = s(node, env, path)
deps_match(self, deps, files)
class PythonScannerTestImportSimplePackageModule1As(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('import_simple_package_module1_as.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py']
deps_match(self, deps, files)
class PythonScannerTestImportSimplePackageModuleAs(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('import_simple_package_module1.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py']
deps_match(self, deps, files)
class PythonScannerTestFromImportSimplePackageModule1(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('from_import_simple_package_module1.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py']
deps_match(self, deps, files)
class PythonScannerTestFromImportSimplePackageModule1As(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('from_import_simple_package_module1_as.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py']
deps_match(self, deps, files)
class PythonScannerTestFromImportSimplePackageModulesNoSpace(
unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('from_import_simple_package_modules_no_space.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py',
'simple_package/module2.py']
deps_match(self, deps, files)
class PythonScannerTestFromImportSimplePackageModulesWithSpace(
unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('from_import_simple_package_modules_with_space.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['simple_package/__init__.py', 'simple_package/module1.py',
'simple_package/module2.py']
deps_match(self, deps, files)
class PythonScannerTestCurdirReferenceScript(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.Dir('curdir_reference').File('script.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['curdir_reference/helper.py']
deps_match(self, deps, files)
class PythonScannerTestImportsNested3(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File('imports_nested3.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['nested1/__init__.py', 'nested1/nested2/__init__.py',
'nested1/nested2/nested3/__init__.py']
deps_match(self, deps, files)
class PythonScannerTestImportsGrandparentModule(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File(
'nested1/nested2/nested3/imports_grandparent_module.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['nested1/module.py']
deps_match(self, deps, files)
class PythonScannerTestImportsParentModule(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File(
'nested1/nested2/nested3/imports_parent_module.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['nested1/nested2/module.py']
deps_match(self, deps, files)
class PythonScannerTestImportsParentThenSubmodule(unittest.TestCase):
def runTest(self):
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
node = env.File(
'nested1/nested2/nested3/imports_parent_then_submodule.py')
path = s.path(env, source=[node])
deps = s(node, env, path)
files = ['nested1/nested2a/__init__.py', 'nested1/nested2a/module.py']
deps_match(self, deps, files)
class PythonScannerTestImportsModuleWithFunc(unittest.TestCase):
def runTest(self):
"""
This test case tests the following import statement:
`from simple_package.module1 import somefunc` with somefunc.py existing
in the same folder as module1.py. It validates that the scanner doesn't
accidentally take a dependency somefunc.py.
"""
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
env['ENV']['PYTHONPATH'] = test.workpath('')
deps = s(env.File('from_import_simple_package_module1_func.py'), env,
lambda : s.path(env))
files = ['simple_package/__init__.py', 'simple_package/module1.py']
deps_match(self, deps, files)
class PythonScannerTestFromNested1ImportNested2(unittest.TestCase):
def runTest(self):
"""
This test case tests the following import statement:
`from nested1 import module, nested2`. In this test, module is a Python
module and nested2 is a package. Validates that the scanner can handle
such mixed imports.
"""
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
env['ENV']['PYTHONPATH'] = test.workpath('')
deps = s(env.File('from_nested1_import_multiple.py'), env,
lambda : s.path(env))
files = ['nested1/__init__.py', 'nested1/module.py',
'nested1/nested2/__init__.py']
deps_match(self, deps, files)
class PythonScannerTestImportUnknownFiles(unittest.TestCase):
def runTest(self):
"""
This test case tests importing files that are not found. If Python
really can't find those files, it will fail. But this is intended to
test the various failure paths in the scanner to make sure that they
don't raise exceptions.
"""
env = DummyEnvironment()
s = SCons.Scanner.Python.PythonScanner
env['ENV']['PYTHONPATH'] = test.workpath('')
deps = s(env.File('imports_unknown_files.py'), env,
lambda : s.path(env))
files = []
deps_match(self, deps, files)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,165 +0,0 @@
# 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 collections
import os
import TestCmd
import SCons.Scanner.RC
import SCons.Node.FS
import SCons.Warnings
test = TestCmd.TestCmd(workdir = '')
os.chdir(test.workpath(''))
# create some source files and headers:
test.write('t1.rc','''
#include "t1.h"
''')
test.write('t2.rc',"""
#include "t1.h"
ICO_TEST ICON DISCARDABLE "abc.ico"
BMP_TEST BITMAP DISCARDABLE "def.bmp"
cursor1 CURSOR "bullseye.cur"
ID_RESPONSE_ERROR_PAGE HTML "responseerrorpage.htm"
5 FONT "cmroman.fnt"
1 MESSAGETABLE "MSG00409.bin"
1 MESSAGETABLE MSG00410.bin
1 TYPELIB "testtypelib.tlb"
TEST_REGIS REGISTRY MOVEABLE PURE "testregis.rgs"
TEST_D3DFX D3DFX DISCARDABLE "testEffect.fx"
""")
test.write('t3.rc','#include "t1.h"\r\n')
# Create dummy include files
headers = ['t1.h',
'abc.ico','def.bmp','bullseye.cur','responseerrorpage.htm','cmroman.fnt',
'testEffect.fx',
'MSG00409.bin','MSG00410.bin','testtypelib.tlb','testregis.rgs']
for h in headers:
test.write(h, " ")
# define some helpers:
class DummyEnvironment(collections.UserDict):
def __init__(self, **kwargs):
super().__init__()
self.data.update(kwargs)
self.fs = SCons.Node.FS.FS(test.workpath(''))
def Dictionary(self, *args):
return self.data
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def __contains__(self, key):
return key in self.data
def get_calculator(self):
return None
def get_factory(self, factory):
return factory or self.fs.File
def Dir(self, filename):
return self.fs.Dir(filename)
def File(self, filename):
return self.fs.File(filename)
global my_normpath
my_normpath = os.path.normpath
if os.path.normcase('foo') == os.path.normcase('FOO'):
my_normpath = os.path.normcase
def deps_match(self, deps, headers):
scanned = sorted(map(my_normpath, list(map(str, deps))))
expect = sorted(map(my_normpath, headers))
self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
# define some tests:
class RCScannerTestCase1(unittest.TestCase):
def runTest(self):
path = []
env = DummyEnvironment(RCSUFFIXES=['.rc','.rc2'],
CPPPATH=path)
s = SCons.Scanner.RC.RCScan()
deps = s(env.File('t1.rc'), env, path)
headers = ['t1.h']
deps_match(self, deps, headers)
class RCScannerTestCase2(unittest.TestCase):
def runTest(self):
path = []
env = DummyEnvironment(RCSUFFIXES=['.rc','.rc2'],
CPPPATH=path)
s = SCons.Scanner.RC.RCScan()
deps = s(env.File('t2.rc'), env, path)
headers = ['MSG00410.bin',
'abc.ico','bullseye.cur',
'cmroman.fnt','def.bmp',
'MSG00409.bin',
'responseerrorpage.htm',
't1.h',
'testEffect.fx',
'testregis.rgs','testtypelib.tlb']
deps_match(self, deps, headers)
class RCScannerTestCase3(unittest.TestCase):
def runTest(self):
path = []
env = DummyEnvironment(RCSUFFIXES=['.rc','.rc2'],
CPPPATH=path)
s = SCons.Scanner.RC.RCScan()
deps = s(env.File('t3.rc'), env, path)
headers = ['t1.h']
deps_match(self, deps, headers)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,635 +0,0 @@
# 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 collections
import unittest
import TestUnit
import SCons.compat
import SCons.Scanner
from SCons.Scanner import ScannerBase, Selector, Classic, ClassicCPP, Current, FindPathDirs
class DummyFS:
def File(self, name):
return DummyNode(name)
class DummyEnvironment(collections.UserDict):
def __init__(self, mapping=None, **kwargs):
super().__init__(mapping)
self.data.update(kwargs)
self.fs = DummyFS()
def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
def subst_list(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return [self.data[strSubst[1:]]]
return [[strSubst]]
def subst_path(self, path, target=None, source=None, conv=None):
if not isinstance(path, list):
path = [path]
return list(map(self.subst, path))
def get_factory(self, factory):
return factory or self.fs.File
class DummyNode:
def __init__(self, name, search_result=()):
self.name = name
self.search_result = tuple(search_result)
def rexists(self):
return True
def __str__(self):
return self.name
def Rfindalldirs(self, pathlist):
return self.search_result + pathlist
def __repr__(self):
return self.name
def __eq__(self, other):
return self.name == other.name
def __repr__(self):
return self.name
def __eq__(self, other):
return self.name == other.name
class FindPathDirsTestCase(unittest.TestCase):
def test_FindPathDirs(self):
"""Test the FindPathDirs callable class"""
env = DummyEnvironment(LIBPATH = [ 'foo' ])
env.fs = DummyFS()
env.fs._cwd = DummyNode('cwd')
dir = DummyNode('dir', ['xxx'])
fpd = FindPathDirs('LIBPATH')
result = fpd(env)
assert str(result) == "('foo',)", result
result = fpd(env, dir)
assert str(result) == "('xxx', 'foo')", result
class ScannerTestCase(unittest.TestCase):
def test_creation(self):
"""Test creation of Scanner objects"""
def func(self):
pass
s = ScannerBase(func)
assert isinstance(s, ScannerBase), s
s = ScannerBase({})
assert isinstance(s, ScannerBase), s
s = ScannerBase(func, name='fooscan')
assert str(s) == 'fooscan', str(s)
s = ScannerBase({}, name='barscan')
assert str(s) == 'barscan', str(s)
s = ScannerBase(func, name='fooscan', argument=9)
assert str(s) == 'fooscan', str(s)
assert s.argument == 9, s.argument
s = ScannerBase({}, name='fooscan', argument=888)
assert str(s) == 'fooscan', str(s)
assert s.argument == 888, s.argument
class ScannerBaseTestCase(unittest.TestCase):
class skey_node:
def __init__(self, key):
self.key = key
def scanner_key(self):
return self.key
def rexists(self):
return 1
def func(self, filename, env, target, *args):
self.filename = filename
self.env = env
self.target = target
if len(args) > 0:
self.arg = args[0]
return self.deps
def test(self, scanner, env, filename, deps, *args):
self.deps = deps
path = scanner.path(env)
scanned = scanner(filename, env, path)
scanned_strs = [str(x) for x in scanned]
self.assertTrue(self.filename == filename, "the filename was passed incorrectly")
self.assertTrue(self.env == env, "the environment was passed incorrectly")
self.assertTrue(scanned_strs == deps, "the dependencies were returned incorrectly")
for d in scanned:
self.assertTrue(not isinstance(d, str), "got a string in the dependencies")
if len(args) > 0:
self.assertTrue(self.arg == args[0], "the argument was passed incorrectly")
else:
self.assertFalse(hasattr(self, "arg"), "an argument was given when it shouldn't have been")
def test___call__dict(self):
"""Test calling ScannerBase objects with a dictionary"""
called = []
def s1func(node, env, path, called=called):
called.append('s1func')
called.append(node)
return []
def s2func(node, env, path, called=called):
called.append('s2func')
called.append(node)
return []
s1 = ScannerBase(s1func)
s2 = ScannerBase(s2func)
selector = ScannerBase({'.x' : s1, '.y' : s2})
nx = self.skey_node('.x')
env = DummyEnvironment()
selector(nx, env, [])
assert called == ['s1func', nx], called
del called[:]
ny = self.skey_node('.y')
selector(ny, env, [])
assert called == ['s2func', ny], called
def test_path(self):
"""Test the ScannerBase path() method"""
def pf(env, cwd, target, source, argument=None):
return "pf: %s %s %s %s %s" % \
(env.VARIABLE, cwd, target[0], source[0], argument)
env = DummyEnvironment()
env.VARIABLE = 'v1'
target = DummyNode('target')
source = DummyNode('source')
s = ScannerBase(self.func, path_function=pf)
p = s.path(env, 'here', [target], [source])
assert p == "pf: v1 here target source None", p
s = ScannerBase(self.func, path_function=pf, argument="xyz")
p = s.path(env, 'here', [target], [source])
assert p == "pf: v1 here target source xyz", p
def test_positional(self):
"""Test the ScannerBase class using positional arguments"""
s = ScannerBase(self.func, "Pos")
env = DummyEnvironment()
env.VARIABLE = "var1"
self.test(s, env, DummyNode('f1.cpp'), ['f1.h', 'f1.hpp'])
env = DummyEnvironment()
env.VARIABLE = "i1"
self.test(s, env, DummyNode('i1.cpp'), ['i1.h', 'i1.hpp'])
def test_keywords(self):
"""Test the ScannerBase class using keyword arguments"""
s = ScannerBase(function = self.func, name = "Key")
env = DummyEnvironment()
env.VARIABLE = "var2"
self.test(s, env, DummyNode('f2.cpp'), ['f2.h', 'f2.hpp'])
env = DummyEnvironment()
env.VARIABLE = "i2"
self.test(s, env, DummyNode('i2.cpp'), ['i2.h', 'i2.hpp'])
def test_pos_opt(self):
"""Test the ScannerBase class using both position and optional arguments"""
arg = "this is the argument"
s = ScannerBase(self.func, "PosArg", arg)
env = DummyEnvironment()
env.VARIABLE = "var3"
self.test(s, env, DummyNode('f3.cpp'), ['f3.h', 'f3.hpp'], arg)
env = DummyEnvironment()
env.VARIABLE = "i3"
self.test(s, env, DummyNode('i3.cpp'), ['i3.h', 'i3.hpp'], arg)
def test_key_opt(self):
"""Test the ScannerBase class using both keyword and optional arguments"""
arg = "this is another argument"
s = ScannerBase(function = self.func, name = "KeyArg", argument = arg)
env = DummyEnvironment()
env.VARIABLE = "var4"
self.test(s, env, DummyNode('f4.cpp'), ['f4.h', 'f4.hpp'], arg)
env = DummyEnvironment()
env.VARIABLE = "i4"
self.test(s, env, DummyNode('i4.cpp'), ['i4.h', 'i4.hpp'], arg)
def test___cmp__(self):
"""Test the ScannerBase class __cmp__() method"""
s = ScannerBase(self.func, "Cmp")
assert s is not None
def test_hash(self):
"""Test the ScannerBase class __hash__() method"""
s = ScannerBase(self.func, "Hash")
mapping = {}
mapping[s] = 777
i = hash(id(s))
h = hash(list(mapping)[0])
self.assertTrue(h == i,
"hash Scanner base class expected %s, got %s" % (i, h))
def test_scan_check(self):
"""Test the ScannerBase class scan_check() method"""
def my_scan(filename, env, target, *args):
return []
def check(node, env, s=self):
s.checked[str(node)] = 1
return 1
env = DummyEnvironment()
s = ScannerBase(my_scan, "Check", scan_check = check)
self.checked = {}
path = s.path(env)
scanned = s(DummyNode('x'), env, path)
self.assertTrue(self.checked['x'] == 1,
"did not call check function")
def test_recursive(self):
"""Test the ScannerBase class recursive flag"""
nodes = [1, 2, 3, 4]
s = ScannerBase(function = self.func)
n = s.recurse_nodes(nodes)
self.assertTrue(n == [], "default behavior returned nodes: %s" % n)
s = ScannerBase(function = self.func, recursive = None)
n = s.recurse_nodes(nodes)
self.assertTrue(n == [], "recursive = None returned nodes: %s" % n)
s = ScannerBase(function = self.func, recursive = 1)
n = s.recurse_nodes(nodes)
self.assertTrue(n == n, "recursive = 1 didn't return all nodes: %s" % n)
def odd_only(nodes):
return [n for n in nodes if n % 2]
s = ScannerBase(function = self.func, recursive = odd_only)
n = s.recurse_nodes(nodes)
self.assertTrue(n == [1, 3], "recursive = 1 didn't return all nodes: %s" % n)
def test_get_skeys(self):
"""Test the ScannerBase get_skeys() method"""
s = ScannerBase(function = self.func)
sk = s.get_skeys()
self.assertTrue(sk == [], "did not initialize to expected []")
s = ScannerBase(function = self.func, skeys = ['.1', '.2'])
sk = s.get_skeys()
self.assertTrue(sk == ['.1', '.2'], "sk was %s, not ['.1', '.2']")
s = ScannerBase(function = self.func, skeys = '$LIST')
env = DummyEnvironment(LIST = ['.3', '.4'])
sk = s.get_skeys(env)
self.assertTrue(sk == ['.3', '.4'], "sk was %s, not ['.3', '.4']")
def test_select(self):
"""Test the ScannerBase select() method"""
scanner = ScannerBase(function = self.func)
s = scanner.select('.x')
assert s is scanner, s
selector = ScannerBase({'.x' : 1, '.y' : 2})
s = selector.select(self.skey_node('.x'))
assert s == 1, s
s = selector.select(self.skey_node('.y'))
assert s == 2, s
s = selector.select(self.skey_node('.z'))
assert s is None, s
def test_add_scanner(self):
"""Test the ScannerBase add_scanner() method"""
selector = ScannerBase({'.x' : 1, '.y' : 2})
s = selector.select(self.skey_node('.z'))
assert s is None, s
selector.add_scanner('.z', 3)
s = selector.select(self.skey_node('.z'))
assert s == 3, s
def test___str__(self):
"""Test the ScannerBase __str__() method"""
scanner = ScannerBase(function = self.func)
s = str(scanner)
assert s == 'NONE', s
scanner = ScannerBase(function = self.func, name = 'xyzzy')
s = str(scanner)
assert s == 'xyzzy', s
class SelectorTestCase(unittest.TestCase):
class skey_node:
def __init__(self, key):
self.key = key
def scanner_key(self):
return self.key
def rexists(self):
return 1
def test___init__(self):
"""Test creation of Scanner.Selector object"""
s = Selector({})
assert isinstance(s, Selector), s
assert s.mapping == {}, s.mapping
def test___call__(self):
"""Test calling Scanner.Selector objects"""
called = []
def s1func(node, env, path, called=called):
called.append('s1func')
called.append(node)
return []
def s2func(node, env, path, called=called):
called.append('s2func')
called.append(node)
return []
s1 = ScannerBase(s1func)
s2 = ScannerBase(s2func)
selector = Selector({'.x' : s1, '.y' : s2})
nx = self.skey_node('.x')
env = DummyEnvironment()
selector(nx, env, [])
assert called == ['s1func', nx], called
del called[:]
ny = self.skey_node('.y')
selector(ny, env, [])
assert called == ['s2func', ny], called
def test_select(self):
"""Test the Scanner.Selector select() method"""
selector = Selector({'.x' : 1, '.y' : 2})
s = selector.select(self.skey_node('.x'))
assert s == 1, s
s = selector.select(self.skey_node('.y'))
assert s == 2, s
s = selector.select(self.skey_node('.z'))
assert s is None, s
def test_add_scanner(self):
"""Test the Scanner.Selector add_scanner() method"""
selector = Selector({'.x' : 1, '.y' : 2})
s = selector.select(self.skey_node('.z'))
assert s is None, s
selector.add_scanner('.z', 3)
s = selector.select(self.skey_node('.z'))
assert s == 3, s
class CurrentTestCase(unittest.TestCase):
def test_class(self):
"""Test the Scanner.Current class"""
class MyNode:
def __init__(self):
self.called_has_builder = None
self.called_is_up_to_date = None
self.func_called = None
def rexists(self):
return 1
class HasNoBuilder(MyNode):
def has_builder(self):
self.called_has_builder = 1
return None
class IsNotCurrent(MyNode):
def has_builder(self):
self.called_has_builder = 1
return 1
def is_up_to_date(self):
self.called_is_up_to_date = 1
return None
class IsCurrent(MyNode):
def has_builder(self):
self.called_has_builder = 1
return 1
def is_up_to_date(self):
self.called_is_up_to_date = 1
return 1
def func(node, env, path):
node.func_called = 1
return []
env = DummyEnvironment()
s = Current(func)
path = s.path(env)
hnb = HasNoBuilder()
s(hnb, env, path)
self.assertTrue(hnb.called_has_builder, "did not call has_builder()")
self.assertTrue(not hnb.called_is_up_to_date, "did call is_up_to_date()")
self.assertTrue(hnb.func_called, "did not call func()")
inc = IsNotCurrent()
s(inc, env, path)
self.assertTrue(inc.called_has_builder, "did not call has_builder()")
self.assertTrue(inc.called_is_up_to_date, "did not call is_up_to_date()")
self.assertTrue(not inc.func_called, "did call func()")
ic = IsCurrent()
s(ic, env, path)
self.assertTrue(ic.called_has_builder, "did not call has_builder()")
self.assertTrue(ic.called_is_up_to_date, "did not call is_up_to_date()")
self.assertTrue(ic.func_called, "did not call func()")
class ClassicTestCase(unittest.TestCase):
def func(self, filename, env, target, *args):
self.filename = filename
self.env = env
self.target = target
if len(args) > 0:
self.arg = args[0]
return self.deps
def test_find_include(self):
"""Test the Scanner.Classic find_include() method"""
env = DummyEnvironment()
s = Classic("t", ['.suf'], 'MYPATH', r'^my_inc (\S+)')
def _find_file(filename, paths):
return paths[0]+'/'+filename
save = SCons.Node.FS.find_file
SCons.Node.FS.find_file = _find_file
try:
n, i = s.find_include('aaa', 'foo', ('path',))
assert n == 'foo/aaa', n
assert i == 'aaa', i
finally:
SCons.Node.FS.find_file = save
def test_name(self):
"""Test setting the Scanner.Classic name"""
s = Classic("my_name", ['.s'], 'MYPATH', r'^my_inc (\S+)')
assert s.name == "my_name", s.name
def test_scan(self):
"""Test the Scanner.Classic scan() method"""
class MyNode:
def __init__(self, name):
self.name = name
self._rfile = self
self.includes = None
def rfile(self):
return self._rfile
def exists(self):
return self._exists
def get_contents(self):
return self._contents
def get_text_contents(self):
return self._contents
def get_dir(self):
return self._dir
class MyScanner(Classic):
def find_include(self, include, source_dir, path):
return include, include
env = DummyEnvironment()
s = MyScanner("t", ['.suf'], 'MYPATH', r'^my_inc (\S+)')
# This set of tests is intended to test the scanning operation
# of the Classic scanner.
# Note that caching has been added for not just the includes
# but the entire scan call. The caching is based on the
# arguments, so we will fiddle with the path parameter to
# defeat this caching for the purposes of these tests.
# If the node doesn't exist, scanning turns up nothing.
n1 = MyNode("n1")
n1._exists = None
ret = s.function(n1, env)
assert ret == [], ret
# Verify that it finds includes from the contents.
n = MyNode("n")
n._exists = 1
n._dir = MyNode("n._dir")
n._contents = 'my_inc abc\n'
ret = s.function(n, env, ('foo',))
assert ret == ['abc'], ret
# Verify that it uses the cached include info.
n._contents = 'my_inc def\n'
ret = s.function(n, env, ('foo2',))
assert ret == ['abc'], ret
# Verify that if we wipe the cache, it uses the new contents.
n.includes = None
ret = s.function(n, env, ('foo3',))
assert ret == ['def'], ret
# We no longer cache overall scan results, which would be returned
# if individual results are de-cached. If we ever restore that
# functionality, this test goes back here.
#ret = s.function(n, env, ('foo2',))
#assert ret == ['abc'], 'caching inactive; got: %s'%ret
# Verify that it sorts what it finds.
n.includes = ['xyz', 'uvw']
ret = s.function(n, env, ('foo4',))
assert ret == ['uvw', 'xyz'], ret
# Verify that we use the rfile() node.
nr = MyNode("nr")
nr._exists = 1
nr._dir = MyNode("nr._dir")
nr.includes = ['jkl', 'mno']
n._rfile = nr
ret = s.function(n, env, ('foo5',))
assert ret == ['jkl', 'mno'], ret
def test_recursive(self):
"""Test the Scanner.Classic class recursive flag"""
nodes = [1, 2, 3, 4]
s = Classic("Test", [], None, "", function=self.func, recursive=1)
n = s.recurse_nodes(nodes)
self.assertTrue(n == n,
"recursive = 1 didn't return all nodes: %s" % n)
def odd_only(nodes):
return [n for n in nodes if n % 2]
s = Classic("Test", [], None, "", function=self.func, recursive=odd_only)
n = s.recurse_nodes(nodes)
self.assertTrue(n == [1, 3],
"recursive = 1 didn't return all nodes: %s" % n)
class ClassicCPPTestCase(unittest.TestCase):
def test_find_include(self):
"""Test the Scanner.ClassicCPP find_include() method"""
env = DummyEnvironment()
s = ClassicCPP("Test", [], None, "")
def _find_file(filename, paths):
return paths[0]+'/'+filename
save = SCons.Node.FS.find_file
SCons.Node.FS.find_file = _find_file
try:
n, i = s.find_include(('"', 'aaa'), 'foo', ('path',))
assert n == 'foo/aaa', n
assert i == 'aaa', i
n, i = s.find_include(('<', 'bbb'), 'foo', ('path',))
assert n == 'path/bbb', n
assert i == 'bbb', i
n, i = s.find_include(('<', 'ccc'), 'foo', ('path',))
assert n == 'path/ccc', n
assert i == 'ccc', i
finally:
SCons.Node.FS.find_file = save
def suite():
suite = unittest.TestSuite()
tclasses = [
FindPathDirsTestCase,
ScannerTestCase,
ScannerBaseTestCase,
SelectorTestCase,
CurrentTestCase,
ClassicTestCase,
ClassicCPPTestCase,
]
for tclass in tclasses:
names = unittest.getTestCaseNames(tclass, 'test_')
suite.addTests(list(map(tclass, names)))
return suite
if __name__ == "__main__":
TestUnit.run(suite())
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -97,7 +97,6 @@ class SConsPrintHelpException(Exception):
display = SCons.Util.display
progress_display = SCons.Util.DisplayEngine()
class Progressor:
prev = ''
count = 0

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
# 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.
"""
Unit tests for linkCommon package
"""
import unittest
from SCons.Environment import Environment
class SharedLibraryTestCase(unittest.TestCase):
def setUp(self):
pass
def test_shlib_symlink_emitter(self):
"""Test shlib_symlink_emitter() """
env = Environment(tools=['gnulink'])
target = env.SharedLibrary('lib', 'lib.c', SHLIBPREFIX='lib', SHLIBSUFFIX=".so")
target_name = str(target[0])
self.assertEqual(str(target_name), 'liblib.so', "Expected target 'liblib.so' != '%s'" % target_name)
target = env.SharedLibrary('xyz', 'lib.c', SHLIBPREFIX='xyz', SHLIBSUFFIX=".so", SHLIBVERSION='1.2.3')
t0 = target[0]
target_name = str(t0)
assert target_name == 'xyzxyz.so.1.2.3', "Expected target 'xyzxyz.so.1.2.3' != '%s'" % target_name
if hasattr(t0.attributes, 'shliblinks'):
(soname_symlink, t0_1) = t0.attributes.shliblinks[0]
(shlib_noversion_symlink, t0_2) = t0.attributes.shliblinks[1]
self.assertEqual(t0_1, t0, "soname_symlink target is not target[0]")
self.assertEqual(t0_2, t0, "shlib_noversion_symlink target is not target[0]")
self.assertEqual(str(soname_symlink), 'xyzxyz.so.1',
"soname symlink is not 'xyzxyz.so.1': '%s'" % str(soname_symlink))
self.assertEqual(str(shlib_noversion_symlink), 'xyzxyz.so',
"shlib_noversion_symlink is not 'xyzxyz.so': '%s'" % str(shlib_noversion_symlink))
else:
self.fail('Target xyzxyz.so.1.2.3 has no .attributes.shliblinks')
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

File diff suppressed because it is too large Load Diff

View File

@ -1,122 +0,0 @@
# 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 SCons.Errors
import SCons.Variables
class BoolVariableTestCase(unittest.TestCase):
def test_BoolVariable(self):
"""Test BoolVariable creation"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.BoolVariable('test', 'test option help', 0))
o = opts.options[0]
assert o.key == 'test', o.key
assert o.help == 'test option help (yes|no)', o.help
assert o.default == 0, o.default
assert o.validator is not None, o.validator
assert o.converter is not None, o.converter
def test_converter(self):
"""Test the BoolVariable converter"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.BoolVariable('test', 'test option help', 0))
o = opts.options[0]
true_values = [
'y', 'Y',
'yes', 'YES',
't', 'T',
'true', 'TRUE',
'on', 'ON',
'all', 'ALL',
'1',
]
false_values = [
'n', 'N',
'no', 'NO',
'f', 'F',
'false', 'FALSE',
'off', 'OFF',
'none', 'NONE',
'0',
]
for t in true_values:
x = o.converter(t)
assert x, "converter returned false for '%s'" % t
for f in false_values:
x = o.converter(f)
assert not x, "converter returned true for '%s'" % f
caught = None
try:
o.converter('x')
except ValueError:
caught = 1
assert caught, "did not catch expected ValueError"
def test_validator(self):
"""Test the BoolVariable validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.BoolVariable('test', 'test option help', 0))
o = opts.options[0]
env = {
'T' : True,
'F' : False,
'N' : 'xyzzy',
}
o.validator('T', 0, env)
o.validator('F', 0, env)
caught = None
try:
o.validator('N', 0, env)
except SCons.Errors.UserError:
caught = 1
assert caught, "did not catch expected UserError for N"
caught = None
try:
o.validator('NOSUCHKEY', 0, env)
except KeyError:
caught = 1
assert caught, "did not catch expected KeyError for NOSUCHKEY"
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,199 +0,0 @@
# 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 SCons.Errors
import SCons.Variables
class EnumVariableTestCase(unittest.TestCase):
def test_EnumVariable(self):
"""Test EnumVariable creation"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.EnumVariable('test', 'test option help', 0,
['one', 'two', 'three'],
{}))
o = opts.options[0]
assert o.key == 'test', o.key
assert o.help == 'test option help (one|two|three)', o.help
assert o.default == 0, o.default
assert o.validator is not None, o.validator
assert o.converter is not None, o.converter
def test_converter(self):
"""Test the EnumVariable converter"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.EnumVariable('test', 'test option help', 0,
['one', 'two', 'three']))
o = opts.options[0]
for a in ['one', 'two', 'three', 'no_match']:
x = o.converter(a)
assert x == a, x
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.EnumVariable('test', 'test option help', 0,
['one', 'two', 'three'],
{'1' : 'one',
'2' : 'two',
'3' : 'three'}))
o = opts.options[0]
x = o.converter('one')
assert x == 'one', x
x = o.converter('1')
assert x == 'one', x
x = o.converter('two')
assert x == 'two', x
x = o.converter('2')
assert x == 'two', x
x = o.converter('three')
assert x == 'three', x
x = o.converter('3')
assert x == 'three', x
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.EnumVariable('test0', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=0))
opts.Add(SCons.Variables.EnumVariable('test1', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=1))
opts.Add(SCons.Variables.EnumVariable('test2', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=2))
o0 = opts.options[0]
o1 = opts.options[1]
o2 = opts.options[2]
table = {
'one' : ['one', 'one', 'one'],
'One' : ['One', 'One', 'one'],
'ONE' : ['ONE', 'ONE', 'one'],
'two' : ['two', 'two', 'two'],
'twO' : ['twO', 'twO', 'two'],
'TWO' : ['TWO', 'TWO', 'two'],
'three' : ['three', 'three', 'three'],
'thRee' : ['thRee', 'thRee', 'three'],
'THREE' : ['THREE', 'THREE', 'three'],
'a' : ['one', 'one', 'one'],
'A' : ['A', 'one', 'one'],
'b' : ['two', 'two', 'two'],
'B' : ['B', 'two', 'two'],
'c' : ['three', 'three', 'three'],
'C' : ['C', 'three', 'three'],
}
for k, l in table.items():
x = o0.converter(k)
assert x == l[0], "o0 got %s, expected %s" % (x, l[0])
x = o1.converter(k)
assert x == l[1], "o1 got %s, expected %s" % (x, l[1])
x = o2.converter(k)
assert x == l[2], "o2 got %s, expected %s" % (x, l[2])
def test_validator(self):
"""Test the EnumVariable validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.EnumVariable('test0', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=0))
opts.Add(SCons.Variables.EnumVariable('test1', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=1))
opts.Add(SCons.Variables.EnumVariable('test2', 'test option help', 0,
['one', 'two', 'three'],
{'a' : 'one',
'b' : 'two',
'c' : 'three'},
ignorecase=2))
o0 = opts.options[0]
o1 = opts.options[1]
o2 = opts.options[2]
def valid(o, v):
o.validator('X', v, {})
def invalid(o, v):
caught = None
try:
o.validator('X', v, {})
except SCons.Errors.UserError:
caught = 1
assert caught, "did not catch expected UserError for o = %s, v = %s" % (o.key, v)
table = {
'one' : [ valid, valid, valid],
'One' : [invalid, valid, valid],
'ONE' : [invalid, valid, valid],
'two' : [ valid, valid, valid],
'twO' : [invalid, valid, valid],
'TWO' : [invalid, valid, valid],
'three' : [ valid, valid, valid],
'thRee' : [invalid, valid, valid],
'THREE' : [invalid, valid, valid],
'a' : [invalid, invalid, invalid],
'A' : [invalid, invalid, invalid],
'b' : [invalid, invalid, invalid],
'B' : [invalid, invalid, invalid],
'c' : [invalid, invalid, invalid],
'C' : [invalid, invalid, invalid],
'no_v' : [invalid, invalid, invalid],
}
for v, l in table.items():
l[0](o0, v)
l[1](o1, v)
l[2](o2, v)
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,129 +0,0 @@
# 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 copy
import unittest
import SCons.Errors
import SCons.Variables
class ListVariableTestCase(unittest.TestCase):
def test_ListVariable(self):
"""Test ListVariable creation"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.ListVariable('test', 'test option help', 'all',
['one', 'two', 'three']))
o = opts.options[0]
assert o.key == 'test', o.key
assert o.help == 'test option help\n (all|none|comma-separated list of names)\n allowed names: one two three', repr(o.help)
assert o.default == 'all', o.default
assert o.validator is None, o.validator
assert o.converter is not None, o.converter
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.ListVariable('test2', 'test2 help',
['one', 'three'],
['one', 'two', 'three']))
o = opts.options[0]
assert o.default == 'one,three'
def test_converter(self):
"""Test the ListVariable converter"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.ListVariable('test', 'test option help', 'all',
['one', 'two', 'three'],
{'ONE':'one', 'TWO':'two'}))
o = opts.options[0]
x = o.converter('all')
assert str(x) == 'all', x
x = o.converter('none')
assert str(x) == 'none', x
x = o.converter('one')
assert str(x) == 'one', x
x = o.converter('ONE')
assert str(x) == 'one', x
x = o.converter('two')
assert str(x) == 'two', x
x = o.converter('TWO')
assert str(x) == 'two', x
x = o.converter('three')
assert str(x) == 'three', x
x = o.converter('one,two')
assert str(x) == 'one,two', x
x = o.converter('two,one')
assert str(x) == 'one,two', x
x = o.converter('one,three')
assert str(x) == 'one,three', x
x = o.converter('three,one')
assert str(x) == 'one,three', x
x = o.converter('two,three')
assert str(x) == 'three,two', x
x = o.converter('three,two')
assert str(x) == 'three,two', x
x = o.converter('one,two,three')
assert str(x) == 'all', x
x = o.converter('three,two,one')
assert str(x) == 'all', x
x = o.converter('three,ONE,TWO')
assert str(x) == 'all', x
caught = None
try:
x = o.converter('no_match')
except ValueError:
caught = 1
assert caught, "did not catch expected ValueError"
def test_copy(self):
"""Test copying a ListVariable like an Environment would"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.ListVariable('test', 'test option help', 'all',
['one', 'two', 'three']))
o = opts.options[0]
l = o.converter('all')
n = l.__class__(copy.copy(l))
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,119 +0,0 @@
# 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 SCons.Errors
import SCons.Variables
import TestCmd
class PackageVariableTestCase(unittest.TestCase):
def test_PackageVariable(self):
"""Test PackageVariable creation"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PackageVariable('test', 'test option help', '/default/path'))
o = opts.options[0]
assert o.key == 'test', o.key
assert o.help == 'test option help\n ( yes | no | /path/to/test )', repr(o.help)
assert o.default == '/default/path', o.default
assert o.validator is not None, o.validator
assert o.converter is not None, o.converter
def test_converter(self):
"""Test the PackageVariable converter"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PackageVariable('test', 'test option help', '/default/path'))
o = opts.options[0]
true_values = [
'yes', 'YES',
'true', 'TRUE',
'on', 'ON',
'enable', 'ENABLE',
'search', 'SEARCH',
]
false_values = [
'no', 'NO',
'false', 'FALSE',
'off', 'OFF',
'disable', 'DISABLE',
]
for t in true_values:
x = o.converter(t)
assert x, "converter returned false for '%s'" % t
for f in false_values:
x = o.converter(f)
assert not x, "converter returned true for '%s'" % f
x = o.converter('/explicit/path')
assert x == '/explicit/path', x
# Make sure the converter returns True if we give it str(True) and
# False when we give it str(False). This assures consistent operation
# through a cycle of Variables.Save(<file>) -> Variables(<file>).
x = o.converter(str(True))
assert x, "converter returned a string when given str(True)"
x = o.converter(str(False))
assert not x, "converter returned a string when given str(False)"
def test_validator(self):
"""Test the PackageVariable validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PackageVariable('test', 'test option help', '/default/path'))
test = TestCmd.TestCmd(workdir='')
test.write('exists', 'exists\n')
o = opts.options[0]
env = {'F':False, 'T':True, 'X':'x'}
exists = test.workpath('exists')
does_not_exist = test.workpath('does_not_exist')
o.validator('F', '/path', env)
o.validator('T', '/path', env)
o.validator('X', exists, env)
caught = None
try:
o.validator('X', does_not_exist, env)
except SCons.Errors.UserError:
caught = 1
assert caught, "did not catch expected UserError"
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,240 +0,0 @@
# 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 os.path
import unittest
import SCons.Errors
import SCons.Variables
import TestCmd
class PathVariableTestCase(unittest.TestCase):
def test_PathVariable(self):
"""Test PathVariable creation"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path'))
o = opts.options[0]
assert o.key == 'test', o.key
assert o.help == 'test option help ( /path/to/test )', repr(o.help)
assert o.default == '/default/path', o.default
assert o.validator is not None, o.validator
assert o.converter is None, o.converter
def test_PathExists(self):
"""Test the PathExists validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path',
SCons.Variables.PathVariable.PathExists))
test = TestCmd.TestCmd(workdir='')
test.write('exists', 'exists\n')
o = opts.options[0]
o.validator('X', test.workpath('exists'), {})
dne = test.workpath('does_not_exist')
try:
o.validator('X', dne, {})
except SCons.Errors.UserError as e:
assert str(e) == 'Path for option X does not exist: %s' % dne, e
except:
raise Exception("did not catch expected UserError")
def test_PathIsDir(self):
"""Test the PathIsDir validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path',
SCons.Variables.PathVariable.PathIsDir))
test = TestCmd.TestCmd(workdir='')
test.subdir('dir')
test.write('file', "file\n")
o = opts.options[0]
o.validator('X', test.workpath('dir'), {})
f = test.workpath('file')
try:
o.validator('X', f, {})
except SCons.Errors.UserError as e:
assert str(e) == 'Directory path for option X is a file: %s' % f, e
except:
raise Exception("did not catch expected UserError")
dne = test.workpath('does_not_exist')
try:
o.validator('X', dne, {})
except SCons.Errors.UserError as e:
assert str(e) == 'Directory path for option X does not exist: %s' % dne, e
except Exception as e:
raise Exception("did not catch expected UserError") from e
def test_PathIsDirCreate(self):
"""Test the PathIsDirCreate validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path',
SCons.Variables.PathVariable.PathIsDirCreate))
test = TestCmd.TestCmd(workdir='')
test.write('file', "file\n")
o = opts.options[0]
d = test.workpath('dir')
o.validator('X', d, {})
assert os.path.isdir(d)
f = test.workpath('file')
try:
o.validator('X', f, {})
except SCons.Errors.UserError as e:
assert str(e) == 'Path for option X is a file, not a directory: %s' % f, e
except Exception as e:
raise Exception("did not catch expected UserError") from e
f = '/yyy/zzz' # this not exists and should fail to create
try:
o.validator('X', f, {})
except SCons.Errors.UserError as e:
assert str(e) == 'Path for option X could not be created: %s' % f, e
except Exception as e:
raise Exception("did not catch expected UserError") from e
def test_PathIsFile(self):
"""Test the PathIsFile validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path',
SCons.Variables.PathVariable.PathIsFile))
test = TestCmd.TestCmd(workdir='')
test.subdir('dir')
test.write('file', "file\n")
o = opts.options[0]
o.validator('X', test.workpath('file'), {})
d = test.workpath('d')
try:
o.validator('X', d, {})
except SCons.Errors.UserError as e:
assert str(e) == 'File path for option X does not exist: %s' % d, e
except:
raise Exception("did not catch expected UserError")
dne = test.workpath('does_not_exist')
try:
o.validator('X', dne, {})
except SCons.Errors.UserError as e:
assert str(e) == 'File path for option X does not exist: %s' % dne, e
except:
raise Exception("did not catch expected UserError")
def test_PathAccept(self):
"""Test the PathAccept validator"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path',
SCons.Variables.PathVariable.PathAccept))
test = TestCmd.TestCmd(workdir='')
test.subdir('dir')
test.write('file', "file\n")
o = opts.options[0]
o.validator('X', test.workpath('file'), {})
d = test.workpath('d')
o.validator('X', d, {})
dne = test.workpath('does_not_exist')
o.validator('X', dne, {})
def test_validator(self):
"""Test the PathVariable validator argument"""
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test',
'test option help',
'/default/path'))
test = TestCmd.TestCmd(workdir='')
test.write('exists', 'exists\n')
o = opts.options[0]
o.validator('X', test.workpath('exists'), {})
dne = test.workpath('does_not_exist')
try:
o.validator('X', dne, {})
except SCons.Errors.UserError as e:
expect = 'Path for option X does not exist: %s' % dne
assert str(e) == expect, e
else:
raise Exception("did not catch expected UserError")
def my_validator(key, val, env):
raise Exception("my_validator() got called for %s, %s!" % (key, val))
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.PathVariable('test2',
'more help',
'/default/path/again',
my_validator))
o = opts.options[0]
try:
o.validator('Y', 'value', {})
except Exception as e:
assert str(e) == 'my_validator() got called for Y, value!', e
else:
raise Exception("did not catch expected exception from my_validator()")
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,695 +0,0 @@
# 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:

View File

@ -1,131 +0,0 @@
# 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 SCons.Warnings
class TestOutput:
def __call__(self, x):
args = x.args[0]
if len(args) == 1:
args = args[0]
self.out = str(args)
class WarningsTestCase(unittest.TestCase):
def test_Warning(self):
"""Test warn function."""
# Reset global state
SCons.Warnings._enabled = []
SCons.Warnings._warningAsException = 0
to = TestOutput()
SCons.Warnings._warningOut=to
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"Foo")
assert to.out == "Foo", to.out
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
"Foo", 1)
assert to.out == "('Foo', 1)", to.out
def test_WarningAsExc(self):
"""Test warnings as exceptions."""
# Reset global state
SCons.Warnings._enabled = []
SCons.Warnings._warningAsException = 0
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
old = SCons.Warnings.warningAsException()
assert old == 0, old
exc_caught = 0
try:
SCons.Warnings.warn(SCons.Warnings.SConsWarning, "Foo")
except:
exc_caught = 1
assert exc_caught == 1
old = SCons.Warnings.warningAsException(old)
assert old == 1, old
exc_caught = 0
try:
SCons.Warnings.warn(SCons.Warnings.SConsWarning, "Foo")
except:
exc_caught = 1
assert exc_caught == 0
def test_Disable(self):
"""Test disabling/enabling warnings."""
# Reset global state
SCons.Warnings._enabled = []
SCons.Warnings._warningAsException = 0
to = TestOutput()
SCons.Warnings._warningOut=to
to.out = None
# No warnings by default
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"Foo")
assert to.out is None, to.out
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"Foo")
assert to.out == "Foo", to.out
to.out = None
SCons.Warnings.suppressWarningClass(SCons.Warnings.DeprecatedWarning)
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"Foo")
assert to.out is None, to.out
SCons.Warnings.warn(SCons.Warnings.MandatoryDeprecatedWarning,
"Foo")
assert to.out is None, to.out
# Dependency warnings should still be enabled though
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
SCons.Warnings.warn(SCons.Warnings.DependencyWarning,
"Foo")
assert to.out == "Foo", to.out
# Try reenabling all warnings...
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
SCons.Warnings.enableWarningClass(SCons.Warnings.SConsWarning)
SCons.Warnings.warn(SCons.Warnings.DeprecatedWarning,
"Foo")
assert to.out == "Foo", to.out
if __name__ == "__main__":
unittest.main()
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

View File

@ -1,891 +0,0 @@
# 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 atexit
import unittest
import TestUnit
import cpp
basic_input = """
#include "file1-yes"
#include <file2-yes>
"""
substitution_input = """
#define FILE3 "file3-yes"
#define FILE4 <file4-yes>
#include FILE3
#include FILE4
#define XXX_FILE5 YYY_FILE5
#define YYY_FILE5 ZZZ_FILE5
#define ZZZ_FILE5 FILE5
#define FILE5 "file5-yes"
#define FILE6 <file6-yes>
#define XXX_FILE6 YYY_FILE6
#define YYY_FILE6 ZZZ_FILE6
#define ZZZ_FILE6 FILE6
#include XXX_FILE5
#include XXX_FILE6
"""
ifdef_input = """
#define DEFINED 0
#ifdef DEFINED /* multi-line comment */
#include "file7-yes"
#else
#include "file7-no"
#endif
#ifdef NOT_DEFINED
#include <file8-no>
#else
#include <file8-yes>
#endif
"""
if_boolean_input = """
#define ZERO 0 // single-line comment
#define ONE 1
#if ZERO
#include "file9-no"
#else
#include "file9-yes"
#endif
#if ONE
#include <file10-yes>
#else
#include <file10-no>
#endif
#if ZERO
#include "file11-no-1"
#elif ZERO
#include "file11-no-2"
#else
#include "file11-yes"
#endif
#if ZERO
#include <file12-no-1>
#elif ONE
#include <file12-yes>
#else
#include <file12-no-2>
#endif
#if ONE
#include "file13-yes"
#elif ZERO
#include "file13-no-1"
#else
#include "file13-no-2"
#endif
#if ONE
#include <file14-yes>
#elif ONE
#include <file14-no-1>
#else
#include <file14-no-2>
#endif
"""
if_defined_input = """
#define DEFINED_A 0
#define DEFINED_B 0
#if defined(DEFINED_A)
#include "file15-yes"
#endif
#if ! defined(DEFINED_A)
#include <file16-no>
#else
#include <file16-yes>
#endif
#if defined DEFINED_A
#include "file17-yes"
#endif
#if ! defined DEFINED_A
#include <file18-no>
#else
#include <file18-yes>
#endif
#if ! (defined (DEFINED_A) || defined (DEFINED_B)
#include <file19-no>
#else
#include <file19-yes>
#endif
"""
expression_input = """
#define ZERO 0
#define ONE 1
#if ZERO && ZERO
#include "file19-no"
#else
#include "file19-yes"
#endif
#if ZERO && ONE
#include <file20-no>
#else
#include <file20-yes>
#endif
#if ONE && ZERO
#include "file21-no"
#else
#include "file21-yes"
#endif
#if ONE && ONE
#include <file22-yes>
#else
#include <file22-no>
#endif
#if ZERO || ZERO
#include "file23-no"
#else
#include "file23-yes"
#endif
#if ZERO || ONE
#include <file24-yes>
#else
#include <file24-no>
#endif
#if ONE || ZERO
#include "file25-yes"
#else
#include "file25-no"
#endif
#if ONE || ONE
#include <file26-yes>
#else
#include <file26-no>
#endif
#if ONE == ONE
#include "file27-yes"
#else
#include "file27-no"
#endif
#if ONE != ONE
#include <file28-no>
#else
#include <file28-yes>
#endif
#if ! (ONE == ONE)
#include "file29-no"
#else
#include "file29-yes"
#endif
#if ! (ONE != ONE)
#include <file30-yes>
#else
#include <file30-no>
#endif
#if 123456789UL || 0x13L
#include <file301-yes>
#else
#include <file301-no>
#endif
"""
undef_input = """
#define UNDEFINE 0
#ifdef UNDEFINE
#include "file31-yes"
#else
#include "file31-no"
#endif
#undef UNDEFINE
#ifdef UNDEFINE
#include <file32-no>
#else
#include <file32-yes>
#endif
"""
macro_function_input = """
#define ZERO 0
#define ONE 1
#define FUNC33(x) "file33-yes"
#define FUNC34(x) <file34-yes>
#include FUNC33(ZERO)
#include FUNC34(ZERO)
#define FILE35 "file35-yes"
#define FILE36 <file36-yes>
#define FUNC35(x, y) FILE35
#define FUNC36(x, y) FILE36
#include FUNC35(ZERO, ONE)
#include FUNC36(ZERO, ONE)
#define FILE37 "file37-yes"
#define FILE38 <file38-yes>
#define FUNC37a(x, y) FILE37
#define FUNC38a(x, y) FILE38
#define FUNC37b(x, y) FUNC37a(x, y)
#define FUNC38b(x, y) FUNC38a(x, y)
#define FUNC37c(x, y) FUNC37b(x, y)
#define FUNC38c(x, y) FUNC38b(x, y)
#include FUNC37c(ZERO, ONE)
#include FUNC38c(ZERO, ONE)
#define FILE39 "file39-yes"
#define FILE40 <file40-yes>
#define FUNC39a(x0, y0) FILE39
#define FUNC40a(x0, y0) FILE40
#define FUNC39b(x1, y2) FUNC39a(x1, y1)
#define FUNC40b(x1, y2) FUNC40a(x1, y1)
#define FUNC39c(x2, y2) FUNC39b(x2, y2)
#define FUNC40c(x2, y2) FUNC40b(x2, y2)
#include FUNC39c(ZERO, ONE)
#include FUNC40c(ZERO, ONE)
/* Make sure we don't die if the expansion isn't a string. */
#define FUNC_INTEGER(x) 1
/* Make sure one-character names are recognized. */
#define _(x) translate(x)
#undef _
"""
token_pasting_input = """
#define PASTE_QUOTE(q, name) q##name##-yes##q
#define PASTE_ANGLE(name) <##name##-yes>
#define FUNC41 PASTE_QUOTE(", file41)
#define FUNC42 PASTE_ANGLE(file42)
#include FUNC41
#include FUNC42
"""
no_space_input = """
#include<file43-yes>
#include"file44-yes"
"""
nested_ifs_input = """
#define DEFINED
#ifdef NOT_DEFINED
#include "file7-no"
#ifdef DEFINED
#include "file8-no"
#else
#include "file9-no"
#endif
#else
#include "file7-yes"
#endif
"""
ifndef_input = """
#define DEFINED 0
#ifndef DEFINED
#include "file45-no"
#else
#include "file45-yes"
#endif
#ifndef NOT_DEFINED
#include <file46-yes>
#else
#include <file46-no>
#endif
"""
if_defined_no_space_input = """
#define DEFINED 0
#if(defined DEFINED)
#include "file47-yes"
#endif
#if(!defined DEFINED)
#include <file48-no>
#elif(!defined DEFINED)
#include <file49-no>
#else
#include <file50-yes>
#endif
#if!(defined DEFINED)
#include "file51-no"
#elif!(defined DEFINED)
#include <file52-no>
#else
#include "file53-yes"
#endif
"""
if_no_space_input = """
#define DEFINED 0
#if(DEFINED)
#include "file54-no"
#endif
#if!(DEFINED)
#include <file55-yes>
#elif!(DEFINED)
#include <file56-no>
#endif
#if(DEFINED)
#include "file57-no"
#elif(!DEFINED)
#include <file58-yes>
#endif
#if!( DEFINED)
#include "file59-yes"
#elif!( DEFINED)
#include <file60-no>
#endif
#if( DEFINED)
#include "file61-no"
#elif(! DEFINED)
#include <file62-yes>
#endif
"""
# pp_class = PreProcessor
# #pp_class = DumbPreProcessor
# pp = pp_class(current = ".",
# cpppath = ['/usr/include'],
# print_all = 1)
# #pp(open(sys.argv[1]).read())
# pp(input)
class cppTestCase(unittest.TestCase):
def setUp(self):
self.cpp = self.cpp_class(current = ".",
cpppath = ['/usr/include'])
def test_basic(self):
"""Test basic #include scanning"""
expect = self.basic_expect
result = self.cpp.process_contents(basic_input)
assert expect == result, (expect, result)
def test_substitution(self):
"""Test substitution of #include files using CPP variables"""
expect = self.substitution_expect
result = self.cpp.process_contents(substitution_input)
assert expect == result, (expect, result)
def test_ifdef(self):
"""Test basic #ifdef processing"""
expect = self.ifdef_expect
result = self.cpp.process_contents(ifdef_input)
assert expect == result, (expect, result)
def test_if_boolean(self):
"""Test #if with Boolean values"""
expect = self.if_boolean_expect
result = self.cpp.process_contents(if_boolean_input)
assert expect == result, (expect, result)
def test_if_defined(self):
"""Test #if defined() idioms"""
expect = self.if_defined_expect
result = self.cpp.process_contents(if_defined_input)
assert expect == result, (expect, result)
def test_expression(self):
"""Test #if with arithmetic expressions"""
expect = self.expression_expect
result = self.cpp.process_contents(expression_input)
assert expect == result, (expect, result)
def test_undef(self):
"""Test #undef handling"""
expect = self.undef_expect
result = self.cpp.process_contents(undef_input)
assert expect == result, (expect, result)
def test_macro_function(self):
"""Test using macro functions to express file names"""
expect = self.macro_function_expect
result = self.cpp.process_contents(macro_function_input)
assert expect == result, (expect, result)
def test_token_pasting(self):
"""Test token-pasting to construct file names"""
expect = self.token_pasting_expect
result = self.cpp.process_contents(token_pasting_input)
assert expect == result, (expect, result)
def test_no_space(self):
"""Test no space between #include and the quote"""
expect = self.no_space_expect
result = self.cpp.process_contents(no_space_input)
assert expect == result, (expect, result)
def test_nested_ifs(self):
expect = self.nested_ifs_expect
result = self.cpp.process_contents(nested_ifs_input)
assert expect == result, (expect, result)
def test_ifndef(self):
"""Test basic #ifndef processing"""
expect = self.ifndef_expect
result = self.cpp.process_contents(ifndef_input)
assert expect == result, (expect, result)
def test_if_defined_no_space(self):
"""Test #if(defined, i.e.without space but parenthesis"""
expect = self.if_defined_no_space_expect
result = self.cpp.process_contents(if_defined_no_space_input)
assert expect == result, (expect, result)
def test_if_no_space(self):
"""Test #if(, i.e. without space but parenthesis"""
expect = self.if_no_space_expect
result = self.cpp.process_contents(if_no_space_input)
assert expect == result, (expect, result)
class cppAllTestCase(cppTestCase):
def setUp(self):
self.cpp = self.cpp_class(current = ".",
cpppath = ['/usr/include'],
all=1)
class PreProcessorTestCase(cppAllTestCase):
cpp_class = cpp.PreProcessor
basic_expect = [
('include', '"', 'file1-yes'),
('include', '<', 'file2-yes'),
]
substitution_expect = [
('include', '"', 'file3-yes'),
('include', '<', 'file4-yes'),
('include', '"', 'file5-yes'),
('include', '<', 'file6-yes'),
]
ifdef_expect = [
('include', '"', 'file7-yes'),
('include', '<', 'file8-yes'),
]
if_boolean_expect = [
('include', '"', 'file9-yes'),
('include', '<', 'file10-yes'),
('include', '"', 'file11-yes'),
('include', '<', 'file12-yes'),
('include', '"', 'file13-yes'),
('include', '<', 'file14-yes'),
]
if_defined_expect = [
('include', '"', 'file15-yes'),
('include', '<', 'file16-yes'),
('include', '"', 'file17-yes'),
('include', '<', 'file18-yes'),
('include', '<', 'file19-yes'),
]
expression_expect = [
('include', '"', 'file19-yes'),
('include', '<', 'file20-yes'),
('include', '"', 'file21-yes'),
('include', '<', 'file22-yes'),
('include', '"', 'file23-yes'),
('include', '<', 'file24-yes'),
('include', '"', 'file25-yes'),
('include', '<', 'file26-yes'),
('include', '"', 'file27-yes'),
('include', '<', 'file28-yes'),
('include', '"', 'file29-yes'),
('include', '<', 'file30-yes'),
('include', '<', 'file301-yes'),
]
undef_expect = [
('include', '"', 'file31-yes'),
('include', '<', 'file32-yes'),
]
macro_function_expect = [
('include', '"', 'file33-yes'),
('include', '<', 'file34-yes'),
('include', '"', 'file35-yes'),
('include', '<', 'file36-yes'),
('include', '"', 'file37-yes'),
('include', '<', 'file38-yes'),
('include', '"', 'file39-yes'),
('include', '<', 'file40-yes'),
]
token_pasting_expect = [
('include', '"', 'file41-yes'),
('include', '<', 'file42-yes'),
]
no_space_expect = [
('include', '<', 'file43-yes'),
('include', '"', 'file44-yes'),
]
nested_ifs_expect = [
('include', '"', 'file7-yes'),
]
ifndef_expect = [
('include', '"', 'file45-yes'),
('include', '<', 'file46-yes'),
]
if_defined_no_space_expect = [
('include', '"', 'file47-yes'),
('include', '<', 'file50-yes'),
('include', '"', 'file53-yes'),
]
if_no_space_expect = [
('include', '<', 'file55-yes'),
('include', '<', 'file58-yes'),
('include', '"', 'file59-yes'),
('include', '<', 'file62-yes'),
]
class DumbPreProcessorTestCase(cppAllTestCase):
cpp_class = cpp.DumbPreProcessor
basic_expect = [
('include', '"', 'file1-yes'),
('include', '<', 'file2-yes'),
]
substitution_expect = [
('include', '"', 'file3-yes'),
('include', '<', 'file4-yes'),
('include', '"', 'file5-yes'),
('include', '<', 'file6-yes'),
]
ifdef_expect = [
('include', '"', 'file7-yes'),
('include', '"', 'file7-no'),
('include', '<', 'file8-no'),
('include', '<', 'file8-yes'),
]
if_boolean_expect = [
('include', '"', 'file9-no'),
('include', '"', 'file9-yes'),
('include', '<', 'file10-yes'),
('include', '<', 'file10-no'),
('include', '"', 'file11-no-1'),
('include', '"', 'file11-no-2'),
('include', '"', 'file11-yes'),
('include', '<', 'file12-no-1'),
('include', '<', 'file12-yes'),
('include', '<', 'file12-no-2'),
('include', '"', 'file13-yes'),
('include', '"', 'file13-no-1'),
('include', '"', 'file13-no-2'),
('include', '<', 'file14-yes'),
('include', '<', 'file14-no-1'),
('include', '<', 'file14-no-2'),
]
if_defined_expect = [
('include', '"', 'file15-yes'),
('include', '<', 'file16-no'),
('include', '<', 'file16-yes'),
('include', '"', 'file17-yes'),
('include', '<', 'file18-no'),
('include', '<', 'file18-yes'),
('include', '<', 'file19-no'),
('include', '<', 'file19-yes'),
]
expression_expect = [
('include', '"', 'file19-no'),
('include', '"', 'file19-yes'),
('include', '<', 'file20-no'),
('include', '<', 'file20-yes'),
('include', '"', 'file21-no'),
('include', '"', 'file21-yes'),
('include', '<', 'file22-yes'),
('include', '<', 'file22-no'),
('include', '"', 'file23-no'),
('include', '"', 'file23-yes'),
('include', '<', 'file24-yes'),
('include', '<', 'file24-no'),
('include', '"', 'file25-yes'),
('include', '"', 'file25-no'),
('include', '<', 'file26-yes'),
('include', '<', 'file26-no'),
('include', '"', 'file27-yes'),
('include', '"', 'file27-no'),
('include', '<', 'file28-no'),
('include', '<', 'file28-yes'),
('include', '"', 'file29-no'),
('include', '"', 'file29-yes'),
('include', '<', 'file30-yes'),
('include', '<', 'file30-no'),
('include', '<', 'file301-yes'),
('include', '<', 'file301-no'),
]
undef_expect = [
('include', '"', 'file31-yes'),
('include', '"', 'file31-no'),
('include', '<', 'file32-no'),
('include', '<', 'file32-yes'),
]
macro_function_expect = [
('include', '"', 'file33-yes'),
('include', '<', 'file34-yes'),
('include', '"', 'file35-yes'),
('include', '<', 'file36-yes'),
('include', '"', 'file37-yes'),
('include', '<', 'file38-yes'),
('include', '"', 'file39-yes'),
('include', '<', 'file40-yes'),
]
token_pasting_expect = [
('include', '"', 'file41-yes'),
('include', '<', 'file42-yes'),
]
no_space_expect = [
('include', '<', 'file43-yes'),
('include', '"', 'file44-yes'),
]
nested_ifs_expect = [
('include', '"', 'file7-no'),
('include', '"', 'file8-no'),
('include', '"', 'file9-no'),
('include', '"', 'file7-yes')
]
ifndef_expect = [
('include', '"', 'file45-no'),
('include', '"', 'file45-yes'),
('include', '<', 'file46-yes'),
('include', '<', 'file46-no'),
]
if_defined_no_space_expect = [
('include', '"', 'file47-yes'),
('include', '<', 'file48-no'),
('include', '<', 'file49-no'),
('include', '<', 'file50-yes'),
('include', '"', 'file51-no'),
('include', '<', 'file52-no'),
('include', '"', 'file53-yes'),
]
if_no_space_expect = [
('include', '"', 'file54-no'),
('include', '<', 'file55-yes'),
('include', '<', 'file56-no'),
('include', '"', 'file57-no'),
('include', '<', 'file58-yes'),
('include', '"', 'file59-yes'),
('include', '<', 'file60-no'),
('include', '"', 'file61-no'),
('include', '<', 'file62-yes'),
]
import os
import re
import shutil
import tempfile
_Cleanup = []
def _clean():
for dir in _Cleanup:
if os.path.exists(dir):
shutil.rmtree(dir)
atexit.register(_clean)
if os.name in ('posix', 'nt'):
tmpprefix = 'cppTests.' + str(os.getpid()) + '.'
else:
tmpprefix = 'cppTests.'
class fileTestCase(unittest.TestCase):
cpp_class = cpp.DumbPreProcessor
def setUp(self):
path = tempfile.mkdtemp(prefix=tmpprefix)
_Cleanup.append(path)
self.tempdir = path
self.orig_cwd = os.getcwd()
os.chdir(path)
def tearDown(self):
os.chdir(self.orig_cwd)
shutil.rmtree(self.tempdir)
_Cleanup.remove(self.tempdir)
def strip_initial_spaces(self, s):
lines = s.split('\n')
spaces = re.match(' *', lines[0]).group(0)
def strip_spaces(l, spaces=spaces):
if l[:len(spaces)] == spaces:
l = l[len(spaces):]
return l
return '\n'.join(map(strip_spaces, lines))
def write(self, file, contents):
with open(file, 'w') as f:
f.write(self.strip_initial_spaces(contents))
def test_basic(self):
"""Test basic file inclusion"""
self.write('f1.h', """\
#include "f2.h"
""")
self.write('f2.h', """\
#include <f3.h>
""")
self.write('f3.h', """\
""")
p = cpp.DumbPreProcessor(current = os.curdir,
cpppath = [os.curdir])
result = p('f1.h')
assert result == ['f2.h', 'f3.h'], result
def test_current_file(self):
"""Test use of the .current_file attribute"""
self.write('f1.h', """\
#include <f2.h>
""")
self.write('f2.h', """\
#include "f3.h"
""")
self.write('f3.h', """\
""")
class MyPreProcessor(cpp.DumbPreProcessor):
def __init__(self, *args, **kw):
cpp.DumbPreProcessor.__init__(self, *args, **kw)
self.files = []
def __call__(self, file):
self.files.append(file)
return cpp.DumbPreProcessor.__call__(self, file)
def scons_current_file(self, t):
r = cpp.DumbPreProcessor.scons_current_file(self, t)
self.files.append(self.current_file)
return r
p = MyPreProcessor(current = os.curdir, cpppath = [os.curdir])
result = p('f1.h')
assert result == ['f2.h', 'f3.h'], result
assert p.files == ['f1.h', 'f2.h', 'f3.h', 'f2.h', 'f1.h'], p.files
if __name__ == '__main__':
suite = unittest.TestSuite()
tclasses = [ PreProcessorTestCase,
DumbPreProcessorTestCase,
fileTestCase,
]
for tclass in tclasses:
names = unittest.getTestCaseNames(tclass, 'test_')
try:
names = sorted(set(names))
except NameError:
pass
suite.addTests(list(map(tclass, names)))
TestUnit.run(suite)
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:

4
sc.py Normal file
View File

@ -0,0 +1,4 @@
from SCons.Script.Main import main
main()