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.
@@ -2,26 +2,28 @@ require_relative 'spec_helper'
2
2
  require 'httpimagestore/configuration'
3
3
  Configuration::Scope.logger = Logger.new('/dev/null')
4
4
 
5
+ require 'httpimagestore/configuration/handler'
5
6
  require 'httpimagestore/configuration/path'
7
+ MemoryLimit.logger = Logger.new('/dev/null')
6
8
 
7
9
  describe Configuration do
8
10
  describe 'path rendering' do
9
11
  it 'should load paths form single line and multi line declarations and render spec templates' do
10
12
  subject = Configuration.read(<<-'EOF')
11
13
  path "uri" "#{path}"
12
- path "hash" "#{digest}.#{extension}"
14
+ path "hash" "#{input_digest}.#{extension}"
13
15
  path {
14
- "hash-name" "#{digest}/#{imagename}.#{extension}"
15
- "structured" "#{dirname}/#{digest}/#{basename}.#{extension}"
16
- "structured-name" "#{dirname}/#{digest}/#{basename}-#{imagename}.#{extension}"
16
+ "hash-name" "#{input_digest}/#{image_name}.#{extension}"
17
+ "structured" "#{dirname}/#{input_digest}/#{basename}.#{extension}"
18
+ "structured-name" "#{dirname}/#{input_digest}/#{basename}-#{image_name}.#{extension}"
17
19
  }
18
20
  EOF
19
21
 
20
22
  subject.paths['uri'].render(path: 'test/abc.jpg').should == 'test/abc.jpg'
21
- subject.paths['hash'].render(path: 'test/abc.jpg', _body: 'hello').should == '2cf24dba5fb0a30e.jpg'
22
- subject.paths['hash-name'].render(path: 'test/abc.jpg', _body: 'hello', imagename: 'xbrna').should == '2cf24dba5fb0a30e/xbrna.jpg'
23
- subject.paths['structured'].render(path: 'test/abc.jpg', _body: 'hello').should == 'test/2cf24dba5fb0a30e/abc.jpg'
24
- subject.paths['structured-name'].render(path: 'test/abc.jpg', _body: 'hello', imagename: 'xbrna').should == 'test/2cf24dba5fb0a30e/abc-xbrna.jpg'
23
+ subject.paths['hash'].render(input_digest: '2cf24dba5fb0a30e', extension: 'jpg').should == '2cf24dba5fb0a30e.jpg'
24
+ subject.paths['hash-name'].render(input_digest: '2cf24dba5fb0a30e', image_name: 'xbrna', extension: 'jpg').should == '2cf24dba5fb0a30e/xbrna.jpg'
25
+ subject.paths['structured'].render(dirname: 'test', input_digest: '2cf24dba5fb0a30e', basename: 'abc', extension: 'jpg').should == 'test/2cf24dba5fb0a30e/abc.jpg'
26
+ subject.paths['structured-name'].render(dirname: 'test', input_digest: '2cf24dba5fb0a30e', basename: 'abc', extension: 'jpg', image_name: 'xbrna').should == 'test/2cf24dba5fb0a30e/abc-xbrna.jpg'
25
27
  end
26
28
 
27
29
  describe 'error handling' do
@@ -62,29 +64,74 @@ describe Configuration do
62
64
  subject.paths['test'].render
63
65
  }.to raise_error Configuration::NoValueForPathTemplatePlaceholerError, %q{cannot generate path 'test' from template '#{abc}#{xyz}': no value for '#{abc}'}
64
66
  end
67
+ end
65
68
 
66
- it 'should raise NoValueForPathTemplatePlaceholerError if path value is not found' do
67
- subject = Configuration.read(<<-'EOF')
69
+ describe 'rendering from RequestState' do
70
+ let :state do
71
+ Configuration::RequestState.new(
72
+ 'test',
73
+ {operation: 'pad'},
74
+ 'test/abc.jpg',
75
+ {width: '123', height: '321'}
76
+ )
77
+ end
78
+
79
+ subject do
80
+ Configuration.read(<<-'EOF')
81
+ path "uri" "#{path}"
82
+ path "hash" "#{input_digest}.#{extension}"
68
83
  path {
69
- "test" "#{dirname}#{basename}"
84
+ "hash-name" "#{input_digest}/#{image_name}.#{extension}"
85
+ "structured" "#{dirname}/#{input_digest}/#{basename}.#{extension}"
86
+ "structured-name" "#{dirname}/#{input_digest}/#{basename}-#{image_name}.#{extension}"
70
87
  }
88
+ path "name" "#{image_name}"
89
+ path "base" "#{basename}"
71
90
  EOF
91
+ end
72
92
 
73
- expect {
74
- subject.paths['test'].render
75
- }.to raise_error Configuration::NoMetaValueForPathTemplatePlaceholerError, %q{cannot generate path 'test' from template '#{dirname}#{basename}': need 'path' to generate value for '#{dirname}'}
93
+ it 'should render path using meta variables and locals' do
94
+
95
+ subject.paths['uri'].render(state).should == 'test/abc.jpg'
96
+ subject.paths['hash'].render(state).should == '9f86d081884c7d65.jpg'
97
+ subject.paths['hash-name'].render(state.with_locals(image_name: 'xbrna')).should == '9f86d081884c7d65/xbrna.jpg'
98
+ subject.paths['structured'].render(state).should == 'test/9f86d081884c7d65/abc.jpg'
99
+ subject.paths['structured-name'].render(state.with_locals(image_name: 'xbrna')).should == 'test/9f86d081884c7d65/abc-xbrna.jpg'
76
100
  end
77
101
 
78
- it 'should raise NoValueForPathTemplatePlaceholerError if body value is not found' do
79
- subject = Configuration.read(<<-'EOF')
80
- path {
81
- "test" "#{digest}"
82
- }
83
- EOF
102
+ describe 'error handling' do
103
+ let :state do
104
+ Configuration::RequestState.new(
105
+ '',
106
+ {operation: 'pad'},
107
+ 'test/abc.jpg',
108
+ {width: '123', height: '321'}
109
+ )
110
+ end
84
111
 
85
- expect {
86
- subject.paths['test'].render(path: '')
87
- }.to raise_error Configuration::NoMetaValueForPathTemplatePlaceholerError, %q{cannot generate path 'test' from template '#{digest}': need 'body' to generate value for '#{digest}'}
112
+ it 'should raise PathRenderingError if body was expected but not provided' do
113
+ expect {
114
+ subject.paths['hash'].render(state)
115
+ }.to raise_error Configuration::PathRenderingError, %q{cannot generate path 'hash' from template '#{input_digest}.#{extension}': need not empty request body to generate value for 'input_digest'}
116
+ end
117
+
118
+ it 'should raise PathRenderingError if variable not defined' do
119
+ expect {
120
+ subject.paths['name'].render(state)
121
+ }.to raise_error Configuration::PathRenderingError, %q{cannot generate path 'name' from template '#{image_name}': variable 'image_name' not defined}
122
+ end
123
+
124
+ it 'should raise PathRenderingError if meta variable dependent variable not defined' do
125
+ state = Configuration::RequestState.new(
126
+ '',
127
+ {operation: 'pad'},
128
+ nil,
129
+ {width: '123', height: '321'}
130
+ )
131
+ expect {
132
+ subject.paths['base'].render(state)
133
+ }.to raise_error Configuration::PathRenderingError, %q{cannot generate path 'base' from template '#{basename}': need 'path' variable to generate value for 'basename'}
134
+ end
88
135
  end
89
136
  end
90
137
  end
@@ -66,6 +66,39 @@ else
66
66
  end
67
67
  end
68
68
 
69
+ describe Configuration::S3SourceStoreBase::CacheRoot do
70
+ subject do
71
+ Configuration::S3SourceStoreBase::CacheRoot.new('/tmp')
72
+ end
73
+
74
+ before do
75
+ @cached_object = Pathname.new('/tmp/0d/bf/50c256d6b6efe55d11d0b6b50600')
76
+ @cached_object.dirname.mkpath
77
+ @cached_object.open('w') do |io|
78
+ io.write 'abc'
79
+ end
80
+
81
+ test2 = Pathname.new('/tmp/46/b9/7a454d831d7570abbb833330d9fb')
82
+ test2.unlink if test2.exist?
83
+ end
84
+
85
+ it 'should build cache file location for storage location from bucket and key' do
86
+ subject.cache_file('mybucket', 'hello/world.jpg').should == "0d/bf/50c256d6b6efe55d11d0b6b50600"
87
+ end
88
+
89
+ it 'should look up object stored on disk by bucket and key' do
90
+ subject.open('mybucket', 'hello/world.jpg') do |io|
91
+ io.read.should == 'abc'
92
+ end
93
+ end
94
+
95
+ it 'should create cache object for bucket and key if it does not exist' do
96
+ subject.open('mybucket', 'hello/world2.jpg') do |io|
97
+ io.read.should == ''
98
+ end
99
+ end
100
+ end
101
+
69
102
  describe Configuration::S3Source do
70
103
  let :state do
71
104
  Configuration::RequestState.new('abc', {test_image: 'test.jpg'})
@@ -91,20 +124,20 @@ else
91
124
  end
92
125
 
93
126
  it 'should source image from S3 using path spec' do
94
- subject.handlers[0].image_sources[0].should be_a Configuration::S3Source
95
- subject.handlers[0].image_sources[0].realize(state)
127
+ subject.handlers[0].sources[0].should be_a Configuration::S3Source
128
+ subject.handlers[0].sources[0].realize(state)
96
129
 
97
130
  state.images['original'].data.should == @test_data
98
131
  end
99
132
 
100
133
  it 'should use S3 object content type for mime type' do
101
- subject.handlers[0].image_sources[0].realize(state)
134
+ subject.handlers[0].sources[0].realize(state)
102
135
 
103
136
  state.images['original'].mime_type.should == 'image/jpeg'
104
137
  end
105
138
 
106
139
  it 'should provide source path and HTTPS url' do
107
- subject.handlers[0].image_sources[0].realize(state)
140
+ subject.handlers[0].sources[0].realize(state)
108
141
 
109
142
  state.images['original'].source_path.should == "test.jpg"
110
143
  state.images['original'].source_url.should start_with "https://"
@@ -126,7 +159,7 @@ else
126
159
  end
127
160
 
128
161
  it 'should still provide valid HTTPS URL incliding prefix' do
129
- subject.handlers[0].image_sources[0].realize(state)
162
+ subject.handlers[0].sources[0].realize(state)
130
163
 
131
164
  state.images['original'].source_url.should start_with "https://"
132
165
  state.images['original'].source_url.should include ENV['AWS_S3_TEST_BUCKET']
@@ -136,12 +169,138 @@ else
136
169
  end
137
170
 
138
171
  it 'should provide source path without prefix' do
139
- subject.handlers[0].image_sources[0].realize(state)
172
+ subject.handlers[0].sources[0].realize(state)
140
173
 
141
174
  state.images['original'].source_path.should == "test.jpg"
142
175
  end
143
176
  end
144
177
 
178
+ describe 'object cache' do
179
+ let :state do
180
+ Configuration::RequestState.new('abc', {test_image: 'test/ghost.jpg'})
181
+ end
182
+
183
+ subject do
184
+ Configuration.read(<<-EOF)
185
+ s3 key="#{ENV['AWS_ACCESS_KEY_ID']}" secret="#{ENV['AWS_SECRET_ACCESS_KEY']}"
186
+ path "hash" "\#{test_image}"
187
+ get {
188
+ source_s3 "original" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="hash" cache-root="/tmp"
189
+ source_s3 "original_cached" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="hash" cache-root="/tmp"
190
+ source_s3 "original_cached_public" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="hash" cache-root="/tmp" public="true"
191
+ source_s3 "original_cached_public2" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="hash" cache-root="/tmp" public="true"
192
+ }
193
+ EOF
194
+ end
195
+
196
+ before do
197
+ @cached_object = Pathname.new('/tmp/ce/26/b196585e28aa99f55b1260b629e2')
198
+ @cached_object.dirname.mkpath
199
+ @cached_object.open('w') do |io|
200
+ header = MessagePack.pack(
201
+ 'private_url' => 'https://s3-eu-west-1.amazonaws.com/test/ghost.jpg?' + ENV['AWS_ACCESS_KEY_ID'],
202
+ 'public_url' => 'https://s3-eu-west-1.amazonaws.com/test/ghost.jpg',
203
+ 'content_type' => 'image/jpeg'
204
+ )
205
+ io.write [header.length].pack('L') # header length
206
+ io.write header
207
+ io.write 'abc'
208
+ end
209
+ end
210
+
211
+ it 'should use cache when configured' do
212
+ subject.handlers[0].sources[0].should be_a Configuration::S3Source
213
+ subject.handlers[0].sources[0].realize(state)
214
+
215
+ state.images['original'].data.should == 'abc'
216
+ end
217
+
218
+ it 'should keep mime type' do
219
+ subject.handlers[0].sources[0].realize(state)
220
+
221
+ state.images['original'].mime_type.should == 'image/jpeg'
222
+ end
223
+
224
+ it 'should keep private source URL' do
225
+ subject.handlers[0].sources[0].realize(state)
226
+
227
+ state.images['original'].source_url.should == 'https://s3-eu-west-1.amazonaws.com/test/ghost.jpg?' + ENV['AWS_ACCESS_KEY_ID']
228
+ end
229
+
230
+ it 'should keep public source URL' do
231
+ subject = Configuration.read(<<-EOF)
232
+ s3 key="#{ENV['AWS_ACCESS_KEY_ID']}" secret="#{ENV['AWS_SECRET_ACCESS_KEY']}"
233
+ path "hash" "\#{test_image}"
234
+ get {
235
+ source_s3 "original" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="hash" cache-root="/tmp" public=true
236
+ }
237
+ EOF
238
+ subject.handlers[0].sources[0].realize(state)
239
+
240
+ state.images['original'].source_url.should == 'https://s3-eu-west-1.amazonaws.com/test/ghost.jpg'
241
+ end
242
+
243
+ it 'shluld use object stored in S3 when not found in the cache' do
244
+ cache_file = Pathname.new('/tmp/af/a3/5eaf0a614693e2d1ed455ac1cedb')
245
+ cache_file.unlink if cache_file.exist?
246
+
247
+ state = Configuration::RequestState.new('abc', {test_image: 'test.jpg'})
248
+ subject.handlers[0].sources[0].realize(state)
249
+
250
+ cache_file.should exist
251
+ end
252
+
253
+ it 'should use cached object writen when it was initialy read' do
254
+ cache_file = Pathname.new('/tmp/af/a3/5eaf0a614693e2d1ed455ac1cedb')
255
+ cache_file.unlink if cache_file.exist?
256
+
257
+ state = Configuration::RequestState.new('abc', {test_image: 'test.jpg'})
258
+ subject.handlers[0].sources[0].realize(state)
259
+
260
+ cache_file.should exist
261
+
262
+ subject.handlers[0].sources[1].realize(state)
263
+
264
+ state.images['original'].data.should == @test_data
265
+ state.images['original'].mime_type.should == 'image/jpeg'
266
+
267
+ state.images['original_cached'].data.should == @test_data
268
+ state.images['original_cached'].mime_type.should == 'image/jpeg'
269
+ end
270
+
271
+ it 'should use update cached object when new properties are read from S3' do
272
+ cache_file = Pathname.new('/tmp/af/a3/5eaf0a614693e2d1ed455ac1cedb')
273
+ cache_file.unlink if cache_file.exist?
274
+
275
+ state = Configuration::RequestState.new('abc', {test_image: 'test.jpg'})
276
+
277
+ ## cache with private URL
278
+ subject.handlers[0].sources[0].realize(state)
279
+
280
+ cache_file.should exist
281
+ sum = Digest::SHA2.new.update(cache_file.read).to_s
282
+
283
+ ## read from cache with private URL
284
+ subject.handlers[0].sources[1].realize(state)
285
+
286
+ # no change
287
+ Digest::SHA2.new.update(cache_file.read).to_s.should == sum
288
+
289
+ ## read from cache; add public URL
290
+ subject.handlers[0].sources[2].realize(state)
291
+
292
+ # should get updated
293
+ Digest::SHA2.new.update(cache_file.read).to_s.should_not == sum
294
+
295
+ sum = Digest::SHA2.new.update(cache_file.read).to_s
296
+ ## read from cahce
297
+ subject.handlers[0].sources[3].realize(state)
298
+
299
+ # no change
300
+ Digest::SHA2.new.update(cache_file.read).to_s.should == sum
301
+ end
302
+ end
303
+
145
304
  describe 'non encrypted connection mode' do
146
305
  subject do
147
306
  Configuration.read(<<-EOF)
@@ -154,14 +313,14 @@ else
154
313
  end
155
314
 
156
315
  it 'should source image from S3 using path spec' do
157
- subject.handlers[0].image_sources[0].should be_a Configuration::S3Source
158
- subject.handlers[0].image_sources[0].realize(state)
316
+ subject.handlers[0].sources[0].should be_a Configuration::S3Source
317
+ subject.handlers[0].sources[0].realize(state)
159
318
 
160
319
  state.images['original'].data.should == @test_data
161
320
  end
162
321
 
163
322
  it 'should provide source HTTP url' do
164
- subject.handlers[0].image_sources[0].realize(state)
323
+ subject.handlers[0].sources[0].realize(state)
165
324
  state.images['original'].source_url.should start_with "http://"
166
325
  state.images['original'].source_url.should include ENV['AWS_S3_TEST_BUCKET']
167
326
  state.images['original'].source_url.should include "/test.jpg"
@@ -181,23 +340,23 @@ else
181
340
  subject do
182
341
  Configuration.read(<<-EOF)
183
342
  s3 key="#{ENV['AWS_ACCESS_KEY_ID']}" secret="#{ENV['AWS_SECRET_ACCESS_KEY']}" ssl=false
184
- path "imagename" "\#{imagename}.jpg"
343
+ path "image_name" "\#{image_name}.jpg"
185
344
  path "bucket" "\#{bucket}.jpg"
186
345
  get {
187
- source_s3 "test-image-name" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="imagename"
346
+ source_s3 "test-image-name" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="image_name"
188
347
  source_s3 "bucket" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="bucket"
189
348
  }
190
349
  EOF
191
350
  end
192
351
 
193
- it 'should provide image name to be used as #{imagename}' do
194
- subject.handlers[0].image_sources[0].realize(state)
352
+ it 'should provide image name to be used as #{image_name}' do
353
+ subject.handlers[0].sources[0].realize(state)
195
354
  state.images['test-image-name'].source_path.should == 'test-image-name.jpg'
196
355
  state.images['test-image-name'].data.should == 'hello world'
197
356
  end
198
357
 
199
358
  it 'should provide bucket to be used as #{bucket}' do
200
- subject.handlers[0].image_sources[1].realize(state)
359
+ subject.handlers[0].sources[1].realize(state)
201
360
  state.images['bucket'].source_path.should == "#{ENV['AWS_S3_TEST_BUCKET']}.jpg"
202
361
  state.images['bucket'].data.should == 'hello bucket'
203
362
  end
@@ -242,7 +401,7 @@ else
242
401
  }
243
402
  EOF
244
403
  expect {
245
- subject.handlers[0].image_sources[0].realize(state)
404
+ subject.handlers[0].sources[0].realize(state)
246
405
  }.to raise_error Configuration::S3NotConfiguredError, 'S3 client not configured'
247
406
  end
248
407
 
@@ -255,7 +414,7 @@ else
255
414
  }
256
415
  EOF
257
416
  expect {
258
- subject.handlers[0].image_sources[0].realize(state)
417
+ subject.handlers[0].sources[0].realize(state)
259
418
  }.to raise_error Configuration::S3NoSuchBucketError, %{S3 bucket '#{ENV['AWS_S3_TEST_BUCKET']}X' does not exist}
260
419
  end
261
420
 
@@ -268,7 +427,7 @@ else
268
427
  }
269
428
  EOF
270
429
  expect {
271
- subject.handlers[0].image_sources[0].realize(state)
430
+ subject.handlers[0].sources[0].realize(state)
272
431
  }.to raise_error Configuration::S3NoSuchKeyError, %{S3 bucket '#{ENV['AWS_S3_TEST_BUCKET']}' does not contain key 'blah'}
273
432
  end
274
433
 
@@ -281,7 +440,7 @@ else
281
440
  }
282
441
  EOF
283
442
  expect {
284
- subject.handlers[0].image_sources[0].realize(state)
443
+ subject.handlers[0].sources[0].realize(state)
285
444
  }.to raise_error Configuration::S3AccessDenied, %{access to S3 bucket 'blah' or key 'test.jpg' was denied}
286
445
  end
287
446
  end
@@ -293,7 +452,7 @@ else
293
452
 
294
453
  it 'should raise MemoryLimit::MemoryLimitedExceededError when sourcing bigger image than limit' do
295
454
  expect {
296
- subject.handlers[0].image_sources[0].realize(state)
455
+ subject.handlers[0].sources[0].realize(state)
297
456
  }.to raise_error MemoryLimit::MemoryLimitedExceededError
298
457
  end
299
458
  end
@@ -326,7 +485,7 @@ else
326
485
  end
327
486
 
328
487
  before :each do
329
- subject.handlers[0].image_sources[0].realize(state)
488
+ subject.handlers[0].sources[0].realize(state)
330
489
  end
331
490
 
332
491
  it 'should source image from S3 using path spec' do
@@ -518,18 +677,18 @@ else
518
677
  subject do
519
678
  Configuration.read(<<-EOF)
520
679
  s3 key="#{ENV['AWS_ACCESS_KEY_ID']}" secret="#{ENV['AWS_SECRET_ACCESS_KEY']}" ssl=false
521
- path "imagename" "\#{imagename}"
680
+ path "image_name" "\#{image_name}"
522
681
  path "bucket" "\#{bucket}"
523
- path "mimeextension" "\#{mimeextension}"
682
+ path "image_mime_extension" "\#{image_mime_extension}"
524
683
  post {
525
- store_s3 "input" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="imagename"
684
+ store_s3 "input" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="image_name"
526
685
  store_s3 "input" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="bucket"
527
- store_s3 "input" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="mimeextension"
686
+ store_s3 "input" bucket="#{ENV['AWS_S3_TEST_BUCKET']}" path="image_mime_extension"
528
687
  }
529
688
  EOF
530
689
  end
531
690
 
532
- it 'should provide image name to be used as #{imagename}' do
691
+ it 'should provide image name to be used as #{image_name}' do
533
692
  subject.handlers[0].stores[0].realize(state)
534
693
 
535
694
  state.images['input'].store_path.should == 'input'
@@ -541,17 +700,17 @@ else
541
700
  state.images['input'].store_path.should == ENV['AWS_S3_TEST_BUCKET']
542
701
  end
543
702
 
544
- it 'should provide image mime type based file extension to be used as #{mimeextension}' do
703
+ it 'should provide image mime type based file extension to be used as #{image_mime_extension}' do
545
704
  state.images['input'].mime_type = 'image/jpeg'
546
705
  subject.handlers[0].stores[2].realize(state)
547
706
 
548
707
  state.images['input'].store_path.should == 'jpg'
549
708
  end
550
709
 
551
- it 'should raise NoValueForPathTemplatePlaceholerError if there is on mime type for image defined and path contains #{mimeextension}' do
710
+ it 'should raise PathRenderingError if there is on mime type for image defined and path contains #{image_mime_extension}' do
552
711
  expect {
553
712
  subject.handlers[0].stores[2].realize(state)
554
- }.to raise_error Configuration::NoValueForPathTemplatePlaceholerError, %q{cannot generate path 'mimeextension' from template '#{mimeextension}': no value for '#{mimeextension}'}
713
+ }.to raise_error Configuration::PathRenderingError, %q{cannot generate path 'image_mime_extension' from template '#{image_mime_extension}': image 'input' does not have data for variable 'image_mime_extension'}
555
714
  end
556
715
  end
557
716
 
@@ -146,7 +146,7 @@ describe Configuration do
146
146
  end
147
147
 
148
148
  before :each do
149
- subject.handlers[0].image_sources[0].realize(state)
149
+ subject.handlers[0].sources[0].realize(state)
150
150
  end
151
151
 
152
152
  describe 'thumbnailing to single spec' do
@@ -164,23 +164,23 @@ describe Configuration do
164
164
  end
165
165
 
166
166
  it 'should provide thumbnail data' do
167
- subject.handlers[0].image_sources[1].realize(state)
167
+ subject.handlers[0].processors[0].realize(state)
168
168
  state.images['original'].data.should_not be_nil
169
169
  end
170
170
 
171
171
  it 'should set thumbnail mime type' do
172
- subject.handlers[0].image_sources[1].realize(state)
172
+ subject.handlers[0].processors[0].realize(state)
173
173
  state.images['original'].mime_type.should == 'image/jpeg'
174
174
  end
175
175
 
176
176
  it 'should use input image source path and url' do
177
- subject.handlers[0].image_sources[1].realize(state)
177
+ subject.handlers[0].processors[0].realize(state)
178
178
  state.images['original'].source_path.should == 'test.in'
179
179
  state.images['original'].source_url.should == 'file://test.in'
180
180
  end
181
181
 
182
182
  it 'should set input image mime type' do
183
- subject.handlers[0].image_sources[1].realize(state)
183
+ subject.handlers[0].processors[0].realize(state)
184
184
  state.images['input'].mime_type.should == 'image/jpeg'
185
185
  end
186
186
 
@@ -202,7 +202,7 @@ describe Configuration do
202
202
 
203
203
  it 'should raise MemoryLimit::MemoryLimitedExceededError when limit is exceeded' do
204
204
  expect {
205
- subject.handlers[0].image_sources[1].realize(state)
205
+ subject.handlers[0].processors[0].realize(state)
206
206
  }.to raise_error MemoryLimit::MemoryLimitedExceededError
207
207
  end
208
208
  end
@@ -220,8 +220,8 @@ describe Configuration do
220
220
  )
221
221
 
222
222
  expect {
223
- subject.handlers[0].image_sources[0].realize(state)
224
- subject.handlers[0].image_sources[1].realize(state)
223
+ subject.handlers[0].sources[0].realize(state)
224
+ subject.handlers[0].processors[0].realize(state)
225
225
  }.to raise_error Configuration::Thumbnail::ThumbnailingError # WTF?, "thumbnailing of 'input' into 'original' failed: at least one image dimension is zero: 0x10"
226
226
  end
227
227
 
@@ -266,26 +266,26 @@ describe Configuration do
266
266
  end
267
267
 
268
268
  it 'should provide thumbnail data' do
269
- subject.handlers[0].image_sources[1].realize(state)
269
+ subject.handlers[0].processors[0].realize(state)
270
270
  state.images['original'].data.should_not be_nil
271
271
  state.images['small'].data.should_not be_nil
272
272
  state.images['padded'].data.should_not be_nil
273
273
  end
274
274
 
275
275
  it 'should set thumbnail mime type' do
276
- subject.handlers[0].image_sources[1].realize(state)
276
+ subject.handlers[0].processors[0].realize(state)
277
277
  state.images['original'].mime_type.should == 'image/jpeg'
278
278
  state.images['small'].mime_type.should == 'image/jpeg'
279
279
  state.images['padded'].mime_type.should == 'image/png'
280
280
  end
281
281
 
282
282
  it 'should set input image mime type' do
283
- subject.handlers[0].image_sources[1].realize(state)
283
+ subject.handlers[0].processors[0].realize(state)
284
284
  state.images['input'].mime_type.should == 'image/jpeg'
285
285
  end
286
286
 
287
287
  it 'should use input image source path and url' do
288
- subject.handlers[0].image_sources[1].realize(state)
288
+ subject.handlers[0].processors[0].realize(state)
289
289
  state.images['original'].source_path.should == 'test.in'
290
290
  state.images['original'].source_url.should == 'file://test.in'
291
291
  state.images['small'].source_path.should == 'test.in'
@@ -312,7 +312,7 @@ describe Configuration do
312
312
 
313
313
  it 'should raise MemoryLimit::MemoryLimitedExceededError when limit is exceeded' do
314
314
  expect {
315
- subject.handlers[0].image_sources[1].realize(state)
315
+ subject.handlers[0].processors[0].realize(state)
316
316
  }.to raise_error MemoryLimit::MemoryLimitedExceededError
317
317
  end
318
318
  end
@@ -344,7 +344,7 @@ describe Configuration do
344
344
  end
345
345
 
346
346
  it 'should provide thumbnails that name match if-image-name-on list' do
347
- subject.handlers[0].image_sources[1].realize(state)
347
+ subject.handlers[0].processors[0].realize(state)
348
348
  state.images.should_not include 'original'
349
349
  state.images['small'].data.should_not be_nil
350
350
  state.images['padded'].data.should_not be_nil
@@ -363,10 +363,10 @@ describe Configuration do
363
363
  }
364
364
  )
365
365
 
366
- subject.handlers[0].image_sources[0].realize(state)
366
+ subject.handlers[0].sources[0].realize(state)
367
367
 
368
368
  expect {
369
- subject.handlers[0].image_sources[1].realize(state)
369
+ subject.handlers[0].processors[0].realize(state)
370
370
  }.to raise_error Configuration::Thumbnail::ThumbnailingError, "thumbnailing of 'input' into 'original' failed: at least one image dimension is zero: 0x10"
371
371
  end
372
372
 
@@ -416,12 +416,12 @@ describe Configuration do
416
416
  end
417
417
 
418
418
  it 'should mark source to be included when output image name in oneline and destination image name in multiline statement match if-image-name-on list' do
419
- subject.handlers[0].image_sources[1].excluded?(state).should be_false
420
- subject.handlers[0].image_sources[2].excluded?(state).should be_true
421
- subject.handlers[0].image_sources[3].excluded?(state).should be_true
422
- subject.handlers[0].image_sources[4].excluded?(state).should be_false
423
- subject.handlers[0].image_sources[5].excluded?(state).should be_true
424
- subject.handlers[0].image_sources[6].excluded?(state).should be_false
419
+ subject.handlers[0].processors[0].excluded?(state).should be_false
420
+ subject.handlers[0].processors[1].excluded?(state).should be_true
421
+ subject.handlers[0].processors[2].excluded?(state).should be_true
422
+ subject.handlers[0].processors[3].excluded?(state).should be_false
423
+ subject.handlers[0].processors[4].excluded?(state).should be_true
424
+ subject.handlers[0].processors[5].excluded?(state).should be_false
425
425
  end
426
426
  end
427
427
  end
data/spec/spec_helper.rb CHANGED
@@ -28,21 +28,28 @@ def headers(url)
28
28
  HTTPClient.new.get(url).headers
29
29
  end
30
30
 
31
+ @@running_cmd = {}
31
32
  def start_server(cmd, pid_file, log_file, test_url)
33
+ if @@running_cmd[pid_file]
34
+ return if @@running_cmd[pid_file] == cmd
35
+ stop_server(pid_file)
36
+ end
37
+
32
38
  fork do
33
39
  Daemon.daemonize(pid_file, log_file)
34
40
  log_file = Pathname.new(log_file)
35
41
  log_file.truncate(0) if log_file.exist?
36
42
  exec(cmd)
37
43
  end
38
- return unless Process.wait2.last.exitstatus == 0
44
+
45
+ @@running_cmd[pid_file] = cmd
39
46
 
40
47
  ppid = Process.pid
41
48
  at_exit do
42
49
  stop_server(pid_file) if Process.pid == ppid
43
50
  end
44
51
 
45
- Timeout.timeout(6) do
52
+ Timeout.timeout(10) do
46
53
  begin
47
54
  get test_url
48
55
  rescue Errno::ECONNREFUSED
@@ -56,6 +63,7 @@ def stop_server(pid_file)
56
63
  pid_file = Pathname.new(pid_file)
57
64
  return unless pid_file.exist?
58
65
 
66
+ STDERR.puts http_client.get_content("http://localhost:3000/stats") if pid_file.to_s.include? 'httpimagestore'
59
67
  pid = pid_file.read.strip.to_i
60
68
 
61
69
  Timeout.timeout(20) do
@@ -65,6 +73,7 @@ def stop_server(pid_file)
65
73
  sleep 0.1
66
74
  end
67
75
  rescue Errno::ESRCH
76
+ @@running_cmd.delete pid_file.to_s
68
77
  pid_file.unlink
69
78
  end
70
79
  end