spec/storage/ftp_spec.rb in backup-3.0.20 vs spec/storage/ftp_spec.rb in backup-3.0.21

- old
+ new

@@ -1,232 +1,245 @@ # encoding: utf-8 require File.expand_path('../../spec_helper.rb', __FILE__) describe Backup::Storage::FTP do - - let(:ftp) do - Backup::Storage::FTP.new do |ftp| + let(:model) { Backup::Model.new(:test_trigger, 'test label') } + let(:storage) do + Backup::Storage::FTP.new(model) do |ftp| ftp.username = 'my_username' ftp.password = 'my_password' ftp.ip = '123.45.678.90' - ftp.port = 21 - ftp.path = '~/backups/' - ftp.keep = 20 - ftp.passive_mode = false + ftp.keep = 5 end end - before do - Backup::Configuration::Storage::FTP.clear_defaults! - end + describe '#initialize' do + it 'should set the correct values' do + storage.username.should == 'my_username' + storage.password.should == 'my_password' + storage.ip.should == '123.45.678.90' + storage.port.should == 21 + storage.path.should == 'backups' + storage.passive_mode.should == false - it 'should have defined the configuration properly' do - ftp.username.should == 'my_username' - ftp.password.should == 'my_password' - ftp.ip.should == '123.45.678.90' - ftp.port.should == 21 - ftp.path.should == 'backups/' - ftp.keep.should == 20 - ftp.passive_mode.should == false - end + storage.storage_id.should be_nil + storage.keep.should == 5 + end - it 'should use the defaults if a particular attribute has not been defined' do - Backup::Configuration::Storage::FTP.defaults do |ftp| - ftp.username = 'my_default_username' - ftp.password = 'my_default_password' - ftp.path = '~/backups' + it 'should set a storage_id if given' do + ftp = Backup::Storage::FTP.new(model, 'my storage_id') + ftp.storage_id.should == 'my storage_id' end - ftp = Backup::Storage::FTP.new do |ftp| - ftp.password = 'my_password' - ftp.ip = '123.45.678.90' + it 'should remove any preceeding tilde and slash from the path' do + storage = Backup::Storage::FTP.new(model) do |ftp| + ftp.path = '~/my_backups/path' + end + storage.path.should == 'my_backups/path' end - ftp.username.should == 'my_default_username' - ftp.password.should == 'my_password' - ftp.ip.should == '123.45.678.90' - ftp.port.should == 21 - end + context 'when setting configuration defaults' do + after { Backup::Configuration::Storage::FTP.clear_defaults! } - it 'should have its own defaults' do - ftp = Backup::Storage::FTP.new - ftp.port.should == 21 - ftp.path.should == 'backups' - ftp.passive_mode.should == false - end + it 'should use the configured defaults' do + Backup::Configuration::Storage::FTP.defaults do |ftp| + ftp.username = 'some_username' + ftp.password = 'some_password' + ftp.ip = 'some_ip' + ftp.port = 'some_port' + ftp.path = 'some_path' + ftp.passive_mode = 'some_passive_mode' + ftp.keep = 'some_keep' + end + storage = Backup::Storage::FTP.new(model) + storage.username.should == 'some_username' + storage.password.should == 'some_password' + storage.ip.should == 'some_ip' + storage.port.should == 'some_port' + storage.path.should == 'some_path' + storage.passive_mode.should == 'some_passive_mode' - describe '#perform' do - it 'should invoke transfer! and cycle!' do - ftp.expects(:transfer!) - ftp.expects(:cycle!) - ftp.perform! - end - end + storage.storage_id.should be_nil + storage.keep.should == 'some_keep' + end + it 'should override the configured defaults' do + Backup::Configuration::Storage::FTP.defaults do |ftp| + ftp.username = 'old_username' + ftp.password = 'old_password' + ftp.ip = 'old_ip' + ftp.port = 'old_port' + ftp.path = 'old_path' + ftp.passive_mode = 'old_passive_mode' + ftp.keep = 'old_keep' + end + storage = Backup::Storage::FTP.new(model) do |ftp| + ftp.username = 'new_username' + ftp.password = 'new_password' + ftp.ip = 'new_ip' + ftp.port = 'new_port' + ftp.path = 'new_path' + ftp.passive_mode = 'new_passive_mode' + ftp.keep = 'new_keep' + end + + storage.username.should == 'new_username' + storage.password.should == 'new_password' + storage.ip.should == 'new_ip' + storage.port.should == 'new_port' + storage.path.should == 'new_path' + storage.passive_mode.should == 'new_passive_mode' + + storage.storage_id.should be_nil + storage.keep.should == 'new_keep' + end + end # context 'when setting configuration defaults' + + end # describe '#initialize' + describe '#connection' do let(:connection) { mock } - it 'should establish a connection to the remote server' do + it 'should yield a connection to the remote server' do Net::FTP.expects(:open).with( '123.45.678.90', 'my_username', 'my_password' ).yields(connection) - ftp.send(:connection) do |conn| - conn.should be connection + storage.send(:connection) do |ftp| + ftp.should be(connection) end end - it 'configures net/ftp to use passive mode if passive_mode set to true' do - ftp.passive_mode = true + it 'should set passive mode if @passive_mode is true' do + storage.passive_mode = true Net::FTP.expects(:open).with( '123.45.678.90', 'my_username', 'my_password' ).yields(connection) connection.expects(:passive=).with(true) - ftp.send(:connection) do |conn| - conn.should be connection + storage.send(:connection) do |ftp| + ftp.should be(connection) end end - context 'when re-defining the Net::FTP port' do + it 'should set the Net::FTP_PORT constant' do + storage.port = 40 + Net::FTP.expects(:const_defined?).with(:FTP_PORT).returns(true) + Net::FTP.expects(:send).with(:remove_const, :FTP_PORT) + Net::FTP.expects(:send).with(:const_set, :FTP_PORT, 40) - def reset_ftp_port - if defined? Net::FTP::FTP_PORT - Net::FTP.send(:remove_const, :FTP_PORT) - end; Net::FTP.send(:const_set, :FTP_PORT, 21) - end - - before { reset_ftp_port } - after { reset_ftp_port } - - it 'should re-define Net::FTP::FTP_PORT' do - Net::FTP.stubs(:open) - ftp.port = 40 - ftp.send(:connection) - Net::FTP::FTP_PORT.should == 40 - end - + Net::FTP.expects(:open) + storage.send(:connection) end end # describe '#connection' describe '#transfer!' do let(:connection) { mock } + let(:package) { mock } + let(:s) { sequence '' } before do - ftp.stubs(:storage_name).returns('Storage::FTP') + storage.instance_variable_set(:@package, package) + storage.stubs(:storage_name).returns('Storage::FTP') + storage.stubs(:local_path).returns('/local/path') + storage.stubs(:connection).yields(connection) end - context 'when file chunking is not used' do - it 'should create remote paths and transfer using a single connection' do - local_file = "#{ Backup::TIME }.#{ Backup::TRIGGER }.tar" - remote_file = "#{ Backup::TRIGGER }.tar" + it 'should transfer the package files' do + storage.expects(:remote_path_for).in_sequence(s).with(package). + returns('remote/path') + storage.expects(:create_remote_path).in_sequence(s).with( + 'remote/path', connection + ) - ftp.expects(:connection).yields(connection) - ftp.expects(:create_remote_directories).with(connection) + storage.expects(:files_to_transfer_for).in_sequence(s).with(package). + multiple_yields( + ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'], + ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab'] + ) + # first yield + Backup::Logger.expects(:message).in_sequence(s).with( + "Storage::FTP started transferring " + + "'2011.12.31.11.00.02.backup.tar.enc-aa' to '123.45.678.90'." + ) + connection.expects(:put).in_sequence(s).with( + File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-aa'), + File.join('remote/path', 'backup.tar.enc-aa') + ) + # second yield + Backup::Logger.expects(:message).in_sequence(s).with( + "Storage::FTP started transferring " + + "'2011.12.31.11.00.02.backup.tar.enc-ab' to '123.45.678.90'." + ) + connection.expects(:put).in_sequence(s).with( + File.join('/local/path', '2011.12.31.11.00.02.backup.tar.enc-ab'), + File.join('remote/path', 'backup.tar.enc-ab') + ) - Backup::Logger.expects(:message).with( - "Storage::FTP started transferring '#{local_file}' to '#{ftp.ip}'." - ) - - connection.expects(:put).with( - File.join(Backup::TMP_PATH, local_file), - File.join('backups/myapp', Backup::TIME, remote_file) - ) - - ftp.send(:transfer!) - end + storage.send(:transfer!) end + end # describe '#transfer!' - context 'when file chunking is used' do - it 'should transfer all the provided files using a single connection' do - s = sequence '' + describe '#remove!' do + let(:package) { mock } + let(:connection) { mock } + let(:s) { sequence '' } - ftp.expects(:connection).in_sequence(s).yields(connection) - ftp.expects(:create_remote_directories).in_sequence(s).with(connection) - - ftp.expects(:files_to_transfer).in_sequence(s).multiple_yields( - ['local_file1', 'remote_file1'], ['local_file2', 'remote_file2'] - ) - - Backup::Logger.expects(:message).in_sequence(s).with( - "Storage::FTP started transferring 'local_file1' to '#{ftp.ip}'." - ) - connection.expects(:put).in_sequence(s).with( - File.join(Backup::TMP_PATH, 'local_file1'), - File.join('backups/myapp', Backup::TIME, 'remote_file1') - ) - - Backup::Logger.expects(:message).in_sequence(s).with( - "Storage::FTP started transferring 'local_file2' to '#{ftp.ip}'." - ) - connection.expects(:put).in_sequence(s).with( - File.join(Backup::TMP_PATH, 'local_file2'), - File.join('backups/myapp', Backup::TIME, 'remote_file2') - ) - - ftp.send(:transfer!) - end + before do + storage.stubs(:storage_name).returns('Storage::FTP') + storage.stubs(:connection).yields(connection) end - end # describe '#transfer' - describe '#remove!' do - it 'should remove all remote files with a single FTP connection' do - s = sequence '' - connection = mock - remote_path = "backups/myapp/#{ Backup::TIME }" - ftp.stubs(:storage_name).returns('Storage::FTP') + it 'should remove the package files' do + storage.expects(:remote_path_for).in_sequence(s).with(package). + returns('remote/path') - ftp.expects(:connection).in_sequence(s).yields(connection) - - ftp.expects(:transferred_files).in_sequence(s).multiple_yields( - ['local_file1', 'remote_file1'], ['local_file2', 'remote_file2'] + storage.expects(:transferred_files_for).in_sequence(s).with(package). + multiple_yields( + ['2011.12.31.11.00.02.backup.tar.enc-aa', 'backup.tar.enc-aa'], + ['2011.12.31.11.00.02.backup.tar.enc-ab', 'backup.tar.enc-ab'] ) - + # first yield Backup::Logger.expects(:message).in_sequence(s).with( - "Storage::FTP started removing 'local_file1' from '#{ftp.ip}'." + "Storage::FTP started removing " + + "'2011.12.31.11.00.02.backup.tar.enc-aa' from '123.45.678.90'." ) connection.expects(:delete).in_sequence(s).with( - File.join(remote_path, 'remote_file1') + File.join('remote/path', 'backup.tar.enc-aa') ) - + # second yield Backup::Logger.expects(:message).in_sequence(s).with( - "Storage::FTP started removing 'local_file2' from '#{ftp.ip}'." + "Storage::FTP started removing " + + "'2011.12.31.11.00.02.backup.tar.enc-ab' from '123.45.678.90'." ) connection.expects(:delete).in_sequence(s).with( - File.join(remote_path, 'remote_file2') + File.join('remote/path', 'backup.tar.enc-ab') ) - connection.expects(:rmdir).in_sequence(s).with(remote_path) + connection.expects(:rmdir).with('remote/path').in_sequence(s) - ftp.send(:remove!) + storage.send(:remove!, package) end end # describe '#remove!' - describe '#create_remote_directories!' do - let(:connection) { mock } + describe '#create_remote_path' do + let(:connection) { mock } + let(:remote_path) { 'backups/folder/another_folder' } + let(:s) { sequence '' } context 'while properly creating remote directories one by one' do - it 'should rescue any FTPPermErrors' do - s = sequence '' - ftp.path = '~/backups/some_other_folder/another_folder' - + it 'should rescue any FTPPermErrors and continue' do connection.expects(:mkdir).in_sequence(s). - with("~").raises(Net::FTPPermError) + with("backups").raises(Net::FTPPermError) connection.expects(:mkdir).in_sequence(s). - with("~/backups").raises(Net::FTPPermError) + with("backups/folder") connection.expects(:mkdir).in_sequence(s). - with("~/backups/some_other_folder") - connection.expects(:mkdir).in_sequence(s). - with("~/backups/some_other_folder/another_folder") - connection.expects(:mkdir).in_sequence(s). - with("~/backups/some_other_folder/another_folder/myapp") - connection.expects(:mkdir).in_sequence(s). - with("~/backups/some_other_folder/another_folder/myapp/#{ Backup::TIME }") + with("backups/folder/another_folder") expect do - ftp.send(:create_remote_directories, connection) + storage.send(:create_remote_path, remote_path, connection) end.not_to raise_error end end end