1#!/usr/bin/env perl
2
3=head1 NAME
4
5Options.t - Test commandline options and such
6
7=cut
8
9package FooServer;
10
11use strict;
12use FindBin qw($Bin);
13use lib $Bin;
14use NetServerTest qw(prepare_test ok is use_ok skip like);
15prepare_test({n_tests => 73, plan_only => 1});
16
17use_ok('Net::Server');
18@FooServer::ISA = qw(Net::Server);
19
20### override-able options for this package
21sub options {
22  my $self     = shift;
23  my $prop     = $self->{'server'};
24  my $template = shift;
25
26  ### setup options in the parent classes
27  $self->SUPER::options($template);
28
29  $template->{'my_option'} = \$prop->{'my_option'};
30
31  $prop->{'an_arrayref_item'} ||= [];
32  $template->{'an_arrayref_item'} = $prop->{'an_arrayref_item'};
33}
34
35### provide default values
36sub default_values {
37    return {
38        group => 'defaultgroup',
39        allow => ['127.0.0.1', '192.169.0.1'],
40    };
41}
42
43#sub proto_object {
44#    my ($self, $host, $port, $proto) = @_;
45#    #debug $host, $port, $proto;
46#    #return $self->SUPER::proto_object($host, $port, $proto);
47#    return "Blah";
48#}
49
50### override these to make run not run
51### this will allow all configuration cycles to be run
52sub bind {}
53sub post_bind {}
54sub loop {}
55sub log {}
56sub server_close {
57    my $self = shift;
58    return $self;
59}
60
61###----------------------------------------------------------------###
62
63my $obj = eval { FooServer->new };
64ok($obj, "Got an object ($@)");
65
66my $server = eval { FooServer->run };
67ok($server, "Got a server ($@)");
68my $prop = eval { $server->{'server'} } || {};
69is($prop->{'log_level'}, 2,  "Correct default log_level");
70is($prop->{'log_file'}, "", "Correct default log_file");
71ok(! $prop->{'user'},          "Correct default user");
72my $configured_ports = scalar(@{ $prop->{'_bind'} });
73ok($configured_ports == 1 || $configured_ports == 2, "Had correct configured ports ($configured_ports)");
74my @socks = @{ $prop->{'sock'} };
75is(scalar(@socks), scalar(@{ $prop->{'_bind'} }), "Sockets matched ports");
76my $sock = $socks[0];
77if ($sock->NS_ipv == 4) {
78    is(eval { $sock->NS_host  }, '0.0.0.0',   "Right host");
79} else {
80    is(eval { $sock->NS_host  }, '::',   "Right host");
81}
82is(eval { $sock->NS_port  }, 20203, "Right port");
83is(eval { $sock->NS_proto }, 'TCP', "Right proto");
84
85###----------------------------------------------------------------###
86
87$prop = eval { FooServer->run(port => 2201)->{'server'} };
88ok($prop, "Loaded server");
89$prop ||= {};
90is(scalar(@{ $prop->{'port'} }), 1,    "Had 1 configured ports");
91is($prop->{'port'}->[0], 2201, "Right port");
92
93###----------------------------------------------------------------###
94
95$prop = eval { FooServer->run(port => [2201, 2202])->{'server'} };
96ok($prop, "Loaded server");
97$prop ||= {};
98is(scalar(@{ $prop->{'port'} }), 2,    "Had 1 configured ports");
99is($prop->{'port'}->[0], 2201, "Right port");
100is($prop->{'port'}->[1], 2202, "Right port");
101
102###----------------------------------------------------------------###
103
104$prop = eval { FooServer->run({port => 2201})->{'server'} };
105ok($prop, "Loaded server");
106$prop ||= {};
107is(scalar(@{  $prop->{'port'} }), 1,    "Had 1 configured ports");
108is($prop->{'port'}->[0], 2201, "Right port");
109
110###----------------------------------------------------------------###
111
112$prop = eval { FooServer->new(port => 2201)->run->{'server'} };
113ok($prop, "Loaded server");
114$prop ||= {};
115is(scalar(@{  $prop->{'port'} }), 1,    "Had 1 configured ports");
116is($prop->{'port'}->[0], 2201, "Right port");
117
118###----------------------------------------------------------------###
119
120$prop = eval { FooServer->new({port => 2201})->run->{'server'} };
121ok($prop, "Loaded server");
122$prop ||= {};
123is(scalar(@{  $prop->{'port'} }), 1,    "Had 1 configured ports");
124is($prop->{'port'}->[0], 2201, "Right port");
125
126###----------------------------------------------------------------###
127
128$prop = eval { local @ARGV = ('--port', '2201'); FooServer->run->{'server'} };
129ok($prop, "Loaded server");
130$prop ||= {};
131is(scalar(@{  $prop->{'port'} }), 1,    "Had 1 configured ports");
132is($prop->{'port'}->[0], 2201, "Right port");
133
134###----------------------------------------------------------------###
135
136$prop = eval { local @ARGV = ('--port', '2201', '--port=2202'); FooServer->run->{'server'} };
137ok($prop, "Loaded server");
138$prop ||= {};
139is(scalar(@{  $prop->{'port'} }), 2,    "Had 1 configured ports");
140is($prop->{'port'}->[0], 2201, "Right port");
141is($prop->{'port'}->[1], 2202, "Right port");
142
143###----------------------------------------------------------------###
144
145$prop = eval { FooServer->run(conf_file => __FILE__.'.conf')->{'server'} };
146ok($prop, "Loaded server");
147$prop ||= {};
148is(scalar(@{  $prop->{'port'} }), 3,    "Had 1 configured ports");
149is($prop->{'port'}->[0], 5401, "Right port");
150is($prop->{'port'}->[1], 5402, "Right port");
151is($prop->{'port'}->[2], 5403, "Right port");
152is($prop->{'user'}, 'foo',     "Right user");
153
154###----------------------------------------------------------------###
155
156$prop = eval { local @ARGV = ('--user=cmdline'); FooServer->run(conf_file => __FILE__.'.conf', user => 'runargs')->{'server'} };
157ok($prop, "Loaded server");
158$prop ||= {};
159is($prop->{'user'}, 'cmdline', "Right user \"$prop->{'user'}\"");
160
161###----------------------------------------------------------------###
162
163$prop = eval { FooServer->run(conf_file => __FILE__.'.conf', user => 'runargs')->{'server'} };
164ok($prop, "Loaded server");
165$prop ||= {};
166is($prop->{'user'}, 'runargs', "Right user \"$prop->{'user'}\"");
167
168###----------------------------------------------------------------###
169
170$prop = eval { FooServer->run(my_option => 'wow')->{'server'} };
171ok($prop, "Loaded server");
172$prop ||= {};
173is($prop->{'my_option'}, 'wow', 'Could use custom options');
174
175###----------------------------------------------------------------###
176
177$prop = eval { FooServer->run(an_arrayref_item => 'wow')->{'server'} };
178ok($prop, "Loaded server");
179$prop ||= {};
180is(scalar(@{  $prop->{'an_arrayref_item'} }), 1,     "Had 1 configured custom array option");
181is($prop->{'an_arrayref_item'}->[0], 'wow', "Right value");
182
183###----------------------------------------------------------------###
184
185$prop = eval { FooServer->run(conf_file => __FILE__.'.conf', user => 'runargs')->{'server'} };
186ok($prop, "Loaded server");
187$prop ||= {};
188is($prop->{'my_option'}, 'bar', "Right my_option \"$prop->{'my_option'}\"");
189is(scalar(@{  $prop->{'an_arrayref_item'} }), 3,     "Had 3 configured custom array option");
190is($prop->{'an_arrayref_item'}->[0], 'one',   "Right value");
191is($prop->{'an_arrayref_item'}->[1], 'three', "Right value");
192is($prop->{'an_arrayref_item'}->[2], 'two',   "Right value");
193
194###----------------------------------------------------------------###
195
196$prop = eval { local @ARGV = ('--group=cmdline'); FooServer->run(conf_file => __FILE__.'.conf', group => 'runargs')->{'server'} };
197ok($prop, "Loaded server");
198$prop ||= {};
199is($prop->{'group'}, 'cmdline', "Right group \"$prop->{'group'}\"");
200
201###----------------------------------------------------------------###
202
203$prop = eval { FooServer->run(conf_file => __FILE__.'.conf', group => 'runargs')->{'server'} };
204ok($prop, "Loaded server");
205$prop ||= {};
206is($prop->{'group'}, 'runargs', "Right group \"$prop->{'group'}\"");
207
208###----------------------------------------------------------------###
209
210$prop = eval { FooServer->run(conf_file => __FILE__.'.conf')->{'server'} };
211ok($prop, "Loaded server");
212$prop ||= {};
213is($prop->{'group'}, 'confgroup', "Right group \"$prop->{'group'}\"");
214
215###----------------------------------------------------------------###
216
217$prop = eval { FooServer->run->{'server'} };
218ok($prop, "Loaded server");
219$prop ||= {};
220is($prop->{'group'}, 'defaultgroup', "Right group \"$prop->{'group'}\"");
221is(scalar(@{ $prop->{'allow'} }), 2, "Defaults for allow are set also");
222
223###----------------------------------------------------------------###
224
225{
226    package BarServer;
227    @BarServer::ISA = qw(FooServer);
228    sub default_values {
229        return {
230            conf_file => __FILE__.'.conf'
231        };
232    }
233}
234
235$prop = eval { BarServer->run->{'server'} };
236$prop ||= {};
237is($prop->{'group'}, 'confgroup', "Right group \"$prop->{'group'}\"");
238
239###----------------------------------------------------------------###
240
241$prop = eval { FooServer->new({
242    conf_file => __FILE__.'.conf', # arguments passed to new win
243})->run({
244    conf_file => 'somefile_that_doesnot_exist',
245})->{'server'} };
246$prop ||= {};
247is($prop->{'group'}, 'confgroup', "Right group \"$prop->{'group'}\"");
248
249
250
251###----------------------------------------------------------------###
252
253if (!$ENV{'TEST_LOG4PERL'}) {
254  SKIP: { skip("TEST_LOG4PERL not set - skipping Log::Log4perl tests", 7) };
255} elsif (!eval { require Log::Log4perl; require File::Temp }) {
256  SKIP: { skip("Log::Log4perl not installed: $@", 7) };
257} else {
258
259    $prop = eval { FooServer->run(
260        log_file => "Log::Log4perl"
261    ) };
262    like("$@", qr/Must specify a log4perl_conf file/, "Got error due to missing log4perl_conf");
263
264    my ($log_fh, $log4perl_file) = File::Temp::tempfile(SUFFIX => '.log', UNLINK => 1);
265    unlink $log4perl_file;
266
267    my $conf = << "EOF";
268log4perl.logger.tester = WARN, FileAppndr1
269
270log4perl.appender.FileAppndr1 = Log::Log4perl::Appender::File
271log4perl.appender.FileAppndr1.filename = ${log4perl_file}
272log4perl.appender.FileAppndr1.layout = Log::Log4perl::Layout::SimpleLayout
273EOF
274
275    my ($conf_fh, $conf_file) = File::Temp::tempfile(SUFFIX => '.log4perl', UNLINK => 1);
276    print $conf_fh $conf;
277    close $conf_fh;
278
279    # This log file is same as specified in Options.t.log4perl
280    open my $old_stdout, ">&", STDOUT; # save this off because setting a log_file is going to force close STDIN and STDOUT
281    $prop = eval { FooServer->run(
282        log_file => "Log::Log4perl",
283        log4perl_conf => $conf_file,
284        log4perl_logger => "tester",
285    )->{'server'} };
286    my $err = "$@";
287    open STDOUT, ">&", $old_stdout; # restore it
288
289    # There was a test for a bad log4perl_conf file, but log4perl only allows you to initialise once
290    # so subsequent initialisations always had the bad filename
291    #like( $@, qr/Cannot open config file '.*?'/, "Got error due to missing log4perl_conf file" );
292    ok(!$err, "No Log4perl errors");
293    is(ref($prop->{'log_function'}), "CODE", "Log4perl initialised with function created");
294    ok(-e $log4perl_file, "Log file $log4perl_file found");
295    ok(! -s $log4perl_file, "Log file is 0 bytes");
296
297    $prop->{'log_function'}->(1, "A test message");
298    ok(-s $log4perl_file, "Log file now has data");
299
300    open my $fh, '<', $log4perl_file;
301    my $data = <$fh>;
302    is($data, "ERROR - A test message\n", "Got expected log message");
303}
304