From 55c349fe201a6dd09364afc846517c87eb9cf767 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sat, 6 Feb 2010 13:08:15 +0000 Subject: [PATCH] * Added a test that checks whether users can log in on a virtual console. This uses the `sendkey' command in the QEMU monitor. * For the block/unblock primitives, use the `set_link' command in the QEMU monitor. svn path=/nixos/trunk/; revision=19854 --- lib/build-vms.nix | 2 +- lib/test-driver/Machine.pm | 43 ++++++++++++++++++++++++++++++---- lib/test-driver/test-driver.pl | 2 ++ release.nix | 1 + tests/default.nix | 1 + tests/login.nix | 37 +++++++++++++++++++++++++++++ 6 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 tests/login.nix diff --git a/lib/build-vms.nix b/lib/build-vms.nix index 11eed8e2339..88806683d3e 100644 --- a/lib/build-vms.nix +++ b/lib/build-vms.nix @@ -40,7 +40,7 @@ rec { for i in $out/vms/*; do port2=\$((port++)) echo "forwarding localhost:\$port2 to \$(basename \$i):80" - QEMU_OPTS="-redir tcp:\$port2::80 -net nic,vlan=1 -net socket,vlan=1,mcast=232.0.1.1:1234" \$i/bin/run-*-vm & + QEMU_OPTS="-redir tcp:\$port2::80 -net nic,vlan=1,model=virtio -net socket,vlan=1,mcast=232.0.1.1:1234" \$i/bin/run-*-vm & done EOF chmod +x $out/bin/run-vms diff --git a/lib/test-driver/Machine.pm b/lib/test-driver/Machine.pm index 6840f4e2af0..634f566bd1a 100644 --- a/lib/test-driver/Machine.pm +++ b/lib/test-driver/Machine.pm @@ -107,7 +107,7 @@ sub start { dup2(fileno($serialC), fileno(STDOUT)); dup2(fileno($serialC), fileno(STDERR)); $ENV{TMPDIR} = $self->{stateDir}; - $ENV{QEMU_OPTS} = "-nographic -no-reboot -redir tcp:65535::514 -net nic,vlan=1 -net socket,vlan=1,mcast=$mcastAddr -monitor unix:./monitor"; + $ENV{QEMU_OPTS} = "-nographic -no-reboot -redir tcp:65535::514 -net nic,vlan=1,model=virtio -net socket,vlan=1,mcast=$mcastAddr -monitor unix:./monitor"; $ENV{QEMU_KERNEL_PARAMS} = "hostTmpDir=$ENV{TMPDIR}"; chdir $self->{stateDir} or die; exec $self->{startCommand}; @@ -146,6 +146,7 @@ sub start { # all commands yet. We should use it once it does. sub sendMonitorCommand { my ($self, $command) = @_; + $self->log("sending monitor command: $command"); syswrite $self->{monitor}, "$command\n"; return $self->waitForMonitorPrompt; } @@ -215,6 +216,13 @@ sub waitForShutdown { waitpid $self->{pid}, 0; $self->{pid} = 0; $self->{booted} = 0; + $self->{connected} = 0; +} + + +sub isUp { + my ($self) = @_; + return $self->{booted} && $self->{connected}; } @@ -266,6 +274,15 @@ sub waitUntilSucceeds { } +sub waitUntilFails { + my ($self, $command) = @_; + retry sub { + my ($status, $out) = $self->execute($command); + return 1 if $status != 0; + }; +} + + sub mustFail { my ($self, $command) = @_; my ($status, $out) = $self->execute($command); @@ -337,14 +354,14 @@ sub shutdown { # the test driver can continue to talk to the machine. sub block { my ($self) = @_; - $self->mustSucceed("ifconfig eth1 down"); + $self->sendMonitorCommand("set_link virtio-net-pci.1 down"); } # Make the machine reachable. sub unblock { my ($self) = @_; - $self->mustSucceed("ifconfig eth1 up"); + $self->sendMonitorCommand("set_link virtio-net-pci.1 up"); } @@ -368,7 +385,7 @@ sub waitForX { my ($status, $out) = $self->execute("xwininfo -root > /dev/null 2>&1"); return 1 if $status == 0; } -}; +} sub getWindowNames { @@ -387,7 +404,7 @@ sub waitForWindow { return 1 if $n =~ /$regexp/; } } -}; +} sub copyFileFromHost { @@ -397,4 +414,20 @@ sub copyFileFromHost { } +sub sendKeys { + my ($self, @keys) = @_; + foreach my $key (@keys) { + $key = "spc" if $key eq " "; + $key = "ret" if $key eq "\n"; + $self->sendMonitorCommand("sendkey $key"); + } +} + + +sub sendChars { + my ($self, $chars) = @_; + $self->sendKeys(split //, $chars); +} + + 1; diff --git a/lib/test-driver/test-driver.pl b/lib/test-driver/test-driver.pl index 2ccc6bd4b9a..98666d6c775 100644 --- a/lib/test-driver/test-driver.pl +++ b/lib/test-driver/test-driver.pl @@ -37,6 +37,8 @@ sub runTests { foreach my $vm (values %vms) { my $gcovDir = "/sys/kernel/debug/gcov"; + next unless $vm->isUp(); + my ($status, $out) = $vm->execute("test -e $gcovDir"); next if $status != 0; diff --git a/release.nix b/release.nix index 957e65b681d..d803414de48 100644 --- a/release.nix +++ b/release.nix @@ -128,6 +128,7 @@ let installer.separateBoot = t.installer.separateBoot.test; installer.simple = t.installer.simple.test; kde4 = t.kde4.test; + login = t.login.test; proxy = t.proxy.test; quake3 = t.quake3.test; subversion = t.subversion.report; diff --git a/tests/default.nix b/tests/default.nix index 46b3218168f..a9661d33957 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -31,6 +31,7 @@ in firefox = apply (import ./firefox.nix); installer = pkgs.lib.mapAttrs (name: complete) (call (import ./installer.nix)); kde4 = apply (import ./kde4.nix); + login = apply (import ./login.nix); portmap = apply (import ./portmap.nix); proxy = apply (import ./proxy.nix); quake3 = apply (import ./quake3.nix); diff --git a/tests/login.nix b/tests/login.nix new file mode 100644 index 00000000000..ef00d191dce --- /dev/null +++ b/tests/login.nix @@ -0,0 +1,37 @@ +{ pkgs, ... }: + +{ + + machine = { config, pkgs, ... }: { }; + + testScript = + '' + $machine->mustSucceed("useradd -m alice"); + $machine->mustSucceed("echo foobar | passwd --stdin alice"); + + # Log in as alice on a virtual console. + $machine->waitForJob("tty1"); + $machine->sendChars("alice\n"); + $machine->waitUntilSucceeds("pgrep login"); + $machine->execute("sleep 2"); # urgh: wait for `Password:' + $machine->sendChars("foobar\n"); + $machine->waitUntilSucceeds("pgrep -u alice bash"); + $machine->sendChars("touch done\n"); + $machine->waitForFile("/home/alice/done"); + $machine->sendChars("exit\n"); + $machine->waitUntilFails("pgrep -u alice bash"); + $machine->screenshot("mingetty"); + + # Check whether switching VTs works. + $machine->sendKeys("alt-f10"); + $machine->waitUntilSucceeds("[ \$(fgconsole) = 10 ]"); + $machine->execute("sleep 2"); # allow fbcondecor to catch up (not important) + $machine->screenshot("syslog"); + + # Check whether ctrl-alt-delete works. + $machine->sendKeys("alt-f1"); + $machine->sendKeys("ctrl-alt-delete"); + $machine->waitForShutdown; + ''; + +}