OLD | NEW |
---|---|
(Empty) | |
1 import unittest | |
2 | |
3 import mock | |
4 | |
5 import numpy | |
6 | |
7 from telemetry.web_perf.metrics import webrtc_rendering_stats as stats_helper | |
8 | |
9 | |
10 class FakeEvent(object): | |
11 """Fake event class to mock rendering events.""" | |
12 | |
13 def __init__(self, **kwargs): | |
14 """Initializer for the fake WebMediaPlayerMS::UpdateCurrentFrame events. | |
15 | |
16 The WebMediaPlayerMsRenderingStats only cares about actual render begin, | |
17 actual render end, ideal render instant and serial fields of the events. | |
18 So we only define these four fields here in this fake event class. | |
19 This method is written so as to take whatever valid parameters from the | |
20 event definition. It can also be used to craft incomplete events. | |
21 | |
22 Args: | |
23 kwargs::= dict('actual_begin', 'actual_end', 'ideal_instant', 'serial'). | |
24 """ | |
25 self.args = {} | |
26 name_map = { | |
27 'Actual Render Begin': 'actual_begin', | |
28 'Actual Render End': 'actual_end', | |
29 'Ideal Render Instant': 'ideal_instant', | |
30 'Serial': 'serial'} | |
31 for internal_name, external_name in name_map.iteritems(): | |
32 if external_name in kwargs: | |
33 self.args[internal_name] = kwargs[external_name] | |
34 | |
35 | |
36 class WebMediaPlayerMsRenderingStatsTest(unittest.TestCase): | |
37 | |
38 def setUp(self): | |
39 self.local_stream = ('0blob:http%3A//localhost/9525b098-38ac-4144-913c-' | |
40 '7078bcc689f6') | |
41 self.remote_stream = ('1blob:http%3A//localhost/83c5c476-4439-47b9-9ff1-' | |
42 'ec3737f88610') | |
43 | |
44 def testInitialization(self): | |
45 event_local_stream = FakeEvent(actual_begin=1655987203306, | |
46 actual_end=1655987219972, ideal_instant=1655987154324, | |
47 serial=self.local_stream) | |
48 | |
49 event_remote_stream = FakeEvent(actual_begin=1655987203306, | |
50 actual_end=1655987219972, ideal_instant=1655987167999, | |
51 serial=self.remote_stream) | |
52 | |
53 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats( | |
54 [event_local_stream, event_remote_stream]) | |
55 | |
56 self.assertEqual(2, len(stats_parser.stream_to_events)) | |
57 | |
58 self.assertEqual(event_local_stream.args, | |
59 stats_parser.stream_to_events[self.local_stream][0].args) | |
60 | |
61 self.assertEqual(event_remote_stream.args, | |
62 stats_parser.stream_to_events[self.remote_stream][0].args) | |
63 | |
64 def testInvalidEvents(self): | |
65 event_missing_serial = FakeEvent(actual_begin=1655987244074, | |
66 actual_end=1655987260740, ideal_instant=1655987204839) | |
67 | |
68 event_missing_actual_begin = FakeEvent(actual_end=1655987260740, | |
69 ideal_instant=1655987217999, serial=self.local_stream) | |
70 | |
71 event_missing_actual_end = FakeEvent(actual_end=1655987260740, | |
72 ideal_instant=1655987217999, serial=self.remote_stream) | |
73 | |
74 event_missing_ideal_instant = FakeEvent(actual_begin=1655987260740, | |
75 actual_end=1655987277406, serial=self.remote_stream) | |
76 | |
77 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats( | |
78 [event_missing_serial, event_missing_actual_begin, | |
79 event_missing_actual_end, event_missing_ideal_instant]) | |
80 | |
81 self.assertEqual(0, len(stats_parser.stream_to_events)) | |
82 | |
83 def _GetFakeEvents(self): | |
84 fake_events = [ | |
85 FakeEvent(actual_begin=1663780195583, actual_end=1663780212249, | |
86 ideal_instant=1663780179998, serial=self.remote_stream), | |
87 FakeEvent(actual_begin=1663780212249, actual_end=1663780228915, | |
88 ideal_instant=1663780179998, serial=self.remote_stream), | |
89 FakeEvent(actual_begin=1663780228915, actual_end=1663780245581, | |
90 ideal_instant=1663780197998, serial=self.remote_stream), | |
91 FakeEvent(actual_begin=1663780245581, actual_end=1663780262247, | |
92 ideal_instant=1663780215998, serial=self.remote_stream), | |
93 FakeEvent(actual_begin=1663780262247, actual_end=1663780278913, | |
94 ideal_instant=1663780215998, serial=self.remote_stream), | |
95 FakeEvent(actual_begin=1663780278913, actual_end=1663780295579, | |
96 ideal_instant=1663780254998, serial=self.remote_stream), | |
97 FakeEvent(actual_begin=1663780295579, actual_end=1663780312245, | |
98 ideal_instant=1663780254998, serial=self.remote_stream), | |
99 FakeEvent(actual_begin=1663780312245, actual_end=1663780328911, | |
100 ideal_instant=1663780254998, serial=self.remote_stream), | |
101 FakeEvent(actual_begin=1663780328911, actual_end=1663780345577, | |
102 ideal_instant=1663780310998, serial=self.remote_stream), | |
103 FakeEvent(actual_begin=1663780345577, actual_end=1663780362243, | |
104 ideal_instant=1663780310998, serial=self.remote_stream), | |
105 FakeEvent(actual_begin=1663780362243, actual_end=1663780378909, | |
106 ideal_instant=1663780310998, serial=self.remote_stream), | |
107 FakeEvent(actual_begin=1663780378909, actual_end=1663780395575, | |
108 ideal_instant=1663780361998, serial=self.remote_stream), | |
109 FakeEvent(actual_begin=1663780395575, actual_end=1663780412241, | |
110 ideal_instant=1663780361998, serial=self.remote_stream), | |
111 FakeEvent(actual_begin=1663780412241, actual_end=1663780428907, | |
112 ideal_instant=1663780361998, serial=self.remote_stream), | |
113 FakeEvent(actual_begin=1663780428907, actual_end=1663780445573, | |
114 ideal_instant=1663780412998, serial=self.remote_stream)] | |
115 | |
116 return fake_events | |
117 | |
118 def testGetCadence(self): | |
119 fake_events = self._GetFakeEvents() | |
120 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(fake_events) | |
121 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.
| |
122 self.assertEqual(expected_cadence, stats_parser._GetCadence(fake_events)) | |
123 | |
124 def testGetSourceToOutputDistribution(self): | |
125 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
126 cadence = [2, 1, 2, 3, 3, 3, 1] | |
127 expected_frame_distribution = {1: 2, 2: 2, 3: 3} | |
128 self.assertEqual(expected_frame_distribution, | |
129 stats_parser._GetSourceToOutputDistribution(cadence)) | |
130 | |
131 def testGetFpsFromCadence(self): | |
132 frame_distribution = {1: 2, 2: 2, 3: 3} | |
133 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
134 expected_frame_rate = 28.0 | |
135 self.assertEqual(expected_frame_rate, | |
136 stats_parser._GetFpsFromCadence(frame_distribution)) | |
137 | |
138 def testGetFrozenFramesReports(self): | |
139 frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1} | |
140 expected_frozen_reports = [{'frozen_frames': 5, 'occurrences': 1}] | |
141 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
142 self.assertEqual(expected_frozen_reports, | |
143 stats_parser._GetFrozenFramesReports(frame_distribution)) | |
144 | |
145 def testIsRemoteStream(self): | |
146 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
147 self.assertTrue(stats_parser._IsRemoteStream(self.remote_stream)) | |
148 | |
149 def testGetDrifTimeStats(self): | |
150 fake_events = self._GetFakeEvents() | |
151 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
152 cadence = stats_parser._GetCadence(fake_events) | |
153 expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909] | |
154 expected_rendering_length_error = 29.613733905579398 | |
155 | |
156 self.assertEqual((expected_drift_time, expected_rendering_length_error), | |
157 stats_parser._GetDrifTimeStats(fake_events, cadence)) | |
158 | |
159 def testGetSmoothnessStats(self): | |
160 norm_drift_time = [5948.2857142857138, 9383.7142857142862, | |
161 8049.7142857142862, 2381.7142857142862, 3620.2857142857138, | |
162 4622.2857142857138, 5624.2857142857138] | |
163 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
164 expected_percent_badly_oos = 0.0 | |
165 expected_percent_out_of_sync = 0.0 | |
166 expected_smoothness_score = 100.0 | |
167 expected_smoothness_stats = (expected_percent_badly_oos, | |
168 expected_percent_out_of_sync, expected_smoothness_score) | |
169 | |
170 self.assertEqual(expected_smoothness_stats, | |
171 stats_parser._GetSmoothnessStats(norm_drift_time)) | |
172 | |
173 def testNegativeSmoothnessScoreChangedToZero(self): | |
174 norm_drift_time = [15948.285714285714, 9383.714285714286, | |
175 28049.714285714286, 72381.71428571429, 3620.2857142857138, | |
176 4622.285714285714, 35624.28571428572] | |
177 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
178 expected_percent_badly_oos = 28.571428571428573 | |
179 expected_percent_out_of_sync = 42.857142857142854 | |
180 expected_smoothness_score = 0.0 | |
181 expected_smoothness_stats = (expected_percent_badly_oos, | |
182 expected_percent_out_of_sync, expected_smoothness_score) | |
183 | |
184 self.assertEqual(expected_smoothness_stats, | |
185 stats_parser._GetSmoothnessStats(norm_drift_time)) | |
186 | |
187 def testGetFreezingScore(self): | |
188 frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1} | |
189 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
190 expected_freezing_score = 99.94182664339732 | |
191 self.assertEqual(expected_freezing_score, | |
192 stats_parser._GetFreezingScore(frame_distribution)) | |
193 | |
194 def testNegativeFrezingScoreChangedToZero(self): | |
195 frame_distribution = {1: 2, 2: 2, 3: 2, 8:100} | |
196 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([]) | |
197 self.assertEqual(0.0, stats_parser._GetFreezingScore(frame_distribution)) | |
198 | |
199 def testGetTimeStats(self): | |
200 fake_events = self._GetFakeEvents() | |
201 expected_cadence = [2, 1, 2, 3, 3, 3, 1] | |
202 expected_frame_dist = {1: 2, 2: 2, 3: 569, 6: 1} | |
203 expected_frame_rate = 28.0 | |
204 expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909] | |
205 expected_rendering_length_error = 29.613733905579398 | |
206 expected_percent_badly_oos = 0.0 | |
207 expected_percent_out_of_sync = 0.0 | |
208 expected_smoothness_score = 100.0 | |
209 expected_freezing_score = 99.94182664339732 | |
210 | |
211 stats_cls = stats_helper.WebMediaPlayerMsRenderingStats | |
212 stats_cls._GetCadence = mock.Mock() | |
213 stats_cls._GetCadence.return_value = expected_cadence | |
214 stats_cls._GetSourceToOutputDistribution = mock.Mock() | |
215 stats_cls._GetSourceToOutputDistribution.return_value = expected_frame_dist | |
216 stats_cls._GetFpsFromCadence = mock.Mock() | |
217 stats_cls._GetFpsFromCadence.return_value = expected_frame_rate | |
218 stats_cls._GetDrifTimeStats = mock.Mock() | |
219 stats_cls._GetDrifTimeStats.return_value = (expected_drift_time, | |
220 expected_rendering_length_error) | |
221 stats_cls._GetSmoothnessStats = mock.Mock() | |
222 stats_cls._GetSmoothnessStats.return_value = (expected_percent_badly_oos, | |
223 expected_percent_out_of_sync, expected_smoothness_score) | |
224 stats_cls._GetFreezingScore = mock.Mock() | |
225 stats_cls._GetFreezingScore.return_value = expected_freezing_score | |
226 | |
227 stats_parser = stats_cls(fake_events) | |
228 | |
229 expected_stats = { | |
230 'drift_time': expected_drift_time, | |
231 'mean_drift_time': numpy.mean(expected_drift_time), | |
232 'std_dev_drift_time': numpy.std(expected_drift_time), | |
233 'percent_badly_out_of_sync': expected_percent_badly_oos, | |
234 'percent_out_of_sync': expected_percent_out_of_sync, | |
235 'smoothness_score': expected_smoothness_score, | |
236 'freezing_score': expected_freezing_score, | |
237 'rendering_length_error': expected_rendering_length_error, | |
238 'fps': expected_frame_rate, | |
239 'frame_distribution': expected_frame_dist} | |
240 | |
241 self.assertEqual(expected_stats, stats_parser.GetTimeStats()) | |
OLD | NEW |