http://scons.tigris.org/issues/show_bug.cgi?id=2345
[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 SCons.compat
27
28 import io
29 import os
30 import re
31 import sys
32 from types import *
33 import unittest
34
35 import TestCmd
36
37 sys.stdout = io.StringIO()
38
39 if sys.platform == 'win32':
40     existing_lib = "msvcrt"
41 else:
42     existing_lib = "m"
43
44 class SConfTestCase(unittest.TestCase):
45
46     def setUp(self):
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(''))
51
52     def tearDown(self):
53         self.test.cleanup()
54         import SCons.SConsign
55         SCons.SConsign.Reset()
56         os.chdir(self.save_cwd)
57
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)
61         import SCons.SConsign
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':
65                 m = sys.modules[n]
66                 if isinstance(m, ModuleType):
67                     # if this is really a scons module, clear its namespace
68                     del sys.modules[n]
69                     m.__dict__.clear()
70         # we only use SCons.Environment and SCons.SConf for these tests.
71         import SCons.Environment
72         import SCons.SConf
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'])
79
80         # we want to do some autodetection here
81         # this stuff works with
82         #    - cygwin on Windows (using cmd.exe, not bash)
83         #    - posix
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++':
90             global existing_lib
91             existing_lib = 'm'
92
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.
100
101              import builtins
102              import SCons.Platform.win32
103
104              builtins.file = SCons.Platform.win32._builtin_file
105              builtins.open = SCons.Platform.win32._builtin_open
106
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.
111         
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',
117                             '.c' )
118             return (res1,res2)
119
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'))
125         try:
126             res = checks( self, sconf, TryFunc )
127             assert res[0] and not res[1], res
128         finally:
129             sconf.Finish()
130             
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'))
136         try:
137             res = checks( self, sconf, TryFunc )
138             assert res[0] and not res[1], res
139         finally:
140             sconf.Finish()
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
148
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" );
157         try:
158             res = checks( self, sconf, TryFunc )
159             log = self.test.read( self.test.workpath('config.log') )
160             assert res[0] and res[1], res
161         finally:
162             sconf.Finish()
163
164     def test_TryBuild(self):
165         """Test SConf.TryBuild
166         """
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'))
172         import SCons.Builder
173         class MyBuilder(SCons.Builder.BuilderBase):
174             def __init__(self):
175                 self.prefix = ''
176                 self.suffix = ''
177             def __call__(self, env, target, source):
178                 class MyNode:
179                     def __init__(self, name):
180                         self.name = name
181                         self.state = None
182                         self.waiting_parents = set()
183                         self.side_effects = []
184                         self.builder = None
185                         self.prerequisites = []
186                     def disambiguate(self):
187                         return self
188                     def has_builder(self):
189                         return 1
190                     def add_pre_action(self, *actions):
191                         pass
192                     def add_post_action(self, *actions):
193                         pass
194                     def children(self):
195                         return []
196                     def get_state(self):
197                         return self.state
198                     def set_state(self, state):
199                         self.state = state
200                     def alter_targets(self):
201                         return [], None
202                     def depends_on(self, nodes):
203                         return None
204                     def postprocess(self):
205                         pass
206                     def clear(self):
207                         pass
208                     def is_up_to_date(self):
209                         return None
210                     def prepare(self):
211                         pass
212                     def push_to_cache(self):
213                         pass
214                     def retrieve_from_cache(self):
215                         return 0
216                     def build(self, **kw):
217                         return
218                     def built(self):
219                         pass
220                     def get_stored_info(self):
221                         pass
222                     def do_not_store_info(self):
223                         pass
224                     def get_executor(self):
225                         class Executor:
226                             def __init__(self, targets):
227                                 self.targets = targets
228                             def get_all_targets(self):
229                                 return self.targets
230                         return Executor([self])
231                 return [MyNode('n1'), MyNode('n2')]
232         try:
233             self.scons_env.Append(BUILDERS = {'SConfActionBuilder' : MyBuilder()})
234             sconf.TryBuild(self.scons_env.SConfActionBuilder)
235         finally:
236             sconf.Finish()
237
238     def test_TryCompile(self):
239         """Test SConf.TryCompile
240         """
241         self._baseTryXXX( "TryCompile" ) #self.SConf.SConf.TryCompile )
242         
243     def test_TryLink(self):
244         """Test SConf.TryLink
245         """
246         self._baseTryXXX( "TryLink" ) #self.SConf.SConf.TryLink ) 
247
248     def test_TryRun(self):
249         """Test SConf.TryRun
250         """
251         def checks(sconf):
252             prog = """
253 #include <stdio.h>
254 int main() {
255   printf( "Hello" );
256   return 0;
257 }
258 """
259             res1 = sconf.TryRun( prog, ".c" ) 
260             res2 = sconf.TryRun( "not a c program\n", ".c" )
261             return (res1, res2)
262         
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'))
267         try:
268             res = checks(sconf)
269             assert res[0][0] and res[0][1] == "Hello", res
270             assert not res[1][0] and res[1][1] == "", res
271         finally:
272             sconf.Finish()
273         log = self.test.read( self.test.workpath('config.log') )
274
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'))
280         try:
281             res = checks(sconf)
282             assert res[0][0] and res[0][1] == "Hello", res
283             assert not res[1][0] and res[1][1] == "", res
284         finally:
285             sconf.Finish()
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
293
294
295     def test_TryAction(self):
296         """Test SConf.TryAction
297         """
298         def actionOK(target, source, env):
299             open(str(target[0]), "w").write( "RUN OK\n" )
300             return None
301         def actionFAIL(target, source, env):
302             return 1
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'))
307         try:
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)
312         finally:
313             sconf.Finish()
314
315     def _test_check_compilers(self, comp, func, name):
316         """This is the implementation for CheckCC and CheckCXX tests."""
317         from copy import deepcopy
318
319         # Check that Check* works
320         r = func()
321         assert r, "could not find %s ?" % comp
322
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]
326         r = func()
327         assert not r, "%s worked wo comp ?" % name
328
329         # Check that Check* does fail if comp is set but empty
330         self.scons_env[comp] = ''
331         r = func()
332         assert not r, "%s worked with comp = '' ?" % name
333
334         # Check that Check* does fail if comp is set to buggy executable
335         self.scons_env[comp] = 'thiscccompilerdoesnotexist'
336         r = func()
337         assert not r, "%s worked with comp = thiscompilerdoesnotexist ?" % name
338
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'
342         r = func()
343         assert not r, "%s worked with %sFLAGS = qwertyuiop ?" % (name, comp)
344
345     def test_CheckCC(self):
346         """Test SConf.CheckCC()
347         """
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'))
352         try:
353             try:
354                 self._test_check_compilers('CC', sconf.CheckCC, 'CheckCC')
355             except AssertionError:
356                 sys.stderr.write(self.test.read('config.log'))
357                 raise
358         finally:
359             sconf.Finish()
360
361     def test_CheckSHCC(self):
362         """Test SConf.CheckSHCC()
363         """
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'))
368         try:
369             try:
370                 self._test_check_compilers('SHCC', sconf.CheckSHCC, 'CheckSHCC')
371             except AssertionError:
372                 sys.stderr.write(self.test.read('config.log'))
373                 raise
374         finally:
375             sconf.Finish()
376
377     def test_CheckCXX(self):
378         """Test SConf.CheckCXX()
379         """
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'))
384         try:
385             try:
386                 self._test_check_compilers('CXX', sconf.CheckCXX, 'CheckCXX')
387             except AssertionError:
388                 sys.stderr.write(self.test.read('config.log'))
389                 raise
390         finally:
391             sconf.Finish()
392
393     def test_CheckSHCXX(self):
394         """Test SConf.CheckSHCXX()
395         """
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'))
400         try:
401             try:
402                 self._test_check_compilers('SHCXX', sconf.CheckSHCXX, 'CheckSHCXX')
403             except AssertionError:
404                 sys.stderr.write(self.test.read('config.log'))
405                 raise
406         finally:
407             sconf.Finish()
408
409
410     def test_CheckHeader(self):
411         """Test SConf.CheckHeader()
412         """
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'))
417         try:
418             # CheckHeader()
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"
427
428         finally:
429             sconf.Finish()
430
431     def test_CheckCHeader(self):
432         """Test SConf.CheckCHeader()
433         """
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'))
438
439         try:
440             # CheckCHeader()
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"
447
448         finally:
449             sconf.Finish()
450
451     def test_CheckCXXHeader(self):
452         """Test SConf.CheckCXXHeader()
453         """
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'))
458
459         try:
460             # CheckCXXHeader()
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"
467
468         finally:
469             sconf.Finish()
470
471     def test_CheckLib(self):
472         """Test SConf.CheckLib()
473         """
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'))
478
479         try:
480             # CheckLib()
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"
485
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
505
506             # CheckLib() with autoadd
507             def libs(env):
508                 return env.get('LIBS', [])
509
510             env = sconf.env.Clone()
511
512             try:
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)
518
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
522                 expect = libs(env)
523                 got = libs(sconf.env)
524                 assert got == expect, "before and after LIBS were not the same"
525             finally:
526                 sconf.env = env
527         finally:
528             sconf.Finish()
529
530     def test_CheckLibWithHeader(self):
531         """Test SConf.CheckLibWithHeader()
532         """
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'))
537
538         try:
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"
546
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
568
569             # CheckLibWithHeader with autoadd
570             def libs(env):
571                 return env.get('LIBS', [])
572
573             env = sconf.env.Clone()
574
575             try:
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)
581
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
585                 expect = libs(env)
586                 got = libs(sconf.env)
587                 assert got == expect, "before and after LIBS were not the same"
588             finally:
589                 sconf.env = env
590
591         finally:
592             sconf.Finish()
593
594     def test_CheckFunc(self):
595         """Test SConf.CheckFunc()
596         """
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'))
601
602         try:
603             # CheckFunc()
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"
610
611         finally:
612             sconf.Finish()
613
614     def test_Define(self):
615         """Test SConf.Define()
616         """
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'))
622         try:
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.
626
627             # Test defining one symbol wo value
628             sconf.config_h_text = ''
629             sconf.Define('YOP')
630             assert sconf.config_h_text == '#define YOP\n'
631
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'
636
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'
641
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'
646
647         finally:
648             sconf.Finish()
649
650     def test_CheckTypeSize(self):
651         """Test SConf.CheckTypeSize()
652         """
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'))
657         try:
658             # CheckTypeSize()
659
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 ??"
671
672             # Checking C++
673             r = sconf.CheckTypeSize('const unsigned char', language = 'C++')
674             assert r == 1, "sizeof(const unsigned char) != 1 ??"
675
676             # Checking Non-existing type
677             r = sconf.CheckTypeSize('thistypedefhasnotchancetosexist_scons')
678             assert r == 0, \
679                    "Checking size of thistypedefhasnotchancetosexist_scons succeeded ?"
680
681         finally:
682             sconf.Finish()
683
684     def test_CheckDeclaration(self):
685         """Test SConf.CheckDeclaration()
686         """
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'))
691         try:
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 ??"
700         finally:
701             sconf.Finish()
702
703     def test_(self):
704         """Test SConf.CheckType()
705         """
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'))
710         try:
711             # CheckType()
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"
716
717         finally:
718             sconf.Finish()
719
720     def test_CustomChecks(self):
721         """Test Custom Checks
722         """
723         def CheckCustom(test):
724             test.Message( "Checking UserTest ... " )
725             prog = """
726 #include <stdio.h>
727
728 int main() {
729   printf( "Hello" );
730   return 0;
731 }
732 """
733             (ret, output) = test.TryRun( prog, ".c" )
734             test.Result( ret )
735             assert ret and output == "Hello", (ret, output)
736             return ret
737         
738
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'))
744         try:
745             ret = sconf.CheckCustom()
746             assert ret, ret
747         finally:
748             sconf.Finish()
749             
750
751 if __name__ == "__main__":
752     suite = unittest.makeSuite(SConfTestCase, 'test_')
753     res = unittest.TextTestRunner().run(suite)
754     if not res.wasSuccessful():
755         sys.exit(1)
756
757 # Local Variables:
758 # tab-width:4
759 # indent-tabs-mode:nil
760 # End:
761 # vim: set expandtab tabstop=4 shiftwidth=4: