1
from __future__ import with_statement
7
from tempfile import mkdtemp
8
from shutil import rmtree
9
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
10
from mozunit import MozTestRunner
12
from UserString import UserString
13
# Create a controlled configuration for use by expandlibs
21
'IMPORT_LIB_SUFFIX': '.lib',
22
'LIBS_DESC_SUFFIX': '.desc',
23
'EXPAND_LIBS_LIST_STYLE': 'list',
26
'AR_EXTRACT': 'ar -x',
32
'IMPORT_LIB_SUFFIX': '',
33
'LIBS_DESC_SUFFIX': '.desc',
34
'EXPAND_LIBS_LIST_STYLE': 'linkerscript',
37
config = sys.modules['expandlibs_config'] = imp.new_module('expandlibs_config')
39
from expandlibs import LibDescriptor, ExpandArgs, relativize
40
from expandlibs_gen import generate
41
from expandlibs_exec import ExpandArgsMore
44
return config.LIB_PREFIX + name + config.LIB_SUFFIX
47
return name + config.OBJ_SUFFIX
50
return config.DLL_PREFIX + name + config.DLL_SUFFIX
53
if not len(config.IMPORT_LIB_SUFFIX): return Dll(name)
54
return config.LIB_PREFIX + name + config.IMPORT_LIB_SUFFIX
56
class TestRelativize(unittest.TestCase):
57
def test_relativize(self):
58
'''Test relativize()'''
59
os_path_exists = os.path.exists
62
os.path.exists = exists
63
self.assertEqual(relativize(os.path.abspath(os.curdir)), os.curdir)
64
self.assertEqual(relativize(os.path.abspath(os.pardir)), os.pardir)
65
self.assertEqual(relativize(os.path.join(os.curdir, 'a')), 'a')
66
self.assertEqual(relativize(os.path.join(os.path.abspath(os.curdir), 'a')), 'a')
67
# relativize is expected to return the absolute path if it is shorter
68
self.assertEqual(relativize(os.sep), os.sep)
69
os.path.exists = os.path.exists
71
class TestLibDescriptor(unittest.TestCase):
72
def test_serialize(self):
73
'''Test LibDescriptor's serialization'''
74
desc = LibDescriptor()
75
desc[LibDescriptor.KEYS[0]] = ['a', 'b']
76
self.assertEqual(str(desc), "%s = a b" % LibDescriptor.KEYS[0])
77
desc['unsupported-key'] = ['a']
78
self.assertEqual(str(desc), "%s = a b" % LibDescriptor.KEYS[0])
79
desc[LibDescriptor.KEYS[1]] = ['c', 'd', 'e']
80
self.assertEqual(str(desc), "%s = a b\n%s = c d e" % (LibDescriptor.KEYS[0], LibDescriptor.KEYS[1]))
81
desc[LibDescriptor.KEYS[0]] = []
82
self.assertEqual(str(desc), "%s = c d e" % (LibDescriptor.KEYS[1]))
85
'''Test LibDescriptor's initialization'''
86
desc_list = ["# Comment",
87
"%s = a b" % LibDescriptor.KEYS[1],
89
"foo = bar", # Should be discarded
90
"%s = c d e" % LibDescriptor.KEYS[0]]
91
desc = LibDescriptor(desc_list)
92
self.assertEqual(desc[LibDescriptor.KEYS[1]], ['a', 'b'])
93
self.assertEqual(desc[LibDescriptor.KEYS[0]], ['c', 'd', 'e'])
94
self.assertEqual(False, 'foo' in desc)
96
def wrap_method(conf, wrapped_method):
97
'''Wrapper used to call a test with a specific configuration'''
100
setattr(config, key, conf[key])
110
class ReplicateTests(type):
111
'''Replicates tests for unix and windows variants'''
112
def __new__(cls, clsName, bases, dict):
113
for name in [key for key in dict if key.startswith('test_')]:
114
dict[name + '_unix'] = wrap_method(config_unix, dict[name])
115
dict[name + '_unix'].__doc__ = dict[name].__doc__ + ' (unix)'
116
dict[name + '_win'] = wrap_method(config_win, dict[name])
117
dict[name + '_win'].__doc__ = dict[name].__doc__ + ' (win)'
119
return type.__new__(cls, clsName, bases, dict)
121
class TestCaseWithTmpDir(unittest.TestCase):
122
__metaclass__ = ReplicateTests
124
self.tmpdir = os.path.abspath(mkdtemp(dir=os.curdir))
129
def touch(self, files):
133
def tmpfile(self, *args):
134
return os.path.join(self.tmpdir, *args)
136
class TestExpandLibsGen(TestCaseWithTmpDir):
137
def test_generate(self):
138
'''Test library descriptor generation'''
139
files = [self.tmpfile(f) for f in
140
[Lib('a'), Obj('b'), Lib('c'), Obj('d'), Obj('e'), Lib('f')]]
141
self.touch(files[:-1])
142
self.touch([files[-1] + config.LIBS_DESC_SUFFIX])
144
desc = generate(files)
145
self.assertEqual(desc['OBJS'], [self.tmpfile(Obj(s)) for s in ['b', 'd', 'e']])
146
self.assertEqual(desc['LIBS'], [self.tmpfile(Lib(s)) for s in ['a', 'c', 'f']])
148
class TestExpandInit(TestCaseWithTmpDir):
150
''' Initializes test environment for library expansion tests'''
151
super(TestExpandInit, self).init()
152
# Create 2 fake libraries, each containing 3 objects, and the second
153
# including the first one and another library.
154
os.mkdir(self.tmpfile('libx'))
155
os.mkdir(self.tmpfile('liby'))
156
self.libx_files = [self.tmpfile('libx', Obj(f)) for f in ['g', 'h', 'i']]
157
self.liby_files = [self.tmpfile('liby', Obj(f)) for f in ['j', 'k', 'l']] + [self.tmpfile('liby', Lib('z'))]
158
self.touch(self.libx_files + self.liby_files)
159
with open(self.tmpfile('libx', Lib('x') + config.LIBS_DESC_SUFFIX), 'w') as f:
160
f.write(str(generate(self.libx_files)))
161
with open(self.tmpfile('liby', Lib('y') + config.LIBS_DESC_SUFFIX), 'w') as f:
162
f.write(str(generate(self.liby_files + [self.tmpfile('libx', Lib('x'))])))
164
# Create various objects and libraries
165
self.arg_files = [self.tmpfile(f) for f in [Lib('a'), Obj('b'), Obj('c'), Lib('d'), Obj('e')]]
166
# We always give library names (LIB_PREFIX/SUFFIX), even for
167
# dynamic/import libraries
168
self.files = self.arg_files + [self.tmpfile(ImportLib('f'))]
169
self.arg_files += [self.tmpfile(Lib('f'))]
170
self.touch(self.files)
172
def assertRelEqual(self, args1, args2):
173
self.assertEqual(args1, [relativize(a) for a in args2])
175
class TestExpandArgs(TestExpandInit):
176
def test_expand(self):
177
'''Test library expansion'''
178
# Expanding arguments means libraries with a descriptor are expanded
179
# with the descriptor content, and import libraries are used when
180
# a library doesn't exist
181
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
182
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
184
# When a library exists at the same time as a descriptor, we just use
186
self.touch([self.tmpfile('libx', Lib('x'))])
187
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
188
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + [self.tmpfile('libx', Lib('x'))])
190
self.touch([self.tmpfile('liby', Lib('y'))])
191
args = ExpandArgs(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))])
192
self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])
194
class TestExpandArgsMore(TestExpandInit):
195
def test_makelist(self):
196
'''Test grouping object files in lists'''
197
# ExpandArgsMore does the same as ExpandArgs
198
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
199
self.assertRelEqual(args, ['foo', '-bar'] + self.files + self.liby_files + self.libx_files)
201
# But also has an extra method replacing object files with a list
203
# self.files has objects at #1, #2, #4
204
self.assertRelEqual(args[:3], ['foo', '-bar'] + self.files[:1])
205
self.assertRelEqual(args[4:], [self.files[3]] + self.files[5:] + [self.tmpfile('liby', Lib('z'))])
207
# Check the list file content
208
objs = [f for f in self.files + self.liby_files + self.libx_files if f.endswith(config.OBJ_SUFFIX)]
209
if config.EXPAND_LIBS_LIST_STYLE == "linkerscript":
210
self.assertNotEqual(args[3][0], '@')
212
content = ["INPUT(%s)" % relativize(f) for f in objs]
213
with open(filename, 'r') as f:
214
self.assertEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
215
elif config.EXPAND_LIBS_LIST_STYLE == "list":
216
self.assertEqual(args[3][0], '@')
217
filename = args[3][1:]
219
with open(filename, 'r') as f:
220
self.assertRelEqual([l.strip() for l in f.readlines() if len(l.strip())], content)
223
# Check that all temporary files are properly removed
224
self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
226
def test_extract(self):
227
'''Test library extraction'''
228
# Divert subprocess.call
229
subprocess_call = subprocess.call
231
def call(args, **kargs):
232
# The command called is always AR_EXTRACT
233
ar_extract = config.AR_EXTRACT.split()
234
self.assertRelEqual(args[:len(ar_extract)], ar_extract)
235
# Remaining argument is always one library
236
self.assertRelEqual([os.path.splitext(arg)[1] for arg in args[len(ar_extract):]], [config.LIB_SUFFIX])
237
# Simulate AR_EXTRACT extracting one object file for the library
238
lib = os.path.splitext(os.path.basename(args[len(ar_extract)]))[0]
239
extracted[lib] = os.path.join(kargs['cwd'], "%s" % Obj(lib))
240
self.touch([extracted[lib]])
241
subprocess.call = call
243
# ExpandArgsMore does the same as ExpandArgs
244
self.touch([self.tmpfile('liby', Lib('y'))])
245
with ExpandArgsMore(['foo', '-bar'] + self.arg_files + [self.tmpfile('liby', Lib('y'))]) as args:
246
self.assertRelEqual(args, ['foo', '-bar'] + self.files + [self.tmpfile('liby', Lib('y'))])
248
# ExpandArgsMore also has an extra method extracting static libraries
252
files = self.files + self.liby_files + self.libx_files
253
if not len(config.AR_EXTRACT):
254
# If we don't have an AR_EXTRACT, extract() expands libraries with a
255
# descriptor when the corresponding library exists (which ExpandArgs
257
self.assertRelEqual(args, ['foo', '-bar'] + files)
259
# With AR_EXTRACT, it uses the descriptors when there are, and actually
260
# extracts the remaining libraries
261
self.assertRelEqual(args, ['foo', '-bar'] + [extracted[os.path.splitext(os.path.basename(f))[0]] if f.endswith(config.LIB_SUFFIX) else f for f in files])
264
# Check that all temporary files are properly removed
265
self.assertEqual(True, all([not os.path.exists(f) for f in tmp]))
267
# Restore subprocess.call
268
subprocess.call = subprocess_call
270
if __name__ == '__main__':
271
unittest.main(testRunner=MozTestRunner())