Home | History | Annotate | Download | only in video_YouTubePage
      1 # Copyright (c) 2013 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 logging
      6 import operator
      7 import os
      8 import time
      9 
     10 from autotest_lib.client.bin import test
     11 from autotest_lib.client.common_lib import error
     12 from autotest_lib.client.common_lib.cros import chrome
     13 
     14 
     15 class video_YouTubePage(test.test):
     16     """The main test class of this test.
     17 
     18     """
     19 
     20 
     21     version = 1
     22 
     23     PSEUDO_RANDOM_TIME_1 = 20.25
     24     PSEUDO_RANDOM_TIME_2 = 5.47
     25 
     26     # Minimum number of timeupdates required to fire in the last second.
     27     MIN_LAST_SECOND_UPDATES = 3
     28 
     29     NO_DELAY = 0
     30     MINIMAL_DELAY = 1
     31     MAX_REBUFFER_DELAY = 10
     32 
     33     PLAYING_STATE = 'playing'
     34     PAUSED_STATE = 'paused'
     35     ENDED_STATE = 'ended'
     36     TEST_PAGE = 'http://web-release-qa.youtube.com/watch?v=zuzaxlddWbk&html5=1'
     37 
     38     DISABLE_COOKIES = False
     39 
     40     tab = None
     41 
     42 
     43     def initialize_test(self, chrome, player_page):
     44         """Initializes the test.
     45 
     46         @param chrome: An Autotest Chrome instance.
     47         @param player_page: The URL (string) of the YouTube player page to test.
     48 
     49         """
     50         self.tab = chrome.browser.tabs[0]
     51 
     52         self.tab.Navigate(player_page)
     53         self.tab.WaitForDocumentReadyStateToBeComplete()
     54         time.sleep(2)
     55 
     56         with open(
     57                 os.path.join(os.path.dirname(__file__),
     58                 'files/video_YouTubePageCommon.js')) as f:
     59             js = f.read()
     60             if not self.tab.EvaluateJavaScript(js):
     61                 raise error.TestFail('YouTube page failed to load.')
     62             logging.info('Loaded accompanying .js script.')
     63 
     64 
     65     def get_player_state(self):
     66         """Simple wrapper to get the JS player state.
     67 
     68         @returns: The state of the player (string).
     69 
     70         """
     71         return self.tab.EvaluateJavaScript('window.__getVideoState();')
     72 
     73 
     74     def play_video(self):
     75         """Simple wrapper to play the video.
     76 
     77         """
     78         self.tab.ExecuteJavaScript('window.__playVideo();')
     79 
     80 
     81     def pause_video(self):
     82         """Simple wrapper to pause the video.
     83 
     84         """
     85         self.tab.ExecuteJavaScript('window.__pauseVideo();')
     86 
     87 
     88     def seek_video(self, new_time):
     89         """Simple wrapper to seek the video to a new time.
     90 
     91         @param new_time: Time to seek to.
     92 
     93         """
     94         self.tab.ExecuteJavaScript('window.__seek(%f);' % new_time)
     95 
     96 
     97     def seek_to_almost_end(self, seconds_before_end):
     98         """Simple wrapper to seek to almost the end of the video.
     99 
    100         @param seconds_before_end: How many seconds (a float, not integer)
    101                 before end of video.
    102 
    103         """
    104         self.tab.ExecuteJavaScript(
    105                 'window.__seekToAlmostEnd(%f);' % seconds_before_end)
    106 
    107 
    108     def get_current_time(self):
    109         """Simple wrapper to get the current time in the video.
    110 
    111         @returns: The current time (float).
    112 
    113         """
    114         return self.tab.EvaluateJavaScript('window.__getCurrentTime();')
    115 
    116 
    117     def assert_event_state(self, event, op, error_str):
    118         """Simple wrapper to get the status of a state in the video.
    119 
    120         @param event: A string denoting the event. Check the accompanying JS
    121                 file for the possible values.
    122         @param op: truth or not_ operator from the standard Python operator
    123                 module.
    124         @param error_str: A string for the error output.
    125 
    126         @returns: Whether or not the input event has fired.
    127 
    128         """
    129         result = self.tab.EvaluateJavaScript(
    130                 'window.__getEventHappened("%s");' % event)
    131         if not op(result):
    132             raise error.TestError(error)
    133 
    134 
    135     def clear_event_state(self, event):
    136         """Simple wrapper to clear the status of a state in the video.
    137 
    138         @param event: A string denoting the event. Check the accompanying JS
    139                 file for the possible vlaues.
    140 
    141         """
    142         self.tab.ExecuteJavaScript('window.__clearEventHappened("%s");' % event)
    143 
    144 
    145     def verify_last_second_playback(self):
    146         """Simple wrapper to check the playback of the last second.
    147 
    148         """
    149         result = self.tab.EvaluateJavaScript(
    150                 'window.__getLastSecondTimeupdates()')
    151         if result < self.MIN_LAST_SECOND_UPDATES:
    152             raise error.TestError(
    153                     'Last second did not play back correctly (%d events).' %
    154                     result)
    155 
    156 
    157     def assert_player_state(self, state, max_wait_secs):
    158         """Simple wrapper to busy wait and test the current state of the player.
    159 
    160         @param state: A string denoting the expected state of the player.
    161         @param max_wait_secs: Maximum amount of time to wait before failing.
    162 
    163         @raises: A error.TestError if the state is not as expected.
    164 
    165         """
    166         start_time = time.time()
    167         while True:
    168             current_state = self.get_player_state()
    169             if current_state == state:
    170                 return
    171             elif time.time() < start_time + max_wait_secs:
    172                 time.sleep(0.5)
    173             else:
    174                 raise error.TestError(
    175                         'Current player state "%s" is not the expected state '
    176                         '"%s".' % (current_state, state))
    177 
    178 
    179     def perform_test(self):
    180         """Base method for derived classes to run their test.
    181 
    182         """
    183         raise error.TestFail('Derived class did not specify a perform_test.')
    184 
    185 
    186     def perform_playing_test(self):
    187         """Test to check if the YT page starts off playing.
    188 
    189         """
    190         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    191         if self.get_current_time() <= 0.0:
    192             raise error.TestError('perform_playing_test failed.')
    193 
    194 
    195     def perform_pausing_test(self):
    196         """Test to check if the video is in the 'paused' state.
    197 
    198         """
    199         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    200         self.pause_video()
    201         self.assert_player_state(self.PAUSED_STATE, self.MINIMAL_DELAY)
    202 
    203 
    204     def perform_resuming_test(self):
    205         """Test to check if the video responds to resumption.
    206 
    207         """
    208         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    209         self.pause_video()
    210         self.assert_player_state(self.PAUSED_STATE, self.MINIMAL_DELAY)
    211         self.play_video()
    212         self.assert_player_state(self.PLAYING_STATE, self.MINIMAL_DELAY)
    213 
    214 
    215     def perform_seeking_test(self):
    216         """Test to check if seeking works.
    217 
    218         """
    219         # Test seeking while playing.
    220         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    221         self.seek_video(self.PSEUDO_RANDOM_TIME_1)
    222         time.sleep(self.MINIMAL_DELAY)
    223         if not self.tab.EvaluateJavaScript(
    224                 'window.__getCurrentTime() >= %f;' % self.PSEUDO_RANDOM_TIME_1):
    225             raise error.TestError(
    226                     'perform_seeking_test failed because player time is not '
    227                     'the expected time during playing seeking.')
    228         self.assert_event_state(
    229                 'seeking', operator.truth,
    230                 'perform_seeking_test failed: "seeking" state did not fire.')
    231         self.assert_event_state(
    232                 'seeked', operator.truth,
    233                 'perform_seeking_test failed: "seeked" state did not fire.')
    234 
    235         # Now make sure the video is still playing.
    236 
    237         # Let it buffer/play for at most 10 seconds before continuing.
    238         self.assert_player_state(self.PLAYING_STATE, self.MAX_REBUFFER_DELAY)
    239 
    240         self.clear_event_state('seeking');
    241         self.clear_event_state('seeked');
    242         self.assert_event_state(
    243                 'seeking', operator.not_,
    244                 'perform_seeking_test failed: '
    245                 '"seeking" state did not get cleared.')
    246         self.assert_event_state(
    247                 'seeked', operator.not_,
    248                 'perform_seeking_test failed: '
    249                 '"seeked" state did not get cleared.')
    250 
    251         # Test seeking while paused.
    252         self.pause_video()
    253         self.assert_player_state(self.PAUSED_STATE, self.MINIMAL_DELAY)
    254 
    255         self.seek_video(self.PSEUDO_RANDOM_TIME_2)
    256         time.sleep(self.MINIMAL_DELAY)
    257         if not self.tab.EvaluateJavaScript(
    258                 'window.__getCurrentTime() === %f;' %
    259                 self.PSEUDO_RANDOM_TIME_2):
    260             raise error.TestError(
    261                     'perform_seeking_test failed because player time is not '
    262                     'the expected time.')
    263         self.assert_event_state(
    264                 'seeking', operator.truth,
    265                 'perform_seeking_test failed: "seeking" state did not fire '
    266                 'again.')
    267         self.assert_event_state(
    268                 'seeked', operator.truth,
    269                 'perform_seeking_test failed: "seeked" state did not fire '
    270                 'again.')
    271 
    272         # Make sure the video is paused.
    273         self.assert_player_state(self.PAUSED_STATE, self.NO_DELAY)
    274 
    275 
    276     def perform_frame_drop_test(self):
    277         """Test to check if there are too many dropped frames.
    278 
    279         """
    280         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    281         time.sleep(15)
    282         dropped_frames_percentage = self.tab.EvaluateJavaScript(
    283                 'window.__videoElement.webkitDroppedFrameCount /'
    284                 'window.__videoElement.webkitDecodedFrameCount')
    285         if dropped_frames_percentage > 0.01:
    286             raise error.TestError((
    287                     'perform_frame_drop_test failed due to too many dropped '
    288                     'frames (%f%%)') % (dropped_frames_percentage * 100))
    289 
    290 
    291     def perform_ending_test(self):
    292         """Test to check if the state is 'ended' at the end of a video.
    293 
    294         """
    295         ALMOST_END = 0.1
    296         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    297         self.seek_to_almost_end(ALMOST_END)
    298         self.assert_player_state(self.ENDED_STATE, self.MAX_REBUFFER_DELAY)
    299 
    300 
    301     def perform_last_second_test(self):
    302         """Test to check if the last second is played.
    303 
    304         """
    305         NEAR_END = 2.0
    306         self.assert_player_state(self.PLAYING_STATE, self.NO_DELAY)
    307         self.seek_to_almost_end(NEAR_END)
    308         self.assert_player_state(
    309                 self.ENDED_STATE, self.MAX_REBUFFER_DELAY + NEAR_END)
    310         self.verify_last_second_playback()
    311 
    312 
    313     def run_once(self, subtest_name):
    314         """Main runner for the test.
    315 
    316         @param subtest_name: The name of the test to run, given below.
    317 
    318         """
    319         extension_paths = []
    320         if self.DISABLE_COOKIES:
    321             # To stop the system from erasing the previous profile, enable:
    322             #  options.dont_override_profile = True
    323             extension_path = os.path.join(
    324                     os.path.dirname(__file__),
    325                     'files/cookie-disabler')
    326             extension_paths.append(extension_path)
    327 
    328 
    329         with chrome.Chrome(extension_paths=extension_paths) as cr:
    330             self.initialize_test(cr, self.TEST_PAGE)
    331 
    332             if subtest_name is 'playing':
    333                 self.perform_playing_test()
    334             elif subtest_name is 'pausing':
    335                 self.perform_pausing_test()
    336             elif subtest_name is 'resuming':
    337                 self.perform_resuming_test()
    338             elif subtest_name is 'seeking':
    339                 self.perform_seeking_test()
    340             elif subtest_name is 'frame_drop':
    341                 self.perform_frame_drop_test()
    342             elif subtest_name is 'ending':
    343                 self.perform_ending_test()
    344             elif subtest_name is 'last_second':
    345                 self.perform_last_second_test()
    346