1
# ***** BEGIN LICENSE BLOCK *****
2
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
# The contents of this file are subject to the Mozilla Public License Version
5
# 1.1 (the "License"); you may not use this file except in compliance with
6
# the License. You may obtain a copy of the License at
7
# http://www.mozilla.org/MPL/
9
# Software distributed under the License is distributed on an "AS IS" basis,
10
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
# for the specific language governing rights and limitations under the
14
# The Original Code is Mozilla build system.
16
# The Initial Developer of the Original Code is
18
# Portions created by the Initial Developer are Copyright (C) 2007
19
# the Initial Developer. All Rights Reserved.
22
# Axel Hecht <axel@pike.org>
24
# Alternatively, the contents of this file may be used under the terms of
25
# either the GNU General Public License Version 2 or later (the "GPL"), or
26
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
# in which case the provisions of the GPL or the LGPL are applicable instead
28
# of those above. If you wish to allow use of your version of this file only
29
# under the terms of either the GPL or the LGPL, and not to allow others to
30
# use your version of this file under the terms of the MPL, indicate your
31
# decision by deleting the provisions above and replace them with the notice
32
# and other provisions required by the GPL or the LGPL. If you do not delete
33
# the provisions above, a recipient may use your version of this file under
34
# the terms of any one of the MPL, the GPL or the LGPL.
36
# ***** END LICENSE BLOCK *****
46
from string import letters
49
Test case infrastructure for MozZipFile.
51
This isn't really a unit test, but a test case generator and runner.
52
For a given set of files, lengths, and number of writes, we create
53
a testcase for every combination of the three. There are some
54
symmetries used to reduce the number of test cases, the first file
55
written is always the first file, the second is either the first or
56
the second, the third is one of the first three. That is, if we
57
had 4 files, but only three writes, the fourth file would never even
60
The content written to the jars is pseudorandom with a fixed seed.
64
__file__ = sys.argv[0]
65
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
67
from MozZipFile import ZipFile
73
'thirddir/with/sub/threeleaf')
74
_lengths = map(lambda n: n * 64, [16, 64, 80])
79
'''Return a length given in the _lengths array to allow manual
80
tuning of which lengths of zip entries to use.
86
''''Tensor product of a list of iterables.
88
This generator returns lists of items, one of each given
89
iterable. It iterates over all possible combinations.
91
for item in iterables[0]:
92
if len(iterables) == 1:
95
for others in prod(*iterables[1:]):
100
'Convert a list of ints to a string.'
101
return reduce(lambda x,y: x+'%d%d'%tuple(y), descs,'')
104
def getContent(length):
105
'Get pseudo random content of given length.'
107
for i in xrange(length):
108
rv[i] = random.choice(letters)
112
def createWriter(sizer, *items):
113
'Helper method to fill in tests, one set of writes, one for each item'
114
locitems = copy.deepcopy(items)
115
for item in locitems:
116
item['length'] = sizer(item.pop('length', 0))
119
if os.path.isfile(self.f):
121
zf = ZipFile(self.f, mode, self.compression)
122
for item in locitems:
123
self._write(zf, **item)
128
def createTester(name, *writes):
129
'''Helper method to fill in tests, calls into a list of write
132
_writes = copy.copy(writes)
138
# unit tests get confused if the method name isn't test...
139
tester.__name__ = name
142
class TestExtensiveStored(unittest.TestCase):
143
'''Unit tests for MozZipFile
145
The testcase are actually populated by code following the class
149
stage = "mozzipfilestage"
150
compression = zipfile.ZIP_STORED
152
def leaf(self, *leafs):
153
return os.path.join(self.stage, *leafs)
155
if os.path.exists(self.stage):
156
shutil.rmtree(self.stage)
158
self.f = self.leaf('test.jar')
166
def _verifyZip(self):
167
zf = zipfile.ZipFile(self.f)
168
badEntry = zf.testzip()
169
self.failIf(badEntry, badEntry)
170
zlist = zf.namelist()
172
vlist = self.ref.keys()
174
self.assertEqual(zlist, vlist)
175
for leaf, content in self.ref.iteritems():
176
zcontent = zf.read(leaf)
177
self.assertEqual(content, zcontent)
179
def _write(self, zf, seed=None, leaf=0, length=0):
185
content = getContent(length)
186
self.ref[leaf] = content
187
zf.writestr(leaf, content)
188
dir = os.path.dirname(self.leaf('stage', leaf))
189
if not os.path.isdir(dir):
191
open(self.leaf('stage', leaf), 'w').write(content)
193
# all leafs in all lengths
194
atomics = list(prod(xrange(len(leafs)), xrange(lengths)))
196
# populate TestExtensiveStore with testcases
197
for w in xrange(writes):
198
# Don't iterate over all files for the the first n passes,
199
# those are redundant as long as w < lengths.
200
# There are symmetries in the trailing end, too, but I don't know
201
# how to reduce those out right now.
202
nonatomics = [list(prod(range(min(i,len(leafs))), xrange(lengths)))
203
for i in xrange(1, w+1)] + [atomics]
204
for descs in prod(*nonatomics):
205
suffix = getid(descs)
206
dicts = [dict(leaf=leaf, length=length) for leaf, length in descs]
207
setattr(TestExtensiveStored, '_write' + suffix,
208
createWriter(givenlength, *dicts))
209
setattr(TestExtensiveStored, 'test' + suffix,
210
createTester('test' + suffix, '_write' + suffix))
212
# now create another round of tests, with two writing passes
213
# first, write all file combinations into the jar, close it,
214
# and then write all atomics again.
215
# This should catch more or less all artifacts generated
216
# by the final ordering step when closing the jar.
217
files = [list(prod([i], xrange(lengths))) for i in xrange(len(leafs))]
218
allfiles = reduce(lambda l,r:l+r,
219
[list(prod(*files[:(i+1)])) for i in xrange(len(leafs))])
221
for first in allfiles:
222
testbasename = 'test%s_' % getid(first)
223
test = [None, '_write' + getid(first), None]
224
for second in atomics:
225
test[0] = testbasename + getid([second])
226
test[2] = '_write' + getid([second])
227
setattr(TestExtensiveStored, test[0], createTester(*test))
229
class TestExtensiveDeflated(TestExtensiveStored):
230
'Test all that has been tested with ZIP_STORED with DEFLATED, too.'
231
compression = zipfile.ZIP_DEFLATED
233
if __name__ == '__main__':