NAME

Nginx::Test - simple framework for writing tests for nginx-perl and nginx

SYNOPSIS

use Nginx::Test;
 
my $nginx = find_nginx_perl;
my $dir   = 'tmp/test';

my ($child, $peer) = 
    fork_nginx_handler_die  $nginx, $dir, '', <<'END';
    
    sub handler {
        my $r = shift;
        ...
         
        return OK;
    }
    
END

wait_for_peer $peer, 2
    or die "peer never started\n";

my ($body, $headers) = http_get $peer, "/", 2;
...

DESCRIPTION

Making sure testing isn't a nightmare.

This module provides some basic functions to find nginx-perl, prepare configuration, generate handler, start in a child process, query it and get something back. And it comes with Nginx::Perl. You can simply add it as a dependency for you module and use.

EXPORT

find_nginx_perl
get_nginx_conf_args_die
get_unused_port 
wait_for_peer 
prepare_nginx_dir_die
cat_nginx_logs
fork_nginx_die
fork_child_die
fork_nginx_handler_die
http_get

FUNCTIONS

$nginx = find_nginx_perl ();

Finds executable nginx-perl binary to run. Returns undef if can't find any or executable path otherwise.

$nginx = './objs/nginx-perl'

%CONFARGS = get_nginx_conf_args_dir $nginx;

Runs nginx-perl -V and parses its output to produce set of keys out of the list of configure arguments:

%CONFARGS = ( '--with-http_ssl_module' => 1,
              '--with-...'             => 1  )

$port = get_unused_port ();

Gives you available port number to bind to. Tries to use it first. Returns undef on error.

$rv = wait_for_peer "$host:$port", $timeout;

Tries to connect to $host:$port within $timeout. Returns 1 on success and undef on error.

wait_for_peer "127.0.0.1:1234", 2
    or ...;

prepare_nginx_dir_die $dir, $conf, $package1, $package2, ...;

Creates directory tree suitable to run nginx-perl from. Puts there config and packages specified as string scalars. Dies on errors.

prepare_nginx_dir_die "tmp/foo", <<'ENDCONF', <<'ENDONETWO';

    worker_processes  1;
    events {  
        worker_connections  1024;  
    }
    http {
        server {
            location / {
                ...
            }
        }
    }
 
ENDCONF

    package One::Two;
    
    sub handler {
        ...
    }
    
    1;

ENDONETWO

$text = cat_nginx_logs $dir;

Scans $dir for logs and concatenates them into a single scalar. Useful for diagnostics.

prepate_nginx_dir_dir $dir, ... 
...

ok $foo, "bar", "foo is bar"
    or diag cat_nginx_logs $dir;

$child = fork_nginx_die $nginx, $dir;

Forks nginx-perl using executable binary from $nginx and prepared directory path from $dir. Dies on errors. Internally does something like this: "$nginx -p $dir"

my $child = fork_nginx_die $nginx, $dir;
...
 
undef $child;

$child = fork_child_die sub { ... };

Forks sub in a child process. Dies on errors.

my $child = fork_child_die sub {
    ...
     
    sleep 5;  
};
...
 
undef $child;

@incs = get_nginx_incs $nginx, $dir;

Generates proper @INC to use in nginx-perl.conf during tests.

($child, $peer) = fork_nginx_handler_dir $nginx, $dir, $conf, $code;

Gets unused port, prepares directory for nginx with predefined package name, forks nginx and gives you child object and peer back. Allows to inject $conf into config and $code into the package. Expects to have sub handler { ... } in the code. Dies on errors.

my ($child, $peer) = 
    fork_nginx_handler_die $nginx, $dir, <<'ENDCONF', <<'ENDCODE';
    
    resolver 8.8.8.8;
    
ENDCONF

    sub handler {
        my ($r) = @_;
        ...
        
        return OK;
    }
    
ENDCODE

...
 
undef $child; 

Be aware that this function is not suited for every module. It expects $dir to be relative to the current directory or any of its subdirectories, i.e. foo, foo/bar. And also expects blib/lib and blib/arch to contain your libraries, which is where ExtUtils::MakeMaker puts them.

($body, $headers) = http_get $peer, $uri, $timeout;

Connects to $peer, sends GET request and return $body and $headers.

my ($body, $headers) = http_get '127.0.0.1:1234', '/', 2;

$headers = {  _status        => 200,
              _message       => 'OK',
              _version       => 'HTTP/1.0',
              content-type   => ['text/html'],
              content-length => [1234],
              ...                               }

AUTHOR

Alexandr Gomoliako <zzz@zzz.org.ua>

LICENSE

Copyright 2011 Alexandr Gomoliako. All rights reserved.

This module is free software. It may be used, redistributed and/or modified under the same terms as nginx itself.