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__"
31 from TestCmd import TestCmd
45 def __init__(self, node=None):
47 scanner_count = scanner_count + 1
48 self.hash = scanner_count
50 def path(self, env, dir, target=None, source=None):
52 def __call__(self, node, env, path):
56 def select(self, node):
58 def recurse_nodes(self, nodes):
63 self.scanner = Scanner()
64 def Dictionary(self, *args):
66 def autogenerate(self, **kw):
68 def get_scanner(self, skey):
70 def Override(self, overrides):
72 def _update(self, dict):
76 def __call__(self, targets, sources, env, **kw):
78 if kw.get('execute', 1):
81 def show(self, string):
83 def get_contents(self, target, source, env):
85 def genstring(self, target, source, env):
87 def strfunction(self, targets, sources, env):
89 def get_implicit_deps(self, target, source, env):
93 def __init__(self, factory, action=Action()):
94 self.factory = factory
95 self.env = Environment()
98 self.target_scanner = None
99 self.source_scanner = None
101 def targets(self, t):
104 def source_factory(self, name):
105 return self.factory(name)
107 class _tempdirTestCase(unittest.TestCase):
109 self.save_cwd = os.getcwd()
110 self.test = TestCmd(workdir='')
111 # FS doesn't like the cwd to be something other than its root.
112 os.chdir(self.test.workpath(""))
113 self.fs = SCons.Node.FS.FS()
116 os.chdir(self.save_cwd)
118 class VariantDirTestCase(unittest.TestCase):
120 """Test variant dir functionality"""
121 test=TestCmd(workdir='')
123 fs = SCons.Node.FS.FS()
124 f1 = fs.File('build/test1')
125 fs.VariantDir('build', 'src')
126 f2 = fs.File('build/test2')
128 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
129 assert f2.srcnode().path == os.path.normpath('src/test2'), f2.srcnode().path
130 assert d1.srcnode().path == 'src', d1.srcnode().path
132 fs = SCons.Node.FS.FS()
133 f1 = fs.File('build/test1')
134 fs.VariantDir('build', '.')
135 f2 = fs.File('build/test2')
137 assert f1.srcnode().path == 'test1', f1.srcnode().path
138 assert f2.srcnode().path == 'test2', f2.srcnode().path
139 assert d1.srcnode().path == '.', d1.srcnode().path
141 fs = SCons.Node.FS.FS()
142 fs.VariantDir('build/var1', 'src')
143 fs.VariantDir('build/var2', 'src')
144 f1 = fs.File('build/var1/test1')
145 f2 = fs.File('build/var2/test1')
146 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
147 assert f2.srcnode().path == os.path.normpath('src/test1'), f2.srcnode().path
149 fs = SCons.Node.FS.FS()
150 fs.VariantDir('../var1', 'src')
151 fs.VariantDir('../var2', 'src')
152 f1 = fs.File('../var1/test1')
153 f2 = fs.File('../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
158 test.subdir('work', ['work', 'src'])
159 test.subdir(['work', 'build'], ['work', 'build', 'var1'])
160 test.subdir(['work', 'build', 'var2'])
161 test.subdir('rep1', ['rep1', 'src'])
162 test.subdir(['rep1', 'build'], ['rep1', 'build', 'var1'])
163 test.subdir(['rep1', 'build', 'var2'])
165 # A source file in the source directory
166 test.write([ 'work', 'src', 'test.in' ], 'test.in')
168 # A source file in a subdir of the source directory
169 test.subdir([ 'work', 'src', 'new_dir' ])
170 test.write([ 'work', 'src', 'new_dir', 'test9.out' ], 'test9.out\n')
172 # A source file in the repository
173 test.write([ 'rep1', 'src', 'test2.in' ], 'test2.in')
175 # Some source files in the variant directory
176 test.write([ 'work', 'build', 'var2', 'test.in' ], 'test.old')
177 test.write([ 'work', 'build', 'var2', 'test2.in' ], 'test2.old')
179 # An old derived file in the variant directories
180 test.write([ 'work', 'build', 'var1', 'test.out' ], 'test.old')
181 test.write([ 'work', 'build', 'var2', 'test.out' ], 'test.old')
183 # And just in case we are weird, a derived file in the source
185 test.write([ 'work', 'src', 'test.out' ], 'test.out.src')
187 # A derived file in the repository
188 test.write([ 'rep1', 'build', 'var1', 'test2.out' ], 'test2.out_rep')
189 test.write([ 'rep1', 'build', 'var2', 'test2.out' ], 'test2.out_rep')
191 os.chdir(test.workpath('work'))
193 fs = SCons.Node.FS.FS(test.workpath('work'))
194 fs.VariantDir('build/var1', 'src', duplicate=0)
195 fs.VariantDir('build/var2', 'src')
196 f1 = fs.File('build/var1/test.in')
197 f1out = fs.File('build/var1/test.out')
199 f1out_2 = fs.File('build/var1/test2.out')
201 f2 = fs.File('build/var2/test.in')
202 f2out = fs.File('build/var2/test.out')
204 f2out_2 = fs.File('build/var2/test2.out')
206 fs.Repository(test.workpath('rep1'))
208 assert f1.srcnode().path == os.path.normpath('src/test.in'),\
210 # str(node) returns source path for duplicate = 0
211 assert str(f1) == os.path.normpath('src/test.in'), str(f1)
212 # Build path does not exist
213 assert not f1.exists()
214 # ...but the actual file is not there...
215 assert not os.path.exists(f1.get_abspath())
216 # And duplicate=0 should also work just like a Repository
218 # rfile() should point to the source path
219 assert f1.rfile().path == os.path.normpath('src/test.in'),\
222 assert f2.srcnode().path == os.path.normpath('src/test.in'),\
224 # str(node) returns build path for duplicate = 1
225 assert str(f2) == os.path.normpath('build/var2/test.in'), str(f2)
228 # ...and exists() should copy the file from src to build path
229 assert test.read(['work', 'build', 'var2', 'test.in']) == 'test.in',\
230 test.read(['work', 'build', 'var2', 'test.in'])
231 # Since exists() is true, so should rexists() be
234 f3 = fs.File('build/var1/test2.in')
235 f4 = fs.File('build/var2/test2.in')
237 assert f3.srcnode().path == os.path.normpath('src/test2.in'),\
239 # str(node) returns source path for duplicate = 0
240 assert str(f3) == os.path.normpath('src/test2.in'), str(f3)
241 # Build path does not exist
242 assert not f3.exists()
243 # Source path does not either
244 assert not f3.srcnode().exists()
245 # But we do have a file in the Repository
247 # rfile() should point to the source path
248 assert f3.rfile().path == os.path.normpath(test.workpath('rep1/src/test2.in')),\
251 assert f4.srcnode().path == os.path.normpath('src/test2.in'),\
253 # str(node) returns build path for duplicate = 1
254 assert str(f4) == os.path.normpath('build/var2/test2.in'), str(f4)
255 # Build path should exist
257 # ...and copy over the file into the local build path
258 assert test.read(['work', 'build', 'var2', 'test2.in']) == 'test2.in'
259 # should exist in repository, since exists() is true
261 # rfile() should point to ourselves
262 assert f4.rfile().path == os.path.normpath('build/var2/test2.in'),\
265 f5 = fs.File('build/var1/test.out')
266 f6 = fs.File('build/var2/test.out')
269 # We should not copy the file from the source dir, since this is
271 assert test.read(['work', 'build', 'var1', 'test.out']) == 'test.old'
274 # We should not copy the file from the source dir, since this is
276 assert test.read(['work', 'build', 'var2', 'test.out']) == 'test.old'
278 f7 = fs.File('build/var1/test2.out')
279 f8 = fs.File('build/var2/test2.out')
281 assert not f7.exists()
284 expect = os.path.normpath(test.workpath('rep1/build/var1/test2.out'))
285 assert r == expect, (repr(r), repr(expect))
287 assert not f8.exists()
289 assert f8.rfile().path == os.path.normpath(test.workpath('rep1/build/var2/test2.out')),\
292 # Verify the Mkdir and Link actions are called
293 d9 = fs.Dir('build/var2/new_dir')
294 f9 = fs.File('build/var2/new_dir/test9.out')
296 class MkdirAction(Action):
297 def __init__(self, dir_made):
298 self.dir_made = dir_made
299 def __call__(self, target, source, env, executor=None):
301 target = executor.get_all_targets()
302 source = executor.get_all_sources()
303 self.dir_made.extend(target)
305 save_Link = SCons.Node.FS.Link
307 def link_func(target, source, env, link_made=link_made):
308 link_made.append(target)
309 SCons.Node.FS.Link = link_func
313 d9.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
316 expect = os.path.join('build', 'var2', 'new_dir')
317 assert dir_made[0].path == expect, dir_made[0].path
318 expect = os.path.join('build', 'var2', 'new_dir', 'test9.out')
319 assert link_made[0].path == expect, link_made[0].path
322 SCons.Node.FS.Link = save_Link
324 # Test for an interesting pathological case...we have a source
325 # file in a build path, but not in a source path. This can
326 # happen if you switch from duplicate=1 to duplicate=0, then
327 # delete a source file. At one time, this would cause exists()
328 # to return a 1 but get_contents() to throw.
329 test.write([ 'work', 'build', 'var1', 'asourcefile' ], 'stuff')
330 f10 = fs.File('build/var1/asourcefile')
332 assert f10.get_contents() == 'stuff', f10.get_contents()
334 f11 = fs.File('src/file11')
335 t, m = f11.alter_targets()
336 bdt = [n.path for n in t]
337 var1_file11 = os.path.normpath('build/var1/file11')
338 var2_file11 = os.path.normpath('build/var2/file11')
339 assert bdt == [var1_file11, var2_file11], bdt
341 f12 = fs.File('src/file12')
343 bdt, m = f12.alter_targets()
344 assert bdt == [], [n.path for n in bdt]
346 d13 = fs.Dir('src/new_dir')
347 t, m = d13.alter_targets()
348 bdt = [n.path for n in t]
349 var1_new_dir = os.path.normpath('build/var1/new_dir')
350 var2_new_dir = os.path.normpath('build/var2/new_dir')
351 assert bdt == [var1_new_dir, var2_new_dir], bdt
353 # Test that an IOError trying to Link a src file
354 # into a VariantDir ends up throwing a StopError.
355 fIO = fs.File("build/var2/IOError")
357 save_Link = SCons.Node.FS.Link
358 def Link_IOError(target, source, env):
359 raise IOError, (17, "Link_IOError")
360 SCons.Node.FS.Link = SCons.Action.Action(Link_IOError, None)
362 test.write(['work', 'src', 'IOError'], "work/src/IOError\n")
368 except SCons.Errors.StopError:
370 assert exc_caught, "Should have caught a StopError"
373 SCons.Node.FS.Link = save_Link
375 # Test to see if Link() works...
376 test.subdir('src','build')
377 test.write('src/foo', 'src/foo\n')
378 os.chmod(test.workpath('src/foo'), stat.S_IRUSR)
379 SCons.Node.FS.Link(fs.File(test.workpath('build/foo')),
380 fs.File(test.workpath('src/foo')),
382 os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE)
383 st=os.stat(test.workpath('build/foo'))
384 assert (stat.S_IMODE(st[stat.ST_MODE]) & stat.S_IWRITE), \
385 stat.S_IMODE(st[stat.ST_MODE])
387 # This used to generate a UserError when we forbid the source
388 # directory from being outside the top-level SConstruct dir.
389 fs = SCons.Node.FS.FS()
390 fs.VariantDir('build', '/test/foo')
395 fs = SCons.Node.FS.FS()
396 fs.VariantDir('build', 'build/src')
397 except SCons.Errors.UserError:
399 assert exc_caught, "Should have caught a UserError."
401 test.unlink( "src/foo" )
402 test.unlink( "build/foo" )
404 fs = SCons.Node.FS.FS()
405 fs.VariantDir('build', 'src1')
407 # Calling the same VariantDir twice should work fine.
408 fs.VariantDir('build', 'src1')
410 # Trying to move a variant dir to a second source dir
413 fs.VariantDir('build', 'src2')
414 except SCons.Errors.UserError:
417 assert 0, "Should have caught a UserError."
419 # Test against a former bug. Make sure we can get a repository
420 # path for the variant directory itself!
421 fs=SCons.Node.FS.FS(test.workpath('work'))
423 fs.VariantDir('build/var3', 'src', duplicate=0)
424 d1 = fs.Dir('build/var3')
426 assert r == d1, "%s != %s" % (r, d1)
428 # verify the link creation attempts in file_link()
429 class LinkSimulator :
430 """A class to intercept os.[sym]link() calls and track them."""
432 def __init__( self, duplicate, link, symlink, copy ) :
433 self.duplicate = duplicate
435 self.have['hard'] = link
436 self.have['soft'] = symlink
437 self.have['copy'] = copy
439 self.links_to_be_called = []
440 for link in self.duplicate.split('-'):
442 self.links_to_be_called.append(link)
444 def link_fail( self , src , dest ) :
445 next_link = self.links_to_be_called.pop(0)
446 assert next_link == "hard", \
447 "Wrong link order: expected %s to be called "\
448 "instead of hard" % next_link
449 raise OSError( "Simulating hard link creation error." )
451 def symlink_fail( self , src , dest ) :
452 next_link = self.links_to_be_called.pop(0)
453 assert next_link == "soft", \
454 "Wrong link order: expected %s to be called "\
455 "instead of soft" % next_link
456 raise OSError( "Simulating symlink creation error." )
458 def copy( self , src , dest ) :
459 next_link = self.links_to_be_called.pop(0)
460 assert next_link == "copy", \
461 "Wrong link order: expected %s to be called "\
462 "instead of copy" % next_link
463 # copy succeeds, but use the real copy
464 self.have['copy'](src, dest)
465 # end class LinkSimulator
468 SCons.Node.FS.set_duplicate("no-link-order")
469 assert 0, "Expected exception when passing an invalid duplicate to set_duplicate"
470 except SCons.Errors.InternalError:
473 for duplicate in SCons.Node.FS.Valid_Duplicates:
474 # save the real functions for later restoration
477 except AttributeError:
480 real_symlink = os.symlink
481 except AttributeError:
483 real_copy = shutil.copy2
485 simulator = LinkSimulator(duplicate, real_link, real_symlink, real_copy)
487 # override the real functions with our simulation
488 os.link = simulator.link_fail
489 os.symlink = simulator.symlink_fail
490 shutil.copy2 = simulator.copy
494 SCons.Node.FS.set_duplicate(duplicate)
496 src_foo = test.workpath('src', 'foo')
497 build_foo = test.workpath('build', 'foo')
499 test.write(src_foo, 'src/foo\n')
500 os.chmod(src_foo, stat.S_IRUSR)
502 SCons.Node.FS.Link(fs.File(build_foo),
506 os.chmod(src_foo, stat.S_IRUSR | stat.S_IWRITE)
508 test.unlink(build_foo)
511 # restore the real functions
517 os.symlink = real_symlink
519 delattr(os, 'symlink')
520 shutil.copy2 = real_copy
522 # Test VariantDir "reflection," where a same-named subdirectory
523 # exists underneath a variant_dir.
524 fs = SCons.Node.FS.FS()
525 fs.VariantDir('work/src/b1/b2', 'work/src')
532 'work/src/b1/b2/b1/b2',
533 'work/src/b1/b2/b1/b2/b1',
534 'work/src/b1/b2/b1/b2/b1/b2',
538 'work/src/b1/b2' : 'work/src',
539 'work/src/b1/b2/f' : 'work/src/f',
540 'work/src/b1/b2/b1' : 'work/src/b1/',
541 'work/src/b1/b2/b1/f' : 'work/src/b1/f',
542 'work/src/b1/b2/b1/b2' : 'work/src/b1/b2',
543 'work/src/b1/b2/b1/b2/f' : 'work/src/b1/b2/f',
544 'work/src/b1/b2/b1/b2/b1' : 'work/src/b1/b2/b1',
545 'work/src/b1/b2/b1/b2/b1/f' : 'work/src/b1/b2/b1/f',
546 'work/src/b1/b2/b1/b2/b1/b2' : 'work/src/b1/b2/b1/b2',
547 'work/src/b1/b2/b1/b2/b1/b2/f' : 'work/src/b1/b2/b1/b2/f',
551 'work/src' : 'work/src/b1/b2',
552 'work/src/f' : 'work/src/b1/b2/f',
553 'work/src/b1' : 'work/src/b1/b2/b1',
554 'work/src/b1/f' : 'work/src/b1/b2/b1/f',
562 fnode = fs.File(dir + '/f')
564 dp = dnode.srcnode().path
565 expect = os.path.normpath(srcnode_map.get(dir, dir))
567 print "Dir `%s' srcnode() `%s' != expected `%s'" % (dir, dp, expect)
570 fp = fnode.srcnode().path
571 expect = os.path.normpath(srcnode_map.get(f, f))
573 print "File `%s' srcnode() `%s' != expected `%s'" % (f, fp, expect)
579 fnode = fs.File(dir + '/f')
581 t, m = dnode.alter_targets()
583 expect = os.path.normpath(alter_map.get(dir, dir))
585 print "Dir `%s' alter_targets() `%s' != expected `%s'" % (dir, tp, expect)
588 t, m = fnode.alter_targets()
590 expect = os.path.normpath(alter_map.get(f, f))
592 print "File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect)
597 class BaseTestCase(_tempdirTestCase):
599 """Test the Base.stat() method"""
601 test.write("e1", "e1\n")
602 fs = SCons.Node.FS.FS()
606 assert s is not None, s
612 def test_getmtime(self):
613 """Test the Base.getmtime() method"""
615 test.write("file", "file\n")
616 fs = SCons.Node.FS.FS()
618 file = fs.Entry('file')
619 assert file.getmtime()
621 file = fs.Entry('nonexistent')
622 mtime = file.getmtime()
623 assert mtime is None, mtime
625 def test_getsize(self):
626 """Test the Base.getsize() method"""
628 test.write("file", "file\n")
629 fs = SCons.Node.FS.FS()
631 file = fs.Entry('file')
632 size = file.getsize()
633 assert size == 5, size
635 file = fs.Entry('nonexistent')
636 size = file.getsize()
637 assert size is None, size
639 def test_isdir(self):
640 """Test the Base.isdir() method"""
643 test.write("file", "file\n")
644 fs = SCons.Node.FS.FS()
646 dir = fs.Entry('dir')
649 file = fs.Entry('file')
650 assert not file.isdir()
652 nonexistent = fs.Entry('nonexistent')
653 assert not nonexistent.isdir()
655 def test_isfile(self):
656 """Test the Base.isfile() method"""
659 test.write("file", "file\n")
660 fs = SCons.Node.FS.FS()
662 dir = fs.Entry('dir')
663 assert not dir.isfile()
665 file = fs.Entry('file')
668 nonexistent = fs.Entry('nonexistent')
669 assert not nonexistent.isfile()
671 if hasattr(os, 'symlink'):
672 def test_islink(self):
673 """Test the Base.islink() method"""
676 test.write("file", "file\n")
677 test.symlink("symlink", "symlink")
678 fs = SCons.Node.FS.FS()
680 dir = fs.Entry('dir')
681 assert not dir.islink()
683 file = fs.Entry('file')
684 assert not file.islink()
686 symlink = fs.Entry('symlink')
687 assert symlink.islink()
689 nonexistent = fs.Entry('nonexistent')
690 assert not nonexistent.islink()
692 class DirNodeInfoTestCase(_tempdirTestCase):
693 def test___init__(self):
694 """Test DirNodeInfo initialization"""
695 ddd = self.fs.Dir('ddd')
696 ni = SCons.Node.FS.DirNodeInfo(ddd)
698 class DirBuildInfoTestCase(_tempdirTestCase):
699 def test___init__(self):
700 """Test DirBuildInfo initialization"""
701 ddd = self.fs.Dir('ddd')
702 bi = SCons.Node.FS.DirBuildInfo(ddd)
704 class FileNodeInfoTestCase(_tempdirTestCase):
705 def test___init__(self):
706 """Test FileNodeInfo initialization"""
707 fff = self.fs.File('fff')
708 ni = SCons.Node.FS.FileNodeInfo(fff)
709 assert isinstance(ni, SCons.Node.FS.FileNodeInfo)
711 def test_update(self):
712 """Test updating a File.NodeInfo with on-disk information"""
714 fff = self.fs.File('fff')
716 ni = SCons.Node.FS.FileNodeInfo(fff)
718 test.write('fff', "fff\n")
724 assert hasattr(ni, 'timestamp')
725 assert hasattr(ni, 'size')
732 mtime = st[stat.ST_MTIME]
733 assert ni.timestamp == mtime, (ni.timestamp, mtime)
734 size = st[stat.ST_SIZE]
735 assert ni.size == size, (ni.size, size)
740 test.write('fff', "fff longer size, different time stamp\n")
744 mtime = st[stat.ST_MTIME]
745 assert ni.timestamp != mtime, (ni.timestamp, mtime)
746 size = st[stat.ST_SIZE]
747 assert ni.size != size, (ni.size, size)
754 #mtime = st[stat.ST_MTIME]
755 #assert ni.timestamp == mtime, (ni.timestamp, mtime)
756 #size = st[stat.ST_SIZE]
757 #assert ni.size == size, (ni.size, size)
759 class FileBuildInfoTestCase(_tempdirTestCase):
760 def test___init__(self):
761 """Test File.BuildInfo initialization"""
762 fff = self.fs.File('fff')
763 bi = SCons.Node.FS.FileBuildInfo(fff)
766 def test_convert_to_sconsign(self):
767 """Test converting to .sconsign file format"""
768 fff = self.fs.File('fff')
769 bi = SCons.Node.FS.FileBuildInfo(fff)
770 assert hasattr(bi, 'convert_to_sconsign')
772 def test_convert_from_sconsign(self):
773 """Test converting from .sconsign file format"""
774 fff = self.fs.File('fff')
775 bi = SCons.Node.FS.FileBuildInfo(fff)
776 assert hasattr(bi, 'convert_from_sconsign')
778 def test_prepare_dependencies(self):
779 """Test that we have a prepare_dependencies() method"""
780 fff = self.fs.File('fff')
781 bi = SCons.Node.FS.FileBuildInfo(fff)
782 bi.prepare_dependencies()
784 def test_format(self):
785 """Test the format() method"""
786 f1 = self.fs.File('f1')
787 bi1 = SCons.Node.FS.FileBuildInfo(f1)
789 s1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n1'))
791 d1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n2'))
793 i1sig = SCons.Node.FS.FileNodeInfo(self.fs.File('n3'))
796 bi1.bsources = [self.fs.File('s1')]
797 bi1.bdepends = [self.fs.File('d1')]
798 bi1.bimplicit = [self.fs.File('i1')]
799 bi1.bsourcesigs = [s1sig]
800 bi1.bdependsigs = [d1sig]
801 bi1.bimplicitsigs = [i1sig]
803 bi1.bactsig = 'actionsig'
809 'actionsig [action]',
812 expect = '\n'.join(expect_lines)
813 format = bi1.format()
814 assert format == expect, (repr(expect), repr(format))
816 class FSTestCase(_tempdirTestCase):
817 def test_runTest(self):
818 """Test FS (file system) Node operations
820 This test case handles all of the file system node
821 tests in one environment, so we don't have to set up a
822 complicated directory structure for each test individually.
826 test.subdir('sub', ['sub', 'dir'])
828 wp = test.workpath('')
829 sub = test.workpath('sub', '')
830 sub_dir = test.workpath('sub', 'dir', '')
831 sub_dir_foo = test.workpath('sub', 'dir', 'foo', '')
832 sub_dir_foo_bar = test.workpath('sub', 'dir', 'foo', 'bar', '')
833 sub_foo = test.workpath('sub', 'foo', '')
837 fs = SCons.Node.FS.FS()
840 assert isinstance(e1, SCons.Node.FS.Entry)
843 assert isinstance(d1, SCons.Node.FS.Dir)
844 assert d1.cwd is d1, d1
846 f1 = fs.File('f1', directory = d1)
847 assert isinstance(f1, SCons.Node.FS.File)
849 d1_f1 = os.path.join('d1', 'f1')
850 assert f1.path == d1_f1, "f1.path %s != %s" % (f1.path, d1_f1)
851 assert str(f1) == d1_f1, "str(f1) %s != %s" % (str(f1), d1_f1)
854 assert isinstance(x1, SCons.Node.FS.File)
855 assert str(x1) == os.path.join('d1', 'x1')
858 assert isinstance(x2, SCons.Node.FS.Dir)
859 assert str(x2) == os.path.join('d1', 'x2')
862 assert isinstance(x3, SCons.Node.FS.Entry)
863 assert str(x3) == os.path.join('d1', 'x3')
865 assert d1.File(x1) == x1
866 assert d1.Dir(x2) == x2
867 assert d1.Entry(x3) == x3
872 assert str(x4) == os.path.join('d1', 'x4')
875 assert str(x5) == os.path.join('d1', 'x5')
878 assert str(x6) == os.path.join('d1', 'x6')
880 assert str(x7) == os.path.join('d1', 'x7')
882 assert x1.File(x4) == x4
883 assert x1.Dir(x5) == x5
884 assert x1.Entry(x6) == x6
885 assert x1.Entry(x7) == x7
887 assert x1.Entry(x5) == x5
893 raise Exception, "did not catch expected TypeError"
895 assert x1.Entry(x4) == x4
901 raise Exception, "did not catch expected TypeError"
904 assert isinstance(x6, SCons.Node.FS.File)
907 assert isinstance(x7, SCons.Node.FS.Dir)
913 drive, path = os.path.splitdrive(os.getcwd())
915 def _do_Dir_test(lpath, path_, abspath_, up_path_, sep, fileSys=fs, drive=drive):
916 dir = fileSys.Dir(lpath.replace('/', sep))
919 path_ = path_.replace('/', os.sep)
920 abspath_ = abspath_.replace('/', os.sep)
921 up_path_ = up_path_.replace('/', os.sep)
923 def strip_slash(p, drive=drive):
924 if p[-1] == os.sep and len(p) > 1:
929 path = strip_slash(path_)
930 abspath = strip_slash(abspath_)
931 up_path = strip_slash(up_path_)
932 name = abspath.split(os.sep)[-1]
934 assert dir.name == name, \
935 "dir.name %s != expected name %s" % \
937 assert dir.path == path, \
938 "dir.path %s != expected path %s" % \
940 assert str(dir) == path, \
941 "str(dir) %s != expected path %s" % \
943 assert dir.get_abspath() == abspath, \
944 "dir.abspath %s != expected absolute path %s" % \
945 (dir.get_abspath(), abspath)
946 assert dir.up().path == up_path, \
947 "dir.up().path %s != expected parent path %s" % \
948 (dir.up().path, up_path)
952 def Dir_test(lpath, path_, abspath_, up_path_, sep=sep, func=_do_Dir_test):
953 return func(lpath, path_, abspath_, up_path_, sep)
955 Dir_test('', './', sub_dir, sub)
956 Dir_test('foo', 'foo/', sub_dir_foo, './')
957 Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
958 Dir_test('/foo', '/foo/', '/foo/', '/')
959 Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/')
960 Dir_test('..', sub, sub, wp)
961 Dir_test('foo/..', './', sub_dir, sub)
962 Dir_test('../foo', sub_foo, sub_foo, sub)
963 Dir_test('.', './', sub_dir, sub)
964 Dir_test('./.', './', sub_dir, sub)
965 Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
966 Dir_test('#../foo', sub_foo, sub_foo, sub)
967 Dir_test('#/../foo', sub_foo, sub_foo, sub)
968 Dir_test('#foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
969 Dir_test('#/foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
970 Dir_test('#', './', sub_dir, sub)
973 f2 = fs.File(sep.join(['f1', 'f2']), directory = d1)
975 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
981 dir = fs.Dir(sep.join(['d1', 'f1']))
983 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
991 assert str(x) == ("Tried to lookup Dir '%s' as a File." %
996 # Test that just specifying the drive works to identify
997 # its root directory.
998 p = os.path.abspath(test.workpath('root_file'))
999 drive, path = os.path.splitdrive(p)
1001 # The assert below probably isn't correct for the general
1002 # case, but it works for Windows, which covers a lot
1005 assert str(dir) == drive + os.sep, str(dir)
1007 # Make sure that lookups with and without the drive are
1009 p = os.path.abspath(test.workpath('some/file'))
1010 drive, path = os.path.splitdrive(p)
1014 assert e1 is e2, (e1, e2)
1015 assert str(e1) is str(e2), (str(e1), str(e2))
1017 # Test for a bug in 0.04 that did not like looking up
1018 # dirs with a trailing slash on Windows.
1020 assert d.path == '.', d.abspath
1022 assert d.path == 'foo', d.abspath
1024 # Test for sub-classing of node building.
1029 d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
1030 d1.builder_set(Builder(fs.File))
1032 d1.env_set(Environment())
1038 f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
1039 f1.builder_set(Builder(fs.File))
1041 f1.env_set(Environment())
1045 def match(path, expect):
1046 expect = expect.replace('/', os.sep)
1047 assert path == expect, "path %s != expected %s" % (path, expect)
1050 assert e1.__class__.__name__ == 'Dir'
1051 match(e1.path, "d1")
1052 match(e1.dir.path, ".")
1054 e2 = fs.Entry("d1/f1")
1055 assert e2.__class__.__name__ == 'File'
1056 match(e2.path, "d1/f1")
1057 match(e2.dir.path, "d1")
1060 assert e3.__class__.__name__ == 'Entry'
1061 match(e3.path, "e3")
1062 match(e3.dir.path, ".")
1064 e4 = fs.Entry("d1/e4")
1065 assert e4.__class__.__name__ == 'Entry'
1066 match(e4.path, "d1/e4")
1067 match(e4.dir.path, "d1")
1069 e5 = fs.Entry("e3/e5")
1070 assert e3.__class__.__name__ == 'Dir'
1071 match(e3.path, "e3")
1072 match(e3.dir.path, ".")
1073 assert e5.__class__.__name__ == 'Entry'
1074 match(e5.path, "e3/e5")
1075 match(e5.dir.path, "e3")
1077 e6 = fs.Dir("d1/e4")
1079 assert e4.__class__.__name__ == 'Dir'
1080 match(e4.path, "d1/e4")
1081 match(e4.dir.path, "d1")
1083 e7 = fs.File("e3/e5")
1085 assert e5.__class__.__name__ == 'File'
1086 match(e5.path, "e3/e5")
1087 match(e5.dir.path, "e3")
1089 fs.chdir(fs.Dir('subdir'))
1090 f11 = fs.File("f11")
1091 match(f11.path, "subdir/f11")
1093 e13 = fs.Entry("subdir/e13")
1094 match(e13.path, "subdir/subdir/e13")
1095 fs.chdir(fs.Dir('..'))
1098 f1.builder_set(Builder(fs.File))
1099 f1.env_set(Environment())
1100 xyz = fs.File("xyz")
1101 f1.builder.target_scanner = Scanner(xyz)
1104 assert f1.implicit[0].path == "xyz"
1107 assert f1.implicit == []
1110 assert f1.implicit[0].path == "xyz"
1112 # Test underlying scanning functionality in get_found_includes()
1114 f12 = fs.File("f12")
1117 deps = f12.get_found_includes(env, None, t1)
1118 assert deps == [], deps
1120 class MyScanner(Scanner):
1122 def __call__(self, node, env, path):
1123 self.call_count = self.call_count + 1
1124 return Scanner.__call__(self, node, env, path)
1127 deps = f12.get_found_includes(env, s, t1)
1128 assert deps == [xyz], deps
1129 assert s.call_count == 1, s.call_count
1133 deps = f12.get_found_includes(env, s, t1)
1134 assert deps == [xyz], deps
1135 assert s.call_count == 2, s.call_count
1137 env2 = Environment()
1139 deps = f12.get_found_includes(env2, s, t1)
1140 assert deps == [xyz], deps
1141 assert s.call_count == 3, s.call_count
1145 # Make sure we can scan this file even if the target isn't
1146 # a file that has a scanner (it might be an Alias, e.g.).
1150 deps = f12.get_found_includes(env, s, DummyNode())
1151 assert deps == [xyz], deps
1153 # Test building a file whose directory is not there yet...
1154 f1 = fs.File(test.workpath("foo/bar/baz/ack"))
1155 assert not f1.dir.exists()
1158 assert f1.dir.exists()
1163 fs = SCons.Node.FS.FS()
1164 assert str(fs.getcwd()) == ".", str(fs.getcwd())
1165 fs.chdir(fs.Dir('subdir'))
1166 # The cwd's path is always "."
1167 assert str(fs.getcwd()) == ".", str(fs.getcwd())
1168 assert fs.getcwd().path == 'subdir', fs.getcwd().path
1169 fs.chdir(fs.Dir('../..'))
1170 assert fs.getcwd().path == test.workdir, fs.getcwd().path
1172 f1 = fs.File(test.workpath("do_i_exist"))
1173 assert not f1.exists()
1174 test.write("do_i_exist","\n")
1175 assert not f1.exists(), "exists() call not cached"
1177 assert f1.exists(), "exists() call caching not reset"
1178 test.unlink("do_i_exist")
1181 assert not f1.exists()
1183 # For some reason, in Windows, the \x1a character terminates
1184 # the reading of files in text mode. This tests that
1185 # get_contents() returns the binary contents.
1186 test.write("binary_file", "Foo\x1aBar")
1187 f1 = fs.File(test.workpath("binary_file"))
1188 assert f1.get_contents() == "Foo\x1aBar", f1.get_contents()
1192 eval('test_string = u"Foo\x1aBar"')
1196 # This tests to make sure we can decode UTF-8 text files.
1197 test.write("utf8_file", test_string.encode('utf-8'))
1198 f1 = fs.File(test.workpath("utf8_file"))
1199 assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \
1200 f1.get_text_contents()
1202 def nonexistent(method, s):
1204 x = method(s, create = 0)
1205 except SCons.Errors.UserError:
1208 raise Exception, "did not catch expected UserError"
1210 nonexistent(fs.Entry, 'nonexistent')
1211 nonexistent(fs.Entry, 'nonexistent/foo')
1213 nonexistent(fs.File, 'nonexistent')
1214 nonexistent(fs.File, 'nonexistent/foo')
1216 nonexistent(fs.Dir, 'nonexistent')
1217 nonexistent(fs.Dir, 'nonexistent/foo')
1219 test.write("preserve_me", "\n")
1220 assert os.path.exists(test.workpath("preserve_me"))
1221 f1 = fs.File(test.workpath("preserve_me"))
1223 assert os.path.exists(test.workpath("preserve_me"))
1225 test.write("remove_me", "\n")
1226 assert os.path.exists(test.workpath("remove_me"))
1227 f1 = fs.File(test.workpath("remove_me"))
1228 f1.builder = Builder(fs.File)
1229 f1.env_set(Environment())
1231 assert not os.path.exists(test.workpath("remove_me"))
1233 e = fs.Entry('e_local')
1234 assert not hasattr(e, '_local')
1236 assert e._local == 1
1237 f = fs.File('e_local')
1238 assert f._local == 1
1239 f = fs.File('f_local')
1240 assert f._local == 0
1242 #XXX test_is_up_to_date() for directories
1244 #XXX test_sconsign() for directories
1246 #XXX test_set_signature() for directories
1248 #XXX test_build() for directories
1252 # test Entry.get_contents()
1253 e = fs.Entry('does_not_exist')
1254 c = e.get_contents()
1256 assert e.__class__ == SCons.Node.FS.Entry
1258 test.write("file", "file\n")
1260 e = fs.Entry('file')
1261 c = e.get_contents()
1262 assert c == "file\n", c
1263 assert e.__class__ == SCons.Node.FS.File
1267 # test Entry.get_text_contents()
1268 e = fs.Entry('does_not_exist')
1269 c = e.get_text_contents()
1271 assert e.__class__ == SCons.Node.FS.Entry
1273 test.write("file", "file\n")
1275 e = fs.Entry('file')
1276 c = e.get_text_contents()
1277 assert c == "file\n", c
1278 assert e.__class__ == SCons.Node.FS.File
1284 c = e.get_contents()
1286 assert e.__class__ == SCons.Node.FS.Dir
1288 c = e.get_text_contents()
1290 eval('assert c == u"", c')
1294 if hasattr(os, 'symlink'):
1295 os.symlink('nonexistent', test.workpath('dangling_symlink'))
1296 e = fs.Entry('dangling_symlink')
1297 c = e.get_contents()
1298 assert e.__class__ == SCons.Node.FS.Entry, e.__class__
1300 c = e.get_text_contents()
1302 eval('assert c == u"", c')
1306 test.write("tstamp", "tstamp\n")
1308 # Okay, *this* manipulation accomodates Windows FAT file systems
1309 # that only have two-second granularity on their timestamps.
1310 # We round down the current time to the nearest even integer
1311 # value, subtract two to make sure the timestamp is not "now,"
1312 # and then convert it back to a float.
1313 tstamp = float(int(time.time() / 2) * 2) - 2
1314 os.utime(test.workpath("tstamp"), (tstamp - 2.0, tstamp))
1315 f = fs.File("tstamp")
1316 t = f.get_timestamp()
1317 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
1319 test.unlink("tstamp")
1321 test.subdir('tdir1')
1323 t = d.get_timestamp()
1324 assert t == 0, "expected 0, got %s" % str(t)
1326 test.subdir('tdir2')
1327 f1 = test.workpath('tdir2', 'file1')
1328 f2 = test.workpath('tdir2', 'file2')
1329 test.write(f1, 'file1\n')
1330 test.write(f2, 'file2\n')
1331 current_time = float(int(time.time() / 2) * 2)
1332 t1 = current_time - 4.0
1333 t2 = current_time - 2.0
1334 os.utime(f1, (t1 - 2.0, t1))
1335 os.utime(f2, (t2 - 2.0, t2))
1339 t = d.get_timestamp()
1340 assert t == t2, "expected %f, got %f" % (t2, t)
1342 skey = fs.Entry('eee.x').scanner_key()
1343 assert skey == '.x', skey
1344 skey = fs.Entry('eee.xyz').scanner_key()
1345 assert skey == '.xyz', skey
1347 skey = fs.File('fff.x').scanner_key()
1348 assert skey == '.x', skey
1349 skey = fs.File('fff.xyz').scanner_key()
1350 assert skey == '.xyz', skey
1352 skey = fs.Dir('ddd.x').scanner_key()
1353 assert skey is None, skey
1355 test.write("i_am_not_a_directory", "\n")
1359 fs.Dir(test.workpath("i_am_not_a_directory"))
1362 assert exc_caught, "Should have caught a TypeError"
1364 test.unlink("i_am_not_a_directory")
1371 assert exc_caught, "Should have caught a TypeError"
1373 # XXX test_is_up_to_date()
1379 f = fs.File('does_not_exist')
1383 test.write('exists', "exists\n")
1384 f = fs.File('exists')
1387 assert not os.path.exists(test.workpath('exists')), "exists was not removed"
1389 symlink = test.workpath('symlink')
1391 os.symlink(test.workpath('does_not_exist'), symlink)
1392 assert os.path.islink(symlink)
1393 f = fs.File('symlink')
1396 assert not os.path.islink(symlink), "symlink was not removed"
1397 except AttributeError:
1400 test.write('can_not_remove', "can_not_remove\n")
1401 test.writable(test.workpath('.'), 0)
1402 fp = open(test.workpath('can_not_remove'))
1404 f = fs.File('can_not_remove')
1413 assert exc_caught, "Should have caught an OSError, r = " + str(r)
1415 f = fs.Entry('foo/bar/baz')
1416 assert f.for_signature() == 'baz', f.for_signature()
1417 assert f.get_string(0) == os.path.normpath('foo/bar/baz'), \
1419 assert f.get_string(1) == 'baz', f.get_string(1)
1421 def test_drive_letters(self):
1422 """Test drive-letter look-ups"""
1426 test.subdir('sub', ['sub', 'dir'])
1428 def drive_workpath(drive, dirs, test=test):
1429 x = test.workpath(*dirs)
1430 drive, path = os.path.splitdrive(x)
1433 wp = drive_workpath('X:', [''])
1435 if wp[-1] in (os.sep, '/'):
1436 tmp = os.path.split(wp[:-1])[0]
1438 tmp = os.path.split(wp)[0]
1440 parent_tmp = os.path.split(tmp)[0]
1441 if parent_tmp == 'X:':
1442 parent_tmp = 'X:' + os.sep
1444 tmp_foo = os.path.join(tmp, 'foo')
1446 foo = drive_workpath('X:', ['foo'])
1447 foo_bar = drive_workpath('X:', ['foo', 'bar'])
1448 sub = drive_workpath('X:', ['sub', ''])
1449 sub_dir = drive_workpath('X:', ['sub', 'dir', ''])
1450 sub_dir_foo = drive_workpath('X:', ['sub', 'dir', 'foo', ''])
1451 sub_dir_foo_bar = drive_workpath('X:', ['sub', 'dir', 'foo', 'bar', ''])
1452 sub_foo = drive_workpath('X:', ['sub', 'foo', ''])
1454 fs = SCons.Node.FS.FS()
1460 def _do_Dir_test(lpath, path_, up_path_, sep, fileSys=fs):
1461 dir = fileSys.Dir(lpath.replace('/', sep))
1464 path_ = path_.replace('/', os.sep)
1465 up_path_ = up_path_.replace('/', os.sep)
1468 if p[-1] == os.sep and len(p) > 3:
1471 path = strip_slash(path_)
1472 up_path = strip_slash(up_path_)
1473 name = path.split(os.sep)[-1]
1475 assert dir.name == name, \
1476 "dir.name %s != expected name %s" % \
1478 assert dir.path == path, \
1479 "dir.path %s != expected path %s" % \
1481 assert str(dir) == path, \
1482 "str(dir) %s != expected path %s" % \
1484 assert dir.up().path == up_path, \
1485 "dir.up().path %s != expected parent path %s" % \
1486 (dir.up().path, up_path)
1488 save_os_path = os.path
1489 save_os_sep = os.sep
1494 SCons.Node.FS.initialize_do_splitdrive()
1495 SCons.Node.FS.initialize_normpath_check()
1499 def Dir_test(lpath, path_, up_path_, sep=sep, func=_do_Dir_test):
1500 return func(lpath, path_, up_path_, sep)
1502 Dir_test('#X:', wp, tmp)
1503 Dir_test('X:foo', foo, wp)
1504 Dir_test('X:foo/bar', foo_bar, foo)
1505 Dir_test('X:/foo', 'X:/foo', 'X:/')
1506 Dir_test('X:/foo/bar', 'X:/foo/bar/', 'X:/foo/')
1507 Dir_test('X:..', tmp, parent_tmp)
1508 Dir_test('X:foo/..', wp, tmp)
1509 Dir_test('X:../foo', tmp_foo, tmp)
1510 Dir_test('X:.', wp, tmp)
1511 Dir_test('X:./.', wp, tmp)
1512 Dir_test('X:foo/./bar', foo_bar, foo)
1513 Dir_test('#X:../foo', tmp_foo, tmp)
1514 Dir_test('#X:/../foo', tmp_foo, tmp)
1515 Dir_test('#X:foo/bar', foo_bar, foo)
1516 Dir_test('#X:/foo/bar', foo_bar, foo)
1517 Dir_test('#X:/', wp, tmp)
1519 os.path = save_os_path
1520 os.sep = save_os_sep
1521 SCons.Node.FS.initialize_do_splitdrive()
1522 SCons.Node.FS.initialize_normpath_check()
1524 def test_target_from_source(self):
1525 """Test the method for generating target nodes from sources"""
1529 t = x.target_from_source('pre-', '-suf')
1530 assert str(t) == 'pre-x-suf', str(t)
1531 assert t.__class__ == SCons.Node.FS.Entry
1533 y = fs.File('dir/y')
1534 t = y.target_from_source('pre-', '-suf')
1535 assert str(t) == os.path.join('dir', 'pre-y-suf'), str(t)
1536 assert t.__class__ == SCons.Node.FS.Entry
1539 t = z.target_from_source('pre-', '-suf', lambda x: x[:-1])
1540 assert str(t) == 'pre-z-suf', str(t)
1541 assert t.__class__ == SCons.Node.FS.Entry
1544 t = d.target_from_source('pre-', '-suf')
1545 assert str(t) == 'pre-ddd-suf', str(t)
1546 assert t.__class__ == SCons.Node.FS.Entry
1549 t = e.target_from_source('pre-', '-suf')
1550 assert str(t) == 'pre-eee-suf', str(t)
1551 assert t.__class__ == SCons.Node.FS.Entry
1553 def test_same_name(self):
1554 """Test that a local same-named file isn't found for a Dir lookup"""
1558 test.subdir('subdir')
1559 test.write(['subdir', 'build'], "subdir/build\n")
1561 subdir = fs.Dir('subdir')
1562 fs.chdir(subdir, change_os_dir=1)
1563 self.fs._lookup('#build/file', subdir, SCons.Node.FS.File)
1565 def test_above_root(self):
1566 """Testing looking up a path above the root directory"""
1572 dirs = os.path.normpath(d2.abspath).split(os.sep)
1573 above_path = os.path.join(*['..']*len(dirs) + ['above'])
1574 above = d2.Dir(above_path)
1576 def test_rel_path(self):
1577 """Test the rel_path() method"""
1583 d1_d2 = d1.Dir('d2')
1584 d1_d2_f = d1_d2.File('f')
1588 d3_d4 = d3.Dir('d4')
1589 d3_d4_f = d3_d4.File('f')
1595 d1, d1_d2_f, 'd2/f',
1597 d1, d3_f, '../d3/f',
1598 d1, d3_d4, '../d3/d4',
1599 d1, d3_d4_f, '../d3/d4/f',
1604 d1_f, d1_d2_f, 'd2/f',
1606 d1_f, d3_f, '../d3/f',
1607 d1_f, d3_d4, '../d3/d4',
1608 d1_f, d3_d4_f, '../d3/d4/f',
1611 d1_d2, d1_f, '../f',
1613 d1_d2, d1_d2_f, 'f',
1614 d1_d2, d3, '../../d3',
1615 d1_d2, d3_f, '../../d3/f',
1616 d1_d2, d3_d4, '../../d3/d4',
1617 d1_d2, d3_d4_f, '../../d3/d4/f',
1620 d1_d2_f, d1_f, '../f',
1621 d1_d2_f, d1_d2, '.',
1622 d1_d2_f, d1_d2_f, 'f',
1623 d1_d2_f, d3, '../../d3',
1624 d1_d2_f, d3_f, '../../d3/f',
1625 d1_d2_f, d3_d4, '../../d3/d4',
1626 d1_d2_f, d3_d4_f, '../../d3/d4/f',
1629 if sys.platform in ('win32',):
1630 x_d1 = fs.Dir(r'X:\d1')
1631 x_d1_d2 = x_d1.Dir('d2')
1632 y_d1 = fs.Dir(r'Y:\d1')
1633 y_d1_d2 = y_d1.Dir('d2')
1634 y_d2 = fs.Dir(r'Y:\d2')
1638 x_d1, x_d1_d2, 'd2',
1639 x_d1, y_d1, r'Y:\d1',
1640 x_d1, y_d1_d2, r'Y:\d1\d2',
1641 x_d1, y_d2, r'Y:\d2',
1644 cases.extend(win32_cases)
1648 dir, other, expect = cases[:3]
1649 expect = os.path.normpath(expect)
1651 result = dir.rel_path(other)
1652 if result != expect:
1653 if failed == 0: print
1654 fmt = " dir_path(%(dir)s, %(other)s) => '%(result)s' did not match '%(expect)s'"
1655 print fmt % locals()
1657 assert failed == 0, "%d rel_path() cases failed" % failed
1659 def test_proxy(self):
1660 """Test a Node.FS object wrapped in a proxy instance"""
1661 f1 = self.fs.File('fff')
1663 # Simplest possibly Proxy class that works for our test,
1664 # this is stripped down from SCons.Util.Proxy.
1665 def __init__(self, subject):
1666 self.__subject = subject
1667 def __getattr__(self, name):
1668 return getattr(self.__subject, name)
1670 f2 = self.fs.Entry(p)
1671 assert f1 is f2, (f1, f2)
1675 class DirTestCase(_tempdirTestCase):
1677 def test__morph(self):
1678 """Test handling of actions when morphing an Entry into a Dir"""
1680 e = self.fs.Entry('eee')
1681 x = e.get_executor()
1682 x.add_pre_action('pre')
1683 x.add_post_action('post')
1684 e.must_be_same(SCons.Node.FS.Dir)
1685 a = x.get_action_list()
1686 assert a[0] == 'pre', a
1687 assert a[2] == 'post', a
1689 def test_subclass(self):
1690 """Test looking up subclass of Dir nodes"""
1691 class DirSubclass(SCons.Node.FS.Dir):
1693 sd = self.fs._lookup('special_dir', None, DirSubclass, create=1)
1694 sd.must_be_same(SCons.Node.FS.Dir)
1696 def test_get_env_scanner(self):
1697 """Test the Dir.get_env_scanner() method
1699 import SCons.Defaults
1700 d = self.fs.Dir('ddd')
1701 s = d.get_env_scanner(Environment())
1702 assert s is SCons.Defaults.DirEntryScanner, s
1704 def test_get_target_scanner(self):
1705 """Test the Dir.get_target_scanner() method
1707 import SCons.Defaults
1708 d = self.fs.Dir('ddd')
1709 s = d.get_target_scanner()
1710 assert s is SCons.Defaults.DirEntryScanner, s
1712 def test_scan(self):
1713 """Test scanning a directory for in-memory entries
1718 fs.File(os.path.join('ddd', 'f1'))
1719 fs.File(os.path.join('ddd', 'f2'))
1720 fs.File(os.path.join('ddd', 'f3'))
1721 fs.Dir(os.path.join('ddd', 'd1'))
1722 fs.Dir(os.path.join('ddd', 'd1', 'f4'))
1723 fs.Dir(os.path.join('ddd', 'd1', 'f5'))
1725 kids = sorted([x.path for x in dir.children(None)])
1726 assert kids == [os.path.join('ddd', 'd1'),
1727 os.path.join('ddd', 'f1'),
1728 os.path.join('ddd', 'f2'),
1729 os.path.join('ddd', 'f3')], kids
1731 def test_get_contents(self):
1732 """Test getting the contents for a directory.
1737 test.write(['d', 'g'], "67890\n")
1738 test.write(['d', 'f'], "12345\n")
1739 test.subdir(['d','sub'])
1740 test.write(['d', 'sub','h'], "abcdef\n")
1741 test.subdir(['d','empty'])
1743 d = self.fs.Dir('d')
1744 g = self.fs.File(os.path.join('d', 'g'))
1745 f = self.fs.File(os.path.join('d', 'f'))
1746 h = self.fs.File(os.path.join('d', 'sub', 'h'))
1747 e = self.fs.Dir(os.path.join('d', 'empty'))
1748 s = self.fs.Dir(os.path.join('d', 'sub'))
1750 #TODO(1.5) files = d.get_contents().split('\n')
1751 files = d.get_contents().split('\n')
1753 assert e.get_contents() == '', e.get_contents()
1754 assert e.get_text_contents() == '', e.get_text_contents()
1755 assert e.get_csig()+" empty" == files[0], files
1756 assert f.get_csig()+" f" == files[1], files
1757 assert g.get_csig()+" g" == files[2], files
1758 assert s.get_csig()+" sub" == files[3], files
1760 def test_implicit_re_scans(self):
1761 """Test that adding entries causes a directory to be re-scanned
1768 fs.File(os.path.join('ddd', 'f1'))
1770 kids = sorted([x.path for x in dir.children()])
1771 assert kids == [os.path.join('ddd', 'f1')], kids
1773 fs.File(os.path.join('ddd', 'f2'))
1775 kids = sorted([x.path for x in dir.children()])
1776 assert kids == [os.path.join('ddd', 'f1'),
1777 os.path.join('ddd', 'f2')], kids
1779 def test_entry_exists_on_disk(self):
1780 """Test the Dir.entry_exists_on_disk() method
1784 does_not_exist = self.fs.Dir('does_not_exist')
1785 assert not does_not_exist.entry_exists_on_disk('foo')
1788 test.write(['d', 'exists'], "d/exists\n")
1789 test.write(['d', 'Case-Insensitive'], "d/Case-Insensitive\n")
1791 d = self.fs.Dir('d')
1792 assert d.entry_exists_on_disk('exists')
1793 assert not d.entry_exists_on_disk('does_not_exist')
1795 if os.path.normcase("TeSt") != os.path.normpath("TeSt") or sys.platform == "cygwin":
1796 assert d.entry_exists_on_disk('case-insensitive')
1798 def test_srcdir_list(self):
1799 """Test the Dir.srcdir_list() method
1801 src = self.fs.Dir('src')
1802 bld = self.fs.Dir('bld')
1803 sub1 = bld.Dir('sub')
1804 sub2 = sub1.Dir('sub')
1805 sub3 = sub2.Dir('sub')
1806 self.fs.VariantDir(bld, src, duplicate=0)
1807 self.fs.VariantDir(sub2, src, duplicate=0)
1809 def check(result, expect):
1810 result = list(map(str, result))
1811 expect = list(map(os.path.normpath, expect))
1812 assert result == expect, result
1814 s = src.srcdir_list()
1817 s = bld.srcdir_list()
1820 s = sub1.srcdir_list()
1821 check(s, ['src/sub'])
1823 s = sub2.srcdir_list()
1824 check(s, ['src', 'src/sub/sub'])
1826 s = sub3.srcdir_list()
1827 check(s, ['src/sub', 'src/sub/sub/sub'])
1829 self.fs.VariantDir('src/b1/b2', 'src')
1831 b1_b2 = b1.Dir('b2')
1832 b1_b2_b1 = b1_b2.Dir('b1')
1833 b1_b2_b1_b2 = b1_b2_b1.Dir('b2')
1834 b1_b2_b1_b2_sub = b1_b2_b1_b2.Dir('sub')
1836 s = b1.srcdir_list()
1839 s = b1_b2.srcdir_list()
1842 s = b1_b2_b1.srcdir_list()
1843 check(s, ['src/b1'])
1845 s = b1_b2_b1_b2.srcdir_list()
1846 check(s, ['src/b1/b2'])
1848 s = b1_b2_b1_b2_sub.srcdir_list()
1849 check(s, ['src/b1/b2/sub'])
1851 def test_srcdir_duplicate(self):
1852 """Test the Dir.srcdir_duplicate() method
1857 test.write(['src0', 'exists'], "src0/exists\n")
1859 bld0 = self.fs.Dir('bld0')
1860 src0 = self.fs.Dir('src0')
1861 self.fs.VariantDir(bld0, src0, duplicate=0)
1863 n = bld0.srcdir_duplicate('does_not_exist')
1865 assert not os.path.exists(test.workpath('bld0', 'does_not_exist'))
1867 n = bld0.srcdir_duplicate('exists')
1868 assert str(n) == os.path.normpath('src0/exists'), str(n)
1869 assert not os.path.exists(test.workpath('bld0', 'exists'))
1872 test.write(['src1', 'exists'], "src0/exists\n")
1874 bld1 = self.fs.Dir('bld1')
1875 src1 = self.fs.Dir('src1')
1876 self.fs.VariantDir(bld1, src1, duplicate=1)
1878 n = bld1.srcdir_duplicate('does_not_exist')
1880 assert not os.path.exists(test.workpath('bld1', 'does_not_exist'))
1882 n = bld1.srcdir_duplicate('exists')
1883 assert str(n) == os.path.normpath('bld1/exists'), str(n)
1884 assert os.path.exists(test.workpath('bld1', 'exists'))
1886 def test_srcdir_find_file(self):
1887 """Test the Dir.srcdir_find_file() method
1891 return_true = lambda: 1
1894 test.write(['src0', 'on-disk-f1'], "src0/on-disk-f1\n")
1895 test.write(['src0', 'on-disk-f2'], "src0/on-disk-f2\n")
1896 test.write(['src0', 'on-disk-e1'], "src0/on-disk-e1\n")
1897 test.write(['src0', 'on-disk-e2'], "src0/on-disk-e2\n")
1899 bld0 = self.fs.Dir('bld0')
1900 src0 = self.fs.Dir('src0')
1901 self.fs.VariantDir(bld0, src0, duplicate=0)
1903 derived_f = src0.File('derived-f')
1904 derived_f.is_derived = return_true
1905 exists_f = src0.File('exists-f')
1906 exists_f.exists = return_true
1908 derived_e = src0.Entry('derived-e')
1909 derived_e.is_derived = return_true
1910 exists_e = src0.Entry('exists-e')
1911 exists_e.exists = return_true
1913 def check(result, expect):
1914 result = list(map(str, result))
1915 expect = list(map(os.path.normpath, expect))
1916 assert result == expect, result
1918 # First check from the source directory.
1919 n = src0.srcdir_find_file('does_not_exist')
1920 assert n == (None, None), n
1922 n = src0.srcdir_find_file('derived-f')
1923 check(n, ['src0/derived-f', 'src0'])
1924 n = src0.srcdir_find_file('exists-f')
1925 check(n, ['src0/exists-f', 'src0'])
1926 n = src0.srcdir_find_file('on-disk-f1')
1927 check(n, ['src0/on-disk-f1', 'src0'])
1929 n = src0.srcdir_find_file('derived-e')
1930 check(n, ['src0/derived-e', 'src0'])
1931 n = src0.srcdir_find_file('exists-e')
1932 check(n, ['src0/exists-e', 'src0'])
1933 n = src0.srcdir_find_file('on-disk-e1')
1934 check(n, ['src0/on-disk-e1', 'src0'])
1936 # Now check from the variant directory.
1937 n = bld0.srcdir_find_file('does_not_exist')
1938 assert n == (None, None), n
1940 n = bld0.srcdir_find_file('derived-f')
1941 check(n, ['src0/derived-f', 'bld0'])
1942 n = bld0.srcdir_find_file('exists-f')
1943 check(n, ['src0/exists-f', 'bld0'])
1944 n = bld0.srcdir_find_file('on-disk-f2')
1945 check(n, ['src0/on-disk-f2', 'bld0'])
1947 n = bld0.srcdir_find_file('derived-e')
1948 check(n, ['src0/derived-e', 'bld0'])
1949 n = bld0.srcdir_find_file('exists-e')
1950 check(n, ['src0/exists-e', 'bld0'])
1951 n = bld0.srcdir_find_file('on-disk-e2')
1952 check(n, ['src0/on-disk-e2', 'bld0'])
1955 test.write(['src1', 'on-disk-f1'], "src1/on-disk-f1\n")
1956 test.write(['src1', 'on-disk-f2'], "src1/on-disk-f2\n")
1957 test.write(['src1', 'on-disk-e1'], "src1/on-disk-e1\n")
1958 test.write(['src1', 'on-disk-e2'], "src1/on-disk-e2\n")
1960 bld1 = self.fs.Dir('bld1')
1961 src1 = self.fs.Dir('src1')
1962 self.fs.VariantDir(bld1, src1, duplicate=1)
1964 derived_f = src1.File('derived-f')
1965 derived_f.is_derived = return_true
1966 exists_f = src1.File('exists-f')
1967 exists_f.exists = return_true
1969 derived_e = src1.Entry('derived-e')
1970 derived_e.is_derived = return_true
1971 exists_e = src1.Entry('exists-e')
1972 exists_e.exists = return_true
1974 # First check from the source directory.
1975 n = src1.srcdir_find_file('does_not_exist')
1976 assert n == (None, None), n
1978 n = src1.srcdir_find_file('derived-f')
1979 check(n, ['src1/derived-f', 'src1'])
1980 n = src1.srcdir_find_file('exists-f')
1981 check(n, ['src1/exists-f', 'src1'])
1982 n = src1.srcdir_find_file('on-disk-f1')
1983 check(n, ['src1/on-disk-f1', 'src1'])
1985 n = src1.srcdir_find_file('derived-e')
1986 check(n, ['src1/derived-e', 'src1'])
1987 n = src1.srcdir_find_file('exists-e')
1988 check(n, ['src1/exists-e', 'src1'])
1989 n = src1.srcdir_find_file('on-disk-e1')
1990 check(n, ['src1/on-disk-e1', 'src1'])
1992 # Now check from the variant directory.
1993 n = bld1.srcdir_find_file('does_not_exist')
1994 assert n == (None, None), n
1996 n = bld1.srcdir_find_file('derived-f')
1997 check(n, ['bld1/derived-f', 'src1'])
1998 n = bld1.srcdir_find_file('exists-f')
1999 check(n, ['bld1/exists-f', 'src1'])
2000 n = bld1.srcdir_find_file('on-disk-f2')
2001 check(n, ['bld1/on-disk-f2', 'bld1'])
2003 n = bld1.srcdir_find_file('derived-e')
2004 check(n, ['bld1/derived-e', 'src1'])
2005 n = bld1.srcdir_find_file('exists-e')
2006 check(n, ['bld1/exists-e', 'src1'])
2007 n = bld1.srcdir_find_file('on-disk-e2')
2008 check(n, ['bld1/on-disk-e2', 'bld1'])
2010 def test_dir_on_disk(self):
2011 """Test the Dir.dir_on_disk() method"""
2012 self.test.subdir('sub', ['sub', 'exists'])
2013 self.test.write(['sub', 'file'], "self/file\n")
2014 sub = self.fs.Dir('sub')
2016 r = sub.dir_on_disk('does_not_exist')
2019 r = sub.dir_on_disk('exists')
2022 r = sub.dir_on_disk('file')
2025 def test_file_on_disk(self):
2026 """Test the Dir.file_on_disk() method"""
2027 self.test.subdir('sub', ['sub', 'dir'])
2028 self.test.write(['sub', 'exists'], "self/exists\n")
2029 sub = self.fs.Dir('sub')
2031 r = sub.file_on_disk('does_not_exist')
2034 r = sub.file_on_disk('exists')
2037 r = sub.file_on_disk('dir')
2040 class EntryTestCase(_tempdirTestCase):
2041 def test_runTest(self):
2042 """Test methods specific to the Entry sub-class.
2044 test = TestCmd(workdir='')
2045 # FS doesn't like the cwd to be something other than its root.
2046 os.chdir(test.workpath(""))
2048 fs = SCons.Node.FS.FS()
2052 assert e1.__class__ is SCons.Node.FS.File, e1.__class__
2055 test.write('e3f', "e3f\n")
2057 e3d = fs.Entry('e3d')
2059 assert e3d.__class__ is SCons.Node.FS.Dir, e3d.__class__
2061 e3f = fs.Entry('e3f')
2063 assert e3f.__class__ is SCons.Node.FS.File, e3f.__class__
2065 e3n = fs.Entry('e3n')
2067 assert e3n.__class__ is SCons.Node.FS.Entry, e3n.__class__
2070 test.write('e4f', "e4f\n")
2072 e4d = fs.Entry('e4d')
2073 exists = e4d.exists()
2074 assert e4d.__class__ is SCons.Node.FS.Dir, e4d.__class__
2075 assert exists, "e4d does not exist?"
2077 e4f = fs.Entry('e4f')
2078 exists = e4f.exists()
2079 assert e4f.__class__ is SCons.Node.FS.File, e4f.__class__
2080 assert exists, "e4f does not exist?"
2082 e4n = fs.Entry('e4n')
2083 exists = e4n.exists()
2084 assert e4n.__class__ is SCons.Node.FS.File, e4n.__class__
2085 assert not exists, "e4n exists?"
2088 def __init__(self, val):
2091 def __init__(self, val):
2093 def collect(self, args):
2094 return reduce(lambda x, y: x+y, args)
2095 def signature(self, executor):
2096 return self.val + 222
2097 self.module = M(val)
2100 test.write('e5f', "e5f\n")
2102 def test_Entry_Entry_lookup(self):
2103 """Test looking up an Entry within another Entry"""
2104 self.fs.Entry('#topdir')
2105 self.fs.Entry('#topdir/a/b/c')
2109 class FileTestCase(_tempdirTestCase):
2111 def test_subclass(self):
2112 """Test looking up subclass of File nodes"""
2113 class FileSubclass(SCons.Node.FS.File):
2115 sd = self.fs._lookup('special_file', None, FileSubclass, create=1)
2116 sd.must_be_same(SCons.Node.FS.File)
2118 def test_Dirs(self):
2119 """Test the File.Dirs() method"""
2120 fff = self.fs.File('subdir/fff')
2121 # This simulates that the SConscript file that defined
2122 # fff is in subdir/.
2123 fff.cwd = self.fs.Dir('subdir')
2124 d1 = self.fs.Dir('subdir/d1')
2125 d2 = self.fs.Dir('subdir/d2')
2126 dirs = fff.Dirs(['d1', 'd2'])
2127 assert dirs == [d1, d2], list(map(str, dirs))
2129 def test_exists(self):
2130 """Test the File.exists() method"""
2134 src_f1 = fs.File('src/f1')
2135 assert not src_f1.exists(), "%s apparently exists?" % src_f1
2138 test.write(['src', 'f1'], "src/f1\n")
2140 assert not src_f1.exists(), "%s did not cache previous exists() value" % src_f1
2142 assert src_f1.exists(), "%s apparently does not exist?" % src_f1
2144 test.subdir('build')
2145 fs.VariantDir('build', 'src')
2146 build_f1 = fs.File('build/f1')
2148 assert build_f1.exists(), "%s did not realize that %s exists" % (build_f1, src_f1)
2149 assert os.path.exists(build_f1.abspath), "%s did not get duplicated on disk" % build_f1.abspath
2151 test.unlink(['src', 'f1'])
2152 src_f1.clear() # so the next exists() call will look on disk again
2154 assert build_f1.exists(), "%s did not cache previous exists() value" % build_f1
2156 build_f1.linked = None
2157 assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1)
2158 assert not os.path.exists(build_f1.abspath), "%s did not get removed after %s was removed" % (build_f1, src_f1)
2162 class GlobTestCase(_tempdirTestCase):
2164 _tempdirTestCase.setUp(self)
2166 fs = SCons.Node.FS.FS()
2169 # Make entries on disk that will not have Nodes, so we can verify
2170 # the behavior of looking for things on disk.
2171 self.test.write('disk-bbb', "disk-bbb\n")
2172 self.test.write('disk-aaa', "disk-aaa\n")
2173 self.test.write('disk-ccc', "disk-ccc\n")
2174 self.test.write('#disk-hash', "#disk-hash\n")
2175 self.test.subdir('disk-sub')
2176 self.test.write(['disk-sub', 'disk-ddd'], "disk-sub/disk-ddd\n")
2177 self.test.write(['disk-sub', 'disk-eee'], "disk-sub/disk-eee\n")
2178 self.test.write(['disk-sub', 'disk-fff'], "disk-sub/disk-fff\n")
2180 # Make some entries that have both Nodes and on-disk entries,
2181 # so we can verify what we do with
2182 self.test.write('both-aaa', "both-aaa\n")
2183 self.test.write('both-bbb', "both-bbb\n")
2184 self.test.write('both-ccc', "both-ccc\n")
2185 self.test.write('#both-hash', "#both-hash\n")
2186 self.test.subdir('both-sub1')
2187 self.test.write(['both-sub1', 'both-ddd'], "both-sub1/both-ddd\n")
2188 self.test.write(['both-sub1', 'both-eee'], "both-sub1/both-eee\n")
2189 self.test.write(['both-sub1', 'both-fff'], "both-sub1/both-fff\n")
2190 self.test.subdir('both-sub2')
2191 self.test.write(['both-sub2', 'both-ddd'], "both-sub2/both-ddd\n")
2192 self.test.write(['both-sub2', 'both-eee'], "both-sub2/both-eee\n")
2193 self.test.write(['both-sub2', 'both-fff'], "both-sub2/both-fff\n")
2195 self.both_aaa = fs.File('both-aaa')
2196 self.both_bbb = fs.File('both-bbb')
2197 self.both_ccc = fs.File('both-ccc')
2198 self._both_hash = fs.File('./#both-hash')
2199 self.both_sub1 = fs.Dir('both-sub1')
2200 self.both_sub1_both_ddd = self.both_sub1.File('both-ddd')
2201 self.both_sub1_both_eee = self.both_sub1.File('both-eee')
2202 self.both_sub1_both_fff = self.both_sub1.File('both-fff')
2203 self.both_sub2 = fs.Dir('both-sub2')
2204 self.both_sub2_both_ddd = self.both_sub2.File('both-ddd')
2205 self.both_sub2_both_eee = self.both_sub2.File('both-eee')
2206 self.both_sub2_both_fff = self.both_sub2.File('both-fff')
2208 # Make various Nodes (that don't have on-disk entries) so we
2209 # can verify how we match them.
2210 self.ggg = fs.File('ggg')
2211 self.hhh = fs.File('hhh')
2212 self.iii = fs.File('iii')
2213 self._hash = fs.File('./#hash')
2214 self.subdir1 = fs.Dir('subdir1')
2215 self.subdir1_lll = self.subdir1.File('lll')
2216 self.subdir1_jjj = self.subdir1.File('jjj')
2217 self.subdir1_kkk = self.subdir1.File('kkk')
2218 self.subdir2 = fs.Dir('subdir2')
2219 self.subdir2_lll = self.subdir2.File('lll')
2220 self.subdir2_kkk = self.subdir2.File('kkk')
2221 self.subdir2_jjj = self.subdir2.File('jjj')
2222 self.sub = fs.Dir('sub')
2223 self.sub_dir3 = self.sub.Dir('dir3')
2224 self.sub_dir3_kkk = self.sub_dir3.File('kkk')
2225 self.sub_dir3_jjj = self.sub_dir3.File('jjj')
2226 self.sub_dir3_lll = self.sub_dir3.File('lll')
2229 def do_cases(self, cases, **kwargs):
2231 # First, execute all of the cases with string=True and verify
2232 # that we get the expected strings returned. We do this first
2233 # so the Glob() calls don't add Nodes to the self.fs file system
2237 strings_kwargs = copy.copy(kwargs)
2238 strings_kwargs['strings'] = True
2239 for input, string_expect, node_expect in cases:
2240 r = sorted(self.fs.Glob(input, **strings_kwargs))
2241 assert r == string_expect, "Glob(%s, strings=True) expected %s, got %s" % (input, string_expect, r)
2243 # Now execute all of the cases without string=True and look for
2244 # the expected Nodes to be returned. If we don't have a list of
2245 # actual expected Nodes, that means we're expecting a search for
2246 # on-disk-only files to have returned some newly-created nodes.
2247 # Verify those by running the list through str() before comparing
2248 # them with the expected list of strings.
2249 for input, string_expect, node_expect in cases:
2250 r = self.fs.Glob(input, **kwargs)
2252 r.sort(lambda a,b: cmp(a.path, b.path))
2254 for n in node_expect:
2255 if isinstance(n, str):
2256 n = self.fs.Entry(n)
2258 fmt = lambda n: "%s %s" % (repr(n), repr(str(n)))
2260 r = sorted(map(str, r))
2261 result = string_expect
2265 print "Glob(%s) expected:" % repr(input)
2266 pprint.pprint(list(map(fmt, result)))
2267 print "Glob(%s) got:" % repr(input)
2268 pprint.pprint(list(map(fmt, r)))
2271 def test_exact_match(self):
2272 """Test globbing for exact Node matches"""
2276 ('ggg', ['ggg'], [self.ggg]),
2278 ('subdir1', ['subdir1'], [self.subdir1]),
2280 ('subdir1/jjj', [join('subdir1', 'jjj')], [self.subdir1_jjj]),
2282 ('disk-aaa', ['disk-aaa'], None),
2284 ('disk-sub', ['disk-sub'], None),
2286 ('both-aaa', ['both-aaa'], []),
2289 self.do_cases(cases)
2291 def test_subdir_matches(self):
2292 """Test globbing for exact Node matches in subdirectories"""
2297 [join('subdir1', 'jjj'), join('subdir2', 'jjj')],
2298 [self.subdir1_jjj, self.subdir2_jjj]),
2301 [join('disk-sub', 'disk-ddd')],
2305 self.do_cases(cases)
2307 def test_asterisk1(self):
2308 """Test globbing for simple asterisk Node matches (1)"""
2315 ['#both-hash', '#hash',
2316 'both-aaa', 'both-bbb', 'both-ccc',
2317 'both-sub1', 'both-sub2',
2318 'ggg', 'hhh', 'iii',
2319 'sub', 'subdir1', 'subdir2'],
2320 [self._both_hash, self._hash,
2321 self.both_aaa, self.both_bbb, self.both_ccc, 'both-hash',
2322 self.both_sub1, self.both_sub2,
2323 self.ggg, 'hash', self.hhh, self.iii,
2324 self.sub, self.subdir1, self.subdir2]),
2327 self.do_cases(cases, ondisk=False)
2329 def test_asterisk2(self):
2330 """Test globbing for simple asterisk Node matches (2)"""
2337 ['#both-hash', '#disk-hash', '#hash',
2338 'both-aaa', 'both-bbb', 'both-ccc',
2339 'both-sub1', 'both-sub2',
2340 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub',
2341 'ggg', 'hhh', 'iii',
2342 'sub', 'subdir1', 'subdir2'],
2343 ['./#both-hash', './#disk-hash', './#hash',
2344 'both-aaa', 'both-bbb', 'both-ccc', 'both-hash',
2345 'both-sub1', 'both-sub2',
2346 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub',
2347 'ggg', 'hash', 'hhh', 'iii',
2348 'sub', 'subdir1', 'subdir2']),
2351 self.do_cases(cases)
2353 def test_question_mark(self):
2354 """Test globbing for simple question-mark Node matches"""
2362 ('both-sub?/both-eee',
2363 [join('both-sub1', 'both-eee'), join('both-sub2', 'both-eee')],
2364 [self.both_sub1_both_eee, self.both_sub2_both_eee]),
2367 [join('subdir1', 'jjj'), join('subdir2', 'jjj')],
2368 [self.subdir1_jjj, self.subdir2_jjj]),
2375 self.do_cases(cases)
2377 def test_does_not_exist(self):
2378 """Test globbing for things that don't exist"""
2381 ('does_not_exist', [], []),
2382 ('no_subdir/*', [], []),
2383 ('subdir?/no_file', [], []),
2386 self.do_cases(cases)
2388 def test_subdir_asterisk(self):
2389 """Test globbing for asterisk Node matches in subdirectories"""
2394 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2395 [self.subdir1_kkk, self.subdir2_kkk]),
2398 [join('both-sub1', 'both-ddd'),
2399 join('both-sub1', 'both-eee'),
2400 join('both-sub1', 'both-fff'),
2401 join('both-sub2', 'both-ddd'),
2402 join('both-sub2', 'both-eee'),
2403 join('both-sub2', 'both-fff')],
2404 [self.both_sub1_both_ddd,
2405 self.both_sub1_both_eee,
2406 self.both_sub1_both_fff,
2407 self.both_sub2_both_ddd,
2408 self.both_sub2_both_eee,
2409 self.both_sub2_both_fff],
2413 [join('subdir1', 'jjj'),
2414 join('subdir1', 'kkk'),
2415 join('subdir1', 'lll'),
2416 join('subdir2', 'jjj'),
2417 join('subdir2', 'kkk'),
2418 join('subdir2', 'lll')],
2419 [self.subdir1_jjj, self.subdir1_kkk, self.subdir1_lll,
2420 self.subdir2_jjj, self.subdir2_kkk, self.subdir2_lll]),
2423 [join('sub', 'dir3', 'jjj'),
2424 join('sub', 'dir3', 'kkk'),
2425 join('sub', 'dir3', 'lll')],
2426 [self.sub_dir3_jjj, self.sub_dir3_kkk, self.sub_dir3_lll]),
2429 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2433 [join('subdir1', 'jjj'),
2434 join('subdir1', 'kkk'),
2435 join('subdir1', 'lll'),
2436 join('subdir2', 'jjj'),
2437 join('subdir2', 'kkk'),
2438 join('subdir2', 'lll')],
2442 [join('sub', 'dir3', 'jjj'),
2443 join('sub', 'dir3', 'kkk'),
2444 join('sub', 'dir3', 'lll')],
2448 self.do_cases(cases)
2450 def test_subdir_question(self):
2451 """Test globbing for question-mark Node matches in subdirectories"""
2456 [join('subdir1', 'kkk'), join('subdir2', 'kkk')],
2457 [self.subdir1_kkk, self.subdir2_kkk]),
2460 [join('subdir1', 'lll'), join('subdir2', 'lll')],
2461 [self.subdir1_lll, self.subdir2_lll]),
2464 [join('disk-sub', 'disk-fff')],
2468 [join('subdir1', 'lll'), join('subdir2', 'lll')],
2472 self.do_cases(cases)
2474 def test_sort(self):
2475 """Test whether globbing sorts"""
2477 # At least sometimes this should return out-of-order items
2478 # if Glob doesn't sort.
2479 # It's not a very good test though since it depends on the
2480 # order returned by glob, which might already be sorted.
2481 g = self.fs.Glob('disk-sub/*', strings=True)
2483 os.path.join('disk-sub', 'disk-ddd'),
2484 os.path.join('disk-sub', 'disk-eee'),
2485 os.path.join('disk-sub', 'disk-fff'),
2487 assert g == expect, str(g) + " is not sorted, but should be!"
2489 g = self.fs.Glob('disk-*', strings=True)
2490 expect = [ 'disk-aaa', 'disk-bbb', 'disk-ccc', 'disk-sub' ]
2491 assert g == expect, str(g) + " is not sorted, but should be!"
2494 class RepositoryTestCase(_tempdirTestCase):
2497 _tempdirTestCase.setUp(self)
2499 self.test.subdir('rep1', 'rep2', 'rep3', 'work')
2501 self.rep1 = self.test.workpath('rep1')
2502 self.rep2 = self.test.workpath('rep2')
2503 self.rep3 = self.test.workpath('rep3')
2505 os.chdir(self.test.workpath('work'))
2507 self.fs = SCons.Node.FS.FS()
2508 self.fs.Repository(self.rep1, self.rep2, self.rep3)
2510 def test_getRepositories(self):
2511 """Test the Dir.getRepositories() method"""
2512 self.fs.Repository('foo')
2513 self.fs.Repository(os.path.join('foo', 'bar'))
2514 self.fs.Repository('bar/foo')
2515 self.fs.Repository('bar')
2522 os.path.join('foo', 'bar'),
2523 os.path.join('bar', 'foo'),
2527 rep = self.fs.Dir('#').getRepositories()
2528 r = [os.path.normpath(str(x)) for x in rep]
2529 assert r == expect, r
2531 def test_get_all_rdirs(self):
2532 """Test the Dir.get_all_rdirs() method"""
2533 self.fs.Repository('foo')
2534 self.fs.Repository(os.path.join('foo', 'bar'))
2535 self.fs.Repository('bar/foo')
2536 self.fs.Repository('bar')
2544 os.path.join('foo', 'bar'),
2545 os.path.join('bar', 'foo'),
2549 rep = self.fs.Dir('#').get_all_rdirs()
2550 r = [os.path.normpath(str(x)) for x in rep]
2551 assert r == expect, r
2553 def test_rentry(self):
2554 """Test the Base.entry() method"""
2555 return_true = lambda: 1
2556 return_false = lambda: 0
2558 d1 = self.fs.Dir('d1')
2559 d2 = self.fs.Dir('d2')
2560 d3 = self.fs.Dir('d3')
2562 e1 = self.fs.Entry('e1')
2563 e2 = self.fs.Entry('e2')
2564 e3 = self.fs.Entry('e3')
2566 f1 = self.fs.File('f1')
2567 f2 = self.fs.File('f2')
2568 f3 = self.fs.File('f3')
2570 self.test.write([self.rep1, 'd2'], "")
2571 self.test.subdir([self.rep2, 'd3'])
2572 self.test.write([self.rep3, 'd3'], "")
2574 self.test.write([self.rep1, 'e2'], "")
2575 self.test.subdir([self.rep2, 'e3'])
2576 self.test.write([self.rep3, 'e3'], "")
2578 self.test.write([self.rep1, 'f2'], "")
2579 self.test.subdir([self.rep2, 'f3'])
2580 self.test.write([self.rep3, 'f3'], "")
2586 assert not r is d2, r
2588 assert r == os.path.join(self.rep1, 'd2'), r
2591 assert not r is d3, r
2593 assert r == os.path.join(self.rep2, 'd3'), r
2599 assert not r is e2, r
2601 assert r == os.path.join(self.rep1, 'e2'), r
2604 assert not r is e3, r
2606 assert r == os.path.join(self.rep2, 'e3'), r
2612 assert not r is f2, r
2614 assert r == os.path.join(self.rep1, 'f2'), r
2617 assert not r is f3, r
2619 assert r == os.path.join(self.rep2, 'f3'), r
2621 def test_rdir(self):
2622 """Test the Dir.rdir() method"""
2623 return_true = lambda: 1
2624 return_false = lambda: 0
2626 d1 = self.fs.Dir('d1')
2627 d2 = self.fs.Dir('d2')
2628 d3 = self.fs.Dir('d3')
2630 self.test.subdir([self.rep1, 'd2'])
2631 self.test.write([self.rep2, 'd3'], "")
2632 self.test.subdir([self.rep3, 'd3'])
2638 assert not r is d2, r
2640 assert r == os.path.join(self.rep1, 'd2'), r
2643 assert not r is d3, r
2645 assert r == os.path.join(self.rep3, 'd3'), r
2647 e1 = self.fs.Dir('e1')
2648 e1.exists = return_false
2649 e2 = self.fs.Dir('e2')
2650 e2.exists = return_false
2652 # Make sure we match entries in repositories,
2653 # regardless of whether they're derived or not.
2655 re1 = self.fs.Entry(os.path.join(self.rep1, 'e1'))
2656 re1.exists = return_true
2657 re1.is_derived = return_true
2658 re2 = self.fs.Entry(os.path.join(self.rep2, 'e2'))
2659 re2.exists = return_true
2660 re2.is_derived = return_false
2668 def test_rfile(self):
2669 """Test the File.rfile() method"""
2670 return_true = lambda: 1
2671 return_false = lambda: 0
2673 f1 = self.fs.File('f1')
2674 f2 = self.fs.File('f2')
2675 f3 = self.fs.File('f3')
2677 self.test.write([self.rep1, 'f2'], "")
2678 self.test.subdir([self.rep2, 'f3'])
2679 self.test.write([self.rep3, 'f3'], "")
2685 assert not r is f2, r
2687 assert r == os.path.join(self.rep1, 'f2'), r
2690 assert not r is f3, r
2692 assert r == os.path.join(self.rep3, 'f3'), r
2694 e1 = self.fs.File('e1')
2695 e1.exists = return_false
2696 e2 = self.fs.File('e2')
2697 e2.exists = return_false
2699 # Make sure we match entries in repositories,
2700 # regardless of whether they're derived or not.
2702 re1 = self.fs.Entry(os.path.join(self.rep1, 'e1'))
2703 re1.exists = return_true
2704 re1.is_derived = return_true
2705 re2 = self.fs.Entry(os.path.join(self.rep2, 'e2'))
2706 re2.exists = return_true
2707 re2.is_derived = return_false
2715 def test_Rfindalldirs(self):
2716 """Test the Rfindalldirs() methods"""
2722 rep1_d1 = fs.Dir(test.workpath('rep1', 'd1'))
2723 rep2_d1 = fs.Dir(test.workpath('rep2', 'd1'))
2724 rep3_d1 = fs.Dir(test.workpath('rep3', 'd1'))
2726 sub_d1 = sub.Dir('d1')
2727 rep1_sub_d1 = fs.Dir(test.workpath('rep1', 'sub', 'd1'))
2728 rep2_sub_d1 = fs.Dir(test.workpath('rep2', 'sub', 'd1'))
2729 rep3_sub_d1 = fs.Dir(test.workpath('rep3', 'sub', 'd1'))
2731 r = fs.Top.Rfindalldirs((d1,))
2732 assert r == [d1], list(map(str, r))
2734 r = fs.Top.Rfindalldirs((d1, d2))
2735 assert r == [d1, d2], list(map(str, r))
2737 r = fs.Top.Rfindalldirs(('d1',))
2738 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r))
2740 r = fs.Top.Rfindalldirs(('#d1',))
2741 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r))
2743 r = sub.Rfindalldirs(('d1',))
2744 assert r == [sub_d1, rep1_sub_d1, rep2_sub_d1, rep3_sub_d1], list(map(str, r))
2746 r = sub.Rfindalldirs(('#d1',))
2747 assert r == [d1, rep1_d1, rep2_d1, rep3_d1], list(map(str, r))
2749 r = fs.Top.Rfindalldirs(('d1', d2))
2750 assert r == [d1, rep1_d1, rep2_d1, rep3_d1, d2], list(map(str, r))
2752 def test_rexists(self):
2753 """Test the Entry.rexists() method"""
2757 test.write([self.rep1, 'f2'], "")
2758 test.write([self.rep2, "i_exist"], "\n")
2759 test.write(["work", "i_exist_too"], "\n")
2761 fs.VariantDir('build', '.')
2763 f = fs.File(test.workpath("work", "i_do_not_exist"))
2764 assert not f.rexists()
2766 f = fs.File(test.workpath("work", "i_exist"))
2769 f = fs.File(test.workpath("work", "i_exist_too"))
2772 f1 = fs.File(os.path.join('build', 'f1'))
2773 assert not f1.rexists()
2775 f2 = fs.File(os.path.join('build', 'f2'))
2778 def test_FAT_timestamps(self):
2779 """Test repository timestamps on FAT file systems"""
2783 test.write(["rep2", "tstamp"], "tstamp\n")
2785 # Okay, *this* manipulation accomodates Windows FAT file systems
2786 # that only have two-second granularity on their timestamps.
2787 # We round down the current time to the nearest even integer
2788 # value, subtract two to make sure the timestamp is not "now,"
2789 # and then convert it back to a float.
2790 tstamp = float(int(time.time() / 2) * 2) - 2
2791 os.utime(test.workpath("rep2", "tstamp"), (tstamp - 2.0, tstamp))
2792 f = fs.File("tstamp")
2793 t = f.get_timestamp()
2794 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
2796 test.unlink(["rep2", "tstamp"])
2798 def test_get_contents(self):
2799 """Ensure get_contents() returns binary contents from Repositories"""
2803 test.write(["rep3", "contents"], "Con\x1aTents\n")
2805 c = fs.File("contents").get_contents()
2806 assert c == "Con\x1aTents\n", "got '%s'" % c
2808 test.unlink(["rep3", "contents"])
2810 def test_get_text_contents(self):
2811 """Ensure get_text_contents() returns text contents from
2816 # Use a test string that has a file terminator in it to make
2817 # sure we read the entire file, regardless of its contents.
2819 eval('test_string = u"Con\x1aTents\n"')
2822 class FakeUnicodeString(UserString.UserString):
2823 def encode(self, encoding):
2825 test_string = FakeUnicodeString("Con\x1aTents\n")
2829 test.write(["rep3", "contents"], test_string.encode('ascii'))
2831 c = fs.File("contents").get_text_contents()
2832 assert test_string == c, "got %s" % repr(c)
2834 test.unlink(["rep3", "contents"])
2837 test.write(["rep3", "contents"], test_string.encode('utf-8'))
2839 c = fs.File("contents").get_text_contents()
2840 assert test_string == c, "got %s" % repr(c)
2842 test.unlink(["rep3", "contents"])
2845 test.write(["rep3", "contents"], test_string.encode('utf-16'))
2847 c = fs.File("contents").get_text_contents()
2848 assert test_string == c, "got %s" % repr(c)
2850 test.unlink(["rep3", "contents"])
2852 #def test_is_up_to_date(self):
2856 class find_fileTestCase(unittest.TestCase):
2858 """Testing find_file function"""
2859 test = TestCmd(workdir = '')
2860 test.write('./foo', 'Some file\n')
2861 test.write('./foo2', 'Another file\n')
2864 test.write(['bar', 'on_disk'], 'Another file\n')
2865 test.write(['bar', 'same'], 'bar/same\n')
2867 fs = SCons.Node.FS.FS(test.workpath(""))
2868 # FS doesn't like the cwd to be something other than its root.
2869 os.chdir(test.workpath(""))
2871 node_derived = fs.File(test.workpath('bar/baz'))
2872 node_derived.builder_set(1) # Any non-zero value.
2873 node_pseudo = fs.File(test.workpath('pseudo'))
2874 node_pseudo.set_src_builder(1) # Any non-zero value.
2876 paths = tuple(map(fs.Dir, ['.', 'same', './bar']))
2877 nodes = [SCons.Node.FS.find_file('foo', paths)]
2878 nodes.append(SCons.Node.FS.find_file('baz', paths))
2879 nodes.append(SCons.Node.FS.find_file('pseudo', paths))
2880 nodes.append(SCons.Node.FS.find_file('same', paths))
2882 file_names = list(map(str, nodes))
2883 file_names = list(map(os.path.normpath, file_names))
2884 expect = ['./foo', './bar/baz', './pseudo', './bar/same']
2885 expect = list(map(os.path.normpath, expect))
2886 assert file_names == expect, file_names
2888 # Make sure we don't blow up if there's already a File in place
2889 # of a directory that we'd otherwise try to search. If this
2890 # is broken, we'll see an exception like "Tried to lookup File
2891 # 'bar/baz' as a Dir.
2892 SCons.Node.FS.find_file('baz/no_file_here', paths)
2895 save_sys_stdout = sys.stdout
2898 sio = StringIO.StringIO()
2900 SCons.Node.FS.find_file('foo2', paths, verbose="xyz")
2901 expect = " xyz: looking for 'foo2' in '.' ...\n" + \
2902 " xyz: ... FOUND 'foo2' in '.'\n"
2904 assert c == expect, c
2906 sio = StringIO.StringIO()
2908 SCons.Node.FS.find_file('baz2', paths, verbose=1)
2909 expect = " find_file: looking for 'baz2' in '.' ...\n" + \
2910 " find_file: looking for 'baz2' in 'same' ...\n" + \
2911 " find_file: looking for 'baz2' in 'bar' ...\n"
2913 assert c == expect, c
2915 sio = StringIO.StringIO()
2917 SCons.Node.FS.find_file('on_disk', paths, verbose=1)
2918 expect = " find_file: looking for 'on_disk' in '.' ...\n" + \
2919 " find_file: looking for 'on_disk' in 'same' ...\n" + \
2920 " find_file: looking for 'on_disk' in 'bar' ...\n" + \
2921 " find_file: ... FOUND 'on_disk' in 'bar'\n"
2923 assert c == expect, c
2925 sys.stdout = save_sys_stdout
2927 class StringDirTestCase(unittest.TestCase):
2929 """Test using a string as the second argument of
2932 test = TestCmd(workdir = '')
2934 fs = SCons.Node.FS.FS(test.workpath(''))
2936 d = fs.Dir('sub', '.')
2937 assert str(d) == 'sub', str(d)
2939 f = fs.File('file', 'sub')
2940 assert str(f) == os.path.join('sub', 'file')
2941 assert not f.exists()
2943 class stored_infoTestCase(unittest.TestCase):
2945 """Test how we store build information"""
2946 test = TestCmd(workdir = '')
2948 fs = SCons.Node.FS.FS(test.workpath(''))
2951 f = fs.File('file1', d)
2952 bi = f.get_stored_info()
2953 assert hasattr(bi, 'ninfo')
2959 def get_entry(self, name):
2962 f = fs.File('file2', d)
2963 f.dir.sconsign = MySConsign
2964 bi = f.get_stored_info()
2965 assert bi.xyzzy == 7, bi
2967 class has_src_builderTestCase(unittest.TestCase):
2969 """Test the has_src_builder() method"""
2970 test = TestCmd(workdir = '')
2971 fs = SCons.Node.FS.FS(test.workpath(''))
2972 os.chdir(test.workpath(''))
2974 test.subdir('sub2', ['sub2', 'SCCS'], ['sub2', 'RCS'])
2976 sub1 = fs.Dir('sub1', '.')
2977 f1 = fs.File('f1', sub1)
2978 f2 = fs.File('f2', sub1)
2979 f3 = fs.File('f3', sub1)
2980 sub2 = fs.Dir('sub2', '.')
2981 f4 = fs.File('f4', sub2)
2982 f5 = fs.File('f5', sub2)
2983 f6 = fs.File('f6', sub2)
2984 f7 = fs.File('f7', sub2)
2985 f8 = fs.File('f8', sub2)
2987 h = f1.has_src_builder()
2989 h = f1.has_builder()
2992 b1 = Builder(fs.File)
2993 sub1.set_src_builder(b1)
2995 test.write(['sub1', 'f2'], "sub1/f2\n")
2996 h = f1.has_src_builder() # cached from previous call
2998 h = f1.has_builder() # cached from previous call
3000 h = f2.has_src_builder()
3002 h = f2.has_builder()
3004 h = f3.has_src_builder()
3006 h = f3.has_builder()
3008 assert f3.builder is b1, f3.builder
3010 f7.set_src_builder(b1)
3013 test.write(['sub2', 'SCCS', 's.f5'], "sub2/SCCS/s.f5\n")
3014 test.write(['sub2', 'RCS', 'f6,v'], "sub2/RCS/f6,v\n")
3015 h = f4.has_src_builder()
3017 h = f4.has_builder()
3019 h = f5.has_src_builder()
3021 h = f5.has_builder()
3023 h = f6.has_src_builder()
3025 h = f6.has_builder()
3027 h = f7.has_src_builder()
3029 h = f7.has_builder()
3031 h = f8.has_src_builder()
3033 h = f8.has_builder()
3036 class prepareTestCase(unittest.TestCase):
3038 """Test the prepare() method"""
3040 class MyFile(SCons.Node.FS.File):
3041 def _createDir(self, update=None):
3042 raise SCons.Errors.StopError
3046 fs = SCons.Node.FS.FS()
3047 file = MyFile('foo', fs.Dir('.'), fs)
3052 except SCons.Errors.StopError:
3054 assert exc_caught, "Should have caught a StopError."
3056 class MkdirAction(Action):
3057 def __init__(self, dir_made):
3058 self.dir_made = dir_made
3059 def __call__(self, target, source, env, executor=None):
3061 target = executor.get_all_targets()
3062 source = executor.get_all_sources()
3063 self.dir_made.extend(target)
3066 new_dir = fs.Dir("new_dir")
3067 new_dir.builder = Builder(fs.Dir, action=MkdirAction(dir_made))
3068 new_dir.reset_executor()
3069 xyz = fs.File(os.path.join("new_dir", "xyz"))
3071 xyz.set_state(SCons.Node.up_to_date)
3073 assert dir_made == [], dir_made
3077 assert dir_made[0].path == "new_dir", dir_made[0]
3084 class SConstruct_dirTestCase(unittest.TestCase):
3086 """Test setting the SConstruct directory"""
3088 fs = SCons.Node.FS.FS()
3089 fs.set_SConstruct_dir(fs.Dir('xxx'))
3090 assert fs.SConstruct_dir.path == 'xxx'
3094 class CacheDirTestCase(unittest.TestCase):
3096 def test_get_cachedir_csig(self):
3097 fs = SCons.Node.FS.FS()
3100 r = f9.get_cachedir_csig()
3101 assert r == 'd41d8cd98f00b204e9800998ecf8427e', r
3105 class clearTestCase(unittest.TestCase):
3107 """Test clearing FS nodes of cached data."""
3108 fs = SCons.Node.FS.FS()
3109 test = TestCmd(workdir='')
3112 assert not e.exists()
3113 assert not e.rexists()
3114 assert str(e) == 'e', str(d)
3116 assert not e.exists()
3117 assert not e.rexists()
3118 assert str(e) == 'e', str(d)
3120 d = fs.Dir(test.workpath('d'))
3124 assert str(d) == test.workpath('d'), str(d)
3125 fs.rename(test.workpath('d'), test.workpath('gone'))
3126 # Verify caching is active
3127 assert d.exists(), 'caching not active'
3129 assert str(d) == test.workpath('d'), str(d)
3130 # Now verify clear() resets the cache
3132 assert not d.exists()
3133 assert not d.rexists()
3134 assert str(d) == test.workpath('d'), str(d)
3136 f = fs.File(test.workpath('f'))
3137 test.write(test.workpath('f'), 'file f')
3140 assert str(f) == test.workpath('f'), str(f)
3141 # Verify caching is active
3142 test.unlink(test.workpath('f'))
3145 assert str(f) == test.workpath('f'), str(f)
3146 # Now verify clear() resets the cache
3148 assert not f.exists()
3149 assert not f.rexists()
3150 assert str(f) == test.workpath('f'), str(f)
3154 class disambiguateTestCase(unittest.TestCase):
3156 """Test calling the disambiguate() method."""
3157 test = TestCmd(workdir='')
3159 fs = SCons.Node.FS.FS()
3162 d = ddd.disambiguate()
3165 fff = fs.File('fff')
3166 f = fff.disambiguate()
3170 test.write('efile', "efile\n")
3172 edir = fs.Entry(test.workpath('edir'))
3173 d = edir.disambiguate()
3174 assert d.__class__ is ddd.__class__, d.__class__
3176 efile = fs.Entry(test.workpath('efile'))
3177 f = efile.disambiguate()
3178 assert f.__class__ is fff.__class__, f.__class__
3180 test.subdir('build')
3181 test.subdir(['build', 'bdir'])
3182 test.write(['build', 'bfile'], "build/bfile\n")
3185 test.write(['src', 'bdir'], "src/bdir\n")
3186 test.subdir(['src', 'bfile'])
3188 test.subdir(['src', 'edir'])
3189 test.write(['src', 'efile'], "src/efile\n")
3191 fs.VariantDir(test.workpath('build'), test.workpath('src'))
3193 build_bdir = fs.Entry(test.workpath('build/bdir'))
3194 d = build_bdir.disambiguate()
3195 assert d is build_bdir, d
3196 assert d.__class__ is ddd.__class__, d.__class__
3198 build_bfile = fs.Entry(test.workpath('build/bfile'))
3199 f = build_bfile.disambiguate()
3200 assert f is build_bfile, f
3201 assert f.__class__ is fff.__class__, f.__class__
3203 build_edir = fs.Entry(test.workpath('build/edir'))
3204 d = build_edir.disambiguate()
3205 assert d.__class__ is ddd.__class__, d.__class__
3207 build_efile = fs.Entry(test.workpath('build/efile'))
3208 f = build_efile.disambiguate()
3209 assert f.__class__ is fff.__class__, f.__class__
3211 build_nonexistant = fs.Entry(test.workpath('build/nonexistant'))
3212 f = build_nonexistant.disambiguate()
3213 assert f.__class__ is fff.__class__, f.__class__
3215 class postprocessTestCase(unittest.TestCase):
3217 """Test calling the postprocess() method."""
3218 fs = SCons.Node.FS.FS()
3231 class SpecialAttrTestCase(unittest.TestCase):
3233 """Test special attributes of file nodes."""
3234 test=TestCmd(workdir='')
3235 fs = SCons.Node.FS.FS(test.workpath('work'))
3237 f = fs.Entry('foo/bar/baz.blat').get_subst_proxy()
3240 assert s == os.path.normpath('foo/bar'), s
3241 assert f.dir.is_literal(), f.dir
3242 for_sig = f.dir.for_signature()
3243 assert for_sig == 'bar', for_sig
3246 assert s == 'baz.blat', s
3247 assert f.file.is_literal(), f.file
3248 for_sig = f.file.for_signature()
3249 assert for_sig == 'baz.blat_file', for_sig
3252 assert s == os.path.normpath('foo/bar/baz'), s
3253 assert f.base.is_literal(), f.base
3254 for_sig = f.base.for_signature()
3255 assert for_sig == 'baz.blat_base', for_sig
3258 assert s == 'baz', s
3259 assert f.filebase.is_literal(), f.filebase
3260 for_sig = f.filebase.for_signature()
3261 assert for_sig == 'baz.blat_filebase', for_sig
3264 assert s == '.blat', s
3265 assert f.suffix.is_literal(), f.suffix
3266 for_sig = f.suffix.for_signature()
3267 assert for_sig == 'baz.blat_suffix', for_sig
3270 assert s == test.workpath('work', 'foo', 'bar', 'baz.blat'), s
3271 assert f.abspath.is_literal(), f.abspath
3272 for_sig = f.abspath.for_signature()
3273 assert for_sig == 'baz.blat_abspath', for_sig
3276 assert s == 'foo/bar/baz.blat', s
3277 assert f.posix.is_literal(), f.posix
3279 for_sig = f.posix.for_signature()
3280 assert for_sig == 'baz.blat_posix', for_sig
3283 assert s == 'foo\\bar\\baz.blat', repr(s)
3284 assert f.windows.is_literal(), f.windows
3286 for_sig = f.windows.for_signature()
3287 assert for_sig == 'baz.blat_windows', for_sig
3289 # Deprecated synonym for the .windows suffix.
3291 assert s == 'foo\\bar\\baz.blat', repr(s)
3292 assert f.win32.is_literal(), f.win32
3294 for_sig = f.win32.for_signature()
3295 assert for_sig == 'baz.blat_windows', for_sig
3297 # And now, combinations!!!
3298 s = str(f.srcpath.base)
3299 assert s == os.path.normpath('foo/bar/baz'), s
3300 s = str(f.srcpath.dir)
3301 assert s == str(f.srcdir), s
3302 s = str(f.srcpath.posix)
3303 assert s == 'foo/bar/baz.blat', s
3304 s = str(f.srcpath.windows)
3305 assert s == 'foo\\bar\\baz.blat', s
3306 s = str(f.srcpath.win32)
3307 assert s == 'foo\\bar\\baz.blat', s
3309 # Test what happens with VariantDir()
3310 fs.VariantDir('foo', 'baz')
3313 assert s == os.path.normpath('baz/bar/baz.blat'), s
3314 assert f.srcpath.is_literal(), f.srcpath
3316 assert isinstance(g, SCons.Node.FS.File), g.__class__
3319 assert s == os.path.normpath('baz/bar'), s
3320 assert f.srcdir.is_literal(), f.srcdir
3322 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3324 # And now what happens with VariantDir() + Repository()
3325 fs.Repository(test.workpath('repository'))
3327 f = fs.Entry('foo/sub/file.suffix').get_subst_proxy()
3328 test.subdir('repository',
3329 ['repository', 'baz'],
3330 ['repository', 'baz', 'sub'])
3332 rd = test.workpath('repository', 'baz', 'sub')
3333 rf = test.workpath('repository', 'baz', 'sub', 'file.suffix')
3334 test.write(rf, "\n")
3337 assert s == os.path.normpath('baz/sub/file.suffix'), s
3338 assert f.srcpath.is_literal(), f.srcpath
3340 # Gets disambiguated to SCons.Node.FS.File by get_subst_proxy().
3341 assert isinstance(g, SCons.Node.FS.File), g.__class__
3344 assert s == os.path.normpath('baz/sub'), s
3345 assert f.srcdir.is_literal(), f.srcdir
3347 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3351 assert f.rsrcpath.is_literal(), f.rsrcpath
3352 g = f.rsrcpath.get()
3353 assert isinstance(g, SCons.Node.FS.File), g.__class__
3357 assert f.rsrcdir.is_literal(), f.rsrcdir
3359 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
3361 # Check that attempts to access non-existent attributes of the
3362 # subst proxy generate the right exceptions and messages.
3365 fs.Dir('ddd').get_subst_proxy().no_such_attr
3366 except AttributeError, e:
3367 assert str(e) == "Dir instance 'ddd' has no attribute 'no_such_attr'", e
3369 assert caught, "did not catch expected AttributeError"
3373 fs.Entry('eee').get_subst_proxy().no_such_attr
3374 except AttributeError, e:
3375 # Gets disambiguated to File instance by get_subst_proxy().
3376 assert str(e) == "File instance 'eee' has no attribute 'no_such_attr'", e
3378 assert caught, "did not catch expected AttributeError"
3382 fs.File('fff').get_subst_proxy().no_such_attr
3383 except AttributeError, e:
3384 assert str(e) == "File instance 'fff' has no attribute 'no_such_attr'", e
3386 assert caught, "did not catch expected AttributeError"
3390 class SaveStringsTestCase(unittest.TestCase):
3392 """Test caching string values of nodes."""
3393 test=TestCmd(workdir='')
3400 d0_f = fs.File('d0/f')
3401 d1_f = fs.File('d1/f')
3402 d0_b = fs.File('d0/b')
3403 d1_b = fs.File('d1/b')
3409 return [d0_f, d1_f, d0_b, d1_b]
3412 d0_f, d1_f, d0_b, d1_b = nodes
3418 fs1 = SCons.Node.FS.FS(test.workpath('fs1'))
3420 fs1.VariantDir('d0', 'src', duplicate=0)
3421 fs1.VariantDir('d1', 'src', duplicate=1)
3423 s = list(map(str, nodes))
3424 expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b']))
3425 assert s == expect, s
3429 s = list(map(str, nodes))
3430 expect = list(map(os.path.normpath, ['src/f', 'src/f', 'd0/b', 'd1/b']))
3431 assert s == expect, s
3433 SCons.Node.FS.save_strings(1)
3434 fs2 = SCons.Node.FS.FS(test.workpath('fs2'))
3436 fs2.VariantDir('d0', 'src', duplicate=0)
3437 fs2.VariantDir('d1', 'src', duplicate=1)
3439 s = list(map(str, nodes))
3440 expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b']))
3441 assert s == expect, s
3445 s = list(map(str, nodes))
3446 expect = list(map(os.path.normpath, ['src/f', 'd1/f', 'd0/b', 'd1/b']))
3447 assert s == expect, 'node str() not cached: %s'%s
3450 class AbsolutePathTestCase(unittest.TestCase):
3451 def test_root_lookup_equivalence(self):
3452 """Test looking up /fff vs. fff in the / directory"""
3453 test=TestCmd(workdir='')
3455 fs = SCons.Node.FS.FS('/')
3457 save_cwd = os.getcwd()
3460 fff1 = fs.File('fff')
3461 fff2 = fs.File('/fff')
3462 assert fff1 is fff2, "fff and /fff returned different Nodes!"
3468 if __name__ == "__main__":
3469 suite = unittest.TestSuite()
3470 suite.addTest(VariantDirTestCase())
3471 suite.addTest(find_fileTestCase())
3472 suite.addTest(StringDirTestCase())
3473 suite.addTest(stored_infoTestCase())
3474 suite.addTest(has_src_builderTestCase())
3475 suite.addTest(prepareTestCase())
3476 suite.addTest(SConstruct_dirTestCase())
3477 suite.addTest(clearTestCase())
3478 suite.addTest(disambiguateTestCase())
3479 suite.addTest(postprocessTestCase())
3480 suite.addTest(SpecialAttrTestCase())
3481 suite.addTest(SaveStringsTestCase())
3483 AbsolutePathTestCase,
3487 DirBuildInfoTestCase,
3488 DirNodeInfoTestCase,
3491 FileBuildInfoTestCase,
3492 FileNodeInfoTestCase,
3497 for tclass in tclasses:
3498 names = unittest.getTestCaseNames(tclass, 'test_')
3499 suite.addTests(list(map(tclass, names)))
3500 if not unittest.TextTestRunner().run(suite).wasSuccessful():
3505 # indent-tabs-mode:nil
3507 # vim: set expandtab tabstop=4 shiftwidth=4: