verify_overlaps_test.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. #!/usr/bin/env python
  2. #
  3. # Copyright (C) 2021 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."""
  17. import io
  18. import unittest
  19. import verify_overlaps as vo
  20. class TestDetectOverlaps(unittest.TestCase):
  21. @staticmethod
  22. def read_flag_trie_from_string(csvdata):
  23. with io.StringIO(csvdata) as f:
  24. return vo.read_flag_trie_from_stream(f)
  25. @staticmethod
  26. def read_signature_csv_from_string_as_dict(csvdata):
  27. with io.StringIO(csvdata) as f:
  28. return vo.read_signature_csv_from_stream_as_dict(f)
  29. @staticmethod
  30. def extract_subset_from_monolithic_flags_as_dict_from_string(
  31. monolithic, patterns):
  32. with io.StringIO(patterns) as f:
  33. return vo.extract_subset_from_monolithic_flags_as_dict_from_stream(
  34. monolithic, f)
  35. extractInput = """
  36. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  37. Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
  38. Ljava/util/zip/ZipFile;-><clinit>()V,blocked
  39. Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;,blocked
  40. Ljava/lang/Character;->serialVersionUID:J,sdk
  41. Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V,blocked
  42. """
  43. def test_extract_subset_signature(self):
  44. monolithic = self.read_flag_trie_from_string(
  45. TestDetectOverlaps.extractInput)
  46. patterns = "Ljava/lang/Object;->hashCode()I"
  47. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  48. monolithic, patterns)
  49. expected = {
  50. "Ljava/lang/Object;->hashCode()I": {
  51. None: ["public-api", "system-api", "test-api"],
  52. "signature": "Ljava/lang/Object;->hashCode()I",
  53. },
  54. }
  55. self.assertEqual(expected, subset)
  56. def test_extract_subset_class(self):
  57. monolithic = self.read_flag_trie_from_string(
  58. TestDetectOverlaps.extractInput)
  59. patterns = "java/lang/Object"
  60. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  61. monolithic, patterns)
  62. expected = {
  63. "Ljava/lang/Object;->hashCode()I": {
  64. None: ["public-api", "system-api", "test-api"],
  65. "signature": "Ljava/lang/Object;->hashCode()I",
  66. },
  67. "Ljava/lang/Object;->toString()Ljava/lang/String;": {
  68. None: ["blocked"],
  69. "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
  70. },
  71. }
  72. self.assertEqual(expected, subset)
  73. def test_extract_subset_outer_class(self):
  74. monolithic = self.read_flag_trie_from_string(
  75. TestDetectOverlaps.extractInput)
  76. patterns = "java/lang/Character"
  77. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  78. monolithic, patterns)
  79. expected = {
  80. "Ljava/lang/Character$UnicodeScript;"
  81. "->of(I)Ljava/lang/Character$UnicodeScript;": {
  82. None: ["blocked"],
  83. "signature": "Ljava/lang/Character$UnicodeScript;"
  84. "->of(I)Ljava/lang/Character$UnicodeScript;",
  85. },
  86. "Ljava/lang/Character;->serialVersionUID:J": {
  87. None: ["sdk"],
  88. "signature": "Ljava/lang/Character;->serialVersionUID:J",
  89. },
  90. }
  91. self.assertEqual(expected, subset)
  92. def test_extract_subset_nested_class(self):
  93. monolithic = self.read_flag_trie_from_string(
  94. TestDetectOverlaps.extractInput)
  95. patterns = "java/lang/Character$UnicodeScript"
  96. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  97. monolithic, patterns)
  98. expected = {
  99. "Ljava/lang/Character$UnicodeScript;"
  100. "->of(I)Ljava/lang/Character$UnicodeScript;": {
  101. None: ["blocked"],
  102. "signature": "Ljava/lang/Character$UnicodeScript;"
  103. "->of(I)Ljava/lang/Character$UnicodeScript;",
  104. },
  105. }
  106. self.assertEqual(expected, subset)
  107. def test_extract_subset_package(self):
  108. monolithic = self.read_flag_trie_from_string(
  109. TestDetectOverlaps.extractInput)
  110. patterns = "java/lang/*"
  111. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  112. monolithic, patterns)
  113. expected = {
  114. "Ljava/lang/Character$UnicodeScript;"
  115. "->of(I)Ljava/lang/Character$UnicodeScript;": {
  116. None: ["blocked"],
  117. "signature": "Ljava/lang/Character$UnicodeScript;"
  118. "->of(I)Ljava/lang/Character$UnicodeScript;",
  119. },
  120. "Ljava/lang/Character;->serialVersionUID:J": {
  121. None: ["sdk"],
  122. "signature": "Ljava/lang/Character;->serialVersionUID:J",
  123. },
  124. "Ljava/lang/Object;->hashCode()I": {
  125. None: ["public-api", "system-api", "test-api"],
  126. "signature": "Ljava/lang/Object;->hashCode()I",
  127. },
  128. "Ljava/lang/Object;->toString()Ljava/lang/String;": {
  129. None: ["blocked"],
  130. "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
  131. },
  132. "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V": {
  133. None: ["blocked"],
  134. "signature": "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
  135. },
  136. }
  137. self.assertEqual(expected, subset)
  138. def test_extract_subset_recursive_package(self):
  139. monolithic = self.read_flag_trie_from_string(
  140. TestDetectOverlaps.extractInput)
  141. patterns = "java/**"
  142. subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(
  143. monolithic, patterns)
  144. expected = {
  145. "Ljava/lang/Character$UnicodeScript;"
  146. "->of(I)Ljava/lang/Character$UnicodeScript;": {
  147. None: ["blocked"],
  148. "signature": "Ljava/lang/Character$UnicodeScript;"
  149. "->of(I)Ljava/lang/Character$UnicodeScript;",
  150. },
  151. "Ljava/lang/Character;->serialVersionUID:J": {
  152. None: ["sdk"],
  153. "signature": "Ljava/lang/Character;->serialVersionUID:J",
  154. },
  155. "Ljava/lang/Object;->hashCode()I": {
  156. None: ["public-api", "system-api", "test-api"],
  157. "signature": "Ljava/lang/Object;->hashCode()I",
  158. },
  159. "Ljava/lang/Object;->toString()Ljava/lang/String;": {
  160. None: ["blocked"],
  161. "signature": "Ljava/lang/Object;->toString()Ljava/lang/String;",
  162. },
  163. "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V": {
  164. None: ["blocked"],
  165. "signature": "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V",
  166. },
  167. "Ljava/util/zip/ZipFile;-><clinit>()V": {
  168. None: ["blocked"],
  169. "signature": "Ljava/util/zip/ZipFile;-><clinit>()V",
  170. },
  171. }
  172. self.assertEqual(expected, subset)
  173. def test_read_trie_duplicate(self):
  174. with self.assertRaises(Exception) as context:
  175. self.read_flag_trie_from_string("""
  176. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  177. Ljava/lang/Object;->hashCode()I,blocked
  178. """)
  179. self.assertTrue("Duplicate signature: Ljava/lang/Object;->hashCode()I"
  180. in str(context.exception))
  181. def test_read_trie_missing_member(self):
  182. with self.assertRaises(Exception) as context:
  183. self.read_flag_trie_from_string("""
  184. Ljava/lang/Object,public-api,system-api,test-api
  185. """)
  186. self.assertTrue(
  187. "Invalid signature: Ljava/lang/Object, "
  188. "does not identify a specific member" in str(context.exception))
  189. def test_match(self):
  190. monolithic = self.read_signature_csv_from_string_as_dict("""
  191. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  192. """)
  193. modular = self.read_signature_csv_from_string_as_dict("""
  194. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  195. """)
  196. mismatches = vo.compare_signature_flags(monolithic, modular,
  197. ["blocked"])
  198. expected = []
  199. self.assertEqual(expected, mismatches)
  200. def test_mismatch_overlapping_flags(self):
  201. monolithic = self.read_signature_csv_from_string_as_dict("""
  202. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api
  203. """)
  204. modular = self.read_signature_csv_from_string_as_dict("""
  205. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
  206. """)
  207. mismatches = vo.compare_signature_flags(monolithic, modular,
  208. ["blocked"])
  209. expected = [
  210. (
  211. "Ljava/lang/Object;->toString()Ljava/lang/String;",
  212. ["public-api", "system-api", "test-api"],
  213. ["public-api"],
  214. ),
  215. ]
  216. self.assertEqual(expected, mismatches)
  217. def test_mismatch_monolithic_blocked(self):
  218. monolithic = self.read_signature_csv_from_string_as_dict("""
  219. Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
  220. """)
  221. modular = self.read_signature_csv_from_string_as_dict("""
  222. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
  223. """)
  224. mismatches = vo.compare_signature_flags(monolithic, modular,
  225. ["blocked"])
  226. expected = [
  227. (
  228. "Ljava/lang/Object;->toString()Ljava/lang/String;",
  229. ["public-api", "system-api", "test-api"],
  230. ["blocked"],
  231. ),
  232. ]
  233. self.assertEqual(expected, mismatches)
  234. def test_mismatch_modular_blocked(self):
  235. monolithic = self.read_signature_csv_from_string_as_dict("""
  236. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
  237. """)
  238. modular = self.read_signature_csv_from_string_as_dict("""
  239. Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
  240. """)
  241. mismatches = vo.compare_signature_flags(monolithic, modular,
  242. ["blocked"])
  243. expected = [
  244. (
  245. "Ljava/lang/Object;->toString()Ljava/lang/String;",
  246. ["blocked"],
  247. ["public-api", "system-api", "test-api"],
  248. ),
  249. ]
  250. self.assertEqual(expected, mismatches)
  251. def test_match_treat_missing_from_modular_as_blocked(self):
  252. monolithic = self.read_signature_csv_from_string_as_dict("")
  253. modular = self.read_signature_csv_from_string_as_dict("""
  254. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
  255. """)
  256. mismatches = vo.compare_signature_flags(monolithic, modular,
  257. ["blocked"])
  258. expected = [
  259. (
  260. "Ljava/lang/Object;->toString()Ljava/lang/String;",
  261. ["public-api", "system-api", "test-api"],
  262. [],
  263. ),
  264. ]
  265. self.assertEqual(expected, mismatches)
  266. def test_mismatch_treat_missing_from_modular_as_blocked(self):
  267. monolithic = self.read_signature_csv_from_string_as_dict("""
  268. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  269. """)
  270. modular = {}
  271. mismatches = vo.compare_signature_flags(monolithic, modular,
  272. ["blocked"])
  273. expected = [
  274. (
  275. "Ljava/lang/Object;->hashCode()I",
  276. ["blocked"],
  277. ["public-api", "system-api", "test-api"],
  278. ),
  279. ]
  280. self.assertEqual(expected, mismatches)
  281. def test_blocked_missing_from_modular(self):
  282. monolithic = self.read_signature_csv_from_string_as_dict("""
  283. Ljava/lang/Object;->hashCode()I,blocked
  284. """)
  285. modular = {}
  286. mismatches = vo.compare_signature_flags(monolithic, modular,
  287. ["blocked"])
  288. expected = []
  289. self.assertEqual(expected, mismatches)
  290. def test_match_treat_missing_from_modular_as_empty(self):
  291. monolithic = self.read_signature_csv_from_string_as_dict("")
  292. modular = self.read_signature_csv_from_string_as_dict("""
  293. Ljava/lang/Object;->toString()Ljava/lang/String;,public-api,system-api,test-api
  294. """)
  295. mismatches = vo.compare_signature_flags(monolithic, modular, [])
  296. expected = [
  297. (
  298. "Ljava/lang/Object;->toString()Ljava/lang/String;",
  299. ["public-api", "system-api", "test-api"],
  300. [],
  301. ),
  302. ]
  303. self.assertEqual(expected, mismatches)
  304. def test_mismatch_treat_missing_from_modular_as_empty(self):
  305. monolithic = self.read_signature_csv_from_string_as_dict("""
  306. Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
  307. """)
  308. modular = {}
  309. mismatches = vo.compare_signature_flags(monolithic, modular, [])
  310. expected = [
  311. (
  312. "Ljava/lang/Object;->hashCode()I",
  313. [],
  314. ["public-api", "system-api", "test-api"],
  315. ),
  316. ]
  317. self.assertEqual(expected, mismatches)
  318. def test_empty_missing_from_modular(self):
  319. monolithic = self.read_signature_csv_from_string_as_dict("""
  320. Ljava/lang/Object;->hashCode()I
  321. """)
  322. modular = {}
  323. mismatches = vo.compare_signature_flags(monolithic, modular, [])
  324. expected = []
  325. self.assertEqual(expected, mismatches)
  326. if __name__ == "__main__":
  327. unittest.main(verbosity=2)