Convert VM tests to Python

Perl-based tests are deprecated since NixOS 20.03 and subsequently got
removed in NixOS 20.09, which effectively means that tests are going to
fail as soon as we build it with NixOS 20.09 or anything newer.

I've put "# fmt: off" at the start of every testScript, because
formatting with Black really messes up indentation and I don't think it
really adds anything in value or readability for inlined Python scripts.

Signed-off-by: aszlig <aszlig@nix.build>
This commit is contained in:
aszlig 2020-10-17 22:08:18 +02:00
parent 2a37c35650
commit 5cfdf16dd6
No known key found for this signature in database
GPG key ID: 684089CE67EBB691
4 changed files with 178 additions and 155 deletions

View file

@ -1,6 +1,6 @@
{ nixpkgs, system, overlay }:
with import (nixpkgs + "/nixos/lib/testing.nix") {
with import (nixpkgs + "/nixos/lib/testing-python.nix") {
inherit system;
extraConfigurations = [ { nixpkgs.overlays = [ overlay ]; } ];
};
@ -113,36 +113,37 @@ makeTest (
};
};
testScript = { nodes }:
''
use POSIX qw(strftime);
testScript = { nodes }: ''
# fmt: off
import json
import time
startAll;
start_all()
$github->waitForUnit("httpd.service");
github.wait_for_unit("httpd.service")
$client->succeed("curl -v https://github.com/ >&2");
client.succeed("curl -v https://github.com/ >&2")
client.succeed("nix registry list | grep nixpkgs")
$client->succeed("nix registry list | grep nixpkgs");
rev = client.succeed("nix flake info nixpkgs --json | jq -r .revision")
assert rev.strip() == "${nixpkgs.rev}", "revision mismatch"
$client->succeed("nix flake info nixpkgs --json | jq -r .revision") eq "${nixpkgs.rev}\n"
or die "revision mismatch";
client.succeed("nix registry pin nixpkgs")
$client->succeed("nix registry pin nixpkgs");
client.succeed("nix flake info nixpkgs --tarball-ttl 0 >&2")
$client->succeed("nix flake info nixpkgs --tarball-ttl 0 >&2");
# Shut down the web server. The flake should be cached on the client.
github.succeed("systemctl stop httpd.service")
# Shut down the web server. The flake should be cached on the client.
$github->succeed("systemctl stop httpd.service");
info = json.loads(client.succeed("nix flake info nixpkgs --json"))
date = time.strftime("%Y%m%d%H%M%S", time.gmtime(info['lastModified']))
assert date == "${nixpkgs.lastModifiedDate}", "time mismatch"
my $date = $client->succeed("nix flake info nixpkgs --json | jq -M .lastModified");
strftime("%Y%m%d%H%M%S", gmtime($date)) eq "${nixpkgs.lastModifiedDate}" or die "time mismatch";
client.succeed("nix build nixpkgs#hello")
$client->succeed("nix build nixpkgs#hello");
# The build shouldn't fail even with --tarball-ttl 0 (the server
# being down should not be a fatal error).
$client->succeed("nix build nixpkgs#fuse --tarball-ttl 0");
'';
# The build shouldn't fail even with --tarball-ttl 0 (the server
# being down should not be a fatal error).
client.succeed("nix build nixpkgs#fuse --tarball-ttl 0")
'';
})

View file

@ -2,7 +2,7 @@
{ nixpkgs, system, overlay }:
with import (nixpkgs + "/nixos/lib/testing.nix") {
with import (nixpkgs + "/nixos/lib/testing-python.nix") {
inherit system;
extraConfigurations = [ { nixpkgs.overlays = [ overlay ]; } ];
};
@ -25,41 +25,46 @@ makeTest (let pkgA = pkgs.cowsay; pkgB = pkgs.wget; pkgC = pkgs.hello; in {
};
};
testScript = { nodes }:
''
startAll;
testScript = { nodes }: ''
# fmt: off
import subprocess
# Create an SSH key on the client.
my $key = `${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f key -N ""`;
$client->succeed("mkdir -m 700 /root/.ssh");
$client->copyFileFromHost("key", "/root/.ssh/id_ed25519");
$client->succeed("chmod 600 /root/.ssh/id_ed25519");
start_all()
# Install the SSH key on the server.
$server->succeed("mkdir -m 700 /root/.ssh");
$server->copyFileFromHost("key.pub", "/root/.ssh/authorized_keys");
$server->waitForUnit("sshd");
$client->waitForUnit("network.target");
$client->succeed("ssh -o StrictHostKeyChecking=no " . $server->name() . " 'echo hello world'");
# Create an SSH key on the client.
subprocess.run([
"${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", ""
], capture_output=True, check=True)
# Copy the closure of package A from the client to the server.
$server->fail("nix-store --check-validity ${pkgA}");
$client->succeed("nix-copy-closure --to server --gzip ${pkgA} >&2");
$server->succeed("nix-store --check-validity ${pkgA}");
client.succeed("mkdir -m 700 /root/.ssh")
client.copy_from_host("key", "/root/.ssh/id_ed25519")
client.succeed("chmod 600 /root/.ssh/id_ed25519")
# Copy the closure of package B from the server to the client.
$client->fail("nix-store --check-validity ${pkgB}");
$client->succeed("nix-copy-closure --from server --gzip ${pkgB} >&2");
$client->succeed("nix-store --check-validity ${pkgB}");
# Install the SSH key on the server.
server.succeed("mkdir -m 700 /root/.ssh")
server.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
server.wait_for_unit("sshd")
client.wait_for_unit("network.target")
client.succeed(f"ssh -o StrictHostKeyChecking=no {server.name} 'echo hello world'")
# Copy the closure of package C via the SSH substituter.
$client->fail("nix-store -r ${pkgC}");
# FIXME
#$client->succeed(
# "nix-store --option use-ssh-substituter true"
# . " --option ssh-substituter-hosts root\@server"
# . " -r ${pkgC} >&2");
#$client->succeed("nix-store --check-validity ${pkgC}");
'';
# Copy the closure of package A from the client to the server.
server.fail("nix-store --check-validity ${pkgA}")
client.succeed("nix-copy-closure --to server --gzip ${pkgA} >&2")
server.succeed("nix-store --check-validity ${pkgA}")
# Copy the closure of package B from the server to the client.
client.fail("nix-store --check-validity ${pkgB}")
client.succeed("nix-copy-closure --from server --gzip ${pkgB} >&2")
client.succeed("nix-store --check-validity ${pkgB}")
# Copy the closure of package C via the SSH substituter.
client.fail("nix-store -r ${pkgC}")
# FIXME
# client.succeed(
# "nix-store --option use-ssh-substituter true"
# " --option ssh-substituter-hosts root\@server"
# " -r ${pkgC} >&2"
# )
# client.succeed("nix-store --check-validity ${pkgC}")
'';
})

View file

@ -2,7 +2,7 @@
{ nixpkgs, system, overlay }:
with import (nixpkgs + "/nixos/lib/testing.nix") {
with import (nixpkgs + "/nixos/lib/testing-python.nix") {
inherit system;
extraConfigurations = [ { nixpkgs.overlays = [ overlay ]; } ];
};
@ -66,44 +66,46 @@ in
};
};
testScript = { nodes }:
''
startAll;
testScript = { nodes }: ''
# fmt: off
import subprocess
# Create an SSH key on the client.
my $key = `${pkgs.openssh}/bin/ssh-keygen -t ed25519 -f key -N ""`;
$client->succeed("mkdir -p -m 700 /root/.ssh");
$client->copyFileFromHost("key", "/root/.ssh/id_ed25519");
$client->succeed("chmod 600 /root/.ssh/id_ed25519");
start_all()
# Install the SSH key on the builders.
$client->waitForUnit("network.target");
foreach my $builder ($builder1, $builder2) {
$builder->succeed("mkdir -p -m 700 /root/.ssh");
$builder->copyFileFromHost("key.pub", "/root/.ssh/authorized_keys");
$builder->waitForUnit("sshd");
$client->succeed("ssh -o StrictHostKeyChecking=no " . $builder->name() . " 'echo hello world'");
}
# Create an SSH key on the client.
subprocess.run([
"${pkgs.openssh}/bin/ssh-keygen", "-t", "ed25519", "-f", "key", "-N", ""
], capture_output=True, check=True)
client.succeed("mkdir -p -m 700 /root/.ssh")
client.copy_from_host("key", "/root/.ssh/id_ed25519")
client.succeed("chmod 600 /root/.ssh/id_ed25519")
# Perform a build and check that it was performed on the builder.
my $out = $client->succeed(
"nix-build ${expr nodes.client.config 1} 2> build-output",
"grep -q Hello build-output"
);
$builder1->succeed("test -e $out");
# Install the SSH key on the builders.
client.wait_for_unit("network.target")
for builder in [builder1, builder2]:
builder.succeed("mkdir -p -m 700 /root/.ssh")
builder.copy_from_host("key.pub", "/root/.ssh/authorized_keys")
builder.wait_for_unit("sshd")
client.succeed(f"ssh -o StrictHostKeyChecking=no {builder.name} 'echo hello world'")
# And a parallel build.
my ($out1, $out2) = split /\s/,
$client->succeed('nix-store -r $(nix-instantiate ${expr nodes.client.config 2})\!out $(nix-instantiate ${expr nodes.client.config 3})\!out');
$builder1->succeed("test -e $out1 -o -e $out2");
$builder2->succeed("test -e $out1 -o -e $out2");
# Perform a build and check that it was performed on the builder.
out = client.succeed(
"nix-build ${expr nodes.client.config 1} 2> build-output",
"grep -q Hello build-output"
)
builder1.succeed(f"test -e {out}")
# And a failing build.
$client->fail("nix-build ${expr nodes.client.config 5}");
# And a parallel build.
paths = client.succeed(r'nix-store -r $(nix-instantiate ${expr nodes.client.config 2})\!out $(nix-instantiate ${expr nodes.client.config 3})\!out')
out1, out2 = paths.split()
builder1.succeed(f"test -e {out1} -o -e {out2}")
builder2.succeed(f"test -e {out1} -o -e {out2}")
# Test whether the build hook automatically skips unavailable builders.
$builder1->block;
$client->succeed("nix-build ${expr nodes.client.config 4}");
'';
# And a failing build.
client.fail("nix-build ${expr nodes.client.config 5}")
# Test whether the build hook automatically skips unavailable builders.
builder1.block()
client.succeed("nix-build ${expr nodes.client.config 4}")
'';
})

View file

@ -2,7 +2,7 @@
{ nixpkgs, system, overlay }:
with import (nixpkgs + "/nixos/lib/testing.nix") {
with import (nixpkgs + "/nixos/lib/testing-python.nix") {
inherit system;
extraConfigurations = [ { nixpkgs.overlays = [ overlay ]; } ];
};
@ -17,94 +17,109 @@ makeTest {
virtualisation.pathsInNixDB = [ pkgs.stdenv pkgs.pkgsi686Linux.stdenv ];
};
testScript = { nodes }:
''
startAll;
testScript = { nodes }: ''
# fmt: off
start_all()
# Copying to /tmp should succeed.
$machine->succeed('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
")\' ');
# Copying to /tmp should succeed.
machine.succeed(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
# Creating a setuid binary should fail.
$machine->fail('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 4755 /tmp/id
")\' ');
# Creating a setuid binary should fail.
machine.fail(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 4755 /tmp/id
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
# Creating a setgid binary should fail.
$machine->fail('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 2755 /tmp/id
")\' ');
# Creating a setgid binary should fail.
machine.fail(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 2755 /tmp/id
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
# The checks should also work on 32-bit binaries.
$machine->fail('nix-build --no-sandbox -E \'(with import <nixpkgs> { system = "i686-linux"; }; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 2755 /tmp/id
")\' ');
# The checks should also work on 32-bit binaries.
machine.fail(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> { system = "i686-linux"; }; runCommand "foo" {} "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
chmod 2755 /tmp/id
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
# The tests above use fchmodat(). Test chmod() as well.
$machine->succeed('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"chmod 0666, qw(/tmp/id) or die\"
")\' ');
# The tests above use fchmodat(). Test chmod() as well.
machine.succeed(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"chmod 0666, qw(/tmp/id) or die\"
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 666 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 666 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
$machine->fail('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"chmod 04755, qw(/tmp/id) or die\"
")\' ');
machine.fail(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"chmod 04755, qw(/tmp/id) or die\"
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
# And test fchmod().
$machine->succeed('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 01750, \\\$x or die\"
")\' ');
# And test fchmod().
machine.succeed(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 01750, \\\$x or die\"
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 1750 ]]');
machine.succeed('[[ $(stat -c %a /tmp/id) = 1750 ]]')
$machine->succeed("rm /tmp/id");
machine.succeed("rm /tmp/id")
$machine->fail('nix-build --no-sandbox -E \'(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 04777, \\\$x or die\"
")\' ');
machine.fail(r"""
nix-build --no-sandbox -E '(with import <nixpkgs> {}; runCommand "foo" { buildInputs = [ perl ]; } "
mkdir -p $out
cp ${pkgs.coreutils}/bin/id /tmp/id
perl -e \"my \\\$x; open \\\$x, qw(/tmp/id); chmod 04777, \\\$x or die\"
")'
""".strip())
$machine->succeed('[[ $(stat -c %a /tmp/id) = 555 ]]');
$machine->succeed("rm /tmp/id");
'';
machine.succeed('[[ $(stat -c %a /tmp/id) = 555 ]]')
machine.succeed("rm /tmp/id")
'';
}