Chromium Code Reviews| Index: tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py |
| diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py |
| index 41da978e8c176520b71f0738ec95a5fb27c81d70..56d1ff796bc644803f8b850f494e0886c392a072 100644 |
| --- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py |
| +++ b/tools/telemetry/telemetry/internal/backends/chrome_inspector/tracing_backend_unittest.py |
| @@ -27,50 +27,57 @@ class FakeInspectorWebsocket(object): |
| """ |
| def __init__(self, mock_timer): |
| self._mock_timer = mock_timer |
| - self._responses = [] |
| + self._notifications = [] |
| + self._response_handlers = {} |
| self._handler = None |
| def RegisterDomain(self, _, handler): |
| self._handler = handler |
| - def AddResponse(self, method, value, time): |
| - if self._responses: |
| - assert self._responses[-1][1] < time, ( |
| + def AddNotification(self, method, value, time): |
| + if self._notifications: |
| + assert self._notifications[-1][1] < time, ( |
| 'Current response is scheduled earlier than previous response.') |
| params = {'value': value} |
| response = {'method': method, 'params': params} |
| - self._responses.append((response, time)) |
| + self._notifications.append((response, time)) |
| + |
| + def AddResponseHandler(self, method, handler): |
| + self._response_handlers[method] = handler |
| + |
| + def SyncRequest(self, request, *_args, **_kwargs): |
| + handler = self._response_handlers[request['method']] |
| + return handler(request) if handler else None |
| def Connect(self, _): |
| pass |
| def DispatchNotifications(self, timeout): |
| current_time = self._mock_timer.time() |
| - if not self._responses: |
| + if not self._notifications: |
| self._mock_timer.SetTime(current_time + timeout + 1) |
| raise websocket.WebSocketTimeoutException() |
| - response, time = self._responses[0] |
| + response, time = self._notifications[0] |
| if time - current_time > timeout: |
| self._mock_timer.SetTime(current_time + timeout + 1) |
| raise websocket.WebSocketTimeoutException() |
| - self._responses.pop(0) |
| + self._notifications.pop(0) |
| self._mock_timer.SetTime(time + 1) |
| self._handler(response) |
| class TracingBackendTest(tab_test_case.TabTestCase): |
| - def _StartServer(self): |
| - self._browser.SetHTTPServerDirectories(util.GetUnittestDataDir()) |
| - |
| def setUp(self): |
| super(TracingBackendTest, self).setUp() |
| self._tracing_controller = self._browser.platform.tracing_controller |
| if not self._tracing_controller.IsChromeTracingSupported(): |
| self.skipTest('Browser does not support tracing, skipping test.') |
| - self._StartServer() |
| + |
| + |
| +class TracingBackendTraceTest(TracingBackendTest): |
| def testGotTrace(self): |
| options = tracing_options.TracingOptions() |
| @@ -98,6 +105,87 @@ class TracingBackendTest(tab_test_case.TabTestCase): |
| self.assertRaises(Exception, self._tracing_controller.Stop) |
| +class TracingBackendMemoryTest(TracingBackendTest): |
| + |
| + # Number of consecutively requested memory dumps. |
| + _REQUESTED_DUMP_COUNT = 3 |
| + |
| + @classmethod |
| + def CustomizeBrowserOptions(cls, options): |
| + options.AppendExtraBrowserArgs([ |
| + # Memory maps currently cannot be retrieved on sandboxed processes. |
| + # See crbug.com/461788. |
| + '--no-sandbox', |
| + |
| + # Workaround to disable periodic memory dumps. See crbug.com/513692. |
| + '--enable-memory-benchmarking' |
| + ]) |
| + |
| + def setUp(self): |
| + super(TracingBackendMemoryTest, self).setUp() |
| + if not self._browser.supports_memory_dumping: |
| + self.skipTest('Browser does not support memory dumping, skipping test.') |
| + |
| + def testDumpMemorySuccess(self): |
| + # Check that dumping memory before tracing starts raises an exception. |
| + self.assertRaises(Exception, self._browser.DumpMemory) |
| + |
| + # Start tracing with memory dumps enabled. |
| + options = tracing_options.TracingOptions() |
| + options.enable_chrome_trace = True |
| + self._tracing_controller.Start( |
| + options, tracing_category_filter.TracingCategoryFilter( |
| + 'disabled-by-default-memory-infra')) |
| + |
| + # Request several memory dumps in a row and test that they were all |
| + # succesfully created with unique IDs. |
| + expected_dump_ids = [] |
| + for _ in xrange(self._REQUESTED_DUMP_COUNT): |
| + dump_id = self._browser.DumpMemory() |
| + self.assertIsNotNone(dump_id) |
| + self.assertNotIn(dump_id, expected_dump_ids) |
| + expected_dump_ids.append(dump_id) |
| + |
| + trace_data = self._tracing_controller.Stop() |
| + |
| + # Check that dumping memory after tracing stopped raises an exception. |
| + self.assertRaises(Exception, self._browser.DumpMemory) |
| + |
| + # Test that trace data is parsable. |
| + model = model_module.TimelineModel(trace_data) |
| + self.assertGreater(len(model.processes), 0) |
| + |
| + # Test that the resulting model contains the requested memory dumps in the |
| + # correct order (and nothing more). |
| + actual_dump_ids = [d.dump_id for d in model.IterGlobalMemoryDumps()] |
| + self.assertEqual(actual_dump_ids, expected_dump_ids) |
| + |
| + def testDumpMemoryFailure(self): |
| + # Check that dumping memory before tracing starts raises an exception. |
|
nednguyen
2015/07/29 16:07:41
This is interesting. Dumping memory command can on
petrcermak
2015/07/29 16:15:05
Yes. The reason is that the dump is added to the t
|
| + self.assertRaises(Exception, self._browser.DumpMemory) |
| + |
| + # Start tracing with memory dumps disabled. |
| + options = tracing_options.TracingOptions() |
| + options.enable_chrome_trace = True |
| + self._tracing_controller.Start( |
| + options, tracing_category_filter.TracingCategoryFilter()) |
| + |
| + # Check that the method returns None if the dump was not successful. |
| + self.assertIsNone(self._browser.DumpMemory()) |
| + |
| + trace_data = self._tracing_controller.Stop() |
| + |
| + # Check that dumping memory after tracing stopped raises an exception. |
| + self.assertRaises(Exception, self._browser.DumpMemory) |
| + |
| + # Test that trace data is parsable. |
| + model = model_module.TimelineModel(trace_data) |
| + self.assertGreater(len(model.processes), 0) |
| + |
| + # Test that the resulting model contains no memory dumps. |
| + self.assertEqual(len(list(model.IterGlobalMemoryDumps())), 0) |
| + |
| + |
| class TracingBackendUnitTest(unittest.TestCase): |
| def setUp(self): |
| self._mock_timer = simple_mock.MockTimer(tracing_backend) |
| @@ -107,9 +195,9 @@ class TracingBackendUnitTest(unittest.TestCase): |
| def testCollectTracingDataTimeout(self): |
| inspector = FakeInspectorWebsocket(self._mock_timer) |
| - inspector.AddResponse('Tracing.dataCollected', 'asdf1', 9) |
| - inspector.AddResponse('Tracing.dataCollected', 'asdf2', 19) |
| - inspector.AddResponse('Tracing.tracingComplete', 'asdf3', 35) |
| + inspector.AddNotification('Tracing.dataCollected', 'asdf1', 9) |
| + inspector.AddNotification('Tracing.dataCollected', 'asdf2', 19) |
| + inspector.AddNotification('Tracing.tracingComplete', 'asdf3', 35) |
| with mock.patch('telemetry.internal.backends.chrome_inspector.' |
| 'inspector_websocket.InspectorWebsocket') as mock_class: |
| @@ -125,9 +213,9 @@ class TracingBackendUnitTest(unittest.TestCase): |
| def testCollectTracingDataNoTimeout(self): |
| inspector = FakeInspectorWebsocket(self._mock_timer) |
| - inspector.AddResponse('Tracing.dataCollected', 'asdf1', 9) |
| - inspector.AddResponse('Tracing.dataCollected', 'asdf2', 14) |
| - inspector.AddResponse('Tracing.tracingComplete', 'asdf3', 19) |
| + inspector.AddNotification('Tracing.dataCollected', 'asdf1', 9) |
| + inspector.AddNotification('Tracing.dataCollected', 'asdf2', 14) |
| + inspector.AddNotification('Tracing.tracingComplete', 'asdf3', 19) |
| with mock.patch('telemetry.internal.backends.chrome_inspector.' |
| 'inspector_websocket.InspectorWebsocket') as mock_class: |
| @@ -137,3 +225,29 @@ class TracingBackendUnitTest(unittest.TestCase): |
| backend._CollectTracingData(10) |
| self.assertEqual(2, len(backend._trace_events)) |
| self.assertTrue(backend._has_received_all_tracing_data) |
| + |
| + def testDumpMemorySuccess(self): |
| + inspector = FakeInspectorWebsocket(self._mock_timer) |
| + inspector.AddResponseHandler( |
| + 'Tracing.requestMemoryDump', |
| + lambda req: {'result': {'success': True, 'dumpGuid': '42abc'}}) |
| + |
| + with mock.patch('telemetry.internal.backends.chrome_inspector.' |
| + 'inspector_websocket.InspectorWebsocket') as mock_class: |
| + mock_class.return_value = inspector |
| + backend = tracing_backend.TracingBackend(devtools_port=65000) |
| + |
| + self.assertEqual(backend.DumpMemory(), '42abc') |
| + |
| + def testDumpMemoryFailure(self): |
| + inspector = FakeInspectorWebsocket(self._mock_timer) |
| + inspector.AddResponseHandler( |
| + 'Tracing.requestMemoryDump', |
| + lambda req: {'result': {'success': False, 'dumpGuid': '42abc'}}) |
| + |
| + with mock.patch('telemetry.internal.backends.chrome_inspector.' |
| + 'inspector_websocket.InspectorWebsocket') as mock_class: |
| + mock_class.return_value = inspector |
| + backend = tracing_backend.TracingBackend(devtools_port=65000) |
| + |
| + self.assertIsNone(backend.DumpMemory()) |