2 # Copyright (c) 2001 Steven Knight
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__"
29 from SCons.Environment import *
36 """A dummy Builder class for testing purposes. "Building"
37 a target is simply setting a value in the dictionary.
39 def __init__(self, name = None):
42 def execute(self, target = None, **kw):
50 """A dummy Scanner class for testing purposes. "Scanning"
51 a target is simply setting a value in the dictionary.
53 def __init__(self, name, skeys=[]):
57 def scan(self, filename):
58 scanned_it[filename] = 1
60 def __cmp__(self, other):
61 return cmp(self.__dict__, other.__dict__)
65 class EnvironmentTestCase(unittest.TestCase):
67 def test_Builders(self):
68 """Test Builder execution through different environments
70 One environment is initialized with a single
71 Builder object, one with a list of a single Builder
72 object, and one with a list of two Builder objects.
76 b1 = Builder(name = 'builder1')
77 b2 = Builder(name = 'builder2')
80 env1 = Environment(BUILDERS = b1)
81 env1.builder1.execute(target = 'out1')
82 assert built_it['out1']
85 env2 = Environment(BUILDERS = [b1])
86 env1.builder1.execute(target = 'out1')
87 assert built_it['out1']
91 env3.Update(BUILDERS = [b1, b2])
92 env3.builder1.execute(target = 'out1')
93 env3.builder2.execute(target = 'out2')
94 env3.builder1.execute(target = 'out3')
95 assert built_it['out1']
96 assert built_it['out2']
97 assert built_it['out3']
100 assert env4.builder1.env is env4
101 assert env4.builder2.env is env4
103 def test_Scanners(self):
104 """Test Scanner execution through different environments
106 One environment is initialized with a single
107 Scanner object, one with a list of a single Scanner
108 object, and one with a list of two Scanner objects.
112 s1 = Scanner(name = 'scanner1', skeys = [".c", ".cc"])
113 s2 = Scanner(name = 'scanner2', skeys = [".m4"])
116 env1 = Environment(SCANNERS = s1)
117 env1.scanner1.scan(filename = 'out1')
118 assert scanned_it['out1']
121 env2 = Environment(SCANNERS = [s1])
122 env1.scanner1.scan(filename = 'out1')
123 assert scanned_it['out1']
127 env3.Update(SCANNERS = [s1, s2])
128 env3.scanner1.scan(filename = 'out1')
129 env3.scanner2.scan(filename = 'out2')
130 env3.scanner1.scan(filename = 'out3')
131 assert scanned_it['out1']
132 assert scanned_it['out2']
133 assert scanned_it['out3']
135 s = env3.get_scanner(".c")
137 s = env3.get_scanner(skey=".m4")
139 s = env3.get_scanner(".cxx")
143 """Test construction Environment copying
145 Update the copy independently afterwards and check that
146 the original remains intact (that is, no dangling
147 references point to objects in the copied environment).
148 Copy the original with some construction variable
149 updates and check that the original remains intact
150 and the copy has the updated values.
152 env1 = Environment(XXX = 'x', YYY = 'y')
154 env1copy = env1.Copy()
155 env2.Update(YYY = 'yyy')
157 assert env1 == env1copy
159 env3 = env1.Copy(XXX = 'x3', ZZZ = 'z3')
160 assert env3.Dictionary('XXX') == 'x3'
161 assert env3.Dictionary('YYY') == 'y'
162 assert env3.Dictionary('ZZZ') == 'z3'
163 assert env1 == env1copy
165 # Ensure that lists and dictionaries are
166 # deep copied, but not instances.
169 env1 = Environment(XXX=TestA(), YYY = [ 1, 2, 3 ],
172 env2.Dictionary('YYY').append(4)
173 env2.Dictionary('ZZZ')[5] = 6
174 assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
175 assert 4 in env2.Dictionary('YYY')
176 assert not 4 in env1.Dictionary('YYY')
177 assert env2.Dictionary('ZZZ').has_key(5)
178 assert not env1.Dictionary('ZZZ').has_key(5)
180 def test_Dictionary(self):
181 """Test retrieval of known construction variables
183 Fetch them from the Dictionary and check for well-known
184 defaults that get inserted.
186 env = Environment(XXX = 'x', YYY = 'y', ZZZ = 'z')
187 assert env.Dictionary('XXX') == 'x'
188 assert env.Dictionary('YYY') == 'y'
189 assert env.Dictionary('XXX', 'ZZZ') == ['x', 'z']
190 xxx, zzz = env.Dictionary('XXX', 'ZZZ')
193 assert env.Dictionary().has_key('BUILDERS')
194 assert env.Dictionary().has_key('CC')
195 assert env.Dictionary().has_key('CCFLAGS')
196 assert env.Dictionary().has_key('ENV')
199 """Test setting the external ENV in Environments
202 assert env.Dictionary().has_key('ENV')
204 env = Environment(ENV = { 'PATH' : '/foo:/bar' })
205 assert env.Dictionary('ENV')['PATH'] == '/foo:/bar'
207 def test_Environment(self):
208 """Test construction Environments creation
210 Create two with identical arguments and check that
211 they compare the same.
213 env1 = Environment(XXX = 'x', YYY = 'y')
214 env2 = Environment(XXX = 'x', YYY = 'y')
217 def test_Install(self):
218 """Test Install method"""
220 tgt = env.Install('export', [ 'build/foo1', 'build/foo2' ])
221 paths = map(str, tgt)
223 assert paths == [ 'export/foo1', 'export/foo2' ], paths
225 assert tnode.builder == InstallBuilder
227 def test_InstallAs(self):
230 def test_Update(self):
231 """Test updating an Environment with new construction variables
233 After creation of the Environment, of course.
235 env1 = Environment(AAA = 'a', BBB = 'b')
236 env1.Update(BBB = 'bbb', CCC = 'ccc')
237 env2 = Environment(AAA = 'a', BBB = 'bbb', CCC = 'c')
240 def test_Depends(self):
241 """Test the explicit Depends method."""
243 t = env.Depends(target='EnvironmentTest.py', dependency='Environment.py')
244 assert t.__class__.__name__ == 'File'
245 assert t.path == 'EnvironmentTest.py'
246 assert len(t.depends) == 1
248 assert d.__class__.__name__ == 'File'
249 assert d.path == 'Environment.py'
251 def test_Command(self):
252 """Test the Command() method."""
254 t = env.Command(target='foo.out', source=['foo1.in', 'foo2.in'],
255 action='buildfoo $target $source')
257 assert t.builder.action.__class__.__name__ == 'CommandAction'
258 assert t.builder.action.command == 'buildfoo $target $source'
259 assert 'foo1.in' in map(lambda x: x.path, t.sources)
260 assert 'foo2.in' in map(lambda x: x.path, t.sources)
262 def testFunc(env, target, source):
263 assert target == 'foo.out'
264 assert 'foo1.in' in source and 'foo2.in' in source, source
266 t = env.Command(target='foo.out', source=['foo1.in','foo2.in'],
269 assert t.builder.action.__class__.__name__ == 'FunctionAction'
271 assert 'foo1.in' in map(lambda x: x.path, t.sources)
272 assert 'foo2.in' in map(lambda x: x.path, t.sources)
274 def test_subst(self):
275 """Test substituting construction variables within strings
277 Check various combinations, including recursive expansion
278 of variables into other variables.
280 env = Environment(AAA = 'a', BBB = 'b')
281 str = env.subst("$AAA ${AAA}A $BBBB $BBB")
282 assert str == "a aA b", str
283 env = Environment(AAA = '$BBB', BBB = 'b', BBBA = 'foo')
284 str = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
285 assert str == "b foo b", str
286 env = Environment(AAA = '$BBB', BBB = '$CCC', CCC = 'c')
287 str = env.subst("$AAA ${AAA}A ${AAA}B $BBB")
288 assert str == "c c", str
292 if __name__ == "__main__":
293 suite = unittest.makeSuite(EnvironmentTestCase, 'test_')
294 if not unittest.TextTestRunner().run(suite).wasSuccessful():