1 # Copyright (c) 2012 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.
10 import webgl_conformance_expectations
12 from telemetry
.core
import util
13 from telemetry
.internal
.browser
import browser_finder
14 from telemetry
.page
import page_test
15 from telemetry
.page
import shared_page_state
16 from telemetry
.story
.story_set
import StorySet
19 conformance_path
= os
.path
.join(
20 util
.GetChromiumSrcDir(),
21 'third_party', 'webgl', 'src', 'sdk', 'tests')
23 conformance_harness_script
= r
"""
25 testHarness._allTestSucceeded = true;
26 testHarness._messages = '';
27 testHarness._failures = 0;
28 testHarness._finished = false;
29 testHarness._originalLog = window.console.log;
31 testHarness.log = function(msg) {
32 testHarness._messages += msg + "\n";
33 testHarness._originalLog.apply(window.console, [msg]);
36 testHarness.reportResults = function(url, success, msg) {
37 testHarness._allTestSucceeded = testHarness._allTestSucceeded && !!success;
39 testHarness._failures++;
45 testHarness.notifyFinished = function(url) {
46 testHarness._finished = true;
48 testHarness.navigateToPage = function(src) {
49 var testFrame = document.getElementById("test-frame");
53 window.webglTestHarness = testHarness;
54 window.parent.webglTestHarness = testHarness;
55 window.console.log = testHarness.log;
56 window.onerror = function(message, url, line) {
57 testHarness.reportResults(null, false, message);
58 testHarness.notifyFinished(null);
62 def _DidWebGLTestSucceed(tab
):
63 return tab
.EvaluateJavaScript('webglTestHarness._allTestSucceeded')
65 def _WebGLTestMessages(tab
):
66 return tab
.EvaluateJavaScript('webglTestHarness._messages')
68 def _CompareVersion(version1
, version2
):
69 ver_num1
= [int(x
) for x
in version1
.split('.')]
70 ver_num2
= [int(x
) for x
in version2
.split('.')]
71 size
= min(len(ver_num1
), len(ver_num2
))
72 return cmp(ver_num1
[0:size
], ver_num2
[0:size
])
74 class WebglConformanceValidator(gpu_test_base
.ValidatorBase
):
76 super(WebglConformanceValidator
, self
).__init
__()
78 def ValidateAndMeasurePageInner(self
, page
, tab
, results
):
79 if not _DidWebGLTestSucceed(tab
):
80 raise page_test
.Failure(_WebGLTestMessages(tab
))
82 def CustomizeBrowserOptions(self
, options
):
83 options
.AppendExtraBrowserArgs([
84 '--disable-gesture-requirement-for-media-playback',
85 '--disable-domain-blocking-for-3d-apis',
86 '--disable-gpu-process-crash-limit'
88 browser
= browser_finder
.FindBrowser(options
.finder_options
)
89 if (browser
.target_os
.startswith('android') and
90 browser
.browser_type
== 'android-webview-shell'):
91 # TODO(kbr): this is overly broad. We'd like to do this only on
92 # Nexus 9. It'll go away shortly anyway. crbug.com/499928
94 # The --ignore_egl_sync_failures is only there to work around
95 # some strange failure on the Nexus 9 bot, not reproducible on
97 options
.AppendExtraBrowserArgs([
98 '--disable-gl-extensions=GL_EXT_disjoint_timer_query',
99 '--ignore_egl_sync_failures'
103 class Webgl2ConformanceValidator(WebglConformanceValidator
):
105 super(Webgl2ConformanceValidator
, self
).__init
__()
107 def CustomizeBrowserOptions(self
, options
):
108 options
.AppendExtraBrowserArgs([
109 '--disable-gesture-requirement-for-media-playback',
110 '--disable-domain-blocking-for-3d-apis',
111 '--disable-gpu-process-crash-limit',
112 '--enable-unsafe-es3-apis'
115 class WebglConformancePage(gpu_test_base
.PageBase
):
116 def __init__(self
, story_set
, test
, expectations
):
117 super(WebglConformancePage
, self
).__init
__(
118 url
='file://' + test
, page_set
=story_set
, base_dir
=story_set
.base_dir
,
119 shared_page_state_class
=shared_page_state
.SharedDesktopPageState
,
120 name
=('WebglConformance.%s' %
121 test
.replace('/', '_').replace('-', '_').
122 replace('\\', '_').rpartition('.')[0].replace('.', '_')),
123 expectations
=expectations
)
124 self
.script_to_evaluate_on_commit
= conformance_harness_script
126 def RunNavigateStepsInner(self
, action_runner
):
127 num_tries
= 1 + self
.GetExpectations().GetFlakyRetriesForPage(
128 self
, action_runner
.tab
.browser
)
129 # This loop will run once for tests that aren't marked flaky, and
130 # will fall through to the validator's ValidateAndMeasurePage on
131 # the last iteration.
132 for ii
in xrange(0, num_tries
):
133 # The first time through, the superclass has already run the
134 # default navigation steps.
136 self
.RunDefaultNavigateSteps(action_runner
)
137 action_runner
.WaitForJavaScriptCondition(
138 'webglTestHarness._finished', timeout_in_seconds
=180)
139 if ii
< num_tries
- 1:
140 if _DidWebGLTestSucceed(action_runner
.tab
):
143 print 'FLAKY TEST FAILURE, retrying: ' + self
.display_name
144 print 'Error messages from test run:'
145 print _WebGLTestMessages(action_runner
.tab
)
147 class WebglConformance(gpu_test_base
.TestBase
):
148 """Conformance with Khronos WebGL Conformance Tests"""
150 super(WebglConformance
, self
).__init
__(max_failures
=10)
151 self
._cached
_expectations
= None
155 return 'webgl_conformance'
158 def AddBenchmarkCommandLineArgs(cls
, group
):
159 group
.add_option('--webgl-conformance-version',
160 help='Version of the WebGL conformance tests to run.',
162 group
.add_option('--webgl2-only',
163 help='Whether we include webgl 1 tests if version is 2.0.0 or above.',
166 def CreatePageTest(self
, options
):
167 if _CompareVersion(options
.webgl_conformance_version
, '2.0.0') >= 0:
168 return Webgl2ConformanceValidator()
169 return WebglConformanceValidator()
171 def CreateStorySet(self
, options
):
172 tests
= self
._ParseTests
('00_test_list.txt',
173 options
.webgl_conformance_version
,
174 (options
.webgl2_only
== 'true'),
177 ps
= StorySet(serving_dirs
=[''], base_dir
=conformance_path
)
179 expectations
= self
.GetExpectations()
181 ps
.AddStory(WebglConformancePage(ps
, test
, expectations
))
185 def _CreateExpectations(self
):
186 return webgl_conformance_expectations
.WebGLConformanceExpectations(
190 def _ParseTests(path
, version
, webgl2_only
, folder_min_version
):
192 current_dir
= os
.path
.dirname(path
)
193 full_path
= os
.path
.normpath(os
.path
.join(conformance_path
, path
))
195 if not os
.path
.exists(full_path
):
196 raise Exception('The WebGL conformance test path specified ' +
197 'does not exist: ' + full_path
)
199 with
open(full_path
, 'r') as f
:
206 if line
.startswith('//') or line
.startswith('#'):
209 line_tokens
= line
.split(' ')
210 test_name
= line_tokens
[-1]
214 while i
< len(line_tokens
):
215 token
= line_tokens
[i
]
216 if token
== '--min-version':
218 min_version
= line_tokens
[i
]
221 min_version_to_compare
= min_version
or folder_min_version
223 if (min_version_to_compare
and
224 _CompareVersion(version
, min_version_to_compare
) < 0):
227 if (webgl2_only
and (not ('.txt' in test_name
)) and
228 ((not min_version_to_compare
) or
229 (not min_version_to_compare
.startswith('2')))):
232 if '.txt' in test_name
:
233 include_path
= os
.path
.join(current_dir
, test_name
)
234 # We only check min-version >= 2.0.0 for the top level list.
235 test_paths
+= WebglConformance
._ParseTests
(
236 include_path
, version
, webgl2_only
, min_version_to_compare
)
238 test
= os
.path
.join(current_dir
, test_name
)
239 test_paths
.append(test
)