mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
365 lines
14 KiB
Ruby
365 lines
14 KiB
Ruby
Shindo.tests('Fog::Storage[:rackspace] | large object requests', ['rackspace']) do
|
|
|
|
unless Fog.mocking?
|
|
@directory = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests')
|
|
@directory2 = Fog::Storage[:rackspace].directories.create(:key => 'foglargeobjecttests2')
|
|
@segments = {
|
|
:a => {
|
|
:container => @directory.identity,
|
|
:name => 'fog_large_object/a',
|
|
:data => 'a' * (1024**2 + 10),
|
|
:size => 1024**2 + 10,
|
|
:etag => 'c2e97007d59f0c19b850debdcb80cca5'
|
|
},
|
|
:b => {
|
|
:container => @directory.identity,
|
|
:name => 'fog_large_object/b',
|
|
:data => 'b' * (1024**2 + 20),
|
|
:size => 1024**2 + 20,
|
|
:etag => 'd35f50622a1259daad75ff7d5512c7ef'
|
|
},
|
|
:c => {
|
|
:container => @directory.identity,
|
|
:name => 'fog_large_object2/a',
|
|
:data => 'c' * (1024**2 + 30),
|
|
:size => 1024**2 + 30,
|
|
:etag => '901d3531a87d188041d4d5b43cb464c1'
|
|
},
|
|
:d => {
|
|
:container => @directory2.identity,
|
|
:name => 'fog_large_object2/b',
|
|
:data => 'd' * (1024**2 + 40),
|
|
:size => 1024**2 + 40,
|
|
:etag => '350c0e00525198813920a157df185c8d'
|
|
}
|
|
}
|
|
end
|
|
|
|
tests('success') do
|
|
|
|
tests('upload test segments').succeeds do
|
|
pending if Fog.mocking?
|
|
|
|
@segments.each_value do |segment|
|
|
Fog::Storage[:rackspace].put_object(segment[:container], segment[:name], segment[:data])
|
|
end
|
|
end
|
|
|
|
tests('dynamic large object requests') do
|
|
pending if Fog.mocking?
|
|
|
|
tests('#put_object_manifest alias').succeeds do
|
|
Fog::Storage[:rackspace].put_object_manifest(@directory.identity, 'fog_large_object')
|
|
end
|
|
|
|
tests('using default X-Object-Manifest header') do
|
|
|
|
tests('#put_dynamic_obj_manifest').succeeds do
|
|
Fog::Storage[:rackspace].put_dynamic_obj_manifest(@directory.identity, 'fog_large_object')
|
|
end
|
|
|
|
tests('#get_object streams all segments matching the default prefix').succeeds do
|
|
expected = @segments[:a][:data] + @segments[:b][:data] + @segments[:c][:data]
|
|
Fog::Storage[:rackspace].get_object(@directory.identity, 'fog_large_object').body == expected
|
|
end
|
|
|
|
# When the manifest object name is equal to the segment prefix, OpenStack treats it as if it's the first segment.
|
|
# So you must prepend the manifest object's Etag - Digest::MD5.hexdigest('')
|
|
tests('#head_object returns Etag that includes manifest object in calculation').succeeds do
|
|
etags = ['d41d8cd98f00b204e9800998ecf8427e', @segments[:a][:etag], @segments[:b][:etag], @segments[:c][:etag]]
|
|
expected = "\"#{ Digest::MD5.hexdigest(etags.join) }\"" # returned in quotes "\"2577f38428e895c50de6ea78ccc7da2a"\"
|
|
Fog::Storage[:rackspace].head_object(@directory.identity, 'fog_large_object').headers['Etag'] == expected
|
|
end
|
|
|
|
end
|
|
|
|
tests('specifying X-Object-Manifest segment prefix') do
|
|
|
|
tests('#put_dynamic_obj_manifest').succeeds do
|
|
options = { 'X-Object-Manifest' => "#{ @directory.identity }/fog_large_object/" }
|
|
Fog::Storage[:rackspace].put_dynamic_obj_manifest(@directory.identity, 'fog_large_object', options)
|
|
end
|
|
|
|
tests('#get_object streams segments only matching the specified prefix').succeeds do
|
|
expected = @segments[:a][:data] + @segments[:b][:data]
|
|
Fog::Storage[:rackspace].get_object(@directory.identity, 'fog_large_object').body == expected
|
|
end
|
|
|
|
tests('#head_object returns Etag that does not include manifest object in calculation').succeeds do
|
|
etags = [@segments[:a][:etag], @segments[:b][:etag]]
|
|
expected = "\"#{ Digest::MD5.hexdigest(etags.join) }\"" # returned in quotes "\"0f035ed3cc38aa0ef46dda3478fad44d"\"
|
|
Fog::Storage[:rackspace].head_object(@directory.identity, 'fog_large_object').headers['Etag'] == expected
|
|
end
|
|
|
|
end
|
|
|
|
tests('storing manifest in a different container than the segments') do
|
|
|
|
tests('#put_dynamic_obj_manifest').succeeds do
|
|
options = { 'X-Object-Manifest' => "#{ @directory.identity }/fog_large_object/" }
|
|
Fog::Storage[:rackspace].put_dynamic_obj_manifest(@directory2.identity, 'fog_large_object', options)
|
|
end
|
|
|
|
tests('#get_object').succeeds do
|
|
expected = @segments[:a][:data] + @segments[:b][:data]
|
|
Fog::Storage[:rackspace].get_object(@directory2.identity, 'fog_large_object').body == expected
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
tests('static large object requests') do
|
|
pending if Fog.mocking?
|
|
|
|
tests('single container') do
|
|
|
|
tests('#put_static_obj_manifest').succeeds do
|
|
segments = [
|
|
{ :path => "#{ @segments[:a][:container] }/#{ @segments[:a][:name] }",
|
|
:etag => @segments[:a][:etag],
|
|
:size_bytes => @segments[:a][:size] },
|
|
{ :path => "#{ @segments[:c][:container] }/#{ @segments[:c][:name] }",
|
|
:etag => @segments[:c][:etag],
|
|
:size_bytes => @segments[:c][:size] }
|
|
]
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory.identity, 'fog_large_object', segments)
|
|
end
|
|
|
|
tests('#head_object') do
|
|
etags = [@segments[:a][:etag], @segments[:c][:etag]]
|
|
etag = "\"#{ Digest::MD5.hexdigest(etags.join) }\"" # "\"ad7e633a12e8a4915b45e6dd1d4b0b4b\""
|
|
content_length = (@segments[:a][:size] + @segments[:c][:size]).to_s
|
|
response = Fog::Storage[:rackspace].head_object(@directory.identity, 'fog_large_object')
|
|
|
|
returns(etag, 'returns ETag computed from segments') { response.headers['Etag'] }
|
|
returns(content_length , 'returns Content-Length for all segments') { response.headers['Content-Length'] }
|
|
returns('True', 'returns X-Static-Large-Object header') { response.headers['X-Static-Large-Object'] }
|
|
end
|
|
|
|
tests('#get_object').succeeds do
|
|
expected = @segments[:a][:data] + @segments[:c][:data]
|
|
Fog::Storage[:rackspace].get_object(@directory.identity, 'fog_large_object').body == expected
|
|
end
|
|
|
|
tests('#delete_static_large_object') do
|
|
expected = {
|
|
'Number Not Found' => 0,
|
|
'Response Status' => '200 OK',
|
|
'Errors' => [],
|
|
'Number Deleted' => 3,
|
|
'Response Body' => ''
|
|
}
|
|
returns(expected, 'deletes manifest and segments') do
|
|
Fog::Storage[:rackspace].delete_static_large_object(@directory.identity, 'fog_large_object').body
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
tests('multiple containers') do
|
|
|
|
tests('#put_static_obj_manifest').succeeds do
|
|
segments = [
|
|
{ :path => "#{ @segments[:b][:container] }/#{ @segments[:b][:name] }",
|
|
:etag => @segments[:b][:etag],
|
|
:size_bytes => @segments[:b][:size] },
|
|
{ :path => "#{ @segments[:d][:container] }/#{ @segments[:d][:name] }",
|
|
:etag => @segments[:d][:etag],
|
|
:size_bytes => @segments[:d][:size] }
|
|
]
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory2.identity, 'fog_large_object', segments)
|
|
end
|
|
|
|
tests('#head_object') do
|
|
etags = [@segments[:b][:etag], @segments[:d][:etag]]
|
|
etag = "\"#{ Digest::MD5.hexdigest(etags.join) }\"" # "\"9801a4cc4472896a1e975d03f0d2c3f8\""
|
|
content_length = (@segments[:b][:size] + @segments[:d][:size]).to_s
|
|
response = Fog::Storage[:rackspace].head_object(@directory2.identity, 'fog_large_object')
|
|
|
|
returns(etag, 'returns ETag computed from segments') { response.headers['Etag'] }
|
|
returns(content_length , 'returns Content-Length for all segments') { response.headers['Content-Length'] }
|
|
returns('True', 'returns X-Static-Large-Object header') { response.headers['X-Static-Large-Object'] }
|
|
end
|
|
|
|
tests('#get_object').succeeds do
|
|
expected = @segments[:b][:data] + @segments[:d][:data]
|
|
Fog::Storage[:rackspace].get_object(@directory2.identity, 'fog_large_object').body == expected
|
|
end
|
|
|
|
tests('#delete_static_large_object') do
|
|
expected = {
|
|
'Number Not Found' => 0,
|
|
'Response Status' => '200 OK',
|
|
'Errors' => [],
|
|
'Number Deleted' => 3,
|
|
'Response Body' => ''
|
|
}
|
|
returns(expected, 'deletes manifest and segments') do
|
|
Fog::Storage[:rackspace].delete_static_large_object(@directory2.identity, 'fog_large_object').body
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
tests('failure') do
|
|
|
|
tests('dynamic large object requests') do
|
|
pending if Fog.mocking?
|
|
|
|
tests('#put_dynamic_obj_manifest with missing container').raises(Fog::Storage::Rackspace::NotFound) do
|
|
Fog::Storage[:rackspace].put_dynamic_obj_manifest('fognoncontainer', 'fog_large_object')
|
|
end
|
|
|
|
end
|
|
|
|
tests('static large object requests') do
|
|
pending if Fog.mocking?
|
|
|
|
tests('upload test segments').succeeds do
|
|
Fog::Storage[:rackspace].put_object(@segments[:a][:container], @segments[:a][:name], @segments[:a][:data])
|
|
Fog::Storage[:rackspace].put_object(@segments[:b][:container], @segments[:b][:name], @segments[:b][:data])
|
|
end
|
|
|
|
tests('#put_static_obj_manifest with missing container').raises(Fog::Storage::Rackspace::NotFound) do
|
|
Fog::Storage[:rackspace].put_static_obj_manifest('fognoncontainer', 'fog_large_object', [])
|
|
end
|
|
|
|
tests('#put_static_obj_manifest with missing object') do
|
|
segments = [
|
|
{ :path => "#{ @segments[:c][:container] }/#{ @segments[:c][:name] }",
|
|
:etag => @segments[:c][:etag],
|
|
:size_bytes => @segments[:c][:size] }
|
|
]
|
|
expected = { 'Errors' => [[segments[0][:path], '404 Not Found']] }
|
|
|
|
error = nil
|
|
begin
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory.identity, 'fog_large_object', segments)
|
|
rescue => err
|
|
error = err
|
|
end
|
|
|
|
raises(Fog::Storage::Rackspace::BadRequest) do
|
|
raise error if error
|
|
end
|
|
|
|
expected['Errors'][0][0] = error.response_data['Errors'][0][0] rescue nil
|
|
returns(expected, 'returns error information') do
|
|
error.response_data
|
|
end
|
|
end
|
|
|
|
tests('#put_static_obj_manifest with invalid etag') do
|
|
segments = [
|
|
{ :path => "#{ @segments[:a][:container] }/#{ @segments[:a][:name] }",
|
|
:etag => @segments[:b][:etag],
|
|
:size_bytes => @segments[:a][:size] }
|
|
]
|
|
expected = { 'Errors' => [[segments[0][:path], 'Etag Mismatch']] }
|
|
|
|
error = nil
|
|
begin
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory.identity, 'fog_large_object', segments)
|
|
rescue => err
|
|
error = err
|
|
end
|
|
|
|
raises(Fog::Storage::Rackspace::BadRequest) do
|
|
raise error if error
|
|
end
|
|
|
|
expected['Errors'][0][0] = error.response_data['Errors'][0][0] rescue nil
|
|
returns(expected, 'returns error information') do
|
|
error.response_data
|
|
end
|
|
end
|
|
|
|
tests('#put_static_obj_manifest with invalid byte_size') do
|
|
segments = [
|
|
{ :path => "#{ @segments[:a][:container] }/#{ @segments[:a][:name] }",
|
|
:etag => @segments[:a][:etag],
|
|
:size_bytes => @segments[:b][:size] }
|
|
]
|
|
expected = { 'Errors' => [[segments[0][:path], 'Size Mismatch']] }
|
|
|
|
error = nil
|
|
begin
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory.identity, 'fog_large_object', segments)
|
|
rescue => err
|
|
error = err
|
|
end
|
|
|
|
raises(Fog::Storage::Rackspace::BadRequest) do
|
|
raise error if error
|
|
end
|
|
|
|
expected['Errors'][0][0] = error.response_data['Errors'][0][0] rescue nil
|
|
returns(expected, 'returns error information') do
|
|
error.response_data
|
|
end
|
|
end
|
|
|
|
tests('#delete_static_large_object with missing container') do
|
|
response = Fog::Storage[:rackspace].delete_static_large_object('fognoncontainer', 'fog_large_object')
|
|
|
|
returns(200) { response.status }
|
|
returns(1) { response.body["Number Not Found"] }
|
|
returns("200 OK") { response.body["Response Status"]}
|
|
returns("") { response.body["Response Body"]}
|
|
end
|
|
|
|
tests('#delete_static_large_object with missing manifest') do
|
|
response = Fog::Storage[:rackspace].delete_static_large_object(@directory.identity, 'fog_non_object')
|
|
|
|
returns(200) { response.status }
|
|
returns(1) { response.body["Number Not Found"] }
|
|
returns("200 OK") { response.body["Response Status"]}
|
|
returns("") { response.body["Response Body"]}
|
|
end
|
|
|
|
tests('#delete_static_large_object with missing segment') do
|
|
|
|
tests('#put_static_obj_manifest for segments :a and :b').succeeds do
|
|
segments = [
|
|
{ :path => "#{ @segments[:a][:container] }/#{ @segments[:a][:name] }",
|
|
:etag => @segments[:a][:etag],
|
|
:size_bytes => @segments[:a][:size] },
|
|
{ :path => "#{ @segments[:b][:container] }/#{ @segments[:b][:name] }",
|
|
:etag => @segments[:b][:etag],
|
|
:size_bytes => @segments[:b][:size] }
|
|
]
|
|
Fog::Storage[:rackspace].put_static_obj_manifest(@directory.identity, 'fog_large_object', segments)
|
|
end
|
|
|
|
tests('#delete_object segment :b').succeeds do
|
|
Fog::Storage[:rackspace].delete_object(@segments[:b][:container], @segments[:b][:name])
|
|
end
|
|
|
|
tests('#delete_static_large_object') do
|
|
expected = {
|
|
'Number Not Found' => 1,
|
|
'Response Status' => '200 OK',
|
|
'Errors' => [],
|
|
'Number Deleted' => 2,
|
|
'Response Body' => ''
|
|
}
|
|
returns(expected, 'deletes manifest and segment :a, and reports missing segment :b') do
|
|
Fog::Storage[:rackspace].delete_static_large_object(@directory.identity, 'fog_large_object').body
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
unless Fog.mocking?
|
|
@directory.destroy
|
|
@directory2.destroy
|
|
end
|
|
end
|