| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this |
| # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| from mozpack.mozjar import ( |
| JarReaderError, |
| JarWriterError, |
| JarStruct, |
| JarReader, |
| JarWriter, |
| Deflater, |
| JarLog, |
| ) |
| from collections import OrderedDict |
| from mozpack.test.test_files import MockDest |
| import unittest |
| import mozunit |
| from cStringIO import StringIO |
| from urllib import pathname2url |
| import mozpack.path as mozpath |
| import os |
| |
| |
| class TestJarStruct(unittest.TestCase): |
| class Foo(JarStruct): |
| MAGIC = 0x01020304 |
| STRUCT = OrderedDict([ |
| ('foo', 'uint32'), |
| ('bar', 'uint16'), |
| ('qux', 'uint16'), |
| ('length', 'uint16'), |
| ('length2', 'uint16'), |
| ('string', 'length'), |
| ('string2', 'length2'), |
| ]) |
| |
| def test_jar_struct(self): |
| foo = TestJarStruct.Foo() |
| self.assertEqual(foo.signature, TestJarStruct.Foo.MAGIC) |
| self.assertEqual(foo['foo'], 0) |
| self.assertEqual(foo['bar'], 0) |
| self.assertEqual(foo['qux'], 0) |
| self.assertFalse('length' in foo) |
| self.assertFalse('length2' in foo) |
| self.assertEqual(foo['string'], '') |
| self.assertEqual(foo['string2'], '') |
| |
| self.assertEqual(foo.size, 16) |
| |
| foo['foo'] = 0x42434445 |
| foo['bar'] = 0xabcd |
| foo['qux'] = 0xef01 |
| foo['string'] = 'abcde' |
| foo['string2'] = 'Arbitrarily long string' |
| |
| serialized = b'\x04\x03\x02\x01\x45\x44\x43\x42\xcd\xab\x01\xef' + \ |
| b'\x05\x00\x17\x00abcdeArbitrarily long string' |
| self.assertEqual(foo.size, len(serialized)) |
| foo_serialized = foo.serialize() |
| self.assertEqual(foo_serialized, serialized) |
| |
| def do_test_read_jar_struct(self, data): |
| self.assertRaises(JarReaderError, TestJarStruct.Foo, data) |
| self.assertRaises(JarReaderError, TestJarStruct.Foo, data[2:]) |
| |
| foo = TestJarStruct.Foo(data[1:]) |
| self.assertEqual(foo['foo'], 0x45444342) |
| self.assertEqual(foo['bar'], 0xcdab) |
| self.assertEqual(foo['qux'], 0x01ef) |
| self.assertFalse('length' in foo) |
| self.assertFalse('length2' in foo) |
| self.assertEqual(foo['string'], '012345') |
| self.assertEqual(foo['string2'], '67') |
| |
| def test_read_jar_struct(self): |
| data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \ |
| b'\x01\x06\x00\x02\x0001234567890' |
| self.do_test_read_jar_struct(data) |
| |
| def test_read_jar_struct_memoryview(self): |
| data = b'\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef' + \ |
| b'\x01\x06\x00\x02\x0001234567890' |
| self.do_test_read_jar_struct(memoryview(data)) |
| |
| |
| class TestDeflater(unittest.TestCase): |
| def wrap(self, data): |
| return data |
| |
| def test_deflater_no_compress(self): |
| deflater = Deflater(False) |
| deflater.write(self.wrap('abc')) |
| self.assertFalse(deflater.compressed) |
| self.assertEqual(deflater.uncompressed_size, 3) |
| self.assertEqual(deflater.compressed_size, deflater.uncompressed_size) |
| self.assertEqual(deflater.compressed_data, 'abc') |
| self.assertEqual(deflater.crc32, 0x352441c2) |
| |
| def test_deflater_compress_no_gain(self): |
| deflater = Deflater(True) |
| deflater.write(self.wrap('abc')) |
| self.assertFalse(deflater.compressed) |
| self.assertEqual(deflater.uncompressed_size, 3) |
| self.assertEqual(deflater.compressed_size, deflater.uncompressed_size) |
| self.assertEqual(deflater.compressed_data, 'abc') |
| self.assertEqual(deflater.crc32, 0x352441c2) |
| |
| def test_deflater_compress(self): |
| deflater = Deflater(True) |
| deflater.write(self.wrap('aaaaaaaaaaaaanopqrstuvwxyz')) |
| self.assertTrue(deflater.compressed) |
| self.assertEqual(deflater.uncompressed_size, 26) |
| self.assertNotEqual(deflater.compressed_size, |
| deflater.uncompressed_size) |
| self.assertEqual(deflater.crc32, 0xd46b97ed) |
| # The CRC is the same as when not compressed |
| deflater = Deflater(False) |
| self.assertFalse(deflater.compressed) |
| deflater.write(self.wrap('aaaaaaaaaaaaanopqrstuvwxyz')) |
| self.assertEqual(deflater.crc32, 0xd46b97ed) |
| |
| |
| class TestDeflaterMemoryView(TestDeflater): |
| def wrap(self, data): |
| return memoryview(data) |
| |
| |
| class TestJar(unittest.TestCase): |
| optimize = False |
| |
| def test_jar(self): |
| s = MockDest() |
| with JarWriter(fileobj=s, optimize=self.optimize) as jar: |
| jar.add('foo', 'foo') |
| self.assertRaises(JarWriterError, jar.add, 'foo', 'bar') |
| jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz') |
| jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False) |
| jar.add('baz\\backslash', 'aaaaaaaaaaaaaaa') |
| |
| files = [j for j in JarReader(fileobj=s)] |
| |
| self.assertEqual(files[0].filename, 'foo') |
| self.assertFalse(files[0].compressed) |
| self.assertEqual(files[0].read(), 'foo') |
| |
| self.assertEqual(files[1].filename, 'bar') |
| self.assertTrue(files[1].compressed) |
| self.assertEqual(files[1].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| self.assertEqual(files[2].filename, 'baz/qux') |
| self.assertFalse(files[2].compressed) |
| self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| if os.sep == '\\': |
| self.assertEqual(files[3].filename, 'baz/backslash', |
| 'backslashes in filenames on Windows should get normalized') |
| else: |
| self.assertEqual(files[3].filename, 'baz\\backslash', |
| 'backslashes in filenames on POSIX platform are untouched') |
| |
| s = MockDest() |
| with JarWriter(fileobj=s, compress=False, |
| optimize=self.optimize) as jar: |
| jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz') |
| jar.add('foo', 'foo') |
| jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', True) |
| |
| jar = JarReader(fileobj=s) |
| files = [j for j in jar] |
| |
| self.assertEqual(files[0].filename, 'bar') |
| self.assertFalse(files[0].compressed) |
| self.assertEqual(files[0].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| self.assertEqual(files[1].filename, 'foo') |
| self.assertFalse(files[1].compressed) |
| self.assertEqual(files[1].read(), 'foo') |
| |
| self.assertEqual(files[2].filename, 'baz/qux') |
| self.assertTrue(files[2].compressed) |
| self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| self.assertTrue('bar' in jar) |
| self.assertTrue('foo' in jar) |
| self.assertFalse('baz' in jar) |
| self.assertTrue('baz/qux' in jar) |
| self.assertTrue(jar['bar'], files[1]) |
| self.assertTrue(jar['foo'], files[0]) |
| self.assertTrue(jar['baz/qux'], files[2]) |
| |
| s.seek(0) |
| jar = JarReader(fileobj=s) |
| self.assertTrue('bar' in jar) |
| self.assertTrue('foo' in jar) |
| self.assertFalse('baz' in jar) |
| self.assertTrue('baz/qux' in jar) |
| |
| files[0].seek(0) |
| self.assertEqual(jar['bar'].filename, files[0].filename) |
| self.assertEqual(jar['bar'].compressed, files[0].compressed) |
| self.assertEqual(jar['bar'].read(), files[0].read()) |
| |
| files[1].seek(0) |
| self.assertEqual(jar['foo'].filename, files[1].filename) |
| self.assertEqual(jar['foo'].compressed, files[1].compressed) |
| self.assertEqual(jar['foo'].read(), files[1].read()) |
| |
| files[2].seek(0) |
| self.assertEqual(jar['baz/qux'].filename, files[2].filename) |
| self.assertEqual(jar['baz/qux'].compressed, files[2].compressed) |
| self.assertEqual(jar['baz/qux'].read(), files[2].read()) |
| |
| def test_rejar(self): |
| s = MockDest() |
| with JarWriter(fileobj=s, optimize=self.optimize) as jar: |
| jar.add('foo', 'foo') |
| jar.add('bar', 'aaaaaaaaaaaaanopqrstuvwxyz') |
| jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz', False) |
| |
| new = MockDest() |
| with JarWriter(fileobj=new, optimize=self.optimize) as jar: |
| for j in JarReader(fileobj=s): |
| jar.add(j.filename, j) |
| |
| jar = JarReader(fileobj=new) |
| files = [j for j in jar] |
| |
| self.assertEqual(files[0].filename, 'foo') |
| self.assertFalse(files[0].compressed) |
| self.assertEqual(files[0].read(), 'foo') |
| |
| self.assertEqual(files[1].filename, 'bar') |
| self.assertTrue(files[1].compressed) |
| self.assertEqual(files[1].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| self.assertEqual(files[2].filename, 'baz/qux') |
| self.assertTrue(files[2].compressed) |
| self.assertEqual(files[2].read(), 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| |
| class TestOptimizeJar(TestJar): |
| optimize = True |
| |
| |
| class TestPreload(unittest.TestCase): |
| def test_preload(self): |
| s = MockDest() |
| with JarWriter(fileobj=s) as jar: |
| jar.add('foo', 'foo') |
| jar.add('bar', 'abcdefghijklmnopqrstuvwxyz') |
| jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz') |
| |
| jar = JarReader(fileobj=s) |
| self.assertEqual(jar.last_preloaded, None) |
| |
| with JarWriter(fileobj=s) as jar: |
| jar.add('foo', 'foo') |
| jar.add('bar', 'abcdefghijklmnopqrstuvwxyz') |
| jar.add('baz/qux', 'aaaaaaaaaaaaanopqrstuvwxyz') |
| jar.preload(['baz/qux', 'bar']) |
| |
| jar = JarReader(fileobj=s) |
| self.assertEqual(jar.last_preloaded, 'bar') |
| files = [j for j in jar] |
| |
| self.assertEqual(files[0].filename, 'baz/qux') |
| self.assertEqual(files[1].filename, 'bar') |
| self.assertEqual(files[2].filename, 'foo') |
| |
| |
| class TestJarLog(unittest.TestCase): |
| def test_jarlog(self): |
| base = 'file:' + pathname2url(os.path.abspath(os.curdir)) |
| s = StringIO('\n'.join([ |
| base + '/bar/baz.jar first', |
| base + '/bar/baz.jar second', |
| base + '/bar/baz.jar third', |
| base + '/bar/baz.jar second', |
| base + '/bar/baz.jar second', |
| 'jar:' + base + '/qux.zip!/omni.ja stuff', |
| base + '/bar/baz.jar first', |
| 'jar:' + base + '/qux.zip!/omni.ja other/stuff', |
| 'jar:' + base + '/qux.zip!/omni.ja stuff', |
| base + '/bar/baz.jar third', |
| 'jar:jar:' + base + '/qux.zip!/baz/baz.jar!/omni.ja nested/stuff', |
| 'jar:jar:jar:' + base + '/qux.zip!/baz/baz.jar!/foo.zip!/omni.ja' + |
| ' deeply/nested/stuff', |
| ])) |
| log = JarLog(fileobj=s) |
| canonicalize = lambda p: \ |
| mozpath.normsep(os.path.normcase(os.path.realpath(p))) |
| baz_jar = canonicalize('bar/baz.jar') |
| qux_zip = canonicalize('qux.zip') |
| self.assertEqual(set(log.keys()), set([ |
| baz_jar, |
| (qux_zip, 'omni.ja'), |
| (qux_zip, 'baz/baz.jar', 'omni.ja'), |
| (qux_zip, 'baz/baz.jar', 'foo.zip', 'omni.ja'), |
| ])) |
| self.assertEqual(log[baz_jar], [ |
| 'first', |
| 'second', |
| 'third', |
| ]) |
| self.assertEqual(log[(qux_zip, 'omni.ja')], [ |
| 'stuff', |
| 'other/stuff', |
| ]) |
| self.assertEqual(log[(qux_zip, 'baz/baz.jar', 'omni.ja')], |
| ['nested/stuff']) |
| self.assertEqual(log[(qux_zip, 'baz/baz.jar', 'foo.zip', |
| 'omni.ja')], ['deeply/nested/stuff']) |
| |
| # The above tests also indirectly check the value returned by |
| # JarLog.canonicalize for various jar: and file: urls, but |
| # JarLog.canonicalize also supports plain paths. |
| self.assertEqual(JarLog.canonicalize(os.path.abspath('bar/baz.jar')), |
| baz_jar) |
| self.assertEqual(JarLog.canonicalize('bar/baz.jar'), baz_jar) |
| |
| |
| if __name__ == '__main__': |
| mozunit.main() |