diff options
Diffstat (limited to 'nixos/tests')
34 files changed, 2265 insertions, 0 deletions
diff --git a/nixos/tests/avahi.nix b/nixos/tests/avahi.nix new file mode 100644 index 0000000000000..d95361dcd83d4 --- /dev/null +++ b/nixos/tests/avahi.nix @@ -0,0 +1,55 @@ +{ pkgs, ... }: + +with pkgs; + +{ + nodes = { + one = + { config, pkgs, ... }: { + services.avahi.enable = true; + services.avahi.nssmdns = true; + }; + + two = + { config, pkgs, ... }: { + services.avahi.enable = true; + services.avahi.nssmdns = true; + }; + }; + + # Test whether `avahi-daemon' and `libnss-mdns' work as expected. + testScript = + '' startAll; + + # mDNS. + $one->waitForUnit("network.target"); + $one->succeed("avahi-resolve-host-name one.local | tee out >&2"); + $one->succeed("test \"`cut -f1 < out`\" = one.local"); + $one->succeed("avahi-resolve-host-name two.local | tee out >&2"); + $one->succeed("test \"`cut -f1 < out`\" = two.local"); + + $two->waitForUnit("network.target"); + $two->succeed("avahi-resolve-host-name one.local | tee out >&2"); + $two->succeed("test \"`cut -f1 < out`\" = one.local"); + $two->succeed("avahi-resolve-host-name two.local | tee out >&2"); + $two->succeed("test \"`cut -f1 < out`\" = two.local"); + + # Basic DNS-SD. + $one->succeed("avahi-browse -r -t _workstation._tcp | tee out >&2"); + $one->succeed("test `wc -l < out` -gt 0"); + $two->succeed("avahi-browse -r -t _workstation._tcp | tee out >&2"); + $two->succeed("test `wc -l < out` -gt 0"); + + # More DNS-SD. + $one->execute("avahi-publish -s \"This is a test\" _test._tcp 123 one=1 &"); + $one->sleep(5); + $two->succeed("avahi-browse -r -t _test._tcp | tee out >&2"); + $two->succeed("test `wc -l < out` -gt 0"); + + # NSS-mDNS. + $one->succeed("getent hosts one.local >&2"); + $one->succeed("getent hosts two.local >&2"); + $two->succeed("getent hosts one.local >&2"); + $two->succeed("getent hosts two.local >&2"); + ''; +} diff --git a/nixos/tests/bittorrent.nix b/nixos/tests/bittorrent.nix new file mode 100644 index 0000000000000..180da8267e0f7 --- /dev/null +++ b/nixos/tests/bittorrent.nix @@ -0,0 +1,107 @@ +# This test runs a Bittorrent tracker on one machine, and verifies +# that two client machines can download the torrent using +# `transmission'. The first client (behind a NAT router) downloads +# from the initial seeder running on the tracker. Then we kill the +# initial seeder. The second client downloads from the first client, +# which only works if the first client successfully uses the UPnP-IGD +# protocol to poke a hole in the NAT. + +{ pkgs, ... }: + +let + + # Some random file to serve. + file = pkgs.nixUnstable.src; + + miniupnpdConf = nodes: pkgs.writeText "miniupnpd.conf" + '' + ext_ifname=eth1 + listening_ip=${nodes.router.config.networking.interfaces.eth2.ipAddress}/24 + allow 1024-65535 192.168.2.0/24 1024-65535 + ''; + +in + +{ + + nodes = + { tracker = + { config, pkgs, ... }: + { environment.systemPackages = [ pkgs.transmission pkgs.bittorrent ]; + + # We need Apache on the tracker to serve the torrents. + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.documentRoot = "/tmp"; + }; + + router = + { config, pkgs, ... }: + { environment.systemPackages = [ pkgs.miniupnpd ]; + virtualisation.vlans = [ 1 2 ]; + networking.nat.enable = true; + networking.nat.internalIPs = "192.168.2.0/24"; + networking.nat.externalInterface = "eth1"; + }; + + client1 = + { config, pkgs, nodes, ... }: + { environment.systemPackages = [ pkgs.transmission ]; + virtualisation.vlans = [ 2 ]; + networking.defaultGateway = + nodes.router.config.networking.interfaces.eth2.ipAddress; + }; + + client2 = + { config, pkgs, ... }: + { environment.systemPackages = [ pkgs.transmission ]; + }; + }; + + testScript = + { nodes, ... }: + '' + startAll; + + # Enable NAT on the router and start miniupnpd. + $router->waitForUnit("nat"); + $router->succeed( + "iptables -t nat -N MINIUPNPD", + "iptables -t nat -A PREROUTING -i eth1 -j MINIUPNPD", + "echo 1 > /proc/sys/net/ipv4/ip_forward", + "miniupnpd -f ${miniupnpdConf nodes}" + ); + + # Create the torrent. + $tracker->succeed("mkdir /tmp/data"); + $tracker->succeed("cp ${file} /tmp/data/test.tar.bz2"); + $tracker->succeed("transmission-create /tmp/data/test.tar.bz2 -t http://tracker:6969/announce -o /tmp/test.torrent"); + $tracker->succeed("chmod 644 /tmp/test.torrent"); + + # Start the tracker. !!! use a less crappy tracker + $tracker->waitForUnit("network.target"); + $tracker->succeed("bittorrent-tracker --port 6969 --dfile /tmp/dstate >&2 &"); + $tracker->waitForOpenPort(6969); + + # Start the initial seeder. + my $pid = $tracker->succeed("transmission-cli /tmp/test.torrent -M -w /tmp/data >&2 & echo \$!"); + + # Now we should be able to download from the client behind the NAT. + $tracker->waitForUnit("httpd"); + $client1->waitForUnit("network.target"); + $client1->succeed("transmission-cli http://tracker/test.torrent -w /tmp >&2 &"); + $client1->waitForFile("/tmp/test.tar.bz2"); + $client1->succeed("cmp /tmp/test.tar.bz2 ${file}"); + + # Bring down the initial seeder. + $tracker->succeed("kill -9 $pid"); + + # Now download from the second client. This can only succeed if + # the first client created a NAT hole in the router. + $client2->waitForUnit("network.target"); + $client2->succeed("transmission-cli http://tracker/test.torrent -M -w /tmp >&2 &"); + $client2->waitForFile("/tmp/test.tar.bz2"); + $client2->succeed("cmp /tmp/test.tar.bz2 ${file}"); + ''; + +} diff --git a/nixos/tests/check-filesystems.nix b/nixos/tests/check-filesystems.nix new file mode 100644 index 0000000000000..39e8883ee598f --- /dev/null +++ b/nixos/tests/check-filesystems.nix @@ -0,0 +1,80 @@ +{ nixos ? ./.. +, nixpkgs ? /etc/nixos/nixpkgs +, system ? builtins.currentSystem +}: + +with import ../lib/build-vms.nix { inherit nixos nixpkgs system; }; + +rec { + nodes = { + share = {pkgs, config, ...}: { + services.nfs.server.enable = true; + services.nfs.server.exports = '' + /repos1 192.168.1.0/255.255.255.0(rw,no_root_squash) + /repos2 192.168.1.0/255.255.255.0(rw,no_root_squash) + ''; + services.nfs.server.createMountPoints = true; + + jobs.checkable = { + startOn = [ + config.jobs.nfs_kernel_exports.name + config.jobs.nfs_kernel_nfsd.name + ]; + respawn = true; + }; + }; + + fsCheck = {pkgs, config, ...}: { + fileSystems = + let + repos1 = { + mountPoint = "/repos1"; + autocreate = true; + device = "share:/repos1"; + fsType = "nfs"; + }; + + repos2 = { + mountPoint = "/repos2"; + autocreate = true; + device = "share:/repos2"; + fsType = "nfs"; + }; + in pkgs.lib.mkOverrideTemplate 50 {} [ + repos1 + repos1 # check remount + repos2 # check after remount + ]; + + jobs.checkable = { + startOn = "stopped ${config.jobs.filesystems.name}"; + respawn = true; + }; + }; + }; + + vms = buildVirtualNetwork { inherit nodes; }; + + test = runTests vms + '' + startAll; + + $share->waitForUnit("checkable"); + $fsCheck->waitForUnit("checkable"); + + # check repos1 + $fsCheck->succeed("test -d /repos1"); + $share->succeed("touch /repos1/test1"); + $fsCheck->succeed("test -e /repos1/test1"); + + # check repos2 (check after remount) + $fsCheck->succeed("test -d /repos2"); + $share->succeed("touch /repos2/test2"); + $fsCheck->succeed("test -e /repos2/test2"); + + # check without network + $share->block(); + $fsCheck->fail("test -e /repos1/test1"); + $fsCheck->fail("test -e /repos2/test2"); + ''; +} diff --git a/nixos/tests/common/user-account.nix b/nixos/tests/common/user-account.nix new file mode 100644 index 0000000000000..8157cf8d263e8 --- /dev/null +++ b/nixos/tests/common/user-account.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: + +{ users.extraUsers = pkgs.lib.singleton + { name = "alice"; + description = "Alice Foobar"; + home = "/home/alice"; + createHome = true; + useDefaultShell = true; + password = "foobar"; + }; +} diff --git a/nixos/tests/common/x11.nix b/nixos/tests/common/x11.nix new file mode 100644 index 0000000000000..c5a7c165d1268 --- /dev/null +++ b/nixos/tests/common/x11.nix @@ -0,0 +1,12 @@ +{ services.xserver.enable = true; + + # Automatically log in. + services.xserver.displayManager.auto.enable = true; + + # Use IceWM as the window manager. + services.xserver.windowManager.default = "icewm"; + services.xserver.windowManager.icewm.enable = true; + + # Don't use a desktop manager. + services.xserver.desktopManager.default = "none"; +} diff --git a/nixos/tests/default.nix b/nixos/tests/default.nix new file mode 100644 index 0000000000000..17fe6a6d045fd --- /dev/null +++ b/nixos/tests/default.nix @@ -0,0 +1,37 @@ +{ nixpkgs ? <nixpkgs> +, system ? builtins.currentSystem +, minimal ? false +}: + +with import ../lib/testing.nix { inherit system minimal; }; + +{ + avahi = makeTest (import ./avahi.nix); + bittorrent = makeTest (import ./bittorrent.nix); + firefox = makeTest (import ./firefox.nix); + firewall = makeTest (import ./firewall.nix); + installer = makeTests (import ./installer.nix); + efi-installer = makeTests (import ./efi-installer.nix); + ipv6 = makeTest (import ./ipv6.nix); + kde4 = makeTest (import ./kde4.nix); + #kexec = makeTest (import ./kexec.nix); + login = makeTest (import ./login.nix {}); + latestKernel.login = makeTest (import ./login.nix ({ config, pkgs, ... }: { boot.kernelPackages = pkgs.linuxPackages_latest; })); + misc = makeTest (import ./misc.nix); + #mpich = makeTest (import ./mpich.nix); + mysql = makeTest (import ./mysql.nix); + mysql_replication = makeTest (import ./mysql-replication.nix); + nat = makeTest (import ./nat.nix); + nfs3 = makeTest (import ./nfs.nix { version = 3; }); + #nfs4 = makeTest (import ./nfs.nix { version = 4; }); + openssh = makeTest (import ./openssh.nix); + partition = makeTest (import ./partition.nix); + printing = makeTest (import ./printing.nix); + proxy = makeTest (import ./proxy.nix); + quake3 = makeTest (import ./quake3.nix); + simple = makeTest (import ./simple.nix); + #subversion = makeTest (import ./subversion.nix); + tomcat = makeTest (import ./tomcat.nix); + trac = makeTest (import ./trac.nix); + xfce = makeTest (import ./xfce.nix); +} diff --git a/nixos/tests/efi-installer.nix b/nixos/tests/efi-installer.nix new file mode 100644 index 0000000000000..a9c5d71903066 --- /dev/null +++ b/nixos/tests/efi-installer.nix @@ -0,0 +1,131 @@ +# !!! Merge into normal install tests once all livecds are EFIable +{ pkgs, system, ... }: + +with pkgs.lib; +with import ../lib/qemu-flags.nix; + +let + + # Build the ISO. This is the regular installation CD but with test + # instrumentation. + iso = + (import ../lib/eval-config.nix { + inherit system; + modules = + [ ../modules/installer/cd-dvd/installation-cd-efi.nix + ../modules/testing/test-instrumentation.nix + { key = "serial"; + + # The test cannot access the network, so any sources we + # need must be included in the ISO. + isoImage.storeContents = + [ pkgs.glibcLocales + pkgs.sudo + pkgs.docbook5 + pkgs.docbook5_xsl + pkgs.grub + pkgs.perlPackages.XMLLibXML + pkgs.unionfs-fuse + pkgs.gummiboot + pkgs.libxslt + ]; + } + ]; + }).config.system.build.isoImage; + + + # The config to install + config = builtins.toFile "configuration.nix" '' + { pkgs, ... }: { + imports = [ ./hardware.nix <nixos/modules/testing/test-instrumentation.nix> ]; + boot.kernelPackages = pkgs.linuxPackages_3_10; + boot.loader.grub.enable = false; + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.gummiboot.enable = true; + fonts.enableFontConfig = false; + fileSystems."/".label = "nixos"; + } + ''; + + biosDir = pkgs.runCommand "ovmf-bios" {} '' + mkdir $out + ln -s ${pkgs.OVMF}/FV/OVMF.fd $out/bios.bin + ''; + +in { + simple = { + inherit iso; + nodes = {}; + testScript = '' + createDisk("harddisk", 4 * 1024); + + my $machine = createMachine({ hda => "harddisk", + hdaInterface => "virtio", + cdrom => glob("${iso}/iso/*.iso"), + qemuFlags => '-L ${biosDir} ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"}'}); + $machine->start; + + # Make sure that we get a login prompt etc. + $machine->succeed("echo hello"); + $machine->waitForUnit("rogue"); + $machine->waitForUnit("nixos-manual"); + $machine->waitForUnit("dhcpcd"); + + # Partition the disk. + $machine->succeed( + "sgdisk -Z /dev/vda", + "sgdisk -n 1:0:+256M -N 2 -t 1:ef00 -t 2:8300 -c 1:boot -c 2:root /dev/vda", + "mkfs.vfat -n BOOT /dev/vda1", + "mkfs.ext3 -L nixos /dev/vda2", + "mount LABEL=nixos /mnt", + "mkdir /mnt/boot", + "mount LABEL=BOOT /mnt/boot", + ); + + # Create the NixOS configuration. + $machine->succeed( + "mkdir -p /mnt/etc/nixos", + "nixos-hardware-scan > /mnt/etc/nixos/hardware.nix", + ); + + my $cfg = $machine->succeed("cat /mnt/etc/nixos/hardware.nix"); + print STDERR "Result of the hardware scan:\n$cfg\n"; + + $machine->copyFileFromHost( + "${config}", + "/mnt/etc/nixos/configuration.nix"); + + # Perform the installation. + $machine->succeed("nixos-install >&2"); + + # Do it again to make sure it's idempotent. + $machine->succeed("nixos-install >&2"); + + $machine->shutdown; + + # Now see if we can boot the installation. + my $machine = createMachine({ #hda => "harddisk", +# hdaInterface => "virtio", +# !!! OVMF doesn't boot from virtio http://www.mail-archive.com/edk2-devel@lists.sourceforge.net/msg01501.html + qemuFlags => '-L ${biosDir} ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} -m 512 -hda ' . Cwd::abs_path('harddisk')}); + + # Did /boot get mounted, if appropriate? + $machine->waitForUnit("local-fs.target"); + $machine->succeed("test -e /boot/efi"); + + $machine->succeed("nix-env -i coreutils >&2"); + $machine->succeed("type -tP ls | tee /dev/stderr") =~ /.nix-profile/ + or die "nix-env failed"; + + $machine->succeed("nixos-rebuild switch >&2"); + + $machine->shutdown; + + my $machine = createMachine({ #hda => "harddisk", +# hdaInterface => "virtio", + qemuFlags => '-L ${biosDir} ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} -hda ' . Cwd::abs_path('harddisk')}); + $machine->waitForUnit("network.target"); + $machine->shutdown; + ''; + }; +} diff --git a/nixos/tests/firefox.nix b/nixos/tests/firefox.nix new file mode 100644 index 0000000000000..d6599be13c9ee --- /dev/null +++ b/nixos/tests/firefox.nix @@ -0,0 +1,21 @@ +{ pkgs, ... }: + +{ + + machine = + { config, pkgs, ... }: + + { imports = [ ./common/x11.nix ]; + environment.systemPackages = [ pkgs.firefox ]; + }; + + testScript = + '' + $machine->waitForX; + $machine->execute("firefox file://${pkgs.valgrind}/share/doc/valgrind/html/index.html &"); + $machine->waitForWindow(qr/Valgrind/); + $machine->sleep(40); # wait until Firefox has finished loading the page + $machine->screenshot("screen"); + ''; + +} diff --git a/nixos/tests/firewall.nix b/nixos/tests/firewall.nix new file mode 100644 index 0000000000000..de32b98e5d2f7 --- /dev/null +++ b/nixos/tests/firewall.nix @@ -0,0 +1,48 @@ +# Test the firewall module. + +{ pkgs, ... }: + +{ + + nodes = + { walled = + { config, pkgs, nodes, ... }: + { networking.firewall.enable = true; + networking.firewall.logRefusedPackets = true; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + }; + + attacker = + { config, pkgs, ... }: + { services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + }; + }; + + testScript = + { nodes, ... }: + '' + startAll; + + $walled->waitForUnit("firewall"); + $walled->waitForUnit("httpd"); + $attacker->waitForUnit("network.target"); + + # Local connections should still work. + $walled->succeed("curl -v http://localhost/ >&2"); + + # Connections to the firewalled machine should fail. + $attacker->fail("curl -v http://walled/ >&2"); + $attacker->fail("ping -c 1 walled >&2"); + + # Outgoing connections/pings should still work. + $walled->succeed("curl -v http://attacker/ >&2"); + $walled->succeed("ping -c 1 attacker >&2"); + + # If we stop the firewall, then connections should succeed. + $walled->stopJob("firewall"); + $attacker->succeed("curl -v http://walled/ >&2"); + ''; + +} diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix new file mode 100644 index 0000000000000..0ce7805317128 --- /dev/null +++ b/nixos/tests/installer.nix @@ -0,0 +1,354 @@ +{ pkgs, system, ... }: + +with pkgs.lib; +with import ../lib/qemu-flags.nix; + +let + + # Build the ISO. This is the regular installation CD but with test + # instrumentation. + iso = + (import ../lib/eval-config.nix { + inherit system; + modules = + [ ../modules/installer/cd-dvd/installation-cd-graphical.nix + ../modules/testing/test-instrumentation.nix + { key = "serial"; + boot.loader.grub.timeout = mkOverrideTemplate 0 {} 0; + + # The test cannot access the network, so any sources we + # need must be included in the ISO. + isoImage.storeContents = + [ pkgs.glibcLocales + pkgs.sudo + pkgs.docbook5 + pkgs.docbook5_xsl + pkgs.grub + pkgs.perlPackages.XMLLibXML + pkgs.unionfs-fuse + ]; + } + ]; + }).config.system.build.isoImage; + + + # The configuration to install. + config = { fileSystems, testChannel, grubVersion, grubDevice }: pkgs.writeText "configuration.nix" + '' + { config, pkgs, modulesPath, ... }: + + { imports = + [ ./hardware.nix + "''${modulesPath}/testing/test-instrumentation.nix" + ]; + + boot.loader.grub.version = ${toString grubVersion}; + ${optionalString (grubVersion == 1) '' + boot.loader.grub.splashImage = null; + ''} + boot.loader.grub.device = "${grubDevice}"; + boot.loader.grub.extraConfig = "serial; terminal_output.serial"; + boot.initrd.kernelModules = [ "ext3" "ext4" "xfs" "virtio_console" ]; + + ${fileSystems} + swapDevices = [ { label = "swap"; } ]; + + environment.systemPackages = [ ${optionalString testChannel "pkgs.rlwrap"} ]; + } + ''; + + rootFS = + '' + fileSystems."/".device = "/dev/disk/by-label/nixos"; + ''; + + bootFS = + '' + fileSystems."/boot".device = "/dev/disk/by-label/boot"; + ''; + + + # Configuration of a web server that simulates the Nixpkgs channel + # distribution server. + webserver = + { config, pkgs, ... }: + + { services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.servedDirs = singleton + { urlPath = "/"; + dir = "/tmp/channel"; + }; + + virtualisation.writableStore = true; + virtualisation.pathsInNixDB = channelContents ++ [ pkgs.hello.src ]; + virtualisation.memorySize = 768; + }; + + channelContents = [ pkgs.rlwrap ]; + + + # The test script boots the CD, installs NixOS on an empty hard + # disk, and then reboot from the hard disk. It's parameterized with + # a test script fragment `createPartitions', which must create + # partitions and filesystems, and a configuration.nix fragment + # `fileSystems'. + testScriptFun = { createPartitions, fileSystems, testChannel, grubVersion, grubDevice }: + let iface = if grubVersion == 1 then "scsi" else "virtio"; in + '' + createDisk("harddisk", 4 * 1024); + + my $machine = createMachine({ hda => "harddisk", + hdaInterface => "${iface}", + cdrom => glob("${iso}/iso/*.iso"), + qemuFlags => '${optionalString testChannel (toString (qemuNICFlags 1 1 2))} ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"}'}); + $machine->start; + + ${optionalString testChannel '' + # Create a channel on the web server containing a few packages + # to simulate the Nixpkgs channel. + $webserver->start; + $webserver->waitForUnit("httpd"); + $webserver->succeed( + "nix-push --bzip2 --dest /tmp/channel --manifest --url-prefix http://nixos.org/channels/nixos-unstable " . + "${toString channelContents} >&2"); + $webserver->succeed("mkdir /tmp/channel/sha256"); + $webserver->succeed("cp ${pkgs.hello.src} /tmp/channel/sha256/${pkgs.hello.src.outputHash}"); + ''} + + # Make sure that we get a login prompt etc. + $machine->succeed("echo hello"); + #$machine->waitForUnit('getty@tty2'); + $machine->waitForUnit("rogue"); + $machine->waitForUnit("nixos-manual"); + $machine->waitForUnit("dhcpcd"); + + ${optionalString testChannel '' + # Allow the machine to talk to the fake nixos.org. + $machine->succeed( + "rm /etc/hosts", + "echo 192.168.1.1 nixos.org cache.nixos.org tarballs.nixos.org > /etc/hosts", + "ifconfig eth1 up 192.168.1.2", + ); + + # Test nix-env. + $machine->fail("hello"); + $machine->succeed("nix-env -i hello"); + $machine->succeed("hello") =~ /Hello, world/ + or die "bad `hello' output"; + ''} + + # Partition the disk. + ${createPartitions} + + # Create the NixOS configuration. + $machine->succeed( + "mkdir -p /mnt/etc/nixos", + "nixos-hardware-scan > /mnt/etc/nixos/hardware.nix", + ); + + my $cfg = $machine->succeed("cat /mnt/etc/nixos/hardware.nix"); + print STDERR "Result of the hardware scan:\n$cfg\n"; + + $machine->copyFileFromHost( + "${ config { inherit fileSystems testChannel grubVersion grubDevice; } }", + "/mnt/etc/nixos/configuration.nix"); + + # Perform the installation. + $machine->succeed("nixos-install >&2"); + + # Do it again to make sure it's idempotent. + $machine->succeed("nixos-install >&2"); + + $machine->shutdown; + + # Now see if we can boot the installation. + my $machine = createMachine({ hda => "harddisk", hdaInterface => "${iface}" }); + + # Did /boot get mounted, if appropriate? + $machine->waitForUnit("local-fs.target"); + $machine->succeed("test -e /boot/grub"); + + # Did the swap device get activated? + $machine->waitForUnit("swap.target"); + $machine->succeed("cat /proc/swaps | grep -q /dev"); + + $machine->succeed("nix-env -i coreutils >&2"); + $machine->succeed("type -tP ls | tee /dev/stderr") =~ /.nix-profile/ + or die "nix-env failed"; + + $machine->succeed("nixos-rebuild switch >&2"); + + $machine->shutdown; + + # And just to be sure, check that the machine still boots after + # "nixos-rebuild switch". + my $machine = createMachine({ hda => "harddisk", hdaInterface => "${iface}" }); + $machine->waitForUnit("network.target"); + $machine->shutdown; + ''; + + + makeTest = { createPartitions, fileSystems, testChannel ? false, grubVersion ? 2, grubDevice ? "/dev/vda" }: + { inherit iso; + nodes = if testChannel then { inherit webserver; } else { }; + testScript = testScriptFun { + inherit createPartitions fileSystems testChannel grubVersion grubDevice; + }; + }; + + +in { + + # !!! `parted mkpart' seems to silently create overlapping partitions. + + + # The (almost) simplest partitioning scheme: a swap partition and + # one big filesystem partition. + simple = makeTest + { createPartitions = + '' + $machine->succeed( + "parted /dev/vda mklabel msdos", + "parted /dev/vda -- mkpart primary linux-swap 1M 1024M", + "parted /dev/vda -- 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", + ); + ''; + fileSystems = rootFS; + testChannel = true; + }; + + # Same as the previous, but now with a separate /boot partition. + separateBoot = makeTest + { createPartitions = + '' + $machine->succeed( + "parted /dev/vda mklabel msdos", + "parted /dev/vda -- mkpart primary ext2 1M 50MB", # /boot + "parted /dev/vda -- mkpart primary linux-swap 50MB 1024M", + "parted /dev/vda -- mkpart primary ext2 1024M -1s", # / + "udevadm settle", + "mkswap /dev/vda2 -L swap", + "swapon -L swap", + "mkfs.ext3 -L nixos /dev/vda3", + "mount LABEL=nixos /mnt", + "mkfs.ext3 -L boot /dev/vda1", + "mkdir /mnt/boot", + "mount LABEL=boot /mnt/boot", + ); + ''; + fileSystems = rootFS + bootFS; + }; + + # Create two physical LVM partitions combined into one volume group + # that contains the logical swap and root partitions. + lvm = makeTest + { createPartitions = + '' + $machine->succeed( + "parted /dev/vda mklabel msdos", + "parted /dev/vda -- mkpart primary 1M 2048M", # first PV + "parted /dev/vda -- set 1 lvm on", + "parted /dev/vda -- mkpart primary 2048M -1s", # second PV + "parted /dev/vda -- set 2 lvm on", + "udevadm settle", + "pvcreate /dev/vda1 /dev/vda2", + "vgcreate MyVolGroup /dev/vda1 /dev/vda2", + "lvcreate --size 1G --name swap MyVolGroup", + "lvcreate --size 2G --name nixos MyVolGroup", + "mkswap -f /dev/MyVolGroup/swap -L swap", + "swapon -L swap", + "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", + "mount LABEL=nixos /mnt", + ); + ''; + fileSystems = rootFS; + }; + + /* + swraid = makeTest + { createPartitions = + '' + $machine->succeed( + "parted /dev/vda --" + . " mklabel msdos" + . " mkpart primary ext2 1M 30MB" # /boot + . " mkpart extended 30M -1s" + . " mkpart logical 31M 1531M" # md0 (root), first device + . " mkpart logical 1540M 3040M" # md0 (root), second device + . " mkpart logical 3050M 3306M" # md1 (swap), first device + . " mkpart logical 3320M 3576M", # md1 (swap), second device + "udevadm settle", + "ls -l /dev/vda* >&2", + "cat /proc/partitions >&2", + "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 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", + "mdadm -W /dev/md0", # wait for sync to finish; booting off an unsynced device tends to fail + "mdadm -W /dev/md1", + ); + ''; + fileSystems = rootFS + bootFS; + }; + */ + + # Test a basic install using GRUB 1. + grub1 = makeTest + { createPartitions = + '' + $machine->succeed( + "parted /dev/sda mklabel msdos", + "parted /dev/sda -- mkpart primary linux-swap 1M 1024M", + "parted /dev/sda -- 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", + ); + ''; + fileSystems = rootFS; + grubVersion = 1; + grubDevice = "/dev/sda"; + }; + + # Rebuild the CD configuration with a little modification. + rebuildCD = + { inherit iso; + nodes = { }; + testScript = + '' + my $machine = createMachine({ cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '-m 768' }); + $machine->start; + + # Enable sshd service. + $machine->succeed( + "sed -i 's,^}\$,systemd.services.sshd.wantedBy = pkgs.lib.mkOverride 0 [\"multi-user.target\"]; },' /etc/nixos/configuration.nix" + ); + + $machine->succeed("cat /etc/nixos/configuration.nix >&2"); + + # Apply the new CD configuration. + $machine->succeed("nixos-rebuild test"); + + # Connect to it-self. + $machine->waitForUnit("sshd"); + $machine->waitForOpenPort(22); + + $machine->shutdown; + ''; + }; +} diff --git a/nixos/tests/ipv6.nix b/nixos/tests/ipv6.nix new file mode 100644 index 0000000000000..29d675e180a3f --- /dev/null +++ b/nixos/tests/ipv6.nix @@ -0,0 +1,76 @@ +# Test of IPv6 functionality in NixOS, including whether router +# solicication/advertisement using radvd works. + +{ pkgs, ... }: + +{ + + nodes = + { client = { config, pkgs, ... }: { }; + + server = + { config, pkgs, ... }: + { services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + }; + + router = + { config, pkgs, ... }: + { services.radvd.enable = true; + services.radvd.config = + '' + interface eth1 { + AdvSendAdvert on; + # ULA prefix (RFC 4193). + prefix fd60:cc69:b537:1::/64 { }; + }; + ''; + }; + }; + + testScript = + '' + # Start the router first so that it respond to router solicitations. + $router->waitForUnit("radvd"); + + startAll; + + $client->waitForUnit("network.target"); + $server->waitForUnit("network.target"); + + # Wait until the given interface has a non-tentative address of + # the desired scope (i.e. has completed Duplicate Address + # Detection). + sub waitForAddress { + my ($machine, $iface, $scope) = @_; + $machine->waitUntilSucceeds("[ `ip -o -6 addr show dev $iface scope $scope | grep -v tentative | wc -l` -eq 1 ]"); + my $ip = (split /[ \/]+/, $machine->succeed("ip -o -6 addr show dev $iface scope $scope"))[3]; + $machine->log("$scope address on $iface is $ip"); + return $ip; + } + + subtest "loopback address", sub { + $client->succeed("ping6 -c 1 ::1 >&2"); + $client->fail("ping6 -c 1 ::2 >&2"); + }; + + subtest "local link addressing", sub { + my $clientIp = waitForAddress $client, "eth1", "link"; + my $serverIp = waitForAddress $server, "eth1", "link"; + $client->succeed("ping6 -c 1 -I eth1 $clientIp >&2"); + $client->succeed("ping6 -c 1 -I eth1 $serverIp >&2"); + }; + + subtest "global addressing", sub { + my $clientIp = waitForAddress $client, "eth1", "global"; + my $serverIp = waitForAddress $server, "eth1", "global"; + $client->succeed("ping6 -c 1 $clientIp >&2"); + $client->succeed("ping6 -c 1 $serverIp >&2"); + $client->succeed("curl --fail -g http://[$serverIp]"); + $client->fail("curl --fail -g http://[$clientIp]"); + }; + + # TODO: test reachability of a machine on another network. + ''; + +} diff --git a/nixos/tests/kde4.nix b/nixos/tests/kde4.nix new file mode 100644 index 0000000000000..3fb35bbab0985 --- /dev/null +++ b/nixos/tests/kde4.nix @@ -0,0 +1,67 @@ +{ pkgs, ... }: + +{ + + machine = + { config, pkgs, ... }: + + { imports = [ ./common/user-account.nix ]; + + virtualisation.memorySize = 768; + + services.xserver.enable = true; + + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.documentRoot = "${pkgs.valgrind}/share/doc/valgrind/html"; + + services.xserver.displayManager.kdm.enable = true; + services.xserver.displayManager.kdm.extraConfig = + '' + [X-:0-Core] + AutoLoginEnable=true + AutoLoginUser=alice + AutoLoginPass=foobar + ''; + + services.xserver.desktopManager.kde4.enable = true; + + # Include most of KDE. We don't really test these here, but at + # least they should build. + environment.systemPackages = + [ pkgs.kde4.kdemultimedia + pkgs.kde4.kdegraphics + pkgs.kde4.kdeutils + pkgs.kde4.kdegames + pkgs.kde4.kdeedu + pkgs.kde4.kdeaccessibility + pkgs.kde4.kdeadmin + pkgs.kde4.kdenetwork + pkgs.kde4.kdetoys + pkgs.kde4.kdewebdev + ]; + }; + + testScript = + '' + $machine->waitUntilSucceeds("pgrep plasma-desktop"); + $machine->waitForWindow(qr/plasma-desktop/); + + # Check that logging in has given the user ownership of devices. + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 kwrite /var/log/messages &'"); + $machine->waitForWindow(qr/messages.*KWrite/); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 konqueror http://localhost/ &'"); + $machine->waitForWindow(qr/Valgrind.*Konqueror/); + + $machine->execute("su - alice -c 'DISPLAY=:0.0 gwenview ${pkgs.kde4.kde_wallpapers}/share/wallpapers/Hanami/contents/images/1280x1024.jpg &'"); + $machine->waitForWindow(qr/Gwenview/); + + $machine->sleep(10); + + $machine->screenshot("screen"); + ''; + +} diff --git a/nixos/tests/kexec.nix b/nixos/tests/kexec.nix new file mode 100644 index 0000000000000..b8da332b919b4 --- /dev/null +++ b/nixos/tests/kexec.nix @@ -0,0 +1,18 @@ +# Test whether fast reboots via kexec work. + +{ pkgs, ... }: + +{ + + machine = { config, pkgs, ... }: + { virtualisation.vlans = [ ]; }; + + testScript = + '' + $machine->waitForUnit("multi-user.target"); + $machine->execute("systemctl kexec &"); + $machine->{connected} = 0; + $machine->waitForUnit("multi-user.target"); + ''; + +} diff --git a/nixos/tests/login.nix b/nixos/tests/login.nix new file mode 100644 index 0000000000000..ed7d978671798 --- /dev/null +++ b/nixos/tests/login.nix @@ -0,0 +1,61 @@ +config: { pkgs, ... }: + +{ + + machine = config; + + testScript = + '' + $machine->waitForUnit("default.target"); + $machine->screenshot("postboot"); + + subtest "create user", sub { + $machine->succeed("useradd -m alice"); + $machine->succeed("(echo foobar; echo foobar) | passwd alice"); + }; + + # Check whether switching VTs works. + subtest "virtual console switching", sub { + $machine->sendKeys("alt-f2"); + $machine->waitUntilSucceeds("[ \$(fgconsole) = 2 ]"); + $machine->waitForUnit('getty@tty2.service'); + }; + + # Log in as alice on a virtual console. + subtest "virtual console login", sub { + $machine->sleep(2); # urgh: wait for username prompt + $machine->sendChars("alice\n"); + $machine->waitUntilSucceeds("pgrep login"); + $machine->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"); + }; + + # Check whether systemd gives and removes device ownership as + # needed. + subtest "device permissions", sub { + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + $machine->sendKeys("alt-f1"); + $machine->waitUntilSucceeds("[ \$(fgconsole) = 1 ]"); + $machine->fail("getfacl /dev/snd/timer | grep -q alice"); + $machine->succeed("chvt 2"); + $machine->waitUntilSucceeds("getfacl /dev/snd/timer | grep -q alice"); + }; + + # Log out. + subtest "virtual console logout", sub { + $machine->sendChars("exit\n"); + $machine->waitUntilFails("pgrep -u alice bash"); + $machine->screenshot("mingetty"); + }; + + # Check whether ctrl-alt-delete works. + subtest "ctrl-alt-delete", sub { + $machine->sendKeys("ctrl-alt-delete"); + $machine->waitForShutdown; + }; + ''; + +} diff --git a/nixos/tests/misc.nix b/nixos/tests/misc.nix new file mode 100644 index 0000000000000..e18a208fe4320 --- /dev/null +++ b/nixos/tests/misc.nix @@ -0,0 +1,63 @@ +# Miscellaneous small tests that don't warrant their own VM run. + +{ pkgs, ... }: + +{ + + machine = + { config, pkgs, ... }: + { swapDevices = pkgs.lib.mkOverride 0 + [ { device = "/root/swapfile"; size = 128; } ]; + environment.variables.EDITOR = pkgs.lib.mkOverride 0 "emacs"; + }; + + testScript = + '' + subtest "nixos-version", sub { + $machine->succeed("[ `nixos-version | wc -w` = 2 ]"); + }; + + subtest "nixos-rebuild", sub { + $machine->succeed("nixos-rebuild --help | grep 'Usage:'"); + }; + + # Sanity check for uid/gid assignment. + subtest "users-groups", sub { + $machine->succeed("[ `id -u messagebus` = 4 ]"); + $machine->succeed("[ `id -g messagebus` = 4 ]"); + $machine->succeed("[ `getent group users` = 'users:x:100:' ]"); + }; + + # Regression test for GMP aborts on QEMU. + subtest "gmp", sub { + $machine->succeed("expr 1 + 2"); + }; + + # Test that the swap file got created. + subtest "swapfile", sub { + $machine->waitForUnit("root-swapfile.swap"); + $machine->succeed("ls -l /root/swapfile | grep 134217728"); + }; + + # Test whether kernel.poweroff_cmd is set. + subtest "poweroff_cmd", sub { + $machine->succeed("[ -x \"\$(cat /proc/sys/kernel/poweroff_cmd)\" ]") + }; + + # Test whether the blkio controller is properly enabled. + subtest "blkio-cgroup", sub { + $machine->succeed("[ -n \"\$(cat /sys/fs/cgroup/blkio/blkio.sectors)\" ]") + }; + + # Test whether we have a reboot record in wtmp. + subtest "reboot-wtmp", sub { + $machine->succeed("last | grep reboot >&2"); + }; + + # Test whether we can override environment variables. + subtest "override-env-var", sub { + $machine->succeed('[ "$EDITOR" = emacs ]'); + }; + ''; + +} diff --git a/nixos/tests/mpich-example.c b/nixos/tests/mpich-example.c new file mode 100644 index 0000000000000..c48e3c45b72eb --- /dev/null +++ b/nixos/tests/mpich-example.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <stdlib.h> +#include <mpi.h> + +int +main (int argc, char *argv[]) +{ + int rank, size, length; + char name[BUFSIZ]; + + MPI_Init (&argc, &argv); + MPI_Comm_rank (MPI_COMM_WORLD, &rank); + MPI_Comm_size (MPI_COMM_WORLD, &size); + MPI_Get_processor_name (name, &length); + + printf ("%s: hello world from process %d of %d\n", name, rank, size); + + MPI_Finalize (); + + return EXIT_SUCCESS; +} diff --git a/nixos/tests/mpich.nix b/nixos/tests/mpich.nix new file mode 100644 index 0000000000000..d57512ebdfedd --- /dev/null +++ b/nixos/tests/mpich.nix @@ -0,0 +1,40 @@ +# Simple example to showcase distributed tests using NixOS VMs. + +{ pkgs, ... }: + +with pkgs; + +{ + nodes = { + master = + { config, pkgs, ... }: { + environment.systemPackages = [ gcc mpich2 ]; + #boot.kernelPackages = pkgs.kernelPackages_2_6_29; + }; + + slave = + { config, pkgs, ... }: { + environment.systemPackages = [ gcc mpich2 ]; + }; + }; + + # Start master/slave MPI daemons and compile/run a program that uses both + # nodes. + testScript = + '' + startAll; + + $master->succeed("echo 'MPD_SECRETWORD=secret' > /etc/mpd.conf"); + $master->succeed("chmod 600 /etc/mpd.conf"); + $master->succeed("mpd --daemon --ifhn=master --listenport=4444"); + + $slave->succeed("echo 'MPD_SECRETWORD=secret' > /etc/mpd.conf"); + $slave->succeed("chmod 600 /etc/mpd.conf"); + $slave->succeed("mpd --daemon --host=master --port=4444"); + + $master->succeed("mpicc -o example -Wall ${./mpich-example.c}"); + $slave->succeed("mpicc -o example -Wall ${./mpich-example.c}"); + + $master->succeed("mpiexec -n 2 ./example >&2"); + ''; +} diff --git a/nixos/tests/mysql-replication.nix b/nixos/tests/mysql-replication.nix new file mode 100644 index 0000000000000..28a1187dd184c --- /dev/null +++ b/nixos/tests/mysql-replication.nix @@ -0,0 +1,57 @@ +{ pkgs, ... }: + +let + replicateUser = "replicate"; + replicatePassword = "secret"; +in +{ + nodes = { + master = + { pkgs, config, ... }: + + { + services.mysql.enable = true; + services.mysql.replication.role = "master"; + services.mysql.initialDatabases = [ { name = "testdb"; schema = ./testdb.sql; } ]; + services.mysql.initialScript = pkgs.writeText "initmysql" + '' + create user '${replicateUser}'@'%' identified by '${replicatePassword}'; + grant replication slave on *.* to '${replicateUser}'@'%'; + ''; + }; + + slave1 = + { pkgs, config, nodes, ... }: + + { + services.mysql.enable = true; + services.mysql.replication.role = "slave"; + services.mysql.replication.serverId = 2; + services.mysql.replication.masterHost = nodes.master.config.networking.hostName; + services.mysql.replication.masterUser = replicateUser; + services.mysql.replication.masterPassword = replicatePassword; + }; + + slave2 = + { pkgs, config, nodes, ... }: + + { + services.mysql.enable = true; + services.mysql.replication.role = "slave"; + services.mysql.replication.serverId = 3; + services.mysql.replication.masterHost = nodes.master.config.networking.hostName; + services.mysql.replication.masterUser = replicateUser; + services.mysql.replication.masterPassword = replicatePassword; + }; + }; + + testScript = '' + startAll; + + $master->waitForUnit("mysql"); + $master->waitForUnit("mysql"); + $slave2->waitForUnit("mysql"); + $slave2->sleep(100); # Hopefully this is long enough!! + $slave2->succeed("echo 'use testdb; select * from tests' | mysql -u root -N | grep 4"); + ''; +} diff --git a/nixos/tests/mysql.nix b/nixos/tests/mysql.nix new file mode 100644 index 0000000000000..b48850738b722 --- /dev/null +++ b/nixos/tests/mysql.nix @@ -0,0 +1,22 @@ +{ pkgs, ... }: + +{ + nodes = { + master = + { pkgs, config, ... }: + + { + services.mysql.enable = true; + services.mysql.replication.role = "master"; + services.mysql.initialDatabases = [ { name = "testdb"; schema = ./testdb.sql; } ]; + }; + }; + + testScript = '' + startAll; + + $master->waitForUnit("mysql"); + $master->sleep(10); # Hopefully this is long enough!! + $master->succeed("echo 'use testdb; select * from tests' | mysql -u root -N | grep 4"); + ''; +} diff --git a/nixos/tests/nat.nix b/nixos/tests/nat.nix new file mode 100644 index 0000000000000..55d87ed4fa14d --- /dev/null +++ b/nixos/tests/nat.nix @@ -0,0 +1,77 @@ +# This is a simple distributed test involving a topology with two +# separate virtual networks - the "inside" and the "outside" - with a +# client on the inside network, a server on the outside network, and a +# router connected to both that performs Network Address Translation +# for the client. + +{ pkgs, ... }: + +{ + + nodes = + { client = + { config, pkgs, nodes, ... }: + { virtualisation.vlans = [ 1 ]; + networking.defaultGateway = + nodes.router.config.networking.interfaces.eth2.ipAddress; + }; + + router = + { config, pkgs, ... }: + { virtualisation.vlans = [ 2 1 ]; + networking.nat.enable = true; + networking.nat.internalIPs = "192.168.1.0/24"; + networking.nat.externalInterface = "eth1"; + }; + + server = + { config, pkgs, ... }: + { virtualisation.vlans = [ 2 ]; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.vsftpd.enable = true; + services.vsftpd.anonymousUser = true; + }; + }; + + testScript = + { nodes, ... }: + '' + startAll; + + # The router should have access to the server. + $server->waitForUnit("network.target"); + $server->waitForUnit("httpd"); + $router->waitForUnit("network.target"); + $router->succeed("curl --fail http://server/ >&2"); + + # The client should be also able to connect via the NAT router. + $router->waitForUnit("nat"); + $client->waitForUnit("network.target"); + $client->succeed("curl --fail http://server/ >&2"); + $client->succeed("ping -c 1 server >&2"); + + # Test whether passive FTP works. + $server->waitForUnit("vsftpd"); + $server->succeed("echo Hello World > /home/ftp/foo.txt"); + $client->succeed("curl -v ftp://server/foo.txt >&2"); + + # Test whether active FTP works. + $client->succeed("curl -v -P - ftp://server/foo.txt >&2"); + + # Test ICMP. + $client->succeed("ping -c 1 router >&2"); + $router->succeed("ping -c 1 client >&2"); + + # If we turn off NAT, the client shouldn't be able to reach the server. + $router->stopJob("nat"); + $client->fail("curl --fail --connect-timeout 5 http://server/ >&2"); + $client->fail("ping -c 1 server >&2"); + + # And make sure that restarting the NAT job works. + $router->succeed("systemctl start nat"); + $client->succeed("curl --fail http://server/ >&2"); + $client->succeed("ping -c 1 server >&2"); + ''; + +} diff --git a/nixos/tests/nfs.nix b/nixos/tests/nfs.nix new file mode 100644 index 0000000000000..ee65c298dd00f --- /dev/null +++ b/nixos/tests/nfs.nix @@ -0,0 +1,85 @@ +{ version }: + +{ pkgs, ... }: + +let + + client = + { config, pkgs, ... }: + { fileSystems = pkgs.lib.mkOverride 50 + [ { mountPoint = "/data"; + device = "server:${if version == 4 then "/" else "/data"}"; + fsType = "nfs"; + options = "vers=${toString version}"; + } + ]; + }; + +in + +{ + + nodes = + { client1 = client; + client2 = client; + + server = + { config, pkgs, ... }: + { services.nfs.server.enable = true; + services.nfs.server.exports = + '' + /data 192.168.1.0/255.255.255.0(rw,no_root_squash,no_subtree_check,fsid=0) + ''; + services.nfs.server.createMountPoints = true; + }; + }; + + testScript = + '' + $server->waitForUnit("nfsd"); + $server->waitForUnit("network.target"); + + startAll; + + $client1->waitForUnit("data.mount"); + $client1->succeed("echo bla > /data/foo"); + $server->succeed("test -e /data/foo"); + + $client2->waitForUnit("data.mount"); + $client2->succeed("echo bla > /data/bar"); + $server->succeed("test -e /data/bar"); + + # Test whether restarting ‘nfsd’ works correctly. + $server->succeed("systemctl restart nfsd"); + $client2->succeed("echo bla >> /data/bar"); # will take 90 seconds due to the NFS grace period + + # Test whether we can get a lock. + $client2->succeed("time flock -n -s /data/lock true"); + + # Test locking: client 1 acquires an exclusive lock, so client 2 + # should then fail to acquire a shared lock. + $client1->succeed("flock -x /data/lock -c 'touch locked; sleep 100000' &"); + $client1->waitForFile("locked"); + $client2->fail("flock -n -s /data/lock true"); + + # Test whether client 2 obtains the lock if we reset client 1. + $client2->succeed("flock -x /data/lock -c 'echo acquired; touch locked; sleep 100000' >&2 &"); + $client1->crash; + $client1->start; + $client2->waitForFile("locked"); + + # Test whether locks survive a reboot of the server. + $client1->waitForUnit("data.mount"); + $server->shutdown; + $server->start; + $client1->succeed("touch /data/xyzzy"); + $client1->fail("time flock -n -s /data/lock true"); + + # Test whether unmounting during shutdown happens quickly. + my $t1 = time; + $client1->shutdown; + my $duration = time - $t1; + die "shutdown took too long ($duration seconds)" if $duration > 30; + ''; + +} diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix new file mode 100644 index 0000000000000..16757cf9098e7 --- /dev/null +++ b/nixos/tests/openssh.nix @@ -0,0 +1,35 @@ +{ pkgs, ... }: + +{ + nodes = { + + server = + { config, pkgs, ... }: + + { + services.openssh.enable = true; + }; + + client = + { config, pkgs, ... }: { }; + + }; + + testScript = '' + startAll; + + my $key=`${pkgs.openssh}/bin/ssh-keygen -t dsa -f key -N ""`; + + $server->waitForUnit("sshd"); + + $server->succeed("mkdir -m 700 /root/.ssh"); + $server->copyFileFromHost("key.pub", "/root/.ssh/authorized_keys"); + + $client->succeed("mkdir -m 700 /root/.ssh"); + $client->copyFileFromHost("key", "/root/.ssh/id_dsa"); + $client->succeed("chmod 600 /root/.ssh/id_dsa"); + + $client->waitForUnit("network.target"); + $client->succeed("ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no server 'echo hello world' >&2"); + ''; +} diff --git a/nixos/tests/partition.nix b/nixos/tests/partition.nix new file mode 100644 index 0000000000000..7126e7255ef45 --- /dev/null +++ b/nixos/tests/partition.nix @@ -0,0 +1,227 @@ +{ pkgs, system, ... }: + +with pkgs.lib; + +let + ksExt = pkgs.writeText "ks-ext4" '' + clearpart --all --initlabel --drives=vdb + + part /boot --recommended --label=boot --fstype=ext2 --ondisk=vdb + part swap --recommended --label=swap --fstype=swap --ondisk=vdb + part /nix --size=500 --label=nix --fstype=ext3 --ondisk=vdb + part / --recommended --label=root --fstype=ext4 --ondisk=vdb + ''; + + ksBtrfs = pkgs.writeText "ks-btrfs" '' + clearpart --all --initlabel --drives=vdb,vdc + + part swap1 --recommended --label=swap1 --fstype=swap --ondisk=vdb + part swap2 --recommended --label=swap2 --fstype=swap --ondisk=vdc + + part btrfs.1 --grow --ondisk=vdb + part btrfs.2 --grow --ondisk=vdc + + btrfs / --data=0 --metadata=1 --label=root btrfs.1 btrfs.2 + ''; + + ksRaid = pkgs.writeText "ks-raid" '' + clearpart --all --initlabel --drives=vdb,vdc + + part raid.01 --size=200 --ondisk=vdb + part raid.02 --size=200 --ondisk=vdc + + part swap1 --size=500 --label=swap1 --fstype=swap --ondisk=vdb + part swap2 --size=500 --label=swap2 --fstype=swap --ondisk=vdc + + part raid.11 --grow --ondisk=vdb + part raid.12 --grow --ondisk=vdc + + raid /boot --level=1 --fstype=ext3 --device=md0 raid.01 raid.02 + raid / --level=1 --fstype=xfs --device=md1 raid.11 raid.12 + ''; + + ksRaidLvmCrypt = pkgs.writeText "ks-lvm-crypt" '' + clearpart --all --initlabel --drives=vdb,vdc + + part raid.1 --grow --ondisk=vdb + part raid.2 --grow --ondisk=vdc + + raid pv.0 --level=1 --encrypted --passphrase=x --device=md0 raid.1 raid.2 + + volgroup nixos pv.0 + + logvol /boot --size=200 --fstype=ext3 --name=boot --vgname=nixos + logvol swap --size=500 --fstype=swap --name=swap --vgname=nixos + logvol / --size=1000 --grow --fstype=ext4 --name=root --vgname=nixos + ''; +in { + machine = { config, pkgs, ... }: { + environment.systemPackages = [ + pkgs.pythonPackages.nixpart + pkgs.file pkgs.btrfsProgs pkgs.xfsprogs pkgs.lvm2 + ]; + virtualisation.emptyDiskImages = [ 4096 4096 ]; + }; + + testScript = '' + my $diskStart; + my @mtab; + + sub getMtab { + my $mounts = $machine->succeed("cat /proc/mounts"); + chomp $mounts; + return map [split], split /\n/, $mounts; + } + + sub parttest { + my ($desc, $code) = @_; + $machine->start; + $machine->waitForUnit("default.target"); + + # Gather mounts and superblock + @mtab = getMtab; + $diskStart = $machine->succeed("dd if=/dev/vda bs=512 count=1"); + + subtest($desc, $code); + $machine->shutdown; + } + + sub ensureSanity { + # Check whether the filesystem in /dev/vda is still intact + my $newDiskStart = $machine->succeed("dd if=/dev/vda bs=512 count=1"); + if ($diskStart ne $newDiskStart) { + $machine->log("Something went wrong, the partitioner wrote " . + "something into the first 512 bytes of /dev/vda!"); + die; + } + + # Check whether nixpart has unmounted anything + my @currentMtab = getMtab; + for my $mount (@mtab) { + my $path = $mount->[1]; + unless (grep { $_->[1] eq $path } @currentMtab) { + $machine->log("The partitioner seems to have unmounted $path."); + die; + } + } + } + + sub checkMount { + my $mounts = $machine->succeed("cat /proc/mounts"); + + } + + sub kickstart { + $machine->copyFileFromHost($_[0], "/kickstart"); + $machine->succeed("nixpart -v /kickstart"); + ensureSanity; + } + + sub ensurePartition { + my ($name, $match) = @_; + my $path = $name =~ /^\// ? $name : "/dev/disk/by-label/$name"; + my $out = $machine->succeed("file -Ls $path"); + my @matches = grep(/^$path: .*$match/i, $out); + if (!@matches) { + $machine->log("Partition on $path was expected to have a " . + "file system that matches $match, but instead has: $out"); + die; + } + } + + sub ensureNoPartition { + $machine->succeed("test ! -e /dev/$_[0]"); + } + + sub ensureMountPoint { + $machine->succeed("mountpoint $_[0]"); + } + + sub remountAndCheck { + $machine->nest("Remounting partitions:", sub { + # XXX: "findmnt -ARunl -oTARGET /mnt" seems to NOT print all mounts! + my $getmounts_cmd = "cat /proc/mounts | cut -d' ' -f2 | grep '^/mnt'"; + # Insert canaries first + my $canaries = $machine->succeed($getmounts_cmd . " | while read p;" . + " do touch \"\$p/canary\";" . + " echo \"\$p/canary\"; done"); + # Now unmount manually + $machine->succeed($getmounts_cmd . " | tac | xargs -r umount"); + # /mnt should be empty or non-existing + my $found = $machine->succeed("find /mnt -mindepth 1"); + chomp $found; + if ($found) { + $machine->log("Cruft found in /mnt:\n$found"); + die; + } + # Try to remount with nixpart + $machine->succeed("nixpart -vm /kickstart"); + ensureMountPoint("/mnt"); + # Check if our beloved canaries are dead + chomp $canaries; + $machine->nest("Checking canaries:", sub { + for my $canary (split /\n/, $canaries) { + $machine->succeed("test -e '$canary'"); + } + }); + }); + } + + parttest "ext2, ext3 and ext4 filesystems", sub { + kickstart("${ksExt}"); + ensurePartition("boot", "ext2"); + ensurePartition("swap", "swap"); + ensurePartition("nix", "ext3"); + ensurePartition("root", "ext4"); + ensurePartition("/dev/vdb4", "boot sector"); + ensureNoPartition("vdb6"); + ensureNoPartition("vdc1"); + remountAndCheck; + ensureMountPoint("/mnt/boot"); + ensureMountPoint("/mnt/nix"); + }; + + parttest "btrfs filesystem", sub { + $machine->succeed("modprobe btrfs"); + kickstart("${ksBtrfs}"); + ensurePartition("swap1", "swap"); + ensurePartition("swap2", "swap"); + ensurePartition("/dev/vdb2", "btrfs"); + ensurePartition("/dev/vdc2", "btrfs"); + ensureNoPartition("vdb3"); + ensureNoPartition("vdc3"); + remountAndCheck; + }; + + parttest "RAID1 with XFS", sub { + kickstart("${ksRaid}"); + ensurePartition("swap1", "swap"); + ensurePartition("swap2", "swap"); + ensurePartition("/dev/md0", "ext3"); + ensurePartition("/dev/md1", "xfs"); + ensureNoPartition("vdb4"); + ensureNoPartition("vdc4"); + ensureNoPartition("md2"); + remountAndCheck; + ensureMountPoint("/mnt/boot"); + }; + + parttest "RAID1 with LUKS and LVM", sub { + kickstart("${ksRaidLvmCrypt}"); + ensurePartition("/dev/vdb1", "data"); + ensureNoPartition("vdb2"); + ensurePartition("/dev/vdc1", "data"); + ensureNoPartition("vdc2"); + + ensurePartition("/dev/md0", "luks"); + ensureNoPartition("md1"); + + ensurePartition("/dev/nixos/boot", "ext3"); + ensurePartition("/dev/nixos/swap", "swap"); + ensurePartition("/dev/nixos/root", "ext4"); + + remountAndCheck; + ensureMountPoint("/mnt/boot"); + }; + ''; +} diff --git a/nixos/tests/printing.nix b/nixos/tests/printing.nix new file mode 100644 index 0000000000000..13cc3115d50e6 --- /dev/null +++ b/nixos/tests/printing.nix @@ -0,0 +1,90 @@ +# Test printing via CUPS. + +{ pkgs, ... }: + +{ + + nodes = { + + server = + { config, pkgs, ... }: + { services.printing.enable = true; + services.printing.cupsdConf = + '' + Listen server:631 + <Location /> + Order allow,deny + Allow from all + </Location> + ''; + }; + + client = + { config, pkgs, nodes, ... }: + { services.printing.enable = true; + }; + + }; + + testScript = + '' + startAll; + + # Make sure that cups is up on both sides. + $server->waitForUnit("cupsd.service"); + $client->waitForUnit("cupsd.service"); + $client->succeed("lpstat -r") =~ /scheduler is running/ or die; + $client->succeed("lpstat -H") =~ "/var/run/cups/cups.sock" or die; + $client->succeed("curl --fail http://localhost:631/"); + $client->succeed("curl --fail http://server:631/"); + $server->fail("curl --fail http://client:631/"); + + # Add a HP Deskjet printer connected via USB to the server. + $server->succeed("lpadmin -p DeskjetLocal -v usb://HP/Deskjet%205400%20series?serial=TH93I152S123XY -m 'drv:///sample.drv/deskjet.ppd' -E"); + + # Add it to the client as well via IPP. + $client->succeed("lpadmin -p DeskjetRemote -v ipp://server/printers/DeskjetLocal -m 'drv:///sample.drv/deskjet.ppd' -E"); + $client->succeed("lpadmin -d DeskjetRemote"); + + # Do some status checks. + $client->succeed("lpstat -a") =~ /DeskjetRemote accepting requests/ or die; + $client->succeed("lpstat -h server -a") =~ /DeskjetLocal accepting requests/ or die; + $client->succeed("cupsdisable DeskjetRemote"); + $client->succeed("lpq") =~ /DeskjetRemote is not ready.*no entries/s or die; + $client->succeed("cupsenable DeskjetRemote"); + $client->succeed("lpq") =~ /DeskjetRemote is ready.*no entries/s or die; + + # Test printing various file types. + foreach my $file ("${pkgs.groff}/share/doc/*/examples/mom/typesetting.pdf", + "${pkgs.groff}/share/doc/*/meref.ps", + "${pkgs.cups}/share/doc/cups/images/cups.png", + "${pkgs.xz}/share/doc/xz/faq.txt") + { + $file =~ /([^\/]*)$/; my $fn = $1; + + subtest "print $fn", sub { + + # Print the file on the client. + $client->succeed("lp $file"); + $client->succeed("lpq") =~ /active.*root.*$fn/ or die; + + # Ensure that a raw PCL file appeared in the server's queue + # (showing that the right filters have been applied). Of + # course, since there is no actual USB printer attached, the + # file will stay in the queue forever. + $server->waitForFile("/var/spool/cups/d*-*"); + $server->succeed("lpq -a") =~ /remroot.*$fn/ or die; + $server->succeed("hexdump -C -n2 /var/spool/cups/d*-*") =~ /1b 45/ or die; # 1b 45 = printer reset + + # Delete the job on the client. It should disappear on the + # server as well. + $client->succeed("lprm"); + $client->succeed("lpq -a") =~ /no entries/; + Machine::retry sub { + return 1 if $server->succeed("lpq -a") =~ /no entries/; + }; + }; + } + ''; + +} diff --git a/nixos/tests/proxy.nix b/nixos/tests/proxy.nix new file mode 100644 index 0000000000000..3b79c16ea2c42 --- /dev/null +++ b/nixos/tests/proxy.nix @@ -0,0 +1,94 @@ +{ pkgs, ... }: + +let + + backend = + { config, pkgs, ... }: + + { + services.openssh.enable = true; + + services.httpd.enable = true; + services.httpd.adminAddr = "foo@example.org"; + services.httpd.documentRoot = "${pkgs.valgrind}/share/doc/valgrind/html"; + }; + +in + +{ + + nodes = + { proxy = + { config, pkgs, nodes, ... }: + + { + services.httpd.enable = true; + services.httpd.adminAddr = "bar@example.org"; + services.httpd.extraModules = ["proxy_balancer"]; + + services.httpd.extraConfig = + '' + ExtendedStatus on + + <Location /server-status> + Order deny,allow + Allow from all + SetHandler server-status + </Location> + + <Proxy balancer://cluster> + Allow from all + BalancerMember http://${nodes.backend1.config.networking.hostName} retry=0 + BalancerMember http://${nodes.backend2.config.networking.hostName} retry=0 + </Proxy> + + ProxyStatus full + ProxyPass /server-status ! + ProxyPass / balancer://cluster/ + ProxyPassReverse / balancer://cluster/ + + # For testing; don't want to wait forever for dead backend servers. + ProxyTimeout 5 + ''; + }; + + backend1 = backend; + backend2 = backend; + + client = { config, pkgs, ... }: { }; + }; + + testScript = + '' + startAll; + + $proxy->waitForUnit("httpd"); + $backend1->waitForUnit("httpd"); + $backend2->waitForUnit("httpd"); + + # With the back-ends up, the proxy should work. + $client->succeed("curl --fail http://proxy/"); + + $client->succeed("curl --fail http://proxy/server-status"); + + # Block the first back-end. + $backend1->block; + + # The proxy should still work. + $client->succeed("curl --fail http://proxy/"); + + $client->succeed("curl --fail http://proxy/"); + + # Block the second back-end. + $backend2->block; + + # Now the proxy should fail as well. + $client->fail("curl --fail http://proxy/"); + + # But if the second back-end comes back, the proxy should start + # working again. + $backend2->unblock; + $client->succeed("curl --fail http://proxy/"); + ''; + +} diff --git a/nixos/tests/quake3.nix b/nixos/tests/quake3.nix new file mode 100644 index 0000000000000..925011077805b --- /dev/null +++ b/nixos/tests/quake3.nix @@ -0,0 +1,79 @@ +{ pkgs, ... }: + +let + + # Build Quake with coverage instrumentation. + overrides = pkgs: + rec { + quake3game = pkgs.quake3game.override (args: { + stdenv = pkgs.stdenvAdapters.addCoverageInstrumentation args.stdenv; + }); + }; + +in + +rec { + + client = + { config, pkgs, ... }: + + { imports = [ ./common/x11.nix ]; + services.xserver.driSupport = true; + services.xserver.defaultDepth = pkgs.lib.mkOverride 0 16; + environment.systemPackages = [ pkgs.quake3demo ]; + nixpkgs.config.packageOverrides = overrides; + }; + + nodes = + { server = + { config, pkgs, ... }: + + { jobs."quake3-server" = + { startOn = "startup"; + exec = + "${pkgs.quake3demo}/bin/quake3-server '+set g_gametype 0' " + + "'+map q3dm7' '+addbot grunt' '+addbot daemia' 2> /tmp/log"; + }; + nixpkgs.config.packageOverrides = overrides; + }; + + client1 = client; + client2 = client; + }; + + testScript = + '' + startAll; + + $server->waitForUnit("quake3-server"); + $client1->waitForX; + $client2->waitForX; + + $client1->execute("quake3 '+set r_fullscreen 0' '+set name Foo' '+connect server' &"); + $client2->execute("quake3 '+set r_fullscreen 0' '+set name Bar' '+connect server' &"); + + $server->waitUntilSucceeds("grep -q 'Foo.*entered the game' /tmp/log"); + $server->waitUntilSucceeds("grep -q 'Bar.*entered the game' /tmp/log"); + + $server->sleep(10); # wait for a while to get a nice screenshot + + $client1->block(); + + $server->sleep(20); + + $client1->screenshot("screen1"); + $client2->screenshot("screen2"); + + $client1->unblock(); + + $server->sleep(10); + + $client1->screenshot("screen3"); + $client2->screenshot("screen4"); + + $client1->shutdown(); + $client2->shutdown(); + $server->stopJob("quake3-server"); + ''; + +} diff --git a/nixos/tests/run-in-machine.nix b/nixos/tests/run-in-machine.nix new file mode 100644 index 0000000000000..75bd161ec9efb --- /dev/null +++ b/nixos/tests/run-in-machine.nix @@ -0,0 +1,10 @@ +{ nixpkgs ? <nixpkgs> +, system ? builtins.currentSystem +}: + +with import ../lib/testing.nix { inherit system; }; + +runInMachine { + drv = (import nixpkgs { inherit system; }).aterm; + machine = { config, pkgs, ... }: { services.sshd.enable = true; }; +} diff --git a/nixos/tests/simple.nix b/nixos/tests/simple.nix new file mode 100644 index 0000000000000..eee13a1013345 --- /dev/null +++ b/nixos/tests/simple.nix @@ -0,0 +1,11 @@ +{ pkgs, ... }: + +{ + machine = { config, pkgs, ... }: { }; + + testScript = + '' + startAll; + $machine->shutdown; + ''; +} diff --git a/nixos/tests/subversion.nix b/nixos/tests/subversion.nix new file mode 100644 index 0000000000000..309da90c5df13 --- /dev/null +++ b/nixos/tests/subversion.nix @@ -0,0 +1,117 @@ +{ pkgs, ... }: + +let + + # Build some packages with coverage instrumentation. + overrides = pkgs: + with pkgs.stdenvAdapters; + let + do = pkg: pkg.override (args: { + stdenv = addCoverageInstrumentation args.stdenv; + }); + in + rec { + apr = do pkgs.apr; + aprutil = do pkgs.aprutil; + apacheHttpd = do pkgs.apacheHttpd; + mod_python = do pkgs.mod_python; + subversion = do pkgs.subversion; + + # To build the kernel with coverage instrumentation, we need a + # special patch to make coverage data available under /proc. + linux = pkgs.linux.override (orig: { + stdenv = cleanupBuildTree (keepBuildTree orig.stdenv); + extraConfig = + '' + GCOV_KERNEL y + GCOV_PROFILE_ALL y + ''; + }); + }; + +in + +{ + + nodes = + { webserver = + { config, pkgs, ... }: + + { + services.httpd.enable = true; + services.httpd.adminAddr = "e.dolstra@tudelft.nl"; + services.httpd.extraSubservices = + [ { function = import <services/subversion>; + urlPrefix = ""; + dataDir = "/data/subversion"; + userCreationDomain = "192.168.0.0/16"; + } + ]; + nixpkgs.config.packageOverrides = overrides; + }; + + client = + { config, pkgs, ... }: + + { + environment.systemPackages = [ pkgs.subversion ]; + nixpkgs.config.packageOverrides = overrides; + }; + + }; + + testScript = + '' + startAll; + + $webserver->waitForOpenPort(80); + + print STDERR $client->succeed("svn --version"); + + print STDERR $client->succeed("curl --fail http://webserver/"); + + # Create a new user through the web interface. + $client->succeed("curl --fail -F username=alice -F fullname='Alice Lastname' -F address=alice\@example.org -F password=foobar -F password_again=foobar http://webserver/repoman/adduser"); + + # Let Alice create a new repository. + $client->succeed("curl --fail -u alice:foobar --form repo=xyzzy --form description=Xyzzy http://webserver/repoman/create"); + + $client->succeed("curl --fail http://webserver/") =~ /alice/ or die; + + # Let Alice do a checkout. + my $svnFlags = "--non-interactive --username alice --password foobar"; + $client->succeed("svn co $svnFlags http://webserver/repos/xyzzy wc"); + $client->succeed("echo hello > wc/world"); + $client->succeed("svn add wc/world"); + $client->succeed("svn ci $svnFlags -m 'Added world.' wc/world"); + + # Create a new user on the server through the create-user.pl script. + $webserver->execute("svn-server-create-user.pl bob bob\@example.org Bob"); + $webserver->succeed("svn-server-resetpw.pl bob fnord"); + $client->succeed("curl --fail http://webserver/") =~ /bob/ or die; + + # Bob should not have access to the repo. + my $svnFlagsBob = "--non-interactive --username bob --password fnord"; + $client->fail("svn co $svnFlagsBob http://webserver/repos/xyzzy wc2"); + + # Bob should not be able change the ACLs of the repo. + # !!! Repoman should really return a 403 here. + $client->succeed("curl --fail -u bob:fnord -F description=Xyzzy -F readers=alice,bob -F writers=alice -F watchers= -F tardirs= http://webserver/repoman/update/xyzzy") + =~ /not authorised/ or die; + + # Give Bob access. + $client->succeed("curl --fail -u alice:foobar -F description=Xyzzy -F readers=alice,bob -F writers=alice -F watchers= -F tardirs= http://webserver/repoman/update/xyzzy"); + + # So now his checkout should succeed. + $client->succeed("svn co $svnFlagsBob http://webserver/repos/xyzzy wc2"); + + # Test ViewVC and WebSVN + $client->succeed("curl --fail -u alice:foobar http://webserver/viewvc/xyzzy"); + $client->succeed("curl --fail -u alice:foobar http://webserver/websvn/xyzzy"); + $client->succeed("curl --fail -u alice:foobar http://webserver/repos-xml/xyzzy"); + + # Stop Apache to gather all the coverage data. + $webserver->stopJob("httpd"); + ''; + +} diff --git a/nixos/tests/test-config-examples.sh b/nixos/tests/test-config-examples.sh new file mode 100755 index 0000000000000..1ba2f841c41d9 --- /dev/null +++ b/nixos/tests/test-config-examples.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# This script try to evaluate all configurations which are stored in +# doc/config-examples. This script is useful to ensure that examples are +# working with the current system. + +pwd=$(pwd) +set -xe +for i in ../doc/config-examples/*.nix; do + NIXOS_CONFIG="$pwd/$i" nix-instantiate \ + --eval-only --xml --strict > /dev/null 2>&1 \ + ../default.nix -A system +done +set +xe diff --git a/nixos/tests/testdb.sql b/nixos/tests/testdb.sql new file mode 100644 index 0000000000000..4fb28fea3df9e --- /dev/null +++ b/nixos/tests/testdb.sql @@ -0,0 +1,10 @@ +create table tests +( Id INTEGER NOT NULL, + Name VARCHAR(255) NOT NULL, + primary key(Id) +); + +insert into tests values (1, 'a'); +insert into tests values (2, 'b'); +insert into tests values (3, 'c'); +insert into tests values (4, 'd'); diff --git a/nixos/tests/tomcat.nix b/nixos/tests/tomcat.nix new file mode 100644 index 0000000000000..c25276aa424e5 --- /dev/null +++ b/nixos/tests/tomcat.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: + +{ + nodes = { + server = + { pkgs, config, ... }: + + { + services.tomcat.enable = true; + services.httpd.enable = true; + services.httpd.adminAddr = "foo@bar.com"; + services.httpd.extraSubservices = [ + { serviceType = "tomcat-connector"; + stateDir = "/var/run/httpd"; + logDir = "/var/log/httpd"; + } + ]; + }; + + client = { }; + }; + + testScript = '' + startAll; + + $server->waitForUnit("tomcat"); + $server->sleep(30); # Dirty, but it takes a while before Tomcat handles to requests properly + $client->waitForUnit("network.target"); + $client->succeed("curl --fail http://server/examples/servlets/servlet/HelloWorldExample"); + $client->succeed("curl --fail http://server/examples/jsp/jsp2/simpletag/hello.jsp"); + ''; +} diff --git a/nixos/tests/trac.nix b/nixos/tests/trac.nix new file mode 100644 index 0000000000000..72442c885acec --- /dev/null +++ b/nixos/tests/trac.nix @@ -0,0 +1,71 @@ +{ pkgs, ... }: + +{ + nodes = { + storage = + { config, pkgs, ... }: + { services.nfs.server.enable = true; + services.nfs.server.exports = '' + /repos 192.168.1.0/255.255.255.0(rw,no_root_squash) + ''; + services.nfs.server.createMountPoints = true; + }; + + postgresql = + { config, pkgs, ... }: + { services.postgresql.enable = true; + services.postgresql.package = pkgs.postgresql92; + services.postgresql.enableTCPIP = true; + services.postgresql.authentication = '' + # Generated file; do not edit! + local all all trust + host all all 127.0.0.1/32 trust + host all all ::1/128 trust + host all all 192.168.1.0/24 trust + ''; + }; + + webserver = + { config, pkgs, ... }: + { fileSystems = pkgs.lib.mkOverride 50 + [ { mountPoint = "/repos"; + device = "storage:/repos"; + fsType = "nfs"; + } + ]; + services.httpd.enable = true; + services.httpd.adminAddr = "root@localhost"; + services.httpd.extraSubservices = [ { serviceType = "trac"; } ]; + environment.systemPackages = [ pkgs.pythonPackages.trac pkgs.subversion ]; + }; + + client = + { config, pkgs, ... }: + { imports = [ ./common/x11.nix ]; + services.xserver.desktopManager.kde4.enable = true; + }; + }; + + testScript = + '' + startAll; + + $postgresql->waitForUnit("postgresql"); + $postgresql->succeed("createdb trac"); + + $webserver->succeed("mkdir -p /repos/trac"); + $webserver->succeed("svnadmin create /repos/trac"); + + $webserver->waitForUnit("httpd"); + $webserver->waitForFile("/var/trac"); + $webserver->succeed("mkdir -p /var/trac/projects/test"); + $webserver->succeed("PYTHONPATH=${pkgs.pythonPackages.psycopg2}/lib/${pkgs.python.libPrefix}/site-packages trac-admin /var/trac/projects/test initenv Test postgres://root\@postgresql/trac svn /repos/trac"); + + $client->waitForX; + $client->execute("konqueror http://webserver/projects/test &"); + $client->waitForWindow(qr/Test.*Konqueror/); + $client->sleep(30); # loading takes a long time + + $client->screenshot("screen"); + ''; +} diff --git a/nixos/tests/xfce.nix b/nixos/tests/xfce.nix new file mode 100644 index 0000000000000..9f9692f8a014d --- /dev/null +++ b/nixos/tests/xfce.nix @@ -0,0 +1,32 @@ +{ pkgs, ... }: + +{ + + machine = + { config, pkgs, ... }: + + { imports = [ ./common/user-account.nix ]; + + services.xserver.enable = true; + + services.xserver.displayManager.auto.enable = true; + services.xserver.displayManager.auto.user = "alice"; + + services.xserver.desktopManager.xfce.enable = true; + }; + + testScript = + '' + $machine->waitForWindow(qr/xfce4-panel/); + $machine->sleep(10); + + # Check that logging in has given the user ownership of devices. + $machine->succeed("getfacl /dev/snd/timer | grep -q alice"); + + $machine->succeed("su - alice -c 'DISPLAY=:0.0 xfce4-terminal &'"); + $machine->waitForWindow(qr/Terminal/); + $machine->sleep(10); + $machine->screenshot("screen"); + ''; + +} |