|
| 1 | +# Running and debugging tests |
| 2 | + |
| 3 | +Disko makes extensive use of VM tests. All examples you can find in |
| 4 | +[the example directory](../example) have a respective test suite that verifies |
| 5 | +the example is working in [the tests directory](../tests/). They utilize the |
| 6 | +[NixOS test functionality](https://nixos.org/manual/nixos/stable/#sec-nixos-tests). |
| 7 | + |
| 8 | +We use a wrapper around this called `makeDiskoTest`. There is currently (as of |
| 9 | +2024-10-16) no documentation for all its arguments, but you can have a look at |
| 10 | +[its current code](https://github.com/nix-community/disko/blob/master/lib/tests.nix#L44C5-L58C10), |
| 11 | +that should already be helpful. |
| 12 | + |
| 13 | +However, you don't need to know about all of the inner workings to interact with |
| 14 | +the tests effectively. For some of the most common operations, see the sections |
| 15 | +below. |
| 16 | + |
| 17 | +## Run just one of the tests |
| 18 | + |
| 19 | +```sh |
| 20 | +nix build --no-link .#checks.x86_64-linux.simple-efi |
| 21 | +``` |
| 22 | + |
| 23 | +This will run the test in [`tests/simple-efi.nix`](../tests/simple-efi.nix), |
| 24 | +which builds a VM with all disks specified in the |
| 25 | +[`example/simple-efi.nix`](../example/simple-efi.nix) config connected as |
| 26 | +virtual devices, run disko to format them, reboot, verify the VM boots properly, |
| 27 | +and then run the code specified in `extraTestScript` to validate that the |
| 28 | +partitions have been created and were mounted as expected. |
| 29 | + |
| 30 | +### How `extraTestScript` works |
| 31 | + |
| 32 | +This is written in Python. The most common lines you'll see look something like |
| 33 | +this: |
| 34 | + |
| 35 | +```python |
| 36 | +machine.succeed("test -b /dev/md/raid1"); |
| 37 | +machine.succeed("mountpoint /"); |
| 38 | +``` |
| 39 | + |
| 40 | +The `machine` in these is a machine object, which defines |
| 41 | +[a multitude of functions to interact with and test](https://nixos.org/manual/nixos/stable/#ssec-machine-objects), |
| 42 | +assumptions about the state of the VM after formatting and rebooting. |
| 43 | + |
| 44 | +Disko currently (as of 2024-10-16) doesn't have any tests that utilize multiple |
| 45 | +VMs at once, so the only machine available in these scripts is always just the |
| 46 | +default `machine`. |
| 47 | + |
| 48 | +## Debugging tests |
| 49 | + |
| 50 | +If you make changes to disko, you might break a test, or you may want to modify |
| 51 | +a test to prevent regressions. In these cases, running the full test with |
| 52 | +`nix build` every time is time-consuming and tedious. |
| 53 | + |
| 54 | +Instead, you can build and then run the VM for a test in interactive mode. This |
| 55 | +will create the VM and all virtual disks as required by the test's config, but |
| 56 | +allow you to interact with the machine on a terminal afterwards. |
| 57 | + |
| 58 | +First, build the interactive test driver and run it: |
| 59 | + |
| 60 | +``` |
| 61 | +nix build .#checks.x86_64-linux.simple-efi.driverInteractive |
| 62 | +result/bin/nixos-test-driver --keep-vm-state |
| 63 | +``` |
| 64 | + |
| 65 | +This will open an IPython prompt in which you can use th same objects and |
| 66 | +functions as in `extraTestScript`. In there, you can run |
| 67 | + |
| 68 | +``` |
| 69 | +machine.shell_interact() |
| 70 | +``` |
| 71 | + |
| 72 | +to start the VM and attach the terminal to it. This will also open a QEMU |
| 73 | +window, in which you can log in as `root` with no password, but that makes it |
| 74 | +more difficult to paste input and output. Instead, wait for the systemd messages |
| 75 | +to settle down, and then **simply start typing**. This should make a `$` prompt |
| 76 | +appear, indicating that the machine is ready to take commands. The NixOS manual |
| 77 | +calls out a few special messages to look for, but these are buried underneath |
| 78 | +the systemd logs. |
| 79 | + |
| 80 | +Once you are in this terminal, you're running commands on the VM. The only thing |
| 81 | +that doesn't work here is the `exit` command. Instead, you need to press Ctrl+D |
| 82 | +and wait for a second to return to the IPython prompt. |
| 83 | + |
| 84 | +In summary, a full session looks something like this: |
| 85 | + |
| 86 | +``` |
| 87 | +# nix build .#checks.x86_64-linux.simple-efi.driverInteractive |
| 88 | +# result/bin/nixos-test-driver --keep-vm-state |
| 89 | +start all VLans |
| 90 | +start vlan |
| 91 | +running vlan (pid 146244; ctl /tmp/vde1.ctl) |
| 92 | +(finished: start all VLans, in 0.00 seconds) |
| 93 | +additionally exposed symbols: |
| 94 | + machine, |
| 95 | + vlan1, |
| 96 | + start_all, test_script, machines, vlans, driver, log, os, create_machine, subtest, run_tests, join_all, retry, serial_stdout_off, serial_stdout_on, polling_condition, Machine |
| 97 | +>>> machine.shell_interact() |
| 98 | +machine: waiting for the VM to finish booting |
| 99 | +machine: starting vm |
| 100 | +machine: QEMU running (pid 146286) |
| 101 | +machine # [ 0.000000] Linux version 6.6.48 (nixbld@localhost) (gcc (GCC) 13.3.0, GNU ld (GNU Binutils) 2.42) #1-NixOS SMP PREEMPT_DYNAMIC Thu Aug 29 15:33:59 UTC 2024 |
| 102 | +machine # [ 0.000000] Command line: console=ttyS0 panic=1 boot.panic_on_fail clocksource=acpi_pm loglevel=7 net.ifnames=0 init=/nix/store/0a52bbvxr5p7xijbbk17qqlk8xm4790y-nixos-system-machine-test/init regInfo=/nix/store/3sh5nl75bnj1jg87p5gcrdzs0lk154ma-closure-info/registration console=ttyS0 |
| 103 | +machine # [ 0.000000] BIOS-provided physical RAM map: |
| 104 | +... |
| 105 | +... more systemd messages |
| 106 | +... |
| 107 | +machine # [ 6.135577] dhcpcd[679]: DUID 00:01:00:01:2e:a2:74:e6:52:54:00:12:34:56 |
| 108 | +machine # [ 6.142785] systemd[1]: Finished Kernel Auditing. |
| 109 | +machine: Guest shell says: b'Spawning backdoor root shell...\n' |
| 110 | +machine: connected to guest root shell |
| 111 | +machine: (connecting took 6.61 seconds) |
| 112 | +(finished: waiting for the VM to finish booting, in 6.99 seconds) |
| 113 | +machine: Terminal is ready (there is no initial prompt): |
| 114 | +machine # [ 6.265451] 8021q: 802.1Q VLAN Support v1.8 |
| 115 | +machine # [ 6.186797] nsncd[669]: Oct 16 13:11:55.010 INFO started, config: Config { ignored_request_types: {}, worker_count: 8, handoff_timeout: 3s }, path: "/var/run/nscd/socket" |
| 116 | +... |
| 117 | +... more systemd messages |
| 118 | +... |
| 119 | +machine # [ 12.376900] systemd[1]: Reached target Host and Network Name Lookups. |
| 120 | +machine # [ 12.379265] systemd[1]: Reached target User and Group Name Lookups. |
| 121 | +$ lsblk |
| 122 | +NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS |
| 123 | +fd0 2:0 1 4K 0 disk |
| 124 | +sr0 11:0 1 1024M 0 rom |
| 125 | +vda 253:0 0 1G 0 disk / |
| 126 | +vdb 253:16 0 4G 0 disk |
| 127 | +├─vdb1 253:17 0 500M 0 part |
| 128 | +└─vdb2 253:18 0 3.5G 0 part |
| 129 | +``` |
| 130 | + |
| 131 | +You can find some additional details in |
| 132 | +[the NixOS manual's section on interactive testing](https://nixos.org/manual/nixos/stable/#sec-running-nixos-tests-interactively). |
| 133 | + |
| 134 | +## Running all tests at once |
| 135 | + |
| 136 | +If you have a bit of experience, you might be inclined to run `nix flake check` |
| 137 | +to run all tests at once. However, we instead recommend using |
| 138 | +[nix-fast-build](https://github.com/Mic92/nix-fast-build). The reason for this |
| 139 | +is that each individual test takes a while to run, but only uses <=4GiB of RAM |
| 140 | +and a limited amount of CPU resources. This means they can easily be evaluated |
| 141 | +and run in parallel to save time, but `nix` doesn't to that, so a full test run |
| 142 | +takes >40 minutes on a mid-range system. With `nix-fast-build` you can scale up |
| 143 | +the number of workers depending on your system's capabilities. It also utilizes |
| 144 | +[`nix-output-monitor`](https://github.com/maralorn/nix-output-monitor) to give |
| 145 | +you a progress indicator during the build process as well. For example, on a |
| 146 | +machine with 16GB of RAM, this gives you a 2x speed up without clogging your |
| 147 | +system: |
| 148 | + |
| 149 | +```sh |
| 150 | +nix shell nixpkgs#nix-fast-build |
| 151 | +nix-fast-build --no-link -j 2 --eval-workers 2 --flake .#checks |
| 152 | +``` |
| 153 | + |
| 154 | +You can try higher numbers if you want to. Be careful with scaling up |
| 155 | +`--eval-workers`, each of these will use 100% of a CPU core and they don't leave |
| 156 | +any time for hyperthreading, so 4 workers will max out a a CPU with 4 cores and |
| 157 | +8 threads, potentially rendering your system unresponsive! `-j` is less |
| 158 | +dangerous to scale up, but you probably don't want to go higher than |
| 159 | +`(<ram in your system> - 4GB)/4GB` to prevent excessive swap usage, which will |
| 160 | +would slow down the test VMs to a crawl. |
0 commit comments