make verbose a global state
[pve-firewall.git] / test / fwtester.pl
1 #!/usr/bin/perl
2
3 use lib '../src';
4 use strict;
5 use warnings;
6 use Data::Dumper;
7 use PVE::FirewallSimulator;
8 use Getopt::Long;
9 use File::Basename;
10 use Net::IP;
11
12 my $debug = 0;
13
14 sub print_usage_and_exit {
15     die "usage: $0 [--debug] [testfile [testid]]\n";
16 }
17
18 if (!GetOptions ('debug' => \$debug)) {
19     print_usage_and_exit();
20 }
21
22 PVE::FirewallSimulator::debug($debug);
23  
24 my $testfilename = shift;
25 my $testid = shift;
26
27 sub run_tests {
28     my ($vmdata, $testdir, $testfile, $testid) = @_;
29
30     $testfile = 'tests' if !$testfile;
31
32
33     $vmdata->{testdir} = $testdir;
34
35     my $host_ip = '172.16.1.2';
36
37     PVE::Firewall::local_network('172.16.1.0/24');
38
39     my ($ruleset, $ipset_ruleset) = 
40         PVE::Firewall::compile(undef, undef, $vmdata, 1);
41
42     my $filename = "$testdir/$testfile";
43     my $fh = IO::File->new($filename) ||
44         die "unable to open '$filename' - $!\n";
45
46     my $testcount = 0;
47     while (defined(my $line = <$fh>)) {
48         next if $line =~ m/^\s*$/;
49         next if $line =~ m/^#.*$/;
50         if ($line =~ m/^\{.*\}\s*$/) {
51             my $test = eval $line;
52             die $@ if $@;
53             next if defined($testid) && (!defined($test->{id}) || ($testid ne $test->{id}));
54             PVE::FirewallSimulator::reset_trace();
55             print Dumper($ruleset) if $debug;
56             $testcount++;
57             eval {
58                 my @test_zones = qw(host outside nfvm vm100 ct200);
59                 if (!defined($test->{from}) && !defined($test->{to})) {
60                     die "missing zone speification (from, to)\n";
61                 } elsif (!defined($test->{to})) {
62                     foreach my $zone (@test_zones) {
63                         next if $zone eq $test->{from};
64                         $test->{to} = $zone;
65                         PVE::FirewallSimulator::add_trace("Set Zone: to => '$zone'\n"); 
66                         PVE::FirewallSimulator::simulate_firewall($ruleset, $ipset_ruleset, 
67                                                                   $host_ip, $vmdata, $test);
68                     }
69                 } elsif (!defined($test->{from})) {
70                     foreach my $zone (@test_zones) {
71                         next if $zone eq $test->{to};
72                         $test->{from} = $zone;
73                         PVE::FirewallSimulator::add_trace("Set Zone: from => '$zone'\n"); 
74                         PVE::FirewallSimulator::simulate_firewall($ruleset, $ipset_ruleset, 
75                                                                   $host_ip, $vmdata, $test);
76                     }
77                 } else {
78                     PVE::FirewallSimulator::simulate_firewall($ruleset, $ipset_ruleset, 
79                                                               $host_ip, $vmdata, $test);
80                 }
81             };
82             if (my $err = $@) {
83
84                 print Dumper($ruleset) if !$debug;
85
86                 print PVE::FirewallSimulator::get_trace() . "\n" if !$debug;
87
88                 print "$filename line $.: $line";
89
90                 print "test failed: $err\n";
91
92                 exit(-1);
93             }
94         } else {
95             die "parse error";
96         }
97     }
98
99     die "no tests found\n" if $testcount <= 0;
100
101     print "PASS: $filename\n";
102
103     return undef;
104 }
105
106 my $vmdata = {
107     qemu => {
108         100 => {
109             net0 => "e1000=0E:0B:38:B8:B3:21,bridge=vmbr0,firewall=1",
110             net1 => "e1000=0E:0B:38:B9:B4:21,bridge=vmbr1,firewall=1",
111             net2 => "e1000=0E:0B:38:BA:B4:21,bridge=vmbr2,firewall=1",
112         },
113         101 => {
114             net0 => "e1000=0E:0B:38:B8:B3:22,bridge=vmbr0,firewall=1",
115         },
116         # on bridge vmbr1
117         110 => {
118             net0 => "e1000=0E:0B:38:B8:B4:21,bridge=vmbr1,firewall=1",
119         },
120     },
121     lxc => {
122         200 => {
123             net0 => "name=eth0,hwaddr=0E:18:24:41:2C:43,bridge=vmbr0,firewall=1,ip=10.0.200.1/24",
124         },
125         201 => {
126             net0 => "name=eth0,hwaddr=0E:18:24:41:2C:44,bridge=vmbr0,firewall=1,ip=10.0.200.2/24",
127         },
128     },
129 };
130
131 if ($testfilename) {
132     my $testfile;
133     my $dir;
134
135     if (-d $testfilename) {
136         $dir = $testfilename;
137     } elsif (-f $testfilename) {
138         $dir = dirname($testfilename);
139         $testfile = basename($testfilename);
140     } else {
141         die "no such file/dir '$testfilename'\n"; 
142     }
143
144     run_tests($vmdata, $dir, $testfile, $testid);
145
146 } else { 
147     foreach my $dir (<test-*>) {
148         next if ! -d $dir;
149         run_tests($vmdata, $dir);
150     }
151 }
152
153 print "OK - all tests passed\n";
154
155 exit(0);