1# Copyright (C) 2018 Igalia S.L.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1. Redistributions of source code must retain the above copyright
7# notice, this list of conditions and the following disclaimer.
8# 2. Redistributions in binary form must reproduce the above copyright
9# notice, this list of conditions and the following disclaimer in the
10# documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
13# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
16# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23import unittest
24
25import json
26import os
27
28from webkitpy.common.host_mock import MockHost
29from webkitpy.common.test_expectations import TestExpectations
30from webkitpy.common.webkit_finder import WebKitFinder
31
32
33class MockTestExpectations(TestExpectations):
34
35 def __init__(self, port, expectations, build_type='Release'):
36 host = MockHost()
37 port = host.port_factory.get(port)
38 self._port_name = port.name()
39 self._build_type = build_type
40 self._expectations = json.loads(expectations)
41
42 def is_skip(self, test, subtest):
43 if test in self.skipped_tests():
44 return True
45 return subtest in self.skipped_subtests(test)
46
47
48class ExpectationsTest(unittest.TestCase):
49
50 BASIC = """
51{
52 "imported/w3c/webdriver/tests/test1.py": {
53 "subtests": {
54 "test1_one": {
55 "expected": {"all": {"status": ["FAIL"], "bug": "1234"}}
56 },
57 "test1_two": {
58 "expected": {
59 "all": {"status": ["FAIL"], "bug": "1234"},
60 "gtk": {"status": ["PASS"]}
61 }
62 }
63 }
64 },
65 "imported/w3c/webdriver/tests/test2.py": {
66 "expected": {"all": {"status": ["FAIL"], "bug": "1234"}}
67 },
68 "imported/w3c/webdriver/tests/test3.py": {
69 "expected": {"all": {"status": ["FAIL"], "bug": "1234"}},
70 "subtests": {
71 "test3_one": {
72 "expected": {"all": {"status": ["PASS"]}}
73 }
74 }
75 }
76}"""
77
78 SKIP = """
79{
80 "imported/w3c/webdriver/tests/test1.py": {
81 "expected": {"all": {"status": ["SKIP"], "bug": "1234"}}
82 },
83 "imported/w3c/webdriver/tests/test2.py": {
84 "expected": {"gtk": {"status": ["SKIP"], "bug": "1234"}}
85 },
86 "imported/w3c/webdriver/tests/test3.py": {
87 "expected": {"all": {"status": ["SKIP"], "bug": "1234"}},
88 "subtests": {
89 "test3_one": {
90 "expected": {"all": {"status": ["FAIL"], "bug": "1234"}}
91 }
92 }
93 },
94 "imported/w3c/webdriver/tests/test4.py": {
95 "subtests": {
96 "test4_one": {
97 "expected": {"all": {"status": ["SKIP"], "bug": "1234"}}
98 }
99 }
100 }
101}"""
102
103 FLAKY = """
104{
105 "TestCookieManager": {
106 "subtests": {
107 "/webkit2/WebKitCookieManager/persistent-storage": {
108 "expected": {"gtk": {"status": ["FAIL", "PASS"], "bug": "1234"}}
109 }
110 }
111 },
112 "TestWebKit": {
113 "subtests": {
114 "WebKit.MouseMoveAfterCrash": {
115 "expected": {"all": {"status": ["CRASH", "PASS"], "bug": "1234"}}
116 },
117 "WebKit.WKConnection": {
118 "expected": {"wpe": {"status": ["FAIL", "TIMEOUT"], "bug": "1234"}}
119 }
120 }
121 }
122}"""
123
124 BUILD_TYPE = """
125{
126 "TestCookieManager": {
127 "subtests": {
128 "/webkit2/WebKitCookieManager/persistent-storage": {
129 "expected": {"all": {"status": ["FAIL"], "bug": "1234"}}
130 }
131 }
132 },
133 "TestWebKit": {
134 "subtests": {
135 "WebKit.MouseMoveAfterCrash": {
136 "expected": {"all@Debug": {"status": ["CRASH"], "bug": "1234"}}
137 },
138 "WebKit.WKConnection": {
139 "expected": {"gtk@Release": {"status": ["FAIL"], "bug": "1234"},
140 "gtk@Debug": {"status": ["CRASH"], "bug": "1234"}}
141 }
142 }
143 },
144 "TestWebCore": {
145 "expected": {"all@Debug": {"status": ["CRASH"]}},
146 "subtests": {
147 "ComplexTextControllerTest.InitialAdvanceWithLeftRunInRTL": {
148 "expected": {"all": {"status": ["PASS"], "bug": "1234"}}
149 },
150 "FileMonitorTest.DetectChange": {
151 "expected": {"all@Release": {"status": ["FAIL"], "bug": "1234"}}
152 }
153 }
154 },
155 "TestWebViewEditor": {
156 "expected": {"all@Release": {"status": ["SKIP"]},
157 "wpe@Debug": {"status": ["SKIP"]}},
158 "subtests": {
159 "/webkit2/WebKitWebView/editable/editable": {
160 "expected": {"gtk": {"status": ["FAIL"], "bug": "1234"}}
161 }
162 }
163 }
164}"""
165
166 def assert_exp(self, test, subtest, result):
167 self.assertIn(result, self.expectations.get_expectation(test, subtest))
168
169 def assert_not_exp(self, test, subtest, result):
170 self.assertNotIn(result, self.expectations.get_expectation(test, subtest))
171
172 def assert_bad_exp(self, test):
173 self.assertRaises(AssertionError, self.expectations.get_expectation(test))
174
175 def assert_skip(self, test, subtest, result):
176 self.assertEqual(self.expectations.is_skip(test, subtest), result)
177
178 def test_basic(self):
179 self.expectations = MockTestExpectations('gtk', self.BASIC)
180 self.assert_exp('imported/w3c/webdriver/tests/test5.py', 'test5_two', 'PASS')
181
182 self.assert_exp('imported/w3c/webdriver/tests/test1.py', 'test1_five', 'PASS')
183 self.assert_exp('imported/w3c/webdriver/tests/test1.py', 'test1_one', 'FAIL')
184 self.assert_exp('imported/w3c/webdriver/tests/test1.py', 'test1_two', 'PASS')
185
186 self.assert_exp('imported/w3c/webdriver/tests/test2.py', 'test2_one', 'FAIL')
187
188 self.assert_exp('imported/w3c/webdriver/tests/test3.py', 'test3_two', 'FAIL')
189 self.assert_exp('imported/w3c/webdriver/tests/test3.py', 'test3_one', 'PASS')
190
191 self.expectations = MockTestExpectations('wpe', self.BASIC)
192 self.assert_exp('imported/w3c/webdriver/tests/test1.py', 'test1_two', 'FAIL')
193
194 def test_skip(self):
195 self.expectations = MockTestExpectations('gtk', self.SKIP)
196 self.assert_skip('imported/w3c/webdriver/tests/test5.py', None, False)
197 self.assert_skip('imported/w3c/webdriver/tests/test1.py', None, True)
198 self.assert_skip('imported/w3c/webdriver/tests/test2.py', None, True)
199 self.assert_skip('imported/w3c/webdriver/tests/test3.py', None, True)
200 self.assert_skip('imported/w3c/webdriver/tests/test3.py', 'test3_one', True)
201 self.assert_skip('imported/w3c/webdriver/tests/test4.py', None, False)
202 self.assert_skip('imported/w3c/webdriver/tests/test4.py', 'test4_one', True)
203 self.assert_exp('imported/w3c/webdriver/tests/test4.py', 'test4_one', 'SKIP')
204
205 self.expectations = MockTestExpectations('wpe', self.SKIP)
206 self.assert_skip('imported/w3c/webdriver/tests/test2.py', None, False)
207
208 def test_flaky(self):
209 self.expectations = MockTestExpectations('gtk', self.FLAKY)
210 self.assert_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'PASS')
211 self.assert_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'FAIL')
212 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'CRASH')
213 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'PASS')
214 self.assert_exp('TestWebKit', 'WebKit.WKConnection', 'PASS')
215 self.assert_not_exp('TestWebKit', 'WebKit.WKConnection', 'FAIL')
216 self.assert_not_exp('TestWebKit', 'WebKit.WKConnection', 'TIMEOUT')
217
218 self.expectations = MockTestExpectations('wpe', self.FLAKY)
219 self.assert_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'PASS')
220 self.assert_not_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'FAIL')
221 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'CRASH')
222 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'PASS')
223 self.assert_exp('TestWebKit', 'WebKit.WKConnection', 'FAIL')
224 self.assert_exp('TestWebKit', 'WebKit.WKConnection', 'TIMEOUT')
225
226 def test_build_type(self):
227 self.expectations = MockTestExpectations('gtk', self.BUILD_TYPE, 'Debug')
228 self.assert_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'FAIL')
229 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'CRASH')
230 self.assert_exp('TestWebKit', 'WebKit.WKConnection', 'CRASH')
231 self.assert_exp('TestWebCore', 'ComplexTextControllerTest.InitialAdvanceWithLeftRunInRTL', 'PASS')
232 self.assert_exp('TestWebCore', 'FileMonitorTest.DetectChange', 'CRASH')
233 self.assert_exp('TestWebCore', 'FileSystemTest.MappingMissingFile', 'CRASH')
234 self.assert_skip('TestWebViewEditor', None, False)
235 self.assert_skip('TestWebViewEditor', '/webkit2/WebKitWebView/editable/editable', False)
236 self.assert_exp('TestWebViewEditor', '/webkit2/WebKitWebView/editable/editable', 'FAIL')
237
238 self.expectations = MockTestExpectations('gtk', self.BUILD_TYPE, 'Release')
239 self.assert_exp('TestCookieManager', '/webkit2/WebKitCookieManager/persistent-storage', 'FAIL')
240 self.assert_exp('TestWebKit', 'WebKit.MouseMoveAfterCrash', 'PASS')
241 self.assert_exp('TestWebKit', 'WebKit.WKConnection', 'FAIL')
242 self.assert_exp('TestWebCore', 'ComplexTextControllerTest.InitialAdvanceWithLeftRunInRTL', 'PASS')
243 self.assert_exp('TestWebCore', 'FileMonitorTest.DetectChange', 'FAIL')
244 self.assert_exp('TestWebCore', 'FileSystemTest.MappingMissingFile', 'PASS')
245 self.assert_skip('TestWebViewEditor', None, True)
246 self.assert_skip('TestWebViewEditor', '/webkit2/WebKitWebView/editable/editable', True)
247
248 self.expectations = MockTestExpectations('wpe', self.BUILD_TYPE, 'Release')
249 self.assert_skip('TestWebViewEditor', None, True)
250 self.assert_skip('TestWebViewEditor', '/webkit2/WebKitWebView/editable/editable', True)
251
252 self.expectations = MockTestExpectations('wpe', self.BUILD_TYPE, 'Debug')
253 self.assert_skip('TestWebViewEditor', None, True)
254 self.assert_skip('TestWebViewEditor', '/webkit2/WebKitWebView/editable/editable', True)