File Coverage

lib/Test/APIcast.pm
Criterion Covered Total %
statement 41 96 42.7
branch 0 22 0.0
condition 1 2 50.0
subroutine 15 23 65.2
pod 0 8 0.0
total 57 151 37.7


line stmt bran cond sub pod time code
1             package Test::APIcast;
2 1     1   640 use v5.10.1;
  1         4  
3 1     1   5 use strict;
  1         2  
  1         34  
4 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         39  
5 1     1   5 use Fcntl qw(:flock SEEK_END);
  1         1  
  1         176  
6              
7             our $VERSION = "0.24";
8              
9             BEGIN {
10 1   50 1   53 $ENV{TEST_NGINX_BINARY} ||= 'openresty';
11             }
12              
13 1     1   472 use Test::Nginx::Socket::Lua -Base;
  1         186589  
  1         9  
14 1     1   3029  
  1     1   2  
  1     1   22  
  1     1   4  
  1         2  
  1         25  
  1         4  
  1         2  
  1         15  
  1         3  
  1         2  
  1         24  
15 1     1   4 use Cwd qw(cwd abs_path);
  1         2  
  1         54  
16 1     1   517 use File::Spec::Functions qw(catfile);
  1         767  
  1         64  
17 1     1   516 use File::Slurp qw(read_file);
  1         3854  
  1         1298  
18              
19             my $pwd = cwd();
20             our $path = $ENV{TEST_NGINX_APICAST_PATH} ||= "$pwd/gateway";
21             our $spec = "$pwd/spec";
22             our $servroot = $Test::Nginx::Util::ServRoot;
23              
24             our $Fixtures = abs_path($ENV{TEST_NGINX_FIXTURES} || catfile('t', 'fixtures'));
25              
26             # src/?/policy.lua allows us to require apicast.policy.apolicy
27             $ENV{TEST_NGINX_LUA_PATH} = "$path/src/?.lua;$path/src/?/policy.lua;;";
28             $ENV{TEST_NGINX_MANAGEMENT_CONFIG} = "$path/conf.d/management.conf";
29             $ENV{TEST_NGINX_UPSTREAM_CONFIG} = "$path/http.d/upstream.conf";
30             $ENV{TEST_NGINX_BACKEND_CONFIG} = "$path/conf.d/backend.conf";
31             $ENV{TEST_NGINX_APICAST_CONFIG} = "$path/conf.d/apicast.conf";
32             $ENV{APICAST_DIR} = $path;
33              
34             if ($ENV{DEBUG}) {
35             $ENV{TEST_NGINX_ERROR_LOG} ||= '/dev/stderr';
36             }
37              
38             our @EXPORT = qw( get_random_port );
39              
40             our @PORTS = ();
41              
42             open(my $prove_filename_lock, ">", "/tmp/prove_lock");
43              
44 0     0 0   sub lock {
45 0 0         flock($prove_filename_lock, LOCK_EX) or bail_out "cannot get prove lock.";
46             # and, in case someone appended while we were waiting...
47 0 0         seek($prove_filename_lock, 0, SEEK_END) or bail_out "cannot get prove lock.";
48             }
49              
50 0     0 0   sub unlock {
51 0 0         flock($prove_filename_lock, LOCK_UN) or bail_out "Cannot release prove lock";
52             }
53              
54 0     0 0   sub get_random_port {
55 0           my $tries = 1000;
56 0           my $ServerPort;
57 0           lock();
58 0           for (my $i = 0; $i < $tries; $i++) {
59 0           my $port = int(rand 60000) + 1025;
60              
61 0           my $sock = IO::Socket::INET->new(
62             LocalPort => $port,
63             Proto => 'tcp',
64             );
65              
66 0 0         if (defined $sock) {
67 0           $sock->shutdown(0);
68 0           $sock->close();
69 0           push @PORTS, $sock;
70 0           $ServerPort = $port;
71 0           last;
72             }
73              
74 0 0         if ($Test::Nginx::Util::Verbose) {
75 0           warn "Try again, port $port is already in use: $@\n";
76             }
77             }
78 0           unlock();
79              
80 0 0         if (!defined $ServerPort) {
81 0           bail_out "Cannot find an available listening port number after $tries attempts.\n";
82             }
83              
84 0           return $ServerPort;
85             }
86              
87             env_to_nginx('APICAST_DIR');
88             env_to_nginx("TEST_NGINX_SERVER_PORT=$Test::Nginx::Util::ServerPortForClient");
89              
90             log_level('debug');
91             repeat_each($ENV{TEST_NGINX_REPEAT_EACH} || 2);
92             no_root_location();
93              
94             add_block_preprocessor(sub {
95             my $block = shift;
96              
97             $ENV{TEST_NGINX_RANDOM_PORT} = $block->random_port;
98             });
99              
100              
101 0     0 0   sub close_random_ports {
102 0           my $sock;
103 0           while (defined($sock = shift @PORTS)){
104 0           $sock->close();
105             }
106             };
107              
108             our $dns = sub ($$$) {
109             my ($host, $ip, $ttl) = @_;
110              
111             return sub {
112             # Get DNS request ID from passed UDP datagram
113             my $dns_id = unpack("n", shift);
114             # Set name and encode it
115             my $name = $host;
116             $name =~ s/([^.]+)\.?/chr(length($1)) . $1/ge;
117             $name .= "\0";
118             my $s = '';
119             $s .= pack("n", $dns_id);
120             # DNS response flags, hardcoded
121             # response, opcode, authoritative, truncated, recursion desired, recursion available, reserved
122             my $flags = (1 << 15) + (0 << 11) + (1 << 10) + (0 << 9) + (1 << 8) + (1 << 7) + 0;
123             $flags = pack("n", $flags);
124             $s .= $flags;
125             $s .= pack("nnnn", 1, 1, 0, 0);
126             $s .= $name;
127             $s .= pack("nn", 1, 1); # query class A
128              
129             # Set response address and pack it
130             my @addr = split /\./, $ip;
131             my $data = pack("CCCC", @addr);
132              
133             # pointer reference to the first name
134             # $name = pack("n", 0b1100000000001100);
135              
136             # name + type A + class IN + TTL + length + data(ip)
137             $s .= $name. pack("nnNn", 1, 1, $ttl || 0, 4) . $data;
138             return $s;
139             }
140             };
141              
142             sub Test::Base::Filter::random_port {
143 0     0 0   my ($self, $code) = @_;
144              
145 0           my $block = $self->current_block;
146 0           my $random_port = $block->random_port;
147              
148 0 0         if ( !defined $random_port ) {
149 0 0         if ($Test::Nginx::Util::Randomize) {
150 0           $random_port = get_random_port();
151             } else {
152 0           $random_port = 1953;
153             }
154             }
155              
156 0           $block->set_value('random_port', $random_port);
157              
158 0           $ENV{TEST_NGINX_RANDOM_PORT} = $random_port;
159              
160 0           return $code;
161             }
162              
163              
164             sub Test::Base::Filter::dns {
165 0     0 0   my ($self, $code) = @_;
166              
167 0           my $input = eval $code;
168              
169 0 0         if ($@) {
170 0           die "failed to evaluate code $code: $@\n";
171             }
172              
173 0           return $dns->(@$input)
174             }
175              
176              
177             sub Test::Base::Filter::env {
178 0     0 0   my ($self, $input) = @_;
179              
180 0           return Test::Nginx::Util::expand_env_in_config($input);
181             }
182              
183             sub Test::Base::Filter::fixture {
184 0     0 0   my $name = filter_arguments;
185              
186 0 0         if (! $name) {
187 0           bail_out("fixture filter needs argument - file to be loaded");
188             };
189              
190 0           my $file = catfile($Fixtures, $name);
191              
192 0 0         if (! -f $file) {
193 0           bail_out("$file is not a file - fixture cannot be loaded");
194             }
195 0           my $contents = read_file($file);
196              
197 0           return $contents;
198             }
199              
200              
201             BEGIN {
202 1     1   9 no warnings 'redefine';
  1         3  
  1         131  
203              
204 1     1   6 *write_config_file= \&Test::Nginx::Util::write_config_file;
205              
206             *Test::Nginx::Util::write_config_file = sub ($$) {
207 0           write_config_file(@_);
208 0           close_random_ports();
209 1         70 };
210             }
211              
212             1;
213             __END__