OLD | NEW |
| (Empty) |
1 # Copyright 2013 The Chromium 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 | |
5 import unittest | |
6 | |
7 from telemetry.testing import simple_mock | |
8 | |
9 from metrics import webrtc_stats | |
10 | |
11 | |
12 SAMPLE_JSON = ''' | |
13 [[ | |
14 [ | |
15 { | |
16 "googFrameHeightInput":"480", | |
17 "googFrameWidthInput":"640", | |
18 "googFrameRateSent": "23", | |
19 "packetsLost":"-1", | |
20 "googRtt":"19", | |
21 "packetsSent":"1", | |
22 "bytesSent":"0" | |
23 }, | |
24 { | |
25 "audioInputLevel":"2048", | |
26 "googRtt":"20", | |
27 "googCodecName":"opus", | |
28 "packetsSent":"4", | |
29 "bytesSent":"0" | |
30 } | |
31 ], | |
32 [ | |
33 { | |
34 "googFrameHeightInput":"480", | |
35 "googFrameWidthInput":"640", | |
36 "googFrameRateSent": "21", | |
37 "packetsLost":"-1", | |
38 "googRtt":"18", | |
39 "packetsSent":"8", | |
40 "bytesSent":"6291" | |
41 }, | |
42 { | |
43 "audioInputLevel":"1878", | |
44 "googRtt":"17", | |
45 "googCodecName":"opus", | |
46 "packetsSent":"16", | |
47 "bytesSent":"634" | |
48 } | |
49 ], | |
50 [ | |
51 { | |
52 "googAvailableSendBandwidth":"30000", | |
53 "googAvailableRecvBandwidth":"12345", | |
54 "googTargetEncBitrate":"10000" | |
55 } | |
56 ] | |
57 ], | |
58 [ | |
59 [ | |
60 { | |
61 "googFrameRateReceived": "23", | |
62 "googDecodeMs":"0", | |
63 "packetsReceived":"8", | |
64 "googRenderDelayMs":"10", | |
65 "googMaxDecodeMs":"0", | |
66 "googRtt":"100" | |
67 } | |
68 ], | |
69 [ | |
70 { | |
71 "googFrameRateReceived": "23", | |
72 "googDecodeMs":"14", | |
73 "packetsReceived":"1234", | |
74 "googRenderDelayMs":"102", | |
75 "googMaxDecodeMs":"150", | |
76 "googRtt":"101" | |
77 } | |
78 ], | |
79 [ | |
80 { | |
81 "googAvailableSendBandwidth":"40000", | |
82 "googAvailableRecvBandwidth":"22345", | |
83 "googTargetEncBitrate":"20000" | |
84 } | |
85 ] | |
86 ]] | |
87 ''' | |
88 | |
89 | |
90 class FakeResults(object): | |
91 | |
92 def __init__(self, current_page): | |
93 self._received_values = [] | |
94 self._current_page = current_page | |
95 | |
96 @property | |
97 def received_values(self): | |
98 return self._received_values | |
99 | |
100 @property | |
101 def current_page(self): | |
102 return self._current_page | |
103 | |
104 def AddValue(self, value): | |
105 self._received_values.append(value) | |
106 | |
107 | |
108 class WebRtcStatsUnittest(unittest.TestCase): | |
109 | |
110 def _RunMetricOnJson(self, json_to_return, stats_metric): | |
111 tab = simple_mock.MockObject() | |
112 page = simple_mock.MockObject() | |
113 | |
114 stats_metric.Start(page, tab) | |
115 | |
116 tab.ExpectCall('EvaluateJavaScript', | |
117 simple_mock.DONT_CARE).WillReturn(json_to_return) | |
118 stats_metric.Stop(page, tab) | |
119 | |
120 page.url = simple_mock.MockObject() | |
121 results = FakeResults(page) | |
122 stats_metric.AddResults(tab, results) | |
123 return results | |
124 | |
125 def testExtractsValuesAsTimeSeries(self): | |
126 stats_metric = webrtc_stats.WebRtcStatisticsMetric() | |
127 results = self._RunMetricOnJson(SAMPLE_JSON, stats_metric) | |
128 | |
129 self.assertTrue(results.received_values, | |
130 'Expected values for googDecodeMs and others, got none.') | |
131 self.assertEqual(results.received_values[1].name, | |
132 'peer_connection_0_audio_goog_rtt') | |
133 self.assertEqual(results.received_values[1].values, | |
134 [20.0, 17.0]) | |
135 self.assertEqual(results.received_values[7].name, | |
136 'peer_connection_1_video_goog_rtt') | |
137 self.assertEqual(results.received_values[7].values, | |
138 [100.0, 101.0]) | |
139 | |
140 def testExtractsInterestingMetricsOnly(self): | |
141 stats_metric = webrtc_stats.WebRtcStatisticsMetric() | |
142 results = self._RunMetricOnJson(SAMPLE_JSON, stats_metric) | |
143 | |
144 self.assertTrue(len(results.received_values) > 0) | |
145 self.assertIn('peer_connection_0', results.received_values[0].name, | |
146 'The result should be a ListOfScalarValues instance with ' | |
147 'a name <peer connection id>_<statistic>.') | |
148 all_names = [value.name for value in results.received_values] | |
149 self.assertIn('peer_connection_0_audio_goog_rtt', all_names) | |
150 self.assertNotIn('peer_connection_1_audio_goog_rtt', all_names, | |
151 'Peer connection 1 does not have a goog-rtt in ' | |
152 'the JSON above, unlike peer connection 0 which does.') | |
153 self.assertIn('peer_connection_0_video_goog_rtt', all_names) | |
154 self.assertIn('peer_connection_1_video_goog_rtt', all_names) | |
155 # The audio_audio is intentional since the code distinguishes audio reports | |
156 # from video reports (even though audio_input_level is quite obvious). | |
157 self.assertNotIn('peer_connection_0_audio_audio_input_level', all_names, | |
158 'Input level is in the JSON for both connections but ' | |
159 'should not be reported since it is not interesting.') | |
160 self.assertNotIn('peer_connection_1_audio_audio_input_level', all_names) | |
161 | |
162 def testExtractsParticularMetricsOnlyIfSpecified(self): | |
163 only_goog_rtt_and_max_decode = ['googRtt', 'googMaxDecodeMs'] | |
164 stats_metric = webrtc_stats.WebRtcStatisticsMetric( | |
165 particular_metrics=only_goog_rtt_and_max_decode) | |
166 results = self._RunMetricOnJson(SAMPLE_JSON, stats_metric) | |
167 | |
168 received_names = [value.name for value in results.received_values] | |
169 expected_names = ['peer_connection_0_audio_goog_rtt', | |
170 'peer_connection_0_video_goog_rtt', | |
171 'peer_connection_1_video_goog_max_decode_ms', | |
172 'peer_connection_1_video_goog_rtt'] | |
173 self.assertEqual(expected_names, received_names) | |
174 | |
175 def testReturnsIfJsonIsEmpty(self): | |
176 stats_metric = webrtc_stats.WebRtcStatisticsMetric() | |
177 results = self._RunMetricOnJson('[]', stats_metric) | |
178 self.assertFalse(results.received_values) | |
OLD | NEW |