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