fix(020_13, 020_14): temporal pagination follows TS 104 176 clause 6.4.7.3

TS 104 176 clause 6.4.7.3, temporal pagination, on Retrieve Temporal Evolution of an Entity. The clause is new in TS 104, so the TCs are tagged since_ts104_v1.1.1. #97 held this back until the clause was published.

firstN and lastN are a page size per Attribute, per Entity. offsetN moves the page. The other pages are given by Link headers with the relations intervalafter and intervalbefore, whose URI-references carry offsetN.

  • 020_13: 10 TCs. lastN and firstN, with offsetN, with timerel before, after and between, temporalValues, the last page, a page that covers every instance, and firstN with lastN (400).
  • 020_14: unsynchronized Attributes paginate independently, each with its own page (2 TCs).
  • Retrieve Temporal Representation Of Entity and both Query Temporal Representation Of Entities keywords take firstN and offsetN. The documentation generator knows both parameters (doc/analysis/requests.py).
  • New checks in AssertionUtils, declared in doc/analysis/checks.py: Check Temporal Page Size, Check Temporal Pagination Link and Check Temporal Pagination Link Absent.

The Query side (021_15, 021_16) is the next MR, stacked on this one: it uses the same keywords.

12 TCs. All fail on develop and pass with this MR, against coraine. Doc unit tests 13/13, statisticsDocumentationData.py 0 of 607 failed, robocop format --check clean, robot --dryrun 12/12, no unused test data.

Fix MR 6 of the plan: https://famzang.com/ttf/ngsi-ld-suite-plan.html

Merge request reports

Loading
+76 −123
Changes for TP/NGSI-LD/ContextInformation/Consumption/TemporalEntity/QueryTemporalEvolutionOfEntities/021_15.robot: 76 added lines, 123 removed lines.
Original line number Diff line number Diff line
*** Settings ***
Documentation       Check temporal pagination is applied when querying the temporal evolution of entities
Documentation       Check that temporal pagination (TS 104-176, clause 6.4.7.3) is applied when querying the temporal evolution of entities

Library             DateTime
Resource            ${EXECDIR}/resources/ApiUtils/Common.resource
@@ -10,7 +10,7 @@ Resource ${EXECDIR}/resources/JsonUtils.resource

Suite Setup         Setup Initial Entities
Suite Teardown      Delete Initial Entities
Test Template       Retrieve Temporal Entities
Test Template       Query Temporal Entities With Pagination


*** Variables ***
@@ -18,49 +18,70 @@ ${first_vehicle_payload_file}= pagination/2020-01-vehicule-temporal-represe
${second_vehicle_payload_file}=     2020-09-vehicle-temporal-representation.jsonld
${timeBefore}=                      2019-01-01T01:01:00Z
${timeAfter}=                       2021-01-01T01:01:00Z
${lrt}=                             least recent timestamp
${mrt}=                             most recent timestamp


*** Test Cases ***
021_15_01 Retrieve The Entity With lastN And Timerel Before
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    lastN=${20}    expectedSize=20    timerel=before    timeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
021_15_02 Retrieve The Entity With lastN And Timerel Between
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    lastN=${20}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
021_15_03 Retrieve The Entity With lastN And Timerel After
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    lastN=${20}    expectedSize=20    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${mrt}    expectedRangeEnd=${lrt}
021_15_04 Retrieve The Entity With Timerel Before
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    timerel=before    expectedSize=*    timeAt=${timeAfter}    expectedRangeEnd=${mrt}
021_15_05 Retrieve The Entity With Timerel Between
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
021_15_06 Retrieve The Entity With Timerel After
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
021_15_07 Retrieve The Entity With temporalValues And Timerel After
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    representation=temporalValues    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
021_15_08 Retrieve The Entity With temporalValues, lastN And Timerel Between
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    since_v1.5.1
    representation=temporalValues    lastN=${20}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
021_15_01 Query With lastN Smaller Than The Available Instances
    [Documentation]    lastN paginates in descending order; the deeper page holds EARLIER timestamps → rel="intervalbefore"
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}
    ...    maxInstances=5    expectBeforeOffset=5
021_15_02 Query The Second Page With lastN And offsetN
    [Documentation]    A middle page carries both pointers
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    offsetN=${5}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}
    ...    maxInstances=5    expectBeforeOffset=10    expectAfterOffset=0
021_15_03 Query With firstN
    [Documentation]    firstN paginates in ascending order; the deeper page holds LATER timestamps → rel="intervalafter"
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    timerel=after    timeAt=${timeBefore}
    ...    maxInstances=5    expectAfterOffset=5
021_15_04 Query The Last Page With firstN And offsetN
    [Documentation]    Past the largest attribute's instance count only the backward pointer remains
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    offsetN=${18}    timerel=after    timeAt=${timeBefore}
    ...    maxInstances=2    expectBeforeOffset=13
021_15_05 Query With lastN Covering All Instances
    [Documentation]    Nothing remains beyond the page — no pagination pointers
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${20}    timerel=after    timeAt=${timeBefore}
    ...    maxInstances=20
021_15_06 Query With temporalValues And lastN
    [Documentation]    Pagination pointers are representation-independent
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    representation=temporalValues    lastN=${5}    timerel=after    timeAt=${timeBefore}
    ...    expectBeforeOffset=5
021_15_07 Query With Both firstN And lastN
    [Documentation]    Ascending and descending pagination at once is contradictory
    [Tags]    te-query    core_11_3_3    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    lastN=${5}    timerel=after    timeAt=${timeBefore}
    ...    expectedStatus=400
021_15_08 Query With limit And firstN
    [Documentation]    Both levels of pagination in one response: one Entity per page, so a pointer to the next page of
    ...    Entities (rel="next", clause 6.4.7.2), and two instances per Attribute, so a pointer to the next page of
    ...    instances (rel="intervalafter", clause 6.4.7.3) - both vehicles have more than two
    [Tags]    te-query    core_11_3_3    http_6_4_7_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${2}    limit=${1}    timerel=after    timeAt=${timeBefore}
    ...    maxInstances=2    expectAfterOffset=2    expectNext=${True}


*** Keywords ***
Retrieve Temporal Entities
    [Documentation]    Check temporal pagination behavior on multiple entity endpoint
Query Temporal Entities With Pagination
    [Documentation]    Query the temporal evolution of entities and check the § 6.4.7.3 pagination behaviour
    [Arguments]
    ...    ${representation}=${EMPTY}
    ...    ${timerel}=${EMPTY}
    ...    ${timeAt}=${EMPTY}
    ...    ${endTimeAt}=${EMPTY}
    ...    ${lastN}=${EMPTY}
    ...    ${expectedRangeStart}=${EMPTY}
    ...    ${expectedRangeEnd}=${EMPTY}
    ...    ${expectedSize}=${EMPTY}
    ...    ${firstN}=${EMPTY}
    ...    ${offsetN}=${EMPTY}
    ...    ${limit}=${EMPTY}
    ...    ${maxInstances}=${EMPTY}
    ...    ${expectAfterOffset}=${EMPTY}
    ...    ${expectBeforeOffset}=${EMPTY}
    ...    ${expectNext}=${False}
    ...    ${expectedStatus}=200
    ${entity_types_to_be_retrieved}=    Catenate    SEPARATOR=,    Vehicle

    ${response}=    Query Temporal Representation Of Entities
@@ -71,50 +92,35 @@ Retrieve Temporal Entities
    ...    timeAt=${timeAt}
    ...    endTimeAt=${endTimeAt}
    ...    lastN=${lastN}
    Check Response Status Code    206    ${response.status_code}

    ${contentRange}=    Get Regexp Matches
    ...    ${response.headers}[Content-Range]
    ...    ([a-zA-Z\-]+) (.*-.*-.*)-(.*-.*-.*)\/(.*)
    ...    1
    ...    2
    ...    3
    ...    4
    ${unit}=    Set Variable    ${contentRange}[0][0]
    ${rangeStart}=    Convert Date    ${contentRange}[0][1]
    ${rangeEnd}=    Convert Date    ${contentRange}[0][2]
    ${size}=    Set Variable    ${contentRange}[0][3]

    Check Content Range Part Equal    ${unit}    date-time

    IF    $expectedRangeStart != ''
        IF    $expectedRangeStart == $lrt
            ${expectedRangeStart}=    Get Least Recent Timestamp From Vehicles    ${response.json()}
        ELSE IF    $expectedRangeStart == $mrt
            ${expectedRangeStart}=    Get Most Recent Timestamp From Vehicles    ${response.json()}
    ...    firstN=${firstN}
    ...    offsetN=${offsetN}
    ...    limit=${limit}

    Check Response Status Code    ${expectedStatus}    ${response.status_code}
    IF    '${expectedStatus}' != '200'    RETURN

    IF    '${limit}' != ''    Length Should Be    ${response.json()}    ${limit}

    IF    ${expectNext}
        Check Pagination Link    ${response.headers}    next
    ELSE
            ${expectedRangeStart}=    Convert Date    ${expectedRangeStart}
        Check Pagination Link Absent    ${response.headers}    next
    END
        Check Content Range Part Equal    ${expectedRangeStart}    ${rangeStart}

    IF    '${maxInstances}' != '' and '${representation}' == ''
        Check Temporal Page Size    ${response.json()}    ${maxInstances}
    END

    IF    $expectedRangeEnd != ''
        IF    $expectedRangeEnd == $lrt
            ${expectedRangeEnd}=    Get Least Recent Timestamp From Vehicles
            ...    ${response.json()}
            ...    ${representation}
        ELSE IF    $expectedRangeEnd == $mrt
            ${expectedRangeEnd}=    Get Most Recent Timestamp From Vehicles
            ...    ${response.json()}
            ...    ${representation}
    IF    '${expectAfterOffset}' != ''
        Check Pagination Link    ${response.headers}    intervalafter    ${expectAfterOffset}
    ELSE
            ${expectedRangeEnd}=    Convert Date    ${expectedRangeEnd}
        END
        Check Content Range Part Equal    ${expectedRangeEnd}    ${rangeEnd}
        Check Pagination Link Absent    ${response.headers}    intervalafter
    END

    IF    $expectedSize != ''
        Check Content Range Part Equal    ${expectedSize}    ${size}
    IF    '${expectBeforeOffset}' != ''
        Check Pagination Link    ${response.headers}    intervalbefore    ${expectBeforeOffset}
    ELSE
        Check Pagination Link Absent    ${response.headers}    intervalbefore
    END

Setup Initial Entities
@@ -136,56 +142,3 @@ Setup Initial Entities
Delete Initial Entities
    Delete Temporal Representation Of Entity    ${first_temporal_entity_representation_id}
    Delete Temporal Representation Of Entity    ${second_temporal_entity_representation_id}

Get Least Recent Timestamp From Vehicles
    [Arguments]    ${body}    ${representation}=${EMPTY}

    ${attributeList}=    Get Attribute List From Vehicle Body    ${body}    ${representation}

    ${leastRecentTimestamp}=    Convert Date    ${timeAfter}
    FOR    ${attribute}    IN    @{attributeList}
        IF    $representation == 'temporalValues'
            ${attributeTime}=    Convert Date    ${attribute}[1]
        ELSE
            ${attributeTime}=    Convert Date    ${attribute}[observedAt]
        END

        IF    $leastRecentTimestamp >= $attributeTime
            ${leastRecentTimestamp}=    Set Variable    ${attributeTime}
        END
    END
    RETURN    ${leastRecentTimestamp}

Get Most Recent Timestamp From Vehicles
    [Arguments]    ${body}    ${representation}=${EMPTY}
    ${attributeList}=    Get Attribute List From Vehicle Body    ${body}    ${representation}

    ${mostRecentTimestamp}=    Convert Date    ${timeBefore}
    FOR    ${attribute}    IN    @{attributeList}
        IF    $representation == 'temporalValues'
            ${attributeTime}=    Convert Date    ${attribute}[1]
        ELSE
            ${attributeTime}=    Convert Date    ${attribute}[observedAt]
        END
        IF    $mostRecentTimestamp <= $attributeTime
            ${mostRecentTimestamp}=    Set Variable    ${attributeTime}
        END
    END
    RETURN    ${mostRecentTimestamp}

Get Attribute List From Vehicle Body
    [Arguments]    ${body}    ${representation}=${EMPTY}
    IF    $representation == 'temporalValues'
        ${attributeList}=    Combine Lists
        ...    ${body}[0][speed][values]
        ...    ${body}[0][fuelLevel][values]
        ...    ${body}[1][speed][values]
        ...    ${body}[1][fuelLevel][values]
    ELSE
        ${attributeList}=    Combine Lists
        ...    ${body}[0][speed]
        ...    ${body}[0][fuelLevel]
        ...    ${body}[1][speed]
        ...    ${body}[1][fuelLevel]
    END
    RETURN    ${attributeList}
+8 −15
Changes for TP/NGSI-LD/ContextInformation/Consumption/TemporalEntity/QueryTemporalEvolutionOfEntities/021_16.robot: 8 added lines, 15 removed lines.
Original line number Diff line number Diff line
*** Settings ***
Documentation       Check temporal pagination is applied when querying the temporal evolution of entities via POST
Documentation       Check that temporal pagination (TS 104-176, clause 6.4.7.3) is applied when querying the temporal evolution of entities via POST

Resource            ${EXECDIR}/resources/ApiUtils/Common.resource
Resource            ${EXECDIR}/resources/ApiUtils/TemporalContextInformationConsumption.resource
@@ -19,31 +19,24 @@ ${second_vehicle_payload_file}= 2020-09-vehicle-temporal-representation.json

*** Test Cases ***    PAYLOAD_FILE
021_16_01 Retrieve The Entities Via Post
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    http_8_7_3_1    since_v1.5.1
    entity-operations-before-query.jsonld
    [Tags]    te-retrieve    core_11_3_3    http_6_4_7_3    http_8_7_3_1    since_ts104_v1.1.1
    entity-operations-paginated-query.jsonld


*** Keywords ***
Retrieve Temporal Entities Via Post
    [Documentation]    Check that temporal pagination is triggered on the post temporal query
    [Documentation]    Check that temporal pagination (TS 104-176, clause 6.4.7.3) is triggered on the post temporal query
    [Arguments]    ${payload_file}

    ${response}=    Query Temporal Representation Of Entities Via Post
    ...    query_file_name=${payload_file}
    ...    context=${ngsild_test_suite_context}

    Check Response Status Code    206    ${response.status_code}
    Check Response Status Code    200    ${response.status_code}

    ${contentRange}=    Get Regexp Matches
    ...    ${response.headers}[Content-Range]
    ...    ([a-zA-Z\-]+) (.*-.*-.*)-(.*-.*-.*)\/(.*)
    ...    1
    ...    2
    ...    3
    ...    4
    ${unit}=    Set Variable    ${contentRange}[0][0]

    Check Content Range Part Equal    ${unit}    date-time
    # temporalQ.lastN=5 against a 20-instance fixture: instances remain
    # beyond the page in descending order → rel="intervalbefore" pointer.
    Check Pagination Link    ${response.headers}    intervalbefore    5

Setup Initial Entities
    ${first_temporal_entity_representation_id}=    Generate Random Vehicle Entity Id
+73 −121
Changes for TP/NGSI-LD/ContextInformation/Consumption/TemporalEntity/RetrieveTemporalEvolutionOfEntity/020_13.robot: 73 added lines, 121 removed lines.
Original line number Diff line number Diff line
*** Settings ***
Documentation       Check temporal pagination is applied when retrieving the temporal evolution of an entity
Documentation       Check that temporal pagination (TS 104-176, clause 6.4.7.3) is applied when retrieving the temporal evolution of an entity

Library             DateTime
Resource            ${EXECDIR}/resources/ApiUtils/Common.resource
@@ -10,62 +10,77 @@ Resource ${EXECDIR}/resources/JsonUtils.resource

Suite Setup         Create Temporal Entity
Suite Teardown      Delete Initial Temporal Entity
Test Template       Retrieve Temporal Entity
Test Template       Retrieve Temporal Entity With Pagination


*** Variables ***
${vehicle_payload_file}=    pagination/2020-01-vehicule-temporal-representation-twenty-instances.jsonld
${timeBefore}=              2019-01-01T01:01:00Z
${timeAfter}=               2021-01-01T01:01:00Z
${lrt}=                     least recent timestamp
${mrt}=                     most recent timestamp


*** Test Cases ***
020_13_01 Retrieve An Entity With 20 Instances On Two Attributes
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    ${EMPTY}    expectedSize=*    expectedRangeStart=${lrt}    expectedRangeEnd=${mrt}
020_13_02 Retrieve The Entity With lastN
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    lastN=${20}    expectedSize=20    expectedRangeStart=${mrt}    expectedRangeEnd=${lrt}
020_13_03 Retrieve The Entity With lastN And Timerel Before
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    lastN=${20}    expectedSize=20    timerel=before    timeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
020_13_04 Retrieve The Entity With lastN And Timerel Between
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    lastN=${20}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
020_13_05 Retrieve The Entity With lastN And Timerel After
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    lastN=${20}    expectedSize=20    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${mrt}    expectedRangeEnd=${lrt}
020_13_06 Retrieve The Entity With Timerel Before
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    timerel=before    expectedSize=*    timeAt=${timeAfter}    expectedRangeEnd=${mrt}
020_13_07 Retrieve The Entity With Timerel Between
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
020_13_08 Retrieve The Entity With Timerel After
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
020_13_09 Retrieve The Entity With temporalValues And Timerel After
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    representation=temporalValues    timerel=after    timeAt=${timeBefore}    expectedRangeStart=${timeBefore}    expectedRangeEnd=${mrt}
020_13_10 Retrieve The Entity With temporalValues, lastN And Timerel Between
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    representation=temporalValues    lastN=${20}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    expectedRangeStart=${timeAfter}    expectedRangeEnd=${lrt}
020_13_01 Retrieve The Entity With lastN Smaller Than The Available Instances
    [Documentation]    lastN paginates in descending order; the deeper page holds EARLIER timestamps → rel="intervalbefore"
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    maxInstances=5    expectBeforeOffset=5
020_13_02 Retrieve The Second Page With lastN And offsetN
    [Documentation]    A middle page carries both pointers
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    offsetN=${5}    maxInstances=5    expectBeforeOffset=10    expectAfterOffset=0
020_13_03 Retrieve The Entity With firstN
    [Documentation]    firstN paginates in ascending order; the deeper page holds LATER timestamps → rel="intervalafter"
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    maxInstances=5    expectAfterOffset=5
020_13_04 Retrieve The Last Page With firstN And offsetN
    [Documentation]    Past the attribute's instance count only the backward pointer remains
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    offsetN=${18}    maxInstances=2    expectBeforeOffset=13
020_13_05 Retrieve The Entity With lastN Covering All Instances
    [Documentation]    Nothing remains beyond the page — no pagination pointers
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${20}    maxInstances=20
020_13_06 Retrieve The Entity With lastN And Timerel Before
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    timerel=before    timeAt=${timeAfter}    maxInstances=5    expectBeforeOffset=5
020_13_07 Retrieve The Entity With lastN And Timerel Between
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${5}    timerel=between    timeAt=${timeBefore}    endTimeAt=${timeAfter}    maxInstances=5    expectBeforeOffset=5
020_13_08 Retrieve The Entity With firstN And Timerel After
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    timerel=after    timeAt=${timeBefore}    maxInstances=5    expectAfterOffset=5
020_13_09 Retrieve The Entity With temporalValues And lastN
    [Documentation]    Pagination pointers are representation-independent
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    representation=temporalValues    lastN=${5}    expectBeforeOffset=5
020_13_10 Retrieve The Entity With Both firstN And lastN
    [Documentation]    Ascending and descending pagination at once is contradictory
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${5}    lastN=${5}    expectedStatus=400
020_13_11 Retrieve The Entity Without firstN Or lastN
    [Documentation]    Neither firstN nor lastN: ascending order with the default maximum limit, which is implementation
    ...    specific (clause 6.4.7.3) - so a page of whatever size, in ascending order, and a rel="intervalafter" pointer
    ...    exactly when the default limit cut the 20 instances
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    timerel=after    timeAt=${timeBefore}    defaultLimit=${True}


*** Keywords ***
Retrieve Temporal Entity
    [Documentation]    Check temporal pagination behavior
Retrieve Temporal Entity With Pagination
    [Documentation]    Retrieve the temporal evolution of the entity and check the § 6.4.7.3 pagination behaviour
    [Arguments]
    ...    ${representation}=${EMPTY}
    ...    ${timerel}=${EMPTY}
    ...    ${timeAt}=${EMPTY}
    ...    ${endTimeAt}=${EMPTY}
    ...    ${lastN}=${EMPTY}
    ...    ${expectedRangeStart}=${EMPTY}
    ...    ${expectedRangeEnd}=${EMPTY}
    ...    ${expectedSize}=${EMPTY}
    ...    ${firstN}=${EMPTY}
    ...    ${offsetN}=${EMPTY}
    ...    ${maxInstances}=${EMPTY}
    ...    ${expectAfterOffset}=${EMPTY}
    ...    ${expectBeforeOffset}=${EMPTY}
    ...    ${expectedStatus}=200
    ...    ${defaultLimit}=${False}
    ${response}=    Retrieve Temporal Representation Of Entity
    ...    temporal_entity_representation_id=${temporal_entity_representation_id}
    ...    options=${representation}
@@ -74,50 +89,31 @@ Retrieve Temporal Entity
    ...    timeAt=${timeAt}
    ...    endTimeAt=${endTimeAt}
    ...    lastN=${lastN}
    Check Response Status Code    206    ${response.status_code}

    ${contentRange}=    Get Regexp Matches
    ...    ${response.headers}[Content-Range]
    ...    ([a-zA-Z\-]+) (.*-.*-.*)-(.*-.*-.*)\/(.*)
    ...    1
    ...    2
    ...    3
    ...    4
    ${unit}=    Set Variable    ${contentRange}[0][0]
    ${rangeStart}=    Convert Date    ${contentRange}[0][1]
    ${rangeEnd}=    Convert Date    ${contentRange}[0][2]
    ${size}=    Set Variable    ${contentRange}[0][3]

    Check Content Range Part Equal    ${unit}    date-time

    IF    $expectedRangeStart != ''
        IF    $expectedRangeStart == $lrt
            ${expectedRangeStart}=    Get Least Recent Timestamp From Vehicle Body    ${response.json()}
        ELSE IF    $expectedRangeStart == $mrt
            ${expectedRangeStart}=    Get Most Recent Timestamp From Vehicle Body    ${response.json()}
        ELSE
            ${expectedRangeStart}=    Convert Date    ${expectedRangeStart}
    ...    firstN=${firstN}
    ...    offsetN=${offsetN}

    Check Response Status Code    ${expectedStatus}    ${response.status_code}
    IF    '${expectedStatus}' != '200'    RETURN

    IF    '${maxInstances}' != '' and '${representation}' == ''
        Check Temporal Page Size    ${response.json()}    ${maxInstances}
    END
        Check Content Range Part Equal    ${expectedRangeStart}    ${rangeStart}

    IF    ${defaultLimit}
        Check Default Temporal Page    ${response}    ${20}
        RETURN
    END

    IF    $expectedRangeEnd != ''
        IF    $expectedRangeEnd == $lrt
            ${expectedRangeEnd}=    Get Least Recent Timestamp From Vehicle Body
            ...    ${response.json()}
            ...    ${representation}
        ELSE IF    $expectedRangeEnd == $mrt
            ${expectedRangeEnd}=    Get Most Recent Timestamp From Vehicle Body
            ...    ${response.json()}
            ...    ${representation}
    IF    '${expectAfterOffset}' != ''
        Check Pagination Link    ${response.headers}    intervalafter    ${expectAfterOffset}
    ELSE
            ${expectedRangeEnd}=    Convert Date    ${expectedRangeEnd}
        END
        Check Content Range Part Equal    ${expectedRangeEnd}    ${rangeEnd}
        Check Pagination Link Absent    ${response.headers}    intervalafter
    END

    IF    $expectedSize != ''
        Check Content Range Part Equal    ${expectedSize}    ${size}
    IF    '${expectBeforeOffset}' != ''
        Check Pagination Link    ${response.headers}    intervalbefore    ${expectBeforeOffset}
    ELSE
        Check Pagination Link Absent    ${response.headers}    intervalbefore
    END

Create Temporal Entity
@@ -131,47 +127,3 @@ Create Temporal Entity

Delete Initial Temporal Entity
    Delete Temporal Representation Of Entity    ${temporal_entity_representation_id}

Get Least Recent Timestamp From Vehicle Body
    [Arguments]    ${body}    ${representation}=${EMPTY}
    ${attributeList}=    Get Attribute List From Vehicle Body    ${body}    ${representation}

    ${leastRecentTimestamp}=    Convert Date    ${timeAfter}
    FOR    ${attribute}    IN    @{attributeList}
        IF    $representation == 'temporalValues'
            ${attributeTime}=    Convert Date    ${attribute}[1]
        ELSE
            ${attributeTime}=    Convert Date    ${attribute}[observedAt]
        END

        IF    $leastRecentTimestamp >= $attributeTime
            ${leastRecentTimestamp}=    Set Variable    ${attributeTime}
        END
    END
    RETURN    ${leastRecentTimestamp}

Get Most Recent Timestamp From Vehicle Body
    [Arguments]    ${body}    ${representation}=${EMPTY}
    ${attributeList}=    Get Attribute List From Vehicle Body    ${body}    ${representation}

    ${mostRecentTimestamp}=    Convert Date    ${timeBefore}
    FOR    ${attribute}    IN    @{attributeList}
        IF    $representation == 'temporalValues'
            ${attributeTime}=    Convert Date    ${attribute}[1]
        ELSE
            ${attributeTime}=    Convert Date    ${attribute}[observedAt]
        END
        IF    $mostRecentTimestamp <= $attributeTime
            ${mostRecentTimestamp}=    Set Variable    ${attributeTime}
        END
    END
    RETURN    ${mostRecentTimestamp}

Get Attribute List From Vehicle Body
    [Arguments]    ${body}    ${representation}=${EMPTY}
    IF    $representation == 'temporalValues'
        ${attributeList}=    Combine Lists    ${body}[speed][values]    ${body}[fuelLevel][values]
    ELSE
        ${attributeList}=    Combine Lists    ${body}[speed]    ${body}[fuelLevel]
    END
    RETURN    ${attributeList}
+18 −10
Changes for TP/NGSI-LD/ContextInformation/Consumption/TemporalEntity/RetrieveTemporalEvolutionOfEntity/020_14.robot: 18 added lines, 10 removed lines.
Original line number Diff line number Diff line
*** Settings ***
Documentation       Check that the time range cut before the second attribute to avoid missing data in content-range
Documentation       Check that unsynchronized attributes paginate independently (TS 104-176, clause 6.4.7.3: the page limit applies per Attribute)

Resource            ${EXECDIR}/resources/ApiUtils/Common.resource
Resource            ${EXECDIR}/resources/ApiUtils/TemporalContextInformationConsumption.resource
@@ -19,29 +19,37 @@ ${timeAfter}= 2021-01-01T01:01:00Z


*** Test Cases ***
020_14_01 Retrieve An Entity With 60 Instances Of Unsynchronized Attributes
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    timerel=after    timeAt=${timeBefore}    emptyAttr=fuelLevel
020_14_02 Retrieve The Entity With lastN
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_v1.5.1
    lastN=${100}    timerel=before    timeAt=${timeAfter}    emptyAttr=speed
020_14_01 Retrieve An Entity With Unsynchronized Attributes And firstN
    [Documentation]    Both attributes return their own first page even though their time ranges do not overlap
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    firstN=${30}    timerel=after    timeAt=${timeBefore}    expectedInstances=30
020_14_02 Retrieve An Entity With Unsynchronized Attributes And lastN
    [Documentation]    Both attributes return their own last page even though their time ranges do not overlap
    [Tags]    te-retrieve    core_11_3_2    http_6_4_7_3    since_ts104_v1.1.1
    lastN=${30}    timerel=before    timeAt=${timeAfter}    expectedInstances=30


*** Keywords ***
Retrieve Temporal Entity
    [Documentation]    Check that the time range cut before the second attribute
    [Documentation]    Check that the per-attribute page limit applies to each unsynchronized attribute independently
    [Arguments]
    ...    ${timerel}
    ...    ${timeAt}
    ...    ${emptyAttr}
    ...    ${expectedInstances}
    ...    ${lastN}=${EMPTY}
    ...    ${firstN}=${EMPTY}
    ${response}=    Retrieve Temporal Representation Of Entity
    ...    temporal_entity_representation_id=${temporal_entity_representation_id}
    ...    context=${ngsild_test_suite_context}
    ...    timerel=${timerel}
    ...    timeAt=${timeAt}
    ...    lastN=${lastN}
    Check Data Is Empty    ${response.json()}[${emptyAttr}]
    ...    firstN=${firstN}
    Check Response Status Code    200    ${response.status_code}
    ${speedCount}=    Get Length    ${response.json()}[speed]
    ${fuelCount}=    Get Length    ${response.json()}[fuelLevel]
    Should Be Equal As Integers    ${speedCount}    ${expectedInstances}
    Should Be Equal As Integers    ${fuelCount}    ${expectedInstances}

Create Temporal Entity
    ${temporal_entity_representation_id}=    Generate Random Vehicle Entity Id
+11 −0
Changes for data/temporalEntities/entity-operations-paginated-query.jsonld: 11 added lines, 0 removed lines.
Original line number Diff line number Diff line
{
    "type": "Query",
    "entities": [{
        "type": "Vehicle"
    }],
    "temporalQ": {
       "timerel":"before",
       "timeAt":"2020-08-02T12:05:00Z",
       "lastN": 5
    }
}
Loading
Loading