1*333d2b36SAndroid Build Coastguard Worker#!/usr/bin/env python 2*333d2b36SAndroid Build Coastguard Worker# 3*333d2b36SAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project 4*333d2b36SAndroid Build Coastguard Worker# 5*333d2b36SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the 'License'); 6*333d2b36SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*333d2b36SAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*333d2b36SAndroid Build Coastguard Worker# 9*333d2b36SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*333d2b36SAndroid Build Coastguard Worker# 11*333d2b36SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*333d2b36SAndroid Build Coastguard Worker# distributed under the License is distributed on an 'AS IS' BASIS, 13*333d2b36SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*333d2b36SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*333d2b36SAndroid Build Coastguard Worker# limitations under the License. 16*333d2b36SAndroid Build Coastguard Worker"""Unit tests for verify_overlaps_test.py.""" 17*333d2b36SAndroid Build Coastguard Workerimport io 18*333d2b36SAndroid Build Coastguard Workerimport unittest 19*333d2b36SAndroid Build Coastguard Worker 20*333d2b36SAndroid Build Coastguard Workerfrom signature_trie import InteriorNode 21*333d2b36SAndroid Build Coastguard Workerfrom signature_trie import signature_trie 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Workerclass TestSignatureToElements(unittest.TestCase): 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Worker @staticmethod 27*333d2b36SAndroid Build Coastguard Worker def signature_to_elements(signature): 28*333d2b36SAndroid Build Coastguard Worker return InteriorNode.signature_to_elements(signature) 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker @staticmethod 31*333d2b36SAndroid Build Coastguard Worker def elements_to_signature(elements): 32*333d2b36SAndroid Build Coastguard Worker return InteriorNode.elements_to_selector(elements) 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Worker def test_nested_inner_classes(self): 35*333d2b36SAndroid Build Coastguard Worker elements = [ 36*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 37*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 38*333d2b36SAndroid Build Coastguard Worker ("class", "ProcessBuilder"), 39*333d2b36SAndroid Build Coastguard Worker ("class", "Redirect"), 40*333d2b36SAndroid Build Coastguard Worker ("class", "1"), 41*333d2b36SAndroid Build Coastguard Worker ("member", "<init>()V"), 42*333d2b36SAndroid Build Coastguard Worker ] 43*333d2b36SAndroid Build Coastguard Worker signature = "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V" 44*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 45*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, "L" + self.elements_to_signature(elements)) 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Worker def test_basic_member(self): 48*333d2b36SAndroid Build Coastguard Worker elements = [ 49*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 50*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 51*333d2b36SAndroid Build Coastguard Worker ("class", "Object"), 52*333d2b36SAndroid Build Coastguard Worker ("member", "hashCode()I"), 53*333d2b36SAndroid Build Coastguard Worker ] 54*333d2b36SAndroid Build Coastguard Worker signature = "Ljava/lang/Object;->hashCode()I" 55*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 56*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, "L" + self.elements_to_signature(elements)) 57*333d2b36SAndroid Build Coastguard Worker 58*333d2b36SAndroid Build Coastguard Worker def test_double_dollar_class(self): 59*333d2b36SAndroid Build Coastguard Worker elements = [ 60*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 61*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 62*333d2b36SAndroid Build Coastguard Worker ("class", "CharSequence"), 63*333d2b36SAndroid Build Coastguard Worker ("class", ""), 64*333d2b36SAndroid Build Coastguard Worker ("class", "ExternalSyntheticLambda0"), 65*333d2b36SAndroid Build Coastguard Worker ("member", "<init>(Ljava/lang/CharSequence;)V"), 66*333d2b36SAndroid Build Coastguard Worker ] 67*333d2b36SAndroid Build Coastguard Worker signature = "Ljava/lang/CharSequence$$ExternalSyntheticLambda0;" \ 68*333d2b36SAndroid Build Coastguard Worker "-><init>(Ljava/lang/CharSequence;)V" 69*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 70*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, "L" + self.elements_to_signature(elements)) 71*333d2b36SAndroid Build Coastguard Worker 72*333d2b36SAndroid Build Coastguard Worker def test_no_member(self): 73*333d2b36SAndroid Build Coastguard Worker elements = [ 74*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 75*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 76*333d2b36SAndroid Build Coastguard Worker ("class", "CharSequence"), 77*333d2b36SAndroid Build Coastguard Worker ("class", ""), 78*333d2b36SAndroid Build Coastguard Worker ("class", "ExternalSyntheticLambda0"), 79*333d2b36SAndroid Build Coastguard Worker ] 80*333d2b36SAndroid Build Coastguard Worker signature = "Ljava/lang/CharSequence$$ExternalSyntheticLambda0" 81*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 82*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, "L" + self.elements_to_signature(elements)) 83*333d2b36SAndroid Build Coastguard Worker 84*333d2b36SAndroid Build Coastguard Worker def test_wildcard(self): 85*333d2b36SAndroid Build Coastguard Worker elements = [ 86*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 87*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 88*333d2b36SAndroid Build Coastguard Worker ("wildcard", "*"), 89*333d2b36SAndroid Build Coastguard Worker ] 90*333d2b36SAndroid Build Coastguard Worker signature = "java/lang/*" 91*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 92*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, self.elements_to_signature(elements)) 93*333d2b36SAndroid Build Coastguard Worker 94*333d2b36SAndroid Build Coastguard Worker def test_recursive_wildcard(self): 95*333d2b36SAndroid Build Coastguard Worker elements = [ 96*333d2b36SAndroid Build Coastguard Worker ("package", "java"), 97*333d2b36SAndroid Build Coastguard Worker ("package", "lang"), 98*333d2b36SAndroid Build Coastguard Worker ("wildcard", "**"), 99*333d2b36SAndroid Build Coastguard Worker ] 100*333d2b36SAndroid Build Coastguard Worker signature = "java/lang/**" 101*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 102*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, self.elements_to_signature(elements)) 103*333d2b36SAndroid Build Coastguard Worker 104*333d2b36SAndroid Build Coastguard Worker def test_no_packages_wildcard(self): 105*333d2b36SAndroid Build Coastguard Worker elements = [ 106*333d2b36SAndroid Build Coastguard Worker ("wildcard", "*"), 107*333d2b36SAndroid Build Coastguard Worker ] 108*333d2b36SAndroid Build Coastguard Worker signature = "*" 109*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 110*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, self.elements_to_signature(elements)) 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Worker def test_no_packages_recursive_wildcard(self): 113*333d2b36SAndroid Build Coastguard Worker elements = [ 114*333d2b36SAndroid Build Coastguard Worker ("wildcard", "**"), 115*333d2b36SAndroid Build Coastguard Worker ] 116*333d2b36SAndroid Build Coastguard Worker signature = "**" 117*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 118*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, self.elements_to_signature(elements)) 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker def test_non_standard_class_name(self): 121*333d2b36SAndroid Build Coastguard Worker elements = [ 122*333d2b36SAndroid Build Coastguard Worker ("package", "javax"), 123*333d2b36SAndroid Build Coastguard Worker ("package", "crypto"), 124*333d2b36SAndroid Build Coastguard Worker ("class", "extObjectInputStream"), 125*333d2b36SAndroid Build Coastguard Worker ] 126*333d2b36SAndroid Build Coastguard Worker signature = "Ljavax/crypto/extObjectInputStream" 127*333d2b36SAndroid Build Coastguard Worker self.assertEqual(elements, self.signature_to_elements(signature)) 128*333d2b36SAndroid Build Coastguard Worker self.assertEqual(signature, "L" + self.elements_to_signature(elements)) 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Worker def test_invalid_pattern_wildcard(self): 131*333d2b36SAndroid Build Coastguard Worker pattern = "Ljava/lang/Class*" 132*333d2b36SAndroid Build Coastguard Worker with self.assertRaises(Exception) as context: 133*333d2b36SAndroid Build Coastguard Worker self.signature_to_elements(pattern) 134*333d2b36SAndroid Build Coastguard Worker self.assertIn("invalid wildcard 'Class*'", str(context.exception)) 135*333d2b36SAndroid Build Coastguard Worker 136*333d2b36SAndroid Build Coastguard Worker def test_invalid_pattern_wildcard_and_member(self): 137*333d2b36SAndroid Build Coastguard Worker pattern = "Ljava/lang/*;->hashCode()I" 138*333d2b36SAndroid Build Coastguard Worker with self.assertRaises(Exception) as context: 139*333d2b36SAndroid Build Coastguard Worker self.signature_to_elements(pattern) 140*333d2b36SAndroid Build Coastguard Worker self.assertIn( 141*333d2b36SAndroid Build Coastguard Worker "contains wildcard '*' and member signature 'hashCode()I'", 142*333d2b36SAndroid Build Coastguard Worker str(context.exception)) 143*333d2b36SAndroid Build Coastguard Worker 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Workerclass TestValues(unittest.TestCase): 146*333d2b36SAndroid Build Coastguard Worker def test_add_then_get(self): 147*333d2b36SAndroid Build Coastguard Worker trie = signature_trie() 148*333d2b36SAndroid Build Coastguard Worker trie.add("La/b/C;->l()", 1) 149*333d2b36SAndroid Build Coastguard Worker trie.add("La/b/C$D;->m()", "A") 150*333d2b36SAndroid Build Coastguard Worker trie.add("La/b/C$D;->n()", {}) 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Worker package_a_node = next(iter(trie.child_nodes())) 153*333d2b36SAndroid Build Coastguard Worker self.assertEqual("package", package_a_node.type) 154*333d2b36SAndroid Build Coastguard Worker self.assertEqual("a", package_a_node.selector) 155*333d2b36SAndroid Build Coastguard Worker 156*333d2b36SAndroid Build Coastguard Worker package_b_node = next(iter(package_a_node.child_nodes())) 157*333d2b36SAndroid Build Coastguard Worker self.assertEqual("package", package_b_node.type) 158*333d2b36SAndroid Build Coastguard Worker self.assertEqual("a/b", package_b_node.selector) 159*333d2b36SAndroid Build Coastguard Worker 160*333d2b36SAndroid Build Coastguard Worker class_c_node = next(iter(package_b_node.child_nodes())) 161*333d2b36SAndroid Build Coastguard Worker self.assertEqual("class", class_c_node.type) 162*333d2b36SAndroid Build Coastguard Worker self.assertEqual("a/b/C", class_c_node.selector) 163*333d2b36SAndroid Build Coastguard Worker 164*333d2b36SAndroid Build Coastguard Worker self.assertEqual([1, "A", {}], class_c_node.values(lambda _: True)) 165*333d2b36SAndroid Build Coastguard Worker 166*333d2b36SAndroid Build Coastguard Workerclass TestGetMatchingRows(unittest.TestCase): 167*333d2b36SAndroid Build Coastguard Worker extractInput = """ 168*333d2b36SAndroid Build Coastguard WorkerLjava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript; 169*333d2b36SAndroid Build Coastguard WorkerLjava/lang/Character;->serialVersionUID:J 170*333d2b36SAndroid Build Coastguard WorkerLjava/lang/Object;->hashCode()I 171*333d2b36SAndroid Build Coastguard WorkerLjava/lang/Object;->toString()Ljava/lang/String; 172*333d2b36SAndroid Build Coastguard WorkerLjava/lang/ProcessBuilder$Redirect$1;-><init>()V 173*333d2b36SAndroid Build Coastguard WorkerLjava/util/zip/ZipFile;-><clinit>()V 174*333d2b36SAndroid Build Coastguard Worker""" 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Worker def read_trie(self): 177*333d2b36SAndroid Build Coastguard Worker trie = signature_trie() 178*333d2b36SAndroid Build Coastguard Worker with io.StringIO(self.extractInput.strip()) as f: 179*333d2b36SAndroid Build Coastguard Worker for line in iter(f.readline, ""): 180*333d2b36SAndroid Build Coastguard Worker line = line.rstrip() 181*333d2b36SAndroid Build Coastguard Worker trie.add(line, line) 182*333d2b36SAndroid Build Coastguard Worker return trie 183*333d2b36SAndroid Build Coastguard Worker 184*333d2b36SAndroid Build Coastguard Worker def check_patterns(self, pattern, expected): 185*333d2b36SAndroid Build Coastguard Worker trie = self.read_trie() 186*333d2b36SAndroid Build Coastguard Worker self.check_node_patterns(trie, pattern, expected) 187*333d2b36SAndroid Build Coastguard Worker 188*333d2b36SAndroid Build Coastguard Worker def check_node_patterns(self, node, pattern, expected): 189*333d2b36SAndroid Build Coastguard Worker actual = list(node.get_matching_rows(pattern)) 190*333d2b36SAndroid Build Coastguard Worker actual.sort() 191*333d2b36SAndroid Build Coastguard Worker self.assertEqual(expected, actual) 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Worker def test_member_pattern(self): 194*333d2b36SAndroid Build Coastguard Worker self.check_patterns("java/util/zip/ZipFile;-><clinit>()V", 195*333d2b36SAndroid Build Coastguard Worker ["Ljava/util/zip/ZipFile;-><clinit>()V"]) 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Worker def test_class_pattern(self): 198*333d2b36SAndroid Build Coastguard Worker self.check_patterns("java/lang/Object", [ 199*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->hashCode()I", 200*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->toString()Ljava/lang/String;", 201*333d2b36SAndroid Build Coastguard Worker ]) 202*333d2b36SAndroid Build Coastguard Worker 203*333d2b36SAndroid Build Coastguard Worker # pylint: disable=line-too-long 204*333d2b36SAndroid Build Coastguard Worker def test_nested_class_pattern(self): 205*333d2b36SAndroid Build Coastguard Worker self.check_patterns("java/lang/Character", [ 206*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;", 207*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character;->serialVersionUID:J", 208*333d2b36SAndroid Build Coastguard Worker ]) 209*333d2b36SAndroid Build Coastguard Worker 210*333d2b36SAndroid Build Coastguard Worker def test_wildcard(self): 211*333d2b36SAndroid Build Coastguard Worker self.check_patterns("java/lang/*", [ 212*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;", 213*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character;->serialVersionUID:J", 214*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->hashCode()I", 215*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->toString()Ljava/lang/String;", 216*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V", 217*333d2b36SAndroid Build Coastguard Worker ]) 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Worker def test_recursive_wildcard(self): 220*333d2b36SAndroid Build Coastguard Worker self.check_patterns("java/**", [ 221*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;", 222*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character;->serialVersionUID:J", 223*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->hashCode()I", 224*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->toString()Ljava/lang/String;", 225*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V", 226*333d2b36SAndroid Build Coastguard Worker "Ljava/util/zip/ZipFile;-><clinit>()V", 227*333d2b36SAndroid Build Coastguard Worker ]) 228*333d2b36SAndroid Build Coastguard Worker 229*333d2b36SAndroid Build Coastguard Worker def test_node_wildcard(self): 230*333d2b36SAndroid Build Coastguard Worker trie = self.read_trie() 231*333d2b36SAndroid Build Coastguard Worker node = list(trie.child_nodes())[0] 232*333d2b36SAndroid Build Coastguard Worker self.check_node_patterns(node, "**", [ 233*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;", 234*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Character;->serialVersionUID:J", 235*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->hashCode()I", 236*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/Object;->toString()Ljava/lang/String;", 237*333d2b36SAndroid Build Coastguard Worker "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V", 238*333d2b36SAndroid Build Coastguard Worker "Ljava/util/zip/ZipFile;-><clinit>()V", 239*333d2b36SAndroid Build Coastguard Worker ]) 240*333d2b36SAndroid Build Coastguard Worker 241*333d2b36SAndroid Build Coastguard Worker # pylint: enable=line-too-long 242*333d2b36SAndroid Build Coastguard Worker 243*333d2b36SAndroid Build Coastguard Worker 244*333d2b36SAndroid Build Coastguard Workerif __name__ == "__main__": 245*333d2b36SAndroid Build Coastguard Worker unittest.main(verbosity=2) 246