xref: /aosp_15_r20/external/google-fruit/tests/test_defn_h_includes.py (revision a65addddcf69f38db5b288d787b6b7571a57bb8f)
1*a65addddSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*a65addddSAndroid Build Coastguard Worker#  Copyright 2016 Google Inc. All Rights Reserved.
3*a65addddSAndroid Build Coastguard Worker#
4*a65addddSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker#
8*a65addddSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker#
10*a65addddSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS-IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker# limitations under the License.
15*a65addddSAndroid Build Coastguard Worker
16*a65addddSAndroid Build Coastguard Workerfrom absl.testing import parameterized
17*a65addddSAndroid Build Coastguard Workerfrom fruit_test_common import *
18*a65addddSAndroid Build Coastguard Worker
19*a65addddSAndroid Build Coastguard Workerclass TestDefnHIncludes(parameterized.TestCase):
20*a65addddSAndroid Build Coastguard Worker    def test_defn_file_inclusion(self):
21*a65addddSAndroid Build Coastguard Worker        if os.sep != '/':
22*a65addddSAndroid Build Coastguard Worker            # This only works in platforms where paths are /-separated.
23*a65addddSAndroid Build Coastguard Worker            return
24*a65addddSAndroid Build Coastguard Worker        include_pattern = re.compile(' *#include *<(.*)> *')
25*a65addddSAndroid Build Coastguard Worker
26*a65addddSAndroid Build Coastguard Worker        fruit_headers_root_absolute_path = os.path.abspath(PATH_TO_FRUIT_STATIC_HEADERS)
27*a65addddSAndroid Build Coastguard Worker
28*a65addddSAndroid Build Coastguard Worker        includes = {}
29*a65addddSAndroid Build Coastguard Worker        for root, _, files in os.walk(fruit_headers_root_absolute_path):
30*a65addddSAndroid Build Coastguard Worker            for file in files:
31*a65addddSAndroid Build Coastguard Worker                if file.endswith('.h'):
32*a65addddSAndroid Build Coastguard Worker                    path = os.path.join(root, file)
33*a65addddSAndroid Build Coastguard Worker                    with open(path, 'r') as f:
34*a65addddSAndroid Build Coastguard Worker                        current_includes = set()
35*a65addddSAndroid Build Coastguard Worker                        for line in f.readlines():
36*a65addddSAndroid Build Coastguard Worker                            # Remove the newline
37*a65addddSAndroid Build Coastguard Worker                            line = line[:-1]
38*a65addddSAndroid Build Coastguard Worker                            matches = re.match(include_pattern, line)
39*a65addddSAndroid Build Coastguard Worker                            if matches:
40*a65addddSAndroid Build Coastguard Worker                                current_includes.add(matches.groups()[0])
41*a65addddSAndroid Build Coastguard Worker                        root_relative_path = root.replace(fruit_headers_root_absolute_path, '')
42*a65addddSAndroid Build Coastguard Worker                        relative_path = os.path.join(root_relative_path, file)
43*a65addddSAndroid Build Coastguard Worker                        if relative_path.startswith(os.sep):
44*a65addddSAndroid Build Coastguard Worker                            relative_path = relative_path[1:]
45*a65addddSAndroid Build Coastguard Worker                        includes[relative_path] = current_includes
46*a65addddSAndroid Build Coastguard Worker
47*a65addddSAndroid Build Coastguard Worker        for defn_file, defn_file_includes in includes.items():
48*a65addddSAndroid Build Coastguard Worker            if defn_file.endswith('.defn.h'):
49*a65addddSAndroid Build Coastguard Worker                main_header_file = defn_file.replace('.defn.h', '.h')
50*a65addddSAndroid Build Coastguard Worker                # This is a special case where we don't follow the convention, so we need to specify the corresponding main
51*a65addddSAndroid Build Coastguard Worker                # header file explicitly.
52*a65addddSAndroid Build Coastguard Worker                if defn_file == 'fruit/impl/component_functors.defn.h':
53*a65addddSAndroid Build Coastguard Worker                    main_header_file = 'fruit/component.h'
54*a65addddSAndroid Build Coastguard Worker
55*a65addddSAndroid Build Coastguard Worker                # The .defn.h files for headers in fruit/ are in fruit/impl/
56*a65addddSAndroid Build Coastguard Worker                alternative_main_header_file = main_header_file.replace('fruit/impl/', 'fruit/')
57*a65addddSAndroid Build Coastguard Worker
58*a65addddSAndroid Build Coastguard Worker                if main_header_file not in includes and alternative_main_header_file not in includes:
59*a65addddSAndroid Build Coastguard Worker                    raise Exception('Can\'t find the .h header corresponding to: %s. Considered: %s' % (defn_file, (main_header_file, alternative_main_header_file)))
60*a65addddSAndroid Build Coastguard Worker                if main_header_file not in defn_file_includes and alternative_main_header_file not in defn_file_includes:
61*a65addddSAndroid Build Coastguard Worker                    raise Exception('%s should have included %s, but it includes only: %s' % (defn_file, main_header_file, defn_file_includes))
62*a65addddSAndroid Build Coastguard Worker                if main_header_file in includes and defn_file not in includes[main_header_file]:
63*a65addddSAndroid Build Coastguard Worker                    raise Exception('%s should have included %s, but it includes only: %s' % (main_header_file, defn_file, includes[main_header_file]))
64*a65addddSAndroid Build Coastguard Worker                if alternative_main_header_file in includes and defn_file not in includes[alternative_main_header_file]:
65*a65addddSAndroid Build Coastguard Worker                    raise Exception('%s should have included %s, but it includes only: %s' % (main_header_file, defn_file, includes[alternative_main_header_file]))
66*a65addddSAndroid Build Coastguard Worker                for other_header, other_header_includes in includes.items():
67*a65addddSAndroid Build Coastguard Worker                    if other_header not in (main_header_file, alternative_main_header_file) and defn_file in other_header_includes:
68*a65addddSAndroid Build Coastguard Worker                        raise Exception('Unexpected direct include: %s includes %s' % (other_header, defn_file))
69*a65addddSAndroid Build Coastguard Worker
70*a65addddSAndroid Build Coastguard Workerif __name__ == '__main__':
71*a65addddSAndroid Build Coastguard Worker    absltest.main()
72