Skip to content

Commit

Permalink
Merge pull request #101 from harikitech/topic/increase_test_coverage
Browse files Browse the repository at this point in the history
Add more tests
  • Loading branch information
Surgo authored Jun 27, 2020
2 parents f852182 + 1fefcd0 commit 29e28ec
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 93 deletions.
2 changes: 1 addition & 1 deletion django_elastipymemcache/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION = (1, 3, 0)
VERSION = (1, 3, 1)
__version__ = '.'.join(map(str, VERSION))
2 changes: 1 addition & 1 deletion django_elastipymemcache/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class Client(HashClient):
def get_many(self, keys, gets=False, *args, **kwargs):
# pymemcache's HashClient may returns {'key': False}
end = super(Client, self).get_many(keys, gets, *args, **kwargs)
end = super().get_many(keys, gets, *args, **kwargs)

return {key: end.get(key) for key in end if end.get(key)}

Expand Down
5 changes: 3 additions & 2 deletions django_elastipymemcache/cluster_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ class WrongProtocolData(ValueError):
in telnet protocol
"""
def __init__(self, cmd, response):
super(WrongProtocolData, self).__init__(
'Unexpected response {} for command {}'.format(response, cmd))
super().__init__(
'Unexpected response {} for command {}'.format(response, cmd),
)


def get_cluster_info(
Expand Down
25 changes: 12 additions & 13 deletions django_elastipymemcache/memcached.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from django.core.cache import InvalidCacheBackendError
from django.core.cache.backends.memcached import BaseMemcachedCache

from . import client as pyMemcache_client
from . import client as pymemcache_client
from .cluster_utils import get_cluster_info


Expand Down Expand Up @@ -53,10 +53,10 @@ class ElastiPyMemCache(BaseMemcachedCache):
it used pyMemcache
"""
def __init__(self, server, params):
super(ElastiPyMemCache, self).__init__(
super().__init__(
server,
params,
library=pyMemcache_client,
library=pymemcache_client,
value_not_found_exception=ValueError)
if len(self._servers) > 1:
raise InvalidCacheBackendError(
Expand Down Expand Up @@ -113,27 +113,26 @@ def _cache(self):

return self._client

def close(self, **kwargs):
# libmemcached manages its own connections. Don't call disconnect_all()
# as it resets the failover state and creates unnecessary reconnects.
pass

@invalidate_cache_after_error
def get(self, *args, **kwargs):
return super(ElastiPyMemCache, self).get(*args, **kwargs)
return super().get(*args, **kwargs)

@invalidate_cache_after_error
def get_many(self, *args, **kwargs):
return super(ElastiPyMemCache, self).get_many(*args, **kwargs)
return super().get_many(*args, **kwargs)

@invalidate_cache_after_error
def set(self, *args, **kwargs):
return super(ElastiPyMemCache, self).set(*args, **kwargs)
return super().set(*args, **kwargs)

@invalidate_cache_after_error
def set_many(self, *args, **kwargs):
return super(ElastiPyMemCache, self).set_many(*args, **kwargs)
return super().set_many(*args, **kwargs)

@invalidate_cache_after_error
def delete(self, *args, **kwargs):
return super(ElastiPyMemCache, self).delete(*args, **kwargs)
return super().delete(*args, **kwargs)

@invalidate_cache_after_error
def delete_many(self, *args, **kwargs):
return super().delete_many(*args, **kwargs)
98 changes: 90 additions & 8 deletions tests/test_backend.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import socket
import sys
from unittest.mock import patch, Mock

from nose.tools import eq_
try:
import cPickle as pickle
except ImportError:
import pickle

if sys.version < '3':
from mock import patch, Mock
else:
from unittest.mock import patch, Mock

from django.core.cache import InvalidCacheBackendError
from nose.tools import (
eq_,
raises,
)


@raises(InvalidCacheBackendError)
def test_multiple_servers():
from django_elastipymemcache.memcached import (
ElastiPyMemCache,
)
ElastiPyMemCache('h1:0,h2:0', {})


@raises(InvalidCacheBackendError)
def test_wrong_server_format():
from django_elastipymemcache.memcached import (
ElastiPyMemCache,
)
ElastiPyMemCache('h', {})


@patch('django_elastipymemcache.memcached.get_cluster_info')
Expand Down Expand Up @@ -64,6 +85,14 @@ def test_node_info_cache(get_cluster_info):
'h', '0', False, socket._GLOBAL_DEFAULT_TIMEOUT)


@patch('django_elastipymemcache.memcached.get_cluster_info')
def test_failed_to_connect_servers(get_cluster_info):
from django_elastipymemcache.memcached import ElastiPyMemCache
backend = ElastiPyMemCache('h:0', {})
get_cluster_info.side_effect = OSError()
eq_(backend.get_cluster_nodes(), [])


@patch('django_elastipymemcache.memcached.get_cluster_info')
def test_invalidate_cache(get_cluster_info):
from django_elastipymemcache.memcached import ElastiPyMemCache
Expand Down Expand Up @@ -111,8 +140,7 @@ def test_client_get_many(get_cluster_info):
ret = backend.get_many(['key2'])
eq_(ret, {})

with patch('django_elastipymemcache.client.Client.get_many'), \
patch('pymemcache.client.hash.HashClient._safely_run_func') as p2:
with patch('pymemcache.client.hash.HashClient._safely_run_func') as p2:
p2.return_value = {
':1:key3': 1509111630.048594
}
Expand Down Expand Up @@ -149,3 +177,57 @@ def test_client_get_many(get_cluster_info):
'key2': 1509111630.048594,
},
)


@patch('django_elastipymemcache.memcached.get_cluster_info')
def test_client_set_many(get_cluster_info):
from django_elastipymemcache.memcached import ElastiPyMemCache

servers = [('h1', 0), ('h2', 0)]
get_cluster_info.return_value = {
'nodes': servers
}

backend = ElastiPyMemCache('h:0', {})
ret = backend.set_many({'key1': 'value1', 'key2': 'value2'})
eq_(ret, ['key1', 'key2'])


@patch('django_elastipymemcache.memcached.get_cluster_info')
def test_client_delete(get_cluster_info):
from django_elastipymemcache.memcached import ElastiPyMemCache

servers = [('h1', 0), ('h2', 0)]
get_cluster_info.return_value = {
'nodes': servers
}

backend = ElastiPyMemCache('h:0', {})
ret = backend.delete('key1')
eq_(ret, None)


@patch('django_elastipymemcache.memcached.get_cluster_info')
def test_client_delete_many(get_cluster_info):
from django_elastipymemcache.memcached import ElastiPyMemCache

servers = [('h1', 0), ('h2', 0)]
get_cluster_info.return_value = {
'nodes': servers
}

backend = ElastiPyMemCache('h:0', {})
ret = backend.delete_many(['key1', 'key2'])
eq_(ret, None)


def test_serialize_pickle():
from django_elastipymemcache.memcached import serialize_pickle
eq_(serialize_pickle('key', 'str'), ('str', 1))
eq_(serialize_pickle('key', 0), (pickle.dumps(0), 2))


def test_deserialize_pickle():
from django_elastipymemcache.memcached import deserialize_pickle
eq_(deserialize_pickle('key', 'str', 1), 'str')
eq_(deserialize_pickle('key', pickle.dumps(0), 2), 0)
124 changes: 56 additions & 68 deletions tests/test_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,43 @@
WrongProtocolData,
get_cluster_info,
)
from nose.tools import eq_, raises
from nose.tools import (
eq_,
raises,
)

if sys.version < '3':
from mock import patch, call, MagicMock
else:
from unittest.mock import patch, call, MagicMock


TEST_PROTOCOL_1_READ_UNTIL = [
b'VERSION 1.4.14',
]

TEST_PROTOCOL_1_EXPECT = [
(0, None, b'CONFIG cluster 0 138\r\n1\nhost|ip|11211 host||11211\n\r\nEND\r\n'), # NOQA
]

TEST_PROTOCOL_2_READ_UNTIL = [
b'VERSION 1.4.13',
]

TEST_PROTOCOL_2_EXPECT = [
(0, None, b'CONFIG cluster 0 138\r\n1\nhost|ip|11211 host||11211\n\r\nEND\r\n'), # NOQA
]

TEST_PROTOCOL_3_READ_UNTIL = [
b'VERSION 1.4.14 (Ubuntu)',
]

TEST_PROTOCOL_3_EXPECT = [
(0, None, b'CONFIG cluster 0 138\r\n1\nhost|ip|11211 host||11211\n\r\nEND\r\n'), # NOQA
]

TEST_PROTOCOL_4_READ_UNTIL = [
b'VERSION 1.4.34',
]

TEST_PROTOCOL_4_EXPECT = [
(0, None, b'ERROR\r\n'),
]
# https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/AutoDiscovery.AddingToYourClientLibrary.html
EXAMPLE_RESPONSE = (
b'CONFIG cluster 0 147\r\n'
b'12\n'
b'myCluster.pc4ldq.0001.use1.cache.amazonaws.com|10.82.235.120|11211 '
b'myCluster.pc4ldq.0002.use1.cache.amazonaws.com|10.80.249.27|11211\n\r\n'
b'END\r\n'
)


@patch('django_elastipymemcache.cluster_utils.Telnet')
def test_happy_path(Telnet):
client = Telnet.return_value
client.read_until.side_effect = TEST_PROTOCOL_1_READ_UNTIL
client.expect.side_effect = TEST_PROTOCOL_1_EXPECT
client.read_until.side_effect = [
b'VERSION 1.4.14',
]
client.expect.side_effect = [
(0, None, EXAMPLE_RESPONSE), # NOQA
]
info = get_cluster_info('', 0)
eq_(info['version'], 1)
eq_(info['nodes'], [('ip', 11211), ('host', 11211)])
eq_(info['version'], 12)
eq_(info['nodes'], [('10.82.235.120', 11211), ('10.80.249.27', 11211)])
client.write.assert_has_calls([
call(b'version\n'),
call(b'config get cluster\n'),
])


@raises(WrongProtocolData)
Expand All @@ -62,55 +50,55 @@ def test_bad_protocol():


@patch('django_elastipymemcache.cluster_utils.Telnet')
def test_last_versions(Telnet):
def test_ubuntu_protocol(Telnet):
client = Telnet.return_value
client.read_until.side_effect = TEST_PROTOCOL_1_READ_UNTIL
client.expect.side_effect = TEST_PROTOCOL_1_EXPECT
client.read_until.side_effect = [
b'VERSION 1.4.14 (Ubuntu)',
]
client.expect.side_effect = [
(0, None, b'CONFIG cluster 0 138\r\n1\nhost|ip|11211 host||11211\n\r\nEND\r\n'), # NOQA
]
get_cluster_info('', 0)
client.write.assert_has_calls([
call(b'version\n'),
call(b'config get cluster\n'),
])


@raises(WrongProtocolData)
@patch('django_elastipymemcache.cluster_utils.Telnet')
def test_prev_versions(Telnet):
def test_no_configuration_protocol_support_with_errors(Telnet):
client = Telnet.return_value
client.read_until.side_effect = TEST_PROTOCOL_2_READ_UNTIL
client.expect.side_effect = TEST_PROTOCOL_2_EXPECT
get_cluster_info('', 0)
client.write.assert_has_calls([
call(b'version\n'),
call(b'get AmazonElastiCache:cluster\n'),
])
client.read_until.side_effect = [
b'VERSION 1.4.34',
]
client.expect.side_effect = [
(0, None, b'ERROR\r\n'),
]
get_cluster_info('test', 0)


@raises(WrongProtocolData)
@patch('django_elastipymemcache.cluster_utils.Telnet')
def test_ubuntu_protocol(Telnet):
def test_hoge(Telnet):
client = Telnet.return_value
client.read_until.side_effect = TEST_PROTOCOL_3_READ_UNTIL
client.expect.side_effect = TEST_PROTOCOL_3_EXPECT

# try:
# get_cluster_info('', 0)
# except WrongProtocolData:
# raise AssertionError('Raised WrongProtocolData with Ubuntu version.')
get_cluster_info('', 0)

client.write.assert_has_calls([
call(b'version\n'),
call(b'config get cluster\n'),
])
client.read_until.side_effect = [
b'VERSION 1.4.34',
]
client.expect.side_effect = [
(0, None, b'CONFIG cluster 0 138\r\nfail\nhost|ip|11211 host||11211\n\r\nEND\r\n'), # NOQA
]
get_cluster_info('test', 0)


@raises(WrongProtocolData)
@patch('django_elastipymemcache.cluster_utils.Telnet')
def test_no_configuration_protocol_support_with_errors(Telnet):
def test_no_configuration_protocol_support_with_errors_but_ignored(Telnet):
client = Telnet.return_value
client.read_until.side_effect = TEST_PROTOCOL_4_READ_UNTIL
client.expect.side_effect = TEST_PROTOCOL_4_EXPECT
client.read_until.side_effect = [
b'VERSION 1.4.34',
]
client.expect.side_effect = [
(0, None, b'CONFIG cluster 0 138\r\n1\nfail\n\r\nEND\r\n'), # NOQA
]
get_cluster_info('test', 0)
client.write.assert_has_calls([
call(b'version\n'),
call(b'config get cluster\n'),
])

0 comments on commit 29e28ec

Please sign in to comment.