2 # Copyright (c) 2001, 2002 Steven Knight
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
27 import SCons.Scanner.C
35 test = TestCmd.TestCmd(workdir = '')
37 os.chdir(test.workpath(''))
39 # create some source files and headers:
41 test.write('f1.cpp',"""
51 test.write('f2.cpp',"""
63 test.write('f3.cpp',"""
66 # \t include "f3-test.h"
70 # \t include <d1/f3-test.h>
74 const char* x = "#include <never.h>"
85 test.subdir('d1', ['d1', 'd2'])
87 headers = ['f1.h','f2.h', 'f3-test.h', 'fi.h', 'fj.h', 'never.h',
88 'd1/f1.h', 'd1/f2.h', 'd1/f3-test.h', 'd1/fi.h', 'd1/fj.h',
89 'd1/d2/f1.h', 'd1/d2/f2.h', 'd1/d2/f3-test.h',
90 'd1/d2/f4.h', 'd1/d2/fi.h', 'd1/d2/fj.h']
99 test.write('f3-test.h',"""
104 test.subdir('include', 'subdir', ['subdir', 'include'])
106 test.write('fa.cpp',"""
116 test.write(['include', 'fa.h'], "\n")
117 test.write(['include', 'fb.h'], "\n")
118 test.write(['subdir', 'include', 'fa.h'], "\n")
119 test.write(['subdir', 'include', 'fb.h'], "\n")
122 test.subdir('repository', ['repository', 'include'])
123 test.subdir('work', ['work', 'src'])
125 test.write(['repository', 'include', 'iii.h'], "\n")
127 test.write(['work', 'src', 'fff.c'], """
136 # define some helpers:
139 def __init__(self, cwd=None):
142 class DummyEnvironment:
143 def __init__(self, listCppPath):
144 self.path = listCppPath
146 def Dictionary(self, *args):
148 return { 'CPPPATH': self.path }
149 elif len(args) == 1 and args[0] == 'CPPPATH':
152 raise KeyError, "Dummy environment only has CPPPATH attribute."
154 def __getitem__(self,key):
155 return self.Dictionary()[key]
157 def __setitem__(self,key,value):
158 self.Dictionary()[key] = value
160 def __delitem__(self,key):
161 del self.Dictionary()[key]
163 my_normpath = os.path.normpath
164 if os.path.normcase('foo') == os.path.normcase('FOO'):
166 my_normpath = os.path.normcase
168 def deps_match(self, deps, headers):
169 scanned = map(my_normpath, map(str, deps))
170 expect = map(my_normpath, headers)
171 self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
173 def make_node(filename, fs=SCons.Node.FS.default_fs):
174 return fs.File(test.workpath(filename))
178 class CScannerTestCase1(unittest.TestCase):
180 env = DummyEnvironment([])
181 s = SCons.Scanner.C.CScan()
182 deps = s.scan(make_node('f1.cpp'), env, DummyTarget())
183 headers = ['f1.h', 'f2.h', 'fi.h']
184 deps_match(self, deps, map(test.workpath, headers))
186 class CScannerTestCase2(unittest.TestCase):
188 env = DummyEnvironment([test.workpath("d1")])
189 s = SCons.Scanner.C.CScan()
190 deps = s.scan(make_node('f1.cpp'), env, DummyTarget())
191 headers = ['d1/f2.h', 'f1.h']
192 deps_match(self, deps, map(test.workpath, headers))
194 class CScannerTestCase3(unittest.TestCase):
196 env = DummyEnvironment([test.workpath("d1")])
197 s = SCons.Scanner.C.CScan()
198 deps = s.scan(make_node('f2.cpp'), env, DummyTarget())
199 headers = ['d1/d2/f1.h', 'd1/f1.h', 'f1.h']
200 deps_match(self, deps, map(test.workpath, headers))
202 class CScannerTestCase4(unittest.TestCase):
204 env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
205 s = SCons.Scanner.C.CScan()
206 deps = s.scan(make_node('f2.cpp'), env, DummyTarget())
207 headers = ['d1/d2/f1.h', 'd1/d2/f4.h', 'd1/f1.h', 'f1.h']
208 deps_match(self, deps, map(test.workpath, headers))
210 class CScannerTestCase5(unittest.TestCase):
212 env = DummyEnvironment([])
213 s = SCons.Scanner.C.CScan()
215 n = make_node('f3.cpp')
218 return s.old_rexists()
219 setattr(n, 'old_rexists', n.rexists)
220 setattr(n, 'rexists', my_rexists)
222 deps = s.scan(n, env, DummyTarget())
224 # Make sure rexists() got called on the file node being
225 # scanned, essential for cooperation with BuildDir functionality.
226 assert n.rexists_called
228 headers = ['d1/f1.h', 'd1/f2.h', 'd1/f3-test.h',
229 'f1.h', 'f2.h', 'f3-test.h', 'fi.h', 'fj.h']
230 deps_match(self, deps, map(test.workpath, headers))
232 class CScannerTestCase6(unittest.TestCase):
234 env1 = DummyEnvironment([test.workpath("d1")])
235 env2 = DummyEnvironment([test.workpath("d1/d2")])
236 env3 = DummyEnvironment([test.workpath("d1/../d1")])
237 s = SCons.Scanner.C.CScan()
238 deps1 = s.scan(make_node('f1.cpp'), env1, DummyTarget())
239 deps2 = s.scan(make_node('f1.cpp'), env2, DummyTarget())
240 headers1 = ['d1/f2.h', 'f1.h']
241 headers2 = ['d1/d2/f2.h', 'f1.h']
242 deps_match(self, deps1, map(test.workpath, headers1))
243 deps_match(self, deps2, map(test.workpath, headers2))
245 class CScannerTestCase8(unittest.TestCase):
247 fs = SCons.Node.FS.FS(test.workpath(''))
248 env = DummyEnvironment(["include"])
249 s = SCons.Scanner.C.CScan(fs = fs)
250 deps1 = s.scan(fs.File('fa.cpp'), env, DummyTarget())
251 fs.chdir(fs.Dir('subdir'))
252 target = DummyTarget(fs.getcwd())
253 fs.chdir(fs.Dir('..'))
254 deps2 = s.scan(fs.File('#fa.cpp'), env, target)
255 headers1 = ['include/fa.h', 'include/fb.h']
256 headers2 = ['subdir/include/fa.h', 'subdir/include/fb.h']
257 deps_match(self, deps1, headers1)
258 deps_match(self, deps2, headers2)
260 class CScannerTestCase9(unittest.TestCase):
262 SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
264 def __call__(self, x):
269 SCons.Warnings._warningOut = to
270 test.write('fa.h','\n')
271 fs = SCons.Node.FS.FS(test.workpath(''))
272 s = SCons.Scanner.C.CScan(fs=fs)
273 env = DummyEnvironment([])
274 deps = s.scan(fs.File('fa.cpp'), env, DummyTarget())
276 # Did we catch the warning associated with not finding fb.h?
279 deps_match(self, deps, [ 'fa.h' ])
282 class CScannerTestCase10(unittest.TestCase):
284 fs = SCons.Node.FS.FS(test.workpath(''))
285 fs.chdir(fs.Dir('include'))
286 s = SCons.Scanner.C.CScan(fs=fs)
287 env = DummyEnvironment([])
288 test.write('include/fa.cpp', test.read('fa.cpp'))
289 deps = s.scan(fs.File('#include/fa.cpp'), env, DummyTarget())
290 deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ])
291 test.unlink('include/fa.cpp')
293 class CScannerTestCase11(unittest.TestCase):
295 os.chdir(test.workpath('work'))
296 fs = SCons.Node.FS.FS(test.workpath('work'))
297 fs.Repository(test.workpath('repository'))
298 s = SCons.Scanner.C.CScan(fs=fs)
299 env = DummyEnvironment(['include'])
300 deps = s.scan(fs.File('src/fff.c'), env, DummyTarget())
301 deps_match(self, deps, [test.workpath('repository/include/iii.h')])
302 os.chdir(test.workpath(''))
305 suite = unittest.TestSuite()
306 suite.addTest(CScannerTestCase1())
307 suite.addTest(CScannerTestCase2())
308 suite.addTest(CScannerTestCase3())
309 suite.addTest(CScannerTestCase4())
310 suite.addTest(CScannerTestCase5())
311 suite.addTest(CScannerTestCase6())
312 suite.addTest(CScannerTestCase8())
313 suite.addTest(CScannerTestCase9())
314 suite.addTest(CScannerTestCase10())
315 suite.addTest(CScannerTestCase11())
318 if __name__ == "__main__":
319 runner = unittest.TextTestRunner()
320 result = runner.run(suite())
321 if not result.wasSuccessful():