summaryrefslogtreecommitdiff
path: root/src/engine/SCons/Scanner/ScannerTests.py
diff options
context:
space:
mode:
authorLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:35 +0100
committerLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:35 +0100
commit64c458487151933ee0ba093cf4ac69e177d9be37 (patch)
treef6e3755704f53406eea85532e4ffe5d5ef50b7f0 /src/engine/SCons/Scanner/ScannerTests.py
parent2aec9cc58398cac1376509a7d75edb83b41f984e (diff)
parent72c578fd4b0b4a5a43e18594339ac4ff26c376dc (diff)
Merge commit 'upstream/1.2.0.d20091224'
Diffstat (limited to 'src/engine/SCons/Scanner/ScannerTests.py')
-rw-r--r--src/engine/SCons/Scanner/ScannerTests.py611
1 files changed, 611 insertions, 0 deletions
diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py
new file mode 100644
index 0000000..ae6cb79
--- /dev/null
+++ b/src/engine/SCons/Scanner/ScannerTests.py
@@ -0,0 +1,611 @@
+#
+# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
+#
+
+__revision__ = "src/engine/SCons/Scanner/ScannerTests.py 4577 2009/12/27 19:44:43 scons"
+
+import sys
+import unittest
+import UserDict
+
+import SCons.Scanner
+
+class DummyFS:
+ def File(self, name):
+ return DummyNode(name)
+
+class DummyEnvironment(UserDict.UserDict):
+ def __init__(self, dict=None, **kw):
+ UserDict.UserDict.__init__(self, dict)
+ self.data.update(kw)
+ 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 type(path) != type([]):
+ path = [path]
+ return 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 1
+ def __str__(self):
+ return self.name
+ def Rfindalldirs(self, pathlist):
+ return self.search_result + pathlist
+
+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 = SCons.Scanner.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 = SCons.Scanner.Base(func)
+ assert isinstance(s, SCons.Scanner.Base), s
+ s = SCons.Scanner.Base({})
+ assert isinstance(s, SCons.Scanner.Base), s
+
+ s = SCons.Scanner.Base(func, name='fooscan')
+ assert str(s) == 'fooscan', str(s)
+ s = SCons.Scanner.Base({}, name='barscan')
+ assert str(s) == 'barscan', str(s)
+
+ s = SCons.Scanner.Base(func, name='fooscan', argument=9)
+ assert str(s) == 'fooscan', str(s)
+ assert s.argument == 9, s.argument
+ s = SCons.Scanner.Base({}, name='fooscan', argument=888)
+ assert str(s) == 'fooscan', str(s)
+ assert s.argument == 888, s.argument
+
+
+class BaseTestCase(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 = map(lambda x: str(x), scanned)
+
+ self.failUnless(self.filename == filename, "the filename was passed incorrectly")
+ self.failUnless(self.env == env, "the environment was passed incorrectly")
+ self.failUnless(scanned_strs == deps, "the dependencies were returned incorrectly")
+ for d in scanned:
+ self.failUnless(type(d) != type(""), "got a string in the dependencies")
+
+ if len(args) > 0:
+ self.failUnless(self.arg == args[0], "the argument was passed incorrectly")
+ else:
+ self.failIf(hasattr(self, "arg"), "an argument was given when it shouldn't have been")
+
+ def test___call__dict(self):
+ """Test calling Scanner.Base 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 = SCons.Scanner.Base(s1func)
+ s2 = SCons.Scanner.Base(s2func)
+ selector = SCons.Scanner.Base({'.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 Scanner.Base 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 = SCons.Scanner.Base(self.func, path_function=pf)
+ p = s.path(env, 'here', [target], [source])
+ assert p == "pf: v1 here target source None", p
+
+ s = SCons.Scanner.Base(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 Scanner.Base class using positional arguments"""
+ s = SCons.Scanner.Base(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 Scanner.Base class using keyword arguments"""
+ s = SCons.Scanner.Base(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 Scanner.Base class using both position and optional arguments"""
+ arg = "this is the argument"
+ s = SCons.Scanner.Base(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 Scanner.Base class using both keyword and optional arguments"""
+ arg = "this is another argument"
+ s = SCons.Scanner.Base(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 Scanner.Base class __cmp__() method"""
+ s = SCons.Scanner.Base(self.func, "Cmp")
+ assert cmp(s, None)
+
+ def test_hash(self):
+ """Test the Scanner.Base class __hash__() method"""
+ s = SCons.Scanner.Base(self.func, "Hash")
+ dict = {}
+ dict[s] = 777
+ i = hash(id(s))
+ h = hash(dict.keys()[0])
+ self.failUnless(h == i,
+ "hash Scanner base class expected %s, got %s" % (i, h))
+
+ def test_scan_check(self):
+ """Test the Scanner.Base 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 = SCons.Scanner.Base(my_scan, "Check", scan_check = check)
+ self.checked = {}
+ path = s.path(env)
+ scanned = s(DummyNode('x'), env, path)
+ self.failUnless(self.checked['x'] == 1,
+ "did not call check function")
+
+ def test_recursive(self):
+ """Test the Scanner.Base class recursive flag"""
+ nodes = [1, 2, 3, 4]
+
+ s = SCons.Scanner.Base(function = self.func)
+ n = s.recurse_nodes(nodes)
+ self.failUnless(n == [],
+ "default behavior returned nodes: %s" % n)
+
+ s = SCons.Scanner.Base(function = self.func, recursive = None)
+ n = s.recurse_nodes(nodes)
+ self.failUnless(n == [],
+ "recursive = None returned nodes: %s" % n)
+
+ s = SCons.Scanner.Base(function = self.func, recursive = 1)
+ n = s.recurse_nodes(nodes)
+ self.failUnless(n == n,
+ "recursive = 1 didn't return all nodes: %s" % n)
+
+ def odd_only(nodes):
+ return filter(lambda n: n % 2, nodes)
+ s = SCons.Scanner.Base(function = self.func, recursive = odd_only)
+ n = s.recurse_nodes(nodes)
+ self.failUnless(n == [1, 3],
+ "recursive = 1 didn't return all nodes: %s" % n)
+
+ def test_get_skeys(self):
+ """Test the Scanner.Base get_skeys() method"""
+ s = SCons.Scanner.Base(function = self.func)
+ sk = s.get_skeys()
+ self.failUnless(sk == [],
+ "did not initialize to expected []")
+
+ s = SCons.Scanner.Base(function = self.func, skeys = ['.1', '.2'])
+ sk = s.get_skeys()
+ self.failUnless(sk == ['.1', '.2'],
+ "sk was %s, not ['.1', '.2']")
+
+ s = SCons.Scanner.Base(function = self.func, skeys = '$LIST')
+ env = DummyEnvironment(LIST = ['.3', '.4'])
+ sk = s.get_skeys(env)
+ self.failUnless(sk == ['.3', '.4'],
+ "sk was %s, not ['.3', '.4']")
+
+ def test_select(self):
+ """Test the Scanner.Base select() method"""
+ scanner = SCons.Scanner.Base(function = self.func)
+ s = scanner.select('.x')
+ assert s is scanner, s
+
+ selector = SCons.Scanner.Base({'.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.Base add_scanner() method"""
+ selector = SCons.Scanner.Base({'.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 Scanner.Base __str__() method"""
+ scanner = SCons.Scanner.Base(function = self.func)
+ s = str(scanner)
+ assert s == 'NONE', s
+ scanner = SCons.Scanner.Base(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 = SCons.Scanner.Selector({})
+ assert isinstance(s, SCons.Scanner.Selector), s
+ assert s.dict == {}, s.dict
+
+ 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 = SCons.Scanner.Base(s1func)
+ s2 = SCons.Scanner.Base(s2func)
+ selector = SCons.Scanner.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 = SCons.Scanner.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 = SCons.Scanner.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 = SCons.Scanner.Current(func)
+ path = s.path(env)
+ hnb = HasNoBuilder()
+ s(hnb, env, path)
+ self.failUnless(hnb.called_has_builder, "did not call has_builder()")
+ self.failUnless(not hnb.called_is_up_to_date, "did call is_up_to_date()")
+ self.failUnless(hnb.func_called, "did not call func()")
+ inc = IsNotCurrent()
+ s(inc, env, path)
+ self.failUnless(inc.called_has_builder, "did not call has_builder()")
+ self.failUnless(inc.called_is_up_to_date, "did not call is_up_to_date()")
+ self.failUnless(not inc.func_called, "did call func()")
+ ic = IsCurrent()
+ s(ic, env, path)
+ self.failUnless(ic.called_has_builder, "did not call has_builder()")
+ self.failUnless(ic.called_is_up_to_date, "did not call is_up_to_date()")
+ self.failUnless(ic.func_called, "did not call func()")
+
+class ClassicTestCase(unittest.TestCase):
+ def test_find_include(self):
+ """Test the Scanner.Classic find_include() method"""
+ env = DummyEnvironment()
+ s = SCons.Scanner.Classic("t", ['.suf'], 'MYPATH', '^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 = SCons.Scanner.Classic("my_name", ['.s'], 'MYPATH', '^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(SCons.Scanner.Classic):
+ def find_include(self, include, source_dir, path):
+ return include, include
+
+ env = DummyEnvironment()
+ s = MyScanner("t", ['.suf'], 'MYPATH', '^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
+
+
+
+class ClassicCPPTestCase(unittest.TestCase):
+ def test_find_include(self):
+ """Test the Scanner.ClassicCPP find_include() method"""
+ env = DummyEnvironment()
+ s = SCons.Scanner.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
+
+ # TODO(1.5): remove when 2.2 is minimal; replace ccc
+ # variable in find_include() call below with in-line u'ccc'.
+ try:
+ ccc = eval("u'ccc'")
+ except SyntaxError:
+ ccc = 'ccc'
+
+ 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,
+ BaseTestCase,
+ SelectorTestCase,
+ CurrentTestCase,
+ ClassicTestCase,
+ ClassicCPPTestCase,
+ ]
+ for tclass in tclasses:
+ names = unittest.getTestCaseNames(tclass, 'test_')
+ suite.addTests(map(tclass, names))
+ return suite
+
+if __name__ == "__main__":
+ runner = unittest.TextTestRunner()
+ result = runner.run(suite())
+ if not result.wasSuccessful():
+ sys.exit(1)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4: