Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Unified Diff: tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py

Issue 1254023003: Telemetry Test for WebRTC Rendering. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added unit test to CL Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py
diff --git a/tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py
new file mode 100644
index 0000000000000000000000000000000000000000..999a25044b73c2da8585c1de9de6bdb27f38c74e
--- /dev/null
+++ b/tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py
@@ -0,0 +1,241 @@
+import unittest
+
+import mock
+
+import numpy
+
+from telemetry.web_perf.metrics import webrtc_rendering_stats as stats_helper
+
+
+class FakeEvent(object):
+ """Fake event class to mock rendering events."""
+
+ def __init__(self, **kwargs):
+ """Initializer for the fake WebMediaPlayerMS::UpdateCurrentFrame events.
+
+ The WebMediaPlayerMsRenderingStats only cares about actual render begin,
+ actual render end, ideal render instant and serial fields of the events.
+ So we only define these four fields here in this fake event class.
+ This method is written so as to take whatever valid parameters from the
+ event definition. It can also be used to craft incomplete events.
+
+ Args:
+ kwargs::= dict('actual_begin', 'actual_end', 'ideal_instant', 'serial').
+ """
+ self.args = {}
+ name_map = {
+ 'Actual Render Begin': 'actual_begin',
+ 'Actual Render End': 'actual_end',
+ 'Ideal Render Instant': 'ideal_instant',
+ 'Serial': 'serial'}
+ for internal_name, external_name in name_map.iteritems():
+ if external_name in kwargs:
+ self.args[internal_name] = kwargs[external_name]
+
+
+class WebMediaPlayerMsRenderingStatsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.local_stream = ('0blob:http%3A//localhost/9525b098-38ac-4144-913c-'
+ '7078bcc689f6')
+ self.remote_stream = ('1blob:http%3A//localhost/83c5c476-4439-47b9-9ff1-'
+ 'ec3737f88610')
+
+ def testInitialization(self):
+ event_local_stream = FakeEvent(actual_begin=1655987203306,
+ actual_end=1655987219972, ideal_instant=1655987154324,
+ serial=self.local_stream)
+
+ event_remote_stream = FakeEvent(actual_begin=1655987203306,
+ actual_end=1655987219972, ideal_instant=1655987167999,
+ serial=self.remote_stream)
+
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(
+ [event_local_stream, event_remote_stream])
+
+ self.assertEqual(2, len(stats_parser.stream_to_events))
+
+ self.assertEqual(event_local_stream.args,
+ stats_parser.stream_to_events[self.local_stream][0].args)
+
+ self.assertEqual(event_remote_stream.args,
+ stats_parser.stream_to_events[self.remote_stream][0].args)
+
+ def testInvalidEvents(self):
+ event_missing_serial = FakeEvent(actual_begin=1655987244074,
+ actual_end=1655987260740, ideal_instant=1655987204839)
+
+ event_missing_actual_begin = FakeEvent(actual_end=1655987260740,
+ ideal_instant=1655987217999, serial=self.local_stream)
+
+ event_missing_actual_end = FakeEvent(actual_end=1655987260740,
+ ideal_instant=1655987217999, serial=self.remote_stream)
+
+ event_missing_ideal_instant = FakeEvent(actual_begin=1655987260740,
+ actual_end=1655987277406, serial=self.remote_stream)
+
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(
+ [event_missing_serial, event_missing_actual_begin,
+ event_missing_actual_end, event_missing_ideal_instant])
+
+ self.assertEqual(0, len(stats_parser.stream_to_events))
+
+ def _GetFakeEvents(self):
+ fake_events = [
+ FakeEvent(actual_begin=1663780195583, actual_end=1663780212249,
+ ideal_instant=1663780179998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780212249, actual_end=1663780228915,
+ ideal_instant=1663780179998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780228915, actual_end=1663780245581,
+ ideal_instant=1663780197998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780245581, actual_end=1663780262247,
+ ideal_instant=1663780215998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780262247, actual_end=1663780278913,
+ ideal_instant=1663780215998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780278913, actual_end=1663780295579,
+ ideal_instant=1663780254998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780295579, actual_end=1663780312245,
+ ideal_instant=1663780254998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780312245, actual_end=1663780328911,
+ ideal_instant=1663780254998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780328911, actual_end=1663780345577,
+ ideal_instant=1663780310998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780345577, actual_end=1663780362243,
+ ideal_instant=1663780310998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780362243, actual_end=1663780378909,
+ ideal_instant=1663780310998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780378909, actual_end=1663780395575,
+ ideal_instant=1663780361998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780395575, actual_end=1663780412241,
+ ideal_instant=1663780361998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780412241, actual_end=1663780428907,
+ ideal_instant=1663780361998, serial=self.remote_stream),
+ FakeEvent(actual_begin=1663780428907, actual_end=1663780445573,
+ ideal_instant=1663780412998, serial=self.remote_stream)]
+
+ return fake_events
+
+ def testGetCadence(self):
+ fake_events = self._GetFakeEvents()
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(fake_events)
+ expected_cadence = [2, 1, 2, 3, 3, 3, 1]
phoglund_chromium 2015/09/24 07:11:46 Maybe clarify the expected cadence and how it rela
cpaulin (no longer in chrome) 2015/09/24 21:47:38 Done.
+ self.assertEqual(expected_cadence, stats_parser._GetCadence(fake_events))
+
+ def testGetSourceToOutputDistribution(self):
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ cadence = [2, 1, 2, 3, 3, 3, 1]
+ expected_frame_distribution = {1: 2, 2: 2, 3: 3}
+ self.assertEqual(expected_frame_distribution,
+ stats_parser._GetSourceToOutputDistribution(cadence))
+
+ def testGetFpsFromCadence(self):
+ frame_distribution = {1: 2, 2: 2, 3: 3}
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ expected_frame_rate = 28.0
+ self.assertEqual(expected_frame_rate,
+ stats_parser._GetFpsFromCadence(frame_distribution))
+
+ def testGetFrozenFramesReports(self):
+ frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1}
+ expected_frozen_reports = [{'frozen_frames': 5, 'occurrences': 1}]
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ self.assertEqual(expected_frozen_reports,
+ stats_parser._GetFrozenFramesReports(frame_distribution))
+
+ def testIsRemoteStream(self):
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ self.assertTrue(stats_parser._IsRemoteStream(self.remote_stream))
+
+ def testGetDrifTimeStats(self):
+ fake_events = self._GetFakeEvents()
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ cadence = stats_parser._GetCadence(fake_events)
+ expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909]
+ expected_rendering_length_error = 29.613733905579398
+
+ self.assertEqual((expected_drift_time, expected_rendering_length_error),
+ stats_parser._GetDrifTimeStats(fake_events, cadence))
+
+ def testGetSmoothnessStats(self):
+ norm_drift_time = [5948.2857142857138, 9383.7142857142862,
+ 8049.7142857142862, 2381.7142857142862, 3620.2857142857138,
+ 4622.2857142857138, 5624.2857142857138]
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ expected_percent_badly_oos = 0.0
+ expected_percent_out_of_sync = 0.0
+ expected_smoothness_score = 100.0
+ expected_smoothness_stats = (expected_percent_badly_oos,
+ expected_percent_out_of_sync, expected_smoothness_score)
+
+ self.assertEqual(expected_smoothness_stats,
+ stats_parser._GetSmoothnessStats(norm_drift_time))
+
+ def testNegativeSmoothnessScoreChangedToZero(self):
+ norm_drift_time = [15948.285714285714, 9383.714285714286,
+ 28049.714285714286, 72381.71428571429, 3620.2857142857138,
+ 4622.285714285714, 35624.28571428572]
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ expected_percent_badly_oos = 28.571428571428573
+ expected_percent_out_of_sync = 42.857142857142854
+ expected_smoothness_score = 0.0
+ expected_smoothness_stats = (expected_percent_badly_oos,
+ expected_percent_out_of_sync, expected_smoothness_score)
+
+ self.assertEqual(expected_smoothness_stats,
+ stats_parser._GetSmoothnessStats(norm_drift_time))
+
+ def testGetFreezingScore(self):
+ frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1}
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ expected_freezing_score = 99.94182664339732
+ self.assertEqual(expected_freezing_score,
+ stats_parser._GetFreezingScore(frame_distribution))
+
+ def testNegativeFrezingScoreChangedToZero(self):
+ frame_distribution = {1: 2, 2: 2, 3: 2, 8:100}
+ stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
+ self.assertEqual(0.0, stats_parser._GetFreezingScore(frame_distribution))
+
+ def testGetTimeStats(self):
+ fake_events = self._GetFakeEvents()
+ expected_cadence = [2, 1, 2, 3, 3, 3, 1]
+ expected_frame_dist = {1: 2, 2: 2, 3: 569, 6: 1}
+ expected_frame_rate = 28.0
+ expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909]
+ expected_rendering_length_error = 29.613733905579398
+ expected_percent_badly_oos = 0.0
+ expected_percent_out_of_sync = 0.0
+ expected_smoothness_score = 100.0
+ expected_freezing_score = 99.94182664339732
+
+ stats_cls = stats_helper.WebMediaPlayerMsRenderingStats
+ stats_cls._GetCadence = mock.Mock()
+ stats_cls._GetCadence.return_value = expected_cadence
+ stats_cls._GetSourceToOutputDistribution = mock.Mock()
+ stats_cls._GetSourceToOutputDistribution.return_value = expected_frame_dist
+ stats_cls._GetFpsFromCadence = mock.Mock()
+ stats_cls._GetFpsFromCadence.return_value = expected_frame_rate
+ stats_cls._GetDrifTimeStats = mock.Mock()
+ stats_cls._GetDrifTimeStats.return_value = (expected_drift_time,
+ expected_rendering_length_error)
+ stats_cls._GetSmoothnessStats = mock.Mock()
+ stats_cls._GetSmoothnessStats.return_value = (expected_percent_badly_oos,
+ expected_percent_out_of_sync, expected_smoothness_score)
+ stats_cls._GetFreezingScore = mock.Mock()
+ stats_cls._GetFreezingScore.return_value = expected_freezing_score
+
+ stats_parser = stats_cls(fake_events)
+
+ expected_stats = {
+ 'drift_time': expected_drift_time,
+ 'mean_drift_time': numpy.mean(expected_drift_time),
+ 'std_dev_drift_time': numpy.std(expected_drift_time),
+ 'percent_badly_out_of_sync': expected_percent_badly_oos,
+ 'percent_out_of_sync': expected_percent_out_of_sync,
+ 'smoothness_score': expected_smoothness_score,
+ 'freezing_score': expected_freezing_score,
+ 'rendering_length_error': expected_rendering_length_error,
+ 'fps': expected_frame_rate,
+ 'frame_distribution': expected_frame_dist}
+
+ self.assertEqual(expected_stats, stats_parser.GetTimeStats())

Powered by Google App Engine
This is Rietveld 408576698