• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright (C) 2022 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import unittest
18
19import os
20from pathlib import Path
21from tempfile import TemporaryDirectory
22
23from finder import FileFinder
24
25FILENAME = "myfile.json"
26
27
28def _create_file(root: str, rel_dir_path: str, filename: str):
29    """Helper function to create an empty file in a test directory"""
30    if ".." in rel_dir_path:
31        raise Exception(f".. is not allowed in {rel_dir_path}")
32    # Create the directory if it is does not exist
33    dirpath = os.path.join(root, rel_dir_path)
34    os.makedirs(dirpath, exist_ok=True)
35    # Create an empty file in the newly created directory
36    filepath = os.path.join(dirpath, filename)
37    Path(filepath).touch()
38
39
40class TestFileFinder(unittest.TestCase):
41    def test_single_file_match(self):
42        finder = FileFinder(FILENAME)
43        # root dir
44        with TemporaryDirectory() as tmp:
45            _create_file(tmp, "", FILENAME)
46            _create_file(tmp, "", "some_other_file.json")
47            results = list(finder.find(tmp, search_depth=100))
48            self.assertEqual(1, len(results))
49            self.assertEqual(f"{tmp}/{FILENAME}", results[0])
50        # nested dir
51        with TemporaryDirectory() as tmp:
52            _create_file(tmp, "a/b/c", FILENAME)
53            results = list(finder.find(tmp, search_depth=100))
54            self.assertEqual(1, len(results))
55            self.assertEqual(f"{tmp}/a/b/c/{FILENAME}", results[0])
56
57    def test_multiple_file_matches(self):
58        finder = FileFinder(FILENAME)
59        with TemporaryDirectory() as tmp:
60            _create_file(tmp, "a", FILENAME)
61            _create_file(tmp, "a/b", FILENAME)
62            all_results = sorted(list(finder.find(tmp, search_depth=100)),
63                                 reverse=True)
64            self.assertEqual(2, len(all_results))
65            self.assertEqual(f"{tmp}/a/{FILENAME}", all_results[0])
66            self.assertEqual(f"{tmp}/a/b/{FILENAME}", all_results[1])
67
68    def test_find_does_not_escape_directory(self):
69        finder = FileFinder(FILENAME)
70        with TemporaryDirectory() as tmp:
71            _create_file(tmp, "", FILENAME)
72            _create_file(tmp, "a", FILENAME)
73            _create_file(tmp, "b", FILENAME)
74            search_dir_a_results = list(
75                finder.find(f"{tmp}/a", search_depth=100))
76            self.assertEqual(1, len(search_dir_a_results))
77            self.assertEqual(f"{tmp}/a/{FILENAME}", search_dir_a_results[0])
78
79    def test_depth_pruning(self):
80        finder = FileFinder(FILENAME)
81        with TemporaryDirectory() as tmp:
82            _create_file(tmp, "", FILENAME)
83            _create_file(tmp, "a", FILENAME)
84            _create_file(tmp, "a/b", FILENAME)
85            self.assertEqual(3, len(list(finder.find(tmp, 3))))
86            self.assertEqual(3, len(list(finder.find(tmp, 2))))
87            self.assertEqual(2, len(list(finder.find(tmp, 1))))
88            self.assertEqual(1, len(list(finder.find(tmp, 0))))
89
90    def test_path_pruning(self):
91        with TemporaryDirectory() as tmp:
92            finder = FileFinder(FILENAME, ignore_paths=[f"{tmp}/out"])
93            _create_file(tmp, "", FILENAME)
94            _create_file(tmp, "out",
95                         FILENAME)  # This should not appear in results
96            _create_file(
97                tmp, "a/b/out",
98                FILENAME)  # This is "source code", should appear in results
99            results = sorted(list(finder.find(tmp, search_depth=100)),
100                             reverse=True)
101            self.assertEqual(2, len(results))
102            self.assertEqual(f"{tmp}/{FILENAME}", results[0])
103            self.assertEqual(f"{tmp}/a/b/out/{FILENAME}", results[1])
104
105    def test_hidden_dir_pruning(self):
106        prune_hidden_dir_finder = FileFinder(FILENAME)
107        all_dir_finder = FileFinder(FILENAME, prune_hidden_dirs=False)
108        with TemporaryDirectory() as tmp:
109            _create_file(tmp, "", FILENAME)
110            _create_file(tmp, ".hidden_dir", FILENAME)
111            _create_file(tmp, "visible_dir", FILENAME)
112            self.assertEqual(
113                2,
114                len(list(prune_hidden_dir_finder.find(tmp, search_depth=100))))
115            self.assertEqual(
116                3, len(list(all_dir_finder.find(tmp, search_depth=100))))
117
118
119if __name__ == "__main__":
120    # This unit test assumes that the file separator is /
121    # A generic solution would use os.path.join to join path fragments and make
122    # this test platform agnostic, but would make the test less readable.
123    if os.name != "posix":
124        raise Exception(f"This unit test is not supported on {os.name}")
125    unittest.main()
126