xref: /aosp_15_r20/external/cronet/third_party/protobuf/python/mox.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/python2.4
2*6777b538SAndroid Build Coastguard Worker#
3*6777b538SAndroid Build Coastguard Worker# Copyright 2008 Google Inc.
4*6777b538SAndroid Build Coastguard Worker#
5*6777b538SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*6777b538SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*6777b538SAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*6777b538SAndroid Build Coastguard Worker#
9*6777b538SAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*6777b538SAndroid Build Coastguard Worker#
11*6777b538SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*6777b538SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*6777b538SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*6777b538SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*6777b538SAndroid Build Coastguard Worker# limitations under the License.
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker# This file is used for testing.  The original is at:
18*6777b538SAndroid Build Coastguard Worker#   http://code.google.com/p/pymox/
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker"""Mox, an object-mocking framework for Python.
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard WorkerMox works in the record-replay-verify paradigm.  When you first create
23*6777b538SAndroid Build Coastguard Workera mock object, it is in record mode.  You then programmatically set
24*6777b538SAndroid Build Coastguard Workerthe expected behavior of the mock object (what methods are to be
25*6777b538SAndroid Build Coastguard Workercalled on it, with what parameters, what they should return, and in
26*6777b538SAndroid Build Coastguard Workerwhat order).
27*6777b538SAndroid Build Coastguard Worker
28*6777b538SAndroid Build Coastguard WorkerOnce you have set up the expected mock behavior, you put it in replay
29*6777b538SAndroid Build Coastguard Workermode.  Now the mock responds to method calls just as you told it to.
30*6777b538SAndroid Build Coastguard WorkerIf an unexpected method (or an expected method with unexpected
31*6777b538SAndroid Build Coastguard Workerparameters) is called, then an exception will be raised.
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard WorkerOnce you are done interacting with the mock, you need to verify that
34*6777b538SAndroid Build Coastguard Workerall the expected interactions occurred.  (Maybe your code exited
35*6777b538SAndroid Build Coastguard Workerprematurely without calling some cleanup method!)  The verify phase
36*6777b538SAndroid Build Coastguard Workerensures that every expected method was called; otherwise, an exception
37*6777b538SAndroid Build Coastguard Workerwill be raised.
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard WorkerSuggested usage / workflow:
40*6777b538SAndroid Build Coastguard Worker
41*6777b538SAndroid Build Coastguard Worker  # Create Mox factory
42*6777b538SAndroid Build Coastguard Worker  my_mox = Mox()
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker  # Create a mock data access object
45*6777b538SAndroid Build Coastguard Worker  mock_dao = my_mox.CreateMock(DAOClass)
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker  # Set up expected behavior
48*6777b538SAndroid Build Coastguard Worker  mock_dao.RetrievePersonWithIdentifier('1').AndReturn(person)
49*6777b538SAndroid Build Coastguard Worker  mock_dao.DeletePerson(person)
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker  # Put mocks in replay mode
52*6777b538SAndroid Build Coastguard Worker  my_mox.ReplayAll()
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker  # Inject mock object and run test
55*6777b538SAndroid Build Coastguard Worker  controller.SetDao(mock_dao)
56*6777b538SAndroid Build Coastguard Worker  controller.DeletePersonById('1')
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker  # Verify all methods were called as expected
59*6777b538SAndroid Build Coastguard Worker  my_mox.VerifyAll()
60*6777b538SAndroid Build Coastguard Worker"""
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Workerfrom collections import deque
63*6777b538SAndroid Build Coastguard Workerimport re
64*6777b538SAndroid Build Coastguard Workerimport types
65*6777b538SAndroid Build Coastguard Workerimport unittest
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Workerimport stubout
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Workerclass Error(AssertionError):
70*6777b538SAndroid Build Coastguard Worker  """Base exception for this module."""
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker  pass
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker
75*6777b538SAndroid Build Coastguard Workerclass ExpectedMethodCallsError(Error):
76*6777b538SAndroid Build Coastguard Worker  """Raised when Verify() is called before all expected methods have been called
77*6777b538SAndroid Build Coastguard Worker  """
78*6777b538SAndroid Build Coastguard Worker
79*6777b538SAndroid Build Coastguard Worker  def __init__(self, expected_methods):
80*6777b538SAndroid Build Coastguard Worker    """Init exception.
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker    Args:
83*6777b538SAndroid Build Coastguard Worker      # expected_methods: A sequence of MockMethod objects that should have been
84*6777b538SAndroid Build Coastguard Worker      #   called.
85*6777b538SAndroid Build Coastguard Worker      expected_methods: [MockMethod]
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker    Raises:
88*6777b538SAndroid Build Coastguard Worker      ValueError: if expected_methods contains no methods.
89*6777b538SAndroid Build Coastguard Worker    """
90*6777b538SAndroid Build Coastguard Worker
91*6777b538SAndroid Build Coastguard Worker    if not expected_methods:
92*6777b538SAndroid Build Coastguard Worker      raise ValueError("There must be at least one expected method")
93*6777b538SAndroid Build Coastguard Worker    Error.__init__(self)
94*6777b538SAndroid Build Coastguard Worker    self._expected_methods = expected_methods
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker  def __str__(self):
97*6777b538SAndroid Build Coastguard Worker    calls = "\n".join(["%3d.  %s" % (i, m)
98*6777b538SAndroid Build Coastguard Worker                       for i, m in enumerate(self._expected_methods)])
99*6777b538SAndroid Build Coastguard Worker    return "Verify: Expected methods never called:\n%s" % (calls,)
100*6777b538SAndroid Build Coastguard Worker
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Workerclass UnexpectedMethodCallError(Error):
103*6777b538SAndroid Build Coastguard Worker  """Raised when an unexpected method is called.
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker  This can occur if a method is called with incorrect parameters, or out of the
106*6777b538SAndroid Build Coastguard Worker  specified order.
107*6777b538SAndroid Build Coastguard Worker  """
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker  def __init__(self, unexpected_method, expected):
110*6777b538SAndroid Build Coastguard Worker    """Init exception.
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker    Args:
113*6777b538SAndroid Build Coastguard Worker      # unexpected_method: MockMethod that was called but was not at the head of
114*6777b538SAndroid Build Coastguard Worker      #   the expected_method queue.
115*6777b538SAndroid Build Coastguard Worker      # expected: MockMethod or UnorderedGroup the method should have
116*6777b538SAndroid Build Coastguard Worker      #   been in.
117*6777b538SAndroid Build Coastguard Worker      unexpected_method: MockMethod
118*6777b538SAndroid Build Coastguard Worker      expected: MockMethod or UnorderedGroup
119*6777b538SAndroid Build Coastguard Worker    """
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker    Error.__init__(self)
122*6777b538SAndroid Build Coastguard Worker    self._unexpected_method = unexpected_method
123*6777b538SAndroid Build Coastguard Worker    self._expected = expected
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker  def __str__(self):
126*6777b538SAndroid Build Coastguard Worker    return "Unexpected method call: %s.  Expecting: %s" % \
127*6777b538SAndroid Build Coastguard Worker      (self._unexpected_method, self._expected)
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Workerclass UnknownMethodCallError(Error):
131*6777b538SAndroid Build Coastguard Worker  """Raised if an unknown method is requested of the mock object."""
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker  def __init__(self, unknown_method_name):
134*6777b538SAndroid Build Coastguard Worker    """Init exception.
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Worker    Args:
137*6777b538SAndroid Build Coastguard Worker      # unknown_method_name: Method call that is not part of the mocked class's
138*6777b538SAndroid Build Coastguard Worker      #   public interface.
139*6777b538SAndroid Build Coastguard Worker      unknown_method_name: str
140*6777b538SAndroid Build Coastguard Worker    """
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker    Error.__init__(self)
143*6777b538SAndroid Build Coastguard Worker    self._unknown_method_name = unknown_method_name
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker  def __str__(self):
146*6777b538SAndroid Build Coastguard Worker    return "Method called is not a member of the object: %s" % \
147*6777b538SAndroid Build Coastguard Worker      self._unknown_method_name
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Workerclass Mox(object):
151*6777b538SAndroid Build Coastguard Worker  """Mox: a factory for creating mock objects."""
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker  # A list of types that should be stubbed out with MockObjects (as
154*6777b538SAndroid Build Coastguard Worker  # opposed to MockAnythings).
155*6777b538SAndroid Build Coastguard Worker  _USE_MOCK_OBJECT = [types.ClassType, types.InstanceType, types.ModuleType,
156*6777b538SAndroid Build Coastguard Worker                      types.ObjectType, types.TypeType]
157*6777b538SAndroid Build Coastguard Worker
158*6777b538SAndroid Build Coastguard Worker  def __init__(self):
159*6777b538SAndroid Build Coastguard Worker    """Initialize a new Mox."""
160*6777b538SAndroid Build Coastguard Worker
161*6777b538SAndroid Build Coastguard Worker    self._mock_objects = []
162*6777b538SAndroid Build Coastguard Worker    self.stubs = stubout.StubOutForTesting()
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker  def CreateMock(self, class_to_mock):
165*6777b538SAndroid Build Coastguard Worker    """Create a new mock object.
166*6777b538SAndroid Build Coastguard Worker
167*6777b538SAndroid Build Coastguard Worker    Args:
168*6777b538SAndroid Build Coastguard Worker      # class_to_mock: the class to be mocked
169*6777b538SAndroid Build Coastguard Worker      class_to_mock: class
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker    Returns:
172*6777b538SAndroid Build Coastguard Worker      MockObject that can be used as the class_to_mock would be.
173*6777b538SAndroid Build Coastguard Worker    """
174*6777b538SAndroid Build Coastguard Worker
175*6777b538SAndroid Build Coastguard Worker    new_mock = MockObject(class_to_mock)
176*6777b538SAndroid Build Coastguard Worker    self._mock_objects.append(new_mock)
177*6777b538SAndroid Build Coastguard Worker    return new_mock
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker  def CreateMockAnything(self):
180*6777b538SAndroid Build Coastguard Worker    """Create a mock that will accept any method calls.
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Worker    This does not enforce an interface.
183*6777b538SAndroid Build Coastguard Worker    """
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker    new_mock = MockAnything()
186*6777b538SAndroid Build Coastguard Worker    self._mock_objects.append(new_mock)
187*6777b538SAndroid Build Coastguard Worker    return new_mock
188*6777b538SAndroid Build Coastguard Worker
189*6777b538SAndroid Build Coastguard Worker  def ReplayAll(self):
190*6777b538SAndroid Build Coastguard Worker    """Set all mock objects to replay mode."""
191*6777b538SAndroid Build Coastguard Worker
192*6777b538SAndroid Build Coastguard Worker    for mock_obj in self._mock_objects:
193*6777b538SAndroid Build Coastguard Worker      mock_obj._Replay()
194*6777b538SAndroid Build Coastguard Worker
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker  def VerifyAll(self):
197*6777b538SAndroid Build Coastguard Worker    """Call verify on all mock objects created."""
198*6777b538SAndroid Build Coastguard Worker
199*6777b538SAndroid Build Coastguard Worker    for mock_obj in self._mock_objects:
200*6777b538SAndroid Build Coastguard Worker      mock_obj._Verify()
201*6777b538SAndroid Build Coastguard Worker
202*6777b538SAndroid Build Coastguard Worker  def ResetAll(self):
203*6777b538SAndroid Build Coastguard Worker    """Call reset on all mock objects.  This does not unset stubs."""
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker    for mock_obj in self._mock_objects:
206*6777b538SAndroid Build Coastguard Worker      mock_obj._Reset()
207*6777b538SAndroid Build Coastguard Worker
208*6777b538SAndroid Build Coastguard Worker  def StubOutWithMock(self, obj, attr_name, use_mock_anything=False):
209*6777b538SAndroid Build Coastguard Worker    """Replace a method, attribute, etc. with a Mock.
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker    This will replace a class or module with a MockObject, and everything else
212*6777b538SAndroid Build Coastguard Worker    (method, function, etc) with a MockAnything.  This can be overridden to
213*6777b538SAndroid Build Coastguard Worker    always use a MockAnything by setting use_mock_anything to True.
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker    Args:
216*6777b538SAndroid Build Coastguard Worker      obj: A Python object (class, module, instance, callable).
217*6777b538SAndroid Build Coastguard Worker      attr_name: str.  The name of the attribute to replace with a mock.
218*6777b538SAndroid Build Coastguard Worker      use_mock_anything: bool. True if a MockAnything should be used regardless
219*6777b538SAndroid Build Coastguard Worker        of the type of attribute.
220*6777b538SAndroid Build Coastguard Worker    """
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker    attr_to_replace = getattr(obj, attr_name)
223*6777b538SAndroid Build Coastguard Worker    if type(attr_to_replace) in self._USE_MOCK_OBJECT and not use_mock_anything:
224*6777b538SAndroid Build Coastguard Worker      stub = self.CreateMock(attr_to_replace)
225*6777b538SAndroid Build Coastguard Worker    else:
226*6777b538SAndroid Build Coastguard Worker      stub = self.CreateMockAnything()
227*6777b538SAndroid Build Coastguard Worker
228*6777b538SAndroid Build Coastguard Worker    self.stubs.Set(obj, attr_name, stub)
229*6777b538SAndroid Build Coastguard Worker
230*6777b538SAndroid Build Coastguard Worker  def UnsetStubs(self):
231*6777b538SAndroid Build Coastguard Worker    """Restore stubs to their original state."""
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker    self.stubs.UnsetAll()
234*6777b538SAndroid Build Coastguard Worker
235*6777b538SAndroid Build Coastguard Workerdef Replay(*args):
236*6777b538SAndroid Build Coastguard Worker  """Put mocks into Replay mode.
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker  Args:
239*6777b538SAndroid Build Coastguard Worker    # args is any number of mocks to put into replay mode.
240*6777b538SAndroid Build Coastguard Worker  """
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker  for mock in args:
243*6777b538SAndroid Build Coastguard Worker    mock._Replay()
244*6777b538SAndroid Build Coastguard Worker
245*6777b538SAndroid Build Coastguard Worker
246*6777b538SAndroid Build Coastguard Workerdef Verify(*args):
247*6777b538SAndroid Build Coastguard Worker  """Verify mocks.
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker  Args:
250*6777b538SAndroid Build Coastguard Worker    # args is any number of mocks to be verified.
251*6777b538SAndroid Build Coastguard Worker  """
252*6777b538SAndroid Build Coastguard Worker
253*6777b538SAndroid Build Coastguard Worker  for mock in args:
254*6777b538SAndroid Build Coastguard Worker    mock._Verify()
255*6777b538SAndroid Build Coastguard Worker
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Workerdef Reset(*args):
258*6777b538SAndroid Build Coastguard Worker  """Reset mocks.
259*6777b538SAndroid Build Coastguard Worker
260*6777b538SAndroid Build Coastguard Worker  Args:
261*6777b538SAndroid Build Coastguard Worker    # args is any number of mocks to be reset.
262*6777b538SAndroid Build Coastguard Worker  """
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker  for mock in args:
265*6777b538SAndroid Build Coastguard Worker    mock._Reset()
266*6777b538SAndroid Build Coastguard Worker
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Workerclass MockAnything:
269*6777b538SAndroid Build Coastguard Worker  """A mock that can be used to mock anything.
270*6777b538SAndroid Build Coastguard Worker
271*6777b538SAndroid Build Coastguard Worker  This is helpful for mocking classes that do not provide a public interface.
272*6777b538SAndroid Build Coastguard Worker  """
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker  def __init__(self):
275*6777b538SAndroid Build Coastguard Worker    """ """
276*6777b538SAndroid Build Coastguard Worker    self._Reset()
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker  def __getattr__(self, method_name):
279*6777b538SAndroid Build Coastguard Worker    """Intercept method calls on this object.
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker     A new MockMethod is returned that is aware of the MockAnything's
282*6777b538SAndroid Build Coastguard Worker     state (record or replay).  The call will be recorded or replayed
283*6777b538SAndroid Build Coastguard Worker     by the MockMethod's __call__.
284*6777b538SAndroid Build Coastguard Worker
285*6777b538SAndroid Build Coastguard Worker    Args:
286*6777b538SAndroid Build Coastguard Worker      # method name: the name of the method being called.
287*6777b538SAndroid Build Coastguard Worker      method_name: str
288*6777b538SAndroid Build Coastguard Worker
289*6777b538SAndroid Build Coastguard Worker    Returns:
290*6777b538SAndroid Build Coastguard Worker      A new MockMethod aware of MockAnything's state (record or replay).
291*6777b538SAndroid Build Coastguard Worker    """
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker    return self._CreateMockMethod(method_name)
294*6777b538SAndroid Build Coastguard Worker
295*6777b538SAndroid Build Coastguard Worker  def _CreateMockMethod(self, method_name):
296*6777b538SAndroid Build Coastguard Worker    """Create a new mock method call and return it.
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker    Args:
299*6777b538SAndroid Build Coastguard Worker      # method name: the name of the method being called.
300*6777b538SAndroid Build Coastguard Worker      method_name: str
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker    Returns:
303*6777b538SAndroid Build Coastguard Worker      A new MockMethod aware of MockAnything's state (record or replay).
304*6777b538SAndroid Build Coastguard Worker    """
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker    return MockMethod(method_name, self._expected_calls_queue,
307*6777b538SAndroid Build Coastguard Worker                      self._replay_mode)
308*6777b538SAndroid Build Coastguard Worker
309*6777b538SAndroid Build Coastguard Worker  def __nonzero__(self):
310*6777b538SAndroid Build Coastguard Worker    """Return 1 for nonzero so the mock can be used as a conditional."""
311*6777b538SAndroid Build Coastguard Worker
312*6777b538SAndroid Build Coastguard Worker    return 1
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker  def __eq__(self, rhs):
315*6777b538SAndroid Build Coastguard Worker    """Provide custom logic to compare objects."""
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker    return (isinstance(rhs, MockAnything) and
318*6777b538SAndroid Build Coastguard Worker            self._replay_mode == rhs._replay_mode and
319*6777b538SAndroid Build Coastguard Worker            self._expected_calls_queue == rhs._expected_calls_queue)
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker  def __ne__(self, rhs):
322*6777b538SAndroid Build Coastguard Worker    """Provide custom logic to compare objects."""
323*6777b538SAndroid Build Coastguard Worker
324*6777b538SAndroid Build Coastguard Worker    return not self == rhs
325*6777b538SAndroid Build Coastguard Worker
326*6777b538SAndroid Build Coastguard Worker  def _Replay(self):
327*6777b538SAndroid Build Coastguard Worker    """Start replaying expected method calls."""
328*6777b538SAndroid Build Coastguard Worker
329*6777b538SAndroid Build Coastguard Worker    self._replay_mode = True
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker  def _Verify(self):
332*6777b538SAndroid Build Coastguard Worker    """Verify that all of the expected calls have been made.
333*6777b538SAndroid Build Coastguard Worker
334*6777b538SAndroid Build Coastguard Worker    Raises:
335*6777b538SAndroid Build Coastguard Worker      ExpectedMethodCallsError: if there are still more method calls in the
336*6777b538SAndroid Build Coastguard Worker        expected queue.
337*6777b538SAndroid Build Coastguard Worker    """
338*6777b538SAndroid Build Coastguard Worker
339*6777b538SAndroid Build Coastguard Worker    # If the list of expected calls is not empty, raise an exception
340*6777b538SAndroid Build Coastguard Worker    if self._expected_calls_queue:
341*6777b538SAndroid Build Coastguard Worker      # The last MultipleTimesGroup is not popped from the queue.
342*6777b538SAndroid Build Coastguard Worker      if (len(self._expected_calls_queue) == 1 and
343*6777b538SAndroid Build Coastguard Worker          isinstance(self._expected_calls_queue[0], MultipleTimesGroup) and
344*6777b538SAndroid Build Coastguard Worker          self._expected_calls_queue[0].IsSatisfied()):
345*6777b538SAndroid Build Coastguard Worker        pass
346*6777b538SAndroid Build Coastguard Worker      else:
347*6777b538SAndroid Build Coastguard Worker        raise ExpectedMethodCallsError(self._expected_calls_queue)
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker  def _Reset(self):
350*6777b538SAndroid Build Coastguard Worker    """Reset the state of this mock to record mode with an empty queue."""
351*6777b538SAndroid Build Coastguard Worker
352*6777b538SAndroid Build Coastguard Worker    # Maintain a list of method calls we are expecting
353*6777b538SAndroid Build Coastguard Worker    self._expected_calls_queue = deque()
354*6777b538SAndroid Build Coastguard Worker
355*6777b538SAndroid Build Coastguard Worker    # Make sure we are in setup mode, not replay mode
356*6777b538SAndroid Build Coastguard Worker    self._replay_mode = False
357*6777b538SAndroid Build Coastguard Worker
358*6777b538SAndroid Build Coastguard Worker
359*6777b538SAndroid Build Coastguard Workerclass MockObject(MockAnything, object):
360*6777b538SAndroid Build Coastguard Worker  """A mock object that simulates the public/protected interface of a class."""
361*6777b538SAndroid Build Coastguard Worker
362*6777b538SAndroid Build Coastguard Worker  def __init__(self, class_to_mock):
363*6777b538SAndroid Build Coastguard Worker    """Initialize a mock object.
364*6777b538SAndroid Build Coastguard Worker
365*6777b538SAndroid Build Coastguard Worker    This determines the methods and properties of the class and stores them.
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker    Args:
368*6777b538SAndroid Build Coastguard Worker      # class_to_mock: class to be mocked
369*6777b538SAndroid Build Coastguard Worker      class_to_mock: class
370*6777b538SAndroid Build Coastguard Worker    """
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker    # This is used to hack around the mixin/inheritance of MockAnything, which
373*6777b538SAndroid Build Coastguard Worker    # is not a proper object (it can be anything. :-)
374*6777b538SAndroid Build Coastguard Worker    MockAnything.__dict__['__init__'](self)
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker    # Get a list of all the public and special methods we should mock.
377*6777b538SAndroid Build Coastguard Worker    self._known_methods = set()
378*6777b538SAndroid Build Coastguard Worker    self._known_vars = set()
379*6777b538SAndroid Build Coastguard Worker    self._class_to_mock = class_to_mock
380*6777b538SAndroid Build Coastguard Worker    for method in dir(class_to_mock):
381*6777b538SAndroid Build Coastguard Worker      if callable(getattr(class_to_mock, method)):
382*6777b538SAndroid Build Coastguard Worker        self._known_methods.add(method)
383*6777b538SAndroid Build Coastguard Worker      else:
384*6777b538SAndroid Build Coastguard Worker        self._known_vars.add(method)
385*6777b538SAndroid Build Coastguard Worker
386*6777b538SAndroid Build Coastguard Worker  def __getattr__(self, name):
387*6777b538SAndroid Build Coastguard Worker    """Intercept attribute request on this object.
388*6777b538SAndroid Build Coastguard Worker
389*6777b538SAndroid Build Coastguard Worker    If the attribute is a public class variable, it will be returned and not
390*6777b538SAndroid Build Coastguard Worker    recorded as a call.
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker    If the attribute is not a variable, it is handled like a method
393*6777b538SAndroid Build Coastguard Worker    call. The method name is checked against the set of mockable
394*6777b538SAndroid Build Coastguard Worker    methods, and a new MockMethod is returned that is aware of the
395*6777b538SAndroid Build Coastguard Worker    MockObject's state (record or replay).  The call will be recorded
396*6777b538SAndroid Build Coastguard Worker    or replayed by the MockMethod's __call__.
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker    Args:
399*6777b538SAndroid Build Coastguard Worker      # name: the name of the attribute being requested.
400*6777b538SAndroid Build Coastguard Worker      name: str
401*6777b538SAndroid Build Coastguard Worker
402*6777b538SAndroid Build Coastguard Worker    Returns:
403*6777b538SAndroid Build Coastguard Worker      Either a class variable or a new MockMethod that is aware of the state
404*6777b538SAndroid Build Coastguard Worker      of the mock (record or replay).
405*6777b538SAndroid Build Coastguard Worker
406*6777b538SAndroid Build Coastguard Worker    Raises:
407*6777b538SAndroid Build Coastguard Worker      UnknownMethodCallError if the MockObject does not mock the requested
408*6777b538SAndroid Build Coastguard Worker          method.
409*6777b538SAndroid Build Coastguard Worker    """
410*6777b538SAndroid Build Coastguard Worker
411*6777b538SAndroid Build Coastguard Worker    if name in self._known_vars:
412*6777b538SAndroid Build Coastguard Worker      return getattr(self._class_to_mock, name)
413*6777b538SAndroid Build Coastguard Worker
414*6777b538SAndroid Build Coastguard Worker    if name in self._known_methods:
415*6777b538SAndroid Build Coastguard Worker      return self._CreateMockMethod(name)
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker    raise UnknownMethodCallError(name)
418*6777b538SAndroid Build Coastguard Worker
419*6777b538SAndroid Build Coastguard Worker  def __eq__(self, rhs):
420*6777b538SAndroid Build Coastguard Worker    """Provide custom logic to compare objects."""
421*6777b538SAndroid Build Coastguard Worker
422*6777b538SAndroid Build Coastguard Worker    return (isinstance(rhs, MockObject) and
423*6777b538SAndroid Build Coastguard Worker            self._class_to_mock == rhs._class_to_mock and
424*6777b538SAndroid Build Coastguard Worker            self._replay_mode == rhs._replay_mode and
425*6777b538SAndroid Build Coastguard Worker            self._expected_calls_queue == rhs._expected_calls_queue)
426*6777b538SAndroid Build Coastguard Worker
427*6777b538SAndroid Build Coastguard Worker  def __setitem__(self, key, value):
428*6777b538SAndroid Build Coastguard Worker    """Provide custom logic for mocking classes that support item assignment.
429*6777b538SAndroid Build Coastguard Worker
430*6777b538SAndroid Build Coastguard Worker    Args:
431*6777b538SAndroid Build Coastguard Worker      key: Key to set the value for.
432*6777b538SAndroid Build Coastguard Worker      value: Value to set.
433*6777b538SAndroid Build Coastguard Worker
434*6777b538SAndroid Build Coastguard Worker    Returns:
435*6777b538SAndroid Build Coastguard Worker      Expected return value in replay mode.  A MockMethod object for the
436*6777b538SAndroid Build Coastguard Worker      __setitem__ method that has already been called if not in replay mode.
437*6777b538SAndroid Build Coastguard Worker
438*6777b538SAndroid Build Coastguard Worker    Raises:
439*6777b538SAndroid Build Coastguard Worker      TypeError if the underlying class does not support item assignment.
440*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCallError if the object does not expect the call to
441*6777b538SAndroid Build Coastguard Worker        __setitem__.
442*6777b538SAndroid Build Coastguard Worker
443*6777b538SAndroid Build Coastguard Worker    """
444*6777b538SAndroid Build Coastguard Worker    setitem = self._class_to_mock.__dict__.get('__setitem__', None)
445*6777b538SAndroid Build Coastguard Worker
446*6777b538SAndroid Build Coastguard Worker    # Verify the class supports item assignment.
447*6777b538SAndroid Build Coastguard Worker    if setitem is None:
448*6777b538SAndroid Build Coastguard Worker      raise TypeError('object does not support item assignment')
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker    # If we are in replay mode then simply call the mock __setitem__ method.
451*6777b538SAndroid Build Coastguard Worker    if self._replay_mode:
452*6777b538SAndroid Build Coastguard Worker      return MockMethod('__setitem__', self._expected_calls_queue,
453*6777b538SAndroid Build Coastguard Worker                        self._replay_mode)(key, value)
454*6777b538SAndroid Build Coastguard Worker
455*6777b538SAndroid Build Coastguard Worker
456*6777b538SAndroid Build Coastguard Worker    # Otherwise, create a mock method __setitem__.
457*6777b538SAndroid Build Coastguard Worker    return self._CreateMockMethod('__setitem__')(key, value)
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker  def __getitem__(self, key):
460*6777b538SAndroid Build Coastguard Worker    """Provide custom logic for mocking classes that are subscriptable.
461*6777b538SAndroid Build Coastguard Worker
462*6777b538SAndroid Build Coastguard Worker    Args:
463*6777b538SAndroid Build Coastguard Worker      key: Key to return the value for.
464*6777b538SAndroid Build Coastguard Worker
465*6777b538SAndroid Build Coastguard Worker    Returns:
466*6777b538SAndroid Build Coastguard Worker      Expected return value in replay mode.  A MockMethod object for the
467*6777b538SAndroid Build Coastguard Worker      __getitem__ method that has already been called if not in replay mode.
468*6777b538SAndroid Build Coastguard Worker
469*6777b538SAndroid Build Coastguard Worker    Raises:
470*6777b538SAndroid Build Coastguard Worker      TypeError if the underlying class is not subscriptable.
471*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCallError if the object does not expect the call to
472*6777b538SAndroid Build Coastguard Worker        __setitem__.
473*6777b538SAndroid Build Coastguard Worker
474*6777b538SAndroid Build Coastguard Worker    """
475*6777b538SAndroid Build Coastguard Worker    getitem = self._class_to_mock.__dict__.get('__getitem__', None)
476*6777b538SAndroid Build Coastguard Worker
477*6777b538SAndroid Build Coastguard Worker    # Verify the class supports item assignment.
478*6777b538SAndroid Build Coastguard Worker    if getitem is None:
479*6777b538SAndroid Build Coastguard Worker      raise TypeError('unsubscriptable object')
480*6777b538SAndroid Build Coastguard Worker
481*6777b538SAndroid Build Coastguard Worker    # If we are in replay mode then simply call the mock __getitem__ method.
482*6777b538SAndroid Build Coastguard Worker    if self._replay_mode:
483*6777b538SAndroid Build Coastguard Worker      return MockMethod('__getitem__', self._expected_calls_queue,
484*6777b538SAndroid Build Coastguard Worker                        self._replay_mode)(key)
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker
487*6777b538SAndroid Build Coastguard Worker    # Otherwise, create a mock method __getitem__.
488*6777b538SAndroid Build Coastguard Worker    return self._CreateMockMethod('__getitem__')(key)
489*6777b538SAndroid Build Coastguard Worker
490*6777b538SAndroid Build Coastguard Worker  def __call__(self, *params, **named_params):
491*6777b538SAndroid Build Coastguard Worker    """Provide custom logic for mocking classes that are callable."""
492*6777b538SAndroid Build Coastguard Worker
493*6777b538SAndroid Build Coastguard Worker    # Verify the class we are mocking is callable
494*6777b538SAndroid Build Coastguard Worker    callable = self._class_to_mock.__dict__.get('__call__', None)
495*6777b538SAndroid Build Coastguard Worker    if callable is None:
496*6777b538SAndroid Build Coastguard Worker      raise TypeError('Not callable')
497*6777b538SAndroid Build Coastguard Worker
498*6777b538SAndroid Build Coastguard Worker    # Because the call is happening directly on this object instead of a method,
499*6777b538SAndroid Build Coastguard Worker    # the call on the mock method is made right here
500*6777b538SAndroid Build Coastguard Worker    mock_method = self._CreateMockMethod('__call__')
501*6777b538SAndroid Build Coastguard Worker    return mock_method(*params, **named_params)
502*6777b538SAndroid Build Coastguard Worker
503*6777b538SAndroid Build Coastguard Worker  @property
504*6777b538SAndroid Build Coastguard Worker  def __class__(self):
505*6777b538SAndroid Build Coastguard Worker    """Return the class that is being mocked."""
506*6777b538SAndroid Build Coastguard Worker
507*6777b538SAndroid Build Coastguard Worker    return self._class_to_mock
508*6777b538SAndroid Build Coastguard Worker
509*6777b538SAndroid Build Coastguard Worker
510*6777b538SAndroid Build Coastguard Workerclass MockMethod(object):
511*6777b538SAndroid Build Coastguard Worker  """Callable mock method.
512*6777b538SAndroid Build Coastguard Worker
513*6777b538SAndroid Build Coastguard Worker  A MockMethod should act exactly like the method it mocks, accepting parameters
514*6777b538SAndroid Build Coastguard Worker  and returning a value, or throwing an exception (as specified).  When this
515*6777b538SAndroid Build Coastguard Worker  method is called, it can optionally verify whether the called method (name and
516*6777b538SAndroid Build Coastguard Worker  signature) matches the expected method.
517*6777b538SAndroid Build Coastguard Worker  """
518*6777b538SAndroid Build Coastguard Worker
519*6777b538SAndroid Build Coastguard Worker  def __init__(self, method_name, call_queue, replay_mode):
520*6777b538SAndroid Build Coastguard Worker    """Construct a new mock method.
521*6777b538SAndroid Build Coastguard Worker
522*6777b538SAndroid Build Coastguard Worker    Args:
523*6777b538SAndroid Build Coastguard Worker      # method_name: the name of the method
524*6777b538SAndroid Build Coastguard Worker      # call_queue: deque of calls, verify this call against the head, or add
525*6777b538SAndroid Build Coastguard Worker      #     this call to the queue.
526*6777b538SAndroid Build Coastguard Worker      # replay_mode: False if we are recording, True if we are verifying calls
527*6777b538SAndroid Build Coastguard Worker      #     against the call queue.
528*6777b538SAndroid Build Coastguard Worker      method_name: str
529*6777b538SAndroid Build Coastguard Worker      call_queue: list or deque
530*6777b538SAndroid Build Coastguard Worker      replay_mode: bool
531*6777b538SAndroid Build Coastguard Worker    """
532*6777b538SAndroid Build Coastguard Worker
533*6777b538SAndroid Build Coastguard Worker    self._name = method_name
534*6777b538SAndroid Build Coastguard Worker    self._call_queue = call_queue
535*6777b538SAndroid Build Coastguard Worker    if not isinstance(call_queue, deque):
536*6777b538SAndroid Build Coastguard Worker      self._call_queue = deque(self._call_queue)
537*6777b538SAndroid Build Coastguard Worker    self._replay_mode = replay_mode
538*6777b538SAndroid Build Coastguard Worker
539*6777b538SAndroid Build Coastguard Worker    self._params = None
540*6777b538SAndroid Build Coastguard Worker    self._named_params = None
541*6777b538SAndroid Build Coastguard Worker    self._return_value = None
542*6777b538SAndroid Build Coastguard Worker    self._exception = None
543*6777b538SAndroid Build Coastguard Worker    self._side_effects = None
544*6777b538SAndroid Build Coastguard Worker
545*6777b538SAndroid Build Coastguard Worker  def __call__(self, *params, **named_params):
546*6777b538SAndroid Build Coastguard Worker    """Log parameters and return the specified return value.
547*6777b538SAndroid Build Coastguard Worker
548*6777b538SAndroid Build Coastguard Worker    If the Mock(Anything/Object) associated with this call is in record mode,
549*6777b538SAndroid Build Coastguard Worker    this MockMethod will be pushed onto the expected call queue.  If the mock
550*6777b538SAndroid Build Coastguard Worker    is in replay mode, this will pop a MockMethod off the top of the queue and
551*6777b538SAndroid Build Coastguard Worker    verify this call is equal to the expected call.
552*6777b538SAndroid Build Coastguard Worker
553*6777b538SAndroid Build Coastguard Worker    Raises:
554*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCall if this call is supposed to match an expected method
555*6777b538SAndroid Build Coastguard Worker        call and it does not.
556*6777b538SAndroid Build Coastguard Worker    """
557*6777b538SAndroid Build Coastguard Worker
558*6777b538SAndroid Build Coastguard Worker    self._params = params
559*6777b538SAndroid Build Coastguard Worker    self._named_params = named_params
560*6777b538SAndroid Build Coastguard Worker
561*6777b538SAndroid Build Coastguard Worker    if not self._replay_mode:
562*6777b538SAndroid Build Coastguard Worker      self._call_queue.append(self)
563*6777b538SAndroid Build Coastguard Worker      return self
564*6777b538SAndroid Build Coastguard Worker
565*6777b538SAndroid Build Coastguard Worker    expected_method = self._VerifyMethodCall()
566*6777b538SAndroid Build Coastguard Worker
567*6777b538SAndroid Build Coastguard Worker    if expected_method._side_effects:
568*6777b538SAndroid Build Coastguard Worker      expected_method._side_effects(*params, **named_params)
569*6777b538SAndroid Build Coastguard Worker
570*6777b538SAndroid Build Coastguard Worker    if expected_method._exception:
571*6777b538SAndroid Build Coastguard Worker      raise expected_method._exception
572*6777b538SAndroid Build Coastguard Worker
573*6777b538SAndroid Build Coastguard Worker    return expected_method._return_value
574*6777b538SAndroid Build Coastguard Worker
575*6777b538SAndroid Build Coastguard Worker  def __getattr__(self, name):
576*6777b538SAndroid Build Coastguard Worker    """Raise an AttributeError with a helpful message."""
577*6777b538SAndroid Build Coastguard Worker
578*6777b538SAndroid Build Coastguard Worker    raise AttributeError('MockMethod has no attribute "%s". '
579*6777b538SAndroid Build Coastguard Worker        'Did you remember to put your mocks in replay mode?' % name)
580*6777b538SAndroid Build Coastguard Worker
581*6777b538SAndroid Build Coastguard Worker  def _PopNextMethod(self):
582*6777b538SAndroid Build Coastguard Worker    """Pop the next method from our call queue."""
583*6777b538SAndroid Build Coastguard Worker    try:
584*6777b538SAndroid Build Coastguard Worker      return self._call_queue.popleft()
585*6777b538SAndroid Build Coastguard Worker    except IndexError:
586*6777b538SAndroid Build Coastguard Worker      raise UnexpectedMethodCallError(self, None)
587*6777b538SAndroid Build Coastguard Worker
588*6777b538SAndroid Build Coastguard Worker  def _VerifyMethodCall(self):
589*6777b538SAndroid Build Coastguard Worker    """Verify the called method is expected.
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker    This can be an ordered method, or part of an unordered set.
592*6777b538SAndroid Build Coastguard Worker
593*6777b538SAndroid Build Coastguard Worker    Returns:
594*6777b538SAndroid Build Coastguard Worker      The expected mock method.
595*6777b538SAndroid Build Coastguard Worker
596*6777b538SAndroid Build Coastguard Worker    Raises:
597*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCall if the method called was not expected.
598*6777b538SAndroid Build Coastguard Worker    """
599*6777b538SAndroid Build Coastguard Worker
600*6777b538SAndroid Build Coastguard Worker    expected = self._PopNextMethod()
601*6777b538SAndroid Build Coastguard Worker
602*6777b538SAndroid Build Coastguard Worker    # Loop here, because we might have a MethodGroup followed by another
603*6777b538SAndroid Build Coastguard Worker    # group.
604*6777b538SAndroid Build Coastguard Worker    while isinstance(expected, MethodGroup):
605*6777b538SAndroid Build Coastguard Worker      expected, method = expected.MethodCalled(self)
606*6777b538SAndroid Build Coastguard Worker      if method is not None:
607*6777b538SAndroid Build Coastguard Worker        return method
608*6777b538SAndroid Build Coastguard Worker
609*6777b538SAndroid Build Coastguard Worker    # This is a mock method, so just check equality.
610*6777b538SAndroid Build Coastguard Worker    if expected != self:
611*6777b538SAndroid Build Coastguard Worker      raise UnexpectedMethodCallError(self, expected)
612*6777b538SAndroid Build Coastguard Worker
613*6777b538SAndroid Build Coastguard Worker    return expected
614*6777b538SAndroid Build Coastguard Worker
615*6777b538SAndroid Build Coastguard Worker  def __str__(self):
616*6777b538SAndroid Build Coastguard Worker    params = ', '.join(
617*6777b538SAndroid Build Coastguard Worker        [repr(p) for p in self._params or []] +
618*6777b538SAndroid Build Coastguard Worker        ['%s=%r' % x for x in sorted((self._named_params or {}).items())])
619*6777b538SAndroid Build Coastguard Worker    desc = "%s(%s) -> %r" % (self._name, params, self._return_value)
620*6777b538SAndroid Build Coastguard Worker    return desc
621*6777b538SAndroid Build Coastguard Worker
622*6777b538SAndroid Build Coastguard Worker  def __eq__(self, rhs):
623*6777b538SAndroid Build Coastguard Worker    """Test whether this MockMethod is equivalent to another MockMethod.
624*6777b538SAndroid Build Coastguard Worker
625*6777b538SAndroid Build Coastguard Worker    Args:
626*6777b538SAndroid Build Coastguard Worker      # rhs: the right hand side of the test
627*6777b538SAndroid Build Coastguard Worker      rhs: MockMethod
628*6777b538SAndroid Build Coastguard Worker    """
629*6777b538SAndroid Build Coastguard Worker
630*6777b538SAndroid Build Coastguard Worker    return (isinstance(rhs, MockMethod) and
631*6777b538SAndroid Build Coastguard Worker            self._name == rhs._name and
632*6777b538SAndroid Build Coastguard Worker            self._params == rhs._params and
633*6777b538SAndroid Build Coastguard Worker            self._named_params == rhs._named_params)
634*6777b538SAndroid Build Coastguard Worker
635*6777b538SAndroid Build Coastguard Worker  def __ne__(self, rhs):
636*6777b538SAndroid Build Coastguard Worker    """Test whether this MockMethod is not equivalent to another MockMethod.
637*6777b538SAndroid Build Coastguard Worker
638*6777b538SAndroid Build Coastguard Worker    Args:
639*6777b538SAndroid Build Coastguard Worker      # rhs: the right hand side of the test
640*6777b538SAndroid Build Coastguard Worker      rhs: MockMethod
641*6777b538SAndroid Build Coastguard Worker    """
642*6777b538SAndroid Build Coastguard Worker
643*6777b538SAndroid Build Coastguard Worker    return not self == rhs
644*6777b538SAndroid Build Coastguard Worker
645*6777b538SAndroid Build Coastguard Worker  def GetPossibleGroup(self):
646*6777b538SAndroid Build Coastguard Worker    """Returns a possible group from the end of the call queue or None if no
647*6777b538SAndroid Build Coastguard Worker    other methods are on the stack.
648*6777b538SAndroid Build Coastguard Worker    """
649*6777b538SAndroid Build Coastguard Worker
650*6777b538SAndroid Build Coastguard Worker    # Remove this method from the tail of the queue so we can add it to a group.
651*6777b538SAndroid Build Coastguard Worker    this_method = self._call_queue.pop()
652*6777b538SAndroid Build Coastguard Worker    assert this_method == self
653*6777b538SAndroid Build Coastguard Worker
654*6777b538SAndroid Build Coastguard Worker    # Determine if the tail of the queue is a group, or just a regular ordered
655*6777b538SAndroid Build Coastguard Worker    # mock method.
656*6777b538SAndroid Build Coastguard Worker    group = None
657*6777b538SAndroid Build Coastguard Worker    try:
658*6777b538SAndroid Build Coastguard Worker      group = self._call_queue[-1]
659*6777b538SAndroid Build Coastguard Worker    except IndexError:
660*6777b538SAndroid Build Coastguard Worker      pass
661*6777b538SAndroid Build Coastguard Worker
662*6777b538SAndroid Build Coastguard Worker    return group
663*6777b538SAndroid Build Coastguard Worker
664*6777b538SAndroid Build Coastguard Worker  def _CheckAndCreateNewGroup(self, group_name, group_class):
665*6777b538SAndroid Build Coastguard Worker    """Checks if the last method (a possible group) is an instance of our
666*6777b538SAndroid Build Coastguard Worker    group_class. Adds the current method to this group or creates a new one.
667*6777b538SAndroid Build Coastguard Worker
668*6777b538SAndroid Build Coastguard Worker    Args:
669*6777b538SAndroid Build Coastguard Worker
670*6777b538SAndroid Build Coastguard Worker      group_name: the name of the group.
671*6777b538SAndroid Build Coastguard Worker      group_class: the class used to create instance of this new group
672*6777b538SAndroid Build Coastguard Worker    """
673*6777b538SAndroid Build Coastguard Worker    group = self.GetPossibleGroup()
674*6777b538SAndroid Build Coastguard Worker
675*6777b538SAndroid Build Coastguard Worker    # If this is a group, and it is the correct group, add the method.
676*6777b538SAndroid Build Coastguard Worker    if isinstance(group, group_class) and group.group_name() == group_name:
677*6777b538SAndroid Build Coastguard Worker      group.AddMethod(self)
678*6777b538SAndroid Build Coastguard Worker      return self
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker    # Create a new group and add the method.
681*6777b538SAndroid Build Coastguard Worker    new_group = group_class(group_name)
682*6777b538SAndroid Build Coastguard Worker    new_group.AddMethod(self)
683*6777b538SAndroid Build Coastguard Worker    self._call_queue.append(new_group)
684*6777b538SAndroid Build Coastguard Worker    return self
685*6777b538SAndroid Build Coastguard Worker
686*6777b538SAndroid Build Coastguard Worker  def InAnyOrder(self, group_name="default"):
687*6777b538SAndroid Build Coastguard Worker    """Move this method into a group of unordered calls.
688*6777b538SAndroid Build Coastguard Worker
689*6777b538SAndroid Build Coastguard Worker    A group of unordered calls must be defined together, and must be executed
690*6777b538SAndroid Build Coastguard Worker    in full before the next expected method can be called.  There can be
691*6777b538SAndroid Build Coastguard Worker    multiple groups that are expected serially, if they are given
692*6777b538SAndroid Build Coastguard Worker    different group names.  The same group name can be reused if there is a
693*6777b538SAndroid Build Coastguard Worker    standard method call, or a group with a different name, spliced between
694*6777b538SAndroid Build Coastguard Worker    usages.
695*6777b538SAndroid Build Coastguard Worker
696*6777b538SAndroid Build Coastguard Worker    Args:
697*6777b538SAndroid Build Coastguard Worker      group_name: the name of the unordered group.
698*6777b538SAndroid Build Coastguard Worker
699*6777b538SAndroid Build Coastguard Worker    Returns:
700*6777b538SAndroid Build Coastguard Worker      self
701*6777b538SAndroid Build Coastguard Worker    """
702*6777b538SAndroid Build Coastguard Worker    return self._CheckAndCreateNewGroup(group_name, UnorderedGroup)
703*6777b538SAndroid Build Coastguard Worker
704*6777b538SAndroid Build Coastguard Worker  def MultipleTimes(self, group_name="default"):
705*6777b538SAndroid Build Coastguard Worker    """Move this method into group of calls which may be called multiple times.
706*6777b538SAndroid Build Coastguard Worker
707*6777b538SAndroid Build Coastguard Worker    A group of repeating calls must be defined together, and must be executed in
708*6777b538SAndroid Build Coastguard Worker    full before the next expected method can be called.
709*6777b538SAndroid Build Coastguard Worker
710*6777b538SAndroid Build Coastguard Worker    Args:
711*6777b538SAndroid Build Coastguard Worker      group_name: the name of the unordered group.
712*6777b538SAndroid Build Coastguard Worker
713*6777b538SAndroid Build Coastguard Worker    Returns:
714*6777b538SAndroid Build Coastguard Worker      self
715*6777b538SAndroid Build Coastguard Worker    """
716*6777b538SAndroid Build Coastguard Worker    return self._CheckAndCreateNewGroup(group_name, MultipleTimesGroup)
717*6777b538SAndroid Build Coastguard Worker
718*6777b538SAndroid Build Coastguard Worker  def AndReturn(self, return_value):
719*6777b538SAndroid Build Coastguard Worker    """Set the value to return when this method is called.
720*6777b538SAndroid Build Coastguard Worker
721*6777b538SAndroid Build Coastguard Worker    Args:
722*6777b538SAndroid Build Coastguard Worker      # return_value can be anything.
723*6777b538SAndroid Build Coastguard Worker    """
724*6777b538SAndroid Build Coastguard Worker
725*6777b538SAndroid Build Coastguard Worker    self._return_value = return_value
726*6777b538SAndroid Build Coastguard Worker    return return_value
727*6777b538SAndroid Build Coastguard Worker
728*6777b538SAndroid Build Coastguard Worker  def AndRaise(self, exception):
729*6777b538SAndroid Build Coastguard Worker    """Set the exception to raise when this method is called.
730*6777b538SAndroid Build Coastguard Worker
731*6777b538SAndroid Build Coastguard Worker    Args:
732*6777b538SAndroid Build Coastguard Worker      # exception: the exception to raise when this method is called.
733*6777b538SAndroid Build Coastguard Worker      exception: Exception
734*6777b538SAndroid Build Coastguard Worker    """
735*6777b538SAndroid Build Coastguard Worker
736*6777b538SAndroid Build Coastguard Worker    self._exception = exception
737*6777b538SAndroid Build Coastguard Worker
738*6777b538SAndroid Build Coastguard Worker  def WithSideEffects(self, side_effects):
739*6777b538SAndroid Build Coastguard Worker    """Set the side effects that are simulated when this method is called.
740*6777b538SAndroid Build Coastguard Worker
741*6777b538SAndroid Build Coastguard Worker    Args:
742*6777b538SAndroid Build Coastguard Worker      side_effects: A callable which modifies the parameters or other relevant
743*6777b538SAndroid Build Coastguard Worker        state which a given test case depends on.
744*6777b538SAndroid Build Coastguard Worker
745*6777b538SAndroid Build Coastguard Worker    Returns:
746*6777b538SAndroid Build Coastguard Worker      Self for chaining with AndReturn and AndRaise.
747*6777b538SAndroid Build Coastguard Worker    """
748*6777b538SAndroid Build Coastguard Worker    self._side_effects = side_effects
749*6777b538SAndroid Build Coastguard Worker    return self
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Workerclass Comparator:
752*6777b538SAndroid Build Coastguard Worker  """Base class for all Mox comparators.
753*6777b538SAndroid Build Coastguard Worker
754*6777b538SAndroid Build Coastguard Worker  A Comparator can be used as a parameter to a mocked method when the exact
755*6777b538SAndroid Build Coastguard Worker  value is not known.  For example, the code you are testing might build up a
756*6777b538SAndroid Build Coastguard Worker  long SQL string that is passed to your mock DAO. You're only interested that
757*6777b538SAndroid Build Coastguard Worker  the IN clause contains the proper primary keys, so you can set your mock
758*6777b538SAndroid Build Coastguard Worker  up as follows:
759*6777b538SAndroid Build Coastguard Worker
760*6777b538SAndroid Build Coastguard Worker  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
761*6777b538SAndroid Build Coastguard Worker
762*6777b538SAndroid Build Coastguard Worker  Now whatever query is passed in must contain the string 'IN (1, 2, 4, 5)'.
763*6777b538SAndroid Build Coastguard Worker
764*6777b538SAndroid Build Coastguard Worker  A Comparator may replace one or more parameters, for example:
765*6777b538SAndroid Build Coastguard Worker  # return at most 10 rows
766*6777b538SAndroid Build Coastguard Worker  mock_dao.RunQuery(StrContains('SELECT'), 10)
767*6777b538SAndroid Build Coastguard Worker
768*6777b538SAndroid Build Coastguard Worker  or
769*6777b538SAndroid Build Coastguard Worker
770*6777b538SAndroid Build Coastguard Worker  # Return some non-deterministic number of rows
771*6777b538SAndroid Build Coastguard Worker  mock_dao.RunQuery(StrContains('SELECT'), IsA(int))
772*6777b538SAndroid Build Coastguard Worker  """
773*6777b538SAndroid Build Coastguard Worker
774*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
775*6777b538SAndroid Build Coastguard Worker    """Special equals method that all comparators must implement.
776*6777b538SAndroid Build Coastguard Worker
777*6777b538SAndroid Build Coastguard Worker    Args:
778*6777b538SAndroid Build Coastguard Worker      rhs: any python object
779*6777b538SAndroid Build Coastguard Worker    """
780*6777b538SAndroid Build Coastguard Worker
781*6777b538SAndroid Build Coastguard Worker    raise NotImplementedError('method must be implemented by a subclass.')
782*6777b538SAndroid Build Coastguard Worker
783*6777b538SAndroid Build Coastguard Worker  def __eq__(self, rhs):
784*6777b538SAndroid Build Coastguard Worker    return self.equals(rhs)
785*6777b538SAndroid Build Coastguard Worker
786*6777b538SAndroid Build Coastguard Worker  def __ne__(self, rhs):
787*6777b538SAndroid Build Coastguard Worker    return not self.equals(rhs)
788*6777b538SAndroid Build Coastguard Worker
789*6777b538SAndroid Build Coastguard Worker
790*6777b538SAndroid Build Coastguard Workerclass IsA(Comparator):
791*6777b538SAndroid Build Coastguard Worker  """This class wraps a basic Python type or class.  It is used to verify
792*6777b538SAndroid Build Coastguard Worker  that a parameter is of the given type or class.
793*6777b538SAndroid Build Coastguard Worker
794*6777b538SAndroid Build Coastguard Worker  Example:
795*6777b538SAndroid Build Coastguard Worker  mock_dao.Connect(IsA(DbConnectInfo))
796*6777b538SAndroid Build Coastguard Worker  """
797*6777b538SAndroid Build Coastguard Worker
798*6777b538SAndroid Build Coastguard Worker  def __init__(self, class_name):
799*6777b538SAndroid Build Coastguard Worker    """Initialize IsA
800*6777b538SAndroid Build Coastguard Worker
801*6777b538SAndroid Build Coastguard Worker    Args:
802*6777b538SAndroid Build Coastguard Worker      class_name: basic python type or a class
803*6777b538SAndroid Build Coastguard Worker    """
804*6777b538SAndroid Build Coastguard Worker
805*6777b538SAndroid Build Coastguard Worker    self._class_name = class_name
806*6777b538SAndroid Build Coastguard Worker
807*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
808*6777b538SAndroid Build Coastguard Worker    """Check to see if the RHS is an instance of class_name.
809*6777b538SAndroid Build Coastguard Worker
810*6777b538SAndroid Build Coastguard Worker    Args:
811*6777b538SAndroid Build Coastguard Worker      # rhs: the right hand side of the test
812*6777b538SAndroid Build Coastguard Worker      rhs: object
813*6777b538SAndroid Build Coastguard Worker
814*6777b538SAndroid Build Coastguard Worker    Returns:
815*6777b538SAndroid Build Coastguard Worker      bool
816*6777b538SAndroid Build Coastguard Worker    """
817*6777b538SAndroid Build Coastguard Worker
818*6777b538SAndroid Build Coastguard Worker    try:
819*6777b538SAndroid Build Coastguard Worker      return isinstance(rhs, self._class_name)
820*6777b538SAndroid Build Coastguard Worker    except TypeError:
821*6777b538SAndroid Build Coastguard Worker      # Check raw types if there was a type error.  This is helpful for
822*6777b538SAndroid Build Coastguard Worker      # things like cStringIO.StringIO.
823*6777b538SAndroid Build Coastguard Worker      return type(rhs) == type(self._class_name)
824*6777b538SAndroid Build Coastguard Worker
825*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
826*6777b538SAndroid Build Coastguard Worker    return str(self._class_name)
827*6777b538SAndroid Build Coastguard Worker
828*6777b538SAndroid Build Coastguard Workerclass IsAlmost(Comparator):
829*6777b538SAndroid Build Coastguard Worker  """Comparison class used to check whether a parameter is nearly equal
830*6777b538SAndroid Build Coastguard Worker  to a given value.  Generally useful for floating point numbers.
831*6777b538SAndroid Build Coastguard Worker
832*6777b538SAndroid Build Coastguard Worker  Example mock_dao.SetTimeout((IsAlmost(3.9)))
833*6777b538SAndroid Build Coastguard Worker  """
834*6777b538SAndroid Build Coastguard Worker
835*6777b538SAndroid Build Coastguard Worker  def __init__(self, float_value, places=7):
836*6777b538SAndroid Build Coastguard Worker    """Initialize IsAlmost.
837*6777b538SAndroid Build Coastguard Worker
838*6777b538SAndroid Build Coastguard Worker    Args:
839*6777b538SAndroid Build Coastguard Worker      float_value: The value for making the comparison.
840*6777b538SAndroid Build Coastguard Worker      places: The number of decimal places to round to.
841*6777b538SAndroid Build Coastguard Worker    """
842*6777b538SAndroid Build Coastguard Worker
843*6777b538SAndroid Build Coastguard Worker    self._float_value = float_value
844*6777b538SAndroid Build Coastguard Worker    self._places = places
845*6777b538SAndroid Build Coastguard Worker
846*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
847*6777b538SAndroid Build Coastguard Worker    """Check to see if RHS is almost equal to float_value
848*6777b538SAndroid Build Coastguard Worker
849*6777b538SAndroid Build Coastguard Worker    Args:
850*6777b538SAndroid Build Coastguard Worker      rhs: the value to compare to float_value
851*6777b538SAndroid Build Coastguard Worker
852*6777b538SAndroid Build Coastguard Worker    Returns:
853*6777b538SAndroid Build Coastguard Worker      bool
854*6777b538SAndroid Build Coastguard Worker    """
855*6777b538SAndroid Build Coastguard Worker
856*6777b538SAndroid Build Coastguard Worker    try:
857*6777b538SAndroid Build Coastguard Worker      return round(rhs-self._float_value, self._places) == 0
858*6777b538SAndroid Build Coastguard Worker    except TypeError:
859*6777b538SAndroid Build Coastguard Worker      # This is probably because either float_value or rhs is not a number.
860*6777b538SAndroid Build Coastguard Worker      return False
861*6777b538SAndroid Build Coastguard Worker
862*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
863*6777b538SAndroid Build Coastguard Worker    return str(self._float_value)
864*6777b538SAndroid Build Coastguard Worker
865*6777b538SAndroid Build Coastguard Workerclass StrContains(Comparator):
866*6777b538SAndroid Build Coastguard Worker  """Comparison class used to check whether a substring exists in a
867*6777b538SAndroid Build Coastguard Worker  string parameter.  This can be useful in mocking a database with SQL
868*6777b538SAndroid Build Coastguard Worker  passed in as a string parameter, for example.
869*6777b538SAndroid Build Coastguard Worker
870*6777b538SAndroid Build Coastguard Worker  Example:
871*6777b538SAndroid Build Coastguard Worker  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
872*6777b538SAndroid Build Coastguard Worker  """
873*6777b538SAndroid Build Coastguard Worker
874*6777b538SAndroid Build Coastguard Worker  def __init__(self, search_string):
875*6777b538SAndroid Build Coastguard Worker    """Initialize.
876*6777b538SAndroid Build Coastguard Worker
877*6777b538SAndroid Build Coastguard Worker    Args:
878*6777b538SAndroid Build Coastguard Worker      # search_string: the string you are searching for
879*6777b538SAndroid Build Coastguard Worker      search_string: str
880*6777b538SAndroid Build Coastguard Worker    """
881*6777b538SAndroid Build Coastguard Worker
882*6777b538SAndroid Build Coastguard Worker    self._search_string = search_string
883*6777b538SAndroid Build Coastguard Worker
884*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
885*6777b538SAndroid Build Coastguard Worker    """Check to see if the search_string is contained in the rhs string.
886*6777b538SAndroid Build Coastguard Worker
887*6777b538SAndroid Build Coastguard Worker    Args:
888*6777b538SAndroid Build Coastguard Worker      # rhs: the right hand side of the test
889*6777b538SAndroid Build Coastguard Worker      rhs: object
890*6777b538SAndroid Build Coastguard Worker
891*6777b538SAndroid Build Coastguard Worker    Returns:
892*6777b538SAndroid Build Coastguard Worker      bool
893*6777b538SAndroid Build Coastguard Worker    """
894*6777b538SAndroid Build Coastguard Worker
895*6777b538SAndroid Build Coastguard Worker    try:
896*6777b538SAndroid Build Coastguard Worker      return rhs.find(self._search_string) > -1
897*6777b538SAndroid Build Coastguard Worker    except Exception:
898*6777b538SAndroid Build Coastguard Worker      return False
899*6777b538SAndroid Build Coastguard Worker
900*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
901*6777b538SAndroid Build Coastguard Worker    return '<str containing \'%s\'>' % self._search_string
902*6777b538SAndroid Build Coastguard Worker
903*6777b538SAndroid Build Coastguard Worker
904*6777b538SAndroid Build Coastguard Workerclass Regex(Comparator):
905*6777b538SAndroid Build Coastguard Worker  """Checks if a string matches a regular expression.
906*6777b538SAndroid Build Coastguard Worker
907*6777b538SAndroid Build Coastguard Worker  This uses a given regular expression to determine equality.
908*6777b538SAndroid Build Coastguard Worker  """
909*6777b538SAndroid Build Coastguard Worker
910*6777b538SAndroid Build Coastguard Worker  def __init__(self, pattern, flags=0):
911*6777b538SAndroid Build Coastguard Worker    """Initialize.
912*6777b538SAndroid Build Coastguard Worker
913*6777b538SAndroid Build Coastguard Worker    Args:
914*6777b538SAndroid Build Coastguard Worker      # pattern is the regular expression to search for
915*6777b538SAndroid Build Coastguard Worker      pattern: str
916*6777b538SAndroid Build Coastguard Worker      # flags passed to re.compile function as the second argument
917*6777b538SAndroid Build Coastguard Worker      flags: int
918*6777b538SAndroid Build Coastguard Worker    """
919*6777b538SAndroid Build Coastguard Worker
920*6777b538SAndroid Build Coastguard Worker    self.regex = re.compile(pattern, flags=flags)
921*6777b538SAndroid Build Coastguard Worker
922*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
923*6777b538SAndroid Build Coastguard Worker    """Check to see if rhs matches regular expression pattern.
924*6777b538SAndroid Build Coastguard Worker
925*6777b538SAndroid Build Coastguard Worker    Returns:
926*6777b538SAndroid Build Coastguard Worker      bool
927*6777b538SAndroid Build Coastguard Worker    """
928*6777b538SAndroid Build Coastguard Worker
929*6777b538SAndroid Build Coastguard Worker    return self.regex.search(rhs) is not None
930*6777b538SAndroid Build Coastguard Worker
931*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
932*6777b538SAndroid Build Coastguard Worker    s = '<regular expression \'%s\'' % self.regex.pattern
933*6777b538SAndroid Build Coastguard Worker    if self.regex.flags:
934*6777b538SAndroid Build Coastguard Worker      s += ', flags=%d' % self.regex.flags
935*6777b538SAndroid Build Coastguard Worker    s += '>'
936*6777b538SAndroid Build Coastguard Worker    return s
937*6777b538SAndroid Build Coastguard Worker
938*6777b538SAndroid Build Coastguard Worker
939*6777b538SAndroid Build Coastguard Workerclass In(Comparator):
940*6777b538SAndroid Build Coastguard Worker  """Checks whether an item (or key) is in a list (or dict) parameter.
941*6777b538SAndroid Build Coastguard Worker
942*6777b538SAndroid Build Coastguard Worker  Example:
943*6777b538SAndroid Build Coastguard Worker  mock_dao.GetUsersInfo(In('expectedUserName')).AndReturn(mock_result)
944*6777b538SAndroid Build Coastguard Worker  """
945*6777b538SAndroid Build Coastguard Worker
946*6777b538SAndroid Build Coastguard Worker  def __init__(self, key):
947*6777b538SAndroid Build Coastguard Worker    """Initialize.
948*6777b538SAndroid Build Coastguard Worker
949*6777b538SAndroid Build Coastguard Worker    Args:
950*6777b538SAndroid Build Coastguard Worker      # key is any thing that could be in a list or a key in a dict
951*6777b538SAndroid Build Coastguard Worker    """
952*6777b538SAndroid Build Coastguard Worker
953*6777b538SAndroid Build Coastguard Worker    self._key = key
954*6777b538SAndroid Build Coastguard Worker
955*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
956*6777b538SAndroid Build Coastguard Worker    """Check to see whether key is in rhs.
957*6777b538SAndroid Build Coastguard Worker
958*6777b538SAndroid Build Coastguard Worker    Args:
959*6777b538SAndroid Build Coastguard Worker      rhs: dict
960*6777b538SAndroid Build Coastguard Worker
961*6777b538SAndroid Build Coastguard Worker    Returns:
962*6777b538SAndroid Build Coastguard Worker      bool
963*6777b538SAndroid Build Coastguard Worker    """
964*6777b538SAndroid Build Coastguard Worker
965*6777b538SAndroid Build Coastguard Worker    return self._key in rhs
966*6777b538SAndroid Build Coastguard Worker
967*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
968*6777b538SAndroid Build Coastguard Worker    return '<sequence or map containing \'%s\'>' % self._key
969*6777b538SAndroid Build Coastguard Worker
970*6777b538SAndroid Build Coastguard Worker
971*6777b538SAndroid Build Coastguard Workerclass ContainsKeyValue(Comparator):
972*6777b538SAndroid Build Coastguard Worker  """Checks whether a key/value pair is in a dict parameter.
973*6777b538SAndroid Build Coastguard Worker
974*6777b538SAndroid Build Coastguard Worker  Example:
975*6777b538SAndroid Build Coastguard Worker  mock_dao.UpdateUsers(ContainsKeyValue('stevepm', stevepm_user_info))
976*6777b538SAndroid Build Coastguard Worker  """
977*6777b538SAndroid Build Coastguard Worker
978*6777b538SAndroid Build Coastguard Worker  def __init__(self, key, value):
979*6777b538SAndroid Build Coastguard Worker    """Initialize.
980*6777b538SAndroid Build Coastguard Worker
981*6777b538SAndroid Build Coastguard Worker    Args:
982*6777b538SAndroid Build Coastguard Worker      # key: a key in a dict
983*6777b538SAndroid Build Coastguard Worker      # value: the corresponding value
984*6777b538SAndroid Build Coastguard Worker    """
985*6777b538SAndroid Build Coastguard Worker
986*6777b538SAndroid Build Coastguard Worker    self._key = key
987*6777b538SAndroid Build Coastguard Worker    self._value = value
988*6777b538SAndroid Build Coastguard Worker
989*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
990*6777b538SAndroid Build Coastguard Worker    """Check whether the given key/value pair is in the rhs dict.
991*6777b538SAndroid Build Coastguard Worker
992*6777b538SAndroid Build Coastguard Worker    Returns:
993*6777b538SAndroid Build Coastguard Worker      bool
994*6777b538SAndroid Build Coastguard Worker    """
995*6777b538SAndroid Build Coastguard Worker
996*6777b538SAndroid Build Coastguard Worker    try:
997*6777b538SAndroid Build Coastguard Worker      return rhs[self._key] == self._value
998*6777b538SAndroid Build Coastguard Worker    except Exception:
999*6777b538SAndroid Build Coastguard Worker      return False
1000*6777b538SAndroid Build Coastguard Worker
1001*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1002*6777b538SAndroid Build Coastguard Worker    return '<map containing the entry \'%s: %s\'>' % (self._key, self._value)
1003*6777b538SAndroid Build Coastguard Worker
1004*6777b538SAndroid Build Coastguard Worker
1005*6777b538SAndroid Build Coastguard Workerclass SameElementsAs(Comparator):
1006*6777b538SAndroid Build Coastguard Worker  """Checks whether iterables contain the same elements (ignoring order).
1007*6777b538SAndroid Build Coastguard Worker
1008*6777b538SAndroid Build Coastguard Worker  Example:
1009*6777b538SAndroid Build Coastguard Worker  mock_dao.ProcessUsers(SameElementsAs('stevepm', 'salomaki'))
1010*6777b538SAndroid Build Coastguard Worker  """
1011*6777b538SAndroid Build Coastguard Worker
1012*6777b538SAndroid Build Coastguard Worker  def __init__(self, expected_seq):
1013*6777b538SAndroid Build Coastguard Worker    """Initialize.
1014*6777b538SAndroid Build Coastguard Worker
1015*6777b538SAndroid Build Coastguard Worker    Args:
1016*6777b538SAndroid Build Coastguard Worker      expected_seq: a sequence
1017*6777b538SAndroid Build Coastguard Worker    """
1018*6777b538SAndroid Build Coastguard Worker
1019*6777b538SAndroid Build Coastguard Worker    self._expected_seq = expected_seq
1020*6777b538SAndroid Build Coastguard Worker
1021*6777b538SAndroid Build Coastguard Worker  def equals(self, actual_seq):
1022*6777b538SAndroid Build Coastguard Worker    """Check to see whether actual_seq has same elements as expected_seq.
1023*6777b538SAndroid Build Coastguard Worker
1024*6777b538SAndroid Build Coastguard Worker    Args:
1025*6777b538SAndroid Build Coastguard Worker      actual_seq: sequence
1026*6777b538SAndroid Build Coastguard Worker
1027*6777b538SAndroid Build Coastguard Worker    Returns:
1028*6777b538SAndroid Build Coastguard Worker      bool
1029*6777b538SAndroid Build Coastguard Worker    """
1030*6777b538SAndroid Build Coastguard Worker
1031*6777b538SAndroid Build Coastguard Worker    try:
1032*6777b538SAndroid Build Coastguard Worker      expected = dict([(element, None) for element in self._expected_seq])
1033*6777b538SAndroid Build Coastguard Worker      actual = dict([(element, None) for element in actual_seq])
1034*6777b538SAndroid Build Coastguard Worker    except TypeError:
1035*6777b538SAndroid Build Coastguard Worker      # Fall back to slower list-compare if any of the objects are unhashable.
1036*6777b538SAndroid Build Coastguard Worker      expected = list(self._expected_seq)
1037*6777b538SAndroid Build Coastguard Worker      actual = list(actual_seq)
1038*6777b538SAndroid Build Coastguard Worker      expected.sort()
1039*6777b538SAndroid Build Coastguard Worker      actual.sort()
1040*6777b538SAndroid Build Coastguard Worker    return expected == actual
1041*6777b538SAndroid Build Coastguard Worker
1042*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1043*6777b538SAndroid Build Coastguard Worker    return '<sequence with same elements as \'%s\'>' % self._expected_seq
1044*6777b538SAndroid Build Coastguard Worker
1045*6777b538SAndroid Build Coastguard Worker
1046*6777b538SAndroid Build Coastguard Workerclass And(Comparator):
1047*6777b538SAndroid Build Coastguard Worker  """Evaluates one or more Comparators on RHS and returns an AND of the results.
1048*6777b538SAndroid Build Coastguard Worker  """
1049*6777b538SAndroid Build Coastguard Worker
1050*6777b538SAndroid Build Coastguard Worker  def __init__(self, *args):
1051*6777b538SAndroid Build Coastguard Worker    """Initialize.
1052*6777b538SAndroid Build Coastguard Worker
1053*6777b538SAndroid Build Coastguard Worker    Args:
1054*6777b538SAndroid Build Coastguard Worker      *args: One or more Comparator
1055*6777b538SAndroid Build Coastguard Worker    """
1056*6777b538SAndroid Build Coastguard Worker
1057*6777b538SAndroid Build Coastguard Worker    self._comparators = args
1058*6777b538SAndroid Build Coastguard Worker
1059*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
1060*6777b538SAndroid Build Coastguard Worker    """Checks whether all Comparators are equal to rhs.
1061*6777b538SAndroid Build Coastguard Worker
1062*6777b538SAndroid Build Coastguard Worker    Args:
1063*6777b538SAndroid Build Coastguard Worker      # rhs: can be anything
1064*6777b538SAndroid Build Coastguard Worker
1065*6777b538SAndroid Build Coastguard Worker    Returns:
1066*6777b538SAndroid Build Coastguard Worker      bool
1067*6777b538SAndroid Build Coastguard Worker    """
1068*6777b538SAndroid Build Coastguard Worker
1069*6777b538SAndroid Build Coastguard Worker    for comparator in self._comparators:
1070*6777b538SAndroid Build Coastguard Worker      if not comparator.equals(rhs):
1071*6777b538SAndroid Build Coastguard Worker        return False
1072*6777b538SAndroid Build Coastguard Worker
1073*6777b538SAndroid Build Coastguard Worker    return True
1074*6777b538SAndroid Build Coastguard Worker
1075*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1076*6777b538SAndroid Build Coastguard Worker    return '<AND %s>' % str(self._comparators)
1077*6777b538SAndroid Build Coastguard Worker
1078*6777b538SAndroid Build Coastguard Worker
1079*6777b538SAndroid Build Coastguard Workerclass Or(Comparator):
1080*6777b538SAndroid Build Coastguard Worker  """Evaluates one or more Comparators on RHS and returns an OR of the results.
1081*6777b538SAndroid Build Coastguard Worker  """
1082*6777b538SAndroid Build Coastguard Worker
1083*6777b538SAndroid Build Coastguard Worker  def __init__(self, *args):
1084*6777b538SAndroid Build Coastguard Worker    """Initialize.
1085*6777b538SAndroid Build Coastguard Worker
1086*6777b538SAndroid Build Coastguard Worker    Args:
1087*6777b538SAndroid Build Coastguard Worker      *args: One or more Mox comparators
1088*6777b538SAndroid Build Coastguard Worker    """
1089*6777b538SAndroid Build Coastguard Worker
1090*6777b538SAndroid Build Coastguard Worker    self._comparators = args
1091*6777b538SAndroid Build Coastguard Worker
1092*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
1093*6777b538SAndroid Build Coastguard Worker    """Checks whether any Comparator is equal to rhs.
1094*6777b538SAndroid Build Coastguard Worker
1095*6777b538SAndroid Build Coastguard Worker    Args:
1096*6777b538SAndroid Build Coastguard Worker      # rhs: can be anything
1097*6777b538SAndroid Build Coastguard Worker
1098*6777b538SAndroid Build Coastguard Worker    Returns:
1099*6777b538SAndroid Build Coastguard Worker      bool
1100*6777b538SAndroid Build Coastguard Worker    """
1101*6777b538SAndroid Build Coastguard Worker
1102*6777b538SAndroid Build Coastguard Worker    for comparator in self._comparators:
1103*6777b538SAndroid Build Coastguard Worker      if comparator.equals(rhs):
1104*6777b538SAndroid Build Coastguard Worker        return True
1105*6777b538SAndroid Build Coastguard Worker
1106*6777b538SAndroid Build Coastguard Worker    return False
1107*6777b538SAndroid Build Coastguard Worker
1108*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1109*6777b538SAndroid Build Coastguard Worker    return '<OR %s>' % str(self._comparators)
1110*6777b538SAndroid Build Coastguard Worker
1111*6777b538SAndroid Build Coastguard Worker
1112*6777b538SAndroid Build Coastguard Workerclass Func(Comparator):
1113*6777b538SAndroid Build Coastguard Worker  """Call a function that should verify the parameter passed in is correct.
1114*6777b538SAndroid Build Coastguard Worker
1115*6777b538SAndroid Build Coastguard Worker  You may need the ability to perform more advanced operations on the parameter
1116*6777b538SAndroid Build Coastguard Worker  in order to validate it.  You can use this to have a callable validate any
1117*6777b538SAndroid Build Coastguard Worker  parameter. The callable should return either True or False.
1118*6777b538SAndroid Build Coastguard Worker
1119*6777b538SAndroid Build Coastguard Worker
1120*6777b538SAndroid Build Coastguard Worker  Example:
1121*6777b538SAndroid Build Coastguard Worker
1122*6777b538SAndroid Build Coastguard Worker  def myParamValidator(param):
1123*6777b538SAndroid Build Coastguard Worker    # Advanced logic here
1124*6777b538SAndroid Build Coastguard Worker    return True
1125*6777b538SAndroid Build Coastguard Worker
1126*6777b538SAndroid Build Coastguard Worker  mock_dao.DoSomething(Func(myParamValidator), true)
1127*6777b538SAndroid Build Coastguard Worker  """
1128*6777b538SAndroid Build Coastguard Worker
1129*6777b538SAndroid Build Coastguard Worker  def __init__(self, func):
1130*6777b538SAndroid Build Coastguard Worker    """Initialize.
1131*6777b538SAndroid Build Coastguard Worker
1132*6777b538SAndroid Build Coastguard Worker    Args:
1133*6777b538SAndroid Build Coastguard Worker      func: callable that takes one parameter and returns a bool
1134*6777b538SAndroid Build Coastguard Worker    """
1135*6777b538SAndroid Build Coastguard Worker
1136*6777b538SAndroid Build Coastguard Worker    self._func = func
1137*6777b538SAndroid Build Coastguard Worker
1138*6777b538SAndroid Build Coastguard Worker  def equals(self, rhs):
1139*6777b538SAndroid Build Coastguard Worker    """Test whether rhs passes the function test.
1140*6777b538SAndroid Build Coastguard Worker
1141*6777b538SAndroid Build Coastguard Worker    rhs is passed into func.
1142*6777b538SAndroid Build Coastguard Worker
1143*6777b538SAndroid Build Coastguard Worker    Args:
1144*6777b538SAndroid Build Coastguard Worker      rhs: any python object
1145*6777b538SAndroid Build Coastguard Worker
1146*6777b538SAndroid Build Coastguard Worker    Returns:
1147*6777b538SAndroid Build Coastguard Worker      the result of func(rhs)
1148*6777b538SAndroid Build Coastguard Worker    """
1149*6777b538SAndroid Build Coastguard Worker
1150*6777b538SAndroid Build Coastguard Worker    return self._func(rhs)
1151*6777b538SAndroid Build Coastguard Worker
1152*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1153*6777b538SAndroid Build Coastguard Worker    return str(self._func)
1154*6777b538SAndroid Build Coastguard Worker
1155*6777b538SAndroid Build Coastguard Worker
1156*6777b538SAndroid Build Coastguard Workerclass IgnoreArg(Comparator):
1157*6777b538SAndroid Build Coastguard Worker  """Ignore an argument.
1158*6777b538SAndroid Build Coastguard Worker
1159*6777b538SAndroid Build Coastguard Worker  This can be used when we don't care about an argument of a method call.
1160*6777b538SAndroid Build Coastguard Worker
1161*6777b538SAndroid Build Coastguard Worker  Example:
1162*6777b538SAndroid Build Coastguard Worker  # Check if CastMagic is called with 3 as first arg and 'disappear' as third.
1163*6777b538SAndroid Build Coastguard Worker  mymock.CastMagic(3, IgnoreArg(), 'disappear')
1164*6777b538SAndroid Build Coastguard Worker  """
1165*6777b538SAndroid Build Coastguard Worker
1166*6777b538SAndroid Build Coastguard Worker  def equals(self, unused_rhs):
1167*6777b538SAndroid Build Coastguard Worker    """Ignores arguments and returns True.
1168*6777b538SAndroid Build Coastguard Worker
1169*6777b538SAndroid Build Coastguard Worker    Args:
1170*6777b538SAndroid Build Coastguard Worker      unused_rhs: any python object
1171*6777b538SAndroid Build Coastguard Worker
1172*6777b538SAndroid Build Coastguard Worker    Returns:
1173*6777b538SAndroid Build Coastguard Worker      always returns True
1174*6777b538SAndroid Build Coastguard Worker    """
1175*6777b538SAndroid Build Coastguard Worker
1176*6777b538SAndroid Build Coastguard Worker    return True
1177*6777b538SAndroid Build Coastguard Worker
1178*6777b538SAndroid Build Coastguard Worker  def __repr__(self):
1179*6777b538SAndroid Build Coastguard Worker    return '<IgnoreArg>'
1180*6777b538SAndroid Build Coastguard Worker
1181*6777b538SAndroid Build Coastguard Worker
1182*6777b538SAndroid Build Coastguard Workerclass MethodGroup(object):
1183*6777b538SAndroid Build Coastguard Worker  """Base class containing common behaviour for MethodGroups."""
1184*6777b538SAndroid Build Coastguard Worker
1185*6777b538SAndroid Build Coastguard Worker  def __init__(self, group_name):
1186*6777b538SAndroid Build Coastguard Worker    self._group_name = group_name
1187*6777b538SAndroid Build Coastguard Worker
1188*6777b538SAndroid Build Coastguard Worker  def group_name(self):
1189*6777b538SAndroid Build Coastguard Worker    return self._group_name
1190*6777b538SAndroid Build Coastguard Worker
1191*6777b538SAndroid Build Coastguard Worker  def __str__(self):
1192*6777b538SAndroid Build Coastguard Worker    return '<%s "%s">' % (self.__class__.__name__, self._group_name)
1193*6777b538SAndroid Build Coastguard Worker
1194*6777b538SAndroid Build Coastguard Worker  def AddMethod(self, mock_method):
1195*6777b538SAndroid Build Coastguard Worker    raise NotImplementedError
1196*6777b538SAndroid Build Coastguard Worker
1197*6777b538SAndroid Build Coastguard Worker  def MethodCalled(self, mock_method):
1198*6777b538SAndroid Build Coastguard Worker    raise NotImplementedError
1199*6777b538SAndroid Build Coastguard Worker
1200*6777b538SAndroid Build Coastguard Worker  def IsSatisfied(self):
1201*6777b538SAndroid Build Coastguard Worker    raise NotImplementedError
1202*6777b538SAndroid Build Coastguard Worker
1203*6777b538SAndroid Build Coastguard Workerclass UnorderedGroup(MethodGroup):
1204*6777b538SAndroid Build Coastguard Worker  """UnorderedGroup holds a set of method calls that may occur in any order.
1205*6777b538SAndroid Build Coastguard Worker
1206*6777b538SAndroid Build Coastguard Worker  This construct is helpful for non-deterministic events, such as iterating
1207*6777b538SAndroid Build Coastguard Worker  over the keys of a dict.
1208*6777b538SAndroid Build Coastguard Worker  """
1209*6777b538SAndroid Build Coastguard Worker
1210*6777b538SAndroid Build Coastguard Worker  def __init__(self, group_name):
1211*6777b538SAndroid Build Coastguard Worker    super(UnorderedGroup, self).__init__(group_name)
1212*6777b538SAndroid Build Coastguard Worker    self._methods = []
1213*6777b538SAndroid Build Coastguard Worker
1214*6777b538SAndroid Build Coastguard Worker  def AddMethod(self, mock_method):
1215*6777b538SAndroid Build Coastguard Worker    """Add a method to this group.
1216*6777b538SAndroid Build Coastguard Worker
1217*6777b538SAndroid Build Coastguard Worker    Args:
1218*6777b538SAndroid Build Coastguard Worker      mock_method: A mock method to be added to this group.
1219*6777b538SAndroid Build Coastguard Worker    """
1220*6777b538SAndroid Build Coastguard Worker
1221*6777b538SAndroid Build Coastguard Worker    self._methods.append(mock_method)
1222*6777b538SAndroid Build Coastguard Worker
1223*6777b538SAndroid Build Coastguard Worker  def MethodCalled(self, mock_method):
1224*6777b538SAndroid Build Coastguard Worker    """Remove a method call from the group.
1225*6777b538SAndroid Build Coastguard Worker
1226*6777b538SAndroid Build Coastguard Worker    If the method is not in the set, an UnexpectedMethodCallError will be
1227*6777b538SAndroid Build Coastguard Worker    raised.
1228*6777b538SAndroid Build Coastguard Worker
1229*6777b538SAndroid Build Coastguard Worker    Args:
1230*6777b538SAndroid Build Coastguard Worker      mock_method: a mock method that should be equal to a method in the group.
1231*6777b538SAndroid Build Coastguard Worker
1232*6777b538SAndroid Build Coastguard Worker    Returns:
1233*6777b538SAndroid Build Coastguard Worker      The mock method from the group
1234*6777b538SAndroid Build Coastguard Worker
1235*6777b538SAndroid Build Coastguard Worker    Raises:
1236*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCallError if the mock_method was not in the group.
1237*6777b538SAndroid Build Coastguard Worker    """
1238*6777b538SAndroid Build Coastguard Worker
1239*6777b538SAndroid Build Coastguard Worker    # Check to see if this method exists, and if so, remove it from the set
1240*6777b538SAndroid Build Coastguard Worker    # and return it.
1241*6777b538SAndroid Build Coastguard Worker    for method in self._methods:
1242*6777b538SAndroid Build Coastguard Worker      if method == mock_method:
1243*6777b538SAndroid Build Coastguard Worker        # Remove the called mock_method instead of the method in the group.
1244*6777b538SAndroid Build Coastguard Worker        # The called method will match any comparators when equality is checked
1245*6777b538SAndroid Build Coastguard Worker        # during removal.  The method in the group could pass a comparator to
1246*6777b538SAndroid Build Coastguard Worker        # another comparator during the equality check.
1247*6777b538SAndroid Build Coastguard Worker        self._methods.remove(mock_method)
1248*6777b538SAndroid Build Coastguard Worker
1249*6777b538SAndroid Build Coastguard Worker        # If this group is not empty, put it back at the head of the queue.
1250*6777b538SAndroid Build Coastguard Worker        if not self.IsSatisfied():
1251*6777b538SAndroid Build Coastguard Worker          mock_method._call_queue.appendleft(self)
1252*6777b538SAndroid Build Coastguard Worker
1253*6777b538SAndroid Build Coastguard Worker        return self, method
1254*6777b538SAndroid Build Coastguard Worker
1255*6777b538SAndroid Build Coastguard Worker    raise UnexpectedMethodCallError(mock_method, self)
1256*6777b538SAndroid Build Coastguard Worker
1257*6777b538SAndroid Build Coastguard Worker  def IsSatisfied(self):
1258*6777b538SAndroid Build Coastguard Worker    """Return True if there are not any methods in this group."""
1259*6777b538SAndroid Build Coastguard Worker
1260*6777b538SAndroid Build Coastguard Worker    return len(self._methods) == 0
1261*6777b538SAndroid Build Coastguard Worker
1262*6777b538SAndroid Build Coastguard Worker
1263*6777b538SAndroid Build Coastguard Workerclass MultipleTimesGroup(MethodGroup):
1264*6777b538SAndroid Build Coastguard Worker  """MultipleTimesGroup holds methods that may be called any number of times.
1265*6777b538SAndroid Build Coastguard Worker
1266*6777b538SAndroid Build Coastguard Worker  Note: Each method must be called at least once.
1267*6777b538SAndroid Build Coastguard Worker
1268*6777b538SAndroid Build Coastguard Worker  This is helpful, if you don't know or care how many times a method is called.
1269*6777b538SAndroid Build Coastguard Worker  """
1270*6777b538SAndroid Build Coastguard Worker
1271*6777b538SAndroid Build Coastguard Worker  def __init__(self, group_name):
1272*6777b538SAndroid Build Coastguard Worker    super(MultipleTimesGroup, self).__init__(group_name)
1273*6777b538SAndroid Build Coastguard Worker    self._methods = set()
1274*6777b538SAndroid Build Coastguard Worker    self._methods_called = set()
1275*6777b538SAndroid Build Coastguard Worker
1276*6777b538SAndroid Build Coastguard Worker  def AddMethod(self, mock_method):
1277*6777b538SAndroid Build Coastguard Worker    """Add a method to this group.
1278*6777b538SAndroid Build Coastguard Worker
1279*6777b538SAndroid Build Coastguard Worker    Args:
1280*6777b538SAndroid Build Coastguard Worker      mock_method: A mock method to be added to this group.
1281*6777b538SAndroid Build Coastguard Worker    """
1282*6777b538SAndroid Build Coastguard Worker
1283*6777b538SAndroid Build Coastguard Worker    self._methods.add(mock_method)
1284*6777b538SAndroid Build Coastguard Worker
1285*6777b538SAndroid Build Coastguard Worker  def MethodCalled(self, mock_method):
1286*6777b538SAndroid Build Coastguard Worker    """Remove a method call from the group.
1287*6777b538SAndroid Build Coastguard Worker
1288*6777b538SAndroid Build Coastguard Worker    If the method is not in the set, an UnexpectedMethodCallError will be
1289*6777b538SAndroid Build Coastguard Worker    raised.
1290*6777b538SAndroid Build Coastguard Worker
1291*6777b538SAndroid Build Coastguard Worker    Args:
1292*6777b538SAndroid Build Coastguard Worker      mock_method: a mock method that should be equal to a method in the group.
1293*6777b538SAndroid Build Coastguard Worker
1294*6777b538SAndroid Build Coastguard Worker    Returns:
1295*6777b538SAndroid Build Coastguard Worker      The mock method from the group
1296*6777b538SAndroid Build Coastguard Worker
1297*6777b538SAndroid Build Coastguard Worker    Raises:
1298*6777b538SAndroid Build Coastguard Worker      UnexpectedMethodCallError if the mock_method was not in the group.
1299*6777b538SAndroid Build Coastguard Worker    """
1300*6777b538SAndroid Build Coastguard Worker
1301*6777b538SAndroid Build Coastguard Worker    # Check to see if this method exists, and if so add it to the set of
1302*6777b538SAndroid Build Coastguard Worker    # called methods.
1303*6777b538SAndroid Build Coastguard Worker
1304*6777b538SAndroid Build Coastguard Worker    for method in self._methods:
1305*6777b538SAndroid Build Coastguard Worker      if method == mock_method:
1306*6777b538SAndroid Build Coastguard Worker        self._methods_called.add(mock_method)
1307*6777b538SAndroid Build Coastguard Worker        # Always put this group back on top of the queue, because we don't know
1308*6777b538SAndroid Build Coastguard Worker        # when we are done.
1309*6777b538SAndroid Build Coastguard Worker        mock_method._call_queue.appendleft(self)
1310*6777b538SAndroid Build Coastguard Worker        return self, method
1311*6777b538SAndroid Build Coastguard Worker
1312*6777b538SAndroid Build Coastguard Worker    if self.IsSatisfied():
1313*6777b538SAndroid Build Coastguard Worker      next_method = mock_method._PopNextMethod();
1314*6777b538SAndroid Build Coastguard Worker      return next_method, None
1315*6777b538SAndroid Build Coastguard Worker    else:
1316*6777b538SAndroid Build Coastguard Worker      raise UnexpectedMethodCallError(mock_method, self)
1317*6777b538SAndroid Build Coastguard Worker
1318*6777b538SAndroid Build Coastguard Worker  def IsSatisfied(self):
1319*6777b538SAndroid Build Coastguard Worker    """Return True if all methods in this group are called at least once."""
1320*6777b538SAndroid Build Coastguard Worker    # NOTE(psycho): We can't use the simple set difference here because we want
1321*6777b538SAndroid Build Coastguard Worker    # to match different parameters which are considered the same e.g. IsA(str)
1322*6777b538SAndroid Build Coastguard Worker    # and some string. This solution is O(n^2) but n should be small.
1323*6777b538SAndroid Build Coastguard Worker    tmp = self._methods.copy()
1324*6777b538SAndroid Build Coastguard Worker    for called in self._methods_called:
1325*6777b538SAndroid Build Coastguard Worker      for expected in tmp:
1326*6777b538SAndroid Build Coastguard Worker        if called == expected:
1327*6777b538SAndroid Build Coastguard Worker          tmp.remove(expected)
1328*6777b538SAndroid Build Coastguard Worker          if not tmp:
1329*6777b538SAndroid Build Coastguard Worker            return True
1330*6777b538SAndroid Build Coastguard Worker          break
1331*6777b538SAndroid Build Coastguard Worker    return False
1332*6777b538SAndroid Build Coastguard Worker
1333*6777b538SAndroid Build Coastguard Worker
1334*6777b538SAndroid Build Coastguard Workerclass MoxMetaTestBase(type):
1335*6777b538SAndroid Build Coastguard Worker  """Metaclass to add mox cleanup and verification to every test.
1336*6777b538SAndroid Build Coastguard Worker
1337*6777b538SAndroid Build Coastguard Worker  As the mox unit testing class is being constructed (MoxTestBase or a
1338*6777b538SAndroid Build Coastguard Worker  subclass), this metaclass will modify all test functions to call the
1339*6777b538SAndroid Build Coastguard Worker  CleanUpMox method of the test class after they finish. This means that
1340*6777b538SAndroid Build Coastguard Worker  unstubbing and verifying will happen for every test with no additional code,
1341*6777b538SAndroid Build Coastguard Worker  and any failures will result in test failures as opposed to errors.
1342*6777b538SAndroid Build Coastguard Worker  """
1343*6777b538SAndroid Build Coastguard Worker
1344*6777b538SAndroid Build Coastguard Worker  def __init__(cls, name, bases, d):
1345*6777b538SAndroid Build Coastguard Worker    type.__init__(cls, name, bases, d)
1346*6777b538SAndroid Build Coastguard Worker
1347*6777b538SAndroid Build Coastguard Worker    # also get all the attributes from the base classes to account
1348*6777b538SAndroid Build Coastguard Worker    # for a case when test class is not the immediate child of MoxTestBase
1349*6777b538SAndroid Build Coastguard Worker    for base in bases:
1350*6777b538SAndroid Build Coastguard Worker      for attr_name in dir(base):
1351*6777b538SAndroid Build Coastguard Worker        d[attr_name] = getattr(base, attr_name)
1352*6777b538SAndroid Build Coastguard Worker
1353*6777b538SAndroid Build Coastguard Worker    for func_name, func in d.items():
1354*6777b538SAndroid Build Coastguard Worker      if func_name.startswith('test') and callable(func):
1355*6777b538SAndroid Build Coastguard Worker        setattr(cls, func_name, MoxMetaTestBase.CleanUpTest(cls, func))
1356*6777b538SAndroid Build Coastguard Worker
1357*6777b538SAndroid Build Coastguard Worker  @staticmethod
1358*6777b538SAndroid Build Coastguard Worker  def CleanUpTest(cls, func):
1359*6777b538SAndroid Build Coastguard Worker    """Adds Mox cleanup code to any MoxTestBase method.
1360*6777b538SAndroid Build Coastguard Worker
1361*6777b538SAndroid Build Coastguard Worker    Always unsets stubs after a test. Will verify all mocks for tests that
1362*6777b538SAndroid Build Coastguard Worker    otherwise pass.
1363*6777b538SAndroid Build Coastguard Worker
1364*6777b538SAndroid Build Coastguard Worker    Args:
1365*6777b538SAndroid Build Coastguard Worker      cls: MoxTestBase or subclass; the class whose test method we are altering.
1366*6777b538SAndroid Build Coastguard Worker      func: method; the method of the MoxTestBase test class we wish to alter.
1367*6777b538SAndroid Build Coastguard Worker
1368*6777b538SAndroid Build Coastguard Worker    Returns:
1369*6777b538SAndroid Build Coastguard Worker      The modified method.
1370*6777b538SAndroid Build Coastguard Worker    """
1371*6777b538SAndroid Build Coastguard Worker    def new_method(self, *args, **kwargs):
1372*6777b538SAndroid Build Coastguard Worker      mox_obj = getattr(self, 'mox', None)
1373*6777b538SAndroid Build Coastguard Worker      cleanup_mox = False
1374*6777b538SAndroid Build Coastguard Worker      if mox_obj and isinstance(mox_obj, Mox):
1375*6777b538SAndroid Build Coastguard Worker        cleanup_mox = True
1376*6777b538SAndroid Build Coastguard Worker      try:
1377*6777b538SAndroid Build Coastguard Worker        func(self, *args, **kwargs)
1378*6777b538SAndroid Build Coastguard Worker      finally:
1379*6777b538SAndroid Build Coastguard Worker        if cleanup_mox:
1380*6777b538SAndroid Build Coastguard Worker          mox_obj.UnsetStubs()
1381*6777b538SAndroid Build Coastguard Worker      if cleanup_mox:
1382*6777b538SAndroid Build Coastguard Worker        mox_obj.VerifyAll()
1383*6777b538SAndroid Build Coastguard Worker    new_method.__name__ = func.__name__
1384*6777b538SAndroid Build Coastguard Worker    new_method.__doc__ = func.__doc__
1385*6777b538SAndroid Build Coastguard Worker    new_method.__module__ = func.__module__
1386*6777b538SAndroid Build Coastguard Worker    return new_method
1387*6777b538SAndroid Build Coastguard Worker
1388*6777b538SAndroid Build Coastguard Worker
1389*6777b538SAndroid Build Coastguard Workerclass MoxTestBase(unittest.TestCase):
1390*6777b538SAndroid Build Coastguard Worker  """Convenience test class to make stubbing easier.
1391*6777b538SAndroid Build Coastguard Worker
1392*6777b538SAndroid Build Coastguard Worker  Sets up a "mox" attribute which is an instance of Mox - any mox tests will
1393*6777b538SAndroid Build Coastguard Worker  want this. Also automatically unsets any stubs and verifies that all mock
1394*6777b538SAndroid Build Coastguard Worker  methods have been called at the end of each test, eliminating boilerplate
1395*6777b538SAndroid Build Coastguard Worker  code.
1396*6777b538SAndroid Build Coastguard Worker  """
1397*6777b538SAndroid Build Coastguard Worker
1398*6777b538SAndroid Build Coastguard Worker  __metaclass__ = MoxMetaTestBase
1399*6777b538SAndroid Build Coastguard Worker
1400*6777b538SAndroid Build Coastguard Worker  def setUp(self):
1401*6777b538SAndroid Build Coastguard Worker    self.mox = Mox()
1402