1import ./make-test-python.nix ({ pkgs, firefoxPackage, ... }: {
2 name = "firefox";
3 meta = with pkgs.lib.maintainers; {
4 maintainers = [ eelco shlevy ];
5 };
6
7 machine =
8 { pkgs, ... }:
9
10 { imports = [ ./common/x11.nix ];
11 environment.systemPackages = [
12 firefoxPackage
13 pkgs.xdotool
14 ];
15
16 # Create a virtual sound device, with mixing
17 # and all, for recording audio.
18 boot.kernelModules = [ "snd-aloop" ];
19 sound.enable = true;
20 sound.extraConfig = ''
21 pcm.!default {
22 type plug
23 slave.pcm pcm.dmixer
24 }
25 pcm.dmixer {
26 type dmix
27 ipc_key 1
28 slave {
29 pcm "hw:Loopback,0,0"
30 rate 48000
31 periods 128
32 period_time 0
33 period_size 1024
34 buffer_size 8192
35 }
36 }
37 pcm.recorder {
38 type hw
39 card "Loopback"
40 device 1
41 subdevice 0
42 }
43 '';
44
45 systemd.services.audio-recorder = {
46 description = "Record NixOS test audio to /tmp/record.wav";
47 script = "${pkgs.alsa-utils}/bin/arecord -D recorder -f S16_LE -r48000 /tmp/record.wav";
48 };
49
50 };
51
52 testScript = ''
53 from contextlib import contextmanager
54
55
56 @contextmanager
57 def audio_recording(machine: Machine) -> None:
58 """
59 Perform actions while recording the
60 machine audio output.
61 """
62 machine.systemctl("start audio-recorder")
63 yield
64 machine.systemctl("stop audio-recorder")
65
66
67 def wait_for_sound(machine: Machine) -> None:
68 """
69 Wait until any sound has been emitted.
70 """
71 machine.wait_for_file("/tmp/record.wav")
72 while True:
73 # Get at most 2M of the recording
74 machine.execute("tail -c 2M /tmp/record.wav > /tmp/last")
75 # Get the exact size
76 size = int(machine.succeed("stat -c '%s' /tmp/last").strip())
77 # Compare it against /dev/zero using `cmp` (skipping 50B of WAVE header).
78 # If some non-NULL bytes are found it returns 1.
79 status, output = machine.execute(
80 f"cmp -i 50 -n {size - 50} /tmp/last /dev/zero 2>&1"
81 )
82 if status == 1:
83 break
84 machine.sleep(2)
85
86
87 machine.wait_for_x()
88
89 with subtest("Wait until Firefox has finished loading the Valgrind docs page"):
90 machine.execute(
91 "xterm -e 'firefox file://${pkgs.valgrind.doc}/share/doc/valgrind/html/index.html' >&2 &"
92 )
93 machine.wait_for_window("Valgrind")
94 machine.sleep(40)
95
96 with subtest("Check whether Firefox can play sound"):
97 with audio_recording(machine):
98 machine.succeed(
99 "firefox file://${pkgs.sound-theme-freedesktop}/share/sounds/freedesktop/stereo/phone-incoming-call.oga >&2 &"
100 )
101 wait_for_sound(machine)
102 machine.copy_from_vm("/tmp/record.wav")
103
104 with subtest("Close sound test tab"):
105 machine.execute("xdotool key ctrl+w")
106
107 with subtest("Close default browser prompt"):
108 machine.execute("xdotool key space")
109
110 with subtest("Wait until Firefox draws the developer tool panel"):
111 machine.sleep(10)
112 machine.succeed("xwininfo -root -tree | grep Valgrind")
113 machine.screenshot("screen")
114 '';
115
116})