1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import glob 7import json 8import os 9import re 10import subprocess 11import sys 12import unittest 13 14import PRESUBMIT 15 16 17_TEST_DATA_DIR = 'base/test/data/presubmit' 18 19 20class MockInputApi(object): 21 def __init__(self): 22 self.json = json 23 self.re = re 24 self.os_path = os.path 25 self.python_executable = sys.executable 26 self.subprocess = subprocess 27 self.files = [] 28 self.is_committing = False 29 30 def AffectedFiles(self, file_filter=None): 31 return self.files 32 33 def PresubmitLocalPath(self): 34 return os.path.dirname(__file__) 35 36 def ReadFile(self, filename, mode='rU'): 37 for file_ in self.files: 38 if file_.LocalPath() == filename: 39 return '\n'.join(file_.NewContents()) 40 # Otherwise, file is not in our mock API. 41 raise IOError, "No such file or directory: '%s'" % filename 42 43 44class MockOutputApi(object): 45 class PresubmitResult(object): 46 def __init__(self, message, items=None, long_text=''): 47 self.message = message 48 self.items = items 49 self.long_text = long_text 50 51 class PresubmitError(PresubmitResult): 52 def __init__(self, message, items, long_text=''): 53 MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) 54 self.type = 'error' 55 56 class PresubmitPromptWarning(PresubmitResult): 57 def __init__(self, message, items, long_text=''): 58 MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) 59 self.type = 'warning' 60 61 class PresubmitNotifyResult(PresubmitResult): 62 def __init__(self, message, items, long_text=''): 63 MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) 64 self.type = 'notify' 65 66 class PresubmitPromptOrNotify(PresubmitResult): 67 def __init__(self, message, items, long_text=''): 68 MockOutputApi.PresubmitResult.__init__(self, message, items, long_text) 69 self.type = 'promptOrNotify' 70 71 72class MockFile(object): 73 def __init__(self, local_path, new_contents): 74 self._local_path = local_path 75 self._new_contents = new_contents 76 self._changed_contents = [(i + 1, l) for i, l in enumerate(new_contents)] 77 78 def ChangedContents(self): 79 return self._changed_contents 80 81 def NewContents(self): 82 return self._new_contents 83 84 def LocalPath(self): 85 return self._local_path 86 87 88class MockChange(object): 89 def __init__(self, changed_files): 90 self._changed_files = changed_files 91 92 def LocalPaths(self): 93 return self._changed_files 94 95 96class IncludeOrderTest(unittest.TestCase): 97 def testSystemHeaderOrder(self): 98 scope = [(1, '#include <csystem.h>'), 99 (2, '#include <cppsystem>'), 100 (3, '#include "acustom.h"')] 101 all_linenums = [linenum for (linenum, _) in scope] 102 mock_input_api = MockInputApi() 103 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 104 '', all_linenums) 105 self.assertEqual(0, len(warnings)) 106 107 def testSystemHeaderOrderMismatch1(self): 108 scope = [(10, '#include <cppsystem>'), 109 (20, '#include <csystem.h>'), 110 (30, '#include "acustom.h"')] 111 all_linenums = [linenum for (linenum, _) in scope] 112 mock_input_api = MockInputApi() 113 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 114 '', all_linenums) 115 self.assertEqual(1, len(warnings)) 116 self.assertTrue('20' in warnings[0]) 117 118 def testSystemHeaderOrderMismatch2(self): 119 scope = [(10, '#include <cppsystem>'), 120 (20, '#include "acustom.h"'), 121 (30, '#include <csystem.h>')] 122 all_linenums = [linenum for (linenum, _) in scope] 123 mock_input_api = MockInputApi() 124 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 125 '', all_linenums) 126 self.assertEqual(1, len(warnings)) 127 self.assertTrue('30' in warnings[0]) 128 129 def testSystemHeaderOrderMismatch3(self): 130 scope = [(10, '#include "acustom.h"'), 131 (20, '#include <csystem.h>'), 132 (30, '#include <cppsystem>')] 133 all_linenums = [linenum for (linenum, _) in scope] 134 mock_input_api = MockInputApi() 135 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 136 '', all_linenums) 137 self.assertEqual(2, len(warnings)) 138 self.assertTrue('20' in warnings[0]) 139 self.assertTrue('30' in warnings[1]) 140 141 def testAlphabeticalOrderMismatch(self): 142 scope = [(10, '#include <csystem.h>'), 143 (15, '#include <bsystem.h>'), 144 (20, '#include <cppsystem>'), 145 (25, '#include <bppsystem>'), 146 (30, '#include "bcustom.h"'), 147 (35, '#include "acustom.h"')] 148 all_linenums = [linenum for (linenum, _) in scope] 149 mock_input_api = MockInputApi() 150 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 151 '', all_linenums) 152 self.assertEqual(3, len(warnings)) 153 self.assertTrue('15' in warnings[0]) 154 self.assertTrue('25' in warnings[1]) 155 self.assertTrue('35' in warnings[2]) 156 157 def testSpecialFirstInclude1(self): 158 mock_input_api = MockInputApi() 159 contents = ['#include "some/path/foo.h"', 160 '#include "a/header.h"'] 161 mock_file = MockFile('some/path/foo.cc', contents) 162 warnings = PRESUBMIT._CheckIncludeOrderInFile( 163 mock_input_api, mock_file, range(1, len(contents) + 1)) 164 self.assertEqual(0, len(warnings)) 165 166 def testSpecialFirstInclude2(self): 167 mock_input_api = MockInputApi() 168 contents = ['#include "some/other/path/foo.h"', 169 '#include "a/header.h"'] 170 mock_file = MockFile('some/path/foo.cc', contents) 171 warnings = PRESUBMIT._CheckIncludeOrderInFile( 172 mock_input_api, mock_file, range(1, len(contents) + 1)) 173 self.assertEqual(0, len(warnings)) 174 175 def testSpecialFirstInclude3(self): 176 mock_input_api = MockInputApi() 177 contents = ['#include "some/path/foo.h"', 178 '#include "a/header.h"'] 179 mock_file = MockFile('some/path/foo_platform.cc', contents) 180 warnings = PRESUBMIT._CheckIncludeOrderInFile( 181 mock_input_api, mock_file, range(1, len(contents) + 1)) 182 self.assertEqual(0, len(warnings)) 183 184 def testSpecialFirstInclude4(self): 185 mock_input_api = MockInputApi() 186 contents = ['#include "some/path/bar.h"', 187 '#include "a/header.h"'] 188 mock_file = MockFile('some/path/foo_platform.cc', contents) 189 warnings = PRESUBMIT._CheckIncludeOrderInFile( 190 mock_input_api, mock_file, range(1, len(contents) + 1)) 191 self.assertEqual(1, len(warnings)) 192 self.assertTrue('2' in warnings[0]) 193 194 def testSpecialFirstInclude5(self): 195 mock_input_api = MockInputApi() 196 contents = ['#include "some/other/path/foo.h"', 197 '#include "a/header.h"'] 198 mock_file = MockFile('some/path/foo-suffix.h', contents) 199 warnings = PRESUBMIT._CheckIncludeOrderInFile( 200 mock_input_api, mock_file, range(1, len(contents) + 1)) 201 self.assertEqual(0, len(warnings)) 202 203 def testSpecialFirstInclude6(self): 204 mock_input_api = MockInputApi() 205 contents = ['#include "some/other/path/foo_win.h"', 206 '#include <set>', 207 '#include "a/header.h"'] 208 mock_file = MockFile('some/path/foo_unittest_win.h', contents) 209 warnings = PRESUBMIT._CheckIncludeOrderInFile( 210 mock_input_api, mock_file, range(1, len(contents) + 1)) 211 self.assertEqual(0, len(warnings)) 212 213 def testOrderAlreadyWrong(self): 214 scope = [(1, '#include "b.h"'), 215 (2, '#include "a.h"'), 216 (3, '#include "c.h"')] 217 mock_input_api = MockInputApi() 218 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 219 '', [3]) 220 self.assertEqual(0, len(warnings)) 221 222 def testConflictAdded1(self): 223 scope = [(1, '#include "a.h"'), 224 (2, '#include "c.h"'), 225 (3, '#include "b.h"')] 226 mock_input_api = MockInputApi() 227 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 228 '', [2]) 229 self.assertEqual(1, len(warnings)) 230 self.assertTrue('3' in warnings[0]) 231 232 def testConflictAdded2(self): 233 scope = [(1, '#include "c.h"'), 234 (2, '#include "b.h"'), 235 (3, '#include "d.h"')] 236 mock_input_api = MockInputApi() 237 warnings = PRESUBMIT._CheckIncludeOrderForScope(scope, mock_input_api, 238 '', [2]) 239 self.assertEqual(1, len(warnings)) 240 self.assertTrue('2' in warnings[0]) 241 242 def testIfElifElseEndif(self): 243 mock_input_api = MockInputApi() 244 contents = ['#include "e.h"', 245 '#define foo', 246 '#include "f.h"', 247 '#undef foo', 248 '#include "e.h"', 249 '#if foo', 250 '#include "d.h"', 251 '#elif bar', 252 '#include "c.h"', 253 '#else', 254 '#include "b.h"', 255 '#endif', 256 '#include "a.h"'] 257 mock_file = MockFile('', contents) 258 warnings = PRESUBMIT._CheckIncludeOrderInFile( 259 mock_input_api, mock_file, range(1, len(contents) + 1)) 260 self.assertEqual(0, len(warnings)) 261 262 def testExcludedIncludes(self): 263 # #include <sys/...>'s can appear in any order. 264 mock_input_api = MockInputApi() 265 contents = ['#include <sys/b.h>', 266 '#include <sys/a.h>'] 267 mock_file = MockFile('', contents) 268 warnings = PRESUBMIT._CheckIncludeOrderInFile( 269 mock_input_api, mock_file, range(1, len(contents) + 1)) 270 self.assertEqual(0, len(warnings)) 271 272 contents = ['#include <atlbase.h>', 273 '#include <aaa.h>'] 274 mock_file = MockFile('', contents) 275 warnings = PRESUBMIT._CheckIncludeOrderInFile( 276 mock_input_api, mock_file, range(1, len(contents) + 1)) 277 self.assertEqual(0, len(warnings)) 278 279 contents = ['#include "build/build_config.h"', 280 '#include "aaa.h"'] 281 mock_file = MockFile('', contents) 282 warnings = PRESUBMIT._CheckIncludeOrderInFile( 283 mock_input_api, mock_file, range(1, len(contents) + 1)) 284 self.assertEqual(0, len(warnings)) 285 286 def testCheckOnlyCFiles(self): 287 mock_input_api = MockInputApi() 288 mock_output_api = MockOutputApi() 289 contents = ['#include <b.h>', 290 '#include <a.h>'] 291 mock_file_cc = MockFile('something.cc', contents) 292 mock_file_h = MockFile('something.h', contents) 293 mock_file_other = MockFile('something.py', contents) 294 mock_input_api.files = [mock_file_cc, mock_file_h, mock_file_other] 295 warnings = PRESUBMIT._CheckIncludeOrder(mock_input_api, mock_output_api) 296 self.assertEqual(1, len(warnings)) 297 self.assertEqual(2, len(warnings[0].items)) 298 self.assertEqual('promptOrNotify', warnings[0].type) 299 300 def testUncheckableIncludes(self): 301 mock_input_api = MockInputApi() 302 contents = ['#include <windows.h>', 303 '#include "b.h"', 304 '#include "a.h"'] 305 mock_file = MockFile('', contents) 306 warnings = PRESUBMIT._CheckIncludeOrderInFile( 307 mock_input_api, mock_file, range(1, len(contents) + 1)) 308 self.assertEqual(1, len(warnings)) 309 310 contents = ['#include "gpu/command_buffer/gles_autogen.h"', 311 '#include "b.h"', 312 '#include "a.h"'] 313 mock_file = MockFile('', contents) 314 warnings = PRESUBMIT._CheckIncludeOrderInFile( 315 mock_input_api, mock_file, range(1, len(contents) + 1)) 316 self.assertEqual(1, len(warnings)) 317 318 contents = ['#include "gl_mock_autogen.h"', 319 '#include "b.h"', 320 '#include "a.h"'] 321 mock_file = MockFile('', contents) 322 warnings = PRESUBMIT._CheckIncludeOrderInFile( 323 mock_input_api, mock_file, range(1, len(contents) + 1)) 324 self.assertEqual(1, len(warnings)) 325 326 contents = ['#include "ipc/some_macros.h"', 327 '#include "b.h"', 328 '#include "a.h"'] 329 mock_file = MockFile('', contents) 330 warnings = PRESUBMIT._CheckIncludeOrderInFile( 331 mock_input_api, mock_file, range(1, len(contents) + 1)) 332 self.assertEqual(1, len(warnings)) 333 334 335class VersionControlConflictsTest(unittest.TestCase): 336 def testTypicalConflict(self): 337 lines = ['<<<<<<< HEAD', 338 ' base::ScopedTempDir temp_dir_;', 339 '=======', 340 ' ScopedTempDir temp_dir_;', 341 '>>>>>>> master'] 342 errors = PRESUBMIT._CheckForVersionControlConflictsInFile( 343 MockInputApi(), MockFile('some/path/foo_platform.cc', lines)) 344 self.assertEqual(3, len(errors)) 345 self.assertTrue('1' in errors[0]) 346 self.assertTrue('3' in errors[1]) 347 self.assertTrue('5' in errors[2]) 348 349 350class BadExtensionsTest(unittest.TestCase): 351 def testBadRejFile(self): 352 mock_input_api = MockInputApi() 353 mock_input_api.files = [ 354 MockFile('some/path/foo.cc', ''), 355 MockFile('some/path/foo.cc.rej', ''), 356 MockFile('some/path2/bar.h.rej', ''), 357 ] 358 359 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) 360 self.assertEqual(1, len(results)) 361 self.assertEqual(2, len(results[0].items)) 362 self.assertTrue('foo.cc.rej' in results[0].items[0]) 363 self.assertTrue('bar.h.rej' in results[0].items[1]) 364 365 def testBadOrigFile(self): 366 mock_input_api = MockInputApi() 367 mock_input_api.files = [ 368 MockFile('other/path/qux.h.orig', ''), 369 MockFile('other/path/qux.h', ''), 370 MockFile('other/path/qux.cc', ''), 371 ] 372 373 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) 374 self.assertEqual(1, len(results)) 375 self.assertEqual(1, len(results[0].items)) 376 self.assertTrue('qux.h.orig' in results[0].items[0]) 377 378 def testGoodFiles(self): 379 mock_input_api = MockInputApi() 380 mock_input_api.files = [ 381 MockFile('other/path/qux.h', ''), 382 MockFile('other/path/qux.cc', ''), 383 ] 384 results = PRESUBMIT._CheckPatchFiles(mock_input_api, MockOutputApi()) 385 self.assertEqual(0, len(results)) 386 387 def testOnlyOwnersFiles(self): 388 mock_change = MockChange([ 389 'some/path/OWNERS', 390 'A\Windows\Path\OWNERS', 391 ]) 392 results = PRESUBMIT.GetPreferredTryMasters(None, mock_change) 393 self.assertEqual({}, results) 394 395 396class InvalidOSMacroNamesTest(unittest.TestCase): 397 def testInvalidOSMacroNames(self): 398 lines = ['#if defined(OS_WINDOWS)', 399 ' #elif defined(OS_WINDOW)', 400 ' # if defined(OS_MACOSX) || defined(OS_CHROME)', 401 '# else // defined(OS_MAC)', 402 '#endif // defined(OS_MACOS)'] 403 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile( 404 MockInputApi(), MockFile('some/path/foo_platform.cc', lines)) 405 self.assertEqual(len(lines), len(errors)) 406 self.assertTrue(':1 OS_WINDOWS' in errors[0]) 407 self.assertTrue('(did you mean OS_WIN?)' in errors[0]) 408 409 def testValidOSMacroNames(self): 410 lines = ['#if defined(%s)' % m for m in PRESUBMIT._VALID_OS_MACROS] 411 errors = PRESUBMIT._CheckForInvalidOSMacrosInFile( 412 MockInputApi(), MockFile('some/path/foo_platform.cc', lines)) 413 self.assertEqual(0, len(errors)) 414 415 416class CheckAddedDepsHaveTetsApprovalsTest(unittest.TestCase): 417 def testFilesToCheckForIncomingDeps(self): 418 changed_lines = [ 419 '"+breakpad",', 420 '"+chrome/installer",', 421 '"+chrome/plugin/chrome_content_plugin_client.h",', 422 '"+chrome/utility/chrome_content_utility_client.h",', 423 '"+chromeos/chromeos_paths.h",', 424 '"+components/crash",', 425 '"+components/nacl/common",', 426 '"+content/public/browser/render_process_host.h",', 427 '"+jni/fooblat.h",', 428 '"+grit", # For generated headers', 429 '"+grit/generated_resources.h",', 430 '"+grit/",', 431 '"+policy", # For generated headers and source', 432 '"+sandbox",', 433 '"+tools/memory_watcher",', 434 '"+third_party/lss/linux_syscall_support.h",', 435 ] 436 files_to_check = PRESUBMIT._FilesToCheckForIncomingDeps(re, changed_lines) 437 expected = set([ 438 'breakpad/DEPS', 439 'chrome/installer/DEPS', 440 'chrome/plugin/chrome_content_plugin_client.h', 441 'chrome/utility/chrome_content_utility_client.h', 442 'chromeos/chromeos_paths.h', 443 'components/crash/DEPS', 444 'components/nacl/common/DEPS', 445 'content/public/browser/render_process_host.h', 446 'policy/DEPS', 447 'sandbox/DEPS', 448 'tools/memory_watcher/DEPS', 449 'third_party/lss/linux_syscall_support.h', 450 ]) 451 self.assertEqual(expected, files_to_check); 452 453 454class JSONParsingTest(unittest.TestCase): 455 def testSuccess(self): 456 input_api = MockInputApi() 457 filename = 'valid_json.json' 458 contents = ['// This is a comment.', 459 '{', 460 ' "key1": ["value1", "value2"],', 461 ' "key2": 3 // This is an inline comment.', 462 '}' 463 ] 464 input_api.files = [MockFile(filename, contents)] 465 self.assertEqual(None, 466 PRESUBMIT._GetJSONParseError(input_api, filename)) 467 468 def testFailure(self): 469 input_api = MockInputApi() 470 test_data = [ 471 ('invalid_json_1.json', 472 ['{ x }'], 473 'Expecting property name:'), 474 ('invalid_json_2.json', 475 ['// Hello world!', 476 '{ "hello": "world }'], 477 'Unterminated string starting at:'), 478 ('invalid_json_3.json', 479 ['{ "a": "b", "c": "d", }'], 480 'Expecting property name:'), 481 ('invalid_json_4.json', 482 ['{ "a": "b" "c": "d" }'], 483 'Expecting , delimiter:'), 484 ] 485 486 input_api.files = [MockFile(filename, contents) 487 for (filename, contents, _) in test_data] 488 489 for (filename, _, expected_error) in test_data: 490 actual_error = PRESUBMIT._GetJSONParseError(input_api, filename) 491 self.assertTrue(expected_error in str(actual_error), 492 "'%s' not found in '%s'" % (expected_error, actual_error)) 493 494 def testNoEatComments(self): 495 input_api = MockInputApi() 496 file_with_comments = 'file_with_comments.json' 497 contents_with_comments = ['// This is a comment.', 498 '{', 499 ' "key1": ["value1", "value2"],', 500 ' "key2": 3 // This is an inline comment.', 501 '}' 502 ] 503 file_without_comments = 'file_without_comments.json' 504 contents_without_comments = ['{', 505 ' "key1": ["value1", "value2"],', 506 ' "key2": 3', 507 '}' 508 ] 509 input_api.files = [MockFile(file_with_comments, contents_with_comments), 510 MockFile(file_without_comments, 511 contents_without_comments)] 512 513 self.assertEqual('No JSON object could be decoded', 514 str(PRESUBMIT._GetJSONParseError(input_api, 515 file_with_comments, 516 eat_comments=False))) 517 self.assertEqual(None, 518 PRESUBMIT._GetJSONParseError(input_api, 519 file_without_comments, 520 eat_comments=False)) 521 522 523class IDLParsingTest(unittest.TestCase): 524 def testSuccess(self): 525 input_api = MockInputApi() 526 filename = 'valid_idl_basics.idl' 527 contents = ['// Tests a valid IDL file.', 528 'namespace idl_basics {', 529 ' enum EnumType {', 530 ' name1,', 531 ' name2', 532 ' };', 533 '', 534 ' dictionary MyType1 {', 535 ' DOMString a;', 536 ' };', 537 '', 538 ' callback Callback1 = void();', 539 ' callback Callback2 = void(long x);', 540 ' callback Callback3 = void(MyType1 arg);', 541 ' callback Callback4 = void(EnumType type);', 542 '', 543 ' interface Functions {', 544 ' static void function1();', 545 ' static void function2(long x);', 546 ' static void function3(MyType1 arg);', 547 ' static void function4(Callback1 cb);', 548 ' static void function5(Callback2 cb);', 549 ' static void function6(Callback3 cb);', 550 ' static void function7(Callback4 cb);', 551 ' };', 552 '', 553 ' interface Events {', 554 ' static void onFoo1();', 555 ' static void onFoo2(long x);', 556 ' static void onFoo2(MyType1 arg);', 557 ' static void onFoo3(EnumType type);', 558 ' };', 559 '};' 560 ] 561 input_api.files = [MockFile(filename, contents)] 562 self.assertEqual(None, 563 PRESUBMIT._GetIDLParseError(input_api, filename)) 564 565 def testFailure(self): 566 input_api = MockInputApi() 567 test_data = [ 568 ('invalid_idl_1.idl', 569 ['//', 570 'namespace test {', 571 ' dictionary {', 572 ' DOMString s;', 573 ' };', 574 '};'], 575 'Unexpected "{" after keyword "dictionary".\n'), 576 # TODO(yoz): Disabled because it causes the IDL parser to hang. 577 # See crbug.com/363830. 578 # ('invalid_idl_2.idl', 579 # (['namespace test {', 580 # ' dictionary MissingSemicolon {', 581 # ' DOMString a', 582 # ' DOMString b;', 583 # ' };', 584 # '};'], 585 # 'Unexpected symbol DOMString after symbol a.'), 586 ('invalid_idl_3.idl', 587 ['//', 588 'namespace test {', 589 ' enum MissingComma {', 590 ' name1', 591 ' name2', 592 ' };', 593 '};'], 594 'Unexpected symbol name2 after symbol name1.'), 595 ('invalid_idl_4.idl', 596 ['//', 597 'namespace test {', 598 ' enum TrailingComma {', 599 ' name1,', 600 ' name2,', 601 ' };', 602 '};'], 603 'Trailing comma in block.'), 604 ('invalid_idl_5.idl', 605 ['//', 606 'namespace test {', 607 ' callback Callback1 = void(;', 608 '};'], 609 'Unexpected ";" after "(".'), 610 ('invalid_idl_6.idl', 611 ['//', 612 'namespace test {', 613 ' callback Callback1 = void(long );', 614 '};'], 615 'Unexpected ")" after symbol long.'), 616 ('invalid_idl_7.idl', 617 ['//', 618 'namespace test {', 619 ' interace Events {', 620 ' static void onFoo1();', 621 ' };', 622 '};'], 623 'Unexpected symbol Events after symbol interace.'), 624 ('invalid_idl_8.idl', 625 ['//', 626 'namespace test {', 627 ' interface NotEvent {', 628 ' static void onFoo1();', 629 ' };', 630 '};'], 631 'Did not process Interface Interface(NotEvent)'), 632 ('invalid_idl_9.idl', 633 ['//', 634 'namespace test {', 635 ' interface {', 636 ' static void function1();', 637 ' };', 638 '};'], 639 'Interface missing name.'), 640 ] 641 642 input_api.files = [MockFile(filename, contents) 643 for (filename, contents, _) in test_data] 644 645 for (filename, _, expected_error) in test_data: 646 actual_error = PRESUBMIT._GetIDLParseError(input_api, filename) 647 self.assertTrue(expected_error in str(actual_error), 648 "'%s' not found in '%s'" % (expected_error, actual_error)) 649 650 651class TryServerMasterTest(unittest.TestCase): 652 def testTryServerMasters(self): 653 bots = { 654 'tryserver.chromium.gpu': [ 655 'mac_gpu', 656 'mac_gpu_triggered_tests', 657 'linux_gpu', 658 'linux_gpu_triggered_tests', 659 'win_gpu', 660 'win_gpu_triggered_tests', 661 ], 662 'tryserver.chromium.mac': [ 663 'ios_dbg_simulator', 664 'ios_rel_device', 665 'ios_rel_device_ninja', 666 'mac_asan', 667 'mac_asan_64', 668 'mac_chromium_compile_dbg', 669 'mac_chromium_compile_rel', 670 'mac_chromium_dbg', 671 'mac_chromium_rel', 672 'mac_chromium_rel_swarming', 673 'mac_nacl_sdk', 674 'mac_nacl_sdk_build', 675 'mac_rel_naclmore', 676 'mac_valgrind', 677 'mac_x64_rel', 678 'mac_xcodebuild', 679 ], 680 'tryserver.chromium.linux': [ 681 'android_aosp', 682 'android_chromium_gn_compile_dbg', 683 'android_chromium_gn_compile_rel', 684 'android_clang_dbg', 685 'android_dbg', 686 'android_dbg_recipe', 687 'android_dbg_triggered_tests', 688 'android_dbg_triggered_tests_recipe', 689 'android_fyi_dbg', 690 'android_fyi_dbg_triggered_tests', 691 'android_rel', 692 'android_rel_triggered_tests', 693 'android_x86_dbg', 694 'blink_android_compile_dbg', 695 'blink_android_compile_rel', 696 'blink_presubmit', 697 'chromium_presubmit', 698 'linux_arm_cross_compile', 699 'linux_arm_tester', 700 'linux_asan', 701 'linux_browser_asan', 702 'linux_chromeos_asan', 703 'linux_chromeos_browser_asan', 704 'linux_chromeos_valgrind', 705 'linux_chromium_chromeos_clang_dbg', 706 'linux_chromium_chromeos_clang_rel', 707 'linux_chromium_chromeos_dbg', 708 'linux_chromium_chromeos_rel', 709 'linux_chromium_clang_dbg', 710 'linux_chromium_clang_rel', 711 'linux_chromium_compile_dbg', 712 'linux_chromium_compile_rel', 713 'linux_chromium_dbg', 714 'linux_chromium_gn_dbg', 715 'linux_chromium_gn_rel', 716 'linux_chromium_rel', 717 'linux_chromium_rel_swarming', 718 'linux_chromium_trusty32_dbg', 719 'linux_chromium_trusty32_rel', 720 'linux_chromium_trusty_dbg', 721 'linux_chromium_trusty_rel', 722 'linux_clang_tsan', 723 'linux_ecs_ozone', 724 'linux_layout', 725 'linux_layout_asan', 726 'linux_layout_rel', 727 'linux_layout_rel_32', 728 'linux_nacl_sdk', 729 'linux_nacl_sdk_bionic', 730 'linux_nacl_sdk_bionic_build', 731 'linux_nacl_sdk_build', 732 'linux_redux', 733 'linux_rel_naclmore', 734 'linux_rel_precise32', 735 'linux_valgrind', 736 'tools_build_presubmit', 737 ], 738 'tryserver.chromium.win': [ 739 'win8_aura', 740 'win8_chromium_dbg', 741 'win8_chromium_rel', 742 'win_chromium_compile_dbg', 743 'win_chromium_compile_rel', 744 'win_chromium_dbg', 745 'win_chromium_rel', 746 'win_chromium_rel', 747 'win_chromium_rel_swarming', 748 'win_chromium_rel_swarming', 749 'win_chromium_x64_dbg', 750 'win_chromium_x64_rel', 751 'win_drmemory', 752 'win_nacl_sdk', 753 'win_nacl_sdk_build', 754 'win_rel_naclmore', 755 ], 756 } 757 for master, bots in bots.iteritems(): 758 for bot in bots: 759 self.assertEqual(master, PRESUBMIT.GetTryServerMasterForBot(bot), 760 'bot=%s: expected %s, computed %s' % ( 761 bot, master, PRESUBMIT.GetTryServerMasterForBot(bot))) 762 763 764if __name__ == '__main__': 765 unittest.main() 766