NAME
    Test::Nginx - Testing modules for Nginx C module development

DESCRIPTION
    This distribution provides two testing modules for Nginx C module
    development:

    *   Test::Nginx::LWP

    *   Test::Nginx::Socket

    All of them are based on Test::Base.

    Usually, Test::Nginx::Socket is preferred because it works on a much
    lower level and not that fault tolerant like Test::Nginx::LWP.

    Also, a lot of connection hang issues (like wrong "r->main->count" value
    in nginx 0.8.x) can only be captured by Test::Nginx::Socket because
    Perl's LWP::UserAgent client will close the connection itself which will
    conceal such issues from the testers.

    Test::Nginx automatically starts an nginx instance (from the "PATH" env)
    rooted at t/servroot/ and the default config template makes this nginx
    instance listen on the port 1984 by default. One can specify a different
    port number by setting his port number to the "TEST_NGINX_PORT"
    environment, as in

        export TEST_NGINX_PORT=1989

  etcproxy integration
    The default settings in etcproxy
    (https://github.com/chaoslawful/etcproxy) makes this small TCP proxy
    split the TCP packets into bytes and introduce 1 ms latency among them.

    There's usually various TCP chains that we can put etcproxy into, for
    example

   Test::Nginx <=> nginx
      $ ./etcproxy 1234 1984

    Here we tell etcproxy to listen on port 1234 and to delegate all the TCP
    traffic to the port 1984, the default port that Test::Nginx makes nginx
    listen to.

    And then we tell Test::Nginx to test against the port 1234, where
    etcproxy listens on, rather than the port 1984 that nginx directly
    listens on:

      $ TEST_NGINX_CLIENT_PORT=1234 prove -r t/

    Then the TCP chain now looks like this:

      Test::Nginx <=> etcproxy (1234) <=> nginx (1984)

    So etcproxy can effectively emulate extreme network conditions and
    exercise "unusual" code paths in your nginx server by your tests.

    In practice, *tons* of weird bugs can be captured by this setting. Even
    ourselves didn't expect that this simple approach is so effective.

   nginx <=> memcached
    We first start the memcached server daemon on port 11211:

       memcached -p 11211 -vv

    and then we another etcproxy instance to listen on port 11984 like this

       $ ./etcproxy 11984 11211

    Then we tell our t/foo.t test script to connect to 11984 rather than
    11211:

      # foo.t
      use Test::Nginx::Socket;
      repeat_each(1);
      plan tests => 2 * repeat_each() * blocks();
      $ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;  # make this env take a default value
      run_tests();

      __DATA__

      === TEST 1: sanity
      --- config
      location /foo {
           set $memc_cmd set;
           set $memc_key foo;
           set $memc_value bar;
           memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT;
      }
      --- request
          GET /foo
      --- response_body_like: STORED

    The Test::Nginx library will automatically expand the special macro
    $TEST_NGINX_MEMCACHED_PORT to the environment with the same name. You
    can define your own $TEST_NGINX_BLAH_BLAH_PORT macros as long as its
    prefix is "TEST_NGINX_" and all in upper case letters.

    And now we can run your test script against the etcproxy port 11984:

       TEST_NGINX_MEMCACHED_PORT=11984 prove t/foo.t

    Then the TCP chains look like this:

       Test::Nginx <=> nginx (1984) <=> etcproxy (11984) <=> memcached (11211)

    If "TEST_NGINX_MEMCACHED_PORT" is not set, then it will take the default
    value 11211, which is what we want when there's no etcproxy configured:

       Test::Nginx <=> nginx (1984) <=> memcached (11211)

    This approach also works for proxied mysql and postgres traffic. Please
    see the live test suite of ngx_drizzle and ngx_postgres for more
    details.

    Usually we set both "TEST_NGINX_CLIENT_PORT" and
    "TEST_NGINX_MEMCACHED_PORT" (and etc) at the same time, effectively
    yielding the following chain:

       Test::Nginx <=> etcproxy (1234) <=> nginx (1984) <=> etcproxy (11984) <=> memcached (11211)

    as long as you run two separate etcproxy instances in two separate
    terminals.

    It's easy to verify if the traffic actually goes through your etcproxy
    server. Just check if the terminal running etcproxy emits outputs. By
    default, etcproxy always dump out the incoming and outgoing data to
    stdout/stderr.

  valgrind integration
    Test::Nginx has integrated support for valgrind (<http://valgrind.org>)
    even though by default it does not bother running it with the tests
    because valgrind will significantly slow down the test sutie.

    First ensure that your valgrind executable visible in your PATH env. And
    then run your test suite with the "TEST_NGINX_USE_VALGRIND" env set to
    true:

       TEST_NGINX_USE_VALGRIND=1 prove -r t

    If you see false alarms, you do have a chance to skip them by defining a
    ./valgrind.suppress file at the root of your module source tree, as in

    <https://github.com/chaoslawful/drizzle-nginx-module/blob/master/valgrin
    d.suppress>

    This is the suppression file for ngx_drizzle. Test::Nginx will
    automatically use it to start nginx with valgrind memcheck if this file
    does exist at the expected location.

    If you do see a lot of "Connection refused" errors while running the
    tests this way, then you probably have a slow machine (or a very busy
    one) that the default waiting time is not sufficient for valgrind to
    start. You can define the sleep time to a larger value by setting the
    "TEST_NGINX_SLEEP" env:

       TEST_NGINX_SLEEP=1 prove -r t

    The time unit used here is "second". The default sleep setting just fits
    my ThinkPad ("Core2Duo T9600").

    Applying the no-pool patch to your nginx core is recommended while
    running nginx with valgrind:

    <https://github.com/shrimp/no-pool-nginx>

    The nginx memory pool can prevent valgrind from spotting lots of invalid
    memory reads/writes as well as certain double-free errors. We did find a
    lot more memory issues in many of our modules when we first introduced
    the no-pool patch in practice ;)

    There's also more advanced features in Test::Nginx that have never
    documented. I'd like to write more about them in the near future ;)

Nginx C modules that use Test::Nginx to drive their test suites
    ngx_echo
        <http://github.com/agentzh/echo-nginx-module>

    ngx_headers_more
        <http://github.com/agentzh/headers-more-nginx-module>

    ngx_chunkin
        <http://wiki.nginx.org/NginxHttpChunkinModule>

    ngx_memc
        <http://wiki.nginx.org/NginxHttpMemcModule>

    ngx_drizzle
        <http://github.com/chaoslawful/drizzle-nginx-module>

    ngx_rds_json
        <http://github.com/agentzh/rds-json-nginx-module>

    ngx_xss
        <http://github.com/agentzh/xss-nginx-module>

    ngx_srcache
        <http://github.com/agentzh/srcache-nginx-module>

    ngx_lua
        <http://github.com/chaoslawful/lua-nginx-module>

    ngx_set_misc
        <http://github.com/agentzh/set-misc-nginx-module>

    ngx_array_var
        <http://github.com/agentzh/array-var-nginx-module>

    ngx_form_input
        <http://github.com/calio/form-input-nginx-module>

    ngx_iconv
        <http://github.com/calio/iconv-nginx-module>

    ngx_set_cconv
        <http://github.com/liseen/set-cconv-nginx-module>

    ngx_postgres
        <http://github.com/FRiCKLE/ngx_postgres>

    ngx_coolkit
        <http://github.com/FRiCKLE/ngx_coolkit>

SOURCE REPOSITORY
    This module has a Git repository on Github, which has access for all.

        http://github.com/agentzh/test-nginx

    If you want a commit bit, feel free to drop me a line.

AUTHORS
    agentzh (章亦春) "<agentzh@gmail.com>"

    Antoine BONAVITA "<antoine.bonavita@gmail.com>"

COPYRIGHT & LICENSE
    Copyright (c) 2009-2011, Taobao Inc., Alibaba Group
    (<http://www.taobao.com>).

    Copyright (c) 2009-2011, agentzh "<agentzh@gmail.com>".

    Copyright (c) 2011, Antoine Bonavita "<antoine.bonavita@gmail.com>".

    This module is licensed under the terms of the BSD license.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are
    met:

    *   Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.

    *   Redistributions in binary form must reproduce the above copyright
        notice, this list of conditions and the following disclaimer in the
        documentation and/or other materials provided with the distribution.

    *   Neither the name of the Taobao Inc. nor the names of its
        contributors may be used to endorse or promote products derived from
        this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

SEE ALSO
    Test::Nginx::LWP, Test::Nginx::Socket, Test::Base.

