httpimagestore 1.2.0 → 1.3.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.
@@ -1,4 +1,3 @@
1
- require 'unicorn-cuba-base'
2
1
  require 'httpthumbnailer-client'
3
2
  require 'httpimagestore/ruby_string_template'
4
3
  require 'httpimagestore/configuration/handler'
@@ -126,7 +125,7 @@ module Configuration
126
125
  operation || 'fit',
127
126
  width || 'input',
128
127
  height || 'input',
129
- format || 'jpeg',
128
+ format || 'input',
130
129
  remaining || {},
131
130
  matcher
132
131
  )
@@ -134,7 +133,7 @@ module Configuration
134
133
 
135
134
  matcher = InclusionMatcher.new(source_image_name, node.grab_attributes('if-image-name-on').first) if use_multipart_api
136
135
 
137
- configuration.image_sources << self.new(
136
+ configuration.processors << self.new(
138
137
  configuration.global,
139
138
  source_image_name,
140
139
  specs,
@@ -158,12 +157,14 @@ module Configuration
158
157
  @specs.select do |spec|
159
158
  spec.included?(request_state)
160
159
  end.each do |spec|
161
- rendered_specs.merge! spec.render(request_state.locals)
160
+ rendered_specs.merge! spec.render(request_state)
162
161
  end
163
162
  source_image = request_state.images[@source_image_name]
164
163
 
165
164
  thumbnails = {}
166
165
  input_mime_type = nil
166
+ input_width = nil
167
+ input_height = nil
167
168
 
168
169
  Thumbnail.stats.incr_total_thumbnail_requests
169
170
  Thumbnail.stats.incr_total_thumbnail_requests_bytes source_image.data.bytesize
@@ -192,6 +193,8 @@ module Configuration
192
193
  end
193
194
 
194
195
  input_mime_type = thumbnails.input_mime_type
196
+ input_width = thumbnails.input_width
197
+ input_height = thumbnails.input_height
195
198
 
196
199
  # check each thumbnail for errors
197
200
  thumbnails = Hash[rendered_specs.keys.zip(thumbnails)]
@@ -205,7 +208,7 @@ module Configuration
205
208
 
206
209
  # borrow from memory limit - note that we might have already used too much memory
207
210
  thumbnails.each do |name, thumbnail|
208
- request_state.memory_limit.borrow thumbnail.data.bytesize
211
+ request_state.memory_limit.borrow(thumbnail.data.bytesize, "thumbnail '#{name}'")
209
212
  end
210
213
  else
211
214
  name, rendered_spec = *rendered_specs.first
@@ -213,8 +216,12 @@ module Configuration
213
216
 
214
217
  begin
215
218
  thumbnail = client.thumbnail(source_image.data, *rendered_spec)
216
- request_state.memory_limit.borrow thumbnail.data.bytesize
219
+ request_state.memory_limit.borrow(thumbnail.data.bytesize, "thumbnail '#{name}'")
220
+
217
221
  input_mime_type = thumbnail.input_mime_type
222
+ input_width = thumbnail.input_width
223
+ input_height = thumbnail.input_height
224
+
218
225
  thumbnails[name] = thumbnail
219
226
  rescue HTTPThumbnailerClient::HTTPThumbnailerClientError => error
220
227
  log.warn 'got thumbnailer error', error
@@ -232,8 +239,10 @@ module Configuration
232
239
  Thumbnail.stats.incr_total_thumbnail_thumbnails_bytes thumbnail.data.bytesize
233
240
  end
234
241
 
235
- # update input image mime type from httpthumbnailer provided information
236
- source_image.mime_type = input_mime_type unless source_image.mime_type
242
+ # use httpthumbnailer provided information on input image mime type and size
243
+ source_image.mime_type = input_mime_type if input_mime_type
244
+ source_image.width = input_width if input_width
245
+ source_image.height = input_height if input_height
237
246
 
238
247
  request_state.images.merge! thumbnails
239
248
  end
@@ -1,7 +1,6 @@
1
1
  class ErrorReporter < Controler
2
2
  self.define do
3
3
  on error(
4
- Rack::UnhandledRequest::UnhandledRequestError,
5
4
  Configuration::S3NoSuchKeyError,
6
5
  Configuration::NoSuchFileError
7
6
  ) do |error|
@@ -21,16 +20,7 @@ class ErrorReporter < Controler
21
20
  write_error 400, error
22
21
  end
23
22
 
24
- on error StandardError do |error|
25
- log.error "unhandled error while processing request: #{env['REQUEST_METHOD']} #{env['SCRIPT_NAME']}[#{env["PATH_INFO"]}]", error
26
- log.debug {
27
- out = StringIO.new
28
- PP::pp(env, out, 200)
29
- "Request: \n" + out.string
30
- }
31
-
32
- write_error 500, error
33
- end
23
+ run DefaultErrorReporter
34
24
  end
35
25
  end
36
26
 
@@ -42,7 +42,7 @@
42
42
  <stringProp name="HTTPSampler.concurrentPool">4</stringProp>
43
43
  </ConfigTestElement>
44
44
  <hashTree/>
45
- <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Compatibility API" enabled="true">
45
+ <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Compatibility API" enabled="false">
46
46
  <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
47
47
  <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
48
48
  <boolProp name="LoopController.continue_forever">false</boolProp>
@@ -78,7 +78,7 @@
78
78
  <stringProp name="HTTPSampler.response_timeout"></stringProp>
79
79
  <stringProp name="HTTPSampler.protocol"></stringProp>
80
80
  <stringProp name="HTTPSampler.contentEncoding"></stringProp>
81
- <stringProp name="HTTPSampler.path">/thumbnail/original,search,search_thumb,brochure,brochure_thumb,admin,dmin_thumb,treatment_thumb,staff_member_thumb,consultation,clinic_google_map_thumb</stringProp>
81
+ <stringProp name="HTTPSampler.path">/thumbnail/original,search,search_thumb,brochure,brochure_thumb,admin,dmin_thumb,treatment_thumb,staff_member_thumb,consultation,clinic_google_map_thumb/randwick.jpg</stringProp>
82
82
  <stringProp name="HTTPSampler.method">PUT</stringProp>
83
83
  <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
84
84
  <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -108,7 +108,7 @@
108
108
  <hashTree/>
109
109
  </hashTree>
110
110
  </hashTree>
111
- <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="API v1" enabled="false">
111
+ <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Flexi API" enabled="true">
112
112
  <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
113
113
  <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
114
114
  <boolProp name="LoopController.continue_forever">false</boolProp>
@@ -144,8 +144,8 @@
144
144
  <stringProp name="HTTPSampler.response_timeout"></stringProp>
145
145
  <stringProp name="HTTPSampler.protocol"></stringProp>
146
146
  <stringProp name="HTTPSampler.contentEncoding"></stringProp>
147
- <stringProp name="HTTPSampler.path">/v1/original</stringProp>
148
- <stringProp name="HTTPSampler.method">PUT</stringProp>
147
+ <stringProp name="HTTPSampler.path">/iss/v2/pictures</stringProp>
148
+ <stringProp name="HTTPSampler.method">POST</stringProp>
149
149
  <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
150
150
  <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
151
151
  <boolProp name="HTTPSampler.use_keepalive">false</boolProp>
@@ -172,9 +172,9 @@
172
172
  <stringProp name="RegexExtractor.match_number">1</stringProp>
173
173
  </RegexExtractor>
174
174
  <hashTree/>
175
- <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="contains path" enabled="true">
175
+ <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="contains .jpg file path" enabled="true">
176
176
  <collectionProp name="Asserion.test_strings">
177
- <stringProp name="1768443330">dev/httpimagestore/v1</stringProp>
177
+ <stringProp name="1475827">.jpg</stringProp>
178
178
  </collectionProp>
179
179
  <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
180
180
  <boolProp name="Assertion.assume_success">false</boolProp>
@@ -195,7 +195,7 @@
195
195
  <CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="thumbnail specs" enabled="true">
196
196
  <stringProp name="filename">thumbnail_specs.csv</stringProp>
197
197
  <stringProp name="fileEncoding"></stringProp>
198
- <stringProp name="variableNames">method,width,height,options</stringProp>
198
+ <stringProp name="variableNames">type,method,width,height,options</stringProp>
199
199
  <stringProp name="delimiter">,</stringProp>
200
200
  <boolProp name="quotedData">true</boolProp>
201
201
  <boolProp name="recycle">true</boolProp>
@@ -213,7 +213,7 @@
213
213
  <stringProp name="HTTPSampler.response_timeout"></stringProp>
214
214
  <stringProp name="HTTPSampler.protocol"></stringProp>
215
215
  <stringProp name="HTTPSampler.contentEncoding"></stringProp>
216
- <stringProp name="HTTPSampler.path">/v1/thumbnail/${__BeanShell(vars.get(&quot;store_path&quot;).replace(&quot;/&quot;\, &quot;%2f&quot;))}/${method}/${width}/${height}/${options}</stringProp>
216
+ <stringProp name="HTTPSampler.path">/iss/v2/pictures/${__BeanShell(vars.get(&quot;store_path&quot;).replace(&quot;/:&quot;\, &quot;%2f&quot;))}?type=${type}</stringProp>
217
217
  <stringProp name="HTTPSampler.method">GET</stringProp>
218
218
  <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
219
219
  <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
@@ -238,13 +238,13 @@
238
238
  <DebugPostProcessor guiclass="TestBeanGUI" testclass="DebugPostProcessor" testname="Debug PostProcessor" enabled="false">
239
239
  <boolProp name="displayJMeterProperties">false</boolProp>
240
240
  <boolProp name="displayJMeterVariables">true</boolProp>
241
- <boolProp name="displaySamplerProperties">false</boolProp>
241
+ <boolProp name="displaySamplerProperties">true</boolProp>
242
242
  <boolProp name="displaySystemProperties">false</boolProp>
243
243
  </DebugPostProcessor>
244
244
  <hashTree/>
245
245
  </hashTree>
246
246
  <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
247
- <boolProp name="ResultCollector.error_logging">true</boolProp>
247
+ <boolProp name="ResultCollector.error_logging">false</boolProp>
248
248
  <objProp>
249
249
  <name>saveConfig</name>
250
250
  <value class="SampleSaveConfiguration">
@@ -1,11 +1,11 @@
1
- "crop","input","input","background-color:0xF0F0F0"
2
- "pad","162","162","background-color:0xF0F0F0"
3
- "pad","28","28","background-color:0xF0F0F0"
4
- "pad","264","264","background-color:0xF0F0F0"
5
- "pad","40","40","background-color:0xF0F0F0"
6
- "pad","160","160","background-color:0xF0F0F0"
7
- "pad","65","65","background-color:0xF0F0F0"
8
- "pad","80","60","background-color:0xF0F0F0"
9
- "pad","50","50","background-color:0xF0F0F0"
10
- "pad","126","126","background-color:0xF0F0F0"
11
- "pad","74","74","background-color:0xF0F0F0"
1
+ "original","crop","input","input","background-color:0xF0F0F0"
2
+ "search","pad","162","162","background-color:0xF0F0F0"
3
+ "search_thumb","pad","28","28","background-color:0xF0F0F0"
4
+ "brochure","pad","264","264","background-color:0xF0F0F0"
5
+ "brochure_thumb","pad","40","40","background-color:0xF0F0F0"
6
+ "admin","pad","160","160","background-color:0xF0F0F0"
7
+ "admin_thumb","pad","65","65","background-color:0xF0F0F0"
8
+ "treatment_thumb","pad","80","60","background-color:0xF0F0F0"
9
+ "staff_member_thumb","pad","50","50","background-color:0xF0F0F0"
10
+ "consultation","pad","126","126","background-color:0xF0F0F0"
11
+ "clinic_google_map_thumb","pad","74","74","background-color:0xF0F0F0"
@@ -36,21 +36,21 @@ describe Configuration do
36
36
  end
37
37
 
38
38
  it 'should source image from file using path spec' do
39
- subject.handlers[0].image_sources[0].should be_a Configuration::FileSource
40
- subject.handlers[0].image_sources[0].realize(state)
39
+ subject.handlers[0].sources[0].should be_a Configuration::FileSource
40
+ subject.handlers[0].sources[0].realize(state)
41
41
 
42
42
  state.images["original"].should_not be_nil
43
43
  state.images["original"].data.should == 'abc'
44
44
  end
45
45
 
46
46
  it 'should have nil mime type' do
47
- subject.handlers[0].image_sources[0].realize(state)
47
+ subject.handlers[0].sources[0].realize(state)
48
48
 
49
49
  state.images["original"].mime_type.should be_nil
50
50
  end
51
51
 
52
52
  it 'should have source path and url' do
53
- subject.handlers[0].image_sources[0].realize(state)
53
+ subject.handlers[0].sources[0].realize(state)
54
54
 
55
55
  state.images['original'].source_path.should == "test.in"
56
56
  state.images['original'].source_url.should == "file://test.in"
@@ -65,16 +65,16 @@ describe Configuration do
65
65
 
66
66
  subject do
67
67
  Configuration.read(<<-EOF)
68
- path "imagename" "\#{imagename}.jpg"
68
+ path "image_name" "\#{image_name}.jpg"
69
69
 
70
70
  get "small" {
71
- source_file "test-image-name" root="/tmp" path="imagename"
71
+ source_file "test-image-name" root="/tmp" path="image_name"
72
72
  }
73
73
  EOF
74
74
  end
75
75
 
76
- it 'should provide image name to be used as #{imagename}' do
77
- subject.handlers[0].image_sources[0].realize(state)
76
+ it 'should provide image name to be used as #{image_name}' do
77
+ subject.handlers[0].sources[0].realize(state)
78
78
  state.images['test-image-name'].source_path.should == 'test-image-name.jpg'
79
79
  state.images['test-image-name'].data.should == 'hello world'
80
80
  end
@@ -93,7 +93,7 @@ describe Configuration do
93
93
  EOF
94
94
 
95
95
  expect {
96
- subject.handlers[0].image_sources[0].realize(state)
96
+ subject.handlers[0].sources[0].realize(state)
97
97
  }.to raise_error Configuration::FileStorageOutsideOfRootDirError, %{error while processing image 'original': file storage path '../test.in' outside of root direcotry}
98
98
  end
99
99
 
@@ -109,7 +109,7 @@ describe Configuration do
109
109
  EOF
110
110
 
111
111
  expect {
112
- subject.handlers[0].image_sources[0].realize(state)
112
+ subject.handlers[0].sources[0].realize(state)
113
113
  }.to raise_error Configuration::NoSuchFileError, %{error while processing image 'original': file 'blah' not found}
114
114
  end
115
115
 
@@ -151,7 +151,7 @@ describe Configuration do
151
151
 
152
152
  it 'should rais MemoryLimit::MemoryLimitedExceededError error if limit exceeded runing file sourcing' do
153
153
  expect {
154
- subject.handlers[0].image_sources[0].realize(state)
154
+ subject.handlers[0].sources[0].realize(state)
155
155
  }.to raise_error MemoryLimit::MemoryLimitedExceededError, 'memory limit exceeded'
156
156
  end
157
157
  end
@@ -176,7 +176,7 @@ describe Configuration do
176
176
 
177
177
  before :each do
178
178
  out_file.unlink if out_file.exist?
179
- subject.handlers[0].image_sources[0].realize(state)
179
+ subject.handlers[0].sources[0].realize(state)
180
180
  end
181
181
 
182
182
  after :each do
@@ -227,33 +227,33 @@ describe Configuration do
227
227
  describe 'context locals' do
228
228
  subject do
229
229
  Configuration.read(<<-'EOF')
230
- path "imagename" "#{imagename}.jpg"
231
- path "mimeextension" "test-store-file.#{mimeextension}"
230
+ path "image_name" "#{image_name}.jpg"
231
+ path "image_mime_extension" "test-store-file.#{image_mime_extension}"
232
232
 
233
233
  post "small" {
234
- store_file "input" root="/tmp" path="imagename"
235
- store_file "input" root="/tmp" path="mimeextension"
234
+ store_file "input" root="/tmp" path="image_name"
235
+ store_file "input" root="/tmp" path="image_mime_extension"
236
236
  }
237
237
  EOF
238
238
  end
239
239
 
240
- it 'should provide image name to be used as #{imagename}' do
240
+ it 'should provide image name to be used as #{image_name}' do
241
241
  subject.handlers[0].stores[0].realize(state)
242
242
 
243
243
  state.images['input'].store_path.should == 'input.jpg'
244
244
  end
245
245
 
246
- it 'should provide image mime type based file extension to be used as #{mimeextension}' do
246
+ it 'should provide image mime type based file extension to be used as #{image_mime_extension}' do
247
247
  state.images['input'].mime_type = 'image/jpeg'
248
248
  subject.handlers[0].stores[1].realize(state)
249
249
 
250
250
  state.images['input'].store_path.should == 'test-store-file.jpg'
251
251
  end
252
252
 
253
- it 'should raise NoValueForPathTemplatePlaceholerError if there is on mime type for image defined and path contains #{mimeextension}' do
253
+ it 'should raise PathRenderingError if there is on mime type for image defined and path contains #{image_mime_extension}' do
254
254
  expect {
255
255
  subject.handlers[0].stores[1].realize(state)
256
- }.to raise_error Configuration::NoValueForPathTemplatePlaceholerError, %q{cannot generate path 'mimeextension' from template 'test-store-file.#{mimeextension}': no value for '#{mimeextension}'}
256
+ }.to raise_error Configuration::PathRenderingError, %q{cannot generate path 'image_mime_extension' from template 'test-store-file.#{image_mime_extension}': image 'input' does not have data for variable 'image_mime_extension'}
257
257
  end
258
258
  end
259
259
 
@@ -39,6 +39,156 @@ describe Configuration do
39
39
  end
40
40
 
41
41
  describe Configuration::RequestState do
42
+ subject do
43
+ Configuration::RequestState.new(
44
+ 'test',
45
+ {operation: 'pad'},
46
+ '/hello/world.jpg',
47
+ {width: '123', height: '321'}
48
+ )
49
+ end
50
+
51
+ it 'should behave like hash' do
52
+ subject['a'] = 'b'
53
+ subject['a'].should == 'b'
54
+ end
55
+
56
+ it 'should provide body' do
57
+ subject.body.should == 'test'
58
+ end
59
+
60
+ describe 'variables' do
61
+ it 'should provide path' do
62
+ subject[:path].should == '/hello/world.jpg'
63
+ end
64
+
65
+ it 'should provide query string params' do
66
+ subject[:width].should == '123'
67
+ subject[:height].should == '321'
68
+ end
69
+
70
+ it 'should provide matches' do
71
+ subject[:operation].should == 'pad'
72
+ end
73
+
74
+ it 'should provide query_string_options' do
75
+ subject[:query_string_options].should == 'height:321,width:123'
76
+ end
77
+
78
+ it 'should provide request body digest' do
79
+ subject[:digest].should == '9f86d081884c7d65' # deprecated
80
+ subject[:input_digest].should == '9f86d081884c7d65'
81
+ end
82
+
83
+ it 'should provide request body full sha256 checsum' do
84
+ subject[:input_sha256].should == '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
85
+ end
86
+
87
+ it 'should provide input image mime extension' do
88
+ subject.images['input'] = Struct.new(:data, :mime_type).new('image body', 'image/jpeg')
89
+ subject.images['input'].extend Configuration::ImageMetaData
90
+ subject[:input_image_mime_extension].should == 'jpg'
91
+ end
92
+
93
+ it 'should provide input image width and height' do
94
+ subject.images['input'] = Struct.new(:data, :width, :height).new('image body', 128, 256)
95
+ subject[:input_image_width].should == 128
96
+ subject[:input_image_height].should == 256
97
+ end
98
+
99
+ it 'should provide image body digest' do
100
+ subject.images['abc'] = Struct.new(:data).new('image body')
101
+ subject.with_locals(image_name: 'abc')[:image_digest].should == 'f5288dd892bb007b'
102
+ end
103
+
104
+ it 'should provide image body full sha256 checsum' do
105
+ subject.images['abc'] = Struct.new(:data).new('image body')
106
+ subject.with_locals(image_name: 'abc')[:image_sha256].should == 'f5288dd892bb007b607304a8fb20c91ea769dcd04d82cc8ddf3239602867eb4d'
107
+ end
108
+
109
+ it 'should provide uuid' do
110
+ subject[:uuid].should_not be_empty
111
+ subject[:uuid].should == subject[:uuid]
112
+ end
113
+
114
+ it 'should provide extension' do
115
+ subject[:extension].should == 'jpg'
116
+ end
117
+
118
+ it 'should provide dirname' do
119
+ subject[:dirname].should == '/hello'
120
+ end
121
+
122
+ it 'should provide basename' do
123
+ subject[:basename].should == 'world'
124
+ end
125
+
126
+ it 'should provide image mime extension' do
127
+ subject.images['abc'] = Struct.new(:data, :mime_type).new('image body', 'image/jpeg')
128
+ subject.images['abc'].extend Configuration::ImageMetaData
129
+ subject.with_locals(image_name: 'abc')[:mimeextension].should == 'jpg' # deprecated
130
+ subject.with_locals(image_name: 'abc')[:image_mime_extension].should == 'jpg'
131
+ end
132
+
133
+ it 'should provide image width and height' do
134
+ subject.images['abc'] = Struct.new(:data, :width, :height).new('image body', 128, 256)
135
+ subject.with_locals(image_name: 'abc')[:image_width].should == 128
136
+ subject.with_locals(image_name: 'abc')[:image_height].should == 256
137
+ end
138
+
139
+ describe "error handling" do
140
+ it 'should raise NoRequestBodyToGenerateMetaVariableError when empty body was provided and body needed for variable calculation' do
141
+ subject = Configuration::RequestState.new(
142
+ '',
143
+ {operation: 'pad'},
144
+ '/hello/world.jpg',
145
+ {width: '123', height: '321'}
146
+ )
147
+
148
+ expect {
149
+ subject[:input_digest]
150
+ }.to raise_error Configuration::NoRequestBodyToGenerateMetaVariableError, %q{need not empty request body to generate value for 'input_digest'}
151
+ end
152
+
153
+ it 'should raise ImageNotLoadedError when asking for image related variable of not loaded image' do
154
+ expect {
155
+ subject.with_locals(image_name: 'abc')[:image_mime_extension]
156
+ }.to raise_error Configuration::ImageNotLoadedError, %q{image 'abc' not loaded}
157
+ end
158
+
159
+ it 'should raise NoVariableToGenerateMetaVariableError when no image_name was defined' do
160
+ expect {
161
+ subject.with_locals({})[:image_mime_extension]
162
+ }.to raise_error Configuration::NoVariableToGenerateMetaVariableError, %q{need 'image_name' variable to generate value for 'image_mime_extension'}
163
+ end
164
+
165
+ it 'should raise NoVariableToGenerateMetaVariableError when no path was defined' do
166
+ expect {
167
+ subject.delete(:path)
168
+ subject[:basename]
169
+ }.to raise_error Configuration::NoVariableToGenerateMetaVariableError, %q{need 'path' variable to generate value for 'basename'}
170
+ end
171
+
172
+ it 'should raise NoImageDataForVariableError when image has no mime type' do
173
+ subject.images['abc'] = Struct.new(:data, :mime_type).new('image body', nil)
174
+ subject.images['abc'].extend Configuration::ImageMetaData
175
+ expect {
176
+ subject.with_locals(image_name: 'abc')[:image_mime_extension]
177
+ }.to raise_error Configuration::NoImageDataForVariableError, %q{image 'abc' does not have data for variable 'image_mime_extension'}
178
+ end
179
+
180
+ it 'should raise NoImageDataForVariableError when image has no known width or height' do
181
+ subject.images['abc'] = Struct.new(:data, :width, :height).new('image body', nil, nil)
182
+ expect {
183
+ subject.with_locals(image_name: 'abc')[:image_width]
184
+ }.to raise_error Configuration::NoImageDataForVariableError, %q{image 'abc' does not have data for variable 'image_width'}
185
+ expect {
186
+ subject.with_locals(image_name: 'abc')[:image_height]
187
+ }.to raise_error Configuration::NoImageDataForVariableError, %q{image 'abc' does not have data for variable 'image_height'}
188
+ end
189
+ end
190
+ end
191
+
42
192
  it 'should raise ImageNotLoadedError if image lookup fails' do
43
193
  expect {
44
194
  Configuration::RequestState.new.images['test']
@@ -72,27 +222,27 @@ describe Configuration do
72
222
 
73
223
  describe 'sources' do
74
224
  it 'should have implicit InputSource on non get handlers' do
75
- subject.handlers[0].image_sources.first.should_not be_a Configuration::InputSource
76
- subject.handlers[1].image_sources.first.should be_a Configuration::InputSource
77
- subject.handlers[2].image_sources.first.should be_a Configuration::InputSource
225
+ subject.handlers[0].sources.first.should_not be_a Configuration::InputSource
226
+ subject.handlers[1].sources.first.should be_a Configuration::InputSource
227
+ subject.handlers[2].sources.first.should be_a Configuration::InputSource
78
228
  end
79
229
 
80
230
  describe Configuration::InputSource do
81
231
  it 'should copy input data to "input" image when realized' do
82
232
  state = Configuration::RequestState.new('abc')
83
- input_source = subject.handlers[1].image_sources[0].realize(state)
233
+ input_source = subject.handlers[1].sources[0].realize(state)
84
234
  state.images['input'].data.should == 'abc'
85
235
  end
86
236
 
87
237
  it 'should have nil mime type' do
88
238
  state = Configuration::RequestState.new('abc')
89
- input_source = subject.handlers[1].image_sources[0].realize(state)
239
+ input_source = subject.handlers[1].sources[0].realize(state)
90
240
  state.images['input'].mime_type.should be_nil
91
241
  end
92
242
 
93
243
  it 'should have nil source path and url' do
94
244
  state = Configuration::RequestState.new('abc')
95
- input_source = subject.handlers[1].image_sources[0].realize(state)
245
+ input_source = subject.handlers[1].sources[0].realize(state)
96
246
  state.images['input'].source_path.should be_nil
97
247
  state.images['input'].source_url.should be_nil
98
248
  end
@@ -0,0 +1,45 @@
1
+ require_relative 'spec_helper'
2
+ require 'httpimagestore/configuration'
3
+ Configuration::Scope.logger = Logger.new('/dev/null')
4
+
5
+ require 'httpimagestore/configuration/thumbnailer'
6
+ require 'httpimagestore/configuration/identify'
7
+ MemoryLimit.logger = Logger.new('/dev/null')
8
+
9
+ describe Configuration do
10
+ describe 'thumbnailer' do
11
+ before :all do
12
+ log = support_dir + 'server.log'
13
+ start_server(
14
+ "httpthumbnailer -f -d -l #{log}",
15
+ '/tmp/httpthumbnailer.pid',
16
+ log,
17
+ 'http://localhost:3100/'
18
+ )
19
+ end
20
+
21
+ let :state do
22
+ Configuration::RequestState.new(
23
+ (support_dir + 'compute.jpg').read
24
+ )
25
+ end
26
+
27
+ subject do
28
+ Configuration.read(<<-'EOF')
29
+ put {
30
+ identify "input"
31
+ }
32
+ EOF
33
+ end
34
+
35
+ it 'should provide input image mime type' do
36
+ subject.handlers[0].sources[0].realize(state)
37
+ state.images['input'].mime_type.should be_nil
38
+
39
+ subject.handlers[0].processors[0].realize(state)
40
+ state.images['input'].mime_type.should == 'image/jpeg'
41
+ end
42
+ end
43
+ end
44
+
45
+
@@ -27,7 +27,7 @@ describe Configuration do
27
27
  end
28
28
 
29
29
  before :each do
30
- subject.handlers[0].image_sources[0].realize(state)
30
+ subject.handlers[0].sources[0].realize(state)
31
31
  end
32
32
 
33
33
  it 'should provide given image' do
@@ -112,7 +112,7 @@ describe Configuration do
112
112
  }
113
113
  EOF
114
114
 
115
- subject.handlers[0].image_sources[0].realize(state)
115
+ subject.handlers[0].sources[0].realize(state)
116
116
  subject.handlers[0].stores[0].realize(state)
117
117
  subject.handlers[0].output.realize(state)
118
118
 
@@ -142,8 +142,8 @@ describe Configuration do
142
142
  }
143
143
  EOF
144
144
 
145
- subject.handlers[0].image_sources[0].realize(state)
146
- subject.handlers[0].image_sources[1].realize(state)
145
+ subject.handlers[0].sources[0].realize(state)
146
+ subject.handlers[0].sources[1].realize(state)
147
147
  subject.handlers[0].stores[0].realize(state)
148
148
  subject.handlers[0].stores[1].realize(state)
149
149
  subject.handlers[0].output.realize(state)
@@ -185,9 +185,9 @@ describe Configuration do
185
185
  end
186
186
 
187
187
  it 'should output store path only for images that names match if-image-name-on list' do
188
- subject.handlers[0].image_sources[0].realize(state)
189
- subject.handlers[0].image_sources[1].realize(state)
190
- subject.handlers[0].image_sources[2].realize(state)
188
+ subject.handlers[0].sources[0].realize(state)
189
+ subject.handlers[0].sources[1].realize(state)
190
+ subject.handlers[0].sources[2].realize(state)
191
191
  subject.handlers[0].stores[0].realize(state)
192
192
  subject.handlers[0].stores[1].realize(state)
193
193
  subject.handlers[0].stores[2].realize(state)
@@ -207,7 +207,7 @@ describe Configuration do
207
207
  }
208
208
  EOF
209
209
 
210
- subject.handlers[0].image_sources[0].realize(state)
210
+ subject.handlers[0].sources[0].realize(state)
211
211
 
212
212
  expect {
213
213
  subject.handlers[0].output.realize(state)
@@ -230,7 +230,7 @@ describe Configuration do
230
230
  }
231
231
  EOF
232
232
 
233
- subject.handlers[0].image_sources[0].realize(state)
233
+ subject.handlers[0].sources[0].realize(state)
234
234
  subject.handlers[0].stores[0].realize(state)
235
235
  subject.handlers[0].output.realize(state)
236
236
 
@@ -260,8 +260,8 @@ describe Configuration do
260
260
  }
261
261
  EOF
262
262
 
263
- subject.handlers[0].image_sources[0].realize(state)
264
- subject.handlers[0].image_sources[1].realize(state)
263
+ subject.handlers[0].sources[0].realize(state)
264
+ subject.handlers[0].sources[1].realize(state)
265
265
  subject.handlers[0].stores[0].realize(state)
266
266
  subject.handlers[0].stores[1].realize(state)
267
267
  subject.handlers[0].output.realize(state)
@@ -303,9 +303,9 @@ describe Configuration do
303
303
  end
304
304
 
305
305
  it 'should output store url only for images that names match if-image-name-on list' do
306
- subject.handlers[0].image_sources[0].realize(state)
307
- subject.handlers[0].image_sources[1].realize(state)
308
- subject.handlers[0].image_sources[2].realize(state)
306
+ subject.handlers[0].sources[0].realize(state)
307
+ subject.handlers[0].sources[1].realize(state)
308
+ subject.handlers[0].sources[2].realize(state)
309
309
  subject.handlers[0].stores[0].realize(state)
310
310
  subject.handlers[0].stores[1].realize(state)
311
311
  subject.handlers[0].stores[2].realize(state)
@@ -325,7 +325,7 @@ describe Configuration do
325
325
  }
326
326
  EOF
327
327
 
328
- subject.handlers[0].image_sources[0].realize(state)
328
+ subject.handlers[0].sources[0].realize(state)
329
329
 
330
330
  expect {
331
331
  subject.handlers[0].output.realize(state)