#!/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()