[gvfs] gvfs-test: Add first test for gphoto2 backend



commit 5235e39b054e7574493c50bf60dce874f040bd6c
Author: Martin Pitt <martinpitt gnome org>
Date:   Tue Jun 11 15:13:49 2013 +0200

    gvfs-test: Add first test for gphoto2 backend
    
    Add umockdev dump and ioctl trace for a Canon PowerShot SX200 digicam, with
    ioctls from these commands recorded:
    
      gvfs-mount -li
      gvfs-mount gphoto2://[usb:001,011]/
      gvfs-info gphoto2://[usb:001,011]
      gvfs-info gphoto2://[usb:001,011]/DCIM
      gvfs-info gphoto2://[usb:001,011]/DCIM/100CANON/IMG_0001.JPG
      gvfs-info gphoto2://[usb:001,011]/DCIM/100CANON/IMG_0002.JPG
      gvfs-cat gphoto2://[usb:001,011]/DCIM/100CANON/IMG_0001.JPG
      gvfs-cat gphoto2://[usb:001,011]/DCIM/100CANON/IMG_0002.JPG
    
    (With two tiny test images, not actual big photos)
    
    If umockdev is available, use it to simulate that device and check that we can
    get the directory and file info, and access the pictures.
    
    Note that this does not yet work under gvfs-testbed, as we somehow need to
    inject the $UMOCKDEV_ROOT into the spawned d-bus.

 test/Makefile.am              |    2 +
 test/files/powershot.ioctl.xz |  Bin 0 -> 3912 bytes
 test/files/powershot.umockdev |  312 +++++++++++++++++++++++++++++++++++++++++
 test/gvfs-test                |   89 +++++++++++-
 4 files changed, 400 insertions(+), 3 deletions(-)
---
diff --git a/test/Makefile.am b/test/Makefile.am
index 68b3674..4d2d9ff 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -87,4 +87,6 @@ EXTRA_DIST = \
        files/ssh_host_rsa_key files    \
        files/ssh_host_rsa_key.pub      \
        files/testcert.pem              \
+       files/powershot.ioctl.xz        \
+       files/powershot.umockdev        \
        $(NULL)
diff --git a/test/files/powershot.ioctl.xz b/test/files/powershot.ioctl.xz
new file mode 100644
index 0000000..3e69afe
Binary files /dev/null and b/test/files/powershot.ioctl.xz differ
diff --git a/test/files/powershot.umockdev b/test/files/powershot.umockdev
new file mode 100644
index 0000000..2774af5
--- /dev/null
+++ b/test/files/powershot.umockdev
@@ -0,0 +1,312 @@
+P: /devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.5/1-1.5.2/1-1.5.2.3
+N: 
bus/usb/001/015=1201000200000040A904C03102000102030109022700010100C001090400000306010100070581020002000705020200020007058303080009
+E: BUSNUM=001
+E: DEVNAME=/dev/bus/usb/001/015
+E: DEVNUM=015
+E: DEVTYPE=usb_device
+E: DRIVER=usb
+E: GPHOTO2_DRIVER=PTP
+E: ID_BUS=usb
+E: ID_FOR_SEAT=usb-pci-0000_00_1a_0-usb-0_1_5_2_3
+E: ID_GPHOTO2=1
+E: ID_MODEL=Canon_Digital_Camera
+E: ID_MODEL_ENC=Canon\x20Digital\x20Camera
+E: ID_MODEL_ID=31c0
+E: ID_PATH=pci-0000:00:1a.0-usb-0:1.5.2.3
+E: ID_PATH_TAG=pci-0000_00_1a_0-usb-0_1_5_2_3
+E: ID_REVISION=0002
+E: ID_SERIAL=Canon_Inc._Canon_Digital_Camera_C767F1C714174C309255F70E4A7B2EE2
+E: ID_SERIAL_SHORT=C767F1C714174C309255F70E4A7B2EE2
+E: ID_USB_INTERFACES=:060101:
+E: ID_VENDOR=Canon_Inc.
+E: ID_VENDOR_ENC=Canon\x20Inc.
+E: ID_VENDOR_ID=04a9
+E: MAJOR=189
+E: MINOR=14
+E: PRODUCT=4a9/31c0/2
+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=2mA
+A: bNumConfigurations=1
+A: bNumInterfaces= 1
+A: bcdDevice=0002
+A: bmAttributes=c0
+A: busnum=1
+A: configuration=
+H: 
descriptors=1201000200000040A904C03102000102030109022700010100C001090400000306010100070581020002000705020200020007058303080009
+A: dev=189:14
+A: devnum=15
+A: devpath=1.5.2.3
+A: idProduct=31c0
+A: idVendor=04a9
+A: ltm_capable=no
+A: manufacturer=Canon Inc.
+A: maxchild=0
+A: product=Canon Digital Camera
+A: quirks=0x0
+A: removable=unknown
+A: serial=C767F1C714174C309255F70E4A7B2EE2
+A: speed=480
+A: urbnum=200
+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/011=12010002090001400904580000010102000109021900010100E0320904000001090000000705810301000C
+E: BUSNUM=001
+E: DEVNAME=/dev/bus/usb/001/011
+E: DEVNUM=011
+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_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_ID=0409
+E: MAJOR=189
+E: MINOR=10
+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:10
+A: devnum=11
+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=127
+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_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=63
+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_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_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=115
+A: version= 2.00
+
+P: /devices/pci0000:00/0000:00:1a.0/usb1
+N: bus/usb/001/001=12010002090000406B1D020009030302010109021900010100E0000904000001090000000705810304000C
+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_ID=0002
+E: ID_PATH=pci-0000:00:1a.0
+E: ID_PATH_TAG=pci-0000_00_1a_0
+E: ID_REVISION=0309
+E: ID_SERIAL=Linux_3.9.0-4-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.9.0-4-generic_ehci_hcd
+E: ID_VENDOR_ENC=Linux\x203.9.0-4-generic\x20ehci_hcd
+E: ID_VENDOR_ID=1d6b
+E: MAJOR=189
+E: MINOR=0
+E: PRODUCT=1d6b/2/309
+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=0309
+A: bmAttributes=e0
+A: busnum=1
+A: configuration=
+H: descriptors=12010002090000406B1D020009030302010109021900010100E0000904000001090000000705810304000C
+A: dev=189:0
+A: devnum=1
+A: devpath=0
+A: idProduct=0002
+A: idVendor=1d6b
+A: ltm_capable=no
+A: manufacturer=Linux 3.9.0-4-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: 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     
       24   42   96  1\nehci_qtd           35   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 5360f62..e5094d4 100755
--- a/test/gvfs-test
+++ b/test/gvfs-test
@@ -32,10 +32,20 @@ import shutil
 import fcntl
 import re
 import locale
+import signal
 from glob import glob
 
 from gi.repository import GLib, Gio
 
+try:
+    from gi.repository import UMockdev
+    have_umockdev = subprocess.call(['which', 'umockdev-wrapper'], stdout=subprocess.PIPE) == 0
+except ImportError:
+    have_umockdev = False
+
+# umockdev environment for gphoto/MTP tests
+umockdev_testbed = None
+
 
 def find_alternative(cmds):
     '''Find command in cmds array and return the found alternative'''
@@ -84,6 +94,8 @@ class GvfsTestCase(unittest.TestCase):
 
     def tearDown(self):
         shutil.rmtree(self.workdir)
+        if umockdev_testbed:
+            umockdev_testbed.clear()
 
     def run(self, result=None):
         '''Show dbus daemon output on failed tests'''
@@ -1612,8 +1624,71 @@ class Trash(GvfsTestCase):
             self.assertTrue(os.path.exists(self.my_file))
 
 
+ unittest skipIf(in_testbed, 'this test does not currently work under gvfs-testbed')
+ unittest skipUnless(have_umockdev,
+                     'umockdev not installed; get it from https://launchpad.net/umockdev')
+class GPhoto(GvfsTestCase):
+    def test_mount_api(self):
+        '''gphoto2:// mount with Gio API'''
+
+        self.add_powershot()
+
+        uri = 'gphoto2://[usb:001,015]'
+        gfile_mount = Gio.File.new_for_uri(uri)
+
+        self.assertEqual(self.mount_api(gfile_mount), True)
+        try:
+            # check top-level directory
+            info = gfile_mount.query_info('*', 0, None)
+            self.assertEqual(info.get_content_type(), 'inode/directory')
+            self.assertEqual(info.get_file_type(), Gio.FileType.DIRECTORY)
+            self.assertIn('camera', info.get_display_name().lower())
+            self.assertEqual(info.get_attribute_boolean('access::can-read'), True)
+
+            # check a photo
+            gfile = Gio.File.new_for_uri(uri + '/DCIM/100CANON/IMG_0001.JPG')
+            # FIXME: The first call always fails (only with umockdev)
+            try:
+                info = gfile.query_info('*', 0, None)
+            except GLib.GError:
+                info = gfile.query_info('*', 0, None)
+
+            self.assertEqual(info.get_content_type(), 'image/jpeg')
+            self.assertEqual(info.get_file_type(), Gio.FileType.REGULAR)
+            # we don't care about capitalization
+            self.assertEqual(info.get_display_name().lower(), 'img_0001.jpg')
+            self.assertEqual(info.get_attribute_boolean('access::can-read'), True)
+            self.assertEqual(info.get_attribute_boolean('access::can-write'), True)
+
+            # open photo
+            stream = gfile.read(None)
+            block = stream.read_bytes(20, None)
+            self.assertIn(b'JFIF\x00', block.get_data())
+            stream.close(None)
+
+            # nonexisting file
+            gfile = Gio.File.new_for_uri(uri + '/DCIM/100CANON/IMG_9999.JPG')
+            self.assertRaises(GLib.GError, gfile.query_info, '*', 0, None)
+        finally:
+            self.unmount_api(gfile_mount)
+
+    def add_powershot(self):
+        '''Add PowerShot device and ioctls to umockdev testbed'''
+
+        with open(os.path.join(my_dir, 'files', 'powershot.umockdev')) as f:
+            umockdev_testbed.add_from_string(f.read())
+        umockdev_testbed.load_ioctl('/dev/bus/usb/001/015',
+                                    os.path.join(my_dir, 'files', 'powershot.ioctl.xz'))
+
+        # signal our monitor about the addition
+        #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');
+
+
 def start_dbus():
     '''Run a local D-BUS daemon under temporary XDG directories
+
+    This also runs the D-BUS daemon under umockdev-wrapper (if available), so
+    that it will see fake umockdev devices.
     
     Return temporary XDG home directory.
     '''
@@ -1640,9 +1715,12 @@ def start_dbus():
     env['GVFS_SMB_DEBUG'] = '6'
     env['GVFS_HTTP_DEBUG'] = 'all'
     env['LIBSMB_PROG'] = "nc localhost 1445"
-    dbus_daemon = subprocess.Popen(
-        ['dbus-daemon', '--config-file', dbus_conf, '--print-address=1'],
-        stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
+    argv = ['dbus-daemon', '--config-file', dbus_conf, '--print-address=1']
+    if umockdev_testbed:
+        argv.insert(0, 'umockdev-wrapper')
+        # Python doesn't catch the setenv() from UMockdev.Testbed.new()
+        env['UMOCKDEV_DIR'] = umockdev_testbed.get_root_dir()
+    dbus_daemon = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
     addr = dbus_daemon.stdout.readline().decode()
     os.environ['DBUS_SESSION_BUS_ADDRESS'] = addr
 
@@ -1664,6 +1742,11 @@ if __name__ == '__main__':
     os.environ['LC_ALL'] = 'C'
     
     if not in_testbed:
+        # we need to create the umockdev testbed before launching D-BUS, so
+        # that all spawned gvfs daemons see it
+        if have_umockdev:
+            umockdev_testbed = UMockdev.Testbed.new()
+
         temp_home = start_dbus()
     try:
         unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]