Add bluez test files
authorWu zheng <wu.zheng@intel.com>
Mon, 28 Oct 2013 06:13:43 +0000 (14:13 +0800)
committerWu Zheng <wu.zheng@intel.com>
Thu, 12 Dec 2013 09:51:35 +0000 (04:51 -0500)
Change-Id: I70048612327ef1c97b249e616b7d99fe0f8e3e82

packaging/bluez.spec
test/ftp-client [new file with mode: 0644]
test/map-client [new file with mode: 0644]
test/opp-client [new file with mode: 0644]
test/pbap-client [new file with mode: 0644]

index bdd753c..68b836d 100644 (file)
@@ -111,6 +111,24 @@ make check
 %make_install
 
 # bluez-test
+cd test
+install --mode=0755 \
+       simple-agent \
+       simple-service \
+       list-devices \
+       test-adapter \
+       test-device \
+       test-discovery \
+       test-manager \
+       test-network \
+       test-profile  \
+       test-hfp \
+       ftp-client \
+       map-client \
+       opp-client \
+       pbap-client \
+       $RPM_BUILD_ROOT/%{_bindir}/
+cd ..
 rm -rvf $RPM_BUILD_ROOT/%{_libdir}/gstreamer-*
 install --mode=0755 -D %{S:4} $RPM_BUILD_ROOT/usr/lib/udev/bluetooth.sh
 install --mode=0644 -D %{S:7} $RPM_BUILD_ROOT/%{_sysconfdir}/modprobe.d/50-bluetooth.conf
@@ -192,6 +210,20 @@ install -D -m 0755 %SOURCE102 %{buildroot}%{_sysconfdir}/obex/root-setup.d/000_c
 %{_bindir}/bluetoothctl
 %{_bindir}/btmon
 %{_bindir}/hcidump
+%{_bindir}/simple-agent
+%{_bindir}/simple-service
+%{_bindir}/list-devices
+%{_bindir}/test-adapter
+%{_bindir}/test-device
+%{_bindir}/test-discovery
+%{_bindir}/test-manager
+%{_bindir}/test-network
+%{_bindir}/test-profile
+%{_bindir}/test-hfp
+%{_bindir}/ftp-client
+%{_bindir}/map-client
+%{_bindir}/opp-client
+%{_bindir}/pbap-client
 
 %docs_package
 
diff --git a/test/ftp-client b/test/ftp-client
new file mode 100644 (file)
index 0000000..ae3cbcb
--- /dev/null
@@ -0,0 +1,176 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import gobject
+
+import sys
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+import os.path
+from optparse import OptionParser
+
+BUS_NAME='org.bluez.obex'
+PATH = '/org/bluez/obex'
+CLIENT_INTERFACE='org.bluez.obex.Client1'
+SESSION_INTERFACE='org.bluez.obex.Session1'
+FILE_TRASNFER_INTERFACE='org.bluez.obex.FileTransfer1'
+TRANSFER_INTERFACE='org.bluez.obex.Transfer1'
+
+def parse_options():
+       parser.add_option("-d", "--device", dest="device",
+                       help="Device to connect", metavar="DEVICE")
+       parser.add_option("-c", "--chdir", dest="new_dir",
+                       help="Change current directory to DIR", metavar="DIR")
+       parser.add_option("-l", "--list", action="store_true", dest="list_dir",
+                       help="List the current directory")
+       parser.add_option("-g", "--get", dest="get_file",
+                       help="Get FILE", metavar="FILE")
+       parser.add_option("-p", "--put", dest="put_file",
+                       help="Put FILE", metavar="FILE")
+       parser.add_option("-y", "--copy", dest="copy_file",
+                       help="Copy FILE", metavar="FILE")
+       parser.add_option("-m", "--move", dest="move_file",
+                       help="Move FILE", metavar="FILE")
+       parser.add_option("-n", "--destname", dest="dest_file",
+                       help="Destination FILE", metavar="FILE")
+       parser.add_option("-r", "--remove", dest="remove_file",
+                       help="Remove FILE", metavar="FILE")
+       parser.add_option("-v", "--verbose", action="store_true",
+                       dest="verbose")
+
+       return parser.parse_args()
+
+class FtpClient:
+       def __init__(self, session_path, verbose=False):
+               self.transferred = 0
+               self.transfer_path = None
+               self.transfer_size = 0
+               self.verbose = verbose
+               bus = dbus.SessionBus()
+               obj = bus.get_object(BUS_NAME, session_path)
+               self.session = dbus.Interface(obj, SESSION_INTERFACE)
+               self.ftp = dbus.Interface(obj, FILE_TRASNFER_INTERFACE)
+               bus.add_signal_receiver(self.properties_changed,
+                       dbus_interface="org.freedesktop.DBus.Properties",
+                       signal_name="PropertiesChanged",
+                       path_keyword="path")
+
+       def create_transfer_reply(self, path, properties):
+               self.transfer_path = path
+               self.transfer_size = properties["Size"]
+               if self.verbose:
+                       print("Transfer created: %s" % path)
+
+       def generic_reply(self):
+               if self.verbose:
+                       print("Operation succeeded")
+
+       def error(self, err):
+               print(err)
+               mainloop.quit()
+
+       def properties_changed(self, interface, properties, invalidated, path):
+               if path != self.transfer_path:
+                       return
+
+               if properties['Status'] == 'complete' or \
+                               properties['Status'] == 'error':
+                       if self.verbose:
+                               print("Transfer %s" % properties['Status'])
+                       mainloop.quit()
+                       return
+
+               if properties["Transferred"] == None:
+                       return
+
+               speed = (value - self.transferred) / 1000
+               print("Transfer progress %d/%d at %d kBps" % (value,
+                                                       self.transfer_size,
+                                                       speed))
+               self.transferred = value
+
+       def change_folder(self, new_dir):
+               for node in new_dir.split("/"):
+                       self.ftp.ChangeFolder(node)
+
+       def list_folder(self):
+               for i in self.ftp.ListFolder():
+                       if i["Type"] == "folder":
+                               print("%s/" % (i["Name"]))
+                       else:
+                               print("%s" % (i["Name"]))
+
+       def put_file(self, filename):
+               self.ftp.PutFile(os.path.abspath(filename),
+                               os.path.basename(filename),
+                               reply_handler=self.create_transfer_reply,
+                               error_handler=self.error)
+
+       def get_file(self, filename):
+               self.ftp.GetFile(os.path.abspath(filename),
+                               os.path.basename(filename),
+                               reply_handler=self.create_transfer_reply,
+                               error_handler=self.error)
+
+       def remove_file(self, filename):
+               self.ftp.Delete(filename,
+                               reply_handler=self.generic_reply,
+                               error_handler=self.error)
+
+       def move_file(self, filename, destname):
+               self.ftp.MoveFile(filename, destname,
+                               reply_handler=self.generic_reply,
+                               error_handler=self.error)
+
+       def copy_file(self, filename, destname):
+               self.ftp.CopyFile(filename, destname,
+                               reply_handler=self.generic_reply,
+                               error_handler=self.error)
+
+if  __name__ == '__main__':
+
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       parser = OptionParser()
+
+       (options, args) = parse_options()
+
+       if not options.device:
+               parser.print_help()
+               sys.exit(0)
+
+       bus = dbus.SessionBus()
+       mainloop = gobject.MainLoop()
+
+       client = dbus.Interface(bus.get_object(BUS_NAME, PATH,),
+                                                       CLIENT_INTERFACE)
+
+       print("Creating Session")
+       path = client.CreateSession(options.device, { "Target": "ftp" })
+
+       ftp_client = FtpClient(path, options.verbose)
+
+       if options.new_dir:
+               ftp_client.change_folder(options.new_dir)
+
+       if options.list_dir:
+               ftp_client.list_folder()
+
+       if options.get_file:
+               ftp_client.get_file(options.get_file)
+
+       if options.put_file:
+               ftp_client.put_file(options.put_file)
+
+       if options.move_file:
+               ftp_client.move_file(options.move_file, options.dest_file)
+
+       if options.copy_file:
+               ftp_client.copy_file(options.copy_file, options.dest_file)
+
+       if options.remove_file:
+               ftp_client.remove_file(options.remove_file)
+
+       mainloop.run()
diff --git a/test/map-client b/test/map-client
new file mode 100644 (file)
index 0000000..f3c657f
--- /dev/null
@@ -0,0 +1,231 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import gobject
+
+import sys
+import os
+import dbus
+import dbus.mainloop.glib
+from optparse import OptionParser
+
+from pprint import pformat
+
+BUS_NAME='org.bluez.obex'
+PATH = '/org/bluez/obex'
+CLIENT_INTERFACE = 'org.bluez.obex.Client1'
+SESSION_INTERFACE = 'org.bluez.obex.Session1'
+MESSAGE_ACCESS_INTERFACE = 'org.bluez.obex.MessageAccess1'
+MESSAGE_INTERFACE = 'org.bluez.obex.Message1'
+TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
+
+def unwrap(x):
+    """Hack to unwrap D-Bus values, so that they're easier to read when
+    printed. Taken from d-feet """
+
+    if isinstance(x, list):
+        return map(unwrap, x)
+
+    if isinstance(x, tuple):
+        return tuple(map(unwrap, x))
+
+    if isinstance(x, dict):
+        return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()])
+
+    for t in [unicode, str, long, int, float, bool]:
+        if isinstance(x, t):
+            return t(x)
+
+    return x
+
+def parse_options():
+       parser.add_option("-d", "--device", dest="device",
+                       help="Device to connect", metavar="DEVICE")
+       parser.add_option("-c", "--chdir", dest="new_dir",
+                       help="Change current directory to DIR", metavar="DIR")
+       parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir",
+                       help="List folders in current directory")
+       parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
+       parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg",
+                       help="List messages in supplied CWD subdir")
+       parser.add_option("-g", "--get", action="store", dest="get_msg",
+                       help="Get message contents")
+       parser.add_option("-p", "--push", action="store", dest="push_msg",
+                       help="Push message")
+       parser.add_option("--get-properties", action="store", dest="get_msg_properties",
+                       help="Get message properties")
+       parser.add_option("--mark-read", action="store", dest="mark_msg_read",
+                       help="Marks the messages as read")
+       parser.add_option("--mark-unread", action="store", dest="mark_msg_unread",
+                       help="Marks the messages as unread")
+       parser.add_option("--mark-deleted", action="store", dest="mark_msg_deleted",
+                       help="Deletes the message from the folder")
+       parser.add_option("--mark-undeleted", action="store", dest="mark_msg_undeleted",
+                       help="Undeletes the message")
+       parser.add_option("-u", "--update-inbox", action="store_true", dest="update_inbox",
+                       help="Checks for new mails")
+
+       return parser.parse_args()
+
+def set_folder(session, new_dir):
+       session.SetFolder(new_dir)
+
+class MapClient:
+       def __init__(self, session_path, verbose=False):
+               self.progress = 0
+               self.transfer_path = None
+               self.props = dict()
+               self.verbose = verbose
+               self.path = session_path
+               bus = dbus.SessionBus()
+               obj = bus.get_object(BUS_NAME, session_path)
+               self.session = dbus.Interface(obj, SESSION_INTERFACE)
+               self.map = dbus.Interface(obj, MESSAGE_ACCESS_INTERFACE)
+               bus.add_signal_receiver(self.properties_changed,
+                       dbus_interface="org.freedesktop.DBus.Properties",
+                       signal_name="PropertiesChanged",
+                       path_keyword="path")
+
+       def create_transfer_reply(self, path, properties):
+               self.transfer_path = path
+               self.props[path] = properties
+               if self.verbose:
+                       print("Transfer created: %s (file %s)" % (path,
+                                                       properties["Filename"]))
+
+       def generic_reply(self):
+               if self.verbose:
+                       print("Operation succeeded")
+
+       def error(self, err):
+               print(err)
+               mainloop.quit()
+
+       def transfer_complete(self, path):
+               if self.verbose:
+                       print("Transfer finished")
+               properties = self.props.get(path)
+               if properties == None:
+                       return
+               f = open(properties["Filename"], "r")
+               os.remove(properties["Filename"])
+               print(f.readlines())
+
+       def transfer_error(self, path):
+               print("Transfer %s error" % path)
+               mainloop.quit()
+
+       def properties_changed(self, interface, properties, invalidated, path):
+               req = self.props.get(path)
+               if req == None:
+                       return
+
+               if properties['Status'] == 'complete':
+                       self.transfer_complete(path)
+                       return
+
+               if properties['Status'] == 'error':
+                       self.transfer_error(path)
+                       return
+
+       def set_folder(self, new_dir):
+               self.map.SetFolder(new_dir)
+
+       def list_folders(self):
+               for i in self.map.ListFolders(dict()):
+                       print("%s/" % (i["Name"]))
+
+       def list_messages(self, folder):
+               ret = self.map.ListMessages(folder, dict())
+               print(pformat(unwrap(ret)))
+
+       def get_message(self, handle):
+               self.map.ListMessages("", dict())
+               path = self.path + "/message" + handle
+               obj = bus.get_object(BUS_NAME, path)
+               msg = dbus.Interface(obj, MESSAGE_INTERFACE)
+               msg.Get("", True, reply_handler=self.create_transfer_reply,
+                                               error_handler=self.error)
+
+       def push_message(self, filename):
+               self.map.PushMessage(filename, "telecom/msg/outbox", dict(),
+                               reply_handler=self.create_transfer_reply,
+                               error_handler=self.error)
+
+       def get_message_properties(self, handle):
+               self.map.ListMessages("", dict())
+               path = self.path + "/message" + handle
+               obj = bus.get_object(BUS_NAME, path)
+               msg = dbus.Interface(obj, "org.freedesktop.DBus.Properties")
+               ret = msg.GetAll(MESSAGE_INTERFACE)
+               print(pformat(unwrap(ret)))
+
+       def set_message_property(self, handle, prop, flag):
+               self.map.ListMessages("", dict())
+               path = self.path + "/message" + handle
+               obj = bus.get_object(BUS_NAME, path)
+               msg = dbus.Interface(obj, MESSAGE_INTERFACE)
+               msg.SetProperty (prop, flag);
+
+       def update_inbox(self):
+               self.map.UpdateInbox()
+
+
+if  __name__ == '__main__':
+
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       parser = OptionParser()
+
+       (options, args) = parse_options()
+
+       if not options.device:
+               parser.print_help()
+               exit(0)
+
+       bus = dbus.SessionBus()
+       mainloop = gobject.MainLoop()
+
+       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
+                                                       CLIENT_INTERFACE)
+
+       print("Creating Session")
+       path = client.CreateSession(options.device, { "Target": "map" })
+
+       map_client = MapClient(path, options.verbose)
+
+       if options.new_dir:
+               map_client.set_folder(options.new_dir)
+
+       if options.ls_dir:
+               map_client.list_folders()
+
+       if options.ls_msg is not None:
+               map_client.list_messages(options.ls_msg)
+
+       if options.get_msg is not None:
+               map_client.get_message(options.get_msg)
+
+       if options.push_msg is not None:
+               map_client.push_message(options.push_msg)
+
+       if options.get_msg_properties is not None:
+               map_client.get_message_properties(options.get_msg_properties)
+
+       if options.mark_msg_read is not None:
+               map_client.set_message_property(options.mark_msg_read, "Read", True)
+
+       if options.mark_msg_unread is not None:
+               map_client.set_message_property(options.mark_msg_unread, "Read", False)
+
+       if options.mark_msg_deleted is not None:
+               map_client.set_message_property(options.mark_msg_deleted, "Deleted", True)
+
+       if options.mark_msg_undeleted is not None:
+               map_client.set_message_property(options.mark_msg_undeleted, "Deleted", False)
+
+       if options.update_inbox:
+               map_client.update_inbox()
+
+       mainloop.run()
diff --git a/test/opp-client b/test/opp-client
new file mode 100644 (file)
index 0000000..878c263
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import sys
+import dbus
+import gobject
+import dbus.mainloop.glib
+import os.path
+from optparse import OptionParser
+
+BUS_NAME='org.bluez.obex'
+PATH = '/org/bluez/obex'
+CLIENT_INTERFACE='org.bluez.obex.Client1'
+SESSION_INTERFACE='org.bluez.obex.Session1'
+OBJECT_PUSH_INTERFACE='org.bluez.obex.ObjectPush1'
+TRANSFER_INTERFACE='org.bluez.obex.Transfer1'
+
+def parse_options():
+       parser.add_option("-d", "--device", dest="device",
+                       help="Device to connect", metavar="DEVICE")
+       parser.add_option("-p", "--pull", dest="pull_to_file",
+                       help="Pull vcard and store in FILE", metavar="FILE")
+       parser.add_option("-s", "--send", dest="send_file",
+                       help="Send FILE", metavar="FILE")
+       parser.add_option("-v", "--verbose", action="store_true",
+                       dest="verbose")
+
+       return parser.parse_args()
+
+class OppClient:
+       def __init__(self, session_path, verbose=False):
+               self.transferred = 0
+               self.transfer_path = None
+               self.verbose = verbose
+               bus = dbus.SessionBus()
+               obj = bus.get_object(BUS_NAME, session_path)
+               self.session = dbus.Interface(obj, SESSION_INTERFACE)
+               self.opp = dbus.Interface(obj, OBJECT_PUSH_INTERFACE)
+               bus.add_signal_receiver(self.properties_changed,
+                       dbus_interface="org.freedesktop.DBus.Properties",
+                       signal_name="PropertiesChanged",
+                       path_keyword="path")
+
+       def create_transfer_reply(self, path, properties):
+               self.transfer_path = path
+               self.transfer_size = properties["Size"]
+               if self.verbose:
+                       print("Transfer created: %s" % path)
+
+       def error(self, err):
+               print(err)
+               mainloop.quit()
+
+       def properties_changed(self, interface, properties, invalidated, path):
+               if path != self.transfer_path:
+                       return
+
+               if "Status" in properties and \
+                               (properties["Status"] == "complete" or \
+                               properties["Status"] == "error"):
+                       if self.verbose:
+                               print("Transfer %s" % properties["Status"])
+                       mainloop.quit()
+                       return
+
+               if "Transferred" not in properties:
+                       return
+
+               value = properties["Transferred"]
+               speed = (value - self.transferred) / 1000
+               print("Transfer progress %d/%d at %d kBps" % (value,
+                                                       self.transfer_size,
+                                                       speed))
+               self.transferred = value
+
+       def pull_business_card(self, filename):
+               self.opp.PullBusinessCard(os.path.abspath(filename),
+                               reply_handler=self.create_transfer_reply,
+                               error_handler=self.error)
+
+       def send_file(self, filename):
+               self.opp.SendFile(os.path.abspath(filename),
+                               reply_handler=self.create_transfer_reply,
+                               error_handler=self.error)
+
+if  __name__ == '__main__':
+
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       parser = OptionParser()
+
+       (options, args) = parse_options()
+
+       if not options.device:
+               parser.print_help()
+               sys.exit(0)
+
+       bus = dbus.SessionBus()
+       mainloop = gobject.MainLoop()
+
+       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
+                                                       CLIENT_INTERFACE)
+
+       print("Creating Session")
+       path = client.CreateSession(options.device, { "Target": "OPP" })
+
+       opp_client = OppClient(path, options.verbose)
+
+       if options.pull_to_file:
+               opp_client.pull_business_card(options.pull_to_file)
+
+       if options.send_file:
+               opp_client.send_file(options.send_file)
+
+       mainloop.run()
diff --git a/test/pbap-client b/test/pbap-client
new file mode 100644 (file)
index 0000000..c02833b
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/python
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import gobject
+
+import sys
+import os
+import dbus
+import dbus.service
+import dbus.mainloop.glib
+
+BUS_NAME='org.bluez.obex'
+PATH = '/org/bluez/obex'
+CLIENT_INTERFACE = 'org.bluez.obex.Client1'
+SESSION_INTERFACE = 'org.bluez.obex.Session1'
+PHONEBOOK_ACCESS_INTERFACE = 'org.bluez.obex.PhonebookAccess1'
+TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'
+
+class Transfer:
+       def __init__(self, callback_func):
+               self.callback_func = callback_func
+               self.path = None
+               self.filename = None
+
+class PbapClient:
+       def __init__(self, session_path):
+               self.transfers = 0
+               self.props = dict()
+               self.flush_func = None
+               bus = dbus.SessionBus()
+               obj = bus.get_object(BUS_NAME, session_path)
+               self.session = dbus.Interface(obj, SESSION_INTERFACE)
+               self.pbap = dbus.Interface(obj, PHONEBOOK_ACCESS_INTERFACE)
+               bus.add_signal_receiver(self.properties_changed,
+                       dbus_interface="org.freedesktop.DBus.Properties",
+                       signal_name="PropertiesChanged",
+                       path_keyword="path")
+
+       def register(self, path, properties, transfer):
+               transfer.path = path
+               transfer.filename = properties["Filename"]
+               self.props[path] = transfer
+               print("Transfer created: %s (file %s)" % (path,
+                                                       transfer.filename))
+
+       def error(self, err):
+               print(err)
+               mainloop.quit()
+
+       def transfer_complete(self, path):
+               req = self.props.get(path)
+               if req == None:
+                       return
+               self.transfers -= 1
+               print("Transfer %s complete" % path)
+               try:
+                       f = open(req.filename, "r")
+                       os.remove(req.filename)
+                       lines = f.readlines()
+                       del self.props[path]
+                       req.callback_func(lines)
+               except:
+                       pass
+
+               if (len(self.props) == 0) and (self.transfers == 0):
+                       if self.flush_func != None:
+                               f = self.flush_func
+                               self.flush_func = None
+                               f()
+
+       def transfer_error(self, path):
+               print("Transfer %s error" % path)
+               mainloop.quit()
+
+       def properties_changed(self, interface, properties, invalidated, path):
+               req = self.props.get(path)
+               if req == None:
+                       return
+
+               if properties['Status'] == 'complete':
+                       self.transfer_complete(path)
+                       return
+
+               if properties['Status'] == 'error':
+                       self.transfer_error(path)
+                       return
+
+       def pull(self, vcard, params, func):
+               req = Transfer(func)
+               self.pbap.Pull(vcard, "", params,
+                       reply_handler=lambda o, p: self.register(o, p, req),
+                       error_handler=self.error)
+               self.transfers += 1
+
+       def pull_all(self, params, func):
+               req = Transfer(func)
+               self.pbap.PullAll("", params,
+                       reply_handler=lambda o, p: self.register(o, p, req),
+                       error_handler=self.error)
+               self.transfers += 1
+
+       def flush_transfers(self, func):
+               if (len(self.props) == 0) and (self.transfers == 0):
+                       return
+               self.flush_func = func
+
+       def interface(self):
+               return self.pbap
+
+if  __name__ == '__main__':
+
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       bus = dbus.SessionBus()
+       mainloop = gobject.MainLoop()
+
+       client = dbus.Interface(bus.get_object(BUS_NAME, PATH),
+                                                       CLIENT_INTERFACE)
+
+       if (len(sys.argv) < 2):
+               print("Usage: %s <device>" % (sys.argv[0]))
+               sys.exit(1)
+
+       print("Creating Session")
+       session_path = client.CreateSession(sys.argv[1], { "Target": "PBAP" })
+
+       pbap_client = PbapClient(session_path)
+
+       def process_result(lines, header):
+               if header != None:
+                       print(header)
+               for line in lines:
+                       print(line),
+               print
+
+       def test_paths(paths):
+               if len(paths) == 0:
+                       print
+                       print("FINISHED")
+                       mainloop.quit()
+                       return
+
+               path = paths[0]
+
+               print("\n--- Select Phonebook %s ---\n" % (path))
+               pbap_client.interface().Select("int", path)
+
+               print("\n--- GetSize ---\n")
+               ret = pbap_client.interface().GetSize()
+               print("Size = %d\n" % (ret))
+
+               print("\n--- List vCard ---\n")
+               try:
+                       ret = pbap_client.interface().List(dbus.Dictionary())
+               except:
+                       ret = []
+
+               params = dbus.Dictionary({ "Format" : "vcard30",
+                                               "Fields" : ["PHOTO"] })
+               for item in ret:
+                       print("%s : %s" % (item[0], item[1]))
+                       pbap_client.pull(item[0], params,
+                                       lambda x: process_result(x, None))
+
+               pbap_client.pull_all(params, lambda x: process_result(x,
+                                                       "\n--- PullAll ---\n"))
+
+               pbap_client.flush_transfers(lambda: test_paths(paths[1:]))
+
+       test_paths(["PB", "ICH", "OCH", "MCH", "CCH"])
+
+       mainloop.run()