Merge "add unit tests for db_replicator"

This commit is contained in:
Jenkins 2013-04-08 20:51:57 +00:00 committed by Gerrit Code Review
commit b93b1327f7

View File

@ -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(