1#!/usr/bin/env python3
2
3# Copyright 2021 gRPC authors.
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
17import os
18import sys
19
20os.chdir(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
21
22# Allowance for overrides for specific files
23EXPECTED_NAMES = {
24    'src/proto/grpc/channelz': 'channelz',
25    'src/proto/grpc/status': 'status',
26    'src/proto/grpc/testing': 'testing',
27    'src/proto/grpc/testing/duplicate': 'duplicate',
28    'src/proto/grpc/lb/v1': 'lb',
29    'src/proto/grpc/testing/xds': 'xds',
30    'src/proto/grpc/testing/xds/v3': 'xds_v3',
31    'src/proto/grpc/core': 'core',
32    'src/proto/grpc/health/v1': 'health',
33    'src/proto/grpc/reflection/v1alpha': 'reflection',
34    'src/proto/grpc/reflection/v1': 'reflection_v1',
35}
36
37errors = 0
38for root, dirs, files in os.walk('.'):
39    if root.startswith('./'):
40        root = root[len('./'):]
41    # don't check third party
42    if root.startswith('third_party/'):
43        continue
44    # only check BUILD files
45    if 'BUILD' not in files:
46        continue
47    text = open('%s/BUILD' % root).read()
48    # find a grpc_package clause
49    pkg_start = text.find('grpc_package(')
50    if pkg_start == -1:
51        continue
52    # parse it, taking into account nested parens
53    pkg_end = pkg_start + len('grpc_package(')
54    level = 1
55    while level == 1:
56        if text[pkg_end] == ')':
57            level -= 1
58        elif text[pkg_end] == '(':
59            level += 1
60        pkg_end += 1
61    # it's a python statement, so evaluate it to pull out the name of the package
62    name = eval(text[pkg_start:pkg_end],
63                {'grpc_package': lambda name, **kwargs: name})
64    # the name should be the path within the source tree, excepting some special
65    # BUILD files (really we should normalize them too at some point)
66    # TODO(ctiller): normalize all package names
67    expected_name = EXPECTED_NAMES.get(root, root)
68    if name != expected_name:
69        print("%s/BUILD should define a grpc_package with name=%r, not %r" %
70              (root, expected_name, name))
71        errors += 1
72
73if errors != 0:
74    sys.exit(1)
75