Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: content/test/gpu/gpu_tests/context_lost_integration_test.py

Issue 2271543002: Port context_lost test to new GpuIntegrationTest harness. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More refactorings suggested by eyaich. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/test/gpu/gpu_tests/gpu_integration_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import os
6 import time
7
8 from gpu_tests import gpu_integration_test
9 from gpu_tests import context_lost_expectations
10 from gpu_tests import path_util
11
12 from telemetry.core import exceptions
13 from telemetry.core import util
14
15 data_path = os.path.join(
16 path_util.GetChromiumSrcDir(), 'content', 'test', 'data', 'gpu')
17
18 wait_timeout = 60 # seconds
19
20 harness_script = r"""
21 var domAutomationController = {};
22
23 domAutomationController._loaded = false;
24 domAutomationController._succeeded = false;
25 domAutomationController._finished = false;
26
27 domAutomationController.setAutomationId = function(id) {}
28
29 domAutomationController.send = function(msg) {
30 msg = msg.toLowerCase()
31 if (msg == "loaded") {
32 domAutomationController._loaded = true;
33 } else if (msg == "success") {
34 /* Don't squelch earlier failures! */
35 if (!domAutomationController._finished) {
36 domAutomationController._succeeded = true;
37 }
38 domAutomationController._finished = true;
39 } else {
40 /* Always record failures. */
41 domAutomationController._succeeded = false;
42 domAutomationController._finished = true;
43 }
44 }
45
46 domAutomationController.reset = function() {
47 domAutomationController._succeeded = false;
48 domAutomationController._finished = false;
49 }
50
51 window.domAutomationController = domAutomationController;
52 console.log("Harness injected.");
53 """
54
55 class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest):
56
57 @classmethod
58 def Name(cls):
59 return 'context_lost'
60
61 @classmethod
62 def CustomizeOptions(cls):
63 options = cls._finder_options.browser_options
64 options.AppendExtraBrowserArgs(
65 '--disable-domain-blocking-for-3d-apis')
66 options.AppendExtraBrowserArgs(
67 '--disable-gpu-process-crash-limit')
68 # Required for about:gpucrash handling from Telemetry.
69 options.AppendExtraBrowserArgs('--enable-gpu-benchmarking')
70
71 @classmethod
72 def GenerateGpuTests(cls, options):
73 tests = (('GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash',
74 'gpu_process_crash.html'),
75 ('WebGLContextLostFromGPUProcessExit',
76 'webgl.html?query=kill_after_notification'),
77 ('WebGLContextLostFromLoseContextExtension',
78 'webgl.html?query=WEBGL_lose_context'),
79 ('WebGLContextLostFromQuantity',
80 'webgl.html?query=forced_quantity_loss'),
81 ('WebGLContextLostFromSelectElement',
82 'webgl_with_select_element.html'),
83 ('WebGLContextLostInHiddenTab',
84 'webgl.html?query=kill_after_notification'))
85 for t in tests:
86 yield (t[0], t[1], ('_' + t[0]))
87
88 def RunActualGpuTest(self, test_path, *args):
89 test_name = args[0]
90 tab = self.tab
91 if not tab.browser.supports_tab_control:
92 self.fail('Browser must support tab control')
93 getattr(self, test_name)(test_path)
94
95 @classmethod
96 def _CreateExpectations(cls):
97 return context_lost_expectations.ContextLostExpectations()
98
99 @classmethod
100 def setUpClass(cls):
101 super(cls, ContextLostIntegrationTest).setUpClass()
102 cls.CustomizeOptions()
103 cls.SetBrowserOptions(cls._finder_options)
104 cls.StartBrowser()
105 cls.SetStaticServerDir(data_path)
106
107 def _WaitForPageToFinish(self, tab):
108 try:
109 util.WaitFor(lambda: tab.EvaluateJavaScript(
110 'window.domAutomationController._finished'), wait_timeout)
111 return True
112 except exceptions.TimeoutException:
113 return False
114
115 def _KillGPUProcess(self, number_of_gpu_process_kills,
116 check_crash_count):
117 tab = self.tab
118 # Doing the GPU process kill operation cooperatively -- in the
119 # same page's context -- is much more stressful than restarting
120 # the browser every time.
121 for x in range(number_of_gpu_process_kills):
122 expected_kills = x + 1
123
124 # Reset the test's state.
125 tab.EvaluateJavaScript(
126 'window.domAutomationController.reset()')
127
128 # If we're running the GPU process crash test, we need the test
129 # to have fully reset before crashing the GPU process.
130 if check_crash_count:
131 util.WaitFor(lambda: tab.EvaluateJavaScript(
132 'window.domAutomationController._finished'), wait_timeout)
133
134 # Crash the GPU process.
135 gpucrash_tab = tab.browser.tabs.New()
136 # To access these debug URLs from Telemetry, they have to be
137 # written using the chrome:// scheme.
138 # The try/except is a workaround for crbug.com/368107.
139 try:
140 gpucrash_tab.Navigate('chrome://gpucrash')
141 except Exception:
142 print 'Tab crashed while navigating to chrome://gpucrash'
143 # Activate the original tab and wait for completion.
144 tab.Activate()
145 completed = self._WaitForPageToFinish(tab)
146
147 if check_crash_count:
148 self._CheckCrashCount(tab, expected_kills)
149
150 # The try/except is a workaround for crbug.com/368107.
151 try:
152 gpucrash_tab.Close()
153 except Exception:
154 print 'Tab crashed while closing chrome://gpucrash'
155 if not completed:
156 self.fail('Test didn\'t complete (no context lost event?)')
157 if not tab.EvaluateJavaScript(
158 'window.domAutomationController._succeeded'):
159 self.fail('Test failed (context not restored properly?)')
160
161 def _CheckCrashCount(self, tab, expected_kills):
162 if not tab.browser.supports_system_info:
163 self.fail('Browser must support system info')
164
165 if not tab.EvaluateJavaScript(
166 'window.domAutomationController._succeeded'):
167 self.fail('Test failed (didn\'t render content properly?)')
168
169 number_of_crashes = -1
170 # To allow time for a gpucrash to complete, wait up to 20s,
171 # polling repeatedly.
172 start_time = time.time()
173 current_time = time.time()
174 while current_time - start_time < 20:
175 system_info = tab.browser.GetSystemInfo()
176 number_of_crashes = \
177 system_info.gpu.aux_attributes[u'process_crash_count']
178 if number_of_crashes >= expected_kills:
179 break
180 time.sleep(1)
181 current_time = time.time()
182
183 # Wait 5 more seconds and re-read process_crash_count, in
184 # attempt to catch latent process crashes.
185 time.sleep(5)
186 system_info = tab.browser.GetSystemInfo()
187 number_of_crashes = \
188 system_info.gpu.aux_attributes[u'process_crash_count']
189
190 if number_of_crashes < expected_kills:
191 self.fail('Timed out waiting for a gpu process crash')
192 elif number_of_crashes != expected_kills:
193 self.fail('Expected %d gpu process crashes; got: %d' %
194 (expected_kills, number_of_crashes))
195
196 def _NavigateAndWaitForLoad(self, test_path):
197 url = self.UrlOfStaticFilePath(test_path)
198 tab = self.tab
199 tab.Navigate(url, script_to_evaluate_on_commit=harness_script)
200 tab.action_runner.WaitForJavaScriptCondition(
201 'window.domAutomationController._loaded')
202
203 def _WaitForTabAndCheckCompletion(self):
204 tab = self.tab
205 completed = self._WaitForPageToFinish(tab)
206 if not completed:
207 self.fail('Test didn\'t complete (no context restored event?)')
208 if not tab.EvaluateJavaScript('window.domAutomationController._succeeded'):
209 self.fail('Test failed (context not restored properly?)')
210
211 # The browser test runner synthesizes methods with the exact name
212 # given in GenerateGpuTests, so in order to hand-write our tests but
213 # also go through the _RunGpuTest trampoline, the test needs to be
214 # slightly differently named.
215 def _GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash(self, test_path):
216 self._NavigateAndWaitForLoad(test_path)
217 self._KillGPUProcess(2, True)
218 self._RestartBrowser('must restart after tests that kill the GPU process')
219
220 def _WebGLContextLostFromGPUProcessExit(self, test_path):
221 self._NavigateAndWaitForLoad(test_path)
222 self._KillGPUProcess(1, False)
223 self._RestartBrowser('must restart after tests that kill the GPU process')
224
225 def _WebGLContextLostFromLoseContextExtension(self, test_path):
226 url = self.UrlOfStaticFilePath(test_path)
227 tab = self.tab
228 tab.Navigate(url, script_to_evaluate_on_commit=harness_script)
229 tab.action_runner.WaitForJavaScriptCondition(
230 'window.domAutomationController._finished')
231
232 def _WebGLContextLostFromQuantity(self, test_path):
233 self._NavigateAndWaitForLoad(test_path)
234 # Try to coerce GC to clean up any contexts not attached to the page.
235 # This method seems unreliable, so the page will also attempt to
236 # force GC through excessive allocations.
237 self.tab.CollectGarbage()
238 self._WaitForTabAndCheckCompletion()
239
240 def _WebGLContextLostFromSelectElement(self, test_path):
241 self._NavigateAndWaitForLoad(test_path)
242 self._WaitForTabAndCheckCompletion()
243
244 def _WebGLContextLostInHiddenTab(self, test_path):
245 self._NavigateAndWaitForLoad(test_path)
246 # Test losing a context in a hidden tab. This test passes if the tab
247 # doesn't crash.
248 tab = self.tab
249 dummy_tab = tab.browser.tabs.New()
250 tab.EvaluateJavaScript('loseContextUsingExtension()')
251 tab.Activate()
252 self._WaitForTabAndCheckCompletion()
OLDNEW
« no previous file with comments | « no previous file | content/test/gpu/gpu_tests/gpu_integration_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698