1#!/usr/bin/env python 2# 3# Copyright (C) 2016 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# 17"""Tests for ndkstubgen.py.""" 18import io 19import textwrap 20import unittest 21 22import ndkstubgen 23import symbolfile 24from symbolfile import Arch, Tag 25 26 27# pylint: disable=missing-docstring 28 29 30class GeneratorTest(unittest.TestCase): 31 def test_omit_version(self) -> None: 32 # Thorough testing of the cases involved here is handled by 33 # OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest. 34 src_file = io.StringIO() 35 version_file = io.StringIO() 36 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 37 9, False, False) 38 39 version = symbolfile.Version('VERSION_PRIVATE', None, [], [ 40 symbolfile.Symbol('foo', []), 41 ]) 42 generator.write_version(version) 43 self.assertEqual('', src_file.getvalue()) 44 self.assertEqual('', version_file.getvalue()) 45 46 version = symbolfile.Version('VERSION', None, [Tag('x86')], [ 47 symbolfile.Symbol('foo', []), 48 ]) 49 generator.write_version(version) 50 self.assertEqual('', src_file.getvalue()) 51 self.assertEqual('', version_file.getvalue()) 52 53 version = symbolfile.Version('VERSION', None, [Tag('introduced=14')], [ 54 symbolfile.Symbol('foo', []), 55 ]) 56 generator.write_version(version) 57 self.assertEqual('', src_file.getvalue()) 58 self.assertEqual('', version_file.getvalue()) 59 60 def test_omit_symbol(self) -> None: 61 # Thorough testing of the cases involved here is handled by 62 # SymbolPresenceTest. 63 src_file = io.StringIO() 64 version_file = io.StringIO() 65 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 66 9, False, False) 67 68 version = symbolfile.Version('VERSION_1', None, [], [ 69 symbolfile.Symbol('foo', [Tag('x86')]), 70 ]) 71 generator.write_version(version) 72 self.assertEqual('', src_file.getvalue()) 73 self.assertEqual('', version_file.getvalue()) 74 75 version = symbolfile.Version('VERSION_1', None, [], [ 76 symbolfile.Symbol('foo', [Tag('introduced=14')]), 77 ]) 78 generator.write_version(version) 79 self.assertEqual('', src_file.getvalue()) 80 self.assertEqual('', version_file.getvalue()) 81 82 version = symbolfile.Version('VERSION_1', None, [], [ 83 symbolfile.Symbol('foo', [Tag('llndk')]), 84 ]) 85 generator.write_version(version) 86 self.assertEqual('', src_file.getvalue()) 87 self.assertEqual('', version_file.getvalue()) 88 89 version = symbolfile.Version('VERSION_1', None, [], [ 90 symbolfile.Symbol('foo', [Tag('apex')]), 91 ]) 92 generator.write_version(version) 93 self.assertEqual('', src_file.getvalue()) 94 self.assertEqual('', version_file.getvalue()) 95 96 def test_write(self) -> None: 97 src_file = io.StringIO() 98 version_file = io.StringIO() 99 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 100 9, False, False) 101 102 versions = [ 103 symbolfile.Version('VERSION_1', None, [], [ 104 symbolfile.Symbol('foo', []), 105 symbolfile.Symbol('bar', [Tag('var')]), 106 symbolfile.Symbol('woodly', [Tag('weak')]), 107 symbolfile.Symbol('doodly', 108 [Tag('weak'), Tag('var')]), 109 ]), 110 symbolfile.Version('VERSION_2', 'VERSION_1', [], [ 111 symbolfile.Symbol('baz', []), 112 ]), 113 symbolfile.Version('VERSION_3', 'VERSION_1', [], [ 114 symbolfile.Symbol('qux', [Tag('versioned=14')]), 115 ]), 116 ] 117 118 generator.write(versions) 119 expected_src = textwrap.dedent("""\ 120 void foo() {} 121 int bar = 0; 122 __attribute__((weak)) void woodly() {} 123 __attribute__((weak)) int doodly = 0; 124 void baz() {} 125 void qux() {} 126 """) 127 self.assertEqual(expected_src, src_file.getvalue()) 128 129 expected_version = textwrap.dedent("""\ 130 VERSION_1 { 131 global: 132 foo; 133 bar; 134 woodly; 135 doodly; 136 }; 137 VERSION_2 { 138 global: 139 baz; 140 } VERSION_1; 141 """) 142 self.assertEqual(expected_version, version_file.getvalue()) 143 144 145class IntegrationTest(unittest.TestCase): 146 def test_integration(self) -> None: 147 api_map = { 148 'O': 9000, 149 'P': 9001, 150 } 151 152 input_file = io.StringIO(textwrap.dedent("""\ 153 VERSION_1 { 154 global: 155 foo; # var 156 bar; # x86 157 fizz; # introduced=O 158 buzz; # introduced=P 159 local: 160 *; 161 }; 162 163 VERSION_2 { # arm 164 baz; # introduced=9 165 qux; # versioned=14 166 } VERSION_1; 167 168 VERSION_3 { # introduced=14 169 woodly; 170 doodly; # var 171 } VERSION_2; 172 173 VERSION_4 { # versioned=9 174 wibble; 175 wizzes; # llndk 176 waggle; # apex 177 } VERSION_2; 178 179 VERSION_5 { # versioned=14 180 wobble; 181 } VERSION_4; 182 """)) 183 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), 184 9, False, False) 185 versions = parser.parse() 186 187 src_file = io.StringIO() 188 version_file = io.StringIO() 189 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 190 9, False, False) 191 generator.write(versions) 192 193 expected_src = textwrap.dedent("""\ 194 int foo = 0; 195 void baz() {} 196 void qux() {} 197 void wibble() {} 198 void wobble() {} 199 """) 200 self.assertEqual(expected_src, src_file.getvalue()) 201 202 expected_version = textwrap.dedent("""\ 203 VERSION_1 { 204 global: 205 foo; 206 }; 207 VERSION_2 { 208 global: 209 baz; 210 } VERSION_1; 211 VERSION_4 { 212 global: 213 wibble; 214 } VERSION_2; 215 """) 216 self.assertEqual(expected_version, version_file.getvalue()) 217 218 def test_integration_future_api(self) -> None: 219 api_map = { 220 'O': 9000, 221 'P': 9001, 222 'Q': 9002, 223 } 224 225 input_file = io.StringIO(textwrap.dedent("""\ 226 VERSION_1 { 227 global: 228 foo; # introduced=O 229 bar; # introduced=P 230 baz; # introduced=Q 231 local: 232 *; 233 }; 234 """)) 235 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), 236 9001, False, False) 237 versions = parser.parse() 238 239 src_file = io.StringIO() 240 version_file = io.StringIO() 241 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 242 9001, False, False) 243 generator.write(versions) 244 245 expected_src = textwrap.dedent("""\ 246 void foo() {} 247 void bar() {} 248 """) 249 self.assertEqual(expected_src, src_file.getvalue()) 250 251 expected_version = textwrap.dedent("""\ 252 VERSION_1 { 253 global: 254 foo; 255 bar; 256 }; 257 """) 258 self.assertEqual(expected_version, version_file.getvalue()) 259 260 def test_multiple_definition(self) -> None: 261 input_file = io.StringIO(textwrap.dedent("""\ 262 VERSION_1 { 263 global: 264 foo; 265 foo; 266 bar; 267 baz; 268 qux; # arm 269 local: 270 *; 271 }; 272 273 VERSION_2 { 274 global: 275 bar; 276 qux; # arm64 277 } VERSION_1; 278 279 VERSION_PRIVATE { 280 global: 281 baz; 282 } VERSION_2; 283 284 """)) 285 parser = symbolfile.SymbolFileParser(input_file, {}, Arch('arm'), 16, 286 False, False) 287 288 with self.assertRaises( 289 symbolfile.MultiplyDefinedSymbolError) as ex_context: 290 parser.parse() 291 self.assertEqual(['bar', 'foo'], 292 ex_context.exception.multiply_defined_symbols) 293 294 def test_integration_with_apex(self) -> None: 295 api_map = { 296 'O': 9000, 297 'P': 9001, 298 } 299 300 input_file = io.StringIO(textwrap.dedent("""\ 301 VERSION_1 { 302 global: 303 foo; # var 304 bar; # x86 305 fizz; # introduced=O 306 buzz; # introduced=P 307 local: 308 *; 309 }; 310 311 VERSION_2 { # arm 312 baz; # introduced=9 313 qux; # versioned=14 314 } VERSION_1; 315 316 VERSION_3 { # introduced=14 317 woodly; 318 doodly; # var 319 } VERSION_2; 320 321 VERSION_4 { # versioned=9 322 wibble; 323 wizzes; # llndk 324 waggle; # apex 325 bubble; # apex llndk 326 duddle; # llndk apex 327 } VERSION_2; 328 329 VERSION_5 { # versioned=14 330 wobble; 331 } VERSION_4; 332 """)) 333 parser = symbolfile.SymbolFileParser(input_file, api_map, Arch('arm'), 334 9, False, True) 335 versions = parser.parse() 336 337 src_file = io.StringIO() 338 version_file = io.StringIO() 339 generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'), 340 9, False, True) 341 generator.write(versions) 342 343 expected_src = textwrap.dedent("""\ 344 int foo = 0; 345 void baz() {} 346 void qux() {} 347 void wibble() {} 348 void waggle() {} 349 void bubble() {} 350 void duddle() {} 351 void wobble() {} 352 """) 353 self.assertEqual(expected_src, src_file.getvalue()) 354 355 expected_version = textwrap.dedent("""\ 356 VERSION_1 { 357 global: 358 foo; 359 }; 360 VERSION_2 { 361 global: 362 baz; 363 } VERSION_1; 364 VERSION_4 { 365 global: 366 wibble; 367 waggle; 368 bubble; 369 duddle; 370 } VERSION_2; 371 """) 372 self.assertEqual(expected_version, version_file.getvalue()) 373 374 375def main() -> None: 376 suite = unittest.TestLoader().loadTestsFromName(__name__) 377 unittest.TextTestRunner(verbosity=3).run(suite) 378 379 380if __name__ == '__main__': 381 main() 382