xref: /aosp_15_r20/build/soong/scripts/hiddenapi/signature_patterns_test.py (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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 signature_patterns.py."""
17import io
18import unittest
19
20import signature_patterns
21
22
23class TestGeneratedPatterns(unittest.TestCase):
24
25    csv_flags = """
26Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V,blocked
27Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;,public-api
28Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
29Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
30"""
31
32    @staticmethod
33    def produce_patterns_from_string(csv_text,
34                                     split_packages=None,
35                                     single_packages=None,
36                                     package_prefixes=None):
37        with io.StringIO(csv_text) as f:
38            return signature_patterns.produce_patterns_from_stream(
39                f, split_packages, single_packages, package_prefixes)
40
41    def test_generate_unmatched(self):
42        _, errors = self.produce_patterns_from_string(
43            TestGeneratedPatterns.csv_flags)
44        self.assertEqual([
45            'The following packages were unexpected, please add them to one of '
46            'the hidden_api properties, split_packages, single_packages or '
47            'package_prefixes:\n'
48            '    java.lang'
49        ], errors)
50
51    def test_generate_default(self):
52        patterns, errors = self.produce_patterns_from_string(
53            TestGeneratedPatterns.csv_flags, single_packages=['java/lang'])
54        self.assertEqual([], errors)
55
56        expected = [
57            'java/lang/*',
58        ]
59        self.assertEqual(expected, patterns)
60
61    def test_generate_split_package(self):
62        patterns, errors = self.produce_patterns_from_string(
63            TestGeneratedPatterns.csv_flags, split_packages={'java/lang'})
64        self.assertEqual([], errors)
65
66        expected = [
67            'java/lang/Character',
68            'java/lang/Object',
69            'java/lang/ProcessBuilder',
70        ]
71        self.assertEqual(expected, patterns)
72
73    def test_generate_split_package_wildcard(self):
74        patterns, errors = self.produce_patterns_from_string(
75            TestGeneratedPatterns.csv_flags, split_packages={'*'})
76        self.assertEqual([], errors)
77
78        expected = [
79            'java/lang/Character',
80            'java/lang/Object',
81            'java/lang/ProcessBuilder',
82        ]
83        self.assertEqual(expected, patterns)
84
85    def test_generate_package_prefix(self):
86        patterns, errors = self.produce_patterns_from_string(
87            TestGeneratedPatterns.csv_flags, package_prefixes={'java/lang'})
88        self.assertEqual([], errors)
89
90        expected = [
91            'java/lang/**',
92        ]
93        self.assertEqual(expected, patterns)
94
95    def test_generate_package_prefix_top_package(self):
96        patterns, errors = self.produce_patterns_from_string(
97            TestGeneratedPatterns.csv_flags, package_prefixes={'java'})
98        self.assertEqual([], errors)
99
100        expected = [
101            'java/**',
102        ]
103        self.assertEqual(expected, patterns)
104
105    def test_split_package_wildcard_conflicts_with_other_split_packages(self):
106        errors = signature_patterns.validate_split_packages({'*', 'java'})
107        expected = [
108            'split packages are invalid as they contain both the wildcard (*)'
109            ' and specific packages, use the wildcard or specific packages,'
110            ' not a mixture'
111        ]
112        self.assertEqual(expected, errors)
113
114    def test_split_package_wildcard_conflicts_with_package_prefixes(self):
115        errors = signature_patterns.validate_package_prefixes(
116            {'*'}, [], package_prefixes={'java'})
117        expected = [
118            "split package '*' conflicts with all package prefixes java\n"
119            '    add split_packages:[] to fix',
120        ]
121        self.assertEqual(expected, errors)
122
123    def test_split_package_conflicts_with_package_prefixes(self):
124        errors = signature_patterns.validate_package_prefixes(
125            {'java/split'}, [], package_prefixes={'java'})
126        expected = [
127            'split package java.split is matched by package prefix java',
128        ]
129        self.assertEqual(expected, errors)
130
131    def test_single_package_conflicts_with_package_prefixes(self):
132        errors = signature_patterns.validate_package_prefixes(
133            {}, ['java/single'], package_prefixes={'java'})
134        expected = [
135            'single package java.single is matched by package prefix java',
136        ]
137        self.assertEqual(expected, errors)
138
139    def test_single_package_conflicts_with_split_packages(self):
140        errors = signature_patterns.validate_single_packages({'java/pkg'},
141                                                             ['java/pkg'])
142        expected = [
143            'single_packages and split_packages overlap, please ensure the '
144            'following packages are only present in one:\n    java/pkg'
145        ]
146        self.assertEqual(expected, errors)
147
148
149if __name__ == '__main__':
150    unittest.main(verbosity=2)
151