blob: bd4a9a8def8ca93c2a3c5639fffce937d65c2070 [file] [log] [blame]
Paul Duffinb5cd5222022-02-28 19:06:49 +00001#!/usr/bin/env python
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"""Unit tests for verify_overlaps_test.py."""
17import io
18import unittest
19
20from signature_trie import InteriorNode
21from signature_trie import signature_trie
22
23
24class TestSignatureToElements(unittest.TestCase):
25
26 @staticmethod
27 def signature_to_elements(signature):
28 return InteriorNode.signature_to_elements(signature)
29
Paul Duffin92532e72022-03-09 14:28:34 +000030 @staticmethod
31 def elements_to_signature(elements):
32 return InteriorNode.elements_to_selector(elements)
33
Paul Duffinb5cd5222022-02-28 19:06:49 +000034 def test_nested_inner_classes(self):
35 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000036 ("package", "java"),
37 ("package", "lang"),
38 ("class", "ProcessBuilder"),
39 ("class", "Redirect"),
40 ("class", "1"),
41 ("member", "<init>()V"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000042 ]
43 signature = "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V"
44 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +000045 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +000046
47 def test_basic_member(self):
48 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000049 ("package", "java"),
50 ("package", "lang"),
51 ("class", "Object"),
52 ("member", "hashCode()I"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000053 ]
54 signature = "Ljava/lang/Object;->hashCode()I"
55 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +000056 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +000057
58 def test_double_dollar_class(self):
59 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000060 ("package", "java"),
61 ("package", "lang"),
62 ("class", "CharSequence"),
63 ("class", ""),
64 ("class", "ExternalSyntheticLambda0"),
65 ("member", "<init>(Ljava/lang/CharSequence;)V"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000066 ]
67 signature = "Ljava/lang/CharSequence$$ExternalSyntheticLambda0;" \
68 "-><init>(Ljava/lang/CharSequence;)V"
69 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +000070 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +000071
72 def test_no_member(self):
73 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000074 ("package", "java"),
75 ("package", "lang"),
76 ("class", "CharSequence"),
77 ("class", ""),
78 ("class", "ExternalSyntheticLambda0"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000079 ]
80 signature = "Ljava/lang/CharSequence$$ExternalSyntheticLambda0"
81 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +000082 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +000083
84 def test_wildcard(self):
85 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000086 ("package", "java"),
87 ("package", "lang"),
88 ("wildcard", "*"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000089 ]
90 signature = "java/lang/*"
91 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +000092 self.assertEqual(signature, self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +000093
94 def test_recursive_wildcard(self):
95 elements = [
Paul Duffinea935422022-03-09 14:51:17 +000096 ("package", "java"),
97 ("package", "lang"),
98 ("wildcard", "**"),
Paul Duffinb5cd5222022-02-28 19:06:49 +000099 ]
100 signature = "java/lang/**"
101 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +0000102 self.assertEqual(signature, self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000103
104 def test_no_packages_wildcard(self):
105 elements = [
Paul Duffinea935422022-03-09 14:51:17 +0000106 ("wildcard", "*"),
Paul Duffinb5cd5222022-02-28 19:06:49 +0000107 ]
108 signature = "*"
109 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +0000110 self.assertEqual(signature, self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000111
112 def test_no_packages_recursive_wildcard(self):
113 elements = [
Paul Duffinea935422022-03-09 14:51:17 +0000114 ("wildcard", "**"),
Paul Duffinb5cd5222022-02-28 19:06:49 +0000115 ]
116 signature = "**"
117 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +0000118 self.assertEqual(signature, self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000119
120 def test_non_standard_class_name(self):
121 elements = [
Paul Duffinea935422022-03-09 14:51:17 +0000122 ("package", "javax"),
123 ("package", "crypto"),
124 ("class", "extObjectInputStream"),
Paul Duffinb5cd5222022-02-28 19:06:49 +0000125 ]
126 signature = "Ljavax/crypto/extObjectInputStream"
127 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +0000128 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000129
Paul Duffin19255f12022-03-08 16:35:52 +0000130 def test_invalid_pattern_wildcard(self):
131 pattern = "Ljava/lang/Class*"
132 with self.assertRaises(Exception) as context:
133 self.signature_to_elements(pattern)
134 self.assertIn("invalid wildcard 'Class*'", str(context.exception))
135
Paul Duffinb5cd5222022-02-28 19:06:49 +0000136 def test_invalid_pattern_wildcard_and_member(self):
137 pattern = "Ljava/lang/*;->hashCode()I"
138 with self.assertRaises(Exception) as context:
139 self.signature_to_elements(pattern)
Paul Duffin19255f12022-03-08 16:35:52 +0000140 self.assertIn(
141 "contains wildcard '*' and member signature 'hashCode()I'",
142 str(context.exception))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000143
144
Paul Duffindbbb8372022-04-01 15:04:23 +0100145class TestValues(unittest.TestCase):
146 def test_add_then_get(self):
147 trie = signature_trie()
148 trie.add("La/b/C;->l()", 1)
149 trie.add("La/b/C$D;->m()", "A")
150 trie.add("La/b/C$D;->n()", {})
151
152 package_a_node = next(iter(trie.child_nodes()))
153 self.assertEqual("package", package_a_node.type)
154 self.assertEqual("a", package_a_node.selector)
155
156 package_b_node = next(iter(package_a_node.child_nodes()))
157 self.assertEqual("package", package_b_node.type)
158 self.assertEqual("a/b", package_b_node.selector)
159
160 class_c_node = next(iter(package_b_node.child_nodes()))
161 self.assertEqual("class", class_c_node.type)
162 self.assertEqual("a/b/C", class_c_node.selector)
163
164 self.assertEqual([1, "A", {}], class_c_node.values(lambda _: True))
165
Paul Duffinb5cd5222022-02-28 19:06:49 +0000166class TestGetMatchingRows(unittest.TestCase):
167 extractInput = """
168Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;
169Ljava/lang/Character;->serialVersionUID:J
170Ljava/lang/Object;->hashCode()I
171Ljava/lang/Object;->toString()Ljava/lang/String;
172Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V
173Ljava/util/zip/ZipFile;-><clinit>()V
174"""
175
176 def read_trie(self):
177 trie = signature_trie()
178 with io.StringIO(self.extractInput.strip()) as f:
179 for line in iter(f.readline, ""):
180 line = line.rstrip()
181 trie.add(line, line)
182 return trie
183
184 def check_patterns(self, pattern, expected):
185 trie = self.read_trie()
186 self.check_node_patterns(trie, pattern, expected)
187
188 def check_node_patterns(self, node, pattern, expected):
189 actual = list(node.get_matching_rows(pattern))
190 actual.sort()
191 self.assertEqual(expected, actual)
192
193 def test_member_pattern(self):
194 self.check_patterns("java/util/zip/ZipFile;-><clinit>()V",
195 ["Ljava/util/zip/ZipFile;-><clinit>()V"])
196
197 def test_class_pattern(self):
198 self.check_patterns("java/lang/Object", [
199 "Ljava/lang/Object;->hashCode()I",
200 "Ljava/lang/Object;->toString()Ljava/lang/String;",
201 ])
202
203 # pylint: disable=line-too-long
204 def test_nested_class_pattern(self):
205 self.check_patterns("java/lang/Character", [
206 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
207 "Ljava/lang/Character;->serialVersionUID:J",
208 ])
209
210 def test_wildcard(self):
211 self.check_patterns("java/lang/*", [
212 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
213 "Ljava/lang/Character;->serialVersionUID:J",
214 "Ljava/lang/Object;->hashCode()I",
215 "Ljava/lang/Object;->toString()Ljava/lang/String;",
216 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
217 ])
218
219 def test_recursive_wildcard(self):
220 self.check_patterns("java/**", [
221 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
222 "Ljava/lang/Character;->serialVersionUID:J",
223 "Ljava/lang/Object;->hashCode()I",
224 "Ljava/lang/Object;->toString()Ljava/lang/String;",
225 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
226 "Ljava/util/zip/ZipFile;-><clinit>()V",
227 ])
228
Paul Duffin92532e72022-03-09 14:28:34 +0000229 def test_node_wildcard(self):
230 trie = self.read_trie()
231 node = list(trie.child_nodes())[0]
232 self.check_node_patterns(node, "**", [
233 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
234 "Ljava/lang/Character;->serialVersionUID:J",
235 "Ljava/lang/Object;->hashCode()I",
236 "Ljava/lang/Object;->toString()Ljava/lang/String;",
237 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
238 "Ljava/util/zip/ZipFile;-><clinit>()V",
239 ])
240
Paul Duffinb5cd5222022-02-28 19:06:49 +0000241 # pylint: enable=line-too-long
242
243
244if __name__ == "__main__":
245 unittest.main(verbosity=2)