Commit 28cbacc8 authored by kzangeli's avatar kzangeli Committed by Ken Zangelin
Browse files

fix: 038_02_01 Location parsing + 038_08_03 actually-invalid q

038_02_01 stored the raw Location header as the subscription id;
Location is a URI reference (RFC 9110 § 10.2.2) carrying the resource
path, so the follow-up retrieve and the teardown delete built doubled
URLs and failed — leaking the created subscription into the 041_*
count assertions. The id is now the last path segment, and the
retrieve comparison ignores the clause-12.4.7 Additional Members
(root level and inside 'notification') like its 038_01/038_03
siblings.

038_08_03's fixture used "q": "invalidQuery" — a bare attribute
path, which the § 7.x ABNF (QueryTerm = Attribute) makes a VALID
existence-predicate query that brokers must accept with 201. The
fixture now sends "(invalidQuery" (unbalanced parenthesis), the same
genuinely-invalid form 037_03_02 uses.

The notification_result_regex_expr variable and the assertionUtils.py
threshold_to_diff_deeper=0 fix are re-declared identically to their
origin branch (unmerged MR) — git deduplicates on merge.

Analysis recorded as testsuite-doubts.md #96.
parent 6cc051e7
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -22,7 +22,10 @@ ${subscription_id}= ${EMPTY}
    ${response}=    Create Context Source Registration Subscription    ${subscription_payload}

    Dictionary Should Contain Key    ${response.headers}    Location    msg=HTTP Headers do not contain key 'Location'
    ${subscription_id}=    Get From Dictionary    ${response.headers}    Location
    ${location}=    Get From Dictionary    ${response.headers}    Location
    # Location is a URI reference (RFC 9110 § 10.2.2) — typically the resource
    # path /ngsi-ld/v1/csourceSubscriptions/<id>. Extract the generated id.
    ${subscription_id}=    Fetch From Right    ${location}    /
    Set Suite Variable    ${subscription_id}

    Check Response Status Code    201    ${response.status_code}
@@ -32,7 +35,18 @@ ${subscription_id}= ${EMPTY}
    ...    subscription_id=${subscription_id}
    ...    context=${ngsild_test_suite_context}
    ...    accept=${CONTENT_TYPE_LD_JSON}
    ${ignored_attributes}=    Create List    ${id_regex_expr}    ${status_regex_expr}
    # Ignore the Additional Members ('lastFailure', 'lastNotification', 'timesFailed',
    # 'timesSent', 'status'), 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
    ...    ${id_regex_expr}
    ...    ${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}


+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@
         "type":"Building"
      }
   ],
   "q": "invalidQuery",
   "q": "(invalidQuery",
   "notification":{
      "format":"keyValues",
      "endpoint":{
+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(),
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ ${lastNotification_regex_expr}= root\\['lastNotification'\\]
${timesFailed_regex_expr}=                  root\\['timesFailed'\\]
${timesSent_regex_expr}=                    root\\['timesSent'\\]
${is_active_expr}=                          root\\['isActive'\\]
${notification_result_regex_expr}=          \\['notification'\\]\\['(lastNotification|lastSuccess|lastFailure|timesSent|timesFailed|status)'\\]
${context_source_ignored_regex_expr}=       root\\['@context'\\]