Commit c9fb8d43 authored by Konstantinos Togias's avatar Konstantinos Togias
Browse files

test: prove individual TI removal with the provider empty-list semantics

parent a75cd4dc
Loading
Loading
Loading
Loading
Loading
+9 −0
Changes for ansible/tests/r2_e2e/provider_observer.py: 9 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -29,3 +29,12 @@ def read_subscriptions(qod, http):
        if response.status_code == 200:
            subscriptions.append(response.json())
    return subscriptions


def ti_collection(response):
    """This EURECOM endpoint serializes an existing empty AF collection as null."""
    assert response.status_code == 200, 'TI collection observation failed'
    rows = response.json()
    assert rows is None or isinstance(rows, list), 'Unexpected TI collection shape'
    assert rows is None or all(isinstance(row, dict) for row in rows), 'Invalid TI collection entry'
    return rows or []
+12 −5
Changes for ansible/tests/r2_e2e/test_deploy_to_ti.py: 12 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ from uuid import uuid4
import pytest

from checkpoints import EURECOM_QOS_PROFILES
from provider_observer import read_subscriptions
from provider_observer import read_subscriptions, ti_collection
from qod_scenario import QodScenario, preflight as preflight_network
from conftest import EAM_SCOPES, INSTANCE_SCOPES, KeycloakAdmin, Token, http
from sdk_scenario import Scenario, check_endpoint_metadata, check_reachability, check_requested_resources, poll, preflight
@@ -256,7 +256,7 @@ def test_device_ti_uses_the_deployed_application_endpoint(progressive_scenario,p
    op,profile,token=progressive_scenario.operator,progressive_scenario.profile,progressive_scenario.token
    qod=profile['qod']
    base=qod['base_url']+'/3gpp-traffic-influence/v1/af/subscriptions'
    identity=None
    identity,backend_resource=None,None
    try:
        response=http('POST',op.oeg_url+'/traffic-influence/v0.10/traffic-influence-devices',token,json={
            'apiConsumerId':progressive_scenario.name,'appId':progressive_scenario.app_id,
@@ -274,9 +274,11 @@ def test_device_ti_uses_the_deployed_application_endpoint(progressive_scenario,p
        poll(active,profile['timeout_seconds'],'OEG device TI active')
        response=http('GET',base)
        assert response.status_code==200
        policies=[row for row in response.json() if row.get('afAppId')==progressive_scenario.app_id]
        policies=[row for row in ti_collection(response) if row.get('afAppId')==progressive_scenario.app_id]
        assert len(policies)==1
        policy=policies[0]
        backend_resource=base+'/'+policy['self'].rstrip('/').rsplit('/',1)[-1]
        assert http('GET',backend_resource).status_code==200, 'Observed TI identity is not readable'
        device_ip=qod['session_request']['device']['ipv4Address']['publicAddress']
        assert policy['ipv4Addr']==device_ip and not policy.get('anyUeInd')
        assert policy['notificationDestination']==qod['notification_url']
@@ -296,7 +298,12 @@ def test_device_ti_uses_the_deployed_application_endpoint(progressive_scenario,p
                public=http('GET',op.oeg_url+TI+'/'+identity,token)
                assert public.status_code in (200,404)
                backend=http('GET',base)
                assert backend.status_code==200
                rows=ti_collection(backend)
                if backend_resource:
                    individual=http('GET',backend_resource)
                    assert individual.status_code in (200,404)
                    if individual.status_code!=404:
                        return False
                return (public.status_code==404 or public.json()['state']=='deleted') and not any(
                    row.get('afAppId')==progressive_scenario.app_id for row in backend.json())
                    row.get('afAppId')==progressive_scenario.app_id for row in rows)
            poll(gone,profile['timeout_seconds'],'public TI and provider policy removal')
+12 −1
Changes for ansible/tests/unit/test_eurecom_lab.py: 12 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ ROOT=Path(__file__).resolve().parents[3]
sys.path.insert(0,str(ROOT/'ci'))
sys.path.insert(0,str(ROOT/'ansible/tests/r2_e2e'))
from eurecom_lab import SERVICES, composition
from provider_observer import read_subscriptions
from provider_observer import read_subscriptions, ti_collection
import provider_observer


@@ -69,3 +69,14 @@ def test_created_resource_without_valid_identity_cannot_look_like_an_empty_colle
    with pytest.raises(AssertionError):
        read_subscriptions({'base_url':'http://nef','subscriptions_url':'http://nef'+prefix,
                            'observer':{'container':'owned-ingress'}},None)


@pytest.mark.parametrize('body',[None,[],[{'self':'owned-policy'}]])
def test_ti_collection_preserves_real_provider_empty_and_nonempty_shapes(body):
    assert ti_collection(SimpleNamespace(status_code=200,json=lambda:body)) == (body or [])


@pytest.mark.parametrize('status,body',[(404,None),(200,{}),(200,[None])])
def test_ti_collection_error_or_malformed_body_cannot_prove_absence(status,body):
    with pytest.raises(AssertionError):
        ti_collection(SimpleNamespace(status_code=status,json=lambda:body))
+3 −1
Changes for ci/lab/README.md: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -164,7 +164,9 @@ transparent ingress log records only method, URI, status and upstream Location;
the observer follows actual successful creation identities and verifies their
individual deletion. Missing identities fail observation. No API payloads or
authorization headers are recorded. An initial TI collection GET may return404
before its AF exists. The lab callback route returns204, providing a reachable
before its AF exists, and an existing empty TI collection serializes as JSON
null. Cleanup requires 404 for the observed individual TI resource as well as
public removal; accepting an empty list alone cannot prove deletion. The lab callback route returns 204, providing a reachable
technical destination without implementing notifications in SRM or TF-SDK.

This compatibility tier qualifies API translation, selected provider behavior