1# Copyright 2014 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
5import unittest
6
7from telemetry.unittest import simple_mock
8from telemetry.core.backends.chrome import inspector_websocket
9from telemetry.core.backends.chrome import websocket
10
11
12class FakeSocket(object):
13  """ A fake socket that:
14        + Receives first package of data after 10 second in the first recv().
15        + Receives second package of data after 10 second in the second recv().
16        + Raises a websocket.WebSocketTimeoutException after 15 seconds in the
17          third recv().
18        + Raises a websocket.WebSocketTimeoutException after 15 seconds in the
19          fourth recv().
20        + Receives third package of data after 10 second in the fifth recv().
21        + Receives last package of data (containing 'method') after 10 second
22          in the last recv().
23  """
24  def __init__(self, mock_timer):
25    self._mock_timer = mock_timer
26    self._recv_counter = 0
27
28  def recv(self):
29    self._recv_counter += 1
30    if self._recv_counter == 1:
31      self._mock_timer.SetTime(10)
32      return '["foo"]'
33    elif self._recv_counter == 2:
34      self._mock_timer.SetTime(20)
35      return '["bar"]'
36    elif self._recv_counter == 3:
37      self._mock_timer.SetTime(35)
38      raise websocket.WebSocketTimeoutException()
39    elif self._recv_counter == 4:
40      self._mock_timer.SetTime(50)
41      raise websocket.WebSocketTimeoutException()
42    elif self._recv_counter == 5:
43      self._mock_timer.SetTime(60)
44      return '["baz"]'
45    elif self._recv_counter == 6:
46      self._mock_timer.SetTime(70)
47      return '["method"]'
48
49  def settimeout(self, timeout):
50    pass
51
52
53def _ReraiseExceptionErrorHandler(_elapsed_time):
54  raise
55
56
57def _DoNothingExceptionErrorHandler(_elapsed_time):
58  pass
59
60
61class InspectorWebsocketUnittest(unittest.TestCase):
62
63  def setUp(self):
64    self._mock_timer = simple_mock.MockTimer(inspector_websocket)
65
66  def tearDown(self):
67    self._mock_timer.Restore()
68
69  def testDispatchNotificationUntilDoneTimedOutOne(self):
70    inspector = inspector_websocket.InspectorWebsocket(
71      notification_handler=lambda data: True,
72      error_handler=_ReraiseExceptionErrorHandler)
73    inspector._socket = FakeSocket(self._mock_timer)
74    # The third call to socket.recv() will take 15 seconds without any data
75    # received, hence the below call will raise a
76    # DispatchNotificationsUntilDoneTimeoutException.
77    with self.assertRaises(
78      inspector_websocket.DispatchNotificationsUntilDoneTimeoutException):
79      inspector.DispatchNotificationsUntilDone(12)
80
81  def testDispatchNotificationUntilDoneTimedOutTwo(self):
82    inspector = inspector_websocket.InspectorWebsocket(
83      notification_handler=lambda data: True,
84      error_handler=_DoNothingExceptionErrorHandler)
85    inspector._socket = FakeSocket(self._mock_timer)
86    # The third and forth calls to socket.recv() will take 30 seconds without
87    # any data received, hence the below call will raise a
88    # DispatchNotificationsUntilDoneTimeoutException.
89    with self.assertRaises(
90      inspector_websocket.DispatchNotificationsUntilDoneTimeoutException):
91      inspector.DispatchNotificationsUntilDone(29)
92
93  def testDispatchNotificationUntilDoneNotTimedOut(self):
94    inspector = inspector_websocket.InspectorWebsocket(
95    notification_handler=lambda data: True,
96    error_handler=_ReraiseExceptionErrorHandler)
97    inspector._socket = FakeSocket(self._mock_timer)
98    # Even though it takes 70 seconds to receive all the data, the call below
99    # will succeed since there are no interval which the previous data package
100    # received and the next failed data receiving attempt was greater than
101    # 30 seconds.
102    inspector.DispatchNotificationsUntilDone(31)
103