chromium/third_party/blink/web_tests/external/PRESUBMIT_test.py

#!/usr/bin/env vpython3
# Copyright 2018 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import shutil
import subprocess
import sys
import unittest

import PRESUBMIT


class MockInputApi(object):
    """A minimal mock InputApi for our checks."""

    def __init__(self):
        self.affected_paths = []
        self.sys = sys
        self.os_path = os.path
        self.python_executable = self.python3_executable = sys.executable
        self.subprocess = subprocess
        self.is_windows = sys.platform == 'win32'
        self.environ = os.environ
        self.logging = PrintLogger()
        self.change = MockChange()
        self.no_diffs = False

    def AbsoluteLocalPaths(self):
        return self.affected_paths

    def PresubmitLocalPath(self):
        return os.path.abspath(os.path.dirname(__file__))

    def AffectedSourceFiles(self, filter_func):
        all_files = [MockFile(self.PresubmitLocalPath(), path) for path in self.affected_paths]
        return filter(lambda f: filter_func(f), all_files)


class MockChange(object):
    """A minimal mock Change for our checks."""

    def RepositoryRoot(self):
        here = os.path.dirname(__file__)
        return os.path.abspath(os.path.join(here, '..', '..', '..', '..'))


class PrintLogger(object):
    """A simple logger that just prints log messages."""

    def debug(self, message):
        print(message)


class MockPresubmitError(object):
    """A minimal mock of an error class for our checks."""

    def __init__(self, message, items, long_text):
        self.message = message
        self.items = items
        self.long_text = long_text

    def __repr__(self):
        return self.message + "\n" + self.long_text


class MockPresubmitWarning(object):
    """A minimal mock of an warning class for our checks."""

    def __init__(self, message, items, long_text):
        self.message = message
        self.items = items
        self.long_text = long_text


class MockOutputApi(object):
    """A minimal mock OutputApi for our checks."""

    def PresubmitError(self, message, items=None, long_text=''):
        return MockPresubmitError(message, items, long_text)

    def PresubmitPromptWarning(self, message, items=None, long_text=''):
        return MockPresubmitWarning(message, items, long_text)


class MockFile(object):
    """A minimal mock File for our checks."""

    def __init__(self, presubmit_abs_path, file_abs_path):
        self.abs_path = file_abs_path
        self.local_path = os.path.relpath(file_abs_path, presubmit_abs_path)

    def AbsoluteLocalPath(self):
        return self.abs_path

    def LocalPath(self):
        return self.local_path


class LintWPTTest(unittest.TestCase):
    def setUp(self):
        self._test_file = os.path.join(os.path.dirname(__file__), 'wpt', '_DO_NOT_SUBMIT_.html')
        self._ignored_directory = os.path.join(os.path.dirname(__file__), 'wpt', 'css', '_DNS_')

    def tearDown(self):
        if os.path.exists(self._test_file):
            os.remove(self._test_file)
        if os.path.exists(self._ignored_directory):
            shutil.rmtree(self._ignored_directory)

    def testWPTLintSuccess(self):
        with open(self._test_file, 'w') as f:
            f.write('<body>Hello, world!</body>')
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [os.path.abspath(self._test_file)]
        errors = PRESUBMIT._LintWPT(mock_input, mock_output)
        self.assertEqual(errors, [])

    def testWPTLintErrors(self):
        # Private LayoutTests APIs are not allowed.
        with open(self._test_file, 'w') as f:
            f.write('<script>testRunner.notifyDone()</script>')
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [os.path.abspath(self._test_file)]
        errors = PRESUBMIT._LintWPT(mock_input, mock_output)
        self.assertEqual(len(errors), 1)
        self.assertTrue(isinstance(errors[0], MockPresubmitError))

    def testWPTLintIgnore(self):
        os.mkdir(self._ignored_directory)
        files = []
        for f in ['DIR_METADATA', 'OWNERS', 'test-expected.txt']:
            path = os.path.abspath(os.path.join(self._ignored_directory, f))
            files.append(path)
            open(path, 'w').close()
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = files
        errors = PRESUBMIT._LintWPT(mock_input, mock_output)
        self.assertEqual(errors, [])


class DontModifyIDLFilesTest(unittest.TestCase):
    def testModifiesIDL(self):
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [os.path.join(mock_input.PresubmitLocalPath(), 'wpt', 'interfaces', 'test.idl')]
        errors = PRESUBMIT._DontModifyIDLFiles(mock_input, mock_output)
        self.assertEqual(len(errors), 1)
        self.assertTrue(isinstance(errors[0], MockPresubmitWarning))

    def testModifiesNonIDLFiles(self):
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [os.path.join(mock_input.PresubmitLocalPath(), 'wpt', 'css', 'foo.html')]
        errors = PRESUBMIT._DontModifyIDLFiles(mock_input, mock_output)
        self.assertEqual(errors, [])

    def testModifiesInterfaceDirOutsideOfWPT(self):
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [os.path.join(mock_input.PresubmitLocalPath(), 'other', 'interfaces', 'test.idl')]
        errors = PRESUBMIT._DontModifyIDLFiles(mock_input, mock_output)
        self.assertEqual(errors, [])

    def testModifiesTentativeIDL(self):
        mock_input = MockInputApi()
        mock_output = MockOutputApi()
        mock_input.affected_paths = [
            os.path.join(mock_input.PresubmitLocalPath(), 'wpt', 'interfaces',
                         'test.tentative.idl')
        ]
        errors = PRESUBMIT._DontModifyIDLFiles(mock_input, mock_output)
        self.assertEqual(errors, [])


if __name__ == '__main__':
    unittest.main()