Merge "add unit tests for db_replicator"
This commit is contained in:
commit
b93b1327f7
@ -18,6 +18,8 @@ from contextlib import contextmanager
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import errno
|
import errno
|
||||||
|
import math
|
||||||
|
from mock import patch
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from tempfile import mkdtemp, NamedTemporaryFile
|
from tempfile import mkdtemp, NamedTemporaryFile
|
||||||
|
|
||||||
@ -80,8 +82,13 @@ class FakeRingWithNodes:
|
|||||||
class FakeProcess:
|
class FakeProcess:
|
||||||
def __init__(self, *codes):
|
def __init__(self, *codes):
|
||||||
self.codes = iter(codes)
|
self.codes = iter(codes)
|
||||||
|
self.args = None
|
||||||
|
self.kwargs = None
|
||||||
|
|
||||||
def __call__(self, *args, **kwargs):
|
def __call__(self, *args, **kwargs):
|
||||||
|
self.args = args
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
class Failure:
|
class Failure:
|
||||||
def communicate(innerself):
|
def communicate(innerself):
|
||||||
next = self.codes.next()
|
next = self.codes.next()
|
||||||
@ -96,7 +103,7 @@ class FakeProcess:
|
|||||||
def _mock_process(*args):
|
def _mock_process(*args):
|
||||||
orig_process = db_replicator.subprocess.Popen
|
orig_process = db_replicator.subprocess.Popen
|
||||||
db_replicator.subprocess.Popen = FakeProcess(*args)
|
db_replicator.subprocess.Popen = FakeProcess(*args)
|
||||||
yield
|
yield db_replicator.subprocess.Popen
|
||||||
db_replicator.subprocess.Popen = orig_process
|
db_replicator.subprocess.Popen = orig_process
|
||||||
|
|
||||||
|
|
||||||
@ -121,10 +128,8 @@ class ReplHttp:
|
|||||||
class ChangingMtimesOs:
|
class ChangingMtimesOs:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.mtime = 0
|
self.mtime = 0
|
||||||
self.path = self
|
|
||||||
self.basename = os.path.basename
|
|
||||||
|
|
||||||
def getmtime(self, file):
|
def __call__(self, *args, **kwargs):
|
||||||
self.mtime += 1
|
self.mtime += 1
|
||||||
return self.mtime
|
return self.mtime
|
||||||
|
|
||||||
@ -136,11 +141,14 @@ class FakeBroker:
|
|||||||
db_type = 'container'
|
db_type = 'container'
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.locked = False
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def lock(self):
|
def lock(self):
|
||||||
|
self.locked = True
|
||||||
yield True
|
yield True
|
||||||
|
self.locked = False
|
||||||
|
|
||||||
def get_sync(self, *args, **kwargs):
|
def get_sync(self, *args, **kwargs):
|
||||||
return 5
|
return 5
|
||||||
@ -220,12 +228,123 @@ class TestDBReplicator(unittest.TestCase):
|
|||||||
self.assertEquals(True,
|
self.assertEquals(True,
|
||||||
replicator._rsync_file('/some/file', 'remote:/some/file'))
|
replicator._rsync_file('/some/file', 'remote:/some/file'))
|
||||||
|
|
||||||
|
def test_rsync_file_popen_args(self):
|
||||||
|
replicator = TestReplicator({})
|
||||||
|
with _mock_process(0) as process:
|
||||||
|
replicator._rsync_file('/some/file', 'remote:/some_file')
|
||||||
|
exp_args = ([
|
||||||
|
'rsync', '--quiet', '--no-motd',
|
||||||
|
'--timeout=%s' % int(math.ceil(replicator.node_timeout)),
|
||||||
|
'--contimeout=%s' % int(math.ceil(replicator.conn_timeout)),
|
||||||
|
'--whole-file', '/some/file', 'remote:/some_file'],)
|
||||||
|
self.assertEqual(exp_args, process.args)
|
||||||
|
|
||||||
|
def test_rsync_file_popen_args_whole_file_false(self):
|
||||||
|
replicator = TestReplicator({})
|
||||||
|
with _mock_process(0) as process:
|
||||||
|
replicator._rsync_file('/some/file', 'remote:/some_file', False)
|
||||||
|
exp_args = ([
|
||||||
|
'rsync', '--quiet', '--no-motd',
|
||||||
|
'--timeout=%s' % int(math.ceil(replicator.node_timeout)),
|
||||||
|
'--contimeout=%s' % int(math.ceil(replicator.conn_timeout)),
|
||||||
|
'/some/file', 'remote:/some_file'],)
|
||||||
|
self.assertEqual(exp_args, process.args)
|
||||||
|
|
||||||
def test_rsync_db(self):
|
def test_rsync_db(self):
|
||||||
replicator = TestReplicator({})
|
replicator = TestReplicator({})
|
||||||
replicator._rsync_file = lambda *args: True
|
replicator._rsync_file = lambda *args: True
|
||||||
fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
|
fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
|
||||||
replicator._rsync_db(FakeBroker(), fake_device, ReplHttp(), 'abcd')
|
replicator._rsync_db(FakeBroker(), fake_device, ReplHttp(), 'abcd')
|
||||||
|
|
||||||
|
def test_rsync_db_rsync_file_call(self):
|
||||||
|
fake_device = {'ip': '127.0.0.1', 'port': '0', 'device': 'sda1'}
|
||||||
|
|
||||||
|
def mock_rsync_ip(ip):
|
||||||
|
self.assertEquals(fake_device['ip'], ip)
|
||||||
|
return 'rsync_ip(%s)' % ip
|
||||||
|
|
||||||
|
class MyTestReplicator(TestReplicator):
|
||||||
|
def __init__(self, db_file, remote_file):
|
||||||
|
super(MyTestReplicator, self).__init__({})
|
||||||
|
self.db_file = db_file
|
||||||
|
self.remote_file = remote_file
|
||||||
|
|
||||||
|
def _rsync_file(self_, db_file, remote_file, whole_file=True):
|
||||||
|
self.assertEqual(self_.db_file, db_file)
|
||||||
|
self.assertEqual(self_.remote_file, remote_file)
|
||||||
|
self_._rsync_file_called = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
with patch('swift.common.db_replicator.rsync_ip', mock_rsync_ip):
|
||||||
|
broker = FakeBroker()
|
||||||
|
remote_file = 'rsync_ip(127.0.0.1)::container/sda1/tmp/abcd'
|
||||||
|
replicator = MyTestReplicator(broker.db_file, remote_file)
|
||||||
|
replicator._rsync_db(broker, fake_device, ReplHttp(), 'abcd')
|
||||||
|
self.assert_(replicator._rsync_file_called)
|
||||||
|
|
||||||
|
with patch('swift.common.db_replicator.rsync_ip', mock_rsync_ip):
|
||||||
|
broker = FakeBroker()
|
||||||
|
remote_file = 'rsync_ip(127.0.0.1)::container0/sda1/tmp/abcd'
|
||||||
|
replicator = MyTestReplicator(broker.db_file, remote_file)
|
||||||
|
replicator.vm_test_mode = True
|
||||||
|
replicator._rsync_db(broker, fake_device, ReplHttp(), 'abcd')
|
||||||
|
self.assert_(replicator._rsync_file_called)
|
||||||
|
|
||||||
|
def test_rsync_db_rsync_file_failure(self):
|
||||||
|
class MyTestReplicator(TestReplicator):
|
||||||
|
def __init__(self):
|
||||||
|
super(MyTestReplicator, self).__init__({})
|
||||||
|
self._rsync_file_called = False
|
||||||
|
|
||||||
|
def _rsync_file(self_, *args, **kwargs):
|
||||||
|
self.assertEqual(
|
||||||
|
False, self_._rsync_file_called,
|
||||||
|
'_sync_file() should only be called once')
|
||||||
|
self_._rsync_file_called = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
with patch('os.path.exists', lambda *args: True):
|
||||||
|
replicator = MyTestReplicator()
|
||||||
|
fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
|
||||||
|
replicator._rsync_db(FakeBroker(), fake_device, ReplHttp(), 'abcd')
|
||||||
|
self.assertEqual(True, replicator._rsync_file_called)
|
||||||
|
|
||||||
|
def test_rsync_db_change_after_sync(self):
|
||||||
|
class MyTestReplicator(TestReplicator):
|
||||||
|
def __init__(self, broker):
|
||||||
|
super(MyTestReplicator, self).__init__({})
|
||||||
|
self.broker = broker
|
||||||
|
self._rsync_file_call_count = 0
|
||||||
|
|
||||||
|
def _rsync_file(self_, db_file, remote_file, whole_file=True):
|
||||||
|
self_._rsync_file_call_count += 1
|
||||||
|
if self_._rsync_file_call_count == 1:
|
||||||
|
self.assertEquals(True, whole_file)
|
||||||
|
self.assertEquals(False, self_.broker.locked)
|
||||||
|
elif self_._rsync_file_call_count == 2:
|
||||||
|
self.assertEquals(False, whole_file)
|
||||||
|
self.assertEquals(True, self_.broker.locked)
|
||||||
|
else:
|
||||||
|
raise RuntimeError('_rsync_file() called too many times')
|
||||||
|
return True
|
||||||
|
|
||||||
|
# with journal file
|
||||||
|
with patch('os.path.exists', lambda *args: True):
|
||||||
|
broker = FakeBroker()
|
||||||
|
replicator = MyTestReplicator(broker)
|
||||||
|
fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
|
||||||
|
replicator._rsync_db(broker, fake_device, ReplHttp(), 'abcd')
|
||||||
|
self.assertEquals(2, replicator._rsync_file_call_count)
|
||||||
|
|
||||||
|
# with new mtime
|
||||||
|
with patch('os.path.exists', lambda *args: False):
|
||||||
|
with patch('os.path.getmtime', ChangingMtimesOs()):
|
||||||
|
broker = FakeBroker()
|
||||||
|
replicator = MyTestReplicator(broker)
|
||||||
|
fake_device = {'ip': '127.0.0.1', 'device': 'sda1'}
|
||||||
|
replicator._rsync_db(broker, fake_device, ReplHttp(), 'abcd')
|
||||||
|
self.assertEquals(2, replicator._rsync_file_call_count)
|
||||||
|
|
||||||
def test_in_sync(self):
|
def test_in_sync(self):
|
||||||
replicator = TestReplicator({})
|
replicator = TestReplicator({})
|
||||||
self.assertEquals(replicator._in_sync(
|
self.assertEquals(replicator._in_sync(
|
||||||
|
Loading…
Reference in New Issue
Block a user