summaryrefslogtreecommitdiff
path: root/SCons/Scanner/CTests.py
diff options
context:
space:
mode:
Diffstat (limited to 'SCons/Scanner/CTests.py')
-rw-r--r--SCons/Scanner/CTests.py157
1 files changed, 103 insertions, 54 deletions
diff --git a/SCons/Scanner/CTests.py b/SCons/Scanner/CTests.py
index 14e156e71..6860a10ce 100644
--- a/SCons/Scanner/CTests.py
+++ b/SCons/Scanner/CTests.py
@@ -91,6 +91,27 @@ int main(void)
}
""")
+# include using a macro, defined in source file
+test.write('f9a.c', """\
+#define HEADER "f9.h"
+#include HEADER
+
+int main(void)
+{
+ return 0;
+}
+""")
+
+# include using a macro, not defined in source file
+test.write('f9b.c', """\
+#include HEADER
+
+int main(void)
+{
+ return 0;
+}
+""")
+
# for Emacs -> "
@@ -99,7 +120,7 @@ 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']
+ 'd1/d2/f4.h', 'd1/d2/fi.h', 'd1/d2/fj.h', 'f9.h']
for h in headers:
test.write(h, " ")
@@ -180,7 +201,7 @@ test.write("f5b.h", "\n")
# define some helpers:
class DummyEnvironment(collections.UserDict):
- def __init__(self, **kwargs):
+ def __init__(self, **kwargs) -> None:
super().__init__()
self.data.update(kwargs)
self.fs = SCons.Node.FS.FS(test.workpath(''))
@@ -220,16 +241,16 @@ if os.path.normcase('foo') == os.path.normcase('FOO'):
else:
my_normpath = os.path.normpath
-def deps_match(self, deps, headers):
+def deps_match(self, deps, headers) -> None:
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))
+ self.assertTrue(scanned == expect, f"expect {expect} != scanned {scanned}")
# define some tests:
class CScannerTestCase1(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find local files with no CPPPATH"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
@@ -239,7 +260,7 @@ class CScannerTestCase1(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase2(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find a file in a CPPPATH directory"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1")])
s = SCons.Scanner.C.CScanner()
@@ -249,7 +270,7 @@ class CScannerTestCase2(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase3(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in explicit subdirectories, ignore missing file"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1")])
s = SCons.Scanner.C.CScanner()
@@ -259,7 +280,7 @@ class CScannerTestCase3(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase4(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in explicit subdirectories"""
env = DummyEnvironment(CPPPATH=[test.workpath("d1"), test.workpath("d1/d2")])
s = SCons.Scanner.C.CScanner()
@@ -269,7 +290,7 @@ class CScannerTestCase4(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase5(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Make sure files in repositories will get scanned"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
@@ -294,7 +315,7 @@ class CScannerTestCase5(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase6(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find a same-named file in different directories when CPPPATH changes"""
env1 = DummyEnvironment(CPPPATH=[test.workpath("d1")])
env2 = DummyEnvironment(CPPPATH=[test.workpath("d1/d2")])
@@ -309,7 +330,7 @@ class CScannerTestCase6(unittest.TestCase):
deps_match(self, deps2, headers2)
class CScannerTestCase8(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in a subdirectory relative to the current directory"""
env = DummyEnvironment(CPPPATH=["include"])
s = SCons.Scanner.C.CScanner()
@@ -326,11 +347,11 @@ class CScannerTestCase8(unittest.TestCase):
deps_match(self, deps2, headers2)
class CScannerTestCase9(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Generate a warning when we can't find a #included file"""
SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
class TestOut:
- def __call__(self, x):
+ def __call__(self, x) -> None:
self.out = x
to = TestOut()
@@ -351,7 +372,7 @@ class CScannerTestCase9(unittest.TestCase):
test.unlink('fa.h')
class CScannerTestCase10(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in the local directory when the scanned file is elsewhere"""
fs = SCons.Node.FS.FS(test.workpath(''))
fs.chdir(fs.Dir('include'))
@@ -366,7 +387,7 @@ class CScannerTestCase10(unittest.TestCase):
test.unlink('include/fa.cpp')
class CScannerTestCase11(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""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'))
@@ -386,7 +407,7 @@ class CScannerTestCase11(unittest.TestCase):
os.chdir(test.workpath(''))
class CScannerTestCase12(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in VariantDir() directories"""
os.chdir(test.workpath('work'))
fs = SCons.Node.FS.FS(test.workpath('work'))
@@ -408,7 +429,7 @@ class CScannerTestCase12(unittest.TestCase):
os.chdir(test.workpath(''))
class CScannerTestCase13(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""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):
@@ -424,7 +445,7 @@ class CScannerTestCase13(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase14(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files when there's no space between "#include" and the name"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CScanner()
@@ -434,7 +455,7 @@ class CScannerTestCase14(unittest.TestCase):
deps_match(self, deps, headers)
class CScannerTestCase15(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Verify scanner initialization with the suffixes in $CPPSUFFIXES"""
suffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
".h", ".H", ".hxx", ".hpp", ".hh",
@@ -443,11 +464,11 @@ class CScannerTestCase15(unittest.TestCase):
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
+ assert suffix in s.get_skeys(env), f"{suffix} not in skeys"
class CConditionalScannerTestCase1(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find local files with no CPPPATH"""
env = DummyEnvironment(CPPPATH=[])
s = SCons.Scanner.C.CConditionalScanner()
@@ -458,7 +479,7 @@ class CConditionalScannerTestCase1(unittest.TestCase):
class CConditionalScannerTestCase2(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find local files with no CPPPATH based on #ifdef"""
env = DummyEnvironment(CPPPATH=[], CPPDEFINES=["INCLUDE_F2"])
s = SCons.Scanner.C.CConditionalScanner()
@@ -469,7 +490,7 @@ class CConditionalScannerTestCase2(unittest.TestCase):
class CConditionalScannerTestCase3(unittest.TestCase):
- def runTest(self):
+ def runTest(self) -> None:
"""Find files in explicit subdirectories, ignore missing file"""
env = DummyEnvironment(
CPPPATH=[test.workpath("d1")],
@@ -490,42 +511,70 @@ class CConditionalScannerTestCase3(unittest.TestCase):
headers = ['d1/f1.h']
deps_match(self, deps, headers)
+
+class CConditionalScannerTestCase4(unittest.TestCase):
+ def runTest(self) -> None:
+ """Test that dependency is detected if #include uses a macro."""
+
+ with self.subTest("macro defined in the source file"):
+ env = DummyEnvironment()
+ s = SCons.Scanner.C.CConditionalScanner()
+ deps = s(env.File('f9a.c'), env, s.path(env))
+ headers = ['f9.h']
+ deps_match(self, deps, headers)
+
+ with self.subTest("macro defined on the command line"):
+ env = DummyEnvironment(CPPDEFINES='HEADER=\\"f9.h\\"')
+ #env = DummyEnvironment(CPPDEFINES=['HEADER=\\"f9.h\\"'])
+ s = SCons.Scanner.C.CConditionalScanner()
+ deps = s(env.File('f9b.c'), env, s.path(env))
+ headers = ['f9.h']
+ deps_match(self, deps, headers)
+
+
class dictify_CPPDEFINESTestCase(unittest.TestCase):
- def runTest(self):
- """Make sure single-item tuples convert correctly.
+ def runTest(self) -> None:
+ """Make sure CPPDEFINES converts correctly.
- This is a regression test: AppendUnique turns sequences into
- lists of tuples, and dictify could gack on these.
+ Various types and combinations of types could fail if not handled
+ specifically by dictify_CPPDEFINES - this is a regression test.
"""
- 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
+ with self.subTest("tuples in a sequence, including one without value"):
+ env = DummyEnvironment(CPPDEFINES=[("VALUED", 1), ("UNVALUED",)])
+ d = SCons.Scanner.C.dictify_CPPDEFINES(env)
+ expect = {"VALUED": 1, "UNVALUED": None}
+ self.assertEqual(d, expect)
+
+ with self.subTest("tuple-valued define by itself"):
+ env = DummyEnvironment(CPPDEFINES=("STRING", "VALUE"))
+ d = SCons.Scanner.C.dictify_CPPDEFINES(env)
+ expect = {"STRING": "VALUE"}
+ self.assertEqual(d, expect)
+
+ with self.subTest("string-valued define in a sequence"):
+ env = DummyEnvironment(CPPDEFINES=[("STRING=VALUE")])
+ d = SCons.Scanner.C.dictify_CPPDEFINES(env)
+ expect = {"STRING": "VALUE"}
+ self.assertEqual(d, expect)
+
+ with self.subTest("string-valued define by itself"):
+ env = DummyEnvironment(CPPDEFINES="STRING=VALUE")
+ d = SCons.Scanner.C.dictify_CPPDEFINES(env)
+ expect = {"STRING": "VALUE"}
+ self.assertEqual(d, expect)
+
+ from collections import deque
+ with self.subTest("compound CPPDEFINES in internal format"):
+ env = DummyEnvironment(
+ CPPDEFINES=deque([("STRING", "VALUE"), ("UNVALUED",)])
+ )
+ d = SCons.Scanner.C.dictify_CPPDEFINES(env)
+ expect = {"STRING": "VALUE", "UNVALUED": None}
+ self.assertEqual(d, expect)
+
if __name__ == "__main__":
- TestUnit.run(suite())
+ unittest.main()
# Local Variables:
# tab-width:4