httpthumbnailer 0.3.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|