summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/functional/resource/remote_file_spec.rb194
1 files changed, 192 insertions, 2 deletions
diff --git a/spec/functional/resource/remote_file_spec.rb b/spec/functional/resource/remote_file_spec.rb
index bfc09dccd9..4468951a7a 100644
--- a/spec/functional/resource/remote_file_spec.rb
+++ b/spec/functional/resource/remote_file_spec.rb
@@ -53,20 +53,99 @@ describe Chef::Resource::RemoteFile do
let(:default_mode) { ((0100666 - File.umask) & 07777).to_s(8) }
def start_tiny_server(server_opts={})
+ nyan_uncompressed_filename = File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png')
+ nyan_compressed_filename = File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png.gz')
+ nyan_uncompressed_size = File::Stat.new(nyan_uncompressed_filename).size
+ nyan_compressed_size = File::Stat.new(nyan_compressed_filename).size
+
@server = TinyServer::Manager.new(server_opts)
@server.start
@api = TinyServer::API.instance
@api.clear
+
+ #
+ # trivial endpoints
+ #
+
@api.get("/nyan_cat.png", 200) {
- File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png'), "rb") do |f|
+ File.open(nyan_uncompressed_filename, "rb") do |f|
f.read
end
}
@api.get("/nyan_cat.png.gz", 200, nil, { 'Content-Type' => 'application/gzip', 'Content-Encoding' => 'gzip' } ) {
- File.open(File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png.gz'), "rb") do |f|
+ File.open(nyan_compressed_filename, "rb") do |f|
+ f.read
+ end
+ }
+
+ #
+ # endpoints that set Content-Length correctly
+ #
+
+ @api.get("/nyan_cat_content_length.png", 200, nil,
+ {
+ 'Content-Length' => nyan_uncompressed_size.to_s,
+ }
+ ) {
+ File.open(nyan_uncompressed_filename, "rb") do |f|
+ f.read
+ end
+ }
+
+ # this is sent over the wire compressed by the server, but does not have a .gz extension
+ @api.get("/nyan_cat_content_length_compressed.png", 200, nil,
+ {
+ 'Content-Length' => nyan_compressed_size.to_s,
+ 'Content-Type' => 'application/gzip',
+ 'Content-Encoding' => 'gzip'
+ }
+ ) {
+ File.open(nyan_compressed_filename, "rb") do |f|
f.read
end
}
+
+ #
+ # endpoints that simulate truncated downloads (bad content-length header)
+ #
+
+ @api.get("/nyan_cat_truncated.png", 200, nil,
+ {
+ 'Content-Length' => (nyan_uncompressed_size + 1).to_s,
+ }
+ ) {
+ File.open(nyan_uncompressed_filename, "rb") do |f|
+ f.read
+ end
+ }
+ # this is sent over the wire compressed by the server, but does not have a .gz extension
+ @api.get("/nyan_cat_truncated_compressed.png", 200, nil,
+ {
+ 'Content-Length' => (nyan_compressed_size + 1).to_s,
+ 'Content-Type' => 'application/gzip',
+ 'Content-Encoding' => 'gzip'
+ }
+ ) {
+ File.open(nyan_compressed_filename, "rb") do |f|
+ f.read
+ end
+ }
+
+ #
+ # in the presense of a transfer-encoding header, we must ignore the content-length (this bad content-length should work)
+ #
+
+ @api.get("/nyan_cat_transfer_encoding.png", 200, nil,
+ {
+ 'Content-Length' => (nyan_uncompressed_size + 1).to_s,
+ 'Transfer-Encoding' => 'anything',
+ }
+ ) {
+ File.open(nyan_uncompressed_filename, "rb") do |f|
+ f.read
+ end
+ }
+
end
def stop_tiny_server
@@ -162,4 +241,115 @@ describe Chef::Resource::RemoteFile do
end
+ context "when dealing with content length checking" do
+
+ def binread(file)
+ content = File.open(file, "rb") do |f|
+ f.read
+ end
+ content.force_encoding(Encoding::BINARY) if "".respond_to?(:force_encoding)
+ content
+ end
+
+ before(:all) do
+ start_tiny_server
+ end
+
+ after(:all) do
+ stop_tiny_server
+ end
+
+ context "when downloading compressed data" do
+ let(:expected_content) { binread( File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png') ) }
+ let(:source) { 'http://localhost:9000/nyan_cat_content_length_compressed.png' }
+
+ before do
+ File.should_not exist(path)
+ resource.run_action(:create)
+ end
+
+ it "should create the file" do
+ File.should exist(path)
+ end
+
+ it "should mark the resource as updated" do
+ resource.should be_updated_by_last_action
+ end
+
+ it "has the correct content" do
+ binread(path).should == expected_content
+ end
+ end
+
+ context "when downloding uncompressed data" do
+ let(:expected_content) { binread( File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png') ) }
+ let(:source) { 'http://localhost:9000/nyan_cat_content_length.png' }
+
+ before do
+ File.should_not exist(path)
+ resource.run_action(:create)
+ end
+
+ it "should create the file" do
+ File.should exist(path)
+ end
+
+ it "should mark the resource as updated" do
+ resource.should be_updated_by_last_action
+ end
+
+ it "has the correct content" do
+ binread(path).should == expected_content
+ end
+ end
+
+ context "when downloading truncated compressed data" do
+ let(:source) { 'http://localhost:9000/nyan_cat_truncated_compressed.png' }
+
+ before do
+ File.should_not exist(path)
+ end
+
+ it "should raise ContentLengthMismatch" do
+ lambda { resource.run_action(:create) }.should raise_error(Chef::Exceptions::ContentLengthMismatch)
+ #File.should_not exist(path) # XXX: CHEF-5081
+ end
+ end
+
+ context "when downloding truncated uncompressed data" do
+ let(:source) { 'http://localhost:9000/nyan_cat_truncated.png' }
+
+ before do
+ File.should_not exist(path)
+ end
+
+ it "should raise ContentLengthMismatch" do
+ lambda { resource.run_action(:create) }.should raise_error(Chef::Exceptions::ContentLengthMismatch)
+ #File.should_not exist(path) # XXX: CHEF-5081
+ end
+ end
+
+ context "when downloding data with transfer-encoding set" do
+ let(:expected_content) { binread( File.join(CHEF_SPEC_DATA, 'remote_file', 'nyan_cat.png') ) }
+ let(:source) { 'http://localhost:9000/nyan_cat_transfer_encoding.png' }
+
+ before do
+ File.should_not exist(path)
+ resource.run_action(:create)
+ end
+
+ it "should create the file" do
+ File.should exist(path)
+ end
+
+ it "should mark the resource as updated" do
+ resource.should be_updated_by_last_action
+ end
+
+ it "has the correct content" do
+ binread(path).should == expected_content
+ end
+ end
+
+ end
end