15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto_functional  # Must be imported before pyauto
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GpuTest(pyauto.PyUITest):
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """GPU Tests Runner."""
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GetGpuPID(self):
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Fetch the pid of the GPU process."""
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child_processes = self.GetBrowserInfo()['child_processes']
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for x in child_processes:
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       if x['type'] == 'GPU':
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return x['pid']
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _IsHardwareAccelerated(self, feature):
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Check if gpu is enabled in the machine before running any tests."""
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.NavigateToURL('about:gpu')
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def IsFeatureStatusLoaded():
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      """Returns whether the feature status UI has been loaded.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The about:gpu page fetches status for features asynchronously, so use
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this to check if the fetch is done.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      """
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      js = """
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var list = document.querySelector(".feature-status-list");
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        domAutomationController.send(list.hasChildNodes() ? "done" : "");
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      """
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return self.ExecuteJavascript(js)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self.WaitUntil(IsFeatureStatusLoaded, 10))
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    search = feature + ': Hardware accelerated'
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    find_result = self.FindInPage(search)['match_count']
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if find_result:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # about:gpu page starts a gpu process. Restart the browser to clear
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # the state. We could kill the gpu process, but navigating to a page
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # after killing the gpu can lead to flakiness.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # See crbug.com/93423.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.RestartBrowser()
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return True
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging.warn('Hardware acceleration not available')
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return False
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _VerifyGPUProcessOnPage(self, url):
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url = self.GetFileURLForDataPath('pyauto_private', 'gpu', url)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.NavigateToURL(url)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self.WaitUntil(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      lambda: self._GetGpuPID() is not None), msg='No process for GPU')
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testSingleGpuProcess(self):
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Verify there's only one gpu process shared across all uses."""
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self._IsHardwareAccelerated('WebGL'))
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url = self.GetFileURLForDataPath('pyauto_private',
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     'gpu', 'WebGLField.html')
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.AppendTab(pyauto.GURL(url))
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Open a new window.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.OpenNewBrowserWindow(True)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.NavigateToURL(url, 1, 0)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Open a new incognito window.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.NavigateToURL(url, 1, 0)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Verify there's only 1 gpu process.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gpu_process_count = 0
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for x in self.GetBrowserInfo()['child_processes']:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if x['type'] == 'GPU':
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        gpu_process_count += 1
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertEqual(1, gpu_process_count)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pyauto_functional.Main()
80