summaryrefslogtreecommitdiff
path: root/tests/test_find_top_level.py
blob: aefa72ddb9d848f58d578fabc1bcb15e0eca09bb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# gemato: Top-level Manifest finding tests
# (c) 2017-2022 Michał Górny
# Licensed under the terms of 2-clause BSD license

import gzip
import os
import os.path

import pytest

from gemato.find_top_level import find_top_level_manifest

from tests.testutil import disallow_writes


@pytest.fixture(scope='module')
def plain_tree(tmp_path_factory):
    tmp_path = tmp_path_factory.mktemp('find-top-level-plain-')
    for d in ('empty-subdir',
              'manifest-subdir',
              'deep/manifest-subdir',
              'ignored-dir',
              'ignored-dir/subdir',
              'ignored-dir-not',
              'ignored-empty-dir'):
        os.makedirs(tmp_path / d)
    with open(tmp_path / 'Manifest', 'w') as f:
        f.write('''
IGNORE ignored-dir
IGNORE ignored-empty-dir
''')
    for f in ('manifest-subdir/Manifest',
              'deep/manifest-subdir/Manifest',
              'ignored-dir/Manifest'):
        with open(tmp_path / f, 'w'):
            pass
    disallow_writes(tmp_path)
    yield tmp_path


@pytest.mark.parametrize(
    'start_dir,expected',
    [('.', 'Manifest'),
     ('empty-subdir', 'Manifest'),
     ('manifest-subdir', 'Manifest'),
     ('deep/manifest-subdir', 'Manifest'),
     ('ignored-dir', 'ignored-dir/Manifest'),
     ('ignored-dir/subdir', 'ignored-dir/Manifest'),
     ('ignored-dir-not', 'Manifest'),
     ('ignored-empty-dir', None),
     ])
def test_find_top_level_manifest(plain_tree, start_dir, expected):
    """Test finding top-level Manifest from plain directory tree"""
    mpath = find_top_level_manifest(plain_tree / start_dir)
    if mpath is not None:
        mpath = os.path.relpath(mpath, plain_tree)
    assert mpath == expected


def test_unreadable_manifest(tmp_path):
    """Test failure when one of Manifest files is not readable"""
    with open(tmp_path / 'Manifest', 'w') as f:
        os.fchmod(f.fileno(), 0)
    with pytest.raises(PermissionError):
        find_top_level_manifest(tmp_path)


def test_empty_tree(tmp_path):
    """Test working on empty tree without a Manifest file"""
    assert find_top_level_manifest(tmp_path) is None


def test_root_directory(tmp_path):
    """Test that things do not explode when running on /"""
    if os.path.exists('/Manifest'):
        pytest.skip('Manifest is present in system root ("/")')
    assert find_top_level_manifest('/') is None


def test_cross_device(tmp_path):
    """Test that device boundaries are not crossed"""
    if not os.path.ismount('/proc'):
        pytest.skip('/proc is not a mount point')
    with open(tmp_path / 'Manifest', 'w'):
        pass
    os.symlink('/proc', tmp_path / 'test')
    assert find_top_level_manifest(tmp_path / 'test') is None


@pytest.fixture(scope='module')
def compressed_manifest_tree(tmp_path_factory):
    tmp_path = tmp_path_factory.mktemp('find-top-level-compressed-')
    for d in ('empty-subdir',
              'manifest-subdir',
              'deep/manifest-subdir',
              'ignored-dir',
              'ignored-dir/subdir',
              'ignored-dir-not',
              'ignored-empty-dir'):
        os.makedirs(tmp_path / d)
    with gzip.GzipFile(tmp_path / 'Manifest.gz', 'wb') as f:
        f.write(b'''
IGNORE ignored-dir
IGNORE ignored-empty-dir
''')
    with open(tmp_path / 'manifest-subdir/Manifest', 'wb'):
        pass
    for f in ('deep/manifest-subdir/Manifest.gz',
              'ignored-dir/Manifest.gz'):
        with gzip.GzipFile(tmp_path / f, 'w'):
            pass
    disallow_writes(tmp_path)
    yield tmp_path


@pytest.mark.parametrize(
    'start_dir,allow_compressed,expected',
    [('.', False, None),
     ('.', True, 'Manifest.gz'),
     ('empty-subdir', True, 'Manifest.gz'),
     ('manifest-subdir', True, 'Manifest.gz'),
     ('deep/manifest-subdir', True, 'Manifest.gz'),
     ('ignored-dir', True, 'ignored-dir/Manifest.gz'),
     ('ignored-dir/subdir', True, 'ignored-dir/Manifest.gz'),
     ('ignored-dir-not', True, 'Manifest.gz'),
     ('ignored-empty-dir', True, None),
     ])
def test_find_compressed_top_level_manifest(compressed_manifest_tree,
                                            start_dir,
                                            allow_compressed,
                                            expected):
    """Test finding compressed top-level Manifest """
    mpath = find_top_level_manifest(compressed_manifest_tree / start_dir,
                                    allow_compressed=allow_compressed)
    if mpath is not None:
        mpath = os.path.relpath(mpath, compressed_manifest_tree)
    assert mpath == expected