• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""This pip smoke test verifies dependency files exist in the pip package.
16
17This script runs bazel queries to see what python files are required by the
18tests and ensures they are in the pip package superset.
19"""
20
21from __future__ import absolute_import
22from __future__ import division
23from __future__ import print_function
24
25import os
26import subprocess
27
28os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")))
29
30PIP_PACKAGE_QUERY_EXPRESSION = (
31    "deps(//tensorflow/tools/pip_package:build_pip_package)")
32
33# List of file paths containing BUILD files that should not be included for the
34# pip smoke test.
35BUILD_DENYLIST = [
36    "tensorflow/lite",
37    "tensorflow/compiler/mlir/lite",
38    "tensorflow/python/kernel_tests/signal",
39    "tensorflow/examples",
40    "tensorflow/tools/android",
41    "tensorflow/python/eager/benchmarks",
42]
43
44def GetBuild(dir_base):
45  """Get the list of BUILD file all targets recursively startind at dir_base."""
46  items = []
47  for root, _, files in os.walk(dir_base):
48    for name in files:
49      if (name == "BUILD" and not any(x in root for x in BUILD_DENYLIST)):
50        items.append("//" + root + ":all")
51  return items
52
53
54def BuildPyTestDependencies():
55  python_targets = GetBuild("tensorflow/python")
56  tensorflow_targets = GetBuild("tensorflow")
57  # Build list of test targets,
58  # python - attr(manual|pno_pip)
59  targets = " + ".join(python_targets)
60  targets += ' - attr(tags, "manual|no_pip", %s)' % " + ".join(
61      tensorflow_targets)
62  query_kind = "kind(py_test, %s)" % targets
63  # Skip benchmarks etc.
64  query_filter = 'filter("^((?!benchmark).)*$", %s)' % query_kind
65  # Get the dependencies
66  query_deps = "deps(%s, 1)" % query_filter
67
68  return python_targets, query_deps
69
70
71PYTHON_TARGETS, PY_TEST_QUERY_EXPRESSION = BuildPyTestDependencies()
72
73# TODO(amitpatankar): Clean up denylist.
74# List of dependencies that should not included in the pip package.
75DEPENDENCY_DENYLIST = [
76    "//tensorflow/python:extra_py_tests_deps",
77    "//tensorflow/cc/saved_model:saved_model_test_files",
78    "//tensorflow/cc/saved_model:saved_model_half_plus_two",
79    "//tensorflow:no_tensorflow_py_deps",
80    "//tensorflow/tools/pip_package:win_pip_package_marker",
81    "//tensorflow/python:mixed_precision",
82    "//tensorflow/python:test_ops_2",
83    "//tensorflow/python:tf_optimizer",
84    "//tensorflow/python:compare_test_proto_py",
85    "//tensorflow/core:image_testdata",
86    "//tensorflow/core/lib/lmdb:lmdb_testdata",
87    "//tensorflow/core/lib/lmdb/testdata:lmdb_testdata",
88    "//tensorflow/core/kernels/cloud:bigquery_reader_ops",
89    "//tensorflow/python/debug:grpc_tensorflow_server.par",
90    "//tensorflow/python/feature_column:vocabulary_testdata",
91    "//tensorflow/python:framework/test_file_system.so",
92    "//tensorflow/python/util:nest_test_main_lib",
93    # lite
94    "//tensorflow/lite/experimental/examples/lstm:rnn_cell",
95    "//tensorflow/lite/experimental/examples/lstm:rnn_cell.py",
96    "//tensorflow/lite/experimental/examples/lstm:unidirectional_sequence_lstm_test",  # pylint:disable=line-too-long
97    "//tensorflow/lite/experimental/examples/lstm:unidirectional_sequence_lstm_test.py",  # pylint:disable=line-too-long
98    "//tensorflow/lite/python:interpreter",
99    "//tensorflow/lite/python:interpreter_test",
100    "//tensorflow/lite/python:interpreter.py",
101    "//tensorflow/lite/python:interpreter_test.py",
102]
103
104
105def main():
106  """This script runs the pip smoke test.
107
108  Raises:
109    RuntimeError: If any dependencies for py_tests exist in subSet
110
111  Prerequisites:
112      1. Bazel is installed.
113      2. Running in github repo of tensorflow.
114      3. Configure has been run.
115
116  """
117
118  # pip_package_dependencies_list is the list of included files in pip packages
119  pip_package_dependencies = subprocess.check_output(
120      ["bazel", "cquery", PIP_PACKAGE_QUERY_EXPRESSION])
121  if isinstance(pip_package_dependencies, bytes):
122    pip_package_dependencies = pip_package_dependencies.decode("utf-8")
123  pip_package_dependencies_list = pip_package_dependencies.strip().split("\n")
124  pip_package_dependencies_list = [
125      x.split()[0] for x in pip_package_dependencies_list
126  ]
127  print("Pip package superset size: %d" % len(pip_package_dependencies_list))
128
129  # tf_py_test_dependencies is the list of dependencies for all python
130  # tests in tensorflow
131  tf_py_test_dependencies = subprocess.check_output(
132      ["bazel", "cquery", PY_TEST_QUERY_EXPRESSION])
133  if isinstance(tf_py_test_dependencies, bytes):
134    tf_py_test_dependencies = tf_py_test_dependencies.decode("utf-8")
135  tf_py_test_dependencies_list = tf_py_test_dependencies.strip().split("\n")
136  tf_py_test_dependencies_list = [
137      x.split()[0] for x in tf_py_test_dependencies.strip().split("\n")
138  ]
139  print("Pytest dependency subset size: %d" % len(tf_py_test_dependencies_list))
140
141  missing_dependencies = []
142  # File extensions and endings to ignore
143  ignore_extensions = [
144      "_test", "_test.py", "_test_gpu", "_test_gpu.py", "_test_lib"
145  ]
146
147  ignored_files_count = 0
148  denylisted_dependencies_count = len(DEPENDENCY_DENYLIST)
149  # Compare dependencies
150  for dependency in tf_py_test_dependencies_list:
151    if dependency and dependency.startswith("//tensorflow"):
152      ignore = False
153      # Ignore extensions
154      if any(dependency.endswith(ext) for ext in ignore_extensions):
155        ignore = True
156        ignored_files_count += 1
157
158      # Check if the dependency is in the pip package, the dependency denylist,
159      # or should be ignored because of its file extension.
160      if not (ignore or dependency in pip_package_dependencies_list or
161              dependency in DEPENDENCY_DENYLIST):
162        missing_dependencies.append(dependency)
163
164  print("Ignored files count: %d" % ignored_files_count)
165  print("Denylisted dependencies count: %d" % denylisted_dependencies_count)
166  if missing_dependencies:
167    print("Missing the following dependencies from pip_packages:")
168    for missing_dependency in missing_dependencies:
169      print("\nMissing dependency: %s " % missing_dependency)
170      print("Affected Tests:")
171      rdep_query = ("rdeps(kind(py_test, %s), %s)" %
172                    (" + ".join(PYTHON_TARGETS), missing_dependency))
173      affected_tests = subprocess.check_output(["bazel", "cquery", rdep_query])
174      affected_tests_list = affected_tests.split("\n")[:-2]
175      print("\n".join(affected_tests_list))
176
177    raise RuntimeError("""
178    One or more added test dependencies are not in the pip package.
179If these test dependencies need to be in TensorFlow pip package, please add them to //tensorflow/tools/pip_package/BUILD.
180Else add no_pip tag to the test.""")
181
182  else:
183    print("TEST PASSED")
184
185
186if __name__ == "__main__":
187  main()
188