1# Copyright (C) 2012 Google Inc. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7#     * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9#     * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13#     * Neither the name of Google Inc. nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29import optparse
30import StringIO
31import webkitpy.thirdparty.unittest2 as unittest
32
33from webkitpy.common.host_mock import MockHost
34from webkitpy.layout_tests import lint_test_expectations
35
36
37class FakePort(object):
38    def __init__(self, host, name, path):
39        self.host = host
40        self.name = name
41        self.path = path
42
43    def test_configuration(self):
44        return None
45
46    def expectations_dict(self):
47        self.host.ports_parsed.append(self.name)
48        return {self.path: ''}
49
50    def bot_expectations(self):
51        return {}
52
53    def skipped_layout_tests(self, _):
54        return set([])
55
56    def all_test_configurations(self):
57        return []
58
59    def configuration_specifier_macros(self):
60        return []
61
62    def get_option(self, _, val):
63        return val
64
65    def path_to_generic_test_expectations_file(self):
66        return ''
67
68class FakeFactory(object):
69    def __init__(self, host, ports):
70        self.host = host
71        self.ports = {}
72        for port in ports:
73            self.ports[port.name] = port
74
75    def get(self, port_name, *args, **kwargs):  # pylint: disable=W0613,E0202
76        return self.ports[port_name]
77
78    def all_port_names(self, platform=None):  # pylint: disable=W0613,E0202
79        return sorted(self.ports.keys())
80
81
82class LintTest(unittest.TestCase):
83    def test_all_configurations(self):
84        host = MockHost()
85        host.ports_parsed = []
86        host.port_factory = FakeFactory(host, (FakePort(host, 'a', 'path-to-a'),
87                                               FakePort(host, 'b', 'path-to-b'),
88                                               FakePort(host, 'b-win', 'path-to-b')))
89
90        logging_stream = StringIO.StringIO()
91        options = optparse.Values({'platform': None})
92        res = lint_test_expectations.lint(host, options, logging_stream)
93        self.assertEqual(res, 0)
94        self.assertEqual(host.ports_parsed, ['a', 'b', 'b-win'])
95
96    def test_lint_test_files(self):
97        logging_stream = StringIO.StringIO()
98        options = optparse.Values({'platform': 'test-mac-leopard'})
99        host = MockHost()
100
101        # pylint appears to complain incorrectly about the method overrides pylint: disable=E0202,C0322
102        # FIXME: incorrect complaints about spacing pylint: disable=C0322
103        host.port_factory.all_port_names = lambda platform=None: [platform]
104
105        res = lint_test_expectations.lint(host, options, logging_stream)
106
107        self.assertEqual(res, 0)
108        self.assertIn('Lint succeeded', logging_stream.getvalue())
109
110    def test_lint_test_files__errors(self):
111        options = optparse.Values({'platform': 'test', 'debug_rwt_logging': False})
112        host = MockHost()
113
114        # FIXME: incorrect complaints about spacing pylint: disable=C0322
115        port = host.port_factory.get(options.platform, options=options)
116        port.expectations_dict = lambda: {'foo': '-- syntax error1', 'bar': '-- syntax error2'}
117
118        host.port_factory.get = lambda platform, options=None: port
119        host.port_factory.all_port_names = lambda platform=None: [port.name()]
120
121        logging_stream = StringIO.StringIO()
122
123        res = lint_test_expectations.lint(host, options, logging_stream)
124
125        self.assertEqual(res, -1)
126        self.assertIn('Lint failed', logging_stream.getvalue())
127        self.assertIn('foo:1', logging_stream.getvalue())
128        self.assertIn('bar:1', logging_stream.getvalue())
129
130
131class MainTest(unittest.TestCase):
132    def test_success(self):
133        orig_lint_fn = lint_test_expectations.lint
134
135        # unused args pylint: disable=W0613
136        def interrupting_lint(host, options, logging_stream):
137            raise KeyboardInterrupt
138
139        def successful_lint(host, options, logging_stream):
140            return 0
141
142        def exception_raising_lint(host, options, logging_stream):
143            assert False
144
145        stdout = StringIO.StringIO()
146        stderr = StringIO.StringIO()
147        try:
148            lint_test_expectations.lint = interrupting_lint
149            res = lint_test_expectations.main([], stdout, stderr)
150            self.assertEqual(res, lint_test_expectations.INTERRUPTED_EXIT_STATUS)
151
152            lint_test_expectations.lint = successful_lint
153            res = lint_test_expectations.main(['--platform', 'test'], stdout, stderr)
154            self.assertEqual(res, 0)
155
156            lint_test_expectations.lint = exception_raising_lint
157            res = lint_test_expectations.main([], stdout, stderr)
158            self.assertEqual(res, lint_test_expectations.EXCEPTIONAL_EXIT_STATUS)
159        finally:
160            lint_test_expectations.lint = orig_lint_fn
161