# HG changeset patch # User Sergey Kandaurov # Date 1400055518 -14400 # Node ID 077ffeac825c201f917bdf046a985e247a6e69c6 # Parent 847ea345becb988796f4bd723ea0eee8b7e43cf4 Tests: image filter tests. diff --git a/image_filter.t b/image_filter.t new file mode 100644 --- /dev/null +++ b/image_filter.t @@ -0,0 +1,323 @@ +#!/usr/bin/perl + +# (C) Sergey Kandaurov +# (C) Nginx, Inc. + +# Tests for image filter module. + +############################################################################### + +use warnings; +use strict; + +use Test::More; + +use Socket qw/CRLF/; + +BEGIN { use FindBin; chdir($FindBin::Bin); } + +use lib 'lib'; +use Test::Nginx; + +############################################################################### + +select STDERR; $| = 1; +select STDOUT; $| = 1; + +eval { require GD; }; +plan(skip_all => 'GD not installed') if $@; + +my $t = Test::Nginx->new()->has(qw/http proxy map image/)->plan(39) + ->write_file_expand('nginx.conf', <<'EOF'); + +%%TEST_GLOBALS%% + +daemon off; + +events { +} + +http { + %%TEST_GLOBALS_HTTP%% + + map $arg_w $w { + "" '-'; + default $arg_w; + } + map $arg_h $h { + "" '-'; + default $arg_h; + } + + server { + listen 127.0.0.1:8080; + server_name localhost; + + location /size { + image_filter size; + alias %%TESTDIR%%/; + } + + location /test { + image_filter test; + alias %%TESTDIR%%/; + + location /test/off { + image_filter off; + alias %%TESTDIR%%/; + } + } + + location /resize { + image_filter resize 10 12; + alias %%TESTDIR%%/; + } + location /resize1 { + image_filter resize 10 -; + alias %%TESTDIR%%/; + } + location /resize2 { + image_filter resize - 12; + alias %%TESTDIR%%/; + } + location /resize_var { + image_filter resize $w $h; + alias %%TESTDIR%%/; + } + + location /rotate { + image_filter rotate 90; + alias %%TESTDIR%%/; + } + location /rotate_var { + image_filter rotate $arg_r; + alias %%TESTDIR%%/; + } + + location /crop { + image_filter crop 60 80; + alias %%TESTDIR%%/; + } + location /crop_var { + image_filter crop $arg_w $arg_h; + alias %%TESTDIR%%/; + } + location /crop_rotate { + image_filter crop $arg_w $arg_h; + image_filter rotate $arg_r; + alias %%TESTDIR%%/; + } + location /resize_rotate { + image_filter resize $w $h; + image_filter rotate $arg_r; + alias %%TESTDIR%%/; + + location /resize_rotate/resize { + image_filter resize 10 12; + alias %%TESTDIR%%/; + } + } + + location /interlaced { + image_filter resize 10 12; + image_filter_interlace on; + alias %%TESTDIR%%/; + } + + location /nontransparent { + image_filter resize 10 12; + image_filter_transparency off; + alias %%TESTDIR%%/; + } + + location /quality { + image_filter resize 10 12; + image_filter_jpeg_quality 50; + alias %%TESTDIR%%/; + } + location /quality_var { + image_filter resize 10 12; + image_filter_jpeg_quality $arg_q; + alias %%TESTDIR%%/; + + location /quality_var/quality { + image_filter_jpeg_quality 60; + alias %%TESTDIR%%/; + } + } + + location /buffer { + image_filter test; + image_filter_buffer 1k; + alias %%TESTDIR%%/; + } + location /proxy_buffer { + image_filter rotate 90; + image_filter_buffer 20; + proxy_pass http://127.0.0.1:8081/; + proxy_buffering off; + proxy_buffer_size 512; + } + } +} + +EOF + + +my $im = new GD::Image(100, 120); +my $white = $im->colorAllocate(255, 255, 255); +my $black = $im->colorAllocate(0, 0, 0); + +$im->transparent($white); +$im->rectangle(0, 0, 99, 99, $black); + +$t->write_file('jpeg', $im->jpeg); +$t->write_file('gif', $im->gif); +$t->write_file('png', $im->png); +$t->write_file('txt', 'SEE-THIS'); + +$t->run_daemon(\&http_daemon, $t->testdir()); +$t->run()->waitforsocket('127.0.0.1:8081'); + +############################################################################### + +like(http_head('/test/gif'), qr/200 OK/, 'test'); +like(http_head('/test/gif'), qr!Content-Type: image/gif!, 'test content-type'); +like(http_get('/test/txt'), qr/415 Unsupported/, 'test fail'); +like(http_get('/test/off/txt'), qr/SEE-THIS/, 'off'); + +is(http_get_body('/size/txt'), '{}' . CRLF, 'size wrong type'); +like(http_head('/size/txt'), qr!Content-Type: application/json!, + 'size content-type'); +like(http_get('/size/jpeg'), qr/"width": 100/, 'size width'); +like(http_get('/size/jpeg'), qr/"height": 120/, 'size height'); +like(http_get('/size/jpeg'), qr/"type": "jpeg"/, 'size jpeg'); +like(http_get('/size/gif'), qr/"type": "gif"/, 'size gif'); +like(http_get('/size/png'), qr/"type": "png"/, 'size png'); + +is(gif_size('/resize/gif'), '10 12', 'resize'); +is(gif_size('/resize1/gif'), '10 12', 'resize 1'); +is(gif_size('/resize2/gif'), '10 12', 'resize 2'); + +is(gif_size('/resize_var/gif?w=10&h=12'), '10 12', 'resize var'); +is(gif_size('/resize_var/gif?w=10'), '10 12', 'resize var 1'); +is(gif_size('/resize_var/gif?h=12'), '10 12', 'resize var 2'); + +is(gif_size('/rotate/gif?r=90'), '120 100', 'rotate'); +is(gif_size('/rotate_var/gif?r=180'), '100 120', 'rotate var 1'); +is(gif_size('/rotate_var/gif?r=270'), '120 100', 'rotate var 2'); + +$im = GD::Image->newFromGifData(http_get_body('/gif')); +is($im->interlaced, 0, 'gif interlaced off'); +is($im->transparent, 0, 'gif transparent white'); + +$im = GD::Image->newFromGifData(http_get_body('/interlaced/gif')); +is($im->interlaced, 1, 'gif interlaced on'); + +$im = GD::Image->newFromGifData(http_get_body('/nontransparent/gif')); +is($im->transparent, -1, 'gif transparent loss'); + +$im = GD::Image->newFromPngData(http_get_body('/png')); +is($im->interlaced, 0, 'png interlaced off'); +is($im->transparent, 0, 'png transparent white'); + +# this test produces libpng warning on STDERR: +# "Interlace handling should be turned on when using png_read_image" + +SKIP: { +skip 'can wedge nginx with SIGPIPE', 1 unless $ENV{TEST_NGINX_UNSAFE}; + +$im = GD::Image->newFromPngData(http_get_body('/interlaced/png')); +is($im->interlaced, 1, 'png interlaced on'); + +} + +$im = GD::Image->newFromPngData(http_get_body('/nontransparent/png')); +is($im->transparent, -1, 'png transparent loss'); + +like(http_get('/resize/jpeg'), qr/quality = 75/, 'quality default'); +like(http_get('/quality/jpeg'), qr/quality = 50/, 'quality'); +like(http_get('/quality_var/jpeg?q=40'), qr/quality = 40/, 'quality var'); +like(http_get('/quality_var/quality/jpeg?q=40'), qr/quality = 60/, + 'quality nested'); + +is(gif_size('/crop/gif'), '60 80', 'crop'); +is(gif_size('/crop_var/gif?w=10&h=20'), '10 20', 'crop var'); +is(gif_size('/crop_rotate/gif?w=5&h=6&r=90'), '5 5', 'rotate before crop'); +is(gif_size('/resize_rotate/gif?w=5&h=6&r=90'), '6 5', 'rotate after resize'); +is(gif_size('/resize_rotate/resize/gif??w=5&h=6&r=90'), '10 12', + 'resize rotate nested'); + +like(http_get('/buffer/jpeg'), qr/415 Unsupported/, 'small buffer'); +isnt(http_get('/proxy_buffer/jpeg'), undef, 'small buffer proxy'); + +############################################################################### + +sub gif_size { + join ' ', unpack("x6S2", http_get_body(@_)); +} + +sub http_get_body { + my ($uri) = @_; + + return undef if !defined $uri; + + my $text = http_get($uri); + + if ($text !~ /(.*?)\x0d\x0a?\x0d\x0a?(.*)/ms) { + return undef; + } + + return $2; +} + +############################################################################### + +# serve static files without Content-Length + +sub http_daemon { + my ($root) = @_; + + my $server = IO::Socket::INET->new( + Proto => 'tcp', + LocalHost => '127.0.0.1', + LocalPort => 8081, + Listen => 5, + Reuse => 1 + ) + or die "Can't create listening socket: $!\n"; + + local $SIG{PIPE} = 'IGNORE'; + + while (my $client = $server->accept()) { + $client->autoflush(1); + + my $headers = ''; + my $uri = ''; + + while (<$client>) { + $headers .= $_; + last if (/^\x0d?\x0a?$/); + } + + next if $headers eq ''; + $uri = $1 if $headers =~ /^\S+\s+([^ ]+)\s+HTTP/i; + + open my $fh, '<', $root . $uri or next; + local $/; + my $data = <$fh>; + close $fh; + + print $client <