summaryrefslogtreecommitdiffstats
path: root/plugins/t
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:48:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:48:22 +0000
commit7373ce3d6988706388f136e1c06afd20a3e8d5be (patch)
treee9ae5af7d102667e5706187646db45de8238e8c4 /plugins/t
parentInitial commit. (diff)
downloadmonitoring-plugins-7373ce3d6988706388f136e1c06afd20a3e8d5be.tar.xz
monitoring-plugins-7373ce3d6988706388f136e1c06afd20a3e8d5be.zip
Adding upstream version 2.3.5.upstream/2.3.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--plugins/t/check_apt.t106
-rw-r--r--plugins/t/check_apt_input/debian14
-rw-r--r--plugins/t/check_apt_input/debian237
-rw-r--r--plugins/t/check_apt_input/debian342
-rw-r--r--plugins/t/check_apt_input/ubuntu114
-rw-r--r--plugins/t/check_apt_input/ubuntu254
-rw-r--r--plugins/t/check_by_ssh.t153
-rw-r--r--plugins/t/check_cluster.t82
-rw-r--r--plugins/t/check_curl.t213
-rw-r--r--plugins/t/check_dbi.t103
-rw-r--r--plugins/t/check_dig.t98
-rw-r--r--plugins/t/check_disk.t378
-rw-r--r--plugins/t/check_dns.t115
-rw-r--r--plugins/t/check_dummy.t54
-rw-r--r--plugins/t/check_fping.t34
-rw-r--r--plugins/t/check_ftp.t28
-rw-r--r--plugins/t/check_hpjd.t71
-rw-r--r--plugins/t/check_http.t190
-rw-r--r--plugins/t/check_imap.t38
-rw-r--r--plugins/t/check_jabber.t50
-rw-r--r--plugins/t/check_ldap.t71
-rw-r--r--plugins/t/check_load.t43
-rw-r--r--plugins/t/check_mysql.t74
-rw-r--r--plugins/t/check_mysql_query.t58
-rw-r--r--plugins/t/check_nagios.nagios1.status.log5
-rw-r--r--plugins/t/check_nagios.nagios2.status.dat127
-rw-r--r--plugins/t/check_nagios.t92
-rw-r--r--plugins/t/check_ntp.t110
-rw-r--r--plugins/t/check_ping.t109
-rw-r--r--plugins/t/check_pop.t55
-rw-r--r--plugins/t/check_procs.t49
-rw-r--r--plugins/t/check_smtp.t84
-rw-r--r--plugins/t/check_snmp.t176
-rw-r--r--plugins/t/check_ssh.t41
-rw-r--r--plugins/t/check_swap.t31
-rw-r--r--plugins/t/check_tcp.t55
-rw-r--r--plugins/t/check_time.t36
-rw-r--r--plugins/t/check_udp.t71
-rw-r--r--plugins/t/check_users.t30
-rw-r--r--plugins/t/negate.t90
-rw-r--r--plugins/tests/certs/.gitignore2
-rw-r--r--plugins/tests/certs/client-cert.pem22
-rw-r--r--plugins/tests/certs/client-key.pem28
-rw-r--r--plugins/tests/certs/clientca-cert.pem25
-rw-r--r--plugins/tests/certs/clientca-key.pem28
-rw-r--r--plugins/tests/certs/clientchain-cert.pem45
-rw-r--r--plugins/tests/certs/clientchain-key.pem28
-rw-r--r--plugins/tests/certs/clientintermediate-cert.pem23
-rw-r--r--plugins/tests/certs/clientintermediate-key.pem28
-rw-r--r--plugins/tests/certs/expired-cert.pem24
-rw-r--r--plugins/tests/certs/expired-key.pem28
-rw-r--r--plugins/tests/certs/ext.cnf2
-rwxr-xr-xplugins/tests/certs/generate-certs.sh63
-rw-r--r--plugins/tests/certs/server-cert.pem24
-rw-r--r--plugins/tests/certs/server-key.pem28
-rwxr-xr-xplugins/tests/check_curl.t526
-rwxr-xr-xplugins/tests/check_http.t581
-rwxr-xr-xplugins/tests/check_nt.t80
-rwxr-xr-xplugins/tests/check_procs.t148
-rwxr-xr-xplugins/tests/check_snmp.t286
-rw-r--r--plugins/tests/check_snmp_agent.pl111
-rw-r--r--plugins/tests/conf/snmpd.conf23
-rw-r--r--plugins/tests/var/ps-axwo.darwin96
-rw-r--r--plugins/tests/var/ps-axwo.debian219
-rw-r--r--plugins/tests/var/root1
65 files changed, 5740 insertions, 0 deletions
diff --git a/plugins/t/check_apt.t b/plugins/t/check_apt.t
new file mode 100644
index 0000000..430eb53
--- /dev/null
+++ b/plugins/t/check_apt.t
@@ -0,0 +1,106 @@
+#!/usr/bin/perl -w -I ..
+#
+# Test check_apt using input files.
+# Contributed by Alex Bradley, October 2012
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+sub make_result_regexp {
+ my ($warning, $critical) = @_;
+ my $status;
+ if ($warning == 0 && $critical == 0) {
+ $status = "OK";
+ } elsif ($critical == 0) {
+ $status = "WARNING";
+ } else {
+ $status = "CRITICAL";
+ }
+ return sprintf('/^APT %s: %d packages available for upgrade \(%d critical updates\)\. |available_upgrades=%d;;;0 critical_updates=%d;;;0$/',
+ $status, $warning, $critical, $warning, $critical);
+}
+
+if (-x "./check_apt") {
+ plan tests => 36;
+} else {
+ plan skip_all => "No check_apt compiled";
+}
+
+my $result;
+
+my $testfile_command = "./check_apt %s --input-file=t/check_apt_input/%s";
+
+$result = NPTest->testCmd( sprintf($testfile_command, "", "debian1") );
+is( $result->return_code, 0, "No upgrades" );
+like( $result->output, make_result_regexp(0, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "", "debian2") );
+is( $result->return_code, 1, "Debian apt output, warning" );
+like( $result->output, make_result_regexp(13, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian2") );
+is( $result->return_code, 0, "Debian apt output, no critical" );
+like( $result->output, make_result_regexp(13, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "", "debian3") );
+is( $result->return_code, 2, "Debian apt output, some critical" );
+like( $result->output, make_result_regexp(19, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-o", "debian3") );
+is( $result->return_code, 2, "Debian apt output, some critical" );
+like( $result->output, make_result_regexp(19, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-c '^[^\\(]*\\(.* (Debian-Security:|Ubuntu:[^/]*/[^-]*-security)'", "debian3") );
+is( $result->return_code, 2, "Debian apt output - should have same result when default security regexp specified via -c" );
+like( $result->output, make_result_regexp(19, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-i libc6", "debian3") );
+is( $result->return_code, 1, "Debian apt output, filter for libc6" );
+like( $result->output, make_result_regexp(3, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-i libc6", "debian3") );
+is( $result->return_code, 1, "Debian apt output, filter for libc6, not critical" );
+like( $result->output, make_result_regexp(3, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-i libc6 -i xen", "debian3") );
+is( $result->return_code, 2, "Debian apt output, filter for libc6 and xen" );
+like( $result->output, make_result_regexp(9, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-i libc6 -i xen -i linux", "debian3") );
+is( $result->return_code, 2, "Debian apt output, filter for libc6, xen, linux" );
+like( $result->output, make_result_regexp(12, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-e libc6", "debian3") );
+is( $result->return_code, 2, "Debian apt output, filter out libc6" );
+like( $result->output, make_result_regexp(16, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-e libc6 -o", "debian3") );
+is( $result->return_code, 2, "Debian apt output, filter out libc6, critical" );
+like( $result->output, make_result_regexp(16, 4), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-e libc6 -e xen", "debian3") );
+is( $result->return_code, 1, "Debian apt output, filter out libc6 and xen" );
+like( $result->output, make_result_regexp(10, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-e libc6 -e xen -e linux", "debian3") );
+is( $result->return_code, 1, "Debian apt output, filter out libc6, xen, linux" );
+like( $result->output, make_result_regexp(7, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-c Debian-Security -c linux", "debian3") );
+is( $result->return_code, 2, "Debian apt output, critical on Debian-Security or linux" );
+like( $result->output, make_result_regexp(19, 9), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "-i lib -i linux -e gc1c -c linux-image", "debian3") );
+is( $result->return_code, 2, "Debian apt output, include lib and linux, exclude gc1c, critical on linux-image" );
+like( $result->output, make_result_regexp(10, 2), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "", "ubuntu1") );
+is( $result->return_code, 1, "Ubuntu apt output, warning" );
+like( $result->output, make_result_regexp(5, 0), "Output correct" );
+
+$result = NPTest->testCmd( sprintf($testfile_command, "", "ubuntu2") );
+is( $result->return_code, 2, "Ubuntu apt output, some critical" );
+like( $result->output, make_result_regexp(25, 14), "Output correct" );
+
diff --git a/plugins/t/check_apt_input/debian1 b/plugins/t/check_apt_input/debian1
new file mode 100644
index 0000000..317e7ea
--- /dev/null
+++ b/plugins/t/check_apt_input/debian1
@@ -0,0 +1,4 @@
+NOTE: This is only a simulation!
+ apt-get needs root privileges for real execution.
+ Keep also in mind that locking is deactivated,
+ so don't depend on the relevance to the real current situation!
diff --git a/plugins/t/check_apt_input/debian2 b/plugins/t/check_apt_input/debian2
new file mode 100644
index 0000000..effd155
--- /dev/null
+++ b/plugins/t/check_apt_input/debian2
@@ -0,0 +1,37 @@
+NOTE: This is only a simulation!
+ apt-get needs root privileges for real execution.
+ Keep also in mind that locking is deactivated,
+ so don't depend on the relevance to the real current situation!
+Reading package lists... Done
+Building dependency tree
+Reading state information... Done
+The following packages will be upgraded:
+ base-files debian-archive-keyring dpkg firmware-linux-free libc-bin libc-dev-bin libc6 libc6-dev linux-base
+ linux-image-2.6.32-5-xen-amd64 linux-libc-dev locales lockfile-progs
+13 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
+Inst base-files [6.0squeeze5] (6.0squeeze6 Debian:6.0.6/stable [amd64])
+Conf base-files (6.0squeeze6 Debian:6.0.6/stable [amd64])
+Inst dpkg [1.15.8.12] (1.15.8.13 Debian:6.0.6/stable [amd64])
+Conf dpkg (1.15.8.13 Debian:6.0.6/stable [amd64])
+Inst linux-base [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [all])
+Inst linux-image-2.6.32-5-xen-amd64 [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [amd64])
+Inst debian-archive-keyring [2010.08.28] (2010.08.28+squeeze1 Debian:6.0.6/stable [all])
+Conf debian-archive-keyring (2010.08.28+squeeze1 Debian:6.0.6/stable [all])
+Inst libc6-dev [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64]) []
+Inst libc-dev-bin [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64]) []
+Inst linux-libc-dev [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [amd64]) []
+Inst libc-bin [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64]) [libc6:amd64 ]
+Conf libc-bin (2.11.3-4 Debian:6.0.6/stable [amd64]) [libc6:amd64 ]
+Inst libc6 [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64])
+Conf libc6 (2.11.3-4 Debian:6.0.6/stable [amd64])
+Inst locales [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [all])
+Inst firmware-linux-free [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [all])
+Inst lockfile-progs [0.1.15] (0.1.15+squeeze1 Debian:6.0.6/stable [amd64])
+Conf linux-base (2.6.32-46 Debian:6.0.6/stable [all])
+Conf linux-image-2.6.32-5-xen-amd64 (2.6.32-46 Debian:6.0.6/stable [amd64])
+Conf libc-dev-bin (2.11.3-4 Debian:6.0.6/stable [amd64])
+Conf linux-libc-dev (2.6.32-46 Debian:6.0.6/stable [amd64])
+Conf libc6-dev (2.11.3-4 Debian:6.0.6/stable [amd64])
+Conf locales (2.11.3-4 Debian:6.0.6/stable [all])
+Conf firmware-linux-free (2.6.32-46 Debian:6.0.6/stable [all])
+Conf lockfile-progs (0.1.15+squeeze1 Debian:6.0.6/stable [amd64])
diff --git a/plugins/t/check_apt_input/debian3 b/plugins/t/check_apt_input/debian3
new file mode 100644
index 0000000..719dce9
--- /dev/null
+++ b/plugins/t/check_apt_input/debian3
@@ -0,0 +1,42 @@
+NOTE: This is only a simulation!
+ apt-get needs root privileges for real execution.
+ Keep also in mind that locking is deactivated,
+ so don't depend on the relevance to the real current situation!
+Inst base-files [6.0squeeze5] (6.0squeeze6 Debian:6.0.6/stable [amd64])
+Conf base-files (6.0squeeze6 Debian:6.0.6/stable [amd64])
+Inst dpkg [1.15.8.12] (1.15.8.13 Debian:6.0.6/stable [amd64])
+Conf dpkg (1.15.8.13 Debian:6.0.6/stable [amd64])
+Inst linux-base [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [all])
+Inst linux-image-2.6.32-5-amd64 [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [amd64])
+Inst xen-hypervisor-4.0-amd64 [4.0.1-5.3] (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Inst xen-linux-system-2.6.32-5-xen-amd64 [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [amd64]) []
+Inst linux-image-2.6.32-5-xen-amd64 [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [amd64])
+Inst debian-archive-keyring [2010.08.28] (2010.08.28+squeeze1 Debian:6.0.6/stable [all])
+Conf debian-archive-keyring (2010.08.28+squeeze1 Debian:6.0.6/stable [all])
+Inst libc6-i386 [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64]) []
+Inst libc-bin [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64]) [libc6:amd64 ]
+Conf libc-bin (2.11.3-4 Debian:6.0.6/stable [amd64]) [libc6:amd64 ]
+Inst libc6 [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [amd64])
+Conf libc6 (2.11.3-4 Debian:6.0.6/stable [amd64])
+Inst libgc1c2 [1:6.8-1.2] (1:6.8-2 Debian:6.0.6/stable [amd64])
+Inst locales [2.11.3-3] (2.11.3-4 Debian:6.0.6/stable [all])
+Inst firmware-linux-free [2.6.32-45] (2.6.32-46 Debian:6.0.6/stable [all])
+Inst libxenstore3.0 [4.0.1-5.3] (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Inst lockfile-progs [0.1.15] (0.1.15+squeeze1 Debian:6.0.6/stable [amd64])
+Inst xen-utils-4.0 [4.0.1-5.3] (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Inst xenstore-utils [4.0.1-5.3] (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Inst libconfig-inifiles-perl [2.52-1] (2.52-1+squeeze1 Debian:6.0.6/stable [all])
+Conf linux-base (2.6.32-46 Debian:6.0.6/stable [all])
+Conf linux-image-2.6.32-5-amd64 (2.6.32-46 Debian:6.0.6/stable [amd64])
+Conf xen-hypervisor-4.0-amd64 (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Conf linux-image-2.6.32-5-xen-amd64 (2.6.32-46 Debian:6.0.6/stable [amd64])
+Conf xen-linux-system-2.6.32-5-xen-amd64 (2.6.32-46 Debian:6.0.6/stable [amd64])
+Conf libc6-i386 (2.11.3-4 Debian:6.0.6/stable [amd64])
+Conf libgc1c2 (1:6.8-2 Debian:6.0.6/stable [amd64])
+Conf locales (2.11.3-4 Debian:6.0.6/stable [all])
+Conf firmware-linux-free (2.6.32-46 Debian:6.0.6/stable [all])
+Conf libxenstore3.0 (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Conf lockfile-progs (0.1.15+squeeze1 Debian:6.0.6/stable [amd64])
+Conf xen-utils-4.0 (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Conf xenstore-utils (4.0.1-5.4 Debian:6.0.6/stable, Debian-Security:6.0/stable [amd64])
+Conf libconfig-inifiles-perl (2.52-1+squeeze1 Debian:6.0.6/stable [all])
diff --git a/plugins/t/check_apt_input/ubuntu1 b/plugins/t/check_apt_input/ubuntu1
new file mode 100644
index 0000000..2f61c30
--- /dev/null
+++ b/plugins/t/check_apt_input/ubuntu1
@@ -0,0 +1,14 @@
+NOTE: This is only a simulation!
+ apt-get needs root privileges for real execution.
+ Also keep in mind that locking is deactivated,
+ so don't depend on the relevance to the real current situation!
+Inst grub-pc [1.99-21ubuntu3.1] (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64]) []
+Inst grub-pc-bin [1.99-21ubuntu3.1] (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64]) []
+Inst grub2-common [1.99-21ubuntu3.1] (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64]) []
+Inst grub-efi-amd64-bin [1.99-21ubuntu3.1] (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64]) []
+Inst grub-common [1.99-21ubuntu3.1] (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
+Conf grub-common (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
+Conf grub2-common (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
+Conf grub-pc-bin (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
+Conf grub-pc (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
+Conf grub-efi-amd64-bin (1.99-21ubuntu3.4 Ubuntu:12.04/precise-updates [amd64])
diff --git a/plugins/t/check_apt_input/ubuntu2 b/plugins/t/check_apt_input/ubuntu2
new file mode 100644
index 0000000..29a14a0
--- /dev/null
+++ b/plugins/t/check_apt_input/ubuntu2
@@ -0,0 +1,54 @@
+NOTE: This is only a simulation!
+ apt-get needs root privileges for real execution.
+ Also keep in mind that locking is deactivated,
+ so don't depend on the relevance to the real current situation!
+Inst libc6-dev [2.15-0ubuntu10] (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64]) []
+Inst libc-dev-bin [2.15-0ubuntu10] (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64]) []
+Inst linux-libc-dev [3.2.0-29.46] (3.2.0-31.50 Ubuntu:12.04/precise-security [amd64]) []
+Inst tzdata [2012e-0ubuntu0.12.04] (2012e-0ubuntu0.12.04.1 Ubuntu:12.04/precise-security [all]) []
+Conf tzdata (2012e-0ubuntu0.12.04.1 Ubuntu:12.04/precise-security [all]) []
+Inst libc-bin [2.15-0ubuntu10] (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64]) [libc6:amd64 ]
+Conf libc-bin (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64]) [libc6:amd64 ]
+Inst libc6 [2.15-0ubuntu10] (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Conf libc6 (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Inst libapt-pkg4.12 [0.8.16~exp12ubuntu10.2] (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Conf libapt-pkg4.12 (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Inst ubuntu-keyring [2011.11.21] (2011.11.21.1 Ubuntu:12.04/precise-updates [all])
+Conf ubuntu-keyring (2011.11.21.1 Ubuntu:12.04/precise-updates [all])
+Inst gpgv [1.4.11-3ubuntu2] (1.4.11-3ubuntu2.1 Ubuntu:12.04/precise-security [amd64])
+Conf gpgv (1.4.11-3ubuntu2.1 Ubuntu:12.04/precise-security [amd64])
+Inst gnupg [1.4.11-3ubuntu2] (1.4.11-3ubuntu2.1 Ubuntu:12.04/precise-security [amd64])
+Conf gnupg (1.4.11-3ubuntu2.1 Ubuntu:12.04/precise-security [amd64])
+Inst apt [0.8.16~exp12ubuntu10.2] (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Conf apt (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Inst libssl1.0.0 [1.0.1-4ubuntu5.3] (1.0.1-4ubuntu5.5 Ubuntu:12.04/precise-updates [amd64])
+Conf libssl1.0.0 (1.0.1-4ubuntu5.5 Ubuntu:12.04/precise-updates [amd64])
+Inst libapt-inst1.4 [0.8.16~exp12ubuntu10.2] (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Inst resolvconf [1.63ubuntu15] (1.63ubuntu16 Ubuntu:12.04/precise-updates [all])
+Inst libdbus-1-3 [1.4.18-1ubuntu1] (1.4.18-1ubuntu1.1 Ubuntu:12.04/precise-security [amd64])
+Inst libxml2 [2.7.8.dfsg-5.1ubuntu4.1] (2.7.8.dfsg-5.1ubuntu4.2 Ubuntu:12.04/precise-security [amd64])
+Inst multiarch-support [2.15-0ubuntu10] (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Conf multiarch-support (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Inst apt-utils [0.8.16~exp12ubuntu10.2] (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Inst isc-dhcp-client [4.1.ESV-R4-0ubuntu5.2] (4.1.ESV-R4-0ubuntu5.5 Ubuntu:12.04/precise-security [amd64]) []
+Inst isc-dhcp-common [4.1.ESV-R4-0ubuntu5.2] (4.1.ESV-R4-0ubuntu5.5 Ubuntu:12.04/precise-security [amd64])
+Inst dbus [1.4.18-1ubuntu1] (1.4.18-1ubuntu1.1 Ubuntu:12.04/precise-security [amd64])
+Inst linux-firmware [1.79] (1.79.1 Ubuntu:12.04/precise-updates [all])
+Inst xserver-common [2:1.11.4-0ubuntu10.7] (2:1.11.4-0ubuntu10.8 Ubuntu:12.04/precise-updates [all])
+Inst xserver-xorg-core [2:1.11.4-0ubuntu10.7] (2:1.11.4-0ubuntu10.8 Ubuntu:12.04/precise-updates [amd64])
+Inst xserver-xorg-input-synaptics [1.6.2-1ubuntu1~precise1] (1.6.2-1ubuntu1~precise2 Ubuntu:12.04/precise-updates [amd64])
+Conf libc-dev-bin (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Conf linux-libc-dev (3.2.0-31.50 Ubuntu:12.04/precise-security [amd64])
+Conf libc6-dev (2.15-0ubuntu10.2 Ubuntu:12.04/precise-security [amd64])
+Conf libapt-inst1.4 (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Conf resolvconf (1.63ubuntu16 Ubuntu:12.04/precise-updates [all])
+Conf libdbus-1-3 (1.4.18-1ubuntu1.1 Ubuntu:12.04/precise-security [amd64])
+Conf libxml2 (2.7.8.dfsg-5.1ubuntu4.2 Ubuntu:12.04/precise-security [amd64])
+Conf apt-utils (0.8.16~exp12ubuntu10.3 Ubuntu:12.04/precise-updates [amd64])
+Conf isc-dhcp-common (4.1.ESV-R4-0ubuntu5.5 Ubuntu:12.04/precise-security [amd64])
+Conf isc-dhcp-client (4.1.ESV-R4-0ubuntu5.5 Ubuntu:12.04/precise-security [amd64])
+Conf dbus (1.4.18-1ubuntu1.1 Ubuntu:12.04/precise-security [amd64])
+Conf linux-firmware (1.79.1 Ubuntu:12.04/precise-updates [all])
+Conf xserver-common (2:1.11.4-0ubuntu10.8 Ubuntu:12.04/precise-updates [all])
+Conf xserver-xorg-core (2:1.11.4-0ubuntu10.8 Ubuntu:12.04/precise-updates [amd64])
+Conf xserver-xorg-input-synaptics (1.6.2-1ubuntu1~precise2 Ubuntu:12.04/precise-updates [amd64])
diff --git a/plugins/t/check_by_ssh.t b/plugins/t/check_by_ssh.t
new file mode 100644
index 0000000..b6479f1
--- /dev/null
+++ b/plugins/t/check_by_ssh.t
@@ -0,0 +1,153 @@
+#! /usr/bin/perl -w -I ..
+#
+# check_by_ssh tests
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+# Required parameters
+my $ssh_service = getTestParameter("NP_SSH_HOST", "A host providing SSH service", "localhost");
+my $ssh_key = getTestParameter("NP_SSH_IDENTITY", "A key allowing access to NP_SSH_HOST", "~/.ssh/id_dsa");
+my $ssh_conf = getTestParameter( "NP_SSH_CONFIGFILE", "A config file with ssh settings", "~/.ssh/config");
+
+
+plan skip_all => "SSH_HOST and SSH_IDENTITY must be defined" unless ($ssh_service && $ssh_key);
+
+plan tests => 42;
+
+# Some random check strings/response
+my @response = ('OK: Everything is fine',
+ 'WARNING: Hey, pick me, pick me',
+ 'CRITICAL: Shit happens',
+ 'UNKNOWN: What can I do for ya',
+ 'WOOPS: What did I smoke',
+);
+my @response_re;
+my @check;
+for (@response) {
+ push(@check, "echo $_");
+ my $re_str = $_;
+ $re_str =~ s{(.)} { "\Q$1" }ge;
+ push(@response_re, $re_str);
+}
+
+my $result;
+
+# expand paths
+$ssh_key = glob($ssh_key) if $ssh_key;
+$ssh_conf = glob($ssh_conf) if $ssh_conf;
+
+## Single active checks
+
+for (my $i=0; $i<4; $i++) {
+ $result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C '$check[$i]; exit $i'"
+ );
+ cmp_ok($result->return_code, '==', $i, "Exit with return code $i");
+ is($result->output, $response[$i], "Status text is correct for check $i");
+}
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C 'exit 0'"
+ );
+cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
+is($result->output, 'OK - check_by_ssh: Remote command \'exit 0\' returned status 0', "Status text if command returned none (OK)");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C 'exit 1'"
+ );
+cmp_ok($result->return_code, '==', 1, "Exit with return code 1 (WARNING)");
+is($result->output, 'WARNING - check_by_ssh: Remote command \'exit 1\' returned status 1', "Status text if command returned none (WARNING)");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C 'exit 2'"
+ );
+cmp_ok($result->return_code, '==', 2, "Exit with return code 2 (CRITICAL)");
+is($result->output, 'CRITICAL - check_by_ssh: Remote command \'exit 2\' returned status 2', "Status text if command returned none (CRITICAL)");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C 'exit 3'"
+ );
+cmp_ok($result->return_code, '==', 3, "Exit with return code 3 (UNKNOWN)");
+is($result->output, 'UNKNOWN - check_by_ssh: Remote command \'exit 3\' returned status 3', "Status text if command returned none (UNKNOWN)");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C 'exit 7'"
+ );
+cmp_ok($result->return_code, '==', 7, "Exit with return code 7 (out of bounds)");
+is($result->output, 'UNKNOWN - check_by_ssh: Remote command \'exit 7\' returned status 7', "Status text if command returned none (out of bounds)");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C '$check[4]; exit 8'"
+ );
+cmp_ok($result->return_code, '==', 8, "Exit with return code 8 (out of bounds)");
+is($result->output, $response[4], "Return proper status text even with unknown status codes");
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -F $ssh_conf -C 'exit 0'"
+ );
+cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
+is($result->output, 'OK - check_by_ssh: Remote command \'exit 0\' returned status 0', "Status text if command returned none (OK)");
+
+# Multiple active checks
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -C '$check[1]; sh -c exit\\ 1' -C '$check[0]; sh -c exit\\ 0' -C '$check[3]; sh -c exit\\ 3' -C '$check[2]; sh -c exit\\ 2'"
+ );
+cmp_ok($result->return_code, '==', 0, "Multiple checks always return OK");
+my @lines = split(/\n/, $result->output);
+cmp_ok(scalar(@lines), '==', 8, "Correct number of output lines for multiple checks");
+my %linemap = (
+ '0' => '1',
+ '2' => '0',
+ '4' => '3',
+ '6' => '2',
+);
+foreach my $line (0, 2, 4, 6) {
+ my $code = $linemap{$line};
+ my $statline = $line+1;
+ is($lines[$line], "$response[$code]", "multiple checks status text is correct for line $line");
+ is($lines[$statline], "STATUS CODE: $code", "multiple check status code is correct for line $line");
+}
+
+# Passive checks
+unlink("/tmp/check_by_ssh.$$");
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -n flint -s serv -C '$check[2]; sh -c exit\\ 2' -O /tmp/check_by_ssh.$$"
+ );
+cmp_ok($result->return_code, '==', 0, "Exit always ok on passive checks");
+open(PASV, "/tmp/check_by_ssh.$$") or die("Unable to open '/tmp/check_by_ssh.$$': $!");
+my @pasv = <PASV>;
+close(PASV) or die("Unable to close '/tmp/check_by_ssh.$$': $!");
+cmp_ok(scalar(@pasv), '==', 1, 'One passive result for one check performed');
+for (0) {
+ if ($pasv[$_]) {
+ like($pasv[$_], '/^\[\d+\] PROCESS_SERVICE_CHECK_RESULT;flint;serv;2;' . $response_re[2] . '$/', 'proper result for passive check');
+ } else {
+ fail('proper result for passive check');
+ }
+}
+unlink("/tmp/check_by_ssh.$$") or die("Unable to unlink '/tmp/check_by_ssh.$$': $!");
+undef @pasv;
+
+$result = NPTest->testCmd(
+ "./check_by_ssh -i $ssh_key -H $ssh_service -n flint -s c0:c1:c2:c3:c4 -C '$check[0];sh -c exit\\ 0' -C '$check[1];sh -c exit\\ 1' -C '$check[2];sh -c exit\\ 2' -C '$check[3];sh -c exit\\ 3' -C '$check[4];sh -c exit\\ 9' -O /tmp/check_by_ssh.$$"
+ );
+cmp_ok($result->return_code, '==', 0, "Exit always ok on passive checks");
+open(PASV, "/tmp/check_by_ssh.$$") or die("Unable to open '/tmp/check_by_ssh.$$': $!");
+@pasv = <PASV>;
+close(PASV) or die("Unable to close '/tmp/check_by_ssh.$$': $!");
+cmp_ok(scalar(@pasv), '==', 5, 'Five passive result for five checks performed');
+for (0, 1, 2, 3, 4) {
+ if ($pasv[$_]) {
+ my $ret = $_;
+ $ret = 9 if ($_ == 4);
+ like($pasv[$_], '/^\[\d+\] PROCESS_SERVICE_CHECK_RESULT;flint;c' . $_ . ';' . $ret . ';' . $response_re[$_] . '$/', "proper result for passive check $_");
+ } else {
+ fail("proper result for passive check $_");
+ }
+}
+unlink("/tmp/check_by_ssh.$$") or die("Unable to unlink '/tmp/check_by_ssh.$$': $!");
+
diff --git a/plugins/t/check_cluster.t b/plugins/t/check_cluster.t
new file mode 100644
index 0000000..4736f06
--- /dev/null
+++ b/plugins/t/check_cluster.t
@@ -0,0 +1,82 @@
+#! /usr/bin/perl -w -I ..
+#
+# check_cluster tests
+#
+#
+
+use strict;
+use Test::More tests => 15;
+use NPTest;
+
+my $result;
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0:0 -c 0:0 -d 0,0,0,0"
+ );
+cmp_ok( $result->return_code, '==', 0, "Exit OK if non-ok services are inside critical and warning ranges" );
+like( $result->output, qr/service/i, "Output contains the word 'service' (case insensitive)");
+
+$result = NPTest->testCmd(
+ "./check_cluster -l LABEL -s -w 0:0 -c 0:0 -d 0,0,0,0"
+ );
+like( $result->output, qr/LABEL/, "Output contains the defined label 'LABEL' (case sensitive)");
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0:0 -c 0:1 -d 0,0,0,1"
+ );
+cmp_ok( $result->return_code, '==', 1, "Exit WARNING if non-ok services are inside critical and outside warning ranges" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0:0 -c 0:1 -d 0,0,1,1"
+ );
+cmp_ok( $result->return_code, '==', 2, "Exit CRITICAL if non-ok services are inside critical and outside warning ranges" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0 -c 0 -d 0,0,0,0"
+ );
+cmp_ok( $result->return_code, '==', 0, "Exit OK if non-ok services are inside critical and warning (no ranges)" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0 -c 1 -d 0,0,1,0"
+ );
+cmp_ok( $result->return_code, '==', 1, "Exit WARNING if number of non-ok services exceed warning (no ranges)" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -s -w 0 -c 1 -d 0,0,1,1"
+ );
+cmp_ok( $result->return_code, '==', 2, "Exit Critical if non-ok services exceed critical warning (no ranges)" );
+
+
+#
+# And for hosts..
+#
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0:0 -c 0:0 -d 0,0,0,0"
+ );
+cmp_ok( $result->return_code, '==', 0, "Exit OK if non-ok hosts are inside critical and warning ranges" );
+like( $result->output, qr/host/i, "Output contains the word 'host' (case insensitive)");
+
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0:0 -c 0:1 -d 0,0,0,1"
+ );
+cmp_ok( $result->return_code, '==', 1, "Exit WARNING if non-ok hosts are inside critical and outside warning ranges" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0:0 -c 0:1 -d 0,0,1,1"
+ );
+cmp_ok( $result->return_code, '==', 2, "Exit CRITICAL if non-ok hosts are inside critical and outside warning ranges" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0 -c 0 -d 0,0,0,0"
+ );
+cmp_ok( $result->return_code, '==', 0, "Exit OK if non-ok hosts are inside critical and warning (no ranges)" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0 -c 1 -d 0,0,1,0"
+ );
+cmp_ok( $result->return_code, '==', 1, "Exit WARNING if number of non-ok hosts exceed warning (no ranges)" );
+
+$result = NPTest->testCmd(
+ "./check_cluster -h -w 0 -c 1 -d 0,0,1,1"
+ );
+cmp_ok( $result->return_code, '==', 2, "Exit Critical if non-ok hosts exceed critical warning (no ranges)" );
diff --git a/plugins/t/check_curl.t b/plugins/t/check_curl.t
new file mode 100644
index 0000000..eae98cc
--- /dev/null
+++ b/plugins/t/check_curl.t
@@ -0,0 +1,213 @@
+#! /usr/bin/perl -w -I ..
+#
+# HyperText Transfer Protocol (HTTP) Test via check_curl
+#
+#
+
+use strict;
+use Test::More;
+use POSIX qw/mktime strftime/;
+
+use vars qw($tests $has_ipv6);
+
+BEGIN {
+ use NPTest;
+ $has_ipv6 = NPTest::has_ipv6();
+ $tests = $has_ipv6 ? 59 : 57;
+ plan tests => $tests;
+}
+
+
+my $successOutput = '/OK.*HTTP.*second/';
+
+my $res;
+my $plugin = 'check_http';
+$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
+
+my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
+my $host_tcp_http_ipv6 = getTestParameter("NP_HOST_TCP_HTTP_IPV6", "An IPv6 address providing a HTTP Service (a web server)", "::1");
+my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
+my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
+my $host_tcp_http2 = getTestParameter("NP_HOST_TCP_HTTP2", "A host providing an index page containing the string 'monitoring'", "test.monitoring-plugins.org");
+my $host_tcp_proxy = getTestParameter("NP_HOST_TCP_PROXY", "A host providing a HTTP proxy with CONNECT support", "localhost");
+my $port_tcp_proxy = getTestParameter("NP_PORT_TCP_PROXY", "Port of the proxy with HTTP and CONNECT support", "3128");
+
+my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
+
+
+$res = NPTest->testCmd(
+ "./$plugin $host_tcp_http -wt 300 -ct 600"
+ );
+cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" );
+like( $res->output, $successOutput, "Output OK" );
+
+if ($has_ipv6) {
+ # Test for IPv6 formatting
+ $res = NPTest->testCmd(
+ "./$plugin -I $host_tcp_http_ipv6 -wt 300 -ct 600"
+ );
+ cmp_ok( $res->return_code, '==', 0, "IPv6 URL formatting is working" );
+ like( $res->output, $successOutput, "Output OK" );
+}
+
+$res = NPTest->testCmd(
+ "./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
+ );
+like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" );
+
+$res = NPTest->testCmd(
+ "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
+ );
+cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
+# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!)
+like( $res->output, "/HTTP CRITICAL - Invalid HTTP response received from host on port 80: cURL returned 28 - Connection timed out after/", "Output OK");
+
+$res = NPTest->testCmd(
+ "./$plugin $hostname_invalid -wt 1 -ct 2"
+ );
+cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
+# The first part of the message comes from the OS catalogue, so cannot check this.
+# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename
+# Is also possible to get a socket timeout if DNS is not responding fast enough
+# cURL gives us consistent strings from it's own 'lib/strerror.c'
+like( $res->output, "/cURL returned 6 - Could not resolve host:/", "Output OK");
+
+# host header checks
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
+like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80 -k 'Host: testhost:8001'");
+like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+$res = NPTest->testCmd("./$plugin -v -I $host_tcp_http -p 80 -k 'Host: testhost:8001'");
+like( $res->output, '/^Host: testhost:8001\s*$/ms', "Host Header OK" );
+like( $res->output, '/CURLOPT_URL: http:\/\/'.$host_tcp_http.':80\//ms', "Url OK" );
+
+SKIP: {
+ skip "No internet access", 4 if $internet_access eq "no";
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http -S");
+ like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http:8080 -S -p 443");
+ like( $res->output, '/^Host: '.$host_tls_http.':8080\s*$/ms', "Host Header OK" );
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http:443 -S -p 443");
+ like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http -D -S -p 443");
+ like( $res->output, '/(^Host: '.$host_tls_http.'\s*$)|(cURL returned 60)/ms', "Host Header OK" );
+};
+
+SKIP: {
+ skip "No host serving monitoring in index file", 7 unless $host_tcp_http2;
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring'" );
+ cmp_ok( $res->return_code, "==", 0, "Got a reference to 'monitoring'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing'" );
+ cmp_ok( $res->return_code, "==", 2, "Not got 'mONiTORing'");
+ like ( $res->output, "/pattern not found/", "Error message says 'pattern not found'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -R 'mONiTORing'" );
+ cmp_ok( $res->return_code, "==", 0, "But case insensitive doesn't mind 'mONiTORing'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring' --invert-regex" );
+ cmp_ok( $res->return_code, "==", 2, "Invert results work when found");
+ like ( $res->output, "/pattern found/", "Error message says 'pattern found'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing' --invert-regex" );
+ cmp_ok( $res->return_code, "==", 0, "And also when not found");
+}
+SKIP: {
+ skip "No internet access", 28 if $internet_access eq "no";
+
+ $res = NPTest->testCmd(
+ "./$plugin --ssl $host_tls_http"
+ );
+ cmp_ok( $res->return_code, '==', 0, "Can read https for $host_tls_http" );
+
+ $res = NPTest->testCmd( "./$plugin -C 1 --ssl $host_tls_http" );
+ cmp_ok( $res->return_code, '==', 0, "Checking certificate for $host_tls_http");
+ like ( $res->output, "/Certificate '$host_tls_cert' will expire on/", "Output OK" );
+ my $saved_cert_output = $res->output;
+
+ $res = NPTest->testCmd( "./$plugin -C 8000,1 --ssl $host_tls_http" );
+ cmp_ok( $res->return_code, '==', 1, "Checking certificate for $host_tls_http");
+ like ( $res->output, qr/WARNING - Certificate '$host_tls_cert' expires in \d+ day/, "Output Warning" );
+
+ $res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
+ is( $res->return_code, 0, "Old syntax for cert checking okay" );
+ is( $res->output, $saved_cert_output, "Same output as new syntax" );
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tls_http -C 1" );
+ is( $res->return_code, 0, "Updated syntax for cert checking okay" );
+ is( $res->output, $saved_cert_output, "Same output as new syntax" );
+
+ $res = NPTest->testCmd( "./$plugin -C 1 $host_tls_http" );
+ cmp_ok( $res->output, 'eq', $saved_cert_output, "--ssl option automatically added");
+
+ $res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
+ cmp_ok( $res->output, 'eq', $saved_cert_output, "Old syntax for cert checking still works");
+
+ # run some certificate checks with faketime
+ SKIP: {
+ skip "No faketime binary found", 12 if !$faketime;
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/OK - Certificate '$host_tls_cert' will expire on/, "Catch cert output");
+ is( $res->return_code, 0, "Catch cert output exit code" );
+ my($mon,$day,$hour,$min,$sec,$year) = ($res->output =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)/);
+ if(!defined $year) {
+ die("parsing date failed from: ".$res->output);
+ }
+ my $months = {'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11};
+ my $ts = mktime($sec, $min, $hour, $day, $months->{$mon}, $year-1900);
+ my $time = strftime("%Y-%m-%d %H:%M:%S", localtime($ts));
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' just expired/, "Output on expire date");
+ is( $res->return_code, 2, "Output on expire date" );
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-1))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 0 minutes/, "cert expires in 1 second output");
+ is( $res->return_code, 2, "cert expires in 1 second exit code" );
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-120))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 minutes/, "cert expires in 2 minutes output");
+ is( $res->return_code, 2, "cert expires in 2 minutes exit code" );
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-7200))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 hours/, "cert expires in 2 hours output");
+ is( $res->return_code, 2, "cert expires in 2 hours exit code" );
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expired on/, "Certificate expired output");
+ is( $res->return_code, 2, "Certificate expired exit code" );
+ };
+
+ $res = NPTest->testCmd( "./$plugin --ssl $host_tls_http -E" );
+ like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
+ like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
+
+ $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f curl" );
+ is( $res->return_code, 0, "Redirection based on location is okay");
+
+ $res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" );
+ like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
+}
diff --git a/plugins/t/check_dbi.t b/plugins/t/check_dbi.t
new file mode 100644
index 0000000..c24b5a8
--- /dev/null
+++ b/plugins/t/check_dbi.t
@@ -0,0 +1,103 @@
+#! /usr/bin/perl -w -I ..
+#
+# Database Server Tests via check_dbi
+#
+#
+# Uses the 'sqlite3' DBD driver and command line utility.
+
+use strict;
+use Test::More;
+use NPTest;
+
+use File::Temp;
+
+use vars qw($tests);
+
+plan skip_all => "check_dbi not compiled" unless (-x "check_dbi");
+
+$tests = 20;
+plan tests => $tests;
+
+my $missing_driver_output = "failed to open DBI driver 'sqlite3'";
+
+my $bad_driver_output = "/failed to open DBI driver 'nodriver'/";
+my $conn_time_output = "/OK - connection time: [0-9\.]+s \|/";
+my $missing_query_output = "/Must specify a query to execute/";
+my $no_rows_output = "/WARNING - no rows returned/";
+my $not_numeric_output = "/CRITICAL - result value is not a numeric:/";
+my $query_time_output = "/OK - connection time: [0-9\.]+s, 'SELECT 1' returned 1.000000 in [0-9\.]+s \|/";
+my $syntax_error_output = "/CRITICAL - failed to execute query 'GET ALL FROM test': 1: near \"GET\": syntax error/";
+
+my $result;
+
+SKIP: {
+ my $sqlite3 = qx(which sqlite3 2> /dev/null);
+ chomp($sqlite3);
+
+ skip "No Sqlite3 found", $tests unless $sqlite3;
+
+ my $sqlite3_check = qx(./check_dbi -d sqlite3 -q '');
+ if ($sqlite3_check =~ m/$missing_driver_output/) {
+ skip "No 'sqlite3' DBD driver found", $tests;
+ }
+
+ my $fh = File::Temp->new(
+ TEMPLATE => "/tmp/check_dbi_sqlite3.XXXXXXX",
+ UNLINK => 1,
+ );
+ my $filename = $fh->filename;
+ $filename =~ s/^\/tmp\///;
+
+ system("$sqlite3 /tmp/$filename 'CREATE TABLE test(a INT, b TEXT)'");
+ system("$sqlite3 /tmp/$filename 'INSERT INTO test VALUES (1, \"text1\")'");
+ system("$sqlite3 /tmp/$filename 'INSERT INTO test VALUES (2, \"text2\")'");
+
+ my $check_cmd = "./check_dbi -d sqlite3 -o sqlite3_dbdir=/tmp -o dbname=$filename";
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT 1'");
+ cmp_ok($result->return_code, '==', 0, "Sqlite3 login okay and can run query");
+
+ $result = NPTest->testCmd("$check_cmd");
+ cmp_ok($result->return_code, '==', 3, "Missing query parameter");
+ like($result->output, $missing_query_output, "Missing query parameter error message");
+
+ $result = NPTest->testCmd("$check_cmd -q 'GET ALL FROM test'");
+ cmp_ok($result->return_code, '==', 2, "Invalid query");
+ like($result->output, $syntax_error_output, "Syntax error message");
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT 2.71828' -w 2 -c 3");
+ cmp_ok($result->return_code, '==', 1, "Got warning");
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT 3.1415' -w 2 -c 3");
+ cmp_ok($result->return_code, '==', 2, "Got critical");
+
+ $result = NPTest->testCmd("$check_cmd -q ''");
+ cmp_ok($result->return_code, '==', 1, "No rows returned");
+ like($result->output, $no_rows_output, "Now rows returned warning message");
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT b FROM test'");
+ cmp_ok($result->return_code, '==', 2, "Value is not a numeric");
+ like($result->output, $not_numeric_output, "Value is not a numeric error message");
+
+ $result = NPTest->testCmd("$check_cmd -m QUERY_RESULT -q 'SELECT b FROM test' -e text1");
+ cmp_ok($result->return_code, '==', 0, "Query result string comparison okay");
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT b FROM test' -r 'eXt[0-9]'");
+ cmp_ok($result->return_code, '==', 2, "Query result case-insensitive regex failure");
+
+ $result = NPTest->testCmd("$check_cmd -q 'SELECT b FROM test' -R 'eXt[0-9]'");
+ cmp_ok($result->return_code, '==', 0, "Query result case-sensitive regex okay");
+
+ $result = NPTest->testCmd("$check_cmd -m CONN_TIME -w 0.5 -c 0.7");
+ cmp_ok($result->return_code, '==', 0, "CONN_TIME metric okay");
+ like($result->output, $conn_time_output, "CONN_TIME metric output okay");
+
+ $result = NPTest->testCmd("$check_cmd -m QUERY_TIME -q 'SELECT 1'");
+ cmp_ok($result->return_code, '==', 0, "QUERY_TIME metric okay");
+ like($result->output, $query_time_output, "QUERY_TIME metric output okay");
+
+ $result = NPTest->testCmd("./check_dbi -d nodriver -q ''");
+ cmp_ok($result->return_code, '==', 3, "Unknown DBI driver");
+ like($result->output, $bad_driver_output, "Correct error message");
+}
+
diff --git a/plugins/t/check_dig.t b/plugins/t/check_dig.t
new file mode 100644
index 0000000..3ed6cc8
--- /dev/null
+++ b/plugins/t/check_dig.t
@@ -0,0 +1,98 @@
+#! /usr/bin/perl -w -I ..
+#
+# Domain Name Server (DNS) Tests via check_dig
+#
+#
+
+use strict;
+use Test::More;
+
+
+use vars qw($tests $has_ipv6);
+BEGIN {
+ plan skip_all => "check_dig not compiled" unless (-x "check_dig");
+ use NPTest;
+ $has_ipv6 = NPTest::has_ipv6();
+ $tests = $has_ipv6 ? 16 : 14;
+ plan tests => $tests;
+}
+
+my $successOutput = '/DNS OK - [\.0-9]+ seconds? response time/';
+
+my $hostname_valid = getTestParameter(
+ "NP_HOSTNAME_VALID",
+ "A valid (known to DNS) hostname",
+ "orwell.monitoring-plugins.org"
+ );
+
+my $hostname_valid_ip = getTestParameter(
+ "NP_HOSTNAME_VALID_IP",
+ "The IP address of the valid hostname $hostname_valid",
+ "130.133.8.40",
+ );
+
+my $hostname_valid_reverse = getTestParameter(
+ "NP_HOSTNAME_VALID_REVERSE",
+ "The hostname of $hostname_valid_ip",
+ "orwell.monitoring-plugins.org.",
+ );
+
+my $hostname_invalid = getTestParameter(
+ "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost.monitoring-plugins.org",
+ );
+
+my $dns_server = getTestParameter(
+ "NP_DNS_SERVER",
+ "A non default (remote) DNS server",
+ );
+
+my $res;
+
+SKIP: {
+ skip "check_dig.t: not enough parameters given",
+ 12 unless ($hostname_valid && $hostname_valid_ip && $hostname_valid_reverse && $hostname_invalid && $dns_server);
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5");
+ cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid");
+ like ( $res->output, $successOutput, "Output OK" );
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5 -w 0.000001 -c 0.00001");
+ cmp_ok( $res->return_code, '==', 2, "Critical threshold passed");
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5 -w 0.000001 -c 5");
+ cmp_ok( $res->return_code, '==', 1, "Warning threshold passed");
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -t 1");
+ cmp_ok( $res->return_code, '==', 3, "Invalid command line -l missing");
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_invalid -t 1");
+ cmp_ok( $res->return_code, '==', 2, "Invalid $hostname_invalid");
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5");
+ cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid on $dns_server");
+ like ( $res->output, $successOutput, "Output OK" );
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5 -4");
+ cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid on $dns_server");
+ like ( $res->output, $successOutput, "Output OK for IPv4" );
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -a $hostname_valid_ip -t 5");
+ cmp_ok( $res->return_code, '==', 0, "Got expected address");
+
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -a 10.10.10.10 -t 5");
+ cmp_ok( $res->return_code, '==', 1, "Got wrong address");
+
+ my $ip_reverse = $hostname_valid_ip;
+ $ip_reverse =~ s/(\d+)\.(\d+)\.(\d+)\.(\d+)/$4.$3.$2.$1.in-addr.arpa/;
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $ip_reverse -a $hostname_valid_reverse -T PTR -t 5");
+ cmp_ok( $res->return_code, '==', 0, "Got expected fqdn");
+ like ( $res->output, $successOutput, "Output OK");
+
+ if($has_ipv6) {
+ $res = NPTest->testCmd("./check_dig -H $dns_server -l $hostname_valid -t 5 -6");
+ cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid on $dns_server");
+ like ( $res->output, $successOutput, "Output OK for IPv6" );
+ }
+}
diff --git a/plugins/t/check_disk.t b/plugins/t/check_disk.t
new file mode 100644
index 0000000..ca035ce
--- /dev/null
+++ b/plugins/t/check_disk.t
@@ -0,0 +1,378 @@
+#! /usr/bin/perl -w -I ..
+#
+# Disk Space Tests via check_disk
+#
+#
+
+# TODO: Add in tests for perf data. Need to beef up Monitoring::Plugin::Performance to cater for max, min, etc
+
+use strict;
+use Test::More;
+use NPTest;
+use POSIX qw(ceil floor);
+
+my $successOutput = '/^DISK OK/';
+my $failureOutput = '/^DISK CRITICAL/';
+my $warningOutput = '/^DISK WARNING/';
+
+my $result;
+
+my $mountpoint_valid = getTestParameter( "NP_MOUNTPOINT_VALID", "Path to valid mountpoint", "/");
+my $mountpoint2_valid = getTestParameter( "NP_MOUNTPOINT2_VALID", "Path to another valid mountpoint. Must be different from 1st one", "/var");
+
+if ($mountpoint_valid eq "" or $mountpoint2_valid eq "") {
+ plan skip_all => "Need 2 mountpoints to test";
+} else {
+ plan tests => 88;
+}
+
+$result = NPTest->testCmd(
+ "./check_disk -w 1% -c 1% -p $mountpoint_valid -w 1% -c 1% -p $mountpoint2_valid"
+ );
+cmp_ok( $result->return_code, "==", 0, "Checking two mountpoints (must have at least 1% free in space and inodes)");
+my $c = 0;
+$_ = $result->output;
+$c++ while /\(/g; # counts number of "(" - should be two
+cmp_ok( $c, '==', 2, "Got two mountpoints in output");
+
+
+# Get perf data
+# Should use Monitoring::Plugin
+my @perf_data = sort(split(/ /, $result->perf_output));
+
+
+# Calculate avg_free free on mountpoint1 and mountpoint2
+# because if you check in the middle, you should get different errors
+$_ = $result->output;
+my ($free_on_mp1, $free_on_mp2) = (m/\((\d+)%.*\((\d+)%/);
+die "Cannot parse output: $_" unless ($free_on_mp1 && $free_on_mp2);
+my $avg_free = ceil(($free_on_mp1+$free_on_mp2)/2);
+my ($more_free, $less_free);
+if ($free_on_mp1 > $free_on_mp2) {
+ $more_free = $mountpoint_valid;
+ $less_free = $mountpoint2_valid;
+} elsif ($free_on_mp1 < $free_on_mp2) {
+ $more_free = $mountpoint2_valid;
+ $less_free = $mountpoint_valid;
+} else {
+ die "Two mountpoints are the same - cannot do rest of test";
+}
+if($free_on_mp1 == $avg_free || $free_on_mp2 == $avg_free) {
+ die "One mountpoints has average space free - cannot do rest of test";
+}
+
+
+# Do same for inodes
+$_ = $result->output;
+my ($free_inode_on_mp1, $free_inode_on_mp2) = (m/inode=(\d+)%.*inode=(\d+)%/);
+die "Cannot parse free inodes: $_" unless ($free_inode_on_mp1 && $free_inode_on_mp2);
+my $avg_inode_free = ceil(($free_inode_on_mp1 + $free_inode_on_mp2)/2);
+my ($more_inode_free, $less_inode_free);
+if ($free_inode_on_mp1 > $free_inode_on_mp2) {
+ $more_inode_free = $mountpoint_valid;
+ $less_inode_free = $mountpoint2_valid;
+} elsif ($free_inode_on_mp1 < $free_inode_on_mp2) {
+ $more_inode_free = $mountpoint2_valid;
+ $less_inode_free = $mountpoint_valid;
+} else {
+ die "Two mountpoints with same inodes free - cannot do rest of test";
+}
+if($free_inode_on_mp1 == $avg_inode_free || $free_inode_on_mp2 == $avg_inode_free) {
+ die "One mountpoints has average inodes free - cannot do rest of test";
+}
+
+# Verify performance data
+# First check absolute thresholds...
+$result = NPTest->testCmd(
+ "./check_disk -w 20 -c 10 -p $mountpoint_valid"
+ );
+$_ = $result->perf_output;
+my ($warn_absth_data, $crit_absth_data, $total_absth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
+# default unit is MiB, but perfdata is always bytes
+is ($warn_absth_data, $total_absth_data - (20 * (2 ** 20)), "Wrong warning in perf data using absolute thresholds");
+is ($crit_absth_data, $total_absth_data - (10 * (2 ** 20)), "Wrong critical in perf data using absolute thresholds");
+
+# Then check percent thresholds.
+$result = NPTest->testCmd(
+ "./check_disk -w 20% -c 10% -p $mountpoint_valid"
+ );
+$_ = $result->perf_output;
+my ($warn_percth_data, $crit_percth_data, $total_percth_data) = (m/=.[^;]*;(\d+);(\d+);\d+;(\d+)/);
+is ($warn_percth_data, int((1-20/100)*$total_percth_data), "Wrong warning in perf data using percent thresholds");
+is ($crit_percth_data, int((1-10/100)*$total_percth_data), "Wrong critical in perf data using percent thresholds");
+
+
+# Check when order of mount points are reversed, that perf data remains same
+$result = NPTest->testCmd(
+ "./check_disk -w 1% -c 1% -p $mountpoint2_valid -w 1% -c 1% -p $mountpoint_valid"
+ );
+@_ = sort(split(/ /, $result->perf_output));
+is_deeply( \@perf_data, \@_, "perf data for both filesystems same when reversed");
+
+
+# Basic filesystem checks for sizes
+$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free" );
+cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free");
+like ( $result->output, $successOutput, "OK output" );
+like ( $result->only_output, qr/free space/, "Have free space text");
+like ( $result->only_output, qr/$more_free/, "Have disk name in text");
+
+$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -p $more_free -p $less_free" );
+cmp_ok( $result->return_code, '==', 0, "At least 1 MB available on $more_free and $less_free");
+$_ = $result->output;
+my ($free_mb_on_mp1, $free_mb_on_mp2) = (m/(\d+)MiB .* (\d+)MiB /g);
+my $free_mb_on_all = $free_mb_on_mp1 + $free_mb_on_mp2;
+
+
+
+$result = NPTest->testCmd( "./check_disk -e -w 1 -c 1 -p $more_free" );
+is( $result->only_output, "DISK OK", "No print out of disks with -e for OKs");
+
+$result = NPTest->testCmd( "./check_disk 100 100 $more_free" );
+cmp_ok( $result->return_code, '==', 0, "Old syntax okay" );
+
+$result = NPTest->testCmd( "./check_disk -w 1% -c 1% -p $more_free" );
+cmp_ok( $result->return_code, "==", 0, "At least 1% free" );
+
+$result = NPTest->testCmd(
+ "./check_disk -w 1% -c 1% -p $more_free -w 100% -c 100% -p $less_free"
+ );
+cmp_ok( $result->return_code, "==", 2, "Get critical on less_free mountpoint $less_free" );
+like( $result->output, $failureOutput, "Right output" );
+
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c 0% -p $less_free"
+ );
+cmp_ok( $result->return_code, '==', 1, "Get warning on less_free mountpoint, when checking avg_free");
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c $avg_free% -p $more_free"
+ );
+cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, when checking avg_free");
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
+ );
+cmp_ok( $result->return_code, "==", 1, "Combining above two tests, get warning");
+my $all_disks = $result->output;
+
+$result = NPTest->testCmd(
+ "./check_disk -e -w $avg_free% -c 0% -p $less_free -w $avg_free% -c $avg_free% -p $more_free"
+ );
+isnt( $result->output, $all_disks, "-e gives different output");
+
+# Need spaces around filesystem name in case less_free and more_free are nested
+like( $result->output, qr/ $less_free /, "Found problem $less_free");
+unlike( $result->only_output, qr/ $more_free /, "Has ignored $more_free as not a problem");
+like( $result->perf_output, qr/ $more_free=/, "But $more_free is still in perf data");
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c 0% -p $more_free"
+ );
+cmp_ok( $result->return_code, '==', 0, "Get ok on more_free mountpoint, checking avg_free");
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c $avg_free% -p $less_free"
+ );
+cmp_ok( $result->return_code, '==', 2, "Get critical on less_free, checking avg_free");
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c 0% -p $more_free -w $avg_free% -c $avg_free% -p $less_free"
+ );
+cmp_ok( $result->return_code, '==', 2, "Combining above two tests, get critical");
+
+$result = NPTest->testCmd(
+ "./check_disk -w $avg_free% -c $avg_free% -p $less_free -w $avg_free% -c 0% -p $more_free"
+ );
+cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
+
+
+
+# Basic inode checks for sizes
+
+$result = NPTest->testCmd( "./check_disk --icritical 1% --iwarning 1% -p $more_inode_free" );
+is( $result->return_code, 0, "At least 1% free on inodes for both mountpoints");
+
+$result = NPTest->testCmd( "./check_disk -K 100% -W 100% -p $less_inode_free" );
+is( $result->return_code, 2, "Critical requesting 100% free inodes for both mountpoints");
+
+$result = NPTest->testCmd( "./check_disk --iwarning 1% --icritical 1% -p $more_inode_free -K 100% -W 100% -p $less_inode_free" );
+is( $result->return_code, 2, "Get critical on less_inode_free mountpoint $less_inode_free");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free" );
+is( $result->return_code, 1, "Get warning on less_inode_free, when checking average");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free ");
+is( $result->return_code, 0, "Get ok on more_inode_free when checking average");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
+is ($result->return_code, 1, "Combine above two tests, get warning");
+$all_disks = $result->output;
+
+$result = NPTest->testCmd( "./check_disk -e -W $avg_inode_free% -K 0% -p $less_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $more_inode_free" );
+isnt( $result->output, $all_disks, "-e gives different output");
+like( $result->output, qr/$less_inode_free/, "Found problem $less_inode_free");
+unlike( $result->only_output, qr/$more_inode_free\s/, "Has ignored $more_inode_free as not a problem");
+like( $result->perf_output, qr/$more_inode_free/, "But $more_inode_free is still in perf data");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free" );
+is( $result->return_code, 0, "Get ok on more_inode_free mountpoint, checking average");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
+is( $result->return_code, 2, "Get critical on less_inode_free, checking average");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K 0% -p $more_inode_free -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free" );
+is( $result->return_code, 2, "Combining above two tests, get critical");
+
+$result = NPTest->testCmd( "./check_disk -W $avg_inode_free% -K $avg_inode_free% -p $less_inode_free -W $avg_inode_free% -K 0% -p $more_inode_free" );
+cmp_ok( $result->return_code, '==', 2, "And reversing arguments should not make a difference");
+
+
+
+
+
+
+TODO: {
+ local $TODO = "Invalid percent figures";
+ $result = NPTest->testCmd(
+ "./check_disk -w 10% -c 15% -p $mountpoint_valid"
+ );
+ cmp_ok( $result->return_code, '==', 3, "Invalid command line options" );
+}
+
+$result = NPTest->testCmd(
+ "./check_disk -p $mountpoint_valid -w 10% -c 15%"
+ );
+cmp_ok( $result->return_code, "==", 3, "Invalid options: -p must come after thresholds" );
+
+$result = NPTest->testCmd( "./check_disk -w 100% -c 100% ".${mountpoint_valid} ); # 100% empty
+cmp_ok( $result->return_code, "==", 2, "100% empty" );
+like( $result->output, $failureOutput, "Right output" );
+
+$result = NPTest->testCmd( "./check_disk -w 100000000 -c 100000000 $mountpoint_valid" );
+cmp_ok( $result->return_code, '==', 2, "Check for 100TB free" );
+
+$result = NPTest->testCmd( "./check_disk -w 100 -c 100 -u TB ".${mountpoint_valid} ); # 100 TB empty
+cmp_ok( $result->return_code, "==", 2, "100 TB empty" );
+
+
+# Checking old syntax of check_disk warn crit [fs], with warn/crit at USED% thresholds
+$result = NPTest->testCmd( "./check_disk 0 0 ".${mountpoint_valid} );
+cmp_ok( $result->return_code, "==", 2, "Old syntax: 0% used");
+like ( $result->only_output, qr(^[^;]*;[^;]*$), "Select only one path with positional arguments");
+
+$result = NPTest->testCmd( "./check_disk 100 100 $mountpoint_valid" );
+cmp_ok( $result->return_code, '==', 0, "Old syntax: 100% used" );
+
+$result = NPTest->testCmd( "./check_disk 0 100 $mountpoint_valid" );
+cmp_ok( $result->return_code, '==', 1, "Old syntax: warn 0% used" );
+
+TODO: {
+ local $TODO = "Invalid values";
+ $result = NPTest->testCmd( "./check_disk 0 200 $mountpoint_valid" );
+ cmp_ok( $result->return_code, '==', 3, "Old syntax: Error with values outside percent range" );
+
+ $result = NPTest->testCmd( "./check_disk 200 200 $mountpoint_valid" );
+ cmp_ok( $result->return_code, '==', 3, "Old syntax: Error with values outside percent range" );
+
+ $result = NPTest->testCmd( "./check_disk 200 0 $mountpoint_valid" );
+ cmp_ok( $result->return_code, '==', 3, "Old syntax: Error with values outside percent range" );
+}
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p /bob" );
+cmp_ok( $result->return_code, '==', 2, "Checking /bob - return error because /bob does not exist" );
+like( $result->output, '/^DISK CRITICAL - /bob is not accessible:.*$/', 'Output OK');
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p /" );
+my $root_output = $result->output;
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p /etc" );
+cmp_ok( $result->return_code, '==', 0, "Checking /etc - should return info for /" );
+cmp_ok( $result->output, 'eq', $root_output, "check_disk /etc gives same as check_disk /");
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -E -p /etc " );
+cmp_ok( $result->return_code, '==', 2, "... unless -E/--exact-match is specified");
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p /etc -E " );
+cmp_ok( $result->return_code, '==', 3, "-E/--exact-match must be specified before -p");
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -r /etc -E " );
+cmp_ok( $result->return_code, '==', 3, "-E/--exact-match must be specified before -r");
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p / -p /bob" );
+cmp_ok( $result->return_code, '==', 2, "Checking / and /bob gives critical");
+unlike( $result->perf_output, '/\/bob/', "perf data does not have /bob in it");
+
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p / -p /" );
+unlike( $result->output, '/ \/ .* \/ /', "Should not show same filesystem twice");
+
+# are partitions added if -C is given without path selection -p ?
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -C -w 0% -c 0% -p $mountpoint_valid" );
+like( $result->output, '/;.*;\|/', "-C selects partitions if -p is not given");
+
+# grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit
+$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all + 1) ."-g group -p $mountpoint_valid -p $mountpoint2_valid" );
+cmp_ok( $result->return_code, '==', 2, "grouping: exit crit if the sum of free megs on mp1+mp2 is less than warn/crit");
+
+# grouping: exit warning if the sum of free megs on mp1+mp2 is between -w and -c
+$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all + 1) ." -c ". ($free_mb_on_all - 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
+cmp_ok( $result->return_code, '==', 1, "grouping: exit warning if the sum of free megs on mp1+mp2 is between -w and -c ");
+
+# grouping: exit ok if the sum of free megs on mp1+mp2 is more than warn/crit
+$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all - 1) ." -c ". ($free_mb_on_all - 1) ." -g group -p $mountpoint_valid -p $mountpoint2_valid" );
+cmp_ok( $result->return_code, '==', 0, "grouping: exit ok if the sum of free megs on mp1+mp2 is more than warn/crit");
+
+# grouping: exit unknown if group name is given after -p
+$result = NPTest->testCmd( "./check_disk -w ". ($free_mb_on_all - 1) ." -c ". ($free_mb_on_all - 1) ." -p $mountpoint_valid -g group -p $mountpoint2_valid" );
+cmp_ok( $result->return_code, '==', 3, "Invalid options: -p must come after groupname");
+
+# regex: exit unknown if given regex is not compilable
+$result = NPTest->testCmd( "./check_disk -w 1 -c 1 -r '('" );
+cmp_ok( $result->return_code, '==', 3, "Exit UNKNOWN if regex is not compilable");
+
+# ignore: exit unknown, if all paths are deselected using -i
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -i '$mountpoint_valid' -i '$mountpoint2_valid'" );
+cmp_ok( $result->return_code, '==', 3, "ignore-ereg: Unknown if all fs are ignored (case sensitive)");
+
+# ignore: exit unknown, if all paths are deselected using -I
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -I '".uc($mountpoint_valid)."' -I '".uc($mountpoint2_valid)."'" );
+cmp_ok( $result->return_code, '==', 3, "ignore-ereg: Unknown if all fs are ignored (case insensitive)");
+
+# ignore: exit unknown, if all paths are deselected using -i
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -i '.*'" );
+cmp_ok( $result->return_code, '==', 3, "ignore-ereg: Unknown if all fs are ignored using -i '.*'");
+
+# ignore: test if ignored path is actually ignored
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -i '^$mountpoint2_valid\$'");
+like( $result->output, qr/$mountpoint_valid/, "output data does have $mountpoint_valid in it");
+unlike( $result->output, qr/$mountpoint2_valid/, "output data does not have $mountpoint2_valid in it");
+
+# ignore: test if all paths are listed when ignore regex doesn't match
+$result = NPTest->testCmd( "./check_disk -w 0% -c 0% -p $mountpoint_valid -p $mountpoint2_valid -i '^barbazJodsf\$'");
+like( $result->output, qr/$mountpoint_valid/, "ignore: output data does have $mountpoint_valid when regex doesn't match");
+like( $result->output, qr/$mountpoint2_valid/,"ignore: output data does have $mountpoint2_valid when regex doesn't match");
+
+# ignore-missing: exit okay, when fs is not accessible
+$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p /bob");
+cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for not existing filesystem /bob");
+like( $result->output, '/^DISK OK - No disks were found for provided parameters; - ignored paths: /bob;.*$/', 'Output OK');
+
+# ignore-missing: exit okay, when regex does not match
+$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r /bob");
+cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
+like( $result->output, '/^DISK OK - No disks were found for provided parameters;.*$/', 'Output OK');
+
+# ignore-missing: exit okay, when fs with exact match (-E) is not found
+$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -E -p /etc");
+cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay when exact match does not find fs");
+like( $result->output, '/^DISK OK - No disks were found for provided parameters; - ignored paths: /etc;.*$/', 'Output OK');
+
+# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (regex)
+$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -r '/bob' -r '^/\$'");
+cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
+like( $result->output, '/^DISK OK - free space: \/ .*$/', 'Output OK');
+
+# ignore-missing: exit okay, when checking one existing fs and one non-existing fs (path)
+$result = NPTest->testCmd( "./check_disk --ignore-missing -w 0% -c 0% -p '/bob' -p '/'");
+cmp_ok( $result->return_code, '==', 0, "ignore-missing: return okay for regular expression not matching");
+like( $result->output, '/^DISK OK - free space: / .*; - ignored paths: /bob;.*$/', 'Output OK'); \ No newline at end of file
diff --git a/plugins/t/check_dns.t b/plugins/t/check_dns.t
new file mode 100644
index 0000000..afb2062
--- /dev/null
+++ b/plugins/t/check_dns.t
@@ -0,0 +1,115 @@
+#! /usr/bin/perl -w -I ..
+#
+# Domain Name Server (DNS) Tests via check_dns
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan skip_all => "check_dns not compiled" unless (-x "check_dns");
+
+plan tests => 23;
+
+my $successOutput = '/DNS OK: [\.0-9]+ seconds? response time/';
+
+my $hostname_valid = getTestParameter(
+ "NP_HOSTNAME_VALID",
+ "A valid (known to DNS) hostname",
+ "monitoring-plugins.org",
+ );
+
+my $hostname_valid_ip = getTestParameter(
+ "NP_HOSTNAME_VALID_IP",
+ "The IP address of the valid hostname $hostname_valid",
+ "130.133.8.40",
+ );
+
+my $hostname_valid_cidr = getTestParameter(
+ "NP_HOSTNAME_VALID_CIDR",
+ "An valid CIDR range containing $hostname_valid_ip",
+ "130.133.8.41/30",
+ );
+
+my $hostname_invalid_cidr = getTestParameter(
+ "NP_HOSTNAME_INVALID_CIDR",
+ "An (valid) CIDR range NOT containing $hostname_valid_ip",
+ "130.133.8.39/30",
+ );
+
+my $hostname_valid_reverse = getTestParameter(
+ "NP_HOSTNAME_VALID_REVERSE",
+ "The hostname of $hostname_valid_ip",
+ "orwell.monitoring-plugins.org.",
+ );
+
+my $hostname_invalid = getTestParameter(
+ "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost.altinity.com",
+ );
+
+my $dns_server = getTestParameter(
+ "NP_DNS_SERVER",
+ "A non default (remote) DNS server",
+ );
+
+my $host_nonresponsive = getTestParameter(
+ "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests",
+ "10.0.0.1",
+ );
+
+my $res;
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -t 5");
+cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid");
+like ( $res->output, $successOutput, "Output OK" );
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -t 5 -w 0 -c 0");
+cmp_ok( $res->return_code, '==', 2, "Critical threshold passed");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -t 5 -w 0 -c 5");
+cmp_ok( $res->return_code, '==', 1, "Warning threshold passed");
+like( $res->output, '/\|time=[\d\.]+s;0.0*;5\.0*;0\.0*/', "Output performance data OK" );
+
+$res = NPTest->testCmd("./check_dns -H $hostname_invalid -t 1");
+cmp_ok( $res->return_code, '==', 2, "Invalid $hostname_invalid");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -s $dns_server -t 5");
+cmp_ok( $res->return_code, '==', 0, "Found $hostname_valid on $dns_server");
+like ( $res->output, $successOutput, "Output OK" );
+
+$res = NPTest->testCmd("./check_dns -H $hostname_invalid -s $dns_server -t 1");
+cmp_ok( $res->return_code, '==', 2, "Invalid $hostname_invalid on $dns_server");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -a $hostname_valid_ip -s $host_nonresponsive -t 2");
+cmp_ok( $res->return_code, '==', 2, "Got no answer from unresponsive server");
+like ( $res->output, "/CRITICAL - /", "Output OK");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -a $hostname_valid_ip -t 5");
+cmp_ok( $res->return_code, '==', 0, "Got expected address");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -a 10.10.10.10 -t 5");
+cmp_ok( $res->return_code, '==', 2, "Got wrong address");
+like ( $res->output, "/^DNS CRITICAL.*expected '10.10.10.10' but got '$hostname_valid_ip'".'$/', "Output OK");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid_ip -a $hostname_valid_reverse -t 5");
+cmp_ok( $res->return_code, '==', 0, "Got expected fqdn");
+like ( $res->output, $successOutput, "Output OK");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -a $hostname_valid_cidr -t 5");
+cmp_ok( $res->return_code, '==', 0, "Got expected address");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -a $hostname_invalid_cidr -t 5");
+cmp_ok( $res->return_code, '==', 2, "Got wrong address");
+like ( $res->output, "/^DNS CRITICAL.*expected '$hostname_invalid_cidr' but got '$hostname_valid_ip'".'$/', "Output OK");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_valid -n");
+cmp_ok( $res->return_code, '==', 2, "Found $hostname_valid");
+like ( $res->output, "/^DNS CRITICAL.*Domain '$hostname_valid' was found by the server:/", "Output OK");
+
+$res = NPTest->testCmd("./check_dns -H $hostname_invalid -n");
+cmp_ok( $res->return_code, '==', 0, "Did not find $hostname_invalid");
+like ( $res->output, $successOutput, "Output OK" );
diff --git a/plugins/t/check_dummy.t b/plugins/t/check_dummy.t
new file mode 100644
index 0000000..15fc157
--- /dev/null
+++ b/plugins/t/check_dummy.t
@@ -0,0 +1,54 @@
+#! /usr/bin/perl -w -I ..
+#
+# check_dummy tests
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan tests => 20;
+
+my $res;
+
+$res = NPTest->testCmd("./check_dummy");
+is( $res->return_code, 3, "No args" );
+like( $res->output, "/Could not parse arguments/", "Correct usage message");
+
+$res = NPTest->testCmd("./check_dummy 0");
+is( $res->return_code, 0, "OK state returned");
+is( $res->output, "OK", "Says 'OK'");
+
+$res = NPTest->testCmd("./check_dummy 0 'some random data'");
+is( $res->return_code, 0, "Still OK");
+is( $res->output, "OK: some random data", "Sample text okay");
+
+$res = NPTest->testCmd("./check_dummy 1");
+is( $res->return_code, 1, "Warning okay");
+is( $res->output, "WARNING", "Says 'WARNING'");
+
+$res = NPTest->testCmd("./check_dummy 1 'more stuff'");
+is( $res->return_code, 1, "Still warning");
+is( $res->output, "WARNING: more stuff", "optional text okay" );
+
+$res = NPTest->testCmd("./check_dummy 2");
+is( $res->return_code, 2, "Critical ok" );
+is( $res->output, "CRITICAL", "Says 'CRITICAL'");
+
+$res = NPTest->testCmd("./check_dummy 2 'roughly drafted'");
+is( $res->return_code, 2, "Still critical");
+is( $res->output, "CRITICAL: roughly drafted", "optional text okay" );
+
+$res = NPTest->testCmd("./check_dummy 3");
+is( $res->return_code, 3, "Unknown ok" );
+is( $res->output, "UNKNOWN", "Says 'UNKNOWN'");
+
+$res = NPTest->testCmd("./check_dummy 3 'daringfireball'");
+is( $res->return_code, 3, "Still unknown");
+is( $res->output, "UNKNOWN: daringfireball", "optional text okay" );
+
+$res = NPTest->testCmd("./check_dummy 4");
+is( $res->return_code, 3, "Invalid error code" );
+is( $res->output, "UNKNOWN: Status 4 is not a supported error state", "With appropriate error message");
+
diff --git a/plugins/t/check_fping.t b/plugins/t/check_fping.t
new file mode 100644
index 0000000..67b357b
--- /dev/null
+++ b/plugins/t/check_fping.t
@@ -0,0 +1,34 @@
+#! /usr/bin/perl -w -I ..
+#
+# FPing Tests via check_fping
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my $host_responsive = getTestParameter("NP_HOST_RESPONSIVE", "The hostname of system responsive to network requests", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+my $res;
+
+my $fping = qx(which fping 2> /dev/null);
+chomp($fping);
+if( ! -x "./check_fping") {
+ plan skip_all => "check_fping not found, skipping tests";
+}
+elsif ( !$fping || !-x $fping ) {
+ plan skip_all => "fping not found or cannot be executed, skipping tests";
+} else {
+ plan tests => 3;
+ $res = NPTest->testCmd( "./check_fping $host_responsive" );
+ cmp_ok( $res->return_code, '==', 0, "Responsive host returns OK");
+
+ $res = NPTest->testCmd( "./check_fping $host_nonresponsive" );
+ cmp_ok( $res->return_code, '==', 2, "Non-Responsive host returns Critical");
+
+ $res = NPTest->testCmd( "./check_fping $hostname_invalid" );
+ cmp_ok( $res->return_code, '==', 3, "Invalid host returns Unknown");
+}
diff --git a/plugins/t/check_ftp.t b/plugins/t/check_ftp.t
new file mode 100644
index 0000000..93a7d7c
--- /dev/null
+++ b/plugins/t/check_ftp.t
@@ -0,0 +1,28 @@
+#! /usr/bin/perl -w -I ..
+#
+# File Transfer Protocol (FTP) Test via check_ftp
+#
+#
+
+use strict;
+use Test;
+use NPTest;
+
+use vars qw($tests);
+BEGIN {$tests = 4; plan tests => $tests}
+
+my $host_tcp_ftp = getTestParameter("NP_HOST_TCP_FTP", "A host providing the FTP Service (an FTP server)", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+my $successOutput = '/FTP OK -\s+[0-9]?\.?[0-9]+ second response time/';
+
+my $t;
+
+$t += checkCmd( "./check_ftp $host_tcp_ftp -wt 300 -ct 600", 0, $successOutput );
+$t += checkCmd( "./check_ftp $host_nonresponsive -wt 0 -ct 0 -to 1", 2 );
+$t += checkCmd( "./check_ftp $hostname_invalid -wt 0 -ct 0", 2 );
+
+exit(0) if defined($Test::Harness::VERSION);
+exit($tests - $t);
+
diff --git a/plugins/t/check_hpjd.t b/plugins/t/check_hpjd.t
new file mode 100644
index 0000000..4d64852
--- /dev/null
+++ b/plugins/t/check_hpjd.t
@@ -0,0 +1,71 @@
+#! /usr/bin/perl -w -I ..
+#
+# HP JetDirect Test via check_hpjd
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan skip_all => "check_hpjd not compiled" unless (-x "check_hpjd");
+
+
+my $successOutput = '/^Printer ok - /';
+my $failureOutput = '/Timeout: No [Rr]esponse from /';
+
+my $host_tcp_hpjd = getTestParameter(
+ "NP_HOST_TCP_HPJD",
+ "A host (usually a printer) providing the HP-JetDirect Services"
+ );
+
+my $host_hpjd_port_invalid = getTestParameter(
+ "NP_HOST_HPJD_PORT_INVALID",
+ "A port that HP-JetDirect Services is not listening on",
+ "162"
+ );
+
+my $host_hpjd_port_valid = getTestParameter(
+ "NP_HOST_HPJD_PORT_VALID",
+ "The port that HP-JetDirect Services is currently listening on",
+ "161"
+ );
+
+my $host_nonresponsive = getTestParameter(
+ "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests",
+ "10.0.0.1"
+ );
+
+my $hostname_invalid = getTestParameter(
+ "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost"
+ );
+
+my $tests = $host_tcp_hpjd ? 9 : 5;
+plan tests => $tests;
+my $res;
+
+SKIP: {
+ skip "No HP JetDirect defined", 2 unless $host_tcp_hpjd;
+ $res = NPTest->testCmd("./check_hpjd -H $host_tcp_hpjd");
+ cmp_ok( $res->return_code, 'eq', 0, "Jetdirect responding" );
+ like ( $res->output, $successOutput, "Output correct" );
+
+ $res = NPTest->testCmd("./check_hpjd -H $host_tcp_hpjd -p $host_hpjd_port_valid");
+ cmp_ok( $res->return_code, 'eq', 0, "Jetdirect responding on port $host_hpjd_port_valid" );
+ like ( $res->output, $successOutput, "Output correct" );
+
+ $res = NPTest->testCmd("./check_hpjd -H $host_tcp_hpjd -p $host_hpjd_port_invalid");
+ cmp_ok( $res->return_code, 'eq', 2, "Jetdirect not responding on port $host_hpjd_port_invalid" );
+ like ( $res->output, $failureOutput, "Output correct" );
+}
+
+$res = NPTest->testCmd("./check_hpjd -H $host_nonresponsive");
+cmp_ok( $res->return_code, 'eq', 2, "Host not responding");
+like ( $res->output, $failureOutput, "Output OK" );
+
+$res = NPTest->testCmd("./check_hpjd -H $hostname_invalid");
+cmp_ok( $res->return_code, 'eq', 3, "Hostname invalid");
+
diff --git a/plugins/t/check_http.t b/plugins/t/check_http.t
new file mode 100644
index 0000000..1f2fbdf
--- /dev/null
+++ b/plugins/t/check_http.t
@@ -0,0 +1,190 @@
+#! /usr/bin/perl -w -I ..
+#
+# HyperText Transfer Protocol (HTTP) Test via check_http
+#
+#
+
+use strict;
+use Test::More;
+use POSIX qw/mktime strftime/;
+use NPTest;
+
+plan tests => 49;
+
+my $successOutput = '/OK.*HTTP.*second/';
+
+my $res;
+my $plugin = 'check_http';
+$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
+
+my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
+my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
+my $host_tls_cert = getTestParameter("NP_HOST_TLS_CERT", "the common name of the certificate.", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
+my $host_tcp_http2 = getTestParameter("NP_HOST_TCP_HTTP2", "A host providing an index page containing the string 'monitoring'", "test.monitoring-plugins.org");
+my $host_tcp_proxy = getTestParameter("NP_HOST_TCP_PROXY", "A host providing a HTTP proxy with CONNECT support", "localhost");
+my $port_tcp_proxy = getTestParameter("NP_PORT_TCP_PROXY", "Port of the proxy with HTTP and CONNECT support", "3128");
+
+my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
+
+
+$res = NPTest->testCmd(
+ "./$plugin $host_tcp_http -wt 300 -ct 600"
+ );
+cmp_ok( $res->return_code, '==', 0, "Webserver $host_tcp_http responded" );
+like( $res->output, $successOutput, "Output OK" );
+
+$res = NPTest->testCmd(
+ "./$plugin $host_tcp_http -wt 300 -ct 600 -v -v -v -k 'bob:there' -k 'carl:frown'"
+ );
+like( $res->output, '/bob:there\r\ncarl:frown\r\n/', "Got headers with multiple -k options" );
+
+$res = NPTest->testCmd(
+ "./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3"
+ );
+cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
+cmp_ok( $res->output, 'eq', "CRITICAL - Socket timeout after 3 seconds", "Output OK");
+
+$res = NPTest->testCmd(
+ "./$plugin $hostname_invalid -wt 1 -ct 2"
+ );
+cmp_ok( $res->return_code, '==', 2, "Webserver $hostname_invalid not valid" );
+# The first part of the message comes from the OS catalogue, so cannot check this.
+# On Debian, it is Name or service not known, on Darwin, it is No address associated with nodename
+# Is also possible to get a socket timeout if DNS is not responding fast enough
+like( $res->output, "/Unable to open TCP socket|Socket timeout after/", "Output OK");
+
+# host header checks
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http");
+like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.'\s*$/ms', "Host Header OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+
+$res = NPTest->testCmd("./$plugin -v -H $host_tcp_http:8080 -p 80");
+like( $res->output, '/^Host: '.$host_tcp_http.':8080\s*$/ms', "Host Header OK" );
+
+SKIP: {
+ skip "No internet access", 3 if $internet_access eq "no";
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http -S");
+ like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http:8080 -S -p 443");
+ like( $res->output, '/^Host: '.$host_tls_http.':8080\s*$/ms', "Host Header OK" );
+
+ $res = NPTest->testCmd("./$plugin -v -H $host_tls_http:443 -S -p 443");
+ like( $res->output, '/^Host: '.$host_tls_http.'\s*$/ms', "Host Header OK" );
+};
+
+SKIP: {
+ skip "No host serving monitoring in index file", 7 unless $host_tcp_http2;
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring'" );
+ cmp_ok( $res->return_code, "==", 0, "Got a reference to 'monitoring'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing'" );
+ cmp_ok( $res->return_code, "==", 2, "Not got 'mONiTORing'");
+ like ( $res->output, "/pattern not found/", "Error message says 'pattern not found'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -R 'mONiTORing'" );
+ cmp_ok( $res->return_code, "==", 0, "But case insensitive doesn't mind 'mONiTORing'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'monitoring' --invert-regex" );
+ cmp_ok( $res->return_code, "==", 2, "Invert results work when found");
+ like ( $res->output, "/pattern found/", "Error message says 'pattern found'");
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tcp_http2 -r 'mONiTORing' --invert-regex" );
+ cmp_ok( $res->return_code, "==", 0, "And also when not found");
+}
+SKIP: {
+ skip "No internet access", 22 if $internet_access eq "no";
+
+ $res = NPTest->testCmd(
+ "./$plugin --ssl $host_tls_http"
+ );
+ cmp_ok( $res->return_code, '==', 0, "Can read https for $host_tls_http" );
+
+ $res = NPTest->testCmd( "./$plugin -C 1 --ssl $host_tls_http" );
+ cmp_ok( $res->return_code, '==', 0, "Checking certificate for $host_tls_http");
+ like ( $res->output, "/Certificate '$host_tls_cert' will expire on/", "Output OK" );
+ my $saved_cert_output = $res->output;
+
+ $res = NPTest->testCmd( "./$plugin -C 8000,1 --ssl $host_tls_http" );
+ cmp_ok( $res->return_code, '==', 1, "Checking certificate for $host_tls_http");
+ like ( $res->output, qr/WARNING - Certificate '$host_tls_cert' expires in \d+ day/, "Output Warning" );
+
+ $res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
+ is( $res->return_code, 0, "Old syntax for cert checking okay" );
+ is( $res->output, $saved_cert_output, "Same output as new syntax" );
+
+ $res = NPTest->testCmd( "./$plugin -H $host_tls_http -C 1" );
+ is( $res->return_code, 0, "Updated syntax for cert checking okay" );
+ is( $res->output, $saved_cert_output, "Same output as new syntax" );
+
+ $res = NPTest->testCmd( "./$plugin -C 1 $host_tls_http" );
+ cmp_ok( $res->output, 'eq', $saved_cert_output, "--ssl option automatically added");
+
+ $res = NPTest->testCmd( "./$plugin $host_tls_http -C 1" );
+ cmp_ok( $res->output, 'eq', $saved_cert_output, "Old syntax for cert checking still works");
+
+ # run some certificate checks with faketime
+ SKIP: {
+ skip "No faketime binary found", 7 if !$faketime;
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/OK - Certificate '$host_tls_cert' will expire on/, "Catch cert output");
+ is( $res->return_code, 0, "Catch cert output exit code" );
+ my($mon,$day,$hour,$min,$sec,$year) = ($res->output =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+(\d+)/);
+ if(!defined $year) {
+ die("parsing date failed from: ".$res->output);
+ }
+ my $months = {'Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11};
+ my $ts = mktime($sec, $min, $hour, $day, $months->{$mon}, $year-1900);
+ my $time = strftime("%Y-%m-%d %H:%M:%S", localtime($ts));
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' just expired/, "Output on expire date");
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-1))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 0 minutes/, "cert expires in 1 second output");
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-120))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 minutes/, "cert expires in 2 minutes output");
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts-7200))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expires in 2 hours/, "cert expires in 2 hours output");
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./$plugin -C 1 $host_tls_http");
+ like($res->output, qr/CRITICAL - Certificate '$host_tls_cert' expired on/, "Certificate expired output");
+ };
+
+ $res = NPTest->testCmd( "./$plugin --ssl $host_tls_http -E" );
+ like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
+ like ( $res->output, '/time_ssl=[\d\.]+/', 'Extended Performance Data SSL Output OK' );
+
+ $res = NPTest->testCmd( "./$plugin -H www.mozilla.com -u /firefox -f follow" );
+ is( $res->return_code, 0, "Redirection based on location is okay");
+
+ $res = NPTest->testCmd( "./$plugin -H www.mozilla.com --extended-perfdata" );
+ like ( $res->output, '/time_connect=[\d\.]+/', 'Extended Performance Data Output OK' );
+}
+
+SKIP: {
+ skip "No internet access or proxy configured", 6 if $internet_access eq "no" or ! $host_tcp_proxy;
+
+ $res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -u http://$host_tcp_http -e 200,301,302");
+ is( $res->return_code, 0, "Proxy HTTP works");
+ like($res->output, qr/OK: Status line output matched/, "Proxy HTTP Output is sufficient");
+
+ $res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -H $host_tls_http -S -j CONNECT");
+ is( $res->return_code, 0, "Proxy HTTP CONNECT works");
+ like($res->output, qr/HTTP OK:/, "Proxy HTTP CONNECT output sufficient");
+
+ $res = NPTest->testCmd( "./$plugin -I $host_tcp_proxy -p $port_tcp_proxy -H $host_tls_http -S -j CONNECT:HEAD");
+ is( $res->return_code, 0, "Proxy HTTP CONNECT works with override method");
+ like($res->output, qr/HTTP OK:/, "Proxy HTTP CONNECT output sufficient");
+}
diff --git a/plugins/t/check_imap.t b/plugins/t/check_imap.t
new file mode 100644
index 0000000..cf2f81c
--- /dev/null
+++ b/plugins/t/check_imap.t
@@ -0,0 +1,38 @@
+#! /usr/bin/perl -w -I ..
+#
+# Internet Mail Access Protocol (IMAP) Server Tests via check_imap
+#
+#
+
+use strict;
+use Test::More tests => 7;
+use NPTest;
+
+my $host_tcp_smtp = getTestParameter("NP_HOST_TCP_SMTP", "A host providing an STMP Service (a mail server)", "mailhost");
+my $host_tcp_imap = getTestParameter("NP_HOST_TCP_IMAP", "A host providing an IMAP Service (a mail server)", $host_tcp_smtp);
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+my $t;
+
+$t = NPTest->testCmd( "./check_imap $host_tcp_imap" );
+cmp_ok( $t->return_code, '==', 0, "Contacted imap" );
+
+$t = NPTest->testCmd( "./check_imap -H $host_tcp_imap -p 143 -w 9 -c 9 -to 10 -e '* OK'" );
+cmp_ok( $t->return_code, '==', 0, "Got right response" );
+
+$t = NPTest->testCmd( "./check_imap $host_tcp_imap -p 143 -wt 9 -ct 9 -to 10 -e '* OK'" );
+cmp_ok( $t->return_code, '==', 0, "Check old parameter options" );
+
+$t = NPTest->testCmd( "./check_imap $host_nonresponsive" );
+cmp_ok( $t->return_code, '==', 2, "Get error with non responsive host" );
+
+$t = NPTest->testCmd( "./check_imap $hostname_invalid" );
+cmp_ok( $t->return_code, '==', 2, "Invalid hostname" );
+
+$t = NPTest->testCmd( "./check_imap -H $host_tcp_imap -e unlikely_string");
+cmp_ok( $t->return_code, '==', 1, "Got warning with bad response" );
+
+$t = NPTest->testCmd( "./check_imap -H $host_tcp_imap -e unlikely_string -M crit");
+cmp_ok( $t->return_code, '==', 2, "Got critical error with bad response" );
+
diff --git a/plugins/t/check_jabber.t b/plugins/t/check_jabber.t
new file mode 100644
index 0000000..fcdae17
--- /dev/null
+++ b/plugins/t/check_jabber.t
@@ -0,0 +1,50 @@
+#! /usr/bin/perl -w -I ..
+#
+# Jabber Server Tests via check_jabber
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan tests => 10;
+
+my $host_tcp_jabber = getTestParameter("NP_HOST_TCP_JABBER", "A host providing the Jabber Service", "jabber.de");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+
+my $jabberOK = '/JABBER OK\s-\s\d+\.\d+\ssecond response time on '.$host_tcp_jabber.' port 5222/';
+
+my $jabberUnresponsive = '/CRITICAL\s-\sSocket timeout after\s\d+\sseconds/';
+
+my $jabberInvalid = '/JABBER CRITICAL - Invalid hostname, address or socket:\s.+/';
+
+my $r;
+
+SKIP: {
+ skip "No jabber server defined", 6 unless $host_tcp_jabber;
+
+ $r = NPTest->testCmd( "./check_jabber -H $host_tcp_jabber" );
+ is( $r->return_code, 0, "Connected okay");
+ like( $r->output, $jabberOK, "Output as expected" );
+
+ $r = NPTest->testCmd( "./check_jabber -H $host_tcp_jabber -w 9 -c 9 -t 10" );
+ is( $r->return_code, 0, "Connected okay, within limits" );
+ like( $r->output, $jabberOK, "Output as expected" );
+
+ $r = NPTest->testCmd( "./check_jabber -H $host_tcp_jabber -wt 9 -ct 9 -to 10" );
+ is( $r->return_code, 0, "Old syntax okay" );
+ like( $r->output, $jabberOK, "Output as expected" );
+
+}
+
+$r = NPTest->testCmd( "./check_jabber $host_nonresponsive" );
+is( $r->return_code, 2, "Unresponsive host gives critical" );
+like( $r->output, $jabberUnresponsive );
+
+$r = NPTest->testCmd( "./check_jabber $hostname_invalid" );
+is( $r->return_code, 2, "Invalid hostname gives critical" );
+like( $r->output, $jabberInvalid );
+
diff --git a/plugins/t/check_ldap.t b/plugins/t/check_ldap.t
new file mode 100644
index 0000000..b8a4a76
--- /dev/null
+++ b/plugins/t/check_ldap.t
@@ -0,0 +1,71 @@
+#!/usr/bin/env perl -I ..
+#
+# Lightweight Directory Access Protocol (LDAP) Test via check_ldap
+#
+#
+
+use strict;
+use warnings;
+use Test::More;
+use NPTest;
+
+my $host_tcp_ldap = getTestParameter("NP_HOST_TCP_LDAP", "A host providing the LDAP Service", "localhost");
+my $ldap_base_dn = getTestParameter("NP_LDAP_BASE_DN", "A base dn for the LDAP Service", "cn=admin");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+my($result, $cmd);
+my $command = './check_ldap';
+
+plan tests => 16;
+
+SKIP: {
+ skip "NP_HOST_NONRESPONSIVE not set", 2 if ! $host_nonresponsive;
+
+ $result = NPTest->testCmd("$command -H $host_nonresponsive -b ou=blah -t 2 -w 1 -c 1");
+ is( $result->return_code, 2, "$command -H $host_nonresponsive -b ou=blah -t 5 -w 2 -c 3" );
+ is( $result->output, 'CRITICAL - Socket timeout after 2 seconds', "output ok" );
+};
+
+SKIP: {
+ skip "NP_HOSTNAME_INVALID not set", 2 if ! $hostname_invalid;
+
+ $result = NPTest->testCmd("$command -H $hostname_invalid -b ou=blah -t 5");
+ is( $result->return_code, 2, "$command -H $hostname_invalid -b ou=blah -t 5" );
+ is( $result->output, 'Could not bind to the LDAP server', "output ok" );
+};
+
+SKIP: {
+ skip "NP_HOST_TCP_LDAP not set", 12 if ! $host_tcp_ldap;
+ skip "NP_LDAP_BASE_DN not set", 12 if ! $ldap_base_dn;
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 0, $cmd );
+ like( $result->output, '/^LDAP OK - \d+.\d+ seconds response time\|time=\d+\.\d+s;2\.0+;3\.0+;0\.0+$/', "output ok" );
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3 -W 10000000 -C 10000001";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 0, $cmd );
+ like( $result->output, '/^LDAP OK - found \d+ entries in \d+\.\d+ seconds\|time=\d\.\d+s;2\.0+;3\.0+;0\.0+ entries=\d+\.0+;10000000;10000001;0\.0+$/', "output ok" );
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3 -W 10000000: -C 10000001:";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 2, $cmd );
+ like( $result->output, '/^LDAP CRITICAL - found \d+ entries in \d+\.\d+ seconds\|time=\d\.\d+s;2\.0+;3\.0+;0\.0+ entries=\d+\.0+;10000000:;10000001:;0\.0+$/', "output ok" );
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3 -W 0 -C 0";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 2, $cmd );
+ like( $result->output, '/^LDAP CRITICAL - found \d+ entries in \d+\.\d+ seconds\|time=\d\.\d+s;2\.0+;3\.0+;0\.0+ entries=\d+\.0+;0;0;0\.0+$/', "output ok" );
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3 -W 10000000: -C 10000001";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 1, $cmd );
+ like( $result->output, '/^LDAP WARNING - found \d+ entries in \d+\.\d+ seconds\|time=\d\.\d+s;2\.0+;3\.0+;0\.0+ entries=\d+\.0+;10000000:;10000001;0\.0+$/', "output ok" );
+
+ $cmd = "$command -H $host_tcp_ldap -b $ldap_base_dn -t 5 -w 2 -c 3 -3 -C 10000001";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 0, $cmd );
+ like( $result->output, '/^LDAP OK - found \d+ entries in \d+\.\d+ seconds\|time=\d\.\d+s;2\.0+;3\.0+;0\.0+ entries=\d+\.0+;;10000001;0\.0+$/', "output ok" );
+};
diff --git a/plugins/t/check_load.t b/plugins/t/check_load.t
new file mode 100644
index 0000000..bba8947
--- /dev/null
+++ b/plugins/t/check_load.t
@@ -0,0 +1,43 @@
+#! /usr/bin/perl -w -I ..
+#
+# Load Average Tests via check_load
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my $res;
+
+my $loadValue = "[0-9]+\.?[0-9]+";
+my $successOutput = "/^LOAD OK - total load average: $loadValue, $loadValue, $loadValue/";
+my $successScaledOutput = "/^LOAD OK - scaled load average: $loadValue, $loadValue, $loadValue - total load average: $loadValue, $loadValue, $loadValue/";
+my $failureOutput = "/^LOAD CRITICAL - total load average: $loadValue, $loadValue, $loadValue/";
+my $failurScaledOutput = "/^LOAD CRITICAL - scaled load average: $loadValue, $loadValue, $loadValue - total load average: $loadValue, $loadValue, $loadValue/";
+
+plan tests => 13;
+
+$res = NPTest->testCmd( "./check_load -w 100,100,100 -c 100,100,100" );
+cmp_ok( $res->return_code, 'eq', 0, "load not over 100");
+like( $res->output, $successOutput, "Output OK");
+
+$res = NPTest->testCmd( "./check_load -w 0,0,0 -c 0,0,0" );
+cmp_ok( $res->return_code, 'eq', 2, "Load over 0");
+like( $res->output, $failureOutput, "Output OK");
+
+$res = NPTest->testCmd( "./check_load -r -w 0,0,0 -c 0,0,0" );
+cmp_ok( $res->return_code, 'eq', 2, "Load over 0 with per cpu division");
+like( $res->output, $failurScaledOutput, "Output OK");
+
+$res = NPTest->testCmd( "./check_load -w 100 -c 100,110" );
+cmp_ok( $res->return_code, 'eq', 0, "Plugin can handle non-triplet-arguments");
+like( $res->output, $successOutput, "Output OK");
+like( $res->perf_output, "/load1=$loadValue;100.000;100.000/", "Test handling of non triplet thresholds (load1)");
+like( $res->perf_output, "/load5=$loadValue;100.000;110.000/", "Test handling of non triplet thresholds (load5)");
+like( $res->perf_output, "/load15=$loadValue;100.000;110.000/", "Test handling of non triplet thresholds (load15)");
+
+
+$res = NPTest->testCmd( "./check_load -w 100,100,100 -c 100,100,100 -r" );
+cmp_ok( $res->return_code, 'eq', 0, "load not over 100");
+like( $res->output, $successScaledOutput, "Output OK");
diff --git a/plugins/t/check_mysql.t b/plugins/t/check_mysql.t
new file mode 100644
index 0000000..baf3acc
--- /dev/null
+++ b/plugins/t/check_mysql.t
@@ -0,0 +1,74 @@
+#! /usr/bin/perl -w -I ..
+#
+# MySQL Database Server Tests via check_mysql
+#
+#
+#
+# These are the database permissions required for this test:
+# GRANT SELECT ON $db.* TO $user@$host IDENTIFIED BY '$password';
+# GRANT SUPER, REPLICATION CLIENT ON *.* TO $user@$host;
+# Check with:
+# mysql -u$user -p$password -h$host $db
+
+use strict;
+use Test::More;
+use NPTest;
+
+use vars qw($tests);
+
+plan skip_all => "check_mysql not compiled" unless (-x "check_mysql");
+
+plan tests => 15;
+
+my $bad_login_output = '/Access denied for user /';
+my $mysqlserver = getTestParameter("NP_MYSQL_SERVER", "A MySQL Server hostname or IP with no slaves setup");
+my $mysqlsocket = getTestParameter("NP_MYSQL_SOCKET", "Full path to a MySQL Server socket with no slaves setup");
+my $mysql_login_details = getTestParameter("NP_MYSQL_LOGIN_DETAILS", "Command line parameters to specify login access (requires REPLICATION CLIENT privileges)", "-u test -ptest");
+my $with_slave = getTestParameter("NP_MYSQL_WITH_SLAVE", "MySQL server with slaves setup");
+my $with_slave_login = getTestParameter("NP_MYSQL_WITH_SLAVE_LOGIN", "Login details for server with slave (requires REPLICATION CLIENT privileges)", $mysql_login_details || "-u test -ptest");
+
+my $result;
+
+SKIP: {
+ skip "No mysql server defined", 5 unless $mysqlserver;
+ $result = NPTest->testCmd("./check_mysql -H $mysqlserver $mysql_login_details");
+ cmp_ok( $result->return_code, '==', 0, "Login okay");
+
+ $result = NPTest->testCmd("./check_mysql -H $mysqlserver -u dummy -pdummy");
+ cmp_ok( $result->return_code, '==', 2, "Login failure");
+ like( $result->output, $bad_login_output, "Expected login failure message");
+
+ $result = NPTest->testCmd("./check_mysql -S -H $mysqlserver $mysql_login_details");
+ cmp_ok( $result->return_code, "==", 1, "No slaves defined" );
+ like( $result->output, "/No slaves defined/", "Correct error message");
+}
+
+SKIP: {
+ skip "No mysql socket defined", 5 unless $mysqlsocket;
+ $result = NPTest->testCmd("./check_mysql -s $mysqlsocket $mysql_login_details");
+ cmp_ok( $result->return_code, '==', 0, "Login okay");
+
+ $result = NPTest->testCmd("./check_mysql -s $mysqlsocket -u dummy -pdummy");
+ cmp_ok( $result->return_code, '==', 2, "Login failure");
+ like( $result->output, $bad_login_output, "Expected login failure message");
+
+ $result = NPTest->testCmd("./check_mysql -S -s $mysqlsocket $mysql_login_details");
+ cmp_ok( $result->return_code, "==", 1, "No slaves defined" );
+ like( $result->output, "/No slaves defined/", "Correct error message");
+}
+
+SKIP: {
+ skip "No mysql server with slaves defined", 5 unless $with_slave;
+ $result = NPTest->testCmd("./check_mysql -H $with_slave $with_slave_login");
+ cmp_ok( $result->return_code, '==', 0, "Login okay");
+
+ $result = NPTest->testCmd("./check_mysql -S -H $with_slave $with_slave_login");
+ cmp_ok( $result->return_code, "==", 0, "Slaves okay" );
+
+ $result = NPTest->testCmd("./check_mysql -S -H $with_slave $with_slave_login -w 60");
+ cmp_ok( $result->return_code, '==', 0, 'Slaves are not > 60 seconds behind');
+
+ $result = NPTest->testCmd("./check_mysql -S -H $with_slave $with_slave_login -w 60:");
+ cmp_ok( $result->return_code, '==', 1, 'Alert warning if < 60 seconds behind');
+ like( $result->output, "/^SLOW_SLAVE WARNING:/", "Output okay");
+}
diff --git a/plugins/t/check_mysql_query.t b/plugins/t/check_mysql_query.t
new file mode 100644
index 0000000..c30245b
--- /dev/null
+++ b/plugins/t/check_mysql_query.t
@@ -0,0 +1,58 @@
+#! /usr/bin/perl -w -I ..
+#
+# MySQL Database Server Tests via check_mysql
+#
+#
+#
+# These are the database permissions required for this test:
+# GRANT SELECT ON $db.* TO $user@$host IDENTIFIED BY '$password';
+# Check with:
+# mysql -u$user -p$password -h$host $db
+
+use strict;
+use Test::More;
+use NPTest;
+
+use vars qw($tests);
+
+plan skip_all => "check_mysql_query not compiled" unless (-x "check_mysql_query");
+
+my $mysqlserver = getTestParameter("NP_MYSQL_SERVER", "A MySQL Server with no slaves setup");
+my $mysql_login_details = getTestParameter("NP_MYSQL_LOGIN_DETAILS", "Command line parameters to specify login access", "-u user -ppw -d db");
+my $result;
+
+if (! $mysqlserver) {
+ plan skip_all => "No mysql server defined";
+} else {
+ plan tests => 13;
+}
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SELECT 1+1' -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 0, "Can run query");
+
+$result = NPTest->testCmd("./check_mysql_query -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 3, "Missing query parameter");
+like( $result->output, "/Must specify a SQL query to run/", "Missing query error message");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SELECT 1+1' -H $mysqlserver -u dummy -d mysql");
+cmp_ok( $result->return_code, '==', 2, "Login failure");
+like( $result->output, "/Access denied for user /", "Expected login failure message");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SELECT PI()' -w 3 -c 4 -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 1, "Got warning");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SELECT PI()*2' -w 3 -c 4 -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 2, "Got critical");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SELECT * FROM adsf' -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 2, "Bad query");
+like( $result->output, "/Error with query/", "Bad query error message");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SHOW VARIABLES LIKE \"bob\"' -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 1, "No rows");
+like( $result->output, "/No rows returned/", "No rows error message");
+
+$result = NPTest->testCmd("./check_mysql_query -q 'SHOW VARIABLES' -H $mysqlserver $mysql_login_details");
+cmp_ok( $result->return_code, '==', 2, "Data not numeric");
+like( $result->output, "/Is not a numeric/", "Data not numeric error message");
+
diff --git a/plugins/t/check_nagios.nagios1.status.log b/plugins/t/check_nagios.nagios1.status.log
new file mode 100644
index 0000000..64d9ce7
--- /dev/null
+++ b/plugins/t/check_nagios.nagios1.status.log
@@ -0,0 +1,5 @@
+# Nagios 1.2 Status File
+[1133537544] PROGRAM;1133537484;21980;1;1133537534;0;1;1;1;1;0;1;1;1
+[1133537544] HOST;ADSL;PENDING;0;0;0;0;0;0;0;0;1;1;1;1;0;0.0;0;1;1;(Not enough data to determine host status yet)
+[1133537544] HOST;Internet;UP;1133537486;1132135282;0;1402203;0;0;0;0;1;1;1;1;0;0.00;0;1;1;(Host assumed to be up)
+[1133537544] SERVICE;Internet;TCP/IP;OK;1/3;HARD;1133537486;1133537786;ACTIVE;1;1;1;1132135282;0;OK;1402203;0;0;0;0;0;1;0;4;1;0;0.00;0;1;1;0;PING OK - Packet loss = 0%, RTA = 0.09 ms
diff --git a/plugins/t/check_nagios.nagios2.status.dat b/plugins/t/check_nagios.nagios2.status.dat
new file mode 100644
index 0000000..6f62bac
--- /dev/null
+++ b/plugins/t/check_nagios.nagios2.status.dat
@@ -0,0 +1,127 @@
+########################################
+# NAGIOS STATUS FILE
+#
+# THIS FILE IS AUTOMATICALLY GENERATED
+# BY NAGIOS. DO NOT MODIFY THIS FILE!
+########################################
+
+info {
+ created=1133537302
+ version=2.0b5
+ }
+
+program {
+ modified_host_attributes=0
+ modified_service_attributes=0
+ nagios_pid=2750
+ daemon_mode=1
+ program_start=1133537167
+ last_command_check=1133537297
+ last_log_rotation=0
+ enable_notifications=1
+ active_service_checks_enabled=1
+ passive_service_checks_enabled=1
+ active_host_checks_enabled=1
+ passive_host_checks_enabled=1
+ enable_event_handlers=1
+ obsess_over_services=0
+ obsess_over_hosts=0
+ check_service_freshness=1
+ check_host_freshness=0
+ enable_flap_detection=1
+ enable_failure_prediction=1
+ process_performance_data=0
+ global_host_event_handler=
+ global_service_event_handler=
+ }
+
+host {
+ host_name=ADSL-derby-office
+ modified_attributes=0
+ check_command=check_host_alive_ping
+ event_handler=
+ has_been_checked=0
+ should_be_scheduled=0
+ check_execution_time=0.000
+ check_latency=0.000
+ check_type=0
+ current_state=0
+ last_hard_state=0
+ plugin_output=
+ performance_data=
+ last_check=0
+ next_check=0
+ current_attempt=1
+ max_attempts=3
+ state_type=1
+ last_state_change=0
+ last_hard_state_change=0
+ last_time_up=0
+ last_time_down=0
+ last_time_unreachable=0
+ last_notification=0
+ next_notification=0
+ no_more_notifications=0
+ current_notification_number=0
+ notifications_enabled=1
+ problem_has_been_acknowledged=0
+ acknowledgement_type=0
+ active_checks_enabled=1
+ passive_checks_enabled=1
+ event_handler_enabled=1
+ flap_detection_enabled=1
+ failure_prediction_enabled=1
+ process_performance_data=1
+ obsess_over_host=1
+ last_update=1133537302
+ is_flapping=0
+ percent_state_change=0.00
+ scheduled_downtime_depth=0
+ }
+
+service {
+ host_name=ADSL-derby-office
+ service_description=TCP/IP
+ modified_attributes=0
+ check_command=host5_service23_check_ping
+ event_handler=
+ has_been_checked=0
+ should_be_scheduled=1
+ check_execution_time=0.000
+ check_latency=0.000
+ check_type=0
+ current_state=0
+ last_hard_state=0
+ current_attempt=1
+ max_attempts=3
+ state_type=1
+ last_state_change=0
+ last_hard_state_change=0
+ last_time_ok=0
+ last_time_warning=0
+ last_time_unknown=0
+ last_time_critical=0
+ plugin_output=(Service assumed to be ok)
+ performance_data=
+ last_check=0
+ next_check=1133537317
+ current_notification_number=0
+ last_notification=0
+ next_notification=0
+ no_more_notifications=0
+ notifications_enabled=0
+ active_checks_enabled=1
+ passive_checks_enabled=1
+ event_handler_enabled=1
+ problem_has_been_acknowledged=0
+ acknowledgement_type=0
+ flap_detection_enabled=1
+ failure_prediction_enabled=1
+ process_performance_data=1
+ obsess_over_service=0
+ last_update=1133537302
+ is_flapping=0
+ percent_state_change=0.00
+ scheduled_downtime_depth=0
+ }
+
diff --git a/plugins/t/check_nagios.t b/plugins/t/check_nagios.t
new file mode 100644
index 0000000..f38f5e9
--- /dev/null
+++ b/plugins/t/check_nagios.t
@@ -0,0 +1,92 @@
+#! /usr/bin/perl -w -I ..
+#
+# check_nagios tests
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+if (`uname -s` eq "SunOS\n") {
+ plan skip_all => "Ignoring tests on solaris because of pst3";
+} else {
+ plan tests => 13;
+}
+
+my $successOutput = '/^NAGIOS OK: /';
+my $warningOutput = '/^NAGIOS WARNING: /';
+my $failureOutput = '/^NAGIOS CRITICAL: /';
+
+my $nagios1 = "t/check_nagios.nagios1.status.log";
+my $nagios2 = "t/check_nagios.nagios2.status.dat";
+
+my $result;
+
+# Did use init, but MacOSX 10.4 replaces init with launchd
+# Alternative is to insist that nagios is running to run this test
+# Reasonable to expect cron because build servers will
+# invoke cron to run a build
+my $procname = "cron";
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios1 -e 5 -C $procname"
+ );
+cmp_ok( $result->return_code, '==', 1, "Log over 5 minutes old" );
+like ( $result->output, $warningOutput, "Output for warning correct" );
+
+my $now = time;
+# This substitution is dependent on the testcase
+system( "perl -pe 's/1133537544/$now/' $nagios1 > $nagios1.tmp" ) == 0 or die "Problem with munging $nagios1";
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios1.tmp -e 1 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 0, "Log up to date" );
+like ( $result->output, $successOutput, "Output for success correct" );
+
+my $later = $now - 61;
+system( "perl -pe 's/1133537544/$later/' $nagios1 > $nagios1.tmp" ) == 0 or die "Problem with munging $nagios1";
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios1.tmp -e 1 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 1, "Log correctly seen as over 1 minute old" );
+my ($age) = ($_ = $result->output) =~ /status log updated (\d+) seconds ago/;
+like( $age, '/^6[0-9]$/', "Log correctly seen as between 60-69 seconds old" );
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios1.tmp -e 5 -C unlikely_command_string"
+ );
+cmp_ok( $result->return_code, "==", 2, "Nagios command not found" );
+like ( $result->output, $failureOutput, "Output for failure correct" );
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios2 -e 5 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 1, "Nagios2 for logfile over 5 mins old" );
+
+$now = time;
+system( "perl -pe 's/1133537302/$now/' $nagios2 > $nagios2.tmp" ) == 0 or die "Problem with munging $nagios2";
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios2.tmp -e 1 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 0, "Nagios2 log up to date" );
+
+$later = $now - 61;
+system( "perl -pe 's/1133537302/$later/' $nagios2 > $nagios2.tmp" ) == 0 or die "Problem with munging $nagios2";
+
+$result = NPTest->testCmd(
+ "./check_nagios -F $nagios2.tmp -e 1 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 1, "Nagios2 log correctly seen as over 1 minute old" );
+($age) = ($_ = $result->output) =~ /status log updated (\d+) seconds ago/;
+like( $age, '/^6[0-9]$/', "Log correctly seen as between 60-69 seconds old" );
+
+$result = NPTest->testCmd(
+ "./check_nagios -F t/check_nagios.t -e 1 -C $procname"
+ );
+cmp_ok( $result->return_code, "==", 2, "Invalid log file" );
+
+
diff --git a/plugins/t/check_ntp.t b/plugins/t/check_ntp.t
new file mode 100644
index 0000000..b8fc8fd
--- /dev/null
+++ b/plugins/t/check_ntp.t
@@ -0,0 +1,110 @@
+#! /usr/bin/perl -w -I ..
+#
+# Testing NTP
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my @PLUGINS1 = ('check_ntp', 'check_ntp_peer', 'check_ntp_time');
+my @PLUGINS2 = ('check_ntp_peer');
+
+plan tests => (12 * scalar(@PLUGINS1)) + (6 * scalar(@PLUGINS2));
+
+my $res;
+
+my $ntp_service = getTestParameter( "NP_GOOD_NTP_SERVICE",
+ "A host providing NTP service",
+ "pool.ntp.org");
+
+my $no_ntp_service = getTestParameter( "NP_NO_NTP_SERVICE",
+ "A host NOT providing the NTP service",
+ "localhost" );
+
+my $host_nonresponsive = getTestParameter( "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests",
+ "10.0.0.1" );
+
+my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost");
+
+my $ntp_okmatch1 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
+my $ntp_warnmatch1 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
+my $ntp_critmatch1 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs/';
+my $ntp_okmatch2 = '/^NTP\sOK:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2},\struechimers=[0-9]+/';
+my $ntp_warnmatch2 = '/^NTP\sWARNING:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+,\sstratum=[0-9]{1,2}\s\(WARNING\),\struechimers=[0-9]+/';
+my $ntp_critmatch2 = '/^NTP\sCRITICAL:\sOffset\s-?[0-9]+(\.[0-9]+)?(e-[0-9]{2})?\ssecs,\sjitter=[0-9]+\.[0-9]+\s\(CRITICAL\),\sstratum=[0-9]{1,2},\struechimers=[0-9]+/';
+my $ntp_noresponse = '/^(CRITICAL - Socket timeout after 3 seconds)|(NTP CRITICAL: No response from NTP server)$/';
+my $ntp_nosuchhost = '/^check_ntp.*: Invalid hostname/address - ' . $hostname_invalid . '/';
+
+
+foreach my $plugin (@PLUGINS1) {
+ SKIP: {
+ skip "No NTP server defined", 6 unless $ntp_service;
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000 -c 2000"
+ );
+ cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result (simple check)" );
+ like( $res->output, $ntp_okmatch1, "$plugin: Output match OK (simple check)" );
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000: -c 2000"
+ );
+ cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result (simple check)" );
+ like( $res->output, $ntp_warnmatch1, "$plugin: Output match WARNING (simple check)" );
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000 -c 2000:"
+ );
+ cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result (simple check)" );
+ like( $res->output, $ntp_critmatch1, "$plugin: Output match CRITICAL (simple check)" );
+ }
+
+ SKIP: {
+ skip "No bad NTP server defined", 1 unless $no_ntp_service;
+ $res = NPTest->testCmd(
+ "./$plugin -H $no_ntp_service -t 3"
+ );
+ cmp_ok( $res->return_code, '==', 2, "$plugin: No NTP service" );
+ like( $res->output, $ntp_noresponse, "$plugin: Output match no NTP service" );
+ }
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $host_nonresponsive -t 3"
+ );
+ cmp_ok( $res->return_code, '==', 2, "$plugin: Server not responding" );
+ like( $res->output, $ntp_noresponse, "$plugin: Output match non-responsive" );
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $hostname_invalid"
+ );
+ cmp_ok( $res->return_code, '==', 3, "$plugin: Invalid hostname/address" );
+ like( $res->output, $ntp_nosuchhost, "$plugin: Output match invalid hostname/address" );
+
+}
+
+foreach my $plugin (@PLUGINS2) {
+ SKIP: {
+ skip "No NTP server defined", 6 unless $ntp_service;
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k 200000 -m 1: -n 0:"
+ );
+ cmp_ok( $res->return_code, '==', 0, "$plugin: Good NTP result with jitter, stratum, and truechimers check" );
+ like( $res->output, $ntp_okmatch2, "$plugin: Output match OK with jitter, stratum, and truechimers" );
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000 -c 2000 -W \\~:-1 -C 21 -j 100000 -k 200000 -m 1: -n 0:"
+ );
+ cmp_ok( $res->return_code, '==', 1, "$plugin: Warning NTP result with jitter, stratum, and truechimers check" );
+ like( $res->output, $ntp_warnmatch2, "$plugin: Output match WARNING with jitter, stratum, and truechimers" );
+
+ $res = NPTest->testCmd(
+ "./$plugin -H $ntp_service -w 1000 -c 2000 -W 20 -C 21 -j 100000 -k \\~:-1 -m 1: -n 0:"
+ );
+ cmp_ok( $res->return_code, '==', 2, "$plugin: Critical NTP result with jitter, stratum, and truechimers check" );
+ like( $res->output, $ntp_critmatch2, "$plugin: Output match CRITICAL with jitter, stratum, and truechimers" );
+ }
+}
diff --git a/plugins/t/check_ping.t b/plugins/t/check_ping.t
new file mode 100644
index 0000000..1604f8f
--- /dev/null
+++ b/plugins/t/check_ping.t
@@ -0,0 +1,109 @@
+#! /usr/bin/perl -w -I ..
+#
+# Ping Response Tests via check_ping
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan tests => 20;
+
+my $successOutput = '/PING (ok|OK) - Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms/';
+my $failureOutput = '/Packet loss = +[0-9]{1,2}\%, +RTA = [\.0-9]+ ms/';
+
+my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE",
+ "The hostname of system responsive to network requests",
+ "localhost" );
+
+my $host_nonresponsive = getTestParameter( "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests",
+ "10.0.0.1" );
+
+my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost" );
+
+my $res;
+
+$res = NPTest->testCmd(
+ "./check_ping -H $host_responsive -w 10,100% -c 10,100% -p 1"
+ );
+is( $res->return_code, 0, "Syntax ok" );
+like( $res->output, $successOutput, "Output OK" );
+
+$res = NPTest->testCmd(
+ "./check_ping -H $host_responsive -w 0,0% -c 10,100% -p 1"
+ );
+is( $res->return_code, 1, "Syntax ok, with forced warning" );
+like( $res->output, $failureOutput, "Output OK" );
+
+$res = NPTest->testCmd(
+ "./check_ping -H $host_responsive -w 0,0% -c 0,0% -p 1"
+ );
+is( $res->return_code, 2, "Syntax ok, with forced critical" );
+like( $res->output, $failureOutput, "Output OK" );
+
+$res = NPTest->testCmd(
+ "./check_ping $host_responsive 100 100 1000 1000 -p 1"
+ );
+is( $res->return_code, 0, "Old syntax ok" );
+like( $res->output, $successOutput, "Output OK" );
+
+$res = NPTest->testCmd(
+ "./check_ping $host_responsive 0 0 0 0 -p 1"
+ );
+is( $res->return_code, 2, "Old syntax, with forced critical" );
+like( $res->output, $failureOutput, "Output OK" );
+
+
+# check_ping results will depend on whether the ping command discovered by
+# ./configure has a timeout option. If it does, then the timeout will
+# be set, so check_ping will always get a response. If it doesn't
+# then check_ping will timeout. We do 2 tests for check_ping's timeout
+# - 1 second
+# - 15 seconds
+# The latter should be higher than normal ping timeouts, so should always give a packet loss result
+open(F, "../config.h") or die "Cannot open ../config.h";
+@_ = grep /define PING_HAS_TIMEOUT 1|define PING_PACKETS_FIRST 1/, <F>;
+my $has_timeout;
+$has_timeout = 1 if (scalar @_ == 2); # Need both defined
+close F;
+$res = NPTest->testCmd(
+ "./check_ping -H $host_nonresponsive -w 10,100% -c 10,100% -p 1 -t 1"
+ );
+is( $res->return_code, 2, "Timeout 1 second - host nonresponsive" );
+if ($has_timeout) {
+ like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
+} else {
+ like( $res->output, '/timed out/', "Error contains 'timed out' string" );
+}
+
+$res = NPTest->testCmd(
+ "./check_ping -H $host_nonresponsive -w 10,100% -c 10,100% -p 1 -t 15"
+ );
+is( $res->return_code, 2, "Timeout 15 seconds - host nonresponsive" );
+like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
+
+
+
+
+$res = NPTest->testCmd(
+ "./check_ping $host_nonresponsive -p 1 -t 15 100 100 1000 10000"
+ );
+is( $res->return_code, 2, "Old syntax: Timeout - host nonresponsive" );
+like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
+
+$res = NPTest->testCmd(
+ "./check_ping $hostname_invalid 0 0 0 0 -p 1 -t 1"
+ );
+is( $res->return_code, 3, "Invalid hostname" );
+like( $res->output, '/invalid hostname/i', "Error contains 'invalid hostname' string");
+
+$res = NPTest->testCmd(
+ "./check_ping -w 100,10% -c 200,20%"
+ );
+is( $res->return_code, 3, "No hostname" );
+like( $res->output, '/You must specify a server address or host name/', "Output with appropriate error message");
+
diff --git a/plugins/t/check_pop.t b/plugins/t/check_pop.t
new file mode 100644
index 0000000..62352fd
--- /dev/null
+++ b/plugins/t/check_pop.t
@@ -0,0 +1,55 @@
+#! /usr/bin/perl -w -I ..
+#
+# Post Office Protocol (POP) Server Tests via check_pop
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+plan tests => 5;
+
+my $host_tcp_smtp = getTestParameter(
+ "NP_HOST_TCP_SMTP",
+ "A host providing an STMP Service (a mail server)",
+ "mailhost"
+ );
+
+my $host_tcp_pop = getTestParameter(
+ "NP_HOST_TCP_POP",
+ "A host providing a POP Service (a mail server)",
+ $host_tcp_smtp
+ );
+
+my $host_nonresponsive = getTestParameter(
+ "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests",
+ "10.0.0.1",
+ );
+
+my $hostname_invalid = getTestParameter(
+ "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname",
+ "nosuchhost",
+ );
+
+my %exceptions = ( 2 => "No POP Server present?" );
+
+my $t;
+my $res;
+
+$res = NPTest->testCmd( "./check_pop $host_tcp_pop" );
+cmp_ok( $res->return_code, '==', 0, "POP server ok");
+
+$res = NPTest->testCmd( "./check_pop -H $host_tcp_pop -p 110 -w 9 -c 9 -t 10 -e '+OK'");
+cmp_ok( $res->return_code, '==', 0, "POP server returned +OK");
+
+$res = NPTest->testCmd( "./check_pop $host_tcp_pop -p 110 -wt 9 -ct 9 -to 10 -e '+OK'");
+cmp_ok( $res->return_code, '==', 0, "Old syntax");
+
+$res = NPTest->testCmd( "./check_pop $host_nonresponsive" );
+cmp_ok( $res->return_code, '==', 2, "Non responsive host");
+
+$res = NPTest->testCmd( "./check_pop $hostname_invalid" );
+cmp_ok( $res->return_code, '==', 2, "Invalid host");
diff --git a/plugins/t/check_procs.t b/plugins/t/check_procs.t
new file mode 100644
index 0000000..abe7284
--- /dev/null
+++ b/plugins/t/check_procs.t
@@ -0,0 +1,49 @@
+#! /usr/bin/perl -w -I ..
+#
+# Process Tests via check_procs
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my $t;
+
+if (`uname -s` eq "SunOS\n" && ! -x "/usr/local/nagios/libexec/pst3") {
+ plan skip_all => "Ignoring tests on solaris because of pst3";
+} else {
+ plan tests => 14;
+}
+
+my $result;
+
+$result = NPTest->testCmd( "./check_procs -w 100000 -c 100000" );
+is( $result->return_code, 0, "Checking less than 10000 processes" );
+like( $result->output, '/^PROCS OK: [0-9]+ process(es)? | procs=[0-9]+;100000;100000;0;$/', "Output correct" );
+
+$result = NPTest->testCmd( "./check_procs -w 100000 -c 100000 -s Z" );
+is( $result->return_code, 0, "Checking less than 100000 zombie processes" );
+like( $result->output, '/^PROCS OK: [0-9]+ process(es)? with /', "Output correct" );
+
+if(fork() == 0) { exec("sleep 7"); } else { sleep(1) } # fork a test process in child and give child time to fork in parent
+$result = NPTest->testCmd( "./check_procs -a 'sleep 7'" );
+is( $result->return_code, 0, "Parent process is ignored" );
+like( $result->output, '/^PROCS OK: 1 process?/', "Output correct" );
+
+$result = NPTest->testCmd( "./check_procs -w 0 -c 100000" );
+is( $result->return_code, 1, "Checking warning if processes > 0" );
+like( $result->output, '/^PROCS WARNING: [0-9]+ process(es)? | procs=[0-9]+;0;100000;0;$/', "Output correct" );
+
+$result = NPTest->testCmd( "./check_procs -w 0 -c 0" );
+is( $result->return_code, 2, "Checking critical if processes > 0" );
+like( $result->output, '/^PROCS CRITICAL: [0-9]+ process(es)? | procs=[0-9]+;0;0;0;$/', "Output correct" );
+
+$result = NPTest->testCmd( "./check_procs -w 0 -c 0 -s Ss" );
+is( $result->return_code, 2, "Checking critical if sleeping processes" );
+like( $result->output, '/^PROCS CRITICAL: [0-9]+ process(es)? with /', "Output correct" );
+
+$result = NPTest->testCmd( "./check_procs -w 0 -c 100000 -p 1" );
+is( $result->return_code, 1, "Checking warning for processes by parentid = 1" );
+like( $result->output, '/^PROCS WARNING: [0-9]+ process(es)? with PPID = 1/', "Output correct" );
+
diff --git a/plugins/t/check_smtp.t b/plugins/t/check_smtp.t
new file mode 100644
index 0000000..1a1ebe3
--- /dev/null
+++ b/plugins/t/check_smtp.t
@@ -0,0 +1,84 @@
+#! /usr/bin/perl -w -I ..
+#
+# Simple Mail Transfer Protocol (SMTP) Test via check_smtp
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my $host_tcp_smtp = getTestParameter( "NP_HOST_TCP_SMTP",
+ "A host providing an SMTP Service (a mail server)", "mailhost");
+my $host_tcp_smtp_starttls = getTestParameter( "NP_HOST_TCP_SMTP_STARTTLS",
+ "A host providing SMTP with STARTTLS", $host_tcp_smtp);
+my $host_tcp_smtp_nostarttls = getTestParameter( "NP_HOST_TCP_SMTP_NOSTARTTLS",
+ "A host providing SMTP without STARTTLS", "");
+my $host_tcp_smtp_tls = getTestParameter( "NP_HOST_TCP_SMTP_TLS",
+ "A host providing SMTP with TLS", $host_tcp_smtp);
+
+my $host_nonresponsive = getTestParameter( "NP_HOST_NONRESPONSIVE",
+ "The hostname of system not responsive to network requests", "10.0.0.1" );
+
+my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
+ "An invalid (not known to DNS) hostname", "nosuchhost" );
+my $res;
+
+plan tests => 16;
+
+SKIP: {
+ skip "No SMTP server defined", 4 unless $host_tcp_smtp;
+ $res = NPTest->testCmd( "./check_smtp $host_tcp_smtp" );
+ is ($res->return_code, 0, "OK");
+
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp -p 25 -w 9 -c 9 -t 10 -e 220" );
+ is ($res->return_code, 0, "OK, within 9 second response");
+
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp -p 25 -wt 9 -ct 9 -to 10 -e 220" );
+ is ($res->return_code, 0, "OK, old syntax");
+
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp -e 221" );
+ is ($res->return_code, 1, "WARNING - got correct error when expecting 221 instead of 220" );
+
+ TODO: {
+ local $TODO = "Output is over two lines";
+ like ( $res->output, qr/^SMTP WARNING/, "Correct error message" );
+ }
+
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp --ssl -p 25" );
+ is ($res->return_code, 2, "Check rc of connecting to $host_tcp_smtp with TLS on standard SMTP port" );
+ like ($res->output, qr/^CRITICAL - Cannot make SSL connection\./, "Check output of connecting to $host_tcp_smtp with TLS on standard SMTP port");
+}
+
+SKIP: {
+ skip "No SMTP server with STARTTLS defined", 1 unless $host_tcp_smtp_starttls;
+ # SSL connection for STARTTLS
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_starttls -p 25 -S" );
+ is ($res->return_code, 0, "OK, with STARTTLS" );
+}
+
+SKIP: {
+ skip "No SMTP server without STARTTLS defined", 2 unless $host_tcp_smtp_nostarttls;
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_nostarttls -p 25 -S" );
+ is ($res->return_code, 1, "OK, got warning from server without STARTTLS");
+ is ($res->output, "WARNING - TLS not supported by server", "Right error message" );
+}
+
+SKIP: {
+ skip "No SMTP server with TLS defined", 1 unless $host_tcp_smtp_tls;
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_tls --ssl" );
+ is ($res->return_code, 0, "Check rc of connecting to $host_tcp_smtp_tls with TLS" );
+ like ($res->output, qr/^SMTP OK - /, "Check output of connecting to $host_tcp_smtp_tls with TLS" );
+
+ my $unused_port = 4465;
+ $res = NPTest->testCmd( "./check_smtp -H $host_tcp_smtp_tls -p $unused_port --ssl" );
+ is ($res->return_code, 2, "Check rc of connecting to $host_tcp_smtp_tls with TLS on unused port $unused_port" );
+ like ($res->output, qr/^connect to address $host_tcp_smtp_tls and port $unused_port: Connection refused/, "Check output of connecting to $host_tcp_smtp_tls with TLS on unused port $unused_port");
+}
+
+$res = NPTest->testCmd( "./check_smtp $host_nonresponsive" );
+is ($res->return_code, 2, "CRITICAL - host non responding" );
+
+$res = NPTest->testCmd( "./check_smtp $hostname_invalid" );
+is ($res->return_code, 3, "UNKNOWN - hostname invalid" );
+
diff --git a/plugins/t/check_snmp.t b/plugins/t/check_snmp.t
new file mode 100644
index 0000000..576cc50
--- /dev/null
+++ b/plugins/t/check_snmp.t
@@ -0,0 +1,176 @@
+#! /usr/bin/perl -w -I ..
+#
+# Simple Network Management Protocol (SNMP) Test via check_snmp
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+BEGIN {
+ plan skip_all => 'check_snmp is not compiled' unless -x "./check_snmp";
+ plan tests => 63;
+}
+
+my $res;
+
+my $host_snmp = getTestParameter("NP_HOST_SNMP", "A host providing an SNMP Service", "localhost");
+my $snmp_community = getTestParameter("NP_SNMP_COMMUNITY", "The SNMP Community string for SNMP Testing (assumes snmp v1)", "public");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+my $user_snmp = getTestParameter("NP_SNMP_USER", "An SNMP user", "auth_md5");
+
+
+$res = NPTest->testCmd( "./check_snmp -t 1" );
+is( $res->return_code, 3, "No host name" );
+is( $res->output, "No host specified" );
+
+$res = NPTest->testCmd( "./check_snmp -H fakehostname --ignore-mib-parsing-errors" );
+is( $res->return_code, 3, "No OIDs specified" );
+is( $res->output, "No OIDs specified" );
+
+$res = NPTest->testCmd( "./check_snmp -H fakehost --ignore-mib-parsing-errors -o oids -P 3 -U not_a_user --seclevel=rubbish" );
+is( $res->return_code, 3, "Invalid seclevel" );
+like( $res->output, "/check_snmp: Invalid seclevel - rubbish/" );
+
+$res = NPTest->testCmd( "./check_snmp -H fakehost --ignore-mib-parsing-errors -o oids -P 3c" );
+is( $res->return_code, 3, "Invalid protocol" );
+like( $res->output, "/check_snmp: Invalid SNMP version - 3c/" );
+
+SKIP: {
+ skip "no snmp host defined", 50 if ( ! $host_snmp );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -w 1: -c 1:");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying uptime" );
+ like($res->output, '/^SNMP OK - (\d+)/', "String contains SNMP OK");
+ $res->output =~ /^SNMP OK - (\d+)/;
+ my $value = $1;
+ cmp_ok( $value, ">", 0, "Got a time value" );
+ like($res->perf_output, "/sysUpTime.*$1/", "Got perfdata with value '$1' in it");
+
+
+ # some more threshold tests
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c 1");
+ cmp_ok( $res->return_code, '==', 2, "Threshold test -c 1" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c 1:");
+ cmp_ok( $res->return_code, '==', 0, "Threshold test -c 1:" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c ~:1");
+ cmp_ok( $res->return_code, '==', 2, "Threshold test -c ~:1" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c 1:10");
+ cmp_ok( $res->return_code, '==', 2, "Threshold test -c 1:10" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c \@1:10");
+ cmp_ok( $res->return_code, '==', 0, "Threshold test -c \@1:10" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c 10:1");
+ cmp_ok( $res->return_code, '==', 0, "Threshold test -c 10:1" );
+
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o .1.3.6.1.2.1.1.3.0 -w 1: -c 1:");
+ cmp_ok( $res->return_code, '==', 0, "Test with numeric OID (no mibs loaded)" );
+ like($res->output, '/^SNMP OK - \d+/', "String contains SNMP OK");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysDescr.0");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying sysDescr" );
+ unlike($res->perf_output, '/sysDescr/', "Perfdata doesn't contain string values");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysDescr.0,system.sysDescr.0");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying two string OIDs, comma-separated" );
+ like($res->output, '/^SNMP OK - /', "String contains SNMP OK");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysDescr.0 -o system.sysDescr.0");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying two string OIDs, repeated option" );
+ like($res->output, '/^SNMP OK - /', "String contains SNMP OK");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w 1:1 -c 1:1");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying hrSWRunIndex.1" );
+ like($res->output, '/^SNMP OK - 1\s.*$/', "String fits SNMP OK and output format");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w 0 -c 1:");
+ cmp_ok( $res->return_code, '==', 1, "Exit WARNING when querying hrSWRunIndex.1 and warn-th doesn't apply " );
+ like($res->output, '/^SNMP WARNING - \*1\*\s.*$/', "String matches SNMP WARNING and output format");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w :0 -c 0");
+ cmp_ok( $res->return_code, '==', 2, "Exit CRITICAL when querying hrSWRunIndex.1 and crit-th doesn't apply" );
+ like($res->output, '/^SNMP CRITICAL - \*1\*\s.*$/', "String matches SNMP CRITICAL and output format");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o ifIndex.2,ifIndex.1 -w 1:2 -c 1:2");
+ cmp_ok( $res->return_code, '==', 0, "Checking two OIDs at once" );
+ like($res->output, "/^SNMP OK - 2 1/", "Got two values back" );
+ like( $res->perf_output, "/ifIndex.2=2/", "Got 1st perf data" );
+ like( $res->perf_output, "/ifIndex.1=1/", "Got 2nd perf data" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o ifIndex.2,ifIndex.1 -w 1:2,1:2 -c 2:2,2:2");
+ cmp_ok( $res->return_code, '==', 2, "Checking critical threshold is passed if any one value crosses" );
+ like($res->output, "/^SNMP CRITICAL - 2 *1*/", "Got two values back" );
+ like( $res->perf_output, "/ifIndex.2=2/", "Got 1st perf data" );
+ like( $res->perf_output, "/ifIndex.1=1/", "Got 2nd perf data" );
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w 1:,1: -c 1:,1:");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK when querying hrMemorySize and hrSystemProcesses");
+ like($res->output, '/^SNMP OK - \d+ \d+/', "String contains hrMemorySize and hrSystemProcesses");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w \@:0 -c \@0");
+ cmp_ok( $res->return_code, '==', 0, "Exit OK with inside-range thresholds");
+ like($res->output, '/^SNMP OK - 1\s.*$/', "String matches SNMP OK and output format");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o enterprises.ucdavis.laTable.laEntry.laLoad.3");
+ $res->output =~ m/^SNMP OK - (\d+\.\d{2})\s.*$/;
+ my $lower = $1 - 0.05;
+ my $higher = $1 + 0.05;
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o enterprises.ucdavis.laTable.laEntry.laLoad.3 -w $lower -c $higher");
+ cmp_ok( $res->return_code, '==', 1, "Exit WARNING with fractionnal arguments");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0,host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w ,:0 -c ,:2");
+ cmp_ok( $res->return_code, '==', 1, "Exit WARNING on 2nd threshold");
+ like($res->output, '/^SNMP WARNING - Timeticks:\s\(\d+\)\s+(?:\d+ days?,\s+)?\d+:\d+:\d+\.\d+\s+\*1\*\s.*$/', "First OID returned as string, 2nd checked for thresholds");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrSWRun.hrSWRunTable.hrSWRunEntry.hrSWRunIndex.1 -w '' -c ''");
+ cmp_ok( $res->return_code, '==', 0, "Empty thresholds doesn't crash");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w ,,1 -c ,,2");
+ cmp_ok( $res->return_code, '==', 0, "Skipping first two thresholds on 2 OID check");
+ like($res->output, '/^SNMP OK - \d+ \w+ \d+\s.*$/', "Skipping first two thresholds, result printed rather than parsed");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o host.hrStorage.hrMemorySize.0,host.hrSystem.hrSystemProcesses.0 -w ,, -c ,,");
+ cmp_ok( $res->return_code, '==', 0, "Skipping all thresholds");
+ like($res->output, '/^SNMP OK - \d+ \w+ \d+\s.*$/', "Skipping all thresholds, result printed rather than parsed");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0 -c 1000000000000: -u '1/100 sec'");
+ cmp_ok( $res->return_code, '==', 2, "Timetick used as a threshold");
+ like($res->output, '/^SNMP CRITICAL - \*\d+\* 1\/100 sec.*$/', "Timetick used as a threshold, parsed as numeric");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o system.sysUpTime.0");
+ cmp_ok( $res->return_code, '==', 0, "Timetick used as a string");
+ like($res->output, '/^SNMP OK - Timeticks:\s\(\d+\)\s+(?:\d+ days?,\s+)?\d+:\d+:\d+\.\d+\s.*$/', "Timetick used as a string, result printed rather than parsed");
+
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -C $snmp_community -o HOST-RESOURCES-MIB::hrSWRunName.1");
+ cmp_ok( $res->return_code, '==', 0, "snmp response without datatype");
+ like( $res->output, '/^SNMP OK - "(systemd|init)" \| $/', "snmp response without datatype" );
+}
+
+SKIP: {
+ skip "no SNMP user defined", 1 if ( ! $user_snmp );
+ $res = NPTest->testCmd( "./check_snmp -H $host_snmp --ignore-mib-parsing-errors -o HOST-RESOURCES-MIB::hrSystemUptime.0 -P 3 -U $user_snmp -L noAuthNoPriv");
+ like( $res->output, '/^SNMP OK - Timeticks:\s\(\d+\)\s+(?:\d+ days?,\s+)?\d+:\d+:\d+\.\d+\s.*$/', "noAuthNoPriv security level works properly" );
+}
+
+# These checks need a complete command line. An invalid community is used so
+# the tests can run on hosts w/o snmp host/community in NPTest.cache. Execution will fail anyway
+SKIP: {
+ skip "no non responsive host defined", 2 if ( ! $host_nonresponsive );
+ $res = NPTest->testCmd( "./check_snmp -H $host_nonresponsive --ignore-mib-parsing-errors -C np_foobar -o system.sysUpTime.0 -w 1: -c 1:");
+ cmp_ok( $res->return_code, '==', 2, "Exit CRITICAL with non responsive host" );
+ like($res->output, '/Plugin timed out while executing system call/', "String matches timeout problem");
+}
+
+SKIP: {
+ skip "no non invalid host defined", 2 if ( ! $hostname_invalid );
+ $res = NPTest->testCmd( "./check_snmp -H $hostname_invalid --ignore-mib-parsing-errors -C np_foobar -o system.sysUpTime.0 -w 1: -c 1:");
+ cmp_ok( $res->return_code, '==', 3, "Exit UNKNOWN with non responsive host" );
+ like($res->output, '/External command error: .*(nosuchhost|Name or service not known|Unknown host).*/s', "String matches invalid host");
+}
diff --git a/plugins/t/check_ssh.t b/plugins/t/check_ssh.t
new file mode 100644
index 0000000..a5cd23c
--- /dev/null
+++ b/plugins/t/check_ssh.t
@@ -0,0 +1,41 @@
+#! /usr/bin/perl -w -I ..
+#
+# check_ssh tests
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+# Required parameters
+my $ssh_host = getTestParameter("NP_SSH_HOST", "A host providing SSH service", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1" );
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost" );
+
+
+plan skip_all => "SSH_HOST must be defined" unless $ssh_host;
+plan tests => 6;
+
+
+my $result = NPTest->testCmd(
+ "./check_ssh -H $ssh_host"
+ );
+cmp_ok($result->return_code, '==', 0, "Exit with return code 0 (OK)");
+like($result->output, '/^SSH OK - /', "Status text if command returned none (OK)");
+
+
+$result = NPTest->testCmd(
+ "./check_ssh -H $host_nonresponsive -t 2"
+ );
+cmp_ok($result->return_code, '==', 2, "Exit with return code 0 (OK)");
+like($result->output, '/^CRITICAL - Socket timeout after 2 seconds/', "Status text if command returned none (OK)");
+
+
+
+$result = NPTest->testCmd(
+ "./check_ssh -H $hostname_invalid -t 2"
+ );
+cmp_ok($result->return_code, '==', 3, "Exit with return code 0 (OK)");
+like($result->output, '/^check_ssh: Invalid hostname/', "Status text if command returned none (OK)");
+
diff --git a/plugins/t/check_swap.t b/plugins/t/check_swap.t
new file mode 100644
index 0000000..de9e0f0
--- /dev/null
+++ b/plugins/t/check_swap.t
@@ -0,0 +1,31 @@
+#! /usr/bin/perl -w -I ..
+#
+# Swap Space Tests via check_swap
+#
+#
+
+use strict;
+use Test::More tests => 8;
+use NPTest;
+
+my $successOutput = '/^SWAP OK - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
+my $failureOutput = '/^SWAP CRITICAL - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
+my $warnOutput = '/^SWAP WARNING - [0-9]+\% free \([0-9]+MB out of [0-9]+MB\)/';
+
+my $result;
+
+$result = NPTest->testCmd( "./check_swap -w 1048576 -c 1048576" ); # 1 MB free
+cmp_ok( $result->return_code, "==", 0, "At least 1MB free" );
+like( $result->output, $successOutput, "Right output" );
+
+$result = NPTest->testCmd( "./check_swap -w 1% -c 1%" ); # 1% free
+cmp_ok( $result->return_code, "==", 0, 'At least 1% free' );
+like( $result->output, $successOutput, "Right output" );
+
+$result = NPTest->testCmd( "./check_swap -w 100% -c 100%" ); # 100% (always critical)
+cmp_ok( $result->return_code, "==", 2, 'Get critical because not 100% free' );
+like( $result->output, $failureOutput, "Right output" );
+
+$result = NPTest->testCmd( "./check_swap -w 100% -c 1%" ); # 100% (always warn)
+cmp_ok( $result->return_code, "==", 1, 'Get warning because not 100% free' );
+like( $result->output, $warnOutput, "Right output" );
diff --git a/plugins/t/check_tcp.t b/plugins/t/check_tcp.t
new file mode 100644
index 0000000..cb4de53
--- /dev/null
+++ b/plugins/t/check_tcp.t
@@ -0,0 +1,55 @@
+#! /usr/bin/perl -w -I ..
+#
+# TCP Connection Based Tests via check_tcp
+#
+#
+
+use strict;
+use Test;
+
+use vars qw($tests $has_ipv6);
+BEGIN {
+ use NPTest;
+ $has_ipv6 = NPTest::has_ipv6();
+ $tests = $has_ipv6 ? 14 : 11;
+}
+
+
+my $host_tcp_http = getTestParameter("NP_HOST_TCP_HTTP", "A host providing the HTTP Service (a web server)", "localhost");
+my $host_tls_http = getTestParameter("NP_HOST_TLS_HTTP", "A host providing the HTTPS Service (a tls web server)", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+my $internet_access = getTestParameter("NP_INTERNET_ACCESS", "Is this system directly connected to the internet?", "yes");
+
+my $successOutput = '/^TCP OK\s-\s+[0-9]?\.?[0-9]+ second response time on port [0-9]+/';
+
+my $failedExpect = '/^TCP WARNING\s-\sUnexpected response from host/socket on port [0-9]+/';
+
+my $t;
+
+$tests = $tests - 4 if $internet_access eq "no";
+plan tests => $tests;
+
+$t += checkCmd( "./check_tcp $host_tcp_http -p 80 -wt 300 -ct 600", 0, $successOutput );
+$t += checkCmd( "./check_tcp $host_tcp_http -p 81 -wt 0 -ct 0 -to 1", 2 ); # use invalid port for this test
+$t += checkCmd( "./check_tcp $host_nonresponsive -p 80 -wt 0 -ct 0 -to 1", 2 );
+$t += checkCmd( "./check_tcp $hostname_invalid -p 80 -wt 0 -ct 0 -to 1", 2 );
+if($internet_access ne "no") {
+ $t += checkCmd( "./check_tcp -S -D 1 -H $host_tls_http -p 443", 0 );
+ $t += checkCmd( "./check_tcp -S -D 9000,1 -H $host_tls_http -p 443", 1 );
+ $t += checkCmd( "./check_tcp -S -D 9000 -H $host_tls_http -p 443", 1 );
+ $t += checkCmd( "./check_tcp -S -D 9000,8999 -H $host_tls_http -p 443", 2 );
+}
+
+# Need the \r\n to make it more standards compliant with web servers. Need the various quotes
+# so that perl doesn't interpret the \r\n and is passed onto command line correctly
+$t += checkCmd( "./check_tcp $host_tcp_http -p 80 -E -s ".'"GET / HTTP/1.1\r\n\r\n"'." -e 'ThisShouldntMatch' -j", 1, $failedExpect );
+
+# IPv6 checks
+if($has_ipv6) {
+ $t += checkCmd( "./check_tcp $host_tcp_http -p 80 -wt 300 -ct 600 -6 ", 0, $successOutput );
+ $t += checkCmd( "./check_tcp -6 -p 80 www.heise.de", 0 );
+}
+
+exit(0) if defined($Test::Harness::VERSION);
+exit($tests - $t);
diff --git a/plugins/t/check_time.t b/plugins/t/check_time.t
new file mode 100644
index 0000000..92c2f89
--- /dev/null
+++ b/plugins/t/check_time.t
@@ -0,0 +1,36 @@
+#! /usr/bin/perl -w -I ..
+#
+# System Time Tests via check_time
+#
+#
+
+use strict;
+use Test;
+use NPTest;
+
+use vars qw($tests);
+BEGIN {$tests = 8; plan tests => $tests}
+
+my $host_udp_time = getTestParameter("NP_HOST_UDP_TIME", "A host providing the UDP Time Service", "localhost");
+my $host_nonresponsive = getTestParameter("NP_HOST_NONRESPONSIVE", "The hostname of system not responsive to network requests", "10.0.0.1");
+my $hostname_invalid = getTestParameter("NP_HOSTNAME_INVALID", "An invalid (not known to DNS) hostname", "nosuchhost");
+
+my $successOutput = '/^TIME OK - [0-9]+ second time difference/';
+
+my %exceptions = ( 3 => "No time server present?");
+
+my $t;
+
+# standard mode
+$t += checkCmd( "./check_time -H $host_udp_time -w 999999,59 -c 999999,59 -t 60", 0, $successOutput, %exceptions );
+$t += checkCmd( "./check_time -H $host_udp_time -w 999999 -W 59 -c 999999 -C 59 -t 60", 0, $successOutput, %exceptions );
+
+# reverse compatibility mode
+$t += checkCmd( "./check_time $host_udp_time -wt 59 -ct 59 -cd 999999 -wd 999999 -to 60", 0, $successOutput, %exceptions );
+
+# failure mode
+$t += checkCmd( "./check_time -H $host_nonresponsive -t 1", 2 );
+$t += checkCmd( "./check_time -H $hostname_invalid -t 1", 3 );
+
+exit(0) if defined($Test::Harness::VERSION);
+exit($tests - $t);
diff --git a/plugins/t/check_udp.t b/plugins/t/check_udp.t
new file mode 100644
index 0000000..6c47d09
--- /dev/null
+++ b/plugins/t/check_udp.t
@@ -0,0 +1,71 @@
+#! /usr/bin/perl -w -I ..
+#
+# UDP Connection Based Tests via check_udp
+#
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+my $res;
+
+alarm(120); # make sure tests don't hang
+
+plan tests => 14;
+
+$res = NPTest->testCmd( "./check_udp -H localhost -p 3333" );
+cmp_ok( $res->return_code, '==', 3, "Need send/expect string");
+like ( $res->output, '/With UDP checks, a send/expect string must be specified./', "Output OK");
+
+$res = NPTest->testCmd( "./check_udp -H localhost -p 3333 -s send" );
+cmp_ok( $res->return_code, '==', 3, "Need expect string");
+like ( $res->output, '/With UDP checks, a send/expect string must be specified./', "Output OK");
+
+$res = NPTest->testCmd( "./check_udp -H localhost -p 3333 -e expect" );
+cmp_ok( $res->return_code, '==', 3, "Need send string");
+like ( $res->output, '/With UDP checks, a send/expect string must be specified./', "Output OK");
+
+$res = NPTest->testCmd( "./check_udp -H localhost -p 3333 -s foo -e bar" );
+cmp_ok( $res->return_code, '==', 2, "Errors correctly because no udp service running" );
+like ( $res->output, '/No data received from host/', "Output OK");
+
+my $nc;
+if(system("which nc.traditional >/dev/null 2>&1") == 0) {
+ $nc = 'nc.traditional -w 3 -l -u -p 3333';
+}
+elsif(system("which nc >/dev/null 2>&1") == 0) {
+ $nc = 'nc -w 3 -l -u -4 localhost 3333';
+}
+elsif(system("which netcat >/dev/null 2>&1") == 0) {
+ $nc = 'netcat -w 3 -l -u -p 3333';
+}
+
+SKIP: {
+ skip "solaris netcat does not listen to udp", 6 if $^O eq 'solaris';
+ skip "No netcat available", 6 unless $nc;
+ open (NC, "echo 'barbar' | $nc |");
+ sleep 1;
+ $res = NPTest->testCmd( "./check_udp -H localhost -p 3333 -s '' -e barbar -4" );
+ cmp_ok( $res->return_code, '==', 0, "Got barbar response back" );
+ like ( $res->output, '/\[barbar\]/', "Output OK");
+ close NC;
+
+ # Start up a udp server listening on port 3333, quit after 3 seconds
+ # Otherwise will hang at close
+ my $pid = open(NC, "$nc </dev/null |");
+ sleep 1; # Allow nc to startup
+
+ my $start = time;
+ $res = NPTest->testCmd( "./check_udp -H localhost -p 3333 -s foofoo -e barbar -t 5 -4" );
+ my $duration = time - $start;
+ cmp_ok( $res->return_code, '==', '2', "Hung waiting for response");
+ like ( $res->output, '/Socket timeout after 5 seconds/', "Timeout message");
+ like ( $duration, '/^[56]$/', "Timeout after 5 (possibly 6) seconds");
+ my $read_nc = <NC> || '';
+ close NC;
+ cmp_ok( $read_nc, 'eq', "foofoo", "Data received correctly" );
+}
+
+
+alarm(0); # disable alarm
diff --git a/plugins/t/check_users.t b/plugins/t/check_users.t
new file mode 100644
index 0000000..9ebc2fc
--- /dev/null
+++ b/plugins/t/check_users.t
@@ -0,0 +1,30 @@
+#! /usr/bin/perl -w -I ..
+#
+# Logged in Users Tests via check_users
+#
+# Trick: This check requires at least 1 user logged in. These commands should
+# leave a session open forever in the background:
+#
+# $ ssh -tt localhost </dev/null >/dev/null 2>/dev/null &
+# $ disown %1
+
+use strict;
+use Test;
+use NPTest;
+
+use vars qw($tests);
+BEGIN {$tests = 8; plan tests => $tests}
+
+my $successOutput = '/^USERS OK - [0-9]+ users currently logged in/';
+my $failureOutput = '/^USERS CRITICAL - [0-9]+ users currently logged in/';
+
+my $t;
+
+$t += checkCmd( "./check_users 1000 1000", 0, $successOutput );
+$t += checkCmd( "./check_users 0 0", 2, $failureOutput );
+$t += checkCmd( "./check_users -w 0:1000 -c 0:1000", 0, $successOutput );
+$t += checkCmd( "./check_users -w 0:0 -c 0:0", 2, $failureOutput );
+
+exit(0) if defined($Test::Harness::VERSION);
+exit($tests - $t);
+
diff --git a/plugins/t/negate.t b/plugins/t/negate.t
new file mode 100644
index 0000000..5ec1c84
--- /dev/null
+++ b/plugins/t/negate.t
@@ -0,0 +1,90 @@
+#! /usr/bin/perl -w -I ..
+#
+# negate checks
+# Need check_dummy to work for testing
+#
+
+use strict;
+use Test::More;
+use Cwd;
+use NPTest;
+
+# 15 tests in the first part, 9 in timeout tests and 2 * 32 in the last loops
+plan tests => 88;
+
+my $res;
+
+my $PWD = getcwd();
+
+$res = NPTest->testCmd( "./negate" );
+is( $res->return_code, 3, "Not enough parameters");
+like( $res->output, "/Could not parse arguments/", "Could not parse arguments");
+
+$res = NPTest->testCmd( "./negate bobthebuilder" );
+is( $res->return_code, 3, "Require full path" );
+like( $res->output, "/Require path to command/", "Appropriate error message");
+
+$res = NPTest->testCmd( "./negate $PWD/check_dummy 0 'a dummy okay'" );
+is( $res->return_code, 2, "OK changed to CRITICAL" );
+is( $res->output, "OK: a dummy okay", "Output as expected" );
+
+$res = NPTest->testCmd( "./negate '$PWD/check_dummy 0 redsweaterblog'");
+is( $res->return_code, 2, "OK => CRIT with a single quote for command to run" );
+is( $res->output, "OK: redsweaterblog", "Output as expected" );
+
+$res = NPTest->testCmd( "./negate $PWD/check_dummy 1 'a warn a day keeps the managers at bay'" );
+is( $res->return_code, 1, "WARN stays same" );
+
+$res = NPTest->testCmd( "./negate $PWD/check_dummy 3 mysterious");
+is( $res->return_code, 3, "UNKNOWN stays same" );
+
+$res = NPTest->testCmd( "./negate \"$PWD/check_dummy 0 'a dummy okay'\"" );
+is( $res->output, "OK: a dummy okay", "Checking slashed quotes - the single quotes are re-evaluated at shell" );
+
+# Output is "OK: a" because check_dummy only returns the first arg
+$res = NPTest->testCmd( "./negate $PWD/check_dummy 0 a dummy okay" );
+is( $res->output, "OK: a", "Multiple args passed as arrays" );
+
+$res = NPTest->testCmd( "./negate $PWD/check_dummy 0 'a dummy okay'" );
+is( $res->output, "OK: a dummy okay", "The quoted string is passed through to subcommand correctly" );
+
+$res = NPTest->testCmd( "./negate '$PWD/check_dummy 0' 'a dummy okay'" );
+is( $res->output, "No data returned from command", "Bad command, as expected (trying to execute './check_dummy 0')");
+
+$res = NPTest->testCmd( './negate '.$PWD.'/check_dummy 0 \'$$ a dummy okay\'' );
+is( $res->output, 'OK: $$ a dummy okay', 'Proves that $$ is not being expanded again' );
+
+my %state = (
+ ok => 0,
+ warning => 1,
+ critical => 2,
+ unknown => 3,
+ );
+
+# Timeout tests
+$res = NPTest->testCmd( "./negate -t 2 /bin/sh -c 'sleep 5'" );
+is( $res->output, 'CRITICAL - Plugin timed out after 2 seconds' );
+
+foreach my $state (keys(%state)) {
+ $res = NPTest->testCmd( "./negate -t 2 -T $state /bin/sh -c 'sleep 5'" );
+ is( $res->return_code, $state{$state}, "Got timeout state $state" );
+ is( $res->output, uc($state)." - Plugin timed out after 2 seconds", "Timeout state $state output");
+}
+
+foreach my $current_state (keys(%state)) {
+ foreach my $new_state (keys(%state)) {
+ $res = NPTest->testCmd( "./negate --$current_state=$new_state ./check_dummy ".$state{$current_state}." 'Fake $new_state'" );
+ is( $res->return_code, $state{$new_state}, "Got fake $new_state" );
+ is( $res->output, uc($current_state).": Fake $new_state", "Fake $new_state output");
+ }
+}
+
+# Same as above with substitute
+foreach my $current_state (keys(%state)) {
+ foreach my $new_state (keys(%state)) {
+ $res = NPTest->testCmd( "./negate -s --$current_state=$new_state ./check_dummy ".$state{$current_state}." 'Fake $new_state'" );
+ is( $res->return_code, $state{$new_state}, "Got fake $new_state (with substitute)" );
+ is( $res->output, uc($new_state).": Fake $new_state", "Substituted fake $new_state output");
+ }
+}
+
diff --git a/plugins/tests/certs/.gitignore b/plugins/tests/certs/.gitignore
new file mode 100644
index 0000000..79acaaa
--- /dev/null
+++ b/plugins/tests/certs/.gitignore
@@ -0,0 +1,2 @@
+/*.csr
+/*.srl
diff --git a/plugins/tests/certs/client-cert.pem b/plugins/tests/certs/client-cert.pem
new file mode 100644
index 0000000..5709750
--- /dev/null
+++ b/plugins/tests/certs/client-cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApwCAQIwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYD
+VQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3Jp
+bmcgUGx1Z2luczEkMCIGA1UEAwwbTW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENB
+MSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMB4X
+DTIxMDIyODIxMDIxMloXDTMwMTEyODIxMDIxMlowgZ4xCzAJBgNVBAYTAkRFMRAw
+DgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0
+b3JpbmcgUGx1Z2luczEiMCAGA1UEAwwZTW9uaXRvcmluZyBQbHVnaW5zIENsaWVu
+dDErMCkGCSqGSIb3DQEJARYcZGV2ZWxAbW9uaXRvcmluZy1wbHVnaW5zLm9yZzCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM3EiqfFPomm5dZQPGYG5SrF
+rPvyqseXTzCkwUIUzGf+Sfm3s13zx7e3ije/04yKhTXgK59EQ793q7E2aWhSOz3s
+hwKKdylFkOIyc5jgbAfF1/pLZMK209rLt/mMRksXCRXYrHdTjRMx1ev4C2407+8Y
+8qkf77DuYQmUqCQe7DPOvqLeagdw9JcLGmQNTKHg3fl6wyRl5K1Bsy+qXu2XvEjZ
+0Ng7n8LHjOUkTqUEJndOxci9gL5cHU5ttul/GW34dKOtTuMU/pQX6/ywYusOGVOx
+RYI76OolRqj5BqbNctDIB/obe2RLo+UVx74/0jAxtH4XS23pYjO7NUpJcytsVG8C
+AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAYfaY5n4pCq0NWPCdeVVRr4nr+GAfv1TC
+/PKcGuEoJZKt7TQT+OOA5yeZMZb53OvtA49D1r9aoJzWe946KElWOEBqxDRi5Cdr
+wkqpwGcPT2RfAqA3/cvQZ1XsquboXrCf7ajdl5OC64bs2jkqCFh9gnxuI140g8Ar
+Njol8BFxRPaYWOnwuQwmh/2t0FJqr3WSD85HrNqtxUSNGbTdSsvCfgF0v7QVkvLG
+3/cbx6z5hxzj2JUjhMnCvn+EbasoJt4xyBFvg67Q2229SMwu9YNqS63GVoKUqhCB
+4Gl5v31qx8dAFKuRvnez3ze/6oohwmakZkst4hcQdgZocHhzesvKlg==
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/client-key.pem b/plugins/tests/certs/client-key.pem
new file mode 100644
index 0000000..09b6761
--- /dev/null
+++ b/plugins/tests/certs/client-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNxIqnxT6JpuXW
+UDxmBuUqxaz78qrHl08wpMFCFMxn/kn5t7Nd88e3t4o3v9OMioU14CufREO/d6ux
+NmloUjs97IcCincpRZDiMnOY4GwHxdf6S2TCttPay7f5jEZLFwkV2Kx3U40TMdXr
++AtuNO/vGPKpH++w7mEJlKgkHuwzzr6i3moHcPSXCxpkDUyh4N35esMkZeStQbMv
+ql7tl7xI2dDYO5/Cx4zlJE6lBCZ3TsXIvYC+XB1Obbbpfxlt+HSjrU7jFP6UF+v8
+sGLrDhlTsUWCO+jqJUao+QamzXLQyAf6G3tkS6PlFce+P9IwMbR+F0tt6WIzuzVK
+SXMrbFRvAgMBAAECggEBALtc2pB3p0E6KpAiEU0pvCRdSO1FgsIpAd+eNadRPur2
+fi+XWQkUwGeGBaJL1npja3aqP65PP40pj7nWfNaUAgOZyznCEU0QXiPJor6yo0vU
+l5v+aKpwRao107i0RRF80TYGTMx+1LeEqnCqNOZN56gERHlBbkTiWpOZvBzf1143
+oegTcyM6+Ee6+FYNhHaDyIYD0md1S2wGR+IBPet6HwWiakLNKahFPa7lOLIKfmmD
+iTtifcbf4724wSe44a0uTeP4JrquZSeIKakm8MEmffmYqpycnaakYefd0Xc5UEsH
++VbhKpOWGY3d8FKHqUsTa+6QyXb2uFPo6A+yWm0pdJECgYEA7Prd5sbWACvXOcHT
+ONDBAgyfAVDQwOXi3D4dk6D5mg+/jxl5ZQY5slszJrwsLFtoEzXtYpNfTy3cpNOp
+JLbBDZYnqty+5tD8t3/Zv2IBXCAgvuk5CgfJWP5FNAfiyUEE6Vbp6J/5/vAnODsa
+fxZryN5UsH0X8ew7AlbfcVNyj4kCgYEA3khetIgn+GR6sv9jFRdCT6aJbp0xMsms
+6F4v3L5FG4Kp+SwDHL1bVOhieJ5g8odYp9hDbgTEEqbJfNmyCOu9+OQmZ/mztku7
+6reU8HhYBIvi+hFeJmvqKpdIgU0Zveg4Bst5QordmhPk8AHjBC4xvQ++uh7rwYKd
+WVsS08bGDjcCgYEAlAuNARUKsASzakOqHv5a9VrJIttH7povBYRQmd+gzxwzgcRa
+UEB5XvEWnYZE2lkoRYgVCtYiXqa6BsasDmGVbVV25okNQckhd8mJUMR7MQBpNJsi
+pR+EK/J9bSnYBf52gQdpDYiTdy60ca6KuQZaw5wRsEgV426+1pFK+dM16HECgYBY
+cTsdYb9lmbUoW201CxgbUQwFsw3MQ2pE2pT4o8wjcg3nUpe6a61XT08+5uV0Gl4w
+CmBp+gN52Fr7DjNEUWg5C64sWLIkqmWOspTUSU3cITyiex6W8wEtCRyUNfU0Fp2U
+Nol87HvXvmqtBFMraqXnr8gXjg4H5MxurUoEcWaEaQKBgCT4iIGZwW0Qf2rkFC7B
+xObzVGefivVVbaf8/c/LRO8TMLdnExkShMOmCzHeHV4mMEZDLbMOusHCI7xm10EX
+l3L1I1Kyqnhm1RH3e7TVWgkTmIDW3V5Fgrhm1jx5Iz6et4sb4Uh+bZq9tTLyqfZY
+8s0yJUrfpjRggfk7eUs5s7aY
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientca-cert.pem b/plugins/tests/certs/clientca-cert.pem
new file mode 100644
index 0000000..9ce7cd7
--- /dev/null
+++ b/plugins/tests/certs/clientca-cert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEIzCCAwugAwIBAgIUL9Jfp5zv5B29NgDsNEFU2OM/UHswDQYJKoZIhvcNAQEL
+BQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
+dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEkMCIGA1UEAwwbTW9u
+aXRvcmluZyBQbHVnaW5zIENsaWVudENBMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBt
+b25pdG9yaW5nLXBsdWdpbnMub3JnMB4XDTIxMDIyODIxMDIxMVoXDTMwMTEyODIx
+MDIxMVowgaAxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQH
+DAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEkMCIGA1UEAwwb
+TW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENBMSswKQYJKoZIhvcNAQkBFhxkZXZl
+bEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAyxiWsGrsJFHw3VR0pqHviXUfbfKMw8LaCxI5EQZfInsMVkBIGWEW
+tFW6qDuAOsMdzsrKOnQRNNt852ts/0Uz++z8zysoauAGpc4JnCZuM5A1DU5CFXBx
+w6Ax+1ft3UsTt8C6kfLfs8mPCbtNVqAHrMrIqDxsNSRRxQSqkzp1vD8rwSKcbB1h
+u2+lut1bEqMe7dp89jKOtc6G/1tHUFQuLAGFoX/qk9yPscmQNzL6YbLP4m9r/416
+PsxWsAfyY97hmoYo6mSCue5LmeanOsjf4Kzq90hIJRwrpiUGmxGjW+tPLEhQBZw6
+C2wHyN74YIJYX2xREz2ijT0mgsqdhO5ZxwIDAQABo1MwUTAdBgNVHQ4EFgQUtsP9
+Z3fKkhmFp97Kh/cW/UqHMIMwHwYDVR0jBBgwFoAUtsP9Z3fKkhmFp97Kh/cW/UqH
+MIMwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEApO5o+YECwTEv
+s+elDJZQ20UYwDSiU9Lpf4EcdnRv6FAb5UlhfRTH3ZdKCc/HX7kcKuy3PsF+b8Pw
+EusoKito9OlNEOF5HYAI9/J54/qceqn+SC0INsISeE19PvT0dma7lBSj4OvBv0IS
+GYbdztVaKLWqYgYs0mcEzteUc4MZcy1/C+Ru1i1Kp2s9/vIeAw2PV2+kpWtw88Pb
+FRJomGngP/hQdwniayCltG/Q1smS4iFEHNI5ayLZj1qJGMHwzqGiRr4KknJKfHzv
+fl4NQaFyMY31s1FRIS6QVIRFHVzUAlKZTdzwqEJygg3fUS9n9uDBnyDI/sW7DQuj
+yjSmYRS1hw==
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientca-key.pem b/plugins/tests/certs/clientca-key.pem
new file mode 100644
index 0000000..a939f03
--- /dev/null
+++ b/plugins/tests/certs/clientca-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLGJawauwkUfDd
+VHSmoe+JdR9t8ozDwtoLEjkRBl8iewxWQEgZYRa0VbqoO4A6wx3Oyso6dBE023zn
+a2z/RTP77PzPKyhq4AalzgmcJm4zkDUNTkIVcHHDoDH7V+3dSxO3wLqR8t+zyY8J
+u01WoAesysioPGw1JFHFBKqTOnW8PyvBIpxsHWG7b6W63VsSox7t2nz2Mo61zob/
+W0dQVC4sAYWhf+qT3I+xyZA3Mvphss/ib2v/jXo+zFawB/Jj3uGahijqZIK57kuZ
+5qc6yN/grOr3SEglHCumJQabEaNb608sSFAFnDoLbAfI3vhgglhfbFETPaKNPSaC
+yp2E7lnHAgMBAAECggEAJqAWiJbNMlsjI/Tb+pTxqYLM52wpuVFlhpWApOxBS517
+SywOikUcvE9RoI0wZfyVvq5yp4tLenID3z9fC21t5Yu8yOm8VhclLINy8G+epc/X
+RyCLEOjBuiLNXq/qXRvaNChDU16NjPPYcFFe9AqbaxFl+BkFu1Wc94tbpYSIv7Qt
+L6iBxUTXdgvLM5doa9AazIQzJx+jUsVCgRVQQf3zsLqtp9hH0Pfq+KWFIy5TA+bG
+0NFmYyQndRjtT0ihWGuNU7D8AXa+z7abzk+HydIlx4D//vGgdNq92QYPdnu2BBya
+5Fs6LkmkUonX/I8FbkLbRKkQWNPMt+Ks21t3xcVBgQKBgQDn4HuHVCPwxgU6Mv+5
+0sHJXYBq1fDzrUt0+iTtYkRqViX+9Mp4sUpYgXext/wXFLcKzQQp5B0g1dLYLSRS
+KwhsdiN0J7ZcoP1GMStw8zsayRTf8C3WRU6aACqyFiylYbyh56XomfYgwhja/7l9
+pzpVJD9ecG+mLVAyAkJtK2JolQKBgQDgOZfvrQj0L4QG+9E5VmFc3PE+6k3g+zDO
+MWqTSh0fOHqdTEyet4bMC4DogXGVsvw0/UKwbrGHOk0+ltA5VyKUtK/whSutr/+S
+nhCHljhV0XUN/I3OFcvezFjM3g0oC4uy1cL30hoM4IfeHM1d3EYse9N1Y/Op+mR6
+Sx+fEku16wKBgQC0KQ7RjuZ95N2a4pUe5En9EtD8MU4Nhs/iC5k1d+yAUn8jIT9P
+lzCUo8NEKheMN2Qg2Dor8jlPkdNIc4qM7TKWUxQo49IlFlCzgPCnydRac3HsrMhw
+e1ke/pIt3FzEArR1d27I0xcRTL3TKm4M2ynPjWJPFj0peHue33KNL/A+IQKBgEpL
+awd0Sxo1wEZcG9gmwf32C01wbzuTn3lCsHB7Ryj4GtCR3nVclCJ50U24zjzu4Fhi
+bj1tgA8xhzSs3fOR5phlQkKsrWtQfJtFGm8CnEn7LBDlVMsrN7Dr/qRrEuro4HHy
+GDbq+8y2fO5glr955BqLMOadprf0imRnDeQ0OLffAoGBAJio+X+xpglgMOC4BeH9
+9LcYi9nUEw8MDJNGo9/3e0XKA7spd3HShLDvt8YZhFJ2m168qBpGfezuw0+jpWxy
+PV9q0dokAgDx4pvCzIKaptZ1D30CWXJZHq25VK1tA41PCUIOh8JD5+R0MpxA5rn2
+DbqL4Vq7K7K0imGENYhHdyM+
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientchain-cert.pem b/plugins/tests/certs/clientchain-cert.pem
new file mode 100644
index 0000000..acd1e3e
--- /dev/null
+++ b/plugins/tests/certs/clientchain-cert.pem
@@ -0,0 +1,45 @@
+-----BEGIN CERTIFICATE-----
+MIIDuTCCAqECAQQwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAkRFMRAwDgYD
+VQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0b3Jp
+bmcgUGx1Z2luczEkMCIGA1UEAwwbTW9uaXRvcmluZyBQbHVnaW5zIENsaWVudENB
+MSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMub3JnMB4X
+DTIxMDIyODIxMDIxMloXDTMwMTEyODIxMDIxMlowgaMxCzAJBgNVBAYTAkRFMRAw
+DgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gxGzAZBgNVBAoMEk1vbml0
+b3JpbmcgUGx1Z2luczEnMCUGA1UEAwweTW9uaXRvcmluZyBQbHVnaW5zIENsaWVu
+dENoYWluMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdpbnMu
+b3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAphvoJBbi/rDvm3+X
+8xok0sLCJvCRuUpSbU5wEmREQlkoOGmWK4l6r1JyOphKRBo8+n2MxPiCMvAmTrqx
+VlBmkcmyrwWj392Nga+2SLWTziASk5nFrrhV6U79PkgXnETV2Wk1/FNVIFkB8N+B
+undsTce8LLiCs7hfA5CK7ctJg8fqsAsmgKBNGzBRWwkbvxZPd6xlY6foIJeD7PQ2
+elvTmrD6WXSZq7GshFpDEkL3AifqrPMdsTnbBpyGgJ/fBM1b2dx9k53e25mgEQmn
+iSuYQxn08BsUT0FOvav8ksZLBQz859fuqCtwhikpODO635fD9zK5YkBPlVl+/5xo
+SvKOywIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBh4zeSKjENfY+VDLtPssaNQz2a
+R1ioY40lZ0WoihDSrfG32dqTK/R2YsLKBABjJ7uRYS1NIBMrtS2OktK8BWD5IUTF
+FuGuWilu6IWiTKZrLiZh1rsilNDVqwhorRPxDnbF+qVt9EMIvzKnKdJLGF+CWHN9
+yYJDeTD8MK5uR7zUJR3PsgW4ve5pFTi7z2UJ/xRvgOds6bmeeQnvaWDEL7k2+hrr
+0G899A086NL3htzaOnIllg0xo2D1o4ToncAJn+cUQVJmHZSg9HYiD4Lg3z8uXPAl
+rt/MX7dBm4dnImLXbSg7N3e8FdUtz+kZT9z+beKAeIe9JTbpxtsVUTzUZBBA
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIID2jCCAsKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBoDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwSTW9u
+aXRvcmluZyBQbHVnaW5zMSQwIgYDVQQDDBtNb25pdG9yaW5nIFBsdWdpbnMgQ2xp
+ZW50Q0ExKzApBgkqhkiG9w0BCQEWHGRldmVsQG1vbml0b3JpbmctcGx1Z2lucy5v
+cmcwHhcNMjEwMjI4MjEwMjEyWhcNMzAxMTI4MjEwMjEyWjCBqjELMAkGA1UEBhMC
+REUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwS
+TW9uaXRvcmluZyBQbHVnaW5zMS4wLAYDVQQDDCVNb25pdG9yaW5nIFBsdWdpbnMg
+Q2xpZW50SW50ZXJtZWRpYXRlMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9y
+aW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+6rUgOZ9pAOxrcgeeOT3Vmu1YmY2O/C9tXhpKzDzjTaWUzcdDg00KdsjXfgbDzSiV
+uvMzjX63aKpmqeFG+05D2VzQGit3knqerUgl10FnTotiJGF5CU5/gY1aPxTJ7rj2
+tD6LINBkJcPTyQ4MoJT19pssvCax9erY1RxoXxLblJ+31C+VvrftdmBP4nVKXK26
+4anb1oUQhkgpXpJimJBmF+v7NbDs1Wh21Be80KXUh9SKgePhSQblr2QlRcA7jLgJ
+4PMjZ+KYF+da+4RB7s+DvTXVDMn9AL84E1w5Ut1E8XZV+u4RjWPvNdhK/7GnuxOR
+C9SdxonqkPQ8hiI7thP9bQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4IBAQDKQeiDbyr0/7sEhX33MmTDv84GeWgKl9qqHecx+d/0vImb
+c8XHK0PDa4lVqo/BW4P1hjKzpt2DW35kbOhuqGqM0lasIczef43aCDDEBLwstAe6
+qMoyWGVGoAQbpwT3li2pMrsIYoPwMvoSGNUphjrkdpviff2POkLly7a5RrR1X3qt
+Dai6eYbeMCr9NdgW7AZ5++/sKlFoe+zVk/Ed31s4D2lh3awrApZhVgcoquPmEwpt
+gm+OgRmHw50U4SF3ZaJPwDyLMbx+clH/bgUg0+Za9e53Br1NtGKmw7hh/7CG/hy0
+yxeLd930pH4vZu7s0XM56N/ckkfUzRkAH8dSmhH4
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientchain-key.pem b/plugins/tests/certs/clientchain-key.pem
new file mode 100644
index 0000000..0263604
--- /dev/null
+++ b/plugins/tests/certs/clientchain-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmG+gkFuL+sO+b
+f5fzGiTSwsIm8JG5SlJtTnASZERCWSg4aZYriXqvUnI6mEpEGjz6fYzE+IIy8CZO
+urFWUGaRybKvBaPf3Y2Br7ZItZPOIBKTmcWuuFXpTv0+SBecRNXZaTX8U1UgWQHw
+34G6d2xNx7wsuIKzuF8DkIrty0mDx+qwCyaAoE0bMFFbCRu/Fk93rGVjp+ggl4Ps
+9DZ6W9OasPpZdJmrsayEWkMSQvcCJ+qs8x2xOdsGnIaAn98EzVvZ3H2Tnd7bmaAR
+CaeJK5hDGfTwGxRPQU69q/ySxksFDPzn1+6oK3CGKSk4M7rfl8P3MrliQE+VWX7/
+nGhK8o7LAgMBAAECggEAAfTqMyKh4eYrrGVAYPi53lG0/8htrwUVG3yFDXJo628p
+biCwSCsCavZJqi8JEOxOM5UvB1L2FauGh/7i/+VKkAUUOcOTPpvZguGTACBDcXYn
+Qd3Z2kkJmgn4Kbenr4uQCVOX8zT4F710rGW1nYCyoefsa4pw37UYSW52dH6kiwzW
+9k4X251nDMl/twBdOcjZbL768IEa5l4nySLpUNwfrVbSb1NzBoH0dVioh3DTLjt6
+gaShW4eIpaKczht1U97n6/7WNLl6vHX/mR99k/py8OhzhR1ccYpd2IfSHAWyQT0M
+K8BoNnkjICrr9oc0FCr2BVJa3IzKHlhukF4GTZiGYQKBgQDWCHTwAmwL4FFEBVhj
+pZne/sjaZc8TzPPxA8SkmxwDIZrM7tSu7qUuYgWTM432jZbLILWTyGfXf2PpqyF6
+wOpoBJj1ETkre8ZfRmYvsSvS5vtjF3Drszol+XvZnOclfB5VG3m5P2vYkQ8wI9OE
+Y5jUBgDj0RsCNd8QnrC1u54U/wKBgQDGrd5y8S9kUT0P0lkZit7bYjSPJExtClXt
+V7YNTjELrVCdc0jranxBWaub8NP3e6TGTi9HiQWvk2eOAS2qyccqlK4+YAK5XO3D
+EpFUNNcClq8CErw2POuCAKajrPuSp6vd6q8h4lTzDExVctQS4R9fRKKFBKkPUV5G
+UiKFllnKNQKBgQDBGIQXfLfpxwjKK2BhFihKDOc8UhmOrZtvV4zzTJTrJkg4l0f+
+QoN34ytQcHSleXwP6oSmvWkh/GYxjBj6XE2eZndwsYc4ecSwdB0A7gCxl345Gg7g
+NqRBWmGoJGxNXzsmYVFiFZvAmK5xKgFMMWbR8lCfOCn7xopmviSC8K9gFQKBgFRb
+KmH/SbH8VELNews/TVQ0pEBKlzCM/OLjJOcNVgGxOtM/Say677sHibeST0168AFK
+3QQwh3t+yK8gjPVA6xGHQ1w0g7OUY1c6IP5x2QC+XdwxfDxDLXNrN1WzcrVX/78f
+j/CBGrR/ekGlmanSb/GRQLfdvLJGSBLveLzjk4gpAoGBANN9RUm/aRz3dDBWex46
+kJ15xKJfLZiUeyDvY5+5d7YF4/tw5LU4XmKQNhiojHecykrTzPUMaGyMrbMPNn32
+WFW9CKMjuBEwWpMDJJb1/5NLEvpwu++sr7bUPZkQl76ot6OqgNHodbP8ATqrNr80
+5b8FrEN1LyfkTbabxNyAWcA0
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/clientintermediate-cert.pem b/plugins/tests/certs/clientintermediate-cert.pem
new file mode 100644
index 0000000..608a8fa
--- /dev/null
+++ b/plugins/tests/certs/clientintermediate-cert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID2jCCAsKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBoDELMAkGA1UEBhMCREUx
+EDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwSTW9u
+aXRvcmluZyBQbHVnaW5zMSQwIgYDVQQDDBtNb25pdG9yaW5nIFBsdWdpbnMgQ2xp
+ZW50Q0ExKzApBgkqhkiG9w0BCQEWHGRldmVsQG1vbml0b3JpbmctcGx1Z2lucy5v
+cmcwHhcNMjEwMjI4MjEwMjEyWhcNMzAxMTI4MjEwMjEyWjCBqjELMAkGA1UEBhMC
+REUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11bmljaDEbMBkGA1UECgwS
+TW9uaXRvcmluZyBQbHVnaW5zMS4wLAYDVQQDDCVNb25pdG9yaW5nIFBsdWdpbnMg
+Q2xpZW50SW50ZXJtZWRpYXRlMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9y
+aW5nLXBsdWdpbnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+6rUgOZ9pAOxrcgeeOT3Vmu1YmY2O/C9tXhpKzDzjTaWUzcdDg00KdsjXfgbDzSiV
+uvMzjX63aKpmqeFG+05D2VzQGit3knqerUgl10FnTotiJGF5CU5/gY1aPxTJ7rj2
+tD6LINBkJcPTyQ4MoJT19pssvCax9erY1RxoXxLblJ+31C+VvrftdmBP4nVKXK26
+4anb1oUQhkgpXpJimJBmF+v7NbDs1Wh21Be80KXUh9SKgePhSQblr2QlRcA7jLgJ
+4PMjZ+KYF+da+4RB7s+DvTXVDMn9AL84E1w5Ut1E8XZV+u4RjWPvNdhK/7GnuxOR
+C9SdxonqkPQ8hiI7thP9bQIDAQABoxMwETAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBCwUAA4IBAQDKQeiDbyr0/7sEhX33MmTDv84GeWgKl9qqHecx+d/0vImb
+c8XHK0PDa4lVqo/BW4P1hjKzpt2DW35kbOhuqGqM0lasIczef43aCDDEBLwstAe6
+qMoyWGVGoAQbpwT3li2pMrsIYoPwMvoSGNUphjrkdpviff2POkLly7a5RrR1X3qt
+Dai6eYbeMCr9NdgW7AZ5++/sKlFoe+zVk/Ed31s4D2lh3awrApZhVgcoquPmEwpt
+gm+OgRmHw50U4SF3ZaJPwDyLMbx+clH/bgUg0+Za9e53Br1NtGKmw7hh/7CG/hy0
+yxeLd930pH4vZu7s0XM56N/ckkfUzRkAH8dSmhH4
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/clientintermediate-key.pem b/plugins/tests/certs/clientintermediate-key.pem
new file mode 100644
index 0000000..13f6887
--- /dev/null
+++ b/plugins/tests/certs/clientintermediate-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDqtSA5n2kA7Gty
+B545PdWa7ViZjY78L21eGkrMPONNpZTNx0ODTQp2yNd+BsPNKJW68zONfrdoqmap
+4Ub7TkPZXNAaK3eSep6tSCXXQWdOi2IkYXkJTn+BjVo/FMnuuPa0Posg0GQlw9PJ
+DgyglPX2myy8JrH16tjVHGhfEtuUn7fUL5W+t+12YE/idUpcrbrhqdvWhRCGSCle
+kmKYkGYX6/s1sOzVaHbUF7zQpdSH1IqB4+FJBuWvZCVFwDuMuAng8yNn4pgX51r7
+hEHuz4O9NdUMyf0AvzgTXDlS3UTxdlX67hGNY+812Er/sae7E5EL1J3GieqQ9DyG
+Iju2E/1tAgMBAAECggEACyYJXtNUoIeaXvM/r8ZhJBfMEpcnyJDUKBklnmfyABky
+ZUfmzBDXw2as3b6ihFc+LYAp3bm8KouVjtI1lfBUxrli5StVZa7PZLm9mmjv6Eo0
+ojfDEQ8afWPieoaZRO6iQVOLNkbPyv9vSuiQ7vvEZy9dw54u69h47j6IMqPprDiG
+ropUNeGAvTnh1Vf9/8aCHEvHUNHcc4zjzGiQ+E60JgnbpGVeJKoeiMgrQE0yjweo
+KyKA47Y6vqP6+AxAaPplXtmrx2UCbMjktHNvLvg42+2UlLS5roiwmJYEN9c6iT6t
+y82MJrjEFGZyLG2u6ZQANSJiIWaCnOyT1o2deJ8NoQKBgQD7UxivDTuljQD0so+E
+JX9UaFZ9PgS+8LC9v56PciL4XQ7bcCVP5vVgZZPABiQ9i989Wq7qI042Jrfu5qtE
+SthlOAu80GvAQV+Oujwo7ZzM6ciQtjMsj63r2uayWXnmQ07QcIg7x7y161Pt9Bqr
+LIDrqHziIj/lzT7+6QKZaQwFaQKBgQDvEuSC14CBlMhy2jji71kB/3Ya3c+8dP+A
+kQZL9wEWK4a4dm8IaTS8jl1/luhQUzFRMyh2rWaTqqigSe3dvs5DRblhE5NPwTSI
+9TO7t1EnzjW3R8LxZZsySyiSFnZ/8mR0empxq0Mov37OdXBj0tXuuzREf/hwijWh
+WuLxJUSjZQKBgAIDZ2Y3l+u6lnBfYdDwL/XwJAk6zvTsnq3WdCG4C1mr/St62YGr
+WvnbtnRKWE356d7m9BHCGKVMaBrM1EBmzRb6fPWVQde3blmJWmQFi0UE9mtaWkyY
+Fg+WoFR7bQOQNHhs/lpkPjnC2dhFJVWLtLiuj9mL5rEjlMab/T5XXhZJAoGBAMEP
+FZ8fXbPGrTQqSwPfWpZFcF9zvbynEmkFM/uGRMddcNZnNXSqWJ7nrFNLTuEGvW2g
+DU4A6zPV/YQrDz4hRjmHBZOCFlSyZbUvpY4yFAQ7/p66AY+kiHZNwT5vi1P5Luvs
+qyaNsZcnRMR+i7rg2EeHv0aNvNdMlNBvL5KikNINAoGAU2P/phdwJOUcqgHavQcQ
+ureTEyZ5i5AeNomNeHSj0slG24V9nxOqEL7D00JKln7oAPovYBUWocEnF39uBJe0
+p0Hy7fCCK6EI8/0QyiQuuZmJfDEEvjQqE6irONNH63r2UwDEpDNGFvGsZNuWHLZc
+SXADu5oSNu6o6IydiyOx528=
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/expired-cert.pem b/plugins/tests/certs/expired-cert.pem
new file mode 100644
index 0000000..87fc8e4
--- /dev/null
+++ b/plugins/tests/certs/expired-cert.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEETCCAvmgAwIBAgIUVDKkhcUoYFnjYCw12tScPIqQzqIwDQYJKoZIhvcNAQEL
+BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
+dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u
+aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n
+LXBsdWdpbnMub3JnMB4XDTA4MDEwMTEyMDAwMFoXDTA4MDEwMjEyMDAwMFowgZcx
+CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx
+GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu
+ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp
+bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwg1dmGT3rVqM
+beVWWLy8EAiq9re07AF8sTERy9oIYF5EUq9f0xO53mwwqIWV77O9mF99/kDFGQuQ
+NOnICMSHXNtMXEXzfBaMighw0uyCh1o/VCejNQ5x/HU8aLh930g5DIcOJQ3fZ4v9
+8kBaie7+aPgRMVDM1vIrILfedq9Kt56zvPizkXhDeqxjKyIZdrdoBlX5zAfftWtY
+HpQ+lkThSSXqQnchN6S2JFejmRtsNnceDVOBBdvlzmH0NlfwjynLK3/EJooTsINy
+i9dXD8/Oe8r+UA+nokWvnWC2IAUJjpxW+XAyTG/NofGwX+PwquT0YD5cSlODIwZA
+WAimygWLqQIDAQABo1MwUTAdBgNVHQ4EFgQUsKyJAwR9OXWEcSZMQz73GfpxCJIw
+HwYDVR0jBBgwFoAUsKyJAwR9OXWEcSZMQz73GfpxCJIwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAYKFGX7J3Fc/T9s278w61E2dSsY4DS/mjSDik
+fMWvod6eKw0fE3wJOnkWxjEH3VywTY6CmHd/oiJOaD8lr/Vk+BJfYNVBaVNmguyg
+4LXoWz9Benx0bAIeuDbNAhOvA4H4aIz8UrD9lKFvKdRp42gPMLtMEbzbLcBdT95D
+6BX7EhYm7vTnpitLPgFxVCsJ1JFqv2AQfUm+IkqQkezPs5x0tWLyrvCDNRGJ0kfv
+UuowpUZXDOh3k1vB+xaSOFviieLaCW8TSdd5FZgI2HQj4e6vCKsMGuKKZXrMUTI/
+qtrFlUfsOuwourfC5LMHtCyYo5B3uvAWT1eTXxhrGqyleSlxJQ==
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/expired-key.pem b/plugins/tests/certs/expired-key.pem
new file mode 100644
index 0000000..c5bba56
--- /dev/null
+++ b/plugins/tests/certs/expired-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCDV2YZPetWoxt
+5VZYvLwQCKr2t7TsAXyxMRHL2ghgXkRSr1/TE7nebDCohZXvs72YX33+QMUZC5A0
+6cgIxIdc20xcRfN8FoyKCHDS7IKHWj9UJ6M1DnH8dTxouH3fSDkMhw4lDd9ni/3y
+QFqJ7v5o+BExUMzW8isgt952r0q3nrO8+LOReEN6rGMrIhl2t2gGVfnMB9+1a1ge
+lD6WROFJJepCdyE3pLYkV6OZG2w2dx4NU4EF2+XOYfQ2V/CPKcsrf8QmihOwg3KL
+11cPz857yv5QD6eiRa+dYLYgBQmOnFb5cDJMb82h8bBf4/Cq5PRgPlxKU4MjBkBY
+CKbKBYupAgMBAAECggEBAJ2mdCKJ7LoWdT4W8pZ3BqZUFGkKCF8wOhhOUDH3+ZQp
+IYK3XbdDMF7mMIXIuW4a7W4sLlTwU/Ar98U1JMESwRIMS7YvUke+ngDKKLcDVGwY
+Qpjg9vP0v2Al8qT1NbW/nDF0S2aJJbWfAvnblHK5ClFHL9iL107NQYJ8PqzXbnFL
+gCQRiZxVHlrbn/73ZUMHPGEoU0711U9hSjrsqrRuSAMC+V38s4HxOomZWutlVAHF
+HwClNZBqRO+a2njPyUuV9DM/rl5Tm9IQ89iFo3/QEORICK77HjJYhi+UzdfI5F35
+UntRJt+WLaiAP+K6Vt6oxHSm58qXnOkeLzaAunTTie0CgYEA6OLYfme8xe5zYXWX
+rqmKNYdcVfMkvL+vUfVT475o/piRtE54JC1LYWEFAN8paxEWHD5HZMy0+ONNXfGm
+zyNNTN/Lagz4WcpdFzKQmhfdro7DzRiDfdvwSLmaZDyE41PPPVVvfrI9IeDiUNY4
+nWLSb3sWo96Iuns+RoMqeA9wkqsCgYEA1U/UqeVQVTPlrWyiB2VXoI1xvFCCJTf8
+4NC0gcisxLRrtINk0BwrUJrRy0x1OLpJWiKwUl/W1GgvPPfhbYcUOb669JNtTIjY
+FeIZblCTjz9GzKKmXeDciXvccyEdCJVUlPO3/e2JiJ4mCDjULprifq0a2gcQevFS
+PfqVULhBOvsCgYB5KfS7J1vGmv36ucSWAe0/VlKLATqe3RfpCzt/JQTZWSWNaroF
+EG/ElUaWIoUZCEW5oglg/0Q0rYYGF4DTCingkhrx7ReVF70BIbSsBzi15d8nKNbY
+t4I3RCF4fyggYe1TmsysXS2DH85/gkToVY7oo2CvF0uJwi8vXnTNDDNkiwKBgHKs
+mAc94BHt9GtnGzQepx0I7TvvjAe2MZwqlt+uojKdS8mfWXMHscGDeYVxdRMqEoUC
+YQfnvfYyjDKaj/XxyE3C237gQsICTyh0hHdpmepIeidIyWdumyDOFZVPF+ylWvM4
+kpFQQb/QRWHmKyti2KCBLw5G/fUaBryLGfprE6ZBAoGBANy5rr41A679UQZ0abev
+bOZb7YWOHYp/wReJaQbvLAyR30os3aEY/0ht9S+OWdrgGMezPKvsx2Sqr/CwoFXI
+esiklpknr11maEPxnQJYi4FYiXS1a3NCg7yBvKzFEgx2XnMAC3s6zhuZXaFq4zNu
+pm5Btrq/NZqtVXovS+UhGLvJ
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/certs/ext.cnf b/plugins/tests/certs/ext.cnf
new file mode 100644
index 0000000..d09cee1
--- /dev/null
+++ b/plugins/tests/certs/ext.cnf
@@ -0,0 +1,2 @@
+[ client_ca ]
+basicConstraints = critical, CA:true
diff --git a/plugins/tests/certs/generate-certs.sh b/plugins/tests/certs/generate-certs.sh
new file mode 100755
index 0000000..78660a2
--- /dev/null
+++ b/plugins/tests/certs/generate-certs.sh
@@ -0,0 +1,63 @@
+#!/bin/sh -e
+#
+# Recreates the https server certificates
+#
+# Set the GEN_EXPIRED environment variable to also regenerate
+# the expired certificate.
+
+cd "$(dirname "$0")"
+trap 'rm -f *.csr; rm -f clientca-cert.srl' EXIT
+
+subj() {
+ c="DE"
+ st="Bavaria"
+ l="Munich"
+ o="Monitoring Plugins"
+ cn="Monitoring Plugins"
+ emailAddress="devel@monitoring-plugins.org"
+
+ if [ -n "$1" ]; then
+ # Add to CN
+ cn="$cn $1"
+ fi
+
+ printf "/C=%s/ST=%s/L=%s/O=%s/CN=%s/emailAddress=%s" \
+ "$c" "$st" "$l" "$o" "$cn" "$emailAddress"
+}
+
+# server
+openssl req -new -x509 -days 3560 -nodes \
+ -keyout server-key.pem -out server-cert.pem \
+ -subj "$(subj)"
+# server, expired
+# there is generally no need to regenerate this, as it will stay epxired
+[ -n "$GEN_EXPIRED" ] && TZ=UTC faketime -f '2008-01-01 12:00:00' \
+ openssl req -new -x509 -days 1 -nodes \
+ -keyout expired-key.pem -out expired-cert.pem \
+ -subj "$(subj)"
+
+# client, ca
+openssl req -new -x509 -days 3560 -nodes \
+ -keyout clientca-key.pem -out clientca-cert.pem \
+ -subj "$(subj ClientCA)"
+echo "01" >clientca-cert.srl
+# client
+openssl req -new -nodes \
+ -keyout client-key.pem -out client-cert.csr \
+ -subj "$(subj Client)"
+openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
+ -in client-cert.csr -out client-cert.pem
+# client, intermediate
+openssl req -new -nodes \
+ -keyout clientintermediate-key.pem -out clientintermediate-cert.csr \
+ -subj "$(subj ClientIntermediate)"
+openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
+ -extfile ext.cnf -extensions client_ca \
+ -in clientintermediate-cert.csr -out clientintermediate-cert.pem
+# client, chain
+openssl req -new -nodes \
+ -keyout clientchain-key.pem -out clientchain-cert.csr \
+ -subj "$(subj ClientChain)"
+openssl x509 -days 3560 -req -CA clientca-cert.pem -CAkey clientca-key.pem \
+ -in clientchain-cert.csr -out clientchain-cert.pem
+cat clientintermediate-cert.pem >>clientchain-cert.pem
diff --git a/plugins/tests/certs/server-cert.pem b/plugins/tests/certs/server-cert.pem
new file mode 100644
index 0000000..d1249ef
--- /dev/null
+++ b/plugins/tests/certs/server-cert.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEETCCAvmgAwIBAgIUZwOhY4myaCUaPek3NM+MxbLG9vwwDQYJKoZIhvcNAQEL
+BQAwgZcxCzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZN
+dW5pY2gxGzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9u
+aXRvcmluZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5n
+LXBsdWdpbnMub3JnMB4XDTIxMDIyODIxMDIxMVoXDTMwMTEyODIxMDIxMVowgZcx
+CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdCYXZhcmlhMQ8wDQYDVQQHDAZNdW5pY2gx
+GzAZBgNVBAoMEk1vbml0b3JpbmcgUGx1Z2luczEbMBkGA1UEAwwSTW9uaXRvcmlu
+ZyBQbHVnaW5zMSswKQYJKoZIhvcNAQkBFhxkZXZlbEBtb25pdG9yaW5nLXBsdWdp
+bnMub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/3eBA4WG6xz
+LfM6xcWywxThb1Rp7XAW3ewQd9/PdoWXEe8BJWlLfyYi1drLMcsDywhLkKmW4Vp9
+1R4PAkiljjrB/ZaUMDLJ1ri3dwX4RvXG7crsU3QWFWCBOrf5V2FTRQ2m/H/KyB/6
+rVZANsU47HqTFSPiUm2j7P3wx/wtHeYC+qmNG7zZTjAYPYxfKiod0lytTSmb+h54
+6lxn3+VPEXZAQZlLvPnm/58JnXGrUv7B2yocf5MhKkLJOrGxH2hfwKISfaj2gpOV
+m4PUVYiDzCSpq1fPvwbUxIvdO27xprx+mrGOFM6f2UCEOc35w8FSmYiR2yQTnEJK
+pbSQD6t1jQIDAQABo1MwUTAdBgNVHQ4EFgQUMeYgglT2aWDlF8KEeF2376AlTGYw
+HwYDVR0jBBgwFoAUMeYgglT2aWDlF8KEeF2376AlTGYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAQEAFcEg83rTJdgkp7JLYqK0j8JogSHNlDYchr/r
+VxKBgQwfnjSp5A8d5+uTQ9s3QDabw8v7YeSrzYXbbjuWZ61mnl84tzOQ8LMeESnC
+CBXRCxB8Ow22WsVTVJq279SGYT+cZrdsmqGVWDi1A0C5kH+XTLAioG5CZmmxemD/
+S92ZoRxGyYfg33r+3X6EMcEYtHKGxCUa3EPcPOL4dq2F3nOnyjiWPZm3786H3NY2
+nsYwrEhAdUFtbYSsV5O0c/Zlc33fmTfh654ab35io1DtwmFo7q8J532dUE007EN0
+mIQmhdrjNJJHIftgSt0fuN5m48oLOnX7vvkz+X0WLWfVTtMr0w==
+-----END CERTIFICATE-----
diff --git a/plugins/tests/certs/server-key.pem b/plugins/tests/certs/server-key.pem
new file mode 100644
index 0000000..0de63f8
--- /dev/null
+++ b/plugins/tests/certs/server-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDb/d4EDhYbrHMt
+8zrFxbLDFOFvVGntcBbd7BB33892hZcR7wElaUt/JiLV2ssxywPLCEuQqZbhWn3V
+Hg8CSKWOOsH9lpQwMsnWuLd3BfhG9cbtyuxTdBYVYIE6t/lXYVNFDab8f8rIH/qt
+VkA2xTjsepMVI+JSbaPs/fDH/C0d5gL6qY0bvNlOMBg9jF8qKh3SXK1NKZv6Hnjq
+XGff5U8RdkBBmUu8+eb/nwmdcatS/sHbKhx/kyEqQsk6sbEfaF/AohJ9qPaCk5Wb
+g9RViIPMJKmrV8+/BtTEi907bvGmvH6asY4Uzp/ZQIQ5zfnDwVKZiJHbJBOcQkql
+tJAPq3WNAgMBAAECggEBAIvJDUjQVpXxByL8eazviT5SR0jBf6mC3tTWykQRb7ck
+/bBEiRrnhDRf3CS9KP4TvO5G8BUU3a2GHYzM08akuKXeiiODidfyfbQ1nUZBAdi9
+FVFF7tK8YcflkVfpTMOMMSggm6m33fc58sQvmQ/0U85XuJvnOEkeJ9pQJa49e8GR
+lpCQImF7ygltHPEz4o8qOtNMuPxiHOxpc517+ozQULZk153NTfGok1XctDFFZ3YX
+8okLSfcqZ28mdHYSvI9xf60Cm7cT9tunXHwZ0f1esTFiVYpAp+oTJqtdYxr/fYlL
+oO8G8iIQ7LjdJfgo84PscpKdSRCq3BfnmER1Eyg6hrUCgYEA/0hL5Y/haz/2jYGy
+aa8yZSuD1ZcWtj7pLKrBQnHPHIHsjSBggWhopvonCFvCjgSS1pOFOUAwMGc0T+Dw
+rWo3w8cEUyECl3Bw8gbCWtRXaigzU9TPgCWyx1j5dTopQhLObzS/m7fJFElnYNru
+jqhsUfWS+NKk8a5+A7i9lv4iBLMCgYEA3Jws3Lfj/Xs7LljrvryTMpPthvUGBcyt
+U9Qmf1Hmur90RP5V1rx4FqPQzIeaGQyZDNIUnkhBSqQZNCts3Rzay7N4uQzk8OEg
+S8Llnw76wLwi0SJ4okDtT5tpTR6fcS0M9lGN+zvvfUB4+ul8oub0pMcyme/pywEz
+ap+x3xAQPL8CgYEAiYOBVtTNof9fqdRurh1w8SyipKDx3BRBeQ02c7tozLt0GIWT
+VsJOdXwVIJyFTglKrAnlXvSjwL8nX8wU+eVYyr5fJwSGJ9urC8T2VwVBXW7wTz04
+1Zf5GQdlwW8mIHCPATqR6Kj0yVfNN1BX50L0rqWxmRWnQoUzXn/aqQaWfp8CgYAW
+9693/zEeR8EejyVkAy/z+RCml0XcPrXg31pusPErihkpwazgIVkDSmTHlmqFpxkc
+C5cX73/UrIbvNoIr9wAUawfrhBsltNpu6MiNKbsTa8LYMRWMFuReAFkTLVf+KWmL
+D2yPtmq1iIvP25UdRJw9t3teKWsWtnZK6HtVNM/r8wKBgQDKlqUpy8r4KK+S2w80
+H7rAQJo1DgXsYrgSa2gfppSKro4lm3ltyAfVIrKQKP7uCo9xTGKVQAUPttMs2+17
+nwbwvt7/nG7G1Dk/C/t6b7SJ80VY5b9ZZKIJ0wOjajLufSjPNCe0ZTRn32XusZUn
+nYGB5/QXYr5WGV9YhAkRsFJYgA==
+-----END PRIVATE KEY-----
diff --git a/plugins/tests/check_curl.t b/plugins/tests/check_curl.t
new file mode 100755
index 0000000..3c91483
--- /dev/null
+++ b/plugins/tests/check_curl.t
@@ -0,0 +1,526 @@
+#! /usr/bin/perl -w -I ..
+#
+# Test check_http by having an actual HTTP server running
+#
+# To create the https server certificate:
+# openssl req -new -x509 -keyout server-key.pem -out server-cert.pem -days 3650 -nodes
+# to create a new expired certificate:
+# faketime '2008-01-01 12:00:00' openssl req -new -x509 -keyout expired-key.pem -out expired-cert.pem -days 1 -nodes
+# Country Name (2 letter code) [AU]:DE
+# State or Province Name (full name) [Some-State]:Bavaria
+# Locality Name (eg, city) []:Munich
+# Organization Name (eg, company) [Internet Widgets Pty Ltd]:Monitoring Plugins
+# Organizational Unit Name (eg, section) []:
+# Common Name (e.g. server FQDN or YOUR name) []:Monitoring Plugins
+# Email Address []:devel@monitoring-plugins.org
+
+use strict;
+use Test::More;
+use NPTest;
+use FindBin qw($Bin);
+
+$ENV{'LC_TIME'} = "C";
+
+my $common_tests = 73;
+my $ssl_only_tests = 8;
+# Check that all dependent modules are available
+eval "use HTTP::Daemon 6.01;";
+plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@;
+eval {
+ require HTTP::Status;
+ require HTTP::Response;
+};
+
+my $plugin = 'check_http';
+$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
+
+# look for libcurl version to see if some advanced checks are possible (>= 7.49.0)
+my $advanced_checks = 12;
+my $use_advanced_checks = 0;
+my $required_version = '7.49.0';
+my $virtual_host = 'www.somefunnyhost.com';
+my $virtual_port = 42;
+my $curl_version = '';
+open (my $fh, '-|', "./$plugin --version") or die;
+while (<$fh>) {
+ if (m{libcurl/([\d.]+)\s}) {
+ $curl_version = $1;
+ last;
+ }
+}
+close ($fh);
+if ($curl_version) {
+ my ($major, $minor, $release) = split (/\./, $curl_version);
+ my ($req_major, $req_minor, $req_release) = split (/\./, $required_version);
+ my $check = ($major <=> $req_major or $minor <=> $req_minor or $release <=> $req_release);
+ if ($check >= 0) {
+ $use_advanced_checks = 1;
+ print "Found libcurl $major.$minor.$release. Using advanced checks\n";
+ }
+}
+
+if ($@) {
+ plan skip_all => "Missing required module for test: $@";
+} else {
+ if (-x "./$plugin") {
+ plan tests => $common_tests * 2 + $ssl_only_tests + $advanced_checks;
+ } else {
+ plan skip_all => "No $plugin compiled";
+ }
+}
+
+my $servers = { http => 0 }; # HTTP::Daemon should always be available
+eval { require HTTP::Daemon::SSL };
+if ($@) {
+ diag "Cannot load HTTP::Daemon::SSL: $@";
+} else {
+ $servers->{https} = 0;
+}
+
+# set a fixed version, so the header size doesn't vary
+$HTTP::Daemon::VERSION = "1.00";
+
+my $port_http = 50000 + int(rand(1000));
+my $port_https = $port_http + 1;
+my $port_https_expired = $port_http + 2;
+
+# This array keeps sockets around for implementing timeouts
+my @persist;
+
+# Start up all servers
+my @pids;
+my $pid = fork();
+if ($pid) {
+ # Parent
+ push @pids, $pid;
+ if (exists $servers->{https}) {
+ # Fork a normal HTTPS server
+ $pid = fork();
+ if ($pid) {
+ # Parent
+ push @pids, $pid;
+ # Fork an expired cert server
+ $pid = fork();
+ if ($pid) {
+ push @pids, $pid;
+ } else {
+ my $d = HTTP::Daemon::SSL->new(
+ LocalPort => $port_https_expired,
+ LocalAddr => "127.0.0.1",
+ SSL_cert_file => "$Bin/certs/expired-cert.pem",
+ SSL_key_file => "$Bin/certs/expired-key.pem",
+ ) || die;
+ print "Please contact https expired at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ exit;
+ }
+ } else {
+ my $d = HTTP::Daemon::SSL->new(
+ LocalPort => $port_https,
+ LocalAddr => "127.0.0.1",
+ SSL_cert_file => "$Bin/certs/server-cert.pem",
+ SSL_key_file => "$Bin/certs/server-key.pem",
+ ) || die;
+ print "Please contact https at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ exit;
+ }
+ }
+} else {
+ # Child
+ #print "child\n";
+ my $d = HTTP::Daemon->new(
+ LocalPort => $port_http,
+ LocalAddr => "127.0.0.1",
+ ) || die;
+ print "Please contact http at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ exit;
+}
+
+# give our webservers some time to startup
+sleep(3);
+
+# Run the same server on http and https
+sub run_server {
+ my $d = shift;
+ MAINLOOP: while (my $c = $d->accept ) {
+ while (my $r = $c->get_request) {
+ if ($r->method eq "GET" and $r->url->path =~ m^/statuscode/(\d+)^) {
+ $c->send_basic_header($1);
+ $c->send_crlf;
+ } elsif ($r->method eq "GET" and $r->url->path =~ m^/file/(.*)^) {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_file_response("$Bin/var/$1");
+ } elsif ($r->method eq "GET" and $r->url->path eq "/slow") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ sleep 1;
+ $c->send_response("slow");
+ } elsif ($r->url->path eq "/method") {
+ if ($r->method eq "DELETE") {
+ $c->send_error(HTTP::Status->RC_METHOD_NOT_ALLOWED);
+ } elsif ($r->method eq "foo") {
+ $c->send_error(HTTP::Status->RC_NOT_IMPLEMENTED);
+ } else {
+ $c->send_status_line(200, $r->method);
+ }
+ } elsif ($r->url->path eq "/postdata") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response($r->method.":".$r->content);
+ } elsif ($r->url->path eq "/redirect") {
+ $c->send_redirect( "/redirect2" );
+ } elsif ($r->url->path eq "/redir_external") {
+ $c->send_redirect(($d->isa('HTTP::Daemon::SSL') ? "https" : "http") . "://169.254.169.254/redirect2" );
+ } elsif ($r->url->path eq "/redirect2") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
+ } elsif ($r->url->path eq "/redir_timeout") {
+ $c->send_redirect( "/timeout" );
+ } elsif ($r->url->path eq "/timeout") {
+ # Keep $c from being destroyed, but prevent severe leaks
+ unshift @persist, $c;
+ delete($persist[1000]);
+ next MAINLOOP;
+ } elsif ($r->url->path eq "/header_check") {
+ $c->send_basic_header;
+ $c->send_header('foo');
+ $c->send_crlf;
+ } elsif ($r->url->path eq "/header_broken_check") {
+ $c->send_basic_header;
+ $c->send_header('foo');
+ print $c "Test1:: broken\n";
+ print $c " Test2: leading whitespace\n";
+ $c->send_crlf;
+ } elsif ($r->url->path eq "/virtual_port") {
+ # return sent Host header
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
+ } elsif ($r->url->path eq "/chunked") {
+ my $chunks = ["chunked", "encoding", "test\n"];
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, sub {
+ my $chunk = shift @{$chunks};
+ return unless $chunk;
+ sleep(1);
+ return($chunk);
+ }));
+ } else {
+ $c->send_error(HTTP::Status->RC_FORBIDDEN);
+ }
+ $c->close;
+ }
+ }
+}
+
+END {
+ foreach my $pid (@pids) {
+ if ($pid) { print "Killing $pid\n"; kill "INT", $pid }
+ }
+};
+
+if ($ARGV[0] && $ARGV[0] eq "-d") {
+ while (1) {
+ sleep 100;
+ }
+}
+
+my $result;
+my $command = "./$plugin -H 127.0.0.1";
+
+run_common_tests( { command => "$command -p $port_http" } );
+SKIP: {
+ skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https};
+ run_common_tests( { command => "$command -p $port_https", ssl => 1 } );
+
+ my $expiry = "Thu Nov 28 21:02:11 2030 +0000";
+
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 14" );
+ is( $result->return_code, 0, "$command -p $port_https -S -C 14" );
+ is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on $expiry.", "output ok" );
+
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" );
+ is( $result->return_code, 1, "$command -p $port_https -S -C 14000" );
+ like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
+
+ # Expired cert tests
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" );
+ is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" );
+ like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
+
+ $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" );
+ is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" );
+ is( $result->output,
+ 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 12:00:00 2008 +0000.',
+ "output ok" );
+
+}
+
+my $cmd;
+
+# advanced checks with virtual hostname and virtual port
+SKIP: {
+ skip "libcurl version is smaller than $required_version", 6 unless $use_advanced_checks;
+
+ # http without virtual port
+ $cmd = "./$plugin -H $virtual_host -I 127.0.0.1 -p $port_http -u /virtual_port -r ^$virtual_host:$port_http\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # http with virtual port (!= 80)
+ $cmd = "./$plugin -H $virtual_host:$virtual_port -I 127.0.0.1 -p $port_http -u /virtual_port -r ^$virtual_host:$virtual_port\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # http with virtual port (80)
+ $cmd = "./$plugin -H $virtual_host:80 -I 127.0.0.1 -p $port_http -u /virtual_port -r ^$virtual_host\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+}
+
+# and the same for SSL
+SKIP: {
+ skip "libcurl version is smaller than $required_version and/or HTTP::Daemon::SSL not installed", 6 if ! exists $servers->{https} or not $use_advanced_checks;
+ # https without virtual port
+ $cmd = "./$plugin -H $virtual_host -I 127.0.0.1 -p $port_https --ssl -u /virtual_port -r ^$virtual_host:$port_https\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # https with virtual port (!= 443)
+ $cmd = "./$plugin -H $virtual_host:$virtual_port -I 127.0.0.1 -p $port_https --ssl -u /virtual_port -r ^$virtual_host:$virtual_port\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # https with virtual port (443)
+ $cmd = "./$plugin -H $virtual_host:443 -I 127.0.0.1 -p $port_https --ssl -u /virtual_port -r ^$virtual_host\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+}
+
+
+sub run_common_tests {
+ my ($opts) = @_;
+ my $command = $opts->{command};
+ if ($opts->{ssl}) {
+ $command .= " --ssl";
+ }
+
+ $result = NPTest->testCmd( "$command -u /file/root" );
+ is( $result->return_code, 0, "/file/root");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 274 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /file/root -s Root" );
+ is( $result->return_code, 0, "/file/root search for string");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 274 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /file/root -s NonRoot" );
+ is( $result->return_code, 2, "Missing string check");
+ like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - string 'NonRoot' not found on 'https?://127\.0\.0\.1:\d+/file/root'%, "Shows search string and location");
+
+ $result = NPTest->testCmd( "$command -u /file/root -s NonRootWithOver30charsAndMoreFunThanAWetFish" );
+ is( $result->return_code, 2, "Missing string check");
+ like( $result->output, qr%HTTP CRITICAL: HTTP/1\.1 200 OK - string 'NonRootWithOver30charsAndM...' not found on 'https?://127\.0\.0\.1:\d+/file/root'%, "Shows search string and location");
+
+ $result = NPTest->testCmd( "$command -u /header_check -d foo" );
+ is( $result->return_code, 0, "header_check search for string");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 96 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /header_check -d bar" );
+ is( $result->return_code, 2, "Missing header string check");
+ like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - header 'bar' not found on 'https?://127\.0\.0\.1:\d+/header_check'%, "Shows search string and location");
+
+ $result = NPTest->testCmd( "$command -u /header_broken_check" );
+ is( $result->return_code, 0, "header_check search for string");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 138 bytes in [\d\.]+ second/', "Output correct" );
+
+ my $cmd;
+ $cmd = "$command -u /slow";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, "$cmd");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+ $result->output =~ /in ([\d\.]+) second/;
+ cmp_ok( $1, ">", 1, "Time is > 1 second" );
+
+ $cmd = "$command -u /statuscode/200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/200 -e 200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - Status line output matched "200" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 201 Created - \d+ bytes in [\d\.]+ second /', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 201";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 201 Created - Status line output matched "201" - \d+ bytes in [\d\.]+ second /', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL - Invalid HTTP response received from host on port \d+: HTTP/1.1 201 Created/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/200 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - Status line output matched "200,201,202" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 201 Created - Status line output matched "200,201,202" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/203 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL - Invalid HTTP response received from host on port (\d+): HTTP/1.1 203 Non-Authoritative Information/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j HEAD -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 HEAD - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j POST -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 POST - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j GET -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 GET - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 GET - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -P foo -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 POST - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j DELETE -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 1, $cmd);
+ like( $result->output, '/^HTTP WARNING: HTTP/1.1 405 Method Not Allowed/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j foo -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL: HTTP/1.1 501 Not Implemented/', "Output correct: ".$result->output );
+
+ $cmd = "$command -P stufftoinclude -u /postdata -s POST:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j PUT -P stufftoinclude -u /postdata -s PUT:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # To confirm that the free doesn't segfault
+ $cmd = "$command -P stufftoinclude -j PUT -u /postdata -s PUT:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /redirect";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 301 Moved Permanently - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f follow -u /redirect";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 301 Moved Permanently - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f follow -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f sticky -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f stickyport -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # These tests may block
+ print "ALRM\n";
+
+ # stickyport - on full urlS port is set back to 80 otherwise
+ $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected";
+ eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ alarm(2);
+ $result = NPTest->testCmd( $cmd );
+ };
+ alarm(0);
+ isnt( $@, "alarm\n", $cmd );
+ is( $result->return_code, 0, $cmd );
+
+ # Let's hope there won't be any web server on :80 returning "redirected"!
+ $cmd = "$command -f sticky -u /redir_external -t 5 -s redirected";
+ eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ alarm(2);
+ $result = NPTest->testCmd( $cmd );
+ };
+ alarm(0);
+ isnt( $@, "alarm\n", $cmd );
+ isnt( $result->return_code, 0, $cmd );
+
+ # Test an external address - timeout
+ SKIP: {
+ skip "This doesn't seem to work all the time", 1 unless ($ENV{HTTP_EXTERNAL});
+ $cmd = "$command -f follow -u /redir_external -t 5";
+ eval {
+ $result = NPTest->testCmd( $cmd, 2 );
+ };
+ like( $@, "/timeout in command: $cmd/", $cmd );
+ }
+
+ $cmd = "$command -u /timeout -t 5";
+ eval {
+ $result = NPTest->testCmd( $cmd, 2 );
+ };
+ like( $@, "/timeout in command: $cmd/", $cmd );
+
+ $cmd = "$command -f follow -u /redir_timeout -t 2";
+ eval {
+ $result = NPTest->testCmd( $cmd, 5 );
+ };
+ is( $@, "", $cmd );
+
+ $cmd = "$command -u /chunked -s 'chunkedencodingtest' -d 'Transfer-Encoding: chunked'";
+ eval {
+ $result = NPTest->testCmd( $cmd, 5 );
+ };
+ is( $@, "", $cmd );
+}
diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t
new file mode 100755
index 0000000..6078b27
--- /dev/null
+++ b/plugins/tests/check_http.t
@@ -0,0 +1,581 @@
+#! /usr/bin/perl -w -I ..
+#
+# Test check_http by having an actual HTTP server running
+#
+# To create the https server certificate:
+# ./certs/generate-certs.sh
+
+use strict;
+use Test::More;
+use NPTest;
+use FindBin qw($Bin);
+use IO::Socket::INET;
+
+$ENV{'LC_TIME'} = "C";
+
+my $common_tests = 71;
+my $virtual_port_tests = 8;
+my $ssl_only_tests = 12;
+my $chunked_encoding_special_tests = 1;
+# Check that all dependent modules are available
+eval "use HTTP::Daemon 6.01;";
+plan skip_all => 'HTTP::Daemon >= 6.01 required' if $@;
+eval {
+ require HTTP::Status;
+ require HTTP::Response;
+};
+
+my $plugin = 'check_http';
+$plugin = 'check_curl' if $0 =~ m/check_curl/mx;
+
+if ($@) {
+ plan skip_all => "Missing required module for test: $@";
+} else {
+ if (-x "./$plugin") {
+ plan tests => $common_tests * 2 + $ssl_only_tests + $virtual_port_tests + $chunked_encoding_special_tests;
+ } else {
+ plan skip_all => "No $plugin compiled";
+ }
+}
+
+my $servers = { http => 0 }; # HTTP::Daemon should always be available
+eval { require HTTP::Daemon::SSL };
+if ($@) {
+ diag "Cannot load HTTP::Daemon::SSL: $@";
+} else {
+ $servers->{https} = 0;
+}
+
+# set a fixed version, so the header size doesn't vary
+$HTTP::Daemon::VERSION = "1.00";
+
+my $port_http = 50000 + int(rand(1000));
+my $port_https = $port_http + 1;
+my $port_https_expired = $port_http + 2;
+my $port_https_clientcert = $port_http + 3;
+my $port_hacked_http = $port_http + 4;
+
+# This array keeps sockets around for implementing timeouts
+my @persist;
+
+# Start up all servers
+my @pids;
+# Fork a HTTP server
+my $pid = fork;
+defined $pid or die "Failed to fork";
+if (!$pid) {
+ undef @pids;
+ my $d = HTTP::Daemon->new(
+ LocalPort => $port_http,
+ LocalAddr => "127.0.0.1",
+ ) || die;
+ print "Please contact http at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ die "webserver stopped";
+}
+push @pids, $pid;
+
+# Fork the hacked HTTP server
+undef $pid;
+$pid = fork;
+defined $pid or die "Failed to fork";
+if (!$pid) {
+ # this is the fork
+ undef @pids;
+ my $socket = new IO::Socket::INET (
+ LocalHost => '0.0.0.0',
+ LocalPort => $port_hacked_http,
+ Proto => 'tcp',
+ Listen => 5,
+ Reuse => 1
+ );
+ die "cannot create socket $!n" unless $socket;
+ my $local_sock = $socket->sockport();
+ print "server waiting for client connection on port $local_sock\n";
+ run_hacked_http_server ( $socket );
+ die "hacked http server stopped";
+}
+push @pids, $pid;
+
+if (exists $servers->{https}) {
+ # Fork a normal HTTPS server
+ $pid = fork;
+ defined $pid or die "Failed to fork";
+ if (!$pid) {
+ undef @pids;
+ # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
+ local $SIG{'PIPE'} = 'IGNORE';
+ my $d = HTTP::Daemon::SSL->new(
+ LocalPort => $port_https,
+ LocalAddr => "127.0.0.1",
+ SSL_cert_file => "$Bin/certs/server-cert.pem",
+ SSL_key_file => "$Bin/certs/server-key.pem",
+ ) || die;
+ print "Please contact https at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ die "webserver stopped";
+ }
+ push @pids, $pid;
+
+ # Fork an expired cert server
+ $pid = fork;
+ defined $pid or die "Failed to fork";
+ if (!$pid) {
+ undef @pids;
+ # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
+ local $SIG{'PIPE'} = 'IGNORE';
+ my $d = HTTP::Daemon::SSL->new(
+ LocalPort => $port_https_expired,
+ LocalAddr => "127.0.0.1",
+ SSL_cert_file => "$Bin/certs/expired-cert.pem",
+ SSL_key_file => "$Bin/certs/expired-key.pem",
+ ) || die;
+ print "Please contact https expired at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ die "webserver stopped";
+ }
+ push @pids, $pid;
+
+ # Fork an client cert expecting server
+ $pid = fork;
+ defined $pid or die "Failed to fork";
+ if (!$pid) {
+ undef @pids;
+ # closing the connection after -C cert checks make the daemon exit with a sigpipe otherwise
+ local $SIG{'PIPE'} = 'IGNORE';
+ my $d = HTTP::Daemon::SSL->new(
+ LocalPort => $port_https_clientcert,
+ LocalAddr => "127.0.0.1",
+ SSL_cert_file => "$Bin/certs/server-cert.pem",
+ SSL_key_file => "$Bin/certs/server-key.pem",
+ SSL_verify_mode => IO::Socket::SSL->SSL_VERIFY_PEER | IO::Socket::SSL->SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ SSL_ca_file => "$Bin/certs/clientca-cert.pem",
+ ) || die;
+ print "Please contact https client cert at: <URL:", $d->url, ">\n";
+ run_server( $d );
+ die "webserver stopped";
+ }
+ push @pids, $pid;
+}
+
+# give our webservers some time to startup
+sleep(3);
+
+# Run the same server on http and https
+sub run_server {
+ my $d = shift;
+ while (1) {
+ MAINLOOP: while (my $c = $d->accept) {
+ while (my $r = $c->get_request) {
+ if ($r->method eq "GET" and $r->url->path =~ m^/statuscode/(\d+)^) {
+ $c->send_basic_header($1);
+ $c->send_crlf;
+ } elsif ($r->method eq "GET" and $r->url->path =~ m^/file/(.*)^) {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_file_response("$Bin/var/$1");
+ } elsif ($r->method eq "GET" and $r->url->path eq "/slow") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ sleep 1;
+ $c->send_response("slow");
+ } elsif ($r->url->path eq "/method") {
+ if ($r->method eq "DELETE") {
+ $c->send_error(HTTP::Status->RC_METHOD_NOT_ALLOWED);
+ } elsif ($r->method eq "foo") {
+ $c->send_error(HTTP::Status->RC_NOT_IMPLEMENTED);
+ } else {
+ $c->send_status_line(200, $r->method);
+ }
+ } elsif ($r->url->path eq "/postdata") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response($r->method.":".$r->content);
+ } elsif ($r->url->path eq "/redirect") {
+ $c->send_redirect( "/redirect2" );
+ } elsif ($r->url->path eq "/redir_external") {
+ $c->send_redirect(($d->isa('HTTP::Daemon::SSL') ? "https" : "http") . "://169.254.169.254/redirect2" );
+ } elsif ($r->url->path eq "/redirect2") {
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, 'redirected' ));
+ } elsif ($r->url->path eq "/redir_timeout") {
+ $c->send_redirect( "/timeout" );
+ } elsif ($r->url->path eq "/timeout") {
+ # Keep $c from being destroyed, but prevent severe leaks
+ unshift @persist, $c;
+ delete($persist[1000]);
+ next MAINLOOP;
+ } elsif ($r->url->path eq "/header_check") {
+ $c->send_basic_header;
+ $c->send_header('foo');
+ $c->send_crlf;
+ } elsif ($r->url->path eq "/virtual_port") {
+ # return sent Host header
+ $c->send_basic_header;
+ $c->send_crlf;
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, $r->header ('Host')));
+ } elsif ($r->url->path eq "/chunked") {
+ my $chunks = ["chunked", "encoding", "test\n"];
+ $c->send_response(HTTP::Response->new( 200, 'OK', undef, sub {
+ my $chunk = shift @{$chunks};
+ return unless $chunk;
+ sleep(1);
+ return($chunk);
+ }));
+ } else {
+ $c->send_error(HTTP::Status->RC_FORBIDDEN);
+ }
+ $c->close;
+ }
+ }
+ }
+}
+
+sub run_hacked_http_server {
+ my $socket = shift;
+
+ # auto-flush on socket
+ $| = 1;
+
+
+ while(1)
+ {
+ # waiting for a new client connection
+ my $client_socket = $socket->accept();
+
+ # get information about a newly connected client
+ my $client_address = $client_socket->peerhost();
+ my $client_portn = $client_socket->peerport();
+ print "connection from $client_address:$client_portn";
+
+ # read up to 1024 characters from the connected client
+ my $data = "";
+ $client_socket->recv($data, 1024);
+ print "received data: $data";
+
+ # write response data to the connected client
+ $data = "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n";
+ $client_socket->send($data);
+
+ # notify client that response has been sent
+ shutdown($client_socket, 1);
+ }
+}
+
+END {
+ foreach my $pid (@pids) {
+ if ($pid) { print "Killing $pid\n"; kill "INT", $pid }
+ }
+};
+
+if ($ARGV[0] && $ARGV[0] eq "-d") {
+ while (1) {
+ sleep 100;
+ }
+}
+
+my $result;
+my $command = "./$plugin -H 127.0.0.1";
+
+run_chunked_encoding_special_test( {command => "$command -p $port_hacked_http"});
+run_common_tests( { command => "$command -p $port_http" } );
+SKIP: {
+ skip "HTTP::Daemon::SSL not installed", $common_tests + $ssl_only_tests if ! exists $servers->{https};
+ run_common_tests( { command => "$command -p $port_https", ssl => 1 } );
+
+ my $expiry = "Thu Nov 28 21:02:11 2030 +0000";
+
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 14" );
+ is( $result->return_code, 0, "$command -p $port_https -S -C 14" );
+ is( $result->output, "OK - Certificate 'Monitoring Plugins' will expire on $expiry.", "output ok" );
+
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 14000" );
+ is( $result->return_code, 1, "$command -p $port_https -S -C 14000" );
+ like( $result->output, '/WARNING - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
+
+ # Expired cert tests
+ $result = NPTest->testCmd( "$command -p $port_https -S -C 13960,14000" );
+ is( $result->return_code, 2, "$command -p $port_https -S -C 13960,14000" );
+ like( $result->output, '/CRITICAL - Certificate \'Monitoring Plugins\' expires in \d+ day\(s\) \(' . quotemeta($expiry) . '\)./', "output ok" );
+
+ $result = NPTest->testCmd( "$command -p $port_https_expired -S -C 7" );
+ is( $result->return_code, 2, "$command -p $port_https_expired -S -C 7" );
+ is( $result->output,
+ 'CRITICAL - Certificate \'Monitoring Plugins\' expired on Wed Jan 2 12:00:00 2008 +0000.',
+ "output ok" );
+
+ # client cert tests
+ my $cmd;
+ $cmd = "$command -p $port_https_clientcert"
+ . " -J \"$Bin/certs/client-cert.pem\""
+ . " -K \"$Bin/certs/client-key.pem\""
+ . " -u /statuscode/200";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -p $port_https_clientcert"
+ . " -J \"$Bin/certs/clientchain-cert.pem\""
+ . " -K \"$Bin/certs/clientchain-key.pem\""
+ . " -u /statuscode/200";
+ $result = NPTest->testCmd($cmd);
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+}
+
+my $cmd;
+# check virtual port behaviour
+#
+# http without virtual port
+$cmd = "$command -p $port_http -u /virtual_port -r ^127.0.0.1:$port_http\$";
+$result = NPTest->testCmd( $cmd );
+is( $result->return_code, 0, $cmd);
+like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+# http with virtual port
+$cmd = "$command:80 -p $port_http -u /virtual_port -r ^127.0.0.1\$";
+$result = NPTest->testCmd( $cmd );
+is( $result->return_code, 0, $cmd);
+like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+SKIP: {
+ skip "HTTP::Daemon::SSL not installed", 4 if ! exists $servers->{https};
+ # https without virtual port
+ $cmd = "$command -p $port_https --ssl -u /virtual_port -r ^127.0.0.1:$port_https\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # https with virtual port
+ $cmd = "$command:443 -p $port_https --ssl -u /virtual_port -r ^127.0.0.1\$";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+}
+
+
+sub run_common_tests {
+ my ($opts) = @_;
+ my $command = $opts->{command};
+ if ($opts->{ssl}) {
+ $command .= " --ssl";
+ }
+
+ $result = NPTest->testCmd( "$command -u /file/root" );
+ is( $result->return_code, 0, "/file/root");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 274 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /file/root -s Root" );
+ is( $result->return_code, 0, "/file/root search for string");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 274 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /file/root -s NonRoot" );
+ is( $result->return_code, 2, "Missing string check");
+ like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - string 'NonRoot' not found on 'https?://127\.0\.0\.1:\d+/file/root'%, "Shows search string and location");
+
+ $result = NPTest->testCmd( "$command -u /file/root -s NonRootWithOver30charsAndMoreFunThanAWetFish" );
+ is( $result->return_code, 2, "Missing string check");
+ like( $result->output, qr%HTTP CRITICAL: HTTP/1\.1 200 OK - string 'NonRootWithOver30charsAndM...' not found on 'https?://127\.0\.0\.1:\d+/file/root'%, "Shows search string and location");
+
+ $result = NPTest->testCmd( "$command -u /header_check -d foo" );
+ is( $result->return_code, 0, "header_check search for string");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 96 bytes in [\d\.]+ second/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u /header_check -d bar" );
+ is( $result->return_code, 2, "Missing header string check");
+ like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - header 'bar' not found on 'https?://127\.0\.0\.1:\d+/header_check'%, "Shows search string and location");
+
+ my $cmd;
+ $cmd = "$command -u /slow";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, "$cmd");
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+ $result->output =~ /in ([\d\.]+) second/;
+ cmp_ok( $1, ">", 1, "Time is > 1 second" );
+
+ $cmd = "$command -u /statuscode/200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/200 -e 200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: Status line output matched "200" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 201 Created - \d+ bytes in [\d\.]+ second /', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 201";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: Status line output matched "201" - \d+ bytes in [\d\.]+ second /', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 200";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL - Invalid HTTP response received from host on port \d+: HTTP/1.1 201 Created/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/200 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: Status line output matched "200,201,202" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/201 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: Status line output matched "200,201,202" - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /statuscode/203 -e 200,201,202";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL - Invalid HTTP response received from host on port (\d+): HTTP/1.1 203 Non-Authoritative Information/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j HEAD -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 HEAD - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j POST -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 POST - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j GET -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 GET - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 GET - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -P foo -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 POST - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j DELETE -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 1, $cmd);
+ like( $result->output, '/^HTTP WARNING: HTTP/1.1 405 Method Not Allowed/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j foo -u /method";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 2, $cmd);
+ like( $result->output, '/^HTTP CRITICAL: HTTP/1.1 501 Not Implemented/', "Output correct: ".$result->output );
+
+ $cmd = "$command -P stufftoinclude -u /postdata -s POST:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -j PUT -P stufftoinclude -u /postdata -s PUT:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # To confirm that the free doesn't segfault
+ $cmd = "$command -P stufftoinclude -j PUT -u /postdata -s PUT:stufftoinclude";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /redirect";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 301 Moved Permanently - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f follow -u /redirect";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 301 Moved Permanently - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f follow -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f sticky -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ $cmd = "$command -f stickyport -u /redirect -k 'follow: me'";
+ $result = NPTest->testCmd( $cmd );
+ is( $result->return_code, 0, $cmd);
+ like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - \d+ bytes in [\d\.]+ second/', "Output correct: ".$result->output );
+
+ # These tests may block
+ print "ALRM\n";
+
+ # stickyport - on full urlS port is set back to 80 otherwise
+ $cmd = "$command -f stickyport -u /redir_external -t 5 -s redirected";
+ alarm(2);
+ eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ $result = NPTest->testCmd( $cmd );
+ };
+ isnt( $@, "alarm\n", $cmd );
+ alarm(0);
+ is( $result->return_code, 0, $cmd );
+
+ # Let's hope there won't be any web server on :80 returning "redirected"!
+ $cmd = "$command -f sticky -u /redir_external -t 5 -s redirected";
+ alarm(2);
+ eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ $result = NPTest->testCmd( $cmd );
+ };
+ isnt( $@, "alarm\n", $cmd );
+ alarm(0);
+ isnt( $result->return_code, 0, $cmd );
+
+ # Test an external address - timeout
+ SKIP: {
+ skip "This doesn't seem to work all the time", 1 unless ($ENV{HTTP_EXTERNAL});
+ $cmd = "$command -f follow -u /redir_external -t 5";
+ eval {
+ $result = NPTest->testCmd( $cmd, 2 );
+ };
+ like( $@, "/timeout in command: $cmd/", $cmd );
+ }
+
+ $cmd = "$command -u /timeout -t 5";
+ eval {
+ $result = NPTest->testCmd( $cmd, 2 );
+ };
+ like( $@, "/timeout in command: $cmd/", $cmd );
+
+ $cmd = "$command -f follow -u /redir_timeout -t 2";
+ eval {
+ $result = NPTest->testCmd( $cmd, 5 );
+ };
+ is( $@, "", $cmd );
+
+ $cmd = "$command -u /chunked -s 'chunkedencodingtest' -d 'Transfer-Encoding: chunked'";
+ eval {
+ $result = NPTest->testCmd( $cmd, 5 );
+ };
+ is( $@, "", $cmd );
+}
+
+sub run_chunked_encoding_special_test {
+ my ($opts) = @_;
+ my $command = $opts->{command};
+
+ $cmd = "$command -u / -s 'ChunkedEncodingSpecialTest'";
+ eval {
+ $result = NPTest->testCmd( $cmd, 5 );
+ };
+ is( $@, "", $cmd );
+}
diff --git a/plugins/tests/check_nt.t b/plugins/tests/check_nt.t
new file mode 100755
index 0000000..223d493
--- /dev/null
+++ b/plugins/tests/check_nt.t
@@ -0,0 +1,80 @@
+#! /usr/bin/perl -w -I ..
+#
+# Test check_nt by having a stub check_nt daemon
+#
+
+use strict;
+use Test::More;
+use NPTest;
+use FindBin qw($Bin);
+
+use IO::Socket;
+use IO::Select;
+use POSIX;
+
+my $port = 50000 + int(rand(1000));
+
+my $pid = fork();
+if ($pid) {
+ # Parent
+ #print "parent\n";
+ # give our webserver some time to startup
+ sleep(1);
+} else {
+ # Child
+ #print "child\n";
+
+ my $server = IO::Socket::INET->new(
+ LocalPort => $port,
+ Type => SOCK_STREAM,
+ Reuse => 1,
+ Proto => "tcp",
+ Listen => 10,
+ ) or die "Cannot be a tcp server on port $port: $@";
+
+ $server->autoflush(1);
+
+ print "Please contact me at port $port\n";
+ while (my $client = $server->accept ) {
+ my $data = "";
+ my $rv = $client->recv($data, POSIX::BUFSIZ, 0);
+
+ my ($password, $command, $arg) = split('&', $data);
+
+ if ($command eq "4") {
+ if ($arg eq "c") {
+ print $client "930000000&1000000000";
+ } elsif ($arg eq "d") {
+ print $client "UNKNOWN: Drive is not a fixed drive";
+ }
+ }
+ }
+ exit;
+}
+
+END { if ($pid) { print "Killing $pid\n"; kill "INT", $pid } };
+
+if ($ARGV[0] && $ARGV[0] eq "-d") {
+ sleep 1000;
+}
+
+if (-x "./check_nt") {
+ plan tests => 5;
+} else {
+ plan skip_all => "No check_nt compiled";
+}
+
+my $result;
+my $command = "./check_nt -H 127.0.0.1 -p $port";
+
+$result = NPTest->testCmd( "$command -v USEDDISKSPACE -l c" );
+is( $result->return_code, 0, "USEDDISKSPACE c");
+is( $result->output, q{c:\ - total: 0.93 Gb - used: 0.07 Gb (7%) - free 0.87 Gb (93%) | 'c:\ Used Space'=0.07Gb;0.00;0.00;0.00;0.93}, "Output right" );
+
+$result = NPTest->testCmd( "$command -v USEDDISKSPACE -l d" );
+is( $result->return_code, 3, "USEDDISKSPACE d - invalid");
+is( $result->output, "Free disk space : Invalid drive", "Output right" );
+
+$result = NPTest->testCmd( "./check_nt -v USEDDISKSPACE -l d" );
+is( $result->return_code, 3, "Fail if -H missing");
+
diff --git a/plugins/tests/check_procs.t b/plugins/tests/check_procs.t
new file mode 100755
index 0000000..b3a0a30
--- /dev/null
+++ b/plugins/tests/check_procs.t
@@ -0,0 +1,148 @@
+#! /usr/bin/perl -w -I ..
+#
+# Test check_procs using input files
+#
+
+use strict;
+use Test::More;
+use NPTest;
+
+if (-x "./check_procs") {
+ plan tests => 54;
+} else {
+ plan skip_all => "No check_procs compiled";
+}
+
+my $result;
+my $command = "./check_procs --input-file=tests/var/ps-axwo.darwin";
+my $cmd_etime = "./check_procs --input-file=tests/var/ps-axwo.debian";
+
+$result = NPTest->testCmd( "$command" );
+is( $result->return_code, 0, "Run with no options" );
+is( $result->output, "PROCS OK: 95 processes | procs=95;;;0;", "Output correct" );
+
+$result = NPTest->testCmd( "$command -w 5" );
+is( $result->return_code, 1, "Checking > 5 processes" );
+is( $result->output, "PROCS WARNING: 95 processes | procs=95;5;;0;", "Output correct" );
+
+$result = NPTest->testCmd( "$command -w 4 -c 44" );
+is( $result->return_code, 2, "Checking critical" );
+is( $result->output, "PROCS CRITICAL: 95 processes | procs=95;4;44;0;", "Output correct" );
+
+$result = NPTest->testCmd( "$command -w 100 -c 200" );
+is( $result->return_code, 0, "Checking no threshold breeched" );
+is( $result->output, "PROCS OK: 95 processes | procs=95;100;200;0;", "Output correct" );
+
+$result = NPTest->testCmd( "$command -C launchd -c 5" );
+is( $result->return_code, 2, "Checking processes matched by command name" );
+is( $result->output, "PROCS CRITICAL: 6 processes with command name 'launchd' | procs=6;;5;0;", "Output correct" );
+
+$result = NPTest->testCmd( "$command -X bash -c 5" );
+is( $result->return_code, 2, "Checking processes excluded by command name" );
+is( $result->output, "PROCS CRITICAL: 95 processes with exclude progs 'bash' | procs=95;;5;0;", "Output correct" );
+
+SKIP: {
+ skip 'user with uid 501 required', 4 unless getpwuid(501);
+
+ $result = NPTest->testCmd( "$command -u 501 -w 39 -c 41" );
+ is( $result->return_code, 1, "Checking processes filtered by userid" );
+ like( $result->output, '/^PROCS WARNING: 40 processes with UID = 501 (.*)$/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -C launchd -u 501" );
+ is( $result->return_code, 0, "Checking processes filtered by command name and userid" );
+ like( $result->output, '/^PROCS OK: 1 process with command name \'launchd\', UID = 501 (.*)$/', "Output correct" );
+}
+
+SKIP: {
+ skip 'user with uid -2 required', 8 unless getpwuid(-2);
+ skip 'uid -2 must have name "nobody"', 8 unless getpwuid(-2) eq 'nobody';
+
+ $result = NPTest->testCmd( "$command -u -2 -w 2:2" );
+ is( $result->return_code, 1, "Checking processes with userid=-2" );
+ like( $result->output, '/^PROCS WARNING: 3 processes with UID = -2 \(nobody\)$/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u -2 -w 3:3" );
+ is( $result->return_code, 0, "Checking processes with userid=-2 past threshold" );
+ like( $result->output, '/^PROCS OK: 3 processes with UID = -2 \(nobody\)$/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u -2 -a usb" );
+ is( $result->return_code, 0, "Checking processes with userid=-2 and usb in arguments" );
+ like( $result->output, '/^PROCS OK: 1 process with UID = -2 \(nobody\), args \'usb\'/', "Output correct" );
+
+ $result = NPTest->testCmd( "$command -u -2 -a UsB" );
+ is( $result->return_code, 0, "Checking case sensitivity of args" );
+ like( $result->output, '/^PROCS OK: 0 processes with UID = -2 \(nobody\), args \'UsB\'/', "Output correct" );
+};
+
+SKIP: {
+ skip 'check_procs is compiled with etime format support', 2 if `$command -vvv` =~ m/etime/mx;
+
+ $result = NPTest->testCmd( "$command --ereg-argument-array='mdworker.*501'" );
+ is( $result->return_code, 0, "Checking regexp search of arguments" );
+ is( $result->output, "PROCS OK: 1 process with regex args 'mdworker.*501' | procs=1;;;0;", "Output correct" );
+}
+
+SKIP: {
+ skip 'check_procs is compiled without etime format support', 2 if `$cmd_etime -vvv` !~ m/etime/mx;
+
+ $result = NPTest->testCmd( "$cmd_etime -m ELAPSED -C apache2 -w 1000 -c 2000" );
+ is( $result->return_code, 2, "Checking elapsed time threshold" );
+ is( $result->output, "ELAPSED CRITICAL: 10 crit, 0 warn out of 10 processes with command name 'apache2' | procs=10;;;0; procs_warn=0;;;0; procs_crit=10;;;0;", "Output correct" );
+}
+
+$result = NPTest->testCmd( "$command --vsz 1000000" );
+is( $result->return_code, 0, "Checking filter by VSZ" );
+is( $result->output, 'PROCS OK: 24 processes with VSZ >= 1000000 | procs=24;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command --rss 100000" );
+is( $result->return_code, 0, "Checking filter by RSS" );
+is( $result->output, 'PROCS OK: 3 processes with RSS >= 100000 | procs=3;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command -s S" );
+is( $result->return_code, 0, "Checking filter for sleeping processes" );
+like( $result->output, '/^PROCS OK: 88 processes with STATE = S/', "Output correct" );
+
+$result = NPTest->testCmd( "$command -s Z" );
+is( $result->return_code, 0, "Checking filter for zombies" );
+like( $result->output, '/^PROCS OK: 1 process with STATE = Z/', "Output correct" );
+
+$result = NPTest->testCmd( "$command -p 1 -c 30" );
+is( $result->return_code, 2, "Checking filter for parent id = 1" );
+like( $result->output, '/^PROCS CRITICAL: 39 processes with PPID = 1/', "Output correct" );
+
+$result = NPTest->testCmd( "$command -P 0.71" );
+is( $result->return_code, 0, "Checking filter for percentage cpu > 0.71" );
+is( $result->output, 'PROCS OK: 7 processes with PCPU >= 0.71 | procs=7;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command -P 0.70" );
+is( $result->return_code, 0, "Checking filter for percentage cpu > 0.70" );
+is( $result->output, 'PROCS OK: 8 processes with PCPU >= 0.70 | procs=8;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command --metric=CPU -w 8" );
+is( $result->return_code, 1, "Checking against metric of CPU > 8" );
+is( $result->output, 'CPU WARNING: 1 warn out of 95 processes | procs=95;;;0; procs_warn=1;;;0; procs_crit=0;;;0;', "Output correct" );
+
+# TODO: Because of a conversion to int, if CPU is 1.45%, will not alert, but 2.01% will.
+SKIP: {
+ skip 'user with uid 501 required', 2 unless getpwuid(501);
+
+ $result = NPTest->testCmd( "$command --metric=CPU -w 1 -u 501 -v" );
+ is( $result->return_code, 1, "Checking against metric of CPU > 1 with uid=501 - TODO" );
+ is( $result->output, 'CPU WARNING: 2 warn out of 40 processes with UID = 501 (tonvoon) [Skype, PubSubAgent]', "Output correct" );
+};
+
+$result = NPTest->testCmd( "$command --metric=VSZ -w 1200000 -v" );
+is( $result->return_code, 1, "Checking against VSZ > 1.2GB" );
+is( $result->output, 'VSZ WARNING: 4 warn out of 95 processes [WindowServer, Safari, Mail, Skype] | procs=95;;;0; procs_warn=4;;;0; procs_crit=0;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command --metric=VSZ -w 1200000 -v" );
+is( $result->return_code, 1, "Checking against VSZ > 1.2GB" );
+is( $result->output, 'VSZ WARNING: 4 warn out of 95 processes [WindowServer, Safari, Mail, Skype] | procs=95;;;0; procs_warn=4;;;0; procs_crit=0;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command --metric=RSS -c 70000 -v" );
+is( $result->return_code, 2, "Checking against RSS > 70MB" );
+is( $result->output, 'RSS CRITICAL: 5 crit, 0 warn out of 95 processes [WindowServer, SystemUIServer, Safari, Mail, Safari] | procs=95;;;0; procs_warn=0;;;0; procs_crit=5;;;0;', "Output correct" );
+
+$result = NPTest->testCmd( "$command --ereg-argument-array='(nosuchname|nosuch2name)'" );
+is( $result->return_code, 0, "Checking no pipe symbol in output" );
+is( $result->output, "PROCS OK: 0 processes with regex args '(nosuchname,nosuch2name)' | procs=0;;;0;", "Output correct" );
diff --git a/plugins/tests/check_snmp.t b/plugins/tests/check_snmp.t
new file mode 100755
index 0000000..bfe42e1
--- /dev/null
+++ b/plugins/tests/check_snmp.t
@@ -0,0 +1,286 @@
+#! /usr/bin/perl -w -I ..
+#
+# Test check_snmp by having an actual SNMP agent running
+#
+
+use strict;
+use Test::More;
+use NPTest;
+use FindBin qw($Bin);
+use POSIX qw/strftime/;
+
+my $tests = 81;
+# Check that all dependent modules are available
+eval {
+ require NetSNMP::OID;
+ require NetSNMP::agent;
+ require NetSNMP::ASN;
+};
+
+if ($@) {
+ plan skip_all => "Missing required module for test: $@";
+} else {
+ if (-x "./check_snmp") {
+ # check if snmpd has perl support
+ my $test = `snmpd -c tests/conf/snmpd.conf -C -r -H 2>&1`;
+ if(!defined $test) {
+ plan skip_all => "snmpd required";
+ }
+ elsif($test =~ m/Warning: Unknown token: perl/) {
+ plan skip_all => "snmpd has no perl support";
+ } else {
+ plan tests => $tests;
+ }
+ } else {
+ plan skip_all => "No check_snmp compiled";
+ }
+}
+
+my $port_snmp = 16100 + int(rand(100));
+
+my $faketime = -x '/usr/bin/faketime' ? 1 : 0;
+
+# Start up server
+my @pids;
+my $pid = fork();
+if ($pid) {
+ # Parent
+ push @pids, $pid;
+ # give our agent some time to startup
+ sleep(1);
+} else {
+ # Child
+ #print "child\n";
+
+ print "Please contact SNMP at: $port_snmp\n";
+ close(STDERR); # Comment out to debug snmpd problems (most errors sent there are OK)
+ exec("snmpd -c tests/conf/snmpd.conf -C -f -r udp:$port_snmp");
+}
+
+END {
+ foreach my $pid (@pids) {
+ if ($pid) { print "Killing $pid\n"; kill "INT", $pid }
+ }
+};
+
+if ($ARGV[0] && $ARGV[0] eq "-d") {
+ while (1) {
+ sleep 100;
+ }
+}
+
+# We should merge that with $ENV{'NPTEST_CACHE'}, use one dir for all test data
+$ENV{'MP_STATE_PATH'} ||= "/var/tmp";
+
+my $res;
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.0");
+cmp_ok( $res->return_code, '==', 0, "Exit OK when querying a multi-line string" );
+like($res->output, '/^SNMP OK - /', "String contains SNMP OK");
+like($res->output, '/'.quotemeta('SNMP OK - Cisco Internetwork Operating System Software |
+.1.3.6.1.4.1.8072.3.2.67.0:
+"Cisco Internetwork Operating System Software
+IOS (tm) Catalyst 4000 \"L3\" Switch Software (cat4000-I9K91S-M), Version
+12.2(20)EWA, RELEASE SOFTWARE (fc1)
+Technical Support: http://www.cisco.com/techsupport
+Copyright (c) 1986-2004 by cisco Systems, Inc.
+"').'/m', "String contains all lines");
+
+# sysContact.0 is "Alice" (from our snmpd.conf)
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.0 -o sysContact.0 -o .1.3.6.1.4.1.8072.3.2.67.1");
+cmp_ok( $res->return_code, '==', 0, "Exit OK when querying multi-line OIDs" );
+like($res->output, '/^SNMP OK - /', "String contains SNMP OK");
+like($res->output, '/'.quotemeta('SNMP OK - Cisco Internetwork Operating System Software ').'"?Alice"?'.quotemeta(' Kisco Outernetwork Oserating Gystem Totware |
+.1.3.6.1.4.1.8072.3.2.67.0:
+"Cisco Internetwork Operating System Software
+IOS (tm) Catalyst 4000 \"L3\" Switch Software (cat4000-I9K91S-M), Version
+12.2(20)EWA, RELEASE SOFTWARE (fc1)
+Technical Support: http://www.cisco.com/techsupport
+Copyright (c) 1986-2004 by cisco Systems, Inc.
+"
+.1.3.6.1.4.1.8072.3.2.67.1:
+"Kisco Outernetwork Oserating Gystem Totware
+Copyleft (c) 2400-2689 by kisco Systrems, Inc."').'/m', "String contains all lines with multiple OIDs");
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.2");
+like($res->output, '/'.quotemeta('SNMP OK - This should not confuse check_snmp \"parser\" |
+.1.3.6.1.4.1.8072.3.2.67.2:
+"This should not confuse check_snmp \"parser\"
+into thinking there is no 2nd line"').'/m', "Attempt to confuse parser No.1");
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.3");
+like($res->output, '/'.quotemeta('SNMP OK - It\'s getting even harder if the line |
+.1.3.6.1.4.1.8072.3.2.67.3:
+"It\'s getting even harder if the line
+ends with with this: C:\\\\"').'/m', "Attempt to confuse parser No.2");
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.4");
+like($res->output, '/'.quotemeta('SNMP OK - And now have fun with with this: \"C:\\\\\" |
+.1.3.6.1.4.1.8072.3.2.67.4:
+"And now have fun with with this: \"C:\\\\\"
+because we\'re not done yet!"').'/m', "Attempt to confuse parser No.3");
+
+system("rm -f ".$ENV{'MP_STATE_PATH'}."/*/check_snmp/*");
+
+# run rate checks with faketime. rate checks depend on the exact amount of time spend between the
+# plugin runs which may fail on busy machines.
+# using faketime removes this race condition and also saves all the sleeps in between.
+SKIP: {
+ skip "No faketime binary found", 28 if !$faketime;
+
+ my $ts = time();
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" );
+ is($res->return_code, 0, "Returns OK");
+ is($res->output, "No previous data to calculate rate - assume okay");
+
+ # test rate 1 second later
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" );
+ is($res->return_code, 1, "WARNING - due to going above rate calculation" );
+ is($res->output, "SNMP RATE WARNING - *666* | iso.3.6.1.4.1.8072.3.2.67.10=666;600 ");
+
+ # test rate with same time
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -w 600" );
+ is($res->return_code, 3, "UNKNOWN - basically the divide by zero error" );
+ is($res->output, "Time duration between plugin calls is invalid");
+
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" );
+ is($res->return_code, 0, "OK for first call" );
+ is($res->output, "No previous data to calculate rate - assume okay" );
+
+ # test rate 1 second later
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP RATE OK - inoctets 666 | inoctets=666 ", "Check label");
+
+ # test rate 3 seconds later
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+3))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP RATE OK - inoctets 333 | inoctets=333 ", "Check rate decreases due to longer interval");
+
+
+ # label performance data check
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - test 67996 | test=67996c ", "Check label");
+
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l \"test'test\"" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - test'test 68662 | \"test'test\"=68662c ", "Check label");
+
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test\"test'" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - test\"test 69328 | 'test\"test'=69328c ", "Check label");
+
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l test -O" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - test 69994 | iso.3.6.1.4.1.8072.3.2.67.10=69994c ", "Check label");
+
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - 70660 | iso.3.6.1.4.1.8072.3.2.67.10=70660c ", "Check label");
+
+ $res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 -l 'test test'" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP OK - test test 71326 | 'test test'=71326c ", "Check label");
+
+
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" );
+ is($res->return_code, 0, "OK for first call" );
+ is($res->output, "No previous data to calculate rate - assume okay" );
+
+ # test 1 second later
+ $res = NPTest->testCmd("LC_TIME=C TZ=UTC faketime -f '".strftime("%Y-%m-%d %H:%M:%S", localtime($ts+1))."' ./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10 --rate -l inoctets_per_minute --rate-multiplier=60" );
+ is($res->return_code, 0, "OK as no thresholds" );
+ is($res->output, "SNMP RATE OK - inoctets_per_minute 39960 | inoctets_per_minute=39960 ", "Checking multiplier");
+};
+
+
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.11 -s '\"stringtests\"'" );
+is($res->return_code, 0, "OK as string matches" );
+is($res->output, 'SNMP OK - "stringtests" | ', "Good string match" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.11 -s ring" );
+is($res->return_code, 2, "CRITICAL as string doesn't match (though is a substring)" );
+is($res->output, 'SNMP CRITICAL - *"stringtests"* | ', "Failed string match" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.11 --invert-search -s '\"stringtests\"'" );
+is($res->return_code, 2, "CRITICAL as string matches but inverted" );
+is($res->output, 'SNMP CRITICAL - *"stringtests"* | ', "Inverted string match" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.11 --invert-search -s ring" );
+is($res->return_code, 0, "OK as string doesn't match but inverted" );
+is($res->output, 'SNMP OK - "stringtests" | ', "OK as inverted string no match" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.12 -w 4:5" );
+is($res->return_code, 1, "Numeric in string test" );
+is($res->output, 'SNMP WARNING - *3.5* | iso.3.6.1.4.1.8072.3.2.67.12=3.5;4:5 ', "WARNING threshold checks for string masquerading as number" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.13" );
+is($res->return_code, 0, "Not really numeric test" );
+is($res->output, 'SNMP OK - "87.4startswithnumberbutshouldbestring" | ', "Check string with numeric start is still string" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.14" );
+is($res->return_code, 0, "Not really numeric test (trying best to fool it)" );
+is($res->output, 'SNMP OK - "555\"I said\"" | ', "Check string with a double quote following is still a string (looks like the perl routine will always escape though)" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.15 -r 'CUSTOM CHECK OK'" );
+is($res->return_code, 0, "String check should check whole string, not a parsed number" );
+is($res->output, 'SNMP OK - "CUSTOM CHECK OK: foo is 12345" | ', "String check with numbers returns whole string");
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.16 -w -2: -c -3:" );
+is($res->return_code, 0, "Negative integer check OK" );
+is($res->output, 'SNMP OK - -2 | iso.3.6.1.4.1.8072.3.2.67.16=-2;-2:;-3: ', "Negative integer check OK output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.16 -w -2: -c -3:" );
+is($res->return_code, 1, "Negative integer check WARNING" );
+is($res->output, 'SNMP WARNING - *-3* | iso.3.6.1.4.1.8072.3.2.67.16=-3;-2:;-3: ', "Negative integer check WARNING output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.16 -w -2: -c -3:" );
+is($res->return_code, 2, "Negative integer check CRITICAL" );
+is($res->output, 'SNMP CRITICAL - *-4* | iso.3.6.1.4.1.8072.3.2.67.16=-4;-2:;-3: ', "Negative integer check CRITICAL output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.17 -w -3: -c -6:" );
+is($res->return_code, 1, "Negative integer as string, WARNING" );
+is($res->output, 'SNMP WARNING - *-4* | iso.3.6.1.4.1.8072.3.2.67.17=-4;-3:;-6: ', "Negative integer as string, WARNING output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.17 -w -2: -c -3:" );
+is($res->return_code, 2, "Negative integer as string, CRITICAL" );
+is($res->output, 'SNMP CRITICAL - *-4* | iso.3.6.1.4.1.8072.3.2.67.17=-4;-2:;-3: ', "Negative integer as string, CRITICAL output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.18 -c '~:-6.5'" );
+is($res->return_code, 0, "Negative float OK" );
+is($res->output, 'SNMP OK - -6.6 | iso.3.6.1.4.1.8072.3.2.67.18=-6.6;;@-6.5:~ ', "Negative float OK output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.18 -w '~:-6.65' -c '~:-6.55'" );
+is($res->return_code, 1, "Negative float WARNING" );
+is($res->output, 'SNMP WARNING - *-6.6* | iso.3.6.1.4.1.8072.3.2.67.18=-6.6;@-6.65:~;@-6.55:~ ', "Negative float WARNING output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10,.1.3.6.1.4.1.8072.3.2.67.17 -w '1:100000,-10:20' -c '2:200000,-20:30'" );
+is($res->return_code, 0, "Multiple OIDs with thresholds" );
+like($res->output, '/SNMP OK - \d+ -4 | iso.3.6.1.4.1.8072.3.2.67.10=\d+c;1:100000;2:200000 iso.3.6.1.4.1.8072.3.2.67.17=-4;-10:20;-20:30/', "Multiple OIDs with thresholds output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10,.1.3.6.1.4.1.8072.3.2.67.17 -w '1:100000,-1:2' -c '2:200000,-20:30'" );
+is($res->return_code, 1, "Multiple OIDs with thresholds" );
+like($res->output, '/SNMP WARNING - \d+ \*-4\* | iso.3.6.1.4.1.8072.3.2.67.10=\d+c;1:100000;2:200000 iso.3.6.1.4.1.8072.3.2.67.17=-4;-10:20;-20:30/', "Multiple OIDs with thresholds output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.10,.1.3.6.1.4.1.8072.3.2.67.17 -w 1,2 -c 1" );
+is($res->return_code, 2, "Multiple OIDs with some thresholds" );
+like($res->output, '/SNMP CRITICAL - \*\d+\* \*-4\* | iso.3.6.1.4.1.8072.3.2.67.10=\d+c;1;2 iso.3.6.1.4.1.8072.3.2.67.17=-4;;/', "Multiple OIDs with thresholds output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19");
+is($res->return_code, 0, "Test plain .1.3.6.1.4.1.8072.3.2.67.6 RC" );
+is($res->output,'SNMP OK - 42 | iso.3.6.1.4.1.8072.3.2.67.19=42 ', "Test plain value of .1.3.6.1.4.1.8072.3.2.67.1" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 -M .1");
+is($res->return_code, 0, "Test multiply RC" );
+is($res->output,'SNMP OK - 4.200000 | iso.3.6.1.4.1.8072.3.2.67.19=4.200000 ' , "Test multiply .1 output" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 --multiplier=.1 -f '%.2f' ");
+is($res->return_code, 0, "Test multiply RC + format" );
+is($res->output, 'SNMP OK - 4.20 | iso.3.6.1.4.1.8072.3.2.67.19=4.20 ', "Test multiply .1 output + format" );
+
+$res = NPTest->testCmd( "./check_snmp -H 127.0.0.1 -C public -p $port_snmp -o .1.3.6.1.4.1.8072.3.2.67.19 --multiplier=.1 -f '%.2f' -w 1");
+is($res->return_code, 1, "Test multiply RC + format + thresholds" );
+is($res->output, 'SNMP WARNING - *4.20* | iso.3.6.1.4.1.8072.3.2.67.19=4.20;1 ', "Test multiply .1 output + format + thresholds" );
diff --git a/plugins/tests/check_snmp_agent.pl b/plugins/tests/check_snmp_agent.pl
new file mode 100644
index 0000000..38912e9
--- /dev/null
+++ b/plugins/tests/check_snmp_agent.pl
@@ -0,0 +1,111 @@
+#! /usr/bin/perl -w -I ..
+#
+# Subagent for testing check_snmp
+#
+
+#use strict; # Doesn't work
+use NetSNMP::OID qw(:all);
+use NetSNMP::agent;
+use NetSNMP::ASN qw(ASN_OCTET_STR ASN_COUNTER ASN_COUNTER64 ASN_INTEGER ASN_INTEGER64 ASN_UNSIGNED ASN_UNSIGNED64);
+#use Math::Int64 qw(uint64); # Skip that module while we don't need it
+sub uint64 { return $_ }
+
+if (!$agent) {
+ print "This program must run as an embedded NetSNMP agent\n";
+ exit 1;
+}
+
+my $baseoid = '.1.3.6.1.4.1.8072.3.2.67';
+my $multiline = 'Cisco Internetwork Operating System Software
+IOS (tm) Catalyst 4000 "L3" Switch Software (cat4000-I9K91S-M), Version
+12.2(20)EWA, RELEASE SOFTWARE (fc1)
+Technical Support: http://www.cisco.com/techsupport
+Copyright (c) 1986-2004 by cisco Systems, Inc.
+';
+my $multilin2 = "Kisco Outernetwork Oserating Gystem Totware
+Copyleft (c) 2400-2689 by kisco Systrems, Inc.";
+my $multilin3 = 'This should not confuse check_snmp "parser"
+into thinking there is no 2nd line';
+my $multilin4 = 'It\'s getting even harder if the line
+ends with with this: C:\\';
+my $multilin5 = 'And now have fun with with this: "C:\\"
+because we\'re not done yet!';
+
+# Next are arrays of indexes (Type, initial value and increments)
+# 0..19 <---- please update comment when adding/removing fields
+my @fields = (ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_UNSIGNED, ASN_UNSIGNED, ASN_COUNTER, ASN_COUNTER64, ASN_UNSIGNED, ASN_COUNTER, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_OCTET_STR, ASN_INTEGER, ASN_OCTET_STR, ASN_OCTET_STR, ASN_INTEGER );
+my @values = ($multiline, $multilin2, $multilin3, $multilin4, $multilin5, 4294965296, 1000, 4294965296, uint64("18446744073709351616"), int(rand(2**32)), 64000, "stringtests", "3.5", "87.4startswithnumberbutshouldbestring", '555"I said"', 'CUSTOM CHECK OK: foo is 12345', -2, '-4', '-6.6', 42 );
+# undef increments are randomized
+my @incrts = (undef, undef, undef, undef, undef, 1000, -500, 1000, 100000, undef, 666, undef, undef, undef, undef, undef, -1, undef, undef, 0 );
+
+# Number of elements in our OID
+my $oidelts;
+{
+ my @oid = split(/\./, $baseoid);
+ $oidelts = scalar(@oid);
+}
+
+my $regoid = new NetSNMP::OID($baseoid);
+$agent->register('check_snmp_agent', $regoid, \&my_snmp_handler);
+
+sub my_snmp_handler {
+ my ($handler, $registration_info, $request_info, $requests) = @_;
+
+ for (my $request = $requests; $request; $request = $request->next) {
+ my $oid = $request->getOID();
+ my $index;
+ my $next_index;
+
+ # Validate the OID
+ my @numarray = $oid->to_array();
+ if (@numarray != $oidelts) {
+ if ($request_info->getMode() == MODE_GETNEXT && @numarray == ($oidelts - 1)) {
+ # GETNEXT for the base oid; set it to the first index
+ push(@numarray, 0);
+ $next_index = 0;
+ } else {
+ # We got a request for the base OID or with extra elements
+ $request->setError($request_info, SNMP_ERR_NOERROR);
+ next;
+ }
+ }
+
+ $index = pop(@numarray);
+ if ($index >= scalar(@fields)) {
+ # Index is out of bounds
+ $request->setError($request_info, SNMP_ERR_NOERROR);
+ next;
+ }
+
+ # Handle the request
+ if ($request_info->getMode() == MODE_GETNEXT) {
+ if (++$index >= scalar(@fields)) {
+ # Index will grow out of bounds
+ $request->setError($request_info, SNMP_ERR_NOERROR);
+ next;
+ }
+ $index = (defined($next_index) ? $next_index : $index);
+ $request->setOID("$baseoid.$index");
+ } elsif ($request_info->getMode() != MODE_GET) {
+ # Everything else is write-related modes
+ $request->setError($request_info, SNMP_ERR_READONLY);
+ next;
+ }
+
+ # Set the response... setValue is a bit touchy about the data type, but accepts plain strings.
+ my $value = sprintf("%s", $values[$index]);
+ $request->setValue($fields[$index], $value);
+
+ # And update the value
+ if (defined($incrts[$index])) {
+ $values[$index] += $incrts[$index];
+ } elsif ($fields[$index] != ASN_OCTET_STR) {
+ my $minus = int(rand(2))*-1;
+ $minus = 1 unless ($minus);
+ my $exp = 32;
+ $exp = 64 if ($fields[$index] == ASN_COUNTER64 || $fields[$index] == ASN_INTEGER64 || $fields[$index] == ASN_UNSIGNED64);
+ $values[$index] = int(rand(2**$exp));
+ }
+ }
+}
+
diff --git a/plugins/tests/conf/snmpd.conf b/plugins/tests/conf/snmpd.conf
new file mode 100644
index 0000000..eff5b0b
--- /dev/null
+++ b/plugins/tests/conf/snmpd.conf
@@ -0,0 +1,23 @@
+###############################################################################
+# Access Control
+###############################################################################
+
+com2sec readonly localhost public
+
+group MyROGroup v1 readonly
+group MyROGroup v2c readonly
+
+view all included .1 80
+
+access MyROGroup "" any noauth exact all none none
+
+syslocation Wonderland
+syscontact Alice
+
+
+###############################################################################
+# Embedded Subagents
+###############################################################################
+
+perl do "tests/check_snmp_agent.pl";
+
diff --git a/plugins/tests/var/ps-axwo.darwin b/plugins/tests/var/ps-axwo.darwin
new file mode 100644
index 0000000..b71d834
--- /dev/null
+++ b/plugins/tests/var/ps-axwo.darwin
@@ -0,0 +1,96 @@
+STAT UID PID PPID VSZ RSS %CPU UCOMM COMMAND
+Ss 0 1 0 603456 976 0.0 launchd /sbin/launchd
+Ss 0 10 1 612820 3608 0.0 kextd /usr/libexec/kextd
+Ss 0 11 1 632980 8680 0.0 DirectoryService /usr/sbin/DirectoryService
+Ss 0 12 1 602832 720 0.0 notifyd /usr/sbin/notifyd
+Ss 0 13 1 603916 1136 0.0 syslogd /usr/sbin/syslogd
+Ss 0 14 1 614928 4928 0.0 configd /usr/sbin/configd
+Ss 65 15 1 615496 5616 0.0 mDNSResponder /usr/sbin/mDNSResponder -launchd
+Ss 1 16 1 608960 2212 0.0 distnoted /usr/sbin/distnoted
+Ss 65 18 1 602432 504 0.0 launchd /sbin/launchd
+Ss 0 20 1 614836 5844 0.3 securityd /usr/sbin/securityd -i
+Ss 0 24 1 610536 2704 0.0 ntpd /usr/sbin/ntpd -n -g -p /var/run/ntpd.pid -f /var/db/ntp.drift
+Ss 0 25 1 602228 496 0.0 update /usr/sbin/update
+Ss 0 26 1 609900 2320 0.0 SystemStarter /sbin/SystemStarter
+Ss 0 30 1 834352 36264 0.3 mds /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Support/mds
+Ss 501 31 1 1110572 23948 0.0 loginwindow /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow console
+Ss 0 32 1 609448 2616 0.0 KernelEventAgent /usr/sbin/KernelEventAgent
+Ss 0 34 1 609892 2204 0.0 hidd /usr/libexec/hidd
+Ss 0 35 1 624704 4284 0.0 fseventsd /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/Support/fseventsd
+Ss 0 36 1 610256 2876 0.0 dynamic_pager /sbin/dynamic_pager -F /private/var/vm/swapfile
+Ss 0 39 1 613408 4140 0.0 diskarbitrationd /usr/sbin/diskarbitrationd
+Ss 0 43 1 665708 8024 0.0 blued /usr/sbin/blued
+Ss 0 44 1 609408 2828 0.0 autofsd autofsd
+Ss 0 45 1 654084 9600 0.0 socketfilterfw /usr/libexec/ApplicationFirewall/socketfilterfw
+Ss 0 46 1 704764 12788 0.0 ccc_helper /Applications/Carbon Copy Cloner.app/Contents/Resources/ccc_helper.app/Contents/MacOS/ccc_helper 3231BC22-F30F-45D8-BDE8-47A098D57ABD
+Ss 0 54 1 667956 19212 0.0 coreservicesd /System/Library/CoreServices/coreservicesd
+Ss 88 56 1 1205840 85700 1.6 WindowServer /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Resources/WindowServer -daemon
+Ss 0 67 1 602992 612 0.0 llipd /Library/StartupItems/ParallelsTransporter/llipd
+S 0 83 1 613352 2312 0.0 pvsnatd /Library/StartupItems/Parallels/pvsnatd
+Ss 0 94 1 712036 15056 0.0 coreaudiod /usr/sbin/coreaudiod
+Ss 501 102 1 602432 1040 0.0 launchd /sbin/launchd
+S 501 109 102 1176668 28068 0.0 Spotlight /System/Library/CoreServices/Spotlight.app/Contents/MacOS/Spotlight
+S 501 110 102 941796 10988 0.0 UserEventAgent /usr/sbin/UserEventAgent -l Aqua
+S 501 112 102 610028 2056 0.0 pboard /usr/sbin/pboard
+S 501 114 102 1090056 29196 1.3 Dock /System/Library/CoreServices/Dock.app/Contents/MacOS/Dock -psn_0_24582
+S 501 115 102 685360 14048 0.0 ATSServer /System/Library/Frameworks/ApplicationServices.framework/Frameworks/ATS.framework/Support/ATSServer
+S 501 117 102 1121904 94432 0.1 SystemUIServer /System/Library/CoreServices/SystemUIServer.app/Contents/MacOS/SystemUIServer -psn_0_32776
+S 501 118 102 1110388 42064 1.4 Finder /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder -psn_0_36873
+S 501 123 102 718264 34752 0.0 FileSyncAgent /System/Library/CoreServices/FileSyncAgent.app/Contents/MacOS/FileSyncAgent -launchedByLaunchd
+S 501 127 102 1048388 25344 0.0 smcFanControl /Applications/smcFanControl.app/Contents/MacOS/smcFanControl -psn_0_53261
+S 501 128 102 970912 12924 0.0 iTunesHelper /Applications/iTunes.app/Contents/Resources/iTunesHelper.app/Contents/MacOS/iTunesHelper -psn_0_57358
+S 501 129 102 1095920 23364 1.4 Activity Monitor /Applications/Utilities/Activity Monitor.app/Contents/MacOS/Activity Monitor -psn_0_61455
+S 501 132 102 657212 8356 0.0 dmnotifyd /System/Library/PrivateFrameworks/DMNotification.framework/Versions/Current/Resources/dmnotifyd
+Ss -2 133 1 610464 2328 0.0 usbmuxd /System/Library/PrivateFrameworks/MobileDevice.framework/Versions/A/Resources/usbmuxd -launchd
+Ss 0 136 129 637456 6340 10.6 pmTool /Applications/Utilities/Activity Monitor.app/Contents/Resources/pmTool
+Ss 501 142 1 676652 8984 0.1 diskimages-helpe /System/Library/PrivateFrameworks/DiskImages.framework/Resources/diskimages-helper -uuid F2225770-5EFF-467C-91FD-C990F056B22F -post-exec
+Ss 0 147 1 627640 5928 0.0 hdiejectd /System/Library/PrivateFrameworks/DiskImages.framework/Resources/hdiejectd
+S 501 157 102 1045492 27480 0.0 GrowlHelperApp /Library/PreferencePanes/Growl.prefPane/Contents/Resources/GrowlHelperApp.app/Contents/MacOS/GrowlHelperApp -psn_0_81940
+U 501 158 102 1878012 388136 0.7 Safari /Applications/Safari.app/Contents/MacOS/Safari -psn_0_86037
+S 501 172 102 645560 11344 0.0 AppleSpell /System/Library/Services/AppleSpell.service/Contents/MacOS/AppleSpell -psn_0_98328
+S 501 175 102 1055412 33396 0.0 Terminal /Applications/Utilities/Terminal.app/Contents/MacOS/Terminal -psn_0_102425
+Z 501 186 158 0 0 0.0 Meeting Manager (Meeting Manager)
+S 501 214 102 616988 3808 0.0 ssh-agent /usr/bin/ssh-agent -l
+Ss 502 217 1 602432 1016 0.0 launchd /sbin/launchd
+S 501 499 102 1313808 130396 0.3 Mail /Applications/Mail.app/Contents/MacOS/Mail -psn_0_180268
+S 501 502 102 1091652 52168 0.0 NetNewsWire Lite /Applications/NetNewsWire Lite.app/Contents/MacOS/NetNewsWire Lite -psn_0_184365
+Ss 502 572 56 818908 20988 0.0 loginwindow /System/Library/CoreServices/loginwindow.app/Contents/MacOS/loginwindow
+S 502 585 217 741824 19056 0.0 Spotlight /System/Library/CoreServices/Spotlight.app/Contents/MacOS/Spotlight
+S 502 586 217 941900 11044 0.0 UserEventAgent /usr/sbin/UserEventAgent -l Aqua
+S 502 588 217 757320 18080 0.0 Dock /System/Library/CoreServices/Dock.app/Contents/MacOS/Dock -psn_0_237626
+S 502 590 217 610072 2068 0.0 pboard /usr/sbin/pboard
+S 502 592 217 794140 25456 0.0 SystemUIServer /System/Library/CoreServices/SystemUIServer.app/Contents/MacOS/SystemUIServer -psn_0_245820
+S 502 593 217 845552 30596 0.0 Finder /System/Library/CoreServices/Finder.app/Contents/MacOS/Finder -psn_0_249917
+S 502 594 217 671780 7872 0.0 ATSServer /System/Library/Frameworks/ApplicationServices.framework/Frameworks/ATS.framework/Support/ATSServer
+U 502 605 217 938844 64964 0.0 Pages /Applications/iWork '08/Pages.app/Contents/MacOS/Pages -psn_0_266305
+S 502 609 217 644432 10828 0.0 AppleSpell /System/Library/Services/AppleSpell.service/Contents/MacOS/AppleSpell -psn_0_270402
+S 502 610 217 638552 5216 0.0 AppleSpell /System/Library/Services/AppleSpell.service/Contents/MacOS/AppleSpell -psn_0_274499
+U 502 710 217 1029148 223312 0.0 Safari /Applications/Safari.app/Contents/MacOS/Safari -psn_0_331857
+S 502 712 217 904056 62928 0.3 Mail /Applications/Mail.app/Contents/MacOS/Mail -psn_0_335954
+U 501 998 102 1068272 26532 0.0 Address Book /Applications/Address Book.app/Contents/MacOS/Address Book -psn_0_417894
+S 502 2228 217 820940 30600 0.0 TextEdit /Applications/TextEdit.app/Contents/MacOS/TextEdit -psn_0_729266
+S 501 2431 102 1067868 43492 0.0 iCal /Applications/iCal.app/Contents/MacOS/iCal -psn_0_803012
+S 501 2531 102 1250108 68792 2.4 Skype /Applications/Skype.app/Contents/MacOS/Skype -psn_0_823497
+Ss 92 3143 1 602432 828 0.0 launchd /sbin/launchd
+S 501 3491 102 1048620 31256 0.0 TextEdit /Applications/TextEdit.app/Contents/MacOS/TextEdit -psn_0_962795
+S 501 3536 102 1073340 30524 0.0 Preview /Applications/Preview.app/Contents/MacOS/Preview -psn_0_983280
+S 501 4045 102 1041544 29168 0.0 PasswordWallet /Applications/PasswordWallet.app/Contents/MacOS/PasswordWallet -psn_0_1138966
+S 501 4892 114 1064948 43488 0.0 DashboardClient /System/Library/CoreServices/Dock.app/Contents/Resources/DashboardClient.app/Contents/MacOS/DashboardClient
+S 501 6806 102 1163836 67356 0.0 Colloquy /Applications/Colloquy.app/Contents/MacOS/Colloquy -psn_0_2220574
+U 501 6969 102 1156804 58764 0.0 Adium /Applications/Adium.app/Contents/MacOS/Adium -psn_0_2294320
+S 501 7530 102 671612 17440 0.0 helpdatad /System/Library/PrivateFrameworks/HelpData.framework/Versions/A/Resources/helpdatad
+Ss -2 38255 1 602432 952 0.0 launchd /sbin/launchd
+S 501 40569 102 1160664 49484 0.0 Dictionary /Applications/Dictionary.app/Contents/MacOS/Dictionary -psn_0_4387887
+SNs 501 42683 1 744096 21084 0.0 mdworker /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker MDSImporterWorker com.apple.Spotlight.ImporterWorker.501
+S 501 62225 102 711004 18040 0.0 SyncServer /System/Library/Frameworks/SyncServices.framework/Versions/Current/Resources/SyncServer.app/Contents/MacOS/SyncServer
+SNs -2 62284 1 671812 10880 0.0 mdworker /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker MDSImporterWorker com.apple.Spotlight.ImporterWorker.-2
+Ss 0 62285 1 617056 5472 0.0 cupsd /usr/sbin/cupsd -l
+S 502 62287 217 632360 10044 0.0 PubSubAgent /System/Library/Frameworks/PubSub.framework/Versions/A/Resources/PubSubAgent.app/Contents/MacOS/PubSubAgent
+SNs 502 62288 1 668876 10440 0.0 mdworker /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker MDSImporterWorker com.apple.Spotlight.ImporterWorker.502
+S 501 62296 102 643688 11980 2.2 PubSubAgent /System/Library/Frameworks/PubSub.framework/Versions/A/Resources/PubSubAgent.app/Contents/MacOS/PubSubAgent
+Ss 0 4558 175 630816 6960 0.0 login login -pf tonvoon
+S 501 4559 4558 603600 1736 0.0 bash -bash
+R+ 0 62297 4559 602388 852 0.0 ps /bin/ps -axwo stat
+Ss 0 7301 175 630816 6960 0.0 login login -pf tonvoon
+S 501 7302 7301 603600 1584 0.0 bash -bash
+S+ 501 41381 7302 615408 4196 0.0 ssh ssh dev.net.altinity
diff --git a/plugins/tests/var/ps-axwo.debian b/plugins/tests/var/ps-axwo.debian
new file mode 100644
index 0000000..5889e9a
--- /dev/null
+++ b/plugins/tests/var/ps-axwo.debian
@@ -0,0 +1,219 @@
+STAT UID PID PPID VSZ RSS %CPU ELAPSED COMMAND COMMAND
+Ss 0 1 0 167244 7144 0.1 26-03:07:26 systemd /lib/systemd/systemd --system --deserialize 17
+S 0 2 0 0 0 0.0 26-03:07:26 kthreadd [kthreadd]
+I< 0 3 2 0 0 0.0 26-03:07:26 rcu_gp [rcu_gp]
+I< 0 4 2 0 0 0.0 26-03:07:26 rcu_par_gp [rcu_par_gp]
+I< 0 6 2 0 0 0.0 26-03:07:26 kworker/0:0H-ev [kworker/0:0H-events_highpri]
+I< 0 9 2 0 0 0.0 26-03:07:26 mm_percpu_wq [mm_percpu_wq]
+S 0 10 2 0 0 0.0 26-03:07:26 rcu_tasks_rude_ [rcu_tasks_rude_]
+S 0 11 2 0 0 0.0 26-03:07:26 rcu_tasks_trace [rcu_tasks_trace]
+S 0 12 2 0 0 0.0 26-03:07:26 ksoftirqd/0 [ksoftirqd/0]
+I 0 13 2 0 0 0.0 26-03:07:26 rcu_sched [rcu_sched]
+S 0 14 2 0 0 0.0 26-03:07:26 migration/0 [migration/0]
+S 0 15 2 0 0 0.0 26-03:07:26 cpuhp/0 [cpuhp/0]
+S 0 16 2 0 0 0.0 26-03:07:26 cpuhp/1 [cpuhp/1]
+S 0 17 2 0 0 0.0 26-03:07:26 migration/1 [migration/1]
+S 0 18 2 0 0 0.0 26-03:07:26 ksoftirqd/1 [ksoftirqd/1]
+I< 0 20 2 0 0 0.0 26-03:07:26 kworker/1:0H-ev [kworker/1:0H-events_highpri]
+S 0 21 2 0 0 0.0 26-03:07:26 cpuhp/2 [cpuhp/2]
+S 0 22 2 0 0 0.0 26-03:07:26 migration/2 [migration/2]
+S 0 23 2 0 0 0.0 26-03:07:26 ksoftirqd/2 [ksoftirqd/2]
+I< 0 25 2 0 0 0.0 26-03:07:26 kworker/2:0H-ev [kworker/2:0H-events_highpri]
+S 0 26 2 0 0 0.0 26-03:07:26 cpuhp/3 [cpuhp/3]
+S 0 27 2 0 0 0.0 26-03:07:26 migration/3 [migration/3]
+S 0 28 2 0 0 0.0 26-03:07:26 ksoftirqd/3 [ksoftirqd/3]
+I< 0 30 2 0 0 0.0 26-03:07:26 kworker/3:0H-ev [kworker/3:0H-events_highpri]
+S 0 35 2 0 0 0.0 26-03:07:26 kdevtmpfs [kdevtmpfs]
+I< 0 36 2 0 0 0.0 26-03:07:26 netns [netns]
+S 0 37 2 0 0 0.0 26-03:07:26 kauditd [kauditd]
+S 0 38 2 0 0 0.0 26-03:07:26 khungtaskd [khungtaskd]
+S 0 39 2 0 0 0.0 26-03:07:26 oom_reaper [oom_reaper]
+I< 0 40 2 0 0 0.0 26-03:07:26 writeback [writeback]
+S 0 41 2 0 0 0.0 26-03:07:26 kcompactd0 [kcompactd0]
+SN 0 42 2 0 0 0.0 26-03:07:26 ksmd [ksmd]
+SN 0 43 2 0 0 0.0 26-03:07:26 khugepaged [khugepaged]
+I< 0 62 2 0 0 0.0 26-03:07:26 kintegrityd [kintegrityd]
+I< 0 63 2 0 0 0.0 26-03:07:26 kblockd [kblockd]
+I< 0 64 2 0 0 0.0 26-03:07:26 blkcg_punt_bio [blkcg_punt_bio]
+I< 0 65 2 0 0 0.0 26-03:07:26 edac-poller [edac-poller]
+I< 0 66 2 0 0 0.0 26-03:07:26 devfreq_wq [devfreq_wq]
+I< 0 67 2 0 0 0.0 26-03:07:26 kworker/2:1H-ev [kworker/2:1H-events_highpri]
+S 0 70 2 0 0 0.3 26-03:07:25 kswapd0 [kswapd0]
+I< 0 71 2 0 0 0.0 26-03:07:25 kthrotld [kthrotld]
+I< 0 72 2 0 0 0.0 26-03:07:25 acpi_thermal_pm [acpi_thermal_pm]
+I< 0 74 2 0 0 0.0 26-03:07:25 ipv6_addrconf [ipv6_addrconf]
+I< 0 80 2 0 0 0.0 26-03:07:25 kworker/3:1H-ev [kworker/3:1H-events_highpri]
+I< 0 84 2 0 0 0.0 26-03:07:25 kstrp [kstrp]
+I< 0 87 2 0 0 0.0 26-03:07:25 zswap-shrink [zswap-shrink]
+I< 0 110 2 0 0 0.0 26-03:07:25 kworker/0:1H-ev [kworker/0:1H-events_highpri]
+I< 0 141 2 0 0 0.0 26-03:07:25 ata_sff [ata_sff]
+S 0 143 2 0 0 0.0 26-03:07:25 scsi_eh_0 [scsi_eh_0]
+I< 0 144 2 0 0 0.0 26-03:07:25 scsi_tmf_0 [scsi_tmf_0]
+S 0 145 2 0 0 0.0 26-03:07:25 scsi_eh_1 [scsi_eh_1]
+I< 0 146 2 0 0 0.0 26-03:07:25 scsi_tmf_1 [scsi_tmf_1]
+S 0 147 2 0 0 0.0 26-03:07:25 scsi_eh_2 [scsi_eh_2]
+I< 0 148 2 0 0 0.0 26-03:07:25 scsi_tmf_2 [scsi_tmf_2]
+S 0 149 2 0 0 0.0 26-03:07:25 scsi_eh_3 [scsi_eh_3]
+I< 0 150 2 0 0 0.0 26-03:07:25 scsi_tmf_3 [scsi_tmf_3]
+S 0 151 2 0 0 0.0 26-03:07:25 scsi_eh_4 [scsi_eh_4]
+I< 0 152 2 0 0 0.0 26-03:07:25 scsi_tmf_4 [scsi_tmf_4]
+S 0 153 2 0 0 0.0 26-03:07:25 scsi_eh_5 [scsi_eh_5]
+I< 0 154 2 0 0 0.0 26-03:07:25 scsi_tmf_5 [scsi_tmf_5]
+S 0 158 2 0 0 0.0 26-03:07:25 card0-crtc0 [card0-crtc0]
+S 0 159 2 0 0 0.0 26-03:07:25 card0-crtc1 [card0-crtc1]
+S 0 160 2 0 0 0.0 26-03:07:25 card0-crtc2 [card0-crtc2]
+I< 0 162 2 0 0 0.0 26-03:07:25 kworker/1:1H-ev [kworker/1:1H-events_highpri]
+S 0 163 2 0 0 0.0 26-03:07:25 scsi_eh_6 [scsi_eh_6]
+I< 0 164 2 0 0 0.0 26-03:07:25 scsi_tmf_6 [scsi_tmf_6]
+S 0 165 2 0 0 0.0 26-03:07:25 usb-storage [usb-storage]
+I< 0 167 2 0 0 0.0 26-03:07:25 uas [uas]
+I< 0 176 2 0 0 0.0 26-03:07:25 kdmflush [kdmflush]
+I< 0 177 2 0 0 0.0 26-03:07:25 kdmflush [kdmflush]
+S 0 202 2 0 0 0.0 26-03:07:24 scsi_eh_7 [scsi_eh_7]
+I< 0 203 2 0 0 0.0 26-03:07:24 scsi_tmf_7 [scsi_tmf_7]
+S 0 204 2 0 0 0.0 26-03:07:24 usb-storage [usb-storage]
+I< 0 232 2 0 0 0.0 26-03:07:23 btrfs-worker [btrfs-worker]
+I< 0 233 2 0 0 0.0 26-03:07:23 btrfs-worker-hi [btrfs-worker-hi]
+I< 0 234 2 0 0 0.0 26-03:07:23 btrfs-delalloc [btrfs-delalloc]
+I< 0 235 2 0 0 0.0 26-03:07:23 btrfs-flush_del [btrfs-flush_del]
+I< 0 236 2 0 0 0.0 26-03:07:23 btrfs-cache [btrfs-cache]
+I< 0 237 2 0 0 0.0 26-03:07:23 btrfs-fixup [btrfs-fixup]
+I< 0 238 2 0 0 0.0 26-03:07:23 btrfs-endio [btrfs-endio]
+I< 0 239 2 0 0 0.0 26-03:07:23 btrfs-endio-met [btrfs-endio-met]
+I< 0 240 2 0 0 0.0 26-03:07:23 btrfs-endio-met [btrfs-endio-met]
+I< 0 241 2 0 0 0.0 26-03:07:23 btrfs-endio-rai [btrfs-endio-rai]
+I< 0 242 2 0 0 0.0 26-03:07:23 btrfs-rmw [btrfs-rmw]
+I< 0 243 2 0 0 0.0 26-03:07:23 btrfs-endio-wri [btrfs-endio-wri]
+I< 0 244 2 0 0 0.0 26-03:07:23 btrfs-freespace [btrfs-freespace]
+I< 0 245 2 0 0 0.0 26-03:07:23 btrfs-delayed-m [btrfs-delayed-m]
+I< 0 246 2 0 0 0.0 26-03:07:23 btrfs-readahead [btrfs-readahead]
+I< 0 247 2 0 0 0.0 26-03:07:23 btrfs-qgroup-re [btrfs-qgroup-re]
+S 0 248 2 0 0 0.0 26-03:07:23 btrfs-cleaner [btrfs-cleaner]
+S 0 249 2 0 0 0.2 26-03:07:23 btrfs-transacti [btrfs-transacti]
+I< 0 317 2 0 0 0.0 26-03:07:22 rpciod [rpciod]
+I< 0 322 2 0 0 0.0 26-03:07:22 xprtiod [xprtiod]
+S 0 381 2 0 0 0.0 26-03:07:22 irq/133-mei_me [irq/133-mei_me]
+S 0 422 2 0 0 0.0 26-03:07:22 watchdogd [watchdogd]
+I< 0 523 2 0 0 0.0 26-03:07:22 led_workqueue [led_workqueue]
+I< 0 583 2 0 0 0.0 26-03:07:22 cryptd [cryptd]
+I< 0 590 2 0 0 0.0 26-03:07:22 ext4-rsv-conver [ext4-rsv-conver]
+Ss 104 693 1 12324 4292 0.5 26-03:07:21 dbus-daemon /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
+Ss 0 731 1 575120 1368 0.0 26-03:07:21 systemd-logind /lib/systemd/systemd-logind
+Ssl 0 1111 1 121248 732 0.0 26-03:07:18 unattended-upgr /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
+S 0 1141 2 0 0 0.0 26-03:07:18 lockd [lockd]
+I< 0 1459 2 0 0 0.0 26-03:07:16 nfsiod [nfsiod]
+S 0 1621 2 0 0 0.0 26-03:07:15 NFSv4 callback [NFSv4 callback]
+Ssl 0 1771 1 1548340 676 0.0 26-03:07:13 libvirtd /usr/sbin/libvirtd
+I< 0 24315 2 0 0 0.0 26-02:49:02 cifsiod [cifsiod]
+I< 0 24316 2 0 0 0.0 26-02:49:02 smb3decryptd [smb3decryptd]
+I< 0 24317 2 0 0 0.0 26-02:49:02 cifsfileinfoput [cifsfileinfoput]
+I< 0 24318 2 0 0 0.0 26-02:49:02 cifsoplockd [cifsoplockd]
+I< 0 24319 2 0 0 0.0 26-02:49:02 cifs-dfscache [cifs-dfscache]
+S 0 24322 2 0 0 0.0 26-02:49:02 cifsd [cifsd]
+I< 0 24413 2 0 0 0.0 26-02:48:57 btrfs-worker [btrfs-worker]
+I< 0 24414 2 0 0 0.0 26-02:48:57 btrfs-worker-hi [btrfs-worker-hi]
+I< 0 24415 2 0 0 0.0 26-02:48:57 btrfs-delalloc [btrfs-delalloc]
+I< 0 24416 2 0 0 0.0 26-02:48:57 btrfs-flush_del [btrfs-flush_del]
+I< 0 24418 2 0 0 0.0 26-02:48:57 btrfs-cache [btrfs-cache]
+I< 0 24419 2 0 0 0.0 26-02:48:57 btrfs-fixup [btrfs-fixup]
+I< 0 24420 2 0 0 0.0 26-02:48:57 btrfs-endio [btrfs-endio]
+I< 0 24421 2 0 0 0.0 26-02:48:57 btrfs-endio-met [btrfs-endio-met]
+I< 0 24422 2 0 0 0.0 26-02:48:57 btrfs-endio-met [btrfs-endio-met]
+I< 0 24423 2 0 0 0.0 26-02:48:57 btrfs-endio-rai [btrfs-endio-rai]
+I< 0 24424 2 0 0 0.0 26-02:48:57 btrfs-rmw [btrfs-rmw]
+I< 0 24425 2 0 0 0.0 26-02:48:57 btrfs-endio-wri [btrfs-endio-wri]
+I< 0 24426 2 0 0 0.0 26-02:48:57 btrfs-freespace [btrfs-freespace]
+I< 0 24427 2 0 0 0.0 26-02:48:57 btrfs-delayed-m [btrfs-delayed-m]
+I< 0 24428 2 0 0 0.0 26-02:48:57 btrfs-readahead [btrfs-readahead]
+I< 0 24429 2 0 0 0.0 26-02:48:57 btrfs-qgroup-re [btrfs-qgroup-re]
+S 0 24450 2 0 0 0.0 26-02:48:53 btrfs-cleaner [btrfs-cleaner]
+S 0 24451 2 0 0 0.0 26-02:48:53 btrfs-transacti [btrfs-transacti]
+I< 0 747708 2 0 0 0.0 16-21:06:20 xfsalloc [xfsalloc]
+I< 0 747709 2 0 0 0.0 16-21:06:20 xfs_mru_cache [xfs_mru_cache]
+S 0 747713 2 0 0 0.0 16-21:06:20 jfsIO [jfsIO]
+S 0 747714 2 0 0 0.0 16-21:06:20 jfsCommit [jfsCommit]
+S 0 747715 2 0 0 0.0 16-21:06:20 jfsCommit [jfsCommit]
+S 0 747716 2 0 0 0.0 16-21:06:20 jfsCommit [jfsCommit]
+S 0 747717 2 0 0 0.0 16-21:06:20 jfsCommit [jfsCommit]
+S 0 747718 2 0 0 0.0 16-21:06:20 jfsSync [jfsSync]
+Ss 0 1071687 1 105976 28304 0.0 3-03:12:31 systemd-journal /lib/systemd/systemd-journald
+Ss 0 1934146 1 25672 4704 0.0 11:19:31 cupsd /usr/sbin/cupsd -l
+Ssl 0 1934148 1 182868 8540 0.0 11:19:31 cups-browsed /usr/sbin/cups-browsed
+S 13 1934155 3392655 5752 88 0.0 11:19:31 pinger (pinger)
+S< 33 1934166 3393034 57996 5460 0.0 11:19:31 apache2 /usr/sbin/apache2 -k start
+S< 33 1934167 3393034 216944 13892 0.0 11:19:30 apache2 /usr/sbin/apache2 -k start
+S< 33 1934168 3393034 216944 13756 0.0 11:19:30 apache2 /usr/sbin/apache2 -k start
+S< 33 1934169 3393034 216936 13732 0.0 11:19:30 apache2 /usr/sbin/apache2 -k start
+S< 33 1934170 3393034 216944 13888 0.0 11:19:30 apache2 /usr/sbin/apache2 -k start
+S< 33 1934172 3393034 216944 15388 0.0 11:19:30 apache2 /usr/sbin/apache2 -k start
+S< 33 1934701 3393034 216936 13736 0.0 11:19:29 apache2 /usr/sbin/apache2 -k start
+S< 33 1935056 3393034 216920 13724 0.0 11:19:28 apache2 /usr/sbin/apache2 -k start
+S 7 1936834 1934146 16652 832 0.0 11:18:12 dbus /usr/lib/cups/notifier/dbus dbus://
+S< 33 1955909 3393034 216928 13792 0.0 11:00:25 apache2 /usr/sbin/apache2 -k start
+I< 0 2531464 2 0 0 0.0 06:35:47 kworker/u9:0-i9 [kworker/u9:0-i915_flip]
+I 0 2570506 2 0 0 0.0 06:27:41 kworker/1:0-cgr [kworker/1:0-cgroup_destroy]
+I 0 2596195 2 0 0 0.0 06:21:52 kworker/1:1-eve [kworker/1:1-events]
+I 0 2785341 2 0 0 0.0 03:34:16 kworker/u8:8-bt [kworker/u8:8-btrfs-endio-write]
+I 0 2785520 2 0 0 0.0 03:33:50 kworker/3:0-eve [kworker/3:0-events]
+I 0 2798669 2 0 0 0.0 03:21:09 kworker/u8:5-bt [kworker/u8:5-btrfs-endio-write]
+Ss 0 2803015 1 5616 3108 0.0 03:17:54 cron /usr/sbin/cron -f
+I 0 2845483 2 0 0 0.0 02:38:11 kworker/0:3-eve [kworker/0:3-events]
+I 0 2939490 2 0 0 0.1 01:10:32 kworker/0:0-eve [kworker/0:0-events]
+I 0 2939754 2 0 0 0.0 01:10:26 kworker/u8:1-i9 [kworker/u8:1-i915]
+I 0 2942040 2 0 0 0.0 01:08:02 kworker/u8:7-bt [kworker/u8:7-btrfs-endio-meta]
+S 117 2954268 3392551 40044 5772 0.0 56:37 pickup pickup -l -t unix -u -c
+I 0 2965195 2 0 0 0.0 46:00 kworker/u8:0-bt [kworker/u8:0-btrfs-worker]
+I 0 2977972 2 0 0 0.0 33:54 kworker/u8:2-bt [kworker/u8:2-btrfs-endio-write]
+I 0 2985488 2 0 0 0.0 27:02 kworker/u8:3-bl [kworker/u8:3-blkcg_punt_bio]
+I 0 2987519 2 0 0 1.0 25:15 kworker/2:1-eve [kworker/2:1-events]
+I 0 2987601 2 0 0 0.0 25:03 kworker/u8:9-i9 [kworker/u8:9-i915]
+I< 0 2995218 2 0 0 0.0 18:41 kworker/u9:2-xp [kworker/u9:2-xprtiod]
+I 0 2997170 2 0 0 0.0 16:41 kworker/3:1-rcu [kworker/3:1-rcu_gp]
+I 0 3001264 2 0 0 0.0 13:01 kworker/u8:4-bt [kworker/u8:4-btrfs-endio-write]
+I 0 3004697 2 0 0 0.7 09:41 kworker/2:0-eve [kworker/2:0-events]
+I 0 3010619 2 0 0 1.0 04:29 kworker/2:2-eve [kworker/2:2-events]
+I 0 3014612 2 0 0 0.0 00:41 kworker/3:2-eve [kworker/3:2-events]
+S 0 3015082 2803015 6716 3028 0.0 00:30 cron /usr/sbin/CRON -f
+I 0 3015382 2 0 0 0.0 00:00 kworker/u8:6-bt [kworker/u8:6-btrfs-endio-meta]
+Ss 1 3392068 1 5592 504 0.0 15-02:34:39 atd /usr/sbin/atd -f
+Ssl 0 3392072 1 235796 1740 0.0 15-02:34:39 accounts-daemon /usr/libexec/accounts-daemon
+Ssl 106 3392076 1 315708 6128 0.0 15-02:34:39 colord /usr/libexec/colord
+Ss 0 3392083 1 8120 720 0.0 15-02:34:39 haveged /usr/sbin/haveged --Foreground --verbose=1
+Ss 0 3392090 1 5168 132 0.0 15-02:34:39 blkmapd /usr/sbin/blkmapd
+SNsl 111 3392094 1 155648 440 0.0 15-02:34:39 rtkit-daemon /usr/libexec/rtkit-daemon
+Ssl 0 3392097 1 290168 1352 0.0 15-02:34:39 packagekitd /usr/libexec/packagekitd
+Ss 128 3392100 1 7960 448 0.0 15-02:34:39 rpcbind /sbin/rpcbind -f -w
+Ss 0 3392114 1 13432 616 0.0 15-02:34:39 systemd-machine /lib/systemd/systemd-machined
+Ss 0 3392118 1 13316 848 0.0 15-02:34:39 sshd sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
+Ssl 0 3392124 1 244072 2456 0.0 15-02:34:39 upowerd /usr/libexec/upowerd
+Ssl 0 3392138 1 1634748 10684 0.0 15-02:34:39 containerd /usr/bin/containerd
+Ssl 0 3392139 1 222768 1784 0.0 15-02:34:39 rsyslogd /usr/sbin/rsyslogd -n -iNONE
+Ss 13 3392140 1 3344 152 0.0 15-02:34:39 polipo /usr/bin/polipo -c /etc/polipo/config pidFile=/var/run/polipo/polipo.pid daemonise=true
+Ssl 119 3392156 1 76472 1688 0.0 15-02:34:39 ntpd /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 119:126
+Ss 120 3392168 1 4656 276 0.0 15-02:34:39 rpc.statd /sbin/rpc.statd --no-notify
+Ss 0 3392171 1 5072 432 0.0 15-02:34:39 rpc.mountd /usr/sbin/rpc.mountd --manage-gids
+Ss 0 3392176 1 5008 288 0.0 15-02:34:39 rpc.idmapd /usr/sbin/rpc.idmapd
+Ss 105 3392184 1 15544 6816 3.5 15-02:34:39 avahi-daemon avahi-daemon: running [tsui.local]
+Ss 0 3392186 1 25288 3860 0.0 15-02:34:39 systemd-udevd /lib/systemd/systemd-udevd
+S 105 3392190 3392184 8788 52 0.0 15-02:34:39 avahi-daemon avahi-daemon: chroot helper
+Ssl 0 3392197 1 396120 4188 0.0 15-02:34:39 udisksd /usr/libexec/udisks2/udisksd
+Ssl 0 3392214 1 237504 6632 0.0 15-02:34:39 polkitd /usr/libexec/polkitd --no-debug
+Ss 0 3392284 1 9684 560 0.0 15-02:34:38 xinetd /usr/sbin/xinetd -pidfile /run/xinetd.pid -stayalive -inetd_compat -inetd_ipv6
+Ssl 0 3392285 1 314840 1352 0.0 15-02:34:38 ModemManager /usr/sbin/ModemManager
+Ss 0 3392317 1 2352 140 0.0 15-02:34:38 acpid /usr/sbin/acpid
+S 0 3392400 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392401 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392402 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392403 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392404 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392405 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392407 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+S 0 3392410 2 0 0 0.0 15-02:34:38 nfsd [nfsd]
+Ss 0 3392551 1 40092 1304 0.0 15-02:34:37 master /usr/lib/postfix/sbin/master -w
+S 117 3392553 3392551 40156 568 0.0 15-02:34:37 qmgr qmgr -l -t unix -u
+Ss 0 3392650 1 63652 4 0.0 15-02:34:36 squid /usr/sbin/squid --foreground -sYC
+Ssl 116 3392652 1 1675196 93848 0.0 15-02:34:36 mariadbd /usr/sbin/mariadbd
+S 13 3392655 3392650 81776 21232 0.0 15-02:34:36 squid (squid-1) --kid squid-1 --foreground -sYC
+S 13 3392657 3392655 5572 68 0.0 15-02:34:36 log_file_daemon (logfile-daemon) /var/log/squid/access.log
+S<s 0 3393034 1 216648 7560 0.0 15-02:34:34 apache2 /usr/sbin/apache2 -k start
+Ss 33 3393037 1 3432 180 0.0 15-02:34:34 htcacheclean /usr/bin/htcacheclean -d 120 -p /var/cache/apache2/mod_cache_disk -l 300M -n
diff --git a/plugins/tests/var/root b/plugins/tests/var/root
new file mode 100644
index 0000000..9339e13
--- /dev/null
+++ b/plugins/tests/var/root
@@ -0,0 +1 @@
+Root