xref: /aosp_15_r20/development/vndk/tools/header-checker/tests/test.py (revision 90c8c64db3049935a07c6143d7fd006e26f8ecca)
1#!/usr/bin/env python3
2
3import os
4import shutil
5import stat
6import subprocess
7import sys
8import tempfile
9import unittest
10
11import_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
12import_path = os.path.abspath(os.path.join(import_path, 'utils'))
13sys.path.insert(1, import_path)
14
15from utils import (run_abi_diff, run_and_read_abi_diff, run_header_abi_dumper,
16                   run_header_abi_linker)
17from module import Module
18
19
20SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
21INPUT_DIR = os.path.join(SCRIPT_DIR, 'input')
22EXPECTED_DIR = os.path.join(SCRIPT_DIR, 'expected')
23EXPORTED_HEADER_DIRS = (INPUT_DIR,)
24REF_DUMP_DIR = os.path.join(SCRIPT_DIR, 'reference_dumps')
25
26
27def make_and_copy_dump(module, dump_dir):
28    dump_dir = os.path.join(dump_dir, module.arch)
29    os.makedirs(dump_dir, exist_ok=True)
30    dump_path = os.path.join(dump_dir, module.get_dump_name())
31    module.make_dump(dump_path)
32    return dump_path
33
34
35def _read_output_content(dump_path):
36    with open(dump_path, 'r') as f:
37        return f.read()
38
39
40class HeaderCheckerTest(unittest.TestCase):
41    @classmethod
42    def setUpClass(cls):
43        cls.maxDiff = None
44
45    def setUp(self):
46        self.tmp_dir = None
47
48    def tearDown(self):
49        if self.tmp_dir:
50            self.tmp_dir.cleanup()
51            self.tmp_dir = None
52
53    def get_tmp_dir(self):
54        if not self.tmp_dir:
55            self.tmp_dir = tempfile.TemporaryDirectory()
56        return self.tmp_dir.name
57
58    def run_and_compare(self, input_path, expected_path, cflags=[]):
59        with open(expected_path, 'r') as f:
60            expected_output = f.read()
61        with tempfile.NamedTemporaryFile(dir=self.get_tmp_dir(),
62                                         delete=False) as f:
63            output_path = f.name
64        run_header_abi_dumper(input_path, output_path, cflags,
65                              EXPORTED_HEADER_DIRS)
66        actual_output = _read_output_content(output_path)
67        self.assertEqual(actual_output, expected_output)
68
69    def run_and_compare_name(self, name, cflags=[]):
70        input_path = os.path.join(INPUT_DIR, name)
71        expected_path = os.path.join(EXPECTED_DIR, name)
72        self.run_and_compare(input_path, expected_path, cflags)
73
74    def run_and_compare_name_cpp(self, name, cflags=[]):
75        self.run_and_compare_name(name, cflags + ['-x', 'c++', '-std=c++11'])
76
77    def run_and_compare_name_c_cpp(self, name, cflags=[]):
78        self.run_and_compare_name(name, cflags)
79        self.run_and_compare_name_cpp(name, cflags)
80
81    def run_and_compare_abi_diff(self, old_dump, new_dump, lib, arch,
82                                 expected_return_code, flags=[]):
83        return_code, output = run_and_read_abi_diff(
84            old_dump, new_dump, arch, lib, flags)
85        self.assertEqual(return_code, expected_return_code)
86        return output
87
88    def prepare_and_run_abi_diff(self, old_ref_dump_path, new_ref_dump_path,
89                                 target_arch, expected_return_code, flags=[]):
90        return self.run_and_compare_abi_diff(
91            old_ref_dump_path, new_ref_dump_path, 'test', target_arch,
92            expected_return_code, flags)
93
94    def get_or_create_dump(self, module, create):
95        if create:
96            return make_and_copy_dump(module, self.get_tmp_dir())
97        self.assertTrue(module.has_reference_dump,
98                        f'Module {module.name} is not configured to generate '
99                        f'reference dump.')
100        return os.path.join(REF_DUMP_DIR, module.arch, module.get_dump_name())
101
102    def prepare_and_run_abi_diff_all_archs(self, old_lib, new_lib,
103                                           expected_return_code, flags=[],
104                                           create_old=False, create_new=True):
105        old_modules = Module.get_test_modules_by_name(old_lib)
106        new_modules = Module.get_test_modules_by_name(new_lib)
107        self.assertEqual(len(old_modules), len(new_modules))
108        self.assertTrue(len(old_modules))
109
110        for old_module, new_module in zip(old_modules, new_modules):
111            self.assertEqual(old_module.arch, new_module.arch)
112            old_dump_path = self.get_or_create_dump(old_module, create_old)
113            new_dump_path = self.get_or_create_dump(new_module, create_new)
114            output = self.prepare_and_run_abi_diff(
115                old_dump_path, new_dump_path, new_module.arch,
116                expected_return_code, flags)
117        # Since most test cases are independent of architecture, verifying one
118        # of the reports is sufficient.
119        return output
120
121    def prepare_and_absolute_diff_all_archs(self, old_lib, new_lib):
122        old_modules = Module.get_test_modules_by_name(old_lib)
123        new_modules = Module.get_test_modules_by_name(new_lib)
124        self.assertEqual(len(old_modules), len(new_modules))
125
126        for old_module, new_module in zip(old_modules, new_modules):
127            self.assertEqual(old_module.arch, new_module.arch)
128            old_dump_path = self.get_or_create_dump(old_module, False)
129            new_dump_path = self.get_or_create_dump(new_module, True)
130            self.assertEqual(_read_output_content(old_dump_path),
131                             _read_output_content(new_dump_path))
132
133    def test_example1_cpp(self):
134        self.run_and_compare_name_cpp('example1.cpp')
135
136    def test_example1_h(self):
137        self.run_and_compare_name_cpp('example1.h')
138
139    def test_example2_h(self):
140        self.run_and_compare_name_cpp('example2.h')
141
142    def test_example3_h(self):
143        self.run_and_compare_name_cpp('example3.h')
144
145    def test_libc_and_cpp(self):
146        self.prepare_and_run_abi_diff_all_archs(
147            "libc_and_cpp", "libc_and_cpp", 0)
148
149    def test_libc_and_cpp_and_libc_and_cpp_with_unused_struct(self):
150        self.prepare_and_run_abi_diff_all_archs(
151            "libc_and_cpp", "libc_and_cpp_with_unused_struct", 0)
152
153    def test_libc_and_cpp_and_libc_and_cpp_with_unused_struct_allow(self):
154        self.prepare_and_run_abi_diff_all_archs(
155            "libc_and_cpp", "libc_and_cpp_with_unused_struct", 0,
156            ["-allow-unreferenced-changes"])
157
158    def test_libc_and_cpp_and_libc_and_cpp_with_unused_struct_check_all(self):
159        self.prepare_and_run_abi_diff_all_archs(
160            "libc_and_cpp", "libc_and_cpp_with_unused_struct", 1,
161            ["-check-all-apis"])
162        self.prepare_and_run_abi_diff_all_archs(
163            "libc_and_cpp", "libc_and_cpp_with_unused_struct", 0,
164            ["-check-all-apis",
165             "-ignore-linker-set-key", "_ZTI12UnusedStruct"])
166
167    def test_libc_and_cpp_with_unused_struct_and_libc_and_cpp_with_unused_cstruct(
168            self):
169        self.prepare_and_run_abi_diff_all_archs(
170            "libc_and_cpp_with_unused_struct",
171            "libc_and_cpp_with_unused_cstruct", 0,
172            ['-check-all-apis', '-allow-unreferenced-changes'])
173
174    def test_libc_and_cpp_and_libc_and_cpp_with_unused_struct_check_all_advice(
175            self):
176        self.prepare_and_run_abi_diff_all_archs(
177            "libc_and_cpp", "libc_and_cpp_with_unused_struct", 0,
178            ['-check-all-apis', '-advice-only'])
179
180    def test_libc_and_cpp_opaque_pointer_diff(self):
181        self.prepare_and_run_abi_diff_all_archs(
182            "libc_and_cpp_with_opaque_ptr_a",
183            "libc_and_cpp_with_opaque_ptr_b", 8,
184            ['-consider-opaque-types-different'], True, True)
185
186    def test_libgolden_cpp_return_type_diff(self):
187        self.prepare_and_run_abi_diff_all_archs(
188            "libgolden_cpp", "libgolden_cpp_return_type_diff", 8)
189        self.prepare_and_run_abi_diff_all_archs(
190            "libgolden_cpp", "libgolden_cpp_return_type_diff", 0,
191            ["-ignore-linker-set-key", "_ZN17HighVolumeSpeaker6ListenEv",
192             "-ignore-linker-set-key", "_ZN16LowVolumeSpeaker6ListenEv"])
193
194    def test_libgolden_cpp_add_odr(self):
195        self.prepare_and_run_abi_diff_all_archs(
196            "libgolden_cpp", "libgolden_cpp_odr", 0,
197            ['-check-all-apis', '-allow-unreferenced-changes'])
198
199    def test_libgolden_cpp_add_function(self):
200        self.prepare_and_run_abi_diff_all_archs(
201            "libgolden_cpp", "libgolden_cpp_add_function", 6)
202
203    def test_libgolden_cpp_add_function_allow_extension(self):
204        self.prepare_and_run_abi_diff_all_archs(
205            "libgolden_cpp", "libgolden_cpp_add_function", 0,
206            ['-allow-extensions'])
207
208    def test_libgolden_cpp_add_function_and_elf_symbol(self):
209        self.prepare_and_run_abi_diff_all_archs(
210            "libgolden_cpp", "libgolden_cpp_add_function_and_unexported_elf",
211            6)
212
213    def test_libgolden_cpp_fabricated_function_ast_removed_diff(self):
214        self.prepare_and_run_abi_diff_all_archs(
215            "libgolden_cpp_add_function_sybmol_only",
216            "libgolden_cpp_add_function", 0, [], False, False)
217
218    def test_libgolden_cpp_change_function_access(self):
219        self.prepare_and_run_abi_diff_all_archs(
220            "libgolden_cpp", "libgolden_cpp_change_function_access", 8)
221
222    def test_libgolden_cpp_add_global_variable(self):
223        self.prepare_and_run_abi_diff_all_archs(
224            "libgolden_cpp", "libgolden_cpp_add_global_variable", 6)
225
226    def test_libgolden_cpp_change_global_var_access(self):
227        self.prepare_and_run_abi_diff_all_archs(
228            "libgolden_cpp_add_global_variable",
229            "libgolden_cpp_add_global_variable_private", 8)
230
231    def test_libgolden_cpp_parameter_type_diff(self):
232        self.prepare_and_run_abi_diff_all_archs(
233            "libgolden_cpp", "libgolden_cpp_parameter_type_diff", 8)
234
235    def test_libgolden_cpp_with_vtable_diff(self):
236        self.prepare_and_run_abi_diff_all_archs(
237            "libgolden_cpp", "libgolden_cpp_vtable_diff", 8)
238
239    def test_libgolden_cpp_member_diff_advice_only(self):
240        self.prepare_and_run_abi_diff_all_archs(
241            "libgolden_cpp", "libgolden_cpp_member_diff", 0, ['-advice-only'])
242
243    def test_libgolden_cpp_member_diff(self):
244        self.prepare_and_run_abi_diff_all_archs(
245            "libgolden_cpp", "libgolden_cpp_member_diff", 8)
246        self.prepare_and_run_abi_diff_all_archs(
247            "libgolden_cpp", "libgolden_cpp_member_diff", 0,
248            ["-ignore-linker-set-key", "_ZTI16LowVolumeSpeaker"])
249
250    def test_libgolden_cpp_change_member_access(self):
251        self.prepare_and_run_abi_diff_all_archs(
252            "libgolden_cpp", "libgolden_cpp_change_member_access", 8)
253
254    def test_libgolden_cpp_enum_extended(self):
255        self.prepare_and_run_abi_diff_all_archs(
256            "libgolden_cpp", "libgolden_cpp_enum_extended", 4)
257
258    def test_libgolden_cpp_enum_diff(self):
259        self.prepare_and_run_abi_diff_all_archs(
260            "libgolden_cpp", "libgolden_cpp_enum_diff", 8)
261        self.prepare_and_run_abi_diff_all_archs(
262            "libgolden_cpp", "libgolden_cpp_enum_diff", 0,
263            ["-ignore-linker-set-key", "_ZTIN12SuperSpeaker6VolumeE"])
264
265    def test_libgolden_cpp_member_fake_diff(self):
266        self.prepare_and_run_abi_diff_all_archs(
267            "libgolden_cpp", "libgolden_cpp_member_fake_diff", 0)
268
269    def test_libgolden_cpp_member_integral_type_diff(self):
270        self.prepare_and_run_abi_diff_all_archs(
271            "libgolden_cpp", "libgolden_cpp_member_integral_type_diff", 8)
272
273    def test_libgolden_cpp_member_cv_diff(self):
274        self.prepare_and_run_abi_diff_all_archs(
275            "libgolden_cpp", "libgolden_cpp_member_cv_diff", 8)
276
277    def test_libgolden_cpp_unreferenced_elf_symbol_removed(self):
278        self.prepare_and_run_abi_diff_all_archs(
279            "libgolden_cpp", "libgolden_cpp_unreferenced_elf_symbol_removed",
280            16)
281
282    def test_libgolden_cpp_unreferenced_elf_symbol_added(self):
283        self.prepare_and_run_abi_diff_all_archs(
284            "libgolden_cpp_unreferenced_elf_symbol_removed", "libgolden_cpp",
285            2, create_old=True, create_new=False)
286
287    def test_libreproducability(self):
288        self.prepare_and_absolute_diff_all_archs(
289            "libreproducability", "libreproducability")
290
291    def test_libgolden_cpp_member_name_changed(self):
292        self.prepare_and_run_abi_diff_all_archs(
293            "libgolden_cpp", "libgolden_cpp_member_name_changed", 0)
294
295    def test_libgolden_cpp_member_function_pointer_changed(self):
296        self.prepare_and_run_abi_diff_all_archs(
297            "libgolden_cpp_function_pointer",
298            "libgolden_cpp_function_pointer_parameter_added", 8, [],
299            True, True)
300
301    def test_libgolden_cpp_internal_struct_access_upgraded(self):
302        self.prepare_and_run_abi_diff_all_archs(
303            "libgolden_cpp_internal_private_struct",
304            "libgolden_cpp_internal_public_struct", 4, [], True, True)
305
306    def test_libgolden_cpp_internal_struct_access_downgraded(self):
307        self.prepare_and_run_abi_diff_all_archs(
308            "libgolden_cpp_internal_public_struct",
309            "libgolden_cpp_internal_private_struct", 8, [], True, True)
310
311    def test_libgolden_cpp_inheritance_type_changed(self):
312        self.prepare_and_run_abi_diff_all_archs(
313            "libgolden_cpp", "libgolden_cpp_inheritance_type_changed", 8, [],
314            True, True)
315
316    def test_libpure_virtual_function(self):
317        self.prepare_and_absolute_diff_all_archs(
318            "libpure_virtual_function", "libpure_virtual_function")
319
320    def test_libc_and_cpp_in_json(self):
321        self.prepare_and_absolute_diff_all_archs(
322            "libgolden_cpp_json", "libgolden_cpp_json")
323
324    def test_libc_and_cpp_in_protobuf_and_json(self):
325        self.prepare_and_run_abi_diff_all_archs(
326            "libgolden_cpp", "libgolden_cpp_json", 0,
327            ["-input-format-old", "ProtobufTextFormat",
328             "-input-format-new", "Json"])
329
330    def test_opaque_type_self_diff(self):
331        self.prepare_and_run_abi_diff_all_archs(
332            "libopaque_type", "libopaque_type", 0,
333            ["-input-format-old", "Json", "-input-format-new", "Json",
334             "-consider-opaque-types-different"],
335            create_old=False, create_new=False)
336
337    def test_allow_adding_removing_weak_symbols(self):
338        module_old = Module.get_test_modules_by_name("libweak_symbols_old")[0]
339        module_new = Module.get_test_modules_by_name("libweak_symbols_new")[0]
340        lsdump_old = self.get_or_create_dump(module_old, False)
341        lsdump_new = self.get_or_create_dump(module_new, False)
342
343        options = ["-input-format-old", "Json", "-input-format-new", "Json"]
344
345        # If `-allow-adding-removing-weak-symbols` is not specified, removing a
346        # weak symbol must be treated as an incompatible change.
347        self.run_and_compare_abi_diff(
348            lsdump_old, lsdump_new, "libweak_symbols", "arm64", 8, options)
349
350        # If `-allow-adding-removing-weak-symbols` is specified, removing a
351        # weak symbol must be fine and mustn't be a fatal error.
352        self.run_and_compare_abi_diff(
353            lsdump_old, lsdump_new, "libweak_symbols", "arm64", 0,
354            options + ["-allow-adding-removing-weak-symbols"])
355
356    def test_linker_shared_object_file_and_version_script(self):
357        base_dir = os.path.join(
358            SCRIPT_DIR, 'integration', 'version_script_example')
359
360        cases = [
361            'libversion_script_example',
362            'libversion_script_example_no_mytag',
363            'libversion_script_example_no_private',
364            'libversion_script_example_api_level',
365        ]
366
367        for module_name in cases:
368            module = Module.get_test_modules_by_name(module_name)[0]
369            example_lsdump_old = self.get_or_create_dump(module, False)
370            example_lsdump_new = self.get_or_create_dump(module, True)
371            self.run_and_compare_abi_diff(
372                example_lsdump_old, example_lsdump_new,
373                module_name, "arm64", 0,
374                ["-input-format-old", "Json", "-input-format-new", "Json"])
375
376    def test_no_source(self):
377        self.prepare_and_run_abi_diff_all_archs(
378            "libempty", "libempty", 0,
379            ["-input-format-old", "Json", "-input-format-new", "Json"])
380
381    def test_golden_anonymous_enum(self):
382        self.prepare_and_absolute_diff_all_archs(
383            "libgolden_anonymous_enum", "libgolden_anonymous_enum")
384
385    def test_swap_anonymous_enum(self):
386        self.prepare_and_run_abi_diff_all_archs(
387            "libgolden_anonymous_enum", "libswap_anonymous_enum", 0,
388            ["-input-format-old", "Json", "-input-format-new", "Json",
389             "-check-all-apis"])
390
391    def test_swap_anonymous_enum_field(self):
392        self.prepare_and_run_abi_diff_all_archs(
393            "libgolden_anonymous_enum", "libswap_anonymous_enum_field", 0,
394            ["-input-format-old", "Json", "-input-format-new", "Json",
395             "-check-all-apis"])
396
397    def test_anonymous_enum_odr(self):
398        self.prepare_and_absolute_diff_all_archs(
399            "libanonymous_enum_odr", "libanonymous_enum_odr")
400
401    def test_libifunc(self):
402        self.prepare_and_absolute_diff_all_archs(
403            "libifunc", "libifunc")
404
405    def test_merge_multi_definitions(self):
406        self.prepare_and_absolute_diff_all_archs(
407            "libmerge_multi_definitions", "libmerge_multi_definitions")
408        self.prepare_and_run_abi_diff_all_archs(
409            "libmerge_multi_definitions", "libdiff_multi_definitions", 0,
410            flags=["-input-format-new", "Json", "-input-format-old", "Json",
411                   "-consider-opaque-types-different"],
412            create_old=False, create_new=False)
413
414    def test_print_resource_dir(self):
415        dumper_path = shutil.which("header-abi-dumper")
416        self.assertIsNotNone(dumper_path)
417        dumper_path = os.path.realpath(dumper_path)
418        common_dir = os.path.dirname(os.path.dirname(dumper_path))
419        resource_dir = subprocess.check_output(
420            ["header-abi-dumper", "-print-resource-dir"], text=True,
421            stderr=subprocess.DEVNULL).strip()
422        self.assertIn(os.path.dirname(resource_dir),
423                      (os.path.join(common_dir, "lib64", "clang"),
424                       os.path.join(common_dir, "lib", "clang")))
425        self.assertRegex(os.path.basename(resource_dir), r"^[\d.]+$")
426
427    def test_struct_extensions(self):
428        output = self.prepare_and_run_abi_diff_all_archs(
429            "libstruct_extensions", "liballowed_struct_extensions", 4,
430            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
431            create_old=False, create_new=False)
432        self.assertEqual(output.count("record_type_extension_diffs"), 6)
433
434        output = self.prepare_and_run_abi_diff_all_archs(
435            "liballowed_struct_extensions", "libstruct_extensions", 8,
436            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
437            create_old=False, create_new=False)
438        self.assertEqual(output.count("record_type_diffs"), 6)
439
440    def test_param_size_diff(self):
441        self.prepare_and_run_abi_diff_all_archs(
442            "libpass_by_value", "libparam_size_diff", 8,
443            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
444            create_old=False, create_new=False)
445
446    def test_return_size_diff(self):
447        self.prepare_and_run_abi_diff_all_archs(
448            "libpass_by_value", "libreturn_size_diff", 8,
449            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
450            create_old=False, create_new=False)
451
452    def test_function_extensions(self):
453        diff = self.prepare_and_run_abi_diff_all_archs(
454            "libfunction_extensions", "liballowed_function_extensions", 4,
455            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
456            create_old=False, create_new=False)
457        self.assertEqual(6, diff.count('function_extension_diffs'))
458
459        diff = self.prepare_and_run_abi_diff_all_archs(
460            "liballowed_function_extensions", "libfunction_extensions", 8,
461            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
462            create_old=False, create_new=False)
463        # Adding and removing __restrict__ at the first level are extensions.
464        self.assertEqual(1, diff.count('function_extension_diffs'))
465        self.assertEqual(5, diff.count('function_diffs'))
466
467    def test_array_diff(self):
468        self.prepare_and_absolute_diff_all_archs("libarray", "libarray")
469        self.prepare_and_absolute_diff_all_archs(
470            "libarray_diff", "libarray_diff")
471        diff = self.prepare_and_run_abi_diff_all_archs(
472            "libarray", "libarray_diff", 8,
473            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
474            create_old=False, create_new=False)
475
476        for type_id in ["StructMember", "Pointer", "DoublePointer"]:
477            self.assertNotIn(f'"{type_id}"', diff,
478                             f'"{type_id}" should not be in the diff report.')
479
480        for type_id in ["Struct", "PointerToArray", "PointerTo2DArray",
481                        "Reference", "Element"]:
482            self.assertIn(f'"{type_id}"', diff,
483                          f'"{type_id}" should be in the diff report.')
484
485    def test_union_diff(self):
486        diff = self.prepare_and_run_abi_diff_all_archs(
487            "libunion", "libunion_diff", 8,
488            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
489            create_old=False, create_new=True)
490        self.assertIn('"ChangeType"', diff)
491        self.assertIn('"ChangeTypeInStruct"', diff)
492        self.assertEqual(2, diff.count("fields_diff"))
493        self.assertNotIn("fields_added", diff)
494        self.assertNotIn("fields_removed", diff)
495
496    def test_enum_diff(self):
497        self.prepare_and_absolute_diff_all_archs("libenum", "libenum")
498
499    def test_io_error(self):
500        cpp_path = os.path.join(self.get_tmp_dir(), "test.cpp")
501        sdump_path = os.path.join(self.get_tmp_dir(), "test.sdump")
502        version_script_path = os.path.join(self.get_tmp_dir(), "map.txt")
503        lsdump_path = os.path.join(self.get_tmp_dir(), "test.lsdump")
504        abidiff_path = os.path.join(self.get_tmp_dir(), "test.abidiff")
505        read_only_path = os.path.join(self.get_tmp_dir(), "read_only.txt")
506
507        with open(cpp_path, "w") as cpp_file:
508            cpp_file.write("void func(int) {}")
509        with open(version_script_path, "w") as version_script_file:
510            pass
511        fd = os.open(read_only_path, flags=(os.O_CREAT | os.O_EXCL),
512                     mode=(stat.S_IROTH | stat.S_IRGRP | stat.S_IRUSR))
513        self.assertGreaterEqual(fd, 0)
514        os.close(fd)
515
516        # Make sure that the commands are valid.
517        dumper_flags = ('-output-format', 'Json')
518        run_header_abi_dumper(cpp_path, sdump_path, flags=dumper_flags)
519        self.assertGreater(os.stat(sdump_path).st_size, 0)
520        linker_flags = ('-input-format', 'Json',
521                        '-output-format', 'ProtobufTextFormat')
522        run_header_abi_linker([sdump_path], lsdump_path, version_script_path,
523                              "current", "x86_64", linker_flags)
524        self.assertGreater(os.stat(lsdump_path).st_size, 0)
525        diff_flags = ('-input-format-old', 'ProtobufTextFormat',
526                      '-input-format-new', 'ProtobufTextFormat')
527        return_code = run_abi_diff(lsdump_path, lsdump_path, abidiff_path,
528                                   'x86_64', 'libtest', diff_flags)
529        self.assertEqual(return_code, 0)
530        self.assertGreater(os.stat(abidiff_path).st_size, 0)
531
532        # Test with output error.
533        with self.assertRaises(subprocess.CalledProcessError) as assertion:
534            run_header_abi_dumper(cpp_path, read_only_path, flags=dumper_flags)
535        self.assertEqual(assertion.exception.returncode, 1)
536
537        with self.assertRaises(subprocess.CalledProcessError) as assertion:
538            run_header_abi_linker([sdump_path], read_only_path,
539                                  version_script_path, "current", "x86_64",
540                                  linker_flags)
541        self.assertEqual(assertion.exception.returncode, 255)
542
543        return_code = run_abi_diff(lsdump_path, lsdump_path, read_only_path,
544                                   'x86_64', 'libtest', diff_flags)
545        self.assertEqual(return_code, 1)
546
547    def test_bit_field_diff(self):
548        self.prepare_and_absolute_diff_all_archs(
549            "libbit_field", "libbit_field")
550        self.prepare_and_run_abi_diff_all_archs(
551            "libbit_field", "libbit_field_diff", 8,
552            flags=["-input-format-new", "Json", "-input-format-old", "Json"],
553            create_old=False, create_new=True)
554
555    def test_availability(self):
556        self.prepare_and_absolute_diff_all_archs(
557            "libavailability", "libavailability")
558        self.prepare_and_absolute_diff_all_archs(
559            "libavailability_35", "libavailability_35")
560
561
562if __name__ == '__main__':
563    unittest.main()
564