|
| 1 | +import asyncio |
1 | 2 | from datetime import datetime |
2 | 3 | from decimal import Decimal |
3 | 4 | from http import HTTPStatus |
|
26 | 27 | from sqlalchemy import delete, insert, select |
27 | 28 |
|
28 | 29 | from envoy.notification.task.transmit import HEADER_NOTIFICATION_ID |
| 30 | +from envoy.server.model.server import RuntimeServerConfig |
29 | 31 | from envoy.server.model.subscription import Subscription, SubscriptionResource |
30 | 32 | from envoy.server.model.tariff import PRICE_DECIMAL_POWER |
31 | 33 |
|
@@ -610,6 +612,55 @@ async def test_delete_site_with_active_subscription( |
610 | 612 | ), "Expected unique notification ids for each request" |
611 | 613 |
|
612 | 614 |
|
| 615 | +@pytest.mark.anyio |
| 616 | +async def test_update_server_config_edev_list_notification( |
| 617 | + admin_client_auth: AsyncClient, notifications_enabled: MockedAsyncClient, pg_base_config |
| 618 | +): |
| 619 | + """Tests that updating server config generates subscription notifications for EndDeviceList""" |
| 620 | + |
| 621 | + subscription1_uri = "http://my.example:542/uri" |
| 622 | + |
| 623 | + async with generate_async_session(pg_base_config) as session: |
| 624 | + # Clear any other subs first |
| 625 | + await session.execute(delete(Subscription)) |
| 626 | + |
| 627 | + # Will pickup site notifications |
| 628 | + await session.execute( |
| 629 | + insert(Subscription).values( |
| 630 | + aggregator_id=1, |
| 631 | + changed_time=datetime.now(), |
| 632 | + resource_type=SubscriptionResource.SITE, |
| 633 | + resource_id=None, |
| 634 | + scoped_site_id=None, |
| 635 | + notification_uri=subscription1_uri, |
| 636 | + entity_limit=10, |
| 637 | + ) |
| 638 | + ) |
| 639 | + await session.commit() |
| 640 | + |
| 641 | + # Update edev list config |
| 642 | + edev_list_poll_rate = 131009115 |
| 643 | + config_request = generate_class_instance( |
| 644 | + RuntimeServerConfigRequest, optional_is_none=True, edevl_pollrate_seconds=edev_list_poll_rate |
| 645 | + ) |
| 646 | + resp = await admin_client_auth.post(ServerConfigRuntimeUri, content=config_request.model_dump_json()) |
| 647 | + assert resp.status_code == HTTPStatus.NO_CONTENT |
| 648 | + |
| 649 | + # Give the notifications a chance to propagate |
| 650 | + assert await notifications_enabled.wait_for_n_requests(n=1, timeout_seconds=30) |
| 651 | + |
| 652 | + # Sub 1 got one notification, sub 2 got the other |
| 653 | + assert notifications_enabled.call_count_by_method[HTTPMethod.GET] == 0 |
| 654 | + assert notifications_enabled.call_count_by_method[HTTPMethod.POST] == 1 |
| 655 | + assert notifications_enabled.call_count_by_method_uri[(HTTPMethod.POST, subscription1_uri)] == 1 |
| 656 | + |
| 657 | + assert all([HEADER_NOTIFICATION_ID in r.headers for r in notifications_enabled.logged_requests]) |
| 658 | + assert len(set([r.headers[HEADER_NOTIFICATION_ID] for r in notifications_enabled.logged_requests])) == len( |
| 659 | + notifications_enabled.logged_requests |
| 660 | + ), "Expected unique notification ids for each request" |
| 661 | + assert f'pollRate="{edev_list_poll_rate}"' in notifications_enabled.logged_requests[0].content |
| 662 | + |
| 663 | + |
613 | 664 | @pytest.mark.anyio |
614 | 665 | async def test_update_server_config_fsa_notification( |
615 | 666 | admin_client_auth: AsyncClient, notifications_enabled: MockedAsyncClient, pg_base_config |
@@ -671,6 +722,68 @@ async def test_update_server_config_fsa_notification( |
671 | 722 | ), "Expected unique notification ids for each request" |
672 | 723 |
|
673 | 724 |
|
| 725 | +@pytest.mark.parametrize("none_fsa_value", [True, False]) |
| 726 | +@pytest.mark.anyio |
| 727 | +async def test_update_server_config_fsa_notification_no_change( |
| 728 | + admin_client_auth: AsyncClient, notifications_enabled: MockedAsyncClient, pg_base_config, none_fsa_value: bool |
| 729 | +): |
| 730 | + """Tests that updating server config (with no changed value for FSA) generates 0 notifications""" |
| 731 | + |
| 732 | + subscription1_uri = "http://my.example:542/uri" |
| 733 | + fsa_poll_rate = 123 |
| 734 | + |
| 735 | + async with generate_async_session(pg_base_config) as session: |
| 736 | + # Clear any other subs first |
| 737 | + await session.execute(delete(Subscription)) |
| 738 | + |
| 739 | + # Force the server FSA pollrate config to a known value |
| 740 | + await session.execute(delete(RuntimeServerConfig)) |
| 741 | + await session.execute( |
| 742 | + insert(RuntimeServerConfig).values( |
| 743 | + changed_time=datetime.now(), |
| 744 | + dcap_pollrate_seconds=None, |
| 745 | + edevl_pollrate_seconds=None, |
| 746 | + fsal_pollrate_seconds=fsa_poll_rate, |
| 747 | + derpl_pollrate_seconds=None, |
| 748 | + derl_pollrate_seconds=None, |
| 749 | + mup_postrate_seconds=None, |
| 750 | + site_control_pow10_encoding=None, |
| 751 | + disable_edev_registration=False, |
| 752 | + ) |
| 753 | + ) |
| 754 | + |
| 755 | + # Will pickup FSA notifications for site 2 |
| 756 | + await session.execute( |
| 757 | + insert(Subscription).values( |
| 758 | + aggregator_id=1, |
| 759 | + changed_time=datetime.now(), |
| 760 | + resource_type=SubscriptionResource.FUNCTION_SET_ASSIGNMENTS, |
| 761 | + resource_id=None, |
| 762 | + scoped_site_id=2, |
| 763 | + notification_uri=subscription1_uri, |
| 764 | + entity_limit=10, |
| 765 | + ) |
| 766 | + ) |
| 767 | + |
| 768 | + await session.commit() |
| 769 | + |
| 770 | + # Update config with the subscriptions now live |
| 771 | + config_request = generate_class_instance( |
| 772 | + RuntimeServerConfigRequest, |
| 773 | + optional_is_none=True, |
| 774 | + disable_edev_registration=True, |
| 775 | + fsal_pollrate_seconds=None if none_fsa_value else fsa_poll_rate, |
| 776 | + ) |
| 777 | + resp = await admin_client_auth.post(ServerConfigRuntimeUri, content=config_request.model_dump_json()) |
| 778 | + assert resp.status_code == HTTPStatus.NO_CONTENT |
| 779 | + |
| 780 | + # Give any notifications a chance to propagate |
| 781 | + await asyncio.sleep(3) |
| 782 | + |
| 783 | + # No notifications should've been generated as we aren't actually changing any values associated with the FSA |
| 784 | + assert len(notifications_enabled.logged_requests) == 0 |
| 785 | + |
| 786 | + |
674 | 787 | @pytest.mark.anyio |
675 | 788 | async def test_update_site_default_config_notification( |
676 | 789 | admin_client_auth: AsyncClient, notifications_enabled: MockedAsyncClient, pg_base_config |
|
0 commit comments