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__"
32 from TestCmd import TestCmd
43 # This will be built-in in 2.3. For now fake it.
53 def __init__(self, node=None):
55 scanner_count = scanner_count + 1
56 self.hash = scanner_count
58 def path(self, env, dir, target=None, source=None):
60 def __call__(self, node, env, path):
64 def select(self, node):
66 def recurse_nodes(self, nodes):
71 self.scanner = Scanner()
72 def Dictionary(self, *args):
74 def autogenerate(self, **kw):
76 def get_scanner(self, skey):
78 def Override(self, overrides):
80 def _update(self, dict):
84 def __call__(self, targets, sources, env, **kw):
86 if kw.get('execute', 1):
89 def show(self, string):
91 def get_contents(self, target, source, env):
93 def genstring(self, target, source, env):
95 def strfunction(self, targets, sources, env):
97 def get_implicit_deps(self, target, source, env):
101 def __init__(self, factory, action=Action()):
102 self.factory = factory
103 self.env = Environment()
106 self.target_scanner = None
107 self.source_scanner = None
109 def targets(self, t):
112 def source_factory(self, name):
113 return self.factory(name)
115 class _tempdirTestCase(unittest.TestCase):
117 self.save_cwd = os.getcwd()
118 self.test = TestCmd(workdir='')
119 # FS doesn't like the cwd to be something other than its root.
120 os.chdir(self.test.workpath(""))
121 self.fs = SCons.Node.FS.FS()
124 os.chdir(self.save_cwd)
126 class VariantDirTestCase(unittest.TestCase):
128 """Test variant dir functionality"""
129 test=TestCmd(workdir='')
131 fs = SCons.Node.FS.FS()
132 f1 = fs.File('build/test1')
133 fs.VariantDir('build', 'src')
134 f2 = fs.File('build/test2')
136 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
137 assert f2.srcnode().path == os.path.normpath('src/test2'), f2.srcnode().path
138 assert d1.srcnode().path == 'src', d1.srcnode().path
140 fs = SCons.Node.FS.FS()
141 f1 = fs.File('build/test1')
142 fs.VariantDir('build', '.')
143 f2 = fs.File('build/test2')
145 assert f1.srcnode().path == 'test1', f1.srcnode().path
146 assert f2.srcnode().path == 'test2', f2.srcnode().path
147 assert d1.srcnode().path == '.', d1.srcnode().path
149 fs = SCons.Node.FS.FS()
150 fs.VariantDir('build/var1', 'src')
151 fs.VariantDir('build/var2', 'src')
152 f1 = fs.File('build/var1/test1')
153 f2 = fs.File('build/var2/test1')
154 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
155 assert f2.srcnode().path == os.path.normpath('src/test1'), f2.srcnode().path
157 fs = SCons.Node.FS.FS()
158 fs.VariantDir('../var1', 'src')
159 fs.VariantDir('../var2', 'src')
160 f1 = fs.File('../var1/test1')
161 f2 = fs.File('../var2/test1')
162 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
163 assert f2.srcnode().path == os.path.normpath('src/test1'), f2.srcnode().path
166 test.subdir('work', ['work', 'src'])
167 test.subdir(['work', 'build'], ['work', 'build', 'var1'])
168 test.subdir(['work', 'build', 'var2'])
169 test.subdir('rep1', ['rep1', 'src'])
170 test.subdir(['rep1', 'build'], ['rep1', 'build', 'var1'])
171 test.subdir(['rep1', 'build', 'var2'])
173 # A source file in the source directory
174 test.write([ 'work', 'src', 'test.in' ], 'test.in')
176 # A source file in a subdir of the source directory
177 test.subdir([ 'work', 'src', 'new_dir' ])
178 test.write([ 'work', 'src', 'new_dir', 'test9.out' ], 'test9.out\n')
180 # A source file in the repository
181 test.write([ 'rep1', 'src', 'test2.in' ], 'test2.in')
183 # Some source files in the variant directory
184 test.write([ 'work', 'build', 'var2', 'test.in' ], 'test.old')
185 test.write([ 'work', 'build', 'var2', 'test2.in' ], 'test2.old')
187 # An old derived file in the variant directories
188 test.write([ 'work', 'build', 'var1', 'test.out' ], 'test.old')
189 test.write([ 'work', 'build', 'var2', 'test.out' ], 'test.old')
191 # And just in case we are weird, a derived file in the source
193 test.write([ 'work', 'src', 'test.out' ], 'test.out.src')
195 # A derived file in the repository
196 test.write([ 'rep1', 'build', 'var1', 'test2.out' ], 'test2.out_rep')
197 test.write([ 'rep1', 'build', 'var2', 'test2.out' ], 'test2.out_rep')
199 os.chdir(test.workpath('work'))
201 fs = SCons.Node.FS.FS(test.workpath('work'))
202 fs.VariantDir('build/var1', 'src', duplicate=0)
203 fs.VariantDir('build/var2', 'src')
204 f1 = fs.File('build/var1/test.in')
205 f1out = fs.File('build/var1/test.out')
207 f1out_2 = fs.File('build/var1/test2.out')
209 f2 = fs.File('build/var2/test.in')
210 f2out = fs.File('build/var2/test.out')
212 f2out_2 = fs.File('build/var2/test2.out')
214 fs.Repository(test.workpath('rep1'))
216 assert f1.srcnode().path == os.path.normpath('src/test.in'),\
218 # str(node) returns source path for duplicate = 0
219 assert str(f1) == os.path.normpath('src/test.in'), str(f1)
220 # Build path does not exist
221 assert not f1.exists()
222 # ...but the actual file is not there...
223 assert not os.path.exists(f1.get_abspath())
224 # And duplicate=0 should also work just like a Repository
226 # rfile() should point to the source path
227 assert f1.rfile().path == os.path.normpath('src/test.in'),\
230 assert f2.srcnode().path == os.path.normpath('src/test.in'),\
232 # str(node) returns build path for duplicate = 1
233 assert str(f2) == os.path.normpath('build/var2/test.in'), str(f2)
236 # ...and exists() should copy the file from src to build path
237 assert test.read(['work', 'build', 'var2', 'test.in']) == 'test.in',\
238 test.read(['work', 'build', 'var2', 'test.in'])
239 # Since exists() is true, so should rexists() be
242 f3 = fs.File('build/var1/test2.in')
243 f4 = fs.File('build/var2/test2.in')
245 assert f3.srcnode().path == os.path.normpath('src/test2.in'),\
247 # str(node) returns source path for duplicate = 0
248 assert str(f3) == os.path.normpath('src/test2.in'), str(f3)
249 # Build path does not exist
250 assert not f3.exists()
251 # Source path does not either
252 assert not f3.srcnode().exists()
253 # But we do have a file in the Repository
255 # rfile() should point to the source path
256 assert f3.rfile().path == os.path.normpath(test.workpath('rep1/src/test2.in')),\
259 assert f4.srcnode().path == os.path.normpath('src/test2.in'),\
261 # str(node) returns build path for duplicate = 1
262 assert str(f4) == os.path.normpath('build/var2/test2.in'), str(f4)
263 # Build path should exist
265 # ...and copy over the file into the local build path
266 assert test.read(['work', 'build', 'var2', 'test2.in']) == 'test2.in'
267 # should exist in repository, since exists() is true
269 # rfile() should point to ourselves
270 assert f4.rfile().path == os.path.normpath('build/var2/test2.in'),\
273 f5 = fs.File('build/var1/test.out')
274 f6 = fs.File('build/var2/test.out')
277 # We should not copy the file from the source dir, since this is
279 assert test.read(['work', 'build', 'var1', 'test.out']) == 'test.old'
282 # We should not copy the file from the source dir, since this is
284 assert test.read(['work', 'build', 'var2', 'test.out']) == 'test.old'
286 f7 = fs.File('build/var1/test2.out')
287 f8 = fs.File('build/var2/test2.out')
289 assert not f7.exists()
292 expect = os.path.normpath(test.workpath('rep1/build/var1/test2.out'))
293 assert r == expect, (repr(r), repr(expect))
295 assert not f8.exists()
297 assert f8.rfile().path == os.path.normpath(test.workpath('rep1/build/var2/test2.out')),\
300 # Verify the Mkdir and Link actions are called
301 d9 = fs.Dir('build/var2/new_dir')
302 f9 = fs.File('build/var2/new_dir/test9.out')
304 class MkdirAction(Action):
305 def __init__(self, dir_made):
306 self.dir_made = dir_made
307 def __call__(self, target, source, env):
308 self.dir_made.extend(target)
310 save_Link = SCons.Node.FS.Link
312 def link_func(target, source, env, link_made=link_made):
313 link_made.append(target)
314 SCons.Node.FS.Link = link_func
318 d9.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
321 expect = os.path.join('build', 'var2', 'new_dir')
322 assert dir_made[0].path == expect, dir_made[0].path
323 expect = os.path.join('build', 'var2', 'new_dir', 'test9.out')
324 assert link_made[0].path == expect, link_made[0].path
327 SCons.Node.FS.Link = save_Link
329 # Test for an interesting pathological case...we have a source
330 # file in a build path, but not in a source path. This can
331 # happen if you switch from duplicate=1 to duplicate=0, then
332 # delete a source file. At one time, this would cause exists()
333 # to return a 1 but get_contents() to throw.
334 test.write([ 'work', 'build', 'var1', 'asourcefile' ], 'stuff')
335 f10 = fs.File('build/var1/asourcefile')
337 assert f10.get_contents() == 'stuff', f10.get_contents()
339 f11 = fs.File('src/file11')
340 t, m = f11.alter_targets()
341 bdt = map(lambda n: n.path, t)
342 var1_file11 = os.path.normpath('build/var1/file11')
343 var2_file11 = os.path.normpath('build/var2/file11')
344 assert bdt == [var1_file11, var2_file11], bdt
346 f12 = fs.File('src/file12')
348 bdt, m = f12.alter_targets()
349 assert bdt == [], map(lambda n: n.path, bdt)
351 d13 = fs.Dir('src/new_dir')
352 t, m = d13.alter_targets()
353 bdt = map(lambda n: n.path, t)
354 var1_new_dir = os.path.normpath('build/var1/new_dir')
355 var2_new_dir = os.path.normpath('build/var2/new_dir')
356 assert bdt == [var1_new_dir, var2_new_dir], bdt
358 # Test that an IOError trying to Link a src file
359 # into a VariantDir ends up throwing a StopError.
360 fIO = fs.File("build/var2/IOError")
362 save_Link = SCons.Node.FS.Link
363 def Link_IOError(target, source, env):
364 raise IOError, (17, "Link_IOError")
365 SCons.Node.FS.Link = SCons.Action.Action(Link_IOError, None)
367 test.write(['work', 'src', 'IOError'], "work/src/IOError\n")
373 except SCons.Errors.StopError:
375 assert exc_caught, "Should have caught a StopError"
378 SCons.Node.FS.Link = save_Link
380 # Test to see if Link() works...
381 test.subdir('src','build')
382 test.write('src/foo', 'src/foo\n')
383 os.chmod(test.workpath('src/foo'), stat.S_IRUSR)
384 SCons.Node.FS.Link(fs.File(test.workpath('build/foo')),
385 fs.File(test.workpath('src/foo')),
387 os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE)
388 st=os.stat(test.workpath('build/foo'))
389 assert (stat.S_IMODE(st[stat.ST_MODE]) & stat.S_IWRITE), \
390 stat.S_IMODE(st[stat.ST_MODE])
392 # This used to generate a UserError when we forbid the source
393 # directory from being outside the top-level SConstruct dir.
394 fs = SCons.Node.FS.FS()
395 fs.VariantDir('build', '/test/foo')
400 fs = SCons.Node.FS.FS()
401 fs.VariantDir('build', 'build/src')
402 except SCons.Errors.UserError:
404 assert exc_caught, "Should have caught a UserError."
406 test.unlink( "src/foo" )
407 test.unlink( "build/foo" )
409 fs = SCons.Node.FS.FS()
410 fs.VariantDir('build', 'src1')
412 # Calling the same VariantDir twice should work fine.
413 fs.VariantDir('build', 'src1')
415 # Trying to move a variant dir to a second source dir
418 fs.VariantDir('build', 'src2')
419 except SCons.Errors.UserError:
422 assert 0, "Should have caught a UserError."
424 # Test against a former bug. Make sure we can get a repository
425 # path for the variant directory itself!
426 fs=SCons.Node.FS.FS(test.workpath('work'))
428 fs.VariantDir('build/var3', 'src', duplicate=0)
429 d1 = fs.Dir('build/var3')
431 assert r == d1, "%s != %s" % (r, d1)
433 # verify the link creation attempts in file_link()
434 class LinkSimulator :
435 """A class to intercept os.[sym]link() calls and track them."""
437 def __init__( self, duplicate, link, symlink, copy ) :
438 self.duplicate = duplicate
440 self.have['hard'] = link
441 self.have['soft'] = symlink
442 self.have['copy'] = copy
444 self.links_to_be_called = []
445 for link in string.split(self.duplicate, '-'):
447 self.links_to_be_called.append(link)
449 def link_fail( self , src , dest ) :
450 next_link = self.links_to_be_called.pop(0)
451 assert next_link == "hard", \
452 "Wrong link order: expected %s to be called "\
453 "instead of hard" % next_link
454 raise OSError( "Simulating hard link creation error." )
456 def symlink_fail( self , src , dest ) :
457 next_link = self.links_to_be_called.pop(0)
458 assert next_link == "soft", \
459 "Wrong link order: expected %s to be called "\
460 "instead of soft" % next_link
461 raise OSError( "Simulating symlink creation error." )
463 def copy( self , src , dest ) :
464 next_link = self.links_to_be_called.pop(0)
465 assert next_link == "copy", \
466 "Wrong link order: expected %s to be called "\
467 "instead of copy" % next_link
468 # copy succeeds, but use the real copy
469 self.have['copy'](src, dest)
470 # end class LinkSimulator
473 SCons.Node.FS.set_duplicate("no-link-order")
474 assert 0, "Expected exception when passing an invalid duplicate to set_duplicate"
475 except SCons.Errors.InternalError:
478 for duplicate in SCons.Node.FS.Valid_Duplicates:
479 # save the real functions for later restoration
482 except AttributeError:
485 real_symlink = os.symlink
486 except AttributeError:
488 real_copy = shutil.copy2
490 simulator = LinkSimulator(duplicate, real_link, real_symlink, real_copy)
492 # override the real functions with our simulation
493 os.link = simulator.link_fail
494 os.symlink = simulator.symlink_fail
495 shutil.copy2 = simulator.copy
499 SCons.Node.FS.set_duplicate(duplicate)
501 src_foo = test.workpath('src', 'foo')
502 build_foo = test.workpath('build', 'foo')
504 test.write(src_foo, 'src/foo\n')
505 os.chmod(src_foo, stat.S_IRUSR)
507 SCons.Node.FS.Link(fs.File(build_foo),
511 os.chmod(src_foo, stat.S_IRUSR | stat.S_IWRITE)
513 test.unlink(build_foo)
516 # restore the real functions
522 os.symlink = real_symlink
524 delattr(os, 'symlink')
525 shutil.copy2 = real_copy
527 # Test VariantDir "reflection," where a same-named subdirectory
528 # exists underneath a variant_dir.
529 fs = SCons.Node.FS.FS()
530 fs.VariantDir('work/src/b1/b2', 'work/src')
537 'work/src/b1/b2/b1/b2',
538 'work/src/b1/b2/b1/b2/b1',
539 'work/src/b1/b2/b1/b2/b1/b2',
543 'work/src/b1/b2' : 'work/src',
544 'work/src/b1/b2/f' : 'work/src/f',
545 'work/src/b1/b2/b1' : 'work/src/b1/',
546 'work/src/b1/b2/b1/f' : 'work/src/b1/f',
547 'work/src/b1/b2/b1/b2' : 'work/src/b1/b2',
548 'work/src/b1/b2/b1/b2/f' : 'work/src/b1/b2/f',
549 'work/src/b1/b2/b1/b2/b1' : 'work/src/b1/b2/b1',
550 'work/src/b1/b2/b1/b2/b1/f' : 'work/src/b1/b2/b1/f',
551 'work/src/b1/b2/b1/b2/b1/b2' : 'work/src/b1/b2/b1/b2',
552 'work/src/b1/b2/b1/b2/b1/b2/f' : 'work/src/b1/b2/b1/b2/f',
556 'work/src' : 'work/src/b1/b2',
557 'work/src/f' : 'work/src/b1/b2/f',
558 'work/src/b1' : 'work/src/b1/b2/b1',
559 'work/src/b1/f' : 'work/src/b1/b2/b1/f',
567 fnode = fs.File(dir + '/f')
569 dp = dnode.srcnode().path
570 expect = os.path.normpath(srcnode_map.get(dir, dir))
572 print "Dir `%s' srcnode() `%s' != expected `%s'" % (dir, dp, expect)
575 fp = fnode.srcnode().path
576 expect = os.path.normpath(srcnode_map.get(f, f))
578 print "File `%s' srcnode() `%s' != expected `%s'" % (f, fp, expect)
584 fnode = fs.File(dir + '/f')
586 t, m = dnode.alter_targets()
588 expect = os.path.normpath(alter_map.get(dir, dir))
590 print "Dir `%s' alter_targets() `%s' != expected `%s'" % (dir, tp, expect)
593 t, m = fnode.alter_targets()
595 expect = os.path.normpath(alter_map.get(f, f))
597 print "File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect)
602 class BaseTestCase(_tempdirTestCase):
604 """Test the Base.stat() method"""
606 test.write("e1", "e1\n")
607 fs = SCons.Node.FS.FS()
611 assert not s is None, s
617 def test_getmtime(self):
618 """Test the Base.getmtime() method"""
620 test.write("file", "file\n")
621 fs = SCons.Node.FS.FS()
623 file = fs.Entry('file')
624 assert file.getmtime()
626 file = fs.Entry('nonexistent')
627 mtime = file.getmtime()
628 assert mtime is None, mtime
630 def test_getsize(self):
631 """Test the Base.getsize() method"""
633 test.write("file", "file\n")
634 fs = SCons.Node.FS.FS()
636 file = fs.Entry('file')
637 size = file.getsize()
638 assert size == 5, size
640 file = fs.Entry('nonexistent')
641 size = file.getsize()
642 assert size is None, size
644 def test_isdir(self):
645 """Test the Base.isdir() method"""
648 test.write("file", "file\n")
649 fs = SCons.Node.FS.FS()
651 dir = fs.Entry('dir')
654 file = fs.Entry('file')
655 assert not file.isdir()
657 nonexistent = fs.Entry('nonexistent')
658 assert not nonexistent.isdir()
660 def test_isfile(self):
661 """Test the Base.isfile() method"""
664 test.write("file", "file\n")
665 fs = SCons.Node.FS.FS()
667 dir = fs.Entry('dir')
668 assert not dir.isfile()
670 file = fs.Entry('file')
673 nonexistent = fs.Entry('nonexistent')
674 assert not nonexistent.isfile()
676 if hasattr(os, 'symlink'):
677 def test_islink(self):
678 """Test the Base.islink() method"""
681 test.write("file", "file\n")
682 test.symlink("symlink", "symlink")
683 fs = SCons.Node.FS.FS()
685 dir = fs.Entry('dir')
686 assert not dir.islink()
688 file = fs.Entry('file')
689 assert not file.islink()
691 symlink = fs.Entry('symlink')
692 assert symlink.islink()
694 nonexistent = fs.Entry('nonexistent')
695 assert not nonexistent.islink()
697 class DirNodeInfoTestCase(_tempdirTestCase):
698 def test___init__(self):
699 """Test DirNodeInfo initialization"""
700 ddd = self.fs.Dir('ddd')
701 ni = SCons.Node.FS.DirNodeInfo(ddd)
703 class DirBuildInfoTestCase(_tempdirTestCase):
704 def test___init__(self):
705 """Test DirBuildInfo initialization"""
706 ddd = self.fs.Dir('ddd')
707 bi = SCons.Node.FS.DirBuildInfo(ddd)
709 class FileNodeInfoTestCase(_tempdirTestCase):
710 def test___init__(self):
711 """Test FileNodeInfo initialization"""
712 fff = self.fs.File('fff')
713 ni = SCons.Node.FS.FileNodeInfo(fff)
714 assert isinstance(ni, SCons.Node.FS.FileNodeInfo)
716 def test_update(self):
717 """Test updating a File.NodeInfo with on-disk information"""
719 fff = self.fs.File('fff')
721 ni = SCons.Node.FS.FileNodeInfo(fff)
723 test.write('fff', "fff\n")
729 assert hasattr(ni, 'timestamp')
730 assert hasattr(ni, 'size')
737 mtime = st[stat.ST_MTIME]
738 assert ni.timestamp == mtime, (ni.timestamp, mtime)
739 size = st[stat.ST_SIZE]
740 assert ni.size == size, (ni.size, size)
745 test.write('fff', "fff longer size, different time stamp\n")
749 mtime = st[stat.ST_MTIME]
750 assert ni.timestamp != mtime, (ni.timestamp, mtime)
751 size = st[stat.ST_SIZE]
752 assert ni.size != size, (ni.size, size)
759 #mtime = st[stat.ST_MTIME]
760 #assert ni.timestamp == mtime, (ni.timestamp, mtime)
761 #size = st[stat.ST_SIZE]
762 #assert ni.size == size, (ni.size, size)
764 class FileBuildInfoTestCase(_tempdirTestCase):
765 def test___init__(self):
766 """Test File.BuildInfo initialization"""
767 fff = self.fs.File('fff')
768 bi = SCons.Node.FS.FileBuildInfo(fff)
771 def test_convert_to_sconsign(self):
772 """Test converting to .sconsign file format"""
773 fff = self.fs.File('fff')
774 bi = SCons.Node.FS.FileBuildInfo(fff)
775 assert hasattr(bi, 'convert_to_sconsign')
777 def test_convert_from_sconsign(self):
778 """Test converting from .sconsign file format"""
779 fff = self.fs.File('fff')
780 bi = SCons.Node.FS.FileBuildInfo(fff)
781 assert hasattr(bi, 'convert_from_sconsign')
783 def test_prepare_dependencies(self):
784 """Test that we have a prepare_dependencies() method"""
785 fff = self.fs.File('fff')
786 bi = SCons.Node.FS.FileBuildInfo(fff)
787 bi.prepare_dependencies()
789 def test_format(self):
790 """Test the format() method"""
791 f1 = self.fs.File('f1')
792 bi1 = SCons.Node.FS.FileBuildInfo(f1)
794 s1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n1'))
796 d1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n2'))
798 i1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n3'))
801 bi1.bsources = [self.fs.File('s1')]
802 bi1.bdepends = [self.fs.File('d1')]
803 bi1.bimplicit = [self.fs.File('i1')]
804 bi1.bsourcesigs = [s1sig]
805 bi1.bdependsigs = [d1sig]
806 bi1.bimplicitsigs = [i1sig]
808 bi1.bactsig = 'actionsig'
814 'actionsig [action]',
817 expect = string.join(expect_lines, '\n')
818 format = bi1.format()
819 assert format == expect, (repr(expect), repr(format))
821 class FSTestCase(_tempdirTestCase):
822 def test_runTest(self):
823 """Test FS (file system) Node operations
825 This test case handles all of the file system node
826 tests in one environment, so we don't have to set up a
827 complicated directory structure for each test individually.
831 test.subdir('sub', ['sub', 'dir'])
833 wp = test.workpath('')
834 sub = test.workpath('sub', '')
835 sub_dir = test.workpath('sub', 'dir', '')
836 sub_dir_foo = test.workpath('sub', 'dir', 'foo', '')
837 sub_dir_foo_bar = test.workpath('sub', 'dir', 'foo', 'bar', '')
838 sub_foo = test.workpath('sub', 'foo', '')
842 fs = SCons.Node.FS.FS()
845 assert isinstance(e1, SCons.Node.FS.Entry)
848 assert isinstance(d1, SCons.Node.FS.Dir)
849 assert d1.cwd is d1, d1
851 f1 = fs.File('f1', directory = d1)
852 assert isinstance(f1, SCons.Node.FS.File)
854 d1_f1 = os.path.join('d1', 'f1')
855 assert f1.path == d1_f1, "f1.path %s != %s" % (f1.path, d1_f1)
856 assert str(f1) == d1_f1, "str(f1) %s != %s" % (str(f1), d1_f1)
859 assert isinstance(x1, SCons.Node.FS.File)
860 assert str(x1) == os.path.join('d1', 'x1')
863 assert isinstance(x2, SCons.Node.FS.Dir)
864 assert str(x2) == os.path.join('d1', 'x2')
867 assert isinstance(x3, SCons.Node.FS.Entry)
868 assert str(x3) == os.path.join('d1', 'x3')
870 assert d1.File(x1) == x1
871 assert d1.Dir(x2) == x2
872 assert d1.Entry(x3) == x3
877 assert str(x4) == os.path.join('d1', 'x4')
880 assert str(x5) == os.path.join('d1', 'x5')
883 assert str(x6) == os.path.join('d1', 'x6')
885 assert str(x7) == os.path.join('d1', 'x7')
887 assert x1.File(x4) == x4
888 assert x1.Dir(x5) == x5
889 assert x1.Entry(x6) == x6
890 assert x1.Entry(x7) == x7
892 assert x1.Entry(x5) == x5
898 raise Exception, "did not catch expected TypeError"
900 assert x1.Entry(x4) == x4
906 raise Exception, "did not catch expected TypeError"
909 assert isinstance(x6, SCons.Node.FS.File)
912 assert isinstance(x7, SCons.Node.FS.Dir)
918 drive, path = os.path.splitdrive(os.getcwd())
920 def _do_Dir_test(lpath, path_, abspath_, up_path_, sep, fileSys=fs, drive=drive):
921 dir = fileSys.Dir(string.replace(lpath, '/', sep))
924 path_ = string.replace(path_, '/', os.sep)
925 abspath_ = string.replace(abspath_, '/', os.sep)
926 up_path_ = string.replace(up_path_, '/', os.sep)
928 def strip_slash(p, drive=drive):
929 if p[-1] == os.sep and len(p) > 1:
934 path = strip_slash(path_)
935 abspath = strip_slash(abspath_)
936 up_path = strip_slash(up_path_)
937 name = string.split(abspath, os.sep)[-1]
939 assert dir.name == name, \
940 "dir.name %s != expected name %s" % \
942 assert dir.path == path, \
943 "dir.path %s != expected path %s" % \
945 assert str(dir) == path, \
946 "str(dir) %s != expected path %s" % \
948 assert dir.get_abspath() == abspath, \
949 "dir.abspath %s != expected absolute path %s" % \
950 (dir.get_abspath(), abspath)
951 assert dir.up().path == up_path, \
952 "dir.up().path %s != expected parent path %s" % \
953 (dir.up().path, up_path)
957 def Dir_test(lpath, path_, abspath_, up_path_, sep=sep, func=_do_Dir_test):
958 return func(lpath, path_, abspath_, up_path_, sep)
960 Dir_test('', './', sub_dir, sub)
961 Dir_test('foo', 'foo/', sub_dir_foo, './')
962 Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
963 Dir_test('/foo', '/foo/', '/foo/', '/')
964 Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/')
965 Dir_test('..', sub, sub, wp)
966 Dir_test('foo/..', './', sub_dir, sub)
967 Dir_test('../foo', sub_foo, sub_foo, sub)
968 Dir_test('.', './', sub_dir, sub)
969 Dir_test('./.', './', sub_dir, sub)
970 Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
971 Dir_test('#../foo', sub_foo, sub_foo, sub)
972 Dir_test('#/../foo', sub_foo, sub_foo, sub)
973 Dir_test('#foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
974 Dir_test('#/foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
975 Dir_test('#', './', sub_dir, sub)
978 f2 = fs.File(string.join(['f1', 'f2'], sep), directory = d1)
980 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
986 dir = fs.Dir(string.join(['d1', 'f1'], sep))
988 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
996 assert str(x) == ("Tried to lookup Dir '%s' as a File." %
1001 # Test that just specifying the drive works to identify
1002 # its root directory.
1003 p = os.path.abspath(test.workpath('root_file'))
1004 drive, path = os.path.splitdrive(p)
1006 # The assert below probably isn't correct for the general
1007 # case, but it works for Windows, which covers a lot
1010 assert str(dir) == drive + os.sep, str(dir)
1012 # Make sure that lookups with and without the drive are
1014 p = os.path.abspath(test.workpath('some/file'))
1015 drive, path = os.path.splitdrive(p)
1019 assert e1 is e2, (e1, e2)
1020 assert str(e1) is str(e2), (str(e1), str(e2))
1022 # Test for a bug in 0.04 that did not like looking up
1023 # dirs with a trailing slash on Windows.
1025 assert d.path == '.', d.abspath
1027 assert d.path == 'foo', d.abspath
1029 # Test for sub-classing of node building.
1034 d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
1035 d1.builder_set(Builder(fs.File))
1037 d1.env_set(Environment())
1043 f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
1044 f1.builder_set(Builder(fs.File))
1046 f1.env_set(Environment())
1050 def match(path, expect):
1051 expect = string.replace(expect, '/', os.sep)
1052 assert path == expect, "path %s != expected %s" % (path, expect)
1055 assert e1.__class__.__name__ == 'Dir'
1056 match(e1.path, "d1")
1057 match(e1.dir.path, ".")
1059 e2 = fs.Entry("d1/f1")
1060 assert e2.__class__.__name__ == 'File'
1061 match(e2.path, "d1/f1")
1062 match(e2.dir.path, "d1")
1065 assert e3.__class__.__name__ == 'Entry'
1066 match(e3.path, "e3")
1067 match(e3.dir.path, ".")
1069 e4 = fs.Entry("d1/e4")
1070 assert e4.__class__.__name__ == 'Entry'
1071 match(e4.path, "d1/e4")
1072 match(e4.dir.path, "d1")
1074 e5 = fs.Entry("e3/e5")
1075 assert e3.__class__.__name__ == 'Dir'
1076 match(e3.path, "e3")
1077 match(e3.dir.path, ".")
1078 assert e5.__class__.__name__ == 'Entry'
1079 match(e5.path, "e3/e5")
1080 match(e5.dir.path, "e3")
1082 e6 = fs.Dir("d1/e4")
1084 assert e4.__class__.__name__ == 'Dir'
1085 match(e4.path, "d1/e4")
1086 match(e4.dir.path, "d1")
1088 e7 = fs.File("e3/e5")
1090 assert e5.__class__.__name__ == 'File'
1091 match(e5.path, "e3/e5")
1092 match(e5.dir.path, "e3")
1094 fs.chdir(fs.Dir('subdir'))
1095 f11 = fs.File("f11")
1096 match(f11.path, "subdir/f11")
1098 e13 = fs.Entry("subdir/e13")
1099 match(e13.path, "subdir/subdir/e13")
1100 fs.chdir(fs.Dir('..'))
1103 f1.builder_set(Builder(fs.File))
1104 f1.env_set(Environment())
1105 xyz = fs.File("xyz")
1106 f1.builder.target_scanner = Scanner(xyz)
1109 assert f1.implicit[0].path == "xyz"
1112 assert f1.implicit == []
1115 assert f1.implicit[0].path == "xyz"
1117 # Test underlying scanning functionality in get_found_includes()
1119 f12 = fs.File("f12")
1122 deps = f12.get_found_includes(env, None, t1)
1123 assert deps == [], deps
1125 class MyScanner(Scanner):
1127 def __call__(self, node, env, path):
1128 self.call_count = self.call_count + 1
1129 return Scanner.__call__(self, node, env, path)
1132 deps = f12.get_found_includes(env, s, t1)
1133 assert deps == [xyz], deps
1134 assert s.call_count == 1, s.call_count
1138 deps = f12.get_found_includes(env, s, t1)
1139 assert deps == [xyz], deps
1140 assert s.call_count == 2, s.call_count
1142 env2 = Environment()
1144 deps = f12.get_found_includes(env2, s, t1)
1145 assert deps == [xyz], deps
1146 assert s.call_count == 3, s.call_count
1150 # Make sure we can scan this file even if the target isn't
1151 # a file that has a scanner (it might be an Alias, e.g.).
1155 deps = f12.get_found_includes(env, s, DummyNode())
1156 assert deps == [xyz], deps
1158 # Test building a file whose directory is not there yet...
1159 f1 = fs.File(test.workpath("foo/bar/baz/ack"))
1160 assert not f1.dir.exists()
1163 assert f1.dir.exists()
1168 fs = SCons.Node.FS.FS()
1169 assert str(fs.getcwd()) == ".", str(fs.getcwd())
1170 fs.chdir(fs.Dir('subdir'))
1171 # The cwd's path is always "."
1172 assert str(fs.getcwd()) == ".", str(fs.getcwd())
1173 assert fs.getcwd().path == 'subdir', fs.getcwd().path
1174 fs.chdir(fs.Dir('../..'))
1175 assert fs.getcwd().path == test.workdir, fs.getcwd().path
1177 f1 = fs.File(test.workpath("do_i_exist"))
1178 assert not f1.exists()
1179 test.write("do_i_exist","\n")
1180 assert not f1.exists(), "exists() call not cached"
1182 assert f1.exists(), "exists() call caching not reset"
1183 test.unlink("do_i_exist")
1186 assert not f1.exists()
1188 # For some reason, in Windows, the \x1a character terminates
1189 # the reading of files in text mode. This tests that
1190 # get_contents() returns the binary contents.
1191 test.write("binary_file", "Foo\x1aBar")
1192 f1 = fs.File(test.workpath("binary_file"))
1193 assert f1.get_contents() == "Foo\x1aBar", f1.get_contents()
1195 def nonexistent(method, s):
1197 x = method(s, create = 0)
1198 except SCons.Errors.UserError:
1201 raise Exception, "did not catch expected UserError"
1203 nonexistent(fs.Entry, 'nonexistent')
1204 nonexistent(fs.Entry, 'nonexistent/foo')
1206 nonexistent(fs.File, 'nonexistent')
1207 nonexistent(fs.File, 'nonexistent/foo')
1209 nonexistent(fs.Dir, 'nonexistent')
1210 nonexistent(fs.Dir, 'nonexistent/foo')
1212 test.write("preserve_me", "\n")
1213 assert os.path.exists(test.workpath("preserve_me"))
1214 f1 = fs.File(test.workpath("preserve_me"))
1216 assert os.path.exists(test.workpath("preserve_me"))
1218 test.write("remove_me", "\n")
1219 assert os.path.exists(test.workpath("remove_me"))
1220 f1 = fs.File(test.workpath("remove_me"))
1221 f1.builder = Builder(fs.File)
1222 f1.env_set(Environment())
1224 assert not os.path.exists(test.workpath("remove_me"))
1226 e = fs.Entry('e_local')
1227 assert not hasattr(e, '_local')
1229 assert e._local == 1
1230 f = fs.File('e_local')
1231 assert f._local == 1
1232 f = fs.File('f_local')
1233 assert f._local == 0
1235 #XXX test_is_up_to_date() for directories
1237 #XXX test_sconsign() for directories
1239 #XXX test_set_signature() for directories
1241 #XXX test_build() for directories
1245 # test Entry.get_contents()
1246 e = fs.Entry('does_not_exist')
1247 c = e.get_contents()
1249 assert e.__class__ == SCons.Node.FS.Entry
1251 test.write("file", "file\n")
1253 e = fs.Entry('file')
1254 c = e.get_contents()
1255 assert c == "file\n", c
1256 assert e.__class__ == SCons.Node.FS.File
1262 c = e.get_contents()
1264 assert e.__class__ == SCons.Node.FS.Dir
1266 if hasattr(os, 'symlink'):
1267 os.symlink('nonexistent', test.workpath('dangling_symlink'))
1268 e = fs.Entry('dangling_symlink')
1269 c = e.get_contents()
1270 assert e.__class__ == SCons.Node.FS.Entry, e.__class__
1273 test.write("tstamp", "tstamp\n")
1275 # Okay, *this* manipulation accomodates Windows FAT file systems
1276 # that only have two-second granularity on their timestamps.
1277 # We round down the current time to the nearest even integer
1278 # value, subtract two to make sure the timestamp is not "now,"
1279 # and then convert it back to a float.
1280 tstamp = float(int(time.time() / 2) * 2) - 2
1281 os.utime(test.workpath("tstamp"), (tstamp - 2.0, tstamp))
1282 f = fs.File("tstamp")
1283 t = f.get_timestamp()
1284 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
1286 test.unlink("tstamp")
1288 test.subdir('tdir1')
1290 t = d.get_timestamp()
1291 assert t == 0, "expected 0, got %s" % str(t)
1293 test.subdir('tdir2')
1294 f1 = test.workpath('tdir2', 'file1')
1295 f2 = test.workpath('tdir2', 'file2')
1296 test.write(f1, 'file1\n')
1297 test.write(f2, 'file2\n')
1298 current_time = float(int(time.time() / 2) * 2)
1299 t1 = current_time - 4.0
1300 t2 = current_time - 2.0
1301 os.utime(f1, (t1 - 2.0, t1))
1302 os.utime(f2, (t2 - 2.0, t2))
1306 t = d.get_timestamp()
1307 assert t == t2, "expected %f, got %f" % (t2, t)
1309 skey = fs.Entry('eee.x').scanner_key()
1310 assert skey == '.x', skey
1311 skey = fs.Entry('eee.xyz').scanner_key()
1312 assert skey == '.xyz', skey
1314 skey = fs.File('fff.x').scanner_key()
1315 assert skey == '.x', skey
1316 skey = fs.File('fff.xyz').scanner_key()
1317 assert skey == '.xyz', skey
1319 skey = fs.Dir('ddd.x').scanner_key()
1320 assert skey is None, skey
1322 test.write("i_am_not_a_directory", "\n")
1326 fs.Dir(test.workpath("i_am_not_a_directory"))
1329 assert exc_caught, "Should have caught a TypeError"
1331 test.unlink("i_am_not_a_directory")
1338 assert exc_caught, "Should have caught a TypeError"
1340 # XXX test_is_up_to_date()
1346 f = fs.File('does_not_exist')
1350 test.write('exists', "exists\n")
1351 f = fs.File('exists')
1354 assert not os.path.exists(test.workpath('exists')), "exists was not removed"
1356 symlink = test.workpath('symlink')
1358 os.symlink(test.workpath('does_not_exist'), symlink)
1359 assert os.path.islink(symlink)
1360 f = fs.File('symlink')
1363 assert not os.path.islink(symlink), "symlink was not removed"
1364 except AttributeError:
1367 test.write('can_not_remove', "can_not_remove\n")
1368 test.writable(test.workpath('.'), 0)
1369 fp = open(test.workpath('can_not_remove'))
1371 f = fs.File('can_not_remove')
1380 assert exc_caught, "Should have caught an OSError, r = " + str(r)
1382 f = fs.Entry('foo/bar/baz')
1383 assert f.for_signature() == 'baz', f.for_signature()
1384 assert f.get_string(0) == os.path.normpath('foo/bar/baz'), \
1386 assert f.get_string(1) == 'baz', f.get_string(1)
1388 def test_drive_letters(self):
1389 """Test drive-letter look-ups"""
1393 test.subdir('sub', ['sub', 'dir'])
1395 def drive_workpath(drive, dirs, test=test):
1396 x = apply(test.workpath, dirs)
1397 drive, path = os.path.splitdrive(x)
1400 wp = drive_workpath('X:', [''])
1402 if wp[-1] in (os.sep, '/'):
1403 tmp = os.path.split(wp[:-1])[0]
1405 tmp = os.path.split(wp)[0]
1407 parent_tmp = os.path.split(tmp)[0]
1408 if parent_tmp == 'X:':
1409 parent_tmp = 'X:' + os.sep
1411 tmp_foo = os.path.join(tmp, 'foo')
1413 foo = drive_workpath('X:', ['foo'])
1414 foo_bar = drive_workpath('X:', ['foo', 'bar'])
1415 sub = drive_workpath('X:', ['sub', ''])
1416 sub_dir = drive_workpath('X:', ['sub', 'dir', ''])
1417 sub_dir_foo = drive_workpath('X:', ['sub', 'dir', 'foo', ''])
1418 sub_dir_foo_bar = drive_workpath('X:', ['sub', 'dir', 'foo', 'bar', ''])
1419 sub_foo = drive_workpath('X:', ['sub', 'foo', ''])
1421 fs = SCons.Node.FS.FS()
1427 def _do_Dir_test(lpath, path_, up_path_, sep, fileSys=fs):
1428 dir = fileSys.Dir(string.replace(lpath, '/', sep))
1431 path_ = string.replace(path_, '/', os.sep)
1432 up_path_ = string.replace(up_path_, '/', os.sep)
1435 if p[-1] == os.sep and len(p) > 3:
1438 path = strip_slash(path_)
1439 up_path = strip_slash(up_path_)
1440 name = string.split(path, os.sep)[-1]
1442 assert dir.name == name, \
1443 "dir.name %s != expected name %s" % \
1445 assert dir.path == path, \
1446 "dir.path %s != expected path %s" % \
1448 assert str(dir) == path, \
1449 "str(dir) %s != expected path %s" % \
1451 assert dir.up().path == up_path, \
1452 "dir.up().path %s != expected parent path %s" % \
1453 (dir.up().path, up_path)
1455 save_os_path = os.path
1456 save_os_sep = os.sep
1461 SCons.Node.FS.initialize_do_splitdrive()
1462 SCons.Node.FS.initialize_normpath_check()
1466 def Dir_test(lpath, path_, up_path_, sep=sep, func=_do_Dir_test):
1467 return func(lpath, path_, up_path_, sep)
1469 Dir_test('#X:', wp, tmp)
1470 Dir_test('X:foo', foo, wp)
1471 Dir_test('X:foo/bar', foo_bar, foo)
1472 Dir_test('X:/foo', 'X:/foo', 'X:/')
1473 Dir_test('X:/foo/bar', 'X:/foo/bar/', 'X:/foo/')
1474 Dir_test('X:..', tmp, parent_tmp)
1475 Dir_test('X:foo/..', wp, tmp)
1476 Dir_test('X:../foo', tmp_foo, tmp)
1477 Dir_test('X:.', wp, tmp)
1478 Dir_test('X:./.', wp, tmp)
1479 Dir_test('X:foo/./bar', foo_bar, foo)
1480 Dir_test('#X:../foo', tmp_foo, tmp)
1481 Dir_test('#X:/../foo', tmp_foo, tmp)
1482 Dir_test('#X:foo/bar', foo_bar, foo)
1483 Dir_test('#X:/foo/bar', foo_bar, foo)
1484 Dir_test('#X:/', wp, tmp)
1486 os.path = save_os_path
1487 os.sep = save_os_sep
1488 SCons.Node.FS.initialize_do_splitdrive()
1489 SCons.Node.FS.initialize_normpath_check()
1491 def test_target_from_source(self):
1492 """Test the method for generating target nodes from sources"""
1496 t = x.target_from_source('pre-', '-suf')
1497 assert str(t) == 'pre-x-suf', str(t)
1498 assert t.__class__ == SCons.Node.FS.Entry
1500 y = fs.File('dir/y')
1501 t = y.target_from_source('pre-', '-suf')
1502 assert str(t) == os.path.join('dir', 'pre-y-suf'), str(t)
1503 assert t.__class__ == SCons.Node.FS.Entry
1506 t = z.target_from_source('pre-', '-suf', lambda x: x[:-1])
1507 assert str(t) == 'pre-z-suf', str(t)
1508 assert t.__class__ == SCons.Node.FS.Entry
1511 t = d.target_from_source('pre-', '-suf')
1512 assert str(t) == 'pre-ddd-suf', str(t)
1513 assert t.__class__ == SCons.Node.FS.Entry
1516 t = e.target_from_source('pre-', '-suf')
1517 assert str(t) == 'pre-eee-suf', str(t)
1518 assert t.__class__ == SCons.Node.FS.Entry
1520 def test_same_name(self):
1521 """Test that a local same-named file isn't found for a Dir lookup"""
1525 test.subdir('subdir')
1526 test.write(['subdir', 'build'], "subdir/build\n")
1528 subdir = fs.Dir('subdir')
1529 fs.chdir(subdir, change_os_dir=1)
1530 self.fs._lookup('#build/file', subdir, SCons.Node.FS.File)
1532 def test_above_root(self):
1533 """Testing looking up a path above the root directory"""
1539 dirs = string.split(os.path.normpath(d2.abspath), os.sep)
1540 above_path = apply(os.path.join, ['..']*len(dirs) + ['above'])
1541 above = d2.Dir(above_path)
1543 def test_rel_path(self):
1544 """Test the rel_path() method"""
1550 d1_d2 = d1.Dir('d2')
1551 d1_d2_f = d1_d2.File('f')
1555 d3_d4 = d3.Dir('d4')
1556 d3_d4_f = d3_d4.File('f')
1562 d1, d1_d2_f, 'd2/f',
1564 d1, d3_f, '../d3/f',
1565 d1, d3_d4, '../d3/d4',
1566 d1, d3_d4_f, '../d3/d4/f',
1571 d1_f, d1_d2_f, 'd2/f',
1573 d1_f, d3_f, '../d3/f',
1574 d1_f, d3_d4, '../d3/d4',
1575 d1_f, d3_d4_f, '../d3/d4/f',
1578 d1_d2, d1_f, '../f',
1580 d1_d2, d1_d2_f, 'f',
1581 d1_d2, d3, '../../d3',
1582 d1_d2, d3_f, '../../d3/f',
1583 d1_d2, d3_d4, '../../d3/d4',
1584 d1_d2, d3_d4_f, '../../d3/d4/f',
1587 d1_d2_f, d1_f, '../f',
1588 d1_d2_f, d1_d2, '.',
1589 d1_d2_f, d1_d2_f, 'f',
1590 d1_d2_f, d3, '../../d3',
1591 d1_d2_f, d3_f, '../../d3/f',
1592 d1_d2_f, d3_d4, '../../d3/d4',
1593 d1_d2_f, d3_d4_f, '../../d3/d4/f',
1596 if sys.platform in ('win32',):
1597 x_d1 = fs.Dir(r'X:\d1')
1598 x_d1_d2 = x_d1.Dir('d2')
1599 y_d1 = fs.Dir(r'Y:\d1')
1600 y_d1_d2 = y_d1.Dir('d2')
1601 y_d2 = fs.Dir(r'Y:\d2')
1605 x_d1, x_d1_d2, 'd2',
1606 x_d1, y_d1, r'Y:\d1',
1607 x_d1, y_d1_d2, r'Y:\d1\d2',
1608 x_d1, y_d2, r'Y:\d2',
1611 cases.extend(win32_cases)
1615 dir, other, expect = cases[:3]
1616 expect = os.path.normpath(expect)
1618 result = dir.rel_path(other)
1619 if result != expect:
1620 if failed == 0: print
1621 fmt = " dir_path(%(dir)s, %(other)s) => '%(result)s' did not match '%(expect)s'"
1622 print fmt % locals()
1624 assert failed == 0, "%d rel_path() cases failed" % failed
1626 def test_proxy(self):
1627 """Test a Node.FS object wrapped in a proxy instance"""
1628 f1 = self.fs.File('fff')
1630 # Simplest possibly Proxy class that works for our test,
1631 # this is stripped down from SCons.Util.Proxy.
1632 def __init__(self, subject):
1633 self.__subject = subject
1634 def __getattr__(self, name):
1635 return getattr(self.__subject, name)
1637 f2 = self.fs.Entry(p)
1638 assert f1 is f2, (f1, f2)
1642 class DirTestCase(_tempdirTestCase):
1644 def test__morph(self):
1645 """Test handling of actions when morphing an Entry into a Dir"""
1647 e = self.fs.Entry('eee')
1648 x = e.get_executor()
1649 x.add_pre_action('pre')
1650 x.add_post_action('post')
1651 e.must_be_same(SCons.Node.FS.Dir)
1652 a = x.get_action_list()
1653 assert a[0] == 'pre', a
1654 assert a[2] == 'post', a
1656 def test_get_env_scanner(self):
1657 """Test the Dir.get_env_scanner() method
1659 import SCons.Defaults
1660 d = self.fs.Dir('ddd')
1661 s = d.get_env_scanner(Environment())
1662 assert s is SCons.Defaults.DirEntryScanner, s
1664 def test_get_target_scanner(self):
1665 """Test the Dir.get_target_scanner() method
1667 import SCons.Defaults
1668 d = self.fs.Dir('ddd')
1669 s = d.get_target_scanner()
1670 assert s is SCons.Defaults.DirEntryScanner, s
1672 def test_scan(self):
1673 """Test scanning a directory for in-memory entries
1678 fs.File(os.path.join('ddd', 'f1'))
1679 fs.File(os.path.join('ddd', 'f2'))
1680 fs.File(os.path.join('ddd', 'f3'))
1681 fs.Dir(os.path.join('ddd', 'd1'))
1682 fs.Dir(os.path.join('ddd', 'd1', 'f4'))
1683 fs.Dir(os.path.join('ddd', 'd1', 'f5'))
1685 kids = map(lambda x: x.path, dir.children(None))
1687 assert kids == [os.path.join('ddd', 'd1'),
1688 os.path.join('ddd', 'f1'),
1689 os.path.join('ddd', 'f2'),
1690 os.path.join('ddd', 'f3')], kids
1692 def test_get_contents(self):
1693 """Test getting the contents for a directory.
1698 test.write(['d', 'g'], "67890\n")
1699 test.write(['d', 'f'], "12345\n")
1700 test.subdir(['d','sub'])
1701 test.write(['d', 'sub','h'], "abcdef\n")
1702 test.subdir(['d','empty'])
1704 d = self.fs.Dir('d')
1705 g = self.fs.File(os.path.join('d', 'g'))
1706 f = self.fs.File(os.path.join('d', 'f'))
1707 h = self.fs.File(os.path.join('d', 'sub', 'h'))
1708 e = self.fs.Dir(os.path.join('d', 'empty'))
1709 s = self.fs.Dir(os.path.join('d', 'sub'))
1711 #TODO(1.5) files = d.get_contents().split('\n')
1712 files = string.split(d.get_contents(), '\n')
1714 assert e.get_contents() == '', e.get_contents()
1715 assert e.get_csig()+" empty" == files[0], files
1716 assert f.get_csig()+" f" == files[1], files
1717 assert g.get_csig()+" g" == files[2], files
1718 assert s.get_csig()+" sub" == files[3], files
1720 def test_implicit_re_scans(self):
1721 """Test that adding entries causes a directory to be re-scanned
1728 fs.File(os.path.join('ddd', 'f1'))
1730 kids = map(lambda x: x.path, dir.children())
1732 assert kids == [os.path.join('ddd', 'f1')], kids
1734 fs.File(os.path.join('ddd', 'f2'))
1736 kids = map(lambda x: x.path, dir.children())
1738 assert kids == [os.path.join('ddd', 'f1'),
1739 os.path.join('ddd', 'f2')], kids
1741 def test_entry_exists_on_disk(self):
1742 """Test the Dir.entry_exists_on_disk() method
1746 does_not_exist = self.fs.Dir('does_not_exist')
1747 assert not does_not_exist.entry_exists_on_disk('foo')
1750 test.write(['d', 'exists'], "d/exists\n")
1751 test.write(['d', 'Case-Insensitive'], "d/Case-Insensitive\n")
1753 d = self.fs.Dir('d')
1754 assert d.entry_exists_on_disk('exists')
1755 assert not d.entry_exists_on_disk('does_not_exist')
1757 if os.path.normcase("TeSt") != os.path.normpath("TeSt") or sys.platform == "cygwin":
1758 assert d.entry_exists_on_disk('case-insensitive')
1760 def test_srcdir_list(self):
1761 """Test the Dir.srcdir_list() method
1763 src = self.fs.Dir('src')
1764 bld = self.fs.Dir('bld')
1765 sub1 = bld.Dir('sub')
1766 sub2 = sub1.Dir('sub')
1767 sub3 = sub2.Dir('sub')
1768 self.fs.VariantDir(bld, src, duplicate=0)
1769 self.fs.VariantDir(sub2, src, duplicate=0)
1771 def check(result, expect):
1772 result = map(str, result)
1773 expect = map(os.path.normpath, expect)
1774 assert result == expect, result
1776 s = src.srcdir_list()
1779 s = bld.srcdir_list()
1782 s = sub1.srcdir_list()
1783 check(s, ['src/sub'])
1785 s = sub2.srcdir_list()
1786 check(s, ['src', 'src/sub/sub'])
1788 s = sub3.srcdir_list()
1789 check(s, ['src/sub', 'src/sub/sub/sub'])
1791 self.fs.VariantDir('src/b1/b2', 'src')
1793 b1_b2 = b1.Dir('b2')
1794 b1_b2_b1 = b1_b2.Dir('b1')
1795 b1_b2_b1_b2 = b1_b2_b1.Dir('b2')
1796 b1_b2_b1_b2_sub = b1_b2_b1_b2.Dir('sub')
1798 s = b1.srcdir_list()
1801 s = b1_b2.srcdir_list()
1804 s = b1_b2_b1.srcdir_list()
1805 check(s, ['src/b1'])
1807 s = b1_b2_b1_b2.srcdir_list()
1808 check(s, ['src/b1/b2'])
1810 s = b1_b2_b1_b2_sub.srcdir_list()
1811 check(s, ['src/b1/b2/sub'])
1813 def test_srcdir_duplicate(self):
1814 """Test the Dir.srcdir_duplicate() method
1819 test.write(['src0', 'exists'], "src0/exists\n")
1821 bld0 = self.fs.Dir('bld0')
1822 src0 = self.fs.Dir('src0')
1823 self.fs.VariantDir(bld0, src0, duplicate=0)
1825 n = bld0.srcdir_duplicate('does_not_exist')
1827 assert not os.path.exists(test.workpath('bld0', 'does_not_exist'))
1829 n = bld0.srcdir_duplicate('exists')
1830 assert str(n) == os.path.normpath('src0/exists'), str(n)
1831 assert not os.path.exists(test.workpath('bld0', 'exists'))
1834 test.write(['src1', 'exists'], "src0/exists\n")
1836 bld1 = self.fs.Dir('bld1')
1837 src1 = self.fs.Dir('src1')
1838 self.fs.VariantDir(bld1, src1, duplicate=1)
1840 n = bld1.srcdir_duplicate('does_not_exist')
1842 assert not os.path.exists(test.workpath('bld1', 'does_not_exist'))
1844 n = bld1.srcdir_duplicate('exists')
1845 assert str(n) == os.path.normpath('bld1/exists'), str(n)
1846 assert os.path.exists(test.workpath('bld1', 'exists'))
1848 def test_srcdir_find_file(self):
1849 """Test the Dir.srcdir_find_file() method
1853 return_true = lambda: 1
1856 test.write(['src0', 'on-disk-f1'], "src0/on-disk-f1\n")
1857 test.write(['src0', 'on-disk-f2'], "src0/on-disk-f2\n")
1858 test.write(['src0', 'on-disk-e1'], "src0/on-disk-e1\n")
1859 test.write(['src0', 'on-disk-e2'], "src0/on-disk-e2\n")
1861 bld0 = self.fs.Dir('bld0')
1862 src0 = self.fs.Dir('src0')
1863 self.fs.VariantDir(bld0, src0, duplicate=0)
1865 derived_f = src0.File('derived-f')
1866 derived_f.is_derived = return_true
1867 exists_f = src0.File('exists-f')
1868 exists_f.exists = return_true
1870 derived_e = src0.Entry('derived-e')
1871 derived_e.is_derived = return_true
1872 exists_e = src0.Entry('exists-e')
1873 exists_e.exists = return_true
1875 def check(result, expect):
1876 result = map(str, result)
1877 expect = map(os.path.normpath, expect)
1878 assert result == expect, result
1880 # First check from the source directory.
1881 n = src0.srcdir_find_file('does_not_exist')
1882 assert n == (None, None), n
1884 n = src0.srcdir_find_file('derived-f')
1885 check(n, ['src0/derived-f', 'src0'])
1886 n = src0.srcdir_find_file('exists-f')
1887 check(n, ['src0/exists-f', 'src0'])
1888 n = src0.srcdir_find_file('on-disk-f1')
1889 check(n, ['src0/on-disk-f1', 'src0'])
1891 n = src0.srcdir_find_file('derived-e')
1892 check(n, ['src0/derived-e', 'src0'])
1893 n = src0.srcdir_find_file('exists-e')
1894 check(n, ['src0/exists-e', 'src0'])
1895 n = src0.srcdir_find_file('on-disk-e1')
1896 check(n, ['src0/on-disk-e1', 'src0'])
1898 # Now check from the variant directory.
1899 n = bld0.srcdir_find_file('does_not_exist')
1900 assert n == (None, None), n
1902 n = bld0.srcdir_find_file('derived-f')
1903 check(n, ['src0/derived-f', 'bld0'])
1904 n = bld0.srcdir_find_file('exists-f')
1905 check(n, ['src0/exists-f', 'bld0'])
1906 n = bld0.srcdir_find_file('on-disk-f2')
1907 check(n, ['src0/on-disk-f2', 'bld0'])
1909 n = bld0.srcdir_find_file('derived-e')
1910 check(n, ['src0/derived-e', 'bld0'])
1911 n = bld0.srcdir_find_file('exists-e')
1912 check(n, ['src0/exists-e', 'bld0'])
1913 n = bld0.srcdir_find_file('on-disk-e2')
1914 check(n, ['src0/on-disk-e2', 'bld0'])
1917 test.write(['src1', 'on-disk-f1'], "src1/on-disk-f1\n")
1918 test.write(['src1', 'on-disk-f2'], "src1/on-disk-f2\n")
1919 test.write(['src1', 'on-disk-e1'], "src1/on-disk-e1\n")
1920 test.write(['src1', 'on-disk-e2'], "src1/on-disk-e2\n")
1922 bld1 = self.fs.Dir('bld1')
1923 src1 = self.fs.Dir('src1')
1924 self.fs.VariantDir(bld1, src1, duplicate=1)
1926 derived_f = src1.File('derived-f')
1927 derived_f.is_derived = return_true
1928 exists_f = src1.File('exists-f')
1929 exists_f.exists = return_true
1931 derived_e = src1.Entry('derived-e')
1932 derived_e.is_derived = return_true
1933 exists_e = src1.Entry('exists-e')
1934 exists_e.exists = return_true
1936 # First check from the source directory.
1937 n = src1.srcdir_find_file('does_not_exist')
1938 assert n == (None, None), n
1940 n = src1.srcdir_find_file('derived-f')
1941 check(n, ['src1/derived-f', 'src1'])
1942 n = src1.srcdir_find_file('exists-f')
1943 check(n, ['src1/exists-f', 'src1'])
1944 n = src1.srcdir_find_file('on-disk-f1')
1945 check(n, ['src1/on-disk-f1', 'src1'])
1947 n = src1.srcdir_find_file('derived-e')
1948 check(n, ['src1/derived-e', 'src1'])
1949 n = src1.srcdir_find_file('exists-e')
1950 check(n, ['src1/exists-e', 'src1'])
1951 n = src1.srcdir_find_file('on-disk-e1')
1952 check(n, ['src1/on-disk-e1', 'src1'])
1954 # Now check from the variant directory.
1955 n = bld1.srcdir_find_file('does_not_exist')
1956 assert n == (None, None), n
1958 n = bld1.srcdir_find_file('derived-f')
1959 check(n, ['bld1/derived-f', 'src1'])
1960 n = bld1.srcdir_find_file('exists-f')
1961 check(n, ['bld1/exists-f', 'src1'])
1962 n = bld1.srcdir_find_file('on-disk-f2')
1963 check(n, ['bld1/on-disk-f2', 'bld1'])
1965 n = bld1.srcdir_find_file('derived-e')
1966 check(n, ['bld1/derived-e', 'src1'])
1967 n = bld1.srcdir_find_file('exists-e')
1968 check(n, ['bld1/exists-e', 'src1'])
1969 n = bld1.srcdir_find_file('on-disk-e2')
1970 check(n, ['bld1/on-disk-e2', 'bld1'])
1972 def test_dir_on_disk(self):
1973 """Test the Dir.dir_on_disk() method"""
1974 self.test.subdir('sub', ['sub', 'exists'])
1975 self.test.write(['sub', 'file'], "self/file\n")
1976 sub = self.fs.Dir('sub')
1978 r = sub.dir_on_disk('does_not_exist')
1981 r = sub.dir_on_disk('exists')
1984 r = sub.dir_on_disk('file')
1987 def test_file_on_disk(self):
1988 """Test the Dir.file_on_disk() method"""
1989 self.test.subdir('sub', ['sub', 'dir'])
1990 self.test.write(['sub', 'exists'], "self/exists\n")
1991 sub = self.fs.Dir('sub')
1993 r = sub.file_on_disk('does_not_exist')
1996 r = sub.file_on_disk('exists')
1999 r = sub.file_on_disk('dir')
2002 class EntryTestCase(_tempdirTestCase):
2003 def test_runTest(self):
2004 """Test methods specific to the Entry sub-class.
2006 test = TestCmd(workdir='')
2007 # FS doesn't like the cwd to be something other than its root.
2008 os.chdir(test.workpath(""))
2010 fs = SCons.Node.FS.FS()
2014 assert e1.__class__ is SCons.Node.FS.File, e1.__class__
2017 test.write('e3f', "e3f\n")
2019 e3d = fs.Entry('e3d')
2021 assert e3d.__class__ is SCons.Node.FS.Dir, e3d.__class__
2023 e3f = fs.Entry('e3f')
2025 assert e3f.__class__ is SCons.Node.FS.File, e3f.__class__
2027 e3n = fs.Entry('e3n')
2029 assert e3n.__class__ is SCons.Node.FS.Entry, e3n.__class__
2032 test.write('e4f', "e4f\n")
2034 e4d = fs.Entry('e4d')
2035 exists = e4d.exists()
2036 assert e4d.__class__ is SCons.Node.FS.Dir, e4d.__class__
2037 assert exists, "e4d does not exist?"
2039 e4f = fs.Entry('e4f')
2040 exists = e4f.exists()
2041 assert e4f.__class__ is SCons.Node.FS.File, e4f.__class__
2042 assert exists, "e4f does not exist?"
2044 e4n = fs.Entry('e4n')
2045 exists = e4n.exists()
2046 assert e4n.__class__ is SCons.Node.FS.File, e4n.__class__
2047 assert not exists, "e4n exists?"
2050 def __init__(self, val):
2053 def __init__(self, val):
2055 def collect(self, args):
2056 return reduce(lambda x, y: x+y, args)
2057 def signature(self, executor):
2058 return self.val + 222
2059 self.module = M(val)
2062 test.write('e5f', "e5f\n")
2064 def test_Entry_Entry_lookup(self):
2065 """Test looking up an Entry within another Entry"""
2066 self.fs.Entry('#topdir')
2067 self.fs.Entry('#topdir/a/b/c')
2071 class FileTestCase(_tempdirTestCase):
2073 def test_Dirs(self):
2074 """Test the File.Dirs() method"""
2075 fff = self.fs.File('subdir/fff')
2076 # This simulates that the SConscript file that defined
2077 # fff is in subdir/.
2078 fff.cwd = self.fs.Dir('subdir')
2079 d1 = self.fs.Dir('subdir/d1')
2080 d2 = self.fs.Dir('subdir/d2')
2081 dirs = fff.Dirs(['d1', 'd2'])
2082 assert dirs == [d1, d2], map(str, dirs)
2084 def test_exists(self):
2085 """Test the File.exists() method"""
2089 src_f1 = fs.File('src/f1')
2090 assert not src_f1.exists(), "%s apparently exists?" % src_f1
2093 test.write(['src', 'f1'], "src/f1\n")
2095 assert not src_f1.exists(), "%s did not cache previous exists() value" % src_f1
2097 assert src_f1.exists(), "%s apparently does not exist?" % src_f1
2099 test.subdir('build')
2100 fs.VariantDir('build', 'src')
2101 build_f1 = fs.File('build/f1')
2103 assert build_f1.exists(), "%s did not realize that %s exists" % (build_f1, src_f1)
2104 assert os.path.exists(build_f1.abspath), "%s did not get duplicated on disk" % build_f1.abspath
2106 test.unlink(['src', 'f1'])
2107 src_f1.clear() # so the next exists() call will look on disk again
2109 assert build_f1.exists(), "%s did not cache previous exists() value" % build_f1
2111 build_f1.linked = None
2112 assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1)
2113 assert not os.path.exists(build_f1.abspath), "%s did not get removed after %s was removed" % (build_f1, src_f1)
2117 class GlobTestCase(_tempdirTestCase):
2119 _tempdirTestCase.setUp(self)
2121 fs = SCons.Node.FS.FS()
2124 # Make entries on disk that will not have Nodes, so we can verify
2125 # the behavior of looking for things on disk.
2126 self.test.write('disk-aaa', "disk-aaa\n")
2127 self.test.write('disk-bbb', "disk-bbb\n")
2128 self.test.write('disk-ccc', "disk-ccc\n")
2129 self.test.subdir('disk-sub')
2130 self.test.write(['disk-sub', 'disk-ddd'], "disk-sub/disk-ddd\n")
2131 self.test.write(['disk-sub', 'disk-eee'], "disk-sub/disk-eee\n")
2132 self.test.write(['disk-sub', 'disk-fff'], "disk-sub/disk-fff\n")
2134 # Make some entries that have both Nodes and on-disk entries,
2135 # so we can verify what we do with
2136 self.test.write('both-aaa', "both-aaa\n")
2137 self.test.write('both-bbb', "both-bbb\n")
2138 self.test.write('both-ccc', "both-ccc\n")
2139 self.test.subdir('both-sub1')
2140 self.test.write(['both-sub1', 'both-ddd'], "both-sub1/both-ddd\n")
2141 self.test.write(['both-sub1', 'both-eee'], "both-sub1/both-eee\n")
2142 self.test.write(['both-sub1', 'both-fff'], "both-sub1/both-fff\n")
2143 self.test.subdir('both-sub2')
2144 self.test.write(['both-sub2', 'both-ddd'], "both-sub2/both-ddd\n")
2145 self.test.write(['both-sub2', 'both-eee'], "both-sub2/both-eee\n")
2146 self.test.write(['both-sub2', 'both-fff'], "both-sub2/both-fff\n")
2148 self.both_aaa = fs.File('both-aaa')
2149 self.both_bbb = fs.File('both-bbb')
2150 self.both_ccc = fs.File('both-ccc')
2151 self.both_sub1 = fs.Dir('both-sub1')
2152 self.both_sub1_both_ddd = self.both_sub1.File('both-ddd')
2153 self.both_sub1_both_eee = self.both_sub1.File('both-eee')
2154 self.both_sub1_both_fff = self.both_sub1.File('both-fff')
2155 self.both_sub2 = fs.Dir('both-sub2')
2156 self.both_sub2_both_ddd = self.both_sub2.File('both-ddd')
2157 self.both_sub2_both_eee = self.both_sub2.File('both-eee')
2158 self.both_sub2_both_fff = self.both_sub2.File('both-fff')
2160 # Make various Nodes (that don't have on-disk entries) so we
2161 # can verify how we match them.
2162 self.ggg = fs.File('ggg')
2163 self.hhh = fs.File('hhh')
2164 self.iii = fs.File('iii')
2165 self.subdir1 = fs.Dir('subdir1')
2166 self.subdir1_lll = self.subdir1.File('lll')
2167 self.subdir1_jjj = self.subdir1.File('jjj')
2168 self.subdir1_kkk = self.subdir1.File('kkk')
2169 self.subdir2 = fs.Dir('subdir2')
2170 self.subdir2_lll = self.subdir2.File('lll')
2171 self.subdir2_kkk = self.subdir2.File('kkk')
2172 self.subdir2_jjj = self.subdir2.File('jjj')
2173 self.sub = fs.Dir('sub')
2174 self.sub_dir3 = self.sub.Dir('dir3')
2175 self.sub_dir3_kkk = self.sub_dir3.File('kkk')
2176 self.sub_dir3_jjj = self.sub_dir3.File('jjj')
2177 self.sub_dir3_lll = self.sub_dir3.File('lll')
2180 def do_cases(self, cases, **kwargs):
2182 # First, execute all of the cases with string=True and verify
2183 # that we get the expected strings returned. We do this first
2184 # so the Glob() calls don't add Nodes to the self.fs file system
2188 strings_kwargs = copy.copy(kwargs)
2189 strings_kwargs['strings'] = True
2190 for input, string_expect, node_expect in cases:
2191 r = apply(self.fs.Glob, (input,), strings_kwargs)
2193 assert r == string_expect, "Glob(%s, strings=True) expected %s, got %s" % (input, string_expect, r)
2195 # Now execute all of the cases without string=True and look for
2196 # the expected Nodes to be returned. If we don't have a list of
2197 # actual expected Nodes, that means we're expecting a search for
2198 # on-disk-only files to have returned some newly-created nodes.
2199 # Verify those by running the list through str() before comparing
2200 # them with the expected list of strings.
2201 for input, string_expect, node_expect in cases:
2202 r = apply(self.fs.Glob, (input,), kwargs)
2204 r.sort(lambda a,b: cmp(a.path, b.path))
2205 result = node_expect
2209 result = string_expect
2210 assert r == result, "Glob(%s) expected %s, got %s" % (input, map(str, result), map(str, r))
2212 def test_exact_match(self):
2213 """Test globbing for exact Node matches"""
2217 ('ggg', ['ggg'], [self.ggg]),
2219 ('subdir1', ['subdir1'], [self.subdir1]),
2221 ('subdir1/jjj', [join('subdir1', 'jjj')], [self.subdir1_jjj]),
2223 ('disk-aaa', ['disk-aaa'], None),
2225 ('disk-sub', ['disk-sub'], None),
2227 ('both-aaa', ['both-aaa'], []),
2230 self.do_cases(cases)
2232 def test_subdir_matches(self):
2233 """Test globbing for exact Node matches in subdirectories"""
2238 [join('subdir1', 'jjj'), join('subdir2', 'jjj')],
2239 [self.subdir1_jjj, self.subdir2_jjj]),
2242 [join('disk-sub', 'disk-ddd')],
2246 self.do_cases(cases)
2248 def test_asterisk(self):
2249 """Test globbing for simple asterisk Node matches"""
2256 ['both-aaa', 'both-bbb', 'both-ccc',
2257 'both-sub1', 'both-sub2',
2258 'ggg', 'hhh', 'iii',
2259 'sub', 'subdir1', 'subdir2'],
2260 [self.both_aaa, self.both_bbb, self.both_ccc,
2261 self.both_sub1, self.both_sub2,
2262 self.ggg, self.hhh, self.iii,
2263 self.sub, self.subdir1, self.subdir2]),
2266 self.do_cases(cases, ondisk=False)
2274 ['both-aaa', 'both-bbb', 'both-ccc', 'both-sub1', 'both-sub2',
2275 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub',
2276 'ggg', 'hhh', 'iii',
2277 'sub', 'subdir1', 'subdir2'],
2281 self.do_cases(cases)
2283 def test_question_mark(self):
2284 """Test globbing for simple question-mark Node matches"""
2292 ('both-sub?/both-eee',
2293 [join('both-sub1', 'both-eee'), join('both-sub2', 'both-eee')],
2294 [self.both_sub1_both_eee, self.both_sub2_both_eee]),
2297 [join('subdir1', 'jjj'), join('subdir2', 'jjj')],
2298 [self.subdir1_jjj, self.subdir2_jjj]),
2305 self.do_cases(cases)
2307 def test_does_not_exist(self):
2308 """Test globbing for things that don't exist"""
2311 ('does_not_exist', [], []),
2312 ('no_subdir/*', [], []),
2313 ('subdir?/no_file', [], []),
2316 self.do_cases(cases)
2318 def test_subdir_asterisk(self):
2319 """Test globbing for asterisk Node matches in subdirectories"""
2324 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2325 [self.subdir1_kkk, self.subdir2_kkk]),
2328 [join('both-sub1', 'both-ddd'),
2329 join('both-sub1', 'both-eee'),
2330 join('both-sub1', 'both-fff'),
2331 join('both-sub2', 'both-ddd'),
2332 join('both-sub2', 'both-eee'),
2333 join('both-sub2', 'both-fff')],
2334 [self.both_sub1_both_ddd, self.both_sub1_both_eee, self.both_sub1_both_fff,
2335 self.both_sub2_both_ddd, self.both_sub2_both_eee, self.both_sub2_both_fff],
2339 [join('subdir1', 'jjj'),
2340 join('subdir1', 'kkk'),
2341 join('subdir1', 'lll'),
2342 join('subdir2', 'jjj'),
2343 join('subdir2', 'kkk'),
2344 join('subdir2', 'lll')],
2345 [self.subdir1_jjj, self.subdir1_kkk, self.subdir1_lll,
2346 self.subdir2_jjj, self.subdir2_kkk, self.subdir2_lll]),
2349 [join('sub', 'dir3', 'jjj'),
2350 join('sub', 'dir3', 'kkk'),
2351 join('sub', 'dir3', 'lll')],
2352 [self.sub_dir3_jjj, self.sub_dir3_kkk, self.sub_dir3_lll]),
2355 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2359 [join('subdir1', 'jjj'),
2360 join('subdir1', 'kkk'),
2361 join('subdir1', 'lll'),
2362 join('subdir2', 'jjj'),
2363 join('subdir2', 'kkk'),
2364 join('subdir2', 'lll')],
2368 [join('sub', 'dir3', 'jjj'),
2369 join('sub', 'dir3', 'kkk'),
2370 join('sub', 'dir3', 'lll')],
2374 self.do_cases(cases)
2376 def test_subdir_question(self):
2377 """Test globbing for question-mark Node matches in subdirectories"""
2382 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2383 [self.subdir1_kkk, self.subdir2_kkk]),
2386 [join('subdir1', 'lll'), join('subdir2', 'lll')],
2387 [self.subdir1_lll, self.subdir2_lll]),
2390 [join('disk-sub', 'disk-fff')],
2394 [join('subdir1', 'lll'), join('subdir2', 'lll')],
2398 self.do_cases(cases)
2400 def test_sort(self):
2401 """Test whether globbing sorts"""
2403 # At least sometimes this should return out-of-order items
2404 # if Glob doesn't sort.
2405 g = self.fs.Glob('disk-sub/*', strings=True)
2407 os.path.join('disk-sub', 'disk-ddd'),
2408 os.path.join('disk-sub', 'disk-eee'),
2409 os.path.join('disk-sub', 'disk-fff'),
2411 assert g == expect, str(g) + " is not sorted, but should be!"
2414 class RepositoryTestCase(_tempdirTestCase):
2417 _tempdirTestCase.setUp(self)
2419 self.test.subdir('rep1', 'rep2', 'rep3', 'work')
2421 self.rep1 = self.test.workpath('rep1')
2422 self.rep2 = self.test.workpath('rep2')
2423 self.rep3 = self.test.workpath('rep3')
2425 os.chdir(self.test.workpath('work'))
2427 self.fs = SCons.Node.FS.FS()
2428 self.fs.Repository(self.rep1, self.rep2, self.rep3)
2430 def test_getRepositories(self):
2431 """Test the Dir.getRepositories() method"""
2432 self.fs.Repository('foo')
2433 self.fs.Repository(os.path.join('foo', 'bar'))
2434 self.fs.Repository('bar/foo')
2435 self.fs.Repository('bar')
2442 os.path.join('foo', 'bar'),
2443 os.path.join('bar', 'foo'),
2447 rep = self.fs.Dir('#').getRepositories()
2448 r = map(lambda x, np=os.path.normpath: np(str(x)), rep)
2449 assert r == expect, r
2451 def test_get_all_rdirs(self):
2452 """Test the Dir.get_all_rdirs() method"""
2453 self.fs.Repository('foo')
2454 self.fs.Repository(os.path.join('foo', 'bar'))
2455 self.fs.Repository('bar/foo')
2456 self.fs.Repository('bar')
2464 os.path.join('foo', 'bar'),
2465 os.path.join('bar', 'foo'),
2469 rep = self.fs.Dir('#').get_all_rdirs()
2470 r = map(lambda x, np=os.path.normpath: np(str(x)), rep)
2471 assert r == expect, r
2473 def test_rentry(self):
2474 """Test the Base.entry() method"""
2475 return_true = lambda: 1
2476 return_false = lambda: 0
2478 d1 = self.fs.Dir('d1')
2479 d2 = self.fs.Dir('d2')
2480 d3 = self.fs.Dir('d3')
2482 e1 = self.fs.Entry('e1')
2483 e2 = self.fs.Entry('e2')
2484 e3 = self.fs.Entry('e3')
2486 f1 = self.fs.File('f1')
2487 f2 = self.fs.File('f2')
2488 f3 = self.fs.File('f3')
2490 self.test.write([self.rep1, 'd2'], "")
2491 self.test.subdir([self.rep2, 'd3'])
2492 self.test.write([self.rep3, 'd3'], "")
2494 self.test.write([self.rep1, 'e2'], "")
2495 self.test.subdir([self.rep2, 'e3'])
2496 self.test.write([self.rep3, 'e3'], "")
2498 self.test.write([self.rep1, 'f2'], "")
2499 self.test.subdir([self.rep2, 'f3'])
2500 self.test.write([self.rep3, 'f3'], "")
2506 assert not r is d2, r
2508 assert r == os.path.join(self.rep1, 'd2'), r
2511 assert not r is d3, r
2513 assert r == os.path.join(self.rep2, 'd3'), r
2519 assert not r is e2, r
2521 assert r == os.path.join(self.rep1, 'e2'), r
2524 assert not r is e3, r
2526 assert r == os.path.join(self.rep2, 'e3'), r
2532 assert not r is f2, r
2534 assert r == os.path.join(self.rep1, 'f2'), r
2537 assert not r is f3, r
2539 assert r == os.path.join(self.rep2, 'f3'), r
2541 def test_rdir(self):
2542 """Test the Dir.rdir() method"""
2543 return_true = lambda: 1
2544 return_false = lambda: 0
2546 d1 = self.fs.Dir('d1')
2547 d2 = self.fs.Dir('d2')
2548 d3 = self.fs.Dir('d3')
2550 self.test.subdir([self.rep1, 'd2'])
2551 self.test.write([self.rep2, 'd3'], "")
2552 self.test.subdir([self.rep3, 'd3'])
2558 assert not r is d2, r
2560 assert r == os.path.join(self.rep1, 'd2'), r
2563 assert not r is d3, r
2565 assert r == os.path.join(self.rep3, 'd3'), r
2567 e1 = self.fs.Dir('e1')
2568 e1.exists = return_false
2569 e2 = self.fs.Dir('e2')
2570 e2.exists = return_false
2572 # Make sure we match entries in repositories,
2573 # regardless of whether they're derived or not.
2575 re1 = self.fs.Entry(os.path.join(self.rep1, 'e1'))
2576 re1.exists = return_true
2577 re1.is_derived = return_true
2578 re2 = self.fs.Entry(os.path.join(self.rep2, 'e2'))
2579 re2.exists = return_true
2580 re2.is_derived = return_false
2588 def test_rfile(self):
2589 """Test the File.rfile() method"""
2590 return_true = lambda: 1
2591 return_false = lambda: 0
2593 f1 = self.fs.File('f1')
2594 f2 = self.fs.File('f2')
2595 f3 = self.fs.File('f3')
2597 self.test.write([self.rep1, 'f2'], "")
2598 self.test.subdir([self.rep2, 'f3'])
2599 self.test.write([self.rep3, 'f3'], "")
2605 assert not r is f2, r
2607 assert r == os.path.join(self.rep1, 'f2'), r
2610 assert not r is f3, r
2612 assert r == os.path.join(self.rep3, 'f3'), r
2614 e1 = self.fs.File('e1')
2615 e1.exists = return_false
2616 e2 = self.fs.File('e2')
2617 e2.exists = return_false
2619 # Make sure we match entries in repositories,
2620 # regardless of whether they're derived or not.
2622 re1 = self.fs.Entry(os.path.join(self.rep1, 'e1'))
2623 re1.exists = return_true
2624 re1.is_derived = return_true
2625 re2 = self.fs.Entry(os.path.join(self.rep2, 'e2'))
2626 re2.exists = return_true
2627 re2.is_derived = return_false
2635 def test_Rfindalldirs(self):
2636 """Test the Rfindalldirs() methods"""
2642 rep1_d1 = fs.Dir(test.workpath('rep1', 'd1'))
2643 rep2_d1 = fs.Dir(test.workpath('rep2', 'd1'))
2644 rep3_d1 = fs.Dir(test.workpath('rep3', 'd1'))
2646 sub_d1 = sub.Dir('d1')
2647 rep1_sub_d1 = fs.Dir(test.workpath('rep1', 'sub', 'd1'))
2648 rep2_sub_d1 = fs.Dir(test.workpath('rep2', 'sub', 'd1'))
2649 rep3_sub_d1 = fs.Dir(test.workpath('rep3', 'sub', 'd1'))
2651 r = fs.Top.Rfindalldirs((d1,))
2652 assert r == [d1], map(str, r)
2654 r = fs.Top.Rfindalldirs((d1, d2))
2655 assert r == [d1, d2], map(str, r)
2657 r = fs.Top.Rfindalldirs(('d1',))
2658 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], map(str, r)
2660 r = fs.Top.Rfindalldirs(('#d1',))
2661 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], map(str, r)
2663 r = sub.Rfindalldirs(('d1',))
2664 assert r == [sub_d1, rep1_sub_d1, rep2_sub_d1, rep3_sub_d1], map(str, r)
2666 r = sub.Rfindalldirs(('#d1',))
2667 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], map(str, r)
2669 r = fs.Top.Rfindalldirs(('d1', d2))
2670 assert r == [d1, rep1_d1, rep2_d1, rep3_d1, d2], map(str, r)
2672 def test_rexists(self):
2673 """Test the Entry.rexists() method"""
2677 test.write([self.rep1, 'f2'], "")
2678 test.write([self.rep2, "i_exist"], "\n")
2679 test.write(["work", "i_exist_too"], "\n")
2681 fs.VariantDir('build', '.')
2683 f = fs.File(test.workpath("work", "i_do_not_exist"))
2684 assert not f.rexists()
2686 f = fs.File(test.workpath("work", "i_exist"))
2689 f = fs.File(test.workpath("work", "i_exist_too"))
2692 f1 = fs.File(os.path.join('build', 'f1'))
2693 assert not f1.rexists()
2695 f2 = fs.File(os.path.join('build', 'f2'))
2698 def test_FAT_timestamps(self):
2699 """Test repository timestamps on FAT file systems"""
2703 test.write(["rep2", "tstamp"], "tstamp\n")
2705 # Okay, *this* manipulation accomodates Windows FAT file systems
2706 # that only have two-second granularity on their timestamps.
2707 # We round down the current time to the nearest even integer
2708 # value, subtract two to make sure the timestamp is not "now,"
2709 # and then convert it back to a float.
2710 tstamp = float(int(time.time() / 2) * 2) - 2
2711 os.utime(test.workpath("rep2", "tstamp"), (tstamp - 2.0, tstamp))
2712 f = fs.File("tstamp")
2713 t = f.get_timestamp()
2714 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
2716 test.unlink(["rep2", "tstamp"])
2718 def test_get_contents(self):
2719 """Ensure get_contents() returns binary contents from Repositories"""
2723 test.write(["rep3", "contents"], "Con\x1aTents\n")
2725 c = fs.File("contents").get_contents()
2726 assert c == "Con\x1aTents\n", "got '%s'" % c
2728 test.unlink(["rep3", "contents"])
2730 #def test_is_up_to_date(self):
2734 class find_fileTestCase(unittest.TestCase):
2736 """Testing find_file function"""
2737 test = TestCmd(workdir = '')
2738 test.write('./foo', 'Some file\n')
2739 test.write('./foo2', 'Another file\n')
2742 test.write(['bar', 'on_disk'], 'Another file\n')
2743 test.write(['bar', 'same'], 'bar/same\n')
2745 fs = SCons.Node.FS.FS(test.workpath(""))
2746 # FS doesn't like the cwd to be something other than its root.
2747 os.chdir(test.workpath(""))
2749 node_derived = fs.File(test.workpath('bar/baz'))
2750 node_derived.builder_set(1) # Any non-zero value.
2751 node_pseudo = fs.File(test.workpath('pseudo'))
2752 node_pseudo.set_src_builder(1) # Any non-zero value.
2754 paths = tuple(map(fs.Dir, ['.', 'same', './bar']))
2755 nodes = [SCons.Node.FS.find_file('foo', paths)]
2756 nodes.append(SCons.Node.FS.find_file('baz', paths))
2757 nodes.append(SCons.Node.FS.find_file('pseudo', paths))
2758 nodes.append(SCons.Node.FS.find_file('same', paths))
2760 file_names = map(str, nodes)
2761 file_names = map(os.path.normpath, file_names)
2762 expect = ['./foo', './bar/baz', './pseudo', './bar/same']
2763 expect = map(os.path.normpath, expect)
2764 assert file_names == expect, file_names
2766 # Make sure we don't blow up if there's already a File in place
2767 # of a directory that we'd otherwise try to search. If this
2768 # is broken, we'll see an exception like "Tried to lookup File
2769 # 'bar/baz' as a Dir.
2770 SCons.Node.FS.find_file('baz/no_file_here', paths)
2773 save_sys_stdout = sys.stdout
2776 sio = StringIO.StringIO()
2778 SCons.Node.FS.find_file('foo2', paths, verbose="xyz")
2779 expect = " xyz: looking for 'foo2' in '.' ...\n" + \
2780 " xyz: ... FOUND 'foo2' in '.'\n"
2782 assert c == expect, c
2784 sio = StringIO.StringIO()
2786 SCons.Node.FS.find_file('baz2', paths, verbose=1)
2787 expect = " find_file: looking for 'baz2' in '.' ...\n" + \
2788 " find_file: looking for 'baz2' in 'same' ...\n" + \
2789 " find_file: looking for 'baz2' in 'bar' ...\n"
2791 assert c == expect, c
2793 sio = StringIO.StringIO()
2795 SCons.Node.FS.find_file('on_disk', paths, verbose=1)
2796 expect = " find_file: looking for 'on_disk' in '.' ...\n" + \
2797 " find_file: looking for 'on_disk' in 'same' ...\n" + \
2798 " find_file: looking for 'on_disk' in 'bar' ...\n" + \
2799 " find_file: ... FOUND 'on_disk' in 'bar'\n"
2801 assert c == expect, c
2803 sys.stdout = save_sys_stdout
2805 class StringDirTestCase(unittest.TestCase):
2807 """Test using a string as the second argument of
2810 test = TestCmd(workdir = '')
2812 fs = SCons.Node.FS.FS(test.workpath(''))
2814 d = fs.Dir('sub', '.')
2815 assert str(d) == 'sub', str(d)
2817 f = fs.File('file', 'sub')
2818 assert str(f) == os.path.join('sub', 'file')
2819 assert not f.exists()
2821 class stored_infoTestCase(unittest.TestCase):
2823 """Test how we store build information"""
2824 test = TestCmd(workdir = '')
2826 fs = SCons.Node.FS.FS(test.workpath(''))
2829 f = fs.File('file1', d)
2830 bi = f.get_stored_info()
2831 assert hasattr(bi, 'ninfo')
2837 def get_entry(self, name):
2840 f = fs.File('file2', d)
2841 f.dir.sconsign = MySConsign
2842 bi = f.get_stored_info()
2843 assert bi.xyzzy == 7, bi
2845 class has_src_builderTestCase(unittest.TestCase):
2847 """Test the has_src_builder() method"""
2848 test = TestCmd(workdir = '')
2849 fs = SCons.Node.FS.FS(test.workpath(''))
2850 os.chdir(test.workpath(''))
2852 test.subdir('sub2', ['sub2', 'SCCS'], ['sub2', 'RCS'])
2854 sub1 = fs.Dir('sub1', '.')
2855 f1 = fs.File('f1', sub1)
2856 f2 = fs.File('f2', sub1)
2857 f3 = fs.File('f3', sub1)
2858 sub2 = fs.Dir('sub2', '.')
2859 f4 = fs.File('f4', sub2)
2860 f5 = fs.File('f5', sub2)
2861 f6 = fs.File('f6', sub2)
2862 f7 = fs.File('f7', sub2)
2863 f8 = fs.File('f8', sub2)
2865 h = f1.has_src_builder()
2867 h = f1.has_builder()
2870 b1 = Builder(fs.File)
2871 sub1.set_src_builder(b1)
2873 test.write(['sub1', 'f2'], "sub1/f2\n")
2874 h = f1.has_src_builder() # cached from previous call
2876 h = f1.has_builder() # cached from previous call
2878 h = f2.has_src_builder()
2880 h = f2.has_builder()
2882 h = f3.has_src_builder()
2884 h = f3.has_builder()
2886 assert f3.builder is b1, f3.builder
2888 f7.set_src_builder(b1)
2891 test.write(['sub2', 'SCCS', 's.f5'], "sub2/SCCS/s.f5\n")
2892 test.write(['sub2', 'RCS', 'f6,v'], "sub2/RCS/f6,v\n")
2893 h = f4.has_src_builder()
2895 h = f4.has_builder()
2897 h = f5.has_src_builder()
2899 h = f5.has_builder()
2901 h = f6.has_src_builder()
2903 h = f6.has_builder()
2905 h = f7.has_src_builder()
2907 h = f7.has_builder()
2909 h = f8.has_src_builder()
2911 h = f8.has_builder()
2914 class prepareTestCase(unittest.TestCase):
2916 """Test the prepare() method"""
2918 class MyFile(SCons.Node.FS.File):
2919 def _createDir(self, update=None):
2920 raise SCons.Errors.StopError
2924 fs = SCons.Node.FS.FS()
2925 file = MyFile('foo', fs.Dir('.'), fs)
2930 except SCons.Errors.StopError:
2932 assert exc_caught, "Should have caught a StopError."
2934 class MkdirAction(Action):
2935 def __init__(self, dir_made):
2936 self.dir_made = dir_made
2937 def __call__(self, target, source, env):
2938 self.dir_made.extend(target)
2941 new_dir = fs.Dir("new_dir")
2942 new_dir.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
2943 new_dir.reset_executor()
2944 xyz = fs.File(os.path.join("new_dir", "xyz"))
2946 xyz.set_state(SCons.Node.up_to_date)
2948 assert dir_made == [], dir_made
2952 assert dir_made[0].path == "new_dir", dir_made[0]
2959 class SConstruct_dirTestCase(unittest.TestCase):
2961 """Test setting the SConstruct directory"""
2963 fs = SCons.Node.FS.FS()
2964 fs.set_SConstruct_dir(fs.Dir('xxx'))
2965 assert fs.SConstruct_dir.path == 'xxx'
2969 class CacheDirTestCase(unittest.TestCase):
2971 def test_get_cachedir_csig(self):
2972 fs = SCons.Node.FS.FS()
2975 r = f9.get_cachedir_csig()
2976 assert r == 'd41d8cd98f00b204e9800998ecf8427e', r
2980 class clearTestCase(unittest.TestCase):
2982 """Test clearing FS nodes of cached data."""
2983 fs = SCons.Node.FS.FS()
2984 test = TestCmd(workdir='')
2987 assert not e.exists()
2988 assert not e.rexists()
2989 assert str(e) == 'e', str(d)
2991 assert not e.exists()
2992 assert not e.rexists()
2993 assert str(e) == 'e', str(d)
2995 d = fs.Dir(test.workpath('d'))
2999 assert str(d) == test.workpath('d'), str(d)
3000 fs.rename(test.workpath('d'), test.workpath('gone'))
3001 # Verify caching is active
3002 assert d.exists(), 'caching not active'
3004 assert str(d) == test.workpath('d'), str(d)
3005 # Now verify clear() resets the cache
3007 assert not d.exists()
3008 assert not d.rexists()
3009 assert str(d) == test.workpath('d'), str(d)
3011 f = fs.File(test.workpath('f'))
3012 test.write(test.workpath('f'), 'file f')
3015 assert str(f) == test.workpath('f'), str(f)
3016 # Verify caching is active
3017 test.unlink(test.workpath('f'))
3020 assert str(f) == test.workpath('f'), str(f)
3021 # Now verify clear() resets the cache
3023 assert not f.exists()
3024 assert not f.rexists()
3025 assert str(f) == test.workpath('f'), str(f)
3029 class disambiguateTestCase(unittest.TestCase):
3031 """Test calling the disambiguate() method."""
3032 test = TestCmd(workdir='')
3034 fs = SCons.Node.FS.FS()
3037 d = ddd.disambiguate()
3040 fff = fs.File('fff')
3041 f = fff.disambiguate()
3045 test.write('efile', "efile\n")
3047 edir = fs.Entry(test.workpath('edir'))
3048 d = edir.disambiguate()
3049 assert d.__class__ is ddd.__class__, d.__class__
3051 efile = fs.Entry(test.workpath('efile'))
3052 f = efile.disambiguate()
3053 assert f.__class__ is fff.__class__, f.__class__
3055 test.subdir('build')
3056 test.subdir(['build', 'bdir'])
3057 test.write(['build', 'bfile'], "build/bfile\n")
3060 test.write(['src', 'bdir'], "src/bdir\n")
3061 test.subdir(['src', 'bfile'])
3063 test.subdir(['src', 'edir'])
3064 test.write(['src', 'efile'], "src/efile\n")
3066 fs.VariantDir(test.workpath('build'), test.workpath('src'))
3068 build_bdir = fs.Entry(test.workpath('build/bdir'))
3069 d = build_bdir.disambiguate()
3070 assert d is build_bdir, d
3071 assert d.__class__ is ddd.__class__, d.__class__
3073 build_bfile = fs.Entry(test.workpath('build/bfile'))
3074 f = build_bfile.disambiguate()
3075 assert f is build_bfile, f
3076 assert f.__class__ is fff.__class__, f.__class__
3078 build_edir = fs.Entry(test.workpath('build/edir'))
3079 d = build_edir.disambiguate()
3080 assert d.__class__ is ddd.__class__, d.__class__
3082 build_efile = fs.Entry(test.workpath('build/efile'))
3083 f = build_efile.disambiguate()
3084 assert f.__class__ is fff.__class__, f.__class__
3086 build_nonexistant = fs.Entry(test.workpath('build/nonexistant'))
3087 f = build_nonexistant.disambiguate()
3088 assert f.__class__ is fff.__class__, f.__class__
3090 class postprocessTestCase(unittest.TestCase):
3092 """Test calling the postprocess() method."""
3093 fs = SCons.Node.FS.FS()
3106 class SpecialAttrTestCase(unittest.TestCase):
3108 """Test special attributes of file nodes."""
3109 test=TestCmd(workdir='')
3110 fs = SCons.Node.FS.FS(test.workpath('work'))
3112 f = fs.Entry('foo/bar/baz.blat').get_subst_proxy()
3115 assert s == os.path.normpath('foo/bar'), s
3116 assert f.dir.is_literal(), f.dir
3117 for_sig = f.dir.for_signature()
3118 assert for_sig == 'bar', for_sig
3121 assert s == 'baz.blat', s
3122 assert f.file.is_literal(), f.file
3123 for_sig = f.file.for_signature()
3124 assert for_sig == 'baz.blat_file', for_sig
3127 assert s == os.path.normpath('foo/bar/baz'), s
3128 assert f.base.is_literal(), f.base
3129 for_sig = f.base.for_signature()
3130 assert for_sig == 'baz.blat_base', for_sig
3133 assert s == 'baz', s
3134 assert f.filebase.is_literal(), f.filebase
3135 for_sig = f.filebase.for_signature()
3136 assert for_sig == 'baz.blat_filebase', for_sig
3139 assert s == '.blat', s
3140 assert f.suffix.is_literal(), f.suffix
3141 for_sig = f.suffix.for_signature()
3142 assert for_sig == 'baz.blat_suffix', for_sig
3145 assert s == test.workpath('work', 'foo', 'bar', 'baz.blat'), s
3146 assert f.abspath.is_literal(), f.abspath
3147 for_sig = f.abspath.for_signature()
3148 assert for_sig == 'baz.blat_abspath', for_sig
3151 assert s == 'foo/bar/baz.blat', s
3152 assert f.posix.is_literal(), f.posix
3154 for_sig = f.posix.for_signature()
3155 assert for_sig == 'baz.blat_posix', for_sig
3158 assert s == 'foo\\bar\\baz.blat', repr(s)
3159 assert f.windows.is_literal(), f.windows
3161 for_sig = f.windows.for_signature()
3162 assert for_sig == 'baz.blat_windows', for_sig
3164 # Deprecated synonym for the .windows suffix.
3166 assert s == 'foo\\bar\\baz.blat', repr(s)
3167 assert f.win32.is_literal(), f.win32
3169 for_sig = f.win32.for_signature()
3170 assert for_sig == 'baz.blat_windows', for_sig
3172 # And now, combinations!!!
3173 s = str(f.srcpath.base)
3174 assert s == os.path.normpath('foo/bar/baz'), s
3175 s = str(f.srcpath.dir)
3176 assert s == str(f.srcdir), s
3177 s = str(f.srcpath.posix)
3178 assert s == 'foo/bar/baz.blat', s
3179 s = str(f.srcpath.windows)
3180 assert s == 'foo\\bar\\baz.blat', s
3181 s = str(f.srcpath.win32)
3182 assert s == 'foo\\bar\\baz.blat', s
3184 # Test what happens with VariantDir()
3185 fs.VariantDir('foo', 'baz')
3188 assert s == os.path.normpath('baz/bar/baz.blat'), s
3189 assert f.srcpath.is_literal(), f.srcpath
3191 assert isinstance(g, SCons.Node.FS.File), g.__class__
3194 assert s == os.path.normpath('baz/bar'), s
3195 assert f.srcdir.is_literal(), f.srcdir
3197 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3199 # And now what happens with VariantDir() + Repository()
3200 fs.Repository(test.workpath('repository'))
3202 f = fs.Entry('foo/sub/file.suffix').get_subst_proxy()
3203 test.subdir('repository',
3204 ['repository', 'baz'],
3205 ['repository', 'baz', 'sub'])
3207 rd = test.workpath('repository', 'baz', 'sub')
3208 rf = test.workpath('repository', 'baz', 'sub', 'file.suffix')
3209 test.write(rf, "\n")
3212 assert s == os.path.normpath('baz/sub/file.suffix'), s
3213 assert f.srcpath.is_literal(), f.srcpath
3215 assert isinstance(g, SCons.Node.FS.Entry), g.__class__
3218 assert s == os.path.normpath('baz/sub'), s
3219 assert f.srcdir.is_literal(), f.srcdir
3221 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3225 assert f.rsrcpath.is_literal(), f.rsrcpath
3226 g = f.rsrcpath.get()
3227 assert isinstance(g, SCons.Node.FS.File), g.__class__
3231 assert f.rsrcdir.is_literal(), f.rsrcdir
3233 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3235 # Check that attempts to access non-existent attributes of the
3236 # subst proxy generate the right exceptions and messages.
3239 fs.Dir('ddd').get_subst_proxy().no_such_attr
3240 except AttributeError, e:
3241 assert str(e) == "Dir instance 'ddd' has no attribute 'no_such_attr'", e
3243 assert caught, "did not catch expected AttributeError"
3247 fs.Entry('eee').get_subst_proxy().no_such_attr
3248 except AttributeError, e:
3249 assert str(e) == "Entry instance 'eee' has no attribute 'no_such_attr'", e
3251 assert caught, "did not catch expected AttributeError"
3255 fs.File('fff').get_subst_proxy().no_such_attr
3256 except AttributeError, e:
3257 assert str(e) == "File instance 'fff' has no attribute 'no_such_attr'", e
3259 assert caught, "did not catch expected AttributeError"
3263 class SaveStringsTestCase(unittest.TestCase):
3265 """Test caching string values of nodes."""
3266 test=TestCmd(workdir='')
3273 d0_f = fs.File('d0/f')
3274 d1_f = fs.File('d1/f')
3275 d0_b = fs.File('d0/b')
3276 d1_b = fs.File('d1/b')
3282 return [d0_f, d1_f, d0_b, d1_b]
3285 d0_f, d1_f, d0_b, d1_b = nodes
3291 fs1 = SCons.Node.FS.FS(test.workpath('fs1'))
3293 fs1.VariantDir('d0', 'src', duplicate=0)
3294 fs1.VariantDir('d1', 'src', duplicate=1)
3297 expect = map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])
3298 assert s == expect, s
3303 expect = map(os.path.normpath, ['src/f', 'src/f', 'd0/b', 'd1/b'])
3304 assert s == expect, s
3306 SCons.Node.FS.save_strings(1)
3307 fs2 = SCons.Node.FS.FS(test.workpath('fs2'))
3309 fs2.VariantDir('d0', 'src', duplicate=0)
3310 fs2.VariantDir('d1', 'src', duplicate=1)
3313 expect = map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])
3314 assert s == expect, s
3319 expect = map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b'])
3320 assert s == expect, 'node str() not cached: %s'%s
3323 class AbsolutePathTestCase(unittest.TestCase):
3324 def test_root_lookup_equivalence(self):
3325 """Test looking up /fff vs. fff in the / directory"""
3326 test=TestCmd(workdir='')
3328 fs = SCons.Node.FS.FS('/')
3330 save_cwd = os.getcwd()
3333 fff1 = fs.File('fff')
3334 fff2 = fs.File('/fff')
3335 assert fff1 is fff2, "fff and /fff returned different Nodes!"
3341 if __name__ == "__main__":
3342 suite = unittest.TestSuite()
3343 suite.addTest(VariantDirTestCase())
3344 suite.addTest(find_fileTestCase())
3345 suite.addTest(StringDirTestCase())
3346 suite.addTest(stored_infoTestCase())
3347 suite.addTest(has_src_builderTestCase())
3348 suite.addTest(prepareTestCase())
3349 suite.addTest(SConstruct_dirTestCase())
3350 suite.addTest(clearTestCase())
3351 suite.addTest(disambiguateTestCase())
3352 suite.addTest(postprocessTestCase())
3353 suite.addTest(SpecialAttrTestCase())
3354 suite.addTest(SaveStringsTestCase())
3356 AbsolutePathTestCase,
3360 DirBuildInfoTestCase,
3361 DirNodeInfoTestCase,
3364 FileBuildInfoTestCase,
3365 FileNodeInfoTestCase,
3370 for tclass in tclasses:
3371 names = unittest.getTestCaseNames(tclass, 'test_')
3372 suite.addTests(map(tclass, names))
3373 if not unittest.TextTestRunner().run(suite).wasSuccessful():