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