nixVersions.stable: 2.15 -> 2.17
[NixPkgs.git] / nixos / tests / mtp.nix
blob8f0835d75d3fea5e55c94ccf8c70883921d6bcf8
1 import ./make-test-python.nix ({ pkgs, ... }: {
2   name = "mtp";
3   meta = with pkgs.lib.maintainers; {
4     maintainers = [ matthewcroughan nixinator ];
5   };
7   nodes =
8   {
9     client = { config, pkgs, ... }: {
10       # DBUS runs only once a user session is created, which means a user has to
11       # login. Here, we log in as root. Once logged in, the gvfs-daemon service runs
12       # as UID 0 in User-0.service
13       services.getty.autologinUser = "root";
15       # XDG_RUNTIME_DIR is needed for running systemd-user services such as
16       # gvfs-daemon as root.
17       environment.variables.XDG_RUNTIME_DIR = "/run/user/0";
19       environment.systemPackages = with pkgs; [ usbutils glib jmtpfs tree ];
20       services.gvfs.enable = true;
22       # Creates a usb-mtp device inside the VM, which is mapped to the host's
23       # /tmp folder, it is able to write files to this location, but only has
24       # permissions to read its own creations.
25       virtualisation.qemu.options = [
26         "-usb"
27         "-device usb-mtp,rootdir=/tmp,readonly=false"
28       ];
29     };
30   };
33   testScript = { nodes, ... }:
34     let
35       # Creates a list of QEMU MTP devices matching USB ID (46f4:0004). This
36       # value can be sourced in a shell script. This is so we can loop over the
37       # devices we find, as this test may want to use more than one MTP device
38       # in future.
39       mtpDevices = pkgs.writeScript "mtpDevices.sh" ''
40         export mtpDevices=$(lsusb -d 46f4:0004 | awk {'print $2","$4'} | sed 's/[:-]/ /g')
41       '';
42       # Qemu is only capable of creating an MTP device with Picture Transfer
43       # Protocol. This means that gvfs must use gphoto2:// rather than mtp://
44       # when mounting.
45       # https://github.com/qemu/qemu/blob/970bc16f60937bcfd334f14c614bd4407c247961/hw/usb/dev-mtp.c#L278
46       gvfs = rec {
47         mountAllMtpDevices = pkgs.writeScript "mountAllMtpDevices.sh" ''
48           set -e
49           source ${mtpDevices}
50           for i in $mtpDevices
51           do
52             gio mount "gphoto2://[usb:$i]/"
53           done
54         '';
55         unmountAllMtpDevices = pkgs.writeScript "unmountAllMtpDevices.sh" ''
56           set -e
57           source ${mtpDevices}
58           for i in $mtpDevices
59           do
60             gio mount -u "gphoto2://[usb:$i]/"
61           done
62         '';
63         # gvfsTest:
64         # 1. Creates a 10M test file
65         # 2. Copies it to the device using GIO tools
66         # 3. Checks for corruption with `diff`
67         # 4. Removes the file, then unmounts the disks.
68         gvfsTest = pkgs.writeScript "gvfsTest.sh" ''
69           set -e
70           source ${mtpDevices}
71           ${mountAllMtpDevices}
72           dd if=/dev/urandom of=testFile10M bs=1M count=10
73           for i in $mtpDevices
74           do
75             gio copy ./testFile10M gphoto2://[usb:$i]/
76             ls -lah /run/user/0/gvfs/*/testFile10M
77             gio remove gphoto2://[usb:$i]/testFile10M
78           done
79           ${unmountAllMtpDevices}
80         '';
81       };
82       jmtpfs = {
83         # jmtpfsTest:
84         # 1. Mounts the device on a dir named `phone` using jmtpfs
85         # 2. Puts the current Nixpkgs libmtp version into a file
86         # 3. Checks for corruption with `diff`
87         # 4. Prints the directory tree
88         jmtpfsTest = pkgs.writeScript "jmtpfsTest.sh" ''
89           set -e
90           mkdir phone
91           jmtpfs phone
92           echo "${pkgs.libmtp.version}" > phone/tmp/testFile
93           echo "${pkgs.libmtp.version}" > testFile
94           diff phone/tmp/testFile testFile
95           tree phone
96         '';
97       };
98     in
99     # Using >&2 allows the results of the scripts to be printed to the terminal
100     # when building this test with Nix. Scripts would otherwise complete
101     # silently.
102     ''
103     start_all()
104     client.wait_for_unit("multi-user.target")
105     client.wait_for_unit("dbus.service")
106     client.succeed("${gvfs.gvfsTest} >&2")
107     client.succeed("${jmtpfs.jmtpfsTest} >&2")
108   '';