Commit b638e4a7 authored by kzangeli's avatar kzangeli
Browse files

Merge origin/develop into integration/all-fixes

Resolved keeping this branch's authored fixes (jsonldContext suite-scope
comments, DeleteEntity 002_02 cases, CSR resource arg) over develop's cleanup
removals; develop's new TPs (Purge Entities, IOP-case Create/Query, multivalued
relationships, NGSI-LD Nulls, objectType-on-relationship) merged in.
testsuite-doubts.md removed from git tracking but kept locally (gitignored).
parents 86ec956d 69c243df
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -5,3 +5,4 @@ results
.vscode/
.venv
.DS_Store
testsuite-doubts.md
+1 −1
Original line number Diff line number Diff line
@@ -3,4 +3,4 @@ repos:
    rev: v6.9.2
    hooks:
      - id: robocop-format
        additional_dependencies: [typing_extensions]
        additional_dependencies: [typing_extensions, click]
+29 −35
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@ Thank you for contributing! This document explains the conventions and rules all
  - [Keywords](#keywords)
  - [Test data files](#test-data-files)
- [Updating the documentation](#updating-the-documentation)
- [Running the unit tests](#running-the-unit-tests)
- [Self-review checklist](#self-review-checklist)

---
@@ -51,7 +50,7 @@ This project uses **[Conventional Commits](https://www.conventionalcommits.org/)
| `chore`    | Tooling, configuration, dependencies, CI/CD changes         |
| `refactor` | Internal restructuring with no behaviour change             |
| `docs`     | Documentation-only changes                                  |
| `test`     | Changes to the unit test suite under `doc/tests/`           |
| `test`     | Changes to the documentation generation tooling under `doc/`|

The scope (in parentheses) is optional but encouraged when the change is limited to a specific API group or
subsystem, e.g. `feat(subscription)`, `fix(temporal)`, `chore(robocop)`.
@@ -187,30 +186,39 @@ python3 scripts/find_unused_test_data.py

## Updating the documentation

The test suite ships with an auto-generated documentation system. Changes that affect the documentation must be
accompanied by the appropriate updates.
The test suite ships with an auto-generated documentation system that produces the deliverable listing every
Test Case of the Test Suite. The documentation is regenerated when a new version of the deliverable is needed:

**When a new Test Case is created:**

1. Declare it in `doc/tests/test_{group}.py`.
2. Run the documentation generator for the new TC:
   ```bash
   python doc/generateDocumentationData.py {new_tc_id}
   ```
3. Copy the generated file to the correct group folder:
```bash
   cp doc/results/{new_tc_id}.json doc/files/{group}/{subgroup}/
cd doc ; python statisticsDocumentationData.py
```
4. Update `doc/analysis/initial_setup.py` if a new setup keyword was introduced.
5. Update `doc/analysis/requests.py` if a new request parameter or endpoint was added.

**When a new permutation is added to an existing Test Case:**
This walks every `.robot` file and reports how many Test Cases failed to be parsed. The documentation is
considered healthy when it reports **`0` failures**. Run it after any change that could affect generation — and
between deliveries — to confirm the documentation still generates successfully and that no drift was introduced.

> **Note:** the per-Test-Case JSON files are **no longer versioned**. There is no manual "copy the generated
> JSON into `doc/files/`" step anymore: the generator writes to `doc/results/` (git-ignored), which is
> overwritten on each run. As a result, legitimate changes to a Test Case (adding/removing a tag, rewording its
> documentation, …) require no committed JSON update and never fail documentation generation.

Run the documentation generator for the affected TC and copy the output, as above.
For generation to keep succeeding, keep the following declarations in sync with the `.robot` files:

**When a new directory of Test Cases is created:**
- **New assertion keyword** — declare it in `doc/analysis/checks.py` (`self.checks` and `self.args`) with a
  method that returns its documentation string.
- **New endpoint keyword** — declare it in `doc/analysis/requests.py` (`self.op` and `self.description`) with
  its documentation method.
- **New request/query parameter** on an existing endpoint — add it to that endpoint's `expected_parameters` and
  its `match` cases in `doc/analysis/requests.py`.
- **New setup/teardown keyword** — declare it in `doc/analysis/initial_setup.py` (or reuse an existing name).
- **New directory of Test Cases** — declare it in `doc/analysis/generaterobotdata.py` along with its acronym.

Declare it in `doc/analysis/generaterobotdata.py` along with its acronym.
When `statisticsDocumentationData.py` reports a failure, its message points at the cause — most often a keyword
used in a `.robot` file but not declared above, a setup keyword name that does not match `initial_setup.py`, or a
Test Case whose name does not match its file name.

To inspect the generated documentation of a single Test Case, run `python doc/generateDocumentationData.py
{tc_id}`; it writes `doc/results/{tc_id}.json` (git-ignored) for you to review.

### Generate documentation for support keywords

@@ -225,19 +233,6 @@ And, to generate documentation for the Test Cases:

---

## Running the unit tests

Before submitting, verify that the documentation unit tests pass:

```bash
python -m unittest discover -s ./doc/tests -t ./doc
```

These tests detect undeclared Test Cases and inconsistencies between the test suite files and the documentation
metadata. A failing unit test indicates either a missing declaration or a stale JSON documentation file.

---

## Maintenance scripts

### Find unused test data files
@@ -279,7 +274,6 @@ Before opening a merge request, confirm the following:
- [ ] The pre-commit hook ran without errors (or reformatted files were re-staged).
- [ ] New Test Cases follow the naming convention (`XXX_YY_NN`) and carry the required tags.
- [ ] New or modified keywords are declared in the relevant `doc/analysis/` files.
- [ ] Documentation data has been regenerated for any new or modified Test Case.
- [ ] New test data files have been placed in the correct `data/` subdirectory.
- [ ] No unused test data files were introduced (`find_unused_test_data.py` returns no new entries).
- [ ] `python -m unittest discover -s ./doc/tests -t ./doc` passes locally.
- [ ] Documentation still generates without failures (`cd doc ; python statisticsDocumentationData.py` reports `0` failures).
+106 −0
Original line number Diff line number Diff line
*** Settings ***
Documentation       Three brokers are set up A, B and C. A has two registrations, one inclusive for the entities created in B and one exclusive for the entity created in C. 
...                 The client sends a HTTP GET request to check that quering the offparking type returns the entities in B and C.
Resource            ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextSourceRegistration.resource
Resource            ${EXECDIR}/resources/AssertionUtils.resource
Resource            ${EXECDIR}/resources/JsonUtils.resource

Test Setup          Setup Initial Context Source Registrations
Test Teardown       Delete Entities and Delete Registrations

*** Variables ***
${first_entity_payload_filename}               interoperability/offstreet-parking1-full.jsonld
${second_entity_payload_filename}              interoperability/offstreet-parking2-full.jsonld
${third_entity_payload_filename}               interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld
${inclusive_registration_payload_file_path}    csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld
${exclusive_registration_payload_file_path}    csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld
${b1_url}
${b2_url}
${b3_url}

*** Test Cases ***
IOP_CNF_01_01 Query Entities Of Type OffstreetParking Via GET
    [Documentation]    Pre-conditions: no user context. Data only on leaves. B contains OffStreetParking1 and OffStreetParking2 without location and totalSpotsNumber. C contains OffStreetParking2.
    ...                Registrations established: Inclusive in A to B. Exclusive in A to C.
    [Tags]    since_v1.6.1    iop    4_3_3    cf_06    additive-inclusive    proxy-exclusive    4_3_6    5_7_2    6_4_3_1

    #Agent queries all entities with type OffstreetParking in A and checks for a successful response that contains the attributes of both entities in B and C.
    ${response}=    Query Entities    entity_types=OffstreetParking    broker_url=${b1_url}
    Check Response Status Code    200    ${response.status_code}
    @{payload}=    Set Variable   ${response.json()}
    Should Contain    ${payload}\[OffstreetParking1]    availableSpotsNumber
    Should Contain    ${payload}\[OffstreetParking1]    totalSpotsNumber
    Should Contain    ${payload}\[OffstreetParking2]    availableSpotsNumber
    Should Contain    ${payload}\[OffstreetParking2]    location

    #Agent queries all entities with type OffstreetParking in B and C
    ${response}=    Query Entities    entity_types=OffstreetParking    broker_url=${b2_url}
    @{first_expected_payload}=    Set Variable    ${response.json()}
    ${entity_ids}=    Create List    ${entity_id}    ${second_entity_id}
    Check Response Body Containing Entities URIS set to    ${entity_ids}    ${response.json()}

    ${response}=    Query Entities    entity_types=OffstreetParking    broker_url=${b3_url}
    @{second_expected_payload}=    Set Variable    ${response.json()}
    Check Response Body Containing Entities URIS set to    ${entity_id}    ${response.json()}

    #Agent checks that OffstreetParking1 in A is the same as the one in B and that OffstreetParking2 in A contains the attributes of both OffstreetParking2 in B and C.
    Should Be Equal    ${payload}\[OffstreetParking1]    ${first_expected_payload}\[OffstreetParking1]
    Should Contain    ${payload}\[OffstreetParking2]    ${first_expected_payload}\[OffstreetParking2][totalSpotsNumber]
    Should Contain    ${payload}\[OffstreetParking2]    ${second_expected_payload}\[OffstreetParking2][location]

*** Keywords ***
Setup Initial Context Source Registrations
    ${entity_id}=    Generate Random Parking Entity Id
    Set Suite Variable    ${entity_id}
    ${second_entity_id}=    Generate Random Parking Entity Id
    Set Suite Variable    ${second_entity_id}
    ${response}=    Create Entity    ${first_entity_payload_filename}    ${entity_id}    broker_url=${b2_url}
    Check Response Status Code    201    ${response.status_code}
    ${response}=    Create Entity    ${third_entity_payload_filename}    ${second_entity_id}    broker_url=${b2_url}
    Check Response Status Code    201    ${response.status_code}
    ${response}=    Create Entity    ${second_entity_payload_filename}    ${entity_id}    broker_url=${b3_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id1}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id1}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id1}
    ...    ${inclusive_registration_payload_file_path}
    ...    entity_id=${entity_id}
    ...    broker_url=${b2_url}
    ...    mode=inclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id2}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id2}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id2}
    ...    ${inclusive_registration_payload_file_path}
    ...    entity_id=${second_entity_id}
    ...    broker_url=${b2_url}
    ...    mode=inclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id3}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id3}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id3}
    ...    ${exclusive_registration_payload_file_path}
    ...    entity_id=${entity_id}
    ...    broker_url=${b3_url}
    ...    mode=exclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

Delete Entities And Delete Registrations
    Delete Context Source Registration    ${registration_id1}    broker_url=${b1_url}
    Delete Context Source Registration    ${registration_id2}    broker_url=${b1_url}
    Delete Context Source Registration    ${registration_id3}    broker_url=${b1_url}
    Delete Entity    ${entity_id}    broker_url=${b2_url}
    Delete Entity    ${second_entity_id}    broker_url=${b2_url}
    Delete Entity    ${entity_id}    broker_url=${b3_url}
 No newline at end of file
+107 −0
Original line number Diff line number Diff line
*** Settings ***
Documentation       Three brokers are set up A, B and C. A has two registrations, one inclusive for the entities created in B and one exclusive for the entity created in C. 
...                 The client sends and HTTP POST request to check that the entities can be queried from all brokers.

Resource            ${EXECDIR}/resources/ApiUtils/ContextInformationConsumption.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextInformationProvision.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextSourceDiscovery.resource
Resource            ${EXECDIR}/resources/ApiUtils/ContextSourceRegistration.resource
Resource            ${EXECDIR}/resources/AssertionUtils.resource
Resource            ${EXECDIR}/resources/JsonUtils.resource

Test Setup          Setup Initial Context Source Registrations
Test Teardown       Delete Entities and Delete Registrations

*** Variables ***
${first_entity_payload_filename}               interoperability/offstreet-parking1-full.jsonld
${second_entity_payload_filename}              interoperability/offstreet-parking2-full.jsonld
${third_entity_payload_filename}               interoperability/offstreet-parking2-no-location-and-totalspotsnumber.jsonld
${inclusive_registration_payload_file_path}    csourceRegistrations/interoperability/context-source-registration-inclusive-2.jsonld
${exclusive_registration_payload_file_path}    csourceRegistrations/interoperability/context-source-registration-exclusive-2.jsonld
${b1_url}
${b2_url}
${b3_url}

*** Test Cases ***
IOP_CNF_01_01 Query Entities Of Type OffstreetParking Via POST
    [Documentation]    Pre-conditions: no user context. Data only on leaves. B contains OffStreetParking1 and OffStreetParking2 without location and totalSpotsNumber. C contains OffStreetParking2.
    ...                Registrations established: Inclusive in A to B. Exclusive in A to C.
    [Tags]    since_v1.6.1    iop    4_3_3    cf_06    additive-inclusive    proxy-exclusive    4_3_6    5_7_2    6_23_2_1

    #Agent queries all entities with type OffstreetParking in A and checks for a successful response that contains the attributes of both entities in B and C.
    @{entities}=    Create List    ${entity_id}    ${second_entity_id}
    ${response}=    Query Entities Via POST   entities=${entities}    broker_url=${b1_url}
    Check Response Status Code    200    ${response.status_code}
    @{payload}=    Set Variable   ${response.json()}
    Should Contain    ${payload}\[OffstreetParking1]    availableSpotsNumber
    Should Contain    ${payload}\[OffstreetParking1]    totalSpotsNumber
    Should Contain    ${payload}\[OffstreetParking2]    availableSpotsNumber
    Should Contain    ${payload}\[OffstreetParking2]    location

    #Agent queries all entities with type OffstreetParking in B and C
    ${response}=    Query Entities Via POST   entities=${entities}    broker_url=${b2_url}
    @{first_expected_payload}=    Set Variable    ${response.json()}
    Check Response Body Containing Entities URIS set to    ${entities}    ${response.json()}

    ${response}=    Query Entities Via POST   entities=${entity_id}    broker_url=${b3_url}
    @{second_expected_payload}=    Set Variable    ${response.json()}
    Check Response Body Containing Entities URIS set to    ${entity_id}    ${response.json()}

    #Agent checks that OffstreetParking1 in A is the same as the one in B and that OffstreetParking2 in A contains the attributes of both OffstreetParking2 in B and C.
    Should Be Equal    ${payload}\[OffstreetParking1]    ${first_expected_payload}\[OffstreetParking1]
    Should Contain    ${payload}\[OffstreetParking2]    ${first_expected_payload}\[OffstreetParking2][totalSpotsNumber]
    Should Contain    ${payload}\[OffstreetParking2]    ${second_expected_payload}\[OffstreetParking2][location]

*** Keywords ***
Setup Initial Context Source Registrations
    ${entity_id}=    Generate Random Parking Entity Id
    Set Suite Variable    ${entity_id}
    ${second_entity_id}=    Generate Random Parking Entity Id
    Set Suite Variable    ${second_entity_id}
    ${response}=    Create Entity    ${first_entity_payload_filename}    ${entity_id}    broker_url=${b2_url}
    Check Response Status Code    201    ${response.status_code}
    ${response}=    Create Entity    ${third_entity_payload_filename}    ${second_entity_id}    broker_url=${b2_url}
    Check Response Status Code    201    ${response.status_code}
    ${response}=    Create Entity    ${second_entity_payload_filename}    ${entity_id}    broker_url=${b3_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id1}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id1}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id1}
    ...    ${inclusive_registration_payload_file_path}
    ...    entity_id=${entity_id}
    ...    broker_url=${b2_url}
    ...    mode=inclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id2}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id2}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id2}
    ...    ${inclusive_registration_payload_file_path}
    ...    entity_id=${second_entity_id}
    ...    broker_url=${b2_url}
    ...    mode=inclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

    ${registration_id3}=     Generate Random CSR Id
    Set Suite Variable    ${registration_id3}
    ${registration_payload}=    Prepare Context Source Registration From File
    ...    ${registration_id3}
    ...    ${exclusive_registration_payload_file_path}
    ...    entity_id=${entity_id}
    ...    broker_url=${b3_url}
    ...    mode=exclusive
    ${response}=    Create Context Source Registration With Return    ${registration_payload}    broker_url=${b1_url}
    Check Response Status Code    201    ${response.status_code}

Delete Entities And Delete Registrations
    Delete Context Source Registration    ${registration_id1}    broker_url=${b1_url}
    Delete Context Source Registration    ${registration_id2}    broker_url=${b1_url}
    Delete Context Source Registration    ${registration_id3}    broker_url=${b1_url}
    Delete Entity    ${entity_id}    broker_url=${b2_url}
    Delete Entity    ${second_entity_id}    broker_url=${b2_url}
    Delete Entity    ${entity_id}    broker_url=${b3_url}
 No newline at end of file
Loading