Bug 1211959 - Tests check if video has started using played range. r=AutomatedTester a=test-only
authorBryce Van Dyk <bvandyk@mozilla.com>
Fri, 05 Aug 2016 12:38:54 +1200
changeset 349770 8bf3072e8e924fc4fbfd150daf4c2106a62bae0e
parent 349769 fdc2f1d67e3977e4fbc79d0acbb32259eca0f524
child 349771 12f39bee3e5a15eb4b2698327b38cffce1aebf50
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersAutomatedTester, test-only
bugs1211959
milestone50.0a2
Bug 1211959 - Tests check if video has started using played range. r=AutomatedTester a=test-only Previously the tests would check if playback had started by looking at the first recorded time, and then looking at the current time. If there were a lag it was possible for the first recorded time to be at the end of the video (i.e. playback already finished), in which case the video playing would not register. This patch instead uses the played ranges from the video element. Now so long as there is a non-empty played range we trust playback started. MozReview-Commit-ID: 5C39A42KRdj
dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
--- a/dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
+++ b/dom/media/test/external/external_media_tests/media_utils/video_puppeteer.py
@@ -83,23 +83,23 @@ class VideoPuppeteer(object):
                                                           'Using first.')
             if len(videos_found) <= 0:
                 self.marionette.log(type(self).__name__ + ': no video '
                                                           'elements found.')
                 return
             self.video = videos_found[0]
             self.marionette.execute_script("log('video element obtained');")
             if autostart:
-                self.start();
+                self.start()
 
     def start(self):
         # To get an accurate expected_duration, playback must have started
         wait = Wait(self, timeout=self.timeout)
-        verbose_until(wait, self, lambda v: v.current_time > 0,
-                      "Check if video current_time > 0")
+        verbose_until(wait, self, playback_started,
+                      "Check if video has played some range")
         self._start_time = self.current_time
         self._start_wall_time = clock()
         self.update_expected_duration()
 
     def update_expected_duration(self):
         """
         Update the duration of the target video at self.test_url (in seconds).
 
@@ -168,16 +168,30 @@ class VideoPuppeteer(object):
     def remaining_time(self):
         """
         :return: How much time is remaining given the duration of the video
             and the duration that has been set.
         """
         return self.expected_duration - self.current_time
 
     @property
+    def played(self):
+        """
+        :return: A TimeRanges objected containing the played time ranges.
+        """
+        raw_time_ranges = self.execute_video_script(
+            'var played = arguments[0].wrappedJSObject.played;'
+            'var timeRanges = [];'
+            'for (var i = 0; i < played.length; i++) {'
+            'timeRanges.push([played.start(i), played.end(i)]);'
+            '}'
+            'return [played.length, timeRanges];')
+        return TimeRanges(raw_time_ranges[0], raw_time_ranges[1])
+
+    @property
     def video_src(self):
         """
         :return: The url of the actual video file, as opposed to the url
             of the page with the video element.
         """
         with self.marionette.using_context('content'):
             return self.video.get_attribute('src')
 
@@ -271,28 +285,51 @@ class VideoPuppeteer(object):
 
 class VideoException(Exception):
     """
     Exception class to use for video-specific error processing.
     """
     pass
 
 
+class TimeRanges:
+    """
+    Class to represent the TimeRanges data returned by played(). Exposes a
+    similar interface to the JavaScript TimeRanges object.
+    """
+    def __init__(self, length, ranges):
+        self.length = length
+        self.ranges = [(pair[0], pair[1]) for pair in ranges]
+
+    def __repr__(self):
+        return 'TimeRanges: length: {}, ranges: {}'\
+               .format(self.length, self.ranges)
+
+    def start(self, index):
+        return self.ranges[index][0]
+
+    def end(self, index):
+        return self.ranges[index][1]
+
+
 def playback_started(video):
     """
     Determine if video has started
 
     :param video: The VideoPuppeteer instance that we are interested in.
 
     :return: True if is playing; False otherwise
     """
     try:
-        return video.current_time > video._start_time
+        played_ranges = video.played
+        return played_ranges.length > 0 and \
+               played_ranges.start(0) < played_ranges.end(0) and \
+               played_ranges.end(0) > 0.0
     except Exception as e:
-        print ('Got exception %s' % e)
+        print ('Got exception {}'.format(e))
         return False
 
 
 def playback_done(video):
     """
     If we are near the end and there is still a video element, then
     we are essentially done. If this happens to be last time we are polled
     before the video ends, we won't get another chance.