From d951f39564ea61fdb2be1dece281fab46e1e97ea Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Tue, 2 Jul 2013 10:45:19 +0200 Subject: gvfs-test: Add first test for mtp backend Add umockdev dump and ioctl trace for a Sony Xperia Mini mobile phone (with CyanogenMod), with some small demo files and the ioctls from these commands recorded: gvfs-mount 'mtp://[usb:001,017]' gvfs-ls 'mtp://[usb:001,017]/SD-Karte' gvfs-ls 'mtp://[usb:001,017]/SD-Karte/Music' gvfs-ls 'mtp://[usb:001,017]/SD-Karte/Music/GStreamer - The Test Sine' gvfs-info 'mtp://[usb:001,017]/SD-Karte/Music/GStreamer - The Test Sine' gvfs-info 'mtp://[usb:001,017]/SD-Karte/Music/GStreamer - The Test Sine/sine.ogg' gvfs-cat 'mtp://[usb:001,017]/SD-Karte/Music/GStreamer - The Test Sine/sine.ogg' gvfs-cat 'mtp://[usb:001,017]/SD-Karte/hello.txt' gvfs-info 'mtp://[usb:001,017]/SD-Karte/hello.txt' gvfs-info 'mtp://[usb:001,017]/SD-Karte/DCIM/100CANON/IMG_0001.JPG' gvfs-cat 'mtp://[usb:001,017]/SD-Karte/DCIM/100CANON/IMG_0001.JPG' If umockdev is available, use it to simulate that device and check that we can get the directory and file info, and access the file contents. This bumps the (optional) umockdev dependency to >= 0.2.10. --- test/files/mtp_xperia.ioctl.xz | Bin 0 -> 8184 bytes test/files/mtp_xperia.umockdev | 328 +++++++++++++++++++++++++++++++++++++++++ test/gvfs-test | 85 +++++++++++ 3 files changed, 413 insertions(+) create mode 100644 test/files/mtp_xperia.ioctl.xz create mode 100644 test/files/mtp_xperia.umockdev diff --git a/test/files/mtp_xperia.ioctl.xz b/test/files/mtp_xperia.ioctl.xz new file mode 100644 index 00000000..f929398f Binary files /dev/null and b/test/files/mtp_xperia.ioctl.xz differ diff --git a/test/files/mtp_xperia.umockdev b/test/files/mtp_xperia.umockdev new file mode 100644 index 00000000..f66209a7 --- /dev/null +++ b/test/files/mtp_xperia.umockdev @@ -0,0 +1,328 @@ +P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.2/1-1.5.2.4 +N: bus/usb/001/017=1201000200000040CE0F660126020203040109022700010100C0FA0904000003FFFF00050705810200020007050202000200070582031C0006 +S: libmtp-1-1.5.2.4 +E: BUSNUM=001 +E: DEVLINKS=/dev/libmtp-1-1.5.2.4 +E: DEVNAME=/dev/bus/usb/001/017 +E: DEVNUM=017 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1_5_2_4 +E: ID_MEDIA_PLAYER=1 +E: ID_MODEL=MiniPro +E: ID_MODEL_ENC=MiniPro +E: ID_MODEL_FROM_DATABASE=Xperia Mini Pro +E: ID_MODEL_ID=0166 +E: ID_MTP_DEVICE=1 +E: ID_PATH=pci-0000:00:1a.0-usb-0:1.5.2.4 +E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1_5_2_4 +E: ID_REVISION=0226 +E: ID_SERIAL=Sony_MiniPro_0123456789ABCDEF +E: ID_SERIAL_SHORT=0123456789ABCDEF +E: ID_USB_INTERFACES=:ffff00: +E: ID_VENDOR=Sony +E: ID_VENDOR_ENC=Sony +E: ID_VENDOR_FROM_DATABASE=Sony Ericsson Mobile Communications AB +E: ID_VENDOR_ID=0fce +E: MAJOR=189 +E: MINOR=16 +E: PRODUCT=fce/166/226 +E: SUBSYSTEM=usb +E: TAGS=:seat:uaccess: +E: TYPE=0/0/0 +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=00 +A: bDeviceProtocol=00 +A: bDeviceSubClass=00 +A: bMaxPacketSize0=64 +A: bMaxPower=500mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0226 +A: bmAttributes=c0 +A: busnum=1 +A: configuration= +H: descriptors=1201000200000040CE0F660126020203040109022700010100C0FA0904000003FFFF00050705810200020007050202000200070582031C0006 +A: dev=189:16 +A: devnum=17 +A: devpath=1.5.2.4 +A: idProduct=0166 +A: idVendor=0fce +A: ltm_capable=no +A: manufacturer=Sony +A: maxchild=0 +A: product=MiniPro +A: quirks=0x0 +A: removable=unknown +A: serial=0123456789ABCDEF +A: speed=480 +A: urbnum=649 +A: version= 2.00 + +P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.2 +N: bus/usb/001/006=12010002090001400904580000010102000109021900010100E0320904000001090000000705810301000C +E: BUSNUM=001 +E: DEVNAME=/dev/bus/usb/001/006 +E: DEVNUM=006 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1_5_2 +E: ID_MODEL=USB2.0_Hub_Controller +E: ID_MODEL_ENC=USB2.0\x20Hub\x20Controller +E: ID_MODEL_FROM_DATABASE=HighSpeed Hub +E: ID_MODEL_ID=0058 +E: ID_PATH=pci-0000:00:1a.0-usb-0:1.5.2 +E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1_5_2 +E: ID_REVISION=0100 +E: ID_SERIAL=NEC_Corporation_USB2.0_Hub_Controller +E: ID_USB_INTERFACES=:090000: +E: ID_VENDOR=NEC_Corporation +E: ID_VENDOR_ENC=NEC\x20Corporation +E: ID_VENDOR_FROM_DATABASE=NEC Corp. +E: ID_VENDOR_ID=0409 +E: MAJOR=189 +E: MINOR=5 +E: PRODUCT=409/58/100 +E: SUBSYSTEM=usb +E: TAGS=:seat: +E: TYPE=9/0/1 +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=09 +A: bDeviceProtocol=01 +A: bDeviceSubClass=00 +A: bMaxPacketSize0=64 +A: bMaxPower=100mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0100 +A: bmAttributes=e0 +A: busnum=1 +A: configuration= +H: descriptors=12010002090001400904580000010102000109021900010100E0320904000001090000000705810301000C +A: dev=189:5 +A: devnum=6 +A: devpath=1.5.2 +A: idProduct=0058 +A: idVendor=0409 +A: ltm_capable=no +A: manufacturer=NEC Corporation +A: maxchild=4 +A: product=USB2.0 Hub Controller +A: quirks=0x0 +A: removable=unknown +A: speed=480 +A: urbnum=244 +A: version= 2.00 + +P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5 +N: bus/usb/001/004=1201000209000240EF17051001000000000109022900010100E0010904000001090001000705810301000C0904000101090002000705810301000C +E: BUSNUM=001 +E: DEVNAME=/dev/bus/usb/001/004 +E: DEVNUM=004 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1_5 +E: ID_MODEL=1005 +E: ID_MODEL_ENC=1005 +E: ID_MODEL_ID=1005 +E: ID_PATH=pci-0000:00:1a.0-usb-0:1.5 +E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1_5 +E: ID_REVISION=0001 +E: ID_SERIAL=17ef_1005 +E: ID_USB_INTERFACES=:090001:090002: +E: ID_VENDOR=17ef +E: ID_VENDOR_ENC=17ef +E: ID_VENDOR_FROM_DATABASE=Lenovo +E: ID_VENDOR_ID=17ef +E: MAJOR=189 +E: MINOR=3 +E: PRODUCT=17ef/1005/1 +E: SUBSYSTEM=usb +E: TAGS=:seat: +E: TYPE=9/0/2 +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=09 +A: bDeviceProtocol=02 +A: bDeviceSubClass=00 +A: bMaxPacketSize0=64 +A: bMaxPower=2mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0001 +A: bmAttributes=e0 +A: busnum=1 +A: configuration= +H: descriptors=1201000209000240EF17051001000000000109022900010100E0010904000001090001000705810301000C0904000101090002000705810301000C +A: dev=189:3 +A: devnum=4 +A: devpath=1.5 +A: idProduct=1005 +A: idVendor=17ef +A: ltm_capable=no +A: maxchild=4 +A: quirks=0x0 +A: removable=removable +A: speed=480 +A: urbnum=39 +A: version= 2.00 + +P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1 +N: bus/usb/001/002=12010002090001408780200000000000000109021900010100E0000904000001090000000705810301000C +E: BUSNUM=001 +E: DEVNAME=/dev/bus/usb/001/002 +E: DEVNUM=002 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1 +E: ID_MODEL=0020 +E: ID_MODEL_ENC=0020 +E: ID_MODEL_FROM_DATABASE=Integrated Rate Matching Hub +E: ID_MODEL_ID=0020 +E: ID_PATH=pci-0000:00:1a.0-usb-0:1 +E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1 +E: ID_REVISION=0000 +E: ID_SERIAL=8087_0020 +E: ID_USB_INTERFACES=:090000: +E: ID_VENDOR=8087 +E: ID_VENDOR_ENC=8087 +E: ID_VENDOR_FROM_DATABASE=Intel Corp. +E: ID_VENDOR_ID=8087 +E: MAJOR=189 +E: MINOR=1 +E: PRODUCT=8087/20/0 +E: SUBSYSTEM=usb +E: TAGS=:seat: +E: TYPE=9/0/1 +A: authorized=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=09 +A: bDeviceProtocol=01 +A: bDeviceSubClass=00 +A: bMaxPacketSize0=64 +A: bMaxPower=0mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0000 +A: bmAttributes=e0 +A: busnum=1 +A: configuration= +H: descriptors=12010002090001408780200000000000000109021900010100E0000904000001090000000705810301000C +A: dev=189:1 +A: devnum=2 +A: devpath=1 +A: idProduct=0020 +A: idVendor=8087 +A: ltm_capable=no +A: maxchild=6 +A: quirks=0x0 +A: removable=fixed +A: speed=480 +A: urbnum=66 +A: version= 2.00 + +P: /devices/pci0000:00/0000:00:1a.0/usb1 +N: bus/usb/001/001=12010002090000406B1D020010030302010109021900010100E0000904000001090000000705810304000C +E: BUSNUM=001 +E: DEVNAME=/dev/bus/usb/001/001 +E: DEVNUM=001 +E: DEVTYPE=usb_device +E: DRIVER=usb +E: ID_BUS=usb +E: ID_FOR_SEAT=usb-pci-0000_00_1a_0 +E: ID_MODEL=EHCI_Host_Controller +E: ID_MODEL_ENC=EHCI\x20Host\x20Controller +E: ID_MODEL_FROM_DATABASE=2.0 root hub +E: ID_MODEL_ID=0002 +E: ID_PATH=pci-0000:00:1a.0 +E: ID_PATH_TAG=pci-0000_00_1a_0 +E: ID_REVISION=0310 +E: ID_SERIAL=Linux_3.10.0-0-generic_ehci_hcd_EHCI_Host_Controller_0000:00:1a.0 +E: ID_SERIAL_SHORT=0000:00:1a.0 +E: ID_USB_INTERFACES=:090000: +E: ID_VENDOR=Linux_3.10.0-0-generic_ehci_hcd +E: ID_VENDOR_ENC=Linux\x203.10.0-0-generic\x20ehci_hcd +E: ID_VENDOR_FROM_DATABASE=Linux Foundation +E: ID_VENDOR_ID=1d6b +E: MAJOR=189 +E: MINOR=0 +E: PRODUCT=1d6b/2/310 +E: SUBSYSTEM=usb +E: TAGS=:seat: +E: TYPE=9/0/0 +A: authorized=1 +A: authorized_default=1 +A: avoid_reset_quirk=0 +A: bConfigurationValue=1 +A: bDeviceClass=09 +A: bDeviceProtocol=00 +A: bDeviceSubClass=00 +A: bMaxPacketSize0=64 +A: bMaxPower=0mA +A: bNumConfigurations=1 +A: bNumInterfaces= 1 +A: bcdDevice=0310 +A: bmAttributes=e0 +A: busnum=1 +A: configuration= +H: descriptors=12010002090000406B1D020010030302010109021900010100E0000904000001090000000705810304000C +A: dev=189:0 +A: devnum=1 +A: devpath=0 +A: idProduct=0002 +A: idVendor=1d6b +A: ltm_capable=no +A: manufacturer=Linux 3.10.0-0-generic ehci_hcd +A: maxchild=3 +A: product=EHCI Host Controller +A: quirks=0x0 +A: removable=unknown +A: serial=0000:00:1a.0 +A: speed=480 +A: urbnum=26 +A: version= 2.00 + +P: /devices/pci0000:00/0000:00:1a.0 +E: DRIVER=ehci-pci +E: ID_MODEL_FROM_DATABASE=5 Series/3400 Series Chipset USB2 Enhanced Host Controller +E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller +E: ID_PCI_INTERFACE_FROM_DATABASE=EHCI +E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller +E: ID_VENDOR_FROM_DATABASE=Intel Corporation +E: MODALIAS=pci:v00008086d00003B3Csv000017AAsd00002163bc0Csc03i20 +E: PCI_CLASS=C0320 +E: PCI_ID=8086:3B3C +E: PCI_SLOT_NAME=0000:00:1a.0 +E: PCI_SUBSYS_ID=17AA:2163 +E: SUBSYSTEM=pci +A: broken_parity_status=0 +A: class=0x0c0320 +A: companion= +H: config=86803C3B060190020620030C00000000008072F2000000000000000000000000000000000000000000000000AA1763210000000050000000000000000B040000 +A: consistent_dma_mask_bits=32 +A: d3cold_allowed=1 +A: device=0x3b3c +A: dma_mask_bits=32 +A: irq=23 +A: local_cpulist=0-3 +A: local_cpus=00000000,00000000,00000000,00000000,00000000,00000000,00000000,0000000f +A: modalias=pci:v00008086d00003B3Csv000017AAsd00002163bc0Csc03i20 +A: msi_bus= +A: numa_node=-1 +A: pools=poolinfo - 0.1\nehci_sitd 0 0 96 0\nehci_itd 0 0 192 0\nehci_qh 25 42 96 1\nehci_qtd 36 42 96 1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 9 32 128 1\nbuffer-32 1 128 32 1 +A: resource=0x00000000f2728000 0x00000000f27283ff 0x0000000000040200\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000 +A: subsystem_device=0x2163 +A: subsystem_vendor=0x17aa +A: uframe_periodic_max=100 +A: vendor=0x8086 + diff --git a/test/gvfs-test b/test/gvfs-test index bd8fdbbb..6aab9743 100755 --- a/test/gvfs-test +++ b/test/gvfs-test @@ -40,6 +40,8 @@ from gi.repository import GLib, Gio try: from gi.repository import UMockdev have_umockdev = subprocess.call(['which', 'umockdev-wrapper'], stdout=subprocess.PIPE) == 0 + # needs >= 0.2.10 + have_umockdev = have_umockdev and hasattr(UMockdev.Testbed, 'add_from_file') except ImportError: have_umockdev = False @@ -1691,6 +1693,89 @@ class GPhoto(GvfsTestCase): #umockdev_testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.2/1-1.5.2.3', 'add'); +@unittest.skipUnless(have_umockdev, + 'umockdev not installed; get it from https://launchpad.net/umockdev') +class Mtp(GvfsTestCase): + @classmethod + def setUpClass(klass): + '''Load Sony Xperia MTP dump into testbed''' + + GvfsTestCase.setUpClass() + umockdev_testbed.add_from_file(os.path.join(my_dir, 'files', 'mtp_xperia.umockdev')) + umockdev_testbed.load_ioctl('/dev/bus/usb/001/017', + os.path.join(my_dir, 'files', 'mtp_xperia.ioctl.xz')) + + def shell(self): + subprocess.call(['umockdev-wrapper', 'bash', '-i']) + + def xtest_detect(self): + '''mtp:// detection''' + + out = self.program_out_success(['umockdev-wrapper', 'gvfs-mount', '-li']) + print(out) + + def test_mount_cli(self): + '''mtp:// mount with CLI''' + + uri = 'mtp://[usb:001,017]' + + # this might take a bit until everything is detected + timeout = 5 + while timeout > 0: + if subprocess.call(['gvfs-mount', uri], stderr=subprocess.PIPE) == 0: + break + timeout -= 1 + time.sleep(0.5) + else: + self.fail('gvfs-mount %s failed' % uri) + + try: + # The top-level name is defined by the mobile firmware + self.assertEqual(self.program_out_success(['gvfs-ls', uri]), 'SD-Karte\n') + self.assertEqual(self.program_out_success(['gvfs-ls', uri + '/SD-Karte']), + 'DCIM\nhello.txt\nLOST.DIR\nMusic\nAndroid\nclockworkmod\n') + self.assertEqual(self.program_out_success(['gvfs-ls', uri + '/SD-Karte/Music']), + 'GStreamer - The Test Sine\n') + self.assertEqual(self.program_out_success(['gvfs-ls', uri + '/SD-Karte/Music/GStreamer - The Test Sine']), + 'sine.ogg\n') + + # info for a dir and a music file + out = self.program_out_success(['gvfs-info', uri + '/SD-Karte/Music/GStreamer - The Test Sine']) + self.assertIn('standard::content-type: inode/directory', out) + self.assertIn('access::can-read: TRUE', out) + self.assertIn('access::can-write: TRUE', out) + self.assertIn('access::can-delete: TRUE', out) + + out = self.program_out_success(['gvfs-info', uri + '/SD-Karte/Music/GStreamer - The Test Sine/sine.ogg']) + self.assertIn('standard::content-type: audio/ogg', out) + self.assertIn('standard::size: 4400', out) + self.assertIn('access::can-read: TRUE', out) + self.assertIn('access::can-write: TRUE', out) + self.assertIn('access::can-delete: TRUE', out) + + # read ogg file + out = subprocess.check_output(['gvfs-cat', uri + '/SD-Karte/Music/GStreamer - The Test Sine/sine.ogg']) + self.assertTrue(out.startswith(b'OggS\x00'), out[:20]) + + # text file + self.assertEqual(self.program_out_success(['gvfs-cat', uri + '/SD-Karte/hello.txt']), + 'world\n') + out = self.program_out_success(['gvfs-info', uri + '/SD-Karte/hello.txt']) + self.assertIn('standard::content-type: text/plain', out) + self.assertIn('standard::size: 6', out) + + # photo + out = self.program_out_success(['gvfs-info', uri + '/SD-Karte/DCIM/100CANON/IMG_0001.JPG']) + self.assertIn('standard::content-type: image/jpeg', out) + self.assertIn('standard::size: 8843', out) + self.assertIn('preview::icon:', out) + + out = subprocess.check_output(['gvfs-cat', uri + '/SD-Karte/DCIM/100CANON/IMG_0001.JPG']) + self.assertIn(b'JFIF', out[:20]) + finally: + self.unmount(uri) + + def start_dbus(): '''Run a local D-BUS daemon under temporary XDG directories -- cgit v1.2.3