• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2013 The Chromium OS 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
5import logging
6import time
7
8from autotest_lib.client.bin import utils
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros.graphics import graphics_utils
11
12
13PLAYBACK_TEST_TIME_S = 10
14PLAYER_ENDED_STATE = 'Ended'
15PLAYER_PAUSE_STATE = 'Paused'
16PLAYER_PLAYING_STATE = 'Playing'
17WAIT_TIMEOUT_S = 20
18
19
20class YouTubeHelper(object):
21    """A helper class contains YouTube related utility functions.
22
23       To use this class, please call wait_for_player_state(playing) as below
24       before calling set_video_duration. Please note that set_video_duration
25       must be called in order to access few functions which uses the video
26       length member variable.
27
28       yh = youtube_helper.YouTubeHelper(tab)
29       yh.wait_for_player_state(PLAYER_PLAYING_STATE)
30       yh.set_video_duration()
31
32    """
33
34    def __init__(self, youtube_tab):
35        self._tab = youtube_tab
36        self._video_duration = 0
37
38
39    def set_video_duration(self):
40        """Sets the video duration."""
41        self._video_duration = (int(self._tab.EvaluateJavaScript(
42            'player.getDuration()')))
43
44    def video_current_time(self):
45        """Returns video's current playback time.
46
47        Returns:
48            returns the current playback location in seconds (int).
49
50        """
51        return int(self._tab.EvaluateJavaScript('player.getCurrentTime()'))
52
53    def get_player_status(self):
54        """Returns the player status."""
55        return self._tab.EvaluateJavaScript(
56            '(typeof playerStatus !== \'undefined\') && '
57            'playerStatus.innerHTML')
58
59    def get_playback_quality(self):
60        """Returns the playback quality."""
61        return self._tab.EvaluateJavaScript('player.getPlaybackQuality()')
62
63    def wait_for_player_state(self, expected_status):
64        """Wait till the player status changes to expected_status.
65
66        If the status doesn't change for long, the test will time out after
67        WAIT_TIMEOUT_S and fails.
68
69        @param expected_status: status which is expected for the test
70                                to continue.
71
72        """
73        utils.poll_for_condition(
74            lambda: self.get_player_status() == expected_status,
75            exception=error.TestError(
76                'Video failed to load. Player expected status: %s'
77                ' and current status: %s.'
78                % (expected_status, self.get_player_status())),
79            timeout=WAIT_TIMEOUT_S,
80            sleep_interval=1)
81
82    def verify_video_playback(self):
83        """Verify the video playback."""
84        logging.info('Verifying the YouTube video playback.')
85        playback = 0  # seconds
86        prev_playback = 0
87        count = 0
88        while (self.video_current_time() < self._video_duration
89               and playback < PLAYBACK_TEST_TIME_S):
90            time.sleep(1)
91            if self.video_current_time() <= prev_playback:
92                if count < 2:
93                    logging.info('Retrying to video playback test.')
94                    self._tab.ExecuteJavaScript(
95                        'player.seekTo(%d, true)'
96                        % (self.video_current_time() + 2))
97                    time.sleep(1)
98                    count = count + 1
99                else:
100                    player_status = self.get_player_status()
101                    raise error.TestError(
102                        'Video is not playing. Player status: %s.' %
103                        player_status)
104            prev_playback = self.video_current_time()
105            playback = playback + 1
106
107    def verify_player_states(self):
108        """Verify the player states like play, pause, ended and seek."""
109        logging.info('Verifying the player states.')
110        self._tab.ExecuteJavaScript('player.pauseVideo()')
111        self.wait_for_player_state(PLAYER_PAUSE_STATE)
112        self._tab.ExecuteJavaScript('player.playVideo()')
113        self.wait_for_player_state(PLAYER_PLAYING_STATE)
114        # We are seeking the player position to (video length - 2 seconds).
115        # Since the player waits for WAIT_TIMEOUT_S for the status change,
116        # the video should be ended before we hit the timeout.
117        video_end_test_duration = (self._video_duration -
118                                   self.video_current_time() - 2)
119        if video_end_test_duration >= WAIT_TIMEOUT_S:
120            self._tab.ExecuteJavaScript(
121                'player.seekTo(%d, true)' % (self._video_duration - 5))
122            self.wait_for_player_state(PLAYER_ENDED_STATE)
123        else:
124            raise error.TestError(
125                'Test video is not long enough for the video end test.')
126        # Verifying seek back from the end position.
127        self._tab.ExecuteJavaScript('player.seekTo(%d, true)'
128                                    % (self._video_duration / 2))
129        self.wait_for_player_state(PLAYER_PLAYING_STATE)
130        # So the playback doesn't stay at the mid.
131        seek_test = False
132        for _ in range(WAIT_TIMEOUT_S):
133            logging.info('Waiting for seek position to change.')
134            time.sleep(1)
135            seek_position = self.video_current_time()
136            if (seek_position > self._video_duration / 2
137                    and seek_position < self._video_duration):
138                seek_test = True
139                break
140        if not seek_test:
141            raise error.TestError(
142                'Seek location is wrong. '
143                'Video length: %d, seek position: %d.' %
144                (self._video_duration, seek_position))
145