anchor.diff:            "cryptsetup luksOpen --key-file /mnt/keyfile /dev/vda3 crypt",
             "mkfs.ext3 -L test /dev/mapper/crypt",
             "cryptsetup luksClose crypt",
  -          "mkdir -p /mnt/test"
  -        );
  -      '';
  -      extraConfig = ''
  -        fileSystems."/test" =
  -        { device = "/dev/disk/by-label/test";
  -          fsType = "ext3";
  -          encrypted.enable = true;
  -          encrypted.blkDev = "/dev/vda3";
  -          encrypted.label = "crypt";
  -          encrypted.keyFile = "/mnt-root/keyfile";
  -        };
  -      '';
  -    };
  -
  -
  -  swraid = makeInstallerTest "swraid"
  -    { createPartitions =
  -        ''
  -          $machine->succeed(
  -              "flock /dev/vda parted --script /dev/vda --"
  -              . " mklabel msdos"
  -              . " mkpart primary ext2 1M 100MB" # /boot
  -              . " mkpart extended 100M -1s"
  -              . " mkpart logical 102M 2102M" # md0 (root), first device
  -              . " mkpart logical 2103M 4103M" # md0 (root), second device
  -              . " mkpart logical 4104M 4360M" # md1 (swap), first device
  -              . " mkpart logical 4361M 4617M", # md1 (swap), second device
  -              "udevadm settle",
  -              "ls -l /dev/vda* >&2",
  -              "cat /proc/partitions >&2",
  -              "udevadm control --stop-exec-queue",
  -              "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda5 /dev/vda6",
  -              "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 --raid-devices=2 /dev/vda7 /dev/vda8",
  -              "udevadm control --start-exec-queue",
  -              "udevadm settle",
  -              "mkswap -f /dev/md1 -L swap",
  -              "swapon -L swap",
  -              "mkfs.ext3 -L nixos /dev/md0",
  -              "mount LABEL=nixos /mnt",
  -              "mkfs.ext3 -L boot /dev/vda1",
  -              "mkdir /mnt/boot",
  -              "mount LABEL=boot /mnt/boot",
  -              "udevadm settle",
  -          );
  -        '';
  -      preBootCommands = ''
  -        $machine->start;
  -        $machine->fail("dmesg | grep 'immediate safe mode'");
  -      '';
  -    };
  +          "mkdir -p /mnt/test",
  +      )
  +    '';
  +    extraConfig = ''
  +      fileSystems."/test" = {
  +        device = "/dev/disk/by-label/test";
  +        fsType = "ext3";
  +        encrypted.enable = true;
  +        encrypted.blkDev = "/dev/vda3";
  +        encrypted.label = "crypt";
  +        encrypted.keyFile = "/mnt-root/keyfile";
  +      };
  +    '';
  +  };
  +
  +  swraid = makeInstallerTest "swraid" {
  +    createPartitions = ''
  +      machine.succeed(
  +          "flock /dev/vda parted --script /dev/vda --"
  +          + " mklabel msdos"
  +          + " mkpart primary ext2 1M 100MB"  # /boot
  +          + " mkpart extended 100M -1s"
  +          + " mkpart logical 102M 2102M"  # md0 (root), first device
  +          + " mkpart logical 2103M 4103M"  # md0 (root), second device
  +          + " mkpart logical 4104M 4360M"  # md1 (swap), first device
  +          + " mkpart logical 4361M 4617M",  # md1 (swap), second device
  +          "udevadm settle",
  +          "ls -l /dev/vda* >&2",
  +          "cat /proc/partitions >&2",
  +          "udevadm control --stop-exec-queue",
  +          "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 "
  +          + "--raid-devices=2 /dev/vda5 /dev/vda6",
  +          "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 "
  +          + "--raid-devices=2 /dev/vda7 /dev/vda8",
  +          "udevadm control --start-exec-queue",
  +          "udevadm settle",
  +          "mkswap -f /dev/md1 -L swap",
  +          "swapon -L swap",
  +          "mkfs.ext3 -L nixos /dev/md0",
  +          "mount LABEL=nixos /mnt",
  +          "mkfs.ext3 -L boot /dev/vda1",
  +          "mkdir /mnt/boot",
  +          "mount LABEL=boot /mnt/boot",
  +          "udevadm settle",
  +      )
  +    '';
  +    preBootCommands = ''
  +      machine.start()
  +      machine.fail("dmesg | grep 'immediate safe mode'")
  +    '';
  +  };
   
     # Test a basic install using GRUB 1.
  -  grub1 = makeInstallerTest "grub1"
  -    { createPartitions =
  -        ''
  -          $machine->succeed(
  -              "flock /dev/sda parted --script /dev/sda -- mklabel msdos"
  -              . " mkpart primary linux-swap 1M 1024M"
  -              . " mkpart primary ext2 1024M -1s",
  -              "udevadm settle",
  -              "mkswap /dev/sda1 -L swap",
  -              "swapon -L swap",
  -              "mkfs.ext3 -L nixos /dev/sda2",
  -              "mount LABEL=nixos /mnt",
  -              "mkdir -p /mnt/tmp",
  -          );
  -        '';
  -      grubVersion = 1;
  -      grubDevice = "/dev/sda";
  -    };
  +  grub1 = makeInstallerTest "grub1" {
  +    createPartitions = ''
  +      machine.succeed(
  +          "flock /dev/sda parted --script /dev/sda -- mklabel msdos"
  +          + " mkpart primary linux-swap 1M 1024M"
  +          + " mkpart primary ext2 1024M -1s",
  +          "udevadm settle",
  +          "mkswap /dev/sda1 -L swap",
  +          "swapon -L swap",
  +          "mkfs.ext3 -L nixos /dev/sda2",
  +          "mount LABEL=nixos /mnt",
  +          "mkdir -p /mnt/tmp",
  +      )
  +    '';
  +    grubVersion = 1;
  +    grubDevice = "/dev/sda";
  +  };
   
     # Test using labels to identify volumes in grub
     simpleLabels = makeInstallerTest "simpleLabels" {
       createPartitions = ''
  -      $machine->succeed(
  -        "sgdisk -Z /dev/vda",
  -        "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
  -        "mkswap /dev/vda2 -L swap",
  -        "swapon -L swap",
  -        "mkfs.ext4 -L root /dev/vda3",
  -        "mount LABEL=root /mnt",
  -      );
  +      machine.succeed(
  +          "sgdisk -Z /dev/vda",
  +          "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda",
  +          "mkswap /dev/vda2 -L swap",
  +          "swapon -L swap",
  +          "mkfs.ext4 -L root /dev/vda3",
  +          "mount LABEL=root /mnt",
  +      )
       '';
       grubIdentifier = "label";
     };
  
positive.code:             "mkfs.ext3 -L boot /dev/vda1",
              "mkdir -p /mnt/boot",
              "mount LABEL=boot /mnt/boot",
            );
          '';
          extraConfig = ''
            boot.kernelParams = lib.mkAfter [ "console=tty0" ];
          '';
          enableOCR = true;
          preBootCommands = ''
            $machine->start;
            $machine->waitForText(qr/Passphrase for/);
            $machine->sendChars("supersecret\n");
          '';
        };
  
    # The (almost) simplest partitioning scheme: a swap partition and
    # one big filesystem partition.
    simple-test-config = { createPartitions =
         ''
           $machine->succeed(
               "flock /dev/vda parted --script /dev/vda -- mklabel msdos"
               . " mkpart primary linux-swap 1M 1024M"
               . " mkpart primary ext2 1024M -1s",
               "udevadm settle",
               "mkswap /dev/vda1 -L swap",
               "swapon -L swap",
               "mkfs.ext3 -L nixos /dev/vda2",
               "mount LABEL=nixos /mnt",
           );
         '';
     };
  
    simple-uefi-grub-config =
      { createPartitions =
          ''
            $machine->succeed(
                "flock /dev/vda parted --script /dev/vda -- mklabel gpt"
                . " mkpart ESP fat32 1M 50MiB" # /boot
                . " set 1 boot on"
                . " mkpart primary linux-swap 50MiB 1024MiB"
                . " mkpart primary ext2 1024MiB -1MiB", # /
                "udevadm settle",
                "mkswap /dev/vda2 -L swap",
                "swapon -L swap",
                "mkfs.ext3 -L nixos /dev/vda3",
                "mount LABEL=nixos /mnt",
                "mkfs.vfat -n BOOT /dev/vda1",
                "mkdir -p /mnt/boot",
                "mount LABEL=BOOT /mnt/boot",
            );
          '';
          bootLoader = "grub";
          grubUseEfi = true;
      };
  
    clone-test-extraconfig = { extraConfig =
           ''
           environment.systemPackages = [ pkgs.grub2 ];
           boot.loader.grub.configurationName = "Home";
           nesting.clone = [
           {
             boot.loader.grub.configurationName = lib.mkForce "Work";
  
             environment.etc = {
               "gitconfig".text = "
                 [core]
                   gitproxy = none for work.com
                   ";
             };
           }
           ];
           '';
         testCloneConfig = true;
    };
  
  
  
negative.code:                   , grubIdentifier, preBootCommands, extraConfig
                    , testCloneConfig
                    }:
      let iface = if grubVersion == 1 then "ide" else "virtio";
          isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi);
          bios  = if pkgs.stdenv.isAarch64 then "QEMU_EFI.fd" else "OVMF.fd";
      in if !isEfi && !(pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then
        throw "Non-EFI boot methods are only supported on i686 / x86_64"
      else ''
        def assemble_qemu_flags():
            flags = "-cpu host"
            ${if system == "x86_64-linux"
              then ''flags += " -m 768"''
              else ''flags += " -m 512 -enable-kvm -machine virt,gic-version=host"''
            }
            return flags
  
  
        qemu_flags = {"qemuFlags": assemble_qemu_flags()}
  
        hd_flags = {
            "hdaInterface": "${iface}",
            "hda": "vm-state-machine/machine.qcow2",
        }
        ${optionalString isEfi ''
          hd_flags.update(
              bios="${pkgs.OVMF.fd}/FV/${bios}"
          )''
        }
        default_flags = {**hd_flags, **qemu_flags}
  
  
        def create_machine_named(name):
            return create_machine({**default_flags, "name": "boot-after-install"})
  
  
        machine.start()
  
        with subtest("Assert readiness of login prompt"):
            machine.succeed("echo hello")
            machine.wait_for_unit("nixos-manual")
  
        with subtest("Wait for hard disks to appear in /dev"):
            machine.succeed("udevadm settle")
  
        ${createPartitions}
  
        with subtest("Create the NixOS configuration"):
            machine.succeed("nixos-generate-config --root /mnt")
            machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2")
            machine.copy_from_host(
                "${ makeConfig {
                      inherit bootLoader grubVersion grubDevice grubIdentifier
                              grubUseEfi extraConfig;
                    }
                }",
                "/mnt/etc/nixos/configuration.nix",
            )
  
        with subtest("Perform the installation"):
            machine.succeed("nixos-install < /dev/null >&2")
  
        with subtest("Do it again to make sure it's idempotent"):
            machine.succeed("nixos-install < /dev/null >&2")
  
        with subtest("Shutdown system after installation"):
            machine.succeed("umount /mnt/boot || true")
            machine.succeed("umount /mnt")
            machine.succeed("sync")
            machine.shutdown()
  
        # Now see if we can boot the installation.
        machine = create_machine_named("boot-after-install")
  
        # For example to enter LUKS passphrase.
        ${preBootCommands}
  
        with subtest("Assert that /boot get mounted"):
            machine.wait_for_unit("local-fs.target")
            ${if bootLoader == "grub"
                then ''machine.succeed("test -e /boot/grub")''
                else ''machine.succeed("test -e /boot/loader/loader.conf")''
            }
  
        with subtest("Check whether /root has correct permissions"):
            assert "700" in machine.succeed("stat -c '%a' /root")
  
        with subtest("Assert swap device got activated"):
            # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved
            machine.wait_for_unit("swap.target")
            machine.succeed("cat /proc/swaps | grep -q /dev")
  
        with subtest("Check that the store is in good shape"):
            machine.succeed("nix-store --verify --check-contents >&2")
  
        with subtest("Check whether the channel works"):
            machine.succeed("nix-env -iA nixos.procps >&2")
            assert ".nix-profile" in machine.succeed("type -tP ps | tee /dev/stderr")
  
        with subtest(
            "Check that the daemon works, and that non-root users can run builds "
            "(this will build a new profile generation through the daemon)"
        ):
            machine.succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2")
  
        with subtest("Configure system with writable Nix store on next boot"):
            # we're not using copy_from_host here because the installer image
            # doesn't know about the host-guest sharing mechanism.
            machine.copy_from_host_via_shell(
                "${ makeConfig {
                      inherit bootLoader grubVersion grubDevice grubIdentifier
                              grubUseEfi extraConfig;
                      forceGrubReinstallCount = 1;
                    }
                }",
                "/etc/nixos/configuration.nix",
            )
  
        with subtest("Check whether nixos-rebuild works"):
            machine.succeed("nixos-rebuild switch >&2")
  
        with subtest("Test nixos-option"):
            kernel_modules = machine.succeed("nixos-option boot.initrd.kernelModules")
            assert "virtio_console" in kernel_modules
            assert "List of modules" in kernel_modules
            assert "qemu-guest.nix" in kernel_modules
  
        machine.shutdown()
  
        # Check whether a writable store build works
        machine = create_machine_named("rebuild-switch")
        ${preBootCommands}
        machine.wait_for_unit("multi-user.target")
  
        # we're not using copy_from_host here because the installer image
        # doesn't know about the host-guest sharing mechanism.
        machine.copy_from_host_via_shell(
            "${ makeConfig {
                  inherit bootLoader grubVersion grubDevice grubIdentifier
                  grubUseEfi extraConfig;
                  forceGrubReinstallCount = 2;
                }
            }",
            "/etc/nixos/configuration.nix",
        )
        machine.succeed("nixos-rebuild boot >&2")
        machine.shutdown()
  
        # And just to be sure, check that the machine still boots after
        # "nixos-rebuild switch".
        machine = create_machine_named("boot-after-rebuild-switch")
        ${preBootCommands}
        machine.wait_for_unit("network.target")
        machine.shutdown()
  
        # Tests for validating clone configuration entries in grub menu
      ''
      + optionalString testCloneConfig ''
        # Reboot Machine
        machine = create_machine_named("clone-default-config")
        ${preBootCommands}
        machine.wait_for_unit("multi-user.target")
  
        with subtest("Booted configuration name should be 'Home'"):
            # This is not the name that shows in the grub menu.
            # The default configuration is always shown as "Default"
            machine.succeed("cat /run/booted-system/configuration-name >&2")
            assert "Home" in machine.succeed("cat /run/booted-system/configuration-name")
  
        with subtest("We should **not** find a file named /etc/gitconfig"):
            machine.fail("test -e /etc/gitconfig")
  
        with subtest("Set grub to boot the second configuration"):
            machine.succeed("grub-reboot 1")
  
        machine.shutdown()
  
        # Reboot Machine
        machine = create_machine_named("clone-alternate-config")
        ${preBootCommands}
  
        machine.wait_for_unit("multi-user.target")
        with subtest("Booted configuration name should be Work"):
            machine.succeed("cat /run/booted-system/configuration-name >&2")
            assert "Work" in machine.succeed("cat /run/booted-system/configuration-name")
  
        with subtest("We should find a file named /etc/gitconfig"):
            machine.succeed("test -e /etc/gitconfig")
  
        machine.shutdown()
      '';
  
  
  