| #!/usr/bin/env python |
| # Copyright 2014 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Unit tests for Copyright Scanner utilities.""" |
| |
| import os |
| import re |
| import sys |
| import unittest |
| |
| test_dir = os.path.dirname(os.path.abspath(__file__)) |
| sys.path.extend([ |
| os.path.normpath(os.path.join(test_dir, '..', '..', 'tools')), |
| os.path.join(test_dir), |
| ]) |
| |
| import find_depot_tools |
| from testing_support.super_mox import SuperMoxTestBase |
| |
| import copyright_scanner |
| |
| class FindCopyrightsTest(SuperMoxTestBase): |
| def setUp(self): |
| SuperMoxTestBase.setUp(self) |
| self.input_api = self.mox.CreateMockAnything() |
| self.input_api.re = re |
| self.input_api.os_path = os.path |
| self.input_api.os_walk = os.walk |
| |
| def ShouldMatchReferenceOutput(self, test_data, expected_output): |
| for data in test_data: |
| self.input_api.ReadFile = lambda _1, _2: data |
| actual_output = copyright_scanner.FindCopyrights(self.input_api, '', ['']) |
| self.assertEqual( |
| expected_output, |
| actual_output, |
| 'Input """\n%s""", expected output: "%s", actual: "%s"' % \ |
| (data, expected_output, actual_output)); |
| |
| def testCopyrightedFiles(self): |
| test_data = [ |
| '// (c) 2014 Google Inc.\n//\n// (a) One\n//\n// (b) Two\n//\n', |
| 'Copyright 2014 Google Inc.\n', |
| 'Copr. 2014 Google Inc.', |
| '\xc2\xa9 2014 Google Inc.', |
| 'Copyright 2014 Google Inc.' |
| ] |
| self.ShouldMatchReferenceOutput(test_data, [['2014 Google Inc.']]) |
| |
| def testGeneratedFiles(self): |
| test_data = [ |
| 'ALL CHANGES MADE IN THIS FILE WILL BE LOST\nCopyright 2014 Google\n', |
| 'GENERATED FILE. DO NOT EDIT\nCopyright 2014 Google\n', |
| 'GENERATED. DO NOT DELETE THIS FILE.\nCopyright 2014 Google\n', |
| 'DO NOT EDIT\nCopyright 2014 Google\n', |
| 'DO NOT DELETE THIS FILE\nCopyright 2014 Google\n', |
| 'All changes made in this file will be lost\nCopyright 2014 Google\n', |
| 'Automatically generated file\nCopyright 2014 Google\n', |
| 'Synthetically generated dummy file\nCopyright 2014 Google\n', |
| 'Generated data (by gnugnu)\nCopyright 2014 Google\n' |
| ] |
| self.ShouldMatchReferenceOutput(test_data, [['GENERATED FILE']]) |
| |
| def testNonCopyrightedFiles(self): |
| test_data = [ |
| 'std::cout << "Copyright 2014 Google"\n', |
| '// Several points can be made:\n//\n// (a) One\n//\n// (b) Two\n' |
| '//\n// (c) Three\n//\n', |
| 'See \'foo\' for copyright information.\n', |
| 'See \'foo\' for the copyright notice.\n', |
| 'See \'foo\' for the copyright and other things.\n' |
| ] |
| self.ShouldMatchReferenceOutput(test_data, [['*No copyright*']]) |
| |
| def testNonGeneratedFiles(self): |
| test_data = [ |
| 'This file was prohibited from being generated.\n', |
| 'Please do not delete our files! They are valuable to us.\n', |
| 'Manually generated from dice rolls.\n', |
| '"""This Python script produces generated data\n"""\n', |
| '\'\'\'This Python script produces generated data\n\'\'\'\n' |
| ] |
| self.ShouldMatchReferenceOutput(test_data, [['*No copyright*']]) |
| |
| |
| class FindFilesTest(SuperMoxTestBase): |
| def setUp(self): |
| SuperMoxTestBase.setUp(self) |
| self.input_api = self.mox.CreateMockAnything() |
| self.input_api.re = re |
| self.input_api.os_path = os.path |
| |
| def testFilesAsStartPaths(self): |
| self.input_api.os_path.isfile = lambda _: True |
| input_files = [ |
| 'a', |
| 'a.cc', |
| 'a.txt', |
| 'foo/a', |
| 'foo/a.cc', |
| 'foo/a.txt', |
| 'third_party/a', |
| 'third_party/a.cc', |
| 'third_party/a.txt', |
| 'foo/third_party/a', |
| 'foo/third_party/a.cc' |
| 'foo/third_party/a.txt', |
| ] |
| root_dir = '/src' |
| actual = copyright_scanner.FindFiles( |
| self.input_api, root_dir, input_files, ['']) |
| self.assertEqual(['a.cc', 'foo/a.cc'], actual) |
| actual = copyright_scanner.FindFiles( |
| self.input_api, root_dir, input_files, ['third_party']) |
| self.assertEqual(['a.cc', 'foo/a.cc'], actual) |
| actual = copyright_scanner.FindFiles( |
| self.input_api, root_dir, input_files, ['foo']) |
| self.assertEqual(['a.cc'], actual) |
| actual = copyright_scanner.FindFiles( |
| self.input_api, root_dir, input_files, ['foo', 'third_party']) |
| self.assertEqual(['a.cc'], actual) |
| actual = copyright_scanner.FindFiles( |
| self.input_api, root_dir, input_files, ['foo/third_party']) |
| self.assertEqual(['a.cc', 'foo/a.cc'], actual) |
| |
| def testDirAsStartPath(self): |
| self.input_api.os_path.isfile = lambda _: False |
| join = self.input_api.os_path.join |
| normpath = self.input_api.os_path.normpath |
| root_dir = '/src' |
| scan_from = '.' |
| base_path = join(root_dir, scan_from) |
| |
| def mock_os_walk(path): |
| return lambda _: [(join(base_path, path), [''], ['a', 'a.cc', 'a.txt'])] |
| |
| self.input_api.os_walk = mock_os_walk('') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], [''])) |
| self.assertEqual(['a.cc'], actual) |
| |
| self.input_api.os_walk = mock_os_walk('third_party') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], [''])) |
| self.assertEqual([], actual) |
| |
| self.input_api.os_walk = mock_os_walk('foo') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], [''])) |
| self.assertEqual(['foo/a.cc'], actual) |
| |
| self.input_api.os_walk = mock_os_walk('foo') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], ['foo'])) |
| self.assertEqual([], actual) |
| |
| self.input_api.os_walk = mock_os_walk('foo/bar') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], ['foo'])) |
| self.assertEqual([], actual) |
| |
| self.input_api.os_walk = mock_os_walk('foo/third_party') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], [''])) |
| self.assertEqual([], actual) |
| |
| self.input_api.os_walk = mock_os_walk('foo/third_party') |
| actual = map(normpath, copyright_scanner.FindFiles( |
| self.input_api, root_dir, [scan_from], ['foo/third_party'])) |
| self.assertEqual([], actual) |
| |
| |
| class AnalyzeScanResultsTest(SuperMoxTestBase): |
| def setUp(self): |
| SuperMoxTestBase.setUp(self) |
| self.input_api = self.mox.CreateMockAnything() |
| self.input_api.os_path = os.path |
| |
| def testAnalyzeScanResults(self): |
| # Tests whitelisted vs. current files state logic. |
| # |
| # Whitelisted - in whitelist, and contains 3rd party code => OK |
| # Missing - in whitelist, but doesn't exist |
| # Stale - in whitelist, but is clean |
| # Unknown - not in whitelist, but contains 3rd party code |
| self.input_api.os_path.isfile = lambda x: x != 'Missing' |
| self.assertEqual( |
| (['Unknown'], ['Missing'], ['Stale']), |
| copyright_scanner.AnalyzeScanResults(self.input_api, \ |
| ['Whitelisted', 'Missing', 'Stale'], ['Whitelisted', 'Unknown'])) |
| |
| |
| class ScanAtPresubmitTest(SuperMoxTestBase): |
| def setUp(self): |
| SuperMoxTestBase.setUp(self) |
| self.input_api = self.mox.CreateMockAnything() |
| self.input_api.re = re |
| self.input_api.os_path = os.path |
| self.output_api = self.mox.CreateMockAnything() |
| def tearDown(self): |
| self.mox.UnsetStubs() |
| SuperMoxTestBase.tearDown(self) |
| |
| class AffectedFileMock(object): |
| def __init__(self, local_path, action): |
| self._local_path = local_path |
| self._action = action |
| def LocalPath(self): |
| return self._local_path |
| def Action(self): |
| return self._action |
| |
| def CreateAffectedFilesFunc(self, paths_and_actions): |
| result = [] |
| for i in range(0, len(paths_and_actions), 2): |
| result.append(ScanAtPresubmitTest.AffectedFileMock( |
| paths_and_actions[i], paths_and_actions[i + 1])) |
| return lambda: result |
| |
| def CreateDoScanAtPresubmitFunc(self): |
| self._whitelisted_files = None |
| self._files_to_check = None |
| def ScanAtPresubmitStub(_, whitelisted, to_check): |
| self._whitelisted_files = whitelisted |
| self._files_to_check = to_check |
| return ([], [], []) |
| return ScanAtPresubmitStub |
| |
| def GetWhitelistedFiles(self): |
| return sorted(self._whitelisted_files) |
| |
| def GetFilesToCheck(self): |
| return sorted(self._files_to_check) |
| |
| def testWhitelistedUntouched(self): |
| # When a change doesn't touch the whitelist file, any updated files |
| # (except deleted) must be checked. The whitelist used for analysis |
| # must be trimmed to the changed files subset. |
| # |
| # A_NW.cc - added, not whitelisted => check |
| # A_W.cc - added, whitelisted => check, remain on the trimmed whitelist |
| # D_NW.cc - deleted, not whitelisted => ignore |
| # D_W.cc - deleted and whitelisted => remain on w/l |
| # M_NW.cc - modified, not whitelisted => check |
| # M_W.cc - modified and whitelisted => check, remain on w/l |
| # NM_W.cc - not modified, whitelisted => trim from w/l |
| # W - the whitelist file |
| |
| self.input_api.AffectedFiles = self.CreateAffectedFilesFunc( |
| ['A_NW.cc', 'A', 'A_W.cc', 'A', 'D_NW.cc', 'D', 'D_W.cc', 'D', |
| 'M_NW.cc', 'M', 'M_W.cc', 'M']) |
| self.mox.StubOutWithMock(copyright_scanner, '_GetWhitelistFileName') |
| copyright_scanner._GetWhitelistFileName = lambda _: 'W' |
| self.mox.StubOutWithMock(copyright_scanner, 'LoadWhitelistedFilesList') |
| copyright_scanner.LoadWhitelistedFilesList = \ |
| lambda _: ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc'] |
| self.mox.StubOutWithMock(copyright_scanner, '_DoScanAtPresubmit') |
| copyright_scanner._DoScanAtPresubmit = self.CreateDoScanAtPresubmitFunc() |
| self.mox.ReplayAll() |
| copyright_scanner.ScanAtPresubmit(self.input_api, self.output_api) |
| self.assertEqual( |
| ['A_W.cc', 'D_W.cc', 'M_W.cc'], self.GetWhitelistedFiles()) |
| self.assertEqual( |
| ['A_NW.cc', 'A_W.cc', 'M_NW.cc', 'M_W.cc'], self.GetFilesToCheck()) |
| |
| def testWhitelistTouched(self): |
| # When the whitelist file is touched by the change, all the files listed in |
| # it, including deleted entries, must be re-checked. All modified files |
| # (including the deleted ones) must be checked as well. The current contents |
| # of the whitelist are used for analysis. |
| # Whitelist addition or deletion are not considered. |
| # |
| # All the files from names testWhitelistedUntouched are re-used, but now |
| # action for all of them is 'check' (except for the w/l file itself). |
| # A_DW.cc - added, deleted from w/l => check |
| # D_DW.cc - deleted from repo and w/l => check |
| # M_DW.cc - modified, deleted from w/l => check |
| self.input_api.AffectedFiles = self.CreateAffectedFilesFunc( |
| ['A_DW.cc', 'A', 'A_NW.cc', 'A', 'A_W.cc', 'A', |
| 'D_DW.cc', 'D', 'D_NW.cc', 'D', 'D_W.cc', 'D', |
| 'M_DW.cc', 'M', 'M_NW.cc', 'M', 'M_W.cc', 'M', 'W', 'M']) |
| self.mox.StubOutWithMock(copyright_scanner, '_GetWhitelistFileName') |
| copyright_scanner._GetWhitelistFileName = lambda _: 'W' |
| self.mox.StubOutWithMock(copyright_scanner, '_GetDeletedContents') |
| def GetDeletedContentsStub(affected_file): |
| self.assertEqual('W', affected_file.LocalPath()) |
| return ['A_DW.cc', 'D_DW.cc', 'M_DW.cc'] |
| copyright_scanner._GetDeletedContents = GetDeletedContentsStub |
| self.mox.StubOutWithMock(copyright_scanner, 'LoadWhitelistedFilesList') |
| copyright_scanner.LoadWhitelistedFilesList = \ |
| lambda _: ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc'] |
| self.mox.StubOutWithMock(copyright_scanner, '_DoScanAtPresubmit') |
| copyright_scanner._DoScanAtPresubmit = self.CreateDoScanAtPresubmitFunc() |
| self.mox.ReplayAll() |
| copyright_scanner.ScanAtPresubmit(self.input_api, self.output_api) |
| self.assertEqual( |
| ['A_W.cc', 'D_W.cc', 'M_W.cc', 'NM_W.cc'], self.GetWhitelistedFiles()) |
| self.assertEqual( |
| ['A_DW.cc', 'A_NW.cc', 'A_W.cc', 'D_DW.cc', 'D_NW.cc', 'D_W.cc', |
| 'M_DW.cc', 'M_NW.cc', 'M_W.cc', 'NM_W.cc' ], self.GetFilesToCheck()) |
| |
| if __name__ == '__main__': |
| unittest.main() |