add diskco pkg
This commit is contained in:
16
pkgs/disko/tests/bcachefs.nix
Normal file
16
pkgs/disko/tests/bcachefs.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "bcachefs";
|
||||
disko-config = ../example/bcachefs.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("lsblk >&2");
|
||||
'';
|
||||
# so that the installer boots with a bcachefs enabled kernel
|
||||
extraInstallerConfig = {
|
||||
boot.supportedFilesystems = [ "bcachefs" ];
|
||||
};
|
||||
}
|
||||
16
pkgs/disko/tests/boot-raid1.nix
Normal file
16
pkgs/disko/tests/boot-raid1.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "boot-raid1";
|
||||
disko-config = ../example/boot-raid1.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/boot");
|
||||
machine.succeed("mountpoint /boot");
|
||||
'';
|
||||
extraSystemConfig = {
|
||||
# sadly systemd-boot fails to install to a raid /boot device
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
};
|
||||
}
|
||||
11
pkgs/disko/tests/btrfs-only-root-subvolume.nix
Normal file
11
pkgs/disko/tests/btrfs-only-root-subvolume.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "btrfs-only-root-subvolume";
|
||||
disko-config = ../example/btrfs-only-root-subvolume.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("btrfs subvolume list /");
|
||||
'';
|
||||
}
|
||||
20
pkgs/disko/tests/btrfs-subvolumes.nix
Normal file
20
pkgs/disko/tests/btrfs-subvolumes.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "btrfs-subvolumes";
|
||||
disko-config = ../example/btrfs-subvolumes.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test ! -e /test");
|
||||
machine.succeed("test -e /home/user");
|
||||
machine.succeed("btrfs subvolume list / | grep -qs 'path test$'");
|
||||
machine.succeed("btrfs subvolume list / | grep -qs 'path nix$'");
|
||||
machine.succeed("btrfs subvolume list / | grep -qs 'path home$'");
|
||||
machine.succeed("test -e /.swapvol/swapfile");
|
||||
machine.succeed("test -e /.swapvol/rel-path");
|
||||
machine.succeed("test -e /partition-root/swapfile");
|
||||
machine.succeed("test -e /partition-root/swapfile1");
|
||||
'';
|
||||
}
|
||||
|
||||
34
pkgs/disko/tests/cli.nix
Normal file
34
pkgs/disko/tests/cli.nix
Normal file
@@ -0,0 +1,34 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "cli";
|
||||
disko-config = ../example/complex.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig = {
|
||||
networking.hostId = "8425e349";
|
||||
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
fileSystems."/zfs_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
};
|
||||
testMode = "direct";
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid1p1");
|
||||
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
machine.succeed("mountpoint /zfs_legacy_fs");
|
||||
machine.succeed("mountpoint /ext4onzfs");
|
||||
machine.succeed("mountpoint /ext4_on_lvm");
|
||||
'';
|
||||
extraSystemConfig = {
|
||||
imports = [
|
||||
../module.nix
|
||||
];
|
||||
};
|
||||
extraInstallerConfig = {
|
||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
||||
imports = [
|
||||
../module.nix
|
||||
];
|
||||
};
|
||||
}
|
||||
29
pkgs/disko/tests/complex.nix
Normal file
29
pkgs/disko/tests/complex.nix
Normal file
@@ -0,0 +1,29 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "complex";
|
||||
disko-config = ../example/complex.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig = {
|
||||
networking.hostId = "8425e349";
|
||||
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
fileSystems."/zfs_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
};
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid1p1");
|
||||
|
||||
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
machine.succeed("mountpoint /zfs_legacy_fs");
|
||||
machine.succeed("mountpoint /ext4onzfs");
|
||||
machine.succeed("mountpoint /ext4_on_lvm");
|
||||
|
||||
|
||||
machine.succeed("test -e /ext4_on_lvm/file-from-postMountHook");
|
||||
'';
|
||||
extraInstallerConfig = {
|
||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
||||
};
|
||||
}
|
||||
20
pkgs/disko/tests/default.nix
Normal file
20
pkgs/disko/tests/default.nix
Normal file
@@ -0,0 +1,20 @@
|
||||
{ makeTest ? import <nixpkgs/nixos/tests/make-test-python.nix>
|
||||
, eval-config ? import <nixpkgs/nixos/lib/eval-config.nix>
|
||||
, pkgs ? import <nixpkgs> { }
|
||||
}:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
diskoLib = import ../lib { inherit lib makeTest eval-config; };
|
||||
|
||||
allTestFilenames =
|
||||
builtins.map (lib.removeSuffix ".nix") (
|
||||
builtins.filter
|
||||
(x: lib.hasSuffix ".nix" x && x != "default.nix")
|
||||
(lib.attrNames (builtins.readDir ./.))
|
||||
);
|
||||
incompatibleTests = lib.optionals pkgs.stdenv.buildPlatform.isRiscV64 [ "zfs" "zfs-over-legacy" "cli" "module" "complex" ];
|
||||
allCompatibleFilenames = lib.subtractLists incompatibleTests allTestFilenames;
|
||||
|
||||
allTests = lib.genAttrs allCompatibleFilenames (test: import (./. + "/${test}.nix") { inherit diskoLib pkgs; });
|
||||
in
|
||||
allTests
|
||||
23
pkgs/disko/tests/disko-install/configuration.nix
Normal file
23
pkgs/disko/tests/disko-install/configuration.nix
Normal file
@@ -0,0 +1,23 @@
|
||||
{ lib, pkgs, modulesPath, ... }: {
|
||||
imports = [
|
||||
(modulesPath + "/testing/test-instrumentation.nix")
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
(modulesPath + "/profiles/minimal.nix")
|
||||
];
|
||||
|
||||
networking.hostName = "disko-machine";
|
||||
|
||||
# do not try to fetch stuff from the internet
|
||||
nix.settings = {
|
||||
substituters = lib.mkForce [ ];
|
||||
hashed-mirrors = null;
|
||||
connect-timeout = 3;
|
||||
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
};
|
||||
services.openssh.enable = true;
|
||||
boot.kernelParams = [ "console=tty0" ] ++
|
||||
(lib.optional (pkgs.stdenv.hostPlatform.isAarch) "ttyAMA0,115200") ++
|
||||
(lib.optional (pkgs.stdenv.hostPlatform.isRiscV64) "ttySIF0,115200") ++
|
||||
[ "console=ttyS0,115200" ];
|
||||
}
|
||||
66
pkgs/disko/tests/disko-install/default.nix
Normal file
66
pkgs/disko/tests/disko-install/default.nix
Normal file
@@ -0,0 +1,66 @@
|
||||
{ pkgs ? import <nixpkgs> { }, self, diskoVersion }:
|
||||
let
|
||||
disko = pkgs.callPackage ../../package.nix { inherit diskoVersion; };
|
||||
|
||||
dependencies = [
|
||||
self.nixosConfigurations.testmachine.pkgs.stdenv.drvPath
|
||||
(self.nixosConfigurations.testmachine.pkgs.closureInfo { rootPaths = [ ]; }).drvPath
|
||||
|
||||
# https://github.com/NixOS/nixpkgs/blob/f2fd33a198a58c4f3d53213f01432e4d88474956/nixos/modules/system/activation/top-level.nix#L342
|
||||
self.nixosConfigurations.testmachine.pkgs.perlPackages.ConfigIniFiles
|
||||
self.nixosConfigurations.testmachine.pkgs.perlPackages.FileSlurp
|
||||
|
||||
self.nixosConfigurations.testmachine.config.system.build.toplevel
|
||||
self.nixosConfigurations.testmachine.config.system.build.diskoScript
|
||||
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
|
||||
|
||||
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
|
||||
in
|
||||
pkgs.nixosTest {
|
||||
name = "disko-test";
|
||||
nodes.machine = {
|
||||
virtualisation.emptyDiskImages = [ 4096 ];
|
||||
virtualisation.memorySize = 3000;
|
||||
environment.etc."install-closure".source = "${closureInfo}/store-paths";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def create_test_machine(
|
||||
oldmachine=None, **kwargs
|
||||
): # taken from <nixpkgs/nixos/tests/installer.nix>
|
||||
start_command = [
|
||||
"${pkgs.qemu_test}/bin/qemu-kvm",
|
||||
"-cpu",
|
||||
"max",
|
||||
"-m",
|
||||
"1024",
|
||||
"-virtfs",
|
||||
"local,path=/nix/store,security_model=none,mount_tag=nix-store",
|
||||
"-drive",
|
||||
f"file={oldmachine.state_dir}/empty0.qcow2,id=drive1,if=none,index=1,werror=report",
|
||||
"-device",
|
||||
"virtio-blk-pci,drive=drive1",
|
||||
]
|
||||
machine = create_machine(start_command=" ".join(start_command), **kwargs)
|
||||
driver.machines.append(machine)
|
||||
return machine
|
||||
machine.succeed("lsblk >&2")
|
||||
|
||||
print(machine.succeed("tty"))
|
||||
machine.succeed("umask 066; echo > /tmp/age.key")
|
||||
permission = machine.succeed("stat -c %a /tmp/age.key").strip()
|
||||
assert permission == "600", f"expected permission 600 on /tmp/age.key, got {permission}"
|
||||
|
||||
machine.succeed("${disko}/bin/disko-install --disk main /dev/vdb --extra-files /tmp/age.key /var/lib/secrets/age.key --flake ${../..}#testmachine")
|
||||
# test idempotency
|
||||
machine.succeed("${disko}/bin/disko-install --mode mount --disk main /dev/vdb --flake ${../..}#testmachine")
|
||||
machine.shutdown()
|
||||
|
||||
new_machine = create_test_machine(oldmachine=machine, name="after_install")
|
||||
new_machine.start()
|
||||
name = new_machine.succeed("hostname").strip()
|
||||
assert name == "disko-machine", f"expected hostname 'disko-machine', got {name}"
|
||||
permission = new_machine.succeed("stat -c %a /var/lib/secrets/age.key").strip()
|
||||
assert permission == "600", f"expected permission 600 on /var/lib/secrets/age.key, got {permission}"
|
||||
'';
|
||||
}
|
||||
16
pkgs/disko/tests/f2fs.nix
Normal file
16
pkgs/disko/tests/f2fs.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "f2fs";
|
||||
disko-config = ../example/f2fs.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("lsblk --fs >&2");
|
||||
'';
|
||||
# so that the installer boots with a f2fs enabled kernel
|
||||
extraInstallerConfig = {
|
||||
boot.supportedFilesystems = [ "f2fs" ];
|
||||
};
|
||||
}
|
||||
12
pkgs/disko/tests/gpt-bios-compat.nix
Normal file
12
pkgs/disko/tests/gpt-bios-compat.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "gpt-bios-compat";
|
||||
disko-config = ../example/gpt-bios-compat.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
efi = false;
|
||||
}
|
||||
13
pkgs/disko/tests/gpt-name-with-special-chars.nix
Normal file
13
pkgs/disko/tests/gpt-name-with-special-chars.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "gpt-name-with-whitespace";
|
||||
disko-config = ../example/gpt-name-with-whitespace.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("mountpoint '/name with spaces'");
|
||||
machine.succeed("mountpoint '/name^with\\some@special#chars'");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/gpt-unformatted.nix
Normal file
11
pkgs/disko/tests/gpt-unformatted.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "gpt-unformatted";
|
||||
disko-config = ../example/gpt-unformatted.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/hybrid-mbr.nix
Normal file
11
pkgs/disko/tests/hybrid-mbr.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "hybrid-mbr";
|
||||
disko-config = ../example/hybrid-mbr.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
12
pkgs/disko/tests/hybrid-tmpfs-on-root.nix
Normal file
12
pkgs/disko/tests/hybrid-tmpfs-on-root.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "hybrid-tmpfs-on-root";
|
||||
disko-config = ../example/hybrid-tmpfs-on-root.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("findmnt / --types tmpfs");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/hybrid.nix
Normal file
11
pkgs/disko/tests/hybrid.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "hybrid";
|
||||
disko-config = ../example/hybrid.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
12
pkgs/disko/tests/legacy-table-with-whitespace.nix
Normal file
12
pkgs/disko/tests/legacy-table-with-whitespace.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "legacy-table-with-whitespace";
|
||||
disko-config = ../example/legacy-table-with-whitespace.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("mountpoint /name_with_spaces");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/legacy-table.nix
Normal file
11
pkgs/disko/tests/legacy-table.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "legacy-table";
|
||||
disko-config = ../example/legacy-table.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/long-device-name.nix
Normal file
11
pkgs/disko/tests/long-device-name.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "long-device-name";
|
||||
disko-config = ../example/long-device-name.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
14
pkgs/disko/tests/luks-btrfs-raid.nix
Normal file
14
pkgs/disko/tests/luks-btrfs-raid.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
diskoLib ? pkgs.callPackage ../lib { },
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "luks-btrfs-raid";
|
||||
disko-config = ../example/luks-btrfs-raid.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("cryptsetup isLuks /dev/vda2");
|
||||
machine.succeed("cryptsetup isLuks /dev/vdb1");
|
||||
machine.succeed("btrfs subvolume list /");
|
||||
'';
|
||||
}
|
||||
14
pkgs/disko/tests/luks-btrfs-subvolumes.nix
Normal file
14
pkgs/disko/tests/luks-btrfs-subvolumes.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "luks-btrfs-subvolumes";
|
||||
disko-config = ../example/luks-btrfs-subvolumes.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("cryptsetup isLuks /dev/vda2");
|
||||
machine.succeed("btrfs subvolume list / | grep -qs 'path nix$'");
|
||||
machine.succeed("btrfs subvolume list / | grep -qs 'path home$'");
|
||||
machine.succeed("test -e /.swapvol/swapfile");
|
||||
'';
|
||||
}
|
||||
17
pkgs/disko/tests/luks-interactive-login.nix
Normal file
17
pkgs/disko/tests/luks-interactive-login.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> { },
|
||||
diskoLib ? pkgs.callPackage ../lib { },
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "luks-interactive-login";
|
||||
disko-config = ../example/luks-interactive-login.nix;
|
||||
enableOCR = true;
|
||||
extraTestScript = ''
|
||||
machine.succeed("cryptsetup isLuks /dev/vda2");
|
||||
'';
|
||||
bootCommands = ''
|
||||
machine.wait_for_text("[Pp]assphrase for")
|
||||
machine.send_chars("secretsecret\n")
|
||||
'';
|
||||
}
|
||||
12
pkgs/disko/tests/luks-lvm.nix
Normal file
12
pkgs/disko/tests/luks-lvm.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "luks-lvm";
|
||||
disko-config = ../example/luks-lvm.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("cryptsetup isLuks /dev/vda2");
|
||||
machine.succeed("mountpoint /home");
|
||||
'';
|
||||
}
|
||||
16
pkgs/disko/tests/luks-on-mdadm.nix
Normal file
16
pkgs/disko/tests/luks-on-mdadm.nix
Normal file
@@ -0,0 +1,16 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "luks-on-mdadm";
|
||||
disko-config = ../example/luks-on-mdadm.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid1");
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
extraSystemConfig = {
|
||||
# sadly systemd-boot fails to install to a raid /boot device
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
};
|
||||
}
|
||||
18
pkgs/disko/tests/lvm-raid.nix
Normal file
18
pkgs/disko/tests/lvm-raid.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "lvm-raid";
|
||||
disko-config = ../example/lvm-raid.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /home");
|
||||
'';
|
||||
extraInstallerConfig = {
|
||||
boot.kernelModules = [ "dm-raid" "raid0" "dm-mirror" ];
|
||||
};
|
||||
extraSystemConfig = {
|
||||
# sadly systemd-boot fails to install to a raid /boot device
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
};
|
||||
}
|
||||
11
pkgs/disko/tests/lvm-sizes-sort.nix
Normal file
11
pkgs/disko/tests/lvm-sizes-sort.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "lvm-sizes-sort";
|
||||
disko-config = ../example/lvm-sizes-sort.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /home");
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/lvm-thin.nix
Normal file
11
pkgs/disko/tests/lvm-thin.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "lvm-thin";
|
||||
disko-config = ../example/lvm-thin.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /home");
|
||||
'';
|
||||
}
|
||||
13
pkgs/disko/tests/make-disk-image-impure.nix
Normal file
13
pkgs/disko/tests/make-disk-image-impure.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, ...
|
||||
}:
|
||||
|
||||
(pkgs.nixos [
|
||||
../module.nix
|
||||
../example/simple-efi.nix
|
||||
({ config, ... }: {
|
||||
documentation.enable = false;
|
||||
system.stateVersion = config.system.nixos.version;
|
||||
disko.checkScripts = true;
|
||||
})
|
||||
]).config.system.build.diskoImagesScript
|
||||
14
pkgs/disko/tests/make-disk-image.nix
Normal file
14
pkgs/disko/tests/make-disk-image.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, ...
|
||||
}:
|
||||
|
||||
(pkgs.nixos [
|
||||
../module.nix
|
||||
../example/simple-efi.nix
|
||||
({ config, ... }: {
|
||||
documentation.enable = false;
|
||||
system.stateVersion = config.system.nixos.version;
|
||||
disko.memSize = 2048;
|
||||
disko.checkScripts = true;
|
||||
})
|
||||
]).config.system.build.diskoImages
|
||||
13
pkgs/disko/tests/mdadm-raid0.nix
Normal file
13
pkgs/disko/tests/mdadm-raid0.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "mdadm-raid0";
|
||||
disko-config = ../example/mdadm-raid0.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid0");
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
efi = false;
|
||||
}
|
||||
13
pkgs/disko/tests/mdadm.nix
Normal file
13
pkgs/disko/tests/mdadm.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "mdadm";
|
||||
disko-config = ../example/mdadm.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid1");
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
efi = false;
|
||||
}
|
||||
26
pkgs/disko/tests/module.nix
Normal file
26
pkgs/disko/tests/module.nix
Normal file
@@ -0,0 +1,26 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "module";
|
||||
disko-config = ../example/complex.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig = {
|
||||
networking.hostId = "8425e349";
|
||||
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
};
|
||||
testMode = "module";
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/md/raid1p1");
|
||||
|
||||
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
machine.succeed("mountpoint /zfs_legacy_fs");
|
||||
machine.succeed("mountpoint /ext4onzfs");
|
||||
machine.succeed("mountpoint /ext4_on_lvm");
|
||||
'';
|
||||
extraInstallerConfig = {
|
||||
boot.kernelModules = [ "dm-raid" "dm-mirror" ];
|
||||
};
|
||||
}
|
||||
14
pkgs/disko/tests/multi-device-no-deps.nix
Normal file
14
pkgs/disko/tests/multi-device-no-deps.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "multi-device-no-deps";
|
||||
disko-config = ../example/multi-device-no-deps.nix;
|
||||
testBoot = false;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /mnt/a");
|
||||
machine.succeed("mountpoint /mnt/b");
|
||||
'';
|
||||
}
|
||||
13
pkgs/disko/tests/negative-size.nix
Normal file
13
pkgs/disko/tests/negative-size.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
# this is a regression test for https://github.com/nix-community/disko/issues/52
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "negative-size";
|
||||
disko-config = ../example/negative-size.nix;
|
||||
testBoot = false;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /mnt");
|
||||
'';
|
||||
}
|
||||
48
pkgs/disko/tests/non-root-zfs.nix
Normal file
48
pkgs/disko/tests/non-root-zfs.nix
Normal file
@@ -0,0 +1,48 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "non-root-zfs";
|
||||
disko-config = ../example/non-root-zfs.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig.networking.hostId = "8425e349";
|
||||
postDisko = ''
|
||||
machine.succeed("mountpoint /mnt/storage")
|
||||
machine.succeed("mountpoint /mnt/storage/dataset")
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /mnt/storage")[1].rstrip()
|
||||
print(f"/mnt/storage {filesystem=}")
|
||||
assert filesystem == "zfs", "/mnt/storage is not ZFS"
|
||||
|
||||
machine.fail("mountpoint /mnt/storage2")
|
||||
machine.succeed("mountpoint /mnt/storage2/dataset")
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /mnt/storage2")[1].rstrip()
|
||||
print(f"/mnt/storage2 {filesystem=}")
|
||||
assert filesystem != "zfs", "/mnt/storage should not be ZFS"
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /mnt/storage2/dataset")[1].rstrip()
|
||||
print(f"/mnt/storage2/dataset {filesystem=}")
|
||||
assert filesystem == "zfs", "/mnt/storage/dataset is not ZFS"
|
||||
'';
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /storage")
|
||||
machine.succeed("mountpoint /storage/dataset")
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /storage")[1].rstrip()
|
||||
print(f"/storage {filesystem=}")
|
||||
assert filesystem == "zfs", "/storage is not ZFS"
|
||||
|
||||
machine.fail("mountpoint /storage2")
|
||||
machine.succeed("mountpoint /storage2/dataset")
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /storage2")[1].rstrip()
|
||||
print(f"/storage2 {filesystem=}")
|
||||
assert filesystem != "zfs", "/storage should not be ZFS"
|
||||
|
||||
filesystem = machine.execute("stat --file-system --format=%T /storage2/dataset")[1].rstrip()
|
||||
print(f"/storage2/dataset {filesystem=}")
|
||||
assert filesystem == "zfs", "/storage/dataset is not ZFS"
|
||||
'';
|
||||
}
|
||||
11
pkgs/disko/tests/simple-efi.nix
Normal file
11
pkgs/disko/tests/simple-efi.nix
Normal file
@@ -0,0 +1,11 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "simple-efi";
|
||||
disko-config = ../example/simple-efi.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
}
|
||||
5
pkgs/disko/tests/standalone.nix
Normal file
5
pkgs/disko/tests/standalone.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{ pkgs ? import <nixpkgs> { }, ... }:
|
||||
(pkgs.nixos [
|
||||
../example/stand-alone/configuration.nix
|
||||
{ documentation.enable = false; }
|
||||
]).config.system.build.toplevel
|
||||
31
pkgs/disko/tests/swap.nix
Normal file
31
pkgs/disko/tests/swap.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "swap";
|
||||
disko-config = ../example/swap.nix;
|
||||
extraTestScript = ''
|
||||
import json
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("swapon --show >&2");
|
||||
machine.succeed("lsblk -o +PARTTYPENAME --json /dev/vda >&2");
|
||||
out = json.loads(machine.succeed("lsblk -o +PARTTYPENAME --json /dev/vda"))
|
||||
|
||||
encrypted_swap_crypt = out["blockdevices"][0]["children"][1]
|
||||
mnt_point = encrypted_swap_crypt["children"][0]["mountpoints"][0]
|
||||
assert mnt_point == "[SWAP]", f"Expected encrypted swap partition to be mounted as [SWAP], got {mnt_point}"
|
||||
part_type = encrypted_swap_crypt["parttypename"]
|
||||
# The dm-crypt partition should be labelled as swap, not dm-crypt, see https://github.com/util-linux/util-linux/issues/3238
|
||||
assert part_type == "Linux swap", f"Expected encrypted swap container to be of type Linux swap, got {part_type}"
|
||||
|
||||
plain_swap_part = out["blockdevices"][0]["children"][3]
|
||||
mnt_point = plain_swap_part["mountpoints"][0]
|
||||
assert mnt_point == "[SWAP]", f"Expected swap partition to be mounted as [SWAP], got {mnt_point}"
|
||||
part_type = plain_swap_part["parttypename"]
|
||||
assert part_type == "Linux swap", f"Expected plain swap partition to be of type Linux swap, got {part_type}"
|
||||
'';
|
||||
extraSystemConfig = {
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
};
|
||||
}
|
||||
12
pkgs/disko/tests/tmpfs.nix
Normal file
12
pkgs/disko/tests/tmpfs.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "tmpfs";
|
||||
disko-config = ../example/tmpfs.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
machine.succeed("mountpoint /tmp");
|
||||
'';
|
||||
}
|
||||
12
pkgs/disko/tests/with-lib.nix
Normal file
12
pkgs/disko/tests/with-lib.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "with-lib";
|
||||
disko-config = ../example/with-lib.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
'';
|
||||
efi = false;
|
||||
}
|
||||
13
pkgs/disko/tests/xfs.nix
Normal file
13
pkgs/disko/tests/xfs.nix
Normal file
@@ -0,0 +1,13 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "xfs";
|
||||
disko-config = ../example/xfs-with-quota.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("mountpoint /");
|
||||
|
||||
machine.succeed("xfs_quota -c 'print' / | grep -q '(pquota)'")
|
||||
'';
|
||||
}
|
||||
15
pkgs/disko/tests/zfs-over-legacy.nix
Normal file
15
pkgs/disko/tests/zfs-over-legacy.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "zfs-over-legacy";
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig.networking.hostId = "8425e349";
|
||||
disko-config = ../example/zfs-over-legacy.nix;
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -e /zfs_fs");
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
'';
|
||||
}
|
||||
|
||||
77
pkgs/disko/tests/zfs-with-vdevs.nix
Normal file
77
pkgs/disko/tests/zfs-with-vdevs.nix
Normal file
@@ -0,0 +1,77 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "zfs-with-vdevs";
|
||||
disko-config = ../example/zfs-with-vdevs.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig = {
|
||||
networking.hostId = "8425e349";
|
||||
# It looks like the 60s of NixOS is sometimes not enough for our virtio-based zpool.
|
||||
# This fixes the flakeiness of the test.
|
||||
boot.initrd.postResumeCommands = ''
|
||||
for i in $(seq 1 120); do
|
||||
if zpool list | grep -q zroot || zpool import -N zroot; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
'';
|
||||
};
|
||||
extraTestScript = ''
|
||||
def assert_property(ds, property, expected_value):
|
||||
out = machine.succeed(f"zfs get -H {property} {ds} -o value").rstrip()
|
||||
assert (
|
||||
out == expected_value
|
||||
), f"Expected {property}={expected_value} on {ds}, got: {out}"
|
||||
|
||||
# These fields are 0 if l2arc is disabled
|
||||
assert (
|
||||
machine.succeed(
|
||||
"cat /proc/spl/kstat/zfs/arcstats"
|
||||
" | grep '^l2_' | tr -s ' '"
|
||||
" | cut -s -d ' ' -f3 | uniq"
|
||||
).strip() != "0"
|
||||
), "Excepted cache to be utilized."
|
||||
|
||||
assert_property("zroot", "compression", "zstd")
|
||||
assert_property("zroot/zfs_fs", "com.sun:auto-snapshot", "true")
|
||||
assert_property("zroot/zfs_fs", "compression", "zstd")
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
|
||||
# Take the status output and flatten it so that each device is on a single line prefixed with with the group (either
|
||||
# the pool name or a designation like log/cache/spare/dedup/special) and first portion of the vdev name (empty for a
|
||||
# disk from a single vdev, mirror for devices in a mirror. This makes it easy to verify that the layout is as
|
||||
# expected.
|
||||
group = ""
|
||||
vdev = ""
|
||||
actual = []
|
||||
for line in machine.succeed("zpool status -P zroot").split("\n"):
|
||||
first_word = line.strip().split(" ", 1)[0]
|
||||
if line.startswith("\t ") and first_word.startswith("/"):
|
||||
actual.append(f"{group}{vdev}{first_word}")
|
||||
elif line.startswith("\t "):
|
||||
vdev = f"{first_word.split('-', 1)[0]} "
|
||||
elif line.startswith("\t"):
|
||||
group = f"{first_word} "
|
||||
vdev = ""
|
||||
actual.sort()
|
||||
expected=sorted([
|
||||
'zroot /dev/disk/by-partlabel/disk-data1-zfs',
|
||||
'zroot mirror /dev/disk/by-partlabel/disk-data2-zfs',
|
||||
'zroot mirror /dev/disk/by-partlabel/disk-data3-zfs',
|
||||
'dedup /dev/disk/by-partlabel/disk-dedup3-zfs',
|
||||
'dedup mirror /dev/disk/by-partlabel/disk-dedup1-zfs',
|
||||
'dedup mirror /dev/disk/by-partlabel/disk-dedup2-zfs',
|
||||
'special /dev/disk/by-partlabel/disk-special3-zfs',
|
||||
'special mirror /dev/disk/by-partlabel/disk-special1-zfs',
|
||||
'special mirror /dev/disk/by-partlabel/disk-special2-zfs',
|
||||
'logs /dev/disk/by-partlabel/disk-log3-zfs',
|
||||
'logs mirror /dev/disk/by-partlabel/disk-log1-zfs',
|
||||
'logs mirror /dev/disk/by-partlabel/disk-log2-zfs',
|
||||
'cache /dev/disk/by-partlabel/disk-cache-zfs',
|
||||
'spares /dev/disk/by-partlabel/disk-spare-zfs',
|
||||
])
|
||||
assert actual == expected, f"Incorrect pool layout. Expected:\n\t{'\n\t'.join(expected)}\nActual:\n\t{'\n\t'.join(actual)}"
|
||||
'';
|
||||
}
|
||||
41
pkgs/disko/tests/zfs.nix
Normal file
41
pkgs/disko/tests/zfs.nix
Normal file
@@ -0,0 +1,41 @@
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, diskoLib ? pkgs.callPackage ../lib { }
|
||||
}:
|
||||
diskoLib.testLib.makeDiskoTest {
|
||||
inherit pkgs;
|
||||
name = "zfs";
|
||||
disko-config = ../example/zfs.nix;
|
||||
extraInstallerConfig.networking.hostId = "8425e349";
|
||||
extraSystemConfig = {
|
||||
networking.hostId = "8425e349";
|
||||
fileSystems."/zfs_legacy_fs".options = [ "nofail" ]; # TODO find out why we need this!
|
||||
};
|
||||
extraTestScript = ''
|
||||
machine.succeed("test -b /dev/zvol/zroot/zfs_volume");
|
||||
machine.succeed("test -b /dev/zvol/zroot/zfs_encryptedvolume");
|
||||
|
||||
def assert_property(ds, property, expected_value):
|
||||
out = machine.succeed(f"zfs get -H {property} {ds} -o value").rstrip()
|
||||
assert (
|
||||
out == expected_value
|
||||
), f"Expected {property}={expected_value} on {ds}, got: {out}"
|
||||
|
||||
assert_property("zroot", "compression", "zstd")
|
||||
assert_property("zroot/zfs_fs", "compression", "zstd")
|
||||
assert_property("zroot", "com.sun:auto-snapshot", "false")
|
||||
assert_property("zroot/zfs_fs", "com.sun:auto-snapshot", "true")
|
||||
assert_property("zroot/zfs_volume", "volsize", "10M")
|
||||
assert_property("zroot/zfs_encryptedvolume", "volsize", "10M")
|
||||
assert_property("zroot/zfs_unmounted_fs", "mountpoint", "none")
|
||||
|
||||
machine.succeed("zfs get name zroot@blank")
|
||||
|
||||
machine.succeed("mountpoint /zfs_fs");
|
||||
machine.succeed("mountpoint /zfs_legacy_fs");
|
||||
machine.succeed("mountpoint /ext4onzfs");
|
||||
machine.succeed("mountpoint /ext4onzfsencrypted");
|
||||
machine.succeed("mountpoint /zfs_crypted");
|
||||
machine.succeed("zfs get keystatus zroot/encrypted");
|
||||
machine.succeed("zfs get keystatus zroot/encrypted/test");
|
||||
'';
|
||||
}
|
||||
Reference in New Issue
Block a user