Enable pyright strict mode (#2652)

- added pyrightconfig.json with typeCheckingMode=strict
- added type hints to all files except api.py
- added type stubs for dns, etcd, consul, kazoo, pysyncobj and other modules
- added type stubs for psycopg2 and urllib3 with some little fixes
- fixes most of the issues reported by pyright
- remaining issues will be addressed later, along with enabling CI linting task
This commit is contained in:
Alexander Kukushkin
2023-05-09 09:38:00 +02:00
committed by GitHub
parent 1ac9b11f33
commit 76b3b99de2
102 changed files with 4803 additions and 2150 deletions
+4 -5
View File
@@ -23,6 +23,7 @@ class MockResponse(object):
def __init__(self, status_code=200):
self.status_code = status_code
self.headers = {'content-type': 'json'}
self.content = '{}'
self.reason = 'Not Found'
@@ -38,10 +39,6 @@ class MockResponse(object):
def getheader(*args):
return ''
@staticmethod
def getheaders():
return {'content-type': 'json'}
def requests_get(url, method='GET', endpoint=None, data='', **kwargs):
members = '[{"id":14855829450254237642,"peerURLs":["http://localhost:2380","http://localhost:7001"],' +\
@@ -85,6 +82,8 @@ class MockCursor(object):
self.description = [Mock()]
def execute(self, sql, *params):
if isinstance(sql, bytes):
sql = sql.decode('utf-8')
if sql.startswith('blabla'):
raise psycopg.ProgrammingError()
elif sql == 'CHECKPOINT' or sql.startswith('SELECT pg_catalog.pg_create_'):
@@ -98,7 +97,7 @@ class MockCursor(object):
elif sql.startswith('SELECT slot_name'):
self.results = [('blabla', 'physical'), ('foobar', 'physical'), ('ls', 'logical', 'a', 'b', 5, 100, 500)]
elif sql.startswith('WITH slots AS (SELECT slot_name, active'):
self.results = [(False, True)]
self.results = [(False, True)] if self.rowcount == 1 else [None]
elif sql.startswith('SELECT CASE WHEN pg_catalog.pg_is_in_recovery()'):
self.results = [(1, 2, 1, 0, False, 1, 1, None, None,
[{"slot_name": "ls", "confirmed_flush_lsn": 12345}],
+1 -1
View File
@@ -136,8 +136,8 @@ class TestCitus(BaseTestPostgresql):
self.assertEqual(parameters['shared_preload_libraries'], 'citus,foo,bar')
self.assertEqual(parameters['wal_level'], 'logical')
@patch.object(CitusHandler, 'is_enabled', Mock(return_value=False))
def test_bootstrap(self):
self.c._config = None
self.c.bootstrap()
def test_ignore_replication_slot(self):
+3 -2
View File
@@ -19,8 +19,9 @@ class TestConfig(unittest.TestCase):
def test_set_dynamic_configuration(self):
with patch.object(Config, '_build_effective_configuration', Mock(side_effect=Exception)):
self.assertIsNone(self.config.set_dynamic_configuration({'foo': 'bar'}))
self.assertTrue(self.config.set_dynamic_configuration({'standby_cluster': {}}))
self.assertFalse(self.config.set_dynamic_configuration({'foo': 'bar'}))
self.assertTrue(self.config.set_dynamic_configuration({'standby_cluster': {}, 'postgresql': {
'parameters': {'cluster_name': 1, 'wal_keep_size': 1, 'track_commit_timestamp': 1, 'wal_level': 1}}}))
def test_reload_local_configuration(self):
os.environ.update({
+2
View File
@@ -195,6 +195,8 @@ class TestConsul(unittest.TestCase):
@patch.object(consul.Consul.KV, 'delete', Mock(return_value=True))
def test_delete_leader(self):
self.c.delete_leader()
self.c._name = 'other'
self.c.delete_leader()
@patch.object(consul.Consul.KV, 'put', Mock(return_value=True))
def test_initialize(self):
+5 -1
View File
@@ -9,7 +9,7 @@ from mock import patch, Mock, PropertyMock
from patroni.ctl import ctl, load_config, output_members, get_dcs, parse_dcs, \
get_all_members, get_any_member, get_cursor, query_member, PatroniCtlException, apply_config_changes, \
format_config_for_editing, show_diff, invoke_editor, format_pg_version, CONFIG_FILE_PATH, PatronictlPrettyTable
from patroni.dcs.etcd import AbstractEtcdClientWithFailover, Failover
from patroni.dcs.etcd import AbstractEtcdClientWithFailover, Cluster, Failover
from patroni.psycopg import OperationalError
from patroni.utils import tzutc
from prettytable import PrettyTable, ALL
@@ -639,6 +639,10 @@ class TestCtl(unittest.TestCase):
self.runner.invoke(ctl, ['edit-config', 'dummy', '--force', '--apply', '-'], input='foo: bar')
mock_get_dcs.return_value.set_config_value.return_value = True
self.runner.invoke(ctl, ['edit-config', 'dummy', '--force', '--apply', '-'], input='foo: bar')
mock_get_dcs.return_value.get_cluster = Mock(return_value=Cluster.empty())
result = self.runner.invoke(ctl, ['edit-config', 'dummy'])
assert result.exit_code == 1
assert 'The config key does not exist in the cluster dummy' in result.output
@patch('patroni.ctl.get_dcs')
def test_version(self, mock_get_dcs):
+3 -1
View File
@@ -138,7 +138,9 @@ class TestClient(unittest.TestCase):
@patch.object(EtcdClient, '_get_machines_list',
Mock(return_value=['http://localhost:2379', 'http://localhost:4001']))
def setUp(self):
self.client = EtcdClient({'srv': 'test', 'retry_timeout': 3}, DnsCachingResolver())
self.etcd = Etcd({'namespace': '/patroni/', 'ttl': 30, 'retry_timeout': 3,
'srv': 'test', 'scope': 'test', 'name': 'foo'})
self.client = self.etcd._client
self.client.http.request = http_request
self.client.http.request_encode_body = http_request
+16 -5
View File
@@ -3,7 +3,7 @@ import json
import unittest
import urllib3
from mock import Mock, patch
from mock import Mock, PropertyMock, patch
from patroni.dcs.etcd import DnsCachingResolver
from patroni.dcs.etcd3 import PatroniEtcd3Client, Cluster, Etcd3Client, Etcd3Error, Etcd3ClientError, RetryFailedError,\
InvalidAuthToken, Unavailable, Unknown, UnsupportedEtcdVersion, UserEmpty, AuthFailed, base64_encode, Etcd3
@@ -85,6 +85,11 @@ class BaseTestEtcd3(unittest.TestCase):
class TestKVCache(BaseTestEtcd3):
@patch.object(urllib3.PoolManager, 'urlopen', mock_urlopen)
@patch.object(Etcd3Client, 'watchprefix', Mock(return_value=urllib3.response.HTTPResponse()))
def test__build_cache(self):
self.kv_cache._build_cache()
def test__do_watch(self):
self.client.watchprefix = Mock(return_value=False)
self.assertRaises(AttributeError, self.kv_cache._do_watch, '1')
@@ -94,14 +99,17 @@ class TestKVCache(BaseTestEtcd3):
def test_run(self):
self.assertRaises(SleepException, self.kv_cache.run)
@patch.object(urllib3.PoolManager, 'urlopen', mock_urlopen)
@patch.object(urllib3.response.HTTPResponse, 'read_chunked',
Mock(return_value=[b'{"error":{"grpc_code":14,"message":"","http_code":503}}']))
@patch.object(Etcd3Client, 'watchprefix', Mock(return_value=urllib3.response.HTTPResponse()))
def test_kill_stream(self):
self.assertRaises(Unavailable, self.kv_cache._do_watch, '1')
self.kv_cache.kill_stream()
with patch.object(MockResponse, 'connection', create=True) as mock_conn:
with patch.object(urllib3.response.HTTPResponse, 'connection') as mock_conn:
self.kv_cache.kill_stream()
mock_conn.sock.close.side_effect = Exception
self.kv_cache.kill_stream()
type(mock_conn).sock = PropertyMock(side_effect=Exception)
self.kv_cache.kill_stream()
class TestPatroniEtcd3Client(BaseTestEtcd3):
@@ -180,7 +188,8 @@ class TestEtcd3(BaseTestEtcd3):
@patch.object(urllib3.PoolManager, 'urlopen', mock_urlopen)
def setUp(self):
super(TestEtcd3, self).setUp()
self.assertRaises(AttributeError, self.kv_cache._build_cache)
# self.assertRaises(AttributeError, self.kv_cache._build_cache)
self.kv_cache._build_cache()
self.kv_cache._is_ready = True
self.etcd3.get_cluster()
@@ -276,6 +285,8 @@ class TestEtcd3(BaseTestEtcd3):
def test_delete_leader(self):
self.etcd3.delete_leader()
self.etcd3._name = 'other'
self.etcd3.delete_leader()
def test_delete_cluster(self):
self.etcd3.delete_cluster()
+20 -29
View File
@@ -244,7 +244,6 @@ class TestHa(PostgresInit):
def test_bootstrap_as_standby_leader(self, initialize):
self.p.data_directory_empty = true
self.ha.cluster = get_cluster_not_initialized_without_leader(cluster_config=ClusterConfig(0, {}, 0))
self.ha.cluster.is_unlocked = true
self.ha.patroni.config._dynamic_configuration = {"standby_cluster": {"port": 5432}}
self.assertEqual(self.ha.run_cycle(), 'trying to bootstrap a new standby leader')
@@ -261,7 +260,6 @@ class TestHa(PostgresInit):
def test_start_as_cascade_replica_in_standby_cluster(self):
self.p.data_directory_empty = true
self.ha.cluster = get_standby_cluster_initialized_with_only_leader()
self.ha.cluster.is_unlocked = false
self.assertEqual(self.ha.run_cycle(), "trying to bootstrap from replica 'test'")
def test_recover_replica_failed(self):
@@ -381,8 +379,8 @@ class TestHa(PostgresInit):
self.ha._async_executor.schedule('promote')
self.assertEqual(self.ha.run_cycle(), 'lost leader before promote')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_long_promote(self):
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.p.is_leader = false
self.p.set_role('primary')
@@ -407,14 +405,13 @@ class TestHa(PostgresInit):
self.p.is_leader = false
self.assertEqual(self.ha.run_cycle(), 'following a different leader because i am not the healthiest node')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_promote_because_have_lock(self):
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.p.is_leader = false
self.assertEqual(self.ha.run_cycle(), 'promoted self to leader because I had the session lock')
def test_promote_without_watchdog(self):
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.p.is_leader = true
with patch.object(Watchdog, 'activate', Mock(return_value=False)):
@@ -424,24 +421,22 @@ class TestHa(PostgresInit):
def test_leader_with_lock(self):
self.ha.cluster = get_cluster_initialized_with_leader()
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), the leader with the lock')
def test_coordinator_leader_with_lock(self):
self.ha.cluster = get_cluster_initialized_with_leader()
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), the leader with the lock')
@patch.object(Postgresql, '_wait_for_connection_close', Mock())
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_demote_because_not_having_lock(self):
self.ha.cluster.is_unlocked = false
with patch.object(Watchdog, 'is_running', PropertyMock(return_value=True)):
self.assertEqual(self.ha.run_cycle(), 'demoting self because I do not have the lock and I was a leader')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_demote_because_update_lock_failed(self):
self.ha.cluster.is_unlocked = false
self.ha.has_lock = true
self.ha.update_lock = false
self.assertEqual(self.ha.run_cycle(), 'demoted self because failed to update leader lock in DCS')
@@ -450,8 +445,8 @@ class TestHa(PostgresInit):
self.p.is_leader = false
self.assertEqual(self.ha.run_cycle(), 'not promoting because failed to update leader lock in DCS')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_follow(self):
self.ha.cluster.is_unlocked = false
self.p.is_leader = false
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), a secondary, and following a leader ()')
self.ha.patroni.replicatefrom = "foo"
@@ -465,8 +460,8 @@ class TestHa(PostgresInit):
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), a secondary, and following a leader ()')
del self.ha.cluster.config.data['postgresql']['use_slots']
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_follow_in_pause(self):
self.ha.cluster.is_unlocked = false
self.ha.is_paused = true
self.assertEqual(self.ha.run_cycle(), 'PAUSE: continue to run as primary without lock')
self.p.is_leader = false
@@ -659,10 +654,12 @@ class TestHa(PostgresInit):
self.ha.update_lock = false
self.p.set_role('primary')
with patch('patroni.async_executor.CriticalTask.cancel', Mock(return_value=False)):
with patch('patroni.postgresql.Postgresql.terminate_starting_postmaster') as mock_terminate:
self.assertEqual(self.ha.run_cycle(), 'lost leader lock during restart')
mock_terminate.assert_called()
with patch('patroni.async_executor.CriticalTask.cancel', Mock(return_value=False)),\
patch('patroni.async_executor.CriticalTask.result',
PropertyMock(return_value=PostmasterProcess(os.getpid())), create=True),\
patch('patroni.postgresql.Postgresql.terminate_starting_postmaster') as mock_terminate:
self.assertEqual(self.ha.run_cycle(), 'lost leader lock during restart')
mock_terminate.assert_called()
self.ha.is_paused = true
self.assertEqual(self.ha.run_cycle(), 'PAUSE: restart in progress')
@@ -741,7 +738,6 @@ class TestHa(PostgresInit):
def test_manual_failover_process_no_leader(self):
self.p.is_leader = false
self.ha.cluster = get_cluster_initialized_without_leader(failover=Failover(0, '', self.p.name, None))
self.assertEqual(self.ha.run_cycle(), 'promoted self to leader by acquiring session lock')
self.ha.cluster = get_cluster_initialized_without_leader(failover=Failover(0, '', 'leader', None))
self.p.set_role('replica')
self.assertEqual(self.ha.run_cycle(), 'promoted self to leader by acquiring session lock')
@@ -847,10 +843,10 @@ class TestHa(PostgresInit):
self.assertFalse(self.ha.is_healthiest_node())
def test__is_healthiest_node(self):
self.p.is_leader = false
self.ha.cluster = get_cluster_initialized_without_leader(sync=('postgresql1', self.p.name))
self.ha.global_config = self.ha.patroni.config.get_global_config(self.ha.cluster)
self.assertTrue(self.ha._is_healthiest_node(self.ha.old_cluster.members))
self.p.is_leader = false
self.ha.fetch_node_status = get_node_status() # accessible, in_recovery
self.assertTrue(self.ha._is_healthiest_node(self.ha.old_cluster.members))
self.ha.fetch_node_status = get_node_status(in_recovery=False) # accessible, not in_recovery
@@ -864,6 +860,8 @@ class TestHa(PostgresInit):
self.ha.global_config = self.ha.patroni.config.get_global_config(self.ha.cluster)
with patch('patroni.postgresql.Postgresql.last_operation', return_value=1):
self.assertFalse(self.ha._is_healthiest_node(self.ha.old_cluster.members))
with patch('patroni.postgresql.Postgresql.replica_cached_timeline', return_value=None):
self.assertFalse(self.ha._is_healthiest_node(self.ha.old_cluster.members))
with patch('patroni.postgresql.Postgresql.replica_cached_timeline', return_value=1):
self.assertFalse(self.ha._is_healthiest_node(self.ha.old_cluster.members))
self.ha.patroni.nofailover = True
@@ -972,11 +970,11 @@ class TestHa(PostgresInit):
with patch.object(Leader, 'conn_url', PropertyMock(return_value='')):
self.assertEqual(self.ha.run_cycle(), 'continue following the old known standby leader')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=True))
def test_process_unhealthy_standby_cluster_as_standby_leader(self):
self.p.is_leader = false
self.p.name = 'leader'
self.ha.cluster = get_standby_cluster_initialized_with_only_leader()
self.ha.cluster.is_unlocked = true
self.ha.sysid_valid = true
self.p._sysid = True
self.assertEqual(self.ha.run_cycle(), 'promoted self to a standby leader by acquiring session lock')
@@ -987,7 +985,6 @@ class TestHa(PostgresInit):
self.p.is_leader = false
self.p.name = 'replica'
self.ha.cluster = get_standby_cluster_initialized_with_only_leader()
self.ha.is_unlocked = true
self.assertTrue(self.ha.run_cycle().startswith('running pg_rewind from remote_member:'))
def test_recover_unhealthy_leader_in_standby_cluster(self):
@@ -998,13 +995,13 @@ class TestHa(PostgresInit):
self.ha.cluster = get_standby_cluster_initialized_with_only_leader()
self.assertEqual(self.ha.run_cycle(), 'starting as a standby leader because i had the session lock')
@patch.object(Cluster, 'is_unlocked', Mock(return_value=True))
def test_recover_unhealthy_unlocked_standby_cluster(self):
self.p.is_leader = false
self.p.name = 'leader'
self.p.is_running = false
self.p.follow = false
self.ha.cluster = get_standby_cluster_initialized_with_only_leader()
self.ha.cluster.is_unlocked = true
self.ha.has_lock = false
self.assertEqual(self.ha.run_cycle(), 'trying to follow a remote member because standby cluster is unhealthy')
@@ -1287,10 +1284,10 @@ class TestHa(PostgresInit):
@patch('patroni.postgresql.mtime', Mock(return_value=1588316884))
@patch('builtins.open', Mock(side_effect=Exception))
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_restore_cluster_config(self):
self.ha.cluster.config.data.clear()
self.ha.has_lock = true
self.ha.cluster.is_unlocked = false
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), the leader with the lock')
def test_watch(self):
@@ -1341,9 +1338,9 @@ class TestHa(PostgresInit):
@patch('patroni.postgresql.mtime', Mock(return_value=1588316884))
@patch('builtins.open', mock_open(read_data=('1\t0/40159C0\tno recovery target specified\n\n'
'2\t1/40159C0\tno recovery target specified\n')))
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_update_cluster_history(self):
self.ha.has_lock = true
self.ha.cluster.is_unlocked = false
for tl in (1, 3):
self.p.get_primary_timeline = Mock(return_value=tl)
self.assertEqual(self.ha.run_cycle(), 'no action. I am (postgresql0), the leader with the lock')
@@ -1355,9 +1352,9 @@ class TestHa(PostgresInit):
self.ha.run_cycle()
exit_mock.assert_called_once_with(1)
@patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
def test_after_pause(self):
self.ha.has_lock = true
self.ha.cluster.is_unlocked = false
self.ha.is_paused = true
self.assertEqual(self.ha.run_cycle(), 'PAUSE: no action. I am (postgresql0), the leader with the lock')
self.ha.is_paused = false
@@ -1409,16 +1406,10 @@ class TestHa(PostgresInit):
@patch.object(Postgresql, 'major_version', PropertyMock(return_value=130000))
@patch.object(SlotsHandler, 'sync_replication_slots', Mock(return_value=['ls']))
def test_follow_copy(self):
self.ha.cluster.is_unlocked = false
self.ha.cluster.config.data['slots'] = {'ls': {'database': 'a', 'plugin': 'b'}}
self.p.is_leader = false
self.assertTrue(self.ha.run_cycle().startswith('Copying logical slots'))
def test_is_failover_possible(self):
self.ha.fetch_node_status = Mock(return_value=_MemberStatus(self.ha.cluster.members[0],
True, True, 0, 2, None, {}, False))
self.assertFalse(self.ha.is_failover_possible(self.ha.cluster.members))
def test_acquire_lock(self):
self.ha.dcs.attempt_to_acquire_leader = Mock(side_effect=[DCSError('foo'), Exception])
self.assertRaises(DCSError, self.ha.acquire_lock)
+21 -11
View File
@@ -5,6 +5,7 @@ import mock
import socket
import time
import unittest
import urllib3
from mock import Mock, PropertyMock, mock_open, patch
from patroni.dcs.kubernetes import Cluster, k8s_client, k8s_config, K8sConfig, K8sConnectionFailed,\
@@ -34,6 +35,9 @@ def mock_list_namespaced_config_map(*args, **kwargs):
metadata.update({'name': 'test-1-leader', 'labels': {Kubernetes._CITUS_LABEL: '1'},
'annotations': {'leader': 'p-3', 'ttl': '30s'}})
items.append(k8s_client.V1ConfigMap(metadata=k8s_client.V1ObjectMeta(**metadata)))
metadata.update({'name': 'test-2-config', 'labels': {Kubernetes._CITUS_LABEL: '2'}, 'annotations': {}})
items.append(k8s_client.V1ConfigMap(metadata=k8s_client.V1ObjectMeta(**metadata)))
metadata = k8s_client.V1ObjectMeta(resource_version='1')
return k8s_client.V1ConfigMapList(metadata=metadata, items=items, kind='ConfigMapList')
@@ -403,13 +407,18 @@ class TestKubernetesEndpoints(BaseTestKubernetes):
self.assertEqual(('create_config_service failed',), mock_logger_exception.call_args[0])
def mock_watch(*args):
return urllib3.HTTPResponse()
class TestCacheBuilder(BaseTestKubernetes):
@patch.object(k8s_client.CoreV1Api, 'list_namespaced_config_map', mock_list_namespaced_config_map, create=True)
@patch('patroni.dcs.kubernetes.ObjectCache._watch')
def test__build_cache(self, mock_response):
@patch('patroni.dcs.kubernetes.ObjectCache._watch', mock_watch)
@patch.object(urllib3.HTTPResponse, 'read_chunked')
def test__build_cache(self, mock_read_chunked):
self.k._citus_group = '0'
mock_response.return_value.read_chunked.return_value = [json.dumps(
mock_read_chunked.return_value = [json.dumps(
{'type': 'MODIFIED', 'object': {'metadata': {
'name': self.k.config_path, 'resourceVersion': '2', 'annotations': {self.k._CONFIG: 'foo'}}}}
).encode('utf-8'), ('\n' + json.dumps(
@@ -435,12 +444,13 @@ class TestCacheBuilder(BaseTestKubernetes):
self.assertRaises(AttributeError, self.k._kinds._do_watch, '1')
@patch.object(k8s_client.CoreV1Api, 'list_namespaced_config_map', mock_list_namespaced_config_map, create=True)
@patch('patroni.dcs.kubernetes.ObjectCache._watch')
def test_kill_stream(self, mock_watch):
self.k._kinds.kill_stream()
mock_watch.return_value.read_chunked.return_value = []
mock_watch.return_value.connection.sock.close.side_effect = Exception
self.k._kinds._do_watch('1')
self.k._kinds.kill_stream()
type(mock_watch.return_value).connection = PropertyMock(side_effect=Exception)
@patch('patroni.dcs.kubernetes.ObjectCache._watch', mock_watch)
@patch.object(urllib3.HTTPResponse, 'read_chunked', Mock(return_value=[]))
def test_kill_stream(self):
self.k._kinds.kill_stream()
with patch.object(urllib3.HTTPResponse, 'connection') as mock_connection:
mock_connection.sock.close.side_effect = Exception
self.k._kinds._do_watch('1')
self.k._kinds.kill_stream()
with patch.object(urllib3.HTTPResponse, 'connection', PropertyMock(side_effect=Exception)):
self.k._kinds.kill_stream()
+6 -2
View File
@@ -369,6 +369,10 @@ class TestPostgresql(BaseTestPostgresql):
def test_latest_checkpoint_location(self, mock_popen):
mock_popen.return_value.communicate.return_value = (None, None)
self.assertEqual(self.p.latest_checkpoint_location(), 28163096)
with patch.object(Postgresql, 'controldata', Mock(return_value={'Database cluster state': 'shut down',
'Latest checkpoint location': 'k/1ADBC18',
"Latest checkpoint's TimeLineID": '1'})):
self.assertIsNone(self.p.latest_checkpoint_location())
# 9.3 and 9.4 format
mock_popen.return_value.communicate.side_effect = [
(b'rmgr: XLOG len (rec/tot): 72/ 104, tx: 0, lsn: 0/01ADBC18, prev 0/01ADBBB8, '
@@ -518,10 +522,10 @@ class TestPostgresql(BaseTestPostgresql):
def test_can_create_replica_without_replication_connection(self):
self.p.config._config['create_replica_method'] = []
self.assertFalse(self.p.can_create_replica_without_replication_connection())
self.assertFalse(self.p.can_create_replica_without_replication_connection(None))
self.p.config._config['create_replica_method'] = ['wale', 'basebackup']
self.p.config._config['wale'] = {'command': 'foo', 'no_leader': 1}
self.assertTrue(self.p.can_create_replica_without_replication_connection())
self.assertTrue(self.p.can_create_replica_without_replication_connection(None))
def test_replica_method_can_work_without_replication_connection(self):
self.assertFalse(self.p.replica_method_can_work_without_replication_connection('basebackup'))
+2
View File
@@ -111,6 +111,8 @@ class TestSlotsHandler(BaseTestPostgresql):
self.s.copy_logical_slots(self.cluster, ['ls'])
with patch.object(MockCursor, 'execute', Mock(side_effect=psycopg.OperationalError)):
self.s.copy_logical_slots(self.cluster, ['foo'])
with patch.object(Cluster, 'leader', PropertyMock(return_value=None)):
self.s.copy_logical_slots(self.cluster, ['foo'])
@patch.object(Postgresql, 'stop', Mock(return_value=True))
@patch.object(Postgresql, 'start', Mock(return_value=True))
+1 -1
View File
@@ -36,7 +36,7 @@ class TestUtils(unittest.TestCase):
def test_enable_keepalive(self):
with patch('socket.SIO_KEEPALIVE_VALS', 1, create=True):
self.assertIsNotNone(enable_keepalive(Mock(), 10, 5))
self.assertIsNone(enable_keepalive(Mock(), 10, 5))
with patch('socket.SIO_KEEPALIVE_VALS', None, create=True):
for platform in ('linux2', 'darwin', 'other'):
with patch('sys.platform', platform):
+1 -1
View File
@@ -123,7 +123,7 @@ class TestWALERestore(unittest.TestCase):
with patch.object(WALERestore, 'run', Mock(return_value=1)), \
patch('time.sleep', mock_sleep):
self.assertEqual(_main(), 1)
self.assertTrue(sleeps[0], WALE_TEST_RETRIES)
self.assertEqual(sleeps[0], WALE_TEST_RETRIES)
@patch('os.path.isfile', Mock(return_value=True))
def test_get_major_version(self):
+5
View File
@@ -110,6 +110,11 @@ class TestWatchdog(unittest.TestCase):
watchdog.keepalive()
self.assertEqual(len(device.writes), 1)
watchdog.impl._fd, fd = None, watchdog.impl._fd
watchdog.keepalive()
self.assertEqual(len(device.writes), 1)
watchdog.impl._fd = fd
watchdog.disable()
self.assertFalse(device.open)
self.assertEqual(device.writes[-1], b'V')
+3 -5
View File
@@ -13,6 +13,7 @@ from patroni.dcs.zookeeper import Cluster, Leader, PatroniKazooClient,\
class MockKazooClient(Mock):
handler = PatroniSequentialThreadingHandler(10)
leader = False
exists = True
@@ -154,11 +155,6 @@ class TestZooKeeper(unittest.TestCase):
def test_session_listener(self):
self.zk.session_listener(KazooState.SUSPENDED)
def test_members_watcher(self):
self.zk._fetch_cluster = False
self.zk.members_watcher(None)
self.assertTrue(self.zk._fetch_cluster)
def test_reload_config(self):
self.zk.reload_config({'ttl': 20, 'retry_timeout': 10, 'loop_wait': 10})
self.zk.reload_config({'ttl': 20, 'retry_timeout': 10, 'loop_wait': 5})
@@ -223,6 +219,8 @@ class TestZooKeeper(unittest.TestCase):
def test_cancel_initialization(self):
self.zk.cancel_initialization()
with patch.object(MockKazooClient, 'delete', Mock()):
self.zk.cancel_initialization()
def test_touch_member(self):
self.zk._name = 'buzz'