• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2# Copyright (c) 2012 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import re
7import time
8
9import pyauto_functional
10import pyauto
11import pyauto_errors
12import test_utils
13
14
15class YoutubeTestHelper():
16  """Helper functions for Youtube tests.
17
18  For sample usage, look at class YoutubeTest.
19  """
20
21  # YouTube player states
22  is_unstarted = '-1'
23  is_playing = '1'
24  is_paused = '2'
25  has_ended = '0'
26  _pyauto = None
27
28  def __init__(self, pyauto):
29    self._pyauto = pyauto
30
31  def IsFlashPluginEnabled(self):
32    """Verify flash plugin availability and its state."""
33    return [x for x in self._pyauto.GetPluginsInfo().Plugins() \
34            if x['name'] == 'Shockwave Flash' and x['enabled']]
35
36  def AssertPlayerState(self, state, msg):
37    expected_regex = '^%s$' % state
38    self.WaitForDomNode('id("playerState")', expected_value=expected_regex,
39                        msg=msg)
40
41  def WaitUntilPlayerReady(self):
42    """Verify that player is ready."""
43    self.AssertPlayerState(state=self.is_unstarted,
44                           msg='Failed to load youtube player.')
45
46  def GetPlayerState(self):
47    """Returns a player state."""
48    js = """
49        var val = ytplayer.getPlayerState();
50        window.domAutomationController.send(val + '');
51    """
52    return self._pyauto.ExecuteJavascript(js)
53
54  def GetVideoInfo(self):
55    """Returns Youtube video info."""
56    youtube_apis = self._pyauto.GetPrivateInfo()['youtube_api']
57    youtube_debug_text = youtube_apis['GetDebugText']
58    return  self._pyauto.ExecuteJavascript(
59        'window.domAutomationController.send(%s);' % youtube_debug_text)
60
61  def GetVideoDroppedFrames(self):
62    """Returns total Youtube video dropped frames.
63
64    Returns:
65      -1 if failed to get video frames from the video data
66    """
67    video_data = self._pyauto.GetVideoInfo()
68    matched = re.search('droppedFrames=([\d\.]+)', video_data)
69    if matched:
70      return int(matched.group(1))
71    else:
72      return -1
73
74  def GetVideoFrames(self):
75    """Returns Youtube video frames/second.
76
77    Returns:
78      -1 if failed to get droppd frames from the video data.
79    """
80    video_data = self._pyauto.GetVideoInfo()
81    matched = re.search('videoFps=([\d\.]+)', video_data)
82    if matched:
83      return int(matched.group(1))
84    else:
85      return -1
86
87  def GetVideoTotalBytes(self):
88    """Returns video total size in bytes.
89
90    To call this function, video must be in the paying state,
91    or this returns 0.
92    """
93    total_bytes = 0
94    total_bytes = self._pyauto.ExecuteJavascript("""
95        bytesTotal = document.getElementById("bytesTotal");
96        window.domAutomationController.send(bytesTotal.innerHTML);
97    """)
98    return int(total_bytes)
99
100  def GetVideoLoadedBytes(self):
101    """Returns video size in bytes."""
102    loaded_bytes = 0
103    loaded_bytes = self.ExecuteJavascript("""
104        bytesLoaded = document.getElementById("bytesLoaded");
105        window.domAutomationController.send(bytesLoaded.innerHTML);
106    """)
107    return int(loaded_bytes)
108
109  def GetCurrentVideoTime(self):
110    """Returns the current time of the video in seconds."""
111    current_time = 0
112    current_time = self.ExecuteJavascript("""
113        videoCurrentTime = document.getElementById("videoCurrentTime");
114        window.domAutomationController.send(videoCurrentTime.innerHTML);
115    """)
116    return int(current_time)
117
118  def PlayVideo(self):
119    """Plays the loaded video."""
120    self._pyauto.ExecuteJavascript("""
121        ytplayer.playVideo();
122        window.domAutomationController.send('');
123    """)
124
125  def StopVideo(self):
126    """Stops the video and cancels loading."""
127    self._pyauto.ExecuteJavascript("""
128        ytplayer.stopVideo();
129        window.domAutomationController.send('');
130    """)
131
132  def PauseVideo(self):
133    """Pause the video."""
134    self.ExecuteJavascript("""
135        ytplayer.pauseVideo();
136        window.domAutomationController.send('');
137    """)
138
139  def PlayVideoAndAssert(self, youtube_video='zuzaxlddWbk',
140                         ignore_assert=False):
141    """Start video and assert the playing state.
142
143    By default test uses http://www.youtube.com/watch?v=zuzaxlddWbki.
144
145    Args:
146      youtube_video: The string ID of the youtube video to play.
147      ignore_assert: flag to ignore the assertion and continue the test.
148    """
149    self._pyauto.assertTrue(self._pyauto.IsFlashPluginEnabled(),
150        msg='From here Flash plugin is disabled or not available.')
151    url = self._pyauto.GetHttpURLForDataPath(
152        'media', 'youtube.html?video=' + youtube_video)
153    self._pyauto.NavigateToURL(url)
154    self.WaitUntilPlayerReady()
155    i = 0
156    # The YouTube player will get in a state where it does not return the
157    # number of loaded bytes.  When this happens we need to reload the page
158    # before starting the test.
159    while self.GetVideoLoadedBytes() == 1 and i < 30:
160      self._pyauto.NavigateToURL(url)
161      self.WaitUntilPlayerReady()
162      i = i + 1
163    self.PlayVideo()
164    if ignore_assert:
165      return self.is_playing
166    self.AssertPlayerState(state=self.is_playing,
167                           msg='Player did not enter the playing state.')
168
169  def VideoBytesLoadingAndAssert(self):
170    """Assert the video loading."""
171    total_bytes = self.GetVideoTotalBytes()
172    prev_loaded_bytes = 0
173    loaded_bytes = 0
174    count = 0
175    while loaded_bytes < total_bytes:
176      # We want to test bytes loading only twice
177      count = count + 1
178      if count == 2:
179        break
180      loaded_bytes = self.GetVideoLoadedBytes()
181      self.assertTrue(prev_loaded_bytes <= loaded_bytes)
182      prev_loaded_bytes = loaded_bytes
183      # Give some time to load a video
184      time.sleep(1)
185
186  def PlayFAVideo(self):
187    """Play and assert FA video playing.
188
189    We are using multiple test videos in case any FA video playback fails
190    becuase other tests are palying the same video and the test gets the
191    simultaneous playback error.
192    """
193    fa_videos = ('APRpcscmbY0', 'yQqvrED-np0', 'KJuFw6hQdNY',
194                 'BeFQbgxr_9g', 'L6JwlOudqA4')
195    credentials = self.GetPrivateInfo()['test_fa_account']
196    test_utils.GoogleAccountsLogin(self,
197        credentials['username'], credentials['password'])
198    for video in fa_videos:
199      result = self.PlayVideoAndAssert(video, ignore_assert=True)
200      if result is self.is_playing:
201        return
202    self.assertTrue(False, msg='Player did not enter the playing state.')
203
204
205class YoutubeTest(pyauto.PyUITest, YoutubeTestHelper):
206  """Test case for Youtube videos."""
207
208  def __init__(self, methodName='runTest', **kwargs):
209    pyauto.PyUITest.__init__(self, methodName, **kwargs)
210    YoutubeTestHelper.__init__(self, self)
211
212  def testPlayerStatus(self):
213    """Test that YouTube loads a player and changes player states.
214
215    Test verifies various player states like unstarted, playing, paused
216    and ended.
217    """
218    # Navigating to Youtube video. This video is 122 seconds long.
219    # During tests, we are not goinig to play this video full.
220    self.PlayVideoAndAssert()
221    self.PauseVideo()
222    self.AssertPlayerState(state=self.is_paused,
223                           msg='Player did not enter the paused state.')
224    # Seek to the end of video
225    self.ExecuteJavascript("""
226        val = ytplayer.getDuration();
227        ytplayer.seekTo(val, true);
228        window.domAutomationController.send('');
229    """)
230    self.PlayVideo()
231    # We've seeked to almost the end of the video but not quite.
232    # Wait until the end.
233    self.AssertPlayerState(state=self.has_ended,
234                           msg='Player did not reach the stopped state.')
235
236  def testPlayerResolution(self):
237    """Test various video resolutions."""
238    self.PlayVideoAndAssert()
239    resolutions = self.ExecuteJavascript("""
240        res = ytplayer.getAvailableQualityLevels();
241        window.domAutomationController.send(res.toString());
242    """)
243    resolutions = resolutions.split(',')
244    for res in resolutions:
245      self.ExecuteJavascript("""
246          ytplayer.setPlaybackQuality('%s');
247          window.domAutomationController.send('');
248      """ % res)
249      curr_res = self.ExecuteJavascript("""
250          res = ytplayer.getPlaybackQuality();
251          window.domAutomationController.send(res + '');
252      """)
253      self.assertEqual(res, curr_res, msg='Resolution is not set to %s.' % res)
254
255  def testPlayerBytes(self):
256    """Test that player downloads video bytes."""
257    self.PlayVideoAndAssert()
258    self.VideoBytesLoadingAndAssert()
259
260  def testFAVideo(self):
261    """Test that FlashAccess/DRM video plays."""
262    self.PlayFAVideo()
263    self.StopVideo()
264
265  def testFAVideoBytes(self):
266    """Test FlashAccess/DRM video bytes loading."""
267    self.PlayFAVideo()
268    self.VideoBytesLoadingAndAssert()
269    self.StopVideo()
270
271
272if __name__ == '__main__':
273  pyauto_functional.Main()
274