blob: 12956910789cc7cee71edf610bd30cdd4937b9b6 [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
Paul Duffin19255f12022-03-08 16:35:52 +0000120 def test_invalid_no_class_or_wildcard(self):
121 signature = "java/lang"
122 with self.assertRaises(Exception) as context:
123 self.signature_to_elements(signature)
124 self.assertIn(
125 "last element 'lang' is lower case but should be an "
126 "upper case class name or wildcard", str(context.exception))
127
Paul Duffinb5cd5222022-02-28 19:06:49 +0000128 def test_non_standard_class_name(self):
129 elements = [
Paul Duffinea935422022-03-09 14:51:17 +0000130 ("package", "javax"),
131 ("package", "crypto"),
132 ("class", "extObjectInputStream"),
Paul Duffinb5cd5222022-02-28 19:06:49 +0000133 ]
134 signature = "Ljavax/crypto/extObjectInputStream"
135 self.assertEqual(elements, self.signature_to_elements(signature))
Paul Duffin92532e72022-03-09 14:28:34 +0000136 self.assertEqual(signature, "L" + self.elements_to_signature(elements))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000137
Paul Duffin19255f12022-03-08 16:35:52 +0000138 def test_invalid_pattern_wildcard(self):
139 pattern = "Ljava/lang/Class*"
140 with self.assertRaises(Exception) as context:
141 self.signature_to_elements(pattern)
142 self.assertIn("invalid wildcard 'Class*'", str(context.exception))
143
Paul Duffinb5cd5222022-02-28 19:06:49 +0000144 def test_invalid_pattern_wildcard_and_member(self):
145 pattern = "Ljava/lang/*;->hashCode()I"
146 with self.assertRaises(Exception) as context:
147 self.signature_to_elements(pattern)
Paul Duffin19255f12022-03-08 16:35:52 +0000148 self.assertIn(
149 "contains wildcard '*' and member signature 'hashCode()I'",
150 str(context.exception))
Paul Duffinb5cd5222022-02-28 19:06:49 +0000151
152
153class TestGetMatchingRows(unittest.TestCase):
154 extractInput = """
155Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;
156Ljava/lang/Character;->serialVersionUID:J
157Ljava/lang/Object;->hashCode()I
158Ljava/lang/Object;->toString()Ljava/lang/String;
159Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V
160Ljava/util/zip/ZipFile;-><clinit>()V
161"""
162
163 def read_trie(self):
164 trie = signature_trie()
165 with io.StringIO(self.extractInput.strip()) as f:
166 for line in iter(f.readline, ""):
167 line = line.rstrip()
168 trie.add(line, line)
169 return trie
170
171 def check_patterns(self, pattern, expected):
172 trie = self.read_trie()
173 self.check_node_patterns(trie, pattern, expected)
174
175 def check_node_patterns(self, node, pattern, expected):
176 actual = list(node.get_matching_rows(pattern))
177 actual.sort()
178 self.assertEqual(expected, actual)
179
180 def test_member_pattern(self):
181 self.check_patterns("java/util/zip/ZipFile;-><clinit>()V",
182 ["Ljava/util/zip/ZipFile;-><clinit>()V"])
183
184 def test_class_pattern(self):
185 self.check_patterns("java/lang/Object", [
186 "Ljava/lang/Object;->hashCode()I",
187 "Ljava/lang/Object;->toString()Ljava/lang/String;",
188 ])
189
190 # pylint: disable=line-too-long
191 def test_nested_class_pattern(self):
192 self.check_patterns("java/lang/Character", [
193 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
194 "Ljava/lang/Character;->serialVersionUID:J",
195 ])
196
197 def test_wildcard(self):
198 self.check_patterns("java/lang/*", [
199 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
200 "Ljava/lang/Character;->serialVersionUID:J",
201 "Ljava/lang/Object;->hashCode()I",
202 "Ljava/lang/Object;->toString()Ljava/lang/String;",
203 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
204 ])
205
206 def test_recursive_wildcard(self):
207 self.check_patterns("java/**", [
208 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
209 "Ljava/lang/Character;->serialVersionUID:J",
210 "Ljava/lang/Object;->hashCode()I",
211 "Ljava/lang/Object;->toString()Ljava/lang/String;",
212 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
213 "Ljava/util/zip/ZipFile;-><clinit>()V",
214 ])
215
Paul Duffin92532e72022-03-09 14:28:34 +0000216 def test_node_wildcard(self):
217 trie = self.read_trie()
218 node = list(trie.child_nodes())[0]
219 self.check_node_patterns(node, "**", [
220 "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;",
221 "Ljava/lang/Character;->serialVersionUID:J",
222 "Ljava/lang/Object;->hashCode()I",
223 "Ljava/lang/Object;->toString()Ljava/lang/String;",
224 "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
225 "Ljava/util/zip/ZipFile;-><clinit>()V",
226 ])
227
Paul Duffinb5cd5222022-02-28 19:06:49 +0000228 # pylint: enable=line-too-long
229
230
231if __name__ == "__main__":
232 unittest.main(verbosity=2)