1#!/usr/bin/env python 2 3# Copyright 2017 The WebRTC project authors. All Rights Reserved. 4# 5# Use of this source code is governed by a BSD-style license 6# that can be found in the LICENSE file in the root of the source 7# tree. An additional intellectual property rights grant can be found 8# in the file PATENTS. All contributing project authors may 9# be found in the AUTHORS file in the root of the source tree. 10 11import os 12import shutil 13import tempfile 14import textwrap 15import unittest 16 17import PRESUBMIT 18# pylint: disable=line-too-long 19from presubmit_test_mocks import MockInputApi, MockOutputApi, MockFile, MockChange 20 21 22class CheckBugEntryFieldTest(unittest.TestCase): 23 def testCommitMessageBugEntryWithNoError(self): 24 mock_input_api = MockInputApi() 25 mock_output_api = MockOutputApi() 26 mock_input_api.change = MockChange([], ['webrtc:1234']) 27 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 28 mock_output_api) 29 self.assertEqual(0, len(errors)) 30 31 def testCommitMessageBugEntryReturnError(self): 32 mock_input_api = MockInputApi() 33 mock_output_api = MockOutputApi() 34 mock_input_api.change = MockChange([], ['webrtc:1234', 'webrtc=4321']) 35 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 36 mock_output_api) 37 self.assertEqual(1, len(errors)) 38 self.assertEqual(('Bogus Bug entry: webrtc=4321. Please specify' 39 ' the issue tracker prefix and the issue number,' 40 ' separated by a colon, e.g. webrtc:123 or' 41 ' chromium:12345.'), str(errors[0])) 42 43 def testCommitMessageBugEntryWithoutPrefix(self): 44 mock_input_api = MockInputApi() 45 mock_output_api = MockOutputApi() 46 mock_input_api.change = MockChange([], ['1234']) 47 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 48 mock_output_api) 49 self.assertEqual(1, len(errors)) 50 self.assertEqual(('Bug entry requires issue tracker prefix, ' 51 'e.g. webrtc:1234'), str(errors[0])) 52 53 def testCommitMessageBugEntryIsNone(self): 54 mock_input_api = MockInputApi() 55 mock_output_api = MockOutputApi() 56 mock_input_api.change = MockChange([], ['None']) 57 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 58 mock_output_api) 59 self.assertEqual(0, len(errors)) 60 61 def testCommitMessageBugEntrySupportInternalBugReference(self): 62 mock_input_api = MockInputApi() 63 mock_output_api = MockOutputApi() 64 mock_input_api.change.BUG = 'b/12345' 65 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 66 mock_output_api) 67 self.assertEqual(0, len(errors)) 68 mock_input_api.change.BUG = 'b/12345, webrtc:1234' 69 errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, 70 mock_output_api) 71 self.assertEqual(0, len(errors)) 72 73 74class CheckNewlineAtTheEndOfProtoFilesTest(unittest.TestCase): 75 76 def setUp(self): 77 self.tmp_dir = tempfile.mkdtemp() 78 self.proto_file_path = os.path.join(self.tmp_dir, 'foo.proto') 79 self.input_api = MockInputApi() 80 self.output_api = MockOutputApi() 81 82 def tearDown(self): 83 shutil.rmtree(self.tmp_dir, ignore_errors=True) 84 85 def testErrorIfProtoFileDoesNotEndWithNewline(self): 86 self._GenerateProtoWithoutNewlineAtTheEnd() 87 self.input_api.files = [MockFile(self.proto_file_path)] 88 errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(self.input_api, 89 self.output_api, 90 lambda x: True) 91 self.assertEqual(1, len(errors)) 92 self.assertEqual( 93 'File %s must end with exactly one newline.' % self.proto_file_path, 94 str(errors[0])) 95 96 def testNoErrorIfProtoFileEndsWithNewline(self): 97 self._GenerateProtoWithNewlineAtTheEnd() 98 self.input_api.files = [MockFile(self.proto_file_path)] 99 errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles(self.input_api, 100 self.output_api, 101 lambda x: True) 102 self.assertEqual(0, len(errors)) 103 104 def _GenerateProtoWithNewlineAtTheEnd(self): 105 with open(self.proto_file_path, 'w') as f: 106 f.write(textwrap.dedent(""" 107 syntax = "proto2"; 108 option optimize_for = LITE_RUNTIME; 109 package webrtc.audioproc; 110 """)) 111 112 def _GenerateProtoWithoutNewlineAtTheEnd(self): 113 with open(self.proto_file_path, 'w') as f: 114 f.write(textwrap.dedent(""" 115 syntax = "proto2"; 116 option optimize_for = LITE_RUNTIME; 117 package webrtc.audioproc;""")) 118 119 120class CheckNoMixingSourcesTest(unittest.TestCase): 121 122 def setUp(self): 123 self.tmp_dir = tempfile.mkdtemp() 124 self.file_path = os.path.join(self.tmp_dir, 'BUILD.gn') 125 self.input_api = MockInputApi() 126 self.output_api = MockOutputApi() 127 128 def tearDown(self): 129 shutil.rmtree(self.tmp_dir, ignore_errors=True) 130 131 def testErrorIfCAndCppAreMixed(self): 132 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.cc', 'bar.h']) 133 134 def testErrorIfCAndObjCAreMixed(self): 135 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.m', 'bar.h']) 136 137 def testErrorIfCAndObjCppAreMixed(self): 138 self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.mm', 'bar.h']) 139 140 def testErrorIfCppAndObjCAreMixed(self): 141 self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.m', 'bar.h']) 142 143 def testErrorIfCppAndObjCppAreMixed(self): 144 self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.mm', 'bar.h']) 145 146 def testNoErrorIfOnlyC(self): 147 self._AssertNumberOfErrorsWithSources(0, ['foo.c', 'bar.c', 'bar.h']) 148 149 def testNoErrorIfOnlyCpp(self): 150 self._AssertNumberOfErrorsWithSources(0, ['foo.cc', 'bar.cc', 'bar.h']) 151 152 def testNoErrorIfOnlyObjC(self): 153 self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.m', 'bar.h']) 154 155 def testNoErrorIfOnlyObjCpp(self): 156 self._AssertNumberOfErrorsWithSources(0, ['foo.mm', 'bar.mm', 'bar.h']) 157 158 def testNoErrorIfObjCAndObjCppAreMixed(self): 159 self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.mm', 'bar.h']) 160 161 def testNoErrorIfSourcesAreInExclusiveIfBranches(self): 162 self._GenerateBuildFile(textwrap.dedent(""" 163 rtc_library("bar_foo") { 164 if (is_win) { 165 sources = [ 166 "bar.cc", 167 ], 168 } 169 if (is_ios) { 170 sources = [ 171 "bar.mm", 172 ], 173 } 174 } 175 rtc_library("foo_bar") { 176 if (is_win) { 177 sources = [ 178 "foo.cc", 179 ], 180 } 181 if (is_ios) { 182 sources = [ 183 "foo.mm", 184 ], 185 } 186 } 187 """)) 188 self.input_api.files = [MockFile(self.file_path)] 189 errors = PRESUBMIT.CheckNoMixingSources(self.input_api, 190 [MockFile(self.file_path)], 191 self.output_api) 192 self.assertEqual(0, len(errors)) 193 194 def testErrorIfSourcesAreNotInExclusiveIfBranches(self): 195 self._GenerateBuildFile(textwrap.dedent(""" 196 rtc_library("bar_foo") { 197 if (is_win) { 198 sources = [ 199 "bar.cc", 200 ], 201 } 202 if (foo_bar) { 203 sources += [ 204 "bar.mm", 205 ], 206 } 207 } 208 rtc_library("foo_bar") { 209 if (is_win) { 210 sources = [ 211 "foo.cc", 212 ], 213 } 214 if (foo_bar) { 215 sources += [ 216 "foo.mm", 217 ], 218 } 219 if (is_ios) { 220 sources = [ 221 "bar.m", 222 "bar.c", 223 ], 224 } 225 } 226 """)) 227 self.input_api.files = [MockFile(self.file_path)] 228 errors = PRESUBMIT.CheckNoMixingSources(self.input_api, 229 [MockFile(self.file_path)], 230 self.output_api) 231 self.assertEqual(1, len(errors)) 232 self.assertTrue('bar.cc' in str(errors[0])) 233 self.assertTrue('bar.mm' in str(errors[0])) 234 self.assertTrue('foo.cc' in str(errors[0])) 235 self.assertTrue('foo.mm' in str(errors[0])) 236 self.assertTrue('bar.m' in str(errors[0])) 237 self.assertTrue('bar.c' in str(errors[0])) 238 239 def _AssertNumberOfErrorsWithSources(self, number_of_errors, sources): 240 assert len(sources) == 3, 'This function accepts a list of 3 source files' 241 self._GenerateBuildFile(textwrap.dedent(""" 242 rtc_static_library("bar_foo") { 243 sources = [ 244 "%s", 245 "%s", 246 "%s", 247 ], 248 } 249 rtc_library("foo_bar") { 250 sources = [ 251 "%s", 252 "%s", 253 "%s", 254 ], 255 } 256 """ % (tuple(sources) * 2))) 257 self.input_api.files = [MockFile(self.file_path)] 258 errors = PRESUBMIT.CheckNoMixingSources(self.input_api, 259 [MockFile(self.file_path)], 260 self.output_api) 261 self.assertEqual(number_of_errors, len(errors)) 262 if number_of_errors == 1: 263 for source in sources: 264 if not source.endswith('.h'): 265 self.assertTrue(source in str(errors[0])) 266 267 def _GenerateBuildFile(self, content): 268 with open(self.file_path, 'w') as f: 269 f.write(content) 270 271 272if __name__ == '__main__': 273 unittest.main() 274