From 6a3645218109daf6efd90083049a6c545caf3ad7 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 20 Mar 2022 00:46:57 +0100 Subject: [PATCH] Removed the tests from scons. --- SCSCons/ActionTests.py | 2333 ----------- SCSCons/BuilderTests.py | 1629 -------- SCSCons/CacheDirTests.py | 369 -- SCSCons/DefaultsTests.py | 76 - SCSCons/EnvironmentTests.py | 4053 ------------------ SCSCons/EnvironmentValuesTest.py | 39 - SCSCons/ErrorsTests.py | 128 - SCSCons/ExecutorTests.py | 487 --- SCSCons/MemoizeTests.py | 169 - SCSCons/Node/AliasTests.py | 117 - SCSCons/Node/FSTests.py | 4056 ------------------- SCSCons/Node/NodeTests.py | 1382 ------- SCSCons/Node/PythonTests.py | 186 - SCSCons/PathListTests.py | 193 - SCSCons/Platform/PlatformTests.py | 330 -- SCSCons/Platform/virtualenvTests.py | 240 -- SCSCons/SConfTests.py | 783 ---- SCSCons/SConsignTests.py | 390 -- SCSCons/Scanner/CTests.py | 534 --- SCSCons/Scanner/DTests.py | 272 -- SCSCons/Scanner/DirTests.py | 130 - SCSCons/Scanner/FortranTests.py | 538 --- SCSCons/Scanner/IDLTests.py | 451 --- SCSCons/Scanner/LaTeXTests.py | 177 - SCSCons/Scanner/ProgTests.py | 264 -- SCSCons/Scanner/PythonTests.py | 331 -- SCSCons/Scanner/RCTests.py | 165 - SCSCons/Scanner/ScannerTests.py | 635 --- SCSCons/Script/Main.py | 1 - SCSCons/SubstTests.py | 1298 ------ SCSCons/TaskmasterTests.py | 1257 ------ SCSCons/Tool/linkCommon/linkCommmonTests.py | 75 - SCSCons/UtilTests.py | 1213 ------ SCSCons/Variables/BoolVariableTests.py | 122 - SCSCons/Variables/EnumVariableTests.py | 199 - SCSCons/Variables/ListVariableTests.py | 129 - SCSCons/Variables/PackageVariableTests.py | 119 - SCSCons/Variables/PathVariableTests.py | 240 -- SCSCons/Variables/VariablesTests.py | 695 ---- SCSCons/WarningsTests.py | 131 - SCSCons/cppTests.py | 891 ---- sc.py | 4 + 42 files changed, 4 insertions(+), 26827 deletions(-) delete mode 100644 SCSCons/ActionTests.py delete mode 100644 SCSCons/BuilderTests.py delete mode 100644 SCSCons/CacheDirTests.py delete mode 100644 SCSCons/DefaultsTests.py delete mode 100644 SCSCons/EnvironmentTests.py delete mode 100644 SCSCons/EnvironmentValuesTest.py delete mode 100644 SCSCons/ErrorsTests.py delete mode 100644 SCSCons/ExecutorTests.py delete mode 100644 SCSCons/MemoizeTests.py delete mode 100644 SCSCons/Node/AliasTests.py delete mode 100644 SCSCons/Node/FSTests.py delete mode 100644 SCSCons/Node/NodeTests.py delete mode 100644 SCSCons/Node/PythonTests.py delete mode 100644 SCSCons/PathListTests.py delete mode 100644 SCSCons/Platform/PlatformTests.py delete mode 100644 SCSCons/Platform/virtualenvTests.py delete mode 100644 SCSCons/SConfTests.py delete mode 100644 SCSCons/SConsignTests.py delete mode 100644 SCSCons/Scanner/CTests.py delete mode 100644 SCSCons/Scanner/DTests.py delete mode 100644 SCSCons/Scanner/DirTests.py delete mode 100644 SCSCons/Scanner/FortranTests.py delete mode 100644 SCSCons/Scanner/IDLTests.py delete mode 100644 SCSCons/Scanner/LaTeXTests.py delete mode 100644 SCSCons/Scanner/ProgTests.py delete mode 100644 SCSCons/Scanner/PythonTests.py delete mode 100644 SCSCons/Scanner/RCTests.py delete mode 100644 SCSCons/Scanner/ScannerTests.py delete mode 100644 SCSCons/SubstTests.py delete mode 100644 SCSCons/TaskmasterTests.py delete mode 100644 SCSCons/Tool/linkCommon/linkCommmonTests.py delete mode 100644 SCSCons/UtilTests.py delete mode 100644 SCSCons/Variables/BoolVariableTests.py delete mode 100644 SCSCons/Variables/EnumVariableTests.py delete mode 100644 SCSCons/Variables/ListVariableTests.py delete mode 100644 SCSCons/Variables/PackageVariableTests.py delete mode 100644 SCSCons/Variables/PathVariableTests.py delete mode 100644 SCSCons/Variables/VariablesTests.py delete mode 100644 SCSCons/WarningsTests.py delete mode 100644 SCSCons/cppTests.py create mode 100644 sc.py diff --git a/SCSCons/ActionTests.py b/SCSCons/ActionTests.py deleted file mode 100644 index 29ed4a789..000000000 --- a/SCSCons/ActionTests.py +++ /dev/null @@ -1,2333 +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. -# - -# Define a null function and a null class for use as builder actions. -# Where these are defined in the file seems to affect their byte-code -# contents, so try to minimize changes by defining them here, before we -# even import anything. - -def GlobalFunc(): - pass - - -class GlobalActFunc: - def __call__(self): - pass - - -import io -import os -import sys -import types -import unittest -import subprocess - -import SCons.Action -import SCons.Environment -import SCons.Errors - -import TestCmd - -# Initial setup of the common environment for all tests, -# a temporary working directory containing a -# script for writing arguments to an output file. -# -# We don't do this as a setUp() method because it's -# unnecessary to create a separate directory and script -# for each test, they can just use the one. -test = TestCmd.TestCmd(workdir='') - -test.write('act.py', """\ -import os, string, sys - -with open(sys.argv[1], 'w') as f: - f.write("act.py: '" + "' '".join(sys.argv[2:]) + "'\\n") - try: - if sys.argv[3]: - f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n") - except: - pass - -if 'ACTPY_PIPE' in os.environ: - if 'PIPE_STDOUT_FILE' in os.environ: - with open(os.environ['PIPE_STDOUT_FILE'], 'r') as f: - stdout_msg = f.read() - else: - stdout_msg = "act.py: stdout: executed act.py %s\\n" % ' '.join(sys.argv[1:]) - sys.stdout.write( stdout_msg ) - if 'PIPE_STDERR_FILE' in os.environ: - with open(os.environ['PIPE_STDERR_FILE'], 'r') as f: - stderr_msg = f.read() - else: - stderr_msg = "act.py: stderr: executed act.py %s\\n" % ' '.join(sys.argv[1:]) - sys.stderr.write(stderr_msg) -sys.exit(0) -""") - -test.write('exit.py', """\ -import sys -sys.exit(int(sys.argv[1])) -""") - -act_py = test.workpath('act.py') -exit_py = test.workpath('exit.py') - -outfile = test.workpath('outfile') -outfile2 = test.workpath('outfile2') -pipe_file = test.workpath('pipe.out') - -scons_env = SCons.Environment.Environment() - -# Capture all the stuff the Actions will print, -# so it doesn't clutter the output. -sys.stdout = io.StringIO() - - -class CmdStringHolder: - def __init__(self, cmd, literal=None): - self.data = str(cmd) - self.literal = literal - - def is_literal(self): - return self.literal - - def escape(self, escape_func): - """Escape the string with the supplied function. The - function is expected to take an arbitrary string, then - return it with all special characters escaped and ready - for passing to the command interpreter. - - After calling this function, the next call to str() will - return the escaped string. - """ - - if self.is_literal(): - return escape_func(self.data) - elif ' ' in self.data or '\t' in self.data: - return '"%s"' % self.data - else: - return self.data - - -class Environment: - def __init__(self, **kw): - self.d = {} - self.d['SHELL'] = scons_env['SHELL'] - self.d['SPAWN'] = scons_env['SPAWN'] - self.d['PSPAWN'] = scons_env['PSPAWN'] - self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in kw.items(): - self.d[k] = v - - # Just use the underlying scons_subst*() utility methods. - def subst(self, strSubst, raw=0, target=[], source=[], conv=None): - return SCons.Subst.scons_subst(strSubst, self, raw, - target, source, self.d, conv=conv) - - subst_target_source = subst - - def subst_list(self, strSubst, raw=0, target=[], source=[], conv=None): - return SCons.Subst.scons_subst_list(strSubst, self, raw, - target, source, self.d, conv=conv) - - def __getitem__(self, item): - return self.d[item] - - def __setitem__(self, item, value): - self.d[item] = value - - def __contains__(self, key): - return key in self.d - - def get(self, key, value=None): - return self.d.get(key, value) - - def items(self): - return list(self.d.items()) - - def Dictionary(self): - return self.d - - def Clone(self, **kw): - res = Environment() - res.d = SCons.Util.semi_deepcopy(self.d) - for k, v in kw.items(): - res.d[k] = v - return res - - def sig_dict(self): - d = {} - for k, v in self.items(): d[k] = v - d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] - d['TARGET'] = d['TARGETS'][0] - d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] - d['SOURCE'] = d['SOURCES'][0] - return d - - -class DummyNode: - def __init__(self, name): - self.name = name - - def str_for_display(self): - return '"' + self.name + '"' - - def __str__(self): - return self.name - - def rfile(self): - return self - - def get_subst_proxy(self): - return self - - -if os.name == 'java': - python = os.path.join(sys.prefix, 'jython') -else: - python = os.environ.get('python_executable', sys.executable) -_python_ = test.escape(python) - -_null = SCons.Action._null - - -def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw): - def call_action(a, pos_call=pos_call, str_call=str_call, kw=kw): - a = SCons.Action.Action(*a, **kw) - # returned object must provide these entry points - assert hasattr(a, '__call__') - assert hasattr(a, 'get_contents') - assert hasattr(a, 'genstring') - pos_call(a) - str_call(a) - return a - - a = call_action((cmd, cmdstrfunc)) - assert a.varlist == (), a.varlist - - a = call_action((cmd, cmdstrfunc, 'foo')) - assert a.varlist == ('foo',), a.varlist - - a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c')) - assert a.varlist == ('a', 'b', 'c'), a.varlist - - a = call_action((cmd, cmdstrfunc, ['a', 'b', 'c'])) - assert a.varlist == ('a', 'b', 'c'), a.varlist - - kw['varlist'] = 'foo' - a = call_action((cmd, cmdstrfunc)) - assert a.varlist == ('foo',), a.varlist - - kw['varlist'] = ['x', 'y', 'z'] - a = call_action((cmd, cmdstrfunc)) - assert a.varlist == ('x', 'y', 'z'), a.varlist - - a = call_action((cmd, cmdstrfunc, 'foo')) - assert a.varlist == ('foo', 'x', 'y', 'z'), a.varlist - - a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c')) - assert a.varlist == ('a', 'b', 'c', 'x', 'y', 'z'), a.varlist - - -def test_positional_args(pos_callback, cmd, **kw): - """Test that Action() returns the expected type and that positional args work. - """ - act = SCons.Action.Action(cmd, **kw) - pos_callback(act) - assert act.varlist == (), act.varlist - - if not isinstance(act, SCons.Action._ActionAction): - # only valid cmdstrfunc is None - def none(a): - pass - - test_varlist(pos_callback, none, cmd, None, **kw) - else: - # _ActionAction should have set these - assert hasattr(act, 'strfunction') - assert act.cmdstr is _null, act.cmdstr - assert act.presub is _null, act.presub - assert act.chdir is None, act.chdir - assert act.exitstatfunc is SCons.Action.default_exitstatfunc, \ - act.exitstatfunc - - def cmdstr(a): - assert hasattr(a, 'strfunction') - assert a.cmdstr == 'cmdstr', a.cmdstr - - test_varlist(pos_callback, cmdstr, cmd, 'cmdstr', **kw) - - def fun(): - pass - - def strfun(a, fun=fun): - assert a.strfunction is fun, a.strfunction - assert a.cmdstr == _null, a.cmdstr - - test_varlist(pos_callback, strfun, cmd, fun, **kw) - - def none(a): - assert hasattr(a, 'strfunction') - assert a.cmdstr is None, a.cmdstr - - test_varlist(pos_callback, none, cmd, None, **kw) - - """Test handling of bad cmdstrfunc arguments """ - try: - a = SCons.Action.Action(cmd, [], **kw) - except SCons.Errors.UserError as e: - s = str(e) - m = 'Invalid command display variable' - assert s.find(m) != -1, 'Unexpected string: %s' % s - else: - raise Exception("did not catch expected UserError") - - return act - - -class ActionTestCase(unittest.TestCase): - """Test the Action() factory function""" - - def test_FunctionAction(self): - """Test the Action() factory's creation of FunctionAction objects - """ - - def foo(): - pass - - def func_action(a, foo=foo): - assert isinstance(a, SCons.Action.FunctionAction), a - assert a.execfunction == foo, a.execfunction - - test_positional_args(func_action, foo) - # a singleton list returns the contained action - test_positional_args(func_action, [foo]) - - def test_CommandAction(self): - """Test the Action() factory's creation of CommandAction objects - """ - - def cmd_action(a): - assert isinstance(a, SCons.Action.CommandAction), a - assert a.cmd_list == "string", a.cmd_list - - test_positional_args(cmd_action, "string") - # a singleton list returns the contained action - test_positional_args(cmd_action, ["string"]) - - def line_action(a): - assert isinstance(a, SCons.Action.CommandAction), a - assert a.cmd_list == ["explicit", "command", "line"], a.cmd_list - - test_positional_args(line_action, [["explicit", "command", "line"]]) - - def test_ListAction(self): - """Test the Action() factory's creation of ListAction objects - """ - a1 = SCons.Action.Action(["x", "y", "z", ["a", "b", "c"]]) - assert isinstance(a1, SCons.Action.ListAction), a1 - assert a1.varlist == (), a1.varlist - assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0] - assert a1.list[0].cmd_list == "x", a1.list[0].cmd_list - assert isinstance(a1.list[1], SCons.Action.CommandAction), a1.list[1] - assert a1.list[1].cmd_list == "y", a1.list[1].cmd_list - assert isinstance(a1.list[2], SCons.Action.CommandAction), a1.list[2] - assert a1.list[2].cmd_list == "z", a1.list[2].cmd_list - assert isinstance(a1.list[3], SCons.Action.CommandAction), a1.list[3] - assert a1.list[3].cmd_list == ["a", "b", "c"], a1.list[3].cmd_list - - a2 = SCons.Action.Action("x\ny\nz") - assert isinstance(a2, SCons.Action.ListAction), a2 - assert a2.varlist == (), a2.varlist - assert isinstance(a2.list[0], SCons.Action.CommandAction), a2.list[0] - assert a2.list[0].cmd_list == "x", a2.list[0].cmd_list - assert isinstance(a2.list[1], SCons.Action.CommandAction), a2.list[1] - assert a2.list[1].cmd_list == "y", a2.list[1].cmd_list - assert isinstance(a2.list[2], SCons.Action.CommandAction), a2.list[2] - assert a2.list[2].cmd_list == "z", a2.list[2].cmd_list - - def foo(): - pass - - a3 = SCons.Action.Action(["x", foo, "z"]) - assert isinstance(a3, SCons.Action.ListAction), a3 - assert a3.varlist == (), a3.varlist - assert isinstance(a3.list[0], SCons.Action.CommandAction), a3.list[0] - assert a3.list[0].cmd_list == "x", a3.list[0].cmd_list - assert isinstance(a3.list[1], SCons.Action.FunctionAction), a3.list[1] - assert a3.list[1].execfunction == foo, a3.list[1].execfunction - assert isinstance(a3.list[2], SCons.Action.CommandAction), a3.list[2] - assert a3.list[2].cmd_list == "z", a3.list[2].cmd_list - - a4 = SCons.Action.Action(["x", "y"], strfunction=foo) - assert isinstance(a4, SCons.Action.ListAction), a4 - assert a4.varlist == (), a4.varlist - assert isinstance(a4.list[0], SCons.Action.CommandAction), a4.list[0] - assert a4.list[0].cmd_list == "x", a4.list[0].cmd_list - assert a4.list[0].strfunction == foo, a4.list[0].strfunction - assert isinstance(a4.list[1], SCons.Action.CommandAction), a4.list[1] - assert a4.list[1].cmd_list == "y", a4.list[1].cmd_list - assert a4.list[1].strfunction == foo, a4.list[1].strfunction - - a5 = SCons.Action.Action("x\ny", strfunction=foo) - assert isinstance(a5, SCons.Action.ListAction), a5 - assert a5.varlist == (), a5.varlist - assert isinstance(a5.list[0], SCons.Action.CommandAction), a5.list[0] - assert a5.list[0].cmd_list == "x", a5.list[0].cmd_list - assert a5.list[0].strfunction == foo, a5.list[0].strfunction - assert isinstance(a5.list[1], SCons.Action.CommandAction), a5.list[1] - assert a5.list[1].cmd_list == "y", a5.list[1].cmd_list - assert a5.list[1].strfunction == foo, a5.list[1].strfunction - - def test_CommandGeneratorAction(self): - """Test the Action() factory's creation of CommandGeneratorAction objects - """ - - def foo(): pass - - def gen_action(a, foo=foo): - assert isinstance(a, SCons.Action.CommandGeneratorAction), a - assert a.generator is foo, a.generator - - test_positional_args(gen_action, foo, generator=1) - - def test_LazyCmdGeneratorAction(self): - """Test the Action() factory's creation of lazy CommandGeneratorAction objects - """ - - def lazy_action(a): - assert isinstance(a, SCons.Action.LazyAction), a - assert a.var == "FOO", a.var - assert a.cmd_list == "${FOO}", a.cmd_list - - test_positional_args(lazy_action, "$FOO") - test_positional_args(lazy_action, "${FOO}") - - def test_no_action(self): - """Test when the Action() factory can't create an action object - """ - try: - a5 = SCons.Action.Action(1) - except TypeError: - pass - else: - assert 0, "Should have thrown a TypeError creating Action from an int." - - def test_reentrance(self): - """Test the Action() factory when the action is already an Action object - """ - a1 = SCons.Action.Action("foo") - a2 = SCons.Action.Action(a1) - assert a2 is a1, a2 - - -class _ActionActionTestCase(unittest.TestCase): - - def test__init__(self): - """Test creation of _ActionAction objects - """ - - def func1(): - pass - - def func2(): - pass - - def func3(): - pass - - a = SCons.Action._ActionAction() - assert not hasattr(a, 'strfunction') - assert a.cmdstr is _null, a.cmdstr - assert a.varlist == (), a.varlist - assert a.presub is _null, a.presub - assert a.chdir is None, a.chdir - assert a.exitstatfunc is SCons.Action.default_exitstatfunc, a.exitstatfunc - - assert SCons.Action._ActionAction(kwarg=1) - assert not hasattr(a, 'kwarg') - assert not hasattr(a, 'strfunction') - assert a.cmdstr is _null, a.cmdstr - assert a.varlist == (), a.varlist - assert a.presub is _null, a.presub - assert a.chdir is None, a.chdir - assert a.exitstatfunc is SCons.Action.default_exitstatfunc, a.exitstatfunc - - a = SCons.Action._ActionAction(strfunction=func1) - assert a.strfunction is func1, a.strfunction - - a = SCons.Action._ActionAction(strfunction=None) - assert not hasattr(a, 'strfunction') - assert a.cmdstr is None, a.cmdstr - - a = SCons.Action._ActionAction(cmdstr='cmdstr') - assert not hasattr(a, 'strfunction') - assert a.cmdstr == 'cmdstr', a.cmdstr - - a = SCons.Action._ActionAction(cmdstr=None) - assert not hasattr(a, 'strfunction') - assert a.cmdstr is None, a.cmdstr - - t = ('a', 'b', 'c') - a = SCons.Action._ActionAction(varlist=t) - assert a.varlist == t, a.varlist - - a = SCons.Action._ActionAction(presub=func1) - assert a.presub is func1, a.presub - - a = SCons.Action._ActionAction(chdir=1) - assert a.chdir == 1, a.chdir - - a = SCons.Action._ActionAction(exitstatfunc=func1) - assert a.exitstatfunc is func1, a.exitstatfunc - - a = SCons.Action._ActionAction( - # alphabetical order ... - chdir='x', - cmdstr='cmdstr', - exitstatfunc=func3, - presub=func2, - strfunction=func1, - varlist=t, - ) - assert a.chdir == 'x', a.chdir - assert a.cmdstr == 'cmdstr', a.cmdstr - assert a.exitstatfunc is func3, a.exitstatfunc - assert a.presub is func2, a.presub - assert a.strfunction is func1, a.strfunction - assert a.varlist is t, a.varlist - - def test_dup_keywords(self): - """Test handling of both cmdstr and strfunction arguments - """ - - def func(): - pass - - try: - a = SCons.Action.Action('foo', cmdstr='string', strfunction=func) - except SCons.Errors.UserError as e: - s = str(e) - m = 'Cannot have both strfunction and cmdstr args to Action()' - assert s.find(m) != -1, 'Unexpected string: %s' % s - else: - raise Exception("did not catch expected UserError") - - def test___cmp__(self): - """Test Action comparison - """ - a1 = SCons.Action.Action("x") - a2 = SCons.Action.Action("x") - assert a1 == a2 - a3 = SCons.Action.Action("y") - assert a1 != a3 - assert a2 != a3 - - def test_print_cmd_lines(self): - """Test the print_cmd_lines() method - """ - save_stdout = sys.stdout - - try: - def execfunc(target, source, env): - pass - - a = SCons.Action.Action(execfunc) - - sio = io.StringIO() - sys.stdout = sio - a.print_cmd_line("foo bar", None, None, None) - s = sio.getvalue() - assert s == "foo bar\n", s - - finally: - sys.stdout = save_stdout - - def test___call__(self): - """Test calling an Action - """ - save_stdout = sys.stdout - - save_print_actions = SCons.Action.print_actions - save_print_actions_presub = SCons.Action.print_actions_presub - save_execute_actions = SCons.Action.execute_actions - # SCons.Action.print_actions = 0 - - test = TestCmd.TestCmd(workdir='') - test.subdir('sub', 'xyz') - os.chdir(test.workpath()) - - try: - env = Environment() - - def execfunc(target, source, env): - assert isinstance(target, list), type(target) - assert isinstance(source, list), type(source) - return 7 - - a = SCons.Action.Action(execfunc) - - def firstfunc(target, source, env): - assert isinstance(target, list), type(target) - assert isinstance(source, list), type(source) - return 0 - - def lastfunc(target, source, env): - assert isinstance(target, list), type(target) - assert isinstance(source, list), type(source) - return 9 - - b = SCons.Action.Action([firstfunc, execfunc, lastfunc]) - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env) - assert result.status == 7, result - s = sio.getvalue() - assert s == "execfunc(['out'], ['in'])\n", s - - a.chdir = 'xyz' - expect = "os.chdir(%s)\nexecfunc(['out'], ['in'])\nos.chdir(%s)\n" - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == expect % (repr('xyz'), repr(test.workpath())), s - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env, chdir='sub') - assert result.status == 7, result.status - s = sio.getvalue() - assert s == expect % (repr('sub'), repr(test.workpath())), s - - a.chdir = None - - sio = io.StringIO() - sys.stdout = sio - result = b("out", "in", env) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\n", s - - SCons.Action.execute_actions = 0 - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env) - assert result == 0, result - s = sio.getvalue() - assert s == "execfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = b("out", "in", env) - assert result == 0, result - s = sio.getvalue() - assert s == "firstfunc(['out'], ['in'])\nexecfunc(['out'], ['in'])\nlastfunc(['out'], ['in'])\n", s - - SCons.Action.print_actions_presub = 1 - SCons.Action.execute_actions = 1 - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env, presub=0) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "execfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env, presub=1) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = b(["out"], "in", env, presub=1) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "Building out with action:\n firstfunc(target, source, env)\nfirstfunc(['out'], ['in'])\nBuilding out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = b(["out", "list"], "in", env, presub=1) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "Building out and list with action:\n firstfunc(target, source, env)\nfirstfunc(['out', 'list'], ['in'])\nBuilding out and list with action:\n execfunc(target, source, env)\nexecfunc(['out', 'list'], ['in'])\n", s - - a2 = SCons.Action.Action(execfunc) - - sio = io.StringIO() - sys.stdout = sio - result = a2("out", "in", env) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "Building out with action:\n execfunc(target, source, env)\nexecfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = a2("out", "in", env, presub=0) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == "execfunc(['out'], ['in'])\n", s - - SCons.Action.execute_actions = 0 - - sio = io.StringIO() - sys.stdout = sio - result = a2("out", "in", env, presub=0) - assert result == 0, result - s = sio.getvalue() - assert s == "execfunc(['out'], ['in'])\n", s - - sio = io.StringIO() - sys.stdout = sio - result = a("out", "in", env, presub=0, execute=1, show=0) - assert result.status == 7, result.status - s = sio.getvalue() - assert s == '', s - - sys.stdout = save_stdout - exitstatfunc_result = [] - - def exitstatfunc(stat, result=exitstatfunc_result): - result.append(stat) - return stat - - result = a("out", "in", env, exitstatfunc=exitstatfunc) - assert result == 0, result - assert exitstatfunc_result == [], exitstatfunc_result - - result = a("out", "in", env, execute=1, exitstatfunc=exitstatfunc) - assert result.status == 7, result.status - assert exitstatfunc_result == [7], exitstatfunc_result - - SCons.Action.execute_actions = 1 - - result = [] - - def my_print_cmd_line(s, target, source, env, result=result): - result.append(s) - - env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line - a("output", "input", env) - assert result == ["execfunc(['output'], ['input'])"], result - - - finally: - sys.stdout = save_stdout - SCons.Action.print_actions = save_print_actions - SCons.Action.print_actions_presub = save_print_actions_presub - SCons.Action.execute_actions = save_execute_actions - - def test_presub_lines(self): - """Test the presub_lines() method - """ - env = Environment() - a = SCons.Action.Action("x") - s = a.presub_lines(env) - assert s == ['x'], s - - a = SCons.Action.Action(["y", "z"]) - s = a.presub_lines(env) - assert s == ['y', 'z'], s - - def func(): - pass - - a = SCons.Action.Action(func) - s = a.presub_lines(env) - assert s == ["func(target, source, env)"], s - - def gen(target, source, env, for_signature): - return 'generat' + env.get('GEN', 'or') - - a = SCons.Action.Action(gen, generator=1) - s = a.presub_lines(env) - assert s == ["generator"], s - s = a.presub_lines(Environment(GEN='ed')) - assert s == ["generated"], s - - a = SCons.Action.Action("$ACT") - s = a.presub_lines(env) - assert s == [''], s - s = a.presub_lines(Environment(ACT='expanded action')) - assert s == ['expanded action'], s - - def test_add(self): - """Test adding Actions to stuff.""" - - # Adding actions to other Actions or to stuff that can - # be converted into an Action should produce a ListAction - # containing all the Actions. - def bar(): - return None - - baz = SCons.Action.Action(bar, generator=1) - act1 = SCons.Action.Action('foo bar') - act2 = SCons.Action.Action(['foo', bar]) - - sum = act1 + act2 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 3, len(sum.list) - assert [isinstance(x, SCons.Action.ActionBase) for x in sum.list] == [1, 1, 1] - - sum = act1 + act1 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 2, len(sum.list) - - sum = act2 + act2 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 4, len(sum.list) - - # Should also be able to add command generators to each other - # or to actions - sum = baz + baz - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 2, len(sum.list) - - sum = baz + act1 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 2, len(sum.list) - - sum = act2 + baz - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 3, len(sum.list) - - # Also should be able to add Actions to anything that can - # be converted into an action. - sum = act1 + bar - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 2, len(sum.list) - assert isinstance(sum.list[1], SCons.Action.FunctionAction) - - sum = 'foo bar' + act2 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 3, len(sum.list) - assert isinstance(sum.list[0], SCons.Action.CommandAction) - - sum = ['foo', 'bar'] + act1 - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 3, sum.list - assert isinstance(sum.list[0], SCons.Action.CommandAction) - assert isinstance(sum.list[1], SCons.Action.CommandAction) - - sum = act2 + [baz, bar] - assert isinstance(sum, SCons.Action.ListAction), str(sum) - assert len(sum.list) == 4, len(sum.list) - assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction) - assert isinstance(sum.list[3], SCons.Action.FunctionAction) - - # OK to add None on either side (should be ignored) - sum = act1 + None - assert sum == act1 - - sum = None + act1 - assert sum == act1 - - try: - sum = act2 + 1 - except TypeError: - pass - else: - assert 0, "Should have thrown a TypeError adding to an int." - - try: - sum = 1 + act2 - except TypeError: - pass - else: - assert 0, "Should have thrown a TypeError adding to an int." - - -class CommandActionTestCase(unittest.TestCase): - - def test___init__(self): - """Test creation of a command Action - """ - a = SCons.Action.CommandAction(["xyzzy"]) - assert a.cmd_list == ["xyzzy"], a.cmd_list - assert a.cmdstr is _null, a.cmdstr - - a = SCons.Action.CommandAction(["abra"], cmdstr="cadabra") - assert a.cmd_list == ["abra"], a.cmd_list - assert a.cmdstr == "cadabra", a.cmdstr - - def test___str__(self): - """Test fetching the pre-substitution string for command Actions - """ - env = Environment() - act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE') - s = str(act) - assert s == 'xyzzy $TARGET $SOURCE', s - - act = SCons.Action.CommandAction(['xyzzy', - '$TARGET', '$SOURCE', - '$TARGETS', '$SOURCES']) - s = str(act) - assert s == "xyzzy $TARGET $SOURCE $TARGETS $SOURCES", s - - def test_genstring(self): - """Test the genstring() method for command Actions - """ - - env = Environment() - t1 = DummyNode('t1') - t2 = DummyNode('t2') - s1 = DummyNode('s1') - s2 = DummyNode('s2') - act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE') - expect = 'xyzzy $TARGET $SOURCE' - s = act.genstring([], [], env) - assert s == expect, s - s = act.genstring([t1], [s1], env) - assert s == expect, s - s = act.genstring([t1, t2], [s1, s2], env) - assert s == expect, s - - act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES') - expect = 'xyzzy $TARGETS $SOURCES' - s = act.genstring([], [], env) - assert s == expect, s - s = act.genstring([t1], [s1], env) - assert s == expect, s - s = act.genstring([t1, t2], [s1, s2], env) - assert s == expect, s - - act = SCons.Action.CommandAction(['xyzzy', - '$TARGET', '$SOURCE', - '$TARGETS', '$SOURCES']) - expect = "xyzzy $TARGET $SOURCE $TARGETS $SOURCES" - s = act.genstring([], [], env) - assert s == expect, s - s = act.genstring([t1], [s1], env) - assert s == expect, s - s = act.genstring([t1, t2], [s1, s2], env) - assert s == expect, s - - def test_strfunction(self): - """Test fetching the string representation of command Actions - """ - - env = Environment() - t1 = DummyNode('t1') - t2 = DummyNode('t2') - s1 = DummyNode('s1') - s2 = DummyNode('s2') - act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE') - s = act.strfunction([], [], env) - assert s == 'xyzzy', s - s = act.strfunction([t1], [s1], env) - assert s == 'xyzzy t1 s1', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'xyzzy t1 s1', s - - act = SCons.Action.CommandAction('xyzzy $TARGET $SOURCE', - cmdstr='cmdstr - $SOURCE - $TARGET -') - s = act.strfunction([], [], env) - assert s == 'cmdstr - - -', s - s = act.strfunction([t1], [s1], env) - assert s == 'cmdstr - s1 - t1 -', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'cmdstr - s1 - t1 -', s - - act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES') - s = act.strfunction([], [], env) - assert s == 'xyzzy', s - s = act.strfunction([t1], [s1], env) - assert s == 'xyzzy t1 s1', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'xyzzy t1 t2 s1 s2', s - - act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES', - cmdstr='cmdstr = $SOURCES = $TARGETS =') - s = act.strfunction([], [], env) - assert s == 'cmdstr = = =', s - s = act.strfunction([t1], [s1], env) - assert s == 'cmdstr = s1 = t1 =', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'cmdstr = s1 s2 = t1 t2 =', s - - act = SCons.Action.CommandAction(['xyzzy', - '$TARGET', '$SOURCE', - '$TARGETS', '$SOURCES']) - s = act.strfunction([], [], env) - assert s == 'xyzzy', s - s = act.strfunction([t1], [s1], env) - assert s == 'xyzzy t1 s1 t1 s1', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'xyzzy t1 s1 t1 t2 s1 s2', s - - act = SCons.Action.CommandAction('xyzzy $TARGETS $SOURCES', - cmdstr='cmdstr\t$TARGETS\n$SOURCES ') - - s = act.strfunction([], [], env) - assert s == 'cmdstr\t\n ', s - s = act.strfunction([t1], [s1], env) - assert s == 'cmdstr\tt1\ns1 ', s - s = act.strfunction([t1, t2], [s1, s2], env) - assert s == 'cmdstr\tt1 t2\ns1 s2 ', s - - def sf(target, source, env): - return "sf was called" - - act = SCons.Action.CommandAction('foo', strfunction=sf) - s = act.strfunction([], [], env) - assert s == "sf was called", s - - class actclass1: - def __init__(self, targets, sources, env): - pass - - def __call__(self): - return 1 - - class actclass2: - def __init__(self, targets, sources, env): - self.strfunction = 5 - - def __call__(self): - return 2 - - class actclass3: - def __init__(self, targets, sources, env): - pass - - def __call__(self): - return 3 - - def strfunction(self, targets, sources, env): - return 'actclass3 on %s to get %s' % (str(sources[0]), - str(targets[0])) - - class actclass4: - def __init__(self, targets, sources, env): - pass - - def __call__(self): - return 4 - - strfunction = None - - act1 = SCons.Action.Action(actclass1([t1], [s1], env)) - s = act1.strfunction([t1], [s1], env) - assert s == 'actclass1(["t1"], ["s1"])', s - - act2 = SCons.Action.Action(actclass2([t1], [s1], env)) - s = act2.strfunction([t1], [s1], env) - assert s == 'actclass2(["t1"], ["s1"])', s - - act3 = SCons.Action.Action(actclass3([t1], [s1], env)) - s = act3.strfunction([t1], [s1], env) - assert s == 'actclass3 on s1 to get t1', s - - act4 = SCons.Action.Action(actclass4([t1], [s1], env)) - s = act4.strfunction([t1], [s1], env) - assert s is None, s - - act = SCons.Action.CommandAction("@foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("@-foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("-@foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("-foo bar") - s = act.strfunction([], [], env) - assert s == "foo bar", s - - act = SCons.Action.CommandAction("@ foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("@- foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("-@ foo bar") - s = act.strfunction([], [], env) - assert s == "", s - - act = SCons.Action.CommandAction("- foo bar") - s = act.strfunction([], [], env) - assert s == "foo bar", s - - def test_execute(self): - """Test execution of command Actions - - """ - try: - env = self.env - except AttributeError: - env = Environment() - - cmd1 = r'%s %s %s xyzzy' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd1) - r = act([], [], env.Clone()) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'xyzzy'\n", c - - cmd2 = r'%s %s %s $TARGET' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd2) - r = act(DummyNode('foo'), [], env.Clone()) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'foo'\n", c - - cmd3 = r'%s %s %s ${TARGETS}' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd3) - r = act(list(map(DummyNode, ['aaa', 'bbb'])), [], env.Clone()) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'aaa' 'bbb'\n", c - - cmd4 = r'%s %s %s $SOURCES' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd4) - r = act([], [DummyNode('one'), DummyNode('two')], env.Clone()) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'one' 'two'\n", c - - cmd4 = r'%s %s %s ${SOURCES[:2]}' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd4) - sources = [DummyNode('three'), DummyNode('four'), DummyNode('five')] - env2 = env.Clone() - r = act([], source=sources, env=env2) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'three' 'four'\n", c - - cmd5 = r'%s %s %s $TARGET XYZZY' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd5) - env5 = Environment() - if 'ENV' in scons_env: - env5['ENV'] = scons_env['ENV'] - PATH = scons_env['ENV'].get('PATH', '') - else: - env5['ENV'] = {} - PATH = '' - - env5['ENV']['XYZZY'] = 'xyzzy' - r = act(target=DummyNode('out5'), source=[], env=env5) - - act = SCons.Action.CommandAction(cmd5) - r = act(target=DummyNode('out5'), - source=[], - env=env.Clone(ENV={'XYZZY': 'xyzzy5', - 'PATH': PATH})) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy5'\n", c - - class Obj: - def __init__(self, str): - self._str = str - - def __str__(self): - return self._str - - def rfile(self): - return self - - def get_subst_proxy(self): - return self - - cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (_python_, act_py, outfile) - - act = SCons.Action.CommandAction(cmd6) - r = act(target=[Obj('111'), Obj('222')], - source=[Obj('333'), Obj('444'), Obj('555')], - env=env.Clone()) - assert r == 0 - c = test.read(outfile, 'r') - assert c == "act.py: '222' '111' '333' '444'\n", c - - if os.name == 'nt': - # NT treats execs of directories and non-executable files - # as "file not found" errors - expect_nonexistent = 1 - expect_nonexecutable_file = 1 - expect_nonexecutable_dir = 1 - elif sys.platform == 'cygwin': - expect_nonexistent = 127 - # Newer cygwin seems to return 126 for following - expect_nonexecutable_file = 126 - expect_nonexecutable_dir = 127 - else: - expect_nonexistent = 127 - expect_nonexecutable_file = 126 - expect_nonexecutable_dir = 126 - - # Test that a nonexistent command returns 127 - act = SCons.Action.CommandAction(python + "_no_such_command_") - r = act([], [], env.Clone(out=outfile)) - assert r.status == expect_nonexistent, r.status - - # Test that trying to execute a directory returns 126 - dir, tail = os.path.split(python) - act = SCons.Action.CommandAction(dir) - r = act([], [], env.Clone(out=outfile)) - assert r.status == expect_nonexecutable_file, r.status - - # Test that trying to execute a non-executable file returns 126 - act = SCons.Action.CommandAction(outfile) - r = act([], [], env.Clone(out=outfile)) - assert r.status == expect_nonexecutable_dir, r.status - - act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r.status == 1, r.status - - act = SCons.Action.CommandAction('@%s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r.status == 1, r.status - - act = SCons.Action.CommandAction('@-%s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r == 0, r - - act = SCons.Action.CommandAction('-%s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r == 0, r - - act = SCons.Action.CommandAction('@ %s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r.status == 1, r.status - - act = SCons.Action.CommandAction('@- %s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r == 0, r - - act = SCons.Action.CommandAction('- %s %s 1' % (_python_, exit_py)) - r = act([], [], env) - assert r == 0, r - - def test_set_handler(self): - """Test setting the command handler... - """ - - class Test: - def __init__(self): - self.executed = 0 - - t = Test() - - def func(sh, escape, cmd, args, env, test=t): - test.executed = args - test.shell = sh - return 0 - - def escape_func(cmd): - return '**' + cmd + '**' - - class LiteralStr: - def __init__(self, x): - self.data = x - - def __str__(self): - return self.data - - def escape(self, escape_func): - return escape_func(self.data) - - def is_literal(self): - return 1 - - a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN=func) - a([], [], e) - assert t.executed == ['xyzzy'], t.executed - - a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN='$FUNC', FUNC=func) - a([], [], e) - assert t.executed == ['xyzzy'], t.executed - - a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN=func, SHELL='fake shell') - a([], [], e) - assert t.executed == ['xyzzy'], t.executed - assert t.shell == 'fake shell', t.shell - - a = SCons.Action.CommandAction([LiteralStr("xyzzy")]) - e = Environment(SPAWN=func, ESCAPE=escape_func) - a([], [], e) - assert t.executed == ['**xyzzy**'], t.executed - - def test_get_contents(self): - """Test fetching the contents of a command Action - """ - - def CmdGen(target, source, env, for_signature): - assert for_signature - return "%s %s" % \ - (env["foo"], env["bar"]) - - # The number 1 is there to make sure all args get converted to strings. - a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$(", "$bar", - "$)", "stuff", "$)", "|", "$baz", 1]) - c = a.get_contents(target=[], source=[], - env=Environment(foo='FFF', bar='BBB', - baz=CmdGen)) - assert c == b"| | FFF BBB 1", c - - # Make sure that CommandActions use an Environment's - # subst_target_source() method for substitution. - class SpecialEnvironment(Environment): - def subst_target_source(self, strSubst, raw=0, target=[], source=[]): - return 'subst_target_source: ' + strSubst - - c = a.get_contents(target=DummyNode('ttt'), source=DummyNode('sss'), - env=SpecialEnvironment(foo='GGG', bar='CCC', - baz='ZZZ')) - assert c == b'subst_target_source: | $( $foo | $( $bar $) stuff $) | $baz 1', c - - # We've discussed using the real target and source names in a - # CommandAction's signature contents. This would have have the - # advantage of recompiling when a file's name changes (keeping - # debug info current), but it would currently break repository - # logic that will change the file name based on whether the - # files come from a repository or locally. If we ever move to - # that scheme, then all of the '__t1__' and '__s6__' file names - # in the asserts below would change to 't1' and 's6' and the - # like. - t = list(map(DummyNode, ['t1', 't2', 't3', 't4', 't5', 't6'])) - s = list(map(DummyNode, ['s1', 's2', 's3', 's4', 's5', 's6'])) - env = Environment() - - a = SCons.Action.CommandAction(["$TARGET"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"t1", c - - a = SCons.Action.CommandAction(["$TARGETS"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"t1 t2 t3 t4 t5 t6", c - - a = SCons.Action.CommandAction(["${TARGETS[2]}"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"t3", c - - a = SCons.Action.CommandAction(["${TARGETS[3:5]}"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"t4 t5", c - - a = SCons.Action.CommandAction(["$SOURCE"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"s1", c - - a = SCons.Action.CommandAction(["$SOURCES"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"s1 s2 s3 s4 s5 s6", c - - a = SCons.Action.CommandAction(["${SOURCES[2]}"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"s3", c - - a = SCons.Action.CommandAction(["${SOURCES[3:5]}"]) - c = a.get_contents(target=t, source=s, env=env) - assert c == b"s4 s5", c - - def test_get_implicit_deps(self): - """Test getting the implicit dependencies of a command Action.""" - class SpecialEnvironment(Environment): - def WhereIs(self, prog): - return prog - - class fs: - def File(name): - return name - - env = SpecialEnvironment() - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), [_python_]) - - for false_like_value in [False, 0, None, "None", "False", "0", "NONE", "FALSE", "off", "OFF", "NO", "no"]: - env = SpecialEnvironment(IMPLICIT_COMMAND_DEPENDENCIES=false_like_value) - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), []) - - env = SpecialEnvironment(IMPLICIT_COMMAND_DEPENDENCIES="$SUBST_VALUE", SUBST_VALUE=false_like_value) - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), []) - - for true_like_value in [True, 1, "True", "TRUE", "1"]: - env = SpecialEnvironment(IMPLICIT_COMMAND_DEPENDENCIES=true_like_value) - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), [_python_]) - - env = SpecialEnvironment(IMPLICIT_COMMAND_DEPENDENCIES="$SUBST_VALUE", SUBST_VALUE=true_like_value) - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), [_python_]) - - for all_like_Value in ["all", "ALL", 2, "2"]: - env = SpecialEnvironment(IMPLICIT_COMMAND_DEPENDENCIES=all_like_Value) - a = SCons.Action.CommandAction([_python_, exit_py]) - self.assertEqual(a.get_implicit_deps(target=[], source=[], env=env), [_python_, exit_py]) - - -class CommandGeneratorActionTestCase(unittest.TestCase): - - def factory(self, act, **kw): - """Pass any keywords as a dict""" - return SCons.Action.CommandGeneratorAction(act, kw) - - def test___init__(self): - """Test creation of a command generator Action - """ - - def f(target, source, env): - pass - - a = self.factory(f) - assert a.generator == f - - def test___str__(self): - """Test the pre-substitution strings for command generator Actions - """ - - def f(target, source, env, for_signature, self=self): - # See if "env" is really a construction environment (or - # looks like one) by accessing the FindIxes attribute. - # (The Tool/mingw.py module has a generator that uses this, - # and the __str__() method used to cause problems by passing - # us a regular dictionary as a fallback.) - - env.FindIxes - return "FOO" - - a = self.factory(f) - s = str(a) - assert s == 'FOO', s - - def test_genstring(self): - """Test the command generator Action genstring() method - """ - - def f(target, source, env, for_signature, self=self): - dummy = env['dummy'] - self.dummy = dummy - return "$FOO $TARGET $SOURCE $TARGETS $SOURCES" - - a = self.factory(f) - self.dummy = 0 - s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1)) - assert self.dummy == 1, self.dummy - assert s == "$FOO $TARGET $SOURCE $TARGETS $SOURCES", s - - def test_execute(self): - """Test executing a command generator Action - """ - - def f(target, source, env, for_signature, self=self): - dummy = env['dummy'] - self.dummy = dummy - s = env.subst("$FOO") - assert s == 'foo baz\nbar ack', s - return "$FOO" - - def func_action(target, source, env, self=self): - dummy = env['dummy'] - s = env.subst('$foo') - assert s == 'bar', s - self.dummy = dummy - - def f2(target, source, env, for_signature, f=func_action): - return f - - def ch(sh, escape, cmd, args, env, self=self): - self.cmd.append(cmd) - self.args.append(args) - - a = self.factory(f) - self.dummy = 0 - self.cmd = [] - self.args = [] - a([], [], env=Environment(FOO='foo baz\nbar ack', - dummy=1, - SPAWN=ch)) - assert self.dummy == 1, self.dummy - assert self.cmd == ['foo', 'bar'], self.cmd - assert self.args == [['foo', 'baz'], ['bar', 'ack']], self.args - - b = self.factory(f2) - self.dummy = 0 - b(target=[], source=[], env=Environment(foo='bar', - dummy=2)) - assert self.dummy == 2, self.dummy - del self.dummy - - class DummyFile: - def __init__(self, t): - self.t = t - - def rfile(self): - self.t.rfile_called = 1 - return self - - def get_subst_proxy(self): - return self - - def f3(target, source, env, for_signature): - return '' - - c = self.factory(f3) - c(target=[], source=DummyFile(self), env=Environment()) - assert self.rfile_called - - def test_get_contents(self): - """Test fetching the contents of a command generator Action - """ - - def f(target, source, env, for_signature): - foo = env['foo'] - bar = env['bar'] - assert for_signature, for_signature - return [["guux", foo, "$(", "$ignore", "$)", bar, - '${test("$( foo $bar $)")}']] - - def test(mystr): - assert mystr == "$( foo $bar $)", mystr - return "test" - - env = Environment(foo='FFF', bar='BBB', - ignore='foo', test=test) - a = self.factory(f) - c = a.get_contents(target=[], source=[], env=env) - assert c == b"guux FFF BBB test", c - - def test_get_contents_of_function_action(self): - """Test contents of a CommandGeneratorAction-generated FunctionAction - """ - - def LocalFunc(): - pass - - # Since the python bytecode has per version differences, we need different expected results per version - func_matches = { - (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - } - - meth_matches = [ - b"1, 1, 0, 0,(),(),(d\000\000S),(),()", - b"1, 1, 0, 0,(),(),(d\x00\x00S),(),()", - ] - - def f_global(target, source, env, for_signature): - return SCons.Action.Action(GlobalFunc) - - def f_local(target, source, env, for_signature): - return SCons.Action.Action(LocalFunc) - - env = Environment(XYZ='foo') - - a = self.factory(f_global) - c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + repr( - func_matches[sys.version_info[:2]]) - - a = self.factory(f_local) - c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + repr( - func_matches[sys.version_info[:2]]) - - def f_global2(target, source, env, for_signature): - return SCons.Action.Action(GlobalFunc, varlist=['XYZ']) - - def f_local2(target, source, env, for_signature): - return SCons.Action.Action(LocalFunc, varlist=['XYZ']) - - matches_foo = func_matches[sys.version_info[:2]] + b'foo' - - a = self.factory(f_global2) - c = a.get_contents(target=[], source=[], env=env) - assert c in matches_foo, repr(c) - - a = self.factory(f_local2) - c = a.get_contents(target=[], source=[], env=env) - assert c in matches_foo, repr(c) - - -class FunctionActionTestCase(unittest.TestCase): - - def test___init__(self): - """Test creation of a function Action - """ - - def func1(): - pass - - def func2(): - pass - - def func3(): - pass - - def func4(): - pass - - a = SCons.Action.FunctionAction(func1, {}) - assert a.execfunction == func1, a.execfunction - assert isinstance(a.strfunction, types.MethodType), type(a.strfunction) - - a = SCons.Action.FunctionAction(func2, {'strfunction': func3}) - assert a.execfunction == func2, a.execfunction - assert a.strfunction == func3, a.strfunction - - def test___str__(self): - """Test the __str__() method for function Actions - """ - - def func1(): - pass - - a = SCons.Action.FunctionAction(func1, {}) - s = str(a) - assert s == "func1(target, source, env)", s - - class class1: - def __call__(self): - pass - - a = SCons.Action.FunctionAction(class1(), {}) - s = str(a) - assert s == "class1(target, source, env)", s - - def test_execute(self): - """Test executing a function Action - """ - self.inc = 0 - - def f(target, source, env): - s = env['s'] - s.inc = s.inc + 1 - s.target = target - s.source = source - assert env.subst("$BAR") == 'foo bar', env.subst("$BAR") - return 0 - - a = SCons.Action.FunctionAction(f, {}) - a(target=1, source=2, env=Environment(BAR='foo bar', - s=self)) - assert self.inc == 1, self.inc - assert self.source == [2], self.source - assert self.target == [1], self.target - - global count - count = 0 - - def function1(target, source, env): - global count - count = count + 1 - for t in target: - with open(t, 'w') as f: - f.write("function1\n") - return 1 - - act = SCons.Action.FunctionAction(function1, {}) - r = act(target=[outfile, outfile2], source=[], env=Environment()) - assert r.status == 1, r.status - - assert count == 1, count - c = test.read(outfile, 'r') - assert c == "function1\n", c - c = test.read(outfile2, 'r') - assert c == "function1\n", c - - class class1a: - def __init__(self, target, source, env): - with open(env['out'], 'w') as f: - f.write("class1a\n") - - act = SCons.Action.FunctionAction(class1a, {}) - r = act([], [], Environment(out=outfile)) - assert isinstance(r.status, class1a), r.status - c = test.read(outfile, 'r') - assert c == "class1a\n", c - - class class1b: - def __call__(self, target, source, env): - with open(env['out'], 'w') as f: - f.write("class1b\n") - return 2 - - act = SCons.Action.FunctionAction(class1b(), {}) - r = act([], [], Environment(out=outfile)) - assert r.status == 2, r.status - c = test.read(outfile, 'r') - assert c == "class1b\n", c - - def build_it(target, source, env, executor=None, self=self): - self.build_it = 1 - return 0 - - def string_it(target, source, env, executor=None, self=self): - self.string_it = 1 - return None - - act = SCons.Action.FunctionAction(build_it, - {'strfunction': string_it}) - r = act([], [], Environment()) - assert r == 0, r - assert self.build_it - assert self.string_it - - def test_get_contents(self): - """Test fetching the contents of a function Action - """ - - def LocalFunc(): - pass - - func_matches = { - (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - - } - - meth_matches = { - (3, 5): bytearray(b'1, 1, 0, 0,(),(),(d\x00\x00S),(),()'), - (3, 6): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 8): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 9): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 10): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), - } - - def factory(act, **kw): - return SCons.Action.FunctionAction(act, kw) - - a = factory(GlobalFunc) - c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - a = factory(LocalFunc) - c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - matches_foo = func_matches[sys.version_info[:2]] + b'foo' - - a = factory(GlobalFunc, varlist=['XYZ']) - c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - # assert c in func_matches, repr(c) - - c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo')) - assert c == matches_foo, repr(c) - - ##TODO: is this set of tests still needed? - # Make sure a bare string varlist works - a = factory(GlobalFunc, varlist='XYZ') - c = a.get_contents(target=[], source=[], env=Environment()) - # assert c in func_matches, repr(c) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo')) - assert c in matches_foo, repr(c) - - class Foo: - def get_contents(self, target, source, env): - return b'xyzzy' - - a = factory(Foo()) - c = a.get_contents(target=[], source=[], env=Environment()) - assert c == b'xyzzy', repr(c) - - class LocalClass: - def LocalMethod(self): - pass - - lc = LocalClass() - a = factory(lc.LocalMethod) - c = a.get_contents(target=[], source=[], env=Environment()) - assert c == meth_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - meth_matches[sys.version_info[:2]]) - - def test_strfunction(self): - """Test the FunctionAction.strfunction() method - """ - - def func(): - pass - - def factory(act, **kw): - return SCons.Action.FunctionAction(act, kw) - - a = factory(func) - s = a.strfunction(target=[], source=[], env=Environment()) - assert s == 'func([], [])', s - - a = factory(func, strfunction=None) - s = a.strfunction(target=[], source=[], env=Environment()) - assert s is None, s - - a = factory(func, cmdstr='function') - s = a.strfunction(target=[], source=[], env=Environment()) - assert s == 'function', s - - -class ListActionTestCase(unittest.TestCase): - - def test___init__(self): - """Test creation of a list of subsidiary Actions - """ - - def func(): - pass - - a = SCons.Action.ListAction(["x", func, ["y", "z"]]) - assert isinstance(a.list[0], SCons.Action.CommandAction) - assert isinstance(a.list[1], SCons.Action.FunctionAction) - assert isinstance(a.list[2], SCons.Action.ListAction) - assert a.list[2].list[0].cmd_list == 'y' - - def test___str__(self): - """Test the __str__() method for a list of subsidiary Actions - """ - - def f(target, source, env): - pass - - def g(target, source, env): - pass - - a = SCons.Action.ListAction([f, g, "XXX", f]) - s = str(a) - assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s - - def test_genstring(self): - """Test the genstring() method for a list of subsidiary Actions - """ - - def f(target, source, env): - pass - - def g(target, source, env, for_signature): - return 'generated %s %s' % (target[0], source[0]) - - g = SCons.Action.Action(g, generator=1) - a = SCons.Action.ListAction([f, g, "XXX", f]) - s = a.genstring(['foo.x'], ['bar.y'], Environment()) - assert s == "f(target, source, env)\ngenerated foo.x bar.y\nXXX\nf(target, source, env)", s - - def test_execute(self): - """Test executing a list of subsidiary Actions - """ - self.inc = 0 - - def f(target, source, env): - s = env['s'] - s.inc = s.inc + 1 - - a = SCons.Action.ListAction([f, f, f]) - a([], [], Environment(s=self)) - assert self.inc == 3, self.inc - - cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile) - - def function2(target, source, env): - with open(env['out'], 'a') as f: - f.write("function2\n") - return 0 - - class class2a: - def __call__(self, target, source, env): - with open(env['out'], 'a') as f: - f.write("class2a\n") - return 0 - - class class2b: - def __init__(self, target, source, env): - with open(env['out'], 'a') as f: - f.write("class2b\n") - - act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b]) - r = act([], [], Environment(out=outfile)) - assert isinstance(r.status, class2b), r.status - c = test.read(outfile, 'r') - assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c - - def test_get_contents(self): - """Test fetching the contents of a list of subsidiary Actions - """ - self.foo = 0 - - def gen(target, source, env, for_signature): - s = env['s'] - s.foo = 1 - return "y" - - a = SCons.Action.ListAction(["x", - SCons.Action.Action(gen, generator=1), - "z"]) - c = a.get_contents(target=[], source=[], env=Environment(s=self)) - assert self.foo == 1, self.foo - assert c == b"xyz", c - - -class LazyActionTestCase(unittest.TestCase): - def test___init__(self): - """Test creation of a lazy-evaluation Action - """ - # Environment variable references should create a special type - # of LazyAction that lazily evaluates the variable for whether - # it's a string or something else before doing anything. - a9 = SCons.Action.Action('$FOO') - assert isinstance(a9, SCons.Action.LazyAction), a9 - assert a9.var == 'FOO', a9.var - - a10 = SCons.Action.Action('${FOO}') - assert isinstance(a10, SCons.Action.LazyAction), a10 - assert a10.var == 'FOO', a10.var - - def test_genstring(self): - """Test the lazy-evaluation Action genstring() method - """ - - def f(target, source, env): - pass - - a = SCons.Action.Action('$BAR') - env1 = Environment(BAR=f, s=self) - env2 = Environment(BAR='xxx', s=self) - s = a.genstring([], [], env=env1) - assert s == "f(target, source, env)", s - s = a.genstring([], [], env=env2) - assert s == 'xxx', s - - def test_execute(self): - """Test executing a lazy-evaluation Action - """ - - def f(target, source, env): - s = env['s'] - s.test = 1 - return 0 - - a = SCons.Action.Action('$BAR') - a([], [], env=Environment(BAR=f, s=self)) - assert self.test == 1, self.test - cmd = r'%s %s %s lazy' % (_python_, act_py, outfile) - a([], [], env=Environment(BAR=cmd, s=self)) - c = test.read(outfile, 'r') - assert c == "act.py: 'lazy'\n", c - - def test_get_contents(self): - """Test fetching the contents of a lazy-evaluation Action - """ - a = SCons.Action.Action("${FOO}") - env = Environment(FOO=[["This", "is", "a", "test"]]) - c = a.get_contents(target=[], source=[], env=env) - assert c == b"This is a test", c - - def test_get_contents_of_function_action(self): - """Test fetching the contents of a lazy-evaluation FunctionAction - """ - - def LocalFunc(): - pass - - func_matches = { - (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), - } - - meth_matches = [ - b"1, 1, 0, 0,(),(),(d\000\000S),(),()", - b"1, 1, 0, 0,(),(),(d\x00\x00S),(),()", - ] - - def factory(act, **kw): - return SCons.Action.FunctionAction(act, kw) - - a = SCons.Action.Action("${FOO}") - - env = Environment(FOO=factory(GlobalFunc)) - c = a.get_contents(target=[], source=[], env=env) - # assert c in func_matches, "Got\n"+repr(c)+"\nExpected one of \n"+"\n".join([repr(f) for f in func_matches]) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - env = Environment(FOO=factory(LocalFunc)) - c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - # matches_foo = [x + b"foo" for x in func_matches] - matches_foo = func_matches[sys.version_info[:2]] + b'foo' - - env = Environment(FOO=factory(GlobalFunc, varlist=['XYZ'])) - c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - func_matches[sys.version_info[:2]]) - - env['XYZ'] = 'foo' - c = a.get_contents(target=[], source=[], env=env) - assert c in matches_foo, repr(c) - - -class ActionCallerTestCase(unittest.TestCase): - def test___init__(self): - """Test creation of an ActionCaller""" - ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO': 4, 'BAR': 5}) - assert ac.parent == 1, ac.parent - assert ac.args == [2, 3], ac.args - assert ac.kw == {'FOO': 4, 'BAR': 5}, ac.kw - - def test_get_contents(self): - """Test fetching the contents of an ActionCaller""" - - def strfunc(): - pass - - def LocalFunc(): - pass - - matches = { - (3, 5): b'd\x00\x00S', - (3, 6): b'd\x00S\x00', - (3, 7): b'd\x00S\x00', - (3, 8): b'd\x00S\x00', - (3, 9): b'd\x00S\x00', - (3, 10): b'd\x00S\x00', - - } - - af = SCons.Action.ActionFactory(GlobalFunc, strfunc) - ac = SCons.Action.ActionCaller(af, [], {}) - c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - matches[sys.version_info[:2]]) - - af = SCons.Action.ActionFactory(LocalFunc, strfunc) - ac = SCons.Action.ActionCaller(af, [], {}) - c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - matches[sys.version_info[:2]]) - - class LocalActFunc: - def __call__(self): - pass - - af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc) - ac = SCons.Action.ActionCaller(af, [], {}) - c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - matches[sys.version_info[:2]]) - - af = SCons.Action.ActionFactory(LocalActFunc(), strfunc) - ac = SCons.Action.ActionCaller(af, [], {}) - c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( - matches[sys.version_info[:2]]) - - matches = [ - b"", - b"", - ] - - af = SCons.Action.ActionFactory(str, strfunc) - ac = SCons.Action.ActionCaller(af, [], {}) - c = ac.get_contents([], [], Environment()) - assert c == "" or \ - c == "" or \ - c == "", repr(c) - # ^^ class str for python3 - - def test___call__(self): - """Test calling an ActionCaller""" - actfunc_args = [] - - def actfunc(a1, a2, a3, args=actfunc_args): - args.extend([a1, a2, a3]) - - def strfunc(a1, a2, a3): - pass - - e = Environment(FOO=2, BAR=5) - - af = SCons.Action.ActionFactory(actfunc, strfunc) - ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {}) - ac([], [], e) - assert actfunc_args[0] is e, actfunc_args - assert actfunc_args[1] == '2', actfunc_args - assert actfunc_args[2] == 3, actfunc_args - del actfunc_args[:] - - ac = SCons.Action.ActionCaller(af, [], {'a3': '$__env__', 'a2': '$BAR', 'a1': 4}) - ac([], [], e) - assert actfunc_args[0] == 4, actfunc_args - assert actfunc_args[1] == '5', actfunc_args - assert actfunc_args[2] is e, actfunc_args - del actfunc_args[:] - - def test_strfunction(self): - """Test calling the ActionCaller strfunction() method""" - strfunc_args = [] - - def actfunc(a1, a2, a3, a4): - pass - - def strfunc(a1, a2, a3, a4, args=strfunc_args): - args.extend([a1, a2, a3, a4]) - - af = SCons.Action.ActionFactory(actfunc, strfunc) - ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3, '$WS'], {}) - ac.strfunction([], [], Environment(FOO=2, WS='white space')) - assert strfunc_args == [1, '2', 3, 'white space'], strfunc_args - - del strfunc_args[:] - d = {'a3': 6, 'a2': '$BAR', 'a1': 4, 'a4': '$WS'} - ac = SCons.Action.ActionCaller(af, [], d) - ac.strfunction([], [], Environment(BAR=5, WS='w s')) - assert strfunc_args == [4, '5', 6, 'w s'], strfunc_args - - -class ActionFactoryTestCase(unittest.TestCase): - def test___init__(self): - """Test creation of an ActionFactory""" - - def actfunc(): - pass - - def strfunc(): - pass - - ac = SCons.Action.ActionFactory(actfunc, strfunc) - assert ac.actfunc is actfunc, ac.actfunc - assert ac.strfunc is strfunc, ac.strfunc - - def test___call__(self): - """Test calling whatever's returned from an ActionFactory""" - actfunc_args = [] - strfunc_args = [] - - def actfunc(a1, a2, a3, args=actfunc_args): - args.extend([a1, a2, a3]) - - def strfunc(a1, a2, a3, args=strfunc_args): - args.extend([a1, a2, a3]) - - af = SCons.Action.ActionFactory(actfunc, strfunc) - af(3, 6, 9)([], [], Environment()) - assert actfunc_args == [3, 6, 9], actfunc_args - assert strfunc_args == [3, 6, 9], strfunc_args - - -class ActionCompareTestCase(unittest.TestCase): - - def test_1_solo_name(self): - """Test Lazy Cmd Generator Action get_name alone. - - Basically ensures we can locate the builder, comparing it to - itself along the way.""" - bar = SCons.Builder.Builder(action={}) - env = Environment(BUILDERS={'BAR': bar}) - name = bar.get_name(env) - assert name == 'BAR', name - - def test_2_multi_name(self): - """Test LazyCmdGenerator Action get_name multi builders. - - Ensure that we can compare builders (and thereby actions) to - each other safely.""" - foo = SCons.Builder.Builder(action='$FOO', suffix='.foo') - bar = SCons.Builder.Builder(action={}) - assert foo != bar - assert foo.action != bar.action - env = Environment(BUILDERS={'FOO': foo, - 'BAR': bar}) - name = foo.get_name(env) - assert name == 'FOO', name - name = bar.get_name(env) - assert name == 'BAR', name - - def test_3_dict_names(self): - """Test Action/Suffix dicts with get_name. - - Verifies that Action/Suffix dictionaries work correctly, - especially two builders that can generate the same suffix, - where one of the builders has a suffix dictionary with a None - key.""" - - foo = SCons.Builder.Builder(action='$FOO', suffix='.foo') - bar = SCons.Builder.Builder(action={}, suffix={None: '.bar'}) - bar.add_action('.cow', "$MOO") - dog = SCons.Builder.Builder(suffix='.bar') - - env = Environment(BUILDERS={'FOO': foo, - 'BAR': bar, - 'DOG': dog}) - - assert foo.get_name(env) == 'FOO', foo.get_name(env) - assert bar.get_name(env) == 'BAR', bar.get_name(env) - assert dog.get_name(env) == 'DOG', dog.get_name(env) - - -class TestClass: - """A test class used by ObjectContentsTestCase.test_object_contents""" - - def __init__(self): - self.a = "a" - self.b = "b" - - def method(self, arg): - pass - - -class ObjectContentsTestCase(unittest.TestCase): - - def test_function_contents(self): - """Test that Action._function_contents works""" - - def func1(a, b, c): - """A test function""" - return a - - # Since the python bytecode has per version differences, we need different expected results per version - expected = { - (3, 5): (bytearray(b'3, 3, 0, 0,(),(),(|\x00\x00S),(),()')), - (3, 6): (bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()')), - (3, 7): (bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()')), - (3, 8): (bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()')), - (3, 9): (bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()')), - (3, 10): (bytearray(b'3, 3, 0, 0,(N.),(),(|\x00S\x00),(),()'), - bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()')) # 3.10.1, 3.10.2 - } - - c = SCons.Action._function_contents(func1) - assert c in expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr( - expected[sys.version_info[:2]]) - - def test_object_contents(self): - """Test that Action._object_contents works""" - - # See definition above - o = TestClass() - c = SCons.Action._object_contents(o) - - # c = SCons.Action._object_instance_content(o) - - # Since the python bytecode has per version differences, we need different expected results per version - expected = { - (3, 5): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01\x00|\x00\x00_\x00\x00d\x02\x00|\x00\x00_\x01\x00d\x00\x00S),(),(),2, 2, 0, 0,(),(),(d\x00\x00S),(),()}}{{{a=a,b=b}}}"), - (3, 6): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), - (3, 7): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), - (3, 8): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), - (3, 9): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), - (3, 10): bytearray( - b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), - } - - assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr( - expected[sys.version_info[:2]]) - - def test_code_contents(self): - """Test that Action._code_contents works""" - - code = compile("print('Hello, World!')", '', 'exec') - c = SCons.Action._code_contents(code) - - # Since the python bytecode has per version differences, we need different expected results per version - expected = { - (3, 5): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00\x00d\x00\x00\x83\x01\x00\x01d\x01\x00S)'), - (3, 6): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), - (3, 7): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), - (3, 8): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), - (3, 9): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), - (3, 10): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), - } - - assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr(expected[ - sys.version_info[:2]]) - - def test_uncaught_exception_bubbles(self): - """Test that _subproc bubbles uncaught exceptions""" - try: - pobj = SCons.Action._subproc(Environment(), - None, - stdin='devnull', - stderr='devnull', - stdout=subprocess.PIPE) - pobj.wait() - except EnvironmentError: - pass - except Exception: - # pass the test - return - - raise Exception("expected a non-EnvironmentError exception") - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/BuilderTests.py b/SCSCons/BuilderTests.py deleted file mode 100644 index 636534f04..000000000 --- a/SCSCons/BuilderTests.py +++ /dev/null @@ -1,1629 +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 SCons.compat - -# Define a null function for use as a builder action. -# Where this is defined in the file seems to affect its -# byte-code contents, so try to minimize changes by -# defining it here, before we even import anything. -def Func(): - pass - -from collections import UserList -import io -import os.path -import re -import sys -import unittest - -import TestCmd - -import SCons.Action -import SCons.Builder -import SCons.Environment -import SCons.Errors -import SCons.Subst -import SCons.Util - -sys.stdout = io.StringIO() - -# Initial setup of the common environment for all tests, -# a temporary working directory containing a -# script for writing arguments to an output file. -# -# We don't do this as a setUp() method because it's -# unnecessary to create a separate directory and script -# for each test, they can just use the one. -test = TestCmd.TestCmd(workdir = '') - -outfile = test.workpath('outfile') -outfile2 = test.workpath('outfile2') - -infile = test.workpath('infile') -test.write(infile, "infile\n") - -show_string = None - -scons_env = SCons.Environment.Environment() - -env_arg2nodes_called = None - -class Environment: - def __init__(self, **kw): - self.d = {} - self.d['SHELL'] = scons_env['SHELL'] - self.d['SPAWN'] = scons_env['SPAWN'] - self.d['ESCAPE'] = scons_env['ESCAPE'] - for k, v in kw.items(): - self.d[k] = v - global env_arg2nodes_called - env_arg2nodes_called = None - self.scanner = None - self.fs = SCons.Node.FS.FS() - def subst(self, s): - if not SCons.Util.is_String(s): - return s - def substitute(m, d=self.d): - return d.get(m.group(1), '') - return re.sub(r'\$(\w+)', substitute, s) - def subst_target_source(self, string, raw=0, target=None, - source=None, dict=None, conv=None): - return SCons.Subst.scons_subst(string, self, raw, target, - source, dict, conv) - def subst_list(self, string, raw=0, target=None, source=None, conv=None): - return SCons.Subst.scons_subst_list(string, self, raw, target, - source, {}, {}, conv) - def arg2nodes(self, args, factory, **kw): - global env_arg2nodes_called - env_arg2nodes_called = 1 - if not SCons.Util.is_List(args): - args = [args] - list = [] - for a in args: - if SCons.Util.is_String(a): - a = factory(self.subst(a)) - list.append(a) - return list - def get_factory(self, factory): - return factory or self.fs.File - def get_scanner(self, ext): - return self.scanner - def Dictionary(self): - return {} - def autogenerate(self, dir=''): - return {} - def __setitem__(self, item, var): - self.d[item] = var - def __getitem__(self, item): - return self.d[item] - def __contains__(self, key): - return key in self.d - def keys(self): - return list(self.d.keys()) - def get(self, key, value=None): - return self.d.get(key, value) - def Override(self, overrides): - env = Environment(**self.d) - env.d.update(overrides) - env.scanner = self.scanner - return env - def _update(self, dict): - self.d.update(dict) - def items(self): - return list(self.d.items()) - def sig_dict(self): - d = {} - for k,v in self.items(): d[k] = v - d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] - d['TARGET'] = d['TARGETS'][0] - d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] - d['SOURCE'] = d['SOURCES'][0] - return d - def __eq__(self, other): - return self.scanner == other.scanner or self.d == other.d - -class MyAction: - def __init__(self, action): - self.action = action - def __call__(self, *args, **kw): - pass - def get_executor(self, env, overrides, tlist, slist, executor_kw): - return ['executor'] + [self.action] - -class MyNode_without_target_from_source: - def __init__(self, name): - self.name = name - self.sources = [] - self.builder = None - self.is_explicit = None - self.side_effect = 0 - def get_suffix(self): - return os.path.splitext(self.name)[1] - def disambiguate(self): - return self - def __str__(self): - return self.name - def builder_set(self, builder): - self.builder = builder - def has_builder(self): - return self.builder is not None - def set_explicit(self, is_explicit): - self.is_explicit = is_explicit - def has_explicit_builder(self): - return self.is_explicit - def env_set(self, env, safe=0): - self.env = env - def add_source(self, source): - self.sources.extend(source) - def scanner_key(self): - return self.name - def is_derived(self): - return self.has_builder() - def generate_build_env(self, env): - return env - def get_build_env(self): - return self.executor.get_build_env() - def set_executor(self, executor): - self.executor = executor - def get_executor(self, create=1): - return self.executor - -class MyNode(MyNode_without_target_from_source): - def target_from_source(self, prefix, suffix, stripext): - return MyNode(prefix + stripext(str(self))[0] + suffix) - -class BuilderTestCase(unittest.TestCase): - - def test__init__(self): - """Test simple Builder creation - """ - builder = SCons.Builder.Builder(action="foo") - assert builder is not None, builder - builder = SCons.Builder.Builder(action="foo", OVERRIDE='x') - x = builder.overrides['OVERRIDE'] - assert x == 'x', x - - def test__bool__(self): - """Test a builder raising an exception when __bool__ is called. """ - - # basic test: explicitly call it - builder = SCons.Builder.Builder(action="foo") - exc_caught = None - try: - builder.__bool__() - except SCons.Errors.InternalError: - exc_caught = 1 - assert exc_caught, "did not catch expected InternalError exception" - - class Node: - pass - - # the interesting test: checking the attribute this way - # should call back to Builder.__bool__ - so we can tell - # people not to check that way (for performance). - # TODO: workaround #3860: with just a "pass" in the check body, - # py3.10a optimizes out the whole thing, so add a "real" stmt - n = Node() - n.builder = builder - exc_caught = None - try: - if n.builder: - #pass - _ = True - except SCons.Errors.InternalError: - exc_caught = 1 - assert exc_caught, "did not catch expected InternalError exception" - - def test__call__(self): - """Test calling a builder to establish source dependencies - """ - env = Environment() - builder = SCons.Builder.Builder(action="foo", - target_factory=MyNode, - source_factory=MyNode) - - tgt = builder(env, source=[]) - assert tgt == [], tgt - - n1 = MyNode("n1") - n2 = MyNode("n2") - builder(env, target = n1, source = n2) - assert env_arg2nodes_called - assert n1.env == env, n1.env - assert n1.builder == builder, n1.builder - assert n1.sources == [n2], n1.sources - assert n1.executor, "no executor found" - assert not hasattr(n2, 'env') - - l = [1] - ul = UserList([2]) - try: - l.extend(ul) - except TypeError: - def mystr(l): - return str(list(map(str, l))) - else: - mystr = str - - nnn1 = MyNode("nnn1") - nnn2 = MyNode("nnn2") - tlist = builder(env, target = [nnn1, nnn2], source = []) - s = mystr(tlist) - assert s == "['nnn1', 'nnn2']", s - l = list(map(str, tlist)) - assert l == ['nnn1', 'nnn2'], l - - tlist = builder(env, target = 'n3', source = 'n4') - s = mystr(tlist) - assert s == "['n3']", s - target = tlist[0] - l = list(map(str, tlist)) - assert l == ['n3'], l - assert target.name == 'n3' - assert target.sources[0].name == 'n4' - - tlist = builder(env, target = 'n4 n5', source = ['n6 n7']) - s = mystr(tlist) - assert s == "['n4 n5']", s - l = list(map(str, tlist)) - assert l == ['n4 n5'], l - target = tlist[0] - assert target.name == 'n4 n5' - assert target.sources[0].name == 'n6 n7' - - tlist = builder(env, target = ['n8 n9'], source = 'n10 n11') - s = mystr(tlist) - assert s == "['n8 n9']", s - l = list(map(str, tlist)) - assert l == ['n8 n9'], l - target = tlist[0] - assert target.name == 'n8 n9' - assert target.sources[0].name == 'n10 n11' - - # A test to be uncommented when we freeze the environment - # as part of calling the builder. - #env1 = Environment(VAR='foo') - #target = builder(env1, target = 'n12', source = 'n13') - #env1['VAR'] = 'bar' - #be = target.get_build_env() - #assert be['VAR'] == 'foo', be['VAR'] - - n20 = MyNode_without_target_from_source('n20') - flag = 0 - try: - target = builder(env, None, source=n20) - except SCons.Errors.UserError as e: - flag = 1 - assert flag, "UserError should be thrown if a source node can't create a target." - - builder = SCons.Builder.Builder(action="foo", - target_factory=MyNode, - source_factory=MyNode, - prefix='p-', - suffix='.s') - target = builder(env, None, source='n21')[0] - assert target.name == 'p-n21.s', target - - builder = SCons.Builder.Builder(misspelled_action="foo", - suffix = '.s') - try: - builder(env, target = 'n22', source = 'n22') - except SCons.Errors.UserError as e: - pass - else: - raise Exception("Did not catch expected UserError.") - - builder = SCons.Builder.Builder(action="foo") - target = builder(env, None, source='n22', srcdir='src_dir')[0] - p = target.sources[0].get_internal_path() - assert p == os.path.join('src_dir', 'n22'), p - - def test_mistaken_variables(self): - """Test keyword arguments that are often mistakes - """ - import SCons.Warnings - env = Environment() - builder = SCons.Builder.Builder(action="foo") - - save_warn = SCons.Warnings.warn - warned = [] - def my_warn(exception, warning, warned=warned): - warned.append(warning) - SCons.Warnings.warn = my_warn - - try: - target = builder(env, 'mistaken1', sources='mistaken1.c') - assert warned == ["Did you mean to use `source' instead of `sources'?"], warned - del warned[:] - - target = builder(env, 'mistaken2', targets='mistaken2.c') - assert warned == ["Did you mean to use `target' instead of `targets'?"], warned - del warned[:] - - target = builder(env, 'mistaken3', targets='mistaken3', sources='mistaken3.c') - assert "Did you mean to use `source' instead of `sources'?" in warned, warned - assert "Did you mean to use `target' instead of `targets'?" in warned, warned - del warned[:] - finally: - SCons.Warnings.warn = save_warn - - def test_action(self): - """Test Builder creation - - Verify that we can retrieve the supplied action attribute. - """ - builder = SCons.Builder.Builder(action="foo") - assert builder.action.cmd_list == "foo" - - def func(): - pass - builder = SCons.Builder.Builder(action=func) - assert isinstance(builder.action, SCons.Action.FunctionAction) - # Preserve the following so that the baseline test will fail. - # Remove it in favor of the previous test at some convenient - # point in the future. - assert builder.action.execfunction == func - - def test_generator(self): - """Test Builder creation given a generator function.""" - - def generator(): - pass - - builder = SCons.Builder.Builder(generator=generator) - assert builder.action.generator == generator - - def test_cmp(self): - """Test simple comparisons of Builder objects - """ - b1 = SCons.Builder.Builder(src_suffix = '.o') - b2 = SCons.Builder.Builder(src_suffix = '.o') - assert b1 == b2 - b3 = SCons.Builder.Builder(src_suffix = '.x') - assert b1 != b3 - assert b2 != b3 - - def test_target_factory(self): - """Test a Builder that creates target nodes of a specified class - """ - class Foo: - pass - def FooFactory(target): - global Foo - return Foo(target) - builder = SCons.Builder.Builder(target_factory = FooFactory) - assert builder.target_factory is FooFactory - assert builder.source_factory is not FooFactory - - def test_source_factory(self): - """Test a Builder that creates source nodes of a specified class - """ - class Foo: - pass - def FooFactory(source): - global Foo - return Foo(source) - builder = SCons.Builder.Builder(source_factory = FooFactory) - assert builder.target_factory is not FooFactory - assert builder.source_factory is FooFactory - - def test_splitext(self): - """Test the splitext() method attached to a Builder.""" - b = SCons.Builder.Builder() - assert b.splitext('foo') == ('foo','') - assert b.splitext('foo.bar') == ('foo','.bar') - assert b.splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'') - - class MyBuilder(SCons.Builder.BuilderBase): - def splitext(self, path): - return "called splitext()" - - b = MyBuilder() - ret = b.splitext('xyz.c') - assert ret == "called splitext()", ret - - def test_adjust_suffix(self): - """Test how a Builder adjusts file suffixes - """ - b = SCons.Builder.Builder() - assert b.adjust_suffix('.foo') == '.foo' - assert b.adjust_suffix('foo') == '.foo' - assert b.adjust_suffix('$foo') == '$foo' - - class MyBuilder(SCons.Builder.BuilderBase): - def adjust_suffix(self, suff): - return "called adjust_suffix()" - - b = MyBuilder() - ret = b.adjust_suffix('.foo') - assert ret == "called adjust_suffix()", ret - - def test_prefix(self): - """Test Builder creation with a specified target prefix - - Make sure that there is no '.' separator appended. - """ - env = Environment() - builder = SCons.Builder.Builder(prefix = 'lib.') - assert builder.get_prefix(env) == 'lib.' - builder = SCons.Builder.Builder(prefix = 'lib', action='') - assert builder.get_prefix(env) == 'lib' - tgt = builder(env, target = 'tgt1', source = 'src1')[0] - assert tgt.get_internal_path() == 'libtgt1', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = 'tgt2a tgt2b', source = 'src2')[0] - assert tgt.get_internal_path() == 'libtgt2a tgt2b', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = None, source = 'src3')[0] - assert tgt.get_internal_path() == 'libsrc3', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = None, source = 'lib/src4')[0] - assert tgt.get_internal_path() == os.path.join('lib', 'libsrc4'), \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = 'lib/tgt5', source = 'lib/src5')[0] - assert tgt.get_internal_path() == os.path.join('lib', 'libtgt5'), \ - "Target has unexpected name: %s" % tgt.get_internal_path() - - def gen_prefix(env, sources): - return "gen_prefix() says " + env['FOO'] - my_env = Environment(FOO = 'xyzzy') - builder = SCons.Builder.Builder(prefix = gen_prefix) - assert builder.get_prefix(my_env) == "gen_prefix() says xyzzy" - my_env['FOO'] = 'abracadabra' - assert builder.get_prefix(my_env) == "gen_prefix() says abracadabra" - - def my_emit(env, sources): - return env.subst('$EMIT') - my_env = Environment(FOO = '.foo', EMIT = 'emit-') - builder = SCons.Builder.Builder(prefix = {None : 'default-', - '.in' : 'out-', - '.x' : 'y-', - '$FOO' : 'foo-', - '.zzz' : my_emit}, - action = '') - tgt = builder(my_env, target = None, source = 'f1')[0] - assert tgt.get_internal_path() == 'default-f1', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f2.c')[0] - assert tgt.get_internal_path() == 'default-f2', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f3.in')[0] - assert tgt.get_internal_path() == 'out-f3', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f4.x')[0] - assert tgt.get_internal_path() == 'y-f4', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f5.foo')[0] - assert tgt.get_internal_path() == 'foo-f5', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f6.zzz')[0] - assert tgt.get_internal_path() == 'emit-f6', tgt.get_internal_path() - - def test_set_suffix(self): - """Test the set_suffix() method""" - b = SCons.Builder.Builder(action='') - env = Environment(XSUFFIX = '.x') - - s = b.get_suffix(env) - assert s == '', s - - b.set_suffix('.foo') - s = b.get_suffix(env) - assert s == '.foo', s - - b.set_suffix('$XSUFFIX') - s = b.get_suffix(env) - assert s == '.x', s - - def test_src_suffix(self): - """Test Builder creation with a specified source file suffix - - Make sure that the '.' separator is appended to the - beginning if it isn't already present. - """ - env = Environment(XSUFFIX = '.x', YSUFFIX = '.y') - - b1 = SCons.Builder.Builder(src_suffix = '.c', action='') - assert b1.src_suffixes(env) == ['.c'], b1.src_suffixes(env) - - tgt = b1(env, target = 'tgt2', source = 'src2')[0] - assert tgt.sources[0].get_internal_path() == 'src2.c', \ - "Source has unexpected name: %s" % tgt.sources[0].get_internal_path() - - tgt = b1(env, target = 'tgt3', source = 'src3a src3b')[0] - assert len(tgt.sources) == 1 - assert tgt.sources[0].get_internal_path() == 'src3a src3b.c', \ - "Unexpected tgt.sources[0] name: %s" % tgt.sources[0].get_internal_path() - - b2 = SCons.Builder.Builder(src_suffix = '.2', src_builder = b1) - r = sorted(b2.src_suffixes(env)) - assert r == ['.2', '.c'], r - - b3 = SCons.Builder.Builder(action = {'.3a' : '', '.3b' : ''}) - s = sorted(b3.src_suffixes(env)) - assert s == ['.3a', '.3b'], s - - b4 = SCons.Builder.Builder(src_suffix = '$XSUFFIX') - assert b4.src_suffixes(env) == ['.x'], b4.src_suffixes(env) - - b5 = SCons.Builder.Builder(action = { '.y' : ''}) - assert b5.src_suffixes(env) == ['.y'], b5.src_suffixes(env) - - def test_srcsuffix_nonext(self): - """Test target generation from non-extension source suffixes""" - env = Environment() - b6 = SCons.Builder.Builder(action = '', - src_suffix='_src.a', - suffix='.b') - tgt = b6(env, target=None, source='foo_src.a') - assert str(tgt[0]) == 'foo.b', str(tgt[0]) - - b7 = SCons.Builder.Builder(action = '', - src_suffix='_source.a', - suffix='_obj.b') - b8 = SCons.Builder.Builder(action = '', - src_builder=b7, - suffix='.c') - tgt = b8(env, target=None, source='foo_source.a') - assert str(tgt[0]) == 'foo_obj.c', str(tgt[0]) - src = env.fs.File('foo_source.a') - tgt = b8(env, target=None, source=src) - assert str(tgt[0]) == 'foo_obj.c', str(tgt[0]) - - b9 = SCons.Builder.Builder(action={'_src.a' : 'srcaction'}, - suffix='.c') - b9.add_action('_altsrc.b', 'altaction') - tgt = b9(env, target=None, source='foo_altsrc.b') - assert str(tgt[0]) == 'foo.c', str(tgt[0]) - - def test_src_suffix_expansion(self): - """Test handling source suffixes when an expansion is involved""" - env = Environment(OBJSUFFIX = '.obj') - - b1 = SCons.Builder.Builder(action = '', - src_suffix='.c', - suffix='.obj') - b2 = SCons.Builder.Builder(action = '', - src_builder=b1, - src_suffix='.obj', - suffix='.exe') - tgt = b2(env, target=None, source=['foo$OBJSUFFIX']) - s = list(map(str, tgt[0].sources)) - assert s == ['foo.obj'], s - - def test_suffix(self): - """Test Builder creation with a specified target suffix - - Make sure that the '.' separator is appended to the - beginning if it isn't already present. - """ - env = Environment() - builder = SCons.Builder.Builder(suffix = '.o') - assert builder.get_suffix(env) == '.o', builder.get_suffix(env) - builder = SCons.Builder.Builder(suffix = 'o', action='') - assert builder.get_suffix(env) == '.o', builder.get_suffix(env) - tgt = builder(env, target = 'tgt3', source = 'src3')[0] - assert tgt.get_internal_path() == 'tgt3.o', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = 'tgt4a tgt4b', source = 'src4')[0] - assert tgt.get_internal_path() == 'tgt4a tgt4b.o', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - tgt = builder(env, target = None, source = 'src5')[0] - assert tgt.get_internal_path() == 'src5.o', \ - "Target has unexpected name: %s" % tgt.get_internal_path() - - def gen_suffix(env, sources): - return "gen_suffix() says " + env['BAR'] - my_env = Environment(BAR = 'hocus pocus') - builder = SCons.Builder.Builder(suffix = gen_suffix) - assert builder.get_suffix(my_env) == "gen_suffix() says hocus pocus", builder.get_suffix(my_env) - my_env['BAR'] = 'presto chango' - assert builder.get_suffix(my_env) == "gen_suffix() says presto chango" - - def my_emit(env, sources): - return env.subst('$EMIT') - my_env = Environment(BAR = '.bar', EMIT = '.emit') - builder = SCons.Builder.Builder(suffix = {None : '.default', - '.in' : '.out', - '.x' : '.y', - '$BAR' : '.new', - '.zzz' : my_emit}, - action='') - tgt = builder(my_env, target = None, source = 'f1')[0] - assert tgt.get_internal_path() == 'f1.default', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f2.c')[0] - assert tgt.get_internal_path() == 'f2.default', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f3.in')[0] - assert tgt.get_internal_path() == 'f3.out', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f4.x')[0] - assert tgt.get_internal_path() == 'f4.y', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f5.bar')[0] - assert tgt.get_internal_path() == 'f5.new', tgt.get_internal_path() - tgt = builder(my_env, target = None, source = 'f6.zzz')[0] - assert tgt.get_internal_path() == 'f6.emit', tgt.get_internal_path() - - def test_single_source(self): - """Test Builder with single_source flag set""" - def func(target, source, env): - """create the file""" - with open(str(target[0]), "w"): - pass - if len(source) == 1 and len(target) == 1: - env['CNT'][0] = env['CNT'][0] + 1 - - env = Environment() - infiles = [] - outfiles = [] - for i in range(10): - infiles.append(test.workpath('%d.in' % i)) - outfiles.append(test.workpath('%d.out' % i)) - test.write(infiles[-1], "\n") - builder = SCons.Builder.Builder(action=SCons.Action.Action(func,None), - single_source = 1, suffix='.out') - env['CNT'] = [0] - tgt = builder(env, target=outfiles[0], source=infiles[0])[0] - s = str(tgt) - t = os.path.normcase(test.workpath('0.out')) - assert os.path.normcase(s) == t, s - tgt.prepare() - tgt.build() - assert env['CNT'][0] == 1, env['CNT'][0] - tgt = builder(env, outfiles[1], infiles[1])[0] - s = str(tgt) - t = os.path.normcase(test.workpath('1.out')) - assert os.path.normcase(s) == t, s - tgt.prepare() - tgt.build() - assert env['CNT'][0] == 2 - tgts = builder(env, None, infiles[2:4]) - s = list(map(str, tgts)) - expect = [test.workpath('2.out'), test.workpath('3.out')] - expect = list(map(os.path.normcase, expect)) - assert list(map(os.path.normcase, s)) == expect, s - for t in tgts: t.prepare() - tgts[0].build() - tgts[1].build() - assert env['CNT'][0] == 4 - try: - tgt = builder(env, outfiles[4], infiles[4:6]) - except SCons.Errors.UserError: - pass - else: - assert 0 - try: - # The builder may output more than one target per input file. - tgt = builder(env, outfiles[4:6], infiles[4:6]) - except SCons.Errors.UserError: - pass - else: - assert 0 - - - def test_lists(self): - """Testing handling lists of targets and source""" - def function2(target, source, env, tlist = [outfile, outfile2], **kw): - for t in target: - with open(str(t), 'w') as f: - f.write("function2\n") - for t in tlist: - if t not in list(map(str, target)): - with open(t, 'w') as f: - f.write("function2\n") - return 1 - - env = Environment() - builder = SCons.Builder.Builder(action = function2) - - tgts = builder(env, source=[]) - assert tgts == [], tgts - - tgts = builder(env, target = [outfile, outfile2], source = infile) - for t in tgts: - t.prepare() - try: - tgts[0].build() - except SCons.Errors.BuildError: - pass - c = test.read(outfile, 'r') - assert c == "function2\n", c - c = test.read(outfile2, 'r') - assert c == "function2\n", c - - sub1_out = test.workpath('sub1', 'out') - sub2_out = test.workpath('sub2', 'out') - - def function3(target, source, env, tlist = [sub1_out, sub2_out]): - for t in target: - with open(str(t), 'w') as f: - f.write("function3\n") - for t in tlist: - if t not in list(map(str, target)): - with open(t, 'w') as f: - f.write("function3\n") - return 1 - - builder = SCons.Builder.Builder(action = function3) - tgts = builder(env, target = [sub1_out, sub2_out], source = infile) - for t in tgts: - t.prepare() - try: - tgts[0].build() - except SCons.Errors.BuildError: - pass - c = test.read(sub1_out, 'r') - assert c == "function3\n", c - c = test.read(sub2_out, 'r') - assert c == "function3\n", c - assert os.path.exists(test.workpath('sub1')) - assert os.path.exists(test.workpath('sub2')) - - def test_src_builder(self): - """Testing Builders with src_builder""" - # These used to be MultiStepBuilder objects until we - # eliminated it as a separate class - env = Environment() - builder1 = SCons.Builder.Builder(action='foo', - src_suffix='.bar', - suffix='.foo') - builder2 = SCons.Builder.Builder(action=MyAction('act'), - src_builder = builder1, - src_suffix = '.foo') - - tgt = builder2(env, source=[]) - assert tgt == [], tgt - - sources = ['test.bar', 'test2.foo', 'test3.txt', 'test4'] - tgt = builder2(env, target='baz', source=sources)[0] - s = str(tgt) - assert s == 'baz', s - s = list(map(str, tgt.sources)) - assert s == ['test.foo', 'test2.foo', 'test3.txt', 'test4.foo'], s - s = list(map(str, tgt.sources[0].sources)) - assert s == ['test.bar'], s - - tgt = builder2(env, None, 'aaa.bar')[0] - s = str(tgt) - assert s == 'aaa', s - s = list(map(str, tgt.sources)) - assert s == ['aaa.foo'], s - s = list(map(str, tgt.sources[0].sources)) - assert s == ['aaa.bar'], s - - builder3 = SCons.Builder.Builder(action='bld3') - assert builder3.src_builder is not builder1.src_builder - - builder4 = SCons.Builder.Builder(action='bld4', - src_suffix='.i', - suffix='_wrap.c') - builder5 = SCons.Builder.Builder(action=MyAction('act'), - src_builder=builder4, - suffix='.obj', - src_suffix='.c') - builder6 = SCons.Builder.Builder(action=MyAction('act'), - src_builder=builder5, - suffix='.exe', - src_suffix='.obj') - tgt = builder6(env, 'test', 'test.i')[0] - s = str(tgt) - assert s == 'test.exe', s - s = list(map(str, tgt.sources)) - assert s == ['test_wrap.obj'], s - s = list(map(str, tgt.sources[0].sources)) - assert s == ['test_wrap.c'], s - s = list(map(str, tgt.sources[0].sources[0].sources)) - assert s == ['test.i'], s - - def test_target_scanner(self): - """Testing ability to set target and source scanners through a builder.""" - global instanced - class TestScanner: - pass - tscan = TestScanner() - sscan = TestScanner() - env = Environment() - builder = SCons.Builder.Builder(target_scanner=tscan, - source_scanner=sscan, - action='') - tgt = builder(env, target='foo2', source='bar')[0] - assert tgt.builder.target_scanner == tscan, tgt.builder.target_scanner - assert tgt.builder.source_scanner == sscan, tgt.builder.source_scanner - - builder1 = SCons.Builder.Builder(action='foo', - src_suffix='.bar', - suffix='.foo') - builder2 = SCons.Builder.Builder(action='foo', - src_builder = builder1, - target_scanner = tscan, - source_scanner = tscan) - tgt = builder2(env, target='baz2', source='test.bar test2.foo test3.txt')[0] - assert tgt.builder.target_scanner == tscan, tgt.builder.target_scanner - assert tgt.builder.source_scanner == tscan, tgt.builder.source_scanner - - def test_actual_scanner(self): - """Test usage of actual Scanner objects.""" - - import SCons.Scanner - - def func(self): - pass - - scanner = SCons.Scanner.ScannerBase(func, name='fooscan') - - b1 = SCons.Builder.Builder(action='bld', target_scanner=scanner) - b2 = SCons.Builder.Builder(action='bld', target_scanner=scanner) - b3 = SCons.Builder.Builder(action='bld') - - assert b1 == b2 - assert b1 != b3 - - def test_src_scanner(self): - """Testing ability to set a source file scanner through a builder.""" - class TestScanner: - def key(self, env): - return 'TestScannerkey' - def instance(self, env): - return self - def select(self, node): - return self - name = 'TestScanner' - def __str__(self): - return self.name - - scanner = TestScanner() - builder = SCons.Builder.Builder(action='action') - - # With no scanner specified, source_scanner and - # backup_source_scanner are None. - bar_y = MyNode('bar.y') - env1 = Environment() - tgt = builder(env1, target='foo1.x', source='bar.y')[0] - src = tgt.sources[0] - assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner - assert tgt.builder.source_scanner is None, tgt.builder.source_scanner - assert tgt.get_source_scanner(bar_y) is None, tgt.get_source_scanner(bar_y) - assert not src.has_builder(), src.has_builder() - s = src.get_source_scanner(bar_y) - assert isinstance(s, SCons.Util.Null), repr(s) - - # An Environment that has suffix-specified SCANNERS should - # provide a source scanner to the target. - class EnvTestScanner: - def key(self, env): - return '.y' - def instance(self, env): - return self - name = 'EnvTestScanner' - def __str__(self): - return self.name - def select(self, node): - return self - def path(self, env, dir=None): - return () - def __call__(self, node, env, path): - return [] - env3 = Environment(SCANNERS = [EnvTestScanner()]) - env3.scanner = EnvTestScanner() # test env's version of SCANNERS - tgt = builder(env3, target='foo2.x', source='bar.y')[0] - src = tgt.sources[0] - assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner - assert not tgt.builder.source_scanner, tgt.builder.source_scanner - assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y) - assert str(tgt.get_source_scanner(bar_y)) == 'EnvTestScanner', tgt.get_source_scanner(bar_y) - assert not src.has_builder(), src.has_builder() - s = src.get_source_scanner(bar_y) - assert isinstance(s, SCons.Util.Null), repr(s) - - # Can't simply specify the scanner as a builder argument; it's - # global to all invocations of this builder. - tgt = builder(env3, target='foo3.x', source='bar.y', source_scanner = scanner)[0] - src = tgt.sources[0] - assert tgt.builder.target_scanner != scanner, tgt.builder.target_scanner - assert not tgt.builder.source_scanner, tgt.builder.source_scanner - assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y) - assert str(tgt.get_source_scanner(bar_y)) == 'EnvTestScanner', tgt.get_source_scanner(bar_y) - assert not src.has_builder(), src.has_builder() - s = src.get_source_scanner(bar_y) - assert isinstance(s, SCons.Util.Null), s - - # Now use a builder that actually has scanners and ensure that - # the target is set accordingly (using the specified scanner - # instead of the Environment's scanner) - builder = SCons.Builder.Builder(action='action', - source_scanner=scanner, - target_scanner=scanner) - tgt = builder(env3, target='foo4.x', source='bar.y')[0] - src = tgt.sources[0] - assert tgt.builder.target_scanner == scanner, tgt.builder.target_scanner - assert tgt.builder.source_scanner, tgt.builder.source_scanner - assert tgt.builder.source_scanner == scanner, tgt.builder.source_scanner - assert str(tgt.builder.source_scanner) == 'TestScanner', str(tgt.builder.source_scanner) - assert tgt.get_source_scanner(bar_y), tgt.get_source_scanner(bar_y) - assert tgt.get_source_scanner(bar_y) == scanner, tgt.get_source_scanner(bar_y) - assert str(tgt.get_source_scanner(bar_y)) == 'TestScanner', tgt.get_source_scanner(bar_y) - assert not src.has_builder(), src.has_builder() - s = src.get_source_scanner(bar_y) - assert isinstance(s, SCons.Util.Null), s - - - - def test_Builder_API(self): - """Test Builder interface. - - Some of this is tested elsewhere in this file, but this is a - quick collection of common operations on builders with various - forms of component specifications.""" - - builder = SCons.Builder.Builder() - env = Environment(BUILDERS={'Bld':builder}) - - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == '', r - r = builder.get_suffix(env) - assert r == '', r - r = builder.get_src_suffix(env) - assert r == '', r - r = builder.src_suffixes(env) - assert r == [], r - - # src_suffix can be a single string or a list of strings - # src_suffixes() caches its return value, so we use a new - # Builder each time we do any of these tests - - bld = SCons.Builder.Builder() - env = Environment(BUILDERS={'Bld':bld}) - - bld.set_src_suffix('.foo') - r = bld.get_src_suffix(env) - assert r == '.foo', r - r = bld.src_suffixes(env) - assert r == ['.foo'], r - - bld = SCons.Builder.Builder() - env = Environment(BUILDERS={'Bld':bld}) - - bld.set_src_suffix(['.foo', '.bar']) - r = bld.get_src_suffix(env) - assert r == '.foo', r - r = bld.src_suffixes(env) - assert r == ['.foo', '.bar'], r - - bld = SCons.Builder.Builder() - env = Environment(BUILDERS={'Bld':bld}) - - bld.set_src_suffix(['.bar', '.foo']) - r = bld.get_src_suffix(env) - assert r == '.bar', r - r = sorted(bld.src_suffixes(env)) - assert r == ['.bar', '.foo'], r - - # adjust_suffix normalizes the suffix, adding a `.' if needed - - r = builder.adjust_suffix('.foo') - assert r == '.foo', r - r = builder.adjust_suffix('_foo') - assert r == '_foo', r - r = builder.adjust_suffix('$foo') - assert r == '$foo', r - r = builder.adjust_suffix('foo') - assert r == '.foo', r - r = builder.adjust_suffix('f._$oo') - assert r == '.f._$oo', r - - # prefix and suffix can be one of: - # 1. a string (adjusted and env variables substituted), - # 2. a function (passed (env,sources), returns suffix string) - # 3. a dict of src_suffix:suffix settings, key==None is - # default suffix (special case of #2, so adjust_suffix - # not applied) - - builder = SCons.Builder.Builder(prefix='lib', suffix='foo') - - env = Environment(BUILDERS={'Bld':builder}) - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'lib', r - r = builder.get_suffix(env) - assert r == '.foo', r - - mkpref = lambda env,sources: 'Lib' - mksuff = lambda env,sources: '.Foo' - builder = SCons.Builder.Builder(prefix=mkpref, suffix=mksuff) - - env = Environment(BUILDERS={'Bld':builder}) - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'Lib', r - r = builder.get_suffix(env) - assert r == '.Foo', r - - builder = SCons.Builder.Builder(prefix='$PREF', suffix='$SUFF') - - env = Environment(BUILDERS={'Bld':builder},PREF="LIB",SUFF=".FOO") - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'LIB', r - r = builder.get_suffix(env) - assert r == '.FOO', r - - builder = SCons.Builder.Builder(prefix={None:'A_', - '.C':'E_'}, - suffix={None:'.B', - '.C':'.D'}) - - env = Environment(BUILDERS={'Bld':builder}) - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'A_', r - r = builder.get_suffix(env) - assert r == '.B', r - r = builder.get_prefix(env, [MyNode('X.C')]) - assert r == 'E_', r - r = builder.get_suffix(env, [MyNode('X.C')]) - assert r == '.D', r - - builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={}) - env = Environment(BUILDERS={'Bld':builder}) - - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'A_', r - r = builder.get_suffix(env) - assert r is None, r - r = builder.get_src_suffix(env) - assert r == '', r - r = builder.src_suffixes(env) - assert r == [], r - - # Builder actions can be a string, a list, or a dictionary - # whose keys are the source suffix. The add_action() - # specifies a new source suffix/action binding. - - builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={}) - env = Environment(BUILDERS={'Bld':builder}) - builder.add_action('.src_sfx1', 'FOO') - - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'A_', r - r = builder.get_suffix(env) - assert r is None, r - r = builder.get_suffix(env, [MyNode('X.src_sfx1')]) - assert r is None, r - r = builder.get_src_suffix(env) - assert r == '.src_sfx1', r - r = builder.src_suffixes(env) - assert r == ['.src_sfx1'], r - - builder = SCons.Builder.Builder(prefix='A_', suffix={}, action={}) - env = Environment(BUILDERS={'Bld':builder}) - builder.add_action('.src_sfx1', 'FOO') - builder.add_action('.src_sfx2', 'BAR') - - r = builder.get_name(env) - assert r == 'Bld', r - r = builder.get_prefix(env) - assert r == 'A_', r - r = builder.get_suffix(env) - assert r is None, r - r = builder.get_src_suffix(env) - assert r == '.src_sfx1', r - r = sorted(builder.src_suffixes(env)) - assert r == ['.src_sfx1', '.src_sfx2'], r - - - def test_Builder_Args(self): - """Testing passing extra args to a builder.""" - def buildFunc(target, source, env, s=self): - s.foo=env['foo'] - s.bar=env['bar'] - assert env['CC'] == 'mycc' - - env=Environment(CC='cc') - - builder = SCons.Builder.Builder(action=buildFunc) - tgt = builder(env, target='foo', source='bar', foo=1, bar=2, CC='mycc')[0] - tgt.build() - assert self.foo == 1, self.foo - assert self.bar == 2, self.bar - - def test_emitter(self): - """Test emitter functions.""" - def emit(target, source, env): - foo = env.get('foo', 0) - bar = env.get('bar', 0) - for t in target: - assert isinstance(t, MyNode) - assert t.has_builder() - for s in source: - assert isinstance(s, MyNode) - if foo: - target.append("bar%d"%foo) - if bar: - source.append("baz") - return ( target, source ) - - env = Environment() - builder = SCons.Builder.Builder(action='foo', - emitter=emit, - target_factory=MyNode, - source_factory=MyNode) - tgt = builder(env, target='foo2', source='bar')[0] - assert str(tgt) == 'foo2', str(tgt) - assert str(tgt.sources[0]) == 'bar', str(tgt.sources[0]) - - tgt = builder(env, target='foo3', source='bar', foo=1) - assert len(tgt) == 2, len(tgt) - assert 'foo3' in list(map(str, tgt)), list(map(str, tgt)) - assert 'bar1' in list(map(str, tgt)), list(map(str, tgt)) - - tgt = builder(env, target='foo4', source='bar', bar=1)[0] - assert str(tgt) == 'foo4', str(tgt) - assert len(tgt.sources) == 2, len(tgt.sources) - assert 'baz' in list(map(str, tgt.sources)), list(map(str, tgt.sources)) - assert 'bar' in list(map(str, tgt.sources)), list(map(str, tgt.sources)) - - env2=Environment(FOO=emit) - builder2=SCons.Builder.Builder(action='foo', - emitter="$FOO", - target_factory=MyNode, - source_factory=MyNode) - - builder2a=SCons.Builder.Builder(action='foo', - emitter="$FOO", - target_factory=MyNode, - source_factory=MyNode) - - assert builder2 == builder2a, repr(builder2.__dict__) + "\n" + repr(builder2a.__dict__) - - tgt = builder2(env2, target='foo5', source='bar')[0] - assert str(tgt) == 'foo5', str(tgt) - assert str(tgt.sources[0]) == 'bar', str(tgt.sources[0]) - - tgt = builder2(env2, target='foo6', source='bar', foo=2) - assert len(tgt) == 2, len(tgt) - assert 'foo6' in list(map(str, tgt)), list(map(str, tgt)) - assert 'bar2' in list(map(str, tgt)), list(map(str, tgt)) - - tgt = builder2(env2, target='foo7', source='bar', bar=1)[0] - assert str(tgt) == 'foo7', str(tgt) - assert len(tgt.sources) == 2, len(tgt.sources) - assert 'baz' in list(map(str, tgt.sources)), list(map(str, tgt.sources)) - assert 'bar' in list(map(str, tgt.sources)), list(map(str, tgt.sources)) - - def test_emitter_preserve_builder(self): - """Test an emitter not overwriting a newly-set builder""" - env = Environment() - - new_builder = SCons.Builder.Builder(action='new') - node = MyNode('foo8') - new_node = MyNode('foo8.new') - - def emit(target, source, env, nb=new_builder, nn=new_node): - for t in target: - t.builder = nb - return [nn], source - - builder=SCons.Builder.Builder(action='foo', - emitter=emit, - target_factory=MyNode, - source_factory=MyNode) - tgt = builder(env, target=node, source='bar')[0] - assert tgt is new_node, tgt - assert tgt.builder is builder, tgt.builder - assert node.builder is new_builder, node.builder - - def test_emitter_suffix_map(self): - """Test mapping file suffixes to emitter functions""" - env = Environment() - - def emit4a(target, source, env): - source = list(map(str, source)) - target = ['emit4a-' + x[:-3] for x in source] - return (target, source) - def emit4b(target, source, env): - source = list(map(str, source)) - target = ['emit4b-' + x[:-3] for x in source] - return (target, source) - - builder = SCons.Builder.Builder(action='foo', - emitter={'.4a':emit4a, - '.4b':emit4b}, - target_factory=MyNode, - source_factory=MyNode) - tgt = builder(env, None, source='aaa.4a')[0] - assert str(tgt) == 'emit4a-aaa', str(tgt) - tgt = builder(env, None, source='bbb.4b')[0] - assert str(tgt) == 'emit4b-bbb', str(tgt) - tgt = builder(env, None, source='ccc.4c')[0] - assert str(tgt) == 'ccc', str(tgt) - - def emit4c(target, source, env): - source = list(map(str, source)) - target = ['emit4c-' + x[:-3] for x in source] - return (target, source) - - builder.add_emitter('.4c', emit4c) - tgt = builder(env, None, source='ccc.4c')[0] - assert str(tgt) == 'emit4c-ccc', str(tgt) - - def test_emitter_function_list(self): - """Test lists of emitter functions""" - env = Environment() - - def emit1a(target, source, env): - source = list(map(str, source)) - target = target + ['emit1a-' + x[:-2] for x in source] - return (target, source) - def emit1b(target, source, env): - source = list(map(str, source)) - target = target + ['emit1b-' + x[:-2] for x in source] - return (target, source) - builder1 = SCons.Builder.Builder(action='foo', - emitter=[emit1a, emit1b], - node_factory=MyNode) - - tgts = builder1(env, target='target-1', source='aaa.1') - tgts = list(map(str, tgts)) - assert tgts == ['target-1', 'emit1a-aaa', 'emit1b-aaa'], tgts - - # Test a list of emitter functions through the environment. - def emit2a(target, source, env): - source = list(map(str, source)) - target = target + ['emit2a-' + x[:-2] for x in source] - return (target, source) - def emit2b(target, source, env): - source = list(map(str, source)) - target = target + ['emit2b-' + x[:-2] for x in source] - return (target, source) - builder2 = SCons.Builder.Builder(action='foo', - emitter='$EMITTERLIST', - node_factory=MyNode) - - env = Environment(EMITTERLIST = [emit2a, emit2b]) - - tgts = builder2(env, target='target-2', source='aaa.2') - tgts = list(map(str, tgts)) - assert tgts == ['target-2', 'emit2a-aaa', 'emit2b-aaa'], tgts - - def test_emitter_TARGET_SOURCE(self): - """Test use of $TARGET and $SOURCE in emitter results""" - - env = SCons.Environment.Environment() - - def emit(target, source, env): - return (target + ['${SOURCE}.s1', '${TARGET}.t1'], - source + ['${TARGET}.t2', '${SOURCE}.s2']) - - builder = SCons.Builder.Builder(action='foo', - emitter = emit, - node_factory = MyNode) - - targets = builder(env, target = 'TTT', source ='SSS') - sources = targets[0].sources - targets = list(map(str, targets)) - sources = list(map(str, sources)) - assert targets == ['TTT', 'SSS.s1', 'TTT.t1'], targets - assert sources == ['SSS', 'TTT.t2', 'SSS.s2'], targets - - def test_no_target(self): - """Test deducing the target from the source.""" - - env = Environment() - b = SCons.Builder.Builder(action='foo', suffix='.o') - - tgt = b(env, None, 'aaa')[0] - assert str(tgt) == 'aaa.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'aaa', list(map(str, tgt.sources)) - - tgt = b(env, None, 'bbb.c')[0] - assert str(tgt) == 'bbb.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'bbb.c', list(map(str, tgt.sources)) - - tgt = b(env, None, 'ccc.x.c')[0] - assert str(tgt) == 'ccc.x.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'ccc.x.c', list(map(str, tgt.sources)) - - tgt = b(env, None, ['d0.c', 'd1.c'])[0] - assert str(tgt) == 'd0.o', str(tgt) - assert len(tgt.sources) == 2, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'd0.c', list(map(str, tgt.sources)) - assert str(tgt.sources[1]) == 'd1.c', list(map(str, tgt.sources)) - - tgt = b(env, target = None, source='eee')[0] - assert str(tgt) == 'eee.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'eee', list(map(str, tgt.sources)) - - tgt = b(env, target = None, source='fff.c')[0] - assert str(tgt) == 'fff.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'fff.c', list(map(str, tgt.sources)) - - tgt = b(env, target = None, source='ggg.x.c')[0] - assert str(tgt) == 'ggg.x.o', str(tgt) - assert len(tgt.sources) == 1, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'ggg.x.c', list(map(str, tgt.sources)) - - tgt = b(env, target = None, source=['h0.c', 'h1.c'])[0] - assert str(tgt) == 'h0.o', str(tgt) - assert len(tgt.sources) == 2, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'h0.c', list(map(str, tgt.sources)) - assert str(tgt.sources[1]) == 'h1.c', list(map(str, tgt.sources)) - - w = b(env, target='i0.w', source=['i0.x'])[0] - y = b(env, target='i1.y', source=['i1.z'])[0] - tgt = b(env, None, source=[w, y])[0] - assert str(tgt) == 'i0.o', str(tgt) - assert len(tgt.sources) == 2, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'i0.w', list(map(str, tgt.sources)) - assert str(tgt.sources[1]) == 'i1.y', list(map(str, tgt.sources)) - - def test_get_name(self): - """Test getting name of builder. - - Each type of builder should return its environment-specific - name when queried appropriately. """ - - b1 = SCons.Builder.Builder(action='foo', suffix='.o') - b2 = SCons.Builder.Builder(action='foo', suffix='.c') - b3 = SCons.Builder.Builder(action='bar', src_suffix = '.foo', - src_builder = b1) - b4 = SCons.Builder.Builder(action={}) - b5 = SCons.Builder.Builder(action='foo', name='builder5') - b6 = SCons.Builder.Builder(action='foo') - assert isinstance(b4, SCons.Builder.CompositeBuilder) - assert isinstance(b4.action, SCons.Action.CommandGeneratorAction) - - env = Environment(BUILDERS={'bldr1': b1, - 'bldr2': b2, - 'bldr3': b3, - 'bldr4': b4}) - env2 = Environment(BUILDERS={'B1': b1, - 'B2': b2, - 'B3': b3, - 'B4': b4}) - # With no name, get_name will return the class. Allow - # for caching... - b6_names = [ - 'SCons.Builder.BuilderBase', - "", - 'SCons.Memoize.BuilderBase', - "", - ] - - assert b1.get_name(env) == 'bldr1', b1.get_name(env) - assert b2.get_name(env) == 'bldr2', b2.get_name(env) - assert b3.get_name(env) == 'bldr3', b3.get_name(env) - assert b4.get_name(env) == 'bldr4', b4.get_name(env) - assert b5.get_name(env) == 'builder5', b5.get_name(env) - assert b6.get_name(env) in b6_names, b6.get_name(env) - - assert b1.get_name(env2) == 'B1', b1.get_name(env2) - assert b2.get_name(env2) == 'B2', b2.get_name(env2) - assert b3.get_name(env2) == 'B3', b3.get_name(env2) - assert b4.get_name(env2) == 'B4', b4.get_name(env2) - assert b5.get_name(env2) == 'builder5', b5.get_name(env2) - assert b6.get_name(env2) in b6_names, b6.get_name(env2) - - assert b5.get_name(None) == 'builder5', b5.get_name(None) - assert b6.get_name(None) in b6_names, b6.get_name(None) - - # This test worked before adding batch builders, but we must now - # be able to disambiguate a CompositeAction into a more specific - # action based on file suffix at call time. Leave this commented - # out (for now) in case this reflects a real-world use case that - # we must accomodate and we want to resurrect this test. - #tgt = b4(env, target = 'moo', source='cow') - #assert tgt[0].builder.get_name(env) == 'bldr4' - -class CompositeBuilderTestCase(unittest.TestCase): - - def setUp(self): - def func_action(target, source, env): - return 0 - - builder = SCons.Builder.Builder(action={ '.foo' : func_action, - '.bar' : func_action}) - - self.func_action = func_action - self.builder = builder - - def test___init__(self): - """Test CompositeBuilder creation""" - env = Environment() - builder = SCons.Builder.Builder(action={}) - - tgt = builder(env, source=[]) - assert tgt == [], tgt - - assert isinstance(builder, SCons.Builder.CompositeBuilder) - assert isinstance(builder.action, SCons.Action.CommandGeneratorAction) - - def test_target_action(self): - """Test CompositeBuilder setting of target builder actions""" - env = Environment() - builder = self.builder - - tgt = builder(env, target='test1', source='test1.foo')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - assert tgt.builder.action is builder.action - - tgt = builder(env, target='test2', source='test1.bar')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - assert tgt.builder.action is builder.action - - def test_multiple_suffix_error(self): - """Test the CompositeBuilder multiple-source-suffix error""" - env = Environment() - builder = self.builder - - flag = 0 - try: - builder(env, target='test3', source=['test2.bar', 'test1.foo'])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder with files of different suffixes." - expect = "While building `['test3']' from `test1.foo': Cannot build multiple sources with different extensions: .bar, .foo" - assert str(err) == expect, err - - def test_source_ext_match(self): - """Test the CompositeBuilder source_ext_match argument""" - env = Environment() - func_action = self.func_action - builder = SCons.Builder.Builder(action={ '.foo' : func_action, - '.bar' : func_action}, - source_ext_match = None) - - tgt = builder(env, target='test3', source=['test2.bar', 'test1.foo'])[0] - tgt.build() - - def test_suffix_variable(self): - """Test CompositeBuilder defining action suffixes through a variable""" - env = Environment(BAR_SUFFIX = '.BAR2', FOO_SUFFIX = '.FOO2') - func_action = self.func_action - builder = SCons.Builder.Builder(action={ '.foo' : func_action, - '.bar' : func_action, - '$BAR_SUFFIX' : func_action, - '$FOO_SUFFIX' : func_action }) - - tgt = builder(env, target='test4', source=['test4.BAR2'])[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - try: - tgt.build() - flag = 1 - except SCons.Errors.UserError as e: - print(e) - flag = 0 - assert flag, "It should be possible to define actions in composite builders using variables." - env['FOO_SUFFIX'] = '.BAR2' - builder.add_action('$NEW_SUFFIX', func_action) - flag = 0 - try: - builder(env, target='test5', source=['test5.BAR2'])[0] - except SCons.Errors.UserError: - flag = 1 - assert flag, "UserError should be thrown when we call a builder with ambigous suffixes." - - def test_src_builder(self): - """Test CompositeBuilder's use of a src_builder""" - env = Environment() - - foo_bld = SCons.Builder.Builder(action = 'a-foo', - src_suffix = '.ina', - suffix = '.foo') - assert isinstance(foo_bld, SCons.Builder.BuilderBase) - builder = SCons.Builder.Builder(action = { '.foo' : 'foo', - '.bar' : 'bar' }, - src_builder = foo_bld) - assert isinstance(builder, SCons.Builder.CompositeBuilder) - assert isinstance(builder.action, SCons.Action.CommandGeneratorAction) - - tgt = builder(env, target='t1', source='t1a.ina t1b.ina')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - - tgt = builder(env, target='t2', source='t2a.foo t2b.ina')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase), tgt.builder.__dict__ - - bar_bld = SCons.Builder.Builder(action = 'a-bar', - src_suffix = '.inb', - suffix = '.bar') - assert isinstance(bar_bld, SCons.Builder.BuilderBase) - builder = SCons.Builder.Builder(action = { '.foo' : 'foo'}, - src_builder = [foo_bld, bar_bld]) - assert isinstance(builder, SCons.Builder.CompositeBuilder) - assert isinstance(builder.action, SCons.Action.CommandGeneratorAction) - - builder.add_action('.bar', 'bar') - - tgt = builder(env, target='t3-foo', source='t3a.foo t3b.ina')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - - tgt = builder(env, target='t3-bar', source='t3a.bar t3b.inb')[0] - assert isinstance(tgt.builder, SCons.Builder.BuilderBase) - - flag = 0 - try: - builder(env, target='t5', source=['test5a.foo', 'test5b.inb'])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder with files of different suffixes." - expect = "While building `['t5']' from `test5b.bar': Cannot build multiple sources with different extensions: .foo, .bar" - assert str(err) == expect, err - - flag = 0 - try: - builder(env, target='t6', source=['test6a.bar', 'test6b.ina'])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder with files of different suffixes." - expect = "While building `['t6']' from `test6b.foo': Cannot build multiple sources with different extensions: .bar, .foo" - assert str(err) == expect, err - - flag = 0 - try: - builder(env, target='t4', source=['test4a.ina', 'test4b.inb'])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder with files of different suffixes." - expect = "While building `['t4']' from `test4b.bar': Cannot build multiple sources with different extensions: .foo, .bar" - assert str(err) == expect, err - - flag = 0 - try: - builder(env, target='t7', source=[env.fs.File('test7')])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder with files of different suffixes." - expect = "While building `['t7']': Cannot deduce file extension from source files: ['test7']" - assert str(err) == expect, err - - flag = 0 - try: - builder(env, target='t8', source=['test8.unknown'])[0] - except SCons.Errors.UserError as e: - flag = 1 - err = e - assert flag, "UserError should be thrown when we call a builder target with an unknown suffix." - expect = "While building `['t8']' from `['test8.unknown']': Don't know how to build from a source file with suffix `.unknown'. Expected a suffix in this list: ['.foo', '.bar']." - assert str(err) == expect, err - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/CacheDirTests.py b/SCSCons/CacheDirTests.py deleted file mode 100644 index c4a0ed7c1..000000000 --- a/SCSCons/CacheDirTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/DefaultsTests.py b/SCSCons/DefaultsTests.py deleted file mode 100644 index 6a7ce9cef..000000000 --- a/SCSCons/DefaultsTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/EnvironmentTests.py b/SCSCons/EnvironmentTests.py deleted file mode 100644 index c505422f9..000000000 --- a/SCSCons/EnvironmentTests.py +++ /dev/null @@ -1,4053 +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 SCons.compat - -import copy -import io -import os -import sys -import unittest -from collections import UserDict as UD, UserList as UL - -import TestCmd - -import SCons.Warnings -from SCons.Environment import ( - Environment, - NoSubstitutionProxy, - OverrideEnvironment, - SubstitutionEnvironment, - is_valid_construction_var, -) -from SCons.Util import CLVar -from SCons.SConsign import current_sconsign_filename - - -def diff_env(env1, env2): - s1 = "env1 = {\n" - s2 = "env2 = {\n" - d = {} - for k in list(env1._dict.keys()) + list(env2._dict.keys()): - d[k] = None - for k in sorted(d.keys()): - if k in env1: - if k in env2: - if env1[k] != env2[k]: - s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n" - s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n" - else: - s1 = s1 + " " + repr(k) + " : " + repr(env1[k]) + "\n" - elif k in env2: - s2 = s2 + " " + repr(k) + " : " + repr(env2[k]) + "\n" - s1 = s1 + "}\n" - s2 = s2 + "}\n" - return s1 + s2 - -def diff_dict(d1, d2): - s1 = "d1 = {\n" - s2 = "d2 = {\n" - d = {} - for k in list(d1.keys()) + list(d2.keys()): - d[k] = None - for k in sorted(d.keys()): - if k in d1: - if k in d2: - if d1[k] != d2[k]: - s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n" - s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n" - else: - s1 = s1 + " " + repr(k) + " : " + repr(d1[k]) + "\n" - elif k in d2: - s2 = s2 + " " + repr(k) + " : " + repr(d2[k]) + "\n" - s1 = s1 + "}\n" - s2 = s2 + "}\n" - return s1 + s2 - -called_it = {} -built_it = {} - -class Builder(SCons.Builder.BuilderBase): - """A dummy Builder class for testing purposes. "Building" - a target is simply setting a value in the dictionary. - """ - def __init__(self, name = None): - self.name = name - - def __call__(self, env, target=None, source=None, **kw): - global called_it - called_it['target'] = target - called_it['source'] = source - called_it.update(kw) - - def execute(self, target = None, **kw): - global built_it - built_it[target] = 1 - - - -scanned_it = {} - -class Scanner: - """A dummy Scanner class for testing purposes. "Scanning" - a target is simply setting a value in the dictionary. - """ - def __init__(self, name, skeys=[]): - self.name = name - self.skeys = skeys - - def __call__(self, filename): - global scanned_it - scanned_it[filename] = 1 - - def __eq__(self, other): - try: - return self.__dict__ == other.__dict__ - except AttributeError: - return False - - def get_skeys(self, env): - return self.skeys - - def __str__(self): - return self.name - - -class DummyNode: - def __init__(self, name): - self.name = name - def __str__(self): - return self.name - def rfile(self): - return self - def get_subst_proxy(self): - return self - -def test_tool( env ): - env['_F77INCFLAGS'] = '${_concat(INCPREFIX, F77PATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}' - -class TestEnvironmentFixture: - def TestEnvironment(self, *args, **kw): - if not kw or 'tools' not in kw: - kw['tools'] = [test_tool] - default_keys = { 'CC' : 'cc', - 'CCFLAGS' : '-DNDEBUG', - 'ENV' : { 'TMP' : '/tmp' } } - for key, value in default_keys.items(): - if key not in kw: - kw[key] = value - if 'BUILDERS' not in kw: - static_obj = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = '.o', - single_source = 1) - kw['BUILDERS'] = {'Object' : static_obj} - static_obj.add_action('.cpp', 'fake action') - - env = Environment(*args, **kw) - return env - -class SubstitutionTestCase(unittest.TestCase): - - def test___init__(self): - """Test initializing a SubstitutionEnvironment.""" - env = SubstitutionEnvironment() - assert '__env__' not in env - - def test___cmp__(self): - """Test comparing SubstitutionEnvironments.""" - env1 = SubstitutionEnvironment(XXX = 'x') - env2 = SubstitutionEnvironment(XXX = 'x') - env3 = SubstitutionEnvironment(XXX = 'xxx') - env4 = SubstitutionEnvironment(XXX = 'x', YYY = 'x') - - assert env1 == env2 - assert env1 != env3 - assert env1 != env4 - - def test___delitem__(self): - """Test deleting a variable from a SubstitutionEnvironment.""" - env1 = SubstitutionEnvironment(XXX = 'x', YYY = 'y') - env2 = SubstitutionEnvironment(XXX = 'x') - del env1['YYY'] - assert env1 == env2 - - def test___getitem__(self): - """Test fetching a variable from a SubstitutionEnvironment.""" - env = SubstitutionEnvironment(XXX = 'x') - assert env['XXX'] == 'x', env['XXX'] - - def test___setitem__(self): - """Test setting a variable in a SubstitutionEnvironment.""" - env1 = SubstitutionEnvironment(XXX = 'x') - env2 = SubstitutionEnvironment(XXX = 'x', YYY = 'y') - env1['YYY'] = 'y' - assert env1 == env2 - - def test_get(self): - """Test the SubstitutionEnvironment get() method.""" - env = SubstitutionEnvironment(XXX = 'x') - assert env.get('XXX') == 'x', env.get('XXX') - assert env.get('YYY') is None, env.get('YYY') - - def test_contains(self): - """Test the SubstitutionEnvironment __contains__() method.""" - env = SubstitutionEnvironment(XXX = 'x') - assert 'XXX' in env - assert 'YYY' not in env - - def test_keys(self): - """Test the SubstitutionEnvironment keys() method.""" - testdata = {'XXX': 'x', 'YYY': 'y'} - env = SubstitutionEnvironment(**testdata) - keys = list(env.keys()) - assert len(keys) == 2, keys - for k in testdata.keys(): - assert k in keys, keys - - def test_values(self): - """Test the SubstitutionEnvironment values() method.""" - testdata = {'XXX': 'x', 'YYY': 'y'} - env = SubstitutionEnvironment(**testdata) - values = list(env.values()) - assert len(values) == 2, values - for v in testdata.values(): - assert v in values, values - - def test_items(self): - """Test the SubstitutionEnvironment items() method.""" - testdata = {'XXX': 'x', 'YYY': 'y'} - env = SubstitutionEnvironment(**testdata) - items = list(env.items()) - assert len(items) == 2, items - for k, v in testdata.items(): - assert (k, v) in items, items - - def test_setdefault(self): - """Test the SubstitutionEnvironment setdefault() method.""" - env = SubstitutionEnvironment(XXX = 'x') - assert env.setdefault('XXX', 'z') == 'x', env['XXX'] - assert env.setdefault('YYY', 'y') == 'y', env['YYY'] - assert 'YYY' in env - - def test_arg2nodes(self): - """Test the arg2nodes method.""" - env = SubstitutionEnvironment() - dict = {} - class X(SCons.Node.Node): - pass - def Factory(name, directory = None, create = 1, dict=dict, X=X): - if name not in dict: - dict[name] = X() - dict[name].name = name - return dict[name] - - nodes = env.arg2nodes("Util.py UtilTests.py", Factory) - assert len(nodes) == 1, nodes - assert isinstance(nodes[0], X) - assert nodes[0].name == "Util.py UtilTests.py", nodes[0].name - - nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory) - assert len(nodes) == 2, nodes - assert isinstance(nodes[0], X) - assert isinstance(nodes[1], X) - assert nodes[0].name == "Util.py", nodes[0].name - assert nodes[1].name == "UtilTests.py", nodes[1].name - - n1 = Factory("Util.py") - nodes = env.arg2nodes([n1, "UtilTests.py"], Factory) - assert len(nodes) == 2, nodes - assert isinstance(nodes[0], X) - assert isinstance(nodes[1], X) - assert nodes[0].name == "Util.py", nodes[0].name - assert nodes[1].name == "UtilTests.py", nodes[1].name - - class SConsNode(SCons.Node.Node): - pass - nodes = env.arg2nodes(SConsNode()) - assert len(nodes) == 1, nodes - assert isinstance(nodes[0], SConsNode), nodes[0] - - class OtherNode: - pass - nodes = env.arg2nodes(OtherNode()) - assert len(nodes) == 1, nodes - assert isinstance(nodes[0], OtherNode), nodes[0] - - def lookup_a(str, F=Factory): - if str[0] == 'a': - n = F(str) - n.a = 1 - return n - else: - return None - - def lookup_b(str, F=Factory): - if str[0] == 'b': - n = F(str) - n.b = 1 - return n - else: - return None - - env_ll = SubstitutionEnvironment() - env_ll.lookup_list = [lookup_a, lookup_b] - - nodes = env_ll.arg2nodes(['aaa', 'bbb', 'ccc'], Factory) - assert len(nodes) == 3, nodes - - assert nodes[0].name == 'aaa', nodes[0] - assert nodes[0].a == 1, nodes[0] - assert not hasattr(nodes[0], 'b'), nodes[0] - - assert nodes[1].name == 'bbb' - assert not hasattr(nodes[1], 'a'), nodes[1] - assert nodes[1].b == 1, nodes[1] - - assert nodes[2].name == 'ccc' - assert not hasattr(nodes[2], 'a'), nodes[1] - assert not hasattr(nodes[2], 'b'), nodes[1] - - def lookup_bbbb(str, F=Factory): - if str == 'bbbb': - n = F(str) - n.bbbb = 1 - return n - else: - return None - - def lookup_c(str, F=Factory): - if str[0] == 'c': - n = F(str) - n.c = 1 - return n - else: - return None - - nodes = env.arg2nodes(['bbbb', 'ccc'], Factory, - [lookup_c, lookup_bbbb, lookup_b]) - assert len(nodes) == 2, nodes - - assert nodes[0].name == 'bbbb' - assert not hasattr(nodes[0], 'a'), nodes[1] - assert not hasattr(nodes[0], 'b'), nodes[1] - assert nodes[0].bbbb == 1, nodes[1] - assert not hasattr(nodes[0], 'c'), nodes[0] - - assert nodes[1].name == 'ccc' - assert not hasattr(nodes[1], 'a'), nodes[1] - assert not hasattr(nodes[1], 'b'), nodes[1] - assert not hasattr(nodes[1], 'bbbb'), nodes[0] - assert nodes[1].c == 1, nodes[1] - - def test_arg2nodes_target_source(self): - """Test the arg2nodes method with target= and source= keywords - """ - targets = [DummyNode('t1'), DummyNode('t2')] - sources = [DummyNode('s1'), DummyNode('s2')] - env = SubstitutionEnvironment() - nodes = env.arg2nodes(['${TARGET}-a', - '${SOURCE}-b', - '${TARGETS[1]}-c', - '${SOURCES[1]}-d'], - DummyNode, - target=targets, - source=sources) - names = [n.name for n in nodes] - assert names == ['t1-a', 's1-b', 't2-c', 's2-d'], names - - def test_gvars(self): - """Test the base class gvars() method""" - env = SubstitutionEnvironment() - gvars = env.gvars() - assert gvars == {}, gvars - - def test_lvars(self): - """Test the base class lvars() method""" - env = SubstitutionEnvironment() - lvars = env.lvars() - assert lvars == {}, lvars - - def test_subst(self): - """Test substituting construction variables within strings - - Check various combinations, including recursive expansion - of variables into other variables. - """ - env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') - mystr = env.subst("$AAA ${AAA}A $BBBB $BBB") - assert mystr == "a aA b", mystr - - # Changed the tests below to reflect a bug fix in - # subst() - env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') - mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB") - assert mystr == "b bA bB b", mystr - - env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') - mystr = env.subst("$AAA ${AAA}A ${AAA}B $BBB") - assert mystr == "c cA cB c", mystr - - # Lists: - env = SubstitutionEnvironment(AAA = ['a', 'aa', 'aaa']) - mystr = env.subst("$AAA") - assert mystr == "a aa aaa", mystr - - # Tuples: - env = SubstitutionEnvironment(AAA = ('a', 'aa', 'aaa')) - mystr = env.subst("$AAA") - assert mystr == "a aa aaa", mystr - - t1 = DummyNode('t1') - t2 = DummyNode('t2') - s1 = DummyNode('s1') - s2 = DummyNode('s2') - - env = SubstitutionEnvironment(AAA = 'aaa') - s = env.subst('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2]) - assert s == "aaa t1 s1 s2", s - s = env.subst('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2]) - assert s == "aaa t1 t2 s1", s - - # Test callables in the SubstitutionEnvironment - def foo(target, source, env, for_signature): - assert str(target) == 't', target - assert str(source) == 's', source - return env["FOO"] - - env = SubstitutionEnvironment(BAR=foo, FOO='baz') - t = DummyNode('t') - s = DummyNode('s') - - subst = env.subst('test $BAR', target=t, source=s) - assert subst == 'test baz', subst - - # Test not calling callables in the SubstitutionEnvironment - if 0: - # This will take some serious surgery to subst() and - # subst_list(), so just leave these tests out until we can - # do that. - def bar(arg): - pass - - env = SubstitutionEnvironment(BAR=bar, FOO='$BAR') - - subst = env.subst('$BAR', call=None) - assert subst is bar, subst - - subst = env.subst('$FOO', call=None) - assert subst is bar, subst - - def test_subst_kw(self): - """Test substituting construction variables within dictionaries""" - env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') - kw = env.subst_kw({'$AAA' : 'aaa', 'bbb' : '$BBB'}) - assert len(kw) == 2, kw - assert kw['a'] == 'aaa', kw['a'] - assert kw['bbb'] == 'b', kw['bbb'] - - def test_subst_list(self): - """Test substituting construction variables in command lists - """ - env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') - l = env.subst_list("$AAA ${AAA}A $BBBB $BBB") - assert l == [["a", "aA", "b"]], l - - # Changed the tests below to reflect a bug fix in - # subst() - env = SubstitutionEnvironment(AAA = '$BBB', BBB = 'b', BBBA = 'foo') - l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB") - assert l == [["b", "bA", "bB", "b"]], l - - env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = 'c') - l = env.subst_list("$AAA ${AAA}A ${AAA}B $BBB") - assert l == [["c", "cA", "cB", "c"]], l - - env = SubstitutionEnvironment(AAA = '$BBB', BBB = '$CCC', CCC = [ 'a', 'b\nc' ]) - lst = env.subst_list([ "$AAA", "B $CCC" ]) - assert lst == [[ "a", "b"], ["c", "B a", "b"], ["c"]], lst - - t1 = DummyNode('t1') - t2 = DummyNode('t2') - s1 = DummyNode('s1') - s2 = DummyNode('s2') - - env = SubstitutionEnvironment(AAA = 'aaa') - s = env.subst_list('$AAA $TARGET $SOURCES', target=[t1, t2], source=[s1, s2]) - assert s == [["aaa", "t1", "s1", "s2"]], s - s = env.subst_list('$AAA $TARGETS $SOURCE', target=[t1, t2], source=[s1, s2]) - assert s == [["aaa", "t1", "t2", "s1"]], s - - # Test callables in the SubstitutionEnvironment - def foo(target, source, env, for_signature): - assert str(target) == 't', target - assert str(source) == 's', source - return env["FOO"] - - env = SubstitutionEnvironment(BAR=foo, FOO='baz') - t = DummyNode('t') - s = DummyNode('s') - - lst = env.subst_list('test $BAR', target=t, source=s) - assert lst == [['test', 'baz']], lst - - # Test not calling callables in the SubstitutionEnvironment - if 0: - # This will take some serious surgery to subst() and - # subst_list(), so just leave these tests out until we can - # do that. - def bar(arg): - pass - - env = SubstitutionEnvironment(BAR=bar, FOO='$BAR') - - subst = env.subst_list('$BAR', call=None) - assert subst is bar, subst - - subst = env.subst_list('$FOO', call=None) - assert subst is bar, subst - - def test_subst_path(self): - """Test substituting a path list - """ - class MyProxy: - def __init__(self, val): - self.val = val - def get(self): - return self.val + '-proxy' - - class MyNode: - def __init__(self, val): - self.val = val - def get_subst_proxy(self): - return self - def __str__(self): - return self.val - - class MyObj: - def get(self): - return self - - env = SubstitutionEnvironment(FOO='foo', - BAR='bar', - LIST=['one', 'two'], - PROXY=MyProxy('my1')) - - r = env.subst_path('$FOO') - assert r == ['foo'], r - - r = env.subst_path(['$FOO', 'xxx', '$BAR']) - assert r == ['foo', 'xxx', 'bar'], r - - r = env.subst_path(['$FOO', '$LIST', '$BAR']) - assert list(map(str, r)) == ['foo', 'one two', 'bar'], r - - r = env.subst_path(['$FOO', '$TARGET', '$SOURCE', '$BAR']) - assert r == ['foo', '', '', 'bar'], r - - r = env.subst_path(['$FOO', '$TARGET', '$BAR'], target=MyNode('ttt')) - assert list(map(str, r)) == ['foo', 'ttt', 'bar'], r - - r = env.subst_path(['$FOO', '$SOURCE', '$BAR'], source=MyNode('sss')) - assert list(map(str, r)) == ['foo', 'sss', 'bar'], r - - n = MyObj() - - r = env.subst_path(['$PROXY', MyProxy('my2'), n]) - assert r == ['my1-proxy', 'my2-proxy', n], r - - class StringableObj: - def __init__(self, s): - self.s = s - def __str__(self): - return self.s - - env = SubstitutionEnvironment(FOO=StringableObj("foo"), - BAR=StringableObj("bar")) - - r = env.subst_path([ "${FOO}/bar", "${BAR}/baz" ]) - assert r == [ "foo/bar", "bar/baz" ], r - - r = env.subst_path([ "bar/${FOO}", "baz/${BAR}" ]) - assert r == [ "bar/foo", "baz/bar" ], r - - r = env.subst_path([ "bar/${FOO}/bar", "baz/${BAR}/baz" ]) - assert r == [ "bar/foo/bar", "baz/bar/baz" ], r - - def test_subst_target_source(self): - """Test the base environment subst_target_source() method""" - env = SubstitutionEnvironment(AAA = 'a', BBB = 'b') - mystr = env.subst_target_source("$AAA ${AAA}A $BBBB $BBB") - assert mystr == "a aA b", mystr - - def test_backtick(self): - """Test the backtick() method for capturing command output""" - env = SubstitutionEnvironment() - - test = TestCmd.TestCmd(workdir = '') - test.write('stdout.py', """\ -import sys -sys.stdout.write('this came from stdout.py\\n') -sys.exit(0) -""") - test.write('stderr.py', """\ -import sys -sys.stderr.write('this came from stderr.py\\n') -sys.exit(0) -""") - test.write('fail.py', """\ -import sys -sys.exit(1) -""") - test.write('echo.py', """\ -import os, sys -sys.stdout.write(os.environ['ECHO'] + '\\n') -sys.exit(0) -""") - - save_stderr = sys.stderr - - python = '"' + sys.executable + '"' - - try: - sys.stderr = io.StringIO() - cmd = '%s %s' % (python, test.workpath('stdout.py')) - output = env.backtick(cmd) - errout = sys.stderr.getvalue() - assert output == 'this came from stdout.py\n', output - assert errout == '', errout - - sys.stderr = io.StringIO() - cmd = '%s %s' % (python, test.workpath('stderr.py')) - output = env.backtick(cmd) - errout = sys.stderr.getvalue() - assert output == '', output - assert errout == 'this came from stderr.py\n', errout - - sys.stderr = io.StringIO() - cmd = '%s %s' % (python, test.workpath('fail.py')) - try: - env.backtick(cmd) - except OSError as e: - assert str(e) == "'%s' exited 1" % cmd, str(e) - else: - self.fail("did not catch expected OSError") - - sys.stderr = io.StringIO() - cmd = '%s %s' % (python, test.workpath('echo.py')) - env['ENV'] = os.environ.copy() - env['ENV']['ECHO'] = 'this came from ECHO' - output = env.backtick(cmd) - errout = sys.stderr.getvalue() - assert output == 'this came from ECHO\n', output - assert errout == '', errout - - finally: - sys.stderr = save_stderr - - def test_AddMethod(self): - """Test the AddMethod() method""" - env = SubstitutionEnvironment(FOO = 'foo') - - def func(self): - return 'func-' + self['FOO'] - - assert not hasattr(env, 'func') - env.AddMethod(func) - r = env.func() - assert r == 'func-foo', r - - assert not hasattr(env, 'bar') - env.AddMethod(func, 'bar') - r = env.bar() - assert r == 'func-foo', r - - def func2(self, arg=''): - return 'func2-' + self['FOO'] + arg - - env.AddMethod(func2) - r = env.func2() - assert r == 'func2-foo', r - r = env.func2('-xxx') - assert r == 'func2-foo-xxx', r - - env.AddMethod(func2, 'func') - r = env.func() - assert r == 'func2-foo', r - r = env.func('-yyy') - assert r == 'func2-foo-yyy', r - - # Test that clones of clones correctly re-bind added methods. - env1 = Environment(FOO = '1') - env1.AddMethod(func2) - env2 = env1.Clone(FOO = '2') - env3 = env2.Clone(FOO = '3') - env4 = env3.Clone(FOO = '4') - r = env1.func2() - assert r == 'func2-1', r - r = env2.func2() - assert r == 'func2-2', r - r = env3.func2() - assert r == 'func2-3', r - r = env4.func2() - assert r == 'func2-4', r - - # Test that clones don't re-bind an attribute that the user set. - env1 = Environment(FOO = '1') - env1.AddMethod(func2) - def replace_func2(): - return 'replace_func2' - env1.func2 = replace_func2 - env2 = env1.Clone(FOO = '2') - r = env2.func2() - assert r == 'replace_func2', r - - # Test clone rebinding if using global AddMethod. - env1 = Environment(FOO='1') - SCons.Util.AddMethod(env1, func2) - r = env1.func2() - assert r == 'func2-1', r - r = env1.func2('-xxx') - assert r == 'func2-1-xxx', r - env2 = env1.Clone(FOO='2') - r = env2.func2() - assert r == 'func2-2', r - - - def test_Override(self): - """Test overriding construction variables""" - env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4) - assert env['ONE'] == 1, env['ONE'] - assert env['TWO'] == 2, env['TWO'] - assert env['THREE'] == 3, env['THREE'] - assert env['FOUR'] == 4, env['FOUR'] - - env2 = env.Override({'TWO' : '10', - 'THREE' :'x $THREE y', - 'FOUR' : ['x', '$FOUR', 'y']}) - assert env2['ONE'] == 1, env2['ONE'] - assert env2['TWO'] == '10', env2['TWO'] - assert env2['THREE'] == 'x 3 y', env2['THREE'] - assert env2['FOUR'] == ['x', 4, 'y'], env2['FOUR'] - - assert env['ONE'] == 1, env['ONE'] - assert env['TWO'] == 2, env['TWO'] - assert env['THREE'] == 3, env['THREE'] - assert env['FOUR'] == 4, env['FOUR'] - - env2.Replace(ONE = "won") - assert env2['ONE'] == "won", env2['ONE'] - assert env['ONE'] == 1, env['ONE'] - - def test_ParseFlags(self): - """Test the ParseFlags() method - """ - env = SubstitutionEnvironment() - - empty = { - 'ASFLAGS' : [], - 'CFLAGS' : [], - 'CCFLAGS' : [], - 'CXXFLAGS' : [], - 'CPPDEFINES' : [], - 'CPPFLAGS' : [], - 'CPPPATH' : [], - 'FRAMEWORKPATH' : [], - 'FRAMEWORKS' : [], - 'LIBPATH' : [], - 'LIBS' : [], - 'LINKFLAGS' : [], - 'RPATH' : [], - } - - d = env.ParseFlags(None) - assert d == empty, d - - d = env.ParseFlags('') - assert d == empty, d - - d = env.ParseFlags([]) - assert d == empty, d - - s = ( - "-I/usr/include/fum -I bar -X " - '-I"C:\\Program Files\\ASCEND\\include" ' - "-L/usr/fax -L foo -lxxx -l yyy " - '-L"C:\\Program Files\\ASCEND" -lascend ' - "-Wa,-as -Wl,-link " - "-Wl,-rpath=rpath1 " - "-Wl,-R,rpath2 " - "-Wl,-Rrpath3 " - "-Wp,-cpp " - "-std=c99 " - "-std=c++0x " - "-framework Carbon " - "-frameworkdir=fwd1 " - "-Ffwd2 " - "-F fwd3 " - "-dylib_file foo-dylib " - "-pthread " - "-fmerge-all-constants " - "-fopenmp " - "-mno-cygwin -mwindows " - "-arch i386 -isysroot /tmp " - "-iquote /usr/include/foo1 " - "-isystem /usr/include/foo2 " - "-idirafter /usr/include/foo3 " - "-imacros /usr/include/foo4 " - "--param l1-cache-size=32 --param l2-cache-size=6144 " - "+DD64 " - "-DFOO -DBAR=value -D BAZ " - ) - - d = env.ParseFlags(s) - - assert d['ASFLAGS'] == ['-as'], d['ASFLAGS'] - assert d['CFLAGS'] == ['-std=c99'] - assert d['CCFLAGS'] == ['-X', '-Wa,-as', - '-pthread', '-fmerge-all-constants', - '-fopenmp', '-mno-cygwin', - ('-arch', 'i386'), ('-isysroot', '/tmp'), - ('-iquote', '/usr/include/foo1'), - ('-isystem', '/usr/include/foo2'), - ('-idirafter', '/usr/include/foo3'), - ('-imacros', env.fs.File('/usr/include/foo4')), - ('--param', 'l1-cache-size=32'), ('--param', 'l2-cache-size=6144'), - '+DD64'], repr(d['CCFLAGS']) - assert d['CXXFLAGS'] == ['-std=c++0x'], repr(d['CXXFLAGS']) - assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES'] - assert d['CPPFLAGS'] == ['-Wp,-cpp'], d['CPPFLAGS'] - assert d['CPPPATH'] == ['/usr/include/fum', - 'bar', - 'C:\\Program Files\\ASCEND\\include'], d['CPPPATH'] - assert d['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], d['FRAMEWORKPATH'] - assert d['FRAMEWORKS'] == ['Carbon'], d['FRAMEWORKS'] - assert d['LIBPATH'] == ['/usr/fax', - 'foo', - 'C:\\Program Files\\ASCEND'], d['LIBPATH'] - LIBS = list(map(str, d['LIBS'])) - assert LIBS == ['xxx', 'yyy', 'ascend'], (d['LIBS'], LIBS) - assert d['LINKFLAGS'] == ['-Wl,-link', - '-dylib_file', 'foo-dylib', - '-pthread', '-fmerge-all-constants', '-fopenmp', - '-mno-cygwin', '-mwindows', - ('-arch', 'i386'), - ('-isysroot', '/tmp'), - '+DD64'], repr(d['LINKFLAGS']) - assert d['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], d['RPATH'] - - - def test_MergeFlags(self): - """Test the MergeFlags() method.""" - - env = SubstitutionEnvironment() - # does not set flag if value empty - env.MergeFlags('') - assert 'CCFLAGS' not in env, env['CCFLAGS'] - # merges value if flag did not exist - env.MergeFlags('-X') - assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] - - # avoid SubstitutionEnvironment for these, has no .Append method, - # which is needed for unique=False test - env = Environment(CCFLAGS="") - # merge with existing but empty flag - env.MergeFlags('-X') - assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] - # default Unique=True enforces no dupes - env.MergeFlags('-X') - assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] - # Unique=False allows dupes - env.MergeFlags('-X', unique=False) - assert env['CCFLAGS'] == ['-X', '-X'], env['CCFLAGS'] - - # merge from a dict with list values - env = SubstitutionEnvironment(B='b') - env.MergeFlags({'A': ['aaa'], 'B': ['bb', 'bbb']}) - assert env['A'] == ['aaa'], env['A'] - assert env['B'] == ['b', 'bb', 'bbb'], env['B'] - - # issue #2961: merge from a dict with string values - env = SubstitutionEnvironment(B='b') - env.MergeFlags({'A': 'aaa', 'B': 'bb bbb'}) - assert env['A'] == ['aaa'], env['A'] - assert env['B'] == ['b', 'bb', 'bbb'], env['B'] - - # issue #3665: if merging dict which is a compound object - # (i.e. value can be lists, etc.), the value object should not - # be modified. per the issue, this happened if key not in env. - env = SubstitutionEnvironment() - try: - del env['CFLAGS'] # just to be sure - except KeyError: - pass - flags = {'CFLAGS': ['-pipe', '-pthread', '-g']} - import copy - - saveflags = copy.deepcopy(flags) - env.MergeFlags(flags) - self.assertEqual(flags, saveflags) - - -class BaseTestCase(unittest.TestCase,TestEnvironmentFixture): - - reserved_variables = [ - 'CHANGED_SOURCES', - 'CHANGED_TARGETS', - 'SOURCE', - 'SOURCES', - 'TARGET', - 'TARGETS', - 'UNCHANGED_SOURCES', - 'UNCHANGED_TARGETS', - ] - - def test___init__(self): - """Test construction Environment creation - - Create two with identical arguments and check that - they compare the same. - """ - env1 = self.TestEnvironment(XXX = 'x', YYY = 'y') - env2 = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env1 == env2, diff_env(env1, env2) - - assert '__env__' not in env1 - assert '__env__' not in env2 - - def test_variables(self): - """Test that variables only get applied once.""" - class FakeOptions: - def __init__(self, key, val): - self.calls = 0 - self.key = key - self.val = val - def keys(self): - return [self.key] - def Update(self, env): - env[self.key] = self.val - self.calls = self.calls + 1 - - o = FakeOptions('AAA', 'fake_opt') - env = Environment(variables=o, AAA='keyword_arg') - assert o.calls == 1, o.calls - assert env['AAA'] == 'fake_opt', env['AAA'] - - def test_get(self): - """Test the get() method.""" - env = self.TestEnvironment(aaa = 'AAA') - - x = env.get('aaa') - assert x == 'AAA', x - x = env.get('aaa', 'XXX') - assert x == 'AAA', x - x = env.get('bbb') - assert x is None, x - x = env.get('bbb', 'XXX') - assert x == 'XXX', x - - def test_Builder_calls(self): - """Test Builder calls through different environments - """ - global called_it - - b1 = Builder() - b2 = Builder() - - env = Environment() - env.Replace(BUILDERS = { 'builder1' : b1, - 'builder2' : b2 }) - called_it = {} - env.builder1('in1') - assert called_it['target'] is None, called_it - assert called_it['source'] == ['in1'], called_it - - called_it = {} - env.builder2(source = 'in2', xyzzy = 1) - assert called_it['target'] is None, called_it - assert called_it['source'] == ['in2'], called_it - assert called_it['xyzzy'] == 1, called_it - - called_it = {} - env.builder1(foo = 'bar') - assert called_it['foo'] == 'bar', called_it - assert called_it['target'] is None, called_it - assert called_it['source'] is None, called_it - - def test_BuilderWrapper_attributes(self): - """Test getting and setting of BuilderWrapper attributes.""" - b1 = Builder() - b2 = Builder() - e1 = Environment() - e2 = Environment() - - e1.Replace(BUILDERS={'b': b1}) - bw = e1.b - - assert bw.env is e1 - bw.env = e2 - assert bw.env is e2 - - assert bw.builder is b1 - bw.builder = b2 - assert bw.builder is b2 - - self.assertRaises(AttributeError, getattr, bw, 'foobar') - bw.foobar = 42 - assert bw.foobar == 42 - - # This unit test is currently disabled because we don't think the - # underlying method it tests (Environment.BuilderWrapper.execute()) - # is necessary, but we're leaving the code here for now in case - # that's mistaken. - def _DO_NOT_test_Builder_execs(self): - """Test Builder execution through different environments - - One environment is initialized with a single - Builder object, one with a list of a single Builder - object, and one with a list of two Builder objects. - """ - global built_it - - b1 = Builder() - b2 = Builder() - - built_it = {} - env3 = Environment() - env3.Replace(BUILDERS = { 'builder1' : b1, - 'builder2' : b2 }) - env3.builder1.execute(target = 'out1') - env3.builder2.execute(target = 'out2') - env3.builder1.execute(target = 'out3') - assert built_it['out1'] - assert built_it['out2'] - assert built_it['out3'] - - env4 = env3.Clone() - assert env4.builder1.env is env4, "builder1.env (%s) == env3 (%s)?" % ( -env4.builder1.env, env3) - assert env4.builder2.env is env4, "builder2.env (%s) == env3 (%s)?" % ( -env4.builder1.env, env3) - - # Now test BUILDERS as a dictionary. - built_it = {} - env5 = self.TestEnvironment(BUILDERS={ 'foo' : b1 }) - env5['BUILDERS']['bar'] = b2 - env5.foo.execute(target='out1') - env5.bar.execute(target='out2') - assert built_it['out1'] - assert built_it['out2'] - - built_it = {} - env6 = Environment() - env6['BUILDERS'] = { 'foo' : b1, - 'bar' : b2 } - env6.foo.execute(target='out1') - env6.bar.execute(target='out2') - assert built_it['out1'] - assert built_it['out2'] - - - - def test_Scanners(self): - """Test setting SCANNERS in various ways - - One environment is initialized with a single - Scanner object, one with a list of a single Scanner - object, and one with a list of two Scanner objects. - """ - global scanned_it - - s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"]) - s2 = Scanner(name = 'scanner2', skeys = [".m4"]) - s3 = Scanner(name = 'scanner3', skeys = [".m4", ".m5"]) - s4 = Scanner(name = 'scanner4', skeys = [None]) - -# XXX Tests for scanner execution through different environments, -# XXX if we ever want to do that some day -# scanned_it = {} -# env1 = self.TestEnvironment(SCANNERS = s1) -# env1.scanner1(filename = 'out1') -# assert scanned_it['out1'] -# -# scanned_it = {} -# env2 = self.TestEnvironment(SCANNERS = [s1]) -# env1.scanner1(filename = 'out1') -# assert scanned_it['out1'] -# -# scanned_it = {} -# env3 = Environment() -# env3.Replace(SCANNERS = [s1]) -# env3.scanner1(filename = 'out1') -# env3.scanner2(filename = 'out2') -# env3.scanner1(filename = 'out3') -# assert scanned_it['out1'] -# assert scanned_it['out2'] -# assert scanned_it['out3'] - - suffixes = [".c", ".cc", ".cxx", ".m4", ".m5"] - - env = Environment() - try: del env['SCANNERS'] - except KeyError: pass - s = list(map(env.get_scanner, suffixes)) - assert s == [None, None, None, None, None], s - - env = self.TestEnvironment(SCANNERS = []) - s = list(map(env.get_scanner, suffixes)) - assert s == [None, None, None, None, None], s - - env.Replace(SCANNERS = [s1]) - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, None, None], s - - env.Append(SCANNERS = [s2]) - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, s2, None], s - - env.AppendUnique(SCANNERS = [s3]) - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, s2, s3], s - - env = env.Clone(SCANNERS = [s2]) - s = list(map(env.get_scanner, suffixes)) - assert s == [None, None, None, s2, None], s - - env['SCANNERS'] = [s1] - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, None, None], s - - env.PrependUnique(SCANNERS = [s2, s1]) - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, s2, None], s - - env.Prepend(SCANNERS = [s3]) - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, s3, s3], s - - # Verify behavior of case-insensitive suffix matches on Windows. - uc_suffixes = [_.upper() for _ in suffixes] - - env = Environment(SCANNERS = [s1, s2, s3], - PLATFORM = 'linux') - - s = list(map(env.get_scanner, suffixes)) - assert s == [s1, s1, None, s2, s3], s - - s = list(map(env.get_scanner, uc_suffixes)) - assert s == [None, None, None, None, None], s - - env['PLATFORM'] = 'win32' - - s = list(map(env.get_scanner, uc_suffixes)) - assert s == [s1, s1, None, s2, s3], s - - # Verify behavior for a scanner returning None (on Windows - # where we might try to perform case manipulation on None). - env.Replace(SCANNERS = [s4]) - s = list(map(env.get_scanner, suffixes)) - assert s == [None, None, None, None, None], s - - def test_ENV(self): - """Test setting the external ENV in Environments - """ - env = Environment() - assert 'ENV' in env.Dictionary() - - env = self.TestEnvironment(ENV = { 'PATH' : '/foo:/bar' }) - assert env.Dictionary('ENV')['PATH'] == '/foo:/bar' - - def test_ReservedVariables(self): - """Test warning generation when reserved variable names are set""" - - reserved_variables = [ - 'CHANGED_SOURCES', - 'CHANGED_TARGETS', - 'SOURCE', - 'SOURCES', - 'TARGET', - 'TARGETS', - 'UNCHANGED_SOURCES', - 'UNCHANGED_TARGETS', - ] - - warning = SCons.Warnings.ReservedVariableWarning - SCons.Warnings.enableWarningClass(warning) - old = SCons.Warnings.warningAsException(1) - - try: - env4 = Environment() - for kw in self.reserved_variables: - exc_caught = None - try: - env4[kw] = 'xyzzy' - except warning: - exc_caught = 1 - assert exc_caught, "Did not catch ReservedVariableWarning for `%s'" % kw - assert kw not in env4, "`%s' variable was incorrectly set" % kw - finally: - SCons.Warnings.warningAsException(old) - - def test_FutureReservedVariables(self): - """Test warning generation when future reserved variable names are set""" - - future_reserved_variables = [] - - warning = SCons.Warnings.FutureReservedVariableWarning - SCons.Warnings.enableWarningClass(warning) - old = SCons.Warnings.warningAsException(1) - - try: - env4 = Environment() - for kw in future_reserved_variables: - exc_caught = None - try: - env4[kw] = 'xyzzy' - except warning: - exc_caught = 1 - assert exc_caught, "Did not catch FutureReservedVariableWarning for `%s'" % kw - assert kw in env4, "`%s' variable was not set" % kw - finally: - SCons.Warnings.warningAsException(old) - - def test_IllegalVariables(self): - """Test that use of illegal variables raises an exception""" - env = Environment() - def test_it(var, env=env): - exc_caught = None - try: - env[var] = 1 - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch UserError for '%s'" % var - env['aaa'] = 1 - assert env['aaa'] == 1, env['aaa'] - test_it('foo/bar') - test_it('foo.bar') - test_it('foo-bar') - - def test_autogenerate(self): - """Test autogenerating variables in a dictionary.""" - - drive, p = os.path.splitdrive(os.getcwd()) - def normalize_path(path, drive=drive): - if path[0] in '\\/': - path = drive + path - path = os.path.normpath(path) - drive, path = os.path.splitdrive(path) - return drive.lower() + path - - env = self.TestEnvironment(LIBS = [ 'foo', 'bar', 'baz' ], - LIBLINKPREFIX = 'foo', - LIBLINKSUFFIX = 'bar') - - def RDirs(pathlist, fs=env.fs): - return fs.Dir('xx').Rfindalldirs(pathlist) - - env['RDirs'] = RDirs - flags = env.subst_list('$_LIBFLAGS', 1)[0] - assert flags == ['foobar', 'foobar', 'foobazbar'], flags - - blat = env.fs.Dir('blat') - - env.Replace(CPPPATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz') - flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - expect = [ '$(', - normalize_path('foo'), - normalize_path('xx/foobar'), - normalize_path('foo'), - normalize_path('xx/baz/bar'), - normalize_path('foo'), - normalize_path('blatbar'), - '$)', - ] - assert flags == expect, flags - - env.Replace(F77PATH = [ 'foo', '$FOO/bar', blat ], - INCPREFIX = 'foo ', - INCSUFFIX = 'bar', - FOO = 'baz') - flags = env.subst_list('$_F77INCFLAGS', 1)[0] - expect = [ '$(', - normalize_path('foo'), - normalize_path('xx/foobar'), - normalize_path('foo'), - normalize_path('xx/baz/bar'), - normalize_path('foo'), - normalize_path('blatbar'), - '$)', - ] - assert flags == expect, flags - - env.Replace(CPPPATH = '', F77PATH = '', LIBPATH = '') - l = env.subst_list('$_CPPINCFLAGS') - assert l == [[]], l - l = env.subst_list('$_F77INCFLAGS') - assert l == [[]], l - l = env.subst_list('$_LIBDIRFLAGS') - assert l == [[]], l - - env.fs.Repository('/rep1') - env.fs.Repository('/rep2') - env.Replace(CPPPATH = [ 'foo', '/__a__/b', '$FOO/bar', blat], - INCPREFIX = '-I ', - INCSUFFIX = 'XXX', - FOO = 'baz') - flags = env.subst_list('$_CPPINCFLAGS', 1)[0] - expect = [ '$(', - '-I', normalize_path('xx/fooXXX'), - '-I', normalize_path('/rep1/xx/fooXXX'), - '-I', normalize_path('/rep2/xx/fooXXX'), - '-I', normalize_path('/__a__/bXXX'), - '-I', normalize_path('xx/baz/barXXX'), - '-I', normalize_path('/rep1/xx/baz/barXXX'), - '-I', normalize_path('/rep2/xx/baz/barXXX'), - '-I', normalize_path('blatXXX'), - '$)' - ] - def normalize_if_path(arg, np=normalize_path): - if arg not in ('$(','$)','-I'): - return np(str(arg)) - return arg - flags = list(map(normalize_if_path, flags)) - assert flags == expect, flags - - def test_platform(self): - """Test specifying a platform callable when instantiating.""" - class platform: - def __str__(self): return "TestPlatform" - def __call__(self, env): env['XYZZY'] = 777 - - def tool(env): - env['SET_TOOL'] = 'initialized' - assert env['PLATFORM'] == "TestPlatform" - - env = self.TestEnvironment(platform = platform(), tools = [tool]) - assert env['XYZZY'] == 777, env - assert env['PLATFORM'] == "TestPlatform" - assert env['SET_TOOL'] == "initialized" - - def test_Default_PLATFORM(self): - """Test overriding the default PLATFORM variable""" - class platform: - def __str__(self): return "DefaultTestPlatform" - def __call__(self, env): env['XYZZY'] = 888 - - def tool(env): - env['SET_TOOL'] = 'abcde' - assert env['PLATFORM'] == "DefaultTestPlatform" - - import SCons.Defaults - save = SCons.Defaults.ConstructionEnvironment.copy() - try: - import SCons.Defaults - SCons.Defaults.ConstructionEnvironment.update({ - 'PLATFORM' : platform(), - }) - env = self.TestEnvironment(tools = [tool]) - assert env['XYZZY'] == 888, env - assert env['PLATFORM'] == "DefaultTestPlatform" - assert env['SET_TOOL'] == "abcde" - finally: - SCons.Defaults.ConstructionEnvironment = save - - def test_tools(self): - """Test specifying a tool callable when instantiating.""" - def t1(env): - env['TOOL1'] = 111 - def t2(env): - env['TOOL2'] = 222 - def t3(env): - env['AAA'] = env['XYZ'] - def t4(env): - env['TOOL4'] = 444 - env = self.TestEnvironment(tools = [t1, t2, t3], XYZ = 'aaa') - assert env['TOOL1'] == 111, env['TOOL1'] - assert env['TOOL2'] == 222, env - assert env['AAA'] == 'aaa', env - t4(env) - assert env['TOOL4'] == 444, env - - test = TestCmd.TestCmd(workdir = '') - test.write('faketool.py', """\ -def generate(env, **kw): - for k, v in kw.items(): - env[k] = v - -def exists(env): - return True -""") - - env = self.TestEnvironment(tools = [('faketool', {'a':1, 'b':2, 'c':3})], - toolpath = [test.workpath('')]) - assert env['a'] == 1, env['a'] - assert env['b'] == 2, env['b'] - assert env['c'] == 3, env['c'] - - def test_Default_TOOLS(self): - """Test overriding the default TOOLS variable""" - def t5(env): - env['TOOL5'] = 555 - def t6(env): - env['TOOL6'] = 666 - def t7(env): - env['BBB'] = env['XYZ'] - def t8(env): - env['TOOL8'] = 888 - - import SCons.Defaults - save = SCons.Defaults.ConstructionEnvironment.copy() - try: - SCons.Defaults.ConstructionEnvironment.update({ - 'TOOLS' : [t5, t6, t7], - }) - env = Environment(XYZ = 'bbb') - assert env['TOOL5'] == 555, env['TOOL5'] - assert env['TOOL6'] == 666, env - assert env['BBB'] == 'bbb', env - t8(env) - assert env['TOOL8'] == 888, env - finally: - SCons.Defaults.ConstructionEnvironment = save - - def test_null_tools(self): - """Test specifying a tool of None is OK.""" - def t1(env): - env['TOOL1'] = 111 - def t2(env): - env['TOOL2'] = 222 - env = self.TestEnvironment(tools = [t1, None, t2], XYZ = 'aaa') - assert env['TOOL1'] == 111, env['TOOL1'] - assert env['TOOL2'] == 222, env - assert env['XYZ'] == 'aaa', env - env = self.TestEnvironment(tools = [None], XYZ = 'xyz') - assert env['XYZ'] == 'xyz', env - env = self.TestEnvironment(tools = [t1, '', t2], XYZ = 'ddd') - assert env['TOOL1'] == 111, env['TOOL1'] - assert env['TOOL2'] == 222, env - assert env['XYZ'] == 'ddd', env - - def test_default_copy_cache(self): - copied = False - - def copy2(self, src, dst): - nonlocal copied - copied = True - - save_copy_from_cache = SCons.CacheDir.CacheDir.copy_from_cache - SCons.CacheDir.CacheDir.copy_from_cache = copy2 - - save_copy_to_cache = SCons.CacheDir.CacheDir.copy_to_cache - SCons.CacheDir.CacheDir.copy_to_cache = copy2 - - env = self.TestEnvironment() - - SCons.Environment.default_copy_from_cache(env, 'test.in', 'test.out') - assert copied - - copied = False - SCons.Environment.default_copy_to_cache(env, 'test.in', 'test.out') - assert copied - - SCons.CacheDir.CacheDir.copy_from_cache = save_copy_from_cache - SCons.CacheDir.CacheDir.copy_to_cache = save_copy_to_cache - - def test_concat(self): - """Test _concat()""" - e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b']) - s = e1.subst - x = s("${_concat('', '', '', __env__)}") - assert x == '', x - x = s("${_concat('', [], '', __env__)}") - assert x == '', x - x = s("${_concat(PRE, '', SUF, __env__)}") - assert x == '', x - x = s("${_concat(PRE, STR, SUF, __env__)}") - assert x == 'prea bsuf', x - x = s("${_concat(PRE, LIST, SUF, __env__)}") - assert x == 'preasuf prebsuf', x - x = s("${_concat(PRE, LIST, SUF, __env__,affect_signature=False)}", raw=True) - assert x == '$( preasuf prebsuf $)', x - - - def test_concat_nested(self): - """Test _concat() on a nested substitution strings.""" - e = self.TestEnvironment(PRE='pre', SUF='suf', - L1=['a', 'b'], - L2=['c', 'd'], - L3=['$L2']) - x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)') - assert x == 'preasuf prebsuf', x - e.AppendUnique(L1 = ['$L2']) - x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)') - assert x == 'preasuf prebsuf precsuf predsuf', x - e.AppendUnique(L1 = ['$L3']) - x = e.subst('$( ${_concat(PRE, L1, SUF, __env__)} $)') - assert x == 'preasuf prebsuf precsuf predsuf precsuf predsuf', x - - def test_gvars(self): - """Test the Environment gvars() method""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z') - gvars = env.gvars() - assert gvars['XXX'] == 'x', gvars['XXX'] - assert gvars['YYY'] == 'y', gvars['YYY'] - assert gvars['ZZZ'] == 'z', gvars['ZZZ'] - - def test__update(self): - """Test the _update() method""" - env = self.TestEnvironment(X = 'x', Y = 'y', Z = 'z') - assert env['X'] == 'x', env['X'] - assert env['Y'] == 'y', env['Y'] - assert env['Z'] == 'z', env['Z'] - env._update({'X' : 'xxx', - 'TARGET' : 't', - 'TARGETS' : 'ttt', - 'SOURCE' : 's', - 'SOURCES' : 'sss', - 'Z' : 'zzz'}) - assert env['X'] == 'xxx', env['X'] - assert env['Y'] == 'y', env['Y'] - assert env['Z'] == 'zzz', env['Z'] - assert env['TARGET'] == 't', env['TARGET'] - assert env['TARGETS'] == 'ttt', env['TARGETS'] - assert env['SOURCE'] == 's', env['SOURCE'] - assert env['SOURCES'] == 'sss', env['SOURCES'] - - def test_Append(self): - """Test appending to construction variables in an Environment - """ - - b1 = Environment()['BUILDERS'] - b2 = Environment()['BUILDERS'] - assert b1 == b2, diff_dict(b1, b2) - - cases = [ - 'a1', 'A1', 'a1A1', - 'a2', ['A2'], ['a2', 'A2'], - 'a3', UL(['A3']), UL(['a', '3', 'A3']), - 'a4', '', 'a4', - 'a5', [], ['a5'], - 'a6', UL([]), UL(['a', '6']), - 'a7', [''], ['a7', ''], - 'a8', UL(['']), UL(['a', '8', '']), - - ['e1'], 'E1', ['e1', 'E1'], - ['e2'], ['E2'], ['e2', 'E2'], - ['e3'], UL(['E3']), UL(['e3', 'E3']), - ['e4'], '', ['e4'], - ['e5'], [], ['e5'], - ['e6'], UL([]), UL(['e6']), - ['e7'], [''], ['e7', ''], - ['e8'], UL(['']), UL(['e8', '']), - - UL(['i1']), 'I1', UL(['i1', 'I', '1']), - UL(['i2']), ['I2'], UL(['i2', 'I2']), - UL(['i3']), UL(['I3']), UL(['i3', 'I3']), - UL(['i4']), '', UL(['i4']), - UL(['i5']), [], UL(['i5']), - UL(['i6']), UL([]), UL(['i6']), - UL(['i7']), [''], UL(['i7', '']), - UL(['i8']), UL(['']), UL(['i8', '']), - - {'d1':1}, 'D1', {'d1':1, 'D1':None}, - {'d2':1}, ['D2'], {'d2':1, 'D2':None}, - {'d3':1}, UL(['D3']), {'d3':1, 'D3':None}, - {'d4':1}, {'D4':1}, {'d4':1, 'D4':1}, - {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}), - - UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}), - UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}), - UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}), - UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}), - UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}), - - '', 'M1', 'M1', - '', ['M2'], ['M2'], - '', UL(['M3']), UL(['M3']), - '', '', '', - '', [], [], - '', UL([]), UL([]), - '', [''], [''], - '', UL(['']), UL(['']), - - [], 'N1', ['N1'], - [], ['N2'], ['N2'], - [], UL(['N3']), UL(['N3']), - [], '', [], - [], [], [], - [], UL([]), UL([]), - [], [''], [''], - [], UL(['']), UL(['']), - - UL([]), 'O1', ['O', '1'], - UL([]), ['O2'], ['O2'], - UL([]), UL(['O3']), UL(['O3']), - UL([]), '', UL([]), - UL([]), [], UL([]), - UL([]), UL([]), UL([]), - UL([]), [''], UL(['']), - UL([]), UL(['']), UL(['']), - - [''], 'P1', ['', 'P1'], - [''], ['P2'], ['', 'P2'], - [''], UL(['P3']), UL(['', 'P3']), - [''], '', [''], - [''], [], [''], - [''], UL([]), UL(['']), - [''], [''], ['', ''], - [''], UL(['']), UL(['', '']), - - UL(['']), 'Q1', ['', 'Q', '1'], - UL(['']), ['Q2'], ['', 'Q2'], - UL(['']), UL(['Q3']), UL(['', 'Q3']), - UL(['']), '', UL(['']), - UL(['']), [], UL(['']), - UL(['']), UL([]), UL(['']), - UL(['']), [''], UL(['', '']), - UL(['']), UL(['']), UL(['', '']), - ] - - env = Environment() - failed = 0 - while cases: - input, append, expect = cases[:3] - env['XXX'] = copy.copy(input) - try: - env.Append(XXX = append) - except Exception as e: - if failed == 0: print() - print(" %s Append %s exception: %s" % \ - (repr(input), repr(append), e)) - failed = failed + 1 - else: - result = env['XXX'] - if result != expect: - if failed == 0: print() - print(" %s Append %s => %s did not match %s" % \ - (repr(input), repr(append), repr(result), repr(expect))) - failed = failed + 1 - del cases[:3] - assert failed == 0, "%d Append() cases failed" % failed - - env['UL'] = UL(['foo']) - env.Append(UL = 'bar') - result = env['UL'] - assert isinstance(result, UL), repr(result) - assert result == ['foo', 'b', 'a', 'r'], result - - env['CLVar'] = CLVar(['foo']) - env.Append(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['foo', 'bar'], result - - class C: - def __init__(self, name): - self.name = name - def __str__(self): - return self.name - def __eq__(self, other): - raise Exception("should not compare") - - ccc = C('ccc') - - env2 = self.TestEnvironment(CCC1 = ['c1'], CCC2 = ccc) - env2.Append(CCC1 = ccc, CCC2 = ['c2']) - assert env2['CCC1'][0] == 'c1', env2['CCC1'] - assert env2['CCC1'][1] is ccc, env2['CCC1'] - assert env2['CCC2'][0] is ccc, env2['CCC2'] - assert env2['CCC2'][1] == 'c2', env2['CCC2'] - - env3 = self.TestEnvironment(X = {'x1' : 7}) - env3.Append(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10}) - assert env3['X'] == {'x1': 8, 'x2': 9}, env3['X'] - assert env3['Y'] == {'y1': 10}, env3['Y'] - - z1 = Builder() - z2 = Builder() - env4 = self.TestEnvironment(BUILDERS = {'z1' : z1}) - env4.Append(BUILDERS = {'z2' : z2}) - assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS'] - assert hasattr(env4, 'z1') - assert hasattr(env4, 'z2') - - def test_AppendENVPath(self): - """Test appending to an ENV path.""" - env1 = self.TestEnvironment( - ENV={'PATH': r'C:\dir\num\one;C:\dir\num\two'}, - MYENV={'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}, - ) - # have to include the pathsep here so that the test will work on UNIX too. - env1.AppendENVPath('PATH', r'C:\dir\num\two', sep=';') - env1.AppendENVPath('PATH', r'C:\dir\num\three', sep=';') - env1.AppendENVPath('MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';') - assert ( - env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three' - ), env1['ENV']['PATH'] - - env1.AppendENVPath('MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';') - env1.AppendENVPath( - 'MYPATH', r'C:\mydir\num\one', 'MYENV', sep=';', delete_existing=1 - ) - # this should do nothing since delete_existing is 0 - assert ( - env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one' - ), env1['MYENV']['MYPATH'] - - test = TestCmd.TestCmd(workdir='') - test.subdir('sub1', 'sub2') - p = env1['ENV']['PATH'] - env1.AppendENVPath('PATH', '#sub1', sep=';') - env1.AppendENVPath('PATH', env1.fs.Dir('sub2'), sep=';') - assert env1['ENV']['PATH'] == p + ';sub1;sub2', env1['ENV']['PATH'] - - def test_AppendUnique(self): - """Test appending to unique values to construction variables - - This strips values that are already present when lists are - involved.""" - env = self.TestEnvironment(AAA1 = 'a1', - AAA2 = 'a2', - AAA3 = 'a3', - AAA4 = 'a4', - AAA5 = 'a5', - BBB1 = ['b1'], - BBB2 = ['b2'], - BBB3 = ['b3'], - BBB4 = ['b4'], - BBB5 = ['b5'], - CCC1 = '', - CCC2 = '', - DDD1 = ['a', 'b', 'c']) - env['LL1'] = [env.Literal('a literal'), env.Literal('b literal')] - env['LL2'] = [env.Literal('c literal'), env.Literal('b literal')] - env.AppendUnique(AAA1 = 'a1', - AAA2 = ['a2'], - AAA3 = ['a3', 'b', 'c', 'c', 'b', 'a3'], # ignore dups - AAA4 = 'a4.new', - AAA5 = ['a5.new'], - BBB1 = 'b1', - BBB2 = ['b2'], - BBB3 = ['b3', 'c', 'd', 'c', 'b3'], - BBB4 = 'b4.new', - BBB5 = ['b5.new'], - CCC1 = 'c1', - CCC2 = ['c2'], - DDD1 = 'b', - LL1 = env.Literal('a literal'), - LL2 = env.Literal('a literal')) - - assert env['AAA1'] == 'a1a1', env['AAA1'] - assert env['AAA2'] == ['a2'], env['AAA2'] - assert env['AAA3'] == ['a3', 'b', 'c'], env['AAA3'] - assert env['AAA4'] == 'a4a4.new', env['AAA4'] - assert env['AAA5'] == ['a5', 'a5.new'], env['AAA5'] - assert env['BBB1'] == ['b1'], env['BBB1'] - assert env['BBB2'] == ['b2'], env['BBB2'] - assert env['BBB3'] == ['b3', 'c', 'd'], env['BBB3'] - assert env['BBB4'] == ['b4', 'b4.new'], env['BBB4'] - assert env['BBB5'] == ['b5', 'b5.new'], env['BBB5'] - assert env['CCC1'] == 'c1', env['CCC1'] - assert env['CCC2'] == ['c2'], env['CCC2'] - assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1'] - assert env['LL1'] == [env.Literal('a literal'), env.Literal('b literal')], env['LL1'] - assert env['LL2'] == [env.Literal('c literal'), env.Literal('b literal'), env.Literal('a literal')], [str(x) for x in env['LL2']] - - env.AppendUnique(DDD1 = 'b', delete_existing=1) - assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # b moves to end - env.AppendUnique(DDD1 = ['a','b'], delete_existing=1) - assert env['DDD1'] == ['c', 'a', 'b'], env['DDD1'] # a & b move to end - env.AppendUnique(DDD1 = ['e','f', 'e'], delete_existing=1) - assert env['DDD1'] == ['c', 'a', 'b', 'f', 'e'], env['DDD1'] # add last - - env['CLVar'] = CLVar([]) - env.AppendUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar'], result - - env['CLVar'] = CLVar(['abc']) - env.AppendUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['abc', 'bar'], result - - env['CLVar'] = CLVar(['bar']) - env.AppendUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar'], result - - def test_Clone(self): - """Test construction environment cloning. - - The clone should compare equal if there are no overrides. - Update the clone independently afterwards and check that - the original remains intact (that is, no dangling - references point to objects in the copied environment). - Clone the original with some construction variable - updates and check that the original remains intact - and the copy has the updated values. - """ - env1 = self.TestEnvironment(XXX='x', YYY='y') - env2 = env1.Clone() - env1copy = env1.Clone() - assert env1copy == env1 - assert env2 == env1 - env2.Replace(YYY = 'yyy') - assert env1 != env2 - assert env1 == env1copy - - env3 = env1.Clone(XXX='x3', ZZZ='z3') - assert env3 != env1 - assert env3.Dictionary('XXX') == 'x3' - assert env1.Dictionary('XXX') == 'x' - assert env3.Dictionary('YYY') == 'y' - assert env3.Dictionary('ZZZ') == 'z3' - assert env1 == env1copy - - # Ensure that lists and dictionaries are deep copied, but not instances - class TestA: - pass - - env1 = self.TestEnvironment(XXX=TestA(), YYY=[1, 2, 3], ZZZ={1: 2, 3: 4}) - env2 = env1.Clone() - env2.Dictionary('YYY').append(4) - env2.Dictionary('ZZZ')[5] = 6 - assert env1.Dictionary('XXX') is env2.Dictionary('XXX') - assert 4 in env2.Dictionary('YYY') - assert 4 not in env1.Dictionary('YYY') - assert 5 in env2.Dictionary('ZZZ') - assert 5 not in env1.Dictionary('ZZZ') - - # - env1 = self.TestEnvironment(BUILDERS={'b1': Builder()}) - assert hasattr(env1, 'b1'), "env1.b1 was not set" - assert env1.b1.object == env1, "b1.object doesn't point to env1" - env2 = env1.Clone(BUILDERS = {'b2' : Builder()}) - assert env2 != env1 - assert hasattr(env1, 'b1'), "b1 was mistakenly cleared from env1" - assert env1.b1.object == env1, "b1.object was changed" - assert not hasattr(env2, 'b1'), "b1 was not cleared from env2" - assert hasattr(env2, 'b2'), "env2.b2 was not set" - assert env2.b2.object == env2, "b2.object doesn't point to env2" - - # Ensure that specifying new tools in a copied environment works. - def foo(env): env['FOO'] = 1 - def bar(env): env['BAR'] = 2 - def baz(env): env['BAZ'] = 3 - env1 = self.TestEnvironment(tools=[foo]) - env2 = env1.Clone() - env3 = env1.Clone(tools=[bar, baz]) - - assert env1.get('FOO') == 1 - assert env1.get('BAR') is None - assert env1.get('BAZ') is None - assert env2.get('FOO') == 1 - assert env2.get('BAR') is None - assert env2.get('BAZ') is None - assert env3.get('FOO') == 1 - assert env3.get('BAR') == 2 - assert env3.get('BAZ') == 3 - - # Ensure that recursive variable substitution when copying - # environments works properly. - env1 = self.TestEnvironment(CCFLAGS = '-DFOO', XYZ = '-DXYZ') - env2 = env1.Clone(CCFLAGS = '$CCFLAGS -DBAR', - XYZ = ['-DABC', 'x $XYZ y', '-DDEF']) - x = env2.get('CCFLAGS') - assert x == '-DFOO -DBAR', x - x = env2.get('XYZ') - assert x == ['-DABC', 'x -DXYZ y', '-DDEF'], x - - # Ensure that special properties of a class don't get - # lost on copying. - env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2')) - x = env1.get('FLAGS') - assert x == ['flag1', 'flag2'], x - env2 = env1.Clone() - env2.Append(FLAGS = 'flag3 flag4') - x = env2.get('FLAGS') - assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x - x = env1.get('FLAGS') - assert x == ['flag1', 'flag2'], x - - # Ensure that appending directly to a copied CLVar - # doesn't modify the original. - env1 = self.TestEnvironment(FLAGS = CLVar('flag1 flag2')) - x = env1.get('FLAGS') - assert x == ['flag1', 'flag2'], x - env2 = env1.Clone() - env2['FLAGS'] += ['flag3', 'flag4'] - x = env2.get('FLAGS') - assert x == ['flag1', 'flag2', 'flag3', 'flag4'], x - x = env1.get('FLAGS') - assert x == ['flag1', 'flag2'], x - - # Test that the environment stores the toolpath and - # re-uses it for copies. - test = TestCmd.TestCmd(workdir = '') - - test.write('xxx.py', """\ -def exists(env): - return True -def generate(env): - env['XXX'] = 'one' -""") - - test.write('yyy.py', """\ -def exists(env): - return True -def generate(env): - env['YYY'] = 'two' -""") - - env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')]) - assert env['XXX'] == 'one', env['XXX'] - env = env.Clone(tools=['yyy']) - assert env['YYY'] == 'two', env['YYY'] - - - # Test that - real_value = [4] - - def my_tool(env, rv=real_value): - assert env['KEY_THAT_I_WANT'] == rv[0] - env['KEY_THAT_I_WANT'] = rv[0] + 1 - - env = self.TestEnvironment() - - real_value[0] = 5 - env = env.Clone(KEY_THAT_I_WANT=5, tools=[my_tool]) - assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT'] - - real_value[0] = 6 - env = env.Clone(KEY_THAT_I_WANT=6, tools=[my_tool]) - assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT'] - - # test for pull request #150 - env = self.TestEnvironment() - env._dict.pop('BUILDERS') - assert ('BUILDERS' in env) is False - env2 = env.Clone() - - def test_Detect(self): - """Test Detect()ing tools""" - test = TestCmd.TestCmd(workdir = '') - test.subdir('sub1', 'sub2') - sub1 = test.workpath('sub1') - sub2 = test.workpath('sub2') - - if sys.platform == 'win32': - test.write(['sub1', 'xxx'], "sub1/xxx\n") - test.write(['sub2', 'xxx'], "sub2/xxx\n") - - env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) - - x = env.Detect('xxx.exe') - assert x is None, x - - test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n") - - env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) - - x = env.Detect('xxx.exe') - assert x == 'xxx.exe', x - - test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n") - - x = env.Detect('xxx.exe') - assert x == 'xxx.exe', x - - else: - test.write(['sub1', 'xxx.exe'], "sub1/xxx.exe\n") - test.write(['sub2', 'xxx.exe'], "sub2/xxx.exe\n") - - env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) - - x = env.Detect('xxx.exe') - assert x is None, x - - sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') - os.chmod(sub2_xxx_exe, 0o755) - - env = self.TestEnvironment(ENV = { 'PATH' : [sub1, sub2] }) - - x = env.Detect('xxx.exe') - assert x == 'xxx.exe', x - - sub1_xxx_exe = test.workpath('sub1', 'xxx.exe') - os.chmod(sub1_xxx_exe, 0o755) - - x = env.Detect('xxx.exe') - assert x == 'xxx.exe', x - - env = self.TestEnvironment(ENV = { 'PATH' : [] }) - x = env.Detect('xxx.exe') - assert x is None, x - - def test_Dictionary(self): - """Test retrieval of known construction variables - - Fetch them from the Dictionary and check for well-known - defaults that get inserted. - """ - env = self.TestEnvironment(XXX = 'x', YYY = 'y', ZZZ = 'z') - assert env.Dictionary('XXX') == 'x' - assert env.Dictionary('YYY') == 'y' - assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z'] - xxx, zzz = env.Dictionary('XXX', 'ZZZ') - assert xxx == 'x' - assert zzz == 'z' - assert 'BUILDERS' in env.Dictionary() - assert 'CC' in env.Dictionary() - assert 'CCFLAGS' in env.Dictionary() - assert 'ENV' in env.Dictionary() - - assert env['XXX'] == 'x' - env['XXX'] = 'foo' - assert env.Dictionary('XXX') == 'foo' - del env['XXX'] - assert 'XXX' not in env.Dictionary() - - def test_FindIxes(self): - """Test FindIxes()""" - env = self.TestEnvironment(LIBPREFIX='lib', - LIBSUFFIX='.a', - SHLIBPREFIX='lib', - SHLIBSUFFIX='.so', - PREFIX='pre', - SUFFIX='post') - - paths = [os.path.join('dir', 'libfoo.a'), - os.path.join('dir', 'libfoo.so')] - - assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX') - assert paths[1] == env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX') - assert None is env.FindIxes(paths, 'PREFIX', 'POST') - - paths = ['libfoo.a', 'prefoopost'] - - assert paths[0] == env.FindIxes(paths, 'LIBPREFIX', 'LIBSUFFIX') - assert None is env.FindIxes(paths, 'SHLIBPREFIX', 'SHLIBSUFFIX') - assert paths[1] == env.FindIxes(paths, 'PREFIX', 'SUFFIX') - - def test_ParseConfig(self): - """Test the ParseConfig() method""" - env = self.TestEnvironment(COMMAND='command', - ASFLAGS='assembler', - CCFLAGS=[''], - CPPDEFINES=[], - CPPFLAGS=[''], - CPPPATH='string', - FRAMEWORKPATH=[], - FRAMEWORKS=[], - LIBPATH=['list'], - LIBS='', - LINKFLAGS=[''], - RPATH=[]) - - orig_backtick = env.backtick - class my_backtick: - def __init__(self, save_command, output): - self.save_command = save_command - self.output = output - def __call__(self, command): - self.save_command.append(command) - return self.output - - try: - save_command = [] - env.backtick = my_backtick(save_command, - "-I/usr/include/fum -I bar -X\n" + \ - "-L/usr/fax -L foo -lxxx -l yyy " + \ - "-Wa,-as -Wl,-link " + \ - "-Wl,-rpath=rpath1 " + \ - "-Wl,-R,rpath2 " + \ - "-Wl,-Rrpath3 " + \ - "-Wp,-cpp abc " + \ - "-framework Carbon " + \ - "-frameworkdir=fwd1 " + \ - "-Ffwd2 " + \ - "-F fwd3 " + \ - "-pthread " + \ - "-fmerge-all-constants " + \ - "-mno-cygwin -mwindows " + \ - "-arch i386 -isysroot /tmp " + \ - "-iquote /usr/include/foo1 " + \ - "-isystem /usr/include/foo2 " + \ - "-idirafter /usr/include/foo3 " + \ - "+DD64 " + \ - "-DFOO -DBAR=value") - env.ParseConfig("fake $COMMAND") - assert save_command == ['fake command'], save_command - assert env['ASFLAGS'] == ['assembler', '-as'], env['ASFLAGS'] - assert env['CCFLAGS'] == ['', '-X', '-Wa,-as', - '-pthread', '-fmerge-all-constants', '-mno-cygwin', - ('-arch', 'i386'), ('-isysroot', '/tmp'), - ('-iquote', '/usr/include/foo1'), - ('-isystem', '/usr/include/foo2'), - ('-idirafter', '/usr/include/foo3'), - '+DD64'], env['CCFLAGS'] - assert env['CPPDEFINES'] == ['FOO', ['BAR', 'value']], env['CPPDEFINES'] - assert env['CPPFLAGS'] == ['', '-Wp,-cpp'], env['CPPFLAGS'] - assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH'] - assert env['FRAMEWORKPATH'] == ['fwd1', 'fwd2', 'fwd3'], env['FRAMEWORKPATH'] - assert env['FRAMEWORKS'] == ['Carbon'], env['FRAMEWORKS'] - assert env['LIBPATH'] == ['list', '/usr/fax', 'foo'], env['LIBPATH'] - assert env['LIBS'] == ['xxx', 'yyy', env.File('abc')], env['LIBS'] - assert env['LINKFLAGS'] == ['', '-Wl,-link', '-pthread', - '-fmerge-all-constants', - '-mno-cygwin', '-mwindows', - ('-arch', 'i386'), - ('-isysroot', '/tmp'), - '+DD64'], env['LINKFLAGS'] - assert env['RPATH'] == ['rpath1', 'rpath2', 'rpath3'], env['RPATH'] - - env.backtick = my_backtick([], "-Ibar") - env.ParseConfig("fake2") - assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar'], env['CPPPATH'] - env.ParseConfig("fake2", unique=0) - assert env['CPPPATH'] == ['string', '/usr/include/fum', 'bar', 'bar'], env['CPPPATH'] - finally: - env.backtick = orig_backtick - - def test_ParseDepends(self): - """Test the ParseDepends() method""" - test = TestCmd.TestCmd(workdir = '') - - test.write('single', """ -#file: dependency - -f0: \ - d1 \ - d2 \ - d3 \ - -""") - - test.write('multiple', """ -f1: foo -f2 f3: bar -f4: abc def -#file: dependency -f5: \ - ghi \ - jkl \ - mno \ -""") - - env = self.TestEnvironment(SINGLE = test.workpath('single')) - - tlist = [] - dlist = [] - def my_depends(target, dependency, tlist=tlist, dlist=dlist): - tlist.extend(target) - dlist.extend(dependency) - - env.Depends = my_depends - - env.ParseDepends(test.workpath('does_not_exist')) - - exc_caught = None - try: - env.ParseDepends(test.workpath('does_not_exist'), must_exist=1) - except IOError: - exc_caught = 1 - assert exc_caught, "did not catch expected IOError" - - del tlist[:] - del dlist[:] - - env.ParseDepends('$SINGLE', only_one=1) - t = list(map(str, tlist)) - d = list(map(str, dlist)) - assert t == ['f0'], t - assert d == ['d1', 'd2', 'd3'], d - - del tlist[:] - del dlist[:] - - env.ParseDepends(test.workpath('multiple')) - t = list(map(str, tlist)) - d = list(map(str, dlist)) - assert t == ['f1', 'f2', 'f3', 'f4', 'f5'], t - assert d == ['foo', 'bar', 'abc', 'def', 'ghi', 'jkl', 'mno'], d - - exc_caught = None - try: - env.ParseDepends(test.workpath('multiple'), only_one=1) - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - - def test_Platform(self): - """Test the Platform() method""" - env = self.TestEnvironment(WIN32='win32', NONE='no-such-platform') - - exc_caught = None - try: - env.Platform('does_not_exist') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - - exc_caught = None - try: - env.Platform('$NONE') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - - env.Platform('posix') - assert env['OBJSUFFIX'] == '.o', env['OBJSUFFIX'] - - env.Platform('$WIN32') - assert env['OBJSUFFIX'] == '.obj', env['OBJSUFFIX'] - - def test_Prepend(self): - """Test prepending to construction variables in an Environment - """ - cases = [ - 'a1', 'A1', 'A1a1', - 'a2', ['A2'], ['A2', 'a2'], - 'a3', UL(['A3']), UL(['A3', 'a', '3']), - 'a4', '', 'a4', - 'a5', [], ['a5'], - 'a6', UL([]), UL(['a', '6']), - 'a7', [''], ['', 'a7'], - 'a8', UL(['']), UL(['', 'a', '8']), - - ['e1'], 'E1', ['E1', 'e1'], - ['e2'], ['E2'], ['E2', 'e2'], - ['e3'], UL(['E3']), UL(['E3', 'e3']), - ['e4'], '', ['e4'], - ['e5'], [], ['e5'], - ['e6'], UL([]), UL(['e6']), - ['e7'], [''], ['', 'e7'], - ['e8'], UL(['']), UL(['', 'e8']), - - UL(['i1']), 'I1', UL(['I', '1', 'i1']), - UL(['i2']), ['I2'], UL(['I2', 'i2']), - UL(['i3']), UL(['I3']), UL(['I3', 'i3']), - UL(['i4']), '', UL(['i4']), - UL(['i5']), [], UL(['i5']), - UL(['i6']), UL([]), UL(['i6']), - UL(['i7']), [''], UL(['', 'i7']), - UL(['i8']), UL(['']), UL(['', 'i8']), - - {'d1':1}, 'D1', {'d1':1, 'D1':None}, - {'d2':1}, ['D2'], {'d2':1, 'D2':None}, - {'d3':1}, UL(['D3']), {'d3':1, 'D3':None}, - {'d4':1}, {'D4':1}, {'d4':1, 'D4':1}, - {'d5':1}, UD({'D5':1}), UD({'d5':1, 'D5':1}), - - UD({'u1':1}), 'U1', UD({'u1':1, 'U1':None}), - UD({'u2':1}), ['U2'], UD({'u2':1, 'U2':None}), - UD({'u3':1}), UL(['U3']), UD({'u3':1, 'U3':None}), - UD({'u4':1}), {'U4':1}, UD({'u4':1, 'U4':1}), - UD({'u5':1}), UD({'U5':1}), UD({'u5':1, 'U5':1}), - - '', 'M1', 'M1', - '', ['M2'], ['M2'], - '', UL(['M3']), UL(['M3']), - '', '', '', - '', [], [], - '', UL([]), UL([]), - '', [''], [''], - '', UL(['']), UL(['']), - - [], 'N1', ['N1'], - [], ['N2'], ['N2'], - [], UL(['N3']), UL(['N3']), - [], '', [], - [], [], [], - [], UL([]), UL([]), - [], [''], [''], - [], UL(['']), UL(['']), - - UL([]), 'O1', UL(['O', '1']), - UL([]), ['O2'], UL(['O2']), - UL([]), UL(['O3']), UL(['O3']), - UL([]), '', UL([]), - UL([]), [], UL([]), - UL([]), UL([]), UL([]), - UL([]), [''], UL(['']), - UL([]), UL(['']), UL(['']), - - [''], 'P1', ['P1', ''], - [''], ['P2'], ['P2', ''], - [''], UL(['P3']), UL(['P3', '']), - [''], '', [''], - [''], [], [''], - [''], UL([]), UL(['']), - [''], [''], ['', ''], - [''], UL(['']), UL(['', '']), - - UL(['']), 'Q1', UL(['Q', '1', '']), - UL(['']), ['Q2'], UL(['Q2', '']), - UL(['']), UL(['Q3']), UL(['Q3', '']), - UL(['']), '', UL(['']), - UL(['']), [], UL(['']), - UL(['']), UL([]), UL(['']), - UL(['']), [''], UL(['', '']), - UL(['']), UL(['']), UL(['', '']), - ] - - env = Environment() - failed = 0 - while cases: - input, prepend, expect = cases[:3] - env['XXX'] = copy.copy(input) - try: - env.Prepend(XXX = prepend) - except Exception as e: - if failed == 0: print() - print(" %s Prepend %s exception: %s" % \ - (repr(input), repr(prepend), e)) - failed = failed + 1 - else: - result = env['XXX'] - if result != expect: - if failed == 0: print() - print(" %s Prepend %s => %s did not match %s" % \ - (repr(input), repr(prepend), repr(result), repr(expect))) - failed = failed + 1 - del cases[:3] - assert failed == 0, "%d Prepend() cases failed" % failed - - env['UL'] = UL(['foo']) - env.Prepend(UL = 'bar') - result = env['UL'] - assert isinstance(result, UL), repr(result) - assert result == ['b', 'a', 'r', 'foo'], result - - env['CLVar'] = CLVar(['foo']) - env.Prepend(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar', 'foo'], result - - env3 = self.TestEnvironment(X = {'x1' : 7}) - env3.Prepend(X = {'x1' : 8, 'x2' : 9}, Y = {'y1' : 10}) - assert env3['X'] == {'x1': 8, 'x2' : 9}, env3['X'] - assert env3['Y'] == {'y1': 10}, env3['Y'] - - z1 = Builder() - z2 = Builder() - env4 = self.TestEnvironment(BUILDERS = {'z1' : z1}) - env4.Prepend(BUILDERS = {'z2' : z2}) - assert env4['BUILDERS'] == {'z1' : z1, 'z2' : z2}, env4['BUILDERS'] - assert hasattr(env4, 'z1') - assert hasattr(env4, 'z2') - - def test_PrependENVPath(self): - """Test prepending to an ENV path.""" - env1 = self.TestEnvironment( - ENV={'PATH': r'C:\dir\num\one;C:\dir\num\two'}, - MYENV={'MYPATH': r'C:\mydir\num\one;C:\mydir\num\two'}, - ) - # have to include the pathsep here so that the test will work on UNIX too. - env1.PrependENVPath('PATH', r'C:\dir\num\two', sep=';') - env1.PrependENVPath('PATH', r'C:\dir\num\three', sep=';') - assert ( - env1['ENV']['PATH'] == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one' - ), env1['ENV']['PATH'] - - env1.PrependENVPath('MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';') - env1.PrependENVPath('MYPATH', r'C:\mydir\num\one', 'MYENV', sep=';') - # this should do nothing since delete_existing is 0 - env1.PrependENVPath( - 'MYPATH', r'C:\mydir\num\three', 'MYENV', sep=';', delete_existing=0 - ) - assert ( - env1['MYENV']['MYPATH'] == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two' - ), env1['MYENV']['MYPATH'] - - test = TestCmd.TestCmd(workdir='') - test.subdir('sub1', 'sub2') - p = env1['ENV']['PATH'] - env1.PrependENVPath('PATH', '#sub1', sep=';') - env1.PrependENVPath('PATH', env1.fs.Dir('sub2'), sep=';') - assert env1['ENV']['PATH'] == 'sub2;sub1;' + p, env1['ENV']['PATH'] - - def test_PrependUnique(self): - """Test prepending unique values to construction variables - - This strips values that are already present when lists are - involved.""" - env = self.TestEnvironment(AAA1 = 'a1', - AAA2 = 'a2', - AAA3 = 'a3', - AAA4 = 'a4', - AAA5 = 'a5', - BBB1 = ['b1'], - BBB2 = ['b2'], - BBB3 = ['b3'], - BBB4 = ['b4'], - BBB5 = ['b5'], - CCC1 = '', - CCC2 = '', - DDD1 = ['a', 'b', 'c']) - env.PrependUnique(AAA1 = 'a1', - AAA2 = ['a2'], - AAA3 = ['a3', 'b', 'c', 'b', 'a3'], # ignore dups - AAA4 = 'a4.new', - AAA5 = ['a5.new'], - BBB1 = 'b1', - BBB2 = ['b2'], - BBB3 = ['b3', 'b', 'c', 'b3'], - BBB4 = 'b4.new', - BBB5 = ['b5.new'], - CCC1 = 'c1', - CCC2 = ['c2'], - DDD1 = 'b') - assert env['AAA1'] == 'a1a1', env['AAA1'] - assert env['AAA2'] == ['a2'], env['AAA2'] - assert env['AAA3'] == ['c', 'b', 'a3'], env['AAA3'] - assert env['AAA4'] == 'a4.newa4', env['AAA4'] - assert env['AAA5'] == ['a5.new', 'a5'], env['AAA5'] - assert env['BBB1'] == ['b1'], env['BBB1'] - assert env['BBB2'] == ['b2'], env['BBB2'] - assert env['BBB3'] == ['b', 'c', 'b3'], env['BBB3'] - assert env['BBB4'] == ['b4.new', 'b4'], env['BBB4'] - assert env['BBB5'] == ['b5.new', 'b5'], env['BBB5'] - assert env['CCC1'] == 'c1', env['CCC1'] - assert env['CCC2'] == ['c2'], env['CCC2'] - assert env['DDD1'] == ['a', 'b', 'c'], env['DDD1'] - - env.PrependUnique(DDD1 = 'b', delete_existing=1) - assert env['DDD1'] == ['b', 'a', 'c'], env['DDD1'] # b moves to front - env.PrependUnique(DDD1 = ['a','c'], delete_existing=1) - assert env['DDD1'] == ['a', 'c', 'b'], env['DDD1'] # a & c move to front - env.PrependUnique(DDD1 = ['d','e','d'], delete_existing=1) - assert env['DDD1'] == ['d', 'e', 'a', 'c', 'b'], env['DDD1'] - - - env['CLVar'] = CLVar([]) - env.PrependUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar'], result - - env['CLVar'] = CLVar(['abc']) - env.PrependUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar', 'abc'], result - - env['CLVar'] = CLVar(['bar']) - env.PrependUnique(CLVar = 'bar') - result = env['CLVar'] - assert isinstance(result, CLVar), repr(result) - assert result == ['bar'], result - - def test_Replace(self): - """Test replacing construction variables in an Environment - - After creation of the Environment, of course. - """ - env1 = self.TestEnvironment(AAA = 'a', BBB = 'b') - env1.Replace(BBB = 'bbb', CCC = 'ccc') - - env2 = self.TestEnvironment(AAA = 'a', BBB = 'bbb', CCC = 'ccc') - assert env1 == env2, diff_env(env1, env2) - - b1 = Builder() - b2 = Builder() - env3 = self.TestEnvironment(BUILDERS = {'b1' : b1}) - assert hasattr(env3, 'b1'), "b1 was not set" - env3.Replace(BUILDERS = {'b2' : b2}) - assert not hasattr(env3, 'b1'), "b1 was not cleared" - assert hasattr(env3, 'b2'), "b2 was not set" - - def test_ReplaceIxes(self): - """Test ReplaceIxes()""" - env = self.TestEnvironment(LIBPREFIX='lib', - LIBSUFFIX='.a', - SHLIBPREFIX='lib', - SHLIBSUFFIX='.so', - PREFIX='pre', - SUFFIX='post') - - assert 'libfoo.a' == env.ReplaceIxes('libfoo.so', - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'LIBPREFIX', 'LIBSUFFIX') - - assert os.path.join('dir', 'libfoo.a') == env.ReplaceIxes(os.path.join('dir', 'libfoo.so'), - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'LIBPREFIX', 'LIBSUFFIX') - - assert 'libfoo.a' == env.ReplaceIxes('prefoopost', - 'PREFIX', 'SUFFIX', - 'LIBPREFIX', 'LIBSUFFIX') - - def test_SetDefault(self): - """Test the SetDefault method""" - env = self.TestEnvironment(tools = []) - env.SetDefault(V1 = 1) - env.SetDefault(V1 = 2) - assert env['V1'] == 1 - env['V2'] = 2 - env.SetDefault(V2 = 1) - assert env['V2'] == 2 - - def test_Tool(self): - """Test the Tool() method""" - env = self.TestEnvironment(LINK='link', NONE='no-such-tool') - - exc_caught = None - try: - tool = env.Tool('does_not_exist') - except SCons.Errors.UserError: - exc_caught = 1 - else: - assert isinstance(tool, SCons.Tool.Tool) - assert exc_caught, "did not catch expected UserError" - - exc_caught = None - try: - env.Tool('$NONE') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - - # Use a non-existent toolpath directory just to make sure we - # can call Tool() with the keyword argument. - env.Tool('cc', toolpath=['/no/such/directory']) - assert env['CC'] == 'cc', env['CC'] - - env.Tool('$LINK') - assert env['LINK'] == '$SMARTLINK', env['LINK'] - - # Test that the environment stores the toolpath and - # re-uses it for later calls. - test = TestCmd.TestCmd(workdir = '') - - test.write('xxx.py', """\ -def exists(env): - return True -def generate(env): - env['XXX'] = 'one' -""") - - test.write('yyy.py', """\ -def exists(env): - return True -def generate(env): - env['YYY'] = 'two' -""") - - env = self.TestEnvironment(tools=['xxx'], toolpath=[test.workpath('')]) - assert env['XXX'] == 'one', env['XXX'] - env.Tool('yyy') - assert env['YYY'] == 'two', env['YYY'] - - def test_WhereIs(self): - """Test the WhereIs() method""" - test = TestCmd.TestCmd(workdir = '') - - sub1_xxx_exe = test.workpath('sub1', 'xxx.exe') - sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') - sub3_xxx_exe = test.workpath('sub3', 'xxx.exe') - sub4_xxx_exe = test.workpath('sub4', 'xxx.exe') - - test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4') - - if sys.platform != 'win32': - test.write(sub1_xxx_exe, "\n") - - os.mkdir(sub2_xxx_exe) - - test.write(sub3_xxx_exe, "\n") - os.chmod(sub3_xxx_exe, 0o777) - - test.write(sub4_xxx_exe, "\n") - os.chmod(sub4_xxx_exe, 0o777) - - env_path = os.environ['PATH'] - - pathdirs_1234 = [ test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub3'), - test.workpath('sub4'), - ] + env_path.split(os.pathsep) - - pathdirs_1243 = [ test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub4'), - test.workpath('sub3'), - ] + env_path.split(os.pathsep) - - path = os.pathsep.join(pathdirs_1234) - env = self.TestEnvironment(ENV = {'PATH' : path}) - wi = env.WhereIs('') - assert wi is None - wi = env.WhereIs('xxx.exe') - assert wi == test.workpath(sub3_xxx_exe), wi - wi = env.WhereIs('xxx.exe', pathdirs_1243) - assert wi == test.workpath(sub4_xxx_exe), wi - wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243)) - assert wi == test.workpath(sub4_xxx_exe), wi - - wi = env.WhereIs('xxx.exe', reject = sub3_xxx_exe) - assert wi == test.workpath(sub4_xxx_exe), wi - wi = env.WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe) - assert wi == test.workpath(sub4_xxx_exe), wi - - path = os.pathsep.join(pathdirs_1243) - env = self.TestEnvironment(ENV = {'PATH' : path}) - wi = env.WhereIs('xxx.exe') - assert wi == test.workpath(sub4_xxx_exe), wi - wi = env.WhereIs('xxx.exe', pathdirs_1234) - assert wi == test.workpath(sub3_xxx_exe), wi - wi = env.WhereIs('xxx.exe', os.pathsep.join(pathdirs_1234)) - assert wi == test.workpath(sub3_xxx_exe), wi - - if sys.platform == 'win32': - wi = env.WhereIs('xxx', pathext = '') - assert wi is None, wi - - wi = env.WhereIs('xxx', pathext = '.exe') - assert wi == test.workpath(sub4_xxx_exe), wi - - wi = env.WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE') - assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi - - # Test that we return a normalized path even when - # the path contains forward slashes. - forward_slash = test.workpath('') + '/sub3' - wi = env.WhereIs('xxx', path = forward_slash, pathext = '.EXE') - assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi - - - - def test_Action(self): - """Test the Action() method""" - import SCons.Action - - env = self.TestEnvironment(FOO = 'xyzzy') - - a = env.Action('foo') - assert a, a - assert a.__class__ is SCons.Action.CommandAction, a.__class__ - - a = env.Action('$FOO') - assert a, a - assert a.__class__ is SCons.Action.CommandAction, a.__class__ - - a = env.Action('$$FOO') - assert a, a - assert a.__class__ is SCons.Action.LazyAction, a.__class__ - - a = env.Action(['$FOO', 'foo']) - assert a, a - assert a.__class__ is SCons.Action.ListAction, a.__class__ - - def func(arg): - pass - a = env.Action(func) - assert a, a - assert a.__class__ is SCons.Action.FunctionAction, a.__class__ - - def test_AddPostAction(self): - """Test the AddPostAction() method""" - env = self.TestEnvironment(FOO='fff', BAR='bbb') - - n = env.AddPostAction('$FOO', lambda x: x) - assert str(n[0]) == 'fff', n[0] - - n = env.AddPostAction(['ggg', '$BAR'], lambda x: x) - assert str(n[0]) == 'ggg', n[0] - assert str(n[1]) == 'bbb', n[1] - - def test_AddPreAction(self): - """Test the AddPreAction() method""" - env = self.TestEnvironment(FOO='fff', BAR='bbb') - - n = env.AddPreAction('$FOO', lambda x: x) - assert str(n[0]) == 'fff', n[0] - - n = env.AddPreAction(['ggg', '$BAR'], lambda x: x) - assert str(n[0]) == 'ggg', n[0] - assert str(n[1]) == 'bbb', n[1] - - def test_Alias(self): - """Test the Alias() method""" - env = self.TestEnvironment(FOO='kkk', BAR='lll', EA='export_alias') - - tgt = env.Alias('new_alias')[0] - assert str(tgt) == 'new_alias', tgt - assert tgt.sources == [], tgt.sources - assert not hasattr(tgt, 'builder'), tgt.builder - - tgt = env.Alias('None_alias', None)[0] - assert str(tgt) == 'None_alias', tgt - assert tgt.sources == [], tgt.sources - - tgt = env.Alias('empty_list', [])[0] - assert str(tgt) == 'empty_list', tgt - assert tgt.sources == [], tgt.sources - - tgt = env.Alias('export_alias', [ 'asrc1', '$FOO' ])[0] - assert str(tgt) == 'export_alias', tgt - assert len(tgt.sources) == 2, list(map(str, tgt.sources)) - assert str(tgt.sources[0]) == 'asrc1', list(map(str, tgt.sources)) - assert str(tgt.sources[1]) == 'kkk', list(map(str, tgt.sources)) - - n = env.Alias(tgt, source = ['$BAR', 'asrc4'])[0] - assert n is tgt, n - assert len(tgt.sources) == 4, list(map(str, tgt.sources)) - assert str(tgt.sources[2]) == 'lll', list(map(str, tgt.sources)) - assert str(tgt.sources[3]) == 'asrc4', list(map(str, tgt.sources)) - - n = env.Alias('$EA', 'asrc5')[0] - assert n is tgt, n - assert len(tgt.sources) == 5, list(map(str, tgt.sources)) - assert str(tgt.sources[4]) == 'asrc5', list(map(str, tgt.sources)) - - t1, t2 = env.Alias(['t1', 't2'], ['asrc6', 'asrc7']) - assert str(t1) == 't1', t1 - assert str(t2) == 't2', t2 - assert len(t1.sources) == 2, list(map(str, t1.sources)) - assert str(t1.sources[0]) == 'asrc6', list(map(str, t1.sources)) - assert str(t1.sources[1]) == 'asrc7', list(map(str, t1.sources)) - assert len(t2.sources) == 2, list(map(str, t2.sources)) - assert str(t2.sources[0]) == 'asrc6', list(map(str, t2.sources)) - assert str(t2.sources[1]) == 'asrc7', list(map(str, t2.sources)) - - tgt = env.Alias('add', 's1') - tgt = env.Alias('add', 's2')[0] - s = list(map(str, tgt.sources)) - assert s == ['s1', 's2'], s - tgt = env.Alias(tgt, 's3')[0] - s = list(map(str, tgt.sources)) - assert s == ['s1', 's2', 's3'], s - - tgt = env.Alias('act', None, "action1")[0] - s = str(tgt.builder.action) - assert s == "action1", s - tgt = env.Alias('act', None, "action2")[0] - s = str(tgt.builder.action) - assert s == "action1\naction2", s - tgt = env.Alias(tgt, None, "action3")[0] - s = str(tgt.builder.action) - assert s == "action1\naction2\naction3", s - - def test_AlwaysBuild(self): - """Test the AlwaysBuild() method""" - env = self.TestEnvironment(FOO='fff', BAR='bbb') - t = env.AlwaysBuild('a', 'b$FOO', ['c', 'd'], '$BAR', - env.fs.Dir('dir'), env.fs.File('file')) - assert t[0].__class__.__name__ == 'Entry' - assert t[0].get_internal_path() == 'a' - assert t[0].always_build - assert t[1].__class__.__name__ == 'Entry' - assert t[1].get_internal_path() == 'bfff' - assert t[1].always_build - assert t[2].__class__.__name__ == 'Entry' - assert t[2].get_internal_path() == 'c' - assert t[2].always_build - assert t[3].__class__.__name__ == 'Entry' - assert t[3].get_internal_path() == 'd' - assert t[3].always_build - assert t[4].__class__.__name__ == 'Entry' - assert t[4].get_internal_path() == 'bbb' - assert t[4].always_build - assert t[5].__class__.__name__ == 'Dir' - assert t[5].get_internal_path() == 'dir' - assert t[5].always_build - assert t[6].__class__.__name__ == 'File' - assert t[6].get_internal_path() == 'file' - assert t[6].always_build - - def test_VariantDir(self): - """Test the VariantDir() method""" - class MyFS: - def Dir(self, name): - return name - def VariantDir(self, variant_dir, src_dir, duplicate): - self.variant_dir = variant_dir - self.src_dir = src_dir - self.duplicate = duplicate - - env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') - env.fs = MyFS() - - env.VariantDir('build', 'src') - assert env.fs.variant_dir == 'build', env.fs.variant_dir - assert env.fs.src_dir == 'src', env.fs.src_dir - assert env.fs.duplicate == 1, env.fs.duplicate - - env.VariantDir('build${FOO}', '${BAR}src', 0) - assert env.fs.variant_dir == 'buildfff', env.fs.variant_dir - assert env.fs.src_dir == 'bbbsrc', env.fs.src_dir - assert env.fs.duplicate == 0, env.fs.duplicate - - def test_Builder(self): - """Test the Builder() method""" - env = self.TestEnvironment(FOO = 'xyzzy') - - b = env.Builder(action = 'foo') - assert b is not None, b - - b = env.Builder(action = '$FOO') - assert b is not None, b - - b = env.Builder(action = ['$FOO', 'foo']) - assert b is not None, b - - def func(arg): - pass - b = env.Builder(action = func) - assert b is not None, b - b = env.Builder(generator = func) - assert b is not None, b - - def test_CacheDir(self): - """Test the CacheDir() method""" - - test = TestCmd.TestCmd(workdir = '') - - test_cachedir = os.path.join(test.workpath(),'CacheDir') - test_cachedir_config = os.path.join(test_cachedir, 'config') - test_foo = os.path.join(test.workpath(), 'foo-cachedir') - test_foo_config = os.path.join(test_foo,'config') - test_foo1 = os.path.join(test.workpath(), 'foo1-cachedir') - test_foo1_config = os.path.join(test_foo1, 'config') - - env = self.TestEnvironment(CD = test_cachedir) - - env.CacheDir(test_foo) - assert env._CacheDir_path == test_foo, env._CacheDir_path - assert os.path.isfile(test_foo_config), "No file %s"%test_foo_config - - env.CacheDir('$CD') - assert env._CacheDir_path == test_cachedir, env._CacheDir_path - assert os.path.isfile(test_cachedir_config), "No file %s"%test_cachedir_config - - # Now verify that -n/-no_exec wil prevent the CacheDir/config from being created - import SCons.Action - SCons.Action.execute_actions = False - env.CacheDir(test_foo1) - assert env._CacheDir_path == test_foo1, env._CacheDir_path - assert not os.path.isfile(test_foo1_config), "No file %s"%test_foo1_config - - - def test_Clean(self): - """Test the Clean() method""" - env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') - - CT = SCons.Environment.CleanTargets - - foo = env.arg2nodes('foo')[0] - fff = env.arg2nodes('fff')[0] - - t = env.Clean('foo', 'aaa') - l = list(map(str, CT[foo])) - assert l == ['aaa'], l - - t = env.Clean(foo, ['$BAR', 'ccc']) - l = list(map(str, CT[foo])) - assert l == ['aaa', 'bbb', 'ccc'], l - - eee = env.arg2nodes('eee')[0] - - t = env.Clean('$FOO', 'ddd') - l = list(map(str, CT[fff])) - assert l == ['ddd'], l - t = env.Clean(fff, [eee, 'fff']) - l = list(map(str, CT[fff])) - assert l == ['ddd', 'eee', 'fff'], l - - def test_Command(self): - """Test the Command() method.""" - env = Environment() - t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'], - action='buildfoo $target $source')[0] - assert t.builder is not None - assert t.builder.action.__class__.__name__ == 'CommandAction' - assert t.builder.action.cmd_list == 'buildfoo $target $source' - assert 'foo1.in' in [x.get_internal_path() for x in t.sources] - assert 'foo2.in' in [x.get_internal_path() for x in t.sources] - - sub = env.fs.Dir('sub') - t = env.Command(target='bar.out', source='sub', - action='buildbar $target $source')[0] - assert 'sub' in [x.get_internal_path() for x in t.sources] - - def testFunc(env, target, source): - assert str(target[0]) == 'foo.out' - srcs = list(map(str, source)) - assert 'foo1.in' in srcs and 'foo2.in' in srcs, srcs - return 0 - - # avoid spurious output from action - act = env.Action(testFunc, cmdstr=None) - t = env.Command(target='foo.out', source=['foo1.in','foo2.in'], - action=act)[0] - assert t.builder is not None - assert t.builder.action.__class__.__name__ == 'FunctionAction' - t.build() - assert 'foo1.in' in [x.get_internal_path() for x in t.sources] - assert 'foo2.in' in [x.get_internal_path() for x in t.sources] - - x = [] - def test2(baz, x=x): - x.append(baz) - env = self.TestEnvironment(TEST2 = test2) - t = env.Command(target='baz.out', source='baz.in', - action='${TEST2(XYZ)}', - XYZ='magic word')[0] - assert t.builder is not None - t.build() - assert x[0] == 'magic word', x - - t = env.Command(target='${X}.out', source='${X}.in', - action = 'foo', - X = 'xxx')[0] - assert str(t) == 'xxx.out', str(t) - assert 'xxx.in' in [x.get_internal_path() for x in t.sources] - - env = self.TestEnvironment(source_scanner = 'should_not_find_this') - t = env.Command(target='file.out', source='file.in', - action = 'foo', - source_scanner = 'fake')[0] - assert t.builder.source_scanner == 'fake', t.builder.source_scanner - - def test_Configure(self): - """Test the Configure() method""" - # Configure() will write to a local temporary file. - test = TestCmd.TestCmd(workdir = '') - save = os.getcwd() - - try: - os.chdir(test.workpath()) - - env = self.TestEnvironment(FOO = 'xyzzy') - - def func(arg): - pass - - c = env.Configure() - assert c is not None, c - c.Finish() - - c = env.Configure(custom_tests = {'foo' : func, '$FOO' : func}) - assert c is not None, c - assert hasattr(c, 'foo') - assert hasattr(c, 'xyzzy') - c.Finish() - finally: - os.chdir(save) - - def test_Depends(self): - """Test the explicit Depends method.""" - env = self.TestEnvironment(FOO = 'xxx', BAR='yyy') - env.Dir('dir1') - env.Dir('dir2') - env.File('xxx.py') - env.File('yyy.py') - t = env.Depends(target='EnvironmentTest.py', - dependency='Environment.py')[0] - assert t.__class__.__name__ == 'Entry', t.__class__.__name__ - assert t.get_internal_path() == 'EnvironmentTest.py' - assert len(t.depends) == 1 - d = t.depends[0] - assert d.__class__.__name__ == 'Entry', d.__class__.__name__ - assert d.get_internal_path() == 'Environment.py' - - t = env.Depends(target='${FOO}.py', dependency='${BAR}.py')[0] - assert t.__class__.__name__ == 'File', t.__class__.__name__ - assert t.get_internal_path() == 'xxx.py' - assert len(t.depends) == 1 - d = t.depends[0] - assert d.__class__.__name__ == 'File', d.__class__.__name__ - assert d.get_internal_path() == 'yyy.py' - - t = env.Depends(target='dir1', dependency='dir2')[0] - assert t.__class__.__name__ == 'Dir', t.__class__.__name__ - assert t.get_internal_path() == 'dir1' - assert len(t.depends) == 1 - d = t.depends[0] - assert d.__class__.__name__ == 'Dir', d.__class__.__name__ - assert d.get_internal_path() == 'dir2' - - def test_Dir(self): - """Test the Dir() method""" - class MyFS: - def Dir(self, name): - return 'Dir(%s)' % name - - env = self.TestEnvironment(FOO = 'foodir', BAR = 'bardir') - env.fs = MyFS() - - d = env.Dir('d') - assert d == 'Dir(d)', d - - d = env.Dir('$FOO') - assert d == 'Dir(foodir)', d - - d = env.Dir('${BAR}_$BAR') - assert d == 'Dir(bardir_bardir)', d - - d = env.Dir(['dir1']) - assert d == ['Dir(dir1)'], d - - d = env.Dir(['dir1', 'dir2']) - assert d == ['Dir(dir1)', 'Dir(dir2)'], d - - def test_NoClean(self): - """Test the NoClean() method""" - env = self.TestEnvironment(FOO='ggg', BAR='hhh') - env.Dir('p_hhhb') - env.File('p_d') - t = env.NoClean('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') - - assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ - assert t[0].get_internal_path() == 'p_a' - assert t[0].noclean - assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ - assert t[1].get_internal_path() == 'p_hhhb' - assert t[1].noclean - assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ - assert t[2].get_internal_path() == 'p_c' - assert t[2].noclean - assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ - assert t[3].get_internal_path() == 'p_d' - assert t[3].noclean - assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ - assert t[4].get_internal_path() == 'p_ggg' - assert t[4].noclean - - def test_Dump(self): - """Test the Dump() method""" - - env = self.TestEnvironment(FOO = 'foo') - assert env.Dump('FOO') == "'foo'", env.Dump('FOO') - assert len(env.Dump()) > 200, env.Dump() # no args version - - assert env.Dump('FOO', 'json') == '"foo"' # JSON key version - import json - env_dict = json.loads(env.Dump(format = 'json')) - assert env_dict['FOO'] == 'foo' # full JSON version - - try: - env.Dump(format = 'markdown') - except ValueError as e: - assert str(e) == "Unsupported serialization format: markdown." - else: - self.fail("Did not catch expected ValueError.") - - def test_Environment(self): - """Test the Environment() method""" - env = self.TestEnvironment(FOO = 'xxx', BAR = 'yyy') - - e2 = env.Environment(X = '$FOO', Y = '$BAR') - assert e2['X'] == 'xxx', e2['X'] - assert e2['Y'] == 'yyy', e2['Y'] - - def test_Execute(self): - """Test the Execute() method""" - - class MyAction: - def __init__(self, *args, **kw): - self.args = args - def __call__(self, target, source, env): - return "%s executed" % self.args - - env = Environment() - env.Action = MyAction - - result = env.Execute("foo") - assert result == "foo executed", result - - def test_Entry(self): - """Test the Entry() method""" - class MyFS: - def Entry(self, name): - return 'Entry(%s)' % name - - env = self.TestEnvironment(FOO = 'fooentry', BAR = 'barentry') - env.fs = MyFS() - - e = env.Entry('e') - assert e == 'Entry(e)', e - - e = env.Entry('$FOO') - assert e == 'Entry(fooentry)', e - - e = env.Entry('${BAR}_$BAR') - assert e == 'Entry(barentry_barentry)', e - - e = env.Entry(['entry1']) - assert e == ['Entry(entry1)'], e - - e = env.Entry(['entry1', 'entry2']) - assert e == ['Entry(entry1)', 'Entry(entry2)'], e - - def test_File(self): - """Test the File() method""" - class MyFS: - def File(self, name): - return 'File(%s)' % name - - env = self.TestEnvironment(FOO = 'foofile', BAR = 'barfile') - env.fs = MyFS() - - f = env.File('f') - assert f == 'File(f)', f - - f = env.File('$FOO') - assert f == 'File(foofile)', f - - f = env.File('${BAR}_$BAR') - assert f == 'File(barfile_barfile)', f - - f = env.File(['file1']) - assert f == ['File(file1)'], f - - f = env.File(['file1', 'file2']) - assert f == ['File(file1)', 'File(file2)'], f - - def test_FindFile(self): - """Test the FindFile() method""" - env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') - - r = env.FindFile('foo', ['no_such_directory']) - assert r is None, r - - # XXX - - def test_Flatten(self): - """Test the Flatten() method""" - env = Environment() - l = env.Flatten([1]) - assert l == [1] - l = env.Flatten([1, [2, [3, [4]]]]) - assert l == [1, 2, 3, 4], l - - def test_GetBuildPath(self): - """Test the GetBuildPath() method.""" - env = self.TestEnvironment(MAGIC = 'xyzzy') - - p = env.GetBuildPath('foo') - assert p == 'foo', p - - p = env.GetBuildPath('$MAGIC') - assert p == 'xyzzy', p - - def test_Ignore(self): - """Test the explicit Ignore method.""" - env = self.TestEnvironment(FOO='yyy', BAR='zzz') - env.Dir('dir1') - env.Dir('dir2') - env.File('yyyzzz') - env.File('zzzyyy') - - t = env.Ignore(target='targ.py', dependency='dep.py')[0] - assert t.__class__.__name__ == 'Entry', t.__class__.__name__ - assert t.get_internal_path() == 'targ.py' - assert len(t.ignore) == 1 - i = t.ignore[0] - assert i.__class__.__name__ == 'Entry', i.__class__.__name__ - assert i.get_internal_path() == 'dep.py' - - t = env.Ignore(target='$FOO$BAR', dependency='$BAR$FOO')[0] - assert t.__class__.__name__ == 'File', t.__class__.__name__ - assert t.get_internal_path() == 'yyyzzz' - assert len(t.ignore) == 1 - i = t.ignore[0] - assert i.__class__.__name__ == 'File', i.__class__.__name__ - assert i.get_internal_path() == 'zzzyyy' - - t = env.Ignore(target='dir1', dependency='dir2')[0] - assert t.__class__.__name__ == 'Dir', t.__class__.__name__ - assert t.get_internal_path() == 'dir1' - assert len(t.ignore) == 1 - i = t.ignore[0] - assert i.__class__.__name__ == 'Dir', i.__class__.__name__ - assert i.get_internal_path() == 'dir2' - - def test_Literal(self): - """Test the Literal() method""" - env = self.TestEnvironment(FOO='fff', BAR='bbb') - list = env.subst_list([env.Literal('$FOO'), '$BAR'])[0] - assert list == ['$FOO', 'bbb'], list - list = env.subst_list(['$FOO', env.Literal('$BAR')])[0] - assert list == ['fff', '$BAR'], list - - def test_Local(self): - """Test the Local() method.""" - env = self.TestEnvironment(FOO='lll') - - l = env.Local(env.fs.File('fff')) - assert str(l[0]) == 'fff', l[0] - - l = env.Local('ggg', '$FOO') - assert str(l[0]) == 'ggg', l[0] - assert str(l[1]) == 'lll', l[1] - - def test_Precious(self): - """Test the Precious() method""" - env = self.TestEnvironment(FOO='ggg', BAR='hhh') - env.Dir('p_hhhb') - env.File('p_d') - t = env.Precious('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') - - assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ - assert t[0].get_internal_path() == 'p_a' - assert t[0].precious - assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ - assert t[1].get_internal_path() == 'p_hhhb' - assert t[1].precious - assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ - assert t[2].get_internal_path() == 'p_c' - assert t[2].precious - assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ - assert t[3].get_internal_path() == 'p_d' - assert t[3].precious - assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ - assert t[4].get_internal_path() == 'p_ggg' - assert t[4].precious - - def test_Pseudo(self): - """Test the Pseudo() method""" - env = self.TestEnvironment(FOO='ggg', BAR='hhh') - env.Dir('p_hhhb') - env.File('p_d') - t = env.Pseudo('p_a', 'p_${BAR}b', ['p_c', 'p_d'], 'p_$FOO') - - assert t[0].__class__.__name__ == 'Entry', t[0].__class__.__name__ - assert t[0].get_internal_path() == 'p_a' - assert t[0].pseudo - assert t[1].__class__.__name__ == 'Dir', t[1].__class__.__name__ - assert t[1].get_internal_path() == 'p_hhhb' - assert t[1].pseudo - assert t[2].__class__.__name__ == 'Entry', t[2].__class__.__name__ - assert t[2].get_internal_path() == 'p_c' - assert t[2].pseudo - assert t[3].__class__.__name__ == 'File', t[3].__class__.__name__ - assert t[3].get_internal_path() == 'p_d' - assert t[3].pseudo - assert t[4].__class__.__name__ == 'Entry', t[4].__class__.__name__ - assert t[4].get_internal_path() == 'p_ggg' - assert t[4].pseudo - - def test_Repository(self): - """Test the Repository() method.""" - class MyFS: - def __init__(self): - self.list = [] - def Repository(self, *dirs): - self.list.extend(list(dirs)) - def Dir(self, name): - return name - env = self.TestEnvironment(FOO='rrr', BAR='sss') - env.fs = MyFS() - env.Repository('/tmp/foo') - env.Repository('/tmp/$FOO', '/tmp/$BAR/foo') - expect = ['/tmp/foo', '/tmp/rrr', '/tmp/sss/foo'] - assert env.fs.list == expect, env.fs.list - - def test_Scanner(self): - """Test the Scanner() method""" - def scan(node, env, target, arg): - pass - - env = self.TestEnvironment(FOO = scan) - - s = env.Scanner('foo') - assert s is not None, s - - s = env.Scanner(function = 'foo') - assert s is not None, s - - if 0: - s = env.Scanner('$FOO') - assert s is not None, s - - s = env.Scanner(function = '$FOO') - assert s is not None, s - - def test_SConsignFile(self): - """Test the SConsignFile() method""" - import SCons.SConsign - - class MyFS: - SConstruct_dir = os.sep + 'dir' - - env = self.TestEnvironment(FOO = 'SConsign', - BAR = os.path.join(os.sep, 'File')) - env.fs = MyFS() - env.Execute = lambda action: None - - try: - fnames = [] - dbms = [] - def capture(name, dbm_module, fnames=fnames, dbms=dbms): - fnames.append(name) - dbms.append(dbm_module) - - save_SConsign_File = SCons.SConsign.File - SCons.SConsign.File = capture - - env.SConsignFile('foo') - assert fnames[-1] == os.path.join(os.sep, 'dir', 'foo'), fnames - assert dbms[-1] is None, dbms - - env.SConsignFile('$FOO') - assert fnames[-1] == os.path.join(os.sep, 'dir', 'SConsign'), fnames - assert dbms[-1] is None, dbms - - env.SConsignFile('/$FOO') - assert fnames[-1] == os.sep + 'SConsign', fnames - assert dbms[-1] is None, dbms - - env.SConsignFile(os.sep + '$FOO') - assert fnames[-1] == os.sep + 'SConsign', fnames - assert dbms[-1] is None, dbms - - env.SConsignFile('$BAR', 'x') - assert fnames[-1] == os.path.join(os.sep, 'File'), fnames - assert dbms[-1] == 'x', dbms - - env.SConsignFile('__$BAR', 7) - assert fnames[-1] == os.path.join(os.sep, 'dir', '__', 'File'), fnames - assert dbms[-1] == 7, dbms - - env.SConsignFile() - assert fnames[-1] == os.path.join(os.sep, 'dir', current_sconsign_filename()), fnames - assert dbms[-1] is None, dbms - - env.SConsignFile(None) - assert fnames[-1] is None, fnames - assert dbms[-1] is None, dbms - finally: - SCons.SConsign.File = save_SConsign_File - - def test_SideEffect(self): - """Test the SideEffect() method""" - env = self.TestEnvironment(LIB='lll', FOO='fff', BAR='bbb') - env.File('mylll.pdb') - env.Dir('mymmm.pdb') - - foo = env.Object('foo.obj', 'foo.cpp')[0] - bar = env.Object('bar.obj', 'bar.cpp')[0] - s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj']) - assert len(s) == 1, len(s) - s = s[0] - assert s.__class__.__name__ == 'Entry', s.__class__.__name__ - assert s.get_internal_path() == 'mylib.pdb' - assert s.side_effect - assert foo.side_effects == [s] - assert bar.side_effects == [s] - - fff = env.Object('fff.obj', 'fff.cpp')[0] - bbb = env.Object('bbb.obj', 'bbb.cpp')[0] - s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj']) - assert len(s) == 1, len(s) - s = s[0] - assert s.__class__.__name__ == 'File', s.__class__.__name__ - assert s.get_internal_path() == 'mylll.pdb' - assert s.side_effect - assert fff.side_effects == [s], fff.side_effects - assert bbb.side_effects == [s], bbb.side_effects - - ggg = env.Object('ggg.obj', 'ggg.cpp')[0] - ccc = env.Object('ccc.obj', 'ccc.cpp')[0] - s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj']) - assert len(s) == 1, len(s) - s = s[0] - assert s.__class__.__name__ == 'Dir', s.__class__.__name__ - assert s.get_internal_path() == 'mymmm.pdb' - assert s.side_effect - assert ggg.side_effects == [s], ggg.side_effects - assert ccc.side_effects == [s], ccc.side_effects - - # Verify that duplicate side effects are not allowed. - before = len(ggg.side_effects) - s = env.SideEffect('mymmm.pdb', ggg) - assert len(s) == 0, len(s) - assert len(ggg.side_effects) == before, len(ggg.side_effects) - - def test_Split(self): - """Test the Split() method""" - env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') - s = env.Split("foo bar") - assert s == ["foo", "bar"], s - s = env.Split("$FOO bar") - assert s == ["fff", "bar"], s - s = env.Split(["foo", "bar"]) - assert s == ["foo", "bar"], s - s = env.Split(["foo", "${BAR}-bbb"]) - assert s == ["foo", "bbb-bbb"], s - s = env.Split("foo") - assert s == ["foo"], s - s = env.Split("$FOO$BAR") - assert s == ["fffbbb"], s - - - def test_Value(self): - """Test creating a Value() object - """ - env = Environment() - v1 = env.Value('a') - assert v1.value == 'a', v1.value - - value2 = 'a' - v2 = env.Value(value2) - assert v2.value == value2, v2.value - assert v2.value is value2, v2.value - - assert v1 is v2 - - v3 = env.Value('c', 'build-c') - assert v3.value == 'c', v3.value - - v4 = env.Value(b'\x00\x0F', name='name') - assert v4.value == b'\x00\x0F', v4.value - assert v4.name == 'name', v4.name - - - def test_Environment_global_variable(self): - """Test setting Environment variable to an Environment.Base subclass""" - class MyEnv(SCons.Environment.Base): - def xxx(self, string): - return self.subst(string) - - SCons.Environment.Environment = MyEnv - - env = SCons.Environment.Environment(FOO = 'foo') - - f = env.subst('$FOO') - assert f == 'foo', f - - f = env.xxx('$FOO') - assert f == 'foo', f - - def test_bad_keywords(self): - """Test trying to use reserved keywords in an Environment""" - added = [] - - env = self.TestEnvironment(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - INIT = 'init') - bad_msg = '%s is not reserved, but got omitted; see Environment.construction_var_name_ok' - added.append('INIT') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - env.Append(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - APPEND = 'append') - added.append('APPEND') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - env.AppendUnique(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - APPENDUNIQUE = 'appendunique') - added.append('APPENDUNIQUE') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - env.Prepend(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - PREPEND = 'prepend') - added.append('PREPEND') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - env.Prepend(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - PREPENDUNIQUE = 'prependunique') - added.append('PREPENDUNIQUE') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - env.Replace(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - REPLACE = 'replace') - added.append('REPLACE') - for x in self.reserved_variables: - assert x not in env, env[x] - for x in added: - assert x in env, bad_msg % x - - copy = env.Clone(TARGETS = 'targets', - SOURCES = 'sources', - SOURCE = 'source', - TARGET = 'target', - CHANGED_SOURCES = 'changed_sources', - CHANGED_TARGETS = 'changed_targets', - UNCHANGED_SOURCES = 'unchanged_sources', - UNCHANGED_TARGETS = 'unchanged_targets', - COPY = 'copy') - for x in self.reserved_variables: - assert x not in copy, env[x] - for x in added + ['COPY']: - assert x in copy, bad_msg % x - - over = env.Override({'TARGETS' : 'targets', - 'SOURCES' : 'sources', - 'SOURCE' : 'source', - 'TARGET' : 'target', - 'CHANGED_SOURCES' : 'changed_sources', - 'CHANGED_TARGETS' : 'changed_targets', - 'UNCHANGED_SOURCES' : 'unchanged_sources', - 'UNCHANGED_TARGETS' : 'unchanged_targets', - 'OVERRIDE' : 'override'}) - for x in self.reserved_variables: - assert x not in over, over[x] - for x in added + ['OVERRIDE']: - assert x in over, bad_msg % x - - def test_parse_flags(self): - """Test the Base class parse_flags argument""" - # all we have to show is that it gets to MergeFlags internally - env = Environment(tools=[], parse_flags = '-X') - assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] - - env = Environment(tools=[], CCFLAGS=None, parse_flags = '-Y') - assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS'] - - env = Environment(tools=[], CPPDEFINES = 'FOO', parse_flags = '-std=c99 -X -DBAR') - assert env['CFLAGS'] == ['-std=c99'], env['CFLAGS'] - assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] - assert env['CPPDEFINES'] == ['FOO', 'BAR'], env['CPPDEFINES'] - - def test_clone_parse_flags(self): - """Test the env.Clone() parse_flags argument""" - # all we have to show is that it gets to MergeFlags internally - env = Environment(tools = []) - env2 = env.Clone(parse_flags = '-X') - assert 'CCFLAGS' not in env - assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] - - env = Environment(tools = [], CCFLAGS=None) - env2 = env.Clone(parse_flags = '-Y') - assert env['CCFLAGS'] is None, env['CCFLAGS'] - assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS'] - - env = Environment(tools = [], CPPDEFINES = 'FOO') - env2 = env.Clone(parse_flags = '-std=c99 -X -DBAR') - assert 'CFLAGS' not in env - assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS'] - assert 'CCFLAGS' not in env - assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] - assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES'] - assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES'] - - - -class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): - - def setUp(self): - env = Environment() - env._dict = {'XXX' : 'x', 'YYY' : 'y'} - def verify_value(env, key, value, *args, **kwargs): - """Verifies that key is value on the env this is called with.""" - assert env[key] == value - env.AddMethod(verify_value) - env2 = OverrideEnvironment(env, {'XXX' : 'x2'}) - env3 = OverrideEnvironment(env2, {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}) - self.envs = [ env, env2, env3 ] - - def checkpath(self, node, expect): - return str(node) == os.path.normpath(expect) - - def test___init__(self): - """Test OverrideEnvironment initialization""" - env, env2, env3 = self.envs - assert env['XXX'] == 'x', env['XXX'] - assert env2['XXX'] == 'x2', env2['XXX'] - assert env3['XXX'] == 'x3', env3['XXX'] - assert env['YYY'] == 'y', env['YYY'] - assert env2['YYY'] == 'y', env2['YYY'] - assert env3['YYY'] == 'y3', env3['YYY'] - - def test___delitem__(self): - """Test deleting variables from an OverrideEnvironment""" - env, env2, env3 = self.envs - - del env3['XXX'] - assert 'XXX' not in env, "env has XXX?" - assert 'XXX' not in env2, "env2 has XXX?" - assert 'XXX' not in env3, "env3 has XXX?" - - del env3['YYY'] - assert 'YYY' not in env, "env has YYY?" - assert 'YYY' not in env2, "env2 has YYY?" - assert 'YYY' not in env3, "env3 has YYY?" - - del env3['ZZZ'] - assert 'ZZZ' not in env, "env has ZZZ?" - assert 'ZZZ' not in env2, "env2 has ZZZ?" - assert 'ZZZ' not in env3, "env3 has ZZZ?" - - def test_get(self): - """Test the OverrideEnvironment get() method""" - env, env2, env3 = self.envs - assert env.get('XXX') == 'x', env.get('XXX') - assert env2.get('XXX') == 'x2', env2.get('XXX') - assert env3.get('XXX') == 'x3', env3.get('XXX') - assert env.get('YYY') == 'y', env.get('YYY') - assert env2.get('YYY') == 'y', env2.get('YYY') - assert env3.get('YYY') == 'y3', env3.get('YYY') - assert env.get('ZZZ') is None, env.get('ZZZ') - assert env2.get('ZZZ') is None, env2.get('ZZZ') - assert env3.get('ZZZ') == 'z3', env3.get('ZZZ') - - def test_contains(self): - """Test the OverrideEnvironment __contains__() method""" - env, env2, env3 = self.envs - assert 'XXX' in env, 'XXX' in env - assert 'XXX' in env2, 'XXX' in env2 - assert 'XXX' in env3, 'XXX' in env3 - assert 'YYY' in env, 'YYY' in env - assert 'YYY' in env2, 'YYY' in env2 - assert 'YYY' in env3, 'YYY' in env3 - assert 'ZZZ' not in env, 'ZZZ' in env - assert 'ZZZ' not in env2, 'ZZZ' in env2 - assert 'ZZZ' in env3, 'ZZZ' in env3 - - def test_Dictionary(self): - """Test the OverrideEnvironment Dictionary() method""" - env, env2, env3 = self.envs - # nothing overrriden - items = env.Dictionary() - assert items == {'XXX' : 'x', 'YYY' : 'y'}, items - # env2 overrides XXX, YYY unchanged - items = env2.Dictionary() - assert items == {'XXX' : 'x2', 'YYY' : 'y'}, items - # env3 overrides XXX, YYY, adds ZZZ - items = env3.Dictionary() - assert items == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, items - # test one-arg and multi-arg Dictionary - assert env3.Dictionary('XXX') == 'x3', env3.Dictionary('XXX') - xxx, yyy = env2.Dictionary('XXX', 'YYY') - assert xxx == 'x2', xxx - assert yyy == 'y', yyy - del env3['XXX'] - assert 'XXX' not in env3.Dictionary() - assert 'XXX' not in env2.Dictionary() - assert 'XXX' not in env.Dictionary() - - def test_items(self): - """Test the OverrideEnvironment items() method""" - env, env2, env3 = self.envs - items = sorted(env.items()) - assert items == [('XXX', 'x'), ('YYY', 'y')], items - items = sorted(env2.items()) - assert items == [('XXX', 'x2'), ('YYY', 'y')], items - items = sorted(env3.items()) - assert items == [('XXX', 'x3'), ('YYY', 'y3'), ('ZZZ', 'z3')], items - - def test_keys(self): - """Test the OverrideEnvironment keys() method""" - env, env2, env3 = self.envs - keys = sorted(env.keys()) - assert keys == ['XXX', 'YYY'], keys - keys = sorted(env2.keys()) - assert keys == ['XXX', 'YYY'], keys - keys = sorted(env3.keys()) - assert keys == ['XXX', 'YYY', 'ZZZ'], keys - - def test_values(self): - """Test the OverrideEnvironment values() method""" - env, env2, env3 = self.envs - values = sorted(env.values()) - assert values == ['x', 'y'], values - values = sorted(env2.values()) - assert values == ['x2', 'y'], values - values = sorted(env3.values()) - assert values == ['x3', 'y3', 'z3'], values - - def test_setdefault(self): - """Test the OverrideEnvironment setdefault() method.""" - env, env2, env3 = self.envs - # does not set for existing key - assert env2.setdefault('XXX', 'z') == 'x2', env2['XXX'] - # set/return using default for non-existing key - assert env2.setdefault('ZZZ', 'z2') == 'z2', env2['ZZZ'] - # set did not leak through to base env - assert 'ZZZ' not in env - - def test_gvars(self): - """Test the OverrideEnvironment gvars() method""" - env, env2, env3 = self.envs - gvars = env.gvars() - assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars - gvars = env2.gvars() - assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars - gvars = env3.gvars() - assert gvars == {'XXX' : 'x', 'YYY' : 'y'}, gvars - - def test_lvars(self): - """Test the OverrideEnvironment lvars() method""" - env, env2, env3 = self.envs - lvars = env.lvars() - assert lvars == {}, lvars - lvars = env2.lvars() - assert lvars == {'XXX' : 'x2'}, lvars - lvars = env3.lvars() - assert lvars == {'XXX' : 'x3', 'YYY' : 'y3', 'ZZZ' : 'z3'}, lvars - - def test_Replace(self): - """Test the OverrideEnvironment Replace() method""" - env, env2, env3 = self.envs - assert env['XXX'] == 'x', env['XXX'] - assert env2['XXX'] == 'x2', env2['XXX'] - assert env3['XXX'] == 'x3', env3['XXX'] - assert env['YYY'] == 'y', env['YYY'] - assert env2['YYY'] == 'y', env2['YYY'] - assert env3['YYY'] == 'y3', env3['YYY'] - - env.Replace(YYY = 'y4') - - assert env['XXX'] == 'x', env['XXX'] - assert env2['XXX'] == 'x2', env2['XXX'] - assert env3['XXX'] == 'x3', env3['XXX'] - assert env['YYY'] == 'y4', env['YYY'] - assert env2['YYY'] == 'y4', env2['YYY'] - assert env3['YYY'] == 'y3', env3['YYY'] - - # Tests a number of Base methods through an OverrideEnvironment to - # make sure they handle overridden constructionv variables properly. - # - # The following Base methods also call self.subst(), and so could - # theoretically be subject to problems with evaluating overridden - # variables, but they're never really called that way in the rest - # of our code, so we won't worry about them (at least for now): - # - # ParseConfig() - # ParseDepends() - # Platform() - # Tool() - # - # Action() - # Alias() - # Builder() - # CacheDir() - # Configure() - # Environment() - # FindFile() - # Scanner() - - # It's unlikely Clone() will ever be called this way, so let the - # other methods test that handling overridden values works. - #def test_Clone(self): - # """Test the OverrideEnvironment Clone() method""" - # pass - - def test_FindIxes(self): - """Test the OverrideEnvironment FindIxes() method""" - env, env2, env3 = self.envs - x = env.FindIxes(['xaaay'], 'XXX', 'YYY') - assert x == 'xaaay', x - x = env2.FindIxes(['x2aaay'], 'XXX', 'YYY') - assert x == 'x2aaay', x - x = env3.FindIxes(['x3aaay3'], 'XXX', 'YYY') - assert x == 'x3aaay3', x - - def test_ReplaceIxes(self): - """Test the OverrideEnvironment ReplaceIxes() method""" - env, env2, env3 = self.envs - x = env.ReplaceIxes('xaaay', 'XXX', 'YYY', 'YYY', 'XXX') - assert x == 'yaaax', x - x = env2.ReplaceIxes('x2aaay', 'XXX', 'YYY', 'YYY', 'XXX') - assert x == 'yaaax2', x - x = env3.ReplaceIxes('x3aaay3', 'XXX', 'YYY', 'YYY', 'XXX') - assert x == 'y3aaax3', x - - # It's unlikely WhereIs() will ever be called this way, so let the - # other methods test that handling overridden values works. - #def test_WhereIs(self): - # """Test the OverrideEnvironment WhereIs() method""" - # pass - - def test_PseudoBuilderInherits(self): - """Test that pseudo-builders inherit the overrided values.""" - env, env2, env3 = self.envs - env.verify_value('XXX', 'x') - env2.verify_value('XXX', 'x2') - env3.verify_value('XXX', 'x3') - - def test_Dir(self): - """Test the OverrideEnvironment Dir() method""" - env, env2, env3 = self.envs - x = env.Dir('ddir/$XXX') - assert self.checkpath(x, 'ddir/x'), str(x) - x = env2.Dir('ddir/$XXX') - assert self.checkpath(x, 'ddir/x2'), str(x) - x = env3.Dir('ddir/$XXX') - assert self.checkpath(x, 'ddir/x3'), str(x) - - def test_Entry(self): - """Test the OverrideEnvironment Entry() method""" - env, env2, env3 = self.envs - x = env.Entry('edir/$XXX') - assert self.checkpath(x, 'edir/x'), str(x) - x = env2.Entry('edir/$XXX') - assert self.checkpath(x, 'edir/x2'), str(x) - x = env3.Entry('edir/$XXX') - assert self.checkpath(x, 'edir/x3'), str(x) - - def test_File(self): - """Test the OverrideEnvironment File() method""" - env, env2, env3 = self.envs - x = env.File('fdir/$XXX') - assert self.checkpath(x, 'fdir/x'), str(x) - x = env2.File('fdir/$XXX') - assert self.checkpath(x, 'fdir/x2'), str(x) - x = env3.File('fdir/$XXX') - assert self.checkpath(x, 'fdir/x3'), str(x) - - def test_Split(self): - """Test the OverrideEnvironment Split() method""" - env, env2, env3 = self.envs - env['AAA'] = '$XXX $YYY $ZZZ' - x = env.Split('$AAA') - assert x == ['x', 'y'], x - x = env2.Split('$AAA') - assert x == ['x2', 'y'], x - x = env3.Split('$AAA') - assert x == ['x3', 'y3', 'z3'], x - - def test_parse_flags(self): - """Test the OverrideEnvironment parse_flags argument""" - # all we have to show is that it gets to MergeFlags internally - env = SubstitutionEnvironment() - env2 = env.Override({'parse_flags' : '-X'}) - assert 'CCFLAGS' not in env - assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] - - env = SubstitutionEnvironment(CCFLAGS=None) - env2 = env.Override({'parse_flags' : '-Y'}) - assert env['CCFLAGS'] is None, env['CCFLAGS'] - assert env2['CCFLAGS'] == ['-Y'], env2['CCFLAGS'] - - env = SubstitutionEnvironment(CPPDEFINES = 'FOO') - env2 = env.Override({'parse_flags' : '-std=c99 -X -DBAR'}) - assert 'CFLAGS' not in env - assert env2['CFLAGS'] == ['-std=c99'], env2['CFLAGS'] - assert 'CCFLAGS' not in env - assert env2['CCFLAGS'] == ['-X'], env2['CCFLAGS'] - assert env['CPPDEFINES'] == 'FOO', env['CPPDEFINES'] - assert env2['CPPDEFINES'] == ['FOO','BAR'], env2['CPPDEFINES'] - - - -class NoSubstitutionProxyTestCase(unittest.TestCase,TestEnvironmentFixture): - - def test___init__(self): - """Test NoSubstitutionProxy initialization""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env['XXX'] == 'x', env['XXX'] - assert env['YYY'] == 'y', env['YYY'] - - proxy = NoSubstitutionProxy(env) - assert proxy['XXX'] == 'x', proxy['XXX'] - assert proxy['YYY'] == 'y', proxy['YYY'] - - def test_attributes(self): - """Test getting and setting NoSubstitutionProxy attributes""" - env = Environment() - setattr(env, 'env_attr', 'value1') - - proxy = NoSubstitutionProxy(env) - setattr(proxy, 'proxy_attr', 'value2') - - x = getattr(env, 'env_attr') - assert x == 'value1', x - x = getattr(proxy, 'env_attr') - assert x == 'value1', x - - x = getattr(env, 'proxy_attr') - assert x == 'value2', x - x = getattr(proxy, 'proxy_attr') - assert x == 'value2', x - - def test_subst(self): - """Test the NoSubstitutionProxy.subst() method""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env['XXX'] == 'x', env['XXX'] - assert env['YYY'] == 'y', env['YYY'] - - proxy = NoSubstitutionProxy(env) - assert proxy['XXX'] == 'x', proxy['XXX'] - assert proxy['YYY'] == 'y', proxy['YYY'] - - x = env.subst('$XXX') - assert x == 'x', x - x = proxy.subst('$XXX') - assert x == '$XXX', x - - x = proxy.subst('$YYY', raw=7, target=None, source=None, - conv=None, - extra_meaningless_keyword_argument=None) - assert x == '$YYY', x - - def test_subst_kw(self): - """Test the NoSubstitutionProxy.subst_kw() method""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env['XXX'] == 'x', env['XXX'] - assert env['YYY'] == 'y', env['YYY'] - - proxy = NoSubstitutionProxy(env) - assert proxy['XXX'] == 'x', proxy['XXX'] - assert proxy['YYY'] == 'y', proxy['YYY'] - - x = env.subst_kw({'$XXX':'$YYY'}) - assert x == {'x':'y'}, x - x = proxy.subst_kw({'$XXX':'$YYY'}) - assert x == {'$XXX':'$YYY'}, x - - def test_subst_list(self): - """Test the NoSubstitutionProxy.subst_list() method""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env['XXX'] == 'x', env['XXX'] - assert env['YYY'] == 'y', env['YYY'] - - proxy = NoSubstitutionProxy(env) - assert proxy['XXX'] == 'x', proxy['XXX'] - assert proxy['YYY'] == 'y', proxy['YYY'] - - x = env.subst_list('$XXX') - assert x == [['x']], x - x = proxy.subst_list('$XXX') - assert x == [[]], x - - x = proxy.subst_list('$YYY', raw=0, target=None, source=None, conv=None) - assert x == [[]], x - - def test_subst_target_source(self): - """Test the NoSubstitutionProxy.subst_target_source() method""" - env = self.TestEnvironment(XXX = 'x', YYY = 'y') - assert env['XXX'] == 'x', env['XXX'] - assert env['YYY'] == 'y', env['YYY'] - - proxy = NoSubstitutionProxy(env) - assert proxy['XXX'] == 'x', proxy['XXX'] - assert proxy['YYY'] == 'y', proxy['YYY'] - - args = ('$XXX $TARGET $SOURCE $YYY',) - kw = {'target' : DummyNode('ttt'), 'source' : DummyNode('sss')} - x = env.subst_target_source(*args, **kw) - assert x == 'x ttt sss y', x - x = proxy.subst_target_source(*args, **kw) - assert x == ' ttt sss ', x - -class EnvironmentVariableTestCase(unittest.TestCase): - - def test_is_valid_construction_var(self): - """Testing is_valid_construction_var()""" - r = is_valid_construction_var("_a") - assert r is not None, r - r = is_valid_construction_var("z_") - assert r is not None, r - r = is_valid_construction_var("X_") - assert r is not None, r - r = is_valid_construction_var("2a") - assert r is None, r - r = is_valid_construction_var("a2_") - assert r is not None, r - r = is_valid_construction_var("/") - assert r is None, r - r = is_valid_construction_var("_/") - assert r is None, r - r = is_valid_construction_var("a/") - assert r is None, r - r = is_valid_construction_var(".b") - assert r is None, r - r = is_valid_construction_var("_.b") - assert r is None, r - r = is_valid_construction_var("b1._") - assert r is None, r - r = is_valid_construction_var("-b") - assert r is None, r - r = is_valid_construction_var("_-b") - assert r is None, r - r = is_valid_construction_var("b1-_") - assert r is None, r - - - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/EnvironmentValuesTest.py b/SCSCons/EnvironmentValuesTest.py deleted file mode 100644 index 074aa85ca..000000000 --- a/SCSCons/EnvironmentValuesTest.py +++ /dev/null @@ -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() diff --git a/SCSCons/ErrorsTests.py b/SCSCons/ErrorsTests.py deleted file mode 100644 index 9f2f1a280..000000000 --- a/SCSCons/ErrorsTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/ExecutorTests.py b/SCSCons/ExecutorTests.py deleted file mode 100644 index c43c45085..000000000 --- a/SCSCons/ExecutorTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/MemoizeTests.py b/SCSCons/MemoizeTests.py deleted file mode 100644 index 7830d993c..000000000 --- a/SCSCons/MemoizeTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Node/AliasTests.py b/SCSCons/Node/AliasTests.py deleted file mode 100644 index 14662fd9c..000000000 --- a/SCSCons/Node/AliasTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Node/FSTests.py b/SCSCons/Node/FSTests.py deleted file mode 100644 index d78940e3d..000000000 --- a/SCSCons/Node/FSTests.py +++ /dev/null @@ -1,4056 +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 SCons.compat -import os -import os.path -import sys -import time -import unittest -import shutil -import stat - -from TestCmd import TestCmd, IS_WINDOWS - -import SCons.Errors -import SCons.Node.FS -import SCons.Util -import SCons.Warnings -import SCons.Environment - -built_it = None - -scanner_count = 0 - - -class Scanner: - def __init__(self, node=None): - global scanner_count - scanner_count = scanner_count + 1 - self.hash = scanner_count - self.node = node - - def path(self, env, dir, target=None, source=None): - return () - - def __call__(self, node, env, path): - return [self.node] - - def __hash__(self): - return self.hash - - def select(self, node): - return self - - def recurse_nodes(self, nodes): - return nodes - - -class Environment: - def __init__(self): - self.scanner = Scanner() - - def Dictionary(self, *args): - return {} - - def autogenerate(self, **kw): - return {} - - def get_scanner(self, skey): - return self.scanner - - def Override(self, overrides): - return self - - def _update(self, dict): - pass - - -class Action: - def __call__(self, targets, sources, env, **kw): - global built_it - if kw.get('execute', 1): - built_it = 1 - return 0 - - def show(self, string): - pass - - def get_contents(self, target, source, env): - return bytearray("", 'utf-8') - - def genstring(self, target, source, env): - return "" - - def strfunction(self, targets, sources, env): - return "" - - def get_implicit_deps(self, target, source, env): - return [] - - -class Builder: - def __init__(self, factory, action=Action()): - self.factory = factory - self.env = Environment() - self.overrides = {} - self.action = action - self.target_scanner = None - self.source_scanner = None - - def targets(self, t): - return [t] - - def source_factory(self, name): - return self.factory(name) - - -class _tempdirTestCase(unittest.TestCase): - def setUp(self): - self.save_cwd = os.getcwd() - self.test = TestCmd(workdir='') - # FS doesn't like the cwd to be something other than its root. - os.chdir(self.test.workpath("")) - self.fs = SCons.Node.FS.FS() - - def tearDown(self): - os.chdir(self.save_cwd) - - -class VariantDirTestCase(unittest.TestCase): - def runTest(self): - """Test variant dir functionality""" - test = TestCmd(workdir='') - - fs = SCons.Node.FS.FS() - f1 = fs.File('build/test1') - fs.VariantDir('build', 'src') - f2 = fs.File('build/test2') - d1 = fs.Dir('build') - assert f1.srcnode().get_internal_path() == os.path.normpath('src/test1'), f1.srcnode().get_internal_path() - assert f2.srcnode().get_internal_path() == os.path.normpath('src/test2'), f2.srcnode().get_internal_path() - assert d1.srcnode().get_internal_path() == 'src', d1.srcnode().get_internal_path() - - fs = SCons.Node.FS.FS() - f1 = fs.File('build/test1') - fs.VariantDir('build', '.') - f2 = fs.File('build/test2') - d1 = fs.Dir('build') - assert f1.srcnode().get_internal_path() == 'test1', f1.srcnode().get_internal_path() - assert f2.srcnode().get_internal_path() == 'test2', f2.srcnode().get_internal_path() - assert d1.srcnode().get_internal_path() == '.', d1.srcnode().get_internal_path() - - fs = SCons.Node.FS.FS() - fs.VariantDir('build/var1', 'src') - fs.VariantDir('build/var2', 'src') - f1 = fs.File('build/var1/test1') - f2 = fs.File('build/var2/test1') - assert f1.srcnode().get_internal_path() == os.path.normpath('src/test1'), f1.srcnode().get_internal_path() - assert f2.srcnode().get_internal_path() == os.path.normpath('src/test1'), f2.srcnode().get_internal_path() - - fs = SCons.Node.FS.FS() - fs.VariantDir('../var1', 'src') - fs.VariantDir('../var2', 'src') - f1 = fs.File('../var1/test1') - f2 = fs.File('../var2/test1') - assert f1.srcnode().get_internal_path() == os.path.normpath('src/test1'), f1.srcnode().get_internal_path() - assert f2.srcnode().get_internal_path() == os.path.normpath('src/test1'), f2.srcnode().get_internal_path() - - # Set up some files - test.subdir('work', ['work', 'src']) - test.subdir(['work', 'build'], ['work', 'build', 'var1']) - test.subdir(['work', 'build', 'var2']) - test.subdir('rep1', ['rep1', 'src']) - test.subdir(['rep1', 'build'], ['rep1', 'build', 'var1']) - test.subdir(['rep1', 'build', 'var2']) - - # A source file in the source directory - test.write(['work', 'src', 'test.in'], 'test.in') - - # A source file in a subdir of the source directory - test.subdir(['work', 'src', 'new_dir']) - test.write(['work', 'src', 'new_dir', 'test9.out'], 'test9.out\n') - - # A source file in the repository - test.write(['rep1', 'src', 'test2.in'], 'test2.in') - - # Some source files in the variant directory - test.write(['work', 'build', 'var2', 'test.in'], 'test.old') - test.write(['work', 'build', 'var2', 'test2.in'], 'test2.old') - - # An old derived file in the variant directories - test.write(['work', 'build', 'var1', 'test.out'], 'test.old') - test.write(['work', 'build', 'var2', 'test.out'], 'test.old') - - # And just in case we are weird, a derived file in the source - # dir. - test.write(['work', 'src', 'test.out'], 'test.out.src') - - # A derived file in the repository - test.write(['rep1', 'build', 'var1', 'test2.out'], 'test2.out_rep') - test.write(['rep1', 'build', 'var2', 'test2.out'], 'test2.out_rep') - - os.chdir(test.workpath('work')) - - fs = SCons.Node.FS.FS(test.workpath('work')) - fs.VariantDir('build/var1', 'src', duplicate=0) - fs.VariantDir('build/var2', 'src') - f1 = fs.File('build/var1/test.in') - f1out = fs.File('build/var1/test.out') - f1out.builder = 1 - f1out_2 = fs.File('build/var1/test2.out') - f1out_2.builder = 1 - f2 = fs.File('build/var2/test.in') - f2out = fs.File('build/var2/test.out') - f2out.builder = 1 - f2out_2 = fs.File('build/var2/test2.out') - f2out_2.builder = 1 - fs.Repository(test.workpath('rep1')) - - assert f1.srcnode().get_internal_path() == os.path.normpath('src/test.in'), \ - f1.srcnode().get_internal_path() - # str(node) returns source path for duplicate = 0 - assert str(f1) == os.path.normpath('src/test.in'), str(f1) - # Build path does not exist - assert not f1.exists() - # ...but the actual file is not there... - assert not os.path.exists(f1.get_abspath()) - # And duplicate=0 should also work just like a Repository - assert f1.rexists() - # rfile() should point to the source path - assert f1.rfile().get_internal_path() == os.path.normpath('src/test.in'), \ - f1.rfile().get_internal_path() - - assert f2.srcnode().get_internal_path() == os.path.normpath('src/test.in'), \ - f2.srcnode().get_internal_path() - # str(node) returns build path for duplicate = 1 - assert str(f2) == os.path.normpath('build/var2/test.in'), str(f2) - # Build path exists - assert f2.exists() - # ...and exists() should copy the file from src to build path - assert test.read(['work', 'build', 'var2', 'test.in']) == bytearray('test.in', 'utf-8'), \ - test.read(['work', 'build', 'var2', 'test.in']) - # Since exists() is true, so should rexists() be - assert f2.rexists() - - f3 = fs.File('build/var1/test2.in') - f4 = fs.File('build/var2/test2.in') - - assert f3.srcnode().get_internal_path() == os.path.normpath('src/test2.in'), \ - f3.srcnode().get_internal_path() - # str(node) returns source path for duplicate = 0 - assert str(f3) == os.path.normpath('src/test2.in'), str(f3) - # Build path does not exist - assert not f3.exists() - # Source path does not either - assert not f3.srcnode().exists() - # But we do have a file in the Repository - assert f3.rexists() - # rfile() should point to the source path - assert f3.rfile().get_internal_path() == os.path.normpath(test.workpath('rep1/src/test2.in')), \ - f3.rfile().get_internal_path() - - assert f4.srcnode().get_internal_path() == os.path.normpath('src/test2.in'), \ - f4.srcnode().get_internal_path() - # str(node) returns build path for duplicate = 1 - assert str(f4) == os.path.normpath('build/var2/test2.in'), str(f4) - # Build path should exist - assert f4.exists() - # ...and copy over the file into the local build path - assert test.read(['work', 'build', 'var2', 'test2.in']) == bytearray('test2.in', 'utf-8') - # should exist in repository, since exists() is true - assert f4.rexists() - # rfile() should point to ourselves - assert f4.rfile().get_internal_path() == os.path.normpath('build/var2/test2.in'), \ - f4.rfile().get_internal_path() - - f5 = fs.File('build/var1/test.out') - f6 = fs.File('build/var2/test.out') - - assert f5.exists() - # We should not copy the file from the source dir, since this is - # a derived file. - assert test.read(['work', 'build', 'var1', 'test.out']) == bytearray('test.old', 'utf-8') - - assert f6.exists() - # We should not copy the file from the source dir, since this is - # a derived file. - assert test.read(['work', 'build', 'var2', 'test.out']) == bytearray('test.old', 'utf-8') - - f7 = fs.File('build/var1/test2.out') - f8 = fs.File('build/var2/test2.out') - - assert not f7.exists() - assert f7.rexists() - r = f7.rfile().get_internal_path() - expect = os.path.normpath(test.workpath('rep1/build/var1/test2.out')) - assert r == expect, (repr(r), repr(expect)) - - assert not f8.exists() - assert f8.rexists() - assert f8.rfile().get_internal_path() == os.path.normpath(test.workpath('rep1/build/var2/test2.out')), \ - f8.rfile().get_internal_path() - - # Verify the Mkdir and Link actions are called - d9 = fs.Dir('build/var2/new_dir') - f9 = fs.File('build/var2/new_dir/test9.out') - - class MkdirAction(Action): - def __init__(self, dir_made): - self.dir_made = dir_made - - def __call__(self, target, source, env, executor=None): - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - self.dir_made.extend(target) - - save_Link = SCons.Node.FS.Link - link_made = [] - - def link_func(target, source, env, link_made=link_made): - link_made.append(target) - - SCons.Node.FS.Link = link_func - - try: - dir_made = [] - d9.builder = Builder(fs.Dir, action=MkdirAction(dir_made)) - d9.reset_executor() - f9.exists() - expect = os.path.join('build', 'var2', 'new_dir') - assert dir_made[0].get_internal_path() == expect, dir_made[0].get_internal_path() - expect = os.path.join('build', 'var2', 'new_dir', 'test9.out') - assert link_made[0].get_internal_path() == expect, link_made[0].get_internal_path() - assert f9.linked - finally: - SCons.Node.FS.Link = save_Link - - # Test for an interesting pathological case...we have a source - # file in a build path, but not in a source path. This can - # happen if you switch from duplicate=1 to duplicate=0, then - # delete a source file. At one time, this would cause exists() - # to return a 1 but get_contents() to throw. - test.write(['work', 'build', 'var1', 'asourcefile'], 'stuff') - f10 = fs.File('build/var1/asourcefile') - assert f10.exists() - assert f10.get_contents() == bytearray('stuff', 'utf-8'), f10.get_contents() - - f11 = fs.File('src/file11') - t, m = f11.alter_targets() - bdt = [n.get_internal_path() for n in t] - var1_file11 = os.path.normpath('build/var1/file11') - var2_file11 = os.path.normpath('build/var2/file11') - assert bdt == [var1_file11, var2_file11], bdt - - f12 = fs.File('src/file12') - f12.builder = 1 - bdt, m = f12.alter_targets() - assert bdt == [], [n.get_internal_path() for n in bdt] - - d13 = fs.Dir('src/new_dir') - t, m = d13.alter_targets() - bdt = [n.get_internal_path() for n in t] - var1_new_dir = os.path.normpath('build/var1/new_dir') - var2_new_dir = os.path.normpath('build/var2/new_dir') - assert bdt == [var1_new_dir, var2_new_dir], bdt - - # Test that an IOError trying to Link a src file - # into a VariantDir ends up throwing a StopError. - fIO = fs.File("build/var2/IOError") - - save_Link = SCons.Node.FS.Link - - def Link_IOError(target, source, env): - raise IOError(17, "Link_IOError") - - SCons.Node.FS.Link = SCons.Action.Action(Link_IOError, None) - - test.write(['work', 'src', 'IOError'], "work/src/IOError\n") - - try: - exc_caught = 0 - try: - fIO.exists() - except SCons.Errors.StopError: - exc_caught = 1 - assert exc_caught, "Should have caught a StopError" - - finally: - SCons.Node.FS.Link = save_Link - - # Test to see if Link() works... - test.subdir('src', 'build') - test.write('src/foo', 'src/foo\n') - os.chmod(test.workpath('src/foo'), stat.S_IRUSR) - SCons.Node.FS.Link(fs.File(test.workpath('build/foo')), - fs.File(test.workpath('src/foo')), - None) - os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE) - st = os.stat(test.workpath('build/foo')) - assert (stat.S_IMODE(st[stat.ST_MODE]) & stat.S_IWRITE), \ - stat.S_IMODE(st[stat.ST_MODE]) - - # This used to generate a UserError when we forbid the source - # directory from being outside the top-level SConstruct dir. - fs = SCons.Node.FS.FS() - fs.VariantDir('build', '/test/foo') - - exc_caught = 0 - try: - try: - fs = SCons.Node.FS.FS() - fs.VariantDir('build', 'build/src') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "Should have caught a UserError." - finally: - test.unlink("src/foo") - test.unlink("build/foo") - - fs = SCons.Node.FS.FS() - fs.VariantDir('build', 'src1') - - # Calling the same VariantDir twice should work fine. - fs.VariantDir('build', 'src1') - - # Trying to move a variant dir to a second source dir - # should blow up - try: - fs.VariantDir('build', 'src2') - except SCons.Errors.UserError: - pass - else: - assert 0, "Should have caught a UserError." - - # Test against a former bug. Make sure we can get a repository - # path for the variant directory itself! - fs = SCons.Node.FS.FS(test.workpath('work')) - - # not needed this subdir is created above near line 188 - # test.subdir('work') - fs.VariantDir('build/var3', 'src', duplicate=0) - d1 = fs.Dir('build/var3') - r = d1.rdir() - assert r == d1, "%s != %s" % (r, d1) - - # verify the link creation attempts in file_link() - class LinkSimulator: - """A class to intercept os.[sym]link() calls and track them.""" - - def __init__(self, duplicate, link, symlink, copy): - self.duplicate = duplicate - self.have = {'hard': link, 'soft': symlink, 'copy': copy} - - self.links_to_be_called = [] - for link in self.duplicate.split('-'): - if self.have[link]: - self.links_to_be_called.append(link) - - def link_fail(self, src, dest): - next_link = self.links_to_be_called.pop(0) - assert next_link == "hard", \ - "Wrong link order: expected %s to be called " \ - "instead of hard" % next_link - raise OSError("Simulating hard link creation error.") - - def symlink_fail(self, src, dest): - next_link = self.links_to_be_called.pop(0) - assert next_link == "soft", \ - "Wrong link order: expected %s to be called " \ - "instead of soft" % next_link - raise OSError("Simulating symlink creation error.") - - def copy(self, src, dest): - next_link = self.links_to_be_called.pop(0) - assert next_link == "copy", \ - "Wrong link order: expected %s to be called " \ - "instead of copy" % next_link - # copy succeeds, but use the real copy - self.have['copy'](src, dest) - - # end class LinkSimulator - - try: - SCons.Node.FS.set_duplicate("no-link-order") - assert 0, "Expected exception when passing an invalid duplicate to set_duplicate" - except SCons.Errors.InternalError: - pass - - for duplicate in SCons.Node.FS.Valid_Duplicates: - # save the real functions for later restoration - try: - real_link = os.link - except AttributeError: - real_link = None - try: - real_symlink = os.symlink - except AttributeError: - real_symlink = None - - # Disable symlink and link for now in win32. - # We don't have a consistant plan to make these work as yet - # They are only supported with PY3 - if sys.platform == 'win32': - real_symlink = None - real_link = None - - real_copy = shutil.copy2 - - simulator = LinkSimulator(duplicate, real_link, real_symlink, real_copy) - - # override the real functions with our simulation - os.link = simulator.link_fail - os.symlink = simulator.symlink_fail - shutil.copy2 = simulator.copy - - try: - - SCons.Node.FS.set_duplicate(duplicate) - - src_foo = test.workpath('src', 'foo') - build_foo = test.workpath('build', 'foo') - - test.write(src_foo, 'src/foo\n') - os.chmod(src_foo, stat.S_IRUSR) - try: - SCons.Node.FS.Link(fs.File(build_foo), - fs.File(src_foo), - None) - finally: - os.chmod(src_foo, stat.S_IRUSR | stat.S_IWRITE) - test.unlink(src_foo) - test.unlink(build_foo) - - finally: - # restore the real functions - if real_link: - os.link = real_link - else: - delattr(os, 'link') - if real_symlink: - os.symlink = real_symlink - else: - delattr(os, 'symlink') - shutil.copy2 = real_copy - - # Test VariantDir "reflection," where a same-named subdirectory - # exists underneath a variant_dir. - fs = SCons.Node.FS.FS() - fs.VariantDir('work/src/b1/b2', 'work/src') - - dir_list = [ - 'work/src', - 'work/src/b1', - 'work/src/b1/b2', - 'work/src/b1/b2/b1', - 'work/src/b1/b2/b1/b2', - 'work/src/b1/b2/b1/b2/b1', - 'work/src/b1/b2/b1/b2/b1/b2', - ] - - srcnode_map = { - 'work/src/b1/b2': 'work/src', - 'work/src/b1/b2/f': 'work/src/f', - 'work/src/b1/b2/b1': 'work/src/b1/', - 'work/src/b1/b2/b1/f': 'work/src/b1/f', - 'work/src/b1/b2/b1/b2': 'work/src/b1/b2', - 'work/src/b1/b2/b1/b2/f': 'work/src/b1/b2/f', - 'work/src/b1/b2/b1/b2/b1': 'work/src/b1/b2/b1', - 'work/src/b1/b2/b1/b2/b1/f': 'work/src/b1/b2/b1/f', - 'work/src/b1/b2/b1/b2/b1/b2': 'work/src/b1/b2/b1/b2', - 'work/src/b1/b2/b1/b2/b1/b2/f': 'work/src/b1/b2/b1/b2/f', - } - - alter_map = { - 'work/src': 'work/src/b1/b2', - 'work/src/f': 'work/src/b1/b2/f', - 'work/src/b1': 'work/src/b1/b2/b1', - 'work/src/b1/f': 'work/src/b1/b2/b1/f', - } - - errors = 0 - - for dir in dir_list: - dnode = fs.Dir(dir) - f = dir + '/f' - fnode = fs.File(dir + '/f') - - dp = dnode.srcnode().get_internal_path() - expect = os.path.normpath(srcnode_map.get(dir, dir)) - if dp != expect: - print("Dir `%s' srcnode() `%s' != expected `%s'" % (dir, dp, expect)) - errors = errors + 1 - - fp = fnode.srcnode().get_internal_path() - expect = os.path.normpath(srcnode_map.get(f, f)) - if fp != expect: - print("File `%s' srcnode() `%s' != expected `%s'" % (f, fp, expect)) - errors = errors + 1 - - for dir in dir_list: - dnode = fs.Dir(dir) - f = dir + '/f' - fnode = fs.File(dir + '/f') - - t, m = dnode.alter_targets() - tp = t[0].get_internal_path() - expect = os.path.normpath(alter_map.get(dir, dir)) - if tp != expect: - print("Dir `%s' alter_targets() `%s' != expected `%s'" % (dir, tp, expect)) - errors = errors + 1 - - t, m = fnode.alter_targets() - tp = t[0].get_internal_path() - expect = os.path.normpath(alter_map.get(f, f)) - if tp != expect: - print("File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect)) - errors = errors + 1 - - self.assertFalse(errors) - - -class BaseTestCase(_tempdirTestCase): - def test_stat(self): - """Test the Base.stat() method""" - test = self.test - test.write("e1", "e1\n") - fs = SCons.Node.FS.FS() - - e1 = fs.Entry('e1') - s = e1.stat() - assert s is not None, s - - e2 = fs.Entry('e2') - s = e2.stat() - assert s is None, s - - def test_getmtime(self): - """Test the Base.getmtime() method""" - test = self.test - test.write("file", "file\n") - fs = SCons.Node.FS.FS() - - file = fs.Entry('file') - assert file.getmtime() - - file = fs.Entry('nonexistent') - mtime = file.getmtime() - assert mtime is None, mtime - - def test_getsize(self): - """Test the Base.getsize() method""" - test = self.test - test.write("file", "file\n") - fs = SCons.Node.FS.FS() - - file = fs.Entry('file') - size = file.getsize() - assert size == 5, size - - file = fs.Entry('nonexistent') - size = file.getsize() - assert size is None, size - - def test_isdir(self): - """Test the Base.isdir() method""" - test = self.test - test.subdir('dir') - test.write("file", "file\n") - fs = SCons.Node.FS.FS() - - dir = fs.Entry('dir') - assert dir.isdir() - - file = fs.Entry('file') - assert not file.isdir() - - nonexistent = fs.Entry('nonexistent') - assert not nonexistent.isdir() - - def test_isfile(self): - """Test the Base.isfile() method""" - test = self.test - test.subdir('dir') - test.write("file", "file\n") - fs = SCons.Node.FS.FS() - - dir = fs.Entry('dir') - assert not dir.isfile() - - file = fs.Entry('file') - assert file.isfile() - - nonexistent = fs.Entry('nonexistent') - assert not nonexistent.isfile() - - @unittest.skipUnless(sys.platform != 'win32' and hasattr(os, 'symlink'), - "symlink is not used on Windows") - def test_islink(self): - """Test the Base.islink() method""" - test = self.test - test.subdir('dir') - test.write("file", "file\n") - test.symlink("symlink", "symlink") - fs = SCons.Node.FS.FS() - - dir = fs.Entry('dir') - assert not dir.islink() - - file = fs.Entry('file') - assert not file.islink() - - symlink = fs.Entry('symlink') - assert symlink.islink() - - nonexistent = fs.Entry('nonexistent') - assert not nonexistent.islink() - - -class DirNodeInfoTestCase(_tempdirTestCase): - def test___init__(self): - """Test DirNodeInfo initialization""" - ddd = self.fs.Dir('ddd') - ni = SCons.Node.FS.DirNodeInfo() - - -class DirBuildInfoTestCase(_tempdirTestCase): - def test___init__(self): - """Test DirBuildInfo initialization""" - ddd = self.fs.Dir('ddd') - bi = SCons.Node.FS.DirBuildInfo() - - -class FileNodeInfoTestCase(_tempdirTestCase): - def test___init__(self): - """Test FileNodeInfo initialization""" - fff = self.fs.File('fff') - ni = SCons.Node.FS.FileNodeInfo() - assert isinstance(ni, SCons.Node.FS.FileNodeInfo) - - def test_update(self): - """Test updating a File.NodeInfo with on-disk information""" - test = self.test - fff = self.fs.File('fff') - - ni = SCons.Node.FS.FileNodeInfo() - - test.write('fff', "fff\n") - - st = os.stat('fff') - - ni.update(fff) - - assert hasattr(ni, 'timestamp') - assert hasattr(ni, 'size') - - ni.timestamp = 0 - ni.size = 0 - - ni.update(fff) - - mtime = st[stat.ST_MTIME] - assert ni.timestamp == mtime, (ni.timestamp, mtime) - size = st[stat.ST_SIZE] - assert ni.size == size, (ni.size, size) - - import time - time.sleep(2) - - test.write('fff', "fff longer size, different time stamp\n") - - st = os.stat('fff') - - mtime = st[stat.ST_MTIME] - assert ni.timestamp != mtime, (ni.timestamp, mtime) - size = st[stat.ST_SIZE] - assert ni.size != size, (ni.size, size) - - -class FileBuildInfoTestCase(_tempdirTestCase): - def test___init__(self): - """Test File.BuildInfo initialization""" - fff = self.fs.File('fff') - bi = SCons.Node.FS.FileBuildInfo() - assert bi, bi - - def test_convert_to_sconsign(self): - """Test converting to .sconsign file format""" - fff = self.fs.File('fff') - bi = SCons.Node.FS.FileBuildInfo() - assert hasattr(bi, 'convert_to_sconsign') - - def test_convert_from_sconsign(self): - """Test converting from .sconsign file format""" - fff = self.fs.File('fff') - bi = SCons.Node.FS.FileBuildInfo() - assert hasattr(bi, 'convert_from_sconsign') - - def test_prepare_dependencies(self): - """Test that we have a prepare_dependencies() method""" - fff = self.fs.File('fff') - bi = SCons.Node.FS.FileBuildInfo() - bi.prepare_dependencies() - - def test_format(self): - """Test the format() method""" - f1 = self.fs.File('f1') - bi1 = SCons.Node.FS.FileBuildInfo() - - self.fs.File('n1') - self.fs.File('n2') - self.fs.File('n3') - - s1sig = SCons.Node.FS.FileNodeInfo() - s1sig.csig = 1 - d1sig = SCons.Node.FS.FileNodeInfo() - d1sig.timestamp = 2 - i1sig = SCons.Node.FS.FileNodeInfo() - i1sig.size = 3 - - bi1.bsources = [self.fs.File('s1')] - bi1.bdepends = [self.fs.File('d1')] - bi1.bimplicit = [self.fs.File('i1')] - bi1.bsourcesigs = [s1sig] - bi1.bdependsigs = [d1sig] - bi1.bimplicitsigs = [i1sig] - bi1.bact = 'action' - bi1.bactsig = 'actionsig' - - expect_lines = [ - 's1: 1 None None', - 'd1: None 2 None', - 'i1: None None 3', - 'actionsig [action]', - ] - - expect = '\n'.join(expect_lines) - format = bi1.format() - assert format == expect, (repr(expect), repr(format)) - - -class FSTestCase(_tempdirTestCase): - def test_needs_normpath(self): - """Test the needs_normpath Regular expression - - This test case verifies that the regular expression used to - determine whether a path needs normalization works as - expected. - """ - needs_normpath_match = SCons.Node.FS.needs_normpath_match - - do_not_need_normpath = [ - ".", - "/", - "/a", - "/aa", - "/a/", - "/aa/", - "/a/b", - "/aa/bb", - "/a/b/", - "/aa/bb/", - - "", - "a", - "aa", - "a/", - "aa/", - "a/b", - "aa/bb", - "a/b/", - "aa/bb/", - - "a.", - "a..", - "/a.", - "/a..", - "a./", - "a../", - "/a./", - "/a../", - - ".a", - "..a", - "/.a", - "/..a", - ".a/", - "..a/", - "/.a/", - "/..a/", - ] - for p in do_not_need_normpath: - assert needs_normpath_match(p) is None, p - - needs_normpath = [ - "//", - "//a", - "//aa", - "//a/", - "//a/", - "/aa//", - - "//a/b", - "//aa/bb", - "//a/b/", - "//aa/bb/", - - "/a//b", - "/aa//bb", - "/a/b//", - "/aa/bb//", - - "/a/b//", - "/aa/bb//", - - "a//", - "aa//", - "a//b", - "aa//bb", - "a//b/", - "aa//bb/", - "a/b//", - "aa/bb//", - - "..", - "/.", - "/..", - "./", - "../", - "/./", - "/../", - - "a/.", - "a/..", - "./a", - "../a", - "a/./a", - "a/../a", - ] - for p in needs_normpath: - assert needs_normpath_match(p) is not None, p - - def test_runTest(self): - """Test FS (file system) Node operations - - This test case handles all of the file system node - tests in one environment, so we don't have to set up a - complicated directory structure for each test individually. - """ - test = self.test - - test.subdir('sub', ['sub', 'dir']) - - wp = test.workpath('') - sub = test.workpath('sub', '') - sub_dir = test.workpath('sub', 'dir', '') - sub_dir_foo = test.workpath('sub', 'dir', 'foo', '') - sub_dir_foo_bar = test.workpath('sub', 'dir', 'foo', 'bar', '') - sub_foo = test.workpath('sub', 'foo', '') - - os.chdir(sub_dir) - - fs = SCons.Node.FS.FS() - - e1 = fs.Entry('e1') - assert isinstance(e1, SCons.Node.FS.Entry) - - d1 = fs.Dir('d1') - assert isinstance(d1, SCons.Node.FS.Dir) - assert d1.cwd is d1, d1 - - f1 = fs.File('f1', directory=d1) - assert isinstance(f1, SCons.Node.FS.File) - - d1_f1 = os.path.join('d1', 'f1') - assert f1.get_internal_path() == d1_f1, "f1.path %s != %s" % (f1.get_internal_path(), d1_f1) - assert str(f1) == d1_f1, "str(f1) %s != %s" % (str(f1), d1_f1) - - x1 = d1.File('x1') - assert isinstance(x1, SCons.Node.FS.File) - assert str(x1) == os.path.join('d1', 'x1') - - x2 = d1.Dir('x2') - assert isinstance(x2, SCons.Node.FS.Dir) - assert str(x2) == os.path.join('d1', 'x2') - - x3 = d1.Entry('x3') - assert isinstance(x3, SCons.Node.FS.Entry) - assert str(x3) == os.path.join('d1', 'x3') - - assert d1.File(x1) == x1 - assert d1.Dir(x2) == x2 - assert d1.Entry(x3) == x3 - - x1.cwd = d1 - - x4 = x1.File('x4') - assert str(x4) == os.path.join('d1', 'x4') - - x5 = x1.Dir('x5') - assert str(x5) == os.path.join('d1', 'x5') - - x6 = x1.Entry('x6') - assert str(x6) == os.path.join('d1', 'x6') - x7 = x1.Entry('x7') - assert str(x7) == os.path.join('d1', 'x7') - - assert x1.File(x4) == x4 - assert x1.Dir(x5) == x5 - assert x1.Entry(x6) == x6 - assert x1.Entry(x7) == x7 - - assert x1.Entry(x5) == x5 - try: - x1.File(x5) - except TypeError: - pass - else: - raise Exception("did not catch expected TypeError") - - assert x1.Entry(x4) == x4 - try: - x1.Dir(x4) - except TypeError: - pass - else: - raise Exception("did not catch expected TypeError") - - x6 = x1.File(x6) - assert isinstance(x6, SCons.Node.FS.File) - - x7 = x1.Dir(x7) - assert isinstance(x7, SCons.Node.FS.Dir) - - seps = [os.sep] - if os.sep != '/': - seps = seps + ['/'] - - drive, path = os.path.splitdrive(os.getcwd()) - - def _do_Dir_test(lpath, path_, abspath_, up_path_, sep, fileSys=fs, drive=drive): - dir = fileSys.Dir(lpath.replace('/', sep)) - - if os.sep != '/': - path_ = path_.replace('/', os.sep) - abspath_ = abspath_.replace('/', os.sep) - up_path_ = up_path_.replace('/', os.sep) - - def strip_slash(p, drive=drive): - if p[-1] == os.sep and len(p) > 1: - p = p[:-1] - if p[0] == os.sep: - p = drive + p - return p - - path = strip_slash(path_) - abspath = strip_slash(abspath_) - up_path = strip_slash(up_path_) - - name = abspath.split(os.sep)[-1] - - if not name: - if drive: - name = drive - else: - name = os.sep - - if dir.up() is None: - dir_up_path = dir.get_internal_path() - else: - dir_up_path = dir.up().get_internal_path() - - assert dir.name == name, \ - "dir.name %s != expected name %s" % \ - (dir.name, name) - assert dir.get_internal_path() == path, \ - "dir.path %s != expected path %s" % \ - (dir.get_internal_path(), path) - assert str(dir) == path, \ - "str(dir) %s != expected path %s" % \ - (str(dir), path) - assert dir.get_abspath() == abspath, \ - "dir.abspath %s != expected absolute path %s" % \ - (dir.get_abspath(), abspath) - assert dir_up_path == up_path, \ - "dir.up().path %s != expected parent path %s" % \ - (dir_up_path, up_path) - - for sep in seps: - - def Dir_test(lpath, path_, abspath_, up_path_, sep=sep, func=_do_Dir_test): - return func(lpath, path_, abspath_, up_path_, sep) - - Dir_test('/', '/', '/', '/') - Dir_test('', './', sub_dir, sub) - Dir_test('foo', 'foo/', sub_dir_foo, './') - Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') - Dir_test('/foo', '/foo/', '/foo/', '/') - Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/') - Dir_test('..', sub, sub, wp) - Dir_test('foo/..', './', sub_dir, sub) - Dir_test('../foo', sub_foo, sub_foo, sub) - Dir_test('.', './', sub_dir, sub) - Dir_test('./.', './', sub_dir, sub) - Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') - Dir_test('#../foo', sub_foo, sub_foo, sub) - Dir_test('#/../foo', sub_foo, sub_foo, sub) - Dir_test('#foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') - Dir_test('#/foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/') - Dir_test('#', './', sub_dir, sub) - - try: - f2 = fs.File(sep.join(['f1', 'f2']), directory=d1) - except TypeError as x: - assert str(x) == ("Tried to lookup File '%s' as a Dir." % - d1_f1), x - except: - raise - - try: - dir = fs.Dir(sep.join(['d1', 'f1'])) - except TypeError as x: - assert str(x) == ("Tried to lookup File '%s' as a Dir." % - d1_f1), x - except: - raise - - try: - f2 = fs.File('d1') - except TypeError as x: - assert str(x) == ("Tried to lookup Dir '%s' as a File." % - 'd1'), x - except: - raise - - # Test that just specifying the drive works to identify - # its root directory. - p = os.path.abspath(test.workpath('root_file')) - drive, path = os.path.splitdrive(p) - if drive: - # The assert below probably isn't correct for the general - # case, but it works for Windows, which covers a lot - # of ground... - dir = fs.Dir(drive) - assert str(dir) == drive + os.sep, str(dir) - - # Make sure that lookups with and without the drive are - # equivalent. - p = os.path.abspath(test.workpath('some/file')) - drive, path = os.path.splitdrive(p) - - e1 = fs.Entry(p) - e2 = fs.Entry(path) - assert e1 is e2, (e1, e2) - a = str(e1) - b = str(e2) - assert a == b, ("Strings should match for same file/node\n%s\n%s" % (a, b)) - - # Test for a bug in 0.04 that did not like looking up - # dirs with a trailing slash on Windows. - d = fs.Dir('./') - assert d.get_internal_path() == '.', d.get_abspath() - d = fs.Dir('foo/') - assert d.get_internal_path() == 'foo', d.get_abspath() - - # Test for sub-classing of node building. - global built_it - - built_it = None - assert not built_it - d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE - d1.builder_set(Builder(fs.File)) - d1.reset_executor() - d1.env_set(Environment()) - d1.build() - assert built_it - - built_it = None - assert not built_it - f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE - f1.builder_set(Builder(fs.File)) - f1.reset_executor() - f1.env_set(Environment()) - f1.build() - assert built_it - - def match(path, expect): - expect = expect.replace('/', os.sep) - assert path == expect, "path %s != expected %s" % (path, expect) - - e1 = fs.Entry("d1") - assert e1.__class__.__name__ == 'Dir' - match(e1.get_internal_path(), "d1") - match(e1.dir.get_internal_path(), ".") - - e2 = fs.Entry("d1/f1") - assert e2.__class__.__name__ == 'File' - match(e2.get_internal_path(), "d1/f1") - match(e2.dir.get_internal_path(), "d1") - - e3 = fs.Entry("e3") - assert e3.__class__.__name__ == 'Entry' - match(e3.get_internal_path(), "e3") - match(e3.dir.get_internal_path(), ".") - - e4 = fs.Entry("d1/e4") - assert e4.__class__.__name__ == 'Entry' - match(e4.get_internal_path(), "d1/e4") - match(e4.dir.get_internal_path(), "d1") - - e5 = fs.Entry("e3/e5") - assert e3.__class__.__name__ == 'Dir' - match(e3.get_internal_path(), "e3") - match(e3.dir.get_internal_path(), ".") - assert e5.__class__.__name__ == 'Entry' - match(e5.get_internal_path(), "e3/e5") - match(e5.dir.get_internal_path(), "e3") - - e6 = fs.Dir("d1/e4") - assert e6 is e4 - assert e4.__class__.__name__ == 'Dir' - match(e4.get_internal_path(), "d1/e4") - match(e4.dir.get_internal_path(), "d1") - - e7 = fs.File("e3/e5") - assert e7 is e5 - assert e5.__class__.__name__ == 'File' - match(e5.get_internal_path(), "e3/e5") - match(e5.dir.get_internal_path(), "e3") - - fs.chdir(fs.Dir('subdir')) - f11 = fs.File("f11") - match(f11.get_internal_path(), "subdir/f11") - d12 = fs.Dir("d12") - e13 = fs.Entry("subdir/e13") - match(e13.get_internal_path(), "subdir/subdir/e13") - fs.chdir(fs.Dir('..')) - - # Test scanning - f1.builder_set(Builder(fs.File)) - f1.env_set(Environment()) - xyz = fs.File("xyz") - f1.builder.target_scanner = Scanner(xyz) - - f1.scan() - assert f1.implicit[0].get_internal_path() == "xyz" - f1.implicit = [] - f1.scan() - assert f1.implicit == [] - f1.implicit = None - f1.scan() - assert f1.implicit[0].get_internal_path() == "xyz" - - # Test underlying scanning functionality in get_found_includes() - env = Environment() - f12 = fs.File("f12") - t1 = fs.File("t1") - - deps = f12.get_found_includes(env, None, t1) - assert deps == [], deps - - class MyScanner(Scanner): - call_count = 0 - - def __call__(self, node, env, path): - self.call_count = self.call_count + 1 - return Scanner.__call__(self, node, env, path) - - s = MyScanner(xyz) - - deps = f12.get_found_includes(env, s, t1) - assert deps == [xyz], deps - assert s.call_count == 1, s.call_count - - f12.built() - - deps = f12.get_found_includes(env, s, t1) - assert deps == [xyz], deps - assert s.call_count == 2, s.call_count - - env2 = Environment() - - deps = f12.get_found_includes(env2, s, t1) - assert deps == [xyz], deps - assert s.call_count == 3, s.call_count - - # Make sure we can scan this file even if the target isn't - # a file that has a scanner (it might be an Alias, e.g.). - class DummyNode: - pass - - deps = f12.get_found_includes(env, s, DummyNode()) - assert deps == [xyz], deps - - # Test building a file whose directory is not there yet... - f1 = fs.File(test.workpath("foo/bar/baz/ack")) - assert not f1.dir.exists() - f1.prepare() - f1.build() - assert f1.dir.exists() - - os.chdir('..') - - # Test getcwd() - fs = SCons.Node.FS.FS() - assert str(fs.getcwd()) == ".", str(fs.getcwd()) - fs.chdir(fs.Dir('subdir')) - # The cwd's path is always "." - assert str(fs.getcwd()) == ".", str(fs.getcwd()) - assert fs.getcwd().get_internal_path() == 'subdir', fs.getcwd().get_internal_path() - fs.chdir(fs.Dir('../..')) - assert fs.getcwd().get_internal_path() == test.workdir, fs.getcwd().get_internal_path() - - f1 = fs.File(test.workpath("do_i_exist")) - assert not f1.exists() - test.write("do_i_exist", "\n") - assert not f1.exists(), "exists() call not cached" - f1.built() - assert f1.exists(), "exists() call caching not reset" - test.unlink("do_i_exist") - assert f1.exists() - f1.built() - assert not f1.exists() - - # For some reason, in Windows, the \x1a character terminates - # the reading of files in text mode. This tests that - # get_contents() returns the binary contents. - test.write("binary_file", "Foo\x1aBar") - f1 = fs.File(test.workpath("binary_file")) - assert f1.get_contents() == bytearray("Foo\x1aBar", 'utf-8'), \ - f1.get_contents() - - # This tests to make sure we can decode UTF-8 text files. - test_string = "Foo\x1aBar" - test.write("utf8_file", test_string.encode('utf-8')) - f1 = fs.File(test.workpath("utf8_file")) - assert f1.get_text_contents() == "Foo\x1aBar", \ - f1.get_text_contents() - - # Check for string which doesn't have BOM and isn't valid - # ASCII - test_string = b'Gan\xdfauge' - test.write('latin1_file', test_string) - f1 = fs.File(test.workpath("latin1_file")) - assert f1.get_text_contents() == test_string.decode('latin-1'), \ - f1.get_text_contents() - - def nonexistent(method, s): - try: - x = method(s, create=0) - except SCons.Errors.UserError: - pass - else: - raise Exception("did not catch expected UserError") - - nonexistent(fs.Entry, 'nonexistent') - nonexistent(fs.Entry, 'nonexistent/foo') - - nonexistent(fs.File, 'nonexistent') - nonexistent(fs.File, 'nonexistent/foo') - - nonexistent(fs.Dir, 'nonexistent') - nonexistent(fs.Dir, 'nonexistent/foo') - - test.write("preserve_me", "\n") - assert os.path.exists(test.workpath("preserve_me")) - f1 = fs.File(test.workpath("preserve_me")) - f1.prepare() - assert os.path.exists(test.workpath("preserve_me")) - - test.write("remove_me", "\n") - assert os.path.exists(test.workpath("remove_me")) - f1 = fs.File(test.workpath("remove_me")) - f1.builder = Builder(fs.File) - f1.env_set(Environment()) - f1.prepare() - assert not os.path.exists(test.workpath("remove_me")) - - e = fs.Entry('e_local') - assert not hasattr(e, '_local') - e.set_local() - assert e._local == 1 - f = fs.File('e_local') - assert f._local == 1 - f = fs.File('f_local') - assert f._local == 0 - - # XXX test_is_up_to_date() for directories - - # XXX test_sconsign() for directories - - # XXX test_set_signature() for directories - - # XXX test_build() for directories - - # XXX test_root() - - # test Entry.get_contents() - e = fs.Entry('does_not_exist') - c = e.get_contents() - assert c == "", c - assert e.__class__ == SCons.Node.FS.Entry - - test.write("file", "file\n") - try: - e = fs.Entry('file') - c = e.get_contents() - assert c == bytearray("file\n", 'utf-8'), c - assert e.__class__ == SCons.Node.FS.File - finally: - test.unlink("file") - - # test Entry.get_text_contents() - e = fs.Entry('does_not_exist') - c = e.get_text_contents() - assert c == "", c - assert e.__class__ == SCons.Node.FS.Entry - - test.write("file", "file\n") - try: - e = fs.Entry('file') - c = e.get_text_contents() - assert c == "file\n", c - assert e.__class__ == SCons.Node.FS.File - finally: - test.unlink("file") - - test.subdir("dir") - e = fs.Entry('dir') - c = e.get_contents() - assert c == "", c - assert e.__class__ == SCons.Node.FS.Dir - - c = e.get_text_contents() - try: - eval('assert c == "", c') - except SyntaxError: - assert c == "" - - if sys.platform != 'win32' and hasattr(os, 'symlink'): - os.symlink('nonexistent', test.workpath('dangling_symlink')) - e = fs.Entry('dangling_symlink') - c = e.get_contents() - assert e.__class__ == SCons.Node.FS.Entry, e.__class__ - assert c == "", c - c = e.get_text_contents() - assert c == "", c - - test.write("tstamp", "tstamp\n") - try: - # Okay, *this* manipulation accomodates Windows FAT file systems - # that only have two-second granularity on their timestamps. - # We round down the current time to the nearest even integer - # value, subtract two to make sure the timestamp is not "now," - # and then convert it back to a float. - tstamp = float(int(time.time() // 2) * 2) - 2.0 - os.utime(test.workpath("tstamp"), (tstamp - 2.0, tstamp)) - f = fs.File("tstamp") - t = f.get_timestamp() - assert t == tstamp, "expected %f, got %f" % (tstamp, t) - finally: - test.unlink("tstamp") - - test.subdir('tdir1') - d = fs.Dir('tdir1') - t = d.get_timestamp() - assert t == 0, "expected 0, got %s" % str(t) - - test.subdir('tdir2') - f1 = test.workpath('tdir2', 'file1') - f2 = test.workpath('tdir2', 'file2') - test.write(f1, 'file1\n') - test.write(f2, 'file2\n') - current_time = float(int(time.time() // 2) * 2) - t1 = current_time - 4.0 - t2 = current_time - 2.0 - os.utime(f1, (t1 - 2.0, t1)) - os.utime(f2, (t2 - 2.0, t2)) - d = fs.Dir('tdir2') - fs.File(f1) - fs.File(f2) - t = d.get_timestamp() - assert t == t2, "expected %f, got %f" % (t2, t) - - skey = fs.Entry('eee.x').scanner_key() - assert skey == '.x', skey - skey = fs.Entry('eee.xyz').scanner_key() - assert skey == '.xyz', skey - - skey = fs.File('fff.x').scanner_key() - assert skey == '.x', skey - skey = fs.File('fff.xyz').scanner_key() - assert skey == '.xyz', skey - - skey = fs.Dir('ddd.x').scanner_key() - assert skey is None, skey - - test.write("i_am_not_a_directory", "\n") - try: - exc_caught = 0 - try: - fs.Dir(test.workpath("i_am_not_a_directory")) - except TypeError: - exc_caught = 1 - assert exc_caught, "Should have caught a TypeError" - finally: - test.unlink("i_am_not_a_directory") - - exc_caught = 0 - try: - fs.File(sub_dir) - except TypeError: - exc_caught = 1 - assert exc_caught, "Should have caught a TypeError" - - # XXX test_is_up_to_date() - - d = fs.Dir('dir') - r = d.remove() - assert r is None, r - - f = fs.File('does_not_exist') - r = f.remove() - assert r is None, r - - test.write('exists', "exists\n") - f = fs.File('exists') - r = f.remove() - assert r, r - assert not os.path.exists(test.workpath('exists')), "exists was not removed" - - if sys.platform != 'win32' and hasattr(os, 'symlink'): - symlink = test.workpath('symlink') - os.symlink(test.workpath('does_not_exist'), symlink) - assert os.path.islink(symlink) - f = fs.File('symlink') - r = f.remove() - assert r, r - assert not os.path.islink(symlink), "symlink was not removed" - - test.write('can_not_remove', "can_not_remove\n") - test.writable(test.workpath('.'), 0) - fp = open(test.workpath('can_not_remove')) - - f = fs.File('can_not_remove') - exc_caught = 0 - try: - r = f.remove() - except OSError: - exc_caught = 1 - - fp.close() - - assert exc_caught, "Should have caught an OSError, r = " + str(r) - - f = fs.Entry('foo/bar/baz') - assert f.for_signature() == 'baz', f.for_signature() - assert f.get_string(0) == os.path.normpath('foo/bar/baz'), \ - f.get_string(0) - assert f.get_string(1) == 'baz', f.get_string(1) - - def test_drive_letters(self): - """Test drive-letter look-ups""" - - test = self.test - - test.subdir('sub', ['sub', 'dir']) - - def drive_workpath(dirs, test=test): - x = test.workpath(*dirs) - drive, path = os.path.splitdrive(x) - return 'X:' + path - - wp = drive_workpath(['']) - - if wp[-1] in (os.sep, '/'): - tmp = os.path.split(wp[:-1])[0] - else: - tmp = os.path.split(wp)[0] - - parent_tmp = os.path.split(tmp)[0] - if parent_tmp == 'X:': - parent_tmp = 'X:' + os.sep - - tmp_foo = os.path.join(tmp, 'foo') - - foo = drive_workpath(['foo']) - foo_bar = drive_workpath(['foo', 'bar']) - sub = drive_workpath(['sub', '']) - sub_dir = drive_workpath(['sub', 'dir', '']) - sub_dir_foo = drive_workpath(['sub', 'dir', 'foo', '']) - sub_dir_foo_bar = drive_workpath(['sub', 'dir', 'foo', 'bar', '']) - sub_foo = drive_workpath(['sub', 'foo', '']) - - fs = SCons.Node.FS.FS() - - seps = [os.sep] - if os.sep != '/': - seps = seps + ['/'] - - def _do_Dir_test(lpath, path_, up_path_, sep, fileSys=fs): - dir = fileSys.Dir(lpath.replace('/', sep)) - - if os.sep != '/': - path_ = path_.replace('/', os.sep) - up_path_ = up_path_.replace('/', os.sep) - - def strip_slash(p): - if p[-1] == os.sep and len(p) > 3: - p = p[:-1] - return p - - path = strip_slash(path_) - up_path = strip_slash(up_path_) - name = path.split(os.sep)[-1] - - assert dir.name == name, \ - "dir.name %s != expected name %s" % \ - (dir.name, name) - assert dir.get_internal_path() == path, \ - "dir.path %s != expected path %s" % \ - (dir.get_internal_path(), path) - assert str(dir) == path, \ - "str(dir) %s != expected path %s" % \ - (str(dir), path) - assert dir.up().get_internal_path() == up_path, \ - "dir.up().path %s != expected parent path %s" % \ - (dir.up().get_internal_path(), up_path) - - save_os_path = os.path - save_os_sep = os.sep - try: - import ntpath - os.path = ntpath - os.sep = '\\' - SCons.Node.FS.initialize_do_splitdrive() - - for sep in seps: - def Dir_test(lpath, path_, up_path_, sep=sep, func=_do_Dir_test): - return func(lpath, path_, up_path_, sep) - - Dir_test('#X:', wp, tmp) - Dir_test('X:foo', foo, wp) - Dir_test('X:foo/bar', foo_bar, foo) - Dir_test('X:/foo', 'X:/foo', 'X:/') - Dir_test('X:/foo/bar', 'X:/foo/bar/', 'X:/foo/') - Dir_test('X:..', tmp, parent_tmp) - Dir_test('X:foo/..', wp, tmp) - Dir_test('X:../foo', tmp_foo, tmp) - Dir_test('X:.', wp, tmp) - Dir_test('X:./.', wp, tmp) - Dir_test('X:foo/./bar', foo_bar, foo) - Dir_test('#X:../foo', tmp_foo, tmp) - Dir_test('#X:/../foo', tmp_foo, tmp) - Dir_test('#X:foo/bar', foo_bar, foo) - Dir_test('#X:/foo/bar', foo_bar, foo) - Dir_test('#X:/', wp, tmp) - finally: - os.path = save_os_path - os.sep = save_os_sep - SCons.Node.FS.initialize_do_splitdrive() - - def test_unc_path(self): - """Test UNC path look-ups""" - - test = self.test - - test.subdir('sub', ['sub', 'dir']) - - def strip_slash(p): - if p[-1] == os.sep and len(p) > 3: - p = p[:-1] - return p - - def unc_workpath(dirs, test=test): - import ntpath - x = test.workpath(*dirs) - drive, path = ntpath.splitdrive(x) - try: - unc, path = ntpath.splitunc(path) - except AttributeError: - # could be python 3.7 or newer, make sure splitdrive can do UNC - assert ntpath.splitdrive(r'\\split\drive\test')[0] == r'\\split\drive' - path = strip_slash(path) - return '//' + path[1:] - - wp = unc_workpath(['']) - - if wp[-1] in (os.sep, '/'): - tmp = os.path.split(wp[:-1])[0] - else: - tmp = os.path.split(wp)[0] - - parent_tmp = os.path.split(tmp)[0] - - tmp_foo = os.path.join(tmp, 'foo') - - foo = unc_workpath(['foo']) - foo_bar = unc_workpath(['foo', 'bar']) - sub = unc_workpath(['sub', '']) - sub_dir = unc_workpath(['sub', 'dir', '']) - sub_dir_foo = unc_workpath(['sub', 'dir', 'foo', '']) - sub_dir_foo_bar = unc_workpath(['sub', 'dir', 'foo', 'bar', '']) - sub_foo = unc_workpath(['sub', 'foo', '']) - - fs = SCons.Node.FS.FS() - - seps = [os.sep] - if os.sep != '/': - seps = seps + ['/'] - - def _do_Dir_test(lpath, path, up_path, sep, fileSys=fs): - dir = fileSys.Dir(lpath.replace('/', sep)) - - if os.sep != '/': - path = path.replace('/', os.sep) - up_path = up_path.replace('/', os.sep) - - if path == os.sep + os.sep: - name = os.sep + os.sep - else: - name = path.split(os.sep)[-1] - - if dir.up() is None: - dir_up_path = dir.get_internal_path() - else: - dir_up_path = dir.up().get_internal_path() - - assert dir.name == name, \ - "dir.name %s != expected name %s" % \ - (dir.name, name) - assert dir.get_internal_path() == path, \ - "dir.path %s != expected path %s" % \ - (dir.get_internal_path(), path) - assert str(dir) == path, \ - "str(dir) %s != expected path %s" % \ - (str(dir), path) - assert dir_up_path == up_path, \ - "dir.up().path %s != expected parent path %s" % \ - (dir.up().get_internal_path(), up_path) - - save_os_path = os.path - save_os_sep = os.sep - try: - import ntpath - os.path = ntpath - os.sep = '\\' - SCons.Node.FS.initialize_do_splitdrive() - - for sep in seps: - def Dir_test(lpath, path_, up_path_, sep=sep, func=_do_Dir_test): - return func(lpath, path_, up_path_, sep) - - Dir_test('//foo', '//foo', '//') - Dir_test('//foo/bar', '//foo/bar', '//foo') - Dir_test('//', '//', '//') - Dir_test('//..', '//', '//') - Dir_test('//foo/..', '//', '//') - Dir_test('//../foo', '//foo', '//') - Dir_test('//.', '//', '//') - Dir_test('//./.', '//', '//') - Dir_test('//foo/./bar', '//foo/bar', '//foo') - Dir_test('//foo/../bar', '//bar', '//') - Dir_test('//foo/../../bar', '//bar', '//') - Dir_test('//foo/bar/../..', '//', '//') - Dir_test('#//', wp, tmp) - Dir_test('#//../foo', tmp_foo, tmp) - Dir_test('#//../foo', tmp_foo, tmp) - Dir_test('#//foo/bar', foo_bar, foo) - Dir_test('#//foo/bar', foo_bar, foo) - Dir_test('#//', wp, tmp) - finally: - os.path = save_os_path - os.sep = save_os_sep - SCons.Node.FS.initialize_do_splitdrive() - - def test_target_from_source(self): - """Test the method for generating target nodes from sources""" - fs = self.fs - - x = fs.File('x.c') - t = x.target_from_source('pre-', '-suf') - assert str(t) == 'pre-x-suf', str(t) - assert t.__class__ == SCons.Node.FS.Entry - - y = fs.File('dir/y') - t = y.target_from_source('pre-', '-suf') - assert str(t) == os.path.join('dir', 'pre-y-suf'), str(t) - assert t.__class__ == SCons.Node.FS.Entry - - z = fs.File('zz') - t = z.target_from_source('pre-', '-suf', lambda x: x[:-1]) - assert str(t) == 'pre-z-suf', str(t) - assert t.__class__ == SCons.Node.FS.Entry - - d = fs.Dir('ddd') - t = d.target_from_source('pre-', '-suf') - assert str(t) == 'pre-ddd-suf', str(t) - assert t.__class__ == SCons.Node.FS.Entry - - e = fs.Entry('eee') - t = e.target_from_source('pre-', '-suf') - assert str(t) == 'pre-eee-suf', str(t) - assert t.__class__ == SCons.Node.FS.Entry - - def test_same_name(self): - """Test that a local same-named file isn't found for a Dir lookup""" - test = self.test - fs = self.fs - - test.subdir('subdir') - test.write(['subdir', 'build'], "subdir/build\n") - - subdir = fs.Dir('subdir') - fs.chdir(subdir, change_os_dir=1) - self.fs._lookup('#build/file', subdir, SCons.Node.FS.File) - - def test_above_root(self): - """Testing looking up a path above the root directory""" - test = self.test - fs = self.fs - - d1 = fs.Dir('d1') - d2 = d1.Dir('d2') - dirs = os.path.normpath(d2.get_abspath()).split(os.sep) - above_path = os.path.join(*['..'] * len(dirs) + ['above']) - above = d2.Dir(above_path) - - def test_lookup_abs(self): - """Exercise the _lookup_abs function""" - test = self.test - fs = self.fs - - root = fs.Dir('/') - d = root._lookup_abs('/tmp/foo-nonexistent/nonexistent-dir', SCons.Node.FS.Dir) - assert d.__class__ == SCons.Node.FS.Dir, str(d.__class__) - - @unittest.skipUnless(sys.platform == "win32", "requires Windows") - def test_lookup_uncpath(self): - """Testing looking up a UNC path on Windows""" - test = self.test - fs = self.fs - path = '//servername/C$/foo' - f = self.fs._lookup('//servername/C$/foo', fs.Dir('#'), SCons.Node.FS.File) - # before the fix in this commit, this returned 'C:\servername\C$\foo' - # Should be a normalized Windows UNC path as below. - assert str(f) == r'\\servername\C$\foo', \ - 'UNC path %s got looked up as %s' % (path, f) - - @unittest.skipUnless(sys.platform.startswith == "win32", "requires Windows") - def test_unc_drive_letter(self): - """Test drive-letter lookup for windows UNC-style directories""" - share = self.fs.Dir(r'\\SERVER\SHARE\Directory') - assert str(share) == r'\\SERVER\SHARE\Directory', str(share) - - @unittest.skipUnless(sys.platform == "win32", "requires Windows") - def test_UNC_dirs_2689(self): - """Test some UNC dirs that printed incorrectly and/or caused - infinite recursion errors prior to r5180 (SCons 2.1).""" - fs = self.fs - p = fs.Dir(r"\\computername\sharename").get_abspath() - assert p == r"\\computername\sharename", p - p = fs.Dir(r"\\\computername\sharename").get_abspath() - assert p == r"\\computername\sharename", p - - def test_rel_path(self): - """Test the rel_path() method""" - test = self.test - fs = self.fs - - d1 = fs.Dir('d1') - d1_f = d1.File('f') - d1_d2 = d1.Dir('d2') - d1_d2_f = d1_d2.File('f') - - d3 = fs.Dir('d3') - d3_f = d3.File('f') - d3_d4 = d3.Dir('d4') - d3_d4_f = d3_d4.File('f') - - cases = [ - d1, d1, '.', - d1, d1_f, 'f', - d1, d1_d2, 'd2', - d1, d1_d2_f, 'd2/f', - d1, d3, '../d3', - d1, d3_f, '../d3/f', - d1, d3_d4, '../d3/d4', - d1, d3_d4_f, '../d3/d4/f', - - d1_f, d1, '.', - d1_f, d1_f, 'f', - d1_f, d1_d2, 'd2', - d1_f, d1_d2_f, 'd2/f', - d1_f, d3, '../d3', - d1_f, d3_f, '../d3/f', - d1_f, d3_d4, '../d3/d4', - d1_f, d3_d4_f, '../d3/d4/f', - - d1_d2, d1, '..', - d1_d2, d1_f, '../f', - d1_d2, d1_d2, '.', - d1_d2, d1_d2_f, 'f', - d1_d2, d3, '../../d3', - d1_d2, d3_f, '../../d3/f', - d1_d2, d3_d4, '../../d3/d4', - d1_d2, d3_d4_f, '../../d3/d4/f', - - d1_d2_f, d1, '..', - d1_d2_f, d1_f, '../f', - d1_d2_f, d1_d2, '.', - d1_d2_f, d1_d2_f, 'f', - d1_d2_f, d3, '../../d3', - d1_d2_f, d3_f, '../../d3/f', - d1_d2_f, d3_d4, '../../d3/d4', - d1_d2_f, d3_d4_f, '../../d3/d4/f', - ] - - if sys.platform in ('win32',): - x_d1 = fs.Dir(r'X:\d1') - x_d1_d2 = x_d1.Dir('d2') - y_d1 = fs.Dir(r'Y:\d1') - y_d1_d2 = y_d1.Dir('d2') - y_d2 = fs.Dir(r'Y:\d2') - - win32_cases = [ - x_d1, x_d1, '.', - x_d1, x_d1_d2, 'd2', - x_d1, y_d1, r'Y:\d1', - x_d1, y_d1_d2, r'Y:\d1\d2', - x_d1, y_d2, r'Y:\d2', - ] - - cases.extend(win32_cases) - - failed = 0 - while cases: - dir, other, expect = cases[:3] - expect = os.path.normpath(expect) - del cases[:3] - result = dir.rel_path(other) - if result != expect: - if failed == 0: print() - fmt = " dir_path(%(dir)s, %(other)s) => '%(result)s' did not match '%(expect)s'" - print(fmt % locals()) - failed = failed + 1 - assert failed == 0, "%d rel_path() cases failed" % failed - - def test_proxy(self): - """Test a Node.FS object wrapped in a proxy instance""" - f1 = self.fs.File('fff') - - class MyProxy(SCons.Util.Proxy): - __str__ = SCons.Util.Delegate('__str__') - - p = MyProxy(f1) - f2 = self.fs.Entry(p) - assert f1 is f2, (f1, str(f1), f2, str(f2)) - - -class DirTestCase(_tempdirTestCase): - - def test__morph(self): - """Test handling of actions when morphing an Entry into a Dir""" - test = self.test - e = self.fs.Entry('eee') - x = e.get_executor() - x.add_pre_action('pre') - x.add_post_action('post') - e.must_be_same(SCons.Node.FS.Dir) - a = x.get_action_list() - assert 'pre' in a, a - assert 'post' in a, a - - def test_subclass(self): - """Test looking up subclass of Dir nodes""" - - class DirSubclass(SCons.Node.FS.Dir): - pass - - sd = self.fs._lookup('special_dir', None, DirSubclass, create=1) - sd.must_be_same(SCons.Node.FS.Dir) - - def test_get_env_scanner(self): - """Test the Dir.get_env_scanner() method - """ - import SCons.Defaults - d = self.fs.Dir('ddd') - s = d.get_env_scanner(Environment()) - assert s is SCons.Defaults.DirEntryScanner, s - - def test_get_target_scanner(self): - """Test the Dir.get_target_scanner() method - """ - import SCons.Defaults - d = self.fs.Dir('ddd') - s = d.get_target_scanner() - assert s is SCons.Defaults.DirEntryScanner, s - - def test_scan(self): - """Test scanning a directory for in-memory entries - """ - fs = self.fs - - dir = fs.Dir('ddd') - fs.File(os.path.join('ddd', 'f1')) - fs.File(os.path.join('ddd', 'f2')) - fs.File(os.path.join('ddd', 'f3')) - fs.Dir(os.path.join('ddd', 'd1')) - fs.Dir(os.path.join('ddd', 'd1', 'f4')) - fs.Dir(os.path.join('ddd', 'd1', 'f5')) - dir.scan() - kids = sorted([x.get_internal_path() for x in dir.children(None)]) - assert kids == [os.path.join('ddd', 'd1'), - os.path.join('ddd', 'f1'), - os.path.join('ddd', 'f2'), - os.path.join('ddd', 'f3')], kids - - def test_get_contents(self): - """Test getting the contents for a directory. - """ - test = self.test - - test.subdir('d') - test.write(['d', 'g'], "67890\n") - test.write(['d', 'f'], "12345\n") - test.subdir(['d', 'sub']) - test.write(['d', 'sub', 'h'], "abcdef\n") - test.subdir(['d', 'empty']) - - d = self.fs.Dir('d') - g = self.fs.File(os.path.join('d', 'g')) - f = self.fs.File(os.path.join('d', 'f')) - h = self.fs.File(os.path.join('d', 'sub', 'h')) - e = self.fs.Dir(os.path.join('d', 'empty')) - s = self.fs.Dir(os.path.join('d', 'sub')) - - files = d.get_contents().split('\n') - - assert e.get_contents() == '', e.get_contents() - assert e.get_text_contents() == '', e.get_text_contents() - assert e.get_csig() + " empty" == files[0], files - assert f.get_csig() + " f" == files[1], files - assert g.get_csig() + " g" == files[2], files - assert s.get_csig() + " sub" == files[3], files - - def test_hash_chunksize(self): - """ - Test verifying that File.get_csig() correctly uses hash_chunksize. This - variable is documented as the hash chunksize in kilobytes. This test - verifies that if the file size is less than the hash chunksize, - get_contents() is called; otherwise, it verifies that get_contents() - is not called. - """ - chunksize_bytes = SCons.Node.FS.File.hash_chunksize - test = self.test - - test.subdir('chunksize_dir') - test.write(['chunksize_dir', 'f1'], 'a' * (chunksize_bytes // 1024 - 1)) - test.write(['chunksize_dir', 'f2'], 'a' * (chunksize_bytes // 1024)) - test.write(['chunksize_dir', 'f3'], 'a' * (chunksize_bytes + 1)) - - dir = self.fs.Dir('chunksize_dir') - f1 = dir.File('f1') - f2 = dir.File('f2') - f3 = dir.File('f3') - - # Expect f1 and f2 to call get_contents(), while f3 will not because it - # should do reads of chunksize kilobytes at a time. - expected_get_contents_calls = {f1, f2} - self.actual_get_contents_calls = 0 - - def get_contents_override(file_object): - self.actual_get_contents_calls += 1 - if file_object in expected_get_contents_calls: - return file_object._old_get_contents() - else: - raise Exception('get_contents was unexpectedly called on node ' - '%s' % file_object) - - SCons.Node.FS.File._old_get_contents = SCons.Node.FS.File.get_contents - SCons.Node.FS.File.get_contents = get_contents_override.__get__( - None, SCons.Node.FS) - - # Call get_csig() to test get_contents() usage. The actual results of - # the calls to get_csig() are not relevant for this test. If an - # exception is raised, we must first reset the get_contents function - # before reraising it or other tests will fail too. - exception = None - try: - f1.get_csig() - f2.get_csig() - f3.get_csig() - except Exception as e: - exception = e - - SCons.Node.FS.File.get_contents = SCons.Node.FS.File._old_get_contents - delattr(SCons.Node.FS.File, '_old_get_contents') - - if exception: - raise exception - - assert self.actual_get_contents_calls == len(expected_get_contents_calls), \ - self.actual_get_contents_calls - - def test_implicit_re_scans(self): - """Test that adding entries causes a directory to be re-scanned - """ - - fs = self.fs - - dir = fs.Dir('ddd') - - fs.File(os.path.join('ddd', 'f1')) - dir.scan() - kids = sorted([x.get_internal_path() for x in dir.children()]) - assert kids == [os.path.join('ddd', 'f1')], kids - - fs.File(os.path.join('ddd', 'f2')) - dir.scan() - kids = sorted([x.get_internal_path() for x in dir.children()]) - assert kids == [os.path.join('ddd', 'f1'), - os.path.join('ddd', 'f2')], kids - - def test_entry_exists_on_disk(self): - """Test the Dir.entry_exists_on_disk() method - """ - test = self.test - - does_not_exist = self.fs.Dir('does_not_exist') - assert not does_not_exist.entry_exists_on_disk('foo') - - test.subdir('d') - test.write(['d', 'exists'], "d/exists\n") - test.write(['d', 'Case-Insensitive'], "d/Case-Insensitive\n") - - d = self.fs.Dir('d') - assert d.entry_exists_on_disk('exists') - assert not d.entry_exists_on_disk('does_not_exist') - - if os.path.normcase("TeSt") != os.path.normpath("TeSt") or sys.platform == "cygwin": - assert d.entry_exists_on_disk('case-insensitive') - - def test_rentry_exists_on_disk(self): - """Test the Dir.rentry_exists_on_disk() method - """ - test = self.test - - does_not_exist = self.fs.Dir('does_not_exist') - assert not does_not_exist.rentry_exists_on_disk('foo') - - test.subdir('d') - test.write(['d', 'exists'], "d/exists\n") - test.write(['d', 'Case-Insensitive'], "d/Case-Insensitive\n") - - test.subdir('r') - test.write(['r', 'rexists'], "r/rexists\n") - - d = self.fs.Dir('d') - r = self.fs.Dir('r') - d.addRepository(r) - - assert d.rentry_exists_on_disk('exists') - assert d.rentry_exists_on_disk('rexists') - assert not d.rentry_exists_on_disk('does_not_exist') - - if os.path.normcase("TeSt") != os.path.normpath("TeSt") or sys.platform == "cygwin": - assert d.rentry_exists_on_disk('case-insensitive') - - def test_srcdir_list(self): - """Test the Dir.srcdir_list() method - """ - src = self.fs.Dir('src') - bld = self.fs.Dir('bld') - sub1 = bld.Dir('sub') - sub2 = sub1.Dir('sub') - sub3 = sub2.Dir('sub') - self.fs.VariantDir(bld, src, duplicate=0) - self.fs.VariantDir(sub2, src, duplicate=0) - - def check(result, expect): - result = list(map(str, result)) - expect = list(map(os.path.normpath, expect)) - assert result == expect, result - - s = src.srcdir_list() - check(s, []) - - s = bld.srcdir_list() - check(s, ['src']) - - s = sub1.srcdir_list() - check(s, ['src/sub']) - - s = sub2.srcdir_list() - check(s, ['src', 'src/sub/sub']) - - s = sub3.srcdir_list() - check(s, ['src/sub', 'src/sub/sub/sub']) - - self.fs.VariantDir('src/b1/b2', 'src') - b1 = src.Dir('b1') - b1_b2 = b1.Dir('b2') - b1_b2_b1 = b1_b2.Dir('b1') - b1_b2_b1_b2 = b1_b2_b1.Dir('b2') - b1_b2_b1_b2_sub = b1_b2_b1_b2.Dir('sub') - - s = b1.srcdir_list() - check(s, []) - - s = b1_b2.srcdir_list() - check(s, ['src']) - - s = b1_b2_b1.srcdir_list() - check(s, ['src/b1']) - - s = b1_b2_b1_b2.srcdir_list() - check(s, ['src/b1/b2']) - - s = b1_b2_b1_b2_sub.srcdir_list() - check(s, ['src/b1/b2/sub']) - - def test_srcdir_duplicate(self): - """Test the Dir.srcdir_duplicate() method - """ - test = self.test - - test.subdir('src0') - test.write(['src0', 'exists'], "src0/exists\n") - - bld0 = self.fs.Dir('bld0') - src0 = self.fs.Dir('src0') - self.fs.VariantDir(bld0, src0, duplicate=0) - - n = bld0.srcdir_duplicate('does_not_exist') - assert n is None, n - assert not os.path.exists(test.workpath('bld0', 'does_not_exist')) - - n = bld0.srcdir_duplicate('exists') - assert str(n) == os.path.normpath('src0/exists'), str(n) - assert not os.path.exists(test.workpath('bld0', 'exists')) - - test.subdir('src1') - test.write(['src1', 'exists'], "src0/exists\n") - - bld1 = self.fs.Dir('bld1') - src1 = self.fs.Dir('src1') - self.fs.VariantDir(bld1, src1, duplicate=1) - - n = bld1.srcdir_duplicate('does_not_exist') - assert n is None, n - assert not os.path.exists(test.workpath('bld1', 'does_not_exist')) - - n = bld1.srcdir_duplicate('exists') - assert str(n) == os.path.normpath('bld1/exists'), str(n) - assert os.path.exists(test.workpath('bld1', 'exists')) - - def test_srcdir_find_file(self): - """Test the Dir.srcdir_find_file() method - """ - test = self.test - - def return_true(node): - return 1 - - SCons.Node._is_derived_map[2] = return_true - SCons.Node._exists_map[5] = return_true - - test.subdir('src0') - test.write(['src0', 'on-disk-f1'], "src0/on-disk-f1\n") - test.write(['src0', 'on-disk-f2'], "src0/on-disk-f2\n") - test.write(['src0', 'on-disk-e1'], "src0/on-disk-e1\n") - test.write(['src0', 'on-disk-e2'], "src0/on-disk-e2\n") - - bld0 = self.fs.Dir('bld0') - src0 = self.fs.Dir('src0') - self.fs.VariantDir(bld0, src0, duplicate=0) - - derived_f = src0.File('derived-f') - derived_f._func_is_derived = 2 - exists_f = src0.File('exists-f') - exists_f._func_exists = 5 - - derived_e = src0.Entry('derived-e') - derived_e._func_is_derived = 2 - exists_e = src0.Entry('exists-e') - exists_e._func_exists = 5 - - def check(result, expect): - result = list(map(str, result)) - expect = list(map(os.path.normpath, expect)) - assert result == expect, result - - # First check from the source directory. - n = src0.srcdir_find_file('does_not_exist') - assert n == (None, None), n - - n = src0.srcdir_find_file('derived-f') - check(n, ['src0/derived-f', 'src0']) - n = src0.srcdir_find_file('exists-f') - check(n, ['src0/exists-f', 'src0']) - n = src0.srcdir_find_file('on-disk-f1') - check(n, ['src0/on-disk-f1', 'src0']) - - n = src0.srcdir_find_file('derived-e') - check(n, ['src0/derived-e', 'src0']) - n = src0.srcdir_find_file('exists-e') - check(n, ['src0/exists-e', 'src0']) - n = src0.srcdir_find_file('on-disk-e1') - check(n, ['src0/on-disk-e1', 'src0']) - - # Now check from the variant directory. - n = bld0.srcdir_find_file('does_not_exist') - assert n == (None, None), n - - n = bld0.srcdir_find_file('derived-f') - check(n, ['src0/derived-f', 'bld0']) - n = bld0.srcdir_find_file('exists-f') - check(n, ['src0/exists-f', 'bld0']) - n = bld0.srcdir_find_file('on-disk-f2') - check(n, ['src0/on-disk-f2', 'bld0']) - - n = bld0.srcdir_find_file('derived-e') - check(n, ['src0/derived-e', 'bld0']) - n = bld0.srcdir_find_file('exists-e') - check(n, ['src0/exists-e', 'bld0']) - n = bld0.srcdir_find_file('on-disk-e2') - check(n, ['src0/on-disk-e2', 'bld0']) - - test.subdir('src1') - test.write(['src1', 'on-disk-f1'], "src1/on-disk-f1\n") - test.write(['src1', 'on-disk-f2'], "src1/on-disk-f2\n") - test.write(['src1', 'on-disk-e1'], "src1/on-disk-e1\n") - test.write(['src1', 'on-disk-e2'], "src1/on-disk-e2\n") - - bld1 = self.fs.Dir('bld1') - src1 = self.fs.Dir('src1') - self.fs.VariantDir(bld1, src1, duplicate=1) - - derived_f = src1.File('derived-f') - derived_f._func_is_derived = 2 - exists_f = src1.File('exists-f') - exists_f._func_exists = 5 - - derived_e = src1.Entry('derived-e') - derived_e._func_is_derived = 2 - exists_e = src1.Entry('exists-e') - exists_e._func_exists = 5 - - # First check from the source directory. - n = src1.srcdir_find_file('does_not_exist') - assert n == (None, None), n - - n = src1.srcdir_find_file('derived-f') - check(n, ['src1/derived-f', 'src1']) - n = src1.srcdir_find_file('exists-f') - check(n, ['src1/exists-f', 'src1']) - n = src1.srcdir_find_file('on-disk-f1') - check(n, ['src1/on-disk-f1', 'src1']) - - n = src1.srcdir_find_file('derived-e') - check(n, ['src1/derived-e', 'src1']) - n = src1.srcdir_find_file('exists-e') - check(n, ['src1/exists-e', 'src1']) - n = src1.srcdir_find_file('on-disk-e1') - check(n, ['src1/on-disk-e1', 'src1']) - - # Now check from the variant directory. - n = bld1.srcdir_find_file('does_not_exist') - assert n == (None, None), n - - n = bld1.srcdir_find_file('derived-f') - check(n, ['bld1/derived-f', 'src1']) - n = bld1.srcdir_find_file('exists-f') - check(n, ['bld1/exists-f', 'src1']) - n = bld1.srcdir_find_file('on-disk-f2') - check(n, ['bld1/on-disk-f2', 'bld1']) - - n = bld1.srcdir_find_file('derived-e') - check(n, ['bld1/derived-e', 'src1']) - n = bld1.srcdir_find_file('exists-e') - check(n, ['bld1/exists-e', 'src1']) - n = bld1.srcdir_find_file('on-disk-e2') - check(n, ['bld1/on-disk-e2', 'bld1']) - - def test_dir_on_disk(self): - """Test the Dir.dir_on_disk() method""" - self.test.subdir('sub', ['sub', 'exists']) - self.test.write(['sub', 'file'], "self/file\n") - sub = self.fs.Dir('sub') - - r = sub.dir_on_disk('does_not_exist') - assert not r, r - - r = sub.dir_on_disk('exists') - assert r, r - - r = sub.dir_on_disk('file') - assert not r, r - - def test_file_on_disk(self): - """Test the Dir.file_on_disk() method""" - self.test.subdir('sub', ['sub', 'dir']) - self.test.write(['sub', 'exists'], "self/exists\n") - sub = self.fs.Dir('sub') - - r = sub.file_on_disk('does_not_exist') - assert not r, r - - r = sub.file_on_disk('exists') - assert r, r - - r = sub.file_on_disk('dir') - assert not r, r - - -class EntryTestCase(_tempdirTestCase): - def test_runTest(self): - """Test methods specific to the Entry sub-class. - """ - test = TestCmd(workdir='') - # FS doesn't like the cwd to be something other than its root. - os.chdir(test.workpath("")) - - fs = SCons.Node.FS.FS() - - e1 = fs.Entry('e1') - e1.rfile() - assert e1.__class__ is SCons.Node.FS.File, e1.__class__ - - test.subdir('e3d') - test.write('e3f', "e3f\n") - - e3d = fs.Entry('e3d') - e3d.get_contents() - assert e3d.__class__ is SCons.Node.FS.Dir, e3d.__class__ - - e3f = fs.Entry('e3f') - e3f.get_contents() - assert e3f.__class__ is SCons.Node.FS.File, e3f.__class__ - - e3n = fs.Entry('e3n') - e3n.get_contents() - assert e3n.__class__ is SCons.Node.FS.Entry, e3n.__class__ - - test.subdir('e4d') - test.write('e4f', "e4f\n") - - e4d = fs.Entry('e4d') - exists = e4d.exists() - assert e4d.__class__ is SCons.Node.FS.Dir, e4d.__class__ - assert exists, "e4d does not exist?" - - e4f = fs.Entry('e4f') - exists = e4f.exists() - assert e4f.__class__ is SCons.Node.FS.File, e4f.__class__ - assert exists, "e4f does not exist?" - - e4n = fs.Entry('e4n') - exists = e4n.exists() - assert e4n.__class__ is SCons.Node.FS.File, e4n.__class__ - assert not exists, "e4n exists?" - - class MyCalc: - def __init__(self, val): - self.max_drift = 0 - - class M: - def __init__(self, val): - self.val = val - - def collect(self, args): - result = 0 - for a in args: - result += a - return result - - def signature(self, executor): - return self.val + 222 - - self.module = M(val) - - test.subdir('e5d') - test.write('e5f', "e5f\n") - - def test_Entry_Entry_lookup(self): - """Test looking up an Entry within another Entry""" - self.fs.Entry('#topdir') - self.fs.Entry('#topdir/a/b/c') - - -class FileTestCase(_tempdirTestCase): - - def test_subclass(self): - """Test looking up subclass of File nodes""" - - class FileSubclass(SCons.Node.FS.File): - pass - - sd = self.fs._lookup('special_file', None, FileSubclass, create=1) - sd.must_be_same(SCons.Node.FS.File) - - def test_Dirs(self): - """Test the File.Dirs() method""" - fff = self.fs.File('subdir/fff') - # This simulates that the SConscript file that defined - # fff is in subdir/. - fff.cwd = self.fs.Dir('subdir') - d1 = self.fs.Dir('subdir/d1') - d2 = self.fs.Dir('subdir/d2') - dirs = fff.Dirs(['d1', 'd2']) - assert dirs == [d1, d2], list(map(str, dirs)) - - def test_exists(self): - """Test the File.exists() method""" - fs = self.fs - test = self.test - - src_f1 = fs.File('src/f1') - assert not src_f1.exists(), "%s apparently exists?" % src_f1 - - test.subdir('src') - test.write(['src', 'f1'], "src/f1\n") - - assert not src_f1.exists(), "%s did not cache previous exists() value" % src_f1 - src_f1.clear() - assert src_f1.exists(), "%s apparently does not exist?" % src_f1 - - test.subdir('build') - fs.VariantDir('build', 'src') - build_f1 = fs.File('build/f1') - - assert build_f1.exists(), "%s did not realize that %s exists" % (build_f1, src_f1) - assert os.path.exists(build_f1.get_abspath()), "%s did not get duplicated on disk" % build_f1.get_abspath() - - test.unlink(['src', 'f1']) - src_f1.clear() # so the next exists() call will look on disk again - - assert build_f1.exists(), "%s did not cache previous exists() value" % build_f1 - build_f1.clear() - build_f1.linked = None - assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1) - assert not os.path.exists(build_f1.get_abspath()), "%s did not get removed after %s was removed" % ( - build_f1, src_f1) - - def test_changed(self): - """ - Verify that changes between BuildInfo's list of souces, depends, and implicit - dependencies do not corrupt content signature values written to .SConsign - when using CacheDir and Timestamp-MD5 decider. - This is for issue #2980 - """ - - # node should have - # 1 source (for example main.cpp) - # 0 depends - # N implicits (for example ['alpha.h', 'beta.h', 'gamma.h', '/usr/bin/g++']) - - class ChangedNode(SCons.Node.FS.File): - def __init__(self, name, directory=None, fs=None): - SCons.Node.FS.File.__init__(self, name, directory, fs) - self.name = name - self.Tag('found_includes', []) - self.stored_info = None - self.build_env = None - self.changed_since_last_build = 4 - self.timestamp = 1 - - def get_stored_info(self): - return self.stored_info - - def get_build_env(self): - return self.build_env - - def get_timestamp(self): - """ Fake timestamp so they always match""" - return self.timestamp - - def get_contents(self): - return self.name - - def get_ninfo(self): - """ mocked to ensure csig will equal the filename""" - if self.ninfo is not None: - return self.ninfo - self.ninfo = FakeNodeInfo(self.name, self.timestamp) - return self.ninfo - - def get_csig(self): - ninfo = self.get_ninfo() - try: - return ninfo.csig - except AttributeError: - pass - - return "Should Never Happen" - - class ChangedEnvironment(SCons.Environment.Base): - - def __init__(self): - SCons.Environment.Base.__init__(self) - self.decide_source = self._changed_timestamp_then_content - - class FakeNodeInfo: - def __init__(self, csig, timestamp): - self.csig = csig - self.timestamp = timestamp - - # Create nodes - fs = SCons.Node.FS.FS() - d = self.fs.Dir('.') - - node = ChangedNode('main.o', d, fs) # main.o - s1 = ChangedNode('main.cpp', d, fs) # main.cpp - s1.timestamp = 2 # this changed - i1 = ChangedNode('alpha.h', d, fs) # alpha.h - The bug is caused because the second build adds this file - i1.timestamp = 2 # This is the new file. - i2 = ChangedNode('beta.h', d, fs) # beta.h - i3 = ChangedNode('gamma.h', d, fs) # gamma.h - In the bug beta.h's csig from binfo overwrites this ones - i4 = ChangedNode('/usr/bin/g++', d, fs) # /usr/bin/g++ - - node.add_source([s1]) - node.add_dependency([]) - node.implicit = [i1, i2, i3, i4] - node.implicit_set = set() - # node._add_child(node.implicit, node.implicit_set, [n7, n8, n9]) - # node._add_child(node.implicit, node.implicit_set, [n10, n11, n12]) - - # Mock out node's scan method - # node.scan = lambda *args: None - - # Mock out nodes' children() ? - # Should return Node's. - # All those nodes should have changed_since_last_build set to match Timestamp-MD5's - # decider method... - - # Generate sconsign entry needed - sconsign_entry = SCons.SConsign.SConsignEntry() - sconsign_entry.binfo = node.new_binfo() - sconsign_entry.ninfo = node.new_ninfo() - - # mock out loading info from sconsign - # This will cause node.get_stored_info() to return our freshly created sconsign_entry - node.stored_info = sconsign_entry - - # binfo = information from previous build (from sconsign) - # We'll set the following attributes (which are lists): "bsources", "bsourcesigs", - # "bdepends","bdependsigs", "bimplicit", "bimplicitsigs" - bi = sconsign_entry.binfo - bi.bsources = ['main.cpp'] - bi.bsourcesigs = [FakeNodeInfo('main.cpp', 1), ] - - bi.bdepends = [] - bi.bdependsigs = [] - - bi.bimplicit = ['beta.h', 'gamma.h'] - bi.bimplicitsigs = [FakeNodeInfo('beta.h', 1), FakeNodeInfo('gamma.h', 1)] - - ni = sconsign_entry.ninfo - # We'll set the following attributes (which are lists): sources, depends, implicit lists - - # Set timestamp-md5 - # Call changed - # Check results - node.build_env = ChangedEnvironment() - - changed = node.changed() - - # change to true to debug - if False: - print("Changed:%s" % changed) - print("%15s -> csig:%s" % (s1.name, s1.ninfo.csig)) - print("%15s -> csig:%s" % (i1.name, i1.ninfo.csig)) - print("%15s -> csig:%s" % (i2.name, i2.ninfo.csig)) - print("%15s -> csig:%s" % (i3.name, i3.ninfo.csig)) - print("%15s -> csig:%s" % (i4.name, i4.ninfo.csig)) - - self.assertEqual( - i2.name, - i2.ninfo.csig, - "gamma.h's fake csig should equal gamma.h but equals:%s" % i2.ninfo.csig, - ) - - -class GlobTestCase(_tempdirTestCase): - def setUp(self): - _tempdirTestCase.setUp(self) - - fs = SCons.Node.FS.FS() - self.fs = fs - - # Make entries on disk that will not have Nodes, so we can verify - # the behavior of looking for things on disk. - self.test.write('disk-bbb', "disk-bbb\n") - self.test.write('disk-aaa', "disk-aaa\n") - self.test.write('disk-ccc', "disk-ccc\n") - self.test.write('#disk-hash', "#disk-hash\n") - self.test.subdir('disk-sub') - self.test.write(['disk-sub', 'disk-ddd'], "disk-sub/disk-ddd\n") - self.test.write(['disk-sub', 'disk-eee'], "disk-sub/disk-eee\n") - self.test.write(['disk-sub', 'disk-fff'], "disk-sub/disk-fff\n") - - # Make some entries that have both Nodes and on-disk entries, - # so we can verify what we do with - self.test.write('both-aaa', "both-aaa\n") - self.test.write('both-bbb', "both-bbb\n") - self.test.write('both-ccc', "both-ccc\n") - self.test.write('#both-hash', "#both-hash\n") - self.test.subdir('both-sub1') - self.test.write(['both-sub1', 'both-ddd'], "both-sub1/both-ddd\n") - self.test.write(['both-sub1', 'both-eee'], "both-sub1/both-eee\n") - self.test.write(['both-sub1', 'both-fff'], "both-sub1/both-fff\n") - self.test.subdir('both-sub2') - self.test.write(['both-sub2', 'both-ddd'], "both-sub2/both-ddd\n") - self.test.write(['both-sub2', 'both-eee'], "both-sub2/both-eee\n") - self.test.write(['both-sub2', 'both-fff'], "both-sub2/both-fff\n") - - self.both_aaa = fs.File('both-aaa') - self.both_bbb = fs.File('both-bbb') - self.both_ccc = fs.File('both-ccc') - self._both_hash = fs.File('./#both-hash') - self.both_sub1 = fs.Dir('both-sub1') - self.both_sub1_both_ddd = self.both_sub1.File('both-ddd') - self.both_sub1_both_eee = self.both_sub1.File('both-eee') - self.both_sub1_both_fff = self.both_sub1.File('both-fff') - self.both_sub2 = fs.Dir('both-sub2') - self.both_sub2_both_ddd = self.both_sub2.File('both-ddd') - self.both_sub2_both_eee = self.both_sub2.File('both-eee') - self.both_sub2_both_fff = self.both_sub2.File('both-fff') - - # Make various Nodes (that don't have on-disk entries) so we - # can verify how we match them. - self.ggg = fs.File('ggg') - self.hhh = fs.File('hhh') - self.iii = fs.File('iii') - self._hash = fs.File('./#hash') - self.subdir1 = fs.Dir('subdir1') - self.subdir1_lll = self.subdir1.File('lll') - self.subdir1_jjj = self.subdir1.File('jjj') - self.subdir1_kkk = self.subdir1.File('kkk') - self.subdir2 = fs.Dir('subdir2') - self.subdir2_lll = self.subdir2.File('lll') - self.subdir2_kkk = self.subdir2.File('kkk') - self.subdir2_jjj = self.subdir2.File('jjj') - self.sub = fs.Dir('sub') - self.sub_dir3 = self.sub.Dir('dir3') - self.sub_dir3_kkk = self.sub_dir3.File('kkk') - self.sub_dir3_jjj = self.sub_dir3.File('jjj') - self.sub_dir3_lll = self.sub_dir3.File('lll') - - def do_cases(self, cases, **kwargs): - - # First, execute all of the cases with string=True and verify - # that we get the expected strings returned. We do this first - # so the Glob() calls don't add Nodes to the self.fs file system - # hierarchy. - - import copy - strings_kwargs = copy.copy(kwargs) - strings_kwargs['strings'] = True - for input, string_expect, node_expect in cases: - r = sorted(self.fs.Glob(input, **strings_kwargs)) - assert r == string_expect, "Glob(%s, strings=True) expected %s, got %s" % (input, string_expect, r) - - # Now execute all of the cases without string=True and look for - # the expected Nodes to be returned. If we don't have a list of - # actual expected Nodes, that means we're expecting a search for - # on-disk-only files to have returned some newly-created nodes. - # Verify those by running the list through str() before comparing - # them with the expected list of strings. - for input, string_expect, node_expect in cases: - r = self.fs.Glob(input, **kwargs) - if node_expect: - r = sorted(r, key=lambda a: a.get_internal_path()) - result = [] - for n in node_expect: - if isinstance(n, str): - n = self.fs.Entry(n) - result.append(n) - fmt = lambda n: "%s %s" % (repr(n), repr(str(n))) - else: - r = sorted(map(str, r)) - result = string_expect - fmt = lambda n: n - if r != result: - import pprint - print("Glob(%s) expected:" % repr(input)) - pprint.pprint(list(map(fmt, result))) - print("Glob(%s) got:" % repr(input)) - pprint.pprint(list(map(fmt, r))) - self.fail() - - def test_exact_match(self): - """Test globbing for exact Node matches""" - join = os.path.join - - cases = ( - ('ggg', ['ggg'], [self.ggg]), - - ('subdir1', ['subdir1'], [self.subdir1]), - - ('subdir1/jjj', [join('subdir1', 'jjj')], [self.subdir1_jjj]), - - ('disk-aaa', ['disk-aaa'], None), - - ('disk-sub', ['disk-sub'], None), - - ('both-aaa', ['both-aaa'], []), - ) - - self.do_cases(cases) - - def test_subdir_matches(self): - """Test globbing for exact Node matches in subdirectories""" - join = os.path.join - - cases = ( - ('*/jjj', - [join('subdir1', 'jjj'), join('subdir2', 'jjj')], - [self.subdir1_jjj, self.subdir2_jjj]), - - ('*/disk-ddd', - [join('disk-sub', 'disk-ddd')], - None), - ) - - self.do_cases(cases) - - def test_asterisk1(self): - """Test globbing for simple asterisk Node matches (1)""" - cases = ( - ('h*', - ['hhh'], - [self.hhh]), - - ('*', - ['#both-hash', '#hash', - 'both-aaa', 'both-bbb', 'both-ccc', - 'both-sub1', 'both-sub2', - 'ggg', 'hhh', 'iii', - 'sub', 'subdir1', 'subdir2'], - [self._both_hash, self._hash, - self.both_aaa, self.both_bbb, self.both_ccc, 'both-hash', - self.both_sub1, self.both_sub2, - self.ggg, 'hash', self.hhh, self.iii, - self.sub, self.subdir1, self.subdir2]), - ) - - self.do_cases(cases, ondisk=False) - - def test_asterisk2(self): - """Test globbing for simple asterisk Node matches (2)""" - cases = ( - ('disk-b*', - ['disk-bbb'], - None), - - ('*', - ['#both-hash', '#disk-hash', '#hash', - 'both-aaa', 'both-bbb', 'both-ccc', - 'both-sub1', 'both-sub2', - 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub', - 'ggg', 'hhh', 'iii', - 'sub', 'subdir1', 'subdir2'], - ['./#both-hash', './#disk-hash', './#hash', - 'both-aaa', 'both-bbb', 'both-ccc', 'both-hash', - 'both-sub1', 'both-sub2', - 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub', - 'ggg', 'hash', 'hhh', 'iii', - 'sub', 'subdir1', 'subdir2']), - ) - - self.do_cases(cases) - - def test_question_mark(self): - """Test globbing for simple question-mark Node matches""" - join = os.path.join - - cases = ( - ('ii?', - ['iii'], - [self.iii]), - - ('both-sub?/both-eee', - [join('both-sub1', 'both-eee'), join('both-sub2', 'both-eee')], - [self.both_sub1_both_eee, self.both_sub2_both_eee]), - - ('subdir?/jjj', - [join('subdir1', 'jjj'), join('subdir2', 'jjj')], - [self.subdir1_jjj, self.subdir2_jjj]), - - ('disk-cc?', - ['disk-ccc'], - None), - ) - - self.do_cases(cases) - - def test_does_not_exist(self): - """Test globbing for things that don't exist""" - - cases = ( - ('does_not_exist', [], []), - ('no_subdir/*', [], []), - ('subdir?/no_file', [], []), - ) - - self.do_cases(cases) - - def test_subdir_asterisk(self): - """Test globbing for asterisk Node matches in subdirectories""" - join = os.path.join - - cases = ( - ('*/k*', - [join('subdir1', 'kkk'), join('subdir2', 'kkk')], - [self.subdir1_kkk, self.subdir2_kkk]), - - ('both-sub?/*', - [join('both-sub1', 'both-ddd'), - join('both-sub1', 'both-eee'), - join('both-sub1', 'both-fff'), - join('both-sub2', 'both-ddd'), - join('both-sub2', 'both-eee'), - join('both-sub2', 'both-fff')], - [self.both_sub1_both_ddd, - self.both_sub1_both_eee, - self.both_sub1_both_fff, - self.both_sub2_both_ddd, - self.both_sub2_both_eee, - self.both_sub2_both_fff], - ), - - ('subdir?/*', - [join('subdir1', 'jjj'), - join('subdir1', 'kkk'), - join('subdir1', 'lll'), - join('subdir2', 'jjj'), - join('subdir2', 'kkk'), - join('subdir2', 'lll')], - [self.subdir1_jjj, self.subdir1_kkk, self.subdir1_lll, - self.subdir2_jjj, self.subdir2_kkk, self.subdir2_lll]), - - ('sub/*/*', - [join('sub', 'dir3', 'jjj'), - join('sub', 'dir3', 'kkk'), - join('sub', 'dir3', 'lll')], - [self.sub_dir3_jjj, self.sub_dir3_kkk, self.sub_dir3_lll]), - - ('*/k*', - [join('subdir1', 'kkk'), join('subdir2', 'kkk')], - None), - - ('subdir?/*', - [join('subdir1', 'jjj'), - join('subdir1', 'kkk'), - join('subdir1', 'lll'), - join('subdir2', 'jjj'), - join('subdir2', 'kkk'), - join('subdir2', 'lll')], - None), - - ('sub/*/*', - [join('sub', 'dir3', 'jjj'), - join('sub', 'dir3', 'kkk'), - join('sub', 'dir3', 'lll')], - None), - ) - - self.do_cases(cases) - - def test_subdir_question(self): - """Test globbing for question-mark Node matches in subdirectories""" - join = os.path.join - - cases = ( - ('*/?kk', - [join('subdir1', 'kkk'), join('subdir2', 'kkk')], - [self.subdir1_kkk, self.subdir2_kkk]), - - ('subdir?/l?l', - [join('subdir1', 'lll'), join('subdir2', 'lll')], - [self.subdir1_lll, self.subdir2_lll]), - - ('*/disk-?ff', - [join('disk-sub', 'disk-fff')], - None), - - ('subdir?/l?l', - [join('subdir1', 'lll'), join('subdir2', 'lll')], - None), - ) - - self.do_cases(cases) - - def test_sort(self): - """Test whether globbing sorts""" - join = os.path.join - # At least sometimes this should return out-of-order items - # if Glob doesn't sort. - # It's not a very good test though since it depends on the - # order returned by glob, which might already be sorted. - g = self.fs.Glob('disk-sub/*', strings=True) - expect = [ - os.path.join('disk-sub', 'disk-ddd'), - os.path.join('disk-sub', 'disk-eee'), - os.path.join('disk-sub', 'disk-fff'), - ] - assert g == expect, str(g) + " is not sorted, but should be!" - - g = self.fs.Glob('disk-*', strings=True) - expect = ['disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub'] - assert g == expect, str(g) + " is not sorted, but should be!" - - -class RepositoryTestCase(_tempdirTestCase): - - def setUp(self): - _tempdirTestCase.setUp(self) - - self.test.subdir('rep1', 'rep2', 'rep3', 'work') - - self.rep1 = self.test.workpath('rep1') - self.rep2 = self.test.workpath('rep2') - self.rep3 = self.test.workpath('rep3') - - os.chdir(self.test.workpath('work')) - - self.fs = SCons.Node.FS.FS() - self.fs.Repository(self.rep1, self.rep2, self.rep3) - - def test_getRepositories(self): - """Test the Dir.getRepositories() method""" - self.fs.Repository('foo') - self.fs.Repository(os.path.join('foo', 'bar')) - self.fs.Repository('bar/foo') - self.fs.Repository('bar') - - expect = [ - self.rep1, - self.rep2, - self.rep3, - 'foo', - os.path.join('foo', 'bar'), - os.path.join('bar', 'foo'), - 'bar' - ] - - rep = self.fs.Dir('#').getRepositories() - r = [os.path.normpath(str(x)) for x in rep] - assert r == expect, r - - def test_get_all_rdirs(self): - """Test the Dir.get_all_rdirs() method""" - self.fs.Repository('foo') - self.fs.Repository(os.path.join('foo', 'bar')) - self.fs.Repository('bar/foo') - self.fs.Repository('bar') - - expect = [ - '.', - self.rep1, - self.rep2, - self.rep3, - 'foo', - os.path.join('foo', 'bar'), - os.path.join('bar', 'foo'), - 'bar' - ] - - rep = self.fs.Dir('#').get_all_rdirs() - r = [os.path.normpath(str(x)) for x in rep] - assert r == expect, r - - def test_rentry(self): - """Test the Base.entry() method""" - return_true = lambda: 1 - return_false = lambda: 0 - - d1 = self.fs.Dir('d1') - d2 = self.fs.Dir('d2') - d3 = self.fs.Dir('d3') - - e1 = self.fs.Entry('e1') - e2 = self.fs.Entry('e2') - e3 = self.fs.Entry('e3') - - f1 = self.fs.File('f1') - f2 = self.fs.File('f2') - f3 = self.fs.File('f3') - - self.test.write([self.rep1, 'd2'], "") - self.test.subdir([self.rep2, 'd3']) - self.test.write([self.rep3, 'd3'], "") - - self.test.write([self.rep1, 'e2'], "") - self.test.subdir([self.rep2, 'e3']) - self.test.write([self.rep3, 'e3'], "") - - self.test.write([self.rep1, 'f2'], "") - self.test.subdir([self.rep2, 'f3']) - self.test.write([self.rep3, 'f3'], "") - - r = d1.rentry() - assert r is d1, r - - r = d2.rentry() - assert r is not d2, r - r = str(r) - assert r == os.path.join(self.rep1, 'd2'), r - - r = d3.rentry() - assert r is not d3, r - r = str(r) - assert r == os.path.join(self.rep2, 'd3'), r - - r = e1.rentry() - assert r is e1, r - - r = e2.rentry() - assert r is not e2, r - r = str(r) - assert r == os.path.join(self.rep1, 'e2'), r - - r = e3.rentry() - assert r is not e3, r - r = str(r) - assert r == os.path.join(self.rep2, 'e3'), r - - r = f1.rentry() - assert r is f1, r - - r = f2.rentry() - assert r is not f2, r - r = str(r) - assert r == os.path.join(self.rep1, 'f2'), r - - r = f3.rentry() - assert r is not f3, r - r = str(r) - assert r == os.path.join(self.rep2, 'f3'), r - - def test_rdir(self): - """Test the Dir.rdir() method""" - - def return_true(obj): - return 1 - - def return_false(obj): - return 0 - - SCons.Node._exists_map[5] = return_true - SCons.Node._exists_map[6] = return_false - SCons.Node._is_derived_map[2] = return_true - SCons.Node._is_derived_map[3] = return_false - - d1 = self.fs.Dir('d1') - d2 = self.fs.Dir('d2') - d3 = self.fs.Dir('d3') - - self.test.subdir([self.rep1, 'd2']) - self.test.write([self.rep2, 'd3'], "") - self.test.subdir([self.rep3, 'd3']) - - r = d1.rdir() - assert r is d1, r - - r = d2.rdir() - assert r is not d2, r - r = str(r) - assert r == os.path.join(self.rep1, 'd2'), r - - r = d3.rdir() - assert r is not d3, r - r = str(r) - assert r == os.path.join(self.rep3, 'd3'), r - - e1 = self.fs.Dir('e1') - e1._func_exists = 6 - e2 = self.fs.Dir('e2') - e2._func_exists = 6 - - # Make sure we match entries in repositories, - # regardless of whether they're derived or not. - - re1 = self.fs.Entry(os.path.join(self.rep1, 'e1')) - re1._func_exists = 5 - re1._func_is_derived = 2 - re2 = self.fs.Entry(os.path.join(self.rep2, 'e2')) - re2._func_exists = 5 - re2._func_is_derived = 3 - - r = e1.rdir() - assert r is re1, r - - r = e2.rdir() - assert r is re2, r - - def test_rfile(self): - """Test the File.rfile() method""" - - def return_true(obj): - return 1 - - def return_false(obj): - return 0 - - SCons.Node._exists_map[5] = return_true - SCons.Node._exists_map[6] = return_false - SCons.Node._is_derived_map[2] = return_true - SCons.Node._is_derived_map[3] = return_false - - f1 = self.fs.File('f1') - f2 = self.fs.File('f2') - f3 = self.fs.File('f3') - - self.test.write([self.rep1, 'f2'], "") - self.test.subdir([self.rep2, 'f3']) - self.test.write([self.rep3, 'f3'], "") - - r = f1.rfile() - assert r is f1, r - - r = f2.rfile() - assert r is not f2, r - r = str(r) - assert r == os.path.join(self.rep1, 'f2'), r - - r = f3.rfile() - assert r is not f3, r - r = f3.rstr() - assert r == os.path.join(self.rep3, 'f3'), r - - e1 = self.fs.File('e1') - e1._func_exists = 6 - e2 = self.fs.File('e2') - e2._func_exists = 6 - - # Make sure we match entries in repositories, - # regardless of whether they're derived or not. - - re1 = self.fs.Entry(os.path.join(self.rep1, 'e1')) - re1._func_exists = 5 - re1._func_is_derived = 2 - re2 = self.fs.Entry(os.path.join(self.rep2, 'e2')) - re2._func_exists = 5 - re2._func_is_derived = 3 - - r = e1.rfile() - assert r is re1, r - - r = e2.rfile() - assert r is re2, r - - def test_Rfindalldirs(self): - """Test the Rfindalldirs() methods""" - fs = self.fs - test = self.test - - d1 = fs.Dir('d1') - d2 = fs.Dir('d2') - rep1_d1 = fs.Dir(test.workpath('rep1', 'd1')) - rep2_d1 = fs.Dir(test.workpath('rep2', 'd1')) - rep3_d1 = fs.Dir(test.workpath('rep3', 'd1')) - sub = fs.Dir('sub') - sub_d1 = sub.Dir('d1') - rep1_sub_d1 = fs.Dir(test.workpath('rep1', 'sub', 'd1')) - rep2_sub_d1 = fs.Dir(test.workpath('rep2', 'sub', 'd1')) - rep3_sub_d1 = fs.Dir(test.workpath('rep3', 'sub', 'd1')) - - r = fs.Top.Rfindalldirs((d1,)) - assert r == [d1], list(map(str, r)) - - r = fs.Top.Rfindalldirs((d1, d2)) - assert r == [d1, d2], list(map(str, r)) - - r = fs.Top.Rfindalldirs(('d1',)) - assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r)) - - r = fs.Top.Rfindalldirs(('#d1',)) - assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r)) - - r = sub.Rfindalldirs(('d1',)) - assert r == [sub_d1, rep1_sub_d1, rep2_sub_d1, rep3_sub_d1], list(map(str, r)) - - r = sub.Rfindalldirs(('#d1',)) - assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r)) - - r = fs.Top.Rfindalldirs(('d1', d2)) - assert r == [d1, rep1_d1, rep2_d1, rep3_d1, d2], list(map(str, r)) - - def test_rexists(self): - """Test the Entry.rexists() method""" - fs = self.fs - test = self.test - - test.write([self.rep1, 'f2'], "") - test.write([self.rep2, "i_exist"], "\n") - test.write(["work", "i_exist_too"], "\n") - - fs.VariantDir('build', '.') - - f = fs.File(test.workpath("work", "i_do_not_exist")) - assert not f.rexists() - - f = fs.File(test.workpath("work", "i_exist")) - assert f.rexists() - - f = fs.File(test.workpath("work", "i_exist_too")) - assert f.rexists() - - f1 = fs.File(os.path.join('build', 'f1')) - assert not f1.rexists() - - f2 = fs.File(os.path.join('build', 'f2')) - assert f2.rexists() - - def test_FAT_timestamps(self): - """Test repository timestamps on FAT file systems""" - fs = self.fs - test = self.test - - test.write(["rep2", "tstamp"], "tstamp\n") - try: - # Okay, *this* manipulation accomodates Windows FAT file systems - # that only have two-second granularity on their timestamps. - # We round down the current time to the nearest even integer - # value, subtract two to make sure the timestamp is not "now," - # and then convert it back to a float. - tstamp = float(int(time.time() // 2) * 2) - 2.0 - os.utime(test.workpath("rep2", "tstamp"), (tstamp - 2.0, tstamp)) - f = fs.File("tstamp") - t = f.get_timestamp() - assert t == tstamp, "expected %f, got %f" % (tstamp, t) - finally: - test.unlink(["rep2", "tstamp"]) - - def test_get_contents(self): - """Ensure get_contents() returns binary contents from Repositories""" - fs = self.fs - test = self.test - - test.write(["rep3", "contents"], "Con\x1aTents\n") - try: - c = fs.File("contents").get_contents() - assert c == bytearray("Con\x1aTents\n", 'utf-8'), "got '%s'" % c - finally: - test.unlink(["rep3", "contents"]) - - def test_get_text_contents(self): - """Ensure get_text_contents() returns text contents from - Repositories""" - fs = self.fs - test = self.test - - # Use a test string that has a file terminator in it to make - # sure we read the entire file, regardless of its contents. - test_string = "Con\x1aTents\n" - - # Test with ASCII. - test.write(["rep3", "contents"], test_string.encode('ascii')) - try: - c = fs.File("contents").get_text_contents() - assert test_string == c, "got %s" % repr(c) - finally: - test.unlink(["rep3", "contents"]) - - # Test with utf-8 - test.write(["rep3", "contents"], test_string.encode('utf-8')) - try: - c = fs.File("contents").get_text_contents() - assert test_string == c, "got %s" % repr(c) - finally: - test.unlink(["rep3", "contents"]) - - # Test with utf-16 - test.write(["rep3", "contents"], test_string.encode('utf-16')) - try: - c = fs.File("contents").get_text_contents() - assert test_string == c, "got %s" % repr(c) - finally: - test.unlink(["rep3", "contents"]) - - # def test_is_up_to_date(self): - - -class find_fileTestCase(unittest.TestCase): - def runTest(self): - """Testing find_file function""" - test = TestCmd(workdir='') - test.write('./foo', 'Some file\n') - test.write('./foo2', 'Another file\n') - test.subdir('same') - test.subdir('bar') - test.write(['bar', 'on_disk'], 'Another file\n') - test.write(['bar', 'same'], 'bar/same\n') - - fs = SCons.Node.FS.FS(test.workpath("")) - # FS doesn't like the cwd to be something other than its root. - os.chdir(test.workpath("")) - - node_derived = fs.File(test.workpath('bar/baz')) - node_derived.builder_set(1) # Any non-zero value. - node_pseudo = fs.File(test.workpath('pseudo')) - node_pseudo.set_src_builder(1) # Any non-zero value. - - paths = tuple(map(fs.Dir, ['.', 'same', './bar'])) - nodes = [SCons.Node.FS.find_file('foo', paths), - SCons.Node.FS.find_file('baz', paths), - SCons.Node.FS.find_file('pseudo', paths), - SCons.Node.FS.find_file('same', paths) - ] - - file_names = list(map(str, nodes)) - file_names = list(map(os.path.normpath, file_names)) - expect = ['./foo', './bar/baz', './pseudo', './bar/same'] - expect = list(map(os.path.normpath, expect)) - assert file_names == expect, file_names - - # Make sure we don't blow up if there's already a File in place - # of a directory that we'd otherwise try to search. If this - # is broken, we'll see an exception like "Tried to lookup File - # 'bar/baz' as a Dir. - SCons.Node.FS.find_file('baz/no_file_here', paths) - - import io - save_sys_stdout = sys.stdout - - try: - sio = io.StringIO() - sys.stdout = sio - SCons.Node.FS.find_file('foo2', paths, verbose="xyz") - expect = " xyz: looking for 'foo2' in '.' ...\n" + \ - " xyz: ... FOUND 'foo2' in '.'\n" - c = sio.getvalue() - assert c == expect, c - - sio = io.StringIO() - sys.stdout = sio - SCons.Node.FS.find_file('baz2', paths, verbose=1) - expect = " find_file: looking for 'baz2' in '.' ...\n" + \ - " find_file: looking for 'baz2' in 'same' ...\n" + \ - " find_file: looking for 'baz2' in 'bar' ...\n" - c = sio.getvalue() - assert c == expect, c - - sio = io.StringIO() - sys.stdout = sio - SCons.Node.FS.find_file('on_disk', paths, verbose=1) - expect = " find_file: looking for 'on_disk' in '.' ...\n" + \ - " find_file: looking for 'on_disk' in 'same' ...\n" + \ - " find_file: looking for 'on_disk' in 'bar' ...\n" + \ - " find_file: ... FOUND 'on_disk' in 'bar'\n" - c = sio.getvalue() - assert c == expect, c - finally: - sys.stdout = save_sys_stdout - - -class StringDirTestCase(unittest.TestCase): - def runTest(self): - """Test using a string as the second argument of - File() and Dir()""" - - test = TestCmd(workdir='') - test.subdir('sub') - fs = SCons.Node.FS.FS(test.workpath('')) - - d = fs.Dir('sub', '.') - assert str(d) == 'sub', str(d) - assert d.exists() - f = fs.File('file', 'sub') - assert str(f) == os.path.join('sub', 'file') - assert not f.exists() - - -class stored_infoTestCase(unittest.TestCase): - def runTest(self): - """Test how we store build information""" - test = TestCmd(workdir='') - test.subdir('sub') - fs = SCons.Node.FS.FS(test.workpath('')) - - d = fs.Dir('sub') - f = fs.File('file1', d) - bi = f.get_stored_info() - assert hasattr(bi, 'ninfo') - - class MySConsign: - class Null: - def __init__(self): - self.xyzzy = 7 - - def get_entry(self, name): - return self.Null() - - def test_sconsign(node): - return MySConsign() - - f = fs.File('file2', d) - SCons.Node.FS._sconsign_map[2] = test_sconsign - f.dir._func_sconsign = 2 - bi = f.get_stored_info() - assert bi.xyzzy == 7, bi - - -class has_src_builderTestCase(unittest.TestCase): - def runTest(self): - """Test the has_src_builder() method""" - test = TestCmd(workdir='') - fs = SCons.Node.FS.FS(test.workpath('')) - os.chdir(test.workpath('')) - test.subdir('sub1') - - sub1 = fs.Dir('sub1', '.') - f1 = fs.File('f1', sub1) - f2 = fs.File('f2', sub1) - f3 = fs.File('f3', sub1) - - h = f1.has_src_builder() - assert not h, h - h = f1.has_builder() - assert not h, h - - b1 = Builder(fs.File) - sub1.set_src_builder(b1) - - test.write(['sub1', 'f2'], "sub1/f2\n") - h = f1.has_src_builder() # cached from previous call - assert not h, h - h = f1.has_builder() # cached from previous call - assert not h, h - h = f2.has_src_builder() - assert not h, h - h = f2.has_builder() - assert not h, h - h = f3.has_src_builder() - assert h, h - h = f3.has_builder() - assert h, h - assert f3.builder is b1, f3.builder - - -class prepareTestCase(unittest.TestCase): - def runTest(self): - """Test the prepare() method""" - - class MyFile(SCons.Node.FS.File): - def _createDir(self, update=None): - raise SCons.Errors.StopError - - def exists(self): - return None - - fs = SCons.Node.FS.FS() - file = MyFile('foo', fs.Dir('.'), fs) - - exc_caught = 0 - try: - file.prepare() - except SCons.Errors.StopError: - exc_caught = 1 - assert exc_caught, "Should have caught a StopError." - - class MkdirAction(Action): - def __init__(self, dir_made): - self.dir_made = dir_made - - def __call__(self, target, source, env, executor=None): - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - self.dir_made.extend(target) - - dir_made = [] - new_dir = fs.Dir("new_dir") - new_dir.builder = Builder(fs.Dir, action=MkdirAction(dir_made)) - new_dir.reset_executor() - xyz = fs.File(os.path.join("new_dir", "xyz")) - - xyz.set_state(SCons.Node.up_to_date) - xyz.prepare() - assert dir_made == [], dir_made - - xyz.set_state(0) - xyz.prepare() - assert dir_made[0].get_internal_path() == "new_dir", dir_made[0] - - dir = fs.Dir("dir") - dir.prepare() - -@unittest.skipIf(IS_WINDOWS, "No symlinks on windows") -@unittest.skipUnless(hasattr(os, 'symlink'), "Platform doesn't support symlink") -class CleanSymlinksTestCase(_tempdirTestCase): - - def test_cleans_symlinks(self): - """Test the prepare() method will cleanup symlinks.""" - - test = self.test - - with open(test.workpath("foo"), "w") as foo: - foo.write("baz") - - os.symlink(test.workpath("foo"), test.workpath("bar")) - bar = self.fs.File(test.workpath("bar")) - bar.side_effect = True - bar.set_state(0) - assert bar.exists(), "Symlink %s should not exist after prepare"%str(bar) - - bar.prepare() - try: - os.lstat(test.workpath("bar")) - assert False, "bar should not exist" - except FileNotFoundError: - pass - - try: - os.stat(test.workpath("foo")) - except FileNotFoundError: - test.fail('Real file %s should not be removed'%test.workpath('foo')) - - def test_cleans_dangling_symlinks(self): - """Test the prepare() method will cleanup dangling symlinks.""" - test = self.test - - with open(test.workpath("foo"), "w") as foo: - foo.write("baz") - - os.symlink(test.workpath("foo"), test.workpath("bar")) - os.remove(test.workpath("foo")) - try: - os.stat(test.workpath("foo")) - assert False, "foo should not exist" - except FileNotFoundError: - pass - - bar = self.fs.File(test.workpath("bar")) - bar.side_effect = True - bar.set_state(0) - - # Dangling links should report not exists - assert not bar.exists() - - bar.prepare() - try: - os.lstat(test.workpath("bar")) - assert False, "bar [%s] should not exist"%test.workpath("bar") - except FileNotFoundError: - pass - - -class SConstruct_dirTestCase(unittest.TestCase): - def runTest(self): - """Test setting the SConstruct directory""" - - fs = SCons.Node.FS.FS() - fs.set_SConstruct_dir(fs.Dir('xxx')) - assert fs.SConstruct_dir.get_internal_path() == 'xxx' - - -class CacheDirTestCase(unittest.TestCase): - - def test_get_cachedir_csig(self): - fs = SCons.Node.FS.FS() - - f9 = fs.File('f9') - r = f9.get_cachedir_csig() - exsig = SCons.Util.MD5signature(SCons.Util.NOFILE) - assert r == exsig, r - - -class clearTestCase(unittest.TestCase): - def runTest(self): - """Test clearing FS nodes of cached data.""" - fs = SCons.Node.FS.FS() - test = TestCmd(workdir='') - - e = fs.Entry('e') - assert not e.exists() - assert not e.rexists() - assert str(e) == 'e', str(e) - e.clear() - assert not e.exists() - assert not e.rexists() - assert str(e) == 'e', str(e) - - d = fs.Dir(test.workpath('d')) - test.subdir('d') - assert d.exists() - assert d.rexists() - assert str(d) == test.workpath('d'), str(d) - fs.rename(test.workpath('d'), test.workpath('gone')) - # Verify caching is active - assert d.exists(), 'caching not active' - assert d.rexists() - assert str(d) == test.workpath('d'), str(d) - # Now verify clear() resets the cache - d.clear() - assert not d.exists() - assert not d.rexists() - assert str(d) == test.workpath('d'), str(d) - - f = fs.File(test.workpath('f')) - test.write(test.workpath('f'), 'file f') - assert f.exists() - assert f.rexists() - assert str(f) == test.workpath('f'), str(f) - # Verify caching is active - test.unlink(test.workpath('f')) - assert f.exists() - assert f.rexists() - assert str(f) == test.workpath('f'), str(f) - # Now verify clear() resets the cache - f.clear() - assert not f.exists() - assert not f.rexists() - assert str(f) == test.workpath('f'), str(f) - # Now verify clear() resets optional File-specific attributes - optional_attrs = ['cachedir_csig', 'cachesig', 'contentsig'] - for attr in optional_attrs: - setattr(f, attr, 'xyz') - f.clear() - for attr in optional_attrs: - assert not hasattr(f, attr), attr - - -class disambiguateTestCase(unittest.TestCase): - def runTest(self): - """Test calling the disambiguate() method.""" - test = TestCmd(workdir='') - - fs = SCons.Node.FS.FS() - - ddd = fs.Dir('ddd') - d = ddd.disambiguate() - assert d is ddd, d - - fff = fs.File('fff') - f = fff.disambiguate() - assert f is fff, f - - test.subdir('edir') - test.write('efile', "efile\n") - - edir = fs.Entry(test.workpath('edir')) - d = edir.disambiguate() - assert d.__class__ is ddd.__class__, d.__class__ - - efile = fs.Entry(test.workpath('efile')) - f = efile.disambiguate() - assert f.__class__ is fff.__class__, f.__class__ - - test.subdir('build') - test.subdir(['build', 'bdir']) - test.write(['build', 'bfile'], "build/bfile\n") - - test.subdir('src') - test.write(['src', 'bdir'], "src/bdir\n") - test.subdir(['src', 'bfile']) - - test.subdir(['src', 'edir']) - test.write(['src', 'efile'], "src/efile\n") - - fs.VariantDir(test.workpath('build'), test.workpath('src')) - - build_bdir = fs.Entry(test.workpath('build/bdir')) - d = build_bdir.disambiguate() - assert d is build_bdir, d - assert d.__class__ is ddd.__class__, d.__class__ - - build_bfile = fs.Entry(test.workpath('build/bfile')) - f = build_bfile.disambiguate() - assert f is build_bfile, f - assert f.__class__ is fff.__class__, f.__class__ - - build_edir = fs.Entry(test.workpath('build/edir')) - d = build_edir.disambiguate() - assert d.__class__ is ddd.__class__, d.__class__ - - build_efile = fs.Entry(test.workpath('build/efile')) - f = build_efile.disambiguate() - assert f.__class__ is fff.__class__, f.__class__ - - build_nonexistant = fs.Entry(test.workpath('build/nonexistant')) - f = build_nonexistant.disambiguate() - assert f.__class__ is fff.__class__, f.__class__ - - -class postprocessTestCase(unittest.TestCase): - def runTest(self): - """Test calling the postprocess() method.""" - fs = SCons.Node.FS.FS() - - e = fs.Entry('e') - e.postprocess() - - d = fs.Dir('d') - d.postprocess() - - f = fs.File('f') - f.postprocess() - - -class SpecialAttrTestCase(unittest.TestCase): - def runTest(self): - """Test special attributes of file nodes.""" - test = TestCmd(workdir='') - fs = SCons.Node.FS.FS(test.workpath('work')) - - f = fs.Entry('foo/bar/baz.blat').get_subst_proxy() - - s = str(f.dir) - assert s == os.path.normpath('foo/bar'), s - assert f.dir.is_literal(), f.dir - for_sig = f.dir.for_signature() - assert for_sig == 'bar', for_sig - - s = str(f.file) - assert s == 'baz.blat', s - assert f.file.is_literal(), f.file - for_sig = f.file.for_signature() - assert for_sig == 'baz.blat_file', for_sig - - s = str(f.base) - assert s == os.path.normpath('foo/bar/baz'), s - assert f.base.is_literal(), f.base - for_sig = f.base.for_signature() - assert for_sig == 'baz.blat_base', for_sig - - s = str(f.filebase) - assert s == 'baz', s - assert f.filebase.is_literal(), f.filebase - for_sig = f.filebase.for_signature() - assert for_sig == 'baz.blat_filebase', for_sig - - s = str(f.suffix) - assert s == '.blat', s - assert f.suffix.is_literal(), f.suffix - for_sig = f.suffix.for_signature() - assert for_sig == 'baz.blat_suffix', for_sig - - s = str(f.get_abspath()) - assert s == test.workpath('work', 'foo', 'bar', 'baz.blat'), s - assert f.abspath.is_literal(), f.abspath - for_sig = f.abspath.for_signature() - assert for_sig == 'baz.blat_abspath', for_sig - - s = str(f.posix) - assert s == 'foo/bar/baz.blat', s - assert f.posix.is_literal(), f.posix - if f.posix != f: - for_sig = f.posix.for_signature() - assert for_sig == 'baz.blat_posix', for_sig - - s = str(f.windows) - assert s == 'foo\\bar\\baz.blat', repr(s) - assert f.windows.is_literal(), f.windows - if f.windows != f: - for_sig = f.windows.for_signature() - assert for_sig == 'baz.blat_windows', for_sig - - # Deprecated synonym for the .windows suffix. - s = str(f.win32) - assert s == 'foo\\bar\\baz.blat', repr(s) - assert f.win32.is_literal(), f.win32 - if f.win32 != f: - for_sig = f.win32.for_signature() - assert for_sig == 'baz.blat_windows', for_sig - - # And now, combinations!!! - s = str(f.srcpath.base) - assert s == os.path.normpath('foo/bar/baz'), s - s = str(f.srcpath.dir) - assert s == str(f.srcdir), s - s = str(f.srcpath.posix) - assert s == 'foo/bar/baz.blat', s - s = str(f.srcpath.windows) - assert s == 'foo\\bar\\baz.blat', s - s = str(f.srcpath.win32) - assert s == 'foo\\bar\\baz.blat', s - - # Test what happens with VariantDir() - fs.VariantDir('foo', 'baz') - - s = str(f.srcpath) - assert s == os.path.normpath('baz/bar/baz.blat'), s - assert f.srcpath.is_literal(), f.srcpath - g = f.srcpath.get() - assert isinstance(g, SCons.Node.FS.File), g.__class__ - - s = str(f.srcdir) - assert s == os.path.normpath('baz/bar'), s - assert f.srcdir.is_literal(), f.srcdir - g = f.srcdir.get() - assert isinstance(g, SCons.Node.FS.Dir), g.__class__ - - # And now what happens with VariantDir() + Repository() - fs.Repository(test.workpath('repository')) - - f = fs.Entry('foo/sub/file.suffix').get_subst_proxy() - test.subdir('repository', - ['repository', 'baz'], - ['repository', 'baz', 'sub']) - - rd = test.workpath('repository', 'baz', 'sub') - rf = test.workpath('repository', 'baz', 'sub', 'file.suffix') - test.write(rf, "\n") - - s = str(f.srcpath) - assert s == os.path.normpath('baz/sub/file.suffix'), s - assert f.srcpath.is_literal(), f.srcpath - g = f.srcpath.get() - # Gets disambiguated to SCons.Node.FS.File by get_subst_proxy(). - assert isinstance(g, SCons.Node.FS.File), g.__class__ - - s = str(f.srcdir) - assert s == os.path.normpath('baz/sub'), s - assert f.srcdir.is_literal(), f.srcdir - g = f.srcdir.get() - assert isinstance(g, SCons.Node.FS.Dir), g.__class__ - - s = str(f.rsrcpath) - assert s == rf, s - assert f.rsrcpath.is_literal(), f.rsrcpath - g = f.rsrcpath.get() - assert isinstance(g, SCons.Node.FS.File), g.__class__ - - s = str(f.rsrcdir) - assert s == rd, s - assert f.rsrcdir.is_literal(), f.rsrcdir - g = f.rsrcdir.get() - assert isinstance(g, SCons.Node.FS.Dir), g.__class__ - - # Check that attempts to access non-existent attributes of the - # subst proxy generate the right exceptions and messages. - caught = None - try: - fs.Dir('ddd').get_subst_proxy().no_such_attr - except AttributeError as e: - assert str(e) == "Dir instance 'ddd' has no attribute 'no_such_attr'", e - caught = 1 - assert caught, "did not catch expected AttributeError" - - caught = None - try: - fs.Entry('eee').get_subst_proxy().no_such_attr - except AttributeError as e: - # Gets disambiguated to File instance by get_subst_proxy(). - assert str(e) == "File instance 'eee' has no attribute 'no_such_attr'", e - caught = 1 - assert caught, "did not catch expected AttributeError" - - caught = None - try: - fs.File('fff').get_subst_proxy().no_such_attr - except AttributeError as e: - assert str(e) == "File instance 'fff' has no attribute 'no_such_attr'", e - caught = 1 - assert caught, "did not catch expected AttributeError" - - -class SaveStringsTestCase(unittest.TestCase): - def runTest(self): - """Test caching string values of nodes.""" - test = TestCmd(workdir='') - - def setup(fs): - fs.Dir('src') - fs.Dir('d0') - fs.Dir('d1') - - d0_f = fs.File('d0/f') - d1_f = fs.File('d1/f') - d0_b = fs.File('d0/b') - d1_b = fs.File('d1/b') - d1_f.duplicate = 1 - d1_b.duplicate = 1 - d0_b.builder = 1 - d1_b.builder = 1 - - return [d0_f, d1_f, d0_b, d1_b] - - def modify(nodes): - d0_f, d1_f, d0_b, d1_b = nodes - d1_f.duplicate = 0 - d1_b.duplicate = 0 - d0_b.builder = 0 - d1_b.builder = 0 - - fs1 = SCons.Node.FS.FS(test.workpath('fs1')) - nodes = setup(fs1) - fs1.VariantDir('d0', 'src', duplicate=0) - fs1.VariantDir('d1', 'src', duplicate=1) - - s = list(map(str, nodes)) - expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])) - assert s == expect, s - - modify(nodes) - - s = list(map(str, nodes)) - expect = list(map(os.path.normpath, ['src/f', 'src/f', 'd0/b', 'd1/b'])) - assert s == expect, s - - SCons.Node.FS.save_strings(1) - fs2 = SCons.Node.FS.FS(test.workpath('fs2')) - nodes = setup(fs2) - fs2.VariantDir('d0', 'src', duplicate=0) - fs2.VariantDir('d1', 'src', duplicate=1) - - s = list(map(str, nodes)) - expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])) - assert s == expect, s - - modify(nodes) - - s = list(map(str, nodes)) - expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])) - assert s == expect, 'node str() not cached: %s' % s - - -class AbsolutePathTestCase(unittest.TestCase): - def test_root_lookup_equivalence(self): - """Test looking up /fff vs. fff in the / directory""" - test = TestCmd(workdir='') - - fs = SCons.Node.FS.FS('/') - - save_cwd = os.getcwd() - try: - os.chdir('/') - fff1 = fs.File('fff') - fff2 = fs.File('/fff') - assert fff1 is fff2, "fff and /fff returned different Nodes!" - finally: - os.chdir(save_cwd) - - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Node/NodeTests.py b/SCSCons/Node/NodeTests.py deleted file mode 100644 index b36c2e945..000000000 --- a/SCSCons/Node/NodeTests.py +++ /dev/null @@ -1,1382 +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 SCons.compat - -import collections -import re -import unittest - -import SCons.Errors -import SCons.Node -import SCons.Util - - - -built_it = None -built_target = None -built_source = None -cycle_detected = None -built_order = 0 - -def _actionAppend(a1, a2): - all = [] - for curr_a in [a1, a2]: - if isinstance(curr_a, MyAction): - all.append(curr_a) - elif isinstance(curr_a, MyListAction): - all.extend(curr_a.list) - elif isinstance(curr_a, list): - all.extend(curr_a) - else: - raise Exception('Cannot Combine Actions') - return MyListAction(all) - -class MyActionBase: - def __add__(self, other): - return _actionAppend(self, other) - - def __radd__(self, other): - return _actionAppend(other, self) - -class MyAction(MyActionBase): - def __init__(self): - self.order = 0 - - def __call__(self, target, source, env, executor=None): - global built_it, built_target, built_source, built_args, built_order - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - built_it = 1 - built_target = target - built_source = source - built_args = env - built_order = built_order + 1 - self.order = built_order - return 0 - - def get_implicit_deps(self, target, source, env): - return [] - -class MyExecutor: - def __init__(self, env=None, targets=[], sources=[]): - self.env = env - self.targets = targets - self.sources = sources - def get_build_env(self): - return self.env - def get_build_scanner_path(self, scanner): - return 'executor would call %s' % scanner - def cleanup(self): - self.cleaned_up = 1 - def scan_targets(self, scanner): - if not scanner: - return - d = scanner(self.targets) - for t in self.targets: - t.implicit.extend(d) - def scan_sources(self, scanner): - if not scanner: - return - d = scanner(self.sources) - for t in self.targets: - t.implicit.extend(d) - -class MyListAction(MyActionBase): - def __init__(self, list): - self.list = list - def __call__(self, target, source, env): - for A in self.list: - A(target, source, env) - -class Environment: - def __init__(self, **kw): - self._dict = {} - self._dict.update(kw) - def __getitem__(self, key): - return self._dict[key] - def get(self, key, default = None): - return self._dict.get(key, default) - def Dictionary(self, *args): - return {} - def Override(self, overrides): - d = self._dict.copy() - d.update(overrides) - return Environment(**d) - def _update(self, dict): - self._dict.update(dict) - def get_factory(self, factory): - return factory or MyNode - def get_scanner(self, scanner_key): - try: - return self._dict['SCANNERS'][0] - except: - pass - - return [] - -class Builder: - def __init__(self, env=None, is_explicit=1): - if env is None: env = Environment() - self.env = env - self.overrides = {} - self.action = MyAction() - self.source_factory = MyNode - self.is_explicit = is_explicit - self.target_scanner = None - self.source_scanner = None - def targets(self, t): - return [t] - def get_actions(self): - return [self.action] - def get_contents(self, target, source, env): - return 7 - -class NoneBuilder(Builder): - def execute(self, target, source, env): - Builder.execute(self, target, source, env) - return None - -class ListBuilder(Builder): - def __init__(self, *nodes): - Builder.__init__(self) - self.nodes = nodes - def execute(self, target, source, env): - if hasattr(self, 'status'): - return self.status - for n in self.nodes: - n.prepare() - target = self.nodes[0] - self.status = Builder.execute(self, target, source, env) - -class FailBuilder: - def execute(self, target, source, env): - return 1 - -class ExceptBuilder: - def execute(self, target, source, env): - raise SCons.Errors.BuildError - -class ExceptBuilder2: - def execute(self, target, source, env): - raise Exception("foo") - -class Scanner: - called = None - def __call__(self, node): - self.called = 1 - return node.GetTag('found_includes') - def path(self, env, dir=None, target=None, source=None, kw={}): - return () - def select(self, node): - return self - def recurse_nodes(self, nodes): - return nodes - -class MyNode(SCons.Node.Node): - """The base Node class contains a number of do-nothing methods that - we expect to be overridden by real, functional Node subclasses. So - simulate a real, functional Node subclass. - """ - def __init__(self, name): - SCons.Node.Node.__init__(self) - self.name = name - self.Tag('found_includes', []) - def __str__(self): - return self.name - def get_found_includes(self, env, scanner, target): - return scanner(self) - -class Calculator: - def __init__(self, val): - self.max_drift = 0 - class M: - def __init__(self, val): - self.val = val - def signature(self, args): - return self.val - def collect(self, args): - result = self.val - for a in args: - result += a - return result - self.module = M(val) - - - -class NodeInfoBaseTestCase(unittest.TestCase): - # The abstract class NodeInfoBase has not enough default slots to perform - # the merge and format test (arbitrary attributes do not work). Do it with a - # derived class that does provide the slots. - - def test_merge(self): - """Test merging NodeInfoBase attributes""" - - class TestNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('a1', 'a2', 'a3') - - ni1 = TestNodeInfo() - ni2 = TestNodeInfo() - - ni1.a1 = 1 - ni1.a2 = 2 - - ni2.a2 = 222 - ni2.a3 = 333 - - ni1.merge(ni2) - assert ni1.a1 == 1, ni1.a1 - assert ni1.a2 == 222, ni1.a2 - assert ni1.a3 == 333, ni1.a3 - - def test_update(self): - """Test the update() method""" - ni = SCons.Node.NodeInfoBase() - ni.update(SCons.Node.Node()) - - def test_format(self): - """Test the NodeInfoBase.format() method""" - - class TestNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('xxx', 'yyy', 'zzz') - - ni1 = TestNodeInfo() - ni1.xxx = 'x' - ni1.yyy = 'y' - ni1.zzz = 'z' - - f = ni1.format() - assert f == ['x', 'y', 'z'], f - - field_list = ['xxx', 'zzz', 'aaa'] - - f = ni1.format(field_list) - assert f == ['x', 'z', 'None'], f - - - -class BuildInfoBaseTestCase(unittest.TestCase): - - def test___init__(self): - """Test BuildInfoBase initialization""" - n = SCons.Node.Node() - bi = SCons.Node.BuildInfoBase() - assert bi - - def test_merge(self): - """Test merging BuildInfoBase attributes""" - n1 = SCons.Node.Node() - bi1 = SCons.Node.BuildInfoBase() - n2 = SCons.Node.Node() - bi2 = SCons.Node.BuildInfoBase() - - bi1.bsources = 1 - bi1.bdepends = 2 - - bi2.bdepends = 222 - bi2.bact = 333 - - bi1.merge(bi2) - assert bi1.bsources == 1, bi1.bsources - assert bi1.bdepends == 222, bi1.bdepends - assert bi1.bact == 333, bi1.bact - - -class NodeTestCase(unittest.TestCase): - - def test_build(self): - """Test building a node - """ - global built_it, built_order - - # Make sure it doesn't blow up if no builder is set. - node = MyNode("www") - node.build() - assert built_it is None - node.build(extra_kw_argument = 1) - assert built_it is None - - node = MyNode("xxx") - node.builder_set(Builder()) - node.env_set(Environment()) - node.path = "xxx" - node.sources = ["yyy", "zzz"] - node.build() - assert built_it - assert built_target == [node], built_target - assert built_source == ["yyy", "zzz"], built_source - - built_it = None - node = MyNode("qqq") - node.builder_set(NoneBuilder()) - node.env_set(Environment()) - node.path = "qqq" - node.sources = ["rrr", "sss"] - node.builder.overrides = { "foo" : 1, "bar" : 2 } - node.build() - assert built_it - assert built_target == [node], built_target - assert built_source == ["rrr", "sss"], built_source - assert built_args["foo"] == 1, built_args - assert built_args["bar"] == 2, built_args - - fff = MyNode("fff") - ggg = MyNode("ggg") - lb = ListBuilder(fff, ggg) - e = Environment() - fff.builder_set(lb) - fff.env_set(e) - fff.path = "fff" - ggg.builder_set(lb) - ggg.env_set(e) - ggg.path = "ggg" - fff.sources = ["hhh", "iii"] - ggg.sources = ["hhh", "iii"] - built_it = None - fff.build() - assert built_it - assert built_target == [fff], built_target - assert built_source == ["hhh", "iii"], built_source - built_it = None - ggg.build() - assert built_it - assert built_target == [ggg], built_target - assert built_source == ["hhh", "iii"], built_source - - built_it = None - jjj = MyNode("jjj") - b = Builder() - jjj.builder_set(b) - # NOTE: No env_set()! We should pull the environment from the builder. - b.env = Environment() - b.overrides = { "on" : 3, "off" : 4 } - e.builder = b - jjj.build() - assert built_it - assert built_target[0] == jjj, built_target[0] - assert built_source == [], built_source - assert built_args["on"] == 3, built_args - assert built_args["off"] == 4, built_args - - def test_get_build_scanner_path(self): - """Test the get_build_scanner_path() method""" - n = SCons.Node.Node() - x = MyExecutor() - n.set_executor(x) - p = n.get_build_scanner_path('fake_scanner') - assert p == "executor would call fake_scanner", p - - def test_get_executor(self): - """Test the get_executor() method""" - n = SCons.Node.Node() - - try: - n.get_executor(0) - except AttributeError: - pass - else: - self.fail("did not catch expected AttributeError") - - class Builder: - action = 'act' - env = 'env1' - overrides = {} - - n = SCons.Node.Node() - n.builder_set(Builder()) - x = n.get_executor() - assert x.env == 'env1', x.env - - n = SCons.Node.Node() - n.builder_set(Builder()) - n.env_set('env2') - x = n.get_executor() - assert x.env == 'env2', x.env - - def test_set_executor(self): - """Test the set_executor() method""" - n = SCons.Node.Node() - n.set_executor(1) - assert n.executor == 1, n.executor - - def test_executor_cleanup(self): - """Test letting the executor cleanup its cache""" - n = SCons.Node.Node() - x = MyExecutor() - n.set_executor(x) - n.executor_cleanup() - assert x.cleaned_up - - def test_reset_executor(self): - """Test the reset_executor() method""" - n = SCons.Node.Node() - n.set_executor(1) - assert n.executor == 1, n.executor - n.reset_executor() - assert not hasattr(n, 'executor'), "unexpected executor attribute" - - def test_built(self): - """Test the built() method""" - class SubNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('updated',) - def update(self, node): - self.updated = 1 - class SubNode(SCons.Node.Node): - def clear(self): - self.cleared = 1 - - n = SubNode() - n.ninfo = SubNodeInfo() - n.built() - assert n.cleared, n.cleared - assert n.ninfo.updated, n.ninfo.cleared - - def test_push_to_cache(self): - """Test the base push_to_cache() method""" - n = SCons.Node.Node() - r = n.push_to_cache() - assert r is None, r - - def test_retrieve_from_cache(self): - """Test the base retrieve_from_cache() method""" - n = SCons.Node.Node() - r = n.retrieve_from_cache() - assert r == 0, r - - def test_visited(self): - """Test the base visited() method - - Just make sure it's there and we can call it. - """ - n = SCons.Node.Node() - n.visited() - - def test_builder_set(self): - """Test setting a Node's Builder - """ - node = SCons.Node.Node() - b = Builder() - node.builder_set(b) - assert node.builder == b - - def test_has_builder(self): - """Test the has_builder() method - """ - n1 = SCons.Node.Node() - assert n1.has_builder() == 0 - n1.builder_set(Builder()) - assert n1.has_builder() == 1 - - def test_has_explicit_builder(self): - """Test the has_explicit_builder() method - """ - n1 = SCons.Node.Node() - assert not n1.has_explicit_builder() - n1.set_explicit(1) - assert n1.has_explicit_builder() - n1.set_explicit(None) - assert not n1.has_explicit_builder() - - def test_get_builder(self): - """Test the get_builder() method""" - n1 = SCons.Node.Node() - b = n1.get_builder() - assert b is None, b - b = n1.get_builder(777) - assert b == 777, b - n1.builder_set(888) - b = n1.get_builder() - assert b == 888, b - b = n1.get_builder(999) - assert b == 888, b - - def test_multiple_side_effect_has_builder(self): - """Test the multiple_side_effect_has_builder() method - """ - n1 = SCons.Node.Node() - assert n1.multiple_side_effect_has_builder() == 0 - n1.builder_set(Builder()) - assert n1.multiple_side_effect_has_builder() == 1 - - def test_is_derived(self): - """Test the is_derived() method - """ - n1 = SCons.Node.Node() - n2 = SCons.Node.Node() - n3 = SCons.Node.Node() - - n2.builder_set(Builder()) - n3.side_effect = 1 - - assert n1.is_derived() == 0 - assert n2.is_derived() == 1 - assert n3.is_derived() == 1 - - def test_alter_targets(self): - """Test the alter_targets() method - """ - n = SCons.Node.Node() - t, m = n.alter_targets() - assert t == [], t - assert m is None, m - - def test_is_up_to_date(self): - """Test the default is_up_to_date() method - """ - node = SCons.Node.Node() - assert node.is_up_to_date() is None - - def test_children_are_up_to_date(self): - """Test the children_are_up_to_date() method used by subclasses - """ - n1 = SCons.Node.Node() - n2 = SCons.Node.Node() - - n1.add_source([n2]) - assert n1.children_are_up_to_date(), "expected up to date" - n2.set_state(SCons.Node.executed) - assert not n1.children_are_up_to_date(), "expected not up to date" - n2.set_state(SCons.Node.up_to_date) - assert n1.children_are_up_to_date(), "expected up to date" - n1.always_build = 1 - assert not n1.children_are_up_to_date(), "expected not up to date" - - def test_env_set(self): - """Test setting a Node's Environment - """ - node = SCons.Node.Node() - e = Environment() - node.env_set(e) - assert node.env == e - - def test_get_actions(self): - """Test fetching a Node's action list - """ - node = SCons.Node.Node() - node.builder_set(Builder()) - a = node.builder.get_actions() - assert isinstance(a[0], MyAction), a[0] - - def test_get_csig(self): - """Test generic content signature calculation - """ - - class TestNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig',) - try: - SCons.Node.Node.NodeInfo = TestNodeInfo - def my_contents(obj): - return 444 - SCons.Node._get_contents_map[4] = my_contents - node = SCons.Node.Node() - node._func_get_contents = 4 - result = node.get_csig() - assert result in ('550a141f12de6341fba65b0ad0433500', '9a3e61b6bcc8abec08f195526c3132d5a4a98cc0', '3538a1ef2e113da64249eea7bd068b585ec7ce5df73b2d1e319d8c9bf47eb314'), result - finally: - SCons.Node.Node.NodeInfo = SCons.Node.NodeInfoBase - - def test_get_cachedir_csig(self): - """Test content signature calculation for CacheDir - """ - class TestNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig',) - try: - SCons.Node.Node.NodeInfo = TestNodeInfo - def my_contents(obj): - return 555 - SCons.Node._get_contents_map[4] = my_contents - node = SCons.Node.Node() - node._func_get_contents = 4 - result = node.get_cachedir_csig() - assert result in ('15de21c670ae7c3f6f3f1f37029303c9', 'cfa1150f1787186742a9a884b73a43d8cf219f9b', '91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8'), result - finally: - SCons.Node.Node.NodeInfo = SCons.Node.NodeInfoBase - - def test_get_binfo(self): - """Test fetching/creating a build information structure - """ - class TestNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig',) - SCons.Node.Node.NodeInfo = TestNodeInfo - node = SCons.Node.Node() - - binfo = node.get_binfo() - assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo - - node = SCons.Node.Node() - d = SCons.Node.Node() - ninfo = d.get_ninfo() - assert isinstance(ninfo, SCons.Node.NodeInfoBase), ninfo - i = SCons.Node.Node() - ninfo = i.get_ninfo() - assert isinstance(ninfo, SCons.Node.NodeInfoBase), ninfo - node.depends = [d] - node.implicit = [i] - - binfo = node.get_binfo() - assert isinstance(binfo, SCons.Node.BuildInfoBase), binfo - assert hasattr(binfo, 'bsources') - assert hasattr(binfo, 'bsourcesigs') - assert binfo.bdepends == [d] - assert hasattr(binfo, 'bdependsigs') - assert binfo.bimplicit == [i] - assert hasattr(binfo, 'bimplicitsigs') - - def test_explain(self): - """Test explaining why a Node must be rebuilt - """ - class testNode(SCons.Node.Node): - def __str__(self): return 'xyzzy' - node = testNode() - node.exists = lambda: None - # Can't do this with new-style classes (python bug #1066490) - #node.__str__ = lambda: 'xyzzy' - result = node.explain() - assert result == "building `xyzzy' because it doesn't exist\n", result - - class testNode2(SCons.Node.Node): - def __str__(self): return 'null_binfo' - class FS: - pass - node = testNode2() - node.fs = FS() - node.fs.Top = SCons.Node.Node() - result = node.explain() - assert result is None, result - - def get_null_info(): - class Null_SConsignEntry: - class Null_BuildInfo: - def prepare_dependencies(self): - pass - binfo = Null_BuildInfo() - return Null_SConsignEntry() - - node.get_stored_info = get_null_info - #see above: node.__str__ = lambda: 'null_binfo' - result = node.explain() - assert result == "Cannot explain why `null_binfo' is being rebuilt: No previous build information found\n", result - - # XXX additional tests for the guts of the functionality some day - - #def test_del_binfo(self): - # """Test deleting the build information from a Node - # """ - # node = SCons.Node.Node() - # node.binfo = None - # node.del_binfo() - # assert not hasattr(node, 'binfo'), node - - def test_store_info(self): - """Test calling the method to store build information - """ - node = SCons.Node.Node() - SCons.Node.store_info_map[node.store_info](node) - - def test_get_stored_info(self): - """Test calling the method to fetch stored build information - """ - node = SCons.Node.Node() - result = node.get_stored_info() - assert result is None, result - - def test_set_always_build(self): - """Test setting a Node's always_build value - """ - node = SCons.Node.Node() - node.set_always_build() - assert node.always_build - node.set_always_build(3) - assert node.always_build == 3 - - def test_set_noclean(self): - """Test setting a Node's noclean value - """ - node = SCons.Node.Node() - node.set_noclean() - assert node.noclean == 1, node.noclean - node.set_noclean(7) - assert node.noclean == 1, node.noclean - node.set_noclean(0) - assert node.noclean == 0, node.noclean - node.set_noclean(None) - assert node.noclean == 0, node.noclean - - def test_set_precious(self): - """Test setting a Node's precious value - """ - node = SCons.Node.Node() - node.set_precious() - assert node.precious - node.set_precious(7) - assert node.precious == 7 - - def test_set_pseudo(self): - """Test setting a Node's pseudo value - """ - node = SCons.Node.Node() - node.set_pseudo() - assert node.pseudo - node.set_pseudo(False) - assert not node.pseudo - - def test_exists(self): - """Test evaluating whether a Node exists. - """ - node = SCons.Node.Node() - e = node.exists() - assert e == 1, e - - def test_exists_repo(self): - """Test evaluating whether a Node exists locally or in a repository. - """ - node = SCons.Node.Node() - e = node.rexists() - assert e == 1, e - - class MyNode(SCons.Node.Node): - def exists(self): - return 'xyz' - - node = MyNode() - e = node.rexists() - assert e == 'xyz', e - - def test_prepare(self): - """Test preparing a node to be built - - By extension, this also tests the missing() method. - """ - node = SCons.Node.Node() - - n1 = SCons.Node.Node() - n1.builder_set(Builder()) - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n1]) - - node.prepare() # should not throw an exception - - n2 = SCons.Node.Node() - n2.linked = 1 - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n2]) - - node.prepare() # should not throw an exception - - n3 = SCons.Node.Node() - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n3]) - - node.prepare() # should not throw an exception - - class MyNode(SCons.Node.Node): - def rexists(self): - return None - n4 = MyNode() - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n4]) - exc_caught = 0 - try: - node.prepare() - except SCons.Errors.StopError: - exc_caught = 1 - assert exc_caught, "did not catch expected StopError" - - def test_add_dependency(self): - """Test adding dependencies to a Node's list. - """ - node = SCons.Node.Node() - assert node.depends == [] - - zero = SCons.Node.Node() - - one = SCons.Node.Node() - two = SCons.Node.Node() - three = SCons.Node.Node() - four = SCons.Node.Node() - five = SCons.Node.Node() - six = SCons.Node.Node() - - node.add_dependency([zero]) - assert node.depends == [zero] - node.add_dependency([one]) - assert node.depends == [zero, one] - node.add_dependency([two, three]) - assert node.depends == [zero, one, two, three] - node.add_dependency([three, four, one]) - assert node.depends == [zero, one, two, three, four] - - try: - node.add_depends([[five, six]]) - except: - pass - else: - raise Exception("did not catch expected exception") - assert node.depends == [zero, one, two, three, four] - - - def test_add_source(self): - """Test adding sources to a Node's list. - """ - node = SCons.Node.Node() - assert node.sources == [] - - zero = SCons.Node.Node() - one = SCons.Node.Node() - two = SCons.Node.Node() - three = SCons.Node.Node() - four = SCons.Node.Node() - five = SCons.Node.Node() - six = SCons.Node.Node() - - node.add_source([zero]) - assert node.sources == [zero] - node.add_source([one]) - assert node.sources == [zero, one] - node.add_source([two, three]) - assert node.sources == [zero, one, two, three] - node.add_source([three, four, one]) - assert node.sources == [zero, one, two, three, four] - - try: - node.add_source([[five, six]]) - except: - pass - else: - raise Exception("did not catch expected exception") - assert node.sources == [zero, one, two, three, four], node.sources - - def test_add_ignore(self): - """Test adding files whose dependencies should be ignored. - """ - node = SCons.Node.Node() - assert node.ignore == [] - - zero = SCons.Node.Node() - one = SCons.Node.Node() - two = SCons.Node.Node() - three = SCons.Node.Node() - four = SCons.Node.Node() - five = SCons.Node.Node() - six = SCons.Node.Node() - - node.add_ignore([zero]) - assert node.ignore == [zero] - node.add_ignore([one]) - assert node.ignore == [zero, one] - node.add_ignore([two, three]) - assert node.ignore == [zero, one, two, three] - node.add_ignore([three, four, one]) - assert node.ignore == [zero, one, two, three, four] - - try: - node.add_ignore([[five, six]]) - except: - pass - else: - raise Exception("did not catch expected exception") - assert node.ignore == [zero, one, two, three, four] - - def test_get_found_includes(self): - """Test the default get_found_includes() method - """ - node = SCons.Node.Node() - target = SCons.Node.Node() - e = Environment() - deps = node.get_found_includes(e, None, target) - assert deps == [], deps - - def test_get_implicit_deps(self): - """Test get_implicit_deps() - """ - node = MyNode("nnn") - target = MyNode("ttt") - env = Environment() - - # No scanner at all returns [] - deps = node.get_implicit_deps(env, None, target) - assert deps == [], deps - - s = Scanner() - d1 = MyNode("d1") - d2 = MyNode("d2") - node.Tag('found_includes', [d1, d2]) - - # Simple return of the found includes - deps = node.get_implicit_deps(env, s, s.path) - assert deps == [d1, d2], deps - - # By default, our fake scanner recurses - e = MyNode("eee") - f = MyNode("fff") - g = MyNode("ggg") - d1.Tag('found_includes', [e, f]) - d2.Tag('found_includes', [e, f]) - f.Tag('found_includes', [g]) - deps = node.get_implicit_deps(env, s, s.path) - assert deps == [d1, d2, e, f, g], list(map(str, deps)) - - # Recursive scanning eliminates duplicates - e.Tag('found_includes', [f]) - deps = node.get_implicit_deps(env, s, s.path) - assert deps == [d1, d2, e, f, g], list(map(str, deps)) - - # Scanner method can select specific nodes to recurse - def no_fff(nodes): - return [n for n in nodes if str(n)[0] != 'f'] - s.recurse_nodes = no_fff - deps = node.get_implicit_deps(env, s, s.path) - assert deps == [d1, d2, e, f], list(map(str, deps)) - - # Scanner method can short-circuit recursing entirely - s.recurse_nodes = lambda nodes: [] - deps = node.get_implicit_deps(env, s, s.path) - assert deps == [d1, d2], list(map(str, deps)) - - def test_get_env_scanner(self): - """Test fetching the environment scanner for a Node - """ - node = SCons.Node.Node() - scanner = Scanner() - env = Environment(SCANNERS = [scanner]) - s = node.get_env_scanner(env) - assert s == scanner, s - s = node.get_env_scanner(env, {'X':1}) - assert s == scanner, s - - def test_get_target_scanner(self): - """Test fetching the target scanner for a Node - """ - s = Scanner() - b = Builder() - b.target_scanner = s - n = SCons.Node.Node() - n.builder = b - x = n.get_target_scanner() - assert x is s, x - - def test_get_source_scanner(self): - """Test fetching the source scanner for a Node - """ - target = SCons.Node.Node() - source = SCons.Node.Node() - s = target.get_source_scanner(source) - assert isinstance(s, SCons.Util.Null), s - - ts1 = Scanner() - ts2 = Scanner() - ts3 = Scanner() - - class Builder1(Builder): - def __call__(self, source): - r = SCons.Node.Node() - r.builder = self - return [r] - class Builder2(Builder1): - def __init__(self, scanner): - self.source_scanner = scanner - - builder = Builder2(ts1) - - targets = builder([source]) - s = targets[0].get_source_scanner(source) - assert s is ts1, s - - target.builder_set(Builder2(ts1)) - target.builder.source_scanner = ts2 - s = target.get_source_scanner(source) - assert s is ts2, s - - builder = Builder1(env=Environment(SCANNERS = [ts3])) - - targets = builder([source]) - - s = targets[0].get_source_scanner(source) - assert s is ts3, s - - - def test_scan(self): - """Test Scanner functionality - """ - env = Environment() - node = MyNode("nnn") - node.builder = Builder() - node.env_set(env) - x = MyExecutor(env, [node]) - - s = Scanner() - d = MyNode("ddd") - node.Tag('found_includes', [d]) - - node.builder.target_scanner = s - assert node.implicit is None - - node.scan() - assert s.called - assert node.implicit == [d], node.implicit - - # Check that scanning a node with some stored implicit - # dependencies resets internal attributes appropriately - # if the stored dependencies need recalculation. - class StoredNode(MyNode): - def get_stored_implicit(self): - return [MyNode('implicit1'), MyNode('implicit2')] - - save_implicit_cache = SCons.Node.implicit_cache - save_implicit_deps_changed = SCons.Node.implicit_deps_changed - save_implicit_deps_unchanged = SCons.Node.implicit_deps_unchanged - SCons.Node.implicit_cache = 1 - SCons.Node.implicit_deps_changed = None - SCons.Node.implicit_deps_unchanged = None - try: - sn = StoredNode("eee") - sn.builder_set(Builder()) - sn.builder.target_scanner = s - - sn.scan() - - assert sn.implicit == [], sn.implicit - assert sn.children() == [], sn.children() - - finally: - SCons.Node.implicit_cache = save_implicit_cache - SCons.Node.implicit_deps_changed = save_implicit_deps_changed - SCons.Node.implicit_deps_unchanged = save_implicit_deps_unchanged - - def test_scanner_key(self): - """Test that a scanner_key() method exists""" - assert SCons.Node.Node().scanner_key() is None - - def test_children(self): - """Test fetching the non-ignored "children" of a Node. - """ - node = SCons.Node.Node() - n1 = SCons.Node.Node() - n2 = SCons.Node.Node() - n3 = SCons.Node.Node() - n4 = SCons.Node.Node() - n5 = SCons.Node.Node() - n6 = SCons.Node.Node() - n7 = SCons.Node.Node() - n8 = SCons.Node.Node() - n9 = SCons.Node.Node() - n10 = SCons.Node.Node() - n11 = SCons.Node.Node() - n12 = SCons.Node.Node() - - node.add_source([n1, n2, n3]) - node.add_dependency([n4, n5, n6]) - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n7, n8, n9]) - node._add_child(node.implicit, node.implicit_set, [n10, n11, n12]) - node.add_ignore([n2, n5, n8, n11]) - - kids = node.children() - for kid in [n1, n3, n4, n6, n7, n9, n10, n12]: - assert kid in kids, kid - for kid in [n2, n5, n8, n11]: - assert kid not in kids, kid - - def test_all_children(self): - """Test fetching all the "children" of a Node. - """ - node = SCons.Node.Node() - n1 = SCons.Node.Node() - n2 = SCons.Node.Node() - n3 = SCons.Node.Node() - n4 = SCons.Node.Node() - n5 = SCons.Node.Node() - n6 = SCons.Node.Node() - n7 = SCons.Node.Node() - n8 = SCons.Node.Node() - n9 = SCons.Node.Node() - n10 = SCons.Node.Node() - n11 = SCons.Node.Node() - n12 = SCons.Node.Node() - - node.add_source([n1, n2, n3]) - node.add_dependency([n4, n5, n6]) - node.implicit = [] - node.implicit_set = set() - node._add_child(node.implicit, node.implicit_set, [n7, n8, n9]) - node._add_child(node.implicit, node.implicit_set, [n10, n11, n12]) - node.add_ignore([n2, n5, n8, n11]) - - kids = node.all_children() - for kid in [n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12]: - assert kid in kids, kid - - def test_state(self): - """Test setting and getting the state of a node - """ - node = SCons.Node.Node() - assert node.get_state() == SCons.Node.no_state - node.set_state(SCons.Node.executing) - assert node.get_state() == SCons.Node.executing - assert SCons.Node.pending < SCons.Node.executing - assert SCons.Node.executing < SCons.Node.up_to_date - assert SCons.Node.up_to_date < SCons.Node.executed - assert SCons.Node.executed < SCons.Node.failed - - def test_walker(self): - """Test walking a Node tree. - """ - - n1 = MyNode("n1") - - nw = SCons.Node.Walker(n1) - assert not nw.is_done() - assert nw.get_next().name == "n1" - assert nw.is_done() - assert nw.get_next() is None - - n2 = MyNode("n2") - n3 = MyNode("n3") - n1.add_source([n2, n3]) - - nw = SCons.Node.Walker(n1) - n = nw.get_next() - assert n.name == "n2", n.name - n = nw.get_next() - assert n.name == "n3", n.name - n = nw.get_next() - assert n.name == "n1", n.name - n = nw.get_next() - assert n is None, n - - n4 = MyNode("n4") - n5 = MyNode("n5") - n6 = MyNode("n6") - n7 = MyNode("n7") - n2.add_source([n4, n5]) - n3.add_dependency([n6, n7]) - - nw = SCons.Node.Walker(n1) - assert nw.get_next().name == "n4" - assert nw.get_next().name == "n5" - assert n2 in nw.history - assert nw.get_next().name == "n2" - assert nw.get_next().name == "n6" - assert nw.get_next().name == "n7" - assert n3 in nw.history - assert nw.get_next().name == "n3" - assert n1 in nw.history - assert nw.get_next().name == "n1" - assert nw.get_next() is None - - n8 = MyNode("n8") - n8.add_dependency([n3]) - n7.add_dependency([n8]) - - def cycle(node, stack): - global cycle_detected - cycle_detected = 1 - - global cycle_detected - - nw = SCons.Node.Walker(n3, cycle_func = cycle) - n = nw.get_next() - assert n.name == "n6", n.name - n = nw.get_next() - assert n.name == "n8", n.name - assert cycle_detected - cycle_detected = None - n = nw.get_next() - assert n.name == "n7", n.name - n = nw.get_next() - assert nw.get_next() is None - - def test_abspath(self): - """Test the get_abspath() method.""" - n = MyNode("foo") - assert n.get_abspath() == str(n), n.get_abspath() - - def test_for_signature(self): - """Test the for_signature() method.""" - n = MyNode("foo") - assert n.for_signature() == str(n), n.get_abspath() - - def test_get_string(self): - """Test the get_string() method.""" - class TestNode(MyNode): - def __init__(self, name, sig): - MyNode.__init__(self, name) - self.sig = sig - - def for_signature(self): - return self.sig - - n = TestNode("foo", "bar") - assert n.get_string(0) == "foo", n.get_string(0) - assert n.get_string(1) == "bar", n.get_string(1) - - def test_literal(self): - """Test the is_literal() function.""" - n=SCons.Node.Node() - assert n.is_literal() - - def test_sconscripts(self): - """Test the is_sconscript() function.""" - # check nodes are not sconscript unless added to the list - n=SCons.Node.Node() - n2=SCons.Node.Node() - assert not n.is_sconscript() - assert not n2.is_sconscript() - - # add node to sconscript list and verify - SCons.Node.SConscriptNodes.add(n2) - assert not n.is_sconscript() - assert n2.is_sconscript() - - def test_conftests(self): - """Test the is_conftest() function.""" - # check nodes are not sconscript unless added to the list - n=SCons.Node.Node() - n2=SCons.Node.Node() - assert not n.is_conftest() - assert not n2.is_conftest() - - # add node to sconscript list and verify - n2.attributes.conftest_node = 1 - assert not n.is_conftest() - assert n2.is_conftest() - - def test_Annotate(self): - """Test using an interface-specific Annotate function.""" - def my_annotate(node, self=self): - node.Tag('annotation', self.node_string) - - save_Annotate = SCons.Node.Annotate - SCons.Node.Annotate = my_annotate - - try: - self.node_string = '#1' - n = SCons.Node.Node() - a = n.GetTag('annotation') - assert a == '#1', a - - self.node_string = '#2' - n = SCons.Node.Node() - a = n.GetTag('annotation') - assert a == '#2', a - finally: - SCons.Node.Annotate = save_Annotate - - def test_clear(self): - """Test clearing all cached state information.""" - n = SCons.Node.Node() - - n.set_state(3) - n.binfo = 'xyz' - n.includes = 'testincludes' - n.Tag('found_includes', {'testkey':'testvalue'}) - n.implicit = 'testimplicit' - n.cached = 1 - - x = MyExecutor() - n.set_executor(x) - - n.clear() - - assert n.includes is None, n.includes - assert n.cached == 0, n.cached - assert x.cleaned_up - - def test_get_subst_proxy(self): - """Test the get_subst_proxy method.""" - n = MyNode("test") - - assert n.get_subst_proxy() == n, n.get_subst_proxy() - - def test_new_binfo(self): - """Test the new_binfo() method""" - n = SCons.Node.Node() - result = n.new_binfo() - assert isinstance(result, SCons.Node.BuildInfoBase), result - - def test_get_suffix(self): - """Test the base Node get_suffix() method""" - n = SCons.Node.Node() - s = n.get_suffix() - assert s == '', s - - def test_postprocess(self): - """Test calling the base Node postprocess() method""" - n = SCons.Node.Node() - n.waiting_parents = {'foo', 'bar'} - - n.postprocess() - assert n.waiting_parents == set(), n.waiting_parents - - def test_add_to_waiting_parents(self): - """Test the add_to_waiting_parents() method""" - n1 = SCons.Node.Node() - n2 = SCons.Node.Node() - assert n1.waiting_parents == set(), n1.waiting_parents - r = n1.add_to_waiting_parents(n2) - assert r == 1, r - assert n1.waiting_parents == {n2}, n1.waiting_parents - r = n1.add_to_waiting_parents(n2) - assert r == 0, r - - -class NodeListTestCase(unittest.TestCase): - def test___str__(self): - """Test""" - n1 = MyNode("n1") - n2 = MyNode("n2") - n3 = MyNode("n3") - nl = SCons.Node.NodeList([n3, n2, n1]) - - l = [1] - ul = collections.UserList([2]) - s = str(nl) - assert s == "['n3', 'n2', 'n1']", s - - r = repr(nl) - r = re.sub(r'at (0[xX])?[0-9a-fA-F]+', 'at 0x', r) - # Don't care about ancestry: just leaf value of MyNode - r = re.sub(r'<.*?\.MyNode', '"]*3) - assert r == '[%s]' % l, r - - - -if __name__ == "__main__": - unittest.main() - - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Node/PythonTests.py b/SCSCons/Node/PythonTests.py deleted file mode 100644 index b6a3f7930..000000000 --- a/SCSCons/Node/PythonTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/PathListTests.py b/SCSCons/PathListTests.py deleted file mode 100644 index e62baad0d..000000000 --- a/SCSCons/PathListTests.py +++ /dev/null @@ -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 '' - - a = A() - - pl = SCons.PathList.PathList((a,)) - - result = pl.subst_path(self.env, 'y', 'z') - - assert result == ('',), 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: diff --git a/SCSCons/Platform/PlatformTests.py b/SCSCons/Platform/PlatformTests.py deleted file mode 100644 index bdb899638..000000000 --- a/SCSCons/Platform/PlatformTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Platform/virtualenvTests.py b/SCSCons/Platform/virtualenvTests.py deleted file mode 100644 index c840749df..000000000 --- a/SCSCons/Platform/virtualenvTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/SConfTests.py b/SCSCons/SConfTests.py deleted file mode 100644 index 1badad87f..000000000 --- a/SCSCons/SConfTests.py +++ /dev/null @@ -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 -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 ") - 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 \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 - -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: diff --git a/SCSCons/SConsignTests.py b/SCSCons/SConsignTests.py deleted file mode 100644 index e9f20718d..000000000 --- a/SCSCons/SConsignTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/CTests.py b/SCSCons/Scanner/CTests.py deleted file mode 100644 index 14e156e71..000000000 --- a/SCSCons/Scanner/CTests.py +++ /dev/null @@ -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 -#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 - #endif -#else -#include \"f1.h\" -#endif - -#import - -int main(void) -{ - return 0; -} -""") - -test.write('f3.cpp',""" -#include \t "f1.h" - \t #include "f2.h" -# \t include "f3-test.h" - -#include \t - \t #include -# \t include - -// #include "never.h" - -const char* x = "#include " - -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 -""") - - -test.subdir('include', 'subdir', ['subdir', 'include']) - -test.write('fa.cpp',""" -#include \"fa.h\" -#include - -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 -#include - -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 -""") - -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: diff --git a/SCSCons/Scanner/DTests.py b/SCSCons/Scanner/DTests.py deleted file mode 100644 index 25ccca330..000000000 --- a/SCSCons/Scanner/DTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/DirTests.py b/SCSCons/Scanner/DirTests.py deleted file mode 100644 index 1c46c6c3f..000000000 --- a/SCSCons/Scanner/DirTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/FortranTests.py b/SCSCons/Scanner/FortranTests.py deleted file mode 100644 index 729e91a18..000000000 --- a/SCSCons/Scanner/FortranTests.py +++ /dev/null @@ -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 ! 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 ; 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: diff --git a/SCSCons/Scanner/IDLTests.py b/SCSCons/Scanner/IDLTests.py deleted file mode 100644 index 28433d1c8..000000000 --- a/SCSCons/Scanner/IDLTests.py +++ /dev/null @@ -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 -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 -#include \"f1.idl\" -import ; - -[ - 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 - \t #include -# \t include - -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 \" - -[ - 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 -""") - - -test.subdir('include', 'subdir', ['subdir', 'include']) - -test.write('t4.idl',""" -#include \"fa.idl\" -#include - -[ - 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 -#include - -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: diff --git a/SCSCons/Scanner/LaTeXTests.py b/SCSCons/Scanner/LaTeXTests.py deleted file mode 100644 index 252d8d451..000000000 --- a/SCSCons/Scanner/LaTeXTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/ProgTests.py b/SCSCons/Scanner/ProgTests.py deleted file mode 100644 index 5aa057128..000000000 --- a/SCSCons/Scanner/ProgTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/PythonTests.py b/SCSCons/Scanner/PythonTests.py deleted file mode 100644 index 1a4f5b430..000000000 --- a/SCSCons/Scanner/PythonTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/RCTests.py b/SCSCons/Scanner/RCTests.py deleted file mode 100644 index 3655269e9..000000000 --- a/SCSCons/Scanner/RCTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Scanner/ScannerTests.py b/SCSCons/Scanner/ScannerTests.py deleted file mode 100644 index 68332a04e..000000000 --- a/SCSCons/Scanner/ScannerTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Script/Main.py b/SCSCons/Script/Main.py index a340f5b60..ce42d8b4f 100644 --- a/SCSCons/Script/Main.py +++ b/SCSCons/Script/Main.py @@ -97,7 +97,6 @@ class SConsPrintHelpException(Exception): display = SCons.Util.display progress_display = SCons.Util.DisplayEngine() - class Progressor: prev = '' count = 0 diff --git a/SCSCons/SubstTests.py b/SCSCons/SubstTests.py deleted file mode 100644 index b956a258c..000000000 --- a/SCSCons/SubstTests.py +++ /dev/null @@ -1,1298 +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 SCons.compat - -import os -import unittest -from functools import partial - - -import SCons.Errors - -from SCons.Subst import (Literal, SUBST_CMD, SUBST_RAW, SUBST_SIG, SpecialAttrWrapper, collections, - escape_list, quote_spaces, scons_subst, scons_subst_list, scons_subst_once, - subst_dict) - -class DummyNode: - """Simple node work-alike.""" - def __init__(self, name): - self.name = os.path.normpath(name) - def __str__(self): - return self.name - def is_literal(self): - return 1 - def rfile(self): - return self - def get_subst_proxy(self): - return self - -class DummyEnv: - def __init__(self, dict={}): - self.dict = dict - - def Dictionary(self, key = None): - if not key: - return self.dict - return self.dict[key] - - def __getitem__(self, key): - return self.dict[key] - - def get(self, key, default): - return self.dict.get(key, default) - - def sig_dict(self): - dict = self.dict.copy() - dict["TARGETS"] = 'tsig' - dict["SOURCES"] = 'ssig' - return dict - -def cs(target=None, source=None, env=None, for_signature=None): - return 'cs' - -def cl(target=None, source=None, env=None, for_signature=None): - return ['cl'] - -def CmdGen1(target, source, env, for_signature): - # Nifty trick...since Environment references are interpolated, - # instantiate an instance of a callable class with this one, - # which will then get evaluated. - assert str(target) == 't', target - assert str(source) == 's', source - return "${CMDGEN2('foo', %d)}" % for_signature - -class CmdGen2: - def __init__(self, mystr, forsig): - self.mystr = mystr - self.expect_for_signature = forsig - - def __call__(self, target, source, env, for_signature): - assert str(target) == 't', target - assert str(source) == 's', source - assert for_signature == self.expect_for_signature, for_signature - return [ self.mystr, env.Dictionary('BAR') ] - - -def CallableWithDefault(target, source, env, for_signature, other_value="default"): - assert str(target) == 't', target - assert str(source) == 's', source - return "CallableWithDefault: %s"%other_value - -PartialCallable = partial(CallableWithDefault, other_value="partial") - -def CallableWithNoDefault(target, source, env, for_signature, other_value): - assert str(target) == 't', target - assert str(source) == 's', source - return "CallableWithNoDefault: %s"%other_value - -PartialCallableNoDefault = partial(CallableWithNoDefault, other_value="partialNoDefault") - - - -if os.sep == '/': - def cvt(str): - return str -else: - def cvt(str): - return str.replace('/', os.sep) - -class SubstTestCase(unittest.TestCase): - class MyNode(DummyNode): - """Simple node work-alike with some extra stuff for testing.""" - def __init__(self, name): - DummyNode.__init__(self, name) - class Attribute: - pass - self.attribute = Attribute() - self.attribute.attr1 = 'attr$1-' + os.path.basename(name) - self.attribute.attr2 = 'attr$2-' + os.path.basename(name) - def get_stuff(self, extra): - return self.name + extra - foo = 1 - - class TestLiteral: - def __init__(self, literal): - self.literal = literal - def __str__(self): - return self.literal - def is_literal(self): - return 1 - - class TestCallable: - def __init__(self, value): - self.value = value - def __call__(self): - pass - def __str__(self): - return self.value - - # only use of this is currently commented out below - #def function_foo(arg): - # pass - - target = [ MyNode("./foo/bar.exe"), - MyNode("/bar/baz with spaces.obj"), - MyNode("../foo/baz.obj") ] - source = [ MyNode("./foo/blah with spaces.cpp"), - MyNode("/bar/ack.cpp"), - MyNode("../foo/ack.c") ] - - callable_object_1 = TestCallable('callable-1') - callable_object_2 = TestCallable('callable-2') - - def _defines(defs): - l = [] - for d in defs: - if SCons.Util.is_List(d) or isinstance(d, tuple): - l.append(str(d[0]) + '=' + str(d[1])) - else: - l.append(str(d)) - return l - - loc = { - 'xxx' : None, - 'NEWLINE' : 'before\nafter', - - 'null' : '', - 'zero' : 0, - 'one' : 1, - 'BAZ' : 'baz', - 'ONE' : '$TWO', - 'TWO' : '$THREE', - 'THREE' : 'four', - - 'AAA' : 'a', - 'BBB' : 'b', - 'CCC' : 'c', - - 'DO' : DummyNode('do something'), - 'FOO' : DummyNode('foo.in'), - 'BAR' : DummyNode('bar with spaces.out'), - 'CRAZY' : DummyNode('crazy\nfile.in'), - - # $XXX$HHH should expand to GGGIII, not BADNEWS. - 'XXX' : '$FFF', - 'FFF' : 'GGG', - 'HHH' : 'III', - 'FFFIII' : 'BADNEWS', - - 'THING1' : "$(STUFF$)", - 'THING2' : "$THING1", - - 'LITERAL' : TestLiteral("$XXX"), - - # Test that we can expand to and return a function. - #'FUNCTION' : function_foo, - - 'CMDGEN1' : CmdGen1, - 'CMDGEN2' : CmdGen2, - - 'CallableWithDefault': CallableWithDefault, - 'PartialCallable' : PartialCallable, - 'PartialCallableNoDefault' : PartialCallableNoDefault, - - 'LITERALS' : [ Literal('foo\nwith\nnewlines'), - Literal('bar\nwith\nnewlines') ], - - 'NOTHING' : "", - 'NONE' : None, - - # Test various combinations of strings, lists and functions. - 'N' : None, - 'X' : 'x', - 'Y' : '$X', - 'R' : '$R', - 'S' : 'x y', - 'LS' : ['x y'], - 'L' : ['x', 'y'], - 'TS' : ('x y',), - 'T' : ('x', 'y'), - 'CS' : cs, - 'CL' : cl, - 'US' : collections.UserString('us'), - - # Test function calls within ${}. - 'FUNCCALL' : '${FUNC1("$AAA $FUNC2 $BBB")}', - 'FUNC1' : lambda x: x, - 'FUNC2' : lambda target, source, env, for_signature: ['x$CCC'], - - # Various tests refactored from ActionTests.py. - 'LIST' : [["This", "is", "$(", "$a", "$)", "test"]], - - # Test recursion. - 'RECURSE' : 'foo $RECURSE bar', - 'RRR' : 'foo $SSS bar', - 'SSS' : '$RRR', - - # Test callables that don't match the calling arguments. - 'CALLABLE1' : callable_object_1, - 'CALLABLE2' : callable_object_2, - - '_defines' : _defines, - 'DEFS' : [ ('Q1', '"q1"'), ('Q2', '"$AAA"') ], - } - - def basic_comparisons(self, function, convert): - env = DummyEnv(self.loc) - cases = self.basic_cases[:] - kwargs = {'target' : self.target, 'source' : self.source, - 'gvars' : env.Dictionary()} - - failed = 0 - case_count = 0 - while cases: - input, expect = cases[:2] - expect = convert(expect) - try: - result = function(input, env, **kwargs) - except Exception as e: - fmt = " input %s generated %s (%s)" - print(fmt % (repr(input), e.__class__.__name__, repr(e))) - failed = failed + 1 - else: - if result != expect: - if failed == 0: print() - print("[%4d] input %s => \n%s did not match \n%s" % (case_count, repr(input), repr(result), repr(expect))) - failed = failed + 1 - del cases[:2] - case_count += 1 - fmt = "%d %s() cases failed" - assert failed == 0, fmt % (failed, function.__name__) - - -class scons_subst_TestCase(SubstTestCase): - - # Basic tests of substitution functionality. - basic_cases = [ - # Basics: strings without expansions are left alone, and - # the simplest possible expansion to a null-string value. - "test", "test", - "$null", "", - - # Test expansion of integer values. - "test $zero", "test 0", - "test $one", "test 1", - - # Test multiple re-expansion of values. - "test $ONE", "test four", - - # Test a whole bunch of $TARGET[S] and $SOURCE[S] expansions. - "test $TARGETS $SOURCES", - "test foo/bar.exe /bar/baz with spaces.obj ../foo/baz.obj foo/blah with spaces.cpp /bar/ack.cpp ../foo/ack.c", - - "test ${TARGETS[:]} ${SOURCES[0]}", - "test foo/bar.exe /bar/baz with spaces.obj ../foo/baz.obj foo/blah with spaces.cpp", - - "test ${TARGETS[1:]}v", - "test /bar/baz with spaces.obj ../foo/baz.objv", - - "test $TARGET", - "test foo/bar.exe", - - "test $TARGET$NO_SUCH_VAR[0]", - "test foo/bar.exe[0]", - - "test $TARGETS.foo", - "test 1 1 1", - - "test ${SOURCES[0:2].foo}", - "test 1 1", - - "test $SOURCE.foo", - "test 1", - - "test ${TARGET.get_stuff('blah')}", - "test foo/bar.exeblah", - - "test ${SOURCES.get_stuff('blah')}", - "test foo/blah with spaces.cppblah /bar/ack.cppblah ../foo/ack.cblah", - - "test ${SOURCES[0:2].get_stuff('blah')}", - "test foo/blah with spaces.cppblah /bar/ack.cppblah", - - "test ${SOURCES[0:2].get_stuff('blah')}", - "test foo/blah with spaces.cppblah /bar/ack.cppblah", - - "test ${SOURCES.attribute.attr1}", - "test attr$1-blah with spaces.cpp attr$1-ack.cpp attr$1-ack.c", - - "test ${SOURCES.attribute.attr2}", - "test attr$2-blah with spaces.cpp attr$2-ack.cpp attr$2-ack.c", - - # Test adjacent expansions. - "foo$BAZ", - "foobaz", - - "foo${BAZ}", - "foobaz", - - # Test that adjacent expansions don't get re-interpreted - # together. The correct disambiguated expansion should be: - # $XXX$HHH => ${FFF}III => GGGIII - # not: - # $XXX$HHH => ${FFFIII} => BADNEWS - "$XXX$HHH", "GGGIII", - - # Test double-dollar-sign behavior. - "$$FFF$HHH", "$FFFIII", - - # Test double-dollar-sign before open paren. It's not meant - # to be signature escaping - 'echo $$(pwd) > XYZ', 'echo $(pwd) > XYZ', - - # Test that a Literal will stop dollar-sign substitution. - "$XXX $LITERAL $FFF", "GGG $XXX GGG", - - # Test that we don't blow up even if they subscript - # something in ways they "can't." - "${FFF[0]}", "G", - "${FFF[7]}", "", - "${NOTHING[1]}", "", - - # Test various combinations of strings and lists. - #None, '', - '', '', - 'x', 'x', - 'x y', 'x y', - '$N', '', - '$X', 'x', - '$Y', 'x', - '$R', '', - '$S', 'x y', - '$LS', 'x y', - '$L', 'x y', - '$TS', 'x y', - '$T', 'x y', - '$S z', 'x y z', - '$LS z', 'x y z', - '$L z', 'x y z', - '$TS z', 'x y z', - '$T z', 'x y z', - #cs, 'cs', - #cl, 'cl', - '$CS', 'cs', - '$CL', 'cl', - - # Various uses of UserString. - collections.UserString('x'), 'x', - collections.UserString('$X'), 'x', - collections.UserString('$US'), 'us', - '$US', 'us', - - # Test function calls within ${}. - '$FUNCCALL', 'a xc b', - - # Bug reported by Christoph Wiedemann. - cvt('$xxx/bin'), '/bin', - - # Tests callables that don't match our calling arguments. - '$CALLABLE1', 'callable-1', - - # Test handling of quotes. - 'aaa "bbb ccc" ddd', 'aaa "bbb ccc" ddd', - ] - - def test_scons_subst(self): - """Test scons_subst(): basic substitution""" - return self.basic_comparisons(scons_subst, cvt) - - subst_cases = [ - "test $xxx", - "test ", - "test", - "test", - - "test $($xxx$)", - "test $($)", - "test", - "test", - - "test $( $xxx $)", - "test $( $)", - "test", - "test", - - "test $( $THING2 $)", - "test $( $(STUFF$) $)", - "test STUFF", - "test", - - "$AAA ${AAA}A $BBBB $BBB", - "a aA b", - "a aA b", - "a aA b", - - "$RECURSE", - "foo bar", - "foo bar", - "foo bar", - - "$RRR", - "foo bar", - "foo bar", - "foo bar", - - # Verify what happens with no target or source nodes. - "$TARGET $SOURCES", - " ", - "", - "", - - "$TARGETS $SOURCE", - " ", - "", - "", - - # Various tests refactored from ActionTests.py. - "${LIST}", - "This is $( $) test", - "This is test", - "This is test", - - ["|", "$(", "$AAA", "|", "$BBB", "$)", "|", "$CCC", 1], - ["|", "$(", "a", "|", "b", "$)", "|", "c", "1"], - ["|", "a", "|", "b", "|", "c", "1"], - ["|", "|", "c", "1"], - ] - - def test_subst_env(self): - """Test scons_subst(): expansion dictionary""" - # The expansion dictionary no longer comes from the construction - # environment automatically. - env = DummyEnv(self.loc) - s = scons_subst('$AAA', env) - assert s == '', s - - def test_subst_SUBST_modes(self): - """Test scons_subst(): SUBST_* modes""" - env = DummyEnv(self.loc) - subst_cases = self.subst_cases[:] - - gvars = env.Dictionary() - - failed = 0 - while subst_cases: - input, eraw, ecmd, esig = subst_cases[:4] - result = scons_subst(input, env, mode=SUBST_RAW, gvars=gvars) - if result != eraw: - if failed == 0: print() - print(" input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw))) - failed = failed + 1 - result = scons_subst(input, env, mode=SUBST_CMD, gvars=gvars) - if result != ecmd: - if failed == 0: print() - print(" input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd))) - failed = failed + 1 - result = scons_subst(input, env, mode=SUBST_SIG, gvars=gvars) - if result != esig: - if failed == 0: print() - print(" input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig))) - failed = failed + 1 - del subst_cases[:4] - assert failed == 0, "%d subst() mode cases failed" % failed - - def test_subst_target_source(self): - """Test scons_subst(): target= and source= arguments""" - env = DummyEnv(self.loc) - t1 = self.MyNode('t1') - t2 = self.MyNode('t2') - s1 = self.MyNode('s1') - s2 = self.MyNode('s2') - result = scons_subst("$TARGET $SOURCES", env, - target=[t1, t2], - source=[s1, s2]) - assert result == "t1 s1 s2", result - result = scons_subst("$TARGET $SOURCES", env, - target=[t1, t2], - source=[s1, s2], - gvars={}) - assert result == "t1 s1 s2", result - - result = scons_subst("$TARGET $SOURCES", env, target=[], source=[]) - assert result == " ", result - result = scons_subst("$TARGETS $SOURCE", env, target=[], source=[]) - assert result == " ", result - - def test_subst_callable_expansion(self): - """Test scons_subst(): expanding a callable""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - newcom = scons_subst("test $CMDGEN1 $SOURCES $TARGETS", env, - target=self.MyNode('t'), source=self.MyNode('s'), - gvars=gvars) - assert newcom == "test foo bar with spaces.out s t", newcom - - def test_subst_callable_with_default_expansion(self): - """Test scons_subst(): expanding a callable with a default value arg""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - newcom = scons_subst("test $CallableWithDefault $SOURCES $TARGETS", env, - target=self.MyNode('t'), source=self.MyNode('s'), - gvars=gvars) - assert newcom == "test CallableWithDefault: default s t", newcom - - def test_subst_partial_callable_with_default_expansion(self): - """Test scons_subst(): expanding a functools.partial callable which sets - the default value in the callable""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - newcom = scons_subst("test $PartialCallable $SOURCES $TARGETS", env, - target=self.MyNode('t'), source=self.MyNode('s'), - gvars=gvars) - assert newcom == "test CallableWithDefault: partial s t", newcom - - def test_subst_partial_callable_with_no_default_expansion(self): - """Test scons_subst(): expanding a functools.partial callable which sets - the value for extraneous function argument""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - newcom = scons_subst("test $PartialCallableNoDefault $SOURCES $TARGETS", env, - target=self.MyNode('t'), source=self.MyNode('s'), - gvars=gvars) - assert newcom == "test CallableWithNoDefault: partialNoDefault s t", newcom - - def test_subst_attribute_errors(self): - """Test scons_subst(): handling attribute errors""" - env = DummyEnv(self.loc) - try: - class Foo: - pass - scons_subst('${foo.bar}', env, gvars={'foo':Foo()}) - except SCons.Errors.UserError as e: - expect = [ - "AttributeError `bar' trying to evaluate `${foo.bar}'", - "AttributeError `Foo instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", - "AttributeError `'Foo' instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", - "AttributeError `'Foo' object has no attribute 'bar'' trying to evaluate `${foo.bar}'", - ] - assert str(e) in expect, e - else: - raise AssertionError("did not catch expected UserError") - - def test_subst_syntax_errors(self): - """Test scons_subst(): handling syntax errors""" - env = DummyEnv(self.loc) - try: - scons_subst('$foo.bar.3.0', env) - except SCons.Errors.UserError as e: - expect = [ - # Python 2.5 to 3.9 - "SyntaxError `invalid syntax (, line 1)' trying to evaluate `$foo.bar.3.0'", - # Python 3.10 and later - "SyntaxError `invalid syntax. Perhaps you forgot a comma? (, line 1)' trying to evaluate `$foo.bar.3.0'", - ] - assert str(e) in expect, e - else: - raise AssertionError("did not catch expected UserError") - - def test_subst_balance_errors(self): - """Test scons_subst(): handling syntax errors""" - env = DummyEnv(self.loc) - try: - scons_subst('$(', env, mode=SUBST_SIG) - except SCons.Errors.UserError as e: - assert str(e) == "Unbalanced $(/$) in: $(", str(e) - else: - raise AssertionError("did not catch expected UserError") - - try: - scons_subst('$)', env, mode=SUBST_SIG) - except SCons.Errors.UserError as e: - assert str(e) == "Unbalanced $(/$) in: $)", str(e) - else: - raise AssertionError("did not catch expected UserError") - - def test_subst_type_errors(self): - """Test scons_subst(): handling type errors""" - env = DummyEnv(self.loc) - try: - scons_subst("${NONE[2]}", env, gvars={'NONE':None}) - except SCons.Errors.UserError as e: - expect = [ - # Python 2.7 and later - "TypeError `'NoneType' object is not subscriptable' trying to evaluate `${NONE[2]}'", - # Python 2.7 and later under Fedora - "TypeError `'NoneType' object has no attribute '__getitem__'' trying to evaluate `${NONE[2]}'", - ] - assert str(e) in expect, e - else: - raise AssertionError("did not catch expected UserError") - - try: - def func(a, b, c): - pass - scons_subst("${func(1)}", env, gvars={'func':func}) - except SCons.Errors.UserError as e: - expect = [ - # Python 3.5 (and 3.x?) - "TypeError `func() missing 2 required positional arguments: 'b' and 'c'' trying to evaluate `${func(1)}'", - # Python 3.10 - "TypeError `scons_subst_TestCase.test_subst_type_errors..func() missing 2 required positional arguments: 'b' and 'c'' trying to evaluate `${func(1)}'", - ] - assert str(e) in expect, repr(str(e)) - else: - raise AssertionError("did not catch expected UserError") - - def test_subst_raw_function(self): - """Test scons_subst(): fetch function with SUBST_RAW plus conv""" - # Test that the combination of SUBST_RAW plus a pass-through - # conversion routine allows us to fetch a function through the - # dictionary. CommandAction uses this to allow delayed evaluation - # of $SPAWN variables. - env = DummyEnv(self.loc) - gvars = env.Dictionary() - x = lambda x: x - r = scons_subst("$CALLABLE1", env, mode=SUBST_RAW, conv=x, gvars=gvars) - assert r is self.callable_object_1, repr(r) - r = scons_subst("$CALLABLE1", env, mode=SUBST_RAW, gvars=gvars) - assert r == 'callable-1', repr(r) - - # Test how we handle overriding the internal conversion routines. - def s(obj): - return obj - - n1 = self.MyNode('n1') - env = DummyEnv({'NODE' : n1}) - gvars = env.Dictionary() - node = scons_subst("$NODE", env, mode=SUBST_RAW, conv=s, gvars=gvars) - assert node is n1, node - node = scons_subst("$NODE", env, mode=SUBST_CMD, conv=s, gvars=gvars) - assert node is n1, node - node = scons_subst("$NODE", env, mode=SUBST_SIG, conv=s, gvars=gvars) - assert node is n1, node - - def test_subst_overriding_gvars(self): - """Test scons_subst(): supplying an overriding gvars dictionary""" - env = DummyEnv({'XXX' : 'xxx'}) - result = scons_subst('$XXX', env, gvars=env.Dictionary()) - assert result == 'xxx', result - result = scons_subst('$XXX', env, gvars={'XXX' : 'yyy'}) - assert result == 'yyy', result - -class CLVar_TestCase(unittest.TestCase): - def test_CLVar(self): - """Test scons_subst() and scons_subst_list() with CLVar objects""" - - loc = {} - loc['FOO'] = 'foo' - loc['BAR'] = SCons.Util.CLVar('bar') - loc['CALL'] = lambda target, source, env, for_signature: 'call' - env = DummyEnv(loc) - - cmd = SCons.Util.CLVar("test $FOO $BAR $CALL test") - - newcmd = scons_subst(cmd, env, gvars=env.Dictionary()) - assert newcmd == ['test', 'foo', 'bar', 'call', 'test'], newcmd - - cmd_list = scons_subst_list(cmd, env, gvars=env.Dictionary()) - assert len(cmd_list) == 1, cmd_list - assert cmd_list[0][0] == "test", cmd_list[0][0] - assert cmd_list[0][1] == "foo", cmd_list[0][1] - assert cmd_list[0][2] == "bar", cmd_list[0][2] - assert cmd_list[0][3] == "call", cmd_list[0][3] - assert cmd_list[0][4] == "test", cmd_list[0][4] - -class scons_subst_list_TestCase(SubstTestCase): - - basic_cases = [ - "$TARGETS", - [ - ["foo/bar.exe", "/bar/baz with spaces.obj", "../foo/baz.obj"], - ], - - "$SOURCES $NEWLINE $TARGETS", - [ - ["foo/blah with spaces.cpp", "/bar/ack.cpp", "../foo/ack.c", "before"], - ["after", "foo/bar.exe", "/bar/baz with spaces.obj", "../foo/baz.obj"], - ], - - "$SOURCES$NEWLINE", - [ - ["foo/blah with spaces.cpp", "/bar/ack.cpp", "../foo/ack.cbefore"], - ["after"], - ], - - "foo$FFF", - [ - ["fooGGG"], - ], - - "foo${FFF}", - [ - ["fooGGG"], - ], - - "test ${SOURCES.attribute.attr1}", - [ - ["test", "attr$1-blah with spaces.cpp", "attr$1-ack.cpp", "attr$1-ack.c"], - ], - - "test ${SOURCES.attribute.attr2}", - [ - ["test", "attr$2-blah with spaces.cpp", "attr$2-ack.cpp", "attr$2-ack.c"], - ], - - "$DO --in=$FOO --out=$BAR", - [ - ["do something", "--in=foo.in", "--out=bar with spaces.out"], - ], - - # This test is now fixed, and works like it should. - "$DO --in=$CRAZY --out=$BAR", - [ - ["do something", "--in=crazy\nfile.in", "--out=bar with spaces.out"], - ], - - # Try passing a list to scons_subst_list(). - [ "$SOURCES$NEWLINE", "$TARGETS", "This is a test"], - [ - ["foo/blah with spaces.cpp", "/bar/ack.cpp", "../foo/ack.cbefore"], - ["after", "foo/bar.exe", "/bar/baz with spaces.obj", "../foo/baz.obj", "This is a test"], - ], - - # Test against a former bug in scons_subst_list(). - "$XXX$HHH", - [ - ["GGGIII"], - ], - - # Test double-dollar-sign behavior. - "$$FFF$HHH", - [ - ["$FFFIII"], - ], - - # Test various combinations of strings, lists and functions. - None, [[]], - [None], [[]], - '', [[]], - [''], [[]], - 'x', [['x']], - ['x'], [['x']], - 'x y', [['x', 'y']], - ['x y'], [['x y']], - ['x', 'y'], [['x', 'y']], - '$N', [[]], - ['$N'], [[]], - '$X', [['x']], - ['$X'], [['x']], - '$Y', [['x']], - ['$Y'], [['x']], - #'$R', [[]], - #['$R'], [[]], - '$S', [['x', 'y']], - '$S z', [['x', 'y', 'z']], - ['$S'], [['x', 'y']], - ['$S z'], [['x', 'y z']], # XXX - IS THIS BEST? - ['$S', 'z'], [['x', 'y', 'z']], - '$LS', [['x y']], - '$LS z', [['x y', 'z']], - ['$LS'], [['x y']], - ['$LS z'], [['x y z']], - ['$LS', 'z'], [['x y', 'z']], - '$L', [['x', 'y']], - '$L z', [['x', 'y', 'z']], - ['$L'], [['x', 'y']], - ['$L z'], [['x', 'y z']], # XXX - IS THIS BEST? - ['$L', 'z'], [['x', 'y', 'z']], - cs, [['cs']], - [cs], [['cs']], - cl, [['cl']], - [cl], [['cl']], - '$CS', [['cs']], - ['$CS'], [['cs']], - '$CL', [['cl']], - ['$CL'], [['cl']], - - # Various uses of UserString. - collections.UserString('x'), [['x']], - [collections.UserString('x')], [['x']], - collections.UserString('$X'), [['x']], - [collections.UserString('$X')], [['x']], - collections.UserString('$US'), [['us']], - [collections.UserString('$US')], [['us']], - '$US', [['us']], - ['$US'], [['us']], - - # Test function calls within ${}. - '$FUNCCALL', [['a', 'xc', 'b']], - - # Test handling of newlines in white space. - 'foo\nbar', [['foo'], ['bar']], - 'foo\n\nbar', [['foo'], ['bar']], - 'foo \n \n bar', [['foo'], ['bar']], - 'foo \nmiddle\n bar', [['foo'], ['middle'], ['bar']], - - # Bug reported by Christoph Wiedemann. - cvt('$xxx/bin'), [['/bin']], - - # Test variables smooshed together with different prefixes. - 'foo$AAA', [['fooa']], - '<$AAA', [['<', 'a']], - '>$AAA', [['>', 'a']], - '|$AAA', [['|', 'a']], - - # Test callables that don't match our calling arguments. - '$CALLABLE2', [['callable-2']], - - # Test handling of quotes. - # XXX Find a way to handle this in the future. - #'aaa "bbb ccc" ddd', [['aaa', 'bbb ccc', 'ddd']], - - '${_defines(DEFS)}', [['Q1="q1"', 'Q2="a"']], - ] - - def test_scons_subst_list(self): - """Test scons_subst_list(): basic substitution""" - def convert_lists(expect): - return [list(map(cvt, l)) for l in expect] - return self.basic_comparisons(scons_subst_list, convert_lists) - - subst_list_cases = [ - "test $xxx", - [["test"]], - [["test"]], - [["test"]], - - "test $($xxx$)", - [["test", "$($)"]], - [["test"]], - [["test"]], - - "test $( $xxx $)", - [["test", "$(", "$)"]], - [["test"]], - [["test"]], - - "$AAA ${AAA}A $BBBB $BBB", - [["a", "aA", "b"]], - [["a", "aA", "b"]], - [["a", "aA", "b"]], - - "$RECURSE", - [["foo", "bar"]], - [["foo", "bar"]], - [["foo", "bar"]], - - "$RRR", - [["foo", "bar"]], - [["foo", "bar"]], - [["foo", "bar"]], - - # Verify what happens with no target or source nodes. - "$TARGET $SOURCES", - [[]], - [[]], - [[]], - - "$TARGETS $SOURCE", - [[]], - [[]], - [[]], - - # Various test refactored from ActionTests.py - "${LIST}", - [['This', 'is', '$(', '$)', 'test']], - [['This', 'is', 'test']], - [['This', 'is', 'test']], - - ["|", "$(", "$AAA", "|", "$BBB", "$)", "|", "$CCC", 1], - [["|", "$(", "a", "|", "b", "$)", "|", "c", "1"]], - [["|", "a", "|", "b", "|", "c", "1"]], - [["|", "|", "c", "1"]], - ] - - def test_subst_env(self): - """Test scons_subst_list(): expansion dictionary""" - # The expansion dictionary no longer comes from the construction - # environment automatically. - env = DummyEnv() - s = scons_subst_list('$AAA', env) - assert s == [[]], s - - def test_subst_target_source(self): - """Test scons_subst_list(): target= and source= arguments""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - t1 = self.MyNode('t1') - t2 = self.MyNode('t2') - s1 = self.MyNode('s1') - s2 = self.MyNode('s2') - result = scons_subst_list("$TARGET $SOURCES", env, - target=[t1, t2], - source=[s1, s2], - gvars=gvars) - assert result == [['t1', 's1', 's2']], result - result = scons_subst_list("$TARGET $SOURCES", env, - target=[t1, t2], - source=[s1, s2], - gvars={}) - assert result == [['t1', 's1', 's2']], result - - # Test interpolating a callable. - _t = DummyNode('t') - _s = DummyNode('s') - cmd_list = scons_subst_list("testing $CMDGEN1 $TARGETS $SOURCES", - env, target=_t, source=_s, - gvars=gvars) - assert cmd_list == [['testing', 'foo', 'bar with spaces.out', 't', 's']], cmd_list - - def test_subst_escape(self): - """Test scons_subst_list(): escape functionality""" - env = DummyEnv(self.loc) - gvars = env.Dictionary() - def escape_func(foo): - return '**' + foo + '**' - cmd_list = scons_subst_list("abc $LITERALS xyz", env, gvars=gvars) - assert cmd_list == [['abc', - 'foo\nwith\nnewlines', - 'bar\nwith\nnewlines', - 'xyz']], cmd_list - c = cmd_list[0][0].escape(escape_func) - assert c == 'abc', c - c = cmd_list[0][1].escape(escape_func) - assert c == '**foo\nwith\nnewlines**', c - c = cmd_list[0][2].escape(escape_func) - assert c == '**bar\nwith\nnewlines**', c - c = cmd_list[0][3].escape(escape_func) - assert c == 'xyz', c - - # We used to treat literals smooshed together like the whole - # thing was literal and escape it as a unit. The commented-out - # asserts below are in case we ever have to find a way to - # resurrect that functionality in some way. - cmd_list = scons_subst_list("abc${LITERALS}xyz", env, gvars=gvars) - c = cmd_list[0][0].escape(escape_func) - #assert c == '**abcfoo\nwith\nnewlines**', c - assert c == 'abcfoo\nwith\nnewlines', c - c = cmd_list[0][1].escape(escape_func) - #assert c == '**bar\nwith\nnewlinesxyz**', c - assert c == 'bar\nwith\nnewlinesxyz', c - - _t = DummyNode('t') - - cmd_list = scons_subst_list('echo "target: $TARGET"', env, - target=_t, gvars=gvars) - c = cmd_list[0][0].escape(escape_func) - assert c == 'echo', c - c = cmd_list[0][1].escape(escape_func) - assert c == '"target:', c - c = cmd_list[0][2].escape(escape_func) - assert c == 't"', c - - def test_subst_SUBST_modes(self): - """Test scons_subst_list(): SUBST_* modes""" - env = DummyEnv(self.loc) - subst_list_cases = self.subst_list_cases[:] - gvars = env.Dictionary() - - r = scons_subst_list("$TARGET $SOURCES", env, mode=SUBST_RAW, gvars=gvars) - assert r == [[]], r - - failed = 0 - while subst_list_cases: - input, eraw, ecmd, esig = subst_list_cases[:4] - result = scons_subst_list(input, env, mode=SUBST_RAW, gvars=gvars) - if result != eraw: - if failed == 0: print() - print(" input %s => RAW %s did not match %s" % (repr(input), repr(result), repr(eraw))) - failed = failed + 1 - result = scons_subst_list(input, env, mode=SUBST_CMD, gvars=gvars) - if result != ecmd: - if failed == 0: print() - print(" input %s => CMD %s did not match %s" % (repr(input), repr(result), repr(ecmd))) - failed = failed + 1 - result = scons_subst_list(input, env, mode=SUBST_SIG, gvars=gvars) - if result != esig: - if failed == 0: print() - print(" input %s => SIG %s did not match %s" % (repr(input), repr(result), repr(esig))) - failed = failed + 1 - del subst_list_cases[:4] - assert failed == 0, "%d subst() mode cases failed" % failed - - def test_subst_attribute_errors(self): - """Test scons_subst_list(): handling attribute errors""" - env = DummyEnv() - try: - class Foo: - pass - scons_subst_list('${foo.bar}', env, gvars={'foo':Foo()}) - except SCons.Errors.UserError as e: - expect = [ - "AttributeError `bar' trying to evaluate `${foo.bar}'", - "AttributeError `Foo instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", - "AttributeError `'Foo' instance has no attribute 'bar'' trying to evaluate `${foo.bar}'", - "AttributeError `'Foo' object has no attribute 'bar'' trying to evaluate `${foo.bar}'", - ] - assert str(e) in expect, e - else: - raise AssertionError("did not catch expected UserError") - - def test_subst_syntax_errors(self): - """Test scons_subst_list(): handling syntax errors""" - env = DummyEnv() - try: - scons_subst_list('$foo.bar.3.0', env) - except SCons.Errors.UserError as e: - expect = [ - # Python 2.5 to 3.9 - "SyntaxError `invalid syntax (, line 1)' trying to evaluate `$foo.bar.3.0'", - # Python 3.10 and later - "SyntaxError `invalid syntax. Perhaps you forgot a comma? (, line 1)' trying to evaluate `$foo.bar.3.0'", - ] - assert str(e) in expect, e - else: - raise AssertionError("did not catch expected SyntaxError") - - def test_subst_raw_function(self): - """Test scons_subst_list(): fetch function with SUBST_RAW plus conv""" - # Test that the combination of SUBST_RAW plus a pass-through - # conversion routine allows us to fetch a function through the - # dictionary. - env = DummyEnv(self.loc) - gvars = env.Dictionary() - x = lambda x: x - r = scons_subst_list("$CALLABLE2", env, mode=SUBST_RAW, conv=x, gvars=gvars) - assert r == [[self.callable_object_2]], repr(r) - r = scons_subst_list("$CALLABLE2", env, mode=SUBST_RAW, gvars=gvars) - assert r == [['callable-2']], repr(r) - - def test_subst_list_overriding_gvars(self): - """Test scons_subst_list(): overriding conv()""" - env = DummyEnv() - def s(obj): - return obj - - n1 = self.MyNode('n1') - env = DummyEnv({'NODE' : n1}) - gvars=env.Dictionary() - node = scons_subst_list("$NODE", env, mode=SUBST_RAW, conv=s, gvars=gvars) - assert node == [[n1]], node - node = scons_subst_list("$NODE", env, mode=SUBST_CMD, conv=s, gvars=gvars) - assert node == [[n1]], node - node = scons_subst_list("$NODE", env, mode=SUBST_SIG, conv=s, gvars=gvars) - assert node == [[n1]], node - - def test_subst_list_overriding_gvars2(self): - """Test scons_subst_list(): supplying an overriding gvars dictionary""" - env = DummyEnv({'XXX' : 'xxx'}) - result = scons_subst_list('$XXX', env, gvars=env.Dictionary()) - assert result == [['xxx']], result - result = scons_subst_list('$XXX', env, gvars={'XXX' : 'yyy'}) - assert result == [['yyy']], result - -class scons_subst_once_TestCase(unittest.TestCase): - - loc = { - 'CCFLAGS' : '-DFOO', - 'ONE' : 1, - 'RECURSE' : 'r $RECURSE r', - 'LIST' : ['a', 'b', 'c'], - } - - basic_cases = [ - '$CCFLAGS -DBAR', - 'OTHER_KEY', - '$CCFLAGS -DBAR', - - '$CCFLAGS -DBAR', - 'CCFLAGS', - '-DFOO -DBAR', - - 'x $ONE y', - 'ONE', - 'x 1 y', - - 'x $RECURSE y', - 'RECURSE', - 'x r $RECURSE r y', - - '$LIST', - 'LIST', - 'a b c', - - ['$LIST'], - 'LIST', - ['a', 'b', 'c'], - - ['x', '$LIST', 'y'], - 'LIST', - ['x', 'a', 'b', 'c', 'y'], - - ['x', 'x $LIST y', 'y'], - 'LIST', - ['x', 'x a b c y', 'y'], - - ['x', 'x $CCFLAGS y', 'y'], - 'LIST', - ['x', 'x $CCFLAGS y', 'y'], - - ['x', 'x $RECURSE y', 'y'], - 'LIST', - ['x', 'x $RECURSE y', 'y'], - ] - - def test_subst_once(self): - """Test the scons_subst_once() function""" - env = DummyEnv(self.loc) - cases = self.basic_cases[:] - - failed = 0 - while cases: - input, key, expect = cases[:3] - result = scons_subst_once(input, env, key) - if result != expect: - if failed == 0: print() - print(" input %s (%s) => %s did not match %s" % (repr(input), repr(key), repr(result), repr(expect))) - failed = failed + 1 - del cases[:3] - assert failed == 0, "%d subst() cases failed" % failed - -class quote_spaces_TestCase(unittest.TestCase): - def test_quote_spaces(self): - """Test the quote_spaces() method...""" - q = quote_spaces('x') - assert q == 'x', q - - q = quote_spaces('x x') - assert q == '"x x"', q - - q = quote_spaces('x\tx') - assert q == '"x\tx"', q - - class Node: - def __init__(self, name, children=[]): - self.children = children - self.name = name - def __str__(self): - return self.name - def exists(self): - return 1 - def rexists(self): - return 1 - def has_builder(self): - return 1 - def has_explicit_builder(self): - return 1 - def side_effect(self): - return 1 - def precious(self): - return 1 - def always_build(self): - return 1 - def current(self): - return 1 - -class LiteralTestCase(unittest.TestCase): - def test_Literal(self): - """Test the Literal() function.""" - input_list = [ '$FOO', Literal('$BAR') ] - gvars = { 'FOO' : 'BAZ', 'BAR' : 'BLAT' } - - def escape_func(cmd): - return '**' + cmd + '**' - - cmd_list = scons_subst_list(input_list, None, gvars=gvars) - cmd_list = escape_list(cmd_list[0], escape_func) - assert cmd_list == ['BAZ', '**$BAR**'], cmd_list - - def test_LiteralEqualsTest(self): - """Test that Literals compare for equality properly""" - assert Literal('a literal') == Literal('a literal') - assert Literal('a literal') != Literal('b literal') - -class SpecialAttrWrapperTestCase(unittest.TestCase): - def test_SpecialAttrWrapper(self): - """Test the SpecialAttrWrapper() function.""" - input_list = [ '$FOO', SpecialAttrWrapper('$BAR', 'BLEH') ] - gvars = { 'FOO' : 'BAZ', 'BAR' : 'BLAT' } - - def escape_func(cmd): - return '**' + cmd + '**' - - cmd_list = scons_subst_list(input_list, None, gvars=gvars) - cmd_list = escape_list(cmd_list[0], escape_func) - assert cmd_list == ['BAZ', '**$BAR**'], cmd_list - - cmd_list = scons_subst_list(input_list, None, mode=SUBST_SIG, gvars=gvars) - cmd_list = escape_list(cmd_list[0], escape_func) - assert cmd_list == ['BAZ', '**BLEH**'], cmd_list - -class subst_dict_TestCase(unittest.TestCase): - def test_subst_dict(self): - """Test substituting dictionary values in an Action - """ - t = DummyNode('t') - s = DummyNode('s') - d = subst_dict(target=t, source=s) - assert str(d['TARGETS'][0]) == 't', d['TARGETS'] - assert str(d['TARGET']) == 't', d['TARGET'] - assert str(d['SOURCES'][0]) == 's', d['SOURCES'] - assert str(d['SOURCE']) == 's', d['SOURCE'] - - t1 = DummyNode('t1') - t2 = DummyNode('t2') - s1 = DummyNode('s1') - s2 = DummyNode('s2') - d = subst_dict(target=[t1, t2], source=[s1, s2]) - TARGETS = sorted([str(x) for x in d['TARGETS']]) - assert TARGETS == ['t1', 't2'], d['TARGETS'] - assert str(d['TARGET']) == 't1', d['TARGET'] - SOURCES = sorted([str(x) for x in d['SOURCES']]) - assert SOURCES == ['s1', 's2'], d['SOURCES'] - assert str(d['SOURCE']) == 's1', d['SOURCE'] - - class V: - # Fake Value node with no rfile() method. - def __init__(self, name): - self.name = name - def __str__(self): - return 'v-'+self.name - def get_subst_proxy(self): - return self - - class N(V): - def rfile(self): - return self.__class__('rstr-' + self.name) - - t3 = N('t3') - t4 = DummyNode('t4') - t5 = V('t5') - s3 = DummyNode('s3') - s4 = N('s4') - s5 = V('s5') - d = subst_dict(target=[t3, t4, t5], source=[s3, s4, s5]) - TARGETS = sorted([str(x) for x in d['TARGETS']]) - assert TARGETS == ['t4', 'v-t3', 'v-t5'], TARGETS - SOURCES = sorted([str(x) for x in d['SOURCES']]) - assert SOURCES == ['s3', 'v-rstr-s4', 'v-s5'], SOURCES - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/TaskmasterTests.py b/SCSCons/TaskmasterTests.py deleted file mode 100644 index f20fd716f..000000000 --- a/SCSCons/TaskmasterTests.py +++ /dev/null @@ -1,1257 +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 SCons.compat - -import sys -import unittest - - -import SCons.Taskmaster -import SCons.Errors - - -built_text = None -cache_text = [] -visited_nodes = [] -executed = None -scan_called = 0 - -class Node: - def __init__(self, name, kids = [], scans = []): - self.name = name - self.kids = kids - self.scans = scans - self.cached = 0 - self.scanned = 0 - self.scanner = None - self.targets = [self] - self.prerequisites = None - class Builder: - def targets(self, node): - return node.targets - self.builder = Builder() - self.bsig = None - self.csig = None - self.state = SCons.Node.no_state - self.prepared = None - self.ref_count = 0 - self.waiting_parents = set() - self.waiting_s_e = set() - self.side_effect = 0 - self.side_effects = [] - self.alttargets = [] - self.postprocessed = None - self._bsig_val = None - self._current_val = 0 - self.always_build = None - - def disambiguate(self): - return self - - def push_to_cache(self): - pass - - def retrieve_from_cache(self): - global cache_text - if self.cached: - cache_text.append(self.name + " retrieved") - return self.cached - - def make_ready(self): - pass - - def prepare(self): - self.prepared = 1 - self.get_binfo() - - def build(self): - global built_text - built_text = self.name + " built" - - def remove(self): - pass - - # The following four methods new_binfo(), del_binfo(), - # get_binfo(), clear() as well as its calls have been added - # to support the cached_execute() test (issue #2720). - # They are full copies (or snippets) of their actual - # counterparts in the Node class... - def new_binfo(self): - binfo = "binfo" - return binfo - - def del_binfo(self): - """Delete the build info from this node.""" - try: - delattr(self, 'binfo') - except AttributeError: - pass - - def get_binfo(self): - """Fetch a node's build information.""" - try: - return self.binfo - except AttributeError: - pass - - binfo = self.new_binfo() - self.binfo = binfo - - return binfo - - def clear(self): - # The del_binfo() call here isn't necessary for normal execution, - # but is for interactive mode, where we might rebuild the same - # target and need to start from scratch. - self.del_binfo() - - def built(self): - global built_text - if not self.cached: - built_text = built_text + " really" - - # Clear the implicit dependency caches of any Nodes - # waiting for this Node to be built. - for parent in self.waiting_parents: - parent.implicit = None - - self.clear() - - def release_target_info(self): - pass - - def has_builder(self): - return self.builder is not None - - def is_derived(self): - return self.has_builder or self.side_effect - - def alter_targets(self): - return self.alttargets, None - - def visited(self): - global visited_nodes - visited_nodes.append(self.name) - - def children(self): - if not self.scanned: - self.scan() - self.scanned = 1 - return self.kids - - def scan(self): - global scan_called - scan_called = scan_called + 1 - self.kids = self.kids + self.scans - self.scans = [] - - def scanner_key(self): - return self.name - - def add_to_waiting_parents(self, node): - wp = self.waiting_parents - if node in wp: - return 0 - wp.add(node) - return 1 - - def get_state(self): - return self.state - - def set_state(self, state): - self.state = state - - def set_bsig(self, bsig): - self.bsig = bsig - - def set_csig(self, csig): - self.csig = csig - - def store_csig(self): - pass - - def store_bsig(self): - pass - - def is_pseudo_derived(self): - pass - - def is_up_to_date(self): - return self._current_val - - def depends_on(self, nodes): - for node in nodes: - if node in self.kids: - return 1 - return 0 - - def __str__(self): - return self.name - - def postprocess(self): - self.postprocessed = 1 - self.waiting_parents = set() - - def get_executor(self): - if not hasattr(self, 'executor'): - class Executor: - def prepare(self): - pass - def get_action_targets(self): - return self.targets - def get_all_targets(self): - return self.targets - def get_all_children(self): - result = [] - for node in self.targets: - result.extend(node.children()) - return result - def get_all_prerequisites(self): - return [] - def get_action_side_effects(self): - return [] - self.executor = Executor() - self.executor.targets = self.targets - return self.executor - -class OtherError(Exception): - pass - -class MyException(Exception): - pass - - -class TaskmasterTestCase(unittest.TestCase): - - def test_next_task(self): - """Test fetching the next task - """ - global built_text - - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster([n1, n1]) - t = tm.next_task() - t.prepare() - t.execute() - t = tm.next_task() - assert t is None - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - - tm = SCons.Taskmaster.Taskmaster([n3]) - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n1 built", built_text - t.executed() - t.postprocess() - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n2 built", built_text - t.executed() - t.postprocess() - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n3 built", built_text - t.executed() - t.postprocess() - - assert tm.next_task() is None - - built_text = "up to date: " - top_node = n3 - - class MyTask(SCons.Taskmaster.AlwaysTask): - def execute(self): - global built_text - if self.targets[0].get_state() == SCons.Node.up_to_date: - if self.top: - built_text = self.targets[0].name + " up-to-date top" - else: - built_text = self.targets[0].name + " up-to-date" - else: - self.targets[0].build() - - n1.set_state(SCons.Node.no_state) - n1._current_val = 1 - n2.set_state(SCons.Node.no_state) - n2._current_val = 1 - n3.set_state(SCons.Node.no_state) - n3._current_val = 1 - tm = SCons.Taskmaster.Taskmaster(targets = [n3], tasker = MyTask) - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n1 up-to-date", built_text - t.executed() - t.postprocess() - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n2 up-to-date", built_text - t.executed() - t.postprocess() - - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n3 up-to-date top", built_text - t.executed() - t.postprocess() - - assert tm.next_task() is None - - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - n4 = Node("n4") - n5 = Node("n5", [n3, n4]) - tm = SCons.Taskmaster.Taskmaster([n5]) - - t1 = tm.next_task() - assert t1.get_target() == n1 - - t2 = tm.next_task() - assert t2.get_target() == n2 - - t4 = tm.next_task() - assert t4.get_target() == n4 - t4.executed() - t4.postprocess() - - t1.executed() - t1.postprocess() - t2.executed() - t2.postprocess() - t3 = tm.next_task() - assert t3.get_target() == n3 - - t3.executed() - t3.postprocess() - t5 = tm.next_task() - assert t5.get_target() == n5, t5.get_target() - t5.executed() - t5.postprocess() - - assert tm.next_task() is None - - - n4 = Node("n4") - n4.set_state(SCons.Node.executed) - tm = SCons.Taskmaster.Taskmaster([n4]) - assert tm.next_task() is None - - n1 = Node("n1") - n2 = Node("n2", [n1]) - tm = SCons.Taskmaster.Taskmaster([n2,n2]) - t = tm.next_task() - t.executed() - t.postprocess() - t = tm.next_task() - assert tm.next_task() is None - - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1], [n2]) - tm = SCons.Taskmaster.Taskmaster([n3]) - t = tm.next_task() - target = t.get_target() - assert target == n1, target - t.executed() - t.postprocess() - t = tm.next_task() - target = t.get_target() - assert target == n2, target - t.executed() - t.postprocess() - t = tm.next_task() - target = t.get_target() - assert target == n3, target - t.executed() - t.postprocess() - assert tm.next_task() is None - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - n4 = Node("n4", [n3]) - n5 = Node("n5", [n3]) - global scan_called - scan_called = 0 - tm = SCons.Taskmaster.Taskmaster([n4]) - t = tm.next_task() - assert t.get_target() == n1 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n2 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n3 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n4 - t.executed() - t.postprocess() - assert tm.next_task() is None - assert scan_called == 4, scan_called - - tm = SCons.Taskmaster.Taskmaster([n5]) - t = tm.next_task() - assert t.get_target() == n5, t.get_target() - t.executed() - assert tm.next_task() is None - assert scan_called == 5, scan_called - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3") - n4 = Node("n4", [n1,n2,n3]) - n5 = Node("n5", [n4]) - n3.side_effect = 1 - n1.side_effects = n2.side_effects = n3.side_effects = [n4] - tm = SCons.Taskmaster.Taskmaster([n1,n2,n3,n4,n5]) - t = tm.next_task() - assert t.get_target() == n1 - assert n4.state == SCons.Node.executing, n4.state - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n2 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n3 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n4 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n5 - assert not tm.next_task() - t.executed() - t.postprocess() - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3") - n4 = Node("n4", [n1,n2,n3]) - def reverse(dependencies): - dependencies.reverse() - return dependencies - tm = SCons.Taskmaster.Taskmaster([n4], order=reverse) - t = tm.next_task() - assert t.get_target() == n3, t.get_target() - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n2, t.get_target() - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n1, t.get_target() - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n4, t.get_target() - t.executed() - t.postprocess() - - n5 = Node("n5") - n6 = Node("n6") - n7 = Node("n7") - n6.alttargets = [n7] - - tm = SCons.Taskmaster.Taskmaster([n5]) - t = tm.next_task() - assert t.get_target() == n5 - t.executed() - t.postprocess() - - tm = SCons.Taskmaster.Taskmaster([n6]) - t = tm.next_task() - assert t.get_target() == n7 - t.executed() - t.postprocess() - t = tm.next_task() - assert t.get_target() == n6 - t.executed() - t.postprocess() - - n1 = Node("n1") - n2 = Node("n2", [n1]) - n1.set_state(SCons.Node.failed) - tm = SCons.Taskmaster.Taskmaster([n2]) - assert tm.next_task() is None - - n1 = Node("n1") - n2 = Node("n2") - n1.targets = [n1, n2] - n1._current_val = 1 - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - t.executed() - t.postprocess() - - s = n1.get_state() - assert s == SCons.Node.executed, s - s = n2.get_state() - assert s == SCons.Node.executed, s - - - def test_make_ready_out_of_date(self): - """Test the Task.make_ready() method's list of out-of-date Nodes - """ - ood = [] - def TaskGen(tm, targets, top, node, ood=ood): - class MyTask(SCons.Taskmaster.AlwaysTask): - def make_ready(self): - SCons.Taskmaster.Task.make_ready(self) - self.ood.extend(self.out_of_date) - - t = MyTask(tm, targets, top, node) - t.ood = ood - return t - - n1 = Node("n1") - c2 = Node("c2") - c2._current_val = 1 - n3 = Node("n3") - c4 = Node("c4") - c4._current_val = 1 - a5 = Node("a5") - a5._current_val = 1 - a5.always_build = 1 - tm = SCons.Taskmaster.Taskmaster(targets = [n1, c2, n3, c4, a5], - tasker = TaskGen) - - del ood[:] - t = tm.next_task() - assert ood == [n1], ood - - del ood[:] - t = tm.next_task() - assert ood == [], ood - - del ood[:] - t = tm.next_task() - assert ood == [n3], ood - - del ood[:] - t = tm.next_task() - assert ood == [], ood - - del ood[:] - t = tm.next_task() - assert ood == [a5], ood - - def test_make_ready_exception(self): - """Test handling exceptions from Task.make_ready() - """ - class MyTask(SCons.Taskmaster.AlwaysTask): - def make_ready(self): - raise MyException("from make_ready()") - - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster(targets = [n1], tasker = MyTask) - t = tm.next_task() - exc_type, exc_value, exc_tb = t.exception - assert exc_type == MyException, repr(exc_type) - assert str(exc_value) == "from make_ready()", exc_value - - def test_needs_execute(self): - """Test that we can't instantiate a Task subclass without needs_execute - - We should be getting: - TypeError: Can't instantiate abstract class MyTask with abstract methods needs_execute - """ - class MyTask(SCons.Taskmaster.Task): - pass - - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster(targets=[n1], tasker=MyTask) - with self.assertRaises(TypeError): - _ = tm.next_task() - - def test_make_ready_all(self): - """Test the make_ready_all() method""" - class MyTask(SCons.Taskmaster.AlwaysTask): - make_ready = SCons.Taskmaster.Task.make_ready_all - - n1 = Node("n1") - c2 = Node("c2") - c2._current_val = 1 - n3 = Node("n3") - c4 = Node("c4") - c4._current_val = 1 - - tm = SCons.Taskmaster.Taskmaster(targets = [n1, c2, n3, c4]) - - t = tm.next_task() - target = t.get_target() - assert target is n1, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - target = t.get_target() - assert target is c2, target - assert target.state == SCons.Node.up_to_date, target.state - t = tm.next_task() - target = t.get_target() - assert target is n3, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - target = t.get_target() - assert target is c4, target - assert target.state == SCons.Node.up_to_date, target.state - t = tm.next_task() - assert t is None - - n1 = Node("n1") - c2 = Node("c2") - n3 = Node("n3") - c4 = Node("c4") - - tm = SCons.Taskmaster.Taskmaster(targets = [n1, c2, n3, c4], - tasker = MyTask) - - t = tm.next_task() - target = t.get_target() - assert target is n1, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - target = t.get_target() - assert target is c2, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - target = t.get_target() - assert target is n3, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - target = t.get_target() - assert target is c4, target - assert target.state == SCons.Node.executing, target.state - t = tm.next_task() - assert t is None - - - def test_children_errors(self): - """Test errors when fetching the children of a node. - """ - class StopNode(Node): - def children(self): - raise SCons.Errors.StopError("stop!") - class ExitNode(Node): - def children(self): - sys.exit(77) - - n1 = StopNode("n1") - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - exc_type, exc_value, exc_tb = t.exception - assert exc_type == SCons.Errors.StopError, repr(exc_type) - assert str(exc_value) == "stop!", exc_value - - n2 = ExitNode("n2") - tm = SCons.Taskmaster.Taskmaster([n2]) - t = tm.next_task() - exc_type, exc_value = t.exception - assert exc_type == SCons.Errors.ExplicitExit, repr(exc_type) - assert exc_value.node == n2, exc_value.node - assert exc_value.status == 77, exc_value.status - - def test_cycle_detection(self): - """Test detecting dependency cycles - """ - n1 = Node("n1") - n2 = Node("n2", [n1]) - n3 = Node("n3", [n2]) - n1.kids = [n3] - - tm = SCons.Taskmaster.Taskmaster([n3]) - try: - t = tm.next_task() - except SCons.Errors.UserError as e: - assert str(e) == "Dependency cycle: n3 -> n1 -> n2 -> n3", str(e) - else: - assert 'Did not catch expected UserError' - - def test_next_top_level_candidate(self): - """Test the next_top_level_candidate() method - """ - n1 = Node("n1") - n2 = Node("n2", [n1]) - n3 = Node("n3", [n2]) - - tm = SCons.Taskmaster.Taskmaster([n3]) - t = tm.next_task() - assert t.targets == [n1], t.targets - t.fail_stop() - assert t.targets == [n3], list(map(str, t.targets)) - assert t.top == 1, t.top - - def test_stop(self): - """Test the stop() method - - Both default and overridden in a subclass. - """ - global built_text - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - - tm = SCons.Taskmaster.Taskmaster([n3]) - t = tm.next_task() - t.prepare() - t.execute() - assert built_text == "n1 built", built_text - t.executed() - t.postprocess() - assert built_text == "n1 built really", built_text - - tm.stop() - assert tm.next_task() is None - - class MyTM(SCons.Taskmaster.Taskmaster): - def stop(self): - global built_text - built_text = "MyTM.stop()" - SCons.Taskmaster.Taskmaster.stop(self) - - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - - built_text = None - tm = MyTM([n3]) - tm.next_task().execute() - assert built_text == "n1 built" - - tm.stop() - assert built_text == "MyTM.stop()" - assert tm.next_task() is None - - def test_executed(self): - """Test when a task has been executed - """ - global built_text - global visited_nodes - - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - built_text = "xxx" - visited_nodes = [] - n1.set_state(SCons.Node.executing) - - t.executed() - - s = n1.get_state() - assert s == SCons.Node.executed, s - assert built_text == "xxx really", built_text - assert visited_nodes == ['n1'], visited_nodes - - n2 = Node("n2") - tm = SCons.Taskmaster.Taskmaster([n2]) - t = tm.next_task() - built_text = "should_not_change" - visited_nodes = [] - n2.set_state(None) - - t.executed() - - s = n2.get_state() - assert s is None, s - assert built_text == "should_not_change", built_text - assert visited_nodes == ['n2'], visited_nodes - - n3 = Node("n3") - n4 = Node("n4") - n3.targets = [n3, n4] - tm = SCons.Taskmaster.Taskmaster([n3]) - t = tm.next_task() - visited_nodes = [] - n3.set_state(SCons.Node.up_to_date) - n4.set_state(SCons.Node.executing) - - t.executed() - - s = n3.get_state() - assert s == SCons.Node.up_to_date, s - s = n4.get_state() - assert s == SCons.Node.executed, s - assert visited_nodes == ['n3', 'n4'], visited_nodes - - def test_prepare(self): - """Test preparation of multiple Nodes for a task - """ - n1 = Node("n1") - n2 = Node("n2") - tm = SCons.Taskmaster.Taskmaster([n1, n2]) - t = tm.next_task() - # This next line is moderately bogus. We're just reaching - # in and setting the targets for this task to an array. The - # "right" way to do this would be to have the next_task() call - # set it up by having something that approximates a real Builder - # return this list--but that's more work than is probably - # warranted right now. - n1.get_executor().targets = [n1, n2] - t.prepare() - assert n1.prepared - assert n2.prepared - - n3 = Node("n3") - n4 = Node("n4") - tm = SCons.Taskmaster.Taskmaster([n3, n4]) - t = tm.next_task() - # More bogus reaching in and setting the targets. - n3.set_state(SCons.Node.up_to_date) - n3.get_executor().targets = [n3, n4] - t.prepare() - assert n3.prepared - assert n4.prepared - - # If the Node has had an exception recorded while it was getting - # prepared, then prepare() should raise that exception. - class MyException(Exception): - pass - - built_text = None - n5 = Node("n5") - tm = SCons.Taskmaster.Taskmaster([n5]) - t = tm.next_task() - t.exception_set((MyException, "exception value")) - exc_caught = None - exc_actually_caught = None - exc_value = None - try: - t.prepare() - except MyException as e: - exc_caught = 1 - exc_value = e - except Exception as exc_actually_caught: - pass - assert exc_caught, "did not catch expected MyException: %s" % exc_actually_caught - assert str(exc_value) == "exception value", exc_value - assert built_text is None, built_text - - # Regression test, make sure we prepare not only - # all targets, but their side effects as well. - n6 = Node("n6") - n7 = Node("n7") - n8 = Node("n8") - n9 = Node("n9") - n10 = Node("n10") - - n6.side_effects = [ n8 ] - n7.side_effects = [ n9, n10 ] - - tm = SCons.Taskmaster.Taskmaster([n6, n7]) - t = tm.next_task() - # More bogus reaching in and setting the targets. - n6.get_executor().targets = [n6, n7] - t.prepare() - assert n6.prepared - assert n7.prepared - assert n8.prepared - assert n9.prepared - assert n10.prepared - - # Make sure we call an Executor's prepare() method. - class ExceptionExecutor: - def prepare(self): - raise Exception("Executor.prepare() exception") - def get_all_targets(self): - return self.nodes - def get_all_children(self): - result = [] - for node in self.nodes: - result.extend(node.children()) - return result - def get_all_prerequisites(self): - return [] - def get_action_side_effects(self): - return [] - - n11 = Node("n11") - n11.executor = ExceptionExecutor() - n11.executor.nodes = [n11] - tm = SCons.Taskmaster.Taskmaster([n11]) - t = tm.next_task() - try: - t.prepare() - except Exception as e: - assert str(e) == "Executor.prepare() exception", e - else: - raise AssertionError("did not catch expected exception") - - def test_execute(self): - """Test executing a task - """ - global built_text - global cache_text - - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - t.execute() - assert built_text == "n1 built", built_text - - def raise_UserError(): - raise SCons.Errors.UserError - n2 = Node("n2") - n2.build = raise_UserError - tm = SCons.Taskmaster.Taskmaster([n2]) - t = tm.next_task() - try: - t.execute() - except SCons.Errors.UserError: - pass - else: - self.fail("did not catch expected UserError") - - def raise_BuildError(): - raise SCons.Errors.BuildError - n3 = Node("n3") - n3.build = raise_BuildError - tm = SCons.Taskmaster.Taskmaster([n3]) - t = tm.next_task() - try: - t.execute() - except SCons.Errors.BuildError: - pass - else: - self.fail("did not catch expected BuildError") - - # On a generic (non-BuildError) exception from a Builder, - # the target should throw a BuildError exception with the - # args set to the exception value, instance, and traceback. - def raise_OtherError(): - raise OtherError - n4 = Node("n4") - n4.build = raise_OtherError - tm = SCons.Taskmaster.Taskmaster([n4]) - t = tm.next_task() - try: - t.execute() - except SCons.Errors.BuildError as e: - assert e.node == n4, e.node - assert e.errstr == "OtherError : ", e.errstr - assert len(e.exc_info) == 3, e.exc_info - exc_traceback = sys.exc_info()[2] - assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2] - else: - self.fail("did not catch expected BuildError") - - built_text = None - cache_text = [] - n5 = Node("n5") - n6 = Node("n6") - n6.cached = 1 - tm = SCons.Taskmaster.Taskmaster([n5]) - t = tm.next_task() - # This next line is moderately bogus. We're just reaching - # in and setting the targets for this task to an array. The - # "right" way to do this would be to have the next_task() call - # set it up by having something that approximates a real Builder - # return this list--but that's more work than is probably - # warranted right now. - t.targets = [n5, n6] - t.execute() - assert built_text == "n5 built", built_text - assert cache_text == [], cache_text - - built_text = None - cache_text = [] - n7 = Node("n7") - n8 = Node("n8") - n7.cached = 1 - n8.cached = 1 - tm = SCons.Taskmaster.Taskmaster([n7]) - t = tm.next_task() - # This next line is moderately bogus. We're just reaching - # in and setting the targets for this task to an array. The - # "right" way to do this would be to have the next_task() call - # set it up by having something that approximates a real Builder - # return this list--but that's more work than is probably - # warranted right now. - t.targets = [n7, n8] - t.execute() - assert built_text is None, built_text - assert cache_text == ["n7 retrieved", "n8 retrieved"], cache_text - - def test_cached_execute(self): - """Test executing a task with cached targets - """ - # In issue #2720 Alexei Klimkin detected that the previous - # workflow for execute() led to problems in a multithreaded build. - # We have: - # task.prepare() - # task.execute() - # task.executed() - # -> node.visited() - # for the Serial flow, but - # - Parallel - - Worker - - # task.prepare() - # requestQueue.put(task) - # task = requestQueue.get() - # task.execute() - # resultQueue.put(task) - # task = resultQueue.get() - # task.executed() - # ->node.visited() - # in parallel. Since execute() used to call built() when a target - # was cached, it could unblock dependent nodes before the binfo got - # restored again in visited(). This resulted in spurious - # "file not found" build errors, because files fetched from cache would - # be seen as not up to date and wouldn't be scanned for implicit - # dependencies. - # - # The following test ensures that execute() only marks targets as cached, - # but the actual call to built() happens in executed() only. - # Like this, the binfo should still be intact after calling execute()... - global cache_text - - n1 = Node("n1") - # Mark the node as being cached - n1.cached = 1 - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - t.prepare() - t.execute() - assert cache_text == ["n1 retrieved"], cache_text - # If no binfo exists anymore, something has gone wrong... - has_binfo = hasattr(n1, 'binfo') - assert has_binfo, has_binfo - - def test_exception(self): - """Test generic Taskmaster exception handling - - """ - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster([n1]) - t = tm.next_task() - - t.exception_set((1, 2)) - exc_type, exc_value = t.exception - assert exc_type == 1, exc_type - assert exc_value == 2, exc_value - - t.exception_set(3) - assert t.exception == 3 - - try: 1//0 - except: - # Moved from below - t.exception_set(None) - #pass - -# import pdb; pdb.set_trace() - - # Having this here works for python 2.x, - # but it is a tuple (None, None, None) when called outside - # an except statement - # t.exception_set(None) - - exc_type, exc_value, exc_tb = t.exception - assert exc_type is ZeroDivisionError, "Expecting ZeroDevisionError got:%s"%exc_type - exception_values = [ - "integer division or modulo", - "integer division or modulo by zero", - "integer division by zero", # PyPy2 - ] - assert str(exc_value) in exception_values, exc_value - - class Exception1(Exception): - pass - - # Previously value was None, but while PY2 None = "", in Py3 None != "", so set to "" - t.exception_set((Exception1, "")) - try: - t.exception_raise() - except: - exc_type, exc_value = sys.exc_info()[:2] - assert exc_type == Exception1, exc_type - assert str(exc_value) == '', "Expecting empty string got:%s (type %s)"%(exc_value,type(exc_value)) - else: - assert 0, "did not catch expected exception" - - class Exception2(Exception): - pass - - t.exception_set((Exception2, "xyzzy")) - try: - t.exception_raise() - except: - exc_type, exc_value = sys.exc_info()[:2] - assert exc_type == Exception2, exc_type - assert str(exc_value) == "xyzzy", exc_value - else: - assert 0, "did not catch expected exception" - - class Exception3(Exception): - pass - - try: - 1//0 - except: - tb = sys.exc_info()[2] - t.exception_set((Exception3, "arg", tb)) - try: - t.exception_raise() - except: - exc_type, exc_value, exc_tb = sys.exc_info() - assert exc_type == Exception3, exc_type - assert str(exc_value) == "arg", exc_value - import traceback - x = traceback.extract_tb(tb)[-1] - y = traceback.extract_tb(exc_tb)[-1] - assert x == y, "x = %s, y = %s" % (x, y) - else: - assert 0, "did not catch expected exception" - - def test_postprocess(self): - """Test postprocessing targets to give them a chance to clean up - """ - n1 = Node("n1") - tm = SCons.Taskmaster.Taskmaster([n1]) - - t = tm.next_task() - assert not n1.postprocessed - t.postprocess() - assert n1.postprocessed - - n2 = Node("n2") - n3 = Node("n3") - tm = SCons.Taskmaster.Taskmaster([n2, n3]) - - assert not n2.postprocessed - assert not n3.postprocessed - t = tm.next_task() - t.postprocess() - assert n2.postprocessed - assert not n3.postprocessed - t = tm.next_task() - t.postprocess() - assert n2.postprocessed - assert n3.postprocessed - - def test_trace(self): - """Test Taskmaster tracing - """ - import io - - trace = io.StringIO() - n1 = Node("n1") - n2 = Node("n2") - n3 = Node("n3", [n1, n2]) - tm = SCons.Taskmaster.Taskmaster([n1, n1, n3], trace=trace) - t = tm.next_task() - t.prepare() - t.execute() - t.postprocess() - n1.set_state(SCons.Node.executed) - t = tm.next_task() - t.prepare() - t.execute() - t.postprocess() - n2.set_state(SCons.Node.executed) - t = tm.next_task() - t.prepare() - t.execute() - t.postprocess() - t = tm.next_task() - assert t is None - - value = trace.getvalue() - expect = """\ - -Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node and its children: -Taskmaster: Evaluating - -Task.make_ready_current(): node -Task.prepare(): node -Task.execute(): node -Task.postprocess(): node - -Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node and its children: -Taskmaster: already handled (executed) -Taskmaster: Considering node and its children: -Taskmaster: -Taskmaster: -Taskmaster: adjusted ref count: , child 'n2' -Taskmaster: Considering node and its children: -Taskmaster: Evaluating - -Task.make_ready_current(): node -Task.prepare(): node -Task.execute(): node -Task.postprocess(): node -Task.postprocess(): removing -Task.postprocess(): adjusted parent ref count - -Taskmaster: Looking for a node to evaluate -Taskmaster: Considering node and its children: -Taskmaster: -Taskmaster: -Taskmaster: Evaluating - -Task.make_ready_current(): node -Task.prepare(): node -Task.execute(): node -Task.postprocess(): node - -Taskmaster: Looking for a node to evaluate -Taskmaster: No candidate anymore. - -""" - assert value == expect, value - - - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Tool/linkCommon/linkCommmonTests.py b/SCSCons/Tool/linkCommon/linkCommmonTests.py deleted file mode 100644 index e55660d77..000000000 --- a/SCSCons/Tool/linkCommon/linkCommmonTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/UtilTests.py b/SCSCons/UtilTests.py deleted file mode 100644 index 5ed31cb78..000000000 --- a/SCSCons/UtilTests.py +++ /dev/null @@ -1,1213 +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 functools -import io -import os -import sys -import unittest -import unittest.mock -import hashlib -import warnings -from collections import UserDict, UserList, UserString, namedtuple - -import TestCmd - -import SCons.Errors -import SCons.compat -from SCons.Util import ( - ALLOWED_HASH_FORMATS, - AddPathIfNotExists, - AppendPath, - CLVar, - LogicalLines, - NodeList, - PrependPath, - Proxy, - Selector, - WhereIs, - _attempt_init_of_python_3_9_hash_object, - _attempt_get_hash_function, - _get_hash_object, - _set_allowed_viable_default_hashes, - adjustixes, - containsAll, - containsAny, - containsOnly, - dictify, - display, - flatten, - get_env_bool, - get_environment_var, - get_native_path, - get_os_env_bool, - hash_collect, - hash_signature, - is_Dict, - is_List, - is_String, - is_Tuple, - print_tree, - render_tree, - set_hash_format, - silent_intern, - splitext, - to_String, - to_bytes, - to_str, -) - -# These Util classes have no unit tests. Some don't make sense to test? -# DisplayEngine, Delegate, MethodWrapper, UniqueList, Unbuffered, Null, NullSeq - - -class OutBuffer: - def __init__(self): - self.buffer = "" - - def write(self, str): - self.buffer = self.buffer + str - - -class dictifyTestCase(unittest.TestCase): - def test_dictify(self): - """Test the dictify() function""" - r = dictify(['a', 'b', 'c'], [1, 2, 3]) - assert r == {'a': 1, 'b': 2, 'c': 3}, r - - r = {} - dictify(['a'], [1], r) - dictify(['b'], [2], r) - dictify(['c'], [3], r) - assert r == {'a': 1, 'b': 2, 'c': 3}, r - - -class UtilTestCase(unittest.TestCase): - def test_splitext(self): - assert splitext('foo') == ('foo', '') - assert splitext('foo.bar') == ('foo', '.bar') - assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'), '') - - class Node: - def __init__(self, name, children=[]): - self.children = children - self.name = name - self.nocache = None - - def __str__(self): - return self.name - - def exists(self): - return 1 - - def rexists(self): - return 1 - - def has_builder(self): - return 1 - - def has_explicit_builder(self): - return 1 - - def side_effect(self): - return 1 - - def precious(self): - return 1 - - def always_build(self): - return 1 - - def is_up_to_date(self): - return 1 - - def noclean(self): - return 1 - - def tree_case_1(self): - """Fixture for the render_tree() and print_tree() tests.""" - windows_h = self.Node("windows.h") - stdlib_h = self.Node("stdlib.h") - stdio_h = self.Node("stdio.h") - bar_c = self.Node("bar.c", [stdlib_h, windows_h]) - bar_o = self.Node("bar.o", [bar_c]) - foo_c = self.Node("foo.c", [stdio_h]) - foo_o = self.Node("foo.o", [foo_c]) - foo = self.Node("foo", [foo_o, bar_o]) - - expect = """\ -+-foo - +-foo.o - | +-foo.c - | +-stdio.h - +-bar.o - +-bar.c - +-stdlib.h - +-windows.h -""" - - lines = expect.split('\n')[:-1] - lines = ['[E BSPACN ]' + l for l in lines] - withtags = '\n'.join(lines) + '\n' - - return foo, expect, withtags - - def tree_case_2(self, prune=1): - """Fixture for the render_tree() and print_tree() tests.""" - - types_h = self.Node('types.h') - malloc_h = self.Node('malloc.h') - stdlib_h = self.Node('stdlib.h', [types_h, malloc_h]) - bar_h = self.Node('bar.h', [stdlib_h]) - blat_h = self.Node('blat.h', [stdlib_h]) - blat_c = self.Node('blat.c', [blat_h, bar_h]) - blat_o = self.Node('blat.o', [blat_c]) - - expect = """\ -+-blat.o - +-blat.c - +-blat.h - | +-stdlib.h - | +-types.h - | +-malloc.h - +-bar.h -""" - if prune: - expect += """ +-[stdlib.h] -""" - else: - expect += """ +-stdlib.h - +-types.h - +-malloc.h -""" - - lines = expect.split('\n')[:-1] - lines = ['[E BSPACN ]' + l for l in lines] - withtags = '\n'.join(lines) + '\n' - - return blat_o, expect, withtags - - def test_render_tree(self): - """Test the render_tree() function""" - - def get_children(node): - return node.children - - node, expect, withtags = self.tree_case_1() - actual = render_tree(node, get_children) - assert expect == actual, (expect, actual) - - node, expect, withtags = self.tree_case_2() - actual = render_tree(node, get_children, 1) - assert expect == actual, (expect, actual) - - # Ensure that we can call render_tree on the same Node - # again. This wasn't possible in version 2.4.1 and earlier - # due to a bug in render_tree (visited was set to {} as default - # parameter) - actual = render_tree(node, get_children, 1) - assert expect == actual, (expect, actual) - - def test_print_tree(self): - """Test the print_tree() function""" - - def get_children(node): - return node.children - - save_stdout = sys.stdout - - try: - node, expect, withtags = self.tree_case_1() - - IOStream = io.StringIO - sys.stdout = IOStream() - print_tree(node, get_children) - actual = sys.stdout.getvalue() - assert expect == actual, (expect, actual) - - sys.stdout = IOStream() - print_tree(node, get_children, showtags=1) - actual = sys.stdout.getvalue() - assert withtags == actual, (withtags, actual) - - # Test that explicitly setting prune to zero works - # the same as the default (see above) - node, expect, withtags = self.tree_case_2(prune=0) - - sys.stdout = IOStream() - print_tree(node, get_children, 0) - actual = sys.stdout.getvalue() - assert expect == actual, (expect, actual) - - sys.stdout = IOStream() - print_tree(node, get_children, 0, showtags=1) - actual = sys.stdout.getvalue() - assert withtags == actual, (withtags, actual) - - # Test output with prune=1 - node, expect, withtags = self.tree_case_2(prune=1) - - sys.stdout = IOStream() - print_tree(node, get_children, 1) - actual = sys.stdout.getvalue() - assert expect == actual, (expect, actual) - - # Ensure that we can call print_tree on the same Node - # again. This wasn't possible in version 2.4.1 and earlier - # due to a bug in print_tree (visited was set to {} as default - # parameter) - sys.stdout = IOStream() - print_tree(node, get_children, 1) - actual = sys.stdout.getvalue() - assert expect == actual, (expect, actual) - - sys.stdout = IOStream() - print_tree(node, get_children, 1, showtags=1) - actual = sys.stdout.getvalue() - assert withtags == actual, (withtags, actual) - finally: - sys.stdout = save_stdout - - def test_is_Dict(self): - assert is_Dict({}) - assert is_Dict(UserDict()) - try: - class mydict(dict): - pass - except TypeError: - pass - else: - assert is_Dict(mydict({})) - assert not is_Dict([]) - assert not is_Dict(()) - assert not is_Dict("") - - - def test_is_List(self): - assert is_List([]) - assert is_List(UserList()) - try: - class mylist(list): - pass - except TypeError: - pass - else: - assert is_List(mylist([])) - assert not is_List(()) - assert not is_List({}) - assert not is_List("") - - def test_is_String(self): - assert is_String("") - assert is_String(UserString('')) - try: - class mystr(str): - pass - except TypeError: - pass - else: - assert is_String(mystr('')) - assert not is_String({}) - assert not is_String([]) - assert not is_String(()) - - def test_is_Tuple(self): - assert is_Tuple(()) - try: - class mytuple(tuple): - pass - except TypeError: - pass - else: - assert is_Tuple(mytuple(())) - assert not is_Tuple([]) - assert not is_Tuple({}) - assert not is_Tuple("") - - def test_to_Bytes(self): - """ Test the to_Bytes method""" - self.assertEqual(to_bytes('Hello'), - bytearray('Hello', 'utf-8'), - "Check that to_bytes creates byte array when presented with non byte string.") - - def test_to_String(self): - """Test the to_String() method.""" - assert to_String(1) == "1", to_String(1) - assert to_String([1, 2, 3]) == str([1, 2, 3]), to_String([1, 2, 3]) - assert to_String("foo") == "foo", to_String("foo") - assert to_String(None) == 'None' - # test low level string converters too - assert to_str(None) == 'None' - assert to_bytes(None) == b'None' - - s1 = UserString('blah') - assert to_String(s1) == s1, s1 - assert to_String(s1) == 'blah', s1 - - class Derived(UserString): - pass - - s2 = Derived('foo') - assert to_String(s2) == s2, s2 - assert to_String(s2) == 'foo', s2 - - - def test_WhereIs(self): - test = TestCmd.TestCmd(workdir='') - - sub1_xxx_exe = test.workpath('sub1', 'xxx.exe') - sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') - sub3_xxx_exe = test.workpath('sub3', 'xxx.exe') - sub4_xxx_exe = test.workpath('sub4', 'xxx.exe') - - test.subdir('subdir', 'sub1', 'sub2', 'sub3', 'sub4') - - if sys.platform != 'win32': - test.write(sub1_xxx_exe, "\n") - - os.mkdir(sub2_xxx_exe) - - test.write(sub3_xxx_exe, "\n") - os.chmod(sub3_xxx_exe, 0o777) - - test.write(sub4_xxx_exe, "\n") - os.chmod(sub4_xxx_exe, 0o777) - - env_path = os.environ['PATH'] - - try: - pathdirs_1234 = [test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub3'), - test.workpath('sub4'), - ] + env_path.split(os.pathsep) - - pathdirs_1243 = [test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub4'), - test.workpath('sub3'), - ] + env_path.split(os.pathsep) - - os.environ['PATH'] = os.pathsep.join(pathdirs_1234) - wi = WhereIs('xxx.exe') - assert wi == test.workpath(sub3_xxx_exe), wi - wi = WhereIs('xxx.exe', pathdirs_1243) - assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243)) - assert wi == test.workpath(sub4_xxx_exe), wi - - wi = WhereIs('xxx.exe', reject=sub3_xxx_exe) - assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx.exe', pathdirs_1243, reject=sub3_xxx_exe) - assert wi == test.workpath(sub4_xxx_exe), wi - - os.environ['PATH'] = os.pathsep.join(pathdirs_1243) - wi = WhereIs('xxx.exe') - assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx.exe', pathdirs_1234) - assert wi == test.workpath(sub3_xxx_exe), wi - wi = WhereIs('xxx.exe', os.pathsep.join(pathdirs_1234)) - assert wi == test.workpath(sub3_xxx_exe), wi - - if sys.platform == 'win32': - wi = WhereIs('xxx', pathext='') - assert wi is None, wi - - wi = WhereIs('xxx', pathext='.exe') - assert wi == test.workpath(sub4_xxx_exe), wi - - wi = WhereIs('xxx', path=pathdirs_1234, pathext='.BAT;.EXE') - assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi - - # Test that we return a normalized path even when - # the path contains forward slashes. - forward_slash = test.workpath('') + '/sub3' - wi = WhereIs('xxx', path=forward_slash, pathext='.EXE') - assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi - - del os.environ['PATH'] - wi = WhereIs('xxx.exe') - assert wi is None, wi - - finally: - os.environ['PATH'] = env_path - - def test_get_env_var(self): - """Testing get_environment_var().""" - assert get_environment_var("$FOO") == "FOO", get_environment_var("$FOO") - assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}") - assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234") - assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}") - assert get_environment_var("${BAR}FOO") is None, get_environment_var("${BAR}FOO") - assert get_environment_var("$BAR ") is None, get_environment_var("$BAR ") - assert get_environment_var("FOO$BAR") is None, get_environment_var("FOO$BAR") - assert get_environment_var("$FOO[0]") is None, get_environment_var("$FOO[0]") - assert get_environment_var("${some('complex expression')}") is None, get_environment_var( - "${some('complex expression')}") - - def test_Proxy(self): - """Test generic Proxy class.""" - - class Subject: - def foo(self): - return 1 - - def bar(self): - return 2 - - s = Subject() - s.baz = 3 - - class ProxyTest(Proxy): - def bar(self): - return 4 - - p = ProxyTest(s) - - assert p.foo() == 1, p.foo() - assert p.bar() == 4, p.bar() - assert p.baz == 3, p.baz - - p.baz = 5 - s.baz = 6 - - assert p.baz == 5, p.baz - assert p.get() == s, p.get() - - def test_display(self): - old_stdout = sys.stdout - sys.stdout = OutBuffer() - display("line1") - display.set_mode(0) - display("line2") - display.set_mode(1) - display("line3") - display("line4\n", append_newline=0) - display.set_mode(0) - display("dont print1") - display("dont print2\n", append_newline=0) - display.set_mode(1) - assert sys.stdout.buffer == "line1\nline3\nline4\n" - sys.stdout = old_stdout - - def test_get_native_path(self): - """Test the get_native_path() function.""" - import tempfile - f, filename = tempfile.mkstemp(text=True) - os.close(f) - data = '1234567890 ' + filename - try: - with open(filename, 'w') as f: - f.write(data) - with open(get_native_path(filename), 'r') as f: - assert f.read() == data - finally: - try: - os.unlink(filename) - except OSError: - pass - - def test_PrependPath(self): - """Test prepending to a path""" - p1 = r'C:\dir\num\one;C:\dir\num\two' - p2 = r'C:\mydir\num\one;C:\mydir\num\two' - # have to include the pathsep here so that the test will work on UNIX too. - p1 = PrependPath(p1, r'C:\dir\num\two', sep=';') - p1 = PrependPath(p1, r'C:\dir\num\three', sep=';') - assert p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one', p1 - - p2 = PrependPath(p2, r'C:\mydir\num\three', sep=';') - p2 = PrependPath(p2, r'C:\mydir\num\one', sep=';') - assert p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two', p2 - - # check (only) first one is kept if there are dupes in new - p3 = r'C:\dir\num\one' - p3 = PrependPath(p3, r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\two', sep=';') - assert p3 == r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\one', p3 - - def test_AppendPath(self): - """Test appending to a path.""" - p1 = r'C:\dir\num\one;C:\dir\num\two' - p2 = r'C:\mydir\num\one;C:\mydir\num\two' - # have to include the pathsep here so that the test will work on UNIX too. - p1 = AppendPath(p1, r'C:\dir\num\two', sep=';') - p1 = AppendPath(p1, r'C:\dir\num\three', sep=';') - assert p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three', p1 - - p2 = AppendPath(p2, r'C:\mydir\num\three', sep=';') - p2 = AppendPath(p2, r'C:\mydir\num\one', sep=';') - assert p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one', p2 - - # check (only) last one is kept if there are dupes in new - p3 = r'C:\dir\num\one' - p3 = AppendPath(p3, r'C:\dir\num\two;C:\dir\num\three;C:\dir\num\two', sep=';') - assert p3 == r'C:\dir\num\one;C:\dir\num\three;C:\dir\num\two', p3 - - def test_PrependPathPreserveOld(self): - """Test prepending to a path while preserving old paths""" - p1 = r'C:\dir\num\one;C:\dir\num\two' - # have to include the pathsep here so that the test will work on UNIX too. - p1 = PrependPath(p1, r'C:\dir\num\two', sep=';', delete_existing=0) - p1 = PrependPath(p1, r'C:\dir\num\three', sep=';') - assert p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two', p1 - - def test_AppendPathPreserveOld(self): - """Test appending to a path while preserving old paths""" - p1 = r'C:\dir\num\one;C:\dir\num\two' - # have to include the pathsep here so that the test will work on UNIX too. - p1 = AppendPath(p1, r'C:\dir\num\one', sep=';', delete_existing=0) - p1 = AppendPath(p1, r'C:\dir\num\three', sep=';') - assert p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three', p1 - - def test_addPathIfNotExists(self): - """Test the AddPathIfNotExists() function""" - env_dict = {'FOO': os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BAR': os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BLAT': [os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat')]} - AddPathIfNotExists(env_dict, 'FOO', os.path.normpath('/foo/bar')) - AddPathIfNotExists(env_dict, 'BAR', os.path.normpath('/bar/foo')) - AddPathIfNotExists(env_dict, 'BAZ', os.path.normpath('/foo/baz')) - AddPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/blat')) - AddPathIfNotExists(env_dict, 'BLAT', os.path.normpath('/baz/foo')) - - assert env_dict['FOO'] == os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), env_dict['FOO'] - assert env_dict['BAR'] == os.path.normpath('/bar/foo') + os.pathsep + \ - os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), env_dict['BAR'] - assert env_dict['BAZ'] == os.path.normpath('/foo/baz'), env_dict['BAZ'] - assert env_dict['BLAT'] == [os.path.normpath('/baz/foo'), - os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat')], env_dict['BLAT'] - - def test_CLVar(self): - """Test the command-line construction variable class""" - - # the default value should be an empty list - d = CLVar() - assert isinstance(d, CLVar), type(d) - assert d.data == [], d.data - assert str(d) == '', str(d) - - # input to CLVar is a string - should be split - f = CLVar('aa bb') - - r = f + 'cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ' cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', ' cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', ' cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - # input to CLVar is a list of one string, should not be split - f = CLVar(['aa bb']) - - r = f + 'cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ' cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', 'cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', ' cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa bb', ' cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - # input to CLVar is a list of strings - f = CLVar(['aa', 'bb']) - - r = f + 'cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ' cc dd' - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', ' cc dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + ['cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - r = f + [' cc', 'dd'] - assert isinstance(r, CLVar), type(r) - assert r.data == ['aa', 'bb', ' cc', 'dd'], r.data - assert str(r) == 'aa bb cc dd', str(r) - - # make sure inplace adding a string works as well (issue 2399) - # UserList would convert the string to a list of chars - f = CLVar(['aa', 'bb']) - f += 'cc dd' - assert isinstance(f, CLVar), type(f) - assert f.data == ['aa', 'bb', 'cc', 'dd'], f.data - assert str(f) == 'aa bb cc dd', str(f) - - f = CLVar(['aa', 'bb']) - f += ' cc dd' - assert isinstance(f, CLVar), type(f) - assert f.data == ['aa', 'bb', 'cc', 'dd'], f.data - assert str(f) == 'aa bb cc dd', str(f) - - - def test_Selector(self): - """Test the Selector class""" - - class MyNode: - def __init__(self, name): - self.name = name - - def __str__(self): - return self.name - - def get_suffix(self): - return os.path.splitext(self.name)[1] - - s = Selector({'a': 'AAA', 'b': 'BBB'}) - assert s['a'] == 'AAA', s['a'] - assert s['b'] == 'BBB', s['b'] - exc_caught = None - try: - x = s['c'] - except KeyError: - exc_caught = 1 - assert exc_caught, "should have caught a KeyError" - s['c'] = 'CCC' - assert s['c'] == 'CCC', s['c'] - - class DummyEnv(UserDict): - def subst(self, key): - if key[0] == '$': - return self[key[1:]] - return key - - env = DummyEnv() - - s = Selector({'.d': 'DDD', '.e': 'EEE'}) - ret = s(env, []) - assert ret is None, ret - ret = s(env, [MyNode('foo.d')]) - assert ret == 'DDD', ret - ret = s(env, [MyNode('bar.e')]) - assert ret == 'EEE', ret - ret = s(env, [MyNode('bar.x')]) - assert ret is None, ret - s[None] = 'XXX' - ret = s(env, [MyNode('bar.x')]) - assert ret == 'XXX', ret - - env = DummyEnv({'FSUFF': '.f', 'GSUFF': '.g'}) - - s = Selector({'$FSUFF': 'FFF', '$GSUFF': 'GGG'}) - ret = s(env, [MyNode('foo.f')]) - assert ret == 'FFF', ret - ret = s(env, [MyNode('bar.g')]) - assert ret == 'GGG', ret - - def test_adjustixes(self): - """Test the adjustixes() function""" - r = adjustixes('file', 'pre-', '-suf') - assert r == 'pre-file-suf', r - r = adjustixes('pre-file', 'pre-', '-suf') - assert r == 'pre-file-suf', r - r = adjustixes('file-suf', 'pre-', '-suf') - assert r == 'pre-file-suf', r - r = adjustixes('pre-file-suf', 'pre-', '-suf') - assert r == 'pre-file-suf', r - r = adjustixes('pre-file.xxx', 'pre-', '-suf') - assert r == 'pre-file.xxx', r - r = adjustixes('dir/file', 'pre-', '-suf') - assert r == os.path.join('dir', 'pre-file-suf'), r - - # Verify that the odd case when library name is specified as 'lib' - # doesn't yield lib.so, but yields the expected liblib.so - r = adjustixes('PREFIX', 'PREFIX', 'SUFFIX') - assert r == 'PREFIXPREFIXSUFFIX', "Failed handling when filename = PREFIX [r='%s']" % r - - def test_containsAny(self): - """Test the containsAny() function""" - assert containsAny('*.py', '*?[]') - assert not containsAny('file.txt', '*?[]') - - def test_containsAll(self): - """Test the containsAll() function""" - assert containsAll('43221', '123') - assert not containsAll('134', '123') - - def test_containsOnly(self): - """Test the containsOnly() function""" - assert containsOnly('.83', '0123456789.') - assert not containsOnly('43221', '123') - - def test_LogicalLines(self): - """Test the LogicalLines class""" - content = """ -foo \\ -bar \\ -baz -foo -bling \\ -bling \\ bling -bling -""" - fobj = io.StringIO(content) - lines = LogicalLines(fobj).readlines() - assert lines == [ - '\n', - 'foo bar baz\n', - 'foo\n', - 'bling bling \\ bling\n', - 'bling\n', - ], lines - - def test_intern(self): - s1 = silent_intern("spam") - s3 = silent_intern(42) - s4 = silent_intern("spam") - assert id(s1) == id(s4) - - -class HashTestCase(unittest.TestCase): - - def test_collect(self): - """Test collecting a list of signatures into a new signature value - """ - for algorithm, expected in { - 'md5': ('698d51a19d8a121ce581499d7b701668', - '8980c988edc2c78cc43ccb718c06efd5', - '53fd88c84ff8a285eb6e0a687e55b8c7'), - 'sha1': ('6216f8a75fd5bb3d5f22b6f9958cdede3fc086c2', - '42eda1b5dcb3586bccfb1c69f22f923145271d97', - '2eb2f7be4e883ebe52034281d818c91e1cf16256'), - 'sha256': ('f6e0a1e2ac41945a9aa7ff8a8aaa0cebc12a3bcc981a929ad5cf810a090e11ae', - '25235f0fcab8767b7b5ac6568786fbc4f7d5d83468f0626bf07c3dbeed391a7a', - 'f8d3d0729bf2427e2e81007588356332e7e8c4133fae4bceb173b93f33411d17'), - }.items(): - # if the current platform does not support the algorithm we're looking at, - # skip the test steps for that algorithm, but display a warning to the user - if algorithm not in ALLOWED_HASH_FORMATS: - warnings.warn("Missing hash algorithm {} on this platform, cannot test with it".format(algorithm), ResourceWarning) - else: - hs = functools.partial(hash_signature, hash_format=algorithm) - s = list(map(hs, ('111', '222', '333'))) - - assert expected[0] == hash_collect(s[0:1], hash_format=algorithm) - assert expected[1] == hash_collect(s[0:2], hash_format=algorithm) - assert expected[2] == hash_collect(s, hash_format=algorithm) - - def test_MD5signature(self): - """Test generating a signature""" - for algorithm, expected in { - 'md5': ('698d51a19d8a121ce581499d7b701668', - 'bcbe3365e6ac95ea2c0343a2395834dd'), - 'sha1': ('6216f8a75fd5bb3d5f22b6f9958cdede3fc086c2', - '1c6637a8f2e1f75e06ff9984894d6bd16a3a36a9'), - 'sha256': ('f6e0a1e2ac41945a9aa7ff8a8aaa0cebc12a3bcc981a929ad5cf810a090e11ae', - '9b871512327c09ce91dd649b3f96a63b7408ef267c8cc5710114e629730cb61f'), - }.items(): - # if the current platform does not support the algorithm we're looking at, - # skip the test steps for that algorithm, but display a warning to the user - if algorithm not in ALLOWED_HASH_FORMATS: - warnings.warn("Missing hash algorithm {} on this platform, cannot test with it".format(algorithm), ResourceWarning) - else: - s = hash_signature('111', hash_format=algorithm) - assert expected[0] == s, s - - s = hash_signature('222', hash_format=algorithm) - assert expected[1] == s, s - -# this uses mocking out, which is platform specific, however, the FIPS -# behavior this is testing is also platform-specific, and only would be -# visible in hosts running Linux with the fips_mode kernel flag along -# with using OpenSSL. - -class FIPSHashTestCase(unittest.TestCase): - def __init__(self, *args, **kwargs): - super(FIPSHashTestCase, self).__init__(*args, **kwargs) - - ############################### - # algorithm mocks, can check if we called with usedforsecurity=False for python >= 3.9 - self.fake_md5=lambda usedforsecurity=True: (usedforsecurity, 'md5') - self.fake_sha1=lambda usedforsecurity=True: (usedforsecurity, 'sha1') - self.fake_sha256=lambda usedforsecurity=True: (usedforsecurity, 'sha256') - ############################### - - ############################### - # hashlib mocks - md5Available = unittest.mock.Mock(md5=self.fake_md5) - del md5Available.sha1 - del md5Available.sha256 - self.md5Available=md5Available - - md5Default = unittest.mock.Mock(md5=self.fake_md5, sha1=self.fake_sha1) - del md5Default.sha256 - self.md5Default=md5Default - - sha1Default = unittest.mock.Mock(sha1=self.fake_sha1, sha256=self.fake_sha256) - del sha1Default.md5 - self.sha1Default=sha1Default - - sha256Default = unittest.mock.Mock(sha256=self.fake_sha256, **{'md5.side_effect': ValueError, 'sha1.side_effect': ValueError}) - self.sha256Default=sha256Default - - all_throw = unittest.mock.Mock(**{'md5.side_effect': ValueError, 'sha1.side_effect': ValueError, 'sha256.side_effect': ValueError}) - self.all_throw=all_throw - - no_algorithms = unittest.mock.Mock() - del no_algorithms.md5 - del no_algorithms.sha1 - del no_algorithms.sha256 - del no_algorithms.nonexist - self.no_algorithms=no_algorithms - - unsupported_algorithm = unittest.mock.Mock(unsupported=self.fake_sha256) - del unsupported_algorithm.md5 - del unsupported_algorithm.sha1 - del unsupported_algorithm.sha256 - del unsupported_algorithm.unsupported - self.unsupported_algorithm=unsupported_algorithm - ############################### - - ############################### - # system version mocks - VersionInfo = namedtuple('VersionInfo', 'major minor micro releaselevel serial') - v3_8 = VersionInfo(3, 8, 199, 'super-beta', 1337) - v3_9 = VersionInfo(3, 9, 0, 'alpha', 0) - v4_8 = VersionInfo(4, 8, 0, 'final', 0) - - self.sys_v3_8 = unittest.mock.Mock(version_info=v3_8) - self.sys_v3_9 = unittest.mock.Mock(version_info=v3_9) - self.sys_v4_8 = unittest.mock.Mock(version_info=v4_8) - ############################### - - def test_basic_failover_bad_hashlib_hash_init(self): - """Tests that if the hashing function is entirely missing from hashlib (hashlib returns None), - the hash init function returns None""" - assert _attempt_init_of_python_3_9_hash_object(None) is None - - def test_basic_failover_bad_hashlib_hash_get(self): - """Tests that if the hashing function is entirely missing from hashlib (hashlib returns None), - the hash get function returns None""" - assert _attempt_get_hash_function("nonexist", self.no_algorithms) is None - - def test_usedforsecurity_flag_behavior(self): - """Test usedforsecurity flag -> should be set to 'True' on older versions of python, and 'False' on Python >= 3.9""" - for version, expected in { - self.sys_v3_8: (True, 'md5'), - self.sys_v3_9: (False, 'md5'), - self.sys_v4_8: (False, 'md5'), - }.items(): - assert _attempt_init_of_python_3_9_hash_object(self.fake_md5, version) == expected - - def test_automatic_default_to_md5(self): - """Test automatic default to md5 even if sha1 available""" - for version, expected in { - self.sys_v3_8: (True, 'md5'), - self.sys_v3_9: (False, 'md5'), - self.sys_v4_8: (False, 'md5'), - }.items(): - _set_allowed_viable_default_hashes(self.md5Default, version) - set_hash_format(None, self.md5Default, version) - assert _get_hash_object(None, self.md5Default, version) == expected - - def test_automatic_default_to_sha256(self): - """Test automatic default to sha256 if other algorithms available but throw""" - for version, expected in { - self.sys_v3_8: (True, 'sha256'), - self.sys_v3_9: (False, 'sha256'), - self.sys_v4_8: (False, 'sha256'), - }.items(): - _set_allowed_viable_default_hashes(self.sha256Default, version) - set_hash_format(None, self.sha256Default, version) - assert _get_hash_object(None, self.sha256Default, version) == expected - - def test_automatic_default_to_sha1(self): - """Test automatic default to sha1 if md5 is missing from hashlib entirely""" - for version, expected in { - self.sys_v3_8: (True, 'sha1'), - self.sys_v3_9: (False, 'sha1'), - self.sys_v4_8: (False, 'sha1'), - }.items(): - _set_allowed_viable_default_hashes(self.sha1Default, version) - set_hash_format(None, self.sha1Default, version) - assert _get_hash_object(None, self.sha1Default, version) == expected - - def test_no_available_algorithms(self): - """expect exceptions on no available algorithms or when all algorithms throw""" - self.assertRaises(SCons.Errors.SConsEnvironmentError, _set_allowed_viable_default_hashes, self.no_algorithms) - self.assertRaises(SCons.Errors.SConsEnvironmentError, _set_allowed_viable_default_hashes, self.all_throw) - self.assertRaises(SCons.Errors.SConsEnvironmentError, _set_allowed_viable_default_hashes, self.unsupported_algorithm) - - def test_bad_algorithm_set_attempt(self): - """expect exceptions on user setting an unsupported algorithm selections, either by host or by SCons""" - - # nonexistant hash algorithm, not supported by SCons - _set_allowed_viable_default_hashes(self.md5Available) - self.assertRaises(SCons.Errors.UserError, set_hash_format, 'blah blah blah', hashlib_used=self.no_algorithms) - - # md5 is default-allowed, but in this case throws when we attempt to use it - _set_allowed_viable_default_hashes(self.md5Available) - self.assertRaises(SCons.Errors.UserError, set_hash_format, 'md5', hashlib_used=self.all_throw) - - # user attempts to use an algorithm that isn't supported by their current system but is supported by SCons - _set_allowed_viable_default_hashes(self.sha1Default) - self.assertRaises(SCons.Errors.UserError, set_hash_format, 'md5', hashlib_used=self.all_throw) - - # user attempts to use an algorithm that is supported by their current system but isn't supported by SCons - _set_allowed_viable_default_hashes(self.sha1Default) - self.assertRaises(SCons.Errors.UserError, set_hash_format, 'unsupported', hashlib_used=self.unsupported_algorithm) - - def tearDown(self): - """Return SCons back to the normal global state for the hashing functions.""" - _set_allowed_viable_default_hashes(hashlib, sys) - set_hash_format(None) - - -class NodeListTestCase(unittest.TestCase): - def test_simple_attributes(self): - """Test simple attributes of a NodeList class""" - - class TestClass: - def __init__(self, name, child=None): - self.child = child - self.bar = name - - t1 = TestClass('t1', TestClass('t1child')) - t2 = TestClass('t2', TestClass('t2child')) - t3 = TestClass('t3') - - nl = NodeList([t1, t2, t3]) - assert nl.bar == ['t1', 't2', 't3'], nl.bar - assert nl[0:2].child.bar == ['t1child', 't2child'], \ - nl[0:2].child.bar - - def test_callable_attributes(self): - """Test callable attributes of a NodeList class""" - - class TestClass: - def __init__(self, name, child=None): - self.child = child - self.bar = name - - def foo(self): - return self.bar + "foo" - - def getself(self): - return self - - t1 = TestClass('t1', TestClass('t1child')) - t2 = TestClass('t2', TestClass('t2child')) - t3 = TestClass('t3') - - nl = NodeList([t1, t2, t3]) - assert nl.foo() == ['t1foo', 't2foo', 't3foo'], nl.foo() - assert nl.bar == ['t1', 't2', 't3'], nl.bar - assert nl.getself().bar == ['t1', 't2', 't3'], nl.getself().bar - assert nl[0:2].child.foo() == ['t1childfoo', 't2childfoo'], \ - nl[0:2].child.foo() - assert nl[0:2].child.bar == ['t1child', 't2child'], \ - nl[0:2].child.bar - - def test_null(self): - """Test a null NodeList""" - nl = NodeList([]) - r = str(nl) - assert r == '', r - for node in nl: - raise Exception("should not enter this loop") - - -class flattenTestCase(unittest.TestCase): - - def test_scalar(self): - """Test flattening a scalar""" - result = flatten('xyz') - self.assertEqual(result, ['xyz'], result) - - def test_dictionary_values(self): - """Test flattening the dictionary values""" - items = {"a": 1, "b": 2, "c": 3} - result = flatten(items.values()) - self.assertEqual(sorted(result), [1, 2, 3]) - - -class OsEnviron: - """Used to temporarily mock os.environ""" - - def __init__(self, environ): - self._environ = environ - - def start(self): - self._stored = os.environ - os.environ = self._environ - - def stop(self): - os.environ = self._stored - del self._stored - - def __enter__(self): - self.start() - return os.environ - - def __exit__(self, *args): - self.stop() - - -class get_env_boolTestCase(unittest.TestCase): - def test_missing(self): - env = dict() - var = get_env_bool(env, 'FOO') - assert var is False, "var should be False, not %s" % repr(var) - env = {'FOO': '1'} - var = get_env_bool(env, 'BAR') - assert var is False, "var should be False, not %s" % repr(var) - - def test_true(self): - for foo in ['TRUE', 'True', 'true', - 'YES', 'Yes', 'yes', - 'Y', 'y', - 'ON', 'On', 'on', - '1', '20', '-1']: - env = {'FOO': foo} - var = get_env_bool(env, 'FOO') - assert var is True, 'var should be True, not %s' % repr(var) - - def test_false(self): - for foo in ['FALSE', 'False', 'false', - 'NO', 'No', 'no', - 'N', 'n', - 'OFF', 'Off', 'off', - '0']: - env = {'FOO': foo} - var = get_env_bool(env, 'FOO', True) - assert var is False, 'var should be True, not %s' % repr(var) - - def test_default(self): - env = {'FOO': 'other'} - var = get_env_bool(env, 'FOO', True) - assert var is True, 'var should be True, not %s' % repr(var) - var = get_env_bool(env, 'FOO', False) - assert var is False, 'var should be False, not %s' % repr(var) - - -class get_os_env_boolTestCase(unittest.TestCase): - def test_missing(self): - with OsEnviron(dict()): - var = get_os_env_bool('FOO') - assert var is False, "var should be False, not %s" % repr(var) - with OsEnviron({'FOO': '1'}): - var = get_os_env_bool('BAR') - assert var is False, "var should be False, not %s" % repr(var) - - def test_true(self): - for foo in ['TRUE', 'True', 'true', - 'YES', 'Yes', 'yes', - 'Y', 'y', - 'ON', 'On', 'on', - '1', '20', '-1']: - with OsEnviron({'FOO': foo}): - var = get_os_env_bool('FOO') - assert var is True, 'var should be True, not %s' % repr(var) - - def test_false(self): - for foo in ['FALSE', 'False', 'false', - 'NO', 'No', 'no', - 'N', 'n', - 'OFF', 'Off', 'off', - '0']: - with OsEnviron({'FOO': foo}): - var = get_os_env_bool('FOO', True) - assert var is False, 'var should be True, not %s' % repr(var) - - def test_default(self): - with OsEnviron({'FOO': 'other'}): - var = get_os_env_bool('FOO', True) - assert var is True, 'var should be True, not %s' % repr(var) - var = get_os_env_bool('FOO', False) - assert var is False, 'var should be False, not %s' % repr(var) - - -if __name__ == "__main__": - unittest.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/SCSCons/Variables/BoolVariableTests.py b/SCSCons/Variables/BoolVariableTests.py deleted file mode 100644 index e486e4b8b..000000000 --- a/SCSCons/Variables/BoolVariableTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Variables/EnumVariableTests.py b/SCSCons/Variables/EnumVariableTests.py deleted file mode 100644 index 75bb54f1f..000000000 --- a/SCSCons/Variables/EnumVariableTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Variables/ListVariableTests.py b/SCSCons/Variables/ListVariableTests.py deleted file mode 100644 index c73cef326..000000000 --- a/SCSCons/Variables/ListVariableTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Variables/PackageVariableTests.py b/SCSCons/Variables/PackageVariableTests.py deleted file mode 100644 index 988fbe01d..000000000 --- a/SCSCons/Variables/PackageVariableTests.py +++ /dev/null @@ -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() -> Variables(). - 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: diff --git a/SCSCons/Variables/PathVariableTests.py b/SCSCons/Variables/PathVariableTests.py deleted file mode 100644 index a9aa8f035..000000000 --- a/SCSCons/Variables/PathVariableTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/Variables/VariablesTests.py b/SCSCons/Variables/VariablesTests.py deleted file mode 100644 index 4672cdd8a..000000000 --- a/SCSCons/Variables/VariablesTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/WarningsTests.py b/SCSCons/WarningsTests.py deleted file mode 100644 index c22b049bd..000000000 --- a/SCSCons/WarningsTests.py +++ /dev/null @@ -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: diff --git a/SCSCons/cppTests.py b/SCSCons/cppTests.py deleted file mode 100644 index 99fa6cfd5..000000000 --- a/SCSCons/cppTests.py +++ /dev/null @@ -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 -""" - - -substitution_input = """ -#define FILE3 "file3-yes" -#define FILE4 - -#include FILE3 -#include FILE4 - -#define XXX_FILE5 YYY_FILE5 -#define YYY_FILE5 ZZZ_FILE5 -#define ZZZ_FILE5 FILE5 - -#define FILE5 "file5-yes" -#define FILE6 - -#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 -#else -#include -#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 -#else -#include -#endif - -#if ZERO -#include "file11-no-1" -#elif ZERO -#include "file11-no-2" -#else -#include "file11-yes" -#endif - -#if ZERO -#include -#elif ONE -#include -#else -#include -#endif - -#if ONE -#include "file13-yes" -#elif ZERO -#include "file13-no-1" -#else -#include "file13-no-2" -#endif - -#if ONE -#include -#elif ONE -#include -#else -#include -#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 -#else -#include -#endif - -#if defined DEFINED_A -#include "file17-yes" -#endif - -#if ! defined DEFINED_A -#include -#else -#include -#endif - -#if ! (defined (DEFINED_A) || defined (DEFINED_B) -#include -#else -#include -#endif - -""" - - -expression_input = """ -#define ZERO 0 -#define ONE 1 - -#if ZERO && ZERO -#include "file19-no" -#else -#include "file19-yes" -#endif - -#if ZERO && ONE -#include -#else -#include -#endif - -#if ONE && ZERO -#include "file21-no" -#else -#include "file21-yes" -#endif - -#if ONE && ONE -#include -#else -#include -#endif - -#if ZERO || ZERO -#include "file23-no" -#else -#include "file23-yes" -#endif - -#if ZERO || ONE -#include -#else -#include -#endif - -#if ONE || ZERO -#include "file25-yes" -#else -#include "file25-no" -#endif - -#if ONE || ONE -#include -#else -#include -#endif - -#if ONE == ONE -#include "file27-yes" -#else -#include "file27-no" -#endif - -#if ONE != ONE -#include -#else -#include -#endif - -#if ! (ONE == ONE) -#include "file29-no" -#else -#include "file29-yes" -#endif - -#if ! (ONE != ONE) -#include -#else -#include -#endif - -#if 123456789UL || 0x13L -#include -#else -#include -#endif -""" - - -undef_input = """ -#define UNDEFINE 0 - -#ifdef UNDEFINE -#include "file31-yes" -#else -#include "file31-no" -#endif - -#undef UNDEFINE - -#ifdef UNDEFINE -#include -#else -#include -#endif -""" - - -macro_function_input = """ -#define ZERO 0 -#define ONE 1 - -#define FUNC33(x) "file33-yes" -#define FUNC34(x) - -#include FUNC33(ZERO) -#include FUNC34(ZERO) - -#define FILE35 "file35-yes" -#define FILE36 - -#define FUNC35(x, y) FILE35 -#define FUNC36(x, y) FILE36 - -#include FUNC35(ZERO, ONE) -#include FUNC36(ZERO, ONE) - -#define FILE37 "file37-yes" -#define FILE38 - -#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 - -#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 -#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 -#else -#include -#endif -""" - - -if_defined_no_space_input = """ -#define DEFINED 0 - -#if(defined DEFINED) -#include "file47-yes" -#endif - -#if(!defined DEFINED) -#include -#elif(!defined DEFINED) -#include -#else -#include -#endif - -#if!(defined DEFINED) -#include "file51-no" -#elif!(defined DEFINED) -#include -#else -#include "file53-yes" -#endif -""" - -if_no_space_input = """ -#define DEFINED 0 - -#if(DEFINED) -#include "file54-no" -#endif - -#if!(DEFINED) -#include -#elif!(DEFINED) -#include -#endif - -#if(DEFINED) -#include "file57-no" -#elif(!DEFINED) -#include -#endif - -#if!( DEFINED) -#include "file59-yes" -#elif!( DEFINED) -#include -#endif - -#if( DEFINED) -#include "file61-no" -#elif(! DEFINED) -#include -#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 - """) - 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 - """) - 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: diff --git a/sc.py b/sc.py new file mode 100644 index 000000000..590d1610f --- /dev/null +++ b/sc.py @@ -0,0 +1,4 @@ + +from SCons.Script.Main import main + +main()