# 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/.
import os
import unittest
from collections
import OrderedDict
import mozunit
import six
import mozpack.path
as mozpath
from mozpack.files
import FileFinder
from mozpack.mozjar
import (
Deflater,
JarLog,
JarReader,
JarReaderError,
JarStruct,
JarWriter,
JarWriterError,
)
from mozpack.test.test_files
import MockDest
test_data_path = mozpath.abspath(mozpath.dirname(__file__))
test_data_path = mozpath.join(test_data_path,
"data")
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"], b
"012345")
self.assertEqual(foo[
"string2"], b
"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(b
"abc"))
self.assertFalse(deflater.compressed)
self.assertEqual(deflater.uncompressed_size, 3)
self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
self.assertEqual(deflater.compressed_data, b
"abc")
self.assertEqual(deflater.crc32, 0x352441C2)
def test_deflater_compress_no_gain(self):
deflater = Deflater(
True)
deflater.write(self.wrap(b
"abc"))
self.assertFalse(deflater.compressed)
self.assertEqual(deflater.uncompressed_size, 3)
self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
self.assertEqual(deflater.compressed_data, b
"abc")
self.assertEqual(deflater.crc32, 0x352441C2)
def test_deflater_compress(self):
deflater = Deflater(
True)
deflater.write(self.wrap(b
"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(b
"aaaaaaaaaaaaanopqrstuvwxyz"))
self.assertEqual(deflater.crc32, 0xD46B97ED)
def test_deflater_empty(self):
deflater = Deflater(
False)
self.assertFalse(deflater.compressed)
self.assertEqual(deflater.uncompressed_size, 0)
self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
self.assertEqual(deflater.compressed_data, b
"")
self.assertEqual(deflater.crc32, 0)
class TestDeflaterMemoryView(TestDeflater):
def wrap(self, data):
return memoryview(data)
class TestJar(unittest.TestCase):
def test_jar(self):
s = MockDest()
with JarWriter(fileobj=s)
as jar:
jar.add(
"foo", b
"foo")
self.assertRaises(JarWriterError, jar.add,
"foo", b
"bar")
jar.add(
"bar", b
"aaaaaaaaaaaaanopqrstuvwxyz")
jar.add(
"baz/qux", b
"aaaaaaaaaaaaanopqrstuvwxyz",
False)
jar.add(
"baz\\backslash", b
"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(), b
"foo")
self.assertEqual(files[1].filename,
"bar")
self.assertTrue(files[1].compressed)
self.assertEqual(files[1].read(), b
"aaaaaaaaaaaaanopqrstuvwxyz")
self.assertEqual(files[2].filename,
"baz/qux")
self.assertFalse(files[2].compressed)
self.assertEqual(files[2].read(), b
"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)
as jar:
jar.add(
"bar", b
"aaaaaaaaaaaaanopqrstuvwxyz")
jar.add(
"foo", b
"foo")
jar.add(
"baz/qux", b
"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(), b
"aaaaaaaaaaaaanopqrstuvwxyz")
self.assertEqual(files[1].filename,
"foo")
self.assertFalse(files[1].compressed)
self.assertEqual(files[1].read(), b
"foo")
self.assertEqual(files[2].filename,
"baz/qux")
self.assertTrue(files[2].compressed)
self.assertEqual(files[2].read(), b
"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)
as jar:
jar.add(
"foo", b
"foo")
jar.add(
"bar", b
"aaaaaaaaaaaaanopqrstuvwxyz")
jar.add(
"baz/qux", b
"aaaaaaaaaaaaanopqrstuvwxyz",
False)
new = MockDest()
with JarWriter(fileobj=new)
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(), b
"foo")
self.assertEqual(files[1].filename,
"bar")
self.assertTrue(files[1].compressed)
self.assertEqual(files[1].read(), b
"aaaaaaaaaaaaanopqrstuvwxyz")
self.assertEqual(files[2].filename,
"baz/qux")
self.assertTrue(files[2].compressed)
self.assertEqual(files[2].read(), b
"aaaaaaaaaaaaanopqrstuvwxyz")
def test_add_from_finder(self):
s = MockDest()
with JarWriter(fileobj=s)
as jar:
finder = FileFinder(test_data_path)
for p, f
in finder.find(
"test_data"):
jar.add(
"test_data", f)
jar = JarReader(fileobj=s)
files = [j
for j
in jar]
self.assertEqual(files[0].filename,
"test_data")
self.assertFalse(files[0].compressed)
self.assertEqual(files[0].read(), b
"test_data")
class TestPreload(unittest.TestCase):
def test_preload(self):
s = MockDest()
with JarWriter(fileobj=s)
as jar:
jar.add(
"foo", b
"foo")
jar.add(
"bar", b
"abcdefghijklmnopqrstuvwxyz")
jar.add(
"baz/qux", b
"aaaaaaaaaaaaanopqrstuvwxyz")
jar = JarReader(fileobj=s)
self.assertEqual(jar.last_preloaded,
None)
with JarWriter(fileobj=s)
as jar:
jar.add(
"foo", b
"foo")
jar.add(
"bar", b
"abcdefghijklmnopqrstuvwxyz")
jar.add(
"baz/qux", b
"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):
s = six.moves.cStringIO(
"\n".join(
[
"bar/baz.jar first",
"bar/baz.jar second",
"bar/baz.jar third",
"bar/baz.jar second",
"bar/baz.jar second",
"omni.ja stuff",
"bar/baz.jar first",
"omni.ja other/stuff",
"omni.ja stuff",
"bar/baz.jar third",
]
)
)
log = JarLog(fileobj=s)
self.assertEqual(
set(log.keys()),
set(
[
"bar/baz.jar",
"omni.ja",
]
),
)
self.assertEqual(
log[
"bar/baz.jar"],
[
"first",
"second",
"third",
],
)
self.assertEqual(
log[
"omni.ja"],
[
"stuff",
"other/stuff",
],
)
if __name__ ==
"__main__":
mozunit.main()