tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_mozjar.py (11763B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 import os
      6 import unittest
      7 from collections import OrderedDict
      8 from io import StringIO
      9 
     10 import mozunit
     11 
     12 import mozpack.path as mozpath
     13 from mozpack.files import FileFinder
     14 from mozpack.mozjar import (
     15    Deflater,
     16    JarLog,
     17    JarReader,
     18    JarReaderError,
     19    JarStruct,
     20    JarWriter,
     21    JarWriterError,
     22 )
     23 from mozpack.test.test_files import MockDest
     24 
     25 test_data_path = mozpath.abspath(mozpath.dirname(__file__))
     26 test_data_path = mozpath.join(test_data_path, "data")
     27 
     28 
     29 class TestJarStruct(unittest.TestCase):
     30    class Foo(JarStruct):
     31        MAGIC = 0x01020304
     32        STRUCT = OrderedDict([
     33            ("foo", "uint32"),
     34            ("bar", "uint16"),
     35            ("qux", "uint16"),
     36            ("length", "uint16"),
     37            ("length2", "uint16"),
     38            ("string", "length"),
     39            ("string2", "length2"),
     40        ])
     41 
     42    def test_jar_struct(self):
     43        foo = TestJarStruct.Foo()
     44        self.assertEqual(foo.signature, TestJarStruct.Foo.MAGIC)
     45        self.assertEqual(foo["foo"], 0)
     46        self.assertEqual(foo["bar"], 0)
     47        self.assertEqual(foo["qux"], 0)
     48        self.assertFalse("length" in foo)
     49        self.assertFalse("length2" in foo)
     50        self.assertEqual(foo["string"], "")
     51        self.assertEqual(foo["string2"], "")
     52 
     53        self.assertEqual(foo.size, 16)
     54 
     55        foo["foo"] = 0x42434445
     56        foo["bar"] = 0xABCD
     57        foo["qux"] = 0xEF01
     58        foo["string"] = "abcde"
     59        foo["string2"] = "Arbitrarily long string"
     60 
     61        serialized = (
     62            b"\x04\x03\x02\x01\x45\x44\x43\x42\xcd\xab\x01\xef"
     63            + b"\x05\x00\x17\x00abcdeArbitrarily long string"
     64        )
     65        self.assertEqual(foo.size, len(serialized))
     66        foo_serialized = foo.serialize()
     67        self.assertEqual(foo_serialized, serialized)
     68 
     69    def do_test_read_jar_struct(self, data):
     70        self.assertRaises(JarReaderError, TestJarStruct.Foo, data)
     71        self.assertRaises(JarReaderError, TestJarStruct.Foo, data[2:])
     72 
     73        foo = TestJarStruct.Foo(data[1:])
     74        self.assertEqual(foo["foo"], 0x45444342)
     75        self.assertEqual(foo["bar"], 0xCDAB)
     76        self.assertEqual(foo["qux"], 0x01EF)
     77        self.assertFalse("length" in foo)
     78        self.assertFalse("length2" in foo)
     79        self.assertEqual(foo["string"], b"012345")
     80        self.assertEqual(foo["string2"], b"67")
     81 
     82    def test_read_jar_struct(self):
     83        data = (
     84            b"\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef"
     85            + b"\x01\x06\x00\x02\x0001234567890"
     86        )
     87        self.do_test_read_jar_struct(data)
     88 
     89    def test_read_jar_struct_memoryview(self):
     90        data = (
     91            b"\x00\x04\x03\x02\x01\x42\x43\x44\x45\xab\xcd\xef"
     92            + b"\x01\x06\x00\x02\x0001234567890"
     93        )
     94        self.do_test_read_jar_struct(memoryview(data))
     95 
     96 
     97 class TestDeflater(unittest.TestCase):
     98    def wrap(self, data):
     99        return data
    100 
    101    def test_deflater_no_compress(self):
    102        deflater = Deflater(False)
    103        deflater.write(self.wrap(b"abc"))
    104        self.assertFalse(deflater.compressed)
    105        self.assertEqual(deflater.uncompressed_size, 3)
    106        self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
    107        self.assertEqual(deflater.compressed_data, b"abc")
    108        self.assertEqual(deflater.crc32, 0x352441C2)
    109 
    110    def test_deflater_compress_no_gain(self):
    111        deflater = Deflater(True)
    112        deflater.write(self.wrap(b"abc"))
    113        self.assertFalse(deflater.compressed)
    114        self.assertEqual(deflater.uncompressed_size, 3)
    115        self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
    116        self.assertEqual(deflater.compressed_data, b"abc")
    117        self.assertEqual(deflater.crc32, 0x352441C2)
    118 
    119    def test_deflater_compress(self):
    120        deflater = Deflater(True)
    121        deflater.write(self.wrap(b"aaaaaaaaaaaaanopqrstuvwxyz"))
    122        self.assertTrue(deflater.compressed)
    123        self.assertEqual(deflater.uncompressed_size, 26)
    124        self.assertNotEqual(deflater.compressed_size, deflater.uncompressed_size)
    125        self.assertEqual(deflater.crc32, 0xD46B97ED)
    126        # The CRC is the same as when not compressed
    127        deflater = Deflater(False)
    128        self.assertFalse(deflater.compressed)
    129        deflater.write(self.wrap(b"aaaaaaaaaaaaanopqrstuvwxyz"))
    130        self.assertEqual(deflater.crc32, 0xD46B97ED)
    131 
    132    def test_deflater_empty(self):
    133        deflater = Deflater(False)
    134        self.assertFalse(deflater.compressed)
    135        self.assertEqual(deflater.uncompressed_size, 0)
    136        self.assertEqual(deflater.compressed_size, deflater.uncompressed_size)
    137        self.assertEqual(deflater.compressed_data, b"")
    138        self.assertEqual(deflater.crc32, 0)
    139 
    140 
    141 class TestDeflaterMemoryView(TestDeflater):
    142    def wrap(self, data):
    143        return memoryview(data)
    144 
    145 
    146 class TestJar(unittest.TestCase):
    147    def test_jar(self):
    148        s = MockDest()
    149        with JarWriter(fileobj=s) as jar:
    150            jar.add("foo", b"foo")
    151            self.assertRaises(JarWriterError, jar.add, "foo", b"bar")
    152            jar.add("bar", b"aaaaaaaaaaaaanopqrstuvwxyz")
    153            jar.add("baz/qux", b"aaaaaaaaaaaaanopqrstuvwxyz", False)
    154            jar.add("baz\\backslash", b"aaaaaaaaaaaaaaa")
    155 
    156        files = [j for j in JarReader(fileobj=s)]
    157 
    158        self.assertEqual(files[0].filename, "foo")
    159        self.assertFalse(files[0].compressed)
    160        self.assertEqual(files[0].read(), b"foo")
    161 
    162        self.assertEqual(files[1].filename, "bar")
    163        self.assertTrue(files[1].compressed)
    164        self.assertEqual(files[1].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    165 
    166        self.assertEqual(files[2].filename, "baz/qux")
    167        self.assertFalse(files[2].compressed)
    168        self.assertEqual(files[2].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    169 
    170        if os.sep == "\\":
    171            self.assertEqual(
    172                files[3].filename,
    173                "baz/backslash",
    174                "backslashes in filenames on Windows should get normalized",
    175            )
    176        else:
    177            self.assertEqual(
    178                files[3].filename,
    179                "baz\\backslash",
    180                "backslashes in filenames on POSIX platform are untouched",
    181            )
    182 
    183        s = MockDest()
    184        with JarWriter(fileobj=s, compress=False) as jar:
    185            jar.add("bar", b"aaaaaaaaaaaaanopqrstuvwxyz")
    186            jar.add("foo", b"foo")
    187            jar.add("baz/qux", b"aaaaaaaaaaaaanopqrstuvwxyz", True)
    188 
    189        jar = JarReader(fileobj=s)
    190        files = [j for j in jar]
    191 
    192        self.assertEqual(files[0].filename, "bar")
    193        self.assertFalse(files[0].compressed)
    194        self.assertEqual(files[0].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    195 
    196        self.assertEqual(files[1].filename, "foo")
    197        self.assertFalse(files[1].compressed)
    198        self.assertEqual(files[1].read(), b"foo")
    199 
    200        self.assertEqual(files[2].filename, "baz/qux")
    201        self.assertTrue(files[2].compressed)
    202        self.assertEqual(files[2].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    203 
    204        self.assertTrue("bar" in jar)
    205        self.assertTrue("foo" in jar)
    206        self.assertFalse("baz" in jar)
    207        self.assertTrue("baz/qux" in jar)
    208        self.assertTrue(jar["bar"], files[1])
    209        self.assertTrue(jar["foo"], files[0])
    210        self.assertTrue(jar["baz/qux"], files[2])
    211 
    212        s.seek(0)
    213        jar = JarReader(fileobj=s)
    214        self.assertTrue("bar" in jar)
    215        self.assertTrue("foo" in jar)
    216        self.assertFalse("baz" in jar)
    217        self.assertTrue("baz/qux" in jar)
    218 
    219        files[0].seek(0)
    220        self.assertEqual(jar["bar"].filename, files[0].filename)
    221        self.assertEqual(jar["bar"].compressed, files[0].compressed)
    222        self.assertEqual(jar["bar"].read(), files[0].read())
    223 
    224        files[1].seek(0)
    225        self.assertEqual(jar["foo"].filename, files[1].filename)
    226        self.assertEqual(jar["foo"].compressed, files[1].compressed)
    227        self.assertEqual(jar["foo"].read(), files[1].read())
    228 
    229        files[2].seek(0)
    230        self.assertEqual(jar["baz/qux"].filename, files[2].filename)
    231        self.assertEqual(jar["baz/qux"].compressed, files[2].compressed)
    232        self.assertEqual(jar["baz/qux"].read(), files[2].read())
    233 
    234    def test_rejar(self):
    235        s = MockDest()
    236        with JarWriter(fileobj=s) as jar:
    237            jar.add("foo", b"foo")
    238            jar.add("bar", b"aaaaaaaaaaaaanopqrstuvwxyz")
    239            jar.add("baz/qux", b"aaaaaaaaaaaaanopqrstuvwxyz", False)
    240 
    241        new = MockDest()
    242        with JarWriter(fileobj=new) as jar:
    243            for j in JarReader(fileobj=s):
    244                jar.add(j.filename, j)
    245 
    246        jar = JarReader(fileobj=new)
    247        files = [j for j in jar]
    248 
    249        self.assertEqual(files[0].filename, "foo")
    250        self.assertFalse(files[0].compressed)
    251        self.assertEqual(files[0].read(), b"foo")
    252 
    253        self.assertEqual(files[1].filename, "bar")
    254        self.assertTrue(files[1].compressed)
    255        self.assertEqual(files[1].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    256 
    257        self.assertEqual(files[2].filename, "baz/qux")
    258        self.assertTrue(files[2].compressed)
    259        self.assertEqual(files[2].read(), b"aaaaaaaaaaaaanopqrstuvwxyz")
    260 
    261    def test_add_from_finder(self):
    262        s = MockDest()
    263        with JarWriter(fileobj=s) as jar:
    264            finder = FileFinder(test_data_path)
    265            for p, f in finder.find("test_data"):
    266                jar.add("test_data", f)
    267 
    268        jar = JarReader(fileobj=s)
    269        files = [j for j in jar]
    270 
    271        self.assertEqual(files[0].filename, "test_data")
    272        self.assertFalse(files[0].compressed)
    273        self.assertEqual(files[0].read(), b"test_data")
    274 
    275 
    276 class TestPreload(unittest.TestCase):
    277    def test_preload(self):
    278        s = MockDest()
    279        with JarWriter(fileobj=s) as jar:
    280            jar.add("foo", b"foo")
    281            jar.add("bar", b"abcdefghijklmnopqrstuvwxyz")
    282            jar.add("baz/qux", b"aaaaaaaaaaaaanopqrstuvwxyz")
    283 
    284        jar = JarReader(fileobj=s)
    285        self.assertEqual(jar.last_preloaded, None)
    286 
    287        with JarWriter(fileobj=s) as jar:
    288            jar.add("foo", b"foo")
    289            jar.add("bar", b"abcdefghijklmnopqrstuvwxyz")
    290            jar.add("baz/qux", b"aaaaaaaaaaaaanopqrstuvwxyz")
    291            jar.preload(["baz/qux", "bar"])
    292 
    293        jar = JarReader(fileobj=s)
    294        self.assertEqual(jar.last_preloaded, "bar")
    295        files = [j for j in jar]
    296 
    297        self.assertEqual(files[0].filename, "baz/qux")
    298        self.assertEqual(files[1].filename, "bar")
    299        self.assertEqual(files[2].filename, "foo")
    300 
    301 
    302 class TestJarLog(unittest.TestCase):
    303    def test_jarlog(self):
    304        s = StringIO(
    305            "\n".join([
    306                "bar/baz.jar first",
    307                "bar/baz.jar second",
    308                "bar/baz.jar third",
    309                "bar/baz.jar second",
    310                "bar/baz.jar second",
    311                "omni.ja stuff",
    312                "bar/baz.jar first",
    313                "omni.ja other/stuff",
    314                "omni.ja stuff",
    315                "bar/baz.jar third",
    316            ])
    317        )
    318        log = JarLog(fileobj=s)
    319        self.assertEqual(
    320            set(log.keys()),
    321            set([
    322                "bar/baz.jar",
    323                "omni.ja",
    324            ]),
    325        )
    326        self.assertEqual(
    327            log["bar/baz.jar"],
    328            [
    329                "first",
    330                "second",
    331                "third",
    332            ],
    333        )
    334        self.assertEqual(
    335            log["omni.ja"],
    336            [
    337                "stuff",
    338                "other/stuff",
    339            ],
    340        )
    341 
    342 
    343 if __name__ == "__main__":
    344    mozunit.main()