From cfff54d3657dee0d1038cd51f1107e5ccb55782f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aur=C3=A9lien=20Nephtali?= <aurelien.nephtali@corp.ovh.com>
Date: Mon, 12 Mar 2018 16:42:47 +0100
Subject: [PATCH] TESTS: Add a script to test the CLI
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Each command is tested with various cases.

Signed-off-by: Aurélien Nephtali <aurelien.nephtali@corp.ovh.com>
---
 tests/00000001.pem |  47 +++++++++++++
 tests/cli.pl       | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/map_acl      |   1 +
 tests/ocsp.der     | Bin 0 -> 471 bytes
 tests/test-cli.cfg |  31 ++++++++
 tests/ticket-keys  |   3 +
 6 files changed, 285 insertions(+)
 create mode 100644 tests/00000001.pem
 create mode 100644 tests/cli.pl
 create mode 100644 tests/map_acl
 create mode 100644 tests/ocsp.der
 create mode 100644 tests/test-cli.cfg
 create mode 100644 tests/ticket-keys

diff --git a/tests/00000001.pem b/tests/00000001.pem
new file mode 100644
index 000000000..1e93faa6e
--- /dev/null
+++ b/tests/00000001.pem
@@ -0,0 +1,47 @@
+-----BEGIN CERTIFICATE-----
+MIIDNjCCAh4CCQCCLNI83wbxbzANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJV
+UzEPMA0GA1UECAwGRGVuaWFsMRQwEgYDVQQHDAtTcHJpbmdmaWVsZDEMMAoGA1UE
+CgwDRGlzMRkwFwYDVQQDDBB3d3cuMDAwMDAwMDEuY29tMB4XDTE4MDIxOTE2NDIy
+MVoXDTE5MDIxOTE2NDIyMVowXTELMAkGA1UEBhMCVVMxDzANBgNVBAgMBkRlbmlh
+bDEUMBIGA1UEBwwLU3ByaW5nZmllbGQxDDAKBgNVBAoMA0RpczEZMBcGA1UEAwwQ
+d3d3LjAwMDAwMDAxLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKvb36Ai1UqtQVTz+eJpHb5h+GwpmlNlQJ9ckLxTh0WpwAu2OUNasD0m+1oW1rab
+5cel+NyF56vGiJ/dv7mu3k7sLTjcqiuSrHt5zbKAjWxhdRvnHYCVy5BaQnOyRZMP
+2POfkmU7owdjtCWTD98gE1baTk5dq+jmfGBwipJy+cvtrlgrrDsVL5ONvtH+kw09
+gPFeY8FeplTLtTaHVFkFbiG1bRpIkrSREdpiQcG4/MvjuVt3jyBWgsNqoBRLSwr8
+wNUAh/hFjsIoUKQiITW4Hg3OZxla2osEXpy87o6A2B37X1d/yNOrH8EdnYqC76+F
+oh0hXA0WvMQuXhhk8gJr1LECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAcFjVht4C
+zsPkDmZMbOw+AVI7IxchClpU8RDg3QvXeDPLCj0XruQN080/KkZRubNIr/7BArSp
+oq+2zQKtUklfp1ZbdrYGf/2RxzmFwdnZHMZS+0aA5FtOrEbKTT+c8Axt8n8SWI7+
+UtmcicJ96nV48044GOaxqVGR48lXxLVmMEHmHFQSKUah9273DI8QIDSdjP00uGjB
+tgKU2RimZFWVbMW+7hfqN0lhtRcmvsq60foNmF/vSWjx8nTzDJrwGMCgNDAAH4zI
+5jDLwHyGL7C21a6hkOEArCZoFfgl4t2wTdmZos8mjgo2+lOhaTNhcD2DCw4btG/2
+/VEhvV51vRJalw==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAq9vfoCLVSq1BVPP54mkdvmH4bCmaU2VAn1yQvFOHRanAC7Y5
+Q1qwPSb7WhbWtpvlx6X43IXnq8aIn92/ua7eTuwtONyqK5Kse3nNsoCNbGF1G+cd
+gJXLkFpCc7JFkw/Y85+SZTujB2O0JZMP3yATVtpOTl2r6OZ8YHCKknL5y+2uWCus
+OxUvk42+0f6TDT2A8V5jwV6mVMu1NodUWQVuIbVtGkiStJER2mJBwbj8y+O5W3eP
+IFaCw2qgFEtLCvzA1QCH+EWOwihQpCIhNbgeDc5nGVraiwRenLzujoDYHftfV3/I
+06sfwR2dioLvr4WiHSFcDRa8xC5eGGTyAmvUsQIDAQABAoIBAB+laVRvlZ8esD0Y
+gBc1DAkWuUwRjR12M6Qkw3IqX2pwi7CcaYcBmBpqpzY7pmYR5woQgfb5oWN8N4RY
+rQlgLgeSbfFekOddJu3FzB7mlSQz/gCZWlFnRAjc1ge/+BfQfz69T5Pcm3Ss42tX
+3UBVA7qmkGzVyuYkKxsHHj1BdsYaPPxcC4PrkJn3VIFhuf4qtmsHL8aXMkwqGeKR
+Zt07vcfDWTdTjGcucayVxBqOrUELvho0rQpJNc5tIb4wC9RZ8Tt5QJviVoX3F9g0
+PZyLB1PsUYNtzZrYqUbcvXbDmhLFdDj/cA0xF2vC33JP2C+5DexIA2TUogKGjM2Z
+cWSuZhECgYEA3HDZeiPkXadMbRxpDwXjRXc5kEj73d805Yl6DA+H5ZwV4OYCSEzb
+z6Mc3OD3KH9AaNdFaPs1BQ+OcgwL36NOFz/NZuaJpUimCwye1UgukJsDGNWVHshK
+X+uE0illgQeNvKAYO0pdV91WT6Ghc2OrFKwO3YDpoIm6uCu3TpyEbG8CgYEAx5TS
+lIUt1s/UvYqvqeANAQ/KJOQV40lJoweFEFA5KcCSX/B2EX77adzUho67C4tSo0qF
+qOy9s9ifrSfcGW3Ww5o8+Gab3x2/wGNpYMjzymUOOU/AR+xXTw7Eyhk53ov1gXyx
+m1qcV1t07eqXx9L/V/TOnoTg2jseYrfaNQt0oN8CgYEAkSSgnQIq59sywBjXt7OJ
+vABPX4gehizkOEo3mN9U/EK0SRtI32/zvxhH9csOEZUPxLgRFJlqhIWEpeT2oG53
+CWnSBXG/qZtW8KmDnyzitAXMmTpv8A+yoMuC7ZmiIr3lfg/vRIKnSSYMIWxr0H0M
+dRUAyKmLqk9lKMRn8pOtwXMCgYBfnGgVRofjNMVR2DK3SuJv88R/T9U8gUuJknyo
+iAYafmqhE208jHydBnG51H6+1QvNtlG5z1BB7DDynvnOJNSR+D3lMiLSDEpkPDur
+ZhmEiEz8H7yZuBtLgGO9/b+/YYVHdxkOt6XWI7YslAoKbIZu+JRTVIzzfwbbfABJ
+ESfaOQKBgQC/UzPRSJIqeUzX+eeSS9G8UFNd2jJWQLWeXhOrA7WJvuSqa221eGEw
+SXq9KWIppYhIs5zU2LgO4v0DUKRjrjg2sY+QNm9/v2jkjYWMemwOJhgeUpB4894L
+vnUIXbZvl3SQBu9Mo8LvNOV+E1RWep+7IpSR+559WQPG/Vt07NGwww==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/cli.pl b/tests/cli.pl
new file mode 100644
index 000000000..8b94b3492
--- /dev/null
+++ b/tests/cli.pl
@@ -0,0 +1,203 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Term::ANSIColor;
+
+my $socat = '/usr/bin/socat';
+my $haproxy = './haproxy';
+my $conf = 'tests/test-cli.cfg';
+
+my $tests = [
+	{ cmd => "help",                                               expected => qr!^Unknown command\. Please enter one of the following commands only :! },
+	{ cmd => "prompt",                                             expected => qr!^\n> $! },
+	{ cmd => "quit",                                               expected => qr!^$! },
+	{ cmd => "show tls-keys #0",                                   expected => qr!\n0\.2 Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND\n\n$! },
+	{ cmd => "multiline ; set ssl tls-key\n#0\nRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERE\n", expected => qr/^\nTLS ticket key updated!\n\n$/ },
+	{ cmd => "set ssl ocsp-response \$(base64 -w 10000 tests/ocsp.der)", expected => qr!^OCSP single response: Certificate ID does not match any certificate or issuer\.\n\n|OCSP single response: no longer valid\.\.\n\n$! },
+	{ cmd => "multiline;set ssl ocsp-response \$(base64 tests/ocsp.der)\n", expected => qr!^\nOCSP single response: Certificate ID does not match any certificate or issuer\.\n\n|OCSP single response: no longer valid\.\.\n\n$! },
+	{ cmd => "show errors",                                        expected => qr!^Total events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n\n$! },
+	{ cmd => "multiline;show\nerrors\n",                           expected => qr!^\nTotal events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n\n$! },
+	{ cmd => "show errors bk",                                     expected => qr!^Total events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n$! },
+	{ cmd => "multiline   ;   show\nerrors bk\n",                  expected => qr!^\nTotal events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n$! },
+	{ cmd => "show errors fe",                                     expected => qr!^Total events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n$! },
+	{ cmd => "multiline; show\nerrors\nfe\n",                      expected => qr!^\nTotal events captured on \[\d+/[a-zA-Z]{3}/\d{4}:\d{2}:\d{2}:\d{2}\.\d{3}\] : \d+\n$! },
+	{ cmd => "disable agent bk/srv",                               expected => qr!^\n$! },
+	{ cmd => "multiline ; disable agent\nbk/srv\n",                expected => qr!^\n\n$! },
+	{ cmd => "disable health bk/srv",                              expected => qr!^\n$! },
+	{ cmd => "disable server bk/srv",                              expected => qr!^\n$! },
+	{ cmd => "multiline;disable\nserver\nbk/srv\n",                expected => qr!^\n\n$! },
+	{ cmd => "enable agent bk/srv",                                expected => qr!^Agent was not configured on this server, cannot enable\.\n\n$! },
+	{ cmd => "enable health bk/srv",                               expected => qr!^\n$! },
+	{ cmd => "enable server bk/srv",                               expected => qr!^\n$! },
+	{ cmd => "set maxconn server bk/srv 1234",                     expected => qr!^\n$! },
+	{ cmd => "multiline;set\nmaxconn\nserver\nbk/srv\n1234\n",     expected => qr!^\n$! },
+	{ cmd => "set maxconn server ab/cd",                           expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "set server bk/srv state ready",                      expected => qr!^\n$! },
+	{ cmd => "multiline ; set server\nbk/srv\nstate\nready\n",     expected => qr!^\n\n$! },
+	{ cmd => "get weight bk/srv",                                  expected => qr!^1 \(initial 1\)\n\n$! },
+	{ cmd => "get weight ab/cd",                                   expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "set weight bk/srv 100",                              expected => qr!^\n$! },
+	{ cmd => "multiline;set\nweight bk/srv\n100\n",                expected => qr!^\n\n$! },
+	{ cmd => "set weight ab/cd",                                   expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "set weight bk/srv",                                  expected => qr!^Require <weight> or <weight%>\.\n\n$! },
+	{ cmd => "show sess",                                          expected => qr!^0x[[:xdigit:]]+: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=\d+ age=0s calls=1 rq\[f=[[:xdigit:]]+h,i=0,an=00h,rx=\d*\S*,wx=,ax=\] rp\[f=[[:xdigit:]]+h,i=0,an=00h,rx=,wx=,ax=\] s0=\[7,8h,fd=12,ex=\] s1=\[7,4018h,fd=-1,ex=\]! },
+	{ cmd => "multiline;show sess\n0\n",                           expected => qr!^\n0x[[:xdigit:]]+: proto=unix_stream src=unix:1 fe=GLOBAL be=<NONE> srv=<none> ts=\d+ age=0s calls=1 rq\[f=[[:xdigit:]]+h,i=0,an=00h,rx=\d*\S*,wx=,ax=\] rp\[f=[[:xdigit:]]+h,i=0,an=00h,rx=,wx=,ax=\] s0=\[7,8h,fd=12,ex=\] s1=\[7,4018h,fd=-1,ex=\]! },
+	{ cmd => "show sess 1",                                        expected => qr!^Session not found\.\n\n$! },
+	{ cmd => "shutdown session 0",                                 expected => qr!^No such session \(use 'show sess'\)\.\n\n$! },
+	{ cmd => "shutdown sessions server bk/srv",                    expected => qr!^\n$! },
+	{ cmd => "clear table ab",                                     expected => qr!^No such table\n\n$! },
+	{ cmd => "clear table bk",                                     expected => qr!^\n$! },
+	{ cmd => "multiline ; clear table\nab\n",                      expected => qr!^\nNo such table\n\n$! },
+	{ cmd => "set table bk key 127.0.0.1",                         expected => qr!^\n$! },
+	{ cmd => "multiline ; set table\nbk\nkey\n127.0.0.2\n",        expected => qr!^\n\n$! },
+	{ cmd => "show table bk",                                      expected => qr!^# table: bk, type: ip, size:204800, used:2\n0x[[:xdigit:]]+: key=127\.0\.0\.1 use=0 exp=\d+ server_id=0\n0x[[:xdigit:]]+: key=127\.0\.0\.2 use=0 exp=\d+ server_id=0\n\n$! },
+	{ cmd => "clear counters",                                     expected => qr!^\n$! },
+	{ cmd => "clear counters all",                                 expected => qr!^\n$! },
+	{ cmd => "show info",                                          expected => qr!^Name: HAProxy\n! },
+	{ cmd => "show info typed",                                    expected => qr!^0\.Name\.1:POS:str:HAProxy! },
+	{ cmd => "show info json",                                     expected => qr!^\[{\"field\":{\"pos\":0,\"name\":\"Name\"},! },
+	{ cmd => "show stat",                                          expected => qr!fe,FRONTEND,,,0,0,2000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,! },
+	{ cmd => "show schema json",                                   expected => qr!^{"\$schema":"http://json-schema.org/draft-04/schema#"! },
+	{ cmd => "show startup-logs",                                  expected => qr!^No startup alerts/warnings\.\n\n$! },
+	{ cmd => "show resolvers",                                     expected => qr!^No resolvers found\n\n$! },
+	{ cmd => "set maxconn global 1234",                            expected => qr!^\n$! },
+	{ cmd => "multiline;set rate-limit connections global 1234\n", expected => qr!^\n\n$! },
+	{ cmd => "set rate-limit sessions global 1234",                expected => qr!^\n$! },
+	{ cmd => "set rate-limit ssl-sessions global 1234",            expected => qr!^\n$! },
+	{ cmd => "set rate-limit http-compression global 1234",        expected => qr!^\n$! },
+	{ cmd => "set severity-output none",                           expected => qr!^\n$! },
+	{ cmd => "set severity-output number 1234",                    expected => qr!^\n$! },
+	{ cmd => "multiline;  set\nseverity-output string\ntest\n",    expected => qr!^\n$! },
+	{ cmd => "multiline;set severity-output string\n" . 'a' x 32768 . "\n", expected => qr!^\n$! },
+	{ cmd => "set timeout cli 1234",                               expected => qr!^\n$! },
+	{ cmd => "show env",                                           expected => qr!PATH=! },
+	{ cmd => "multiline;show\nenv\nPATH\n",                        expected => qr!^\nPATH=! },
+	{ cmd => "show cli sockets",                                   expected => qr!^# socket lvl processes\n/tmp/sock1 admin all\n\n$! },
+	{ cmd => "show fd",                                            expected => qr!iocb=0x[[:xdigit:]]+\(conn_fd_handler\) tmask=0x1 umask=0x[[:xdigit:]]+ cflg=0x[[:xdigit:]]+ fe=GLOBAL\n\n$! },
+	{ cmd => "multiline;show fd\n-1\n",                            expected => qr!^\n\n$! },
+	{ cmd => "show activity",                                      expected => qr!^thread_id: 0\ndate_now: \d+\.\d+\nloops: \d+\nwake_cache: \d+\nwake_tasks: 0\nwake_applets: 0\nwake_signal: 0\npoll_exp: \d+\npoll_drop: \d+\npoll_dead: 0\npoll_skip: 0\nfd_skip: 0\nfd_lock: 0\nfd_del: 0\nconn_dead: 0\nstream: \d+\nempty_rq: \d+\nlong_rq: 0\n\n$! },
+	{ cmd => "disable frontend fe",                                expected => qr!^\n$! },
+	{ cmd => "disable frontend abc",                               expected => qr!^No such frontend\.\n\n$! },
+	{ cmd => "enable frontend fe",                                 expected => qr!^\n$! },
+	{ cmd => "enable frontend abc",                                expected => qr!^No such frontend\.\n\n$! },
+	{ cmd => "multiline;set\nmaxconn frontend fe 1234\n",          expected => qr!^\n\n$! },
+	{ cmd => "set maxconn frontend abc 1234",                      expected => qr!^No such frontend\.\n\n$! },
+	{ cmd => "disable health bk/srv",                              expected => qr!^\n$! },
+	{ cmd => "multiline;show servers\nstate\n",                    expected => qr!^\n1\n# be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id srv_fqdn srv_port\n3 bk 1 srv 127.0.0.1 2 0 100 1 \d 1 0 2 0 0 0 0 - 8001\n\n$! },
+	{ cmd => "show backend",                                       expected => qr!^# name\nbk\nstats\n\n$! },
+	{ cmd => "shutdown frontend fe",                               expected => qr!^\n$! },
+	{ cmd => "shutdown frontend abc",                              expected => qr!^No such frontend\.\n\n$! },
+	{ cmd => "set dynamic-cookie-key backend bk abc",              expected => qr!^\n$! },
+	{ cmd => "set dynamic-cookie-key backend abc abc",             expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "enable dynamic-cookie backend bk",                   expected => qr!^\n$! },
+	{ cmd => "enable dynamic-cookie backend abc",                  expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "disable dynamic-cookie backend bk",                  expected => qr!^\n$! },
+	{ cmd => "multiline;     disable dynamic-cookie backend bk\n", expected => qr!^\n$! },
+	{ cmd => "disable dynamic-cookie backend abc",                 expected => qr!^No such backend\.\n\n$! },
+	{ cmd => "show cache",                                         expected => qr!^\n$! },
+	{ cmd => "add acl #1 127.0.0.1",                               expected => qr!^Unknown ACL identifier\. Please use #<id> or <file>\.\n\n$! },
+	{ cmd => "clear acl #1",                                       expected => qr!^Unknown ACL identifier\. Please use #<id> or <file>\.\n\n$! },
+	{ cmd => "multiline;    del\nacl #1 127.0.0.1\n",              expected => qr!^\nUnknown map identifier\. Please use #<id> or <file>\.\n\n$! },
+	{ cmd => "get acl #0 test.com",                                expected => qr!^type=dom, case=sensitive, match=yes, idx=list, pattern="test.com"\n$! },
+	{ cmd => "show acl",                                           expected => qr!^# id \(file\) description\n0 \(\) acl 'hdr_dom' file 'tests/test-cli\.cfg' line 18\n\n$! },
+	{ cmd => "add map tests/map_acl test.com bk",                  expected => qr!^\n$! },
+	{ cmd => "multiline ; add map\ntests/map_acl test.com\nbk\n",  expected => qr!^\n\n$! },
+	{ cmd => "multiline ; add map\ntests/map test.com\n",          expected => qr!^\n'add map' expects three parameters: map identifier, key and value\.\n\n$! },
+	{ cmd => "multiline ; add map\ntests/mapA test.com\nbk\n",     expected => qr!^\nUnknown map identifier\. Please use #<id> or <file>\.\n\n$! },
+	{ cmd => "clear map #1",                                       expected => qr!^Unknown map identifier\. Please use #<id> or <file>\.\n\n$! },
+	{ cmd => "del map #-1 test.com",                               expected => qr!^\n$! },
+	{ cmd => "get map #-1 test.com",                               expected => qr!^type=str, case=sensitive, found=no\n\n$! },
+	{ cmd => "set map tests/map_acl test.com 12",                  expected => qr!^entry not found\.\n\n$! },
+	{ cmd => "multiline;show map\n",                               expected => qr!^\n# id \(file\) description\n-1 \(tests/map_acl\) pattern loaded from file 'tests/map_acl' used by map at file 'tests/test-cli\.cfg' line 16\n\n$! },
+	{ cmd => "show pools",                                         expected => qr!^Dumping pools usage\. Use SIGQUIT to flush them\.\n! },
+	#
+	{ cmd => 'long ' x 100,                                        expected => qr!^Unknown command\. Please enter one of the following commands only :! },
+	{ cmd => 'multiline;' . "long\n" x 500 . "\n",                 expected => qr!^\nUnknown command\. Please enter one of the following commands only :! },
+	{ cmd => 'set severity-output string ' . 'a' x 16356,          expected => qr!^\n$! },
+	{ cmd => 'set severity-output string ' . 'a' x 16357,          expected => qr!^$|^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} socat\[\d+\] E write\(\d+, 0x[[:xdigit:]]+, \d+\): Broken pipe\n$! },
+];
+
+sub run
+{
+	my ($cmd) = @_;
+	my @output = `echo "$cmd" | $socat /tmp/sock1 - 2>&1`;
+
+	return {
+		status => $?,
+		output => join('', @output),
+	};
+}
+
+sub isatty
+{
+	my ($fh) = @_;
+
+	return -t $fh;
+}
+
+sub main
+{
+	if (! -x $socat) {
+		print STDERR "socat is not installed or not executable\n";
+		exit 1;
+	}
+	if (! -x $haproxy) {
+		print STDERR "haproxy is not compiled or not executable\n";
+		exit 1;
+	}
+
+	my $ok = 'OK';
+	my $fail = 'FAIL';
+
+	if (isatty(\*STDOUT)) {
+		$ok = colored($ok, 'bright_blue');
+		$fail = colored($fail, 'bright_red');
+	}
+
+	my $pid = fork();
+	my $error_count = 0;
+
+	# launch HAProxy
+	if ($pid == 0) {
+		setpgrp(0, 0);
+		exec("$haproxy -f $conf >/dev/null 2>&1");
+	}
+
+	sleep 1;
+
+	foreach my $test (@{$tests}) {
+		my $ret;
+
+		$ret = run($test->{cmd});
+		if ($ret->{output} !~ m/$test->{expected}/) {
+			$error_count++;
+			use Data::Dumper;
+			$Data::Dumper::Useqq = 1;
+			print Dumper $test;
+			print Dumper $ret;
+			print "[$fail] ";
+		}
+		else {
+			print "[$ok]   ";
+		}
+		my $v = $test->{cmd};
+		$v =~ s/\n/\\n/g;
+		print sprintf "%.100s", $v;
+		if (length $v > 100) {
+			print '[...]';
+		}
+		print "\n";
+	}
+
+	# cleanup
+	kill 'KILL', -$pid;
+	waitpid $pid, 0;
+
+	print "Error(s): $error_count/" . @{$tests} . "\n";
+
+	return 0;
+}
+
+exit main;
diff --git a/tests/map_acl b/tests/map_acl
new file mode 100644
index 000000000..3eaa9f3b3
--- /dev/null
+++ b/tests/map_acl
@@ -0,0 +1 @@
+test.com bk
diff --git a/tests/ocsp.der b/tests/ocsp.der
new file mode 100644
index 0000000000000000000000000000000000000000..e0b2f6066d9833dd30dbca7342929d65aab1236f
GIT binary patch
literal 471
zcmXqLV!X`7$grS^@r*$e;|VrSZ8k<$R(1nMMwTYVoj{?j295I;iLr>-UJh7#ZNb`i
zpS=>eQZFlB`SIf#zXZRLfuV(gv7xDfg^`7UWt2g&L7{=C0Vf-)HXk#S6e|OZi07BR
zT@w4t*k&BP=b)QmU6}RcSsQlKm;|{0ZsFv*zV(^IVQ#ULL9^5w7%*&DAP5sOGBPkX
zF$P)6%f_kI=F#?@mywa1m4Ug5k&$8H-Df#FcxQY!JEgYLsPEtV>80@z0T=IV2(sRw
z_}Fv*>YrZ10nT4o#l);uReM~#zDE0D!M3}qvNJ#M352MfImP{Anq|0qx^GRc`}Ox?
znNN!+nK`U6-F;hD@N@f*sZBS%+qtc;Pu4y7QMvEwJgXx!dp6(Fdw=kw=~I#B#wGtG
z&V;JjaaWsqsDFu!VAu7Y7-!&L6VUv%Mau2t(I$?mU0<)Ho?N(fS5@!1zWQ%d=Ise>
zJoGW!w5TcEm+zR9^u7bfg?s0SEl^ps;)wXF4o#8vlT&1!a^Gnu^=@L@Hf5FE-`^)z
mxLq*)wt3seTLG6}E>8dW_Vy=(S&U29KV5adQOM<1cRB#XSjhkY

literal 0
HcmV?d00001

diff --git a/tests/test-cli.cfg b/tests/test-cli.cfg
new file mode 100644
index 000000000..b6a16cd58
--- /dev/null
+++ b/tests/test-cli.cfg
@@ -0,0 +1,31 @@
+global
+	stats socket /tmp/sock1 mode 666 level admin
+	stats timeout 60s
+	tune.ssl.default-dh-param 2048
+
+defaults
+	timeout client 5s
+	timeout server 5s
+	timeout connect 5s
+	mode http
+
+frontend fe
+	bind :8000
+	bind :8043 ssl crt tests/00000001.pem tls-ticket-keys tests/ticket-keys
+
+	use_backend	%[req.hdr(host),lower,map_str(tests/map_acl,bk)]
+	default_backend bk
+	acl host_matches hdr_dom(host) test.com
+	use_backend bk if host_matches
+
+backend bk
+	stick-table type ip size 200k expire 30m
+	stick on src
+	server srv 127.0.0.1:8001
+
+listen stats
+	bind :1936
+
+	stats enable
+	stats uri /
+	stats hide-version
diff --git a/tests/ticket-keys b/tests/ticket-keys
new file mode 100644
index 000000000..c24705ddb
--- /dev/null
+++ b/tests/ticket-keys
@@ -0,0 +1,3 @@
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJC
+Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0ND
-- 
2.11.0

