···1+import ./make-test-python.nix ({ pkgs, ... }: {
2+ name = "mtp";
3+ meta = with pkgs.lib.maintainers; {
4+ maintainers = [ matthewcroughan nixinator ];
5+ };
6+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";
14+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";
18+19+ environment.systemPackages = with pkgs; [ usbutils glib jmtpfs tree ];
20+ services.gvfs.enable = true;
21+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+ };
31+32+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+ '';
109+})
···102 ./0090-pipewire-config-template-paths.patch
103 # Place SPA data files in lib output to avoid dependency cycles
104 ./0095-spa-data-dir.patch
000000105 ];
106107 nativeBuildInputs = [
···102 ./0090-pipewire-config-template-paths.patch
103 # Place SPA data files in lib output to avoid dependency cycles
104 ./0095-spa-data-dir.patch
105+ # Fixes missing function declarations in pipewire headers
106+ # Should be removed after the next release
107+ (fetchpatch {
108+ url = "https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/a2e98e28c1e6fb58b273ef582398d8bee4d2b769.patch";
109+ sha256 = "sha256-tqiiAW2fTEp23HT59XR2D/G08pVENJtpxUI7UVufj/A=";
110+ })
111 ];
112113 nativeBuildInputs = [