-
-
06 Apr 2014 01:27:51 UTC
- Distribution: Test-Nginx
- Module version: 0.23
- Source (raw)
- Browse (raw)
- Changes
- How to Contribute
- Repository
- Issues (0)
- Testers (301 / 0 / 0)
- Kwalitee
Bus factor: 1- 29.26% Coverage
- License: bsd
- Perl: v5.6.1
- Activity
24 month- Tools
- Download (102.71KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
++ed by:1 non-PAUSE user- Dependencies
- Encode
- ExtUtils::MakeMaker
- Fcntl
- File::Find
- File::Path
- File::Temp
- Filter::Util::Call
- HTTP::Response
- IO::Select
- IO::Socket
- IO::Socket::INET
- LWP::UserAgent
- List::MoreUtils
- List::Util
- POSIX
- Test::Base
- Test::LongString
- Text::Diff
- Time::HiRes
- URI::Escape
- and possibly others
- Reverse dependencies
- CPAN Testers List
- Dependency graph
- NAME
- SYNOPSIS
- DESCRIPTION
- Exported Perl Functions
- Sections supported
- config
- http_config
- main_config
- post_main_config
- request
- request_eval
- pipelined_requests
- more_headers
- response_body
- response_body_eval
- response_body_like
- response_body_unlike
- response_headers
- response_headers_like
- raw_response_headers_like
- raw_response_headers_unlike
- error_code
- error_code_like
- timeout
- error_log
- abort
- shutdown
- no_error_log
- grep_error_log
- grep_error_log_out
- log_level
- raw_request
- http09
- ignore_response
- user_files
- skip_eval
- skip_nginx
- skip_nginx2
- stap
- stap_out
- stap_out_like
- stap_out_unlike
- wait
- udp_listen
- udp_reply
- udp_reply_delay
- udp_query
- tcp_listen
- tcp_no_close
- tcp_reply_delay
- tcp_reply
- tcp_query
- tcp_query_len
- raw_request_middle_delay
- no_check_leak
- Environment variables
- TEST_NGINX_VERBOSE
- TEST_NGINX_CHECK_LEAK
- TEST_NGINX_USE_HUP
- TEST_NGINX_POSTPONE_OUTPUT
- TEST_NGINX_NO_CLEAN
- TEST_NGINX_NO_NGINX_MANAGER
- TEST_NGINX_NO_SHUFFLE
- TEST_NGINX_USE_VALGRIND
- TEST_NGINX_USE_STAP
- TEST_NGINX_STAP_OUT
- TEST_NGINX_BINARY
- TEST_NGINX_LOG_LEVEL
- TEST_NGINX_MASTER_PROCESS
- TEST_NGINX_SERVER_PORT
- TEST_NGINX_CLIENT_PORT
- TEST_NGINX_PORT
- TEST_NGINX_SLEEP
- TEST_NGINX_FORCE_RESTART_ON_TEST
- TEST_NGINX_SERVROOT
- TEST_NGINX_IGNORE_MISSING_DIRECTIVES
- TEST_NGINX_EVENT_TYPE
- TEST_NGINX_ERROR_LOG
- Samples
- SOURCE REPOSITORY
- DEBIAN PACKAGES
- AUTHORS
- COPYRIGHT & LICENSE
- SEE ALSO
NAME
Test::Nginx::Socket - Socket-backed test scaffold for the Nginx C modules
SYNOPSIS
use Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * 3 * blocks(); no_shuffle(); run_tests(); __DATA__ === TEST 1: sanity --- config location /echo { echo_before_body hello; echo world; } --- request GET /echo --- response_body hello world --- error_code: 200 === TEST 2: set Server --- config location /foo { echo hi; more_set_headers 'Server: Foo'; } --- request GET /foo --- response_headers Server: Foo --- response_body hi === TEST 3: clear Server --- config location /foo { echo hi; more_clear_headers 'Server: '; } --- request GET /foo --- response_headers_like Server: nginx.* --- response_body hi === TEST 3: chunk size too small --- config chunkin on; location /main { echo_request_body; } --- more_headers Transfer-Encoding: chunked --- request eval "POST /main 4\r hello\r 0\r \r " --- error_code: 400 --- response_body_like: 400 Bad Request
DESCRIPTION
This module provides a test scaffold based on non-blocking IO::Socket for automated testing in Nginx C module development.
This class inherits from Test::Base, thus bringing all its declarative power to the Nginx C module testing practices.
You need to terminate or kill any Nginx processes before running the test suite if you have changed the Nginx server binary. Normally it's as simple as
killall nginx PATH=/path/to/your/nginx-with-memc-module:$PATH prove -r t
This module will create a temporary server root under t/servroot/ of the current working directory and starts and uses the nginx executable in the PATH environment.
You will often want to look into t/servroot/logs/error.log when things go wrong ;)
Exported Perl Functions
The following Perl functions are exported by default:
run_tests
This is the main entry point of the test scaffold. Calling this Perl function before
__DATA__
makes all the tests run. Other configuration Perl functions must be called before calling thisrun_tests
function.no_shuffle
By default, the test scaffold always shuffles the order of the test blocks automatically. Calling this function before calling
run_tests
will disable the suffling.no_long_string
By default, failed string equality test will use the Test::LongString module to generate the error message. Calling this function before calling
run_tests
will turn this off.no_diff
When the
no_long_string
function is called, theText::Diff
module will be used to generate a diff for failed string equality test. Calling thisno_diff
function before callingrun_tests
will turn this diff output format off and just generate the raw "got" text and "expected" text.worker_connections
Call this function before calling
run_tests
to set the Nginx'sworker_connections
configuration value. For example,worker_connections(1024); run_tests();
Default to 64.
repeat_each
Call this function with an integer argument before
run_tests()
to ask the test scaffold to run the specified number of duplicate requests for each test block. When it is called without argument, it returns the current setting.Default to 1.
workers
Call this function before
run_tests()
to configure Nginx'sworker_processes
directive's value. For example,workers(2);
Default to 1.
master_on
Call this function before
run_tests()
to turn on the Nginx master process.By default, the master process is not enabled unless in the "HUP reload" testing mode.
log_level
Call this function before
run_tests()
to set the default error log filtering level in Nginx.This global setting can be overridden by the per-test-block
--- log_level
sections.Default to
debug
.check_accum_error_log
Make
--- error_log
and--- no_error_log
check accumulated error log across duplicate requests controlled byrepeat_each
. By default, only the error logs belonging to the individualrepeat_each
request is tested.no_root_location
By default, the Nginx configuration file generated by the test scaffold automatically emits a
location /
. Calling this function beforerun_tests()
disables this behavior such that the test blocks can have their own root locations.Sections supported
The following sections are supported:
config
Content of this section will be included in the "server" part of the generated config file. This is the place where you want to put the "location" directive enabling the module you want to test. Example:
location /echo { echo_before_body hello; echo world; }
Sometimes you simply don't want to bother copying ten times the same configuration for the ten tests you want to run against your module. One way to do this is to write a config section only for the first test in your
.t
file. All subsequent tests will re-use the same config. Please note that this depends on the order of test, so you should runprove
with variableTEST_NGINX_NO_SHUFFLE=1
(see below for more on this variable).Please note that config section goes through environment variable expansion provided the variables to expand start with TEST_NGINX. So, the following is a perfectly legal (provided
TEST_NGINX_HTML_DIR
is set correctly):location /main { echo_subrequest POST /sub -f $TEST_NGINX_HTML_DIR/blah.txt; }
http_config
Content of this section will be included in the "http" part of the generated config file. This is the place where you want to put the "upstream" directive you might want to test. Example:
upstream database { postgres_server 127.0.0.1:$TEST_NGINX_POSTGRESQL_PORT dbname=ngx_test user=ngx_test password=wrong_pass; }
As you guessed from the example above, this section goes through environment variable expansion (variables have to start with TEST_NGINX).
main_config
Content of this section will be included in the "main" part (or toplevel) of the generated config file. This is very rarely used, except if you are testing nginx core itself. Everything in
--- main_config
will be put before thehttp {}
block generated automatically by the test scaffold.This section goes through environment variable expansion (variables have to start with TEST_NGINX).
post_main_config
Similar to
main_config
, but the content will be put after thehttp {}
block generated by this module.request
This is probably the most important section. It defines the request(s) you are going to send to the nginx server. It offers a pretty powerful grammar which we are going to walk through one example at a time.
In its most basic form, this section looks like that:
--- request GET
This will just do a GET request on the root (i.e. /) of the server using HTTP/1.1.
Of course, you might want to test something else than the root of your web server and even use a different version of HTTP. This is possible:
--- request GET /foo HTTP/1.0
Please note that specifying HTTP/1.0 will not prevent Test::Nginx from sending the
Host
header. Actually Test::Nginx always sends 2 headers:Host
(with value localhost) andConnection
(with value Close for simple requests and keep-alive for all but the last pipelined_requests).You can also add a content to your request:
--- request POST /foo Hello world
Test::Nginx will automatically calculate the content length and add the corresponding header for you.
This being said, as soon as you want to POST real data, you will be interested in using the more_headers section and using the power of Test::Base filters to urlencode the content you are sending. Which gives us a slightly more realistic example:
--- more_headers Content-type: application/x-www-form-urlencoded --- request eval use URI::Escape; "POST /rrd/foo value=".uri_escape("N:12345")
Sometimes a test is more than one request. Typically you want to POST some data and make sure the data has been taken into account with a GET. You can do it using arrays:
--- request eval ["POST /users name=foo", "GET /users/foo"]
This way, REST-like interfaces are pretty easy to test.
When you develop nifty nginx modules you will eventually want to test things with buffers and "weird" network conditions. This is where you split your request into network packets:
--- request eval [["POST /users\nna", "me=foo"]]
Here, Test::Nginx will first send the request line, the headers it automatically added for you and the first two letters of the body ("na" in our example) in ONE network packet. Then, it will send the next packet (here it's "me=foo"). When we talk about packets here, this is nto exactly correct as there is no way to guarantee the behavior of the TCP/IP stack. What Test::Nginx can guarantee is that this will result in two calls to
syswrite
.A good way to make almost sure the two calls result in two packets is to introduce a delay (let's say 2 seconds)before sending the second packet:
--- request eval [["POST /users\nna", {value => "me=foo", delay_before => 2}]]
Of course, everything can be combined till your brain starts boiling ;) :
--- request eval use URI::Escape; my $val="value=".uri_escape("N:12346"); [["POST /rrd/foo ".substr($val, 0, 6), {value => substr($val, 6, 5), delay_before=>5}, substr($val, 11)], "GET /rrd/foo"]
request_eval
Use of this section is deprecated and tests using it should replace it with a
request
section with aneval
filter. More explicitly:--- request_eval "POST /echo_body hello\x00\x01\x02 world\x03\x04\xff"
should be replaced by:
--- request eval "POST /echo_body hello\x00\x01\x02 world\x03\x04\xff"
pipelined_requests
Specify pipelined requests that use a single keep-alive connection to the server.
Here is an example from ngx_lua's test suite:
=== TEST 7: discard body --- config location = /foo { content_by_lua ' ngx.req.discard_body() ngx.say("body: ", ngx.var.request_body) '; } location = /bar { content_by_lua ' ngx.req.read_body() ngx.say("body: ", ngx.var.request_body) '; } --- pipelined_requests eval ["POST /foo hello, world", "POST /bar hiya, world"] --- response_body eval ["body: nil\n", "body: hiya, world\n"]
more_headers
Adds the content of this section as headers to the request being sent. Example:
--- more_headers X-Foo: blah
This will add
X-Foo: blah
to the request (on top of the automatically generated headers likeHost
,Connection
and potentiallyContent-Length
).response_body
The expected value for the body of the submitted request.
--- response_body hello
If the test is made of multiple requests, then the response_body MUST be an array and each request MUST return the corresponding expected body:
--- request eval ["GET /hello", "GET /world"] --- response_body eval ["hello", "world"]
response_body_eval
Use of this section is deprecated and tests using it should replace it with a
request
section with aneval
filter. Therefore:--- response_body_eval "hello\x00\x01\x02 world\x03\x04\xff"
should be replaced by:
--- response_body eval "hello\x00\x01\x02 world\x03\x04\xff"
response_body_like
The body returned by the request MUST match the pattern provided by this section. Example:
--- response_body_like ^elapsed 0\.00[0-5] sec\.$
If the test is made of multiple requests, then response_body_like MUST be an array and each request MUST match the corresponding pattern.
response_body_unlike
Just like
response_body_like
but this test only pass when the specified pattern does not match the actual response body data.response_headers
The headers specified in this section are in the response sent by nginx.
--- response_headers Content-Type: application/x-resty-dbd-stream
Of course, you can specify many headers in this section:
--- response_headers X-Resty-DBD-Module: Content-Type: application/x-resty-dbd-stream
The test will be successful only if all headers are found in the response with the appropriate values.
If the test is made of multiple requests, then response_headers MUST be an array and each element of the array is checked against the response to the corresponding request.
response_headers_like
The value of the headers returned by nginx match the patterns.
--- response_headers_like X-Resty-DBD-Module: ngx_drizzle \d+\.\d+\.\d+ Content-Type: application/x-resty-dbd-stream
This will check that the response's
Content-Type
is application/x-resty-dbd-stream and that theX-Resty-DBD-Module
matchesngx_drizzle \d+\.\d+\.\d+
.The test will be successful only if all headers are found in the response and if the values match the patterns.
If the test is made of multiple requests, then response_headers_like MUST be an array and each element of the array is checked against the response to the corresponding request.
raw_response_headers_like
Checks the headers part of the response against this pattern. This is particularly useful when you want to write tests of redirect functions that are not bound to the value of the port your nginx server (under test) is listening to:
--- raw_response_headers_like: Location: http://localhost(?::\d+)?/foo\r\n
As usual, if the test is made of multiple requests, then raw_response_headers_like MUST be an array.
raw_response_headers_unlike
Just like
raw_response_headers_like
but the subtest only passes when the regex does not match the raw response headers string.error_code
The expected value of the HTTP response code. If not set, this is assumed to be 200. But you can expect other things such as a redirect:
--- error_code: 302
If the test is made of multiple requests, then error_code MUST be an array with the expected value for the response status of each request in the test.
error_code_like
Just like
error_code
, but accepts a Perl regex as the value, for example:--- error_code_like: ^(?:500)?$
If the test is made of multiple requests, then error_code_like MUST be an array with the expected value for the response status of each request in the test.
timeout
Specify the timeout value (in seconds) for the HTTP client embedded into the test scaffold. This has nothing to do with the server side configuration. When the timeout expires, the test scaffold will immediately close the socket for connecting to the Nginx server being tested.
Note that, just as almost all the timeout settings in the Nginx world, this timeout also specifies the maximum waiting time between two successive I/O events on the same socket handle, rather than the total waiting time for the current socket operation.
When the timeout setting expires, a test failure will be triggered with the message "ERROR: client socket timed out - TEST NAME", unless you have specified
--- abort
at the same time.Here is an example:
=== TEST 1: test timeout --- location location = /t { echo_sleep 1; echo ok; } --- request GET /t --- response_body ok --- timeout: 1.5
An optional time unit can be specified, for example,
--- timeout: 50ms
Acceptable time units are
s
(seconds) andms
(milliseconds). If no time unit is specified, then default to seconds.error_log
Checks if the pattern or multiple patterns all appear in lines of the error.log file.
For example,
=== TEST 1: matched with j --- config location /re { content_by_lua ' m = ngx.re.match("hello, 1234", "([0-9]+)", "j") if m then ngx.say(m[0]) else ngx.say("not matched!") end '; } --- request GET /re --- response_body 1234 --- error_log: pcre JIT compiling result: 1
Then the substring "pcre JIT compiling result: 1" must appear literally in a line of error.log.
Multiple patterns are also supported, for example:
--- error_log eval ["abc", qr/blah/]
then the substring "abc" must appear literally in a line of error.log, and the regex
qr/blah
must also match a line in error.log.By default, only the part of the error logs corresponding to the current request is checked. You can make it check accumulated error logs by calling the
check_accum_error_log
Perl function before callingrun_tests
in the boilerplate Perl code above the__DATA__
line.abort
Makes the test scaffold not to treat
--- timeout
expiration as a test failure.shutdown
Perform a
shutdown
() operaton on the client socket connecting to Nginx as soon as sending out all the request data. This section takes an (optional) integer value for the argument to theshutdown
function call. For example,--- shutdown: 1
will make the connection stop sending data, which is the default.
no_error_log
Very much like the
--- error_log
section, but does the opposite test, i.e., pass only when the specified patterns of lines do not appear in the error.log file at all.Here is an example:
--- no_error_log [error]
This test will fail when any of the line in the error.log file contains the string
"[error]"
.Just like the
--- error_log
section, one can also specify multiple patterns:--- no_error_log eval ["abc", qr/blah/]
Then if any line in error.log contains the string
"abc"
or match the Perl regexqr/blah/
, then the test will fail.grep_error_log
This section specifies the Perl regex pattern for filtering out the Nginx error logs.
You can specify a verbatim substring being matched in the error log messages, as in
--- grep_error_log chop some thing we want to see
or specify a Perl regex object to match against the error log message lines, as in
--- grep_error_log eval qr/something should be: \d+/
All the matched substrings in the error log messages will be concatenated by a newline character as a whole to be compared with the value of the
--- grep_error_log_out
section.grep_error_log_out
This section contains the expected output for the filtering operations specified by the
--- grep_error_log
section.If the filtered output varies among the repeated requests (specified by the
repeat_each
function, then you can specify a Perl array as the value, as in--- grep_error_log_out eval ["output for req 0", "output for req 1"]
log_level
Overrides the default error log level for the current test block.
For example:
--- log_level: debug
The default error log level can be specified in the Perl code by calling the
log_level()
function, as inuse Test::Nginx::Socket; repeat_each(2); plan tests => repeat_each() * (3 * blocks()); log_level('warn'); run_tests(); __DATA__ ...
raw_request
The exact request to send to nginx. This is useful when you want to test soem behaviors that are not available with "request" such as an erroneous
Content-Length
header or splitting packets right in the middle of headers:--- raw_request eval ["POST /rrd/taratata HTTP/1.1\r Host: localhost\r Connection: Close\r Content-Type: application/", "x-www-form-urlencoded\r Content-Length:15\r\n\r\nvalue=N%3A12345"]
This can also be useful to tests "invalid" request lines:
--- raw_request GET /foo HTTP/2.0 THE_FUTURE_IS_NOW
http09
Specifies that the HTTP 0.9 protocol is used. This affects how
Test::Nginx::Socket
parses the response.Below is an example from ngx_headers_more module's test suite:
=== TEST 38: HTTP 0.9 (set) --- config location /foo { more_set_input_headers 'X-Foo: howdy'; echo "x-foo: $http_x_foo"; } --- raw_request eval "GET /foo\r\n" --- response_headers ! X-Foo --- response_body x-foo: --- http09
ignore_response
Do not attempt to parse the response or run the response related subtests.
user_files
With this section you can create a file that will be copied in the html directory of the nginx server under test. For example:
--- user_files >>> blah.txt Hello, world
will create a file named
blah.txt
in the html directory of the nginx server tested. The file will contain the text "Hello, world".skip_eval
Skip the specified number of subtests (in the current test block) if the result of running a piece of Perl code is true.
The format for this section is
--- skip_eval <subtest-count>: <perl-code>
For example, to skip 3 subtests when the current operating system is not Linux:
--- skip_eval 3: $^O ne 'linux'
or equivalently,
--- skip_eval: 3: $^O ne 'linux'
skip_nginx
Skip the specified number of subtests (in the current test block) for the specified version range of nginx.
The format for this section is
--- skip_nginx <subtest-count>: <op> <version>
The <subtest-count> value must be a positive integer. The <op> value could be either
>
,>=
,<
, or<=
. the <version> part is a valid nginx version number, like1.0.2
.An example is
=== TEST 1: sample --- config location /t { echo hello; } --- request GET /t --- response_body --- skip_nginx 2: < 0.8.54
That is, skipping 2 subtests in this test block for nginx versions older than 0.8.54.
This
skip_nginx
section only allows you to specify one boolean expression as the skip condition. If you want to use two boolean expressions, you should use theskip_nginx2
section instead.skip_nginx2
This seciton is similar to
skip_nginx
, but the skip condition consists of two boolean expressions joined by the operatorand
oror
.The format for this section is
--- skip_nginx2 <subtest-count>: <op> <version> and|or <op> <version>
For example:
=== TEST 1: sample --- config location /t { echo hello; } --- request GET /t --- response_body --- skip_nginx2 2: < 0.8.53 and >= 0.8.41
stap
This section is used to specify user systemtap script file (.stp file)
Here's an example:
=== TEST 1: stap sample --- config location /t { echo hello; } --- stap probe process("nginx").function("ngx_http_finalize_request") { printf("finalize %s?%s\n", ngx_http_req_uri($r), ngx_http_req_args($r)) } --- stap_out finalize /test?a=3&b=4 --- request GET /test?a=3&b=4 --- response_body hello
There's some macros that can be used in the "--- stap" section value. These macros will be expanded by the test scaffold automatically.
F(function_name)
-
This expands to
probe process("nginx").function("function_name")
. For example, the sample above can be rewritten as=== TEST 1: stap sample --- config location /t { echo hello; } --- stap F(ngx_http_finalize_request) { printf("finalize %s?%s\n", ngx_http_req_uri($r), ngx_http_req_args($r)) } --- stap_out finalize /test?a=3&b=4 --- request GET /test?a=3&b=4 --- response_body hello
T()
-
This macro will be expanded to
println("Fire ", pp())
. M(static-probe-name)
-
This macro will be expanded to
probe process("nginx").mark("static-probe-name")
.For example,
M(http-subrequest-start) { ... }
will be expanded to
probe process("nginx").mark("http-subrequest-start") { ... }
stap_out
This seciton specifies the expected literal output of the systemtap script specified by
stap
.stap_out_like
Just like
stap_out
, but specify a Perl regex pattern instead.stap_out_unlike
Just like
stap_like
, but the subtest only passes when the specified pattern does not match the output of the systemtap script.wait
Takes an integer value for the seconds of time to wait right after processing the Nginx response and before performing the error log and systemtap output checks.
udp_listen
Instantiates a UDP server listening on the port specified in the background for the test case to access. The server will be started and shut down at each iteration of the test case (if repeat_each is set to 3, then there are 3 iterations).
The UDP server will first read and discard a datagram and then send back a datagram with the content specified by the
udp_reply
section value.Here is an example:
=== TEST 1: udp access --- config location = /t { content_by_lua ' local udp = ngx.socket.udp() udp:setpeername("127.0.0.1", 19232) udp:send("blah") local data, err = udp:receive() ngx.say("received: ", data) '; } --- udp_listen: 19232 --- udp_reply: hello world --- request GET /t --- response_body received: hello world
Datagram UNIX domain socket is also supported if a path name ending with ".sock" is given to this directive. For instance,
=== TEST 2: datagram unix domain socket access --- config location = /t { content_by_lua ' local udp = ngx.socket.udp() udp:setpeername("unix:a.sock") udp:send("blah") local data, err = udp:receive() ngx.say("received: ", data) '; } --- udp_listen: a.sock --- udp_reply: hello world --- request GET /t --- response_body received: hello world
udp_reply
This section specifies the datagram reply content for the UDP server created by the
udp_listen
section.You can also specify a delay time before sending out the reply via the
udp_reply_delay
section. By default, there is no delay.An array value can be specified to make the embedded UDP server to send mulitple replies as specified, for example:
--- udp_reply eval [ "hello", "world" ]
See the
udp_listen
section for more details.udp_reply_delay
This section specifies the delay time before sending out the reply specified by the
udp_reply
section.It is
0
delay by default.An optional time unit can be specified, for example,
--- udp_reply_delay: 50ms
Acceptable time units are
s
(seconds) andms
(milliseconds). If no time unit is specified, then default to seconds.udp_query
Tests whether the UDP query sent to the embedded UDP server is equal to what is specified by this directive.
For example,
=== TEST 1: udp access --- config location = /t { content_by_lua ' local udp = ngx.socket.udp() udp:setpeername("127.0.0.1", 19232) udp:send("blah") local data, err = udp:receive() ngx.say("received: ", data) '; } --- udp_listen: 19232 --- udp_reply: hello world --- request GET /t --- udp_query: hello world --- response_body received: hello world
tcp_listen
Just like
udp_listen
, but starts an embedded TCP server listening on the port specified. For example,--- tcp_listen: 12345
Stream-typed unix domain socket is also supported. Just specify the path to the socket file, as in
--- tcp_listen: /tmp/my-socket.sock
tcp_no_close
When this section is present, the embedded TCP server (if any) will not close the current TCP connection.
tcp_reply_delay
Just like
udp_reply_delay
, but for the embedded TCP server.tcp_reply
Just like
tcp_reply
, but for the embedded TCP server.tcp_query
Just like
udp_query
, but for the embedded TCP server.tcp_query_len
Specifies the expected TCP query received by the embedded TCP server.
raw_request_middle_delay
Delay in sec between sending successive packets in the "raw_request" array value. Also used when a request is split in packets.
no_check_leak
Skip the tests in the current test block in the "check leak" testing mode (i.e, with
TEST_NGINX_CHECK_LEAK
=1).Environment variables
All environment variables starting with
TEST_NGINX_
are expanded in the sections used to build the configuration of the server that tests automatically starts. The following environment variables are supported by this module:TEST_NGINX_VERBOSE
Controls whether to output verbose debugging messages in Test::Nginx. Default to empty.
TEST_NGINX_CHECK_LEAK
When set to 1, the test scaffold performs the most general memory leak test by means of calling
weighttpd
/ab
andps
.Specifically, it starts
weighttp
(for HTTP 1.1GET
requests) orab
(for HTTP 1.0 requests) to repeatedly hitting Nginx for seconds in a sub-process, and then after about 1 second, it will start sampling the RSS value of the Nginx process by calling theps
utility every 20 ms. Finally, it will output all the sample point data and the line slope of the linear regression result on the 100 sample points.One typical output for non-leaking test cases:
t/075-logby.t .. 3/17 TEST 2: log_by_lua_file LeakTest: [2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176 2176] LeakTest: k=0.0
and here is an example of leaking:
TEST 5: ngx.ctx available in log_by_lua (not defined yet) LeakTest: [4396 4440 4476 4564 4620 4708 4752 4788 4884 4944 4996 5032 5080 5132 5188 5236 5348 5404 5464 5524 5596 5652 5700 5776 5828 5912 5964 6040 6108 6108 6316 6316 6584 6672 6672 6752 6820 6912 6912 6980 7064 7152 7152 7240 7340 7340 7432 7508 7508 7600 7700 7700 7792 7896 7896 7992 7992 8100 8100 8204 8296 8296 8416 8416 8512 8512 8624 8624 8744 8744 8848 8848 8968 8968 9084 9084 9204 9204 9324 9324 9444 9444 9584 9584 9704 9704 9832 9832 9864 9964 9964 10096 10096 10488 10488 10488 10488 10488 11052 11052] LeakTest: k=64.1
Even very small leaks can be amplified and caught easily by this testing mode because their slopes will usually be far above
1.0
.For now, only
GET
,POST
,PUT
, andHEAD
requests are supported (due to the limited HTTP support in bothab
andweighttp
). Other methods specified in the test cases will turn toGET
with force.The tests in this mode will always succeed because this mode also enforces the "dry-run" mode.
Test blocks carrying the "--- no_check_leak" directive will be skipped in this testing mode.
TEST_NGINX_USE_HUP
When set to 1, the test scaffold will try to send
HUP
signal to the Nginx master process to reload the config file between successive test blocks (but not successiverepeast_each
sub-tests within the same test block). When this envirnoment is set to 1, it will also enfornce the "master_process on" config line in the nginx.conf file, because Nginx is buggy in processing HUP signal when the master process is off.TEST_NGINX_POSTPONE_OUTPUT
Defaults to empty. This environment takes positive integer numbers as its value and it will cause the auto-generated nginx.conf file to have a "postpone_output" setting in the http {} block.
For example, setting TEST_NGINX_POSTPONE_OUTPUT to 1 will have the following line in nginx.conf's http {} block:
postpone_output 1;
and it will effectively disable the write buffering in nginx's ngx_http_write_module.
TEST_NGINX_NO_CLEAN
When this environment is set to 1, it will prevent the test scaffold from quitting the Nginx server at the end of the run. This is very useful when you want to use other tools like gdb or curl inspect the Nginx server manually afterwards.
TEST_NGINX_NO_NGINX_MANAGER
Defaults to 0. If set to 1, Test::Nginx module will not manage (configure/start/stop) the
nginx
process. Can be useful to run tests against an already configured (and running) nginx server.TEST_NGINX_NO_SHUFFLE
Dafaults to 0. If set to 1, will make sure the tests are run in the order they appear in the test file (and not in random order).
TEST_NGINX_USE_VALGRIND
If set, Test::Nginx will start nginx with valgrind with the the value of this environment as the options.
Nginx is actually started with
valgrind -q $TEST_NGINX_USE_VALGRIND --gen-suppressions=all --suppressions=valgrind.suppress
, the suppressions option being used only if there is actually a valgrind.suppress file.If this environment is set to the number
1
or any other non-zero numbers, then it is equivalent to taking the value--tool=memcheck --leak-check=full
.TEST_NGINX_USE_STAP
When set to true values (like 1), the test scaffold will use systemtap to instrument the nginx process.
You can specify the stap script in the
stap
section.Note that you need to use the
stap-nginx
script from thenginx-dtrace
project.TEST_NGINX_STAP_OUT
You can specify the output file for the systemtap tool. By default, a random file name under the system temporary directory is generated.
It's common to specify
TEST_NGINX_STAP_OUT=/dev/stderr
when debugging.TEST_NGINX_BINARY
The command to start nginx. Defaults to
nginx
. Can be used as an alternative to settingPATH
to run a specific nginx instance.TEST_NGINX_LOG_LEVEL
Value of the last argument of the
error_log
configuration directive. Defaults todebug
.TEST_NGINX_MASTER_PROCESS
Value of the
master_process
configuration directive. Defaults tooff
.TEST_NGINX_SERVER_PORT
Value of the port the server started by Test::Nginx will listen to. If not set,
TEST_NGINX_PORT
is used. IfTEST_NGINX_PORT
is not set, then1984
is used. See below for typical use.TEST_NGINX_CLIENT_PORT
Value of the port Test::Nginx will diirect requests to. If not set,
TEST_NGINX_PORT
is used. IfTEST_NGINX_PORT
is not set, then1984
is used. A typical use of this feature is to test extreme network conditions by adding a "proxy" between Test::Nginx and nginx itself. This is described in theetcproxy integration
section of this module README.TEST_NGINX_PORT
A shortcut for setting both
TEST_NGINX_CLIENT_PORT
andTEST_NGINX_SERVER_PORT
.TEST_NGINX_SLEEP
How much time (in seconds) should Test::Nginx sleep between two calls to
syswrite
when sending request data. Defaults to 0.TEST_NGINX_FORCE_RESTART_ON_TEST
Defaults to 1. If set to 0, Test::Nginx will not restart the nginx server when the config does not change between two tests.
TEST_NGINX_SERVROOT
The root of the nginx "hierarchy" (where you find the conf, *_tmp and logs directories). This value will be used with the
-p
option ofnginx
. Defaults to appendingt/servroot
to the current directory.TEST_NGINX_IGNORE_MISSING_DIRECTIVES
If set to 1 will SKIP all tests which
config
sections resulted in aunknown directive
when trying to startnginx
. Useful when you want to run tests on a build of nginx that does not include all modules it should. By default, these tests will FAIL.TEST_NGINX_EVENT_TYPE
This environment can be used to specify a event API type to be used by Nginx. Possible values are
epoll
,kqueue
,select
,rtsig
,poll
, and others.For example,
$ TEST_NGINX_EVENT_TYPE=select prove -r t
TEST_NGINX_ERROR_LOG
Error log files from all tests will be appended to the file specified with this variable. There is no default value which disables the feature. This is very useful when debugging. By default, each test triggers a start/stop cycle for
nginx
. All logs are removed before each restart, so you can only see the logs for the last test run (which you usually do not control except if you setTEST_NGINX_NO_SHUFFLE=1
). With this, you accumulate all logs into a single file that is never cleaned up by Test::Nginx.Samples
You'll find live samples in the following Nginx 3rd-party modules:
- ngx_echo
- ngx_chunkin
- ngx_memc
- ngx_drizzle
- ngx_rds_json
- ngx_xss
- ngx_srcache
- ngx_lua
- ngx_set_misc
- ngx_array_var
- ngx_form_input
- ngx_iconv
- ngx_set_cconv
- ngx_postgres
- 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.
DEBIAN PACKAGES
António P. P. Almeida is maintaining a Debian package for this module in his Debian repository: http://debian.perusio.net
AUTHORS
Yichun "agentzh" Zhang (章亦春)
<agentzh@gmail.com>
, CloudFlare Inc.Antoine BONAVITA
<antoine.bonavita@gmail.com>
COPYRIGHT & LICENSE
Copyright (c) 2009-2014, Yichun Zhang
<agentzh@gmail.com>
, CloudFlare Inc.Copyright (c) 2011-2012, 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 authors 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
Module Install Instructions
To install Test::Nginx, copy and paste the appropriate command in to your terminal.
cpanm Test::Nginx
perl -MCPAN -e shell install Test::Nginx
For more information on module installation, please visit the detailed CPAN module installation guide.