phi/async_tests/test_async_ldap_model.py

197 lines
4.9 KiB
Python
Raw Normal View History

2019-06-30 21:16:48 +02:00
# -*- encoding: utf-8 -*-
2019-04-19 15:56:12 +02:00
import asyncio
from async_generator import asynccontextmanager
from bonsai import LDAPEntry
import mock
2019-04-19 15:56:12 +02:00
import pytest
from phi.async_ldap.model import get_dn, User
from phi.async_ldap.mixins import Member
from phi.exceptions import PhiCannotExecute
2019-04-19 15:56:12 +02:00
BASE_DN = "dc=test,dc=domain,dc=tld"
2019-04-19 15:56:12 +02:00
class MockClient(object):
def __init__(self, *args, **kwargs):
self.return_value = kwargs.get("return_value")
self.connect_called = False
self.conn = mock.MagicMock()
self.search_event = asyncio.Event()
self.add_event = asyncio.Event()
self.delete_event = asyncio.Event()
2019-04-19 15:56:12 +02:00
async def connect_called_with_search(self):
return await self.search_event.wait()
2019-04-19 15:56:12 +02:00
async def connect_called_with_add(self):
return await self.add_event.wait()
2019-04-19 15:56:12 +02:00
async def connect_called_with_delete(self):
return await self.delete_event.wait()
2019-04-19 15:56:12 +02:00
@property
def base_dn(self):
return BASE_DN
2019-04-19 15:56:12 +02:00
@asynccontextmanager
async def connect(self, *args, **kwargs):
self.connect_called = True
2019-04-19 15:56:12 +02:00
async def _search(*a, **kw):
self.search_event.set()
return self.return_value
2019-04-19 15:56:12 +02:00
async def _add(*a, **kw):
self.add_event.set()
return self.return_value
2019-04-19 15:56:12 +02:00
async def _modify(*a, **kw):
return self.return_value
async def _delete(*a, **kw):
self.delete_event.set()
return self.return_value
self.conn.search = mock.MagicMock(side_effect=_search)
self.conn.add = mock.MagicMock(side_effect=_add)
self.conn.modify = mock.MagicMock(side_effect=_modify)
self.conn.delete = mock.MagicMock(side_effect=_delete)
yield self.conn
cl = mock.MagicMock()
cl.base_dn = BASE_DN
2019-04-19 15:56:12 +02:00
@pytest.mark.parametrize(
"input_obj, expected_result",
[
(User(cl, "test_user"), f"uid=test_user,ou=Hackers,{BASE_DN}"),
(
LDAPEntry(f"uid=test_user,ou=Hackers,{BASE_DN}"),
f"uid=test_user,ou=Hackers,{BASE_DN}",
),
(f"uid=test_user,ou=Hackers,{BASE_DN}", f"uid=test_user,ou=Hackers,{BASE_DN}"),
],
)
def test_get_dn(input_obj, expected_result):
assert get_dn(input_obj) == expected_result
def test_get_dn_raises():
with pytest.raises(ValueError) as e:
_ = get_dn(object)
assert "Unacceptable input:" in str(e.value)
def test_repr():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
2019-04-19 15:56:12 +02:00
assert repr(u) == f"<User uid=test_user,ou=Hackers,{BASE_DN}>"
def test_str():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
2019-07-01 22:37:56 +02:00
assert str(u) == f"<User uid=test_user,ou=Hackers,{BASE_DN}>"
2019-07-01 22:37:56 +02:00
@pytest.mark.parametrize(
"input_obj",
[
User(cl, "test_user"),
LDAPEntry(f"uid=test_user,ou=Hackers,{BASE_DN}"),
f"uid=test_user,ou=Hackers,{BASE_DN}",
],
)
def test_eq(input_obj):
u = User(cl, "test_user")
assert u == input_obj
@pytest.mark.asyncio
async def test_User_add():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
assert u.dn == f"uid=test_user,ou=Hackers,{BASE_DN}"
_ = await u.save()
2019-04-19 15:56:12 +02:00
assert _cl.connect_called
assert await _cl.connect_called_with_add()
2019-04-19 15:56:12 +02:00
2019-06-30 21:24:55 +02:00
@pytest.mark.asyncio
async def test_User_modify():
"""
This test does not use the MockClient check facilities because
of implementation details of the Entry class.
"""
_cl = MockClient(
return_value=[
LDAPEntry(f"uid=test_user,ou=Hackers,{BASE_DN}"),
]
)
u = User(_cl, "test_user")
2019-06-30 21:24:55 +02:00
# This is the asyncio equivalent of a semaphore
modified = asyncio.Event()
2019-06-30 21:24:55 +02:00
async def _mock_modify():
modified.set()
2019-06-30 21:24:55 +02:00
u._entry = mock.MagicMock()
u._entry.modify = mock.MagicMock(side_effect=_mock_modify)
2019-04-19 15:56:12 +02:00
u["cn"] = "random_cn"
_ = await u.modify()
assert _cl.connect_called
assert await _cl.connect_called_with_search()
# The `wait()` call here is needed to wait for `_mock_modify`
# to end its async execution
assert await modified.wait()
2019-07-01 22:37:56 +02:00
@pytest.mark.asyncio
async def test_User_delete():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
_ = await u.delete()
assert _cl.connect_called
assert await _cl.connect_called_with_delete()
2019-07-01 22:37:56 +02:00
@pytest.mark.asyncio
async def test_User_get_invalid_attr_raises():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
with pytest.raises(PhiCannotExecute) as ex:
_ = u["iDoNotExist"]
assert "iDoNotExist" in str(ex.value)
assert "is not an allowed ldap attribute" in str(ex.value)
2019-04-19 15:56:12 +02:00
2019-07-06 21:26:21 +02:00
@pytest.mark.asyncio
async def test_User_set_invalid_attr_raises():
_cl = MockClient(return_value=None)
u = User(_cl, "test_user")
2019-07-01 22:48:04 +02:00
with pytest.raises(PhiCannotExecute) as ex:
u["iDoNotExist"] = "hello"
assert "iDoNotExist" in str(ex.value)
assert "is not an allowed ldap attribute" in str(ex.value)