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
42 # This will be built-in in 2.3. For now fake it.
52 def __init__(self, node=None):
54 scanner_count = scanner_count + 1
55 self.hash = scanner_count
57 def path(self, env, target):
59 def __call__(self, node, env, path):
66 self.scanner = Scanner()
67 def Dictionary(self, *args):
69 def autogenerate(self, **kw):
71 def get_scanner(self, skey):
73 def Override(self, overrides):
77 def __call__(self, targets, sources, env):
81 def show(self, string):
83 def strfunction(self, targets, sources, env):
85 def get_actions(self):
89 def __init__(self, factory, action=Action()):
90 self.factory = factory
91 self.env = Environment()
95 def get_actions(self):
101 def source_factory(self, name):
102 return self.factory(name)
104 class BuildDirTestCase(unittest.TestCase):
106 """Test build dir functionality"""
107 test=TestCmd(workdir='')
109 fs = SCons.Node.FS.FS()
110 f1 = fs.File('build/test1')
111 fs.BuildDir('build', 'src')
112 f2 = fs.File('build/test2')
114 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
115 assert f2.srcnode().path == os.path.normpath('src/test2'), f2.srcnode().path
116 assert d1.srcnode().path == 'src', d1.srcnode().path
118 fs = SCons.Node.FS.FS()
119 f1 = fs.File('build/test1')
120 fs.BuildDir('build', '.')
121 f2 = fs.File('build/test2')
123 assert f1.srcnode().path == 'test1', f1.srcnode().path
124 assert f2.srcnode().path == 'test2', f2.srcnode().path
125 assert d1.srcnode().path == '.', d1.srcnode().path
127 fs = SCons.Node.FS.FS()
128 fs.BuildDir('build/var1', 'src')
129 fs.BuildDir('build/var2', 'src')
130 f1 = fs.File('build/var1/test1')
131 f2 = fs.File('build/var2/test1')
132 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
133 assert f2.srcnode().path == os.path.normpath('src/test1'), f2.srcnode().path
135 fs = SCons.Node.FS.FS()
136 fs.BuildDir('../var1', 'src')
137 fs.BuildDir('../var2', 'src')
138 f1 = fs.File('../var1/test1')
139 f2 = fs.File('../var2/test1')
140 assert hasattr(f1, 'overrides')
141 assert f1.srcnode().path == os.path.normpath('src/test1'), f1.srcnode().path
142 assert f2.srcnode().path == os.path.normpath('src/test1'), f2.srcnode().path
145 test.subdir('work', ['work', 'src'])
146 test.subdir(['work', 'build'], ['work', 'build', 'var1'])
147 test.subdir(['work', 'build', 'var2'])
148 test.subdir('rep1', ['rep1', 'src'])
149 test.subdir(['rep1', 'build'], ['rep1', 'build', 'var1'])
150 test.subdir(['rep1', 'build', 'var2'])
152 # A source file in the source directory
153 test.write([ 'work', 'src', 'test.in' ], 'test.in')
155 # A source file in a subdir of the source directory
156 test.subdir([ 'work', 'src', 'new_dir' ])
157 test.write([ 'work', 'src', 'new_dir', 'test9.out' ], 'test9.out\n')
159 # A source file in the repository
160 test.write([ 'rep1', 'src', 'test2.in' ], 'test2.in')
162 # Some source files in the build directory
163 test.write([ 'work', 'build', 'var2', 'test.in' ], 'test.old')
164 test.write([ 'work', 'build', 'var2', 'test2.in' ], 'test2.old')
166 # An old derived file in the build directories
167 test.write([ 'work', 'build', 'var1', 'test.out' ], 'test.old')
168 test.write([ 'work', 'build', 'var2', 'test.out' ], 'test.old')
170 # And just in case we are weird, a derived file in the source
172 test.write([ 'work', 'src', 'test.out' ], 'test.out.src')
174 # A derived file in the repository
175 test.write([ 'rep1', 'build', 'var1', 'test2.out' ], 'test2.out_rep')
176 test.write([ 'rep1', 'build', 'var2', 'test2.out' ], 'test2.out_rep')
178 os.chdir(test.workpath('work'))
180 fs = SCons.Node.FS.FS(test.workpath('work'))
181 fs.BuildDir('build/var1', 'src', duplicate=0)
182 fs.BuildDir('build/var2', 'src')
183 f1 = fs.File('build/var1/test.in')
184 f1out = fs.File('build/var1/test.out')
186 f1out_2 = fs.File('build/var1/test2.out')
188 f2 = fs.File('build/var2/test.in')
189 f2out = fs.File('build/var2/test.out')
191 f2out_2 = fs.File('build/var2/test2.out')
193 fs.Repository(test.workpath('rep1'))
195 assert f1.srcnode().path == os.path.normpath('src/test.in'),\
197 # str(node) returns source path for duplicate = 0
198 assert str(f1) == os.path.normpath('src/test.in'), str(f1)
199 # Build path does not exist
200 assert not f1.exists()
201 # ...but the actual file is not there...
202 assert not os.path.exists(f1.get_abspath())
203 # And duplicate=0 should also work just like a Repository
205 # rfile() should point to the source path
206 assert f1.rfile().path == os.path.normpath('src/test.in'),\
209 assert f2.srcnode().path == os.path.normpath('src/test.in'),\
211 # str(node) returns build path for duplicate = 1
212 assert str(f2) == os.path.normpath('build/var2/test.in'), str(f2)
215 # ...and should copy the file from src to build path
216 assert test.read(['work', 'build', 'var2', 'test.in']) == 'test.in',\
217 test.read(['work', 'build', 'var2', 'test.in'])
218 # Since exists() is true, so should rexists() be
221 f3 = fs.File('build/var1/test2.in')
222 f4 = fs.File('build/var2/test2.in')
224 assert f3.srcnode().path == os.path.normpath('src/test2.in'),\
226 # str(node) returns source path for duplicate = 0
227 assert str(f3) == os.path.normpath('src/test2.in'), str(f3)
228 # Build path does not exist
229 assert not f3.exists()
230 # Source path does not either
231 assert not f3.srcnode().exists()
232 # But we do have a file in the Repository
234 # rfile() should point to the source path
235 assert f3.rfile().path == os.path.normpath(test.workpath('rep1/src/test2.in')),\
238 assert f4.srcnode().path == os.path.normpath('src/test2.in'),\
240 # str(node) returns build path for duplicate = 1
241 assert str(f4) == os.path.normpath('build/var2/test2.in'), str(f4)
242 # Build path should exist
244 # ...and copy over the file into the local build path
245 assert test.read(['work', 'build', 'var2', 'test2.in']) == 'test2.in'
246 # should exist in repository, since exists() is true
248 # rfile() should point to ourselves
249 assert f4.rfile().path == os.path.normpath('build/var2/test2.in'),\
252 f5 = fs.File('build/var1/test.out')
253 f6 = fs.File('build/var2/test.out')
256 # We should not copy the file from the source dir, since this is
258 assert test.read(['work', 'build', 'var1', 'test.out']) == 'test.old'
261 # We should not copy the file from the source dir, since this is
263 assert test.read(['work', 'build', 'var2', 'test.out']) == 'test.old'
265 f7 = fs.File('build/var1/test2.out')
266 f8 = fs.File('build/var2/test2.out')
268 assert not f7.exists()
270 assert f7.rfile().path == os.path.normpath(test.workpath('rep1/build/var1/test2.out')),\
273 assert not f8.exists()
275 assert f8.rfile().path == os.path.normpath(test.workpath('rep1/build/var2/test2.out')),\
278 # Verify the Mkdir and Link actions are called
279 f9 = fs.File('build/var2/new_dir/test9.out')
281 # Test for an interesting pathological case...we have a source
282 # file in a build path, but not in a source path. This can
283 # happen if you switch from duplicate=1 to duplicate=0, then
284 # delete a source file. At one time, this would cause exists()
285 # to return a 1 but get_contents() to throw.
286 test.write([ 'work', 'build', 'var1', 'asourcefile' ], 'stuff')
287 f10 = fs.File('build/var1/asourcefile')
289 assert f10.get_contents() == 'stuff', f10.get_contents()
291 f11 = fs.File('src/file11')
292 t, m = f11.alter_targets()
293 bdt = map(lambda n: n.path, t)
294 var1_file11 = os.path.normpath('build/var1/file11')
295 var2_file11 = os.path.normpath('build/var2/file11')
296 assert bdt == [var1_file11, var2_file11], bdt
298 f12 = fs.File('src/file12')
300 bdt, m = f12.alter_targets()
301 assert bdt == [], map(lambda n: n.path, bdt)
303 d13 = fs.Dir('src/new_dir')
304 t, m = d13.alter_targets()
305 bdt = map(lambda n: n.path, t)
306 var1_new_dir = os.path.normpath('build/var1/new_dir')
307 var2_new_dir = os.path.normpath('build/var2/new_dir')
308 assert bdt == [var1_new_dir, var2_new_dir], bdt
310 save_Mkdir = SCons.Node.FS.Mkdir
312 def mkdir_func(target, source, env, dir_made=dir_made):
313 dir_made.append(target)
314 SCons.Node.FS.Mkdir = mkdir_func
316 save_Link = SCons.Node.FS.Link
318 def link_func(target, source, env, link_made=link_made):
319 link_made.append(target)
320 SCons.Node.FS.Link = link_func
324 expect = os.path.join('build', 'var2', 'new_dir')
325 assert dir_made[0].path == expect, dir_made[0].path
326 expect = os.path.join('build', 'var2', 'new_dir', 'test9.out')
327 assert link_made[0].path == expect, link_made[0].path
330 SCons.Node.FS.Mkdir = save_Mkdir
331 SCons.Node.FS.Link = save_Link
333 # Test that an IOError trying to Link a src file
334 # into a BuildDir ends up throwing a StopError.
335 fIO = fs.File("build/var2/IOError")
337 save_Link = SCons.Node.FS.Link
338 def Link_IOError(target, source, env):
339 raise IOError, "Link_IOError"
340 SCons.Node.FS.Link = Link_IOError
342 test.write(['work', 'src', 'IOError'], "work/src/IOError\n")
348 except SCons.Errors.StopError:
350 assert exc_caught, "Should have caught a StopError"
353 SCons.Node.FS.Link = save_Link
355 # Test to see if Link() works...
356 test.subdir('src','build')
357 test.write('src/foo', 'src/foo\n')
358 os.chmod(test.workpath('src/foo'), stat.S_IRUSR)
359 SCons.Node.FS.Link(fs.File(test.workpath('build/foo')),
360 fs.File(test.workpath('src/foo')),
362 os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE)
363 st=os.stat(test.workpath('build/foo'))
364 assert (stat.S_IMODE(st[stat.ST_MODE]) & stat.S_IWRITE), \
365 stat.S_IMODE(st[stat.ST_MODE])
369 fs = SCons.Node.FS.FS()
370 fs.BuildDir('build', '/test/foo')
371 except SCons.Errors.UserError:
373 assert exc_caught, "Should have caught a UserError."
378 fs = SCons.Node.FS.FS()
379 fs.BuildDir('build', 'build/src')
380 except SCons.Errors.UserError:
382 assert exc_caught, "Should have caught a UserError."
384 test.unlink( "src/foo" )
385 test.unlink( "build/foo" )
387 fs = SCons.Node.FS.FS()
388 fs.BuildDir('build', 'src1')
390 # Calling the same BuildDir twice should work fine.
391 fs.BuildDir('build', 'src1')
393 # Trying to move a build dir to a second source dir
396 fs.BuildDir('build', 'src2')
397 except SCons.Errors.UserError:
400 assert 0, "Should have caught a UserError."
402 # Test against a former bug. Make sure we can get a repository
403 # path for the build directory itself!
404 fs=SCons.Node.FS.FS(test.workpath('work'))
406 fs.BuildDir('build/var3', 'src', duplicate=0)
407 d1 = fs.Dir('build/var3')
408 assert d1.rdir() == fs.Dir('src'), str(d1.rdir())
410 # verify the link creation attempts in file_link()
411 class LinkSimulator :
412 """A class to intercept os.[sym]link() calls and track them."""
414 def __init__( self ) :
418 """Reset the simulator if necessary"""
419 if not self._need_reset() : return # skip if not needed now
420 self.link_called = False
421 self.symlink_called = False
422 self.copy_called = False
424 def _need_reset( self ) :
426 Determines whether or not the simulator needs to be reset.
427 A reset is necessary if the object is first being initialized,
428 or if all three methods have been tried already.
431 ( not hasattr( self , "link_called" ) )
433 ( self.link_called and
434 self.symlink_called and
438 def link_fail( self , src , dest ) :
440 assert not self.symlink_called , \
441 "Wrong link order: symlink tried before hard link."
442 assert not self.copy_called , \
443 "Wrong link order: copy tried before hard link."
444 self.link_called = True
445 raise OSError( "Simulating hard link creation error." )
447 def symlink_fail( self , src , dest ) :
449 assert self.link_called , \
450 "Wrong link order: hard link not tried before symlink."
451 assert not self.copy_called , \
452 "Wrong link order: copy tried before symlink link."
453 self.symlink_called = True
454 raise OSError( "Simulating symlink creation error." )
456 def copy( self , src , dest ) :
458 assert self.link_called , \
459 "Wrong link order: hard link not tried before copy."
460 assert self.symlink_called , \
461 "Wrong link order: symlink not tried before copy."
462 self.copy_called = True
463 # copy succeeds, but use the real copy
464 self._real_copy(src, dest)
465 # end class LinkSimulator
466 simulator = LinkSimulator()
468 # save the real functions for later restoration
473 except AttributeError:
476 real_symlink = os.symlink
477 except AttributeError:
479 real_copy = shutil.copy2
480 simulator._real_copy = real_copy # the simulator needs the real one
482 # override the real functions with our simulation
483 os.link = simulator.link_fail
484 os.symlink = simulator.symlink_fail
485 shutil.copy2 = simulator.copy
488 test.write('src/foo', 'src/foo\n')
490 os.chmod(test.workpath('src/foo'), stat.S_IRUSR)
491 SCons.Node.FS.Link(fs.File(test.workpath('build/foo')),
492 fs.File(test.workpath('src/foo')),
494 os.chmod(test.workpath('src/foo'), stat.S_IRUSR | stat.S_IWRITE)
496 test.unlink( "src/foo" )
497 test.unlink( "build/foo" )
500 # restore the real functions
506 os.symlink = real_symlink
508 delattr(os, 'symlink')
509 shutil.copy2 = real_copy
511 class FSTestCase(unittest.TestCase):
513 """Test FS (file system) Node operations
515 This test case handles all of the file system node
516 tests in one environment, so we don't have to set up a
517 complicated directory structure for each test individually.
519 test = TestCmd(workdir = '')
520 test.subdir('sub', ['sub', 'dir'])
522 wp = test.workpath('')
523 sub = test.workpath('sub', '')
524 sub_dir = test.workpath('sub', 'dir', '')
525 sub_dir_foo = test.workpath('sub', 'dir', 'foo', '')
526 sub_dir_foo_bar = test.workpath('sub', 'dir', 'foo', 'bar', '')
527 sub_foo = test.workpath('sub', 'foo', '')
531 fs = SCons.Node.FS.FS()
534 assert isinstance(e1, SCons.Node.FS.Entry)
537 assert isinstance(d1, SCons.Node.FS.Dir)
538 assert d1.cwd is d1, d1
540 f1 = fs.File('f1', directory = d1)
541 assert isinstance(f1, SCons.Node.FS.File)
543 d1_f1 = os.path.join('d1', 'f1')
544 assert f1.path == d1_f1, "f1.path %s != %s" % (f1.path, d1_f1)
545 assert str(f1) == d1_f1, "str(f1) %s != %s" % (str(f1), d1_f1)
548 assert isinstance(x1, SCons.Node.FS.File)
549 assert str(x1) == os.path.join('d1', 'x1')
552 assert isinstance(x2, SCons.Node.FS.Dir)
553 assert str(x2) == os.path.join('d1', 'x2')
556 assert isinstance(x3, SCons.Node.FS.Entry)
557 assert str(x3) == os.path.join('d1', 'x3')
559 assert d1.File(x1) == x1
560 assert d1.Dir(x2) == x2
561 assert d1.Entry(x3) == x3
566 assert str(x4) == os.path.join('d1', 'x4')
569 assert str(x5) == os.path.join('d1', 'x5')
572 assert str(x6) == os.path.join('d1', 'x6')
574 assert str(x7) == os.path.join('d1', 'x7')
576 assert x1.File(x4) == x4
577 assert x1.Dir(x5) == x5
578 assert x1.Entry(x6) == x6
579 assert x1.Entry(x7) == x7
581 assert x1.Entry(x5) == x5
589 assert x1.Entry(x4) == x4
598 assert isinstance(x6, SCons.Node.FS.File)
601 assert isinstance(x7, SCons.Node.FS.Dir)
609 def Dir_test(lpath, path_, abspath_, up_path_, fileSys=fs, s=sep):
610 dir = fileSys.Dir(string.replace(lpath, '/', s))
613 path_ = string.replace(path_, '/', os.sep)
614 abspath_ = string.replace(abspath_, '/', os.sep)
615 up_path_ = string.replace(up_path_, '/', os.sep)
618 if p[-1] == os.sep and len(p) > 1:
621 path = strip_slash(path_)
622 abspath = strip_slash(abspath_)
623 up_path = strip_slash(up_path_)
624 name = string.split(abspath, os.sep)[-1]
626 assert dir.name == name, \
627 "dir.name %s != expected name %s" % \
629 assert dir.path == path, \
630 "dir.path %s != expected path %s" % \
632 assert str(dir) == path, \
633 "str(dir) %s != expected path %s" % \
635 assert dir.path_ == path_, \
636 "dir.path_ %s != expected path_ %s" % \
638 assert dir.get_abspath() == abspath, \
639 "dir.abspath %s != expected absolute path %s" % \
640 (dir.get_abspath(), abspath)
641 assert dir.abspath_ == abspath_, \
642 "dir.abspath_ %s != expected absolute path_ %s" % \
643 (dir.abspath_, abspath_)
644 assert dir.up().path == up_path, \
645 "dir.up().path %s != expected parent path %s" % \
646 (dir.up().path, up_path)
647 assert dir.up().path_ == up_path_, \
648 "dir.up().path_ %s != expected parent path_ %s" % \
649 (dir.up().path_, up_path_)
651 Dir_test('foo', 'foo/', sub_dir_foo, './')
652 Dir_test('foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
653 Dir_test('/foo', '/foo/', '/foo/', '/')
654 Dir_test('/foo/bar', '/foo/bar/', '/foo/bar/', '/foo/')
655 Dir_test('..', sub, sub, wp)
656 Dir_test('foo/..', './', sub_dir, sub)
657 Dir_test('../foo', sub_foo, sub_foo, sub)
658 Dir_test('.', './', sub_dir, sub)
659 Dir_test('./.', './', sub_dir, sub)
660 Dir_test('foo/./bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
661 Dir_test('#../foo', sub_foo, sub_foo, sub)
662 Dir_test('#/../foo', sub_foo, sub_foo, sub)
663 Dir_test('#foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
664 Dir_test('#/foo/bar', 'foo/bar/', sub_dir_foo_bar, 'foo/')
665 Dir_test('#', './', sub_dir, sub)
668 f2 = fs.File(string.join(['f1', 'f2'], sep), directory = d1)
670 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
676 dir = fs.Dir(string.join(['d1', 'f1'], sep))
678 assert str(x) == ("Tried to lookup File '%s' as a Dir." %
686 assert str(x) == ("Tried to lookup Dir '%s' as a File." %
691 # Test that just specifying the drive works to identify
692 # its root directory.
693 p = os.path.abspath(test.workpath('root_file'))
694 drive, path = os.path.splitdrive(p)
696 # The assert below probably isn't correct for the
697 # general case, but it works for Win32, which covers a
700 assert str(dir) == drive + os.sep, str(dir)
702 # Test Dir.children()
704 fs.File(string.join(['ddd', 'f1'], sep))
705 fs.File(string.join(['ddd', 'f2'], sep))
706 fs.File(string.join(['ddd', 'f3'], sep))
707 fs.Dir(string.join(['ddd', 'd1'], sep))
708 fs.Dir(string.join(['ddd', 'd1', 'f4'], sep))
709 fs.Dir(string.join(['ddd', 'd1', 'f5'], sep))
710 kids = map(lambda x: x.path, dir.children(None))
712 assert kids == [os.path.join('ddd', 'd1'),
713 os.path.join('ddd', 'f1'),
714 os.path.join('ddd', 'f2'),
715 os.path.join('ddd', 'f3')]
716 kids = map(lambda x: x.path_, dir.children(None))
718 assert kids == [os.path.join('ddd', 'd1', ''),
719 os.path.join('ddd', 'f1'),
720 os.path.join('ddd', 'f2'),
721 os.path.join('ddd', 'f3')]
723 # Test for a bug in 0.04 that did not like looking up
724 # dirs with a trailing slash on Win32.
726 assert d.path_ == '.' + os.sep, d.abspath_
728 assert d.path_ == 'foo' + os.sep, d.path_
730 # Test for sub-classing of node building.
735 d1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
736 d1.builder_set(Builder(fs.File))
737 d1.env_set(Environment())
743 f1.add_source([SCons.Node.Node()]) # XXX FAKE SUBCLASS ATTRIBUTE
744 f1.builder_set(Builder(fs.File))
745 f1.env_set(Environment())
749 def match(path, expect):
750 expect = string.replace(expect, '/', os.sep)
751 assert path == expect, "path %s != expected %s" % (path, expect)
754 assert e1.__class__.__name__ == 'Dir'
756 match(e1.path_, "d1/")
757 match(e1.dir.path, ".")
759 e2 = fs.Entry("d1/f1")
760 assert e2.__class__.__name__ == 'File'
761 match(e2.path, "d1/f1")
762 match(e2.path_, "d1/f1")
763 match(e2.dir.path, "d1")
766 assert e3.__class__.__name__ == 'Entry'
768 match(e3.path_, "e3")
769 match(e3.dir.path, ".")
771 e4 = fs.Entry("d1/e4")
772 assert e4.__class__.__name__ == 'Entry'
773 match(e4.path, "d1/e4")
774 match(e4.path_, "d1/e4")
775 match(e4.dir.path, "d1")
777 e5 = fs.Entry("e3/e5")
778 assert e3.__class__.__name__ == 'Dir'
780 match(e3.path_, "e3/")
781 match(e3.dir.path, ".")
782 assert e5.__class__.__name__ == 'Entry'
783 match(e5.path, "e3/e5")
784 match(e5.path_, "e3/e5")
785 match(e5.dir.path, "e3")
789 assert e4.__class__.__name__ == 'Dir'
790 match(e4.path, "d1/e4")
791 match(e4.path_, "d1/e4/")
792 match(e4.dir.path, "d1")
794 e7 = fs.File("e3/e5")
796 assert e5.__class__.__name__ == 'File'
797 match(e5.path, "e3/e5")
798 match(e5.path_, "e3/e5")
799 match(e5.dir.path, "e3")
802 assert e8.get_bsig() is None, e8.get_bsig()
803 assert e8.get_csig() is None, e8.get_csig()
806 assert e8.get_bsig() == 'xxx', e8.get_bsig()
807 assert e8.get_csig() == 'yyy', e8.get_csig()
810 assert f9.get_bsig() is None, f9.get_bsig()
811 assert f9.get_csig() is None, f9.get_csig()
814 assert f9.get_bsig() == 'xxx', f9.get_bsig()
815 assert f9.get_csig() == 'yyy', f9.get_csig()
818 assert d10.get_bsig() is None, d10.get_bsig()
819 assert d10.get_csig() is None, d10.get_csig()
822 assert d10.get_bsig() is None, d10.get_bsig()
823 assert d10.get_csig() is None, d10.get_csig()
825 fs.chdir(fs.Dir('subdir'))
827 match(f11.path, "subdir/f11")
829 match(d12.path_, "subdir/d12/")
830 e13 = fs.Entry("subdir/e13")
831 match(e13.path, "subdir/subdir/e13")
832 fs.chdir(fs.Dir('..'))
835 f1.builder_set(Builder(fs.File))
836 f1.env_set(Environment())
838 f1.target_scanner = Scanner(xyz)
841 assert f1.implicit[0].path_ == "xyz"
844 assert f1.implicit == []
847 assert f1.implicit[0].path_ == "xyz"
849 assert f1.get_stored_implicit()[0] == "xyz"
851 # Test underlying scanning functionality in get_found_includes()
856 deps = f12.get_found_includes(env, None, t1)
857 assert deps == [], deps
859 class MyScanner(Scanner):
861 def __call__(self, node, env, path):
862 self.call_count = self.call_count + 1
863 return Scanner.__call__(self, node, env, path)
866 deps = f12.get_found_includes(env, s, t1)
867 assert deps == [xyz], deps
868 assert s.call_count == 1, s.call_count
870 deps = f12.get_found_includes(env, s, t1)
871 assert deps == [xyz], deps
872 assert s.call_count == 1, s.call_count
876 deps = f12.get_found_includes(env, s, t1)
877 assert deps == [xyz], deps
878 assert s.call_count == 2, s.call_count
880 # Make sure we can scan this file even if the target isn't
881 # a file that has a scanner (it might be an Alias, e.g.).
885 deps = f12.get_found_includes(env, s, DummyNode())
886 assert deps == [xyz], deps
888 # Test building a file whose directory is not there yet...
889 f1 = fs.File(test.workpath("foo/bar/baz/ack"))
890 assert not f1.dir.exists()
893 assert f1.dir.exists()
898 fs = SCons.Node.FS.FS()
899 assert str(fs.getcwd()) == ".", str(fs.getcwd())
900 fs.chdir(fs.Dir('subdir'))
901 # The cwd's path is always "."
902 assert str(fs.getcwd()) == ".", str(fs.getcwd())
903 assert fs.getcwd().path == 'subdir', fs.getcwd().path
904 fs.chdir(fs.Dir('../..'))
905 assert fs.getcwd().path == test.workdir, fs.getcwd().path
907 f1 = fs.File(test.workpath("do_i_exist"))
908 assert not f1.exists()
909 test.write("do_i_exist","\n")
910 assert not f1.exists()
913 test.unlink("do_i_exist")
916 assert not f1.exists()
918 # For some reason, in Win32, the \x1a character terminates
919 # the reading of files in text mode. This tests that
920 # get_contents() returns the binary contents.
921 test.write("binary_file", "Foo\x1aBar")
922 f1 = SCons.Node.FS.default_fs.File(test.workpath("binary_file"))
923 assert f1.get_contents() == "Foo\x1aBar", f1.get_contents()
925 def nonexistent(method, s):
927 x = method(s, create = 0)
928 except SCons.Errors.UserError:
931 raise TestFailed, "did not catch expected UserError"
933 nonexistent(fs.Entry, 'nonexistent')
934 nonexistent(fs.Entry, 'nonexistent/foo')
936 nonexistent(fs.File, 'nonexistent')
937 nonexistent(fs.File, 'nonexistent/foo')
939 nonexistent(fs.Dir, 'nonexistent')
940 nonexistent(fs.Dir, 'nonexistent/foo')
942 test.write("preserve_me", "\n")
943 assert os.path.exists(test.workpath("preserve_me"))
944 f1 = fs.File(test.workpath("preserve_me"))
946 assert os.path.exists(test.workpath("preserve_me"))
948 test.write("remove_me", "\n")
949 assert os.path.exists(test.workpath("remove_me"))
950 f1 = fs.File(test.workpath("remove_me"))
951 f1.builder = Builder(fs.File)
952 f1.env_set(Environment())
954 assert not os.path.exists(test.workpath("remove_me"))
956 e = fs.Entry('e_local')
957 assert not hasattr(e, '_local')
960 f = fs.File('e_local')
962 f = fs.File('f_local')
965 #XXX test current() for directories
967 #XXX test sconsign() for directories
969 #XXX test set_signature() for directories
971 #XXX test build() for directories
975 # test Entry.get_contents()
976 e = fs.Entry('does_not_exist')
980 except AttributeError:
982 assert exc_caught, "Should have caught an AttributError"
984 test.write("file", "file\n")
988 assert c == "file\n", c
989 assert e.__class__ == SCons.Node.FS.File
997 assert e.__class__ == SCons.Node.FS.Dir
999 test.write("tstamp", "tstamp\n")
1001 # Okay, *this* manipulation accomodates Windows FAT file systems
1002 # that only have two-second granularity on their timestamps.
1003 # We round down the current time to the nearest even integer
1004 # value, subtract two to make sure the timestamp is not "now,"
1005 # and then convert it back to a float.
1006 tstamp = float(int(time.time() / 2) * 2) - 2
1007 os.utime(test.workpath("tstamp"), (tstamp - 2.0, tstamp))
1008 f = fs.File("tstamp")
1009 t = f.get_timestamp()
1010 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
1012 test.unlink("tstamp")
1014 test.subdir('tdir1')
1016 t = d.get_timestamp()
1017 assert t == 0, "expected 0, got %s" % str(t)
1019 test.subdir('tdir2')
1021 f1 = test.workpath('tdir2', 'file1')
1022 f2 = test.workpath('tdir2', 'file2')
1023 test.write(f1, 'file1\n')
1024 test.write(f2, 'file2\n')
1027 current_time = float(int(time.time() / 2) * 2)
1028 t1 = current_time - 4.0
1029 t2 = current_time - 2.0
1030 os.utime(f1, (t1 - 2.0, t1))
1031 os.utime(f2, (t2 - 2.0, t2))
1032 t = d.get_timestamp()
1033 assert t == t2, "expected %f, got %f" % (t2, t)
1035 #XXX test get_prevsiginfo()
1037 skey = fs.Entry('eee.x').scanner_key()
1038 assert skey == '.x', skey
1039 skey = fs.Entry('eee.xyz').scanner_key()
1040 assert skey == '.xyz', skey
1042 skey = fs.File('fff.x').scanner_key()
1043 assert skey == '.x', skey
1044 skey = fs.File('fff.xyz').scanner_key()
1045 assert skey == '.xyz', skey
1047 skey = fs.Dir('ddd.x').scanner_key()
1048 assert skey is None, skey
1051 f1 = fs.File('dir/file')
1052 assert f1.dir == d1, f1.dir
1053 parents = f1.get_parents()
1054 assert parents == [ d1 ], parents
1056 test.write("i_am_not_a_directory", "\n")
1060 fs.Dir(test.workpath("i_am_not_a_directory"))
1063 assert exc_caught, "Should have caught a TypeError"
1065 test.unlink("i_am_not_a_directory")
1072 assert exc_caught, "Should have caught a TypeError"
1074 # XXX test calc_signature()
1076 # XXX test current()
1082 f = fs.File('does_not_exist')
1086 test.write('exists', "exists\n")
1087 f = fs.File('exists')
1090 assert not os.path.exists(test.workpath('exists')), "exists was not removed"
1092 symlink = test.workpath('symlink')
1094 os.symlink(test.workpath('does_not_exist'), symlink)
1095 assert os.path.islink(symlink)
1096 f = fs.File('symlink')
1099 assert not os.path.islink(symlink), "symlink was not removed"
1100 except AttributeError:
1103 test.write('can_not_remove', "can_not_remove\n")
1104 test.writable(test.workpath('.'), 0)
1105 fp = open(test.workpath('can_not_remove'))
1107 f = fs.File('can_not_remove')
1116 assert exc_caught, "Should have caught an OSError, r = " + str(r)
1118 f = fs.Entry('foo/bar/baz')
1119 assert f.for_signature() == 'baz', f.for_signature()
1120 assert f.get_string(0) == os.path.normpath('foo/bar/baz'), \
1122 assert f.get_string(1) == 'baz', f.get_string(1)
1125 t = x.target_from_source('pre-', '-suf')
1126 assert str(t) == 'pre-x-suf', str(t)
1128 y = fs.File('dir/y')
1129 t = y.target_from_source('pre-', '-suf')
1130 assert str(t) == os.path.join('dir', 'pre-y-suf'), str(t)
1133 t = z.target_from_source('pre-', '-suf', lambda x: x[:-1])
1134 assert str(t) == 'pre-z-suf', str(t)
1136 class EntryTestCase(unittest.TestCase):
1138 """Test methods specific to the Entry sub-class.
1140 test = TestCmd(workdir='')
1141 # FS doesn't like the cwd to be something other than its root.
1142 os.chdir(test.workpath(""))
1144 fs = SCons.Node.FS.FS()
1148 assert e1.__class__ is SCons.Node.FS.File, e1.__class__
1151 e2.get_found_includes(None, None, None)
1152 assert e2.__class__ is SCons.Node.FS.File, e2.__class__
1155 test.write('e3f', "e3f\n")
1157 e3d = fs.Entry('e3d')
1159 assert e3d.__class__ is SCons.Node.FS.Dir, e3d.__class__
1161 e3f = fs.Entry('e3f')
1163 assert e3f.__class__ is SCons.Node.FS.File, e3f.__class__
1165 e3n = fs.Entry('e3n')
1169 except AttributeError:
1171 assert exc_caught, "did not catch expected AttributeError"
1174 test.write('e4f', "e4f\n")
1176 e4d = fs.Entry('e4d')
1177 exists = e4d.exists()
1178 assert e4d.__class__ is SCons.Node.FS.Dir, e4d.__class__
1179 assert exists, "e4d does not exist?"
1181 e4f = fs.Entry('e4f')
1182 exists = e4f.exists()
1183 assert e4f.__class__ is SCons.Node.FS.File, e4f.__class__
1184 assert exists, "e4f does not exist?"
1186 e4n = fs.Entry('e4n')
1187 exists = e4n.exists()
1188 assert e4n.__class__ is SCons.Node.FS.File, e4n.__class__
1189 assert not exists, "e4n exists?"
1192 def __init__(self, val):
1194 def csig(self, node, cache):
1196 def bsig(self, node, cache):
1197 return self.val + 222
1199 test.write('e5f', "e5f\n")
1201 e5d = fs.Entry('e5d')
1202 sig = e5d.calc_signature(MyCalc(555))
1203 assert e5d.__class__ is SCons.Node.FS.Dir, e5d.__class__
1204 assert sig == 777, sig
1206 e5f = fs.Entry('e5f')
1207 sig = e5f.calc_signature(MyCalc(666))
1208 assert e5f.__class__ is SCons.Node.FS.File, e5f.__class__
1209 assert sig == 666, sig
1211 e5n = fs.Entry('e5n')
1212 sig = e5n.calc_signature(MyCalc(777))
1213 assert e5n.__class__ is SCons.Node.FS.File, e5n.__class__
1214 assert sig is None, sig
1218 class RepositoryTestCase(unittest.TestCase):
1220 """Test FS (file system) Repository operations
1223 fs = SCons.Node.FS.FS()
1225 fs.Repository('foo')
1226 fs.Repository(os.path.join('foo', 'bar'))
1227 fs.Repository(os.path.join('bar', 'foo'))
1228 fs.Repository('bar')
1230 rep = fs.Dir('#').getRepositories()
1231 assert len(rep) == 4, map(str, rep)
1232 r = map(lambda x, np=os.path.normpath: np(str(x)), rep)
1234 os.path.join('foo', 'bar'),
1235 os.path.join('bar', 'foo'),
1238 test = TestCmd(workdir = '')
1239 test.subdir('rep1', 'rep2', 'rep3', 'work')
1241 rep1 = test.workpath('rep1')
1242 rep2 = test.workpath('rep2')
1243 rep3 = test.workpath('rep3')
1245 os.chdir(test.workpath('work'))
1247 fs = SCons.Node.FS.FS()
1248 fs.Repository(rep1, rep2, rep3)
1250 f1 = fs.File(os.path.join('f1'))
1251 assert f1.rfile() is f1
1253 test.write([rep1, 'f2'], "")
1256 assert not f2.rfile() is f2, f2.rfile()
1257 assert str(f2.rfile()) == os.path.join(rep1, 'f2'), str(f2.rfile())
1259 test.subdir([rep2, 'f3'])
1260 test.write([rep3, 'f3'], "")
1263 assert not f3.rfile() is f3, f3.rfile()
1264 assert f3.rstr() == os.path.join(rep3, 'f3'), f3.rstr()
1266 assert fs.Rsearch('f1') is None
1267 assert fs.Rsearch('f2')
1268 assert fs.Rsearch(f3) is f3
1270 list = fs.Rsearchall(fs.Dir('d1'))
1271 assert len(list) == 1, list
1272 assert list[0].path == 'd1', list[0].path
1274 list = fs.Rsearchall([fs.Dir('d1')])
1275 assert len(list) == 1, list
1276 assert list[0].path == 'd1', list[0].path
1278 list = fs.Rsearchall('d2')
1279 assert list == [], list
1281 list = fs.Rsearchall('#d2')
1282 assert list == [], list
1284 test.subdir(['work', 'd2'])
1285 fs.File('d2').built() # Clear exists cache
1286 list = fs.Rsearchall('d2')
1287 assert map(str, list) == ['d2'], list
1289 test.subdir(['rep2', 'd2'])
1290 fs.File('../rep2/d2').built() # Clear exists cache
1291 list = fs.Rsearchall('d2')
1292 assert map(str, list) == ['d2', test.workpath('rep2', 'd2')], list
1294 test.subdir(['rep1', 'd2'])
1295 fs.File('../rep1/d2').built() # Clear exists cache
1296 list = fs.Rsearchall('d2')
1297 assert map(str, list) == ['d2',
1298 test.workpath('rep1', 'd2'),
1299 test.workpath('rep2', 'd2')], list
1301 list = fs.Rsearchall(['d3', 'd4'])
1302 assert list == [], list
1304 test.subdir(['work', 'd3'])
1305 fs.File('d3').built() # Clear exists cache
1306 list = map(str, fs.Rsearchall(['d3', 'd4']))
1307 assert list == ['d3'], list
1309 test.subdir(['rep3', 'd4'])
1310 fs.File('../rep3/d4').built() # Clear exists cache
1311 list = map(str, fs.Rsearchall(['d3', 'd4']))
1312 assert list == ['d3', test.workpath('rep3', 'd4')], list
1314 list = map(str, fs.Rsearchall(string.join(['d3', 'd4'], os.pathsep)))
1315 assert list == ['d3', test.workpath('rep3', 'd4')], list
1317 work_d4 = fs.File(os.path.join('work', 'd4'))
1318 list = map(str, fs.Rsearchall(['d3', work_d4]))
1319 assert list == ['d3', str(work_d4)], list
1321 fs.BuildDir('build', '.')
1323 f = fs.File(test.workpath("work", "i_do_not_exist"))
1324 assert not f.rexists()
1326 test.write(["rep2", "i_exist"], "\n")
1327 f = fs.File(test.workpath("work", "i_exist"))
1330 test.write(["work", "i_exist_too"], "\n")
1331 f = fs.File(test.workpath("work", "i_exist_too"))
1334 f1 = fs.File(os.path.join('build', 'f1'))
1335 assert not f1.rexists()
1337 f2 = fs.File(os.path.join('build', 'f2'))
1340 test.write(["rep2", "tstamp"], "tstamp\n")
1342 # Okay, *this* manipulation accomodates Windows FAT file systems
1343 # that only have two-second granularity on their timestamps.
1344 # We round down the current time to the nearest even integer
1345 # value, subtract two to make sure the timestamp is not "now,"
1346 # and then convert it back to a float.
1347 tstamp = float(int(time.time() / 2) * 2) - 2
1348 os.utime(test.workpath("rep2", "tstamp"), (tstamp - 2.0, tstamp))
1349 f = fs.File("tstamp")
1350 t = f.get_timestamp()
1351 assert t == tstamp, "expected %f, got %f" % (tstamp, t)
1353 test.unlink(["rep2", "tstamp"])
1355 # Make sure get_contents() returns the binary contents.
1356 test.write(["rep3", "contents"], "Con\x1aTents\n")
1358 c = fs.File("contents").get_contents()
1359 assert c == "Con\x1aTents\n", "got '%s'" % c
1361 test.unlink(["rep3", "contents"])
1363 # XXX test calc_signature()
1365 # XXX test current()
1367 class find_fileTestCase(unittest.TestCase):
1369 """Testing find_file function"""
1370 test = TestCmd(workdir = '')
1371 test.write('./foo', 'Some file\n')
1372 fs = SCons.Node.FS.FS(test.workpath(""))
1373 os.chdir(test.workpath("")) # FS doesn't like the cwd to be something other than it's root
1374 node_derived = fs.File(test.workpath('bar/baz'))
1375 node_derived.builder_set(1) # Any non-zero value.
1376 node_pseudo = fs.File(test.workpath('pseudo'))
1377 node_pseudo.set_src_builder(1) # Any non-zero value.
1378 paths = map(fs.Dir, ['.', './bar'])
1379 nodes = [SCons.Node.FS.find_file('foo', paths, fs.File),
1380 SCons.Node.FS.find_file('baz', paths, fs.File),
1381 SCons.Node.FS.find_file('pseudo', paths, fs.File)]
1382 file_names = map(str, nodes)
1383 file_names = map(os.path.normpath, file_names)
1384 assert os.path.normpath('./foo') in file_names, file_names
1385 assert os.path.normpath('./bar/baz') in file_names, file_names
1386 assert os.path.normpath('./pseudo') in file_names, file_names
1388 class StringDirTestCase(unittest.TestCase):
1390 """Test using a string as the second argument of
1393 test = TestCmd(workdir = '')
1395 fs = SCons.Node.FS.FS(test.workpath(''))
1397 d = fs.Dir('sub', '.')
1398 assert str(d) == 'sub'
1400 f = fs.File('file', 'sub')
1401 assert str(f) == os.path.join('sub', 'file')
1402 assert not f.exists()
1404 class has_src_builderTestCase(unittest.TestCase):
1406 """Test the has_src_builder() method"""
1407 test = TestCmd(workdir = '')
1408 fs = SCons.Node.FS.FS(test.workpath(''))
1409 os.chdir(test.workpath(''))
1411 test.subdir('sub2', ['sub2', 'SCCS'], ['sub2', 'RCS'])
1413 sub1 = fs.Dir('sub1', '.')
1414 f1 = fs.File('f1', sub1)
1415 f2 = fs.File('f2', sub1)
1416 f3 = fs.File('f3', sub1)
1417 sub2 = fs.Dir('sub2', '.')
1418 f4 = fs.File('f4', sub2)
1419 f5 = fs.File('f5', sub2)
1420 f6 = fs.File('f6', sub2)
1422 h = f1.has_src_builder()
1425 b1 = Builder(fs.File)
1426 sub1.set_src_builder(b1)
1428 test.write(['sub1', 'f2'], "sub1/f2\n")
1429 h = f1.has_src_builder() # cached from previous call
1431 h = f2.has_src_builder()
1433 h = f3.has_src_builder()
1435 assert f3.builder is b1, f3.builder
1437 test.write(['sub2', 'SCCS', 's.f5'], "sub2/SCCS/s.f5\n")
1438 test.write(['sub2', 'RCS', 'f6,v'], "sub2/RCS/f6,v\n")
1439 h = f4.has_src_builder()
1441 h = f5.has_src_builder()
1443 h = f6.has_src_builder()
1446 class prepareTestCase(unittest.TestCase):
1448 """Test the prepare() method"""
1450 class MyFile(SCons.Node.FS.File):
1451 def _createDir(self):
1452 raise SCons.Errors.StopError
1456 fs = SCons.Node.FS.FS()
1457 file = MyFile('foo', fs.Dir('.'), fs)
1462 except SCons.Errors.StopError:
1464 assert exc_caught, "Should have caught a StopError."
1466 save_Mkdir = SCons.Node.FS.Mkdir
1468 def mkdir_func(target, source, env, dir_made=dir_made):
1469 dir_made.append(target)
1470 SCons.Node.FS.Mkdir = mkdir_func
1472 file = fs.File(os.path.join("new_dir", "xyz"))
1474 file.set_state(SCons.Node.up_to_date)
1476 assert dir_made == [], dir_made
1479 assert dir_made[0].path == "new_dir", dir_made[0].path
1481 SCons.Node.FS.Mkdir = save_Mkdir
1486 class get_actionsTestCase(unittest.TestCase):
1488 """Test the Dir's get_action() method"""
1490 fs = SCons.Node.FS.FS()
1492 a = dir.get_actions()
1495 class SConstruct_dirTestCase(unittest.TestCase):
1497 """Test setting the SConstruct directory"""
1499 fs = SCons.Node.FS.FS()
1500 fs.set_SConstruct_dir(fs.Dir('xxx'))
1501 assert fs.SConstruct_dir.path == 'xxx'
1503 class CacheDirTestCase(unittest.TestCase):
1505 """Test CacheDir functionality"""
1506 test = TestCmd(workdir='')
1510 fs = SCons.Node.FS.FS()
1511 assert fs.CachePath is None, fs.CachePath
1512 assert fs.cache_force is None, fs.cache_force
1513 assert fs.cache_show is None, fs.cache_show
1515 fs.CacheDir('cache')
1516 assert fs.CachePath == 'cache', fs.CachePath
1518 save_CacheRetrieve = SCons.Node.FS.CacheRetrieve
1520 def retrieve_succeed(target, source, env, self=self):
1521 self.retrieved.append(target)
1523 def retrieve_fail(target, source, env, self=self):
1524 self.retrieved.append(target)
1527 f1 = fs.File("cd.f1")
1528 f1.builder_set(Builder(fs.File))
1529 f1.env_set(Environment())
1531 SCons.Node.FS.CacheRetrieve = retrieve_succeed
1535 r = f1.retrieve_from_cache()
1537 assert self.retrieved == [f1], self.retrieved
1538 assert built_it is None, built_it
1540 SCons.Node.FS.CacheRetrieve = retrieve_fail
1544 r = f1.retrieve_from_cache()
1546 assert self.retrieved == [f1], self.retrieved
1547 assert built_it is None, built_it
1549 SCons.Node.FS.CacheRetrieve = save_CacheRetrieve
1551 save_CacheRetrieveSilent = SCons.Node.FS.CacheRetrieveSilent
1555 f2 = fs.File("cd.f2")
1556 f2.builder_set(Builder(fs.File))
1557 f2.env_set(Environment())
1559 SCons.Node.FS.CacheRetrieveSilent = retrieve_succeed
1563 r = f2.retrieve_from_cache()
1565 assert self.retrieved == [f2], self.retrieved
1566 assert built_it is None, built_it
1568 SCons.Node.FS.CacheRetrieveSilent = retrieve_fail
1572 r = f2.retrieve_from_cache()
1574 assert self.retrieved == [f2], self.retrieved
1575 assert built_it is None, built_it
1577 SCons.Node.FS.CacheRetrieveSilent = save_CacheRetrieveSilent
1579 save_CachePush = SCons.Node.FS.CachePush
1580 def push(target, source, env, self=self):
1581 self.pushed.append(target)
1583 SCons.Node.FS.CachePush = push
1588 cd_f3 = test.workpath("cd.f3")
1591 assert self.pushed == [], self.pushed
1592 test.write(cd_f3, "cd.f3\n")
1594 assert self.pushed == [f3], self.pushed
1598 cd_f4 = test.workpath("cd.f4")
1601 assert self.pushed == [], self.pushed
1602 test.write(cd_f4, "cd.f4\n")
1604 assert self.pushed == [], self.pushed
1607 assert self.pushed == [f4], self.pushed
1609 SCons.Node.FS.CachePush = save_CachePush
1611 # Verify how the cachepath() method determines the name
1612 # of the file in cache.
1613 def my_collect(list):
1615 save_collect = SCons.Sig.MD5.collect
1616 SCons.Sig.MD5.collect = my_collect
1618 f5 = fs.File("cd.f5")
1619 f5.set_bsig('a_fake_bsig')
1621 dirname = os.path.join('cache', 'A')
1622 filename = os.path.join(dirname, 'a_fake_bsig')
1623 assert cp == (dirname, filename), cp
1625 SCons.Sig.MD5.collect = save_collect
1627 # Verify that no bsig raises an InternalERror
1628 f6 = fs.File("cd.f6")
1633 except SCons.Errors.InternalError:
1637 # Verify that we raise a warning if we can't copy a file to cache.
1638 save_copy2 = shutil.copy2
1639 def copy2(src, dst):
1641 shutil.copy2 = copy2
1642 save_mkdir = os.mkdir
1646 old_warn_exceptions = SCons.Warnings.warningAsException(1)
1647 SCons.Warnings.enableWarningClass(SCons.Warnings.CacheWriteErrorWarning)
1650 cd_f7 = test.workpath("cd.f7")
1651 test.write(cd_f7, "cd.f7\n")
1653 f7.set_bsig('f7_bsig')
1658 except SCons.Warnings.CacheWriteErrorWarning:
1662 shutil.copy2 = save_copy2
1663 os.mkdir = save_mkdir
1664 SCons.Warnings.warningAsException(old_warn_exceptions)
1665 SCons.Warnings.suppressWarningClass(SCons.Warnings.CacheWriteErrorWarning)
1667 # Verify that we don't blow up if there's no strfunction()
1670 act.strfunction = None
1671 f8 = fs.File("cd.f8")
1672 f8.builder_set(Builder(fs.File, action=act))
1673 f8.env_set(Environment())
1675 SCons.Node.FS.CacheRetrieveSilent = retrieve_succeed
1679 r = f8.retrieve_from_cache()
1681 assert self.retrieved == [f8], self.retrieved
1682 assert built_it is None, built_it
1684 SCons.Node.FS.CacheRetrieveSilent = retrieve_fail
1688 r = f8.retrieve_from_cache()
1690 assert self.retrieved == [f8], self.retrieved
1691 assert built_it is None, built_it
1693 SCons.Node.FS.CacheRetrieveSilent = save_CacheRetrieveSilent
1695 class clearTestCase(unittest.TestCase):
1697 fs = SCons.Node.FS.FS()
1703 assert not hasattr(e, '_exists')
1704 assert not hasattr(e, '_rexists')
1710 assert not hasattr(d, '_exists')
1711 assert not hasattr(d, '_rexists')
1717 assert not hasattr(f, '_exists')
1718 assert not hasattr(f, '_rexists')
1720 class SpecialAttrTestCase(unittest.TestCase):
1722 """Test special attributes of file nodes."""
1723 test=TestCmd(workdir='')
1724 fs = SCons.Node.FS.FS(test.workpath('work'))
1726 f = fs.Entry('foo/bar/baz.blat').get_subst_proxy()
1729 assert s == os.path.normpath('foo/bar'), s
1730 assert f.dir.is_literal(), f.dir
1731 for_sig = f.dir.for_signature()
1732 assert for_sig == 'bar', for_sig
1735 assert s == 'baz.blat', s
1736 assert f.file.is_literal(), f.file
1737 for_sig = f.file.for_signature()
1738 assert for_sig == 'baz.blat_file', for_sig
1741 assert s == os.path.normpath('foo/bar/baz'), s
1742 assert f.base.is_literal(), f.base
1743 for_sig = f.base.for_signature()
1744 assert for_sig == 'baz.blat_base', for_sig
1747 assert s == 'baz', s
1748 assert f.filebase.is_literal(), f.filebase
1749 for_sig = f.filebase.for_signature()
1750 assert for_sig == 'baz.blat_filebase', for_sig
1753 assert s == '.blat', s
1754 assert f.suffix.is_literal(), f.suffix
1755 for_sig = f.suffix.for_signature()
1756 assert for_sig == 'baz.blat_suffix', for_sig
1759 assert s == test.workpath('work', 'foo', 'bar', 'baz.blat'), s
1760 assert f.abspath.is_literal(), f.abspath
1761 for_sig = f.abspath.for_signature()
1762 assert for_sig == 'baz.blat_abspath', for_sig
1765 assert s == 'foo/bar/baz.blat', s
1766 assert f.posix.is_literal(), f.posix
1768 for_sig = f.posix.for_signature()
1769 assert for_sig == 'baz.blat_posix', for_sig
1771 # And now, combinations!!!
1772 s = str(f.srcpath.base)
1773 assert s == os.path.normpath('foo/bar/baz'), s
1774 s = str(f.srcpath.dir)
1775 assert s == str(f.srcdir), s
1776 s = str(f.srcpath.posix)
1777 assert s == 'foo/bar/baz.blat', s
1779 # Test what happens with BuildDir()
1780 fs.BuildDir('foo', 'baz')
1783 assert s == os.path.normpath('baz/bar/baz.blat'), s
1784 assert f.srcpath.is_literal(), f.srcpath
1786 assert isinstance(g, SCons.Node.FS.Entry), g.__class__
1789 assert s == os.path.normpath('baz/bar'), s
1790 assert f.srcdir.is_literal(), f.srcdir
1792 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
1794 # And now what happens with BuildDir() + Repository()
1795 fs.Repository(test.workpath('repository'))
1797 f = fs.Entry('foo/sub/file.suffix').get_subst_proxy()
1798 test.subdir('repository',
1799 ['repository', 'baz'],
1800 ['repository', 'baz', 'sub'])
1802 rd = test.workpath('repository', 'baz', 'sub')
1803 rf = test.workpath('repository', 'baz', 'sub', 'file.suffix')
1804 test.write(rf, "\n")
1807 assert s == os.path.normpath('baz/sub/file.suffix'), s
1808 assert f.srcpath.is_literal(), f.srcpath
1810 assert isinstance(g, SCons.Node.FS.Entry), g.__class__
1813 assert s == os.path.normpath('baz/sub'), s
1814 assert f.srcdir.is_literal(), f.srcdir
1816 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
1820 assert f.rsrcpath.is_literal(), f.rsrcpath
1821 g = f.rsrcpath.get()
1822 assert isinstance(g, SCons.Node.FS.File), g.__class__
1826 assert f.rsrcdir.is_literal(), f.rsrcdir
1828 assert isinstance(g, SCons.Node.FS.Dir), g.__class__
1830 # Check that attempts to access non-existent attributes of the
1831 # subst proxy generate the right exceptions and messages.
1834 fs.Dir('ddd').get_subst_proxy().no_such_attr
1835 except AttributeError, e:
1836 assert str(e) == "Dir instance 'ddd' has no attribute 'no_such_attr'", e
1838 assert caught, "did not catch expected AttributeError"
1842 fs.Entry('eee').get_subst_proxy().no_such_attr
1843 except AttributeError, e:
1844 assert str(e) == "Entry instance 'eee' has no attribute 'no_such_attr'", e
1846 assert caught, "did not catch expected AttributeError"
1850 fs.File('fff').get_subst_proxy().no_such_attr
1851 except AttributeError, e:
1852 assert str(e) == "File instance 'fff' has no attribute 'no_such_attr'", e
1854 assert caught, "did not catch expected AttributeError"
1858 if __name__ == "__main__":
1859 suite = unittest.TestSuite()
1860 suite.addTest(FSTestCase())
1861 suite.addTest(BuildDirTestCase())
1862 suite.addTest(EntryTestCase())
1863 suite.addTest(RepositoryTestCase())
1864 suite.addTest(find_fileTestCase())
1865 suite.addTest(StringDirTestCase())
1866 suite.addTest(has_src_builderTestCase())
1867 suite.addTest(prepareTestCase())
1868 suite.addTest(get_actionsTestCase())
1869 suite.addTest(SConstruct_dirTestCase())
1870 suite.addTest(CacheDirTestCase())
1871 suite.addTest(clearTestCase())
1872 suite.addTest(SpecialAttrTestCase())
1873 if not unittest.TextTestRunner().run(suite).wasSuccessful():