1import collections 2import dbus 3import dbus.service 4import dbus.mainloop.glib 5import gobject 6import logging 7import threading 8 9""" MockFlimflam provides a select few methods from the flimflam 10 DBus API so that we can track "dbus-send" invocations sent 11 by the shill init scripts. It could be used as a kernel for 12 a test of other facilities that use the shill/flimflam DBus 13 API and at that point it should be moved out of this specific 14 test. """ 15 16MethodCall = collections.namedtuple("MethodCall", ["method", "argument"]) 17 18class FlimflamManager(dbus.service.Object): 19 """ The flimflam DBus Manager object instance. Methods in this 20 object are called whenever a DBus RPC method is invoked. """ 21 def __init__(self, bus, object_path): 22 dbus.service.Object.__init__(self, bus, object_path) 23 self.method_calls = [] 24 25 26 @dbus.service.method('org.chromium.flimflam.Manager', 27 in_signature='s', out_signature='o') 28 def CreateProfile(self, profile): 29 """ Creates a profile. 30 31 @param profile string name of profile to create. 32 33 """ 34 self.add_method_call('CreateProfile', profile) 35 return '/' 36 37 38 @dbus.service.method('org.chromium.flimflam.Manager', 39 in_signature='s', out_signature='') 40 def RemoveProfile(self, profile): 41 """ Removes a profile. 42 43 @param profile string name of profile to remove. 44 45 """ 46 self.add_method_call('RemoveProfile', profile) 47 48 49 @dbus.service.method('org.chromium.flimflam.Manager', 50 in_signature='s', out_signature='o') 51 def PushProfile(self, profile): 52 """ Pushes a profile. 53 54 @param profile string name of profile to push. 55 56 """ 57 self.add_method_call('PushProfile', profile) 58 return '/' 59 60 61 @dbus.service.method('org.chromium.flimflam.Manager', 62 in_signature='ss', out_signature='o') 63 def InsertUserProfile(self, profile, user_hash): 64 """ Inserts a profile. 65 66 @param profile string name of profile to insert. 67 @param user_hash string user hash associated with this profile. 68 69 """ 70 self.add_method_call('InsertUserProfile', (profile, user_hash)) 71 return '/' 72 73 74 @dbus.service.method('org.chromium.flimflam.Manager', 75 in_signature='s', out_signature='') 76 def PopProfile(self, profile): 77 """ Pops a profile. 78 79 @param profile string name of profile to pop. 80 81 """ 82 self.add_method_call('PopProfile', profile) 83 84 85 @dbus.service.method('org.chromium.flimflam.Manager', 86 in_signature='', out_signature='') 87 def PopAllUserProfiles(self): 88 """ Pops all user profiles from the profile stack.. """ 89 self.add_method_call('PopAllUserProfiles', '') 90 91 92 def add_method_call(self, method, arg): 93 """ Note that a method call was made. 94 95 @param method string the method that was called. 96 @param arg tuple list of arguments that were called on |method|. 97 98 """ 99 print "Called method %s" % method 100 logging.info("Mock Flimflam method %s called with argument %s", 101 method, arg) 102 self.method_calls.append(MethodCall(method, arg)) 103 104 105 def get_method_calls(self): 106 """ Provide the method call list, clears this list internally. 107 108 @return list of MethodCall objects 109 110 """ 111 method_calls = self.method_calls 112 self.method_calls = [] 113 return method_calls 114 115 116class MockFlimflam(threading.Thread): 117 """ This thread object instantiates a mock flimflam manager and 118 runs a mainloop that receives DBus API messages. """ 119 FLIMFLAM = "org.chromium.flimflam" 120 def __init__(self): 121 threading.Thread.__init__(self) 122 gobject.threads_init() 123 124 125 def run(self): 126 """ Runs the main loop. """ 127 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 128 self.bus = dbus.SystemBus() 129 name = dbus.service.BusName(self.FLIMFLAM, self.bus) 130 self.manager = FlimflamManager(self.bus, '/') 131 self.mainloop = gobject.MainLoop() 132 self.mainloop.run() 133 134 135 def quit(self): 136 """ Quits the main loop. """ 137 self.mainloop.quit() 138 139 140 def get_method_calls(self): 141 """ Returns the method calls that were called on the mock object. 142 143 @return list of MethodCall objects representing the methods called. 144 145 """ 146 return self.manager.get_method_calls() 147 148 149if __name__ == '__main__': 150 MockFlimflam().run() 151