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__"
37 sys.stdout = io.StringIO()
39 if sys.platform == 'win32':
40 existing_lib = "msvcrt"
44 class SConfTestCase(unittest.TestCase):
47 # we always want to start with a clean directory
48 self.save_cwd = os.getcwd()
49 self.test = TestCmd.TestCmd(workdir = '')
50 os.chdir(self.test.workpath(''))
55 SCons.SConsign.Reset()
56 os.chdir(self.save_cwd)
58 def _resetSConfState(self):
59 # Ok, this is tricky, and i do not know, if everything is sane.
60 # We try to reset scons' state (including all global variables)
62 SCons.SConsign.write() # simulate normal scons-finish
63 for n in sys.modules.keys():
64 if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat':
66 if isinstance(m, ModuleType):
67 # if this is really a scons module, clear its namespace
70 # we only use SCons.Environment and SCons.SConf for these tests.
71 import SCons.Environment
73 self.Environment = SCons.Environment
74 self.SConf = SCons.SConf
75 # and we need a new environment, cause references may point to
76 # old modules (well, at least this is safe ...)
77 self.scons_env = self.Environment.Environment()
78 self.scons_env.AppendENVPath('PATH', os.environ['PATH'])
80 # we want to do some autodetection here
81 # this stuff works with
82 # - cygwin on Windows (using cmd.exe, not bash)
84 # - msvc on Windows (hopefully)
85 if (not self.scons_env.Detect( self.scons_env.subst('$CXX') ) or
86 not self.scons_env.Detect( self.scons_env.subst('$CC') ) or
87 not self.scons_env.Detect( self.scons_env.subst('$LINK') )):
88 raise Exception("This test needs an installed compiler!")
89 if self.scons_env['CXX'] == 'g++':
93 if sys.platform in ['cygwin', 'win32']:
94 # On Windows, SCons.Platform.win32 redefines the builtin
95 # file() and open() functions to close the file handles.
96 # This interferes with the unittest.py infrastructure in
97 # some way. Just sidestep the issue by restoring the
98 # original builtin functions whenever we have to reset
99 # all of our global state.
102 import SCons.Platform.win32
104 builtins.file = SCons.Platform.win32._builtin_file
105 builtins.open = SCons.Platform.win32._builtin_open
107 def _baseTryXXX(self, TryFunc):
108 # TryCompile and TryLink are much the same, so we can test them
109 # in one method, we pass the function as a string ('TryCompile',
110 # 'TryLink'), so we are aware of reloading modules.
112 def checks(self, sconf, TryFuncString):
113 TryFunc = self.SConf.SConfBase.__dict__[TryFuncString]
114 res1 = TryFunc( sconf, "int main() { return 0; }\n", ".c" )
115 res2 = TryFunc( sconf,
116 '#include "no_std_header.h"\nint main() {return 0; }\n',
120 # 1. test initial behaviour (check ok / failed)
121 self._resetSConfState()
122 sconf = self.SConf.SConf(self.scons_env,
123 conf_dir=self.test.workpath('config.tests'),
124 log_file=self.test.workpath('config.log'))
126 res = checks( self, sconf, TryFunc )
127 assert res[0] and not res[1], res
131 # 2.1 test the error caching mechanism (no dependencies have changed)
132 self._resetSConfState()
133 sconf = self.SConf.SConf(self.scons_env,
134 conf_dir=self.test.workpath('config.tests'),
135 log_file=self.test.workpath('config.log'))
137 res = checks( self, sconf, TryFunc )
138 assert res[0] and not res[1], res
141 # we should have exactly one one error cached
142 log = self.test.read( self.test.workpath('config.log') )
143 expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
144 firstOcc = expr.match( log )
145 assert firstOcc is not None, log
146 secondOcc = expr.match( log, firstOcc.end(0) )
147 assert secondOcc is None, log
149 # 2.2 test the error caching mechanism (dependencies have changed)
150 self._resetSConfState()
151 sconf = self.SConf.SConf(self.scons_env,
152 conf_dir=self.test.workpath('config.tests'),
153 log_file=self.test.workpath('config.log'))
154 no_std_header_h = self.test.workpath('config.tests', 'no_std_header.h')
155 test_h = self.test.write( no_std_header_h,
156 "/* we are changing a dependency now */\n" );
158 res = checks( self, sconf, TryFunc )
159 log = self.test.read( self.test.workpath('config.log') )
160 assert res[0] and res[1], res
164 def test_TryBuild(self):
165 """Test SConf.TryBuild
167 # 1 test that we can try a builder that returns a list of nodes
168 self._resetSConfState()
169 sconf = self.SConf.SConf(self.scons_env,
170 conf_dir=self.test.workpath('config.tests'),
171 log_file=self.test.workpath('config.log'))
173 class MyBuilder(SCons.Builder.BuilderBase):
177 def __call__(self, env, target, source):
179 def __init__(self, name):
182 self.waiting_parents = set()
183 self.side_effects = []
185 self.prerequisites = []
186 def disambiguate(self):
188 def has_builder(self):
190 def add_pre_action(self, *actions):
192 def add_post_action(self, *actions):
198 def set_state(self, state):
200 def alter_targets(self):
202 def depends_on(self, nodes):
204 def postprocess(self):
208 def is_up_to_date(self):
212 def push_to_cache(self):
214 def retrieve_from_cache(self):
216 def build(self, **kw):
220 def get_stored_info(self):
222 def do_not_store_info(self):
224 def get_executor(self):
226 def __init__(self, targets):
227 self.targets = targets
228 def get_all_targets(self):
230 return Executor([self])
231 return [MyNode('n1'), MyNode('n2')]
233 self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
234 sconf.TryBuild(self.scons_env.SConfActionBuilder)
238 def test_TryCompile(self):
239 """Test SConf.TryCompile
241 self._baseTryXXX( "TryCompile" ) #self.SConf.SConf.TryCompile )
243 def test_TryLink(self):
244 """Test SConf.TryLink
246 self._baseTryXXX( "TryLink" ) #self.SConf.SConf.TryLink )
248 def test_TryRun(self):
259 res1 = sconf.TryRun( prog, ".c" )
260 res2 = sconf.TryRun( "not a c program\n", ".c" )
263 self._resetSConfState()
264 sconf = self.SConf.SConf(self.scons_env,
265 conf_dir=self.test.workpath('config.tests'),
266 log_file=self.test.workpath('config.log'))
269 assert res[0][0] and res[0][1] == "Hello", res
270 assert not res[1][0] and res[1][1] == "", res
273 log = self.test.read( self.test.workpath('config.log') )
275 # test the caching mechanism
276 self._resetSConfState()
277 sconf = self.SConf.SConf(self.scons_env,
278 conf_dir=self.test.workpath('config.tests'),
279 log_file=self.test.workpath('config.log'))
282 assert res[0][0] and res[0][1] == "Hello", res
283 assert not res[1][0] and res[1][1] == "", res
286 # we should have exactly one error cached
287 log = self.test.read( self.test.workpath('config.log') )
288 expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
289 firstOcc = expr.match( log )
290 assert firstOcc is not None, log
291 secondOcc = expr.match( log, firstOcc.end(0) )
292 assert secondOcc is None, log
295 def test_TryAction(self):
296 """Test SConf.TryAction
298 def actionOK(target, source, env):
299 open(str(target[0]), "w").write( "RUN OK\n" )
301 def actionFAIL(target, source, env):
303 self._resetSConfState()
304 sconf = self.SConf.SConf(self.scons_env,
305 conf_dir=self.test.workpath('config.tests'),
306 log_file=self.test.workpath('config.log'))
308 (ret, output) = sconf.TryAction(action=actionOK)
309 assert ret and output == "RUN OK" + os.linesep, (ret, output)
310 (ret, output) = sconf.TryAction(action=actionFAIL)
311 assert not ret and output == "", (ret, output)
315 def _test_check_compilers(self, comp, func, name):
316 """This is the implementation for CheckCC and CheckCXX tests."""
317 from copy import deepcopy
319 # Check that Check* works
321 assert r, "could not find %s ?" % comp
323 # Check that Check* does fail if comp is not available in env
324 oldcomp = deepcopy(self.scons_env[comp])
325 del self.scons_env[comp]
327 assert not r, "%s worked wo comp ?" % name
329 # Check that Check* does fail if comp is set but empty
330 self.scons_env[comp] = ''
332 assert not r, "%s worked with comp = '' ?" % name
334 # Check that Check* does fail if comp is set to buggy executable
335 self.scons_env[comp] = 'thiscccompilerdoesnotexist'
337 assert not r, "%s worked with comp = thiscompilerdoesnotexist ?" % name
339 # Check that Check* does fail if CFLAGS is buggy
340 self.scons_env[comp] = oldcomp
341 self.scons_env['%sFLAGS' % comp] = '/WX qwertyuiop.c'
343 assert not r, "%s worked with %sFLAGS = qwertyuiop ?" % (name, comp)
345 def test_CheckCC(self):
346 """Test SConf.CheckCC()
348 self._resetSConfState()
349 sconf = self.SConf.SConf(self.scons_env,
350 conf_dir=self.test.workpath('config.tests'),
351 log_file=self.test.workpath('config.log'))
354 self._test_check_compilers('CC', sconf.CheckCC, 'CheckCC')
355 except AssertionError:
356 sys.stderr.write(self.test.read('config.log'))
361 def test_CheckSHCC(self):
362 """Test SConf.CheckSHCC()
364 self._resetSConfState()
365 sconf = self.SConf.SConf(self.scons_env,
366 conf_dir=self.test.workpath('config.tests'),
367 log_file=self.test.workpath('config.log'))
370 self._test_check_compilers('SHCC', sconf.CheckSHCC, 'CheckSHCC')
371 except AssertionError:
372 sys.stderr.write(self.test.read('config.log'))
377 def test_CheckCXX(self):
378 """Test SConf.CheckCXX()
380 self._resetSConfState()
381 sconf = self.SConf.SConf(self.scons_env,
382 conf_dir=self.test.workpath('config.tests'),
383 log_file=self.test.workpath('config.log'))
386 self._test_check_compilers('CXX', sconf.CheckCXX, 'CheckCXX')
387 except AssertionError:
388 sys.stderr.write(self.test.read('config.log'))
393 def test_CheckSHCXX(self):
394 """Test SConf.CheckSHCXX()
396 self._resetSConfState()
397 sconf = self.SConf.SConf(self.scons_env,
398 conf_dir=self.test.workpath('config.tests'),
399 log_file=self.test.workpath('config.log'))
402 self._test_check_compilers('SHCXX', sconf.CheckSHCXX, 'CheckSHCXX')
403 except AssertionError:
404 sys.stderr.write(self.test.read('config.log'))
410 def test_CheckHeader(self):
411 """Test SConf.CheckHeader()
413 self._resetSConfState()
414 sconf = self.SConf.SConf(self.scons_env,
415 conf_dir=self.test.workpath('config.tests'),
416 log_file=self.test.workpath('config.log'))
419 r = sconf.CheckHeader( "stdio.h", include_quotes="<>", language="C" )
420 assert r, "did not find stdio.h"
421 r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C" )
422 assert not r, "unexpectedly found HopefullyNoHeader.noh"
423 r = sconf.CheckHeader( "vector", include_quotes="<>", language="C++" )
424 assert r, "did not find vector"
425 r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C++" )
426 assert not r, "unexpectedly found HopefullyNoHeader.noh"
431 def test_CheckCHeader(self):
432 """Test SConf.CheckCHeader()
434 self._resetSConfState()
435 sconf = self.SConf.SConf(self.scons_env,
436 conf_dir=self.test.workpath('config.tests'),
437 log_file=self.test.workpath('config.log'))
441 r = sconf.CheckCHeader( "stdio.h", include_quotes="<>" )
442 assert r, "did not find stdio.h"
443 r = sconf.CheckCHeader( ["math.h", "stdio.h"], include_quotes="<>" )
444 assert r, "did not find stdio.h, #include math.h first"
445 r = sconf.CheckCHeader( "HopefullyNoCHeader.noh" )
446 assert not r, "unexpectedly found HopefullyNoCHeader.noh"
451 def test_CheckCXXHeader(self):
452 """Test SConf.CheckCXXHeader()
454 self._resetSConfState()
455 sconf = self.SConf.SConf(self.scons_env,
456 conf_dir=self.test.workpath('config.tests'),
457 log_file=self.test.workpath('config.log'))
461 r = sconf.CheckCXXHeader( "vector", include_quotes="<>" )
462 assert r, "did not find vector"
463 r = sconf.CheckCXXHeader( ["stdio.h", "vector"], include_quotes="<>" )
464 assert r, "did not find vector, #include stdio.h first"
465 r = sconf.CheckCXXHeader( "HopefullyNoCXXHeader.noh" )
466 assert not r, "unexpectedly found HopefullyNoCXXHeader.noh"
471 def test_CheckLib(self):
472 """Test SConf.CheckLib()
474 self._resetSConfState()
475 sconf = self.SConf.SConf(self.scons_env,
476 conf_dir=self.test.workpath('config.tests'),
477 log_file=self.test.workpath('config.log'))
481 r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
482 assert r, "did not find %s" % existing_lib
483 r = sconf.CheckLib( "hopefullynolib", "main", autoadd=0 )
484 assert not r, "unexpectedly found hopefullynolib"
486 # CheckLib() with list of libs
487 r = sconf.CheckLib( [existing_lib], "main", autoadd=0 )
488 assert r, "did not find %s" % existing_lib
489 r = sconf.CheckLib( ["hopefullynolib"], "main", autoadd=0 )
490 assert not r, "unexpectedly found hopefullynolib"
491 # This is a check that a null list doesn't find functions
492 # that are in libraries that must be explicitly named.
493 # This works on POSIX systems where you have to -lm to
494 # get the math functions, but it fails on Visual Studio
495 # where you apparently get all those functions for free.
496 # Comment out this check until someone who understands
497 # Visual Studio better can come up with a corresponding
498 # test (if that ever really becomes necessary).
499 #r = sconf.CheckLib( [], "sin", autoadd=0 )
500 #assert not r, "unexpectedly found nonexistent library"
501 r = sconf.CheckLib( [existing_lib,"hopefullynolib"], "main", autoadd=0 )
502 assert r, "did not find %s,%s " % (existing_lib,r)
503 r = sconf.CheckLib( ["hopefullynolib",existing_lib], "main", autoadd=0 )
504 assert r, "did not find %s " % existing_lib
506 # CheckLib() with autoadd
508 return env.get('LIBS', [])
510 env = sconf.env.Clone()
513 r = sconf.CheckLib( existing_lib, "main", autoadd=1 )
514 assert r, "did not find main in %s" % existing_lib
515 expect = libs(env) + [existing_lib]
516 got = libs(sconf.env)
517 assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
519 sconf.env = env.Clone()
520 r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
521 assert r, "did not find main in %s" % existing_lib
523 got = libs(sconf.env)
524 assert got == expect, "before and after LIBS were not the same"
530 def test_CheckLibWithHeader(self):
531 """Test SConf.CheckLibWithHeader()
533 self._resetSConfState()
534 sconf = self.SConf.SConf(self.scons_env,
535 conf_dir=self.test.workpath('config.tests'),
536 log_file=self.test.workpath('config.log'))
539 # CheckLibWithHeader()
540 r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
541 assert r, "did not find %s" % existing_lib
542 r = sconf.CheckLibWithHeader( existing_lib, ["stdio.h", "math.h"], "C", autoadd=0 )
543 assert r, "did not find %s, #include stdio.h first" % existing_lib
544 r = sconf.CheckLibWithHeader( "hopefullynolib", "math.h", "C", autoadd=0 )
545 assert not r, "unexpectedly found hopefullynolib"
547 # CheckLibWithHeader() with lists of libs
548 r = sconf.CheckLibWithHeader( [existing_lib], "math.h", "C", autoadd=0 )
549 assert r, "did not find %s" % existing_lib
550 r = sconf.CheckLibWithHeader( [existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
551 assert r, "did not find %s, #include stdio.h first" % existing_lib
552 # This is a check that a null list doesn't find functions
553 # that are in libraries that must be explicitly named.
554 # This works on POSIX systems where you have to -lm to
555 # get the math functions, but it fails on Visual Studio
556 # where you apparently get all those functions for free.
557 # Comment out this check until someone who understands
558 # Visual Studio better can come up with a corresponding
559 # test (if that ever really becomes necessary).
560 #r = sconf.CheckLibWithHeader( [], "math.h", "C", call="sin(3);", autoadd=0 )
561 #assert not r, "unexpectedly found non-existent library"
562 r = sconf.CheckLibWithHeader( ["hopefullynolib"], "math.h", "C", autoadd=0 )
563 assert not r, "unexpectedly found hopefullynolib"
564 r = sconf.CheckLibWithHeader( ["hopefullynolib",existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
565 assert r, "did not find %s, #include stdio.h first" % existing_lib
566 r = sconf.CheckLibWithHeader( [existing_lib,"hopefullynolib"], ["stdio.h", "math.h"], "C", autoadd=0 )
567 assert r, "did not find %s, #include stdio.h first" % existing_lib
569 # CheckLibWithHeader with autoadd
571 return env.get('LIBS', [])
573 env = sconf.env.Clone()
576 r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
577 assert r, "did not find math.h with %s" % existing_lib
578 expect = libs(env) + [existing_lib]
579 got = libs(sconf.env)
580 assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
582 sconf.env = env.Clone()
583 r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
584 assert r, "did not find math.h with %s" % existing_lib
586 got = libs(sconf.env)
587 assert got == expect, "before and after LIBS were not the same"
594 def test_CheckFunc(self):
595 """Test SConf.CheckFunc()
597 self._resetSConfState()
598 sconf = self.SConf.SConf(self.scons_env,
599 conf_dir=self.test.workpath('config.tests'),
600 log_file=self.test.workpath('config.log'))
604 r = sconf.CheckFunc('strcpy')
605 assert r, "did not find strcpy"
606 r = sconf.CheckFunc('strcpy', '/* header */ char strcpy();')
607 assert r, "did not find strcpy"
608 r = sconf.CheckFunc('hopefullynofunction')
609 assert not r, "unexpectedly found hopefullynofunction"
614 def test_Define(self):
615 """Test SConf.Define()
617 self._resetSConfState()
618 sconf = self.SConf.SConf(self.scons_env,
619 conf_dir=self.test.workpath('config.tests'),
620 log_file=self.test.workpath('config.log'),
621 config_h = self.test.workpath('config.h'))
623 # XXX: we test the generated config.h string. This is not so good,
624 # ideally, we would like to test if the generated file included in
625 # a test program does what we want.
627 # Test defining one symbol wo value
628 sconf.config_h_text = ''
630 assert sconf.config_h_text == '#define YOP\n'
632 # Test defining one symbol with integer value
633 sconf.config_h_text = ''
634 sconf.Define('YOP', 1)
635 assert sconf.config_h_text == '#define YOP 1\n'
637 # Test defining one symbol with string value
638 sconf.config_h_text = ''
639 sconf.Define('YOP', '"YIP"')
640 assert sconf.config_h_text == '#define YOP "YIP"\n'
642 # Test defining one symbol with string value
643 sconf.config_h_text = ''
644 sconf.Define('YOP', "YIP")
645 assert sconf.config_h_text == '#define YOP YIP\n'
650 def test_CheckTypeSize(self):
651 """Test SConf.CheckTypeSize()
653 self._resetSConfState()
654 sconf = self.SConf.SConf(self.scons_env,
655 conf_dir=self.test.workpath('config.tests'),
656 log_file=self.test.workpath('config.log'))
660 # In ANSI C, sizeof(char) == 1.
661 r = sconf.CheckTypeSize('char', expect = 1)
662 assert r == 1, "sizeof(char) != 1 ??"
663 r = sconf.CheckTypeSize('char', expect = 0)
664 assert r == 0, "sizeof(char) == 0 ??"
665 r = sconf.CheckTypeSize('char', expect = 2)
666 assert r == 0, "sizeof(char) == 2 ??"
667 r = sconf.CheckTypeSize('char')
668 assert r == 1, "sizeof(char) != 1 ??"
669 r = sconf.CheckTypeSize('const unsigned char')
670 assert r == 1, "sizeof(const unsigned char) != 1 ??"
673 r = sconf.CheckTypeSize('const unsigned char', language = 'C++')
674 assert r == 1, "sizeof(const unsigned char) != 1 ??"
676 # Checking Non-existing type
677 r = sconf.CheckTypeSize('thistypedefhasnotchancetosexist_scons')
679 "Checking size of thistypedefhasnotchancetosexist_scons succeeded ?"
684 def test_CheckDeclaration(self):
685 """Test SConf.CheckDeclaration()
687 self._resetSConfState()
688 sconf = self.SConf.SConf(self.scons_env,
689 conf_dir=self.test.workpath('config.tests'),
690 log_file=self.test.workpath('config.log'))
692 # In ANSI C, malloc should be available in stdlib
693 r = sconf.CheckDeclaration('malloc', includes = "#include <stdlib.h>")
694 assert r, "malloc not declared ??"
695 # For C++, __cplusplus should be declared
696 r = sconf.CheckDeclaration('__cplusplus', language = 'C++')
697 assert r, "__cplusplus not declared in C++ ??"
698 r = sconf.CheckDeclaration('__cplusplus', language = 'C')
699 assert not r, "__cplusplus declared in C ??"
704 """Test SConf.CheckType()
706 self._resetSConfState()
707 sconf = self.SConf.SConf(self.scons_env,
708 conf_dir=self.test.workpath('config.tests'),
709 log_file=self.test.workpath('config.log'))
712 r = sconf.CheckType('off_t', '#include <sys/types.h>\n')
713 assert r, "did not find off_t"
714 r = sconf.CheckType('hopefullynotypedef_not')
715 assert not r, "unexpectedly found hopefullynotypedef_not"
720 def test_CustomChecks(self):
721 """Test Custom Checks
723 def CheckCustom(test):
724 test.Message( "Checking UserTest ... " )
733 (ret, output) = test.TryRun( prog, ".c" )
735 assert ret and output == "Hello", (ret, output)
739 self._resetSConfState()
740 sconf = self.SConf.SConf(self.scons_env,
741 custom_tests={'CheckCustom': CheckCustom},
742 conf_dir=self.test.workpath('config.tests'),
743 log_file=self.test.workpath('config.log'))
745 ret = sconf.CheckCustom()
751 if __name__ == "__main__":
752 suite = unittest.makeSuite(SConfTestCase, 'test_')
753 res = unittest.TextTestRunner().run(suite)
754 if not res.wasSuccessful():
759 # indent-tabs-mode:nil
761 # vim: set expandtab tabstop=4 shiftwidth=4: