Skip to content

Instantly share code, notes, and snippets.

@marzdgzmn
Created December 12, 2018 11:36
Show Gist options
  • Save marzdgzmn/fe94064b777c084aa4ef0284f0a46290 to your computer and use it in GitHub Desktop.
Save marzdgzmn/fe94064b777c084aa4ef0284f0a46290 to your computer and use it in GitHub Desktop.
require 'rise/mirror_manager/sync'
require 'ostruct'
require 'pry'
require 'tmpdir'
require 'tempfile'
Sync = Rise::MirrorManager::Sync
SyncStatus = Rise::MirrorManager::SyncStatus
SyncLog = Rise::MirrorManager::Logging::SyncLog
Error = Rise::MirrorManager::Error
DB = Rise::MirrorManager::Database
tmp_dir = Dir.mktmpdir
RSpec.describe Rise::MirrorManager::Sync do
after(:all) do
FileUtils.rm_rf(tmp_dir) if File.exist?(tmp_dir)
end
# subject { described_class.new(mirror: mirror) }
describe '.run' do
remote_source = 'rsync://rise.ph'
rsync_opts = '-r -i -s -e'
rsync_delete_opts = '-d -d -d'
mirror = OpenStruct.new(name: 'dummy_mirror',
local_dir: tmp_dir,
pre_cmd: true, remote_source: remote_source,
rsync_opts: rsync_opts,
rsync_delete_opts: rsync_delete_opts)
let(:sync) { Sync.new(mirror) }
let(:logger) { double(SyncLog, log_info: nil, log_warn: nil, log_error: nil) }
before(:each) do
allow(SyncLog).to receive(:new).and_return(logger)
allow(Sync).to receive(:new).with(mirror).and_return(sync)
end
context 'when establishing a lock' do
lock_file = File.join(mirror.local_dir, "#{mirror.name}.lock")
it 'should create a lock file' do
allow(sync).to receive(:sync)
expect(File).to receive(:open).with(lock_file, File::RDWR | File::CREAT, 0o644)
Sync.run(mirror)
end
context 'when trying to establish a lock when a lock file already exists' do
before(:each) do
File.open(lock_file, File::RDWR | File::CREAT) do |f|
f.write(5)
f.flush
end
end
it 'should create a new one if the corresponding process for the existing lock file does not exist' do
allow(Process).to receive(:kill).with(0, 5).and_raise Errno::ESRCH
expect(File).to receive(:delete).with(lock_file).twice # twice == delete existing lock file + release_lock
expect(File).to receive(:open).with(lock_file, File::RDWR | File::CREAT, 0o644)
allow(sync).to receive(:sync)
sync.run
end
it 'should log an error and exit if app does not have privilege to send signal to the process' do
allow(Process).to receive(:kill).and_raise Errno::EPERM
allow(sync).to receive(:exit).and_throw(:exit)
expect(logger).to receive(:log_error).with('No permission/privilege to send signal to process(5)')
expect { sync.run }.to throw_symbol :exit
end
it 'should log an error and exit if the corresponding process for the lock file is running' do
allow(Process).to receive(:kill)
allow(sync).to receive(:exit).and_throw(:exit)
expect(logger).to receive(:log_error).with('Cannot establish lock. Another process(5) is currently running and holding the lock.')
expect { sync.run }.to throw_symbol :exit
end
end
end
context 'when precmd fails' do
before(:each) { mirror.pre_cmd = "(echo 'pre_cmd error' >&2; exit 1)" } # simulate a failing error
it 'should update database sync status to FAILED' do
allow(sync).to receive(:exit).and_throw(:exit)
expect(sync).to receive(:update_precmd_result).with(mirror.name, SyncStatus::FAILED)
expect { sync.run }.to throw_symbol :exit
end
it 'should log the error' do
allow(sync).to receive(:exit).and_throw(:exit)
expect(logger).to receive(:log_error).with(/pre_cmd error/)
expect { sync.run }.to throw_symbol :exit
end
context 'when precmd fails and raises to Errno::ENOENT' do
before(:each) { mirror.pre_cmd = 'nonExistingCmd' }
it 'should update database sync status to FAILED' do
allow(sync).to receive(:exit).and_throw(:exit)
expect(sync).to receive(:update_precmd_result).with(mirror.name, SyncStatus::FAILED)
expect { sync.run }.to throw_symbol :exit
end
it 'it should log the error' do
allow(sync).to receive(:exit).and_throw(:exit)
expect(logger).to receive(:log_error).with(/No such file or directory - nonExistingCmd/)
expect { sync.run }.to throw_symbol :exit
end
end
end
context 'when running sync' do
context 'when syncing fails' do
it 'should update database sync status to FAILED' do
puts sync.inspect
result = OpenStruct.new(output: 'failed rsync', success?: false)
allow(Marz::Rsync).to receive(:run).with(remote_source, tmp_dir, (rsync_opts + ' ' + rsync_delete_opts).split).and_yield(result)
allow(sync).to receive(:exit).and_throw(:exit)
expect(sync).to receive(:update_sync_result).with(SyncStatus::FAILED)
expect { sync.run }.to throw_symbol :exit
end
it 'should log sync error' do
result = OpenStruct.new(output: 'failed rsync', success?: false)
allow(Marz::Rsync).to receive(:run).with(remote_source, tmp_dir, (rsync_opts + ' ' + rsync_delete_opts).split).and_yield(result)
allow(sync).to receive(:exit).and_throw(:exit)
expect(logger). to receive(:log_error).with('failed rsync')
expect { sync.run }.to throw_symbol :exit
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment