tor-browser

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

test_archive.py (6046B)


      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 hashlib
      6 import os
      7 import shutil
      8 import stat
      9 import tarfile
     10 import tempfile
     11 import unittest
     12 
     13 import pytest
     14 from mozunit import main
     15 
     16 from mozpack.archive import (
     17    DEFAULT_MTIME,
     18    create_tar_bz2_from_files,
     19    create_tar_from_files,
     20    create_tar_gz_from_files,
     21 )
     22 from mozpack.files import GeneratedFile
     23 
     24 MODE_STANDARD = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
     25 
     26 
     27 def file_hash(path):
     28    h = hashlib.sha1()
     29    with open(path, "rb") as fh:
     30        while True:
     31            data = fh.read(8192)
     32            if not data:
     33                break
     34            h.update(data)
     35 
     36    return h.hexdigest()
     37 
     38 
     39 class TestArchive(unittest.TestCase):
     40    def _create_files(self, root):
     41        files = {}
     42        for i in range(10):
     43            p = os.path.join(root, "file%02d" % i)
     44            with open(p, "wb") as fh:
     45                fh.write(b"file%02d" % i)
     46            # Need to set permissions or umask may influence testing.
     47            os.chmod(p, MODE_STANDARD)
     48            files["file%02d" % i] = p
     49 
     50        for i in range(10):
     51            files["file%02d" % (i + 10)] = GeneratedFile(b"file%02d" % (i + 10))
     52 
     53        return files
     54 
     55    def _verify_basic_tarfile(self, tf):
     56        self.assertEqual(len(tf.getmembers()), 20)
     57 
     58        names = ["file%02d" % i for i in range(20)]
     59        self.assertEqual(tf.getnames(), names)
     60 
     61        for ti in tf.getmembers():
     62            self.assertEqual(ti.uid, 0)
     63            self.assertEqual(ti.gid, 0)
     64            self.assertEqual(ti.uname, "")
     65            self.assertEqual(ti.gname, "")
     66            self.assertEqual(ti.mode, MODE_STANDARD)
     67            self.assertEqual(ti.mtime, DEFAULT_MTIME)
     68 
     69    @pytest.mark.xfail(
     70        reason="ValueError is not thrown despite being provided directory."
     71    )
     72    def test_dirs_refused(self):
     73        d = tempfile.mkdtemp()
     74        try:
     75            tp = os.path.join(d, "test.tar")
     76            with open(tp, "wb") as fh:
     77                with self.assertRaisesRegex(ValueError, "not a regular"):
     78                    create_tar_from_files(fh, {"test": d})
     79        finally:
     80            shutil.rmtree(d)
     81 
     82    @pytest.mark.xfail(reason="ValueError is not thrown despite uid/gid being set.")
     83    def test_setuid_setgid_refused(self):
     84        d = tempfile.mkdtemp()
     85        try:
     86            uid = os.path.join(d, "setuid")
     87            gid = os.path.join(d, "setgid")
     88            with open(uid, "a"):
     89                pass
     90            with open(gid, "a"):
     91                pass
     92 
     93            os.chmod(uid, MODE_STANDARD | stat.S_ISUID)
     94            os.chmod(gid, MODE_STANDARD | stat.S_ISGID)
     95 
     96            tp = os.path.join(d, "test.tar")
     97            with open(tp, "wb") as fh:
     98                with self.assertRaisesRegex(ValueError, "cannot add file with setuid"):
     99                    create_tar_from_files(fh, {"test": uid})
    100                with self.assertRaisesRegex(ValueError, "cannot add file with setuid"):
    101                    create_tar_from_files(fh, {"test": gid})
    102        finally:
    103            shutil.rmtree(d)
    104 
    105    def test_create_tar_basic(self):
    106        d = tempfile.mkdtemp()
    107        try:
    108            files = self._create_files(d)
    109 
    110            tp = os.path.join(d, "test.tar")
    111            with open(tp, "wb") as fh:
    112                create_tar_from_files(fh, files)
    113 
    114            # Output should be deterministic.
    115            self.assertEqual(file_hash(tp), "01cd314e277f060e98c7de6c8ea57f96b3a2065c")
    116 
    117            with tarfile.open(tp, "r") as tf:
    118                self._verify_basic_tarfile(tf)
    119 
    120        finally:
    121            shutil.rmtree(d)
    122 
    123    @pytest.mark.xfail(reason="hash mismatch")
    124    def test_executable_preserved(self):
    125        d = tempfile.mkdtemp()
    126        try:
    127            p = os.path.join(d, "exec")
    128            with open(p, "wb") as fh:
    129                fh.write("#!/bin/bash\n")
    130            os.chmod(p, MODE_STANDARD | stat.S_IXUSR)
    131 
    132            tp = os.path.join(d, "test.tar")
    133            with open(tp, "wb") as fh:
    134                create_tar_from_files(fh, {"exec": p})
    135 
    136            self.assertEqual(file_hash(tp), "357e1b81c0b6cfdfa5d2d118d420025c3c76ee93")
    137 
    138            with tarfile.open(tp, "r") as tf:
    139                m = tf.getmember("exec")
    140                self.assertEqual(m.mode, MODE_STANDARD | stat.S_IXUSR)
    141 
    142        finally:
    143            shutil.rmtree(d)
    144 
    145    def test_create_tar_gz_basic(self):
    146        d = tempfile.mkdtemp()
    147        try:
    148            files = self._create_files(d)
    149 
    150            gp = os.path.join(d, "test.tar.gz")
    151            with open(gp, "wb") as fh:
    152                create_tar_gz_from_files(fh, files)
    153 
    154            self.assertEqual(file_hash(gp), "7c4da5adc5088cdf00911d5daf9a67b15de714b7")
    155 
    156            with tarfile.open(gp, "r:gz") as tf:
    157                self._verify_basic_tarfile(tf)
    158 
    159        finally:
    160            shutil.rmtree(d)
    161 
    162    def test_tar_gz_name(self):
    163        d = tempfile.mkdtemp()
    164        try:
    165            files = self._create_files(d)
    166 
    167            gp = os.path.join(d, "test.tar.gz")
    168            with open(gp, "wb") as fh:
    169                create_tar_gz_from_files(fh, files, filename="foobar")
    170 
    171            self.assertEqual(file_hash(gp), "721e00083c17d16df2edbddf40136298c06d0c49")
    172 
    173            with tarfile.open(gp, "r:gz") as tf:
    174                self._verify_basic_tarfile(tf)
    175 
    176        finally:
    177            shutil.rmtree(d)
    178 
    179    def test_create_tar_bz2_basic(self):
    180        d = tempfile.mkdtemp()
    181        try:
    182            files = self._create_files(d)
    183 
    184            bp = os.path.join(d, "test.tar.bz2")
    185            with open(bp, "wb") as fh:
    186                create_tar_bz2_from_files(fh, files)
    187 
    188            self.assertEqual(file_hash(bp), "eb5096d2fbb71df7b3d690001a6f2e82a5aad6a7")
    189 
    190            with tarfile.open(bp, "r:bz2") as tf:
    191                self._verify_basic_tarfile(tf)
    192        finally:
    193            shutil.rmtree(d)
    194 
    195 
    196 if __name__ == "__main__":
    197    main()