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 ['repository', 'src' ])
124 test.subdir('work', ['work', 'src'])
126 test.write(['repository', 'include', 'iii.h'], "\n")
128 test.write(['work', 'src', 'fff.c'], """
138 test.write([ 'work', 'src', 'aaa.c'], """
147 test.write([ 'work', 'src', 'bbb.h'], "\n")
149 test.write([ 'repository', 'src', 'ccc.c'], """
158 test.write([ 'repository', 'src', 'ddd.h'], "\n")
160 # define some helpers:
162 class DummyEnvironment:
163 def __init__(self, listCppPath):
164 self.path = listCppPath
166 def Dictionary(self, *args):
168 return { 'CPPPATH': self.path }
169 elif len(args) == 1 and args[0] == 'CPPPATH':
172 raise KeyError, "Dummy environment only has CPPPATH attribute."
174 def subst(self, arg):
177 def has_key(self, key):
178 return self.Dictionary().has_key(key)
180 def __getitem__(self,key):
181 return self.Dictionary()[key]
183 def __setitem__(self,key,value):
184 self.Dictionary()[key] = value
186 def __delitem__(self,key):
187 del self.Dictionary()[key]
190 my_normpath = os.path.normpath
191 if os.path.normcase('foo') == os.path.normcase('FOO'):
193 my_normpath = os.path.normcase
195 def deps_match(self, deps, headers):
196 scanned = map(my_normpath, map(str, deps))
197 expect = map(my_normpath, headers)
198 self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned))
200 def make_node(filename, fs=SCons.Node.FS.default_fs):
201 return fs.File(test.workpath(filename))
205 class CScannerTestCase1(unittest.TestCase):
207 env = DummyEnvironment([])
208 s = SCons.Scanner.C.CScan()
210 deps = s(make_node('f1.cpp'), env, path)
211 headers = ['f1.h', 'f2.h']
212 deps_match(self, deps, map(test.workpath, headers))
214 class CScannerTestCase2(unittest.TestCase):
216 env = DummyEnvironment([test.workpath("d1")])
217 s = SCons.Scanner.C.CScan()
219 deps = s(make_node('f1.cpp'), env, path)
220 headers = ['d1/f2.h', 'f1.h']
221 deps_match(self, deps, map(test.workpath, headers))
223 class CScannerTestCase3(unittest.TestCase):
225 env = DummyEnvironment([test.workpath("d1")])
226 s = SCons.Scanner.C.CScan()
228 deps = s(make_node('f2.cpp'), env, path)
229 headers = ['d1/d2/f1.h', 'd1/f1.h', 'f1.h']
230 deps_match(self, deps, map(test.workpath, headers))
232 class CScannerTestCase4(unittest.TestCase):
234 env = DummyEnvironment([test.workpath("d1"), test.workpath("d1/d2")])
235 s = SCons.Scanner.C.CScan()
237 deps = s(make_node('f2.cpp'), env, path)
238 headers = ['d1/d2/f1.h', 'd1/d2/f4.h', 'd1/f1.h', 'f1.h']
239 deps_match(self, deps, map(test.workpath, headers))
241 class CScannerTestCase5(unittest.TestCase):
243 env = DummyEnvironment([])
244 s = SCons.Scanner.C.CScan()
247 n = make_node('f3.cpp')
250 return s.old_rexists()
251 setattr(n, 'old_rexists', n.rexists)
252 setattr(n, 'rexists', my_rexists)
254 deps = s(n, env, path)
256 # Make sure rexists() got called on the file node being
257 # scanned, essential for cooperation with BuildDir functionality.
258 assert n.rexists_called
260 headers = ['d1/f1.h', 'd1/f2.h', 'd1/f3-test.h',
261 'f1.h', 'f2.h', 'f3-test.h']
262 deps_match(self, deps, map(test.workpath, headers))
264 class CScannerTestCase6(unittest.TestCase):
266 env1 = DummyEnvironment([test.workpath("d1")])
267 env2 = DummyEnvironment([test.workpath("d1/d2")])
268 s = SCons.Scanner.C.CScan()
271 deps1 = s(make_node('f1.cpp'), env1, path1)
272 deps2 = s(make_node('f1.cpp'), env2, path2)
273 headers1 = ['d1/f2.h', 'f1.h']
274 headers2 = ['d1/d2/f2.h', 'f1.h']
275 deps_match(self, deps1, map(test.workpath, headers1))
276 deps_match(self, deps2, map(test.workpath, headers2))
278 class CScannerTestCase8(unittest.TestCase):
280 fs = SCons.Node.FS.FS(test.workpath(''))
281 env = DummyEnvironment(["include"])
282 s = SCons.Scanner.C.CScan(fs = fs)
284 deps1 = s(fs.File('fa.cpp'), env, path)
285 fs.chdir(fs.Dir('subdir'))
287 fs.chdir(fs.Dir('..'))
288 path = s.path(env, dir)
289 deps2 = s(fs.File('#fa.cpp'), env, path)
290 headers1 = ['include/fa.h', 'include/fb.h']
291 headers2 = ['subdir/include/fa.h', 'subdir/include/fb.h']
292 deps_match(self, deps1, headers1)
293 deps_match(self, deps2, headers2)
295 class CScannerTestCase9(unittest.TestCase):
297 SCons.Warnings.enableWarningClass(SCons.Warnings.DependencyWarning)
299 def __call__(self, x):
304 SCons.Warnings._warningOut = to
305 test.write('fa.h','\n')
306 fs = SCons.Node.FS.FS(test.workpath(''))
307 env = DummyEnvironment([])
308 s = SCons.Scanner.C.CScan(fs=fs)
310 deps = s(fs.File('fa.cpp'), env, path)
312 # Did we catch the warning associated with not finding fb.h?
315 deps_match(self, deps, [ 'fa.h' ])
318 class CScannerTestCase10(unittest.TestCase):
320 fs = SCons.Node.FS.FS(test.workpath(''))
321 fs.chdir(fs.Dir('include'))
322 env = DummyEnvironment([])
323 s = SCons.Scanner.C.CScan(fs=fs)
325 test.write('include/fa.cpp', test.read('fa.cpp'))
326 deps = s(fs.File('#include/fa.cpp'), env, path)
327 fs.chdir(fs.Dir('..'))
328 deps_match(self, deps, [ 'include/fa.h', 'include/fb.h' ])
329 test.unlink('include/fa.cpp')
331 class CScannerTestCase11(unittest.TestCase):
333 os.chdir(test.workpath('work'))
334 fs = SCons.Node.FS.FS(test.workpath('work'))
335 fs.Repository(test.workpath('repository'))
337 # Create a derived file in a directory that does not exist yet.
338 # This was a bug at one time.
339 f1=fs.File('include2/jjj.h')
341 env = DummyEnvironment(['include', 'include2'])
342 s = SCons.Scanner.C.CScan(fs=fs)
344 deps = s(fs.File('src/fff.c'), env, path)
345 deps_match(self, deps, [ test.workpath('repository/include/iii.h'), 'include2/jjj.h' ])
346 os.chdir(test.workpath(''))
348 class CScannerTestCase12(unittest.TestCase):
350 os.chdir(test.workpath('work'))
351 fs = SCons.Node.FS.FS(test.workpath('work'))
352 fs.BuildDir('build1', 'src', 1)
353 fs.BuildDir('build2', 'src', 0)
354 fs.Repository(test.workpath('repository'))
355 env = DummyEnvironment([])
356 s = SCons.Scanner.C.CScan(fs = fs)
358 deps1 = s(fs.File('build1/aaa.c'), env, path)
359 deps_match(self, deps1, [ 'build1/bbb.h' ])
360 deps2 = s(fs.File('build2/aaa.c'), env, path)
361 deps_match(self, deps2, [ 'src/bbb.h' ])
362 deps3 = s(fs.File('build1/ccc.c'), env, path)
363 deps_match(self, deps3, [ 'build1/ddd.h' ])
364 deps4 = s(fs.File('build2/ccc.c'), env, path)
365 deps_match(self, deps4, [ test.workpath('repository/src/ddd.h') ])
366 os.chdir(test.workpath(''))
368 class CScannerTestCase13(unittest.TestCase):
370 class SubstEnvironment(DummyEnvironment):
371 def subst(self, arg, test=test):
372 return test.workpath("d1")
373 env = SubstEnvironment(["blah"])
374 s = SCons.Scanner.C.CScan()
376 deps = s(make_node('f1.cpp'), env, path)
377 headers = ['d1/f2.h', 'f1.h']
378 deps_match(self, deps, map(test.workpath, headers))
382 suite = unittest.TestSuite()
383 suite.addTest(CScannerTestCase1())
384 suite.addTest(CScannerTestCase2())
385 suite.addTest(CScannerTestCase3())
386 suite.addTest(CScannerTestCase4())
387 suite.addTest(CScannerTestCase5())
388 suite.addTest(CScannerTestCase6())
389 suite.addTest(CScannerTestCase8())
390 suite.addTest(CScannerTestCase9())
391 suite.addTest(CScannerTestCase10())
392 suite.addTest(CScannerTestCase11())
393 suite.addTest(CScannerTestCase12())
394 suite.addTest(CScannerTestCase13())
397 if __name__ == "__main__":
398 runner = unittest.TextTestRunner()
399 result = runner.run(suite())
400 if not result.wasSuccessful():