1*60517a1eSAndroid Build Coastguard Worker# Copyright 2023 The Bazel Authors. All rights reserved. 2*60517a1eSAndroid Build Coastguard Worker# 3*60517a1eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*60517a1eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*60517a1eSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*60517a1eSAndroid Build Coastguard Worker# 7*60517a1eSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*60517a1eSAndroid Build Coastguard Worker# 9*60517a1eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*60517a1eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*60517a1eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*60517a1eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*60517a1eSAndroid Build Coastguard Worker# limitations under the License. 14*60517a1eSAndroid Build Coastguard Worker 15*60517a1eSAndroid Build Coastguard Workerimport os 16*60517a1eSAndroid Build Coastguard Workerimport pathlib 17*60517a1eSAndroid Build Coastguard Workerimport re 18*60517a1eSAndroid Build Coastguard Workerimport sys 19*60517a1eSAndroid Build Coastguard Workerimport unittest 20*60517a1eSAndroid Build Coastguard Worker 21*60517a1eSAndroid Build Coastguard Workerfrom lib import main 22*60517a1eSAndroid Build Coastguard Worker 23*60517a1eSAndroid Build Coastguard Worker 24*60517a1eSAndroid Build Coastguard Workerclass ExampleTest(unittest.TestCase): 25*60517a1eSAndroid Build Coastguard Worker def test_coverage_doesnt_shadow_stdlib(self): 26*60517a1eSAndroid Build Coastguard Worker # When we try to import the html module 27*60517a1eSAndroid Build Coastguard Worker import html as html_stdlib 28*60517a1eSAndroid Build Coastguard Worker 29*60517a1eSAndroid Build Coastguard Worker try: 30*60517a1eSAndroid Build Coastguard Worker import coverage.html as html_coverage 31*60517a1eSAndroid Build Coastguard Worker except ImportError: 32*60517a1eSAndroid Build Coastguard Worker self.skipTest("not running under coverage, skipping") 33*60517a1eSAndroid Build Coastguard Worker 34*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 35*60517a1eSAndroid Build Coastguard Worker "html", 36*60517a1eSAndroid Build Coastguard Worker f"{html_stdlib.__name__}", 37*60517a1eSAndroid Build Coastguard Worker "'html' from stdlib was not loaded correctly", 38*60517a1eSAndroid Build Coastguard Worker ) 39*60517a1eSAndroid Build Coastguard Worker 40*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 41*60517a1eSAndroid Build Coastguard Worker "coverage.html", 42*60517a1eSAndroid Build Coastguard Worker f"{html_coverage.__name__}", 43*60517a1eSAndroid Build Coastguard Worker "'coverage.html' was not loaded correctly", 44*60517a1eSAndroid Build Coastguard Worker ) 45*60517a1eSAndroid Build Coastguard Worker 46*60517a1eSAndroid Build Coastguard Worker self.assertNotEqual( 47*60517a1eSAndroid Build Coastguard Worker html_stdlib, 48*60517a1eSAndroid Build Coastguard Worker html_coverage, 49*60517a1eSAndroid Build Coastguard Worker "'html' import should not be shadowed by coverage", 50*60517a1eSAndroid Build Coastguard Worker ) 51*60517a1eSAndroid Build Coastguard Worker 52*60517a1eSAndroid Build Coastguard Worker def test_coverage_sys_path(self): 53*60517a1eSAndroid Build Coastguard Worker all_paths = ",\n ".join(sys.path) 54*60517a1eSAndroid Build Coastguard Worker 55*60517a1eSAndroid Build Coastguard Worker for i, path in enumerate(sys.path[1:-2]): 56*60517a1eSAndroid Build Coastguard Worker self.assertFalse( 57*60517a1eSAndroid Build Coastguard Worker "/coverage" in path, 58*60517a1eSAndroid Build Coastguard Worker f"Expected {i + 2}th '{path}' to not contain 'coverage.py' paths, " 59*60517a1eSAndroid Build Coastguard Worker f"sys.path has {len(sys.path)} items:\n {all_paths}", 60*60517a1eSAndroid Build Coastguard Worker ) 61*60517a1eSAndroid Build Coastguard Worker 62*60517a1eSAndroid Build Coastguard Worker first_item, last_item = sys.path[0], sys.path[-1] 63*60517a1eSAndroid Build Coastguard Worker self.assertFalse( 64*60517a1eSAndroid Build Coastguard Worker first_item.endswith("coverage"), 65*60517a1eSAndroid Build Coastguard Worker f"Expected the first item in sys.path '{first_item}' to not be related to coverage", 66*60517a1eSAndroid Build Coastguard Worker ) 67*60517a1eSAndroid Build Coastguard Worker 68*60517a1eSAndroid Build Coastguard Worker # We're trying to make sure that the coverage library added by the 69*60517a1eSAndroid Build Coastguard Worker # toolchain is _after_ any user-provided dependencies. This lets users 70*60517a1eSAndroid Build Coastguard Worker # override what coverage version they're using. 71*60517a1eSAndroid Build Coastguard Worker first_coverage_index = None 72*60517a1eSAndroid Build Coastguard Worker last_user_dep_index = None 73*60517a1eSAndroid Build Coastguard Worker for i, path in enumerate(sys.path): 74*60517a1eSAndroid Build Coastguard Worker if re.search("rules_python.*[~+]pip[~+]", path): 75*60517a1eSAndroid Build Coastguard Worker last_user_dep_index = i 76*60517a1eSAndroid Build Coastguard Worker if first_coverage_index is None and re.search( 77*60517a1eSAndroid Build Coastguard Worker ".*rules_python.*[~+]python[~+].*coverage.*", path 78*60517a1eSAndroid Build Coastguard Worker ): 79*60517a1eSAndroid Build Coastguard Worker first_coverage_index = i 80*60517a1eSAndroid Build Coastguard Worker 81*60517a1eSAndroid Build Coastguard Worker if os.environ.get("COVERAGE_MANIFEST"): 82*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone( 83*60517a1eSAndroid Build Coastguard Worker first_coverage_index, 84*60517a1eSAndroid Build Coastguard Worker "Expected to find toolchain coverage, but " 85*60517a1eSAndroid Build Coastguard Worker + f"it was not found.\nsys.path:\n{all_paths}", 86*60517a1eSAndroid Build Coastguard Worker ) 87*60517a1eSAndroid Build Coastguard Worker self.assertIsNotNone( 88*60517a1eSAndroid Build Coastguard Worker last_user_dep_index, 89*60517a1eSAndroid Build Coastguard Worker "Expected to find at least one user dep, " 90*60517a1eSAndroid Build Coastguard Worker + "but none were found.\nsys.path:\n{all_paths}", 91*60517a1eSAndroid Build Coastguard Worker ) 92*60517a1eSAndroid Build Coastguard Worker # we are running under the 'bazel coverage :test' 93*60517a1eSAndroid Build Coastguard Worker self.assertGreater( 94*60517a1eSAndroid Build Coastguard Worker first_coverage_index, 95*60517a1eSAndroid Build Coastguard Worker last_user_dep_index, 96*60517a1eSAndroid Build Coastguard Worker "Expected coverage provided by the toolchain to be after " 97*60517a1eSAndroid Build Coastguard Worker + "user provided dependencies.\n" 98*60517a1eSAndroid Build Coastguard Worker + f"Found coverage at index: {first_coverage_index}\n" 99*60517a1eSAndroid Build Coastguard Worker + f"Last user dep at index: {last_user_dep_index}\n" 100*60517a1eSAndroid Build Coastguard Worker + f"Full sys.path:\n{all_paths}", 101*60517a1eSAndroid Build Coastguard Worker ) 102*60517a1eSAndroid Build Coastguard Worker else: 103*60517a1eSAndroid Build Coastguard Worker self.assertIsNone( 104*60517a1eSAndroid Build Coastguard Worker first_coverage_index, 105*60517a1eSAndroid Build Coastguard Worker "Expected toolchain coverage to not be present\n" 106*60517a1eSAndroid Build Coastguard Worker + f"Found coverage at index: {first_coverage_index}\n" 107*60517a1eSAndroid Build Coastguard Worker + f"Full sys.path:\n{all_paths}", 108*60517a1eSAndroid Build Coastguard Worker ) 109*60517a1eSAndroid Build Coastguard Worker 110*60517a1eSAndroid Build Coastguard Worker def test_main(self): 111*60517a1eSAndroid Build Coastguard Worker self.assertEqual( 112*60517a1eSAndroid Build Coastguard Worker """\ 113*60517a1eSAndroid Build Coastguard Worker- - 114*60517a1eSAndroid Build Coastguard WorkerA 1 115*60517a1eSAndroid Build Coastguard WorkerB 2 116*60517a1eSAndroid Build Coastguard Worker- -""", 117*60517a1eSAndroid Build Coastguard Worker main([["A", 1], ["B", 2]]), 118*60517a1eSAndroid Build Coastguard Worker ) 119*60517a1eSAndroid Build Coastguard Worker 120*60517a1eSAndroid Build Coastguard Worker 121*60517a1eSAndroid Build Coastguard Workerif __name__ == "__main__": 122*60517a1eSAndroid Build Coastguard Worker unittest.main() 123