httpthumbnailer 0.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -11
- data/Gemfile.lock +75 -51
- data/README.md +184 -54
- data/VERSION +1 -1
- data/bin/httpthumbnailer +76 -133
- data/features/httpthumbnailer.feature +11 -260
- data/features/step_definitions/httpthumbnailer_steps.rb +89 -44
- data/features/support/env.rb +22 -9
- data/features/support/test-large.jpg +0 -0
- data/features/thumbnail.feature +241 -0
- data/features/thumbnails.feature +142 -0
- data/httpthumbnailer.gemspec +39 -40
- data/lib/httpthumbnailer/error_reporter.rb +38 -0
- data/lib/httpthumbnailer/plugin/thumbnailer.rb +396 -0
- data/lib/httpthumbnailer/thumbnail_specs.rb +50 -47
- data/lib/httpthumbnailer/thumbnailer.rb +52 -229
- data/load_test/load_test-cd9679c.csv +10 -0
- data/load_test/load_test-v0.3.1.csv +10 -0
- data/load_test/load_test.jmx +49 -34
- data/load_test/soak_test-ac0c6bcbe5e-broken-libjpeg-tatoos.csv +11 -0
- data/load_test/soak_test-cd9679c.csv +10 -0
- data/load_test/soak_test-f98334a-tatoos.csv +11 -0
- data/load_test/soak_test.jmx +697 -0
- data/spec/image_processing_spec.rb +148 -0
- data/spec/spec_helper.rb +4 -1
- data/spec/thumbnail_specs_spec.rb +18 -5
- metadata +101 -71
- data/lib/httpthumbnailer/multipart_response.rb +0 -45
- data/spec/multipart_response_spec.rb +0 -95
- data/spec/thumbnailer_spec.rb +0 -33
@@ -1,14 +1,7 @@
|
|
1
|
-
Given /httpthumbnailer log is empty/ do
|
2
|
-
(support_dir + 'server.log').truncate(0)
|
3
|
-
end
|
4
|
-
|
5
1
|
Given /httpthumbnailer server is running at (.*)/ do |url|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
support_dir + 'server.log',
|
10
|
-
url
|
11
|
-
)
|
2
|
+
log = support_dir + 'server.log'
|
3
|
+
cmd = "bundle exec #{script('httpthumbnailer')} -f -d -l #{log} -w 1"
|
4
|
+
start_server(cmd, '/tmp/httpthumbnailer.pid', log, url)
|
12
5
|
end
|
13
6
|
|
14
7
|
Given /(.*) file content as request body/ do |file|
|
@@ -16,61 +9,90 @@ Given /(.*) file content as request body/ do |file|
|
|
16
9
|
end
|
17
10
|
|
18
11
|
When /I do (.*) request (.*)/ do |method, url|
|
19
|
-
@response =
|
12
|
+
@response = http_client.request(method, url, nil, @request_body)
|
20
13
|
end
|
21
14
|
|
22
|
-
|
15
|
+
When /I save response body/ do
|
16
|
+
@saved_response_body = @response.body
|
17
|
+
end
|
18
|
+
|
19
|
+
Then /(.*) header should be (.*)/ do |header, value|
|
23
20
|
@response.header[header].should_not be_empty
|
24
21
|
@response.header[header].first.should == value
|
25
22
|
end
|
26
23
|
|
27
|
-
Then /I
|
24
|
+
Then /I should get multipart response/ do
|
28
25
|
@response.header['Content-Type'].first.should match /^multipart/
|
29
|
-
|
26
|
+
parser = MultipartParser::Reader.new(MultipartParser::Reader.extract_boundary_value(@response.header['Content-Type'].last))
|
27
|
+
@response_multipart = []
|
28
|
+
|
29
|
+
parser.on_part do |part|
|
30
|
+
part_struct = OpenStruct.new
|
31
|
+
part_struct.headers = part.headers
|
32
|
+
|
33
|
+
part_struct.body = ''
|
34
|
+
part.on_data do |data|
|
35
|
+
part_struct.body << data
|
36
|
+
end
|
37
|
+
|
38
|
+
part.on_end do
|
39
|
+
@response_multipart << part_struct
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
parser.write @response.body
|
44
|
+
|
45
|
+
parser.ended?.should be_true
|
46
|
+
@response_multipart.should_not be_empty
|
30
47
|
end
|
31
48
|
|
32
|
-
Then /response body
|
49
|
+
Then /response body should be CRLF endend lines like/ do |body|
|
33
50
|
@response.body.should match(body)
|
34
|
-
@response.body.
|
51
|
+
@response.body.each_line do |line|
|
35
52
|
line[-2,2].should == "\r\n"
|
36
53
|
end
|
37
54
|
end
|
38
55
|
|
39
|
-
Then /response body
|
56
|
+
Then /response body should be CRLF endend lines$/ do |body|
|
40
57
|
@response.body.should == body.gsub("\n", "\r\n") + "\r\n"
|
41
58
|
end
|
42
59
|
|
43
|
-
Then /response status
|
60
|
+
Then /response status should be (.*)/ do |status|
|
44
61
|
@response.status.should == status.to_i
|
45
62
|
end
|
46
63
|
|
47
|
-
Then /response content type
|
64
|
+
Then /response content type should be (.*)/ do |content_type|
|
48
65
|
@response.header['Content-Type'].first.should == content_type
|
49
66
|
end
|
50
67
|
|
51
|
-
Then /
|
52
|
-
|
68
|
+
Then /response mime type should be (.*)/ do |mime_type|
|
69
|
+
step "response content type should be #{mime_type}"
|
70
|
+
end
|
71
|
+
|
72
|
+
Then /(.*) part mime type should be (.*)/ do |part, mime|
|
73
|
+
@response_multipart[part_no(part)].headers['content-type'].should == mime
|
74
|
+
end
|
75
|
+
|
76
|
+
Then /(.*) part content type should be (.*)/ do |part, content_type|
|
77
|
+
@response_multipart[part_no(part)].headers['content-type'].should == content_type
|
53
78
|
end
|
54
79
|
|
55
|
-
Then /(.*) part
|
56
|
-
@response_multipart
|
80
|
+
Then /(.*) part status should be (.*)/ do |part, status|
|
81
|
+
@response_multipart[part_no(part)].headers['status'].should == status
|
57
82
|
end
|
58
83
|
|
59
|
-
Then /(.*) part body
|
60
|
-
@response_multipart
|
84
|
+
Then /(.*) part body should be CRLF endend lines$/ do |part, body|
|
85
|
+
@response_multipart[part_no(part)].body.should == body.gsub("\n", "\r\n")
|
61
86
|
end
|
62
87
|
|
63
|
-
Then /(.*) part body
|
64
|
-
pbody = @response_multipart
|
88
|
+
Then /(.*) part body should be CRLF endend lines like$/ do |part, body|
|
89
|
+
pbody = @response_multipart[part_no(part)].body
|
65
90
|
pbody.should match(body)
|
66
|
-
pbody.each do |line|
|
67
|
-
line[-2,2].should == "\r\n"
|
68
|
-
end
|
69
91
|
end
|
70
92
|
|
71
|
-
Then /
|
72
|
-
mime = @
|
73
|
-
data = @
|
93
|
+
Then /response should contain (.*) image of size (.*)x(.*)/ do |format, width, height|
|
94
|
+
mime = @response.header['Content-Type'].first
|
95
|
+
data = @response.body
|
74
96
|
fail("expecte image got #{mime}: #{data}") unless mime =~ /^image\//
|
75
97
|
|
76
98
|
@image.destroy! if @image
|
@@ -81,27 +103,50 @@ Then /(.*) part will contain (.*) image of size (.*)x(.*)/ do |part, format, wid
|
|
81
103
|
@image.rows.should == height.to_i
|
82
104
|
end
|
83
105
|
|
84
|
-
|
85
|
-
|
86
|
-
|
106
|
+
|
107
|
+
Then /(.*) part should contain (.*) image of size (.*)x(.*)/ do |part, format, width, height|
|
108
|
+
mime = @response_multipart[part_no(part)].headers['content-type']
|
109
|
+
data = @response_multipart[part_no(part)].body
|
110
|
+
|
111
|
+
mime.should match /^image\//
|
112
|
+
data.should_not be_empty
|
113
|
+
|
114
|
+
@image.destroy! if @image
|
115
|
+
@image = Magick::Image.from_blob(data).first
|
116
|
+
|
117
|
+
@image.format.should == format
|
118
|
+
@image.columns.should == width.to_i
|
119
|
+
@image.rows.should == height.to_i
|
87
120
|
end
|
88
121
|
|
89
|
-
Then /
|
90
|
-
|
91
|
-
|
92
|
-
|
122
|
+
Then /saved response body will be smaller than response body/ do
|
123
|
+
@saved_response_body.length.should < @response.body.length
|
124
|
+
end
|
125
|
+
|
126
|
+
And /response will be saved as (.*) for human inspection/ do |file|
|
127
|
+
data = @response.body
|
128
|
+
(support_dir + file).open('w'){|f| f.write(data)}
|
93
129
|
end
|
94
130
|
|
95
131
|
And /(.*) part body will be saved as (.*) for human inspection/ do |part, file|
|
96
|
-
data = @response_multipart
|
132
|
+
data = @response_multipart[part_no(part)].body
|
97
133
|
(support_dir + file).open('w'){|f| f.write(data)}
|
98
134
|
end
|
99
135
|
|
100
|
-
And /that image pixel at (.*)x(.*)
|
136
|
+
And /that image pixel at (.*)x(.*) should be of color (.*)/ do |x, y, color|
|
101
137
|
@image.pixel_color(x.to_i, y.to_i).to_color.sub(/^#/, '0x').should == color
|
102
138
|
end
|
103
139
|
|
104
|
-
And /
|
105
|
-
|
140
|
+
And /that image should be (.*) bit image/ do |bits|
|
141
|
+
@image.depth.should == bits.to_i
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
And /there should be no leaked images/ do
|
146
|
+
Integer(http_client.get_content("http://localhost:3100/stats/images_loaded").strip).should == 0
|
147
|
+
end
|
148
|
+
|
149
|
+
And /there should be maximum (.*) images loaded during single request/ do |max|
|
150
|
+
Integer(http_client.get_content("http://localhost:3100/stats/max_images_loaded").strip).should <= max.to_i
|
106
151
|
end
|
107
152
|
|
data/features/support/env.rb
CHANGED
@@ -7,13 +7,12 @@ rescue Bundler::BundlerError => e
|
|
7
7
|
exit e.status_code
|
8
8
|
end
|
9
9
|
|
10
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
11
10
|
|
12
11
|
require 'rspec/expectations'
|
12
|
+
require 'multipart_parser/reader'
|
13
13
|
require 'daemon'
|
14
14
|
require 'timeout'
|
15
15
|
require 'httpclient'
|
16
|
-
require 'httpthumbnailer/multipart_response'
|
17
16
|
require "open3"
|
18
17
|
require "thread"
|
19
18
|
require 'RMagick'
|
@@ -43,28 +42,36 @@ def part_no(part)
|
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
def http_client
|
46
|
+
client = HTTPClient.new
|
47
|
+
#client.debug_dev = STDOUT
|
48
|
+
client
|
49
49
|
end
|
50
50
|
|
51
|
+
@@running_cmd = {}
|
51
52
|
def start_server(cmd, pid_file, log_file, test_url)
|
52
|
-
|
53
|
+
if @@running_cmd[pid_file]
|
54
|
+
return if @@running_cmd[pid_file] == cmd
|
55
|
+
stop_server(pid_file)
|
56
|
+
end
|
53
57
|
|
54
58
|
fork do
|
55
59
|
Daemon.daemonize(pid_file, log_file)
|
60
|
+
log_file = Pathname.new(log_file)
|
61
|
+
log_file.truncate(0) if log_file.exist?
|
56
62
|
exec(cmd)
|
57
63
|
end
|
58
|
-
|
64
|
+
|
65
|
+
@@running_cmd[pid_file] = cmd
|
59
66
|
|
60
67
|
ppid = Process.pid
|
61
68
|
at_exit do
|
62
69
|
stop_server(pid_file) if Process.pid == ppid
|
63
70
|
end
|
64
71
|
|
65
|
-
Timeout.timeout(
|
72
|
+
Timeout.timeout(6) do
|
66
73
|
begin
|
67
|
-
|
74
|
+
http_client.get_content test_url
|
68
75
|
rescue Errno::ECONNREFUSED
|
69
76
|
sleep 0.1
|
70
77
|
retry
|
@@ -76,6 +83,7 @@ def stop_server(pid_file)
|
|
76
83
|
pid_file = Pathname.new(pid_file)
|
77
84
|
return unless pid_file.exist?
|
78
85
|
|
86
|
+
STDERR.puts http_client.get_content("http://localhost:3100/stats")
|
79
87
|
pid = pid_file.read.strip.to_i
|
80
88
|
|
81
89
|
Timeout.timeout(20) do
|
@@ -90,3 +98,8 @@ def stop_server(pid_file)
|
|
90
98
|
end
|
91
99
|
end
|
92
100
|
|
101
|
+
After do |scenario|
|
102
|
+
step 'there should be no leaked images'
|
103
|
+
step 'there should be maximum 3 images loaded during single request'
|
104
|
+
end
|
105
|
+
|
Binary file
|
@@ -0,0 +1,241 @@
|
|
1
|
+
Feature: Generating single thumbnail with PUT request
|
2
|
+
In order to generate a single image thumbnail
|
3
|
+
A user must PUT an image to URL in format
|
4
|
+
/thumbnail[/<thumbnail type>,<width>,<height>,<format>
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given httpthumbnailer server is running at http://localhost:3100/
|
8
|
+
|
9
|
+
@test
|
10
|
+
Scenario: Single thumbnail
|
11
|
+
Given test.jpg file content as request body
|
12
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,16,16,png
|
13
|
+
Then response status should be 200
|
14
|
+
Then response should contain PNG image of size 16x16
|
15
|
+
And that image should be 8 bit image
|
16
|
+
And response mime type should be image/png
|
17
|
+
|
18
|
+
@transparent
|
19
|
+
Scenario: Transparent image to JPEG handling - default background color white
|
20
|
+
Given test-transparent.png file content as request body
|
21
|
+
When I do PUT request http://localhost:3100/thumbnail/fit,128,128,jpeg
|
22
|
+
Then response status should be 200
|
23
|
+
And response will be saved as test-transparent-default.png for human inspection
|
24
|
+
Then response should contain JPEG image of size 128x128
|
25
|
+
And that image pixel at 32x32 should be of color white
|
26
|
+
|
27
|
+
@input_format
|
28
|
+
Scenario: Thumbnails of format input should have same format as input image
|
29
|
+
Given test.jpg file content as request body
|
30
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,4,8,input
|
31
|
+
Then response status should be 200
|
32
|
+
Then response should contain JPEG image of size 4x8
|
33
|
+
And response mime type should be image/jpeg
|
34
|
+
Given test.png file content as request body
|
35
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,4,8,input
|
36
|
+
Then response status should be 200
|
37
|
+
Then response should contain PNG image of size 4x8
|
38
|
+
And that image should be 8 bit image
|
39
|
+
And response mime type should be image/png
|
40
|
+
|
41
|
+
@input_size
|
42
|
+
Scenario: Thumbnails of width or height input should have input image width or height
|
43
|
+
Given test.jpg file content as request body
|
44
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,input,16,png
|
45
|
+
Then response status should be 200
|
46
|
+
Then response should contain PNG image of size 509x16
|
47
|
+
And response mime type should be image/png
|
48
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,4,input,png
|
49
|
+
Then response status should be 200
|
50
|
+
Then response should contain PNG image of size 4x719
|
51
|
+
And response mime type should be image/png
|
52
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,input,input,png
|
53
|
+
Then response status should be 200
|
54
|
+
Then response should contain PNG image of size 509x719
|
55
|
+
And response mime type should be image/png
|
56
|
+
|
57
|
+
@fit
|
58
|
+
Scenario: Fit thumbnailing method
|
59
|
+
Given test.jpg file content as request body
|
60
|
+
When I do PUT request http://localhost:3100/thumbnail/fit,128,128,png
|
61
|
+
Then response status should be 200
|
62
|
+
Then response should contain PNG image of size 91x128
|
63
|
+
Given test.jpg file content as request body
|
64
|
+
When I do PUT request http://localhost:3100/thumbnail/fit,1024,1024,png
|
65
|
+
Then response status should be 200
|
66
|
+
Then response should contain PNG image of size 725x1024
|
67
|
+
|
68
|
+
@limit
|
69
|
+
Scenario: Limit thumbnailing method should reduce image size when needed
|
70
|
+
Given test.jpg file content as request body
|
71
|
+
When I do PUT request http://localhost:3100/thumbnail/limit,128,128,png
|
72
|
+
Then response status should be 200
|
73
|
+
Then response should contain PNG image of size 91x128
|
74
|
+
Given test.jpg file content as request body
|
75
|
+
When I do PUT request http://localhost:3100/thumbnail/limit,1024,1024,png
|
76
|
+
Then response status should be 200
|
77
|
+
Then response should contain PNG image of size 509x719
|
78
|
+
|
79
|
+
@pad @transparent
|
80
|
+
Scenario: Pad thumbnailing method - default background color white
|
81
|
+
Given test.jpg file content as request body
|
82
|
+
When I do PUT request http://localhost:3100/thumbnail/pad,128,128,png
|
83
|
+
Then response status should be 200
|
84
|
+
And response will be saved as test-pad.png for human inspection
|
85
|
+
Then response should contain PNG image of size 128x128
|
86
|
+
And that image pixel at 2x2 should be of color white
|
87
|
+
|
88
|
+
@pad @transparent
|
89
|
+
Scenario: Pad thumbnailing method with specified background color
|
90
|
+
Given test.jpg file content as request body
|
91
|
+
When I do PUT request http://localhost:3100/thumbnail/pad,128,128,png,background-color:green
|
92
|
+
Then response status should be 200
|
93
|
+
And response will be saved as test-pad-background-color.png for human inspection
|
94
|
+
Then response should contain PNG image of size 128x128
|
95
|
+
And that image pixel at 2x2 should be of color green
|
96
|
+
|
97
|
+
@error_handling
|
98
|
+
Scenario: Reporitng of unsupported media type
|
99
|
+
Given test.txt file content as request body
|
100
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,128,png
|
101
|
+
Then response status should be 415
|
102
|
+
And response content type should be text/plain
|
103
|
+
And response body should be CRLF endend lines like
|
104
|
+
"""
|
105
|
+
unsupported media type: no decode delegate for this image format
|
106
|
+
"""
|
107
|
+
|
108
|
+
@error_handling
|
109
|
+
Scenario: Reporitng of bad thumbanil spec format - bad dimension value
|
110
|
+
Given test.jpg file content as request body
|
111
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,bogous,png
|
112
|
+
Then response status should be 400
|
113
|
+
And response content type should be text/plain
|
114
|
+
And response body should be CRLF endend lines
|
115
|
+
"""
|
116
|
+
bad dimension value: bogous
|
117
|
+
"""
|
118
|
+
|
119
|
+
@error_handling
|
120
|
+
Scenario: Reporitng of bad thumbanil spec format - missing param
|
121
|
+
Given test.jpg file content as request body
|
122
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,png
|
123
|
+
Then response status should be 400
|
124
|
+
And response content type should be text/plain
|
125
|
+
And response body should be CRLF endend lines
|
126
|
+
"""
|
127
|
+
missing argument in: crop,128,png
|
128
|
+
"""
|
129
|
+
|
130
|
+
@error_handling
|
131
|
+
Scenario: Reporitng of bad thumbanil spec format - bad options format
|
132
|
+
Given test.jpg file content as request body
|
133
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,128,png,fas-xyz
|
134
|
+
Then response status should be 400
|
135
|
+
And response content type should be text/plain
|
136
|
+
And response body should be CRLF endend lines
|
137
|
+
"""
|
138
|
+
missing option key or value in: fas-xyz
|
139
|
+
"""
|
140
|
+
|
141
|
+
@error_handling
|
142
|
+
Scenario: Reporitng of bad operation value
|
143
|
+
Given test.jpg file content as request body
|
144
|
+
When I do PUT request http://localhost:3100/thumbnail/blah,128,128,png
|
145
|
+
Then response status should be 400
|
146
|
+
And response content type should be text/plain
|
147
|
+
And response body should be CRLF endend lines
|
148
|
+
"""
|
149
|
+
thumbnail method 'blah' is not supported
|
150
|
+
"""
|
151
|
+
|
152
|
+
@error_handling
|
153
|
+
Scenario: Reporitng of image thumbnailing errors
|
154
|
+
Given test.jpg file content as request body
|
155
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,0,0,jpeg
|
156
|
+
Then response status should be 400
|
157
|
+
And response content type should be text/plain
|
158
|
+
And response body should be CRLF endend lines
|
159
|
+
"""
|
160
|
+
at least one image dimension is zero: 0x0
|
161
|
+
"""
|
162
|
+
|
163
|
+
@optimization
|
164
|
+
Scenario: Handing of large image data - possible thanks to loading size optimization
|
165
|
+
Given test-large.jpg file content as request body
|
166
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,16,16,png
|
167
|
+
Then response status should be 200
|
168
|
+
Then response should contain PNG image of size 16x16
|
169
|
+
|
170
|
+
@resources
|
171
|
+
Scenario: Memory limits exhausted while loading - no loading optimization possible
|
172
|
+
Given test-large.jpg file content as request body
|
173
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,7000,7000,png
|
174
|
+
Then response status should be 413
|
175
|
+
And response content type should be text/plain
|
176
|
+
And response body should be CRLF endend lines like
|
177
|
+
"""
|
178
|
+
image too large: cache resources exhausted
|
179
|
+
"""
|
180
|
+
|
181
|
+
@resources
|
182
|
+
Scenario: Memory limits exhausted while thumbnailing
|
183
|
+
Given test.jpg file content as request body
|
184
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,16000,16000,jpeg
|
185
|
+
Then response status should be 413
|
186
|
+
And response content type should be text/plain
|
187
|
+
And response body should be CRLF endend lines like
|
188
|
+
"""
|
189
|
+
image too large: cache resources exhausted
|
190
|
+
"""
|
191
|
+
|
192
|
+
@quality
|
193
|
+
Scenario: Quality option - JPEG
|
194
|
+
Given test.jpg file content as request body
|
195
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg,quality:10
|
196
|
+
When I save response body
|
197
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg,quality:80
|
198
|
+
Then saved response body will be smaller than response body
|
199
|
+
When I save response body
|
200
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg,quality:90
|
201
|
+
Then saved response body will be smaller than response body
|
202
|
+
|
203
|
+
@quality
|
204
|
+
Scenario: Quality option - JPEG - default 85
|
205
|
+
Given test.jpg file content as request body
|
206
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg,quality:84
|
207
|
+
When I save response body
|
208
|
+
Then response mime type should be image/jpeg
|
209
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg
|
210
|
+
Then saved response body will be smaller than response body
|
211
|
+
Then response mime type should be image/jpeg
|
212
|
+
When I save response body
|
213
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,32,32,jpeg,quality:86
|
214
|
+
Then saved response body will be smaller than response body
|
215
|
+
Then response mime type should be image/jpeg
|
216
|
+
|
217
|
+
@quality
|
218
|
+
Scenario: Quality option - PNG (XY where X - zlib compresion level, Y - filter)
|
219
|
+
Given test.jpg file content as request body
|
220
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,128,png,quality:90
|
221
|
+
When I save response body
|
222
|
+
Then response mime type should be image/png
|
223
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,128,png,quality:50
|
224
|
+
Then saved response body will be smaller than response body
|
225
|
+
Then response mime type should be image/png
|
226
|
+
When I save response body
|
227
|
+
When I do PUT request http://localhost:3100/thumbnail/crop,128,128,png,quality:10
|
228
|
+
Then saved response body will be smaller than response body
|
229
|
+
Then response mime type should be image/png
|
230
|
+
|
231
|
+
@hint
|
232
|
+
Scenario: Hint on input image mime type
|
233
|
+
Given test.jpg file content as request body
|
234
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png
|
235
|
+
Then response status should be 200
|
236
|
+
And X-Input-Image-Content-Type header should be image/jpeg
|
237
|
+
Given test.png file content as request body
|
238
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png
|
239
|
+
Then response status should be 200
|
240
|
+
And X-Input-Image-Content-Type header should be image/png
|
241
|
+
|
@@ -0,0 +1,142 @@
|
|
1
|
+
Feature: Generating set of thumbnails with single PUT request
|
2
|
+
In order to generate a set of image thumbnails
|
3
|
+
A user must PUT an image to URL in format
|
4
|
+
/thumbnails[/<thumbnail type>,<width>,<height>,<format>[,<option key>:<option value>]+]+
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given httpthumbnailer server is running at http://localhost:3100/
|
8
|
+
|
9
|
+
@multipart
|
10
|
+
Scenario: Single thumbnail
|
11
|
+
Given test.jpg file content as request body
|
12
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png
|
13
|
+
Then response status should be 200
|
14
|
+
And I should get multipart response
|
15
|
+
Then first part should contain PNG image of size 16x16
|
16
|
+
And that image should be 8 bit image
|
17
|
+
And first part mime type should be image/png
|
18
|
+
|
19
|
+
@multipart
|
20
|
+
Scenario: Multiple thumbnails
|
21
|
+
Given test.jpg file content as request body
|
22
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png/crop,4,8,jpeg/crop,16,32,jpeg
|
23
|
+
Then response status should be 200
|
24
|
+
And I should get multipart response
|
25
|
+
Then first part should contain PNG image of size 16x16
|
26
|
+
And first part mime type should be image/png
|
27
|
+
Then second part should contain JPEG image of size 4x8
|
28
|
+
And second part mime type should be image/jpeg
|
29
|
+
Then third part should contain JPEG image of size 16x32
|
30
|
+
And third part mime type should be image/jpeg
|
31
|
+
|
32
|
+
@input_size
|
33
|
+
Scenario: Thumbnails of width or height input should have input image width or height
|
34
|
+
Given test.jpg file content as request body
|
35
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,input,16,jpeg/crop,4,input,png/crop,input,input,png
|
36
|
+
Then response status should be 200
|
37
|
+
And I should get multipart response
|
38
|
+
Then first part should contain JPEG image of size 509x16
|
39
|
+
Then second part should contain PNG image of size 4x719
|
40
|
+
Then third part should contain PNG image of size 509x719
|
41
|
+
|
42
|
+
@leaking
|
43
|
+
Scenario: Image leaking on error
|
44
|
+
Given test.jpg file content as request body
|
45
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,0,0,png/fit,0,0,jpeg/pad,0,0,jpeg
|
46
|
+
Then response status should be 200
|
47
|
+
And I should get multipart response
|
48
|
+
And first part content type should be text/plain
|
49
|
+
And second part content type should be text/plain
|
50
|
+
And third part content type should be text/plain
|
51
|
+
|
52
|
+
@error_handling
|
53
|
+
Scenario: Reporitng of bad thumbanil spec format - bad dimension value
|
54
|
+
Given test.jpg file content as request body
|
55
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,4,4,png/crop,128,bogous,png
|
56
|
+
Then response status should be 400
|
57
|
+
And response content type should be text/plain
|
58
|
+
And response body should be CRLF endend lines
|
59
|
+
"""
|
60
|
+
bad dimension value: bogous
|
61
|
+
"""
|
62
|
+
|
63
|
+
@error_handling
|
64
|
+
Scenario: Reporitng of bad thumbanil spec format - missing param
|
65
|
+
Given test.jpg file content as request body
|
66
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,4,4,png/crop,128,png
|
67
|
+
Then response status should be 400
|
68
|
+
And response content type should be text/plain
|
69
|
+
And response body should be CRLF endend lines
|
70
|
+
"""
|
71
|
+
missing argument in: crop,128,png
|
72
|
+
"""
|
73
|
+
|
74
|
+
@error_handling
|
75
|
+
Scenario: Reporitng of bad thumbanil spec format - bad options format
|
76
|
+
Given test.jpg file content as request body
|
77
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,4,4,png/crop,128,128,png,fas-fda
|
78
|
+
Then response status should be 400
|
79
|
+
And response content type should be text/plain
|
80
|
+
And response body should be CRLF endend lines
|
81
|
+
"""
|
82
|
+
missing option key or value in: fas-fda
|
83
|
+
"""
|
84
|
+
|
85
|
+
@error_handling
|
86
|
+
Scenario: Reporitng of bad operation value
|
87
|
+
Given test.jpg file content as request body
|
88
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,4,4,png/blah,128,128,png
|
89
|
+
Then response status should be 200
|
90
|
+
And I should get multipart response
|
91
|
+
And second part content type should be text/plain
|
92
|
+
And second part body should be CRLF endend lines
|
93
|
+
"""
|
94
|
+
thumbnail method 'blah' is not supported
|
95
|
+
"""
|
96
|
+
And second part status should be 400
|
97
|
+
|
98
|
+
@error_handling
|
99
|
+
Scenario: Reporitng of image thumbnailing errors
|
100
|
+
Given test.jpg file content as request body
|
101
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png/crop,0,0,jpeg/crop,16,32,jpeg
|
102
|
+
Then response status should be 200
|
103
|
+
And I should get multipart response
|
104
|
+
Then first part should contain PNG image of size 16x16
|
105
|
+
And first part mime type should be image/png
|
106
|
+
And second part content type should be text/plain
|
107
|
+
And second part body should be CRLF endend lines
|
108
|
+
"""
|
109
|
+
at least one image dimension is zero: 0x0
|
110
|
+
"""
|
111
|
+
And second part status should be 400
|
112
|
+
Then third part should contain JPEG image of size 16x32
|
113
|
+
And third part mime type should be image/jpeg
|
114
|
+
|
115
|
+
@resources
|
116
|
+
Scenario: Memory limits exhausted while thumbnailing
|
117
|
+
Given test.jpg file content as request body
|
118
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png/crop,16000,16000,jpeg/crop,16,32,jpeg
|
119
|
+
Then response status should be 200
|
120
|
+
And I should get multipart response
|
121
|
+
Then first part should contain PNG image of size 16x16
|
122
|
+
And first part mime type should be image/png
|
123
|
+
And second part content type should be text/plain
|
124
|
+
And second part body should be CRLF endend lines like
|
125
|
+
"""
|
126
|
+
image too large: cache resources exhausted
|
127
|
+
"""
|
128
|
+
And second part status should be 413
|
129
|
+
Then third part should contain JPEG image of size 16x32
|
130
|
+
And third part mime type should be image/jpeg
|
131
|
+
|
132
|
+
@hint
|
133
|
+
Scenario: Hint on input image mime type
|
134
|
+
Given test.jpg file content as request body
|
135
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png
|
136
|
+
Then response status should be 200
|
137
|
+
And X-Input-Image-Content-Type header should be image/jpeg
|
138
|
+
Given test.png file content as request body
|
139
|
+
When I do PUT request http://localhost:3100/thumbnails/crop,16,16,png
|
140
|
+
Then response status should be 200
|
141
|
+
And X-Input-Image-Content-Type header should be image/png
|
142
|
+
|