test_pathutils.py (6624B)
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 from fnmatch import fnmatch 7 8 import mozunit 9 import pytest 10 11 from mozlint import pathutils 12 13 here = os.path.abspath(os.path.dirname(__file__)) 14 root = os.path.join(here, "filter") 15 16 17 def assert_paths(a, b): 18 def normalize(p): 19 if not os.path.isabs(p): 20 p = os.path.join(root, p) 21 return os.path.normpath(p) 22 23 assert set(map(normalize, a)) == set(map(normalize, b)) 24 25 26 @pytest.mark.parametrize( 27 "test", 28 ( 29 { 30 "paths": ["a.js", "subdir1/subdir3/d.js"], 31 "include": ["."], 32 "exclude": ["subdir1"], 33 "expected": ["a.js"], 34 }, 35 { 36 "paths": ["a.js", "subdir1/subdir3/d.js"], 37 "include": ["subdir1/subdir3"], 38 "exclude": ["subdir1"], 39 "expected": ["subdir1/subdir3/d.js"], 40 }, 41 { 42 "paths": ["."], 43 "include": ["."], 44 "exclude": ["**/c.py", "subdir1/subdir3"], 45 "extensions": ["py"], 46 "expected": ["."], 47 "expected_exclude": ["subdir2/c.py", "subdir1/subdir3"], 48 }, 49 { 50 "paths": [ 51 "a.py", 52 "a.js", 53 "subdir1/b.py", 54 "subdir2/c.py", 55 "subdir1/subdir3/d.py", 56 ], 57 "include": ["."], 58 "exclude": ["**/c.py", "subdir1/subdir3"], 59 "extensions": ["py"], 60 "expected": ["a.py", "subdir1/b.py"], 61 }, 62 pytest.param( 63 { 64 "paths": [ 65 "a.py", 66 "a.js", 67 "subdir1/b.py", 68 "subdir2/c.py", 69 "subdir1/subdir3/d.py", 70 ], 71 "include": ["."], 72 "exclude": [], 73 "exclude_extensions": ["py"], 74 "expected": ["a.js"], 75 }, 76 id="Excluding .py should only return .js file.", 77 ), 78 pytest.param( 79 { 80 "paths": [ 81 "a.py", 82 "a.js", 83 "subdir1/b.py", 84 "subdir2/c.py", 85 "subdir1/subdir3/d.py", 86 ], 87 "include": ["."], 88 "exclude": [], 89 "exclude_extensions": ["js"], 90 "expected": [ 91 "a.py", 92 "subdir1/b.py", 93 "subdir2/c.py", 94 "subdir1/subdir3/d.py", 95 ], 96 }, 97 id="Excluding .js should only return .py files.", 98 ), 99 { 100 "paths": ["a.py", "a.js", "subdir2"], 101 "include": ["."], 102 "exclude": [], 103 "extensions": ["py"], 104 "expected": ["a.py", "subdir2"], 105 }, 106 { 107 "paths": ["subdir1"], 108 "include": ["."], 109 "exclude": ["subdir1/subdir3"], 110 "extensions": ["py"], 111 "expected": ["subdir1"], 112 "expected_exclude": ["subdir1/subdir3"], 113 }, 114 { 115 "paths": ["docshell"], 116 "include": ["docs"], 117 "exclude": [], 118 "expected": [], 119 }, 120 { 121 "paths": ["does/not/exist"], 122 "include": ["."], 123 "exclude": [], 124 "expected": [], 125 }, 126 { 127 "paths": ["a.py"], 128 "include": ["a.js"], 129 "exclude": [], 130 "expected": [], 131 }, 132 ), 133 ) 134 def test_filterpaths(test): 135 expected = test.pop("expected") 136 expected_exclude = test.pop("expected_exclude", []) 137 138 paths, exclude = pathutils.filterpaths(root, **test) 139 assert_paths(paths, expected) 140 assert_paths(exclude, expected_exclude) 141 142 143 @pytest.mark.parametrize( 144 "test", 145 ( 146 { 147 "paths": ["subdir1/b.js"], 148 "config": { 149 "exclude": ["subdir1"], 150 "extensions": ["js"], 151 }, 152 "expected": [], 153 }, 154 { 155 "paths": ["subdir1"], 156 "config": { 157 "exclude": ["subdir1"], 158 "extensions": ["js"], 159 }, 160 "expected": [], 161 }, 162 pytest.param( 163 { 164 "paths": ["a.py", "subdir1"], 165 "config": { 166 "exclude": ["subdir1"], 167 "exclude_extensions": ["gob"], 168 }, 169 "expected": ["a.py"], 170 }, 171 id="Excluding both subdirs and nonsense extensions returns other files.", 172 ), 173 pytest.param( 174 { 175 "paths": ["a.py", "a.js", "subdir1"], 176 "config": { 177 "exclude": [], 178 "exclude_extensions": ["py"], 179 }, 180 "expected": ["a.js", "subdir1/subdir3/d.js", "subdir1/b.js"], 181 }, 182 id="Excluding .py files returns only non-.py files, also from subdirs.", 183 ), 184 ), 185 ) 186 def test_expand_exclusions(test): 187 expected = test.pop("expected", []) 188 189 input_paths = [os.path.join(root, p) for p in test["paths"]] 190 paths = list(pathutils.expand_exclusions(input_paths, test["config"], root)) 191 assert_paths(paths, expected) 192 193 194 @pytest.mark.parametrize( 195 "paths,expected", 196 [ 197 (["subdir1/*"], ["subdir1"]), 198 (["subdir2/*"], ["subdir2"]), 199 (["subdir1/*.*", "subdir1/subdir3/*", "subdir2/*"], ["subdir1", "subdir2"]), 200 ([root + "/*", "subdir1/*.*", "subdir1/subdir3/*", "subdir2/*"], [root]), 201 (["subdir1/b.py", "subdir1/subdir3"], ["subdir1/b.py", "subdir1/subdir3"]), 202 (["subdir1/b.py", "subdir1/b.js"], ["subdir1/b.py", "subdir1/b.js"]), 203 (["subdir1/subdir3"], ["subdir1/subdir3"]), 204 ( 205 [ 206 "foo", 207 "foobar", 208 ], 209 ["foo", "foobar"], 210 ), 211 ], 212 ) 213 def test_collapse(paths, expected): 214 os.chdir(root) 215 216 inputs = [] 217 for path in paths: 218 base, name = os.path.split(path) 219 if "*" in name: 220 for n in os.listdir(base): 221 if not fnmatch(n, name): 222 continue 223 inputs.append(os.path.join(base, n)) 224 else: 225 inputs.append(path) 226 227 print(f"inputs: {inputs}") 228 assert_paths(pathutils.collapse(inputs), expected) 229 230 231 if __name__ == "__main__": 232 mozunit.main()