d0da84a95efa7d0c6480b7caf463f42d94ee45f8
[scons.git] / src / engine / SCons / SConfTests.py
1 #
2 # __COPYRIGHT__
3 #
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:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
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.
22 #
23
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
25
26 import os
27 import re
28 import StringIO
29 import sys
30 from types import *
31 import unittest
32
33 import TestCmd
34
35 sys.stdout = StringIO.StringIO()
36
37 if sys.platform == 'win32':
38     existing_lib = "msvcrt"
39 else:
40     existing_lib = "m"
41
42 class SConfTestCase(unittest.TestCase):
43
44     def setUp(self):
45         # we always want to start with a clean directory
46         self.save_cwd = os.getcwd()
47         self.test = TestCmd.TestCmd(workdir = '') 
48         os.chdir(self.test.workpath(''))
49
50     def tearDown(self):
51         self.test.cleanup()
52         import SCons.SConsign
53         SCons.SConsign.Reset()
54         os.chdir(self.save_cwd)
55
56     def _resetSConfState(self):
57         # Ok, this is tricky, and i do not know, if everything is sane.
58         # We try to reset scons' state (including all global variables)
59         import SCons.SConsign
60         SCons.SConsign.write() # simulate normal scons-finish
61         for n in sys.modules.keys():
62             if n.split('.')[0] == 'SCons' and n[:12] != 'SCons.compat':
63                 m = sys.modules[n]
64                 if type(m) is ModuleType:
65                     # if this is really a scons module, clear its namespace
66                     del sys.modules[n]
67                     m.__dict__.clear()
68         # we only use SCons.Environment and SCons.SConf for these tests.
69         import SCons.Environment
70         import SCons.SConf
71         self.Environment = SCons.Environment
72         self.SConf = SCons.SConf
73         # and we need a new environment, cause references may point to
74         # old modules (well, at least this is safe ...)
75         self.scons_env = self.Environment.Environment()
76         self.scons_env.AppendENVPath('PATH', os.environ['PATH'])
77
78         # we want to do some autodetection here
79         # this stuff works with
80         #    - cygwin on Windows (using cmd.exe, not bash)
81         #    - posix
82         #    - msvc on Windows (hopefully)
83         if (not self.scons_env.Detect( self.scons_env.subst('$CXX') ) or
84             not self.scons_env.Detect( self.scons_env.subst('$CC') ) or
85             not self.scons_env.Detect( self.scons_env.subst('$LINK') )):
86             raise Exception, "This test needs an installed compiler!"
87         if self.scons_env['CXX'] == 'g++':
88             global existing_lib
89             existing_lib = 'm'
90
91         if sys.platform in ['cygwin', 'win32']:
92              # On Windows, SCons.Platform.win32 redefines the builtin
93              # file() and open() functions to close the file handles.
94              # This interferes with the unittest.py infrastructure in
95              # some way.  Just sidestep the issue by restoring the
96              # original builtin functions whenever we have to reset
97              # all of our global state.
98
99              import __builtin__
100              import SCons.Platform.win32
101
102              __builtin__.file = SCons.Platform.win32._builtin_file
103              __builtin__.open = SCons.Platform.win32._builtin_open
104
105     def _baseTryXXX(self, TryFunc):
106         # TryCompile and TryLink are much the same, so we can test them
107         # in one method, we pass the function as a string ('TryCompile',
108         # 'TryLink'), so we are aware of reloading modules.
109         
110         def checks(self, sconf, TryFuncString):
111             TryFunc = self.SConf.SConfBase.__dict__[TryFuncString]
112             res1 = TryFunc( sconf, "int main() { return 0; }\n", ".c" )
113             res2 = TryFunc( sconf,
114                             '#include "no_std_header.h"\nint main() {return 0; }\n',
115                             '.c' )
116             return (res1,res2)
117
118         # 1. test initial behaviour (check ok / failed)
119         self._resetSConfState()
120         sconf = self.SConf.SConf(self.scons_env,
121                                  conf_dir=self.test.workpath('config.tests'),
122                                  log_file=self.test.workpath('config.log'))
123         try:
124             res = checks( self, sconf, TryFunc )
125             assert res[0] and not res[1], res
126         finally:
127             sconf.Finish()
128             
129         # 2.1 test the error caching mechanism (no dependencies have changed)
130         self._resetSConfState()
131         sconf = self.SConf.SConf(self.scons_env,
132                                  conf_dir=self.test.workpath('config.tests'),
133                                  log_file=self.test.workpath('config.log'))
134         try:
135             res = checks( self, sconf, TryFunc )
136             assert res[0] and not res[1], res
137         finally:
138             sconf.Finish()
139         # we should have exactly one one error cached 
140         log = self.test.read( self.test.workpath('config.log') )
141         expr = re.compile( ".*failed in a previous run and all", re.DOTALL ) 
142         firstOcc = expr.match( log )
143         assert firstOcc is not None, log
144         secondOcc = expr.match( log, firstOcc.end(0) )
145         assert secondOcc is None, log
146
147         # 2.2 test the error caching mechanism (dependencies have changed)
148         self._resetSConfState()
149         sconf = self.SConf.SConf(self.scons_env,
150                                  conf_dir=self.test.workpath('config.tests'),
151                                  log_file=self.test.workpath('config.log'))
152         no_std_header_h = self.test.workpath('config.tests', 'no_std_header.h')
153         test_h = self.test.write( no_std_header_h,
154                                   "/* we are changing a dependency now */\n" );
155         try:
156             res = checks( self, sconf, TryFunc )
157             log = self.test.read( self.test.workpath('config.log') )
158             assert res[0] and res[1], res
159         finally:
160             sconf.Finish()
161
162     def test_TryBuild(self):
163         """Test SConf.TryBuild
164         """
165         # 1 test that we can try a builder that returns a list of nodes
166         self._resetSConfState()
167         sconf = self.SConf.SConf(self.scons_env,
168                                  conf_dir=self.test.workpath('config.tests'),
169                                  log_file=self.test.workpath('config.log'))
170         import SCons.Builder
171         class MyBuilder(SCons.Builder.BuilderBase):
172             def __init__(self):
173                 self.prefix = ''
174                 self.suffix = ''
175             def __call__(self, env, target, source):
176                 class MyNode:
177                     def __init__(self, name):
178                         self.name = name
179                         self.state = None
180                         self.waiting_parents = set()
181                         self.side_effects = []
182                         self.builder = None
183                         self.prerequisites = []
184                     def disambiguate(self):
185                         return self
186                     def has_builder(self):
187                         return 1
188                     def add_pre_action(self, *actions):
189                         pass
190                     def add_post_action(self, *actions):
191                         pass
192                     def children(self):
193                         return []
194                     def get_state(self):
195                         return self.state
196                     def set_state(self, state):
197                         self.state = state
198                     def alter_targets(self):
199                         return [], None
200                     def depends_on(self, nodes):
201                         return None
202                     def postprocess(self):
203                         pass
204                     def clear(self):
205                         pass
206                     def is_up_to_date(self):
207                         return None
208                     def prepare(self):
209                         pass
210                     def push_to_cache(self):
211                         pass
212                     def retrieve_from_cache(self):
213                         return 0
214                     def build(self, **kw):
215                         return
216                     def built(self):
217                         pass
218                     def get_stored_info(self):
219                         pass
220                     def do_not_store_info(self):
221                         pass
222                     def get_executor(self):
223                         class Executor:
224                             def __init__(self, targets):
225                                 self.targets = targets
226                             def get_all_targets(self):
227                                 return self.targets
228                         return Executor([self])
229                 return [MyNode('n1'), MyNode('n2')]
230         try:
231             self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
232             sconf.TryBuild(self.scons_env.SConfActionBuilder)
233         finally:
234             sconf.Finish()
235
236     def test_TryCompile(self):
237         """Test SConf.TryCompile
238         """
239         self._baseTryXXX( "TryCompile" ) #self.SConf.SConf.TryCompile )
240         
241     def test_TryLink(self):
242         """Test SConf.TryLink
243         """
244         self._baseTryXXX( "TryLink" ) #self.SConf.SConf.TryLink ) 
245
246     def test_TryRun(self):
247         """Test SConf.TryRun
248         """
249         def checks(sconf):
250             prog = """
251 #include <stdio.h>
252 int main() {
253   printf( "Hello" );
254   return 0;
255 }
256 """
257             res1 = sconf.TryRun( prog, ".c" ) 
258             res2 = sconf.TryRun( "not a c program\n", ".c" )
259             return (res1, res2)
260         
261         self._resetSConfState()
262         sconf = self.SConf.SConf(self.scons_env,
263                                  conf_dir=self.test.workpath('config.tests'),
264                                  log_file=self.test.workpath('config.log'))
265         try:
266             res = checks(sconf)
267             assert res[0][0] and res[0][1] == "Hello", res
268             assert not res[1][0] and res[1][1] == "", res
269         finally:
270             sconf.Finish()
271         log = self.test.read( self.test.workpath('config.log') )
272
273         # test the caching mechanism
274         self._resetSConfState()
275         sconf = self.SConf.SConf(self.scons_env,
276                                  conf_dir=self.test.workpath('config.tests'),
277                                  log_file=self.test.workpath('config.log'))
278         try:
279             res = checks(sconf)
280             assert res[0][0] and res[0][1] == "Hello", res
281             assert not res[1][0] and res[1][1] == "", res
282         finally:
283             sconf.Finish()
284         # we should have exactly one error cached 
285         log = self.test.read( self.test.workpath('config.log') )
286         expr = re.compile( ".*failed in a previous run and all", re.DOTALL )
287         firstOcc = expr.match( log )
288         assert firstOcc is not None, log
289         secondOcc = expr.match( log, firstOcc.end(0) )
290         assert secondOcc is None, log
291
292
293     def test_TryAction(self):
294         """Test SConf.TryAction
295         """
296         def actionOK(target, source, env):
297             open(str(target[0]), "w").write( "RUN OK\n" )
298             return None
299         def actionFAIL(target, source, env):
300             return 1
301         self._resetSConfState()
302         sconf = self.SConf.SConf(self.scons_env,
303                                   conf_dir=self.test.workpath('config.tests'),
304                                   log_file=self.test.workpath('config.log'))
305         try:
306             (ret, output) = sconf.TryAction(action=actionOK)
307             assert ret and output == "RUN OK" + os.linesep, (ret, output)
308             (ret, output) = sconf.TryAction(action=actionFAIL)
309             assert not ret and output == "", (ret, output)
310         finally:
311             sconf.Finish()
312
313     def _test_check_compilers(self, comp, func, name):
314         """This is the implementation for CheckCC and CheckCXX tests."""
315         from copy import deepcopy
316
317         # Check that Check* works
318         r = func()
319         assert r, "could not find %s ?" % comp
320
321         # Check that Check* does fail if comp is not available in env
322         oldcomp = deepcopy(self.scons_env[comp])
323         del self.scons_env[comp]
324         r = func()
325         assert not r, "%s worked wo comp ?" % name
326
327         # Check that Check* does fail if comp is set but empty
328         self.scons_env[comp] = ''
329         r = func()
330         assert not r, "%s worked with comp = '' ?" % name
331
332         # Check that Check* does fail if comp is set to buggy executable
333         self.scons_env[comp] = 'thiscccompilerdoesnotexist'
334         r = func()
335         assert not r, "%s worked with comp = thiscompilerdoesnotexist ?" % name
336
337         # Check that Check* does fail if CFLAGS is buggy
338         self.scons_env[comp] = oldcomp
339         self.scons_env['%sFLAGS' % comp] = '/WX qwertyuiop.c'
340         r = func()
341         assert not r, "%s worked with %sFLAGS = qwertyuiop ?" % (name, comp)
342
343     def test_CheckCC(self):
344         """Test SConf.CheckCC()
345         """
346         self._resetSConfState()
347         sconf = self.SConf.SConf(self.scons_env,
348                                  conf_dir=self.test.workpath('config.tests'),
349                                  log_file=self.test.workpath('config.log'))
350         try:
351             try:
352                 self._test_check_compilers('CC', sconf.CheckCC, 'CheckCC')
353             except AssertionError:
354                 sys.stderr.write(self.test.read('config.log'))
355                 raise
356         finally:
357             sconf.Finish()
358
359     def test_CheckSHCC(self):
360         """Test SConf.CheckSHCC()
361         """
362         self._resetSConfState()
363         sconf = self.SConf.SConf(self.scons_env,
364                                  conf_dir=self.test.workpath('config.tests'),
365                                  log_file=self.test.workpath('config.log'))
366         try:
367             try:
368                 self._test_check_compilers('SHCC', sconf.CheckSHCC, 'CheckSHCC')
369             except AssertionError:
370                 sys.stderr.write(self.test.read('config.log'))
371                 raise
372         finally:
373             sconf.Finish()
374
375     def test_CheckCXX(self):
376         """Test SConf.CheckCXX()
377         """
378         self._resetSConfState()
379         sconf = self.SConf.SConf(self.scons_env,
380                                  conf_dir=self.test.workpath('config.tests'),
381                                  log_file=self.test.workpath('config.log'))
382         try:
383             try:
384                 self._test_check_compilers('CXX', sconf.CheckCXX, 'CheckCXX')
385             except AssertionError:
386                 sys.stderr.write(self.test.read('config.log'))
387                 raise
388         finally:
389             sconf.Finish()
390
391     def test_CheckSHCXX(self):
392         """Test SConf.CheckSHCXX()
393         """
394         self._resetSConfState()
395         sconf = self.SConf.SConf(self.scons_env,
396                                  conf_dir=self.test.workpath('config.tests'),
397                                  log_file=self.test.workpath('config.log'))
398         try:
399             try:
400                 self._test_check_compilers('SHCXX', sconf.CheckSHCXX, 'CheckSHCXX')
401             except AssertionError:
402                 sys.stderr.write(self.test.read('config.log'))
403                 raise
404         finally:
405             sconf.Finish()
406
407
408     def test_CheckHeader(self):
409         """Test SConf.CheckHeader()
410         """
411         self._resetSConfState()
412         sconf = self.SConf.SConf(self.scons_env,
413                                  conf_dir=self.test.workpath('config.tests'),
414                                  log_file=self.test.workpath('config.log'))
415         try:
416             # CheckHeader()
417             r = sconf.CheckHeader( "stdio.h", include_quotes="<>", language="C" )
418             assert r, "did not find stdio.h"
419             r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C" )
420             assert not r, "unexpectedly found HopefullyNoHeader.noh"
421             r = sconf.CheckHeader( "vector", include_quotes="<>", language="C++" )
422             assert r, "did not find vector"
423             r = sconf.CheckHeader( "HopefullyNoHeader.noh", language="C++" )
424             assert not r, "unexpectedly found HopefullyNoHeader.noh"
425
426         finally:
427             sconf.Finish()
428
429     def test_CheckCHeader(self):
430         """Test SConf.CheckCHeader()
431         """
432         self._resetSConfState()
433         sconf = self.SConf.SConf(self.scons_env,
434                                  conf_dir=self.test.workpath('config.tests'),
435                                  log_file=self.test.workpath('config.log'))
436
437         try:
438             # CheckCHeader()
439             r = sconf.CheckCHeader( "stdio.h", include_quotes="<>" )
440             assert r, "did not find stdio.h"
441             r = sconf.CheckCHeader( ["math.h", "stdio.h"], include_quotes="<>" )
442             assert r, "did not find stdio.h, #include math.h first"
443             r = sconf.CheckCHeader( "HopefullyNoCHeader.noh" )
444             assert not r, "unexpectedly found HopefullyNoCHeader.noh"
445
446         finally:
447             sconf.Finish()
448
449     def test_CheckCXXHeader(self):
450         """Test SConf.CheckCXXHeader()
451         """
452         self._resetSConfState()
453         sconf = self.SConf.SConf(self.scons_env,
454                                  conf_dir=self.test.workpath('config.tests'),
455                                  log_file=self.test.workpath('config.log'))
456
457         try:
458             # CheckCXXHeader()
459             r = sconf.CheckCXXHeader( "vector", include_quotes="<>" )
460             assert r, "did not find vector"
461             r = sconf.CheckCXXHeader( ["stdio.h", "vector"], include_quotes="<>" )
462             assert r, "did not find vector, #include stdio.h first"
463             r = sconf.CheckCXXHeader( "HopefullyNoCXXHeader.noh" )
464             assert not r, "unexpectedly found HopefullyNoCXXHeader.noh"
465
466         finally:
467             sconf.Finish()
468
469     def test_CheckLib(self):
470         """Test SConf.CheckLib()
471         """
472         self._resetSConfState()
473         sconf = self.SConf.SConf(self.scons_env,
474                                  conf_dir=self.test.workpath('config.tests'),
475                                  log_file=self.test.workpath('config.log'))
476
477         try:
478             # CheckLib()
479             r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
480             assert r, "did not find %s" % existing_lib
481             r = sconf.CheckLib( "hopefullynolib", "main", autoadd=0 )
482             assert not r, "unexpectedly found hopefullynolib"
483
484             # CheckLib() with list of libs
485             r = sconf.CheckLib( [existing_lib], "main", autoadd=0 )
486             assert r, "did not find %s" % existing_lib
487             r = sconf.CheckLib( ["hopefullynolib"], "main", autoadd=0 )
488             assert not r, "unexpectedly found hopefullynolib"
489             # This is a check that a null list doesn't find functions
490             # that are in libraries that must be explicitly named.
491             # This works on POSIX systems where you have to -lm to
492             # get the math functions, but it fails on Visual Studio
493             # where you apparently get all those functions for free.
494             # Comment out this check until someone who understands
495             # Visual Studio better can come up with a corresponding
496             # test (if that ever really becomes necessary).
497             #r = sconf.CheckLib( [], "sin", autoadd=0 )
498             #assert not r, "unexpectedly found nonexistent library"
499             r = sconf.CheckLib( [existing_lib,"hopefullynolib"], "main", autoadd=0 )
500             assert r, "did not find %s,%s " % (existing_lib,r)
501             r = sconf.CheckLib( ["hopefullynolib",existing_lib], "main", autoadd=0 )
502             assert r, "did not find %s " % existing_lib
503
504             # CheckLib() with autoadd
505             def libs(env):
506                 return env.get('LIBS', [])
507
508             env = sconf.env.Clone()
509
510             try:
511                 r = sconf.CheckLib( existing_lib, "main", autoadd=1 )
512                 assert r, "did not find main in %s" % existing_lib
513                 expect = libs(env) + [existing_lib]
514                 got = libs(sconf.env)
515                 assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
516
517                 sconf.env = env.Clone()
518                 r = sconf.CheckLib( existing_lib, "main", autoadd=0 )
519                 assert r, "did not find main in %s" % existing_lib
520                 expect = libs(env)
521                 got = libs(sconf.env)
522                 assert got == expect, "before and after LIBS were not the same"
523             finally:
524                 sconf.env = env
525         finally:
526             sconf.Finish()
527
528     def test_CheckLibWithHeader(self):
529         """Test SConf.CheckLibWithHeader()
530         """
531         self._resetSConfState()
532         sconf = self.SConf.SConf(self.scons_env,
533                                  conf_dir=self.test.workpath('config.tests'),
534                                  log_file=self.test.workpath('config.log'))
535
536         try:
537             # CheckLibWithHeader()
538             r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
539             assert r, "did not find %s" % existing_lib
540             r = sconf.CheckLibWithHeader( existing_lib, ["stdio.h", "math.h"], "C", autoadd=0 )
541             assert r, "did not find %s, #include stdio.h first" % existing_lib
542             r = sconf.CheckLibWithHeader( "hopefullynolib", "math.h", "C", autoadd=0 )
543             assert not r, "unexpectedly found hopefullynolib"
544
545             # CheckLibWithHeader() with lists of libs
546             r = sconf.CheckLibWithHeader( [existing_lib], "math.h", "C", autoadd=0 )
547             assert r, "did not find %s" % existing_lib
548             r = sconf.CheckLibWithHeader( [existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
549             assert r, "did not find %s, #include stdio.h first" % existing_lib
550             # This is a check that a null list doesn't find functions
551             # that are in libraries that must be explicitly named.
552             # This works on POSIX systems where you have to -lm to
553             # get the math functions, but it fails on Visual Studio
554             # where you apparently get all those functions for free.
555             # Comment out this check until someone who understands
556             # Visual Studio better can come up with a corresponding
557             # test (if that ever really becomes necessary).
558             #r = sconf.CheckLibWithHeader( [], "math.h", "C", call="sin(3);", autoadd=0 )
559             #assert not r, "unexpectedly found non-existent library"
560             r = sconf.CheckLibWithHeader( ["hopefullynolib"], "math.h", "C", autoadd=0 )
561             assert not r, "unexpectedly found hopefullynolib"
562             r = sconf.CheckLibWithHeader( ["hopefullynolib",existing_lib], ["stdio.h", "math.h"], "C", autoadd=0 )
563             assert r, "did not find %s, #include stdio.h first" % existing_lib
564             r = sconf.CheckLibWithHeader( [existing_lib,"hopefullynolib"], ["stdio.h", "math.h"], "C", autoadd=0 )
565             assert r, "did not find %s, #include stdio.h first" % existing_lib
566
567             # CheckLibWithHeader with autoadd
568             def libs(env):
569                 return env.get('LIBS', [])
570
571             env = sconf.env.Clone()
572
573             try:
574                 r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=1 )
575                 assert r, "did not find math.h with %s" % existing_lib
576                 expect = libs(env) + [existing_lib]
577                 got = libs(sconf.env)
578                 assert got == expect, "LIBS: expected %s, got %s" % (expect, got)
579
580                 sconf.env = env.Clone()
581                 r = sconf.CheckLibWithHeader( existing_lib, "math.h", "C", autoadd=0 )
582                 assert r, "did not find math.h with %s" % existing_lib
583                 expect = libs(env)
584                 got = libs(sconf.env)
585                 assert got == expect, "before and after LIBS were not the same"
586             finally:
587                 sconf.env = env
588
589         finally:
590             sconf.Finish()
591
592     def test_CheckFunc(self):
593         """Test SConf.CheckFunc()
594         """
595         self._resetSConfState()
596         sconf = self.SConf.SConf(self.scons_env,
597                                  conf_dir=self.test.workpath('config.tests'),
598                                  log_file=self.test.workpath('config.log'))
599
600         try:
601             # CheckFunc()
602             r = sconf.CheckFunc('strcpy')
603             assert r, "did not find strcpy"
604             r = sconf.CheckFunc('strcpy', '/* header */ char strcpy();')
605             assert r, "did not find strcpy"
606             r = sconf.CheckFunc('hopefullynofunction')
607             assert not r, "unexpectedly found hopefullynofunction"
608
609         finally:
610             sconf.Finish()
611
612     def test_Define(self):
613         """Test SConf.Define()
614         """
615         self._resetSConfState()
616         sconf = self.SConf.SConf(self.scons_env,
617                                  conf_dir=self.test.workpath('config.tests'),
618                                  log_file=self.test.workpath('config.log'),
619                                  config_h = self.test.workpath('config.h'))
620         try:
621             # XXX: we test the generated config.h string. This is not so good,
622             # ideally, we would like to test if the generated file included in
623             # a test program does what we want.
624
625             # Test defining one symbol wo value
626             sconf.config_h_text = ''
627             sconf.Define('YOP')
628             assert sconf.config_h_text == '#define YOP\n'
629
630             # Test defining one symbol with integer value
631             sconf.config_h_text = ''
632             sconf.Define('YOP', 1)
633             assert sconf.config_h_text == '#define YOP 1\n'
634
635             # Test defining one symbol with string value
636             sconf.config_h_text = ''
637             sconf.Define('YOP', '"YIP"')
638             assert sconf.config_h_text == '#define YOP "YIP"\n'
639
640             # Test defining one symbol with string value
641             sconf.config_h_text = ''
642             sconf.Define('YOP', "YIP")
643             assert sconf.config_h_text == '#define YOP YIP\n'
644
645         finally:
646             sconf.Finish()
647
648     def test_CheckTypeSize(self):
649         """Test SConf.CheckTypeSize()
650         """
651         self._resetSConfState()
652         sconf = self.SConf.SConf(self.scons_env,
653                                  conf_dir=self.test.workpath('config.tests'),
654                                  log_file=self.test.workpath('config.log'))
655         try:
656             # CheckTypeSize()
657
658             # In ANSI C, sizeof(char) == 1.
659             r = sconf.CheckTypeSize('char', expect = 1)
660             assert r == 1, "sizeof(char) != 1 ??"
661             r = sconf.CheckTypeSize('char', expect = 0)
662             assert r == 0, "sizeof(char) == 0 ??"
663             r = sconf.CheckTypeSize('char', expect = 2)
664             assert r == 0, "sizeof(char) == 2 ??"
665             r = sconf.CheckTypeSize('char')
666             assert r == 1, "sizeof(char) != 1 ??"
667             r = sconf.CheckTypeSize('const unsigned char')
668             assert r == 1, "sizeof(const unsigned char) != 1 ??"
669
670             # Checking C++
671             r = sconf.CheckTypeSize('const unsigned char', language = 'C++')
672             assert r == 1, "sizeof(const unsigned char) != 1 ??"
673
674             # Checking Non-existing type
675             r = sconf.CheckTypeSize('thistypedefhasnotchancetosexist_scons')
676             assert r == 0, \
677                    "Checking size of thistypedefhasnotchancetosexist_scons succeeded ?"
678
679         finally:
680             sconf.Finish()
681
682     def test_CheckDeclaration(self):
683         """Test SConf.CheckDeclaration()
684         """
685         self._resetSConfState()
686         sconf = self.SConf.SConf(self.scons_env,
687                                  conf_dir=self.test.workpath('config.tests'),
688                                  log_file=self.test.workpath('config.log'))
689         try:
690             # In ANSI C, malloc should be available in stdlib
691             r = sconf.CheckDeclaration('malloc', includes = "#include <stdlib.h>")
692             assert r, "malloc not declared ??"
693             # For C++, __cplusplus should be declared 
694             r = sconf.CheckDeclaration('__cplusplus', language = 'C++')
695             assert r, "__cplusplus not declared in C++ ??"
696             r = sconf.CheckDeclaration('__cplusplus', language = 'C')
697             assert not r, "__cplusplus declared  in C ??"
698         finally:
699             sconf.Finish()
700
701     def test_(self):
702         """Test SConf.CheckType()
703         """
704         self._resetSConfState()
705         sconf = self.SConf.SConf(self.scons_env,
706                                  conf_dir=self.test.workpath('config.tests'),
707                                  log_file=self.test.workpath('config.log'))
708         try:
709             # CheckType()
710             r = sconf.CheckType('off_t', '#include <sys/types.h>\n')
711             assert r, "did not find off_t"
712             r = sconf.CheckType('hopefullynotypedef_not')
713             assert not r, "unexpectedly found hopefullynotypedef_not"
714
715         finally:
716             sconf.Finish()
717
718     def test_CustomChecks(self):
719         """Test Custom Checks
720         """
721         def CheckCustom(test):
722             test.Message( "Checking UserTest ... " )
723             prog = """
724 #include <stdio.h>
725
726 int main() {
727   printf( "Hello" );
728   return 0;
729 }
730 """
731             (ret, output) = test.TryRun( prog, ".c" )
732             test.Result( ret )
733             assert ret and output == "Hello", (ret, output)
734             return ret
735         
736
737         self._resetSConfState()
738         sconf = self.SConf.SConf(self.scons_env,
739                                  custom_tests={'CheckCustom': CheckCustom},
740                                  conf_dir=self.test.workpath('config.tests'),
741                                  log_file=self.test.workpath('config.log'))
742         try:
743             ret = sconf.CheckCustom()
744             assert ret, ret
745         finally:
746             sconf.Finish()
747             
748
749 if __name__ == "__main__":
750     suite = unittest.makeSuite(SConfTestCase, 'test_')
751     res = unittest.TextTestRunner().run(suite)
752     if not res.wasSuccessful():
753         sys.exit(1)
754
755 # Local Variables:
756 # tab-width:4
757 # indent-tabs-mode:nil
758 # End:
759 # vim: set expandtab tabstop=4 shiftwidth=4: