|  | #!/usr/bin/env vpython3 | 
|  |  | 
|  | #  Copyright 2017 The WebRTC project authors. All Rights Reserved. | 
|  | # | 
|  | #  Use of this source code is governed by a BSD-style license | 
|  | #  that can be found in the LICENSE file in the root of the source | 
|  | #  tree. An additional intellectual property rights grant can be found | 
|  | #  in the file PATENTS.  All contributing project authors may | 
|  | #  be found in the AUTHORS file in the root of the source tree. | 
|  |  | 
|  | from __future__ import absolute_import | 
|  | import os | 
|  | import shutil | 
|  | import tempfile | 
|  | import textwrap | 
|  | import unittest | 
|  |  | 
|  | import PRESUBMIT | 
|  | # pylint: disable=line-too-long | 
|  | from presubmit_test_mocks import MockInputApi, MockOutputApi, MockFile, MockChange | 
|  |  | 
|  |  | 
|  | class CheckBugEntryFieldTest(unittest.TestCase): | 
|  | def testCommitMessageBugEntryWithNoError(self): | 
|  | mock_input_api = MockInputApi() | 
|  | mock_output_api = MockOutputApi() | 
|  | mock_input_api.change = MockChange([], ['webrtc:1234']) | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  | def testCommitMessageBugEntryReturnError(self): | 
|  | mock_input_api = MockInputApi() | 
|  | mock_output_api = MockOutputApi() | 
|  | mock_input_api.change = MockChange([], ['webrtc:1234', 'webrtc=4321']) | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual(('Bogus Bug entry: webrtc=4321. Please specify' | 
|  | ' the issue tracker prefix and the issue number,' | 
|  | ' separated by a colon, e.g. webrtc:123 or' | 
|  | ' chromium:12345.'), str(errors[0])) | 
|  |  | 
|  | def testCommitMessageBugEntryWithoutPrefix(self): | 
|  | mock_input_api = MockInputApi() | 
|  | mock_output_api = MockOutputApi() | 
|  | mock_input_api.change = MockChange([], ['1234']) | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual(('Bug entry requires issue tracker prefix, ' | 
|  | 'e.g. webrtc:1234'), str(errors[0])) | 
|  |  | 
|  | def testCommitMessageBugEntryIsNone(self): | 
|  | mock_input_api = MockInputApi() | 
|  | mock_output_api = MockOutputApi() | 
|  | mock_input_api.change = MockChange([], ['None']) | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  | def testCommitMessageBugEntrySupportInternalBugReference(self): | 
|  | mock_input_api = MockInputApi() | 
|  | mock_output_api = MockOutputApi() | 
|  | mock_input_api.change.BUG = 'b/12345' | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(0, len(errors)) | 
|  | mock_input_api.change.BUG = 'b/12345, webrtc:1234' | 
|  | errors = PRESUBMIT.CheckCommitMessageBugEntry(mock_input_api, | 
|  | mock_output_api) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  |  | 
|  | class CheckNewlineAtTheEndOfProtoFilesTest(unittest.TestCase): | 
|  | def setUp(self): | 
|  | self.tmp_dir = tempfile.mkdtemp() | 
|  | self.proto_file_path = os.path.join(self.tmp_dir, 'foo.proto') | 
|  | self.input_api = MockInputApi() | 
|  | self.output_api = MockOutputApi() | 
|  |  | 
|  | def tearDown(self): | 
|  | shutil.rmtree(self.tmp_dir, ignore_errors=True) | 
|  |  | 
|  | def testErrorIfProtoFileDoesNotEndWithNewline(self): | 
|  | self._GenerateProtoWithoutNewlineAtTheEnd() | 
|  | self.input_api.files = [MockFile(self.proto_file_path)] | 
|  | errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles( | 
|  | self.input_api, self.output_api, lambda x: True) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual( | 
|  | 'File %s must end with exactly one newline.' % self.proto_file_path, | 
|  | str(errors[0])) | 
|  |  | 
|  | def testNoErrorIfProtoFileEndsWithNewline(self): | 
|  | self._GenerateProtoWithNewlineAtTheEnd() | 
|  | self.input_api.files = [MockFile(self.proto_file_path)] | 
|  | errors = PRESUBMIT.CheckNewlineAtTheEndOfProtoFiles( | 
|  | self.input_api, self.output_api, lambda x: True) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  | def _GenerateProtoWithNewlineAtTheEnd(self): | 
|  | with open(self.proto_file_path, 'w') as f: | 
|  | f.write( | 
|  | textwrap.dedent(""" | 
|  | syntax = "proto2"; | 
|  | option optimize_for = LITE_RUNTIME; | 
|  | package webrtc.audioproc; | 
|  | """)) | 
|  |  | 
|  | def _GenerateProtoWithoutNewlineAtTheEnd(self): | 
|  | with open(self.proto_file_path, 'w') as f: | 
|  | f.write( | 
|  | textwrap.dedent(""" | 
|  | syntax = "proto2"; | 
|  | option optimize_for = LITE_RUNTIME; | 
|  | package webrtc.audioproc;""")) | 
|  |  | 
|  |  | 
|  | class CheckNoMixingSourcesTest(unittest.TestCase): | 
|  | def setUp(self): | 
|  | self.tmp_dir = tempfile.mkdtemp() | 
|  | self.file_path = os.path.join(self.tmp_dir, 'BUILD.gn') | 
|  | self.input_api = MockInputApi() | 
|  | self.output_api = MockOutputApi() | 
|  |  | 
|  | def tearDown(self): | 
|  | shutil.rmtree(self.tmp_dir, ignore_errors=True) | 
|  |  | 
|  | def testErrorIfCAndCppAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.cc', 'bar.h']) | 
|  |  | 
|  | def testErrorIfCAndObjCAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.m', 'bar.h']) | 
|  |  | 
|  | def testErrorIfCAndObjCppAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(1, ['foo.c', 'bar.mm', 'bar.h']) | 
|  |  | 
|  | def testErrorIfCppAndObjCAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.m', 'bar.h']) | 
|  |  | 
|  | def testErrorIfCppAndObjCppAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(1, ['foo.cc', 'bar.mm', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfOnlyC(self): | 
|  | self._AssertNumberOfErrorsWithSources(0, ['foo.c', 'bar.c', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfOnlyCpp(self): | 
|  | self._AssertNumberOfErrorsWithSources(0, ['foo.cc', 'bar.cc', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfOnlyObjC(self): | 
|  | self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.m', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfOnlyObjCpp(self): | 
|  | self._AssertNumberOfErrorsWithSources(0, ['foo.mm', 'bar.mm', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfObjCAndObjCppAreMixed(self): | 
|  | self._AssertNumberOfErrorsWithSources(0, ['foo.m', 'bar.mm', 'bar.h']) | 
|  |  | 
|  | def testNoErrorIfSourcesAreInExclusiveIfBranches(self): | 
|  | self._GenerateBuildFile( | 
|  | textwrap.dedent(""" | 
|  | rtc_library("bar_foo") { | 
|  | if (is_win) { | 
|  | sources = [ | 
|  | "bar.cc", | 
|  | ], | 
|  | } | 
|  | if (is_ios) { | 
|  | sources = [ | 
|  | "bar.mm", | 
|  | ], | 
|  | } | 
|  | } | 
|  | rtc_library("foo_bar") { | 
|  | if (is_win) { | 
|  | sources = [ | 
|  | "foo.cc", | 
|  | ], | 
|  | } | 
|  | if (is_ios) { | 
|  | sources = [ | 
|  | "foo.mm", | 
|  | ], | 
|  | } | 
|  | } | 
|  | """)) | 
|  | self.input_api.files = [MockFile(self.file_path)] | 
|  | errors = PRESUBMIT.CheckNoMixingSources(self.input_api, | 
|  | [MockFile(self.file_path)], | 
|  | self.output_api) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  | def testErrorIfSourcesAreNotInExclusiveIfBranches(self): | 
|  | self._GenerateBuildFile( | 
|  | textwrap.dedent(""" | 
|  | rtc_library("bar_foo") { | 
|  | if (is_win) { | 
|  | sources = [ | 
|  | "bar.cc", | 
|  | ], | 
|  | } | 
|  | if (foo_bar) { | 
|  | sources += [ | 
|  | "bar.mm", | 
|  | ], | 
|  | } | 
|  | } | 
|  | rtc_library("foo_bar") { | 
|  | if (is_win) { | 
|  | sources = [ | 
|  | "foo.cc", | 
|  | ], | 
|  | } | 
|  | if (foo_bar) { | 
|  | sources += [ | 
|  | "foo.mm", | 
|  | ], | 
|  | } | 
|  | if (is_ios) { | 
|  | sources = [ | 
|  | "bar.m", | 
|  | "bar.c", | 
|  | ], | 
|  | } | 
|  | } | 
|  | """)) | 
|  | self.input_api.files = [MockFile(self.file_path)] | 
|  | errors = PRESUBMIT.CheckNoMixingSources(self.input_api, | 
|  | [MockFile(self.file_path)], | 
|  | self.output_api) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertTrue('bar.cc' in str(errors[0])) | 
|  | self.assertTrue('bar.mm' in str(errors[0])) | 
|  | self.assertTrue('foo.cc' in str(errors[0])) | 
|  | self.assertTrue('foo.mm' in str(errors[0])) | 
|  | self.assertTrue('bar.m' in str(errors[0])) | 
|  | self.assertTrue('bar.c' in str(errors[0])) | 
|  |  | 
|  | def _AssertNumberOfErrorsWithSources(self, number_of_errors, sources): | 
|  | assert len(sources) == 3, 'This function accepts a list of 3 source files' | 
|  | self._GenerateBuildFile( | 
|  | textwrap.dedent(""" | 
|  | rtc_static_library("bar_foo") { | 
|  | sources = [ | 
|  | "%s", | 
|  | "%s", | 
|  | "%s", | 
|  | ], | 
|  | } | 
|  | rtc_library("foo_bar") { | 
|  | sources = [ | 
|  | "%s", | 
|  | "%s", | 
|  | "%s", | 
|  | ], | 
|  | } | 
|  | """ % (tuple(sources) * 2))) | 
|  | self.input_api.files = [MockFile(self.file_path)] | 
|  | errors = PRESUBMIT.CheckNoMixingSources(self.input_api, | 
|  | [MockFile(self.file_path)], | 
|  | self.output_api) | 
|  | self.assertEqual(number_of_errors, len(errors)) | 
|  | if number_of_errors == 1: | 
|  | for source in sources: | 
|  | if not source.endswith('.h'): | 
|  | self.assertTrue(source in str(errors[0])) | 
|  |  | 
|  | def _GenerateBuildFile(self, content): | 
|  | with open(self.file_path, 'w') as f: | 
|  | f.write(content) | 
|  |  | 
|  |  | 
|  | class CheckAssertUsageTest(unittest.TestCase): | 
|  | def setUp(self): | 
|  | self.input_api = MockInputApi() | 
|  | self.output_api = MockOutputApi() | 
|  | self._content_with_assert = ['void Foo() {', '    assert(true);', '}'] | 
|  | self._content_without_assert = ['void Foo() {', '    RTC_CHECK(true);', '}'] | 
|  |  | 
|  | def testDetectsAssertInCcFile(self): | 
|  | self.input_api.files = [ | 
|  | MockFile('with_assert.cc', self._content_with_assert), | 
|  | MockFile('without_assert.cc', self._content_without_assert), | 
|  | ] | 
|  | errors = PRESUBMIT.CheckAssertUsage(self.input_api, | 
|  | self.output_api, lambda x: True) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual('with_assert.cc', errors[0].items[0]) | 
|  |  | 
|  | def testDetectsAssertInHeaderFile(self): | 
|  | self.input_api.files = [ | 
|  | MockFile('with_assert.h', self._content_with_assert), | 
|  | MockFile('without_assert.h', self._content_without_assert), | 
|  | ] | 
|  | errors = PRESUBMIT.CheckAssertUsage(self.input_api, | 
|  | self.output_api, lambda x: True) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual('with_assert.h', errors[0].items[0]) | 
|  |  | 
|  | def testDetectsAssertInObjCFile(self): | 
|  | self.input_api.files = [ | 
|  | MockFile('with_assert.m', self._content_with_assert), | 
|  | MockFile('without_assert.m', self._content_without_assert), | 
|  | ] | 
|  | errors = PRESUBMIT.CheckAssertUsage(self.input_api, | 
|  | self.output_api, lambda x: True) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual('with_assert.m', errors[0].items[0]) | 
|  |  | 
|  | def testDetectsAssertInObjCppFile(self): | 
|  | self.input_api.files = [ | 
|  | MockFile('with_assert.mm', self._content_with_assert), | 
|  | MockFile('without_assert.mm', self._content_without_assert), | 
|  | ] | 
|  | errors = PRESUBMIT.CheckAssertUsage(self.input_api, | 
|  | self.output_api, lambda x: True) | 
|  | self.assertEqual(1, len(errors)) | 
|  | self.assertEqual('with_assert.mm', errors[0].items[0]) | 
|  |  | 
|  | def testDoesntDetectAssertInOtherFiles(self): | 
|  | self.input_api.files = [ | 
|  | MockFile('with_assert.cpp', self._content_with_assert), | 
|  | ] | 
|  | errors = PRESUBMIT.CheckAssertUsage(self.input_api, | 
|  | self.output_api, lambda x: True) | 
|  | self.assertEqual(0, len(errors)) | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | unittest.main() |