2010-04-28 Eric Seidel <eric@webkit.org>
[WebKit-https.git] / WebKitTools / Scripts / webkitpy / layout_tests / port / base_unittest.py
1 # Copyright (C) 2010 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
29 import base
30 import unittest
31 import tempfile
32
33 from webkitpy.common.system.executive import Executive, ScriptError
34 from webkitpy.thirdparty.mock import Mock
35
36
37 class PortTest(unittest.TestCase):
38
39     def test_format_wdiff_output_as_html(self):
40         output = "OUTPUT %s %s %s" % (base.Port._WDIFF_DEL, base.Port._WDIFF_ADD, base.Port._WDIFF_END)
41         html = base.Port()._format_wdiff_output_as_html(output)
42         expected_html = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre>OUTPUT <span class=del> <span class=add> </span></pre>"
43         self.assertEqual(html, expected_html)
44
45     def test_wdiff_command(self):
46         port = base.Port()
47         port._path_to_wdiff = lambda: "/path/to/wdiff"
48         command = port._wdiff_command("/actual/path", "/expected/path")
49         expected_command = [
50             "/path/to/wdiff",
51             "--start-delete=##WDIFF_DEL##",
52             "--end-delete=##WDIFF_END##",
53             "--start-insert=##WDIFF_ADD##",
54             "--end-insert=##WDIFF_END##",
55             "/actual/path",
56             "/expected/path",
57         ]
58         self.assertEqual(command, expected_command)
59
60     def _file_with_contents(self, contents, encoding="utf-8"):
61         new_file = tempfile.NamedTemporaryFile()
62         new_file.write(contents.encode(encoding))
63         new_file.flush()
64         return new_file
65
66     def test_run_wdiff(self):
67         executive = Executive()
68         # This may fail on some systems.  We could ask the port
69         # object for the wdiff path, but since we don't know what
70         # port object to use, this is sufficient for now.
71         try:
72             wdiff_path = executive.run_command(["which", "wdiff"]).rstrip()
73         except Exception, e:
74             wdiff_path = None
75
76         port = base.Port()
77         port._path_to_wdiff = lambda: wdiff_path
78
79         if wdiff_path:
80             # "with tempfile.NamedTemporaryFile() as actual" does not seem to work in Python 2.5
81             actual = self._file_with_contents(u"foo")
82             expected = self._file_with_contents(u"bar")
83             wdiff = port._run_wdiff(actual.name, expected.name)
84             expected_wdiff = "<head><style>.del { background: #faa; } .add { background: #afa; }</style></head><pre><span class=del>foo</span><span class=add>bar</span></pre>"
85             self.assertEqual(wdiff, expected_wdiff)
86             # Running the full wdiff_text method should give the same result.
87             base._wdiff_available = True  # In case it's somehow already disabled.
88             wdiff = port.wdiff_text(actual.name, expected.name)
89             self.assertEqual(wdiff, expected_wdiff)
90             # wdiff should still be available after running wdiff_text with a valid diff.
91             self.assertTrue(base._wdiff_available)
92             actual.close()
93             expected.close()
94
95             # Bogus paths should raise a script error.
96             self.assertRaises(ScriptError, port._run_wdiff, "/does/not/exist", "/does/not/exist2")
97             self.assertRaises(ScriptError, port.wdiff_text, "/does/not/exist", "/does/not/exist2")
98             # wdiff will still be available after running wdiff_text with invalid paths.
99             self.assertTrue(base._wdiff_available)
100             base._wdiff_available = True
101
102         # If wdiff does not exist _run_wdiff should throw an OSError.
103         port._path_to_wdiff = lambda: "/invalid/path/to/wdiff"
104         self.assertRaises(OSError, port._run_wdiff, "foo", "bar")
105
106         # wdiff_text should not throw an error if wdiff does not exist.
107         self.assertEqual(port.wdiff_text("foo", "bar"), "")
108         # However wdiff should not be available after running wdiff_text if wdiff is missing.
109         self.assertFalse(base._wdiff_available)
110         base._wdiff_available = True
111
112
113 class DriverTest(unittest.TestCase):
114
115     def _assert_wrapper(self, wrapper_string, expected_wrapper):
116         wrapper = base.Driver._command_wrapper(wrapper_string)
117         self.assertEqual(wrapper, expected_wrapper)
118
119     def test_command_wrapper(self):
120         self._assert_wrapper(None, [])
121         self._assert_wrapper("valgrind", ["valgrind"])
122
123         # Validate that shlex works as expected.
124         command_with_spaces = "valgrind --smc-check=\"check with spaces!\" --foo"
125         expected_parse = ["valgrind", "--smc-check=check with spaces!", "--foo"]
126         self._assert_wrapper(command_with_spaces, expected_parse)