diff options
author | Edi Feschiyan <edi.feschiyan@konsulko.com> | 2020-06-12 22:44:25 +0300 |
---|---|---|
committer | Edi Feschiyan <edi.feschiyan@konsulko.com> | 2020-06-12 22:44:25 +0300 |
commit | 8a8b87e65c0b3d579f8ea420e23a9cd07528dfe1 (patch) | |
tree | d5ced56f53104781bf156b38dbad7aba48578ca1 | |
parent | e2bb2d3ff3f909b9417040de4dd8ea876777a6ee (diff) |
Adding cookiecutter, preparing for setuptools, new services
-rw-r--r-- | README.md | 0 | ||||
-rw-r--r-- | services/audiomixer.py (renamed from audiomixer.py) | 0 | ||||
-rw-r--r-- | services/base.py (renamed from aglbaseservice.py) | 3 | ||||
-rw-r--r-- | services/bluetooth-map.py | 0 | ||||
-rw-r--r-- | services/bluetooth-pbap.py | 0 | ||||
-rw-r--r-- | services/bluetooth.py (renamed from bluetooth.py) | 3 | ||||
-rw-r--r-- | services/geoclue.py (renamed from geoclue.py) | 0 | ||||
-rw-r--r-- | services/gps.py (renamed from gps.py) | 0 | ||||
-rw-r--r-- | services/mediaplayer.py (renamed from mediaplayer.py) | 0 | ||||
-rw-r--r-- | services/network.py | 0 | ||||
-rw-r--r-- | services/nfc.py (renamed from nfc.py) | 0 | ||||
-rw-r--r-- | services/taskmanager.py | 0 | ||||
-rw-r--r-- | services/weather.py (renamed from weather.py) | 0 | ||||
-rw-r--r-- | setup.py | 0 | ||||
-rw-r--r-- | templates/service/cookiecutter.json | 6 | ||||
-rw-r--r-- | templates/service/{{cookiecutter.file_name}}.py | 9 | ||||
-rw-r--r-- | templates/test/{{cookiecutter.file_name}}.py | 0 | ||||
-rw-r--r-- | test_bluetooth.py | 50 | ||||
-rw-r--r-- | tests/test_bluetooth.py | 104 | ||||
-rw-r--r-- | tests/test_gps.py (renamed from test_gps.py) | 26 | ||||
-rw-r--r-- | tests/test_weather.py | 0 |
21 files changed, 145 insertions, 56 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/README.md diff --git a/audiomixer.py b/services/audiomixer.py index e594471..e594471 100644 --- a/audiomixer.py +++ b/services/audiomixer.py diff --git a/aglbaseservice.py b/services/base.py index 2146491..03d4793 100644 --- a/aglbaseservice.py +++ b/services/base.py @@ -241,6 +241,9 @@ class AGLBaseService: except Exception as e: self.logger.error("Unhandled seal: " + str(e)) + async def afbresponse(self): + return AFBResponse(await self.response()) + async def request(self, verb: str, values: Union[str, dict] = "", msgid: int = None): msgid = next(newrand()) if msgid is None else msgid l = json.dumps([AFBT.REQUEST, str(msgid), f'{self.api}/{verb}', values]) diff --git a/services/bluetooth-map.py b/services/bluetooth-map.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/services/bluetooth-map.py diff --git a/services/bluetooth-pbap.py b/services/bluetooth-pbap.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/services/bluetooth-pbap.py diff --git a/bluetooth.py b/services/bluetooth.py index 658d2e7..b73f8a8 100644 --- a/bluetooth.py +++ b/services/bluetooth.py @@ -64,6 +64,9 @@ class BluetoothService(AGLBaseService): async def confirm_pairing(self, pincode): return await self.request('confirm_pairing', {'pincode': pincode}) + async def remove_device(self, device): + return await self.request('remove_device', {'device': device}) + async def avrcp_controls(self): pass diff --git a/geoclue.py b/services/geoclue.py index df1afd6..df1afd6 100644 --- a/geoclue.py +++ b/services/geoclue.py diff --git a/mediaplayer.py b/services/mediaplayer.py index 9291981..9291981 100644 --- a/mediaplayer.py +++ b/services/mediaplayer.py diff --git a/services/network.py b/services/network.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/services/network.py diff --git a/services/taskmanager.py b/services/taskmanager.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/services/taskmanager.py diff --git a/weather.py b/services/weather.py index f3c02d0..f3c02d0 100644 --- a/weather.py +++ b/services/weather.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/setup.py diff --git a/templates/service/cookiecutter.json b/templates/service/cookiecutter.json new file mode 100644 index 0000000..f37ea1f --- /dev/null +++ b/templates/service/cookiecutter.json @@ -0,0 +1,6 @@ +{ + "aglsystemdservice": "agl-service-something", + "classname": "NewService", + "api": "serviceapi", + "verblist": ["subscribe", "unsubscribe"] +}
\ No newline at end of file diff --git a/templates/service/{{cookiecutter.file_name}}.py b/templates/service/{{cookiecutter.file_name}}.py new file mode 100644 index 0000000..6defd28 --- /dev/null +++ b/templates/service/{{cookiecutter.file_name}}.py @@ -0,0 +1,9 @@ +from aglbaseservice import AGLBaseService, AFBResponse +import asyncio +import os + +class {{cookiecutter.classname}}(AGLBaseService): + + def __init__(self, ip, port=None, service='{{cookiecutter.aglsystemdservice}}'): + super().__init__(api='{{cookiecutter.api}}', ip=ip, port=port, service=service) + diff --git a/templates/test/{{cookiecutter.file_name}}.py b/templates/test/{{cookiecutter.file_name}}.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/templates/test/{{cookiecutter.file_name}}.py diff --git a/test_bluetooth.py b/test_bluetooth.py deleted file mode 100644 index 1ccf499..0000000 --- a/test_bluetooth.py +++ /dev/null @@ -1,50 +0,0 @@ -import asyncio -import os -import pytest -from bluetooth import BluetoothService as BTS -import logging -from aglbaseservice import AFBResponse, AFBT - -logger = logging.getLogger(f'pytest-{BTS.service}') -logger.setLevel(logging.DEBUG) -pytestmark = pytest.mark.asyncio - - -@pytest.fixture(scope="module") -def event_loop(): - loop = asyncio.get_event_loop() - yield loop - loop.close() - - -@pytest.fixture(scope='module') -async def service(): - address = os.environ.get('AGL_TGT_IP', 'localhost') - port = os.environ.get('AGL_TGT_PORT', None) - - bts = await BTS(ip=address, port=port) - yield bts - await bts.websocket.close() - - -async def test_default_adapter(event_loop, service: BTS): - id = await service.default_adapter() - resp = AFBResponse(await service.response()) - assert resp.status == 'success', resp - assert 'adapter' in resp.data.keys() - assert resp.data['adapter'] == 'hci0' - - -async def test_managed_objects(event_loop, service: BTS): - id = await service.managed_objects() - resp = AFBResponse(await service.response()) - assert resp.status == 'success', str(resp) - - -async def test_has_single_adapter(event_loop, service: BTS): - id = await service.managed_objects() - resp = AFBResponse(await service.response()) - assert len(resp.data['adapters']) == 1, \ - f'Detected {len(resp.data["adapters"])} adapters. Multiple adapters may also break testing' - - diff --git a/tests/test_bluetooth.py b/tests/test_bluetooth.py new file mode 100644 index 0000000..d6b899e --- /dev/null +++ b/tests/test_bluetooth.py @@ -0,0 +1,104 @@ +import asyncio +import os +import pytest +from bluetooth import BluetoothService as BTS +import logging +from aglbaseservice import AFBResponse, AFBT + +logger = logging.getLogger(f'pytest-{BTS.service}') +logger.setLevel(logging.DEBUG) +pytestmark = pytest.mark.asyncio + + +@pytest.fixture(scope='module') +def event_loop(): + loop = asyncio.get_event_loop() + yield loop + loop.close() + + +@pytest.fixture(scope='module') +async def service(): + address = os.environ.get('AGL_TGT_IP', 'localhost') + port = os.environ.get('AGL_TGT_PORT', None) + + bts = await BTS(ip=address, port=port) + yield bts + await bts.websocket.close() + + +@pytest.mark.xfail +@pytest.fixture(scope='module') +def btaddr(): + bthtestaddr = os.environ.get('AGL_TEST_BT_ADDR', None) + if not bthtestaddr: + pytest.xfail('No test bluetooth test address set in environment variables') + + return bthtestaddr + + +@pytest.mark.dependency +async def test_default_adapter(event_loop, service: BTS): + id = await service.default_adapter() + resp = AFBResponse(await service.response()) + assert resp.status == 'success', resp + assert 'adapter' in resp.data.keys() + assert resp.data['adapter'] == 'hci0' + + +@pytest.mark.dependency(depends=['test_default_adapter']) +async def test_managed_objects(event_loop, service: BTS): + id = await service.managed_objects() + resp = AFBResponse(await service.response()) + assert resp.status == 'success', str(resp) + + +@pytest.mark.dependency(depends=['test_default_adapter']) +async def test_has_single_adapter(event_loop, service: BTS): + id = await service.managed_objects() + resp = AFBResponse(await service.response()) + assert len(resp.data['adapters']) == 1, \ + f'Detected {len(resp.data["adapters"])} adapters. Multiple adapters may also break testing' + + +@pytest.mark.dependency(depends=['test_default_adapter']) +async def test_adapter_state(event_loop, service: BTS): + id = await service.adapter_state('hci0') + resp = AFBResponse(await service.response()) + assert resp.status == 'success', 'adapter state verb failed' + + +async def test_pairing_verb(event_loop, service: BTS, btaddr): + id = await service.pair(btaddr) + resp = await service.afbresponse() + assert id == resp.msgid + assert resp.status == 'success', f'pair verb failed - {resp.info}' + + +async def test_connect_verb(event_loop, service: BTS, btaddr): + id = await service.connect(btaddr) + resp = await service.afbresponse() + assert id == resp.msgid + assert resp.status == 'success', f'connect verb failed - {resp.info}' + + +async def test_disconnect_verb(event_loop, service: BTS, btaddr): + id = await service.disconnect(btaddr) + resp = await service.afbresponse() + assert id == resp.msgid + assert resp.status == 'success', f'disconnect verb failed - {resp.info}' + + +async def test_remove_pairing_verb(event_loop, service: BTS, btaddr): + id = await service.remove_device(btaddr) + resp = await service.afbresponse() + assert id == resp.msgid + assert resp.status == 'success' + + +@pytest.mark.xfail(reason='This is expected to fail because there has to be an ongoing pairing attempt') +async def test_confirm_pairing_verb(event_loop, service: BTS, btaddr): + id = await service.confirm_pairing(pincode='123456') + resp = await service.afbresponse() + assert id == resp.msgid + assert resp.status == 'success', f'confirm_pairing verb failed - {resp.info}' diff --git a/test_gps.py b/tests/test_gps.py index e1ad15e..2e62405 100644 --- a/test_gps.py +++ b/tests/test_gps.py @@ -4,12 +4,13 @@ import pytest from gps import GPSService as GPS import logging from aglbaseservice import AFBResponse, AFBT +from concurrent.futures import TimeoutError logger = logging.getLogger('pytest-gps') logger.setLevel(logging.DEBUG) pytestmark = pytest.mark.asyncio -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def event_loop(): loop = asyncio.get_event_loop() yield loop @@ -18,7 +19,8 @@ def event_loop(): @pytest.fixture(scope='module') async def service(): address = os.environ.get('AGL_TGT_IP', 'localhost') - gpss = await GPS(ip=address) + port = os.environ.get('AGL_TGT_PORT', None) + gpss = await GPS(ip=address, port=port) yield gpss await gpss.websocket.close() @@ -27,12 +29,19 @@ async def service(): # async for _response in service.listener(): # yield _response +async def test_location_verb(event_loop, service: GPS): + id = await service.location() + resp = AFBResponse(await service.response()) + assert resp.msgid == id + @pytest.mark.xfail # expecting this to fail because of "No 3D GNSS fix" and GPS is unavailable -async def test_location(event_loop, service: GPS): +async def test_location_result(event_loop, service: GPS): id = await service.location() resp = AFBResponse(await service.response()) assert resp.status == 'success' + + async def test_subscribe_location(event_loop, service: GPS): id = await service.subscribe('location') resp = AFBResponse(await service.response()) @@ -45,13 +54,18 @@ async def test_unsubscribe(event_loop, service: GPS): assert resp.msgid == id assert resp.status == 'success' +@pytest.mark.xfail # expecting this to fail because of "No 3D GNSS fix" and GPS is unavailable async def test_location_events(event_loop, service: GPS): id = await service.subscribe('location') resp = AFBResponse(await service.response()) assert resp.msgid == id assert resp.status == 'success' # successful subscription + try: + resp = await asyncio.wait_for(service.response(), 10) + resp = AFBResponse(resp) + assert resp.type == AFBT.EVENT, f'Expected EVENT response, got {resp.type.name} instead' + # TODO one more assert for the actual received event, haven't received a location event yet + except TimeoutError: + pytest.xfail("Did not receive location event") - resp = await asyncio.wait_for(service.response(), 10) - resp = AFBResponse(resp) - assert resp.type == AFBT.EVENT, f'Expected EVENT response, got {resp.type.name} instead' diff --git a/tests/test_weather.py b/tests/test_weather.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/test_weather.py |