Commit 1d2d62ca authored by kzangeli's avatar kzangeli
Browse files

fix: csub status checks broken by the mandatory initial notification (clause 12.4.7)

Per TS 104-175 clause 12.4.7 an initial notification is sent unconditionally upon
csource subscription creation. The csub fixtures point at an unreachable endpoint
(http://localhost:1111/notify), so a compliant broker may legitimately report
status 'failed' (and live counters inside 'notification') right after create:

- 038_03 / 038_06: the status assertion now accepts 'active' or 'failed' (the
  tests' intent — not 'paused' / not 'expired' — is preserved). New keyword
  'Check Response Body Containing an Attribute set to one of'.
- 038_01 / 040_01: ignore the broker-computed Additional Members of
  NotificationParams (clause 5.2.14.2) nested under 'notification', as the
  entity-subscription twins (028_01, 030_03) already do.
- assertionUtils.py: pass threshold_to_diff_deeper=0 to DeepDiff. Since
  deepdiff 8, when more than 1/3 of a dict's keys differ the whole dict is
  reported as changed instead of descending, silently bypassing
  exclude_regex_paths that target the nested keys.
parent d9a20233
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -28,13 +28,16 @@ ${subscription_payload_file_path}= csourceSubscriptions/subscription.jsonld
    ...    context=${ngsild_test_suite_context}
    ...    accept=${CONTENT_TYPE_LD_JSON}

    # One needs to ignore the Additional Members ('lastFailure', 'lastNotification', 'timesFailed', 'timesSent')
    # One needs to ignore the Additional Members ('lastFailure', 'lastNotification', 'timesFailed', 'timesSent'),
    # both at root level and inside 'notification' (clause 5.2.14), where they may have been
    # set already by the initial notification sent upon subscription creation (clause 12.4.7).
    ${ignored_attributes}=    Create List
    ...    ${status_regex_expr}
    ...    ${lastfailure_regex_expr}
    ...    ${lastNotification_regex_expr}
    ...    ${timesFailed_regex_expr}
    ...    ${timesSent_regex_expr}
    ...    ${notification_result_regex_expr}

    Check Created Resource Set To    ${subscription_payload}    ${response1.json()}    ${ignored_attributes}

+10 −4
Original line number Diff line number Diff line
@@ -25,10 +25,16 @@ ${subscription_payload_file_path}= csourceSubscriptions/subscription.jsonld
    Check Response Headers Containing URI set to    ${subscription_id}    ${response.headers}
    ${response1}=    Retrieve Context Source Registration Subscription
    ...    subscription_id=${subscription_id}
    Check Response Body Containing an Attribute set to
    ...    expected_attribute_name=status
    ...    response_body=${response1.json()}
    ...    expected_attribute_value=active
    # The subscription was not created with isActive=false, so its status must not be
    # "paused" (nor "expired"). It cannot be pinned to exactly "active": per clause 12.4.7
    # an initial notification is sent upon subscription creation, and as the fixture's
    # endpoint (http://localhost:1111/notify) is unreachable, a compliant broker may
    # already report "failed" by the time the subscription is retrieved.
    Check Response Body Containing an Attribute set to one of
    ...    status
    ...    ${response1.json()}
    ...    active
    ...    failed


*** Keywords ***
+10 −4
Original line number Diff line number Diff line
@@ -27,10 +27,16 @@ ${subscription_payload_file_path}= csourceSubscriptions/subscription.jsonld
    Sleep    10s
    ${response1}=    Retrieve Context Source Registration Subscription
    ...    subscription_id=${subscription_id}
    Check Response Body Containing an Attribute set to
    ...    expected_attribute_name=status
    ...    response_body=${response1.json()}
    ...    expected_attribute_value=active
    # Without expiresAt the subscription is perpetual, so its status must not be
    # "expired" (nor "paused"). It cannot be pinned to exactly "active": per clause 12.4.7
    # an initial notification is sent upon subscription creation, and as the fixture's
    # endpoint (http://localhost:1111/notify) is unreachable, a compliant broker may
    # already report "failed" by the time the subscription is retrieved.
    Check Response Body Containing an Attribute set to one of
    ...    status
    ...    ${response1.json()}
    ...    active
    ...    failed


*** Keywords ***
+4 −1
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ ${expectation_file_path}= csourceSubscriptions/expectations/subscr

    ${expectation_payload}=    Load Test Sample    ${expectation_file_path}    ${subscription_id}

    # One needs to ignore the Additional Members ('lastFailure', 'lastNotification', 'timesFailed', 'timesSent', 'isActive')
    # One needs to ignore the Additional Members ('lastFailure', 'lastNotification', 'timesFailed', 'timesSent', 'isActive'),
    # both at root level and inside 'notification' (clause 5.2.14), where they may have been
    # set already by the initial notification sent upon subscription creation (clause 12.4.7).
    ${ignored_attributes}=    Create List
    ...    ${status_regex_expr}
    ...    ${lastfailure_regex_expr}
@@ -41,6 +43,7 @@ ${expectation_file_path}= csourceSubscriptions/expectations/subscr
    ...    ${timesFailed_regex_expr}
    ...    ${timesSent_regex_expr}
    ...    ${is_active_expr}
    ...    ${notification_result_regex_expr}

    Check Created Resource Set To
    ...    created_resource=${expectation_payload}
+9 −0
Original line number Diff line number Diff line
@@ -98,10 +98,16 @@ def compare_dictionaries_ignoring_keys(expected, actual, exclude_regex_paths, ig
    :param exclude_regex_paths: list of regex paths of keys to be ignored
    :param ignore_core_context_version: whether any core context version is allowed in the results
    :param group_by: a key to group the results, useful for lists of results

    threshold_to_diff_deeper=0: since deepdiff 8, when more than 1/3 of a dict's keys
    differ, DeepDiff reports the whole dict as changed instead of descending into it,
    which silently bypasses exclude_regex_paths targeting the nested keys (e.g. the
    broker-computed Additional Members inside 'notification'). 0 restores per-key diffs.
    """

    if group_by is not None and ignore_core_context_version:
        res = DeepDiff(expected, actual, exclude_regex_paths=exclude_regex_paths, ignore_order=True, verbose_level=1,
                       threshold_to_diff_deeper=0,
                       iterable_compare_func=compare_func,
                       custom_operators=[
                           AnyCoreContextVersionOperator(),
@@ -111,6 +117,7 @@ def compare_dictionaries_ignoring_keys(expected, actual, exclude_regex_paths, ig
                       group_by=group_by)
    elif group_by is not None:
        res = DeepDiff(expected, actual, exclude_regex_paths=exclude_regex_paths, ignore_order=True, verbose_level=1,
                       threshold_to_diff_deeper=0,
                       iterable_compare_func=compare_func,
                       custom_operators=[
                           StringOrSingleListContextOperator(),
@@ -120,6 +127,7 @@ def compare_dictionaries_ignoring_keys(expected, actual, exclude_regex_paths, ig
                       group_by=group_by)
    elif ignore_core_context_version:
        res = DeepDiff(expected, actual, exclude_regex_paths=exclude_regex_paths, ignore_order=True, verbose_level=1,
                       threshold_to_diff_deeper=0,
                       iterable_compare_func=compare_func,
                       custom_operators=[
                           AnyCoreContextVersionOperator(),
@@ -128,6 +136,7 @@ def compare_dictionaries_ignoring_keys(expected, actual, exclude_regex_paths, ig
                       ])
    else:
        res = DeepDiff(expected, actual, exclude_regex_paths=exclude_regex_paths, ignore_order=True, verbose_level=1,
                       threshold_to_diff_deeper=0,
                       iterable_compare_func=compare_func,
                       custom_operators=[
                           StringOrSingleListContextOperator(),
Loading