summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Lavagetto <lavagetto@gmail.com>2013-11-23 23:59:27 +0100
committerGiuseppe Lavagetto <lavagetto@gmail.com>2013-12-02 19:34:25 +0100
commitae825e32d01cb26ee7da0410e1aa67e6a1a11b19 (patch)
treef7d596edba6231e9ecc899a108fdb305fe0d7ddb
parent0e5789150352a6e841326edd51fb719d8f3cb1e9 (diff)
Complete rewrite of unit tests for requests using mox.
Unit tests needed to be rewriteen much more than integration tests. Mox is used instead of mock because it gives more strict control on call arguments for methods.
-rw-r--r--setup.py3
-rw-r--r--src/etcd/tests/unit/test_request.py633
2 files changed, 249 insertions, 387 deletions
diff --git a/setup.py b/setup.py
index f1a652d..1677d77 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,8 @@ version = '0.2.1'
install_requires = [
'urllib3==1.7',
- 'pyOpenSSL==0.13.1'
+ 'pyOpenSSL==0.13.1',
+ 'mox'
]
diff --git a/src/etcd/tests/unit/test_request.py b/src/etcd/tests/unit/test_request.py
index c47e721..3a0fad4 100644
--- a/src/etcd/tests/unit/test_request.py
+++ b/src/etcd/tests/unit/test_request.py
@@ -1,404 +1,265 @@
import etcd
import unittest
-import mock
+import json
+import mox
+import urllib3
from etcd import EtcdException
-
-class TestClientRequest(unittest.TestCase):
+class TestClientV2ApiInterface(mox.MoxTestBase):
+
+ def setUp(self):
+ mox.MoxTestBase.setUp(self)
+ self.client = etcd.Client()
+ self.mox.StubOutWithMock(self.client, 'api_execute')
+
+
+ def _prepare_response(self, status, d):
+ r = self.mox.CreateMock(urllib3.response.HTTPResponse)
+ r.status = status
+ if isinstance(d, dict):
+ r.data = json.dumps(d)
+ else:
+ r.data = d
+ return r
+
+
+ def _mock_write(self, status, d):
+ resp = self._prepare_response(status, d)
+ self.client.api_execute(mox.IsA(str),self.client._MPUT,
+ mox.IsA(dict)).AndReturn(resp)
+
+ def _mock_get(self, status, d):
+ resp = self._prepare_response(status, d)
+ self.client.api_execute(
+ mox.IsA(str),
+ self.client._MGET,
+ mox.Or(mox.IsA(dict), mox.IsA(None))
+ ).AndReturn(resp)
+
+ def _mock_get_plain(self, status, d):
+ resp = self._prepare_response(status, d)
+ self.client.api_execute(
+ mox.IsA(str),
+ self.client._MGET
+ ).AndReturn(resp)
+
+ def _mock_delete(self, status, d):
+ resp = self._prepare_response(status, d)
+ self.client.api_execute(
+ mox.IsA(str),
+ self.client._MDELETE
+ ).AndReturn(resp)
+
+
+ def _mock_exception(self, exc, msg):
+ self.client.api_execute(
+ mox.IgnoreArg(),
+ mox.IgnoreArg(),
+ mox.IgnoreArg()
+# params = mox.Or(mox.IsA(dict), mox.IsA(None))
+ ).AndRaise(exc(msg))
def test_machines(self):
""" Can request machines """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- "http://127.0.0.1:4002,"
- " http://127.0.0.1:4001,"
- " http://127.0.0.1:4003,"
- " http://127.0.0.1:4001"
- )
-
- assert client.machines == [
- 'http://127.0.0.1:4002',
- 'http://127.0.0.1:4001',
- 'http://127.0.0.1:4003',
- 'http://127.0.0.1:4001'
- ]
+ data = ['http://127.0.0.1:4001','http://127.0.0.1:4002','http://127.0.0.1:4003']
+ d = ','.join(data)
+ self._mock_get_plain(200,d)
+ self.mox.ReplayAll()
+ self.assertEquals(data, self.client.machines)
def test_leader(self):
""" Can request the leader """
- client = etcd.Client()
- client.api_execute = mock.Mock(return_value="http://127.0.0.1:7002")
- result = client.leader
- self.assertEquals('http://127.0.0.1:7002', result)
-
- def test_set(self):
- """ Can set a value """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"set",'
- '"key":"/testkey",'
- '"value":"test",'
- '"expiration":"2013-09-14T00:56:59.316195568+02:00",'
- '"ttl":19,"modifiedIndex":183}')
-
- result = client.set('/testkey', 'test', ttl=19)
-
- self.assertEquals(
- etcd.EtcdResult(
- **{u'action': u'set',
- u'expiration': u'2013-09-14T00:56:59.316195568+02:00',
- u'modifiedIndex': 183,
- u'key': u'/testkey',
- u'ttl': 19,
- u'value': u'test'}), result)
-
- def test_test_and_set(self):
- """ Can test and set a value """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"compareAndSwap",'
- '"key":"/testkey",'
- '"prevValue":"test",'
- '"value":"newvalue",'
- '"expiration":"2013-09-14T02:09:44.24390976+02:00",'
- '"ttl":49,"modifiedIndex":203}')
-
- result = client.test_and_set('/testkey', 'newvalue', 'test', ttl=19)
- self.assertEquals(
- etcd.EtcdResult(
- **{u'action': u'compareAndSwap',
- u'expiration': u'2013-09-14T02:09:44.24390976+02:00',
- u'modifiedIndex': 203,
- u'key': u'/testkey',
- u'prevValue': u'test',
- u'ttl': 49,
- u'value': u'newvalue'}), result)
-
- def test_test_and_test_failure(self):
+ data = "http://127.0.0.1:4001"
+ self._mock_get_plain(200, data)
+ self.mox.ReplayAll()
+ self.assertEquals(self.client.leader, data)
+
+ #test writes
+ def test_set_plain(self):
+ d = {u'action': u'set',
+ u'expiration': u'2013-09-14T00:56:59.316195568+02:00',
+ u'modifiedIndex': 183,
+ u'key': u'/testkey',
+ u'ttl': 19,
+ u'value': u'test'}
+
+ self._mock_write(200, d)
+ self.mox.ReplayAll()
+ res = self.client.write('/testkey', 'test')
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+ def test_newkey(self):
+ d = {u'action': u'set',
+ u'expiration': u'2013-09-14T00:56:59.316195568+02:00',
+ u'modifiedIndex': 183,
+ u'key': u'/testkey',
+ u'ttl': 19,
+ u'value': u'test'}
+
+ self._mock_write(201, d)
+ self.mox.ReplayAll()
+ d['newKey'] = True
+ res = self.client.write('/testkey', 'test')
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+ def test_compare_and_swap(self):
+ d = {u'action': u'compareAndSwap',
+ u'expiration': u'2013-09-14T00:56:59.316195568+02:00',
+ u'modifiedIndex': 183,
+ u'key': u'/testkey',
+ 'prevValue': 'test_old',
+ u'ttl': 19,
+ u'value': u'test'}
+
+ self._mock_write(200,d)
+ self.mox.ReplayAll()
+ res = self.client.write('/testkey', 'test', prevValue = 'test_old')
+ self.assertEquals(res, etcd.EtcdResult(**d))
+ self.mox.UnsetStubs()
+ self.mox.VerifyAll()
+
+ def test_compare_and_swap_existence(self):
+ d = {
+ u'action': u'compareAndSwap',
+ u'expiration': u'2013-09-14T00:56:59.316195568+02:00',
+ u'modifiedIndex': 183,
+ u'key': u'/testkey',
+ u'ttl': 19,
+ u'value': u'test'
+ }
+ self._mock_write(200,d)
+ self.mox.ReplayAll()
+ res = self.client.write('/testkey', 'test', prevExists = True)
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+ def test_compare_and_swap_failure(self):
""" Exception will be raised if prevValue != value in test_set """
-
- client = etcd.Client()
- client.api_execute = mock.Mock(
- side_effect=ValueError(
- 'Test Failed:'
- '[ 1!=3 ]'))
- try:
- result = client.test_and_set(
- '/testkey',
- 'newvalue',
- 'test', ttl=19)
- except ValueError, e:
- #from ipdb import set_trace; set_trace()
- self.assertEquals(
- 'Test Failed:'
- '[ 1!=3 ]', e.message)
+ self._mock_exception(ValueError,'Test Failed : [ 1!=3 ]')
+ self.mox.ReplayAll()
+ self.assertRaises(
+ ValueError,
+ self.client.write,
+ '/testKey',
+ 'test',
+ prevValue='oldbog'
+ )
def test_delete(self):
""" Can delete a value """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"delete",'
- '"key":"/testkey",'
- '"prevValue":"test",'
- '"expiration":"2013-09-14T01:06:35.5242587+02:00",'
- '"modifiedIndex":189}')
-
- result = client.delete('/testkey')
- self.assertEquals(etcd.EtcdResult(
- **{u'action': u'delete',
- u'expiration': u'2013-09-14T01:06:35.5242587+02:00',
- u'modifiedIndex': 189,
- u'key': u'/testkey',
- u'prevValue': u'test'}), result)
-
- def test_get(self):
+ d = {
+ u'action': u'delete',
+ u'key': u'/testkey',
+ }
+ self._mock_delete(200, d)
+ self.mox.ReplayAll()
+ res = self.client.delete('/testKey')
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+ def test_read(self):
""" Can get a value """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"get",'
- '"key":"/testkey",'
- '"value":"test",'
- '"modifiedIndex":190}')
-
- result = client.get('/testkey')
- self.assertEquals(etcd.EtcdResult(
- **{u'action': u'get',
- u'modifiedIndex': 190,
- u'key': u'/testkey',
- u'value': u'test'}), result)
-
- def test_get_multi(self):
- """Can get multiple values"""
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '[{"action":"get",'
- '"key":"/testdir/key1",'
- '"value":"test1",'
- '"modifiedIndex":190},'
- '{"action":"get",'
- '"key":"/testdir/key2",'
- '"value":"test2",'
- '"modifiedIndex":190}]'
+ d = {
+ u'action': u'get',
+ u'modifiedIndex': 190,
+ u'key': u'/testkey',
+ u'value': u'test'
+ }
+ self._mock_get(200,d)
+ self.mox.ReplayAll()
+ res = self.client.read('/testKey')
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+ def test_get_dir(self):
+ """Can get values in dirs"""
+ d = {
+ u'action': u'get',
+ u'modifiedIndex': 190,
+ u'key': u'/testkey',
+ u'dir': True,
+ u'kvs': [
+ {
+ u'key': u'/testDir/testKey',
+ u'modifiedIndex': 150,
+ u'value': 'test'
+ },
+ {
+ u'key': u'/testDir/testKey2',
+ u'modifiedIndex': 190,
+ u'value': 'test2'
+ }
+ ]
+ }
+ self._mock_get(200,d)
+ self.mox.ReplayAll()
+ res = self.client.read('/testDir', recursive = True)
+ self.assertEquals(res, etcd.EtcdResult(**d))
+
+
+class TestClientV2Request(TestClientV2ApiInterface):
+
+ def setUp(self):
+ mox.MoxTestBase.setUp(self)
+ self.client = etcd.Client()
+ self.mox.StubOutWithMock(self.client.http, 'request')
+ self.mox.StubOutWithMock(self.client.http, 'request_encode_body')
+
+ def _mock_write(self, status, d):
+ resp = self._prepare_response(status, d)
+ self.client.http.request_encode_body(
+ self.client._MPUT, mox.IsA(str),
+ encode_multipart=mox.IsA(bool),
+ redirect=mox.IsA(bool),
+ fields=mox.IsA(dict)
+ ).AndReturn(resp)
+
+ def _mock_get(self, status, data):
+ resp = self._prepare_response(status, data)
+ self.client.http.request(
+ self.client._MGET, mox.IsA(str),
+ redirect=mox.IsA(bool),
+ fields=mox.Or(mox.IsA(dict),mox.IsA(None))
+ ).AndReturn(resp)
+
+ def _mock_get_plain(self, status, data):
+ return self._mock_get(status, data)
+
+ def _mock_error(self, error_code, msg, cause, method='PUT', fields=None):
+ resp = self._prepare_response(
+ 500,
+ {'errorCode': error_code,'message': msg, 'cause': cause}
)
- result = client.get('/testdir')
- self.assertEquals([
- etcd.EtcdResult(
- **{u'action': u'get',
- u'modifiedIndex': 190,
- u'key': u'/testdir/key1',
- u'value': u'test1'}),
- etcd.EtcdResult(
- **{u'action': u'get',
- u'modifiedIndex': 190,
- u'key': u'/testdir/key2',
- u'value': u'test2'})
- ], result)
-
- def test_get_subdirs(self):
- """ Can understand dirs in results """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '[{"action":"get",'
- '"key":"/testdir/key1",'
- '"value":"test1",'
- '"modifiedIndex":190},'
- '{"action":"get",'
- '"key":"/testdir/key2",'
- '"dir": true,'
- '"modifiedIndex":191}]'
+ kwds = {'redirect': mox.IsA(bool), 'fields': mox.IsA(type(fields))}
+ if method == 'PUT':
+ kwds['encode_multipart'] = mox.IsA(bool)
+ self.client.http.request_encode_body(
+ method,
+ mox.IsA(str),
+ **kwds
+ ).AndReturn(resp)
+ else:
+ self.client.http.request(
+ method,
+ mox.IsA(str),
+ **kwds
+ ).AndReturn(resp)
+
+ def _mock_delete(self, status, data):
+ resp = self._prepare_response(status, data)
+ self.client.http.request(
+ self.client._MDELETE, mox.IsA(str),
+ redirect=mox.IsA(bool),
+ fields=mox.Or(mox.IsA(dict),mox.IsA(None))
+ ).AndReturn(resp)
+
+
+ def test_compare_and_swap_failure(self):
+ """ Exception will be raised if prevValue != value in test_set """
+ self._mock_error(200, 'Test Failed', '[ 1!=3 ]', fields={'prevValue': 'oldbog'})
+ self.mox.ReplayAll()
+ self.assertRaises(
+ ValueError,
+ self.client.write,
+ '/testKey',
+ 'test',
+ prevValue='oldbog'
)
- result = client.get('/testdir')
- self.assertEquals([
- etcd.EtcdResult(
- **{u'action': u'get',
- u'modifiedIndex': 190,
- u'key': u'/testdir/key1',
- u'value': u'test1'}),
- etcd.EtcdResult(
- **{u'action': u'get',
- u'modifiedIndex': 191,
- u'key': u'/testdir/key2',
- u'dir': True})
- ], result)
-
- def test_not_in(self):
- """ Can check if key is not in client """
- client = etcd.Client()
- client.get = mock.Mock(side_effect=KeyError())
- result = '/testkey' not in client
- self.assertEquals(True, result)
-
- def test_in(self):
- """ Can check if key is in client """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"get",'
- '"key":"/testkey",'
- '"value":"test",'
- '"modifiedIndex":190}')
- result = '/testkey' in client
-
- self.assertEquals(True, result)
-
- def test_simple_watch(self):
- """ Can watch values """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"set",'
- '"key":"/testkey",'
- '"value":"test",'
- '"expiration":"2013-09-14T01:35:07.623681365+02:00",'
- '"ttl":19,'
- '"modifiedIndex":192}')
- result = client.watch('/testkey')
- self.assertEquals(
- etcd.EtcdResult(
- **{u'action': u'set',
- u'expiration': u'2013-09-14T01:35:07.623681365+02:00',
- u'modifiedIndex': 192,
- u'key': u'/testkey',
- u'ttl': 19,
- u'value': u'test'}), result)
-
- def test_index_watch(self):
- """ Can watch values from index """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"set",'
- '"key":"/testkey",'
- '"value":"test",'
- '"expiration":"2013-09-14T01:35:07.623681365+02:00",'
- '"ttl":19,'
- '"modifiedIndex":180}')
- result = client.watch('/testkey', index=180)
- self.assertEquals(
- etcd.EtcdResult(
- **{u'action': u'set',
- u'expiration': u'2013-09-14T01:35:07.623681365+02:00',
- u'modifiedIndex': 180,
- u'key': u'/testkey',
- u'ttl': 19,
- u'value': u'test'}), result)
-
-
-class TestEventGenerator(object):
- def check_watch(self, result):
- assert etcd.EtcdResult(
- **{u'action': u'set',
- u'expiration': u'2013-09-14T01:35:07.623681365+02:00',
- u'modifiedIndex': 180,
- u'key': u'/testkey',
- u'ttl': 19,
- u'value': u'test'}) == result
-
- def test_ethernal_watch(self):
- """ Can watch values from generator """
- client = etcd.Client()
- client.api_execute = mock.Mock(
- return_value=
- '{"action":"set",'
- '"key":"/testkey",'
- '"value":"test",'
- '"expiration":"2013-09-14T01:35:07.623681365+02:00",'
- '"ttl":19,'
- '"modifiedIndex":180}')
- for result in range(1, 5):
- result = client.ethernal_watch('/testkey', index=180).next()
- yield self.check_watch, result
-
-
-class FakeHTTPResponse(object):
- def __init__(self, status, data=''):
- self.status = status
- self.data = data
-
-
-class TestClientApiExecutor(unittest.TestCase):
-
- def test_get(self):
- """ http get request """
- client = etcd.Client()
- response = FakeHTTPResponse(status=200, data='arbitrary json data')
- client.http.request = mock.Mock(return_value=response)
- result = client.api_execute('/v2/keys/testkey', client._MGET)
- self.assertEquals('arbitrary json data', result)
-
- def test_delete(self):
- """ http delete request """
- client = etcd.Client()
- response = FakeHTTPResponse(status=200, data='arbitrary json data')
- client.http.request = mock.Mock(return_value=response)
- result = client.api_execute('/v2/keys/testkey', client._MDELETE)
- self.assertEquals('arbitrary json data', result)
-
- def test_get_error(self):
- """ http get error request 101"""
- client = etcd.Client()
- response = FakeHTTPResponse(status=400,
- data='{"message": "message",'
- ' "cause": "cause",'
- ' "errorCode": 100}')
- client.http.request = mock.Mock(return_value=response)
- try:
- client.api_execute('/v2/keys/testkey', client._MGET)
- assert False
- except KeyError, e:
- self.assertEquals(e.message, "message : cause")
-
- def test_put(self):
- """ http put request """
- client = etcd.Client()
- response = FakeHTTPResponse(status=200, data='arbitrary json data')
- client.http.request_encode_body = mock.Mock(return_value=response)
- result = client.api_execute('/v2/keys/testkey', client._MPUT)
- self.assertEquals('arbitrary json data', result)
-
- def test_test_and_set_error(self):
- """ http put error request 101 """
- client = etcd.Client()
- response = FakeHTTPResponse(
- status=400,
- data='{"message": "message", "cause": "cause", "errorCode": 101}')
- client.http.request_encode_body = mock.Mock(return_value=response)
- payload = {'value': 'value', 'prevValue': 'oldValue', 'ttl': '60'}
- try:
- client.api_execute('/v2/keys/testkey', client._MPUT, payload)
- self.fail()
- except ValueError, e:
- self.assertEquals('message : cause', e.message)
-
- def test_set_error(self):
- """ http put error request 102 """
- client = etcd.Client()
- response = FakeHTTPResponse(
- status=400,
- data='{"message": "message", "cause": "cause", "errorCode": 102}')
- client.http.request_encode_body = mock.Mock(return_value=response)
- payload = {'value': 'value', 'prevValue': 'oldValue', 'ttl': '60'}
- try:
- client.api_execute('/v2/keys/testkey', client._MPUT, payload)
- self.fail()
- except KeyError, e:
- self.assertEquals('message : cause', e.message)
-
- def test_set_error(self):
- """ http put error request 102 """
- client = etcd.Client()
- response = FakeHTTPResponse(
- status=400,
- data='{"message": "message", "cause": "cause", "errorCode": 102}')
- client.http.request_encode_body = mock.Mock(return_value=response)
- payload = {'value': 'value', 'prevValue': 'oldValue', 'ttl': '60'}
- try:
- client.api_execute('/v2/keys/testkey', client._MPUT, payload)
- self.fail()
- except KeyError, e:
- self.assertEquals('message : cause', e.message)
-
- def test_get_error_unknown(self):
- """ http get error request unknown """
- client = etcd.Client()
- response = FakeHTTPResponse(status=400,
- data='{"message": "message",'
- ' "cause": "cause",'
- ' "errorCode": 42}')
- client.http.request = mock.Mock(return_value=response)
- try:
- client.api_execute('/v2/keys/testkey', client._MGET)
- assert False
- except EtcdException, e:
- self.assertEquals(e.message, "Unable to decode server response")
-
- def test_get_error_request_invalid(self):
- """ http get error request invalid """
- client = etcd.Client()
- response = FakeHTTPResponse(status=200,
- data='{){){)*garbage*')
- client.http.request = mock.Mock(return_value=response)
- try:
- client.get('/testkey')
- assert False
- except EtcdException, e:
- self.assertEquals(e.message, "Unable to decode server response")
-
- def test_get_error_invalid(self):
- """ http get error request invalid """
- client = etcd.Client()
- response = FakeHTTPResponse(status=400,
- data='{){){)*garbage*')
- client.http.request = mock.Mock(return_value=response)
- try:
- client.api_execute('/v2/keys/testkey', client._MGET)
- assert False
- except ValueError, e:
- assert True