mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2025-02-19 14:14:20 +01:00
Removed the tests from scons.
This commit is contained in:
parent
d93618c84e
commit
6a36452181
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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:
|
@ -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
@ -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()
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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
@ -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:
|
1213
SCSCons/UtilTests.py
1213
SCSCons/UtilTests.py
File diff suppressed because it is too large
Load Diff
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
@ -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:
|
Loading…
Reference in New Issue
Block a user