From a7723973dc30dc83fc61bc7553c391ccd53583bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Fri, 17 Nov 2023 13:36:48 +0100 Subject: [PATCH 01/34] FIX improve problematic attribute reporting on updates --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 36 ++++++++++++++++------ src/lib/rest/OrionError.cpp | 11 +++++++ src/lib/rest/OrionError.h | 2 ++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index afdec2510f..33759a32bd 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -2448,7 +2448,7 @@ static bool updateContextAttributeItem " - offending attribute: " + targetAttr->getName(); cerP->statusCode.fill(SccInvalidParameter, details); - oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); + //oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); /* Although 'ca' has been already pushed into cerP, the pointer is still valid, of course */ ca->found = false; @@ -2613,7 +2613,7 @@ static bool deleteContextAttributeItem " - attribute not found"; cerP->statusCode.fill(SccInvalidParameter, details); - oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); + //oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); alarmMgr.badInput(clientIp, "attribute to be deleted is not found", targetAttr->getName()); ca->found = false; @@ -3645,7 +3645,7 @@ static unsigned int updateEntity *attributeAlreadyExistsList += " ]"; } - if ((apiVersion == V2) && (action == ActionTypeUpdate)) + if ((apiVersion == V2) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) { @@ -4451,16 +4451,34 @@ unsigned int processContextElement if (attributeAlreadyExistsError == true) { - std::string details = "one or more of the attributes in the request already exist: " + attributeAlreadyExistsList; - buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + if (responseP->oe.code == SccInvalidModification) + { + // Another previous entity had problems. Use appendDetails() + responseP->oe.appendDetails(", " + eP->id + " - " + attributeAlreadyExistsList); + } + else + { + // First entity with this problem. Use fill() + std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; + buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); + responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + } } if (attributeNotExistingError == true) { - std::string details = "one or more of the attributes in the request do not exist: " + attributeNotExistingList; - buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + if (responseP->oe.code == SccInvalidModification) + { + // Another previous entity had problems. Use appendDetails() + responseP->oe.appendDetails(", " + eP->id + " - " + attributeNotExistingList); + } + else + { + // First entity with this problem. Use fill() + std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; + buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); + responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + } } // Response in responseP diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index cbec3a9c9e..9b25f1014d 100644 --- a/src/lib/rest/OrionError.cpp +++ b/src/lib/rest/OrionError.cpp @@ -98,6 +98,17 @@ void OrionError::fill(const StatusCode& sc) +/* **************************************************************************** +* +* OrionError::appendDetails - +*/ +void OrionError::appendDetails(const std::string& _details) +{ + details += _details; +} + + + /* **************************************************************************** * * OrionError::smartRender - diff --git a/src/lib/rest/OrionError.h b/src/lib/rest/OrionError.h index 47833a0dac..318cb83790 100644 --- a/src/lib/rest/OrionError.h +++ b/src/lib/rest/OrionError.h @@ -55,6 +55,8 @@ typedef struct OrionError std::string toJsonV1(void); void fill(HttpStatusCode _code, const std::string& _details, const std::string& _reasonPhrase = ""); void fill(const StatusCode& sc); + void appendDetails(const std::string& _details); + private: void shrinkReasonPhrase(void); From f4eb0a2718766d7a0248082ca7c781d2e6ae5116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 20 Nov 2023 15:08:32 +0100 Subject: [PATCH 02/34] FIX ftest --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 4 +- .../patch_v2_entities_eid.test | 4 +- .../patch_entity_with_param_type.test | 4 +- .../append_and_append_only_combinations.test | 4 +- .../append_only_attribute_already_there.test | 4 +- .../append_only_error_if_exists.test | 4 +- .../982_post_entity_with_type_param.test | 4 +- .../delete_not_exist_attr.test | 8 +- .../v1_append_strict.test | 8 +- .../patch_unknown_attribute.test | 4 +- .../error_response_for_entity_not_found.test | 4 +- .../ngsiv2_entity_id_revisited.test | 4 +- .../batch_update_APPEND.test | 4 +- ...date_DELETE_non_existing_and_existing.test | 8 +- ...xisting_and_existing_several_entities.test | 342 ++++++++++++++++++ ...batch_update_DELETE_non_existing_attr.test | 8 +- .../batch_update_UPDATE.test | 4 +- .../patch_non_existing_attribute.test | 4 +- ...error_updating_non_existing_attribute.test | 4 +- .../PATCH_offending_attributes.test | 8 +- 20 files changed, 390 insertions(+), 48 deletions(-) create mode 100644 test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 33759a32bd..feb5a99bf2 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -3623,7 +3623,7 @@ static unsigned int updateEntity { for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) { - if (attrs.hasField(eP->attributeVector[ix]->name)) + if (attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) { alarmMgr.badInput(clientIp, "attribute already exists", eP->attributeVector[ix]->name); *attributeAlreadyExistsError = true; @@ -3649,7 +3649,7 @@ static unsigned int updateEntity { for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) { - if (!attrs.hasField (eP->attributeVector[ix]->name)) + if (!attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) { *attributeNotExistingError = true; diff --git a/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test b/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test index 283558281f..5848be90e5 100644 --- a/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test +++ b/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test @@ -171,10 +171,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 110 +Content-Length: 115 { - "description": "one or more of the attributes in the request do not exist: [ attr3 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ attr3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test b/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test index 56e7955391..41c90e2615 100644 --- a/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test +++ b/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test @@ -169,10 +169,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test b/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test index e00bf7c539..de25c1bcc8 100644 --- a/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test +++ b/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test @@ -263,10 +263,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 116 { - "description": "one or more of the attributes in the request already exist: [ attr4 ]", + "description": "one or more of the attributes in the request already exist: E1 - [ attr4 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0981_POST_v2_attributes/append_only_attribute_already_there.test b/test/functionalTest/cases/0981_POST_v2_attributes/append_only_attribute_already_there.test index b03a038c07..ffc8b54c54 100644 --- a/test/functionalTest/cases/0981_POST_v2_attributes/append_only_attribute_already_there.test +++ b/test/functionalTest/cases/0981_POST_v2_attributes/append_only_attribute_already_there.test @@ -75,10 +75,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 116 { - "description": "one or more of the attributes in the request already exist: [ attr1 ]", + "description": "one or more of the attributes in the request already exist: E1 - [ attr1 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0981_POST_v2_attributes/append_only_error_if_exists.test b/test/functionalTest/cases/0981_POST_v2_attributes/append_only_error_if_exists.test index 3755d1e4b6..ecd48882a5 100644 --- a/test/functionalTest/cases/0981_POST_v2_attributes/append_only_error_if_exists.test +++ b/test/functionalTest/cases/0981_POST_v2_attributes/append_only_error_if_exists.test @@ -119,10 +119,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 116 { - "description": "one or more of the attributes in the request already exist: [ attr1 ]", + "description": "one or more of the attributes in the request already exist: E1 - [ attr1 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test b/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test index 2f6c1dcee9..3208886ffb 100644 --- a/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test +++ b/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test @@ -238,10 +238,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 108 +Content-Length: 113 { - "description": "one or more of the attributes in the request already exist: [ A3 ]", + "description": "one or more of the attributes in the request already exist: E1 - [ A3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test index 405123b429..ae337a1564 100644 --- a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test +++ b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test @@ -102,15 +102,15 @@ Content-Length: 121 03. DELETE /v2/entities/E1/attrs/none ===================================== -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 79 +Content-Length: 114 { - "description": "The entity does not have such an attribute", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E1 - [ none ]", + "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test b/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test index 1dd08bb2c6..6588f5b23e 100644 --- a/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test +++ b/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test @@ -239,7 +239,7 @@ HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 224 +Content-Length: 229 { "contextResponses": [ @@ -251,7 +251,7 @@ Content-Length: 224 }, "statusCode": { "code": "400", - "details": "one or more of the attributes in the request already exist: [ attr2 ]", + "details": "one or more of the attributes in the request already exist: E1 - [ attr2 ]", "reasonPhrase": "Bad Request" } } @@ -289,7 +289,7 @@ HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 388 +Content-Length: 393 { "contextResponses": [ @@ -319,7 +319,7 @@ Content-Length: 388 }, "statusCode": { "code": "400", - "details": "one or more of the attributes in the request already exist: [ attr2 ]", + "details": "one or more of the attributes in the request already exist: E1 - [ attr2 ]", "reasonPhrase": "Bad Request" } } diff --git a/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test b/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test index c4dc659d5c..555d8cefda 100644 --- a/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test +++ b/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test @@ -75,10 +75,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test index c4d4e2c97b..11cca7a827 100644 --- a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test +++ b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test @@ -97,10 +97,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 113 +Content-Length: 122 { - "description": "one or more of the attributes in the request do not exist: [ dfgdfgdf ]", + "description": "one or more of the attributes in the request do not exist: room_2 - [ dfgdfgdf ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test b/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test index 98be178f7c..3f08385cc0 100644 --- a/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test +++ b/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test @@ -148,10 +148,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request already exist: [ A ]", + "description": "one or more of the attributes in the request already exist: E1 - [ A ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test b/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test index f281d869f0..b9e1c5da97 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test @@ -202,10 +202,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 108 +Content-Length: 113 { - "description": "one or more of the attributes in the request already exist: [ A1 ]", + "description": "one or more of the attributes in the request already exist: E1 - [ A1 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test index 8cd808c80b..1a6828476f 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test @@ -229,15 +229,15 @@ Content-Length: 454 03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing) and E3-A1/A2=null using POST /v2/op/update with delete, get error =========================================================================================================================== -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 79 +Content-Length: 112 { - "description": "The entity does not have such an attribute", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", + "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test new file mode 100644 index 0000000000..a8b308e3d9 --- /dev/null +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test @@ -0,0 +1,342 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +V2 batch update DELETE in non existing and existing attribute (fail in several entities) + +--SHELL-INIT-- +dbInit CB +brokerStart CB 0 + +--SHELL-- + +# +# 01. Create E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 using POST /v2/op/update with append +# 02. GET /v2/entities to see E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 +# 03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing), E3-A1/A2=null and E4-A1/A2 (A1 not existing) using POST /v2/op/update with delete, get error +# 04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities +# + +echo "01. Create E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 using POST /v2/op/update with append" +echo "=====================================================================================================" +payload='{ + "actionType": "append", + "entities": [ + { + "id": "E1", + "type": "T", + "A1": { + "type": "Number", + "value": 11 + }, + "A2": { + "type": "Number", + "value": 12 + }, + "A3": { + "type": "Number", + "value": 13 + } + }, + { + "id": "E2", + "type": "T", + "A1": { + "type": "Number", + "value": 21 + }, + "A3": { + "type": "Number", + "value": 23 + } + }, + { + "id": "E3", + "type": "T", + "A1": { + "type": "Number", + "value": 31 + }, + "A2": { + "type": "Number", + "value": 32 + }, + "A3": { + "type": "Number", + "value": 33 + } + }, + { + "id": "E4", + "type": "T", + "A2": { + "type": "Number", + "value": 42 + }, + "A3": { + "type": "Number", + "value": 43 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. GET /v2/entities to see E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3" +echo "=================================================================================" +orionCurl --url /v2/entities +echo +echo + + +echo "03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing), E3-A1/A2=null and E4-A1/A2 (A1 not existing) using POST /v2/op/update with delete, get error" +echo "=======================================================================================================================================================" +payload='{ + "actionType": "delete", + "entities": [ + { + "id": "E1", + "type": "T", + "A1": { + "type": "Number", + "value": null + }, + "A2": { + "type": "Number", + "value": null + } + }, + { + "id": "E2", + "type": "T", + "A1": { + "type": "Number", + "value": null + }, + "A2": { + "type": "Number", + "value": null + } + }, + { + "id": "E3", + "type": "T", + "A1": { + "type": "Number", + "value": null + }, + "A2": { + "type": "Number", + "value": null + } + }, + { + "id": "E4", + "type": "T", + "A1": { + "type": "Number", + "value": null + }, + "A2": { + "type": "Number", + "value": null + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities" +echo "===================================================================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- +01. Create E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 using POST /v2/op/update with append +===================================================================================================== +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. GET /v2/entities to see E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 +================================================================================= +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 573 + +[ + { + "A1": { + "metadata": {}, + "type": "Number", + "value": 11 + }, + "A2": { + "metadata": {}, + "type": "Number", + "value": 12 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 13 + }, + "id": "E1", + "type": "T" + }, + { + "A1": { + "metadata": {}, + "type": "Number", + "value": 21 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 23 + }, + "id": "E2", + "type": "T" + }, + { + "A1": { + "metadata": {}, + "type": "Number", + "value": 31 + }, + "A2": { + "metadata": {}, + "type": "Number", + "value": 32 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 33 + }, + "id": "E3", + "type": "T" + }, + { + "A2": { + "metadata": {}, + "type": "Number", + "value": 42 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 43 + }, + "id": "E4", + "type": "T" + } +] + + +03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing), E3-A1/A2=null and E4-A1/A2 (A1 not existing) using POST /v2/op/update with delete, get error +======================================================================================================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 125 + +{ + "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ], E4 - [ A1 ]", + "error": "Unprocessable" +} + + +04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities +=================================================================================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 381 + +[ + { + "A3": { + "metadata": {}, + "type": "Number", + "value": 13 + }, + "id": "E1", + "type": "T" + }, + { + "A1": { + "metadata": {}, + "type": "Number", + "value": 21 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 23 + }, + "id": "E2", + "type": "T" + }, + { + "A3": { + "metadata": {}, + "type": "Number", + "value": 33 + }, + "id": "E3", + "type": "T" + }, + { + "A2": { + "metadata": {}, + "type": "Number", + "value": 42 + }, + "A3": { + "metadata": {}, + "type": "Number", + "value": 43 + }, + "id": "E4", + "type": "T" + } +] + + +--TEARDOWN-- +brokerStop CB +dbDrop CB diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test index 76af634b17..49fe42d62f 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test @@ -199,15 +199,15 @@ Content-Length: 358 03. Delete E1-A2=null, E2-A2=null (not existing) and E3-A2=null using POST /v2/op/update with delete, get error =============================================================================================================== -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 79 +Content-Length: 112 { - "description": "The entity does not have such an attribute", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", + "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test b/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test index 82454712f4..6c5a4b536d 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test @@ -189,10 +189,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request do not exist: [ A3 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ A3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test index b94f11236a..2f11f7300b 100644 --- a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test +++ b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test @@ -89,10 +89,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test index 11c4dfac26..0da279cbfb 100644 --- a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test +++ b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test @@ -83,10 +83,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", + "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test index ea20ea72ed..f1a44d10f5 100644 --- a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test +++ b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test @@ -117,10 +117,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 120 { - "description": "one or more of the attributes in the request do not exist: [ pressur ]", + "description": "one or more of the attributes in the request do not exist: Room1 - [ pressur ]", "error": "Unprocessable" } @@ -131,10 +131,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 128 { - "description": "one or more of the attributes in the request do not exist: [ temper, pressur ]", + "description": "one or more of the attributes in the request do not exist: Room1 - [ temper, pressur ]", "error": "Unprocessable" } From bd76b31edfbd3dfdd2f390b4f93372069bc7a689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 20 Nov 2023 16:46:16 +0100 Subject: [PATCH 03/34] FIX PartialUpdate cases --- src/lib/mongoBackend/mongoUpdateContext.cpp | 19 +++++++++++++++++++ ...date_DELETE_non_existing_and_existing.test | 2 +- ...xisting_and_existing_several_entities.test | 2 +- ...batch_update_DELETE_non_existing_attr.test | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 5c6dabff7c..e5ce9081f5 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -150,6 +150,8 @@ HttpStatusCode mongoUpdateContext else { /* Process each ContextElement */ + bool atLeastOneSuccess = false; + bool atLeastOneFail = false; for (unsigned int ix = 0; ix < requestP->entityVector.size(); ++ix) { notifSent += processContextElement(requestP->entityVector[ix], @@ -166,6 +168,23 @@ HttpStatusCode mongoUpdateContext notifSent, apiVersion, ngsiv2Flavour); + + if (responseP->oe.code == SccNone) + { + atLeastOneSuccess = true; + } + else + { + atLeastOneFail = true; + } + } + + // Only the PartialUpdate case (at least one success + at least one fail) needs to be "intercepted" here + // Other cases follow the usual response processing flow (whatever it is :) + if (atLeastOneSuccess && atLeastOneFail) + { + // FIXME PR: move to errorMessages.h + responseP->oe.reasonPhrase = "PartialUpdate"; } LM_T(LmtNotifier, ("total notifications sent during update: %d", notifSent)); diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test index 1a6828476f..5aff10fa29 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test @@ -237,7 +237,7 @@ Content-Length: 112 { "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test index a8b308e3d9..59bb725854 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test @@ -275,7 +275,7 @@ Content-Length: 125 { "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ], E4 - [ A1 ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test index 49fe42d62f..aa7b436961 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test @@ -207,7 +207,7 @@ Content-Length: 112 { "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", - "error": "Unprocessable" + "error": "PartialUpdate" } From 4ed302297ec0d57f0eba5b4613ec4ebbca294d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 20 Nov 2023 17:09:19 +0100 Subject: [PATCH 04/34] FIX avoid magic string for error response --- src/lib/common/errorMessages.h | 1 + src/lib/mongoBackend/mongoUpdateContext.cpp | 3 +-- src/lib/serviceRoutines/postUpdateContext.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/common/errorMessages.h b/src/lib/common/errorMessages.h index 4a5333e75c..1c9f4c93c6 100644 --- a/src/lib/common/errorMessages.h +++ b/src/lib/common/errorMessages.h @@ -98,6 +98,7 @@ #define ERROR_DESC_NOT_FOUND_REGISTRATION "The requested registration has not been found. Check id" #define ERROR_UNPROCESSABLE "Unprocessable" +#define ERROR_PARTIAL_UPDATE "PartialUpdate" #define ERROR_DESC_UNPROCESSABLE_ALREADY_EXISTS "Already Exists" #define ERROR_NO_RESOURCES_AVAILABLE "NoResourcesAvailable" diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index e5ce9081f5..0443fd1682 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -183,8 +183,7 @@ HttpStatusCode mongoUpdateContext // Other cases follow the usual response processing flow (whatever it is :) if (atLeastOneSuccess && atLeastOneFail) { - // FIXME PR: move to errorMessages.h - responseP->oe.reasonPhrase = "PartialUpdate"; + responseP->oe.reasonPhrase = ERROR_PARTIAL_UPDATE; } LM_T(LmtNotifier, ("total notifications sent during update: %d", notifSent)); diff --git a/src/lib/serviceRoutines/postUpdateContext.cpp b/src/lib/serviceRoutines/postUpdateContext.cpp index e287c2b859..54fd689774 100644 --- a/src/lib/serviceRoutines/postUpdateContext.cpp +++ b/src/lib/serviceRoutines/postUpdateContext.cpp @@ -840,7 +840,7 @@ std::string postUpdateContext failing = failing.substr(0, failing.size() - 2); // If some CER (but not all) fail, then it is a partial update - parseDataP->upcrs.res.oe.fill(SccContextElementNotFound, "Some of the following attributes were not updated: { " + failing + " }", "PartialUpdate"); + parseDataP->upcrs.res.oe.fill(SccContextElementNotFound, "Some of the following attributes were not updated: { " + failing + " }", ERROR_PARTIAL_UPDATE); } else // failures == 0 { From 6dcca23279418ff5bb4b87701bced2661a3fc15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 11:16:33 +0100 Subject: [PATCH 05/34] ADD stub for partical update test cases --- .../partial_update_action_appendstrict.test | 138 ++++++++++ ..._action_appendstrict_several_entities.test | 222 +++++++++++++++++ .../partial_update_action_delete.test | 142 +++++++++++ ...update_action_delete_several_entities.test | 235 ++++++++++++++++++ .../partial_update_action_update.test | 138 ++++++++++ ...update_action_update_several_entities.test | 222 +++++++++++++++++ 6 files changed, 1097 insertions(+) create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test new file mode 100644 index 0000000000..1932dc2d62 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test @@ -0,0 +1,138 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for appendStrict case + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E-A=1 +# 02. POST /v2/op/update appendStrict E A=10, B=20, C=30, get error about already existing attribute A +# 03. Get E, check A=1, B=20, C=30 +# 04. POST /v2/op/update appendStrict E D=400 B=200, get error about about already existing attribute B +# 05. Get E, check A=1, B=20, C=30, D=400 +# + +echo "01. Create entity E-A=1" +echo "=======================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update appendStrict E A=10, B=20, C=30, get error about already existing attribute A" +echo "====================================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get E, check A=1, B=20, C=30" +echo "================================" +orionCurl --url /v2/entities/E +echo +echo + + +echo "04. POST /v2/op/update appendStrict E D=400 B=200, get error about about already existing attribute B" +echo "=====================================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get E, check A=1, B=20, C=30, D=400" +echo "=======================================" +orionCurl --url /v2/entities/E +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test new file mode 100644 index 0000000000..a43f6e01e3 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test @@ -0,0 +1,222 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for appendStrict case for several entities + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3 +# 02. POST /v2/op/update appendStrict E/E1/E2 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1 +# 03. Get entities, E1-A=1/B=20/C=30, E2-A=1/B=2/C=30, E3-A=1/B=2/C=3 +# 04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about already existing attribute B in E1/E2/E3 +# 05. Get entities, E1-A=1/B=20/C=30/D=400, E2-A=1/B=2/C=30/D=400, E3-A=1/B=2/C=3/D=400 +# + +echo "01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3" +echo "====================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "C": { + "value": 3, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update appendStrict E/E1/E2 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1" +echo "===========================================================================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get entities, E1-A=1/B=20/C=30, E2-A=1/B=2/C=30, E3-A=1/B=2/C=3" +echo "===================================================================" +orionCurl --url /v2/entities +echo +echo + + +echo "04. POST /v2/op/update appendStrict E/E1/E2 D=400 B=200, get error about already existing attribute B in E1/E2/E3" +echo "=================================================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get entities, E1-A=1/B=20/C=30/D=400, E2-A=1/B=2/C=30/D=400, E3-A=1/B=2/C=3/D=400" +echo "=====================================================================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test new file mode 100644 index 0000000000..575bde447a --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test @@ -0,0 +1,142 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for delete case + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E-A=1/D=4 +# 02. POST /v2/op/update delete E A=10, B=20, C=30, get error about entity does not have attribute B and C +# 03. Get E, check D=4 +# 04. POST /v2/op/update delete E D=400 B=200, get error about entity does not have attribute B +# 05. Get E, check no attr +# + +echo "01. Create entity E-A=1/D=4" +echo "===========================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update delete E A=10, B=20, C=30, get error about entity does not have attribute B and C" +echo "========================================================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get E, check D=4" +echo "====================" +orionCurl --url /v2/entities/E +echo +echo + + +echo "04. POST /v2/op/update delete E D=400 B=200, get error about entity does not have attribute B" +echo "=============================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get E, check no attr" +echo "========================" +orionCurl --url /v2/entities/E +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test new file mode 100644 index 0000000000..a9d623628a --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test @@ -0,0 +1,235 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for delete case for several entities + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E1-A=1/D=4, E2-A=1/B=2/D=4, E3-A=1/B=2/C=3/D=4 +# 02. POST /v2/op/update delete E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 +# 03. Get entities, E1-D=4, E2-D=4, E3-D=4 +# 04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3 +# 05. Get entities without attributes +# + +echo "01. Create entity E1-A=1/D=4, E2-A=1/B=2/D=4, E3-A=1/B=2/C=3/D=4" +echo "================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "C": { + "value": 3, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update delete E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2" +echo "================================================================================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get entities, E1-D=4, E2-D=4, E3-D=4" +echo "========================================" +orionCurl --url /v2/entities +echo +echo + + +echo "04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3" +echo "===============================================================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T", + "id": "E1", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get entities without attributes" +echo "===================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test new file mode 100644 index 0000000000..d22d469a0e --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test @@ -0,0 +1,138 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for update case + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E-A=1 +# 02. POST /v2/op/update update E A=10, B=20, C=30, get error about entity does not have attribute B and C +# 03. Get E, check A=10 +# 04. POST /v2/op/update update E A=100 B=200, get error about entity does not have attribute B +# 05. Get E, check A=100 +# + +echo "01. Create entity E-A=1" +echo "=======================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update update E A=10, B=20, C=30, get error about entity does not have attribute B and C" +echo "========================================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get E, check A=10" +echo "=====================" +orionCurl --url /v2/entities/E +echo +echo + + +echo "04. POST /v2/op/update update E A=100 B=200, get error about entity does not have attribute B" +echo "==============================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get E, check A=100" +echo "======================" +orionCurl --url /v2/entities/E +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test new file mode 100644 index 0000000000..8a03ad8d85 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test @@ -0,0 +1,222 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for update case for several entities + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3 +# 02. POST /v2/op/update update E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 +# 03. Get entities, E1-A=10, E2-A=10/B=20, E3-A=10/B=20/C=30 +# 04. POST /v2/op/update update E/E1/E2 A=100 B=200, get error about entity does not have attribute B in E1 +# 05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=300 +# + +echo "01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3" +echo "====================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "C": { + "value": 3, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update update E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2" +echo "================================================================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get entities, E1-A=10, E2-A=10/B=20, E3-A=10/B=20/C=30" +echo "==========================================================" +orionCurl --url /v2/entities +echo +echo + + +echo "04. POST /v2/op/update update E/E1/E2 A=100 B=200, get error about entity does not have attribute B in E1" +echo "=========================================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=300" +echo "================================================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- + +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From a515124bf5405d5e3ddf551fd1c28266af329bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 13:32:20 +0100 Subject: [PATCH 06/34] FIX delete attributes operation and improve error reporting --- CHANGES_NEXT_RELEASE | 2 +- src/lib/mongoBackend/MongoCommonUpdate.cpp | 6 +- src/lib/rest/OrionError.cpp | 21 ++ src/lib/rest/OrionError.h | 1 + ...date_DELETE_non_existing_and_existing.test | 17 +- ...xisting_and_existing_several_entities.test | 22 +- .../partial_update_action_appendstrict.test | 93 +++++ ..._action_appendstrict_several_entities.test | 195 ++++++++++- .../partial_update_action_delete.test | 65 +++- ...update_action_delete_several_entities.test | 119 ++++++- ..._delete_several_entities_non_existing.test | 298 ++++++++++++++++ .../partial_update_action_update.test | 68 ++++ ...update_action_update_several_entities.test | 144 +++++++- ..._update_several_entities_non_existing.test | 320 ++++++++++++++++++ 14 files changed, 1317 insertions(+), 54 deletions(-) create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index e241145fe2..ba5b1b9d9b 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -3,7 +3,7 @@ - Fix: correctly detect JSON attribute and metadata value changes in subscription triggering logic (#4211, #4434, #643) - Fix: DateTime and geo:json types were not supported in custom notifications using ngsi patching (#4435) - Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated) -- Fix: improve error traces (#4387) +- Fix: on delete attributes operation the lack of attribute in entity doesn't precules attributes which do exist (this way behaving same way as update attributes operation) - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) - Fix: improve logs in MongoDB query logic - Upgrade Debian version from 11.6 to 12.1 in Dockerfile diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index feb5a99bf2..7859fcc24b 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -2618,7 +2618,7 @@ static bool deleteContextAttributeItem alarmMgr.badInput(clientIp, "attribute to be deleted is not found", targetAttr->getName()); ca->found = false; - return false; + //return false; } return true; @@ -4342,7 +4342,7 @@ unsigned int processContextElement } else { - responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ERROR_NOT_FOUND); + responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); } } } @@ -4350,7 +4350,7 @@ unsigned int processContextElement { cerP->statusCode.fill(SccContextElementNotFound); - responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ERROR_NOT_FOUND); + responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); responseP->contextElementResponseVector.push_back(cerP); } else /* APPEND or APPEND_STRICT */ diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index 9b25f1014d..c3839b631f 100644 --- a/src/lib/rest/OrionError.cpp +++ b/src/lib/rest/OrionError.cpp @@ -85,6 +85,27 @@ void OrionError::fill(HttpStatusCode _code, const std::string& _details, const s +/* **************************************************************************** +* +* OrionError::fillOrAppend - +*/ +void OrionError::fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase) +{ + if (code == SccInvalidModification) + { + // Already filled by a prevoius operation. This can happen in batch update processing + details += appendDetail; + } + else + { + code = _code; + reasonPhrase = _reasonPhrase.empty()? httpStatusCodeString(code) : _reasonPhrase; + details = fullDetails; + } +} + + + /* **************************************************************************** * * OrionError::fill - diff --git a/src/lib/rest/OrionError.h b/src/lib/rest/OrionError.h index 318cb83790..5f7e828911 100644 --- a/src/lib/rest/OrionError.h +++ b/src/lib/rest/OrionError.h @@ -55,6 +55,7 @@ typedef struct OrionError std::string toJsonV1(void); void fill(HttpStatusCode _code, const std::string& _details, const std::string& _reasonPhrase = ""); void fill(const StatusCode& sc); + void fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase); void appendDetails(const std::string& _details); diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test index 5aff10fa29..0711ce279d 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test @@ -33,7 +33,7 @@ brokerStart CB 0 # 01. Create E1/T/A1-A2-A3, E2/T/A1-A3 and E3/T/A1-A2-A3 using POST /v2/op/update with append # 02. GET /v2/entities to see E1/T/A1-A2-A3, E2/T/A1-A3 and E3/T/A1-A2-A3 # 03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing) and E3-A1/A2=null using POST /v2/op/update with delete, get error -# 04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3 and E3/T/A3 in entities +# 04. GET /v2/entities to see E1/T/A3, E2/T/A3 and E3/T/A3 in entities # echo "01. Create E1/T/A1-A2-A3, E2/T/A1-A3 and E3/T/A1-A2-A3 using POST /v2/op/update with append" @@ -147,8 +147,8 @@ echo echo -echo "04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3 and E3/T/A3 in entities" -echo "=======================================================================" +echo "04. GET /v2/entities to see E1/T/A3, E2/T/A3 and E3/T/A3 in entities" +echo "====================================================================" orionCurl --url /v2/entities echo echo @@ -241,13 +241,13 @@ Content-Length: 112 } -04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3 and E3/T/A3 in entities -======================================================================= +04. GET /v2/entities to see E1/T/A3, E2/T/A3 and E3/T/A3 in entities +==================================================================== HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 262 +Content-Length: 214 [ { @@ -260,11 +260,6 @@ Content-Length: 262 "type": "T" }, { - "A1": { - "metadata": {}, - "type": "Number", - "value": 21 - }, "A3": { "metadata": {}, "type": "Number", diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test index 59bb725854..d6f1638a6f 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test @@ -33,7 +33,7 @@ brokerStart CB 0 # 01. Create E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 using POST /v2/op/update with append # 02. GET /v2/entities to see E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 # 03. Delete E1-A1/A2=null, E2-A1/A2=null (A2 not existing), E3-A1/A2=null and E4-A1/A2 (A1 not existing) using POST /v2/op/update with delete, get error -# 04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities +# 04. GET /v2/entities to see E1/T/A3, E2/T/A3, E3/T/A3 and E4/T/A3 in entities # echo "01. Create E1/T/A1-A2-A3, E2/T/A1-A3, E3/T/A1-A2-A3 and E4/A2-A3 using POST /v2/op/update with append" @@ -171,8 +171,8 @@ echo echo -echo "04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities" -echo "===================================================================================" +echo "04. GET /v2/entities to see E1/T/A3, E2/T/A3, E3/T/A3 and E4/T/A3 in entities" +echo "=============================================================================" orionCurl --url /v2/entities echo echo @@ -279,13 +279,13 @@ Content-Length: 125 } -04. GET /v2/entities to see E1/T/A3, E2/T/A1-A3, E3/T/A3 and E4/T/A2-A3 in entities -=================================================================================== +04. GET /v2/entities to see E1/T/A3, E2/T/A3, E3/T/A3 and E4/T/A3 in entities +============================================================================= HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 381 +Content-Length: 285 [ { @@ -298,11 +298,6 @@ Content-Length: 381 "type": "T" }, { - "A1": { - "metadata": {}, - "type": "Number", - "value": 21 - }, "A3": { "metadata": {}, "type": "Number", @@ -321,11 +316,6 @@ Content-Length: 381 "type": "T" }, { - "A2": { - "metadata": {}, - "type": "Number", - "value": 42 - }, "A3": { "metadata": {}, "type": "Number", diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test index 1932dc2d62..07630a0d73 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test @@ -127,10 +127,103 @@ echo --REGEXPECT-- +01. Create entity E-A=1 +======================= +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + +02. POST /v2/op/update appendStrict E A=10, B=20, C=30, get error about already existing attribute A +==================================================================================================== +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 +{ + "description": "one or more of the attributes in the request already exist: E - [ A ]", + "error": "Unprocessable" +} + + +03. Get E, check A=1, B=20, C=30 +================================ +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 161 + +{ + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E", + "type": "T" +} + + +04. POST /v2/op/update appendStrict E D=400 B=200, get error about about already existing attribute B +===================================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request already exist: E - [ B ]", + "error": "Unprocessable" +} + + +05. Get E, check A=1, B=20, C=30, D=400 +======================================= +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 209 + +{ + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "D": { + "metadata": {}, + "type": "Number", + "value": 400 + }, + "id": "E", + "type": "T" +} --TEARDOWN-- diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test index a43f6e01e3..3539d2c686 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test @@ -31,9 +31,9 @@ brokerStart CB # # 01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3 -# 02. POST /v2/op/update appendStrict E/E1/E2 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1 +# 02. POST /v2/op/update appendStrict E1/E2/E3 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1 # 03. Get entities, E1-A=1/B=20/C=30, E2-A=1/B=2/C=30, E3-A=1/B=2/C=3 -# 04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about already existing attribute B in E1/E2/E3 +# 04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about already existing attribute B in E1/E2/E3 # 05. Get entities, E1-A=1/B=20/C=30/D=400, E2-A=1/B=2/C=30/D=400, E3-A=1/B=2/C=3/D=400 # @@ -86,8 +86,8 @@ echo echo -echo "02. POST /v2/op/update appendStrict E/E1/E2 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1" -echo "===========================================================================================================================================" +echo "02. POST /v2/op/update appendStrict E1/E2/E3 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1" +echo "============================================================================================================================================" payload='{ "actionType": "appendStrict", "entities": @@ -154,8 +154,8 @@ echo echo -echo "04. POST /v2/op/update appendStrict E/E1/E2 D=400 B=200, get error about already existing attribute B in E1/E2/E3" -echo "=================================================================================================================" +echo "04. POST /v2/op/update appendStrict E1/E2/E3 D=400 B=200, get error about already existing attribute B in E1/E2/E3" +echo "==================================================================================================================" payload='{ "actionType": "appendStrict", "entities": @@ -211,11 +211,194 @@ echo --REGEXPECT-- +01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3 +==================================================== +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/op/update appendStrict E1/E2/E3 A=10, B=20, C=30, get error about already existing attribute A/B/C in E3, A/B in E2 and A in E1 +============================================================================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 145 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A, B ], E3 - [ A, B, C ]", + "error": "Unprocessable" +} + +03. Get entities, E1-A=1/B=20/C=30, E2-A=1/B=2/C=30, E3-A=1/B=2/C=3 +=================================================================== +HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 487 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 2 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E2", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 2 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 3 + }, + "id": "E3", + "type": "T" + } +] +04. POST /v2/op/update appendStrict E1/E2/E3 D=400 B=200, get error about already existing attribute B in E1/E2/E3 +================================================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 136 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", + "error": "Unprocessable" +} + + +05. Get entities, E1-A=1/B=20/C=30/D=400, E2-A=1/B=2/C=30/D=400, E3-A=1/B=2/C=3/D=400 +===================================================================================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 631 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "D": { + "metadata": {}, + "type": "Number", + "value": 400 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 2 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "D": { + "metadata": {}, + "type": "Number", + "value": 400 + }, + "id": "E2", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 1 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 2 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 3 + }, + "D": { + "metadata": {}, + "type": "Number", + "value": 400 + }, + "id": "E3", + "type": "T" + } +] + --TEARDOWN-- brokerStop CB diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test index 575bde447a..a2762ecd29 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test @@ -101,7 +101,7 @@ echo echo "04. POST /v2/op/update delete E D=400 B=200, get error about entity does not have attribute B" echo "=============================================================================================" payload='{ - "actionType": "update", + "actionType": "delete", "entities": [ { @@ -131,10 +131,73 @@ echo --REGEXPECT-- +01. Create entity E-A=1/D=4 +=========================== +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/op/update delete E A=10, B=20, C=30, get error about entity does not have attribute B and C +======================================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 113 + +{ + "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", + "error": "Unprocessable" +} + + +03. Get E, check D=4 +==================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 67 + +{ + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E", + "type": "T" +} + + +04. POST /v2/op/update delete E D=400 B=200, get error about entity does not have attribute B +============================================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 110 + +{ + "description": "one or more of the attributes in the request do not exist: E - [ B ]", + "error": "Unprocessable" +} + +05. Get E, check no attr +======================== +HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 21 +{ + "id": "E", + "type": "T" +} --TEARDOWN-- diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test index a9d623628a..fa0504848d 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test @@ -31,10 +31,10 @@ brokerStart CB # # 01. Create entity E1-A=1/D=4, E2-A=1/B=2/D=4, E3-A=1/B=2/C=3/D=4 -# 02. POST /v2/op/update delete E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 +# 02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 # 03. Get entities, E1-D=4, E2-D=4, E3-D=4 -# 04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3 -# 05. Get entities without attributes +# 04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3 +# 05. Get entities E1, E2 and E3 without attributes # echo "01. Create entity E1-A=1/D=4, E2-A=1/B=2/D=4, E3-A=1/B=2/C=3/D=4" @@ -99,8 +99,8 @@ echo echo -echo "02. POST /v2/op/update delete E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2" -echo "================================================================================================================================" +echo "02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2" +echo "=================================================================================================================================" payload='{ "actionType": "delete", "entities": @@ -167,8 +167,8 @@ echo echo -echo "04. POST /v2/op/update update E/E1/E2 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3" -echo "===============================================================================================================" +echo "04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3" +echo "================================================================================================================" payload='{ "actionType": "delete", "entities": @@ -188,8 +188,8 @@ payload='{ { "type": "T", "id": "E2", - "A": { - "value": 100, + "D": { + "value": 400, "type": "Number" }, "B": { @@ -200,8 +200,8 @@ payload='{ { "type": "T", "id": "E3", - "A": { - "value": 100, + "D": { + "value": 400, "type": "Number" }, "B": { @@ -216,18 +216,111 @@ echo echo -echo "05. Get entities without attributes" -echo "===================================" +echo "05. Get entities E1, E2 and E3 without attributes" +echo "=================================================" orionCurl --url /v2/entities echo echo --REGEXPECT-- +01. Create entity E1-A=1/D=4, E2-A=1/B=2/D=4, E3-A=1/B=2/C=3/D=4 +================================================================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + +02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 +================================================================================================================================= +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 126 +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", + "error": "Unprocessable" +} + + +03. Get entities, E1-D=4, E2-D=4, E3-D=4 +======================================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 208 + +[ + { + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E1", + "type": "T" + }, + { + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E2", + "type": "T" + }, + { + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E3", + "type": "T" + } +] + + +04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E2/E3 +================================================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 135 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", + "error": "Unprocessable" +} + + +05. Get entities E1, E2 and E3 without attributes +================================================= +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 70 + +[ + { + "id": "E1", + "type": "T" + }, + { + "id": "E2", + "type": "T" + }, + { + "id": "E3", + "type": "T" + } +] --TEARDOWN-- diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test new file mode 100644 index 0000000000..299df9f73a --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test @@ -0,0 +1,298 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for delete case for several entities one of them non existing + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E1-A=1/D=4, E3-A=1/B=2/C=3/D=4 +# 02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exists +# 03. Get entities, E1-D=4, E3-D=4 +# 04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E3 and entity E2 does not exist +# 05. Get entities E1 and E3 attributes +# + +echo "01. Create entity E1-A=1/D=4, E3-A=1/B=2/C=3/D=4" +echo "================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "C": { + "value": 3, + "type": "Number" + }, + "D": { + "value": 4, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exists" +echo "============================================================================================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get entities, E1-D=4, E3-D=4" +echo "================================" +orionCurl --url /v2/entities +echo +echo + + +echo "04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E3 and entity E2 does not exist" +echo "==========================================================================================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T", + "id": "E1", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "D": { + "value": 400, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get entities E1 and E3 without attributes" +echo "=============================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- +01. Create entity E1-A=1/D=4, E3-A=1/B=2/C=3/D=4 +================================================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/op/update delete E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exists +============================================================================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 134 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", + "error": "Unprocessable" +} + + +03. Get entities, E1-D=4, E3-D=4 +================================ +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 139 + +[ + { + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E1", + "type": "T" + }, + { + "D": { + "metadata": {}, + "type": "Number", + "value": 4 + }, + "id": "E3", + "type": "T" + } +] + + +04. POST /v2/op/update update E1/E2/E3 D=400 B=200, get error about entity does not have attribute B in E1/E3 and entity E2 does not exist +========================================================================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 143 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself], E3 - [ B ]", + "error": "Unprocessable" +} + + +05. Get entities E1 and E3 without attributes +============================================= +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 47 + +[ + { + "id": "E1", + "type": "T" + }, + { + "id": "E3", + "type": "T" + } +] + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test index d22d469a0e..39307f0ea7 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test @@ -127,10 +127,78 @@ echo --REGEXPECT-- +01. Create entity E-A=1 +======================= +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + +02. POST /v2/op/update update E A=10, B=20, C=30, get error about entity does not have attribute B and C +======================================================================================================== +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 113 +{ + "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", + "error": "Unprocessable" +} + + +03. Get E, check A=10 +===================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 68 + +{ + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "id": "E", + "type": "T" +} + + +04. POST /v2/op/update update E A=100 B=200, get error about entity does not have attribute B +============================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 110 + +{ + "description": "one or more of the attributes in the request do not exist: E - [ B ]", + "error": "Unprocessable" +} + + +05. Get E, check A=100 +====================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 69 + +{ + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "id": "E", + "type": "T" +} --TEARDOWN-- diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test index 8a03ad8d85..a9b2e2887c 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test @@ -34,7 +34,7 @@ brokerStart CB # 02. POST /v2/op/update update E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 # 03. Get entities, E1-A=10, E2-A=10/B=20, E3-A=10/B=20/C=30 # 04. POST /v2/op/update update E/E1/E2 A=100 B=200, get error about entity does not have attribute B in E1 -# 05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=300 +# 05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=30 # echo "01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3" @@ -203,19 +203,157 @@ echo echo -echo "05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=300" -echo "================================================================" +echo "05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=30" +echo "===============================================================" orionCurl --url /v2/entities echo echo --REGEXPECT-- +01. Create entity E1-A=1, E2-A=1/B=2, E3-A=1/B=2/C=3 +==================================================== +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/op/update update E/E1/E2 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and C in E2 +================================================================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 126 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", + "error": "Unprocessable" +} + +03. Get entities, E1-A=10, E2-A=10/B=20, E3-A=10/B=20/C=30 +========================================================== +HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 352 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "id": "E2", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E3", + "type": "T" + } +] +04. POST /v2/op/update update E/E1/E2 A=100 B=200, get error about entity does not have attribute B in E1 +========================================================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B ]", + "error": "Unprocessable" +} + + +05. Get entities, E1-A=100, E2-A=100/B=200, E3-A=100/B=200/C=30 +=============================================================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 357 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 200 + }, + "id": "E2", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 200 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E3", + "type": "T" + } +] + --TEARDOWN-- brokerStop CB diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test new file mode 100644 index 0000000000..dcadc3d607 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test @@ -0,0 +1,320 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +PartialUpdate response for update case for several entities one of them non existing + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create entity E1-A=1, E3-A=1/B=2/C=3 +# 02. POST /v2/op/update update E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exist +# 03. Get entities, E1-A=10, E3-A=10/B=20/C=30 +# 04. POST /v2/op/update update E1/E2/E3 A=100 B=200, get error about entity does not have attribute B in E1 and E2 does not exist +# 05. Get entities, E1-A=100, E3-A=100/B=200/C=30 +# + +echo "01. Create entity E1-A=1, E3-A=1/B=2/C=3" +echo "========================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + }, + "C": { + "value": 3, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/op/update update E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exist" +echo "===========================================================================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 10, + "type": "Number" + }, + "B": { + "value": 20, + "type": "Number" + }, + "C": { + "value": 30, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Get entities, E1-A=10, E3-A=10/B=20/C=30" +echo "============================================" +orionCurl --url /v2/entities +echo +echo + + +echo "04. POST /v2/op/update update E1/E2/E3 A=100 B=200, get error about entity does not have attribute B in E1 and E2 does not exist" +echo "================================================================================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 100, + "type": "Number" + }, + "B": { + "value": 200, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Get entities, E1-A=100, E3-A=100/B=200/C=30" +echo "===============================================" +orionCurl --url /v2/entities +echo +echo + + +--REGEXPECT-- +01. Create entity E1-A=1, E3-A=1/B=2/C=3 +======================================== +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/op/update update E1/E2/E3 A=10, B=20, C=30, get error about entity does not have attribute B and C in E1 and E2 does not exist +=========================================================================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 134 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", + "error": "Unprocessable" +} + + +03. Get entities, E1-A=10, E3-A=10/B=20/C=30 +============================================ +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 235 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 10 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 20 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E3", + "type": "T" + } +] + + +04. POST /v2/op/update update E1/E2/E3 A=100 B=200, get error about entity does not have attribute B in E1 and E2 does not exist +================================================================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 131 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself]", + "error": "Unprocessable" +} + + +05. Get entities, E1-A=100, E3-A=100/B=200/C=30 +=============================================== +HTTP/1.1 200 OK +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 238 + +[ + { + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "id": "E1", + "type": "T" + }, + { + "A": { + "metadata": {}, + "type": "Number", + "value": 100 + }, + "B": { + "metadata": {}, + "type": "Number", + "value": 200 + }, + "C": { + "metadata": {}, + "type": "Number", + "value": 30 + }, + "id": "E3", + "type": "T" + } +] + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From 39b338caaf28583d3200d3540086d6fe93cde10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 15:12:40 +0100 Subject: [PATCH 07/34] FIX refactor --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 31 +++++----------------- src/lib/rest/OrionError.cpp | 11 -------- src/lib/rest/OrionError.h | 1 - 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 7859fcc24b..287320d6c2 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4451,34 +4451,17 @@ unsigned int processContextElement if (attributeAlreadyExistsError == true) { - if (responseP->oe.code == SccInvalidModification) - { - // Another previous entity had problems. Use appendDetails() - responseP->oe.appendDetails(", " + eP->id + " - " + attributeAlreadyExistsList); - } - else - { - // First entity with this problem. Use fill() - std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; - buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); - } + std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; + buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } if (attributeNotExistingError == true) { - if (responseP->oe.code == SccInvalidModification) - { - // Another previous entity had problems. Use appendDetails() - responseP->oe.appendDetails(", " + eP->id + " - " + attributeNotExistingList); - } - else - { - // First entity with this problem. Use fill() - std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; - buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); - } + + std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; + buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); } // Response in responseP diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index c3839b631f..180764bfa1 100644 --- a/src/lib/rest/OrionError.cpp +++ b/src/lib/rest/OrionError.cpp @@ -119,17 +119,6 @@ void OrionError::fill(const StatusCode& sc) -/* **************************************************************************** -* -* OrionError::appendDetails - -*/ -void OrionError::appendDetails(const std::string& _details) -{ - details += _details; -} - - - /* **************************************************************************** * * OrionError::smartRender - diff --git a/src/lib/rest/OrionError.h b/src/lib/rest/OrionError.h index 5f7e828911..d656bac8c9 100644 --- a/src/lib/rest/OrionError.h +++ b/src/lib/rest/OrionError.h @@ -56,7 +56,6 @@ typedef struct OrionError void fill(HttpStatusCode _code, const std::string& _details, const std::string& _reasonPhrase = ""); void fill(const StatusCode& sc); void fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase); - void appendDetails(const std::string& _details); private: From d8214e5448205d1404b7fc0e41412bbd890f3b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 15:48:20 +0100 Subject: [PATCH 08/34] FIX refactor --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 66 ++++++++++------------ 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 287320d6c2..4b034e947c 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -3616,53 +3616,45 @@ static unsigned int updateEntity } // - // Before calling processContextAttributeVector and actually do the work, let's check if the - // request is of type 'append-only' and if we have any problem with attributes already existing. - // - if (action == ActionTypeAppendStrict) + // Calculate list of existing and not existing attributes (used by decide if this was a partial update, full update or full fail + // depending on the operation) + + for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) { - for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) + if (attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) { - if (attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) - { - alarmMgr.badInput(clientIp, "attribute already exists", eP->attributeVector[ix]->name); - *attributeAlreadyExistsError = true; + *attributeAlreadyExistsError = true; - // - // This attribute should now be removed from the 'query' ... - // processContextAttributeVector looks at the 'skip' field - // + // + // If action is ActionTypeAppendStrict, this attribute should now be removed from the 'query' ... + // processContextAttributeVector looks at the 'skip' field + // + if (action == ActionTypeAppendStrict) + { eP->attributeVector[ix]->skip = true; + } - // Add to the list of existing attributes - for the error response - if (*attributeAlreadyExistsList != "[ ") - { - *attributeAlreadyExistsList += ", "; - } - *attributeAlreadyExistsList += eP->attributeVector[ix]->name; + // Add to the list of existing attributes + if (*attributeAlreadyExistsList != "[ ") + { + *attributeAlreadyExistsList += ", "; } + *attributeAlreadyExistsList += eP->attributeVector[ix]->name; } - *attributeAlreadyExistsList += " ]"; - } - - if ((apiVersion == V2) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) - { - for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) + else // !attrs.hasField(dbEncode(eP->attributeVector[ix]->name)) { - if (!attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) - { - *attributeNotExistingError = true; + *attributeNotExistingError = true; - // Add to the list of non existing attributes - for the error response - if (*attributeNotExistingList != "[ ") - { - *attributeNotExistingList += ", "; - } - *attributeNotExistingList += eP->attributeVector[ix]->name; + // Add to the list of non existing attributes + if (*attributeNotExistingList != "[ ") + { + *attributeNotExistingList += ", "; } + *attributeNotExistingList += eP->attributeVector[ix]->name; } - *attributeNotExistingList += " ]"; } + *attributeNotExistingList += " ]"; + *attributeAlreadyExistsList += " ]"; // The logic to detect notification loops is to check that the correlator in the request differs from the last one seen for the entity and, // in addition, the request was sent due to a custom notification @@ -4449,14 +4441,14 @@ unsigned int processContextElement } } - if (attributeAlreadyExistsError == true) + if ((attributeAlreadyExistsError == true) && (action == ActionTypeAppendStrict)) { std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } - if (attributeNotExistingError == true) + if ((attributeNotExistingError == true) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; From 2399c31a2411e2cd1dc8e6ab2b4f29ed5a74ccae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 16:09:40 +0100 Subject: [PATCH 09/34] FIX refactor --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 33 +++++++++++----------- src/lib/mongoBackend/MongoCommonUpdate.h | 17 ++++++++++- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 4b034e947c..4a4ebf10ec 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -3473,9 +3473,9 @@ static unsigned int updateEntity const std::string& xauthToken, Entity* eP, UpdateContextResponse* responseP, - bool* attributeAlreadyExistsError, + unsigned int* attributeAlreadyExistsNumber, std::string* attributeAlreadyExistsList, - bool* attributeNotExistingError, + unsigned int* attributeNotExistingNumber, std::string* attributeNotExistingList, const bool& forcedUpdate, const bool& overrideMetadata, @@ -3486,10 +3486,10 @@ static unsigned int updateEntity ) { // Used to accumulate error response information - *attributeAlreadyExistsError = false; + *attributeAlreadyExistsNumber = 0; *attributeAlreadyExistsList = "[ "; - *attributeNotExistingError = false; + *attributeNotExistingNumber = 0; *attributeNotExistingList = "[ "; const std::string idString = "_id." ENT_ENTITY_ID; @@ -3623,7 +3623,7 @@ static unsigned int updateEntity { if (attrs.hasField(dbEncode(eP->attributeVector[ix]->name))) { - *attributeAlreadyExistsError = true; + (*attributeAlreadyExistsNumber)++;; // // If action is ActionTypeAppendStrict, this attribute should now be removed from the 'query' ... @@ -3643,7 +3643,7 @@ static unsigned int updateEntity } else // !attrs.hasField(dbEncode(eP->attributeVector[ix]->name)) { - *attributeNotExistingError = true; + (*attributeNotExistingNumber)++; // Add to the list of non existing attributes if (*attributeNotExistingList != "[ ") @@ -3694,7 +3694,7 @@ static unsigned int updateEntity // searchContextProviders(tenant, servicePathV, en, eP->attributeVector, cerP); - if (!(attributeAlreadyExistsError && (action == ActionTypeAppendStrict))) + if (!(attributeAlreadyExistsNumber && (action == ActionTypeAppendStrict))) { // Note that CER generation in the case of attributeAlreadyExistsError has its own logic at // processContextElement() function so we need to skip this addition or we will get duplicated @@ -4107,7 +4107,8 @@ unsigned int processContextElement const bool& overrideMetadata, unsigned int notifStartCounter, ApiVersion apiVersion, - Ngsiv2Flavour ngsiv2Flavour + Ngsiv2Flavour ngsiv2Flavour, + UpdateCoverage* updateCoverageP ) { /* Check preconditions */ @@ -4255,11 +4256,11 @@ unsigned int processContextElement unsigned int notifSent = 0; // Used to accumulate error response information, checked at the end - bool attributeAlreadyExistsError = false; - std::string attributeAlreadyExistsList = "[ "; + unsigned int attributeAlreadyExistsNumber = 0; + std::string attributeAlreadyExistsList = "[ "; - bool attributeNotExistingError = false; - std::string attributeNotExistingList = "[ "; + unsigned int attributeNotExistingNumber = 0; + std::string attributeNotExistingList = "[ "; /* Note that the following loop is not executed if result size is 0, which leads to the * 'if' just below to create a new entity */ @@ -4272,9 +4273,9 @@ unsigned int processContextElement xauthToken, eP, responseP, - &attributeAlreadyExistsError, + &attributeAlreadyExistsNumber, &attributeAlreadyExistsList, - &attributeNotExistingError, + &attributeNotExistingNumber, &attributeNotExistingList, forcedUpdate, overrideMetadata, @@ -4441,14 +4442,14 @@ unsigned int processContextElement } } - if ((attributeAlreadyExistsError == true) && (action == ActionTypeAppendStrict)) + if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } - if ((attributeNotExistingError == true) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) + if ((attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; diff --git a/src/lib/mongoBackend/MongoCommonUpdate.h b/src/lib/mongoBackend/MongoCommonUpdate.h index 5a22880c26..baefd1a9ec 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.h +++ b/src/lib/mongoBackend/MongoCommonUpdate.h @@ -36,6 +36,20 @@ #define MONGODB_ERROR_WRONGJSON "Can't extract geo keys" + +/* **************************************************************************** +* +* UpdateCoverage - +*/ +typedef enum UpdateCoverage +{ + FULL_SUCCESS = 0, + FULL_FAILURE = 1, + PARTIAL = 2 +} UpdateCoverage; + + + /* **************************************************************************** * * processContextElement - @@ -55,7 +69,8 @@ extern unsigned int processContextElement const bool& overrideMetadata, unsigned int notifStartCounter, ApiVersion apiVersion = V1, - Ngsiv2Flavour ngsiV2Flavour = NGSIV2_NO_FLAVOUR + Ngsiv2Flavour ngsiV2Flavour = NGSIV2_NO_FLAVOUR, + UpdateCoverage* updateCoverageP = NULL ); #endif // SRC_LIB_MONGOBACKEND_MONGOCOMMONUPDATE_H_ From a14931c40b0f9907d5cd8a279bb36d71d48ed0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 21 Nov 2023 16:55:14 +0100 Subject: [PATCH 10/34] FIX PartialUpdate detection logic --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 36 +++++++++++++++++++ src/lib/mongoBackend/MongoCommonUpdate.h | 7 ++-- src/lib/mongoBackend/mongoUpdateContext.cpp | 35 ++++++++++++------ .../partial_update_action_appendstrict.test | 4 +-- ..._action_appendstrict_several_entities.test | 4 +-- .../partial_update_action_delete.test | 4 +-- ...update_action_delete_several_entities.test | 4 +-- ..._delete_several_entities_non_existing.test | 4 +-- .../partial_update_action_update.test | 4 +-- ...update_action_update_several_entities.test | 4 +-- ..._update_several_entities_non_existing.test | 4 +-- 11 files changed, 80 insertions(+), 30 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 4a4ebf10ec..e4c1e18a85 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4457,6 +4457,42 @@ unsigned int processContextElement responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); } + if (updateCoverageP != NULL) + { + // By default, everyghing gone ok. Next we are going to detect some partial/failure cases + *updateCoverageP = UC_FULL_SUCCESS; + + if ((action == ActionTypeUpdate) || (action == ActionTypeDelete)) + { + // Full failure if the number of the non-existing attributes are all the ones in the request + if (attributeNotExistingNumber == eP->attributeVector.size()) + { + *updateCoverageP = UC_FULL_FAILURE; + } + // Partial failure/success if the number of the non-existing attributes is less than the ones in the request (else branch) + // and at least there was one existing attribute + else if (attributeNotExistingNumber > 0) + { + *updateCoverageP = UC_PARTIAL; + } + } + + if (action == ActionTypeAppendStrict) + { + // Full failure if the number of the existing attributes are all the ones in the request + if (attributeAlreadyExistsNumber == eP->attributeVector.size()) + { + *updateCoverageP = UC_FULL_FAILURE; + } + // Partial failure/success if the number of the existing attributes is less than the ones in the request (else branch) + // and at least there was one non-existing attribute + else if (attributeAlreadyExistsNumber > 0) + { + *updateCoverageP = UC_PARTIAL; + } + } + } + // Response in responseP return notifSent; } diff --git a/src/lib/mongoBackend/MongoCommonUpdate.h b/src/lib/mongoBackend/MongoCommonUpdate.h index baefd1a9ec..dc4463a470 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.h +++ b/src/lib/mongoBackend/MongoCommonUpdate.h @@ -43,9 +43,10 @@ */ typedef enum UpdateCoverage { - FULL_SUCCESS = 0, - FULL_FAILURE = 1, - PARTIAL = 2 + UC_NONE = 0, + UC_FULL_SUCCESS = 1, + UC_FULL_FAILURE = 2, + UC_PARTIAL = 3 } UpdateCoverage; diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 0443fd1682..860a7cdf46 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -150,10 +150,10 @@ HttpStatusCode mongoUpdateContext else { /* Process each ContextElement */ - bool atLeastOneSuccess = false; - bool atLeastOneFail = false; + UpdateCoverage updateCoverage = UC_NONE; for (unsigned int ix = 0; ix < requestP->entityVector.size(); ++ix) { + UpdateCoverage entityUpdateCoverage; notifSent += processContextElement(requestP->entityVector[ix], responseP, requestP->updateActionType, @@ -167,21 +167,34 @@ HttpStatusCode mongoUpdateContext overrideMetadata, notifSent, apiVersion, - ngsiv2Flavour); - - if (responseP->oe.code == SccNone) - { - atLeastOneSuccess = true; - } - else + ngsiv2Flavour, + &entityUpdateCoverage); + switch(updateCoverage) { - atLeastOneFail = true; + case UC_NONE: + updateCoverage = entityUpdateCoverage; + break; + case UC_FULL_SUCCESS: + if (entityUpdateCoverage != UC_FULL_SUCCESS) + { + updateCoverage = UC_PARTIAL; + } + break; + case UC_FULL_FAILURE: + if (entityUpdateCoverage != UC_FULL_FAILURE) + { + updateCoverage = UC_PARTIAL; + } + break; + case UC_PARTIAL: + updateCoverage = UC_PARTIAL; + break; } } // Only the PartialUpdate case (at least one success + at least one fail) needs to be "intercepted" here // Other cases follow the usual response processing flow (whatever it is :) - if (atLeastOneSuccess && atLeastOneFail) + if (updateCoverage == UC_PARTIAL) { responseP->oe.reasonPhrase = ERROR_PARTIAL_UPDATE; } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test index 07630a0d73..ba43328e5e 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test @@ -145,7 +145,7 @@ Content-Length: 111 { "description": "one or more of the attributes in the request already exist: E - [ A ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -188,7 +188,7 @@ Content-Length: 111 { "description": "one or more of the attributes in the request already exist: E - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test index 3539d2c686..0c949c092d 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test @@ -229,7 +229,7 @@ Content-Length: 145 { "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A, B ], E3 - [ A, B, C ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -312,7 +312,7 @@ Content-Length: 136 { "description": "one or more of the attributes in the request already exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test index a2762ecd29..8feabbe5be 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test @@ -149,7 +149,7 @@ Content-Length: 113 { "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -182,7 +182,7 @@ Content-Length: 110 { "description": "one or more of the attributes in the request do not exist: E - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test index fa0504848d..aec5c87f14 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test @@ -242,7 +242,7 @@ Content-Length: 126 { "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -295,7 +295,7 @@ Content-Length: 135 { "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test index 299df9f73a..1bd68a7642 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test @@ -225,7 +225,7 @@ Content-Length: 134 { "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -269,7 +269,7 @@ Content-Length: 143 { "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself], E3 - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test index 39307f0ea7..93999321d6 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test @@ -145,7 +145,7 @@ Content-Length: 113 { "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -178,7 +178,7 @@ Content-Length: 110 { "description": "one or more of the attributes in the request do not exist: E - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test index a9b2e2887c..3059d751be 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test @@ -229,7 +229,7 @@ Content-Length: 126 { "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -297,7 +297,7 @@ Content-Length: 111 { "description": "one or more of the attributes in the request do not exist: E1 - [ B ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test index dcadc3d607..01904cc414 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test @@ -217,7 +217,7 @@ Content-Length: 134 { "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -271,7 +271,7 @@ Content-Length: 131 { "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself]", - "error": "Unprocessable" + "error": "PartialUpdate" } From 4c2d7b55c94a05bfb762330da6bf04182907eb81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 22 Nov 2023 17:12:40 +0100 Subject: [PATCH 11/34] FIX ftest cases --- .../append_and_append_only_combinations.test | 2 +- .../ngsiv2_entity_id_revisited.test | 10 +++++----- .../patch_non_existing_attribute.test | 2 +- .../PATCH_offending_attributes.test | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test b/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test index de25c1bcc8..7410ba41cd 100644 --- a/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test +++ b/test/functionalTest/cases/0981_POST_v2_attributes/append_and_append_only_combinations.test @@ -267,7 +267,7 @@ Content-Length: 116 { "description": "one or more of the attributes in the request already exist: E1 - [ attr4 ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test b/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test index 3f08385cc0..9b23e25341 100644 --- a/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test +++ b/test/functionalTest/cases/1682_ngsiv2_entity_id/ngsiv2_entity_id_revisited.test @@ -74,8 +74,8 @@ orionCurl --url /v2/entities/E1/attrs --payload "$payload" echo echo -echo "04. POST /v2/entities/E1?options=append A and B (and check 400 Bad Request)" -echo "===========================================================================" +echo "04. POST /v2/entities/E1?options=append A and B (and check 422 Unprocessable Content)" +echo "=====================================================================================" payload='{ "A": { "value": 30 @@ -142,8 +142,8 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) -04. POST /v2/entities/E1?options=append A and B (and check 400 Bad Request) -=========================================================================== +04. POST /v2/entities/E1?options=append A and B (and check 422 Unprocessable Content) +===================================================================================== HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) @@ -152,7 +152,7 @@ Content-Length: 112 { "description": "one or more of the attributes in the request already exist: E1 - [ A ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test index 2f11f7300b..7c84e5ef49 100644 --- a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test +++ b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test @@ -93,7 +93,7 @@ Content-Length: 112 { "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", - "error": "Unprocessable" + "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test index f1a44d10f5..0ccf23b652 100644 --- a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test +++ b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test @@ -77,7 +77,7 @@ echo '03. PATCH /v2/entities/Room1/attrs, to update existing attribute (temperat echo '====================================================================================================================================================================' payload='{ "temperature": { - "value": 24, + "value": 25, "type": "Float" }, "temper": { @@ -121,7 +121,7 @@ Content-Length: 120 { "description": "one or more of the attributes in the request do not exist: Room1 - [ pressur ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -135,7 +135,7 @@ Content-Length: 128 { "description": "one or more of the attributes in the request do not exist: Room1 - [ temper, pressur ]", - "error": "Unprocessable" + "error": "PartialUpdate" } @@ -158,7 +158,7 @@ Content-Length: 141 "temperature": { "metadata": {}, "type": "Float", - "value": 24 + "value": 25 }, "type": "Thing" } From 59cf0771ef36bdbc50b31d8e084751ab90097b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 22 Nov 2023 17:34:48 +0100 Subject: [PATCH 12/34] FIX broker NGSIv1 test case --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index e4c1e18a85..be35550e7b 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4442,14 +4442,14 @@ unsigned int processContextElement } } - if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) + if ((apiVersion == V2) && (attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } - if ((attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) + if ((apiVersion == V2) && (attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; From 141dc915d1227b2d2217a055bbb172f2ba766a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Thu, 23 Nov 2023 11:24:05 +0100 Subject: [PATCH 13/34] FIX minor fixes --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index be35550e7b..cc5f16e4f7 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -3694,9 +3694,9 @@ static unsigned int updateEntity // searchContextProviders(tenant, servicePathV, en, eP->attributeVector, cerP); - if (!(attributeAlreadyExistsNumber && (action == ActionTypeAppendStrict))) + if (!((*attributeAlreadyExistsNumber) > 0 && (action == ActionTypeAppendStrict))) { - // Note that CER generation in the case of attributeAlreadyExistsError has its own logic at + // Note that CER generation in the case of attributeAlreadyExistsNumber has its own logic at // processContextElement() function so we need to skip this addition or we will get duplicated // CER responseP->contextElementResponseVector.push_back(cerP); @@ -4442,7 +4442,7 @@ unsigned int processContextElement } } - if ((apiVersion == V2) && (attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) + if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); From 692b788631364c15ba6d3039c92421be1debda68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Fri, 24 Nov 2023 13:51:42 +0100 Subject: [PATCH 14/34] ADD ftest covering all combination cases --- .../all_combinations_appendstrict.test | 390 ++++++++++++++ .../all_combinations_delete.test | 510 ++++++++++++++++++ .../all_combinations_update.test | 391 ++++++++++++++ 3 files changed, 1291 insertions(+) create mode 100644 test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test new file mode 100644 index 0000000000..d72fcb6cc8 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test @@ -0,0 +1,390 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for appendStrict actionType + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E1-A/B, E2-A/B +# 02. Update E1-C/D (full success) + E2-C/D (full success): OK +# 03. Update E1-A/B (full fail) + E2-A/B (full fail): Unprocessable +# 04. Update E1-E/F (full success) + E2-A/B (full fail): PartialUpdate +# 05. Update E1-A/G (partial) + E2-E/F (full success): PartialUpdate +# 06. Update E1-A/H (partial) + E3-A/B (full fail): PartialUpdate +# 07. Update E1-A/I (partial) + E2-A/G (partial): PartialUpdate +# + +echo "01. Create E1-A/B, E2-A/B" +echo "=========================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Update E1-C/D (full success) + E2-C/D (full success): OK" +echo "============================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "C": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "C": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Update E1-A/B (full fail) + E2-A/B (full fail): Unprocessable" +echo "=======================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. Update E1-E/F (full success) + E2-A/B (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "E": { + "value": 1, + "type": "Number" + }, + "F": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Update E1-A/G (partial) + E2-E/F (full success): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "G": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "E": { + "value": 1, + "type": "Number" + }, + "F": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "06. Update E1-A/H (partial) + E3-A/B (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "H": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "07. Update E1-A/I (partial) + E2-A/G (partial): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "I": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "G": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create E1-A/B, E2-A/B +========================= +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. Update E1-C/D (full success) + E2-C/D (full success): OK +============================================================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +03. Update E1-A/B (full fail) + E2-A/B (full fail): Unprocessable +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 130 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ A, B ], E2 - [ A, B ]", + "error": "Unprocessable" +} + + +04. Update E1-E/F (full success) + E2-A/B (full fail): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 115 + +{ + "description": "one or more of the attributes in the request already exist: E2 - [ A, B ]", + "error": "PartialUpdate" +} + + +05. Update E1-A/G (partial) + E2-E/F (full success): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 112 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ A ]", + "error": "PartialUpdate" +} + + +06. Update E1-A/H (partial) + E3-A/B (full fail): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 127 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A, B ]", + "error": "PartialUpdate" +} + + +07. Update E1-A/I (partial) + E2-A/G (partial): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 124 + +{ + "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test new file mode 100644 index 0000000000..afad667f8c --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test @@ -0,0 +1,510 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for delete actionType + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E1-A/B, E2-A/B (6 times, each one with a different type so no interference between update) +# 02. Update E1-A/B (full success) + E2-A/B (full success): OK +# 03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable +# 04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate +# 05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate +# 06. Update E1-A/C (partial) + E3-A/A (full fail): PartialUpdate +# 07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate +# + +echo "01. Create E1-A/B, E2-A/B (6 times, each one with a different type so no interference between update)" +echo "=====================================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T2", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T2", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T3", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T3", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T4", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T4", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T5", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T5", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T6", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T6", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T7", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T7", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Update E1-A/B (full success) + E2-A/B (full success): OK" +echo "============================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T2", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T2", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable" +echo "=======================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T3", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T3", + "id": "E4", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T4", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T4", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T5", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T5", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "06. Update E1-A/C (partial) + E3-A/B (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T6", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T6", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "delete", + "entities": + [ + { + "type": "T7", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T7", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create E1-A/B, E2-A/B (6 times, each one with a different type so no interference between update) +===================================================================================================== +HTTP/1.1 204 No Content +Date: Fri, 24 Nov 2023 12:11:12 GMT +Fiware-Correlator: 8f1e6af0-8ac2-11ee-a0dd-000c29e06b83 + + + +02. Update E1-A/B (full success) + E2-A/B (full success): OK +============================================================ +HTTP/1.1 204 No Content +Date: Fri, 24 Nov 2023 12:11:12 GMT +Fiware-Correlator: 8f30e464-8ac2-11ee-a2a7-000c29e06b83 + + + +03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable +======================================================================= +HTTP/1.1 404 Not Found +Date: Fri, 24 Nov 2023 12:11:12 GMT +Fiware-Correlator: 8f3833cc-8ac2-11ee-96ba-000c29e06b83 +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id. FIX?", + "error": "NotFound" +} + + +04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate +======================================================================= +HTTP/1.1 404 Not Found +Date: Fri, 24 Nov 2023 12:11:12 GMT +Fiware-Correlator: 8f54372a-8ac2-11ee-a6a7-000c29e06b83 +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id. FIX", + "error": "NotFound" +} + + +05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: Fri, 24 Nov 2023 12:11:12 GMT +Fiware-Correlator: 8f6c9cc0-8ac2-11ee-8293-000c29e06b83 +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ]", + "error": "PartialUpdate" +} + + +06. Update E1-A/C (partial) + E3-A/B (full fail): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: Fri, 24 Nov 2023 12:11:13 GMT +Fiware-Correlator: 8f89545a-8ac2-11ee-aa04-000c29e06b83 +Content-Type: application/json +Content-Length: 131 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E3 [entity itself]", + "error": "PartialUpdate" +} + + +07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 123 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E2 - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test new file mode 100644 index 0000000000..8a632022a5 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test @@ -0,0 +1,391 @@ + +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for update actionType + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E1-A/B, E2-A/B +# 02. Update E1-A/B (full success) + E2-A/B (full success): OK +# 03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable +# 04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate +# 05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate +# 06. Update E1-A/C (partial) + E3-A/B (full fail): PartialUpdate +# 07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate +# + +echo "01. Create E1-A/B, E2-A/B" +echo "=========================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Update E1-A/B (full success) + E2-A/B (full success): OK" +echo "============================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable" +echo "=======================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E4", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "06. Update E1-A/C (partial) + E3-A/C (full fail): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E3", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate" +echo "=======================================================================" +payload='{ + "actionType": "update", + "entities": + [ + { + "type": "T", + "id": "E1", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } + }, + { + "type": "T", + "id": "E2", + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create E1-A/B, E2-A/B +========================= +HTTP/1.1 204 No Content +Date: Fri, 24 Nov 2023 12:44:45 GMT +Fiware-Correlator: 3ebe9756-8ac7-11ee-8889-000c29e06b83 + + + +02. Update E1-A/B (full success) + E2-A/B (full success): OK +============================================================ +HTTP/1.1 204 No Content +Date: Fri, 24 Nov 2023 12:44:45 GMT +Fiware-Correlator: 3ec7f8dc-8ac7-11ee-935d-000c29e06b83 + + + +03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable +======================================================================= +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id. FIX?", + "error": "NotFound" +} + + +04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate +======================================================================= +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id. FIX", + "error": "NotFound" +} + + +05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ]", + "error": "PartialUpdate" +} + + +06. Update E1-A/C (partial) + E3-A/C (full fail): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 131 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E3 [entity itself]", + "error": "PartialUpdate" +} + + +07. Update E1-A/C (partial) + E2-A/C (partial): PartialUpdate +======================================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 123 + +{ + "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E2 - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From ebf656c22aaaf228e671fc3633077025fcf65f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Fri, 24 Nov 2023 17:09:40 +0100 Subject: [PATCH 15/34] FIX PartialUpdate cases --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 24 ++++++++--- src/lib/rest/OrionError.cpp | 4 +- .../batch_update_DELETE.test | 8 ++-- .../batch_update_error_entity_not_found.test | 24 +++++------ .../all_combinations_delete.test | 40 +++++++++---------- .../all_combinations_update.test | 24 +++++------ 6 files changed, 68 insertions(+), 56 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index cc5f16e4f7..9196f30a51 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4111,6 +4111,9 @@ unsigned int processContextElement UpdateCoverage* updateCoverageP ) { + // By default, assume everything is gone to be ok. Next in this function we are going to check for some partial/failure cases + *updateCoverageP = UC_FULL_SUCCESS; + /* Check preconditions */ if (!contextElementPreconditionsCheck(eP, responseP, action, apiVersion)) { @@ -4335,7 +4338,13 @@ unsigned int processContextElement } else { - responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); + //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); + std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - [entity itself]"; + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " [entity itself]", ERROR_UNPROCESSABLE); + if (updateCoverageP != NULL) + { + *updateCoverageP = UC_FULL_FAILURE; + } } } } @@ -4343,8 +4352,14 @@ unsigned int processContextElement { cerP->statusCode.fill(SccContextElementNotFound); - responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); + //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); + std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - [entity itself]"; + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " [entity itself]", ERROR_UNPROCESSABLE); responseP->contextElementResponseVector.push_back(cerP); + if (updateCoverageP != NULL) + { + *updateCoverageP = UC_FULL_FAILURE; + } } else /* APPEND or APPEND_STRICT */ { @@ -4444,6 +4459,7 @@ unsigned int processContextElement if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { + // FIXME PR move to errorsMesage.h std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); @@ -4451,7 +4467,6 @@ unsigned int processContextElement if ((apiVersion == V2) && (attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { - std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); @@ -4459,9 +4474,6 @@ unsigned int processContextElement if (updateCoverageP != NULL) { - // By default, everyghing gone ok. Next we are going to detect some partial/failure cases - *updateCoverageP = UC_FULL_SUCCESS; - if ((action == ActionTypeUpdate) || (action == ActionTypeDelete)) { // Full failure if the number of the non-existing attributes are all the ones in the request diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index 180764bfa1..eed3f0b7c0 100644 --- a/src/lib/rest/OrionError.cpp +++ b/src/lib/rest/OrionError.cpp @@ -91,9 +91,9 @@ void OrionError::fill(HttpStatusCode _code, const std::string& _details, const s */ void OrionError::fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase) { - if (code == SccInvalidModification) + if (code == _code) { - // Already filled by a prevoius operation. This can happen in batch update processing + // Already filled by a previous operation. This can happen in batch update processing details += appendDetail; } else diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test index 8568b6fbfb..73c69b1b76 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test @@ -132,15 +132,15 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) 04. Delete E1 again, see it fail ================================ -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 121 { - "description": "The requested entity has not been found. Check type and id", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E1 - [entity itself]", + "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test b/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test index 503dfb3356..e2bd1228a7 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test @@ -86,43 +86,43 @@ echo --REGEXPECT-- 01. Batch Update with actionType UPDATE on non-existing entity, see error ========================================================================= -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 120 { - "description": "The requested entity has not been found. Check type and id", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E - [entity itself]", + "error": "Unprocessable" } 02. Batch Update with actionType DELETE on non-existing entity, see error ========================================================================= -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 120 { - "description": "The requested entity has not been found. Check type and id", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E - [entity itself]", + "error": "Unprocessable" } 03. Batch Update with actionType REPLACE on non-existing entity, see error ========================================================================== -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 120 { - "description": "The requested entity has not been found. Check type and id", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E - [entity itself]", + "error": "Unprocessable" } diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test index afad667f8c..c6fa5be4bc 100644 --- a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test @@ -422,52 +422,52 @@ echo 01. Create E1-A/B, E2-A/B (6 times, each one with a different type so no interference between update) ===================================================================================================== HTTP/1.1 204 No Content -Date: Fri, 24 Nov 2023 12:11:12 GMT -Fiware-Correlator: 8f1e6af0-8ac2-11ee-a0dd-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) 02. Update E1-A/B (full success) + E2-A/B (full success): OK ============================================================ HTTP/1.1 204 No Content -Date: Fri, 24 Nov 2023 12:11:12 GMT -Fiware-Correlator: 8f30e464-8ac2-11ee-a2a7-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) 03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable ======================================================================= -HTTP/1.1 404 Not Found -Date: Fri, 24 Nov 2023 12:11:12 GMT -Fiware-Correlator: 8f3833cc-8ac2-11ee-96ba-000c29e06b83 +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 141 { - "description": "The requested entity has not been found. Check type and id. FIX?", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E3 - [entity itself], E4 [entity itself]", + "error": "Unprocessable" } 04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate ======================================================================= -HTTP/1.1 404 Not Found -Date: Fri, 24 Nov 2023 12:11:12 GMT -Fiware-Correlator: 8f54372a-8ac2-11ee-a6a7-000c29e06b83 +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 121 { - "description": "The requested entity has not been found. Check type and id. FIX", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E3 - [entity itself]", + "error": "PartialUpdate" } 05. Update E1-A/C (partial) + E2-A/B (full success): PartialUpdate ======================================================================= HTTP/1.1 422 Unprocessable Content -Date: Fri, 24 Nov 2023 12:11:12 GMT -Fiware-Correlator: 8f6c9cc0-8ac2-11ee-8293-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json Content-Length: 111 @@ -480,8 +480,8 @@ Content-Length: 111 06. Update E1-A/C (partial) + E3-A/B (full fail): PartialUpdate ======================================================================= HTTP/1.1 422 Unprocessable Content -Date: Fri, 24 Nov 2023 12:11:13 GMT -Fiware-Correlator: 8f89545a-8ac2-11ee-aa04-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json Content-Length: 131 diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test index 8a632022a5..dff1cdc418 100644 --- a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test @@ -303,44 +303,44 @@ echo 01. Create E1-A/B, E2-A/B ========================= HTTP/1.1 204 No Content -Date: Fri, 24 Nov 2023 12:44:45 GMT -Fiware-Correlator: 3ebe9756-8ac7-11ee-8889-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) 02. Update E1-A/B (full success) + E2-A/B (full success): OK ============================================================ HTTP/1.1 204 No Content -Date: Fri, 24 Nov 2023 12:44:45 GMT -Fiware-Correlator: 3ec7f8dc-8ac7-11ee-935d-000c29e06b83 +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) 03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable ======================================================================= -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 141 { - "description": "The requested entity has not been found. Check type and id. FIX?", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E3 - [entity itself], E4 [entity itself]", + "error": "Unprocessable" } 04. Update E1-A/B (full success) + E3-A/B (full fail): PartialUpdate ======================================================================= -HTTP/1.1 404 Not Found +HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 121 { - "description": "The requested entity has not been found. Check type and id. FIX", - "error": "NotFound" + "description": "one or more of the attributes in the request do not exist: E3 - [entity itself]", + "error": "PartialUpdate" } From 06ca9c952e0b34960ba6be97f015e007722e69ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 28 Nov 2023 09:24:17 +0100 Subject: [PATCH 16/34] FIX improve error response for cases 1715 and 3499 --- src/lib/common/errorMessages.h | 3 ++ src/lib/mongoBackend/MongoCommonUpdate.cpp | 27 +++++++------- src/lib/mongoBackend/MongoCommonUpdate.h | 9 ++--- src/lib/mongoBackend/mongoUpdateContext.cpp | 36 ++++++++++++++++--- src/lib/rest/OrionError.cpp | 34 ++++++++++-------- src/lib/rest/OrionError.h | 1 + .../batch_update_APPEND.test | 4 +-- .../batch_update_DELETE.test | 8 ++--- ...date_DELETE_non_existing_and_existing.test | 4 +-- ...xisting_and_existing_several_entities.test | 4 +-- ...batch_update_DELETE_non_existing_attr.test | 4 +-- .../batch_update_UPDATE.test | 4 +-- .../batch_update_error_entity_not_found.test | 24 ++++++------- .../all_combinations_appendstrict.test | 20 +++++------ .../all_combinations_delete.test | 32 ++++++++--------- .../all_combinations_update.test | 32 ++++++++--------- .../partial_update_action_appendstrict.test | 8 ++--- ..._action_appendstrict_several_entities.test | 8 ++--- .../partial_update_action_delete.test | 8 ++--- ...update_action_delete_several_entities.test | 8 ++--- ..._delete_several_entities_non_existing.test | 8 ++--- .../partial_update_action_update.test | 8 ++--- ...update_action_update_several_entities.test | 8 ++--- ..._update_several_entities_non_existing.test | 8 ++--- 24 files changed, 173 insertions(+), 137 deletions(-) diff --git a/src/lib/common/errorMessages.h b/src/lib/common/errorMessages.h index 1c9f4c93c6..a638981806 100644 --- a/src/lib/common/errorMessages.h +++ b/src/lib/common/errorMessages.h @@ -100,6 +100,9 @@ #define ERROR_UNPROCESSABLE "Unprocessable" #define ERROR_PARTIAL_UPDATE "PartialUpdate" #define ERROR_DESC_UNPROCESSABLE_ALREADY_EXISTS "Already Exists" +#define ERROR_DESC_UNPROCESSABLE_ATTR_ALREADY_EXISTS "one or more of the attributes in the request already exist: " + +#define ERROR_DESC_DO_NOT_EXIT "do not exist: " #define ERROR_NO_RESOURCES_AVAILABLE "NoResourcesAvailable" #define ERROR_DESC_NO_RESOURCES_AVAILABLE_GEOLOC "You cannot use more than one geo location attribute when creating an entity. Use ignoreType metadata if you want to add additional informative locations." diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 9196f30a51..6af0df9bcd 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4112,7 +4112,7 @@ unsigned int processContextElement ) { // By default, assume everything is gone to be ok. Next in this function we are going to check for some partial/failure cases - *updateCoverageP = UC_FULL_SUCCESS; + *updateCoverageP = UC_SUCCESS; /* Check preconditions */ if (!contextElementPreconditionsCheck(eP, responseP, action, apiVersion)) @@ -4339,11 +4339,11 @@ unsigned int processContextElement else { //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); - std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - [entity itself]"; - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " [entity itself]", ERROR_UNPROCESSABLE); + std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - [entity itself]"; + responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + eP->id + "/" + eP->type + " [entity itself]", ERROR_NOT_FOUND); if (updateCoverageP != NULL) { - *updateCoverageP = UC_FULL_FAILURE; + *updateCoverageP = UC_ENTITY_NOT_FOUND; } } } @@ -4353,12 +4353,12 @@ unsigned int processContextElement cerP->statusCode.fill(SccContextElementNotFound); //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); - std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - [entity itself]"; - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " [entity itself]", ERROR_UNPROCESSABLE); + std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - [entity itself]"; + responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + eP->id + "/" + eP->type + " [entity itself]", ERROR_NOT_FOUND); responseP->contextElementResponseVector.push_back(cerP); if (updateCoverageP != NULL) { - *updateCoverageP = UC_FULL_FAILURE; + *updateCoverageP = UC_ENTITY_NOT_FOUND; } } else /* APPEND or APPEND_STRICT */ @@ -4459,17 +4459,16 @@ unsigned int processContextElement if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { - // FIXME PR move to errorsMesage.h - std::string details = "one or more of the attributes in the request already exist: " + eP->id + " - " + attributeAlreadyExistsList; + std::string details = ERROR_DESC_UNPROCESSABLE_ATTR_ALREADY_EXISTS + eP->id + "/" + eP->type + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + "/" + eP->type + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } if ((apiVersion == V2) && (attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { - std::string details = "one or more of the attributes in the request do not exist: " + eP->id + " - " + attributeNotExistingList; + std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - " + attributeNotExistingList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + "/" + eP->type + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); } if (updateCoverageP != NULL) @@ -4479,7 +4478,7 @@ unsigned int processContextElement // Full failure if the number of the non-existing attributes are all the ones in the request if (attributeNotExistingNumber == eP->attributeVector.size()) { - *updateCoverageP = UC_FULL_FAILURE; + *updateCoverageP = UC_FULL_ATTRS_FAIL; } // Partial failure/success if the number of the non-existing attributes is less than the ones in the request (else branch) // and at least there was one existing attribute @@ -4494,7 +4493,7 @@ unsigned int processContextElement // Full failure if the number of the existing attributes are all the ones in the request if (attributeAlreadyExistsNumber == eP->attributeVector.size()) { - *updateCoverageP = UC_FULL_FAILURE; + *updateCoverageP = UC_FULL_ATTRS_FAIL; } // Partial failure/success if the number of the existing attributes is less than the ones in the request (else branch) // and at least there was one non-existing attribute diff --git a/src/lib/mongoBackend/MongoCommonUpdate.h b/src/lib/mongoBackend/MongoCommonUpdate.h index dc4463a470..3873b7a4f8 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.h +++ b/src/lib/mongoBackend/MongoCommonUpdate.h @@ -43,10 +43,11 @@ */ typedef enum UpdateCoverage { - UC_NONE = 0, - UC_FULL_SUCCESS = 1, - UC_FULL_FAILURE = 2, - UC_PARTIAL = 3 + UC_NONE = 0, + UC_SUCCESS = 1, + UC_FULL_ATTRS_FAIL = 2, + UC_ENTITY_NOT_FOUND = 3, + UC_PARTIAL = 4 } UpdateCoverage; diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 860a7cdf46..80ebfad8b3 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -172,22 +172,47 @@ HttpStatusCode mongoUpdateContext switch(updateCoverage) { case UC_NONE: + // If global UC is not set yet, then take the UC corresponding to the (first) processed entity updateCoverage = entityUpdateCoverage; break; - case UC_FULL_SUCCESS: - if (entityUpdateCoverage != UC_FULL_SUCCESS) + case UC_SUCCESS: + // If global UC is success, we need also success in the processed entity to keep global success + // Otherwise (full attrs fail, partial, not found entity), the global UC changes to partial + if (entityUpdateCoverage != UC_SUCCESS) { updateCoverage = UC_PARTIAL; } break; - case UC_FULL_FAILURE: - if (entityUpdateCoverage != UC_FULL_FAILURE) + case UC_FULL_ATTRS_FAIL: + // If global UC is full attrs fail, we need also full attrs fail in the processed entity to keep global full attrs fail + // Otherwise (success, partial, not found entity), the global UC changes to partial + if (entityUpdateCoverage != UC_FULL_ATTRS_FAIL) { updateCoverage = UC_PARTIAL; } break; + case UC_ENTITY_NOT_FOUND: + // If global UC is entity not found, we need also entity not found in the processed entity to keep entity not found + // Otherwise, two possibilities: 1) if processed entity is full attrs fail, global UC changes so, or 2) if processed entity is + // success/partial, the global UC changes to partial + if (entityUpdateCoverage == UC_ENTITY_NOT_FOUND) + { + // do nothing (explicity block here for the sake of clearness) + } + else + { + if (entityUpdateCoverage == UC_FULL_ATTRS_FAIL) + { + updateCoverage = UC_FULL_ATTRS_FAIL; + } + else + { + updateCoverage = UC_PARTIAL; + } + } + break; case UC_PARTIAL: - updateCoverage = UC_PARTIAL; + // If global UC is partial, we keep partial (no matter the result of processed entity) break; } } @@ -196,6 +221,7 @@ HttpStatusCode mongoUpdateContext // Other cases follow the usual response processing flow (whatever it is :) if (updateCoverage == UC_PARTIAL) { + responseP->oe.code = SccInvalidModification; responseP->oe.reasonPhrase = ERROR_PARTIAL_UPDATE; } diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index eed3f0b7c0..3f178f690e 100644 --- a/src/lib/rest/OrionError.cpp +++ b/src/lib/rest/OrionError.cpp @@ -42,6 +42,7 @@ OrionError::OrionError() code = SccNone; reasonPhrase = ""; details = ""; + filled = false; } @@ -55,6 +56,7 @@ OrionError::OrionError(HttpStatusCode _code, const std::string& _details, const code = _code; reasonPhrase = _reasonPhrase.empty() ? httpStatusCodeString(code) : _reasonPhrase; details = _details; + filled = true; } @@ -68,6 +70,7 @@ OrionError::OrionError(StatusCode& sc) code = sc.code; reasonPhrase = httpStatusCodeString(code); details = sc.details; + filled = true; } @@ -81,6 +84,21 @@ void OrionError::fill(HttpStatusCode _code, const std::string& _details, const s code = _code; reasonPhrase = _reasonPhrase.empty()? httpStatusCodeString(code) : _reasonPhrase; details = _details; + filled = true; +} + + + +/* **************************************************************************** +* +* OrionError::fill - +*/ +void OrionError::fill(const StatusCode& sc) +{ + code = sc.code; + reasonPhrase = (sc.reasonPhrase.empty())? httpStatusCodeString(code) : sc.reasonPhrase; + details = sc.details; + filled = true; } @@ -91,7 +109,7 @@ void OrionError::fill(HttpStatusCode _code, const std::string& _details, const s */ void OrionError::fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase) { - if (code == _code) + if (filled) { // Already filled by a previous operation. This can happen in batch update processing details += appendDetail; @@ -101,24 +119,12 @@ void OrionError::fillOrAppend(HttpStatusCode _code, const std::string& fullDetai code = _code; reasonPhrase = _reasonPhrase.empty()? httpStatusCodeString(code) : _reasonPhrase; details = fullDetails; + filled = true; } } -/* **************************************************************************** -* -* OrionError::fill - -*/ -void OrionError::fill(const StatusCode& sc) -{ - code = sc.code; - reasonPhrase = (sc.reasonPhrase.empty())? httpStatusCodeString(code) : sc.reasonPhrase; - details = sc.details; -} - - - /* **************************************************************************** * * OrionError::smartRender - diff --git a/src/lib/rest/OrionError.h b/src/lib/rest/OrionError.h index d656bac8c9..ab6110c944 100644 --- a/src/lib/rest/OrionError.h +++ b/src/lib/rest/OrionError.h @@ -44,6 +44,7 @@ typedef struct OrionError HttpStatusCode code; std::string reasonPhrase; std::string details; + bool filled; OrionError(); OrionError(StatusCode& statusCode); diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test b/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test index b9e1c5da97..4cf92b1dfd 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_APPEND.test @@ -202,10 +202,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 113 +Content-Length: 116 { - "description": "one or more of the attributes in the request already exist: E1 - [ A1 ]", + "description": "one or more of the attributes in the request already exist: E1/T1 - [ A1 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test index 73c69b1b76..f18c6bb798 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test @@ -132,15 +132,15 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) 04. Delete E1 again, see it fail ================================ -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 121 +Content-Length: 74 { - "description": "one or more of the attributes in the request do not exist: E1 - [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E1/T1 - [entity itself]", + "error": "NotFound" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test index 0711ce279d..c08cdd99d1 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing.test @@ -233,10 +233,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 69 { - "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", + "description": "do not exist: E2/T - [ A2 ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test index d6f1638a6f..16a31aa672 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test @@ -271,10 +271,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 125 +Content-Length: 84 { - "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ], E4 - [ A1 ]", + "description": "do not exist: E2/T - [ A2 ], E4/T - [ A1 ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test index aa7b436961..e53db2c35c 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_attr.test @@ -203,10 +203,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 69 { - "description": "one or more of the attributes in the request do not exist: E2 - [ A2 ]", + "description": "do not exist: E2/T - [ A2 ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test b/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test index 6c5a4b536d..e1f6702472 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_UPDATE.test @@ -189,10 +189,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: E1 - [ A3 ]", + "description": "do not exist: E1/T1 - [ A3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test b/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test index e2bd1228a7..8efbe70a3f 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_error_entity_not_found.test @@ -86,43 +86,43 @@ echo --REGEXPECT-- 01. Batch Update with actionType UPDATE on non-existing entity, see error ========================================================================= -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 72 { - "description": "one or more of the attributes in the request do not exist: E - [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E/T - [entity itself]", + "error": "NotFound" } 02. Batch Update with actionType DELETE on non-existing entity, see error ========================================================================= -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 72 { - "description": "one or more of the attributes in the request do not exist: E - [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E/T - [entity itself]", + "error": "NotFound" } 03. Batch Update with actionType REPLACE on non-existing entity, see error ========================================================================== -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 72 { - "description": "one or more of the attributes in the request do not exist: E - [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E/T - [entity itself]", + "error": "NotFound" } diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test index d72fcb6cc8..1f0891f10b 100644 --- a/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test @@ -321,10 +321,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 130 +Content-Length: 134 { - "description": "one or more of the attributes in the request already exist: E1 - [ A, B ], E2 - [ A, B ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ A, B ], E2/T - [ A, B ]", "error": "Unprocessable" } @@ -335,10 +335,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 115 +Content-Length: 117 { - "description": "one or more of the attributes in the request already exist: E2 - [ A, B ]", + "description": "one or more of the attributes in the request already exist: E2/T - [ A, B ]", "error": "PartialUpdate" } @@ -349,10 +349,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 114 { - "description": "one or more of the attributes in the request already exist: E1 - [ A ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ A ]", "error": "PartialUpdate" } @@ -363,10 +363,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 127 +Content-Length: 131 { - "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A, B ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ A ], E2/T - [ A, B ]", "error": "PartialUpdate" } @@ -377,10 +377,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 124 +Content-Length: 128 { - "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ A ], E2/T - [ A ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test index c6fa5be4bc..87c733b3c2 100644 --- a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test @@ -233,8 +233,8 @@ echo echo -echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable" -echo "=======================================================================" +echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): NotFound" +echo "==================================================================" payload='{ "actionType": "delete", "entities": @@ -435,17 +435,17 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) -03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable -======================================================================= -HTTP/1.1 422 Unprocessable Content +03. Update E3-A/B (full fail) + E4-A/B (full fail): NotFound +================================================================== +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 141 +Content-Length: 97 { - "description": "one or more of the attributes in the request do not exist: E3 - [entity itself], E4 [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E3/T3 - [entity itself], E4/T3 [entity itself]", + "error": "NotFound" } @@ -455,10 +455,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 121 +Content-Length: 79 { - "description": "one or more of the attributes in the request do not exist: E3 - [entity itself]", + "description": "do not exist: E3/T4 - [entity itself]", "error": "PartialUpdate" } @@ -469,10 +469,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 69 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ]", + "description": "do not exist: E1/T5 - [ C ]", "error": "PartialUpdate" } @@ -483,10 +483,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 131 +Content-Length: 92 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E3 [entity itself]", + "description": "do not exist: E1/T6 - [ C ], E3/T6 [entity itself]", "error": "PartialUpdate" } @@ -497,10 +497,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 123 +Content-Length: 84 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E2 - [ C ]", + "description": "do not exist: E1/T7 - [ C ], E2/T7 - [ C ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test index dff1cdc418..459bf73bc6 100644 --- a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test @@ -114,8 +114,8 @@ echo echo -echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable" -echo "=======================================================================" +echo "03. Update E3-A/B (full fail) + E4-A/B (full fail): NotFound" +echo "==================================================================" payload='{ "actionType": "update", "entities": @@ -316,17 +316,17 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) -03. Update E3-A/B (full fail) + E4-A/B (full fail): Unprocessable -======================================================================= -HTTP/1.1 422 Unprocessable Content +03. Update E3-A/B (full fail) + E4-A/B (full fail): NotFound +================================================================== +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 141 +Content-Length: 95 { - "description": "one or more of the attributes in the request do not exist: E3 - [entity itself], E4 [entity itself]", - "error": "Unprocessable" + "description": "do not exist: E3/T - [entity itself], E4/T [entity itself]", + "error": "NotFound" } @@ -336,10 +336,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 121 +Content-Length: 78 { - "description": "one or more of the attributes in the request do not exist: E3 - [entity itself]", + "description": "do not exist: E3/T - [entity itself]", "error": "PartialUpdate" } @@ -350,10 +350,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 68 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ]", + "description": "do not exist: E1/T - [ C ]", "error": "PartialUpdate" } @@ -364,10 +364,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 131 +Content-Length: 90 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E3 [entity itself]", + "description": "do not exist: E1/T - [ C ], E3/T [entity itself]", "error": "PartialUpdate" } @@ -378,10 +378,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 123 +Content-Length: 82 { - "description": "one or more of the attributes in the request do not exist: E1 - [ C ], E2 - [ C ]", + "description": "do not exist: E1/T - [ C ], E2/T - [ C ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test index ba43328e5e..729203db11 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test @@ -141,10 +141,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 113 { - "description": "one or more of the attributes in the request already exist: E - [ A ]", + "description": "one or more of the attributes in the request already exist: E/T - [ A ]", "error": "PartialUpdate" } @@ -184,10 +184,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 113 { - "description": "one or more of the attributes in the request already exist: E - [ B ]", + "description": "one or more of the attributes in the request already exist: E/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test index 0c949c092d..5e0162caa4 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test @@ -225,10 +225,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 145 +Content-Length: 151 { - "description": "one or more of the attributes in the request already exist: E1 - [ A ], E2 - [ A, B ], E3 - [ A, B, C ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ A ], E2/T - [ A, B ], E3/T - [ A, B, C ]", "error": "PartialUpdate" } @@ -308,10 +308,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 136 +Content-Length: 142 { - "description": "one or more of the attributes in the request already exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", + "description": "one or more of the attributes in the request already exist: E1/T - [ B ], E2/T - [ B ], E3/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test index 8feabbe5be..9916059ffc 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test @@ -145,10 +145,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 113 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", + "description": "do not exist: E/T - [ B, C ]", "error": "PartialUpdate" } @@ -178,10 +178,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 110 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: E - [ B ]", + "description": "do not exist: E/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test index aec5c87f14..4eaba2cf4f 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test @@ -238,10 +238,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 126 +Content-Length: 85 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", + "description": "do not exist: E1/T - [ B, C ], E2/T - [ C ]", "error": "PartialUpdate" } @@ -291,10 +291,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 135 +Content-Length: 96 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 - [ B ], E3 - [ B ]", + "description": "do not exist: E1/T - [ B ], E2/T - [ B ], E3/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test index 1bd68a7642..8141fb7a12 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test @@ -221,10 +221,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 134 +Content-Length: 93 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", + "description": "do not exist: E1/T - [ B, C ], E2/T [entity itself]", "error": "PartialUpdate" } @@ -265,10 +265,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 143 +Content-Length: 104 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself], E3 - [ B ]", + "description": "do not exist: E1/T - [ B ], E2/T [entity itself], E3/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test index 93999321d6..61492c7492 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test @@ -141,10 +141,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 113 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: E - [ B, C ]", + "description": "do not exist: E/T - [ B, C ]", "error": "PartialUpdate" } @@ -174,10 +174,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 110 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: E - [ B ]", + "description": "do not exist: E/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test index 3059d751be..0e8a9e5fef 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test @@ -225,10 +225,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 126 +Content-Length: 85 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 - [ C ]", + "description": "do not exist: E1/T - [ B, C ], E2/T - [ C ]", "error": "PartialUpdate" } @@ -293,10 +293,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 111 +Content-Length: 68 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B ]", + "description": "do not exist: E1/T - [ B ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test index 01904cc414..f22dd0dc35 100644 --- a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test @@ -213,10 +213,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 134 +Content-Length: 93 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B, C ], E2 [entity itself]", + "description": "do not exist: E1/T - [ B, C ], E2/T [entity itself]", "error": "PartialUpdate" } @@ -267,10 +267,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 131 +Content-Length: 90 { - "description": "one or more of the attributes in the request do not exist: E1 - [ B ], E2 [entity itself]", + "description": "do not exist: E1/T - [ B ], E2/T [entity itself]", "error": "PartialUpdate" } From e41242548b3587ac3f8a233f875bcb7db9e9bb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 28 Nov 2023 16:28:19 +0100 Subject: [PATCH 17/34] FIX response error string --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 6af0df9bcd..515b7c0105 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4124,14 +4124,16 @@ unsigned int processContextElement const std::string idString = "_id." ENT_ENTITY_ID; const std::string typeString = "_id." ENT_ENTITY_TYPE; - EntityId en(eP->id, eP->type); - orion::BSONObjBuilder bob; + orion::BSONObjBuilder bob; + EntityId en(eP->id, eP->type); + std::string enStr = eP->id; bob.append(idString, eP->id); if (!eP->type.empty()) { bob.append(typeString, eP->type); + enStr += '/' + eP->type; } // Service path @@ -4338,9 +4340,8 @@ unsigned int processContextElement } else { - //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); - std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - [entity itself]"; - responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + eP->id + "/" + eP->type + " [entity itself]", ERROR_NOT_FOUND); + std::string details = ERROR_DESC_DO_NOT_EXIT + enStr + " - [entity itself]"; + responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + enStr + " [entity itself]", ERROR_NOT_FOUND); if (updateCoverageP != NULL) { *updateCoverageP = UC_ENTITY_NOT_FOUND; @@ -4352,9 +4353,8 @@ unsigned int processContextElement { cerP->statusCode.fill(SccContextElementNotFound); - //responseP->oe.fillOrAppend(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ", " + eP->id + " [entity itself]", ERROR_NOT_FOUND); - std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - [entity itself]"; - responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + eP->id + "/" + eP->type + " [entity itself]", ERROR_NOT_FOUND); + std::string details = ERROR_DESC_DO_NOT_EXIT + enStr + " - [entity itself]"; + responseP->oe.fillOrAppend(SccContextElementNotFound, details, ", " + enStr + " [entity itself]", ERROR_NOT_FOUND); responseP->contextElementResponseVector.push_back(cerP); if (updateCoverageP != NULL) { @@ -4459,16 +4459,16 @@ unsigned int processContextElement if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { - std::string details = ERROR_DESC_UNPROCESSABLE_ATTR_ALREADY_EXISTS + eP->id + "/" + eP->type + " - " + attributeAlreadyExistsList; + std::string details = ERROR_DESC_UNPROCESSABLE_ATTR_ALREADY_EXISTS + enStr + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + "/" + eP->type + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + enStr + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } if ((apiVersion == V2) && (attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { - std::string details = ERROR_DESC_DO_NOT_EXIT + eP->id + "/" + eP->type + " - " + attributeNotExistingList; + std::string details = ERROR_DESC_DO_NOT_EXIT + enStr + " - " + attributeNotExistingList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + eP->id + "/" + eP->type + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + enStr + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); } if (updateCoverageP != NULL) From c5e74e8818a81a6a552a258fcb6f60adeccf0071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Tue, 28 Nov 2023 17:45:44 +0100 Subject: [PATCH 18/34] FIX single entity error description in responses --- src/lib/serviceRoutinesV2/patchEntity.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/serviceRoutinesV2/patchEntity.cpp b/src/lib/serviceRoutinesV2/patchEntity.cpp index 8c505d4bc0..c31c5749b5 100644 --- a/src/lib/serviceRoutinesV2/patchEntity.cpp +++ b/src/lib/serviceRoutinesV2/patchEntity.cpp @@ -85,6 +85,12 @@ std::string patchEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust NotFound description (to avoid redundant missing entity information) + if (parseDataP->upcrs.res.oe.code == SccContextElementNotFound) + { + parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; + } + // 03. Check output from mongoBackend - any errors? if (parseDataP->upcrs.res.oe.code != SccNone ) { From 32bec9f650a394ebee021ff6140a20601474c999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 13:16:20 +0100 Subject: [PATCH 19/34] FIX error reponses for the NotFound case with CPrs in place --- src/lib/serviceRoutinesV2/patchEntity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/serviceRoutinesV2/patchEntity.cpp b/src/lib/serviceRoutinesV2/patchEntity.cpp index c31c5749b5..2d30a9acaa 100644 --- a/src/lib/serviceRoutinesV2/patchEntity.cpp +++ b/src/lib/serviceRoutinesV2/patchEntity.cpp @@ -86,7 +86,7 @@ std::string patchEntity postUpdateContext(ciP, components, compV, parseDataP); // Adjust NotFound description (to avoid redundant missing entity information) - if (parseDataP->upcrs.res.oe.code == SccContextElementNotFound) + if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) { parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; } From d6e484d635ab7ed4ab3b49053805bba5d1164d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 13:34:47 +0100 Subject: [PATCH 20/34] FIX single error description responses --- src/lib/serviceRoutinesV2/putEntityAttribute.cpp | 6 ++++++ .../invalid_error_updating_non_existing_attribute.test | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp index 59ca2e8d4e..b3ef79c042 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp @@ -84,6 +84,12 @@ std::string putEntityAttribute // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust NotFound description (to avoid redundant missing entity information) + if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) + { + parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; + } + // 03. Check error std::string answer = ""; if (parseDataP->upcrs.res.oe.code != SccNone ) diff --git a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test index 0da279cbfb..2592785cec 100644 --- a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test +++ b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test @@ -83,10 +83,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", + "description": "do not exist: E1 - [ A2 ]", "error": "Unprocessable" } From 34b23149b4e0c64bcda9ed718f58eb3cd68fb69c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 15:21:51 +0100 Subject: [PATCH 21/34] FIX old ftest --- src/lib/mongoBackend/MongoCommonUpdate.cpp | 5 ++++- src/lib/serviceRoutinesV2/deleteEntity.cpp | 7 +++++++ src/lib/serviceRoutinesV2/patchEntity.cpp | 1 + src/lib/serviceRoutinesV2/putEntity.cpp | 7 +++++++ src/lib/serviceRoutinesV2/putEntityAttribute.cpp | 1 + src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp | 8 ++++++++ .../0979_patch_v2_entities_eid/patch_v2_entities_eid.test | 4 ++-- .../patch_entity_with_param_type.test | 4 ++-- .../982_post_entity_with_type_param.test | 4 ++-- .../0993_DELETE_v2_entity_attr/delete_not_exist_attr.test | 4 ++-- .../cases/1127_v1_append_strict/v1_append_strict.test | 8 ++++---- .../patch_unknown_attribute.test | 4 ++-- .../error_response_for_entity_not_found.test | 4 ++-- .../patch_non_existing_attribute.test | 4 ++-- .../PATCH_offending_attributes.test | 8 ++++---- 15 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 515b7c0105..6fba6a2fb9 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4112,7 +4112,10 @@ unsigned int processContextElement ) { // By default, assume everything is gone to be ok. Next in this function we are going to check for some partial/failure cases - *updateCoverageP = UC_SUCCESS; + if (updateCoverageP != NULL) + { + *updateCoverageP = UC_SUCCESS; + } /* Check preconditions */ if (!contextElementPreconditionsCheck(eP, responseP, action, apiVersion)) diff --git a/src/lib/serviceRoutinesV2/deleteEntity.cpp b/src/lib/serviceRoutinesV2/deleteEntity.cpp index 45015a83d4..0330694791 100644 --- a/src/lib/serviceRoutinesV2/deleteEntity.cpp +++ b/src/lib/serviceRoutinesV2/deleteEntity.cpp @@ -90,6 +90,13 @@ std::string deleteEntity // Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust NotFound description (to avoid redundant missing entity information) + // FIXME PR: duplicated code in several places + if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) + { + parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; + } + ciP->outMimeType = JSON; // Check for potential error diff --git a/src/lib/serviceRoutinesV2/patchEntity.cpp b/src/lib/serviceRoutinesV2/patchEntity.cpp index 2d30a9acaa..dbc750930f 100644 --- a/src/lib/serviceRoutinesV2/patchEntity.cpp +++ b/src/lib/serviceRoutinesV2/patchEntity.cpp @@ -86,6 +86,7 @@ std::string patchEntity postUpdateContext(ciP, components, compV, parseDataP); // Adjust NotFound description (to avoid redundant missing entity information) + // FIXME PR: duplicated code in several places if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) { parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; diff --git a/src/lib/serviceRoutinesV2/putEntity.cpp b/src/lib/serviceRoutinesV2/putEntity.cpp index 5df120b028..d44b23190a 100644 --- a/src/lib/serviceRoutinesV2/putEntity.cpp +++ b/src/lib/serviceRoutinesV2/putEntity.cpp @@ -84,6 +84,13 @@ std::string putEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust NotFound description (to avoid redundant missing entity information) + // FIXME PR: duplicated code in several places + if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) + { + parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; + } + // 03. Check error std::string answer = ""; if (parseDataP->upcrs.res.oe.code != SccNone ) diff --git a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp index b3ef79c042..53204127ac 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp @@ -85,6 +85,7 @@ std::string putEntityAttribute postUpdateContext(ciP, components, compV, parseDataP); // Adjust NotFound description (to avoid redundant missing entity information) + // FIXME PR: duplicated code in several places if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) { parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; diff --git a/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp b/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp index ce14f00684..c4e8ea8f18 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp @@ -91,6 +91,14 @@ std::string putEntityAttributeValue // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust NotFound description (to avoid redundant missing entity information) + // FIXME PR: duplicated code in several places + if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) + { + parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; + } + + // 03. Check output from mongoBackend std::string answer = ""; if (parseDataP->upcrs.res.oe.code != SccNone) diff --git a/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test b/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test index 5848be90e5..2c5540c1ad 100644 --- a/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test +++ b/test/functionalTest/cases/0979_patch_v2_entities_eid/patch_v2_entities_eid.test @@ -171,10 +171,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 115 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: E1 - [ attr3 ]", + "description": "do not exist: E1 - [ attr3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test b/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test index 41c90e2615..2d2c87bbbe 100644 --- a/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test +++ b/test/functionalTest/cases/0980_patch_entity_v2_wihth_param_type/patch_entity_with_param_type.test @@ -169,10 +169,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", + "description": "do not exist: E1/T1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test b/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test index 3208886ffb..943a3c5436 100644 --- a/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test +++ b/test/functionalTest/cases/0982_post_entity_with_type_param/982_post_entity_with_type_param.test @@ -238,10 +238,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 113 +Content-Length: 116 { - "description": "one or more of the attributes in the request already exist: E1 - [ A3 ]", + "description": "one or more of the attributes in the request already exist: E1/T2 - [ A3 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test index ae337a1564..1f6638006d 100644 --- a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test +++ b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test @@ -106,10 +106,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 114 +Content-Length: 69 { - "description": "one or more of the attributes in the request do not exist: E1 - [ none ]", + "description": "do not exist: E1 - [ none ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test b/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test index 6588f5b23e..746ea2c18c 100644 --- a/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test +++ b/test/functionalTest/cases/1127_v1_append_strict/v1_append_strict.test @@ -239,7 +239,7 @@ HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 229 +Content-Length: 232 { "contextResponses": [ @@ -251,7 +251,7 @@ Content-Length: 229 }, "statusCode": { "code": "400", - "details": "one or more of the attributes in the request already exist: E1 - [ attr2 ]", + "details": "one or more of the attributes in the request already exist: E1/T1 - [ attr2 ]", "reasonPhrase": "Bad Request" } } @@ -289,7 +289,7 @@ HTTP/1.1 200 OK Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 393 +Content-Length: 396 { "contextResponses": [ @@ -319,7 +319,7 @@ Content-Length: 393 }, "statusCode": { "code": "400", - "details": "one or more of the attributes in the request already exist: E1 - [ attr2 ]", + "details": "one or more of the attributes in the request already exist: E1/T1 - [ attr2 ]", "reasonPhrase": "Bad Request" } } diff --git a/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test b/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test index 555d8cefda..5a91ddffa1 100644 --- a/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test +++ b/test/functionalTest/cases/1278_patch_unknown_attribute/patch_unknown_attribute.test @@ -75,10 +75,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", + "description": "do not exist: E1 - [ A2 ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test index 11cca7a827..70b67f7e68 100644 --- a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test +++ b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test @@ -97,10 +97,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 122 +Content-Length: 77 { - "description": "one or more of the attributes in the request do not exist: room_2 - [ dfgdfgdf ]", + "description": "do not exist: room_2 - [ dfgdfgdf ]", "error": "Unprocessable" } diff --git a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test index 7c84e5ef49..d57bda6493 100644 --- a/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test +++ b/test/functionalTest/cases/1784_patch_non_existing_attribute/patch_non_existing_attribute.test @@ -89,10 +89,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: E1 - [ A2 ]", + "description": "do not exist: E1 - [ A2 ]", "error": "PartialUpdate" } diff --git a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test index 0ccf23b652..a69fc89d16 100644 --- a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test +++ b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test @@ -117,10 +117,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 75 { - "description": "one or more of the attributes in the request do not exist: Room1 - [ pressur ]", + "description": "do not exist: Room1 - [ pressur ]", "error": "PartialUpdate" } @@ -131,10 +131,10 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 128 +Content-Length: 83 { - "description": "one or more of the attributes in the request do not exist: Room1 - [ temper, pressur ]", + "description": "do not exist: Room1 - [ temper, pressur ]", "error": "PartialUpdate" } From 8163e116a07492350c2bbdc22d8b5ee24737a3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 16:42:09 +0100 Subject: [PATCH 22/34] FIX rename ftest --- ...appendstrict.test => batch_all_combinations_appendstrict.test} | 0 ...ombinations_delete.test => batch_all_combinations_delete.test} | 0 ...ombinations_update.test => batch_all_combinations_update.test} | 0 ...dstrict.test => batch_partial_update_action_appendstrict.test} | 0 ...atch_partial_update_action_appendstrict_several_entities.test} | 0 ...action_delete.test => batch_partial_update_action_delete.test} | 0 ...t => batch_partial_update_action_delete_several_entities.test} | 0 ...rtial_update_action_delete_several_entities_non_existing.test} | 0 ...action_update.test => batch_partial_update_action_update.test} | 0 ...t => batch_partial_update_action_update_several_entities.test} | 0 ...rtial_update_action_update_several_entities_non_existing.test} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename test/functionalTest/cases/3499_partial_update_response/{all_combinations_appendstrict.test => batch_all_combinations_appendstrict.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{all_combinations_delete.test => batch_all_combinations_delete.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{all_combinations_update.test => batch_all_combinations_update.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_appendstrict.test => batch_partial_update_action_appendstrict.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_appendstrict_several_entities.test => batch_partial_update_action_appendstrict_several_entities.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_delete.test => batch_partial_update_action_delete.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_delete_several_entities.test => batch_partial_update_action_delete_several_entities.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_delete_several_entities_non_existing.test => batch_partial_update_action_delete_several_entities_non_existing.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_update.test => batch_partial_update_action_update.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_update_several_entities.test => batch_partial_update_action_update_several_entities.test} (100%) rename test/functionalTest/cases/3499_partial_update_response/{partial_update_action_update_several_entities_non_existing.test => batch_partial_update_action_update_several_entities_non_existing.test} (100%) diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/all_combinations_appendstrict.test rename to test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/all_combinations_delete.test rename to test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test diff --git a/test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/all_combinations_update.test rename to test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_appendstrict_several_entities.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_delete_several_entities_non_existing.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_update.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test diff --git a/test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test similarity index 100% rename from test/functionalTest/cases/3499_partial_update_response/partial_update_action_update_several_entities_non_existing.test rename to test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test From 3def719df46f4eb1be49e08910c9a8212b76bd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 17:18:25 +0100 Subject: [PATCH 23/34] ADD test caes for single update cases --- .../batch_all_combinations_appendstrict.test | 2 +- .../batch_all_combinations_delete.test | 2 +- .../batch_all_combinations_update.test | 2 +- ...ch_partial_update_action_appendstrict.test | 2 +- ..._action_appendstrict_several_entities.test | 2 +- .../batch_partial_update_action_delete.test | 2 +- ...update_action_delete_several_entities.test | 2 +- ..._delete_several_entities_non_existing.test | 2 +- .../batch_partial_update_action_update.test | 2 +- ...update_action_update_several_entities.test | 2 +- ..._update_several_entities_non_existing.test | 2 +- .../single_all_combinations_appendstrict.test | 200 ++++++++++++++++++ .../single_all_combinations_delete.test | 116 ++++++++++ .../single_all_combinations_update.test | 200 ++++++++++++++++++ 14 files changed, 527 insertions(+), 11 deletions(-) create mode 100644 test/functionalTest/cases/3499_partial_update_response/single_all_combinations_appendstrict.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test create mode 100644 test/functionalTest/cases/3499_partial_update_response/single_all_combinations_update.test diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test index 1f0891f10b..f8b2e1c410 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_appendstrict.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -All fail/success/partial combinations for appendStrict actionType +All fail/success/partial combinations for appendStrict actionType in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test index 87c733b3c2..4f807d90df 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_delete.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -All fail/success/partial combinations for delete actionType +All fail/success/partial combinations for delete actionType in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test index 459bf73bc6..1f95ea79e5 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_all_combinations_update.test @@ -22,7 +22,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -All fail/success/partial combinations for update actionType +All fail/success/partial combinations for update actionType in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test index 729203db11..6c15add5d7 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for appendStrict case +PartialUpdate response for appendStrict case in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test index 5e0162caa4..5dc96ef8f6 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for appendStrict case for several entities +PartialUpdate response for appendStrict case for several entities in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test index 9916059ffc..c7add1534d 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for delete case +PartialUpdate response for delete case in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test index 4eaba2cf4f..4a8e4536c9 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for delete case for several entities +PartialUpdate response for delete case for several entities in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test index 8141fb7a12..1728cf0292 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities_non_existing.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for delete case for several entities one of them non existing +PartialUpdate response for delete case for several entities one of them non existing in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test index 61492c7492..2ffe7c4fe8 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for update case +PartialUpdate response for update case in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test index 0e8a9e5fef..4543a819fb 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for update case for several entities +PartialUpdate response for update case for several entities in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test index f22dd0dc35..2073cc7391 100644 --- a/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities_non_existing.test @@ -21,7 +21,7 @@ # VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh --NAME-- -PartialUpdate response for update case for several entities one of them non existing +PartialUpdate response for update case for several entities one of them non existing in batch operation --SHELL-INIT-- dbInit CB diff --git a/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_appendstrict.test b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_appendstrict.test new file mode 100644 index 0000000000..ddeb1e4024 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_appendstrict.test @@ -0,0 +1,200 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for append strict in single update operation + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E-A/B +# 02. POST /v2/entities/E/attrs?options=append A/B (full fail) +# 03. POST /v2/entities/E/attrs?options=append B/C (partial fail) +# 04. POST /v2/entities/E/attrs?type=T&options=append A/B (full fail) +# 05. POST /v2/entities/E/attrs?type=T&options=append B/D (partial fail) +# + +echo "01. Create E-A/B" +echo "================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. POST /v2/entities/E/attrs?options=append A/B (full fail)" +echo "============================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?options=append' --payload "$payload" +echo +echo + + +echo "03. POST /v2/entities/E/attrs?options=append B/C (partial fail)" +echo "===============================================================" +payload='{ + "B": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?options=append' --payload "$payload" +echo +echo + + +echo "04. POST /v2/entities/E/attrs?type=T&options=append A/B (full fail)" +echo "===================================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?type=T&options=append' --payload "$payload" +echo +echo + + +echo "05. POST /v2/entities/E/attrs?type=T&options=append B/D (partial fail)" +echo "======================================================================" +payload='{ + "B": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?type=T&options=append' --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create E-A/B +================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. POST /v2/entities/E/attrs?options=append A/B (full fail) +============================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 114 + +{ + "description": "one or more of the attributes in the request already exist: E - [ A, B ]", + "error": "Unprocessable" +} + + +03. POST /v2/entities/E/attrs?options=append B/C (partial fail) +=============================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request already exist: E - [ B ]", + "error": "PartialUpdate" +} + + +04. POST /v2/entities/E/attrs?type=T&options=append A/B (full fail) +=================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 116 + +{ + "description": "one or more of the attributes in the request already exist: E/T - [ A, B ]", + "error": "Unprocessable" +} + + +05. POST /v2/entities/E/attrs?type=T&options=append B/D (partial fail) +====================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 113 + +{ + "description": "one or more of the attributes in the request already exist: E/T - [ B ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test new file mode 100644 index 0000000000..edd9ab999c --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test @@ -0,0 +1,116 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for update in single update operation + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E-A/B +# 02. DELETE /v2/entities/E/attrs/C (full fail) +# 03. DELETE /v2/entities/E/attrs/C?type=T (full fail) +# + +echo "01. Create E-A/B" +echo "================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. DELETE /v2/entities/E/attrs/C (full fail)" +echo "=============================================" +orionCurl --url '/v2/entities/E/attrs/C' -X DELETE +echo +echo + + +echo "03. DELETE /v2/entities/E/attrs/C?type=T (full fail)" +echo "====================================================" +orionCurl --url '/v2/entities/E/attrs/C?type=T' -X DELETE +echo +echo + + +--REGEXPECT-- +01. Create E-A/B +================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. DELETE /v2/entities/E/attrs/C (full fail) +============================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 65 + +{ + "description": "do not exist: E - [ C ]", + "error": "Unprocessable" +} + + +03. DELETE /v2/entities/E/attrs/C?type=T (full fail) +==================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 67 + +{ + "description": "do not exist: E/T - [ C ]", + "error": "Unprocessable" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_update.test b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_update.test new file mode 100644 index 0000000000..00ee708439 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_update.test @@ -0,0 +1,200 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +All fail/success/partial combinations for update in single update operation + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# +# 01. Create E-A/B +# 02. PATCH /v2/entities/E/attrs C/D (full fail) +# 03. PATCH /v2/entities/E/attrs A/C (partial fail) +# 04. PATCH /v2/entities/E/attrs?type=T C/D (full fail) +# 05. PATCH /v2/entities/E/attrs?type=T A/C (partial fail) +# + +echo "01. Create E-A/B" +echo "================" +payload='{ + "actionType": "appendStrict", + "entities": + [ + { + "type": "T", + "id": "E", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 2, + "type": "Number" + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. PATCH /v2/entities/E/attrs C/D (full fail)" +echo "==============================================" +payload='{ + "C": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs' --payload "$payload" -X PATCH +echo +echo + + +echo "03. PATCH /v2/entities/E/attrs A/C (partial fail)" +echo "=================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs' --payload "$payload" -X PATCH +echo +echo + + +echo "04. PATCH /v2/entities/E/attrs?type=T C/D (full fail)" +echo "=====================================================" +payload='{ + "C": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?type=T' --payload "$payload" -X PATCH +echo +echo + + +echo "05. PATCH /v2/entities/E/attrs?type=T A/C (partial fail)" +echo "========================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url '/v2/entities/E/attrs?type=T' --payload "$payload" -X PATCH +echo +echo + + +--REGEXPECT-- +01. Create E-A/B +================ +HTTP/1.1 204 No Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +02. PATCH /v2/entities/E/attrs C/D (full fail) +============================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 68 + +{ + "description": "do not exist: E - [ C, D ]", + "error": "Unprocessable" +} + + +03. PATCH /v2/entities/E/attrs A/C (partial fail) +================================================= +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 65 + +{ + "description": "do not exist: E - [ C ]", + "error": "PartialUpdate" +} + + +04. PATCH /v2/entities/E/attrs?type=T C/D (full fail) +===================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 70 + +{ + "description": "do not exist: E/T - [ C, D ]", + "error": "Unprocessable" +} + + +05. PATCH /v2/entities/E/attrs?type=T A/C (partial fail) +======================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 67 + +{ + "description": "do not exist: E/T - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From 3ac1bfc1567cbc373512f68158ad7ab63c666b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 29 Nov 2023 17:39:55 +0100 Subject: [PATCH 24/34] Update CHANGES_NEXT_RELEASE --- CHANGES_NEXT_RELEASE | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index ba5b1b9d9b..4038fd3329 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -3,7 +3,8 @@ - Fix: correctly detect JSON attribute and metadata value changes in subscription triggering logic (#4211, #4434, #643) - Fix: DateTime and geo:json types were not supported in custom notifications using ngsi patching (#4435) - Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated) -- Fix: on delete attributes operation the lack of attribute in entity doesn't precules attributes which do exist (this way behaving same way as update attributes operation) +- Fix: improve error traces (#4387) +- Fix: on delete attributes operation the lack of attribute in entity doesn't precule attributes which do exist (this way behaving same way as update attributes operation) - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) - Fix: improve logs in MongoDB query logic - Upgrade Debian version from 11.6 to 12.1 in Dockerfile From 48c5ca456e58949d25588841d7b5f19d625681b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Thu, 30 Nov 2023 17:21:08 +0100 Subject: [PATCH 25/34] FIX adjust response codes --- CHANGES_NEXT_RELEASE | 2 +- src/lib/serviceRoutinesV2/deleteEntity.cpp | 11 ++++----- src/lib/serviceRoutinesV2/patchEntity.cpp | 9 +++---- .../serviceRoutinesV2/putEntityAttribute.cpp | 9 +++---- .../serviceRoutinesCommon.cpp | 24 +++++++++++++++++++ .../serviceRoutinesV2/serviceRoutinesCommon.h | 10 ++++++++ .../delete_not_exist_attr.test | 8 +++---- .../single_all_combinations_delete.test | 16 ++++++------- 8 files changed, 57 insertions(+), 32 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 4038fd3329..7f815e5662 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -4,7 +4,7 @@ - Fix: DateTime and geo:json types were not supported in custom notifications using ngsi patching (#4435) - Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated) - Fix: improve error traces (#4387) -- Fix: on delete attributes operation the lack of attribute in entity doesn't precule attributes which do exist (this way behaving same way as update attributes operation) +- Fix: on delete attributes operation, the lack of attribute in entity doesn't preclude the deletion of attributes which do exist (this way behaving same way as update attributes operation) - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) - Fix: improve logs in MongoDB query logic - Upgrade Debian version from 11.6 to 12.1 in Dockerfile diff --git a/src/lib/serviceRoutinesV2/deleteEntity.cpp b/src/lib/serviceRoutinesV2/deleteEntity.cpp index 0330694791..f70eaa226c 100644 --- a/src/lib/serviceRoutinesV2/deleteEntity.cpp +++ b/src/lib/serviceRoutinesV2/deleteEntity.cpp @@ -35,6 +35,7 @@ #include "rest/OrionError.h" #include "rest/EntityTypeInfo.h" #include "serviceRoutinesV2/deleteEntity.h" +#include "serviceRoutinesV2/serviceRoutinesCommon.h" #include "serviceRoutines/postUpdateContext.h" #include "parse/forbiddenChars.h" @@ -44,7 +45,7 @@ * * deleteEntity - * -* DELETE /v2/entities/{entityId} +* DELETE /v2/entities/{entityId}[/attrs/{attrName}] * * Payload In: None * Payload Out: None @@ -90,12 +91,8 @@ std::string deleteEntity // Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); - // Adjust NotFound description (to avoid redundant missing entity information) - // FIXME PR: duplicated code in several places - if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) - { - parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; - } + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); ciP->outMimeType = JSON; diff --git a/src/lib/serviceRoutinesV2/patchEntity.cpp b/src/lib/serviceRoutinesV2/patchEntity.cpp index dbc750930f..ad767b632c 100644 --- a/src/lib/serviceRoutinesV2/patchEntity.cpp +++ b/src/lib/serviceRoutinesV2/patchEntity.cpp @@ -34,6 +34,7 @@ #include "apiTypesV2/Entities.h" #include "rest/EntityTypeInfo.h" #include "serviceRoutinesV2/patchEntity.h" +#include "serviceRoutinesV2/serviceRoutinesCommon.h" #include "serviceRoutines/postUpdateContext.h" #include "rest/OrionError.h" @@ -85,12 +86,8 @@ std::string patchEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); - // Adjust NotFound description (to avoid redundant missing entity information) - // FIXME PR: duplicated code in several places - if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) - { - parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; - } + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), false); // 03. Check output from mongoBackend - any errors? if (parseDataP->upcrs.res.oe.code != SccNone ) diff --git a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp index 53204127ac..83d9af39ca 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp @@ -34,6 +34,7 @@ #include "rest/EntityTypeInfo.h" #include "serviceRoutines/postUpdateContext.h" #include "serviceRoutinesV2/putEntityAttribute.h" +#include "serviceRoutinesV2/serviceRoutinesCommon.h" #include "rest/OrionError.h" #include "parse/forbiddenChars.h" #include "alarmMgr/alarmMgr.h" @@ -84,12 +85,8 @@ std::string putEntityAttribute // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); - // Adjust NotFound description (to avoid redundant missing entity information) - // FIXME PR: duplicated code in several places - if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) - { - parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; - } + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), false); // 03. Check error std::string answer = ""; diff --git a/src/lib/serviceRoutinesV2/serviceRoutinesCommon.cpp b/src/lib/serviceRoutinesV2/serviceRoutinesCommon.cpp index 1acc888ee4..083072e0cf 100644 --- a/src/lib/serviceRoutinesV2/serviceRoutinesCommon.cpp +++ b/src/lib/serviceRoutinesV2/serviceRoutinesCommon.cpp @@ -32,6 +32,7 @@ #include "common/string.h" #include "common/RenderFormat.h" +#include "common/errorMessages.h" #include "ngsi/StringList.h" #include "rest/uriParamNames.h" @@ -124,3 +125,26 @@ RenderFormat getRenderFormat(std::map& uriParamOptions) return renderFormat; } + + + +/* **************************************************************************** +* +* adaptErrorCodeForSingleEntityOperation - +* +*/ +void adaptErrorCodeForSingleEntityOperation(OrionError* oeP, bool singleAttributeCheck) +{ + if ((oeP->code == SccContextElementNotFound) & (oeP->reasonPhrase == ERROR_NOT_FOUND)) + { + // In single entity attribute operations (e.g. DELETE /v2/entities/E/attrs/A) when the entity doesn't exist + oeP->details = ERROR_DESC_NOT_FOUND_ENTITY; + } + else if (singleAttributeCheck && (oeP->code == SccInvalidModification) & (oeP->reasonPhrase == ERROR_UNPROCESSABLE)) + { + // In single entity attribute operations (e.g. DELETE /v2/entities/E/attrs/A) when the entity exists but the attribute doesn't + oeP->code = SccContextElementNotFound; + oeP->reasonPhrase = ERROR_NOT_FOUND; + oeP->details = ERROR_DESC_NOT_FOUND_ATTRIBUTE; + } +} \ No newline at end of file diff --git a/src/lib/serviceRoutinesV2/serviceRoutinesCommon.h b/src/lib/serviceRoutinesV2/serviceRoutinesCommon.h index 10e8ee89dd..82dc209738 100644 --- a/src/lib/serviceRoutinesV2/serviceRoutinesCommon.h +++ b/src/lib/serviceRoutinesV2/serviceRoutinesCommon.h @@ -34,6 +34,7 @@ #include "common/string.h" #include "common/RenderFormat.h" #include "ngsi/StringList.h" +#include "rest/OrionError.h" #include "rest/uriParamNames.h" @@ -72,5 +73,14 @@ extern void setMetadataFilter */ extern RenderFormat getRenderFormat(std::map& uriParamOptions); + + +/* **************************************************************************** +* +* adaptErrorCodeForSingleEntityOperation - +* +*/ +extern void adaptErrorCodeForSingleEntityOperation(OrionError* oeP, bool singleAttributeCheck); + #endif // SRC_LIB_SERVICEROUTINESV2_SERVICEROUTINESCOMMON_H_ diff --git a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test index 1f6638006d..405123b429 100644 --- a/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test +++ b/test/functionalTest/cases/0993_DELETE_v2_entity_attr/delete_not_exist_attr.test @@ -102,15 +102,15 @@ Content-Length: 121 03. DELETE /v2/entities/E1/attrs/none ===================================== -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 69 +Content-Length: 79 { - "description": "do not exist: E1 - [ none ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } diff --git a/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test index edd9ab999c..1c8eb4281a 100644 --- a/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test +++ b/test/functionalTest/cases/3499_partial_update_response/single_all_combinations_delete.test @@ -85,29 +85,29 @@ Fiware-Correlator: REGEX([0-9a-f\-]{36}) 02. DELETE /v2/entities/E/attrs/C (full fail) ============================================= -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 65 +Content-Length: 79 { - "description": "do not exist: E - [ C ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } 03. DELETE /v2/entities/E/attrs/C?type=T (full fail) ==================================================== -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 67 +Content-Length: 79 { - "description": "do not exist: E/T - [ C ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } From 3a3d7a5671bd4cde233b0e184480a5c8ad82eab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 09:58:53 +0100 Subject: [PATCH 26/34] ADD ftest for error responses on updates and doc and code changes to align --- CHANGES_NEXT_RELEASE | 1 + doc/manuals/orion-api.md | 239 ++++++++++++++++-- src/lib/common/globals.h | 2 +- src/lib/mongoBackend/MongoCommonUpdate.cpp | 3 +- src/lib/serviceRoutinesV2/postEntity.cpp | 5 +- src/lib/serviceRoutinesV2/putEntity.cpp | 11 +- .../serviceRoutinesV2/putEntityAttribute.cpp | 2 +- .../putEntityAttributeValue.cpp | 10 +- ...s_00_get_entity_and_entity_attributes.test | 101 ++++++++ ...01_update_or_append_entity_attributes.test | 221 ++++++++++++++++ ..._02_update_existing_entity_attributes.test | 193 ++++++++++++++ ...r_responses_03_replace_all_attributes.test | 86 +++++++ .../error_responses_04_delete_entity.test | 80 ++++++ .../error_responses_05_update_attribute.test | 146 +++++++++++ .../error_responses_06_delete_attribute.test | 138 ++++++++++ ...rror_responses_07_get_attribute_value.test | 139 ++++++++++ ...r_responses_08_update_attribute_value.test | 145 +++++++++++ 17 files changed, 1480 insertions(+), 42 deletions(-) create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_00_get_entity_and_entity_attributes.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_01_update_or_append_entity_attributes.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_02_update_existing_entity_attributes.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_03_replace_all_attributes.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_04_delete_entity.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_05_update_attribute.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_06_delete_attribute.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_07_get_attribute_value.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_08_update_attribute_value.test diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 7f815e5662..ef5fd3affb 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -5,6 +5,7 @@ - Fix: logDeprecate not working correctly (`geo:json` wrongly considered as deprecated) - Fix: improve error traces (#4387) - Fix: on delete attributes operation, the lack of attribute in entity doesn't preclude the deletion of attributes which do exist (this way behaving same way as update attributes operation) +- Fix: POST /v2/entities/E/attrs?options=append was wrongly creating entities - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) - Fix: improve logs in MongoDB query logic - Upgrade Debian version from 11.6 to 12.1 in Dockerfile diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index d45e1305f6..577d88b5d7 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -2816,7 +2816,8 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 200 OK -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity _**Response headers**_ @@ -2824,7 +2825,16 @@ Successful operations return `Content-Type` header with `application/json` value _**Response payload**_ -The response is an object representing the entity identified by the ID. The object follows +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +If the entity is found, the response is an object representing the entity identified by the ID. The object follows the JSON entity representation format (described in [JSON Entity Representation](#json-entity-representation) section and side [Simplified Entity Representation](#simplified-entity-representation) and [Partial Representations](#partial-representations) sections). @@ -2899,8 +2909,8 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 200 OK -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity _**Response headers**_ @@ -2908,7 +2918,16 @@ Successful operations return `Content-Type` header with `application/json` value _**Response payload**_ -The payload is an object representing the entity identified by the ID in the URL parameter. The object follows +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +If the entity is found, the payload is an object representing the entity identified by the ID in the URL parameter. The object follows the JSON entity representation format (described in [JSON Entity Representation](#json-entity-representation) section and side [Simplified Entity Representation](#simplified-entity-representation) and [Partial Representations](#partial-representations) sections), but omitting `id` and `type` fields. @@ -3005,8 +3024,44 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity + * 422 Unprocessable Content for existing attributes when `append` options is used + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of *all* attributes exist when `append` options is used: + +``` +{ + "description": "one or more of the attributes in the request already exist: E/T - [ A, B ]", + "error": "Unprocessable" +} +``` + +In the case of *some* (but not all) attributes exist when `append` options is used (partial update): + +``` +{ + "description": "one or more of the attributes in the request already exist: E/T - [ B ]", + "error": "PartialUpdate" +} +``` + +The entity type in `description` is shown only if the request includes it. Otherwise, it is omitted: + +``` +"description": "one or more of the attributes in the request already exist: E - [ B ]", +``` #### Update Existing Entity Attributes `PATCH /v2/entities/{entityId}/attrs` @@ -3068,8 +3123,44 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity + * 422 Unprocessable Content for non existing attributes + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of *none* of the attributes in the request exist: + +``` +{ + "description": "do not exist: E/T - [ C, D ]", + "error": "Unprocessable" +} +``` + +In the case of *some* (but not all) attributes does not exist (partial update): + +``` +{ + "description": "do not exist: E/T - [ C ]", + "error": "PartialUpdate" +} +``` + +The entity type in `description` is shown only if the request includes it. Otherwise, it is omitted: + +``` +"description": "do not exist: E - [ C ]", +``` #### Replace all entity attributes `PUT /v2/entities/{entityId}/attrs` @@ -3130,8 +3221,19 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` #### Remove Entity `DELETE /v2/entities/{entityId}` @@ -3161,8 +3263,19 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` ### Attributes @@ -3287,8 +3400,28 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity or not found attribute + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of not found attribute: + +``` +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} +``` #### Remove a Single Attribute `DELETE /v2/entities/{entityId}/attrs/{attrName}` @@ -3319,8 +3452,28 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity or not found attribute + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of not found attribute: + +``` +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} +``` ### Attribute Value @@ -3359,9 +3512,10 @@ _**Request headers**_ _**Response code**_ -* Successful operation uses 200 OK. -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Successful operation uses 200 OK +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity or not found attribute + * 406 Not Acceptable in the case of not acceptable content _**Response headers**_ @@ -3369,7 +3523,26 @@ _**Response headers**_ _**Response payload**_ -The response payload can be an object, array, string, number, boolean or null with the value of the attribute. +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of not found attribute: + +``` +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} +``` + +In the case of entity and attribute both are found, the response payload can be an object, array, string, +number, boolean or null with the value of the attribute. * If attribute value is JSON Array or Object: * If `Accept` header can be expanded to `application/json` or `text/plain` return the value as a JSON with a @@ -3458,8 +3631,28 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found for not found entity or not found attribute + +_**Response payload**_ + +In the case of not found entity: + +``` +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} +``` + +In the case of not found attribute: + +``` +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} +``` ### Types diff --git a/src/lib/common/globals.h b/src/lib/common/globals.h index 73c68c7187..2d385d9092 100644 --- a/src/lib/common/globals.h +++ b/src/lib/common/globals.h @@ -150,7 +150,7 @@ typedef enum Ngsiv2Flavour NGSIV2_NO_FLAVOUR = 0, NGSIV2_FLAVOUR_ONCREATE = 1, NGSIV2_FLAVOUR_ONAPPEND = 2, - NGSIV2_FLAVOUR_ONUPDATE = 3 + NGSIV2_FLAVOUR_ONPUREAPPEND = 3 } Ngsiv2Flavour; diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 6fba6a2fb9..cea1c10471 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4188,7 +4188,8 @@ unsigned int processContextElement } // This is the case of POST /v2/entities/, in order to check that entity previously exist - if ((entitiesNumber == 0) && (ngsiv2Flavour == NGSIV2_FLAVOUR_ONAPPEND)) + // both for regular case (NGSIV2_FLAVOUR_ONAPPEND) and when ?options=append is used (NGSIV2_FLAVOUR_ONPUREAPPEND) + if ((entitiesNumber == 0) && ((ngsiv2Flavour == NGSIV2_FLAVOUR_ONAPPEND)||(ngsiv2Flavour == NGSIV2_FLAVOUR_ONPUREAPPEND))) { buildGeneralErrorResponse(eP, NULL, responseP, SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY); responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ERROR_NOT_FOUND); diff --git a/src/lib/serviceRoutinesV2/postEntity.cpp b/src/lib/serviceRoutinesV2/postEntity.cpp index 7797bc7e87..c81b095cc9 100644 --- a/src/lib/serviceRoutinesV2/postEntity.cpp +++ b/src/lib/serviceRoutinesV2/postEntity.cpp @@ -76,10 +76,11 @@ std::string postEntity return oe.toJson(); } - if (ciP->uriParamOptions["append"] == true) // pure-append + // FIXME PR: maybe NGSIV2_FLAVOUR_ONPUREAPPEND and NGSIV2_FLAVOUR_ONAPPEND can be merged into a single one + if (ciP->uriParamOptions[OPT_APPEND] == true) // pure-append { op = ActionTypeAppendStrict; - flavor = NGSIV2_FLAVOUR_ONUPDATE; + flavor = NGSIV2_FLAVOUR_ONPUREAPPEND; } else { diff --git a/src/lib/serviceRoutinesV2/putEntity.cpp b/src/lib/serviceRoutinesV2/putEntity.cpp index d44b23190a..0a6f88580d 100644 --- a/src/lib/serviceRoutinesV2/putEntity.cpp +++ b/src/lib/serviceRoutinesV2/putEntity.cpp @@ -34,6 +34,7 @@ #include "apiTypesV2/Entities.h" #include "rest/EntityTypeInfo.h" #include "serviceRoutinesV2/putEntity.h" +#include "serviceRoutinesV2/serviceRoutinesCommon.h" #include "serviceRoutines/postUpdateContext.h" #include "rest/OrionError.h" #include "parse/forbiddenChars.h" @@ -43,7 +44,7 @@ * * putEntity - * -* PUT /v2/entities +* PUT /v2/entities//attrs * * Payload In: Entity * Payload Out: None @@ -84,12 +85,8 @@ std::string putEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); - // Adjust NotFound description (to avoid redundant missing entity information) - // FIXME PR: duplicated code in several places - if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) - { - parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; - } +// Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), false); // 03. Check error std::string answer = ""; diff --git a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp index 83d9af39ca..25713cb229 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttribute.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttribute.cpp @@ -86,7 +86,7 @@ std::string putEntityAttribute postUpdateContext(ciP, components, compV, parseDataP); // Adjust error code if needed - adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), false); + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); // 03. Check error std::string answer = ""; diff --git a/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp b/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp index c4e8ea8f18..0f41e87f36 100644 --- a/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp +++ b/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp @@ -33,6 +33,7 @@ #include "rest/EntityTypeInfo.h" #include "serviceRoutines/postUpdateContext.h" #include "serviceRoutinesV2/putEntityAttributeValue.h" +#include "serviceRoutinesV2/serviceRoutinesCommon.h" #include "rest/OrionError.h" #include "parse/forbiddenChars.h" @@ -91,13 +92,8 @@ std::string putEntityAttributeValue // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); - // Adjust NotFound description (to avoid redundant missing entity information) - // FIXME PR: duplicated code in several places - if ((parseDataP->upcrs.res.oe.code == SccContextElementNotFound) & (parseDataP->upcrs.res.oe.reasonPhrase == ERROR_NOT_FOUND)) - { - parseDataP->upcrs.res.oe.details = ERROR_DESC_NOT_FOUND_ENTITY; - } - + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); // 03. Check output from mongoBackend std::string answer = ""; diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_00_get_entity_and_entity_attributes.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_00_get_entity_and_entity_attributes.test new file mode 100644 index 0000000000..26686104d7 --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_00_get_entity_and_entity_attributes.test @@ -0,0 +1,101 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Get entity (GET /v2/entities/{entityId}) and get entity attributes (GET /v2/entities/{entityId}) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity or not found attribute +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# + +# +# 01. GET /v2/entities/F, see error (NotFound) +# 02. GET /v2/entities/F/attrs, see error (NotFound) +# + + +echo "01. GET /v2/entities/F, see error (NotFound)" +echo "============================================" +orionCurl --url /v2/entities/F +echo +echo + + +echo "02. GET /v2/entities/F/attrs, see error (NotFound)" +echo "==================================================" +orionCurl --url /v2/entities/F/attrs +echo +echo + + +--REGEXPECT-- +01. GET /v2/entities/F, see error (NotFound) +============================================ +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. GET /v2/entities/F/attrs, see error (NotFound) +================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_01_update_or_append_entity_attributes.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_01_update_or_append_entity_attributes.test new file mode 100644 index 0000000000..6348a0d60a --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_01_update_or_append_entity_attributes.test @@ -0,0 +1,221 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Update or Append Entity Attributes (POST /v2/entities/{entityId}/attrs) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response codes: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity +# * 422 Unprocessable Content for existing attributes when `append` options is used +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of *all* attributes exist when `append` options is used: +# +# { +# "description": "one or more of the attributes in the request already exist: E/T - [ A, B ]", +# "error": "Unprocessable" +# } +# +# In the case of *some* (but not all) attributes exist when `append` options is used (partial update): +# +# { +# "description": "one or more of the attributes in the request already exist: E/T - [ B ]", +# "error": "PartialUpdate" +# } +# + +# +# 01. POST /v2/entities/F/attrs, see error (NotFound) +# 02. POST /v2/entities/F/attrs?options=append, see error (NotFound) +# 03. Create entity E/A-B +# 04. POST /v2/entities/E/attrs?options=append with A and B, see error (Unprocessable) +# 05. POST /v2/entities/E/attrs?options=append with B and C, see error (PartialUpdate) +# + +echo "01. POST /v2/entities/F/attrs, see error (NotFound)" +echo "===================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/F/attrs --payload "$payload" +echo +echo + + +echo "02. POST /v2/entities/F/attrs?options=append, see error (NotFound)" +echo "==================================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/F/attrs?options=append --payload "$payload" +echo +echo + + +echo "03. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "04. POST /v2/entities/E/attrs?options=append with A and B, see error (Unprocessable)" +echo "====================================================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/E/attrs?options=append --payload "$payload" +echo +echo + + +echo "05. POST /v2/entities/E/attrs?options=append with B and C, see error (PartialUpdate)" +echo "====================================================================================" +payload='{ + "B": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/E/attrs?options=append --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. POST /v2/entities/F/attrs, see error (NotFound) +=================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. POST /v2/entities/F/attrs?options=append, see error (NotFound) +================================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +03. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +04. POST /v2/entities/E/attrs?options=append with A and B, see error (Unprocessable) +==================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 114 + +{ + "description": "one or more of the attributes in the request already exist: E - [ A, B ]", + "error": "Unprocessable" +} + + +05. POST /v2/entities/E/attrs?options=append with B and C, see error (PartialUpdate) +==================================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 111 + +{ + "description": "one or more of the attributes in the request already exist: E - [ B ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_02_update_existing_entity_attributes.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_02_update_existing_entity_attributes.test new file mode 100644 index 0000000000..3f585d26ae --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_02_update_existing_entity_attributes.test @@ -0,0 +1,193 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Update Existing Entity Attributes (PATCH /v2/entities/{entityId}/attrs) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity +# * 422 Unprocessable Content for non existing attributes +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of *none* of the attributes in the request exist: +# +# { +# "description": "do not exist: E/T - [ C, D ]", +# "error": "Unprocessable" +# } +# +# In the case of *some* (but not all) attributes does not exist (partial update) +# +# { +# "description": "do not exist: E/T - [ C ]", +# "error": "PartialUpdate" +# } +# + +# +# 01. PATCH /v2/entities/F/attrs, see error (NotFound) +# 02. Create entity E/A-B +# 03. PATCH /v2/entities/E/attrs with C and D, see error (Unprocessable) +# 04. PATCH /v2/entities/E/attrs with B and C, see error (PartialUpdate) +# + +echo "01. PATCH /v2/entities/F/attrs, see error (NotFound)" +echo "====================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/F/attrs --payload "$payload" -X PATCH +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. PATCH /v2/entities/E/attrs with C and D, see error (Unprocessable)" +echo "======================================================================" +payload='{ + "C": { + "value": 1, + "type": "Number" + }, + "D": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/E/attrs?options=append --payload "$payload" -X PATCH +echo +echo + + +echo "04. PATCH /v2/entities/E/attrs with B and C, see error (PartialUpdate)" +echo "======================================================================" +payload='{ + "B": { + "value": 1, + "type": "Number" + }, + "C": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/E/attrs?options=append --payload "$payload" -X PATCH +echo +echo + + +--REGEXPECT-- +01. PATCH /v2/entities/F/attrs, see error (NotFound) +==================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. PATCH /v2/entities/E/attrs with C and D, see error (Unprocessable) +====================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 68 + +{ + "description": "do not exist: E - [ C, D ]", + "error": "Unprocessable" +} + + +04. PATCH /v2/entities/E/attrs with B and C, see error (PartialUpdate) +====================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 65 + +{ + "description": "do not exist: E - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_03_replace_all_attributes.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_03_replace_all_attributes.test new file mode 100644 index 0000000000..1829afed4a --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_03_replace_all_attributes.test @@ -0,0 +1,86 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Replace all entity attributes (PUT /v2/entities/{entityId}/attrs) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# + +# +# 01. PUT /v2/entities/F/attrs, see error (NotFound) +# + +echo "01. PUT /v2/entities/F/attrs, see error (NotFound)" +echo "==================================================" +payload='{ + "A": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities/F/attrs --payload "$payload" -X PUT +echo +echo + + + + +--REGEXPECT-- +01. PUT /v2/entities/F/attrs, see error (NotFound) +================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_04_delete_entity.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_04_delete_entity.test new file mode 100644 index 0000000000..7642c28b47 --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_04_delete_entity.test @@ -0,0 +1,80 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Delete entity (DELETE /v2/entities/{entityId}) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# + +# +# 01. DELETE /v2/entities/F, see error (NotFound) +# + +echo "01. DELETE /v2/entities/F, see error (NotFound)" +echo "===============================================" +orionCurl --url /v2/entities/F -X DELETE +echo +echo + + + + +--REGEXPECT-- +01. DELETE /v2/entities/F, see error (NotFound) +=============================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_05_update_attribute.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_05_update_attribute.test new file mode 100644 index 0000000000..830d0e027e --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_05_update_attribute.test @@ -0,0 +1,146 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Update attribute (PUT /v2/entities/{entityId}/attrs/{attrName}) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity or not found attribute +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of not found attribute: +# +# { +# "description": "The entity does not have such an attribute", +# "error": "NotFound" +# } +# + +# +# 01. PUT /v2/entities/F/attrs/C, see error (NotFound) +# 02. Create entity E/A-B +# 03. PUT /v2/entities/E/attrs/C, see error (NotFound) +# + + +echo "01. PUT /v2/entities/F/attrs/C, see error (NotFound)" +echo "====================================================" +payload='{ + "type": "Number", + "value": 1 +}' +orionCurl --url /v2/entities/F/attrs/C --payload "$payload" -X PUT +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. PUT /v2/entities/E/attrs/C, see error (NotFound)" +echo "====================================================" +payload='{ + "type": "Number", + "value": 1 +}' +orionCurl --url /v2/entities/E/attrs/C --payload "$payload" -X PUT +echo +echo + + +--REGEXPECT-- +01. PUT /v2/entities/F/attrs/C, see error (NotFound) +==================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. PUT /v2/entities/E/attrs/C, see error (NotFound) +==================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 79 + +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_06_delete_attribute.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_06_delete_attribute.test new file mode 100644 index 0000000000..5bbf88ef5f --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_06_delete_attribute.test @@ -0,0 +1,138 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Update attribute (PUT /v2/entities/{entityId}/attrs/{attrName}) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity or not found attribute +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of not found attribute: +# +# { +# "description": "The entity does not have such an attribute", +# "error": "NotFound" +# } +# + +# +# 01. DELETE /v2/entities/F/attrs/C, see error (NotFound) +# 02. Create entity E/A-B +# 03. DELETE /v2/entities/E/attrs/C, see error (NotFound) +# + + +echo "01. DELETE /v2/entities/F/attrs/C, see error (NotFound)" +echo "=======================================================" +orionCurl --url /v2/entities/F/attrs/C -X DELETE +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. DELETE /v2/entities/E/attrs/C, see error (NotFound)" +echo "=======================================================" +orionCurl --url /v2/entities/E/attrs/C -X DELETE +echo +echo + + +--REGEXPECT-- +01. DELETE /v2/entities/F/attrs/C, see error (NotFound) +======================================================= +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. DELETE /v2/entities/E/attrs/C, see error (NotFound) +======================================================= +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 79 + +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_07_get_attribute_value.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_07_get_attribute_value.test new file mode 100644 index 0000000000..230695cb1a --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_07_get_attribute_value.test @@ -0,0 +1,139 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Get attribute value (GET /v2/entities/{entityId}/attrs/{attrName}/value) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity or not found attribute +# ... +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of not found attribute: +# +# { +# "description": "The entity does not have such an attribute", +# "error": "NotFound" +# } +# + +# +# 01. GET /v2/entities/F/attrs/C/value, see error (NotFound) +# 02. Create entity E/A-B +# 03. GET /v2/entities/E/attrs/C/value, see error (NotFound) +# + + +echo "01. GET /v2/entities/F/attrs/C/value, see error (NotFound)" +echo "==========================================================" +orionCurl --url /v2/entities/F/attrs/C/value +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. GET /v2/entities/E/attrs/C/value, see error (NotFound)" +echo "==========================================================" +orionCurl --url /v2/entities/E/attrs/C +echo +echo + + +--REGEXPECT-- +01. GET /v2/entities/F/attrs/C/value, see error (NotFound) +========================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. GET /v2/entities/E/attrs/C/value, see error (NotFound) +========================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 79 + +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_08_update_attribute_value.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_08_update_attribute_value.test new file mode 100644 index 0000000000..2997f46d0f --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_08_update_attribute_value.test @@ -0,0 +1,145 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Update attribute value (PUT /v2/entities/{entityId}/attrs/{attrName}/value) error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found for not found entity or not found attribute +# ... +# +# Response payload: +# +# In the case of not found entity: +# +# { +# "description": "The requested entity has not been found. Check type and id", +# "error": "NotFound" +# } +# +# In the case of not found attribute: +# +# { +# "description": "The entity does not have such an attribute", +# "error": "NotFound" +# } +# + +# +# 01. PUT /v2/entities/F/attrs/C/value, see error (NotFound) +# 02. Create entity E/A-B +# 03. PUT /v2/entities/E/attrs/C/value, see error (NotFound) +# + + +echo "01. PUT /v2/entities/F/attrs/C/value, see error (NotFound)" +echo "==========================================================" +payload='{ + "x": 1 +}' +orionCurl --url /v2/entities/F/attrs/C/value --payload "$payload" -X PUT +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. PUT /v2/entities/E/attrs/C/value, see error (NotFound)" +echo "==========================================================" +payload='{ + "x": 1 +}' +orionCurl --url /v2/entities/E/attrs/C/value --payload "$payload" -X PUT +echo +echo + + +--REGEXPECT-- +01. PUT /v2/entities/F/attrs/C/value, see error (NotFound) +========================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 95 + +{ + "description": "The requested entity has not been found. Check type and id", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. PUT /v2/entities/E/attrs/C/value, see error (NotFound) +========================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 79 + +{ + "description": "The entity does not have such an attribute", + "error": "NotFound" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From 2bd828c9cd4d50170595f437dfaa531dca52acce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 11:18:35 +0100 Subject: [PATCH 27/34] FIX align some existing test cases with recent changes --- .../error_response_for_entity_not_found.test | 8 ++++---- .../invalid_error_updating_non_existing_attribute.test | 8 ++++---- .../PATCH_offending_attributes.test | 8 ++++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test index 70b67f7e68..8fafc70198 100644 --- a/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test +++ b/test/functionalTest/cases/1360_error_response_for_entity_not_found/error_response_for_entity_not_found.test @@ -93,15 +93,15 @@ Content-Length: 0 03. Attempt to update attribute dfgdfgdf of entity room_2 (the attribute does not exist) ======================================================================================== -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 77 +Content-Length: 79 { - "description": "do not exist: room_2 - [ dfgdfgdf ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } diff --git a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test index 2592785cec..b546c7e6e5 100644 --- a/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test +++ b/test/functionalTest/cases/2221_invalid_error_updating_non_existing_attribute/invalid_error_updating_non_existing_attribute.test @@ -79,15 +79,15 @@ Content-Length: 0 02. Attempt to replace E1/A2, see error about attribute not found ================================================================= -HTTP/1.1 422 Unprocessable Content +HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 67 +Content-Length: 79 { - "description": "do not exist: E1 - [ A2 ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } diff --git a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test index a69fc89d16..22be5d5436 100644 --- a/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test +++ b/test/functionalTest/cases/2933_PATCH_offending_attributes/PATCH_offending_attributes.test @@ -42,6 +42,8 @@ brokerStart CB echo '01. POST /v2/entities, to create Room1 with temperature and pressure.' echo '=====================================================================' payload='{ + "id": "Room1", + "type": "Thing", "temperature": { "value": 23, "type": "Float" @@ -51,7 +53,7 @@ payload='{ "type": "Float" } }' -orionCurl --url /v2/entities/Room1/attrs?options=append --payload "$payload" +orionCurl --url /v2/entities --payload "$payload" echo echo @@ -105,9 +107,11 @@ echo --REGEXPECT-- 01. POST /v2/entities, to create Room1 with temperature and pressure. ===================================================================== -HTTP/1.1 204 No Content +HTTP/1.1 201 Created Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/Room1?type=Thing +Content-Length: 0 From b240965aa6a3c7bcea3c8c11bdfe790d961af367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 14:14:51 +0100 Subject: [PATCH 28/34] FIX additional test cases for error responses in batch update and align in the code --- doc/manuals/orion-api.md | 84 +++++- src/lib/mongoBackend/mongoUpdateContext.cpp | 4 +- ...or_responses_09a_batch_update_replace.test | 182 +++++++++++++ ...ror_responses_09b_batch_update_update.test | 241 ++++++++++++++++++ ...ror_responses_09c_batch_update_delete.test | 241 ++++++++++++++++++ ...ponses_09d_batch_update_append_strict.test | 230 +++++++++++++++++ 6 files changed, 977 insertions(+), 5 deletions(-) create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test create mode 100644 test/functionalTest/cases/0000_update_error_responses/error_responses_09d_batch_update_append_strict.test diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index 577d88b5d7..967a185cc3 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -4635,9 +4635,87 @@ Example: _**Response code**_ -* Successful operation uses 204 No Content. -* Errors use a non-2xx and (optionally) an error payload. See subsection on [Error Responses](#error-responses) for - more details. +* Successful operation uses 204 No Content +* Errors use a non-2xx code and error payload (see next subsection): + * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases + * 422 Unprocessable Content for other cases + +_**Response payload**_ + +For action type `replace`: + +* If *none* of the entities in `entities` exist: + +``` +{ + "description": "do not exist: F/T - [entity itself], G/T [entity itself]", + "error": "NotFound" +} +``` + +* If *any (but not all)* of the entities in `entities` does not exist (partial update): + +``` +{ + "description": "do not exist: G/T - [entity itself]", + "error": "PartialUpdate" +} +``` + +For action type `update` or `delete`: + +* If *none* of the entities in `entities` exist: + +``` +{ + "description": "do not exist: F/T - [entity itself], G/T [entity itself]", + "error": "NotFound" +} +``` + +* If at least one entity in `entities` exists and in *all* of existing entities there was a *full fail* due to missing attributes: + +``` +{ + "description": "do not exist: E/T - [ C, D ], G/T [entity itself]", + "error": "Unprocessable" +} +``` + +* If at least one entity in `entities` exists and in *at least one* of the existing entities *at least* one attribute exists + but not all entities exist or all entities exist but in at least one entity there is at least one missing attribute (partial update): + +``` +{ + "description": "do not exist: E/T - [ D ], G/T [entity itself]", + "error": "PartialUpdate" +} +``` + +For action type `appendStrict`:` + +* If in *all* entities in `entities` there was a *full fail* due to existing attributes: + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ A, B ], E2/T - [ A, B ]", + "error": "Unprocessable" +} + +* If *in some (but not in all)* entities in `entities` there was a fail due to existing attributes (partial update): + +* If in *at least one entity* in `entities` in *at least* one attribute there was a success but not all entities in `entities` have + a full success (partial update): + +{ + "description": "one or more of the attributes in the request already exist: E2/T - [ A, B ]", + "error": "PartialUpdate" +} + +The entity type in `description` is shown only if the request includes it. Otherwise, it is omitted: + +``` +"description": "one or more of the attributes in the request already exist: E2 - [ A, B ]" +``` ### Query operation diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 80ebfad8b3..4a19eaa863 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -184,9 +184,9 @@ HttpStatusCode mongoUpdateContext } break; case UC_FULL_ATTRS_FAIL: - // If global UC is full attrs fail, we need also full attrs fail in the processed entity to keep global full attrs fail + // If global UC is full attrs fail, we need also full attrs fail or not found entity in the processed entity to keep global full attrs fail // Otherwise (success, partial, not found entity), the global UC changes to partial - if (entityUpdateCoverage != UC_FULL_ATTRS_FAIL) + if ((entityUpdateCoverage != UC_FULL_ATTRS_FAIL) && (entityUpdateCoverage != UC_ENTITY_NOT_FOUND)) { updateCoverage = UC_PARTIAL; } diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test new file mode 100644 index 0000000000..afa86653a0 --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test @@ -0,0 +1,182 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Batch update (POST /v2/op/update) with replace action error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 422 Unprocessable Content for other cases +# +# Response payload: +# +# For action type `replace`: +# +# * If *none* of the entities in `entities` exist: +# +# { +# "description": "do not exist: F/T - [entity itself], G/T [entity itself]", +# "error": "NotFound" +# } +# +# * If *any (but not all)* of the entities in `entities` does not exist (partial update): +# +# { +# "description": "do not exist: G/T - [entity itself]", +# "error": "PartialUpdate" +# } +# + +# +# 01. POST /v2/op/update replace with entities F/G, see error (NotFound) +# 02. Create entity E/A-B +# 03. POST /v2/op/update replace with entities E/G, see error (PartialUpdate) +# + +echo "01. POST /v2/op/update replace with entities F/G, see error (NotFound)" +echo "======================================================================" +payload='{ + "actionType": "replace", + "entities": [ + { + "id": "F", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. POST /v2/op/update replace with entities E/G, see error (PartialUpdate)" +echo "===========================================================================" +payload='{ + "actionType": "replace", + "entities": [ + { + "id": "E", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. POST /v2/op/update replace with entities F/G, see error (NotFound) +====================================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 93 + +{ + "description": "do not exist: F/T - [entity itself], G/T [entity itself]", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. POST /v2/op/update replace with entities E/G, see error (PartialUpdate) +=========================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 77 + +{ + "description": "do not exist: G/T - [entity itself]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test new file mode 100644 index 0000000000..da4ba04e0e --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test @@ -0,0 +1,241 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Batch update (POST /v2/op/update) with update action error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 422 Unprocessable Content for other cases +# +# Response payload: +# +# For action type `update` or `delete`: +# +# * If *none* of the entities in `entities` exist: +# +# { +# "description": "do not exist: F/T - [entity itself], G/T [entity itself]", +# "error": "NotFound" +# } +# +# * If at least one entity in `entities` exists and in *all* of existing entities there was a *full fail* due to missing attributes: +# +# { +# "description": "do not exist: E/T - [ C, D ], G/T [entity itself]", +# "error": "Unprocessable" +# } +# +# * If at least one entity in `entities` exists and in *at least one* of the existing entities *at least* one attribute exists +# but not all entities exists or all entities exist but in at least one entity there is at least one missing attribute (partial update): +# +# { +# "description": "do not exist: E/T - [ D ], G/T [entity itself]", +# "error": "PartialUpdate" +# } +# + +# +# 01. POST /v2/op/update update with entities F/G, see error (NotFound) +# 02. Create entity E/A-B +# 03. POST /v2/op/update update with entities E{C,D}/G, see error (Unprocessable) +# 04. POST /v2/op/update update with entities E{A,D}/G, see error (PartialUpdate) +# + +echo "01. POST /v2/op/update update with entities F/G, see error (NotFound)" +echo "=====================================================================" +payload='{ + "actionType": "update", + "entities": [ + { + "id": "F", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. POST /v2/op/update update with entities E{C,D}/G, see error (Unprocessable)" +echo "===============================================================================" +payload='{ + "actionType": "update", + "entities": [ + { + "id": "E", + "type": "T", + "C": { + "type": "Number", + "value": 1 + }, + "D": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. POST /v2/op/update update with entities E{A,D}/G, see error (PartialUpdate)" +echo "===============================================================================" +payload='{ + "actionType": "update", + "entities": [ + { + "id": "E", + "type": "T", + "A": { + "type": "Number", + "value": 1 + }, + "D": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. POST /v2/op/update update with entities F/G, see error (NotFound) +===================================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 93 + +{ + "description": "do not exist: F/T - [entity itself], G/T [entity itself]", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. POST /v2/op/update update with entities E{C,D}/G, see error (Unprocessable) +=============================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 91 + +{ + "description": "do not exist: E/T - [ C, D ], G/T [entity itself]", + "error": "Unprocessable" +} + + +04. POST /v2/op/update update with entities E{A,D}/G, see error (PartialUpdate) +=============================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 88 + +{ + "description": "do not exist: E/T - [ D ], G/T [entity itself]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test new file mode 100644 index 0000000000..b7467902c5 --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test @@ -0,0 +1,241 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Batch update (POST /v2/op/update) with delete action error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 422 Unprocessable Content for other cases +# +# Response payload: +# +# For action type `update` or `delete`: +# +# * If *none* of the entities in `entities` exist: +# +# { +# "description": "do not exist: F/T - [entity itself], G/T [entity itself]", +# "error": "NotFound" +# } +# +# * If at least one entity in `entities` exists and in *all* of existing entities there was a *full fail* due to missing attributes: +# +# { +# "description": "do not exist: E/T - [ C, D ], G/T [entity itself]", +# "error": "Unprocessable" +# } +# +# * If at least one entity in `entities` exists and in *at least one* of the existing entities *at least* one attribute exists +# but not all entities exists or all entities exist but in at least one entity there is at least one missing attribute (partial update): +# +# { +# "description": "do not exist: E/T - [ D ], G/T [entity itself]", +# "error": "PartialUpdate" +# } +# + +# +# 01. POST /v2/op/update delete with entities F/G, see error (NotFound) +# 02. Create entity E/A-B +# 03. POST /v2/op/update delete with entities E{C,D}/G, see error (Unprocessable) +# 04. POST /v2/op/update delete with entities E{A,D}/G, see error (PartialUpdate) +# + +echo "01. POST /v2/op/update delete with entities F/G, see error (NotFound)" +echo "=====================================================================" +payload='{ + "actionType": "delete", + "entities": [ + { + "id": "F", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "02. Create entity E/A-B" +echo "=======================" +payload='{ + "id": "E", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. POST /v2/op/update delete with entities E{C,D}/G, see error (Unprocessable)" +echo "===============================================================================" +payload='{ + "actionType": "delete", + "entities": [ + { + "id": "E", + "type": "T", + "C": { + "type": "Number", + "value": 1 + }, + "D": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. POST /v2/op/update delete with entities E{A,D}/G, see error (PartialUpdate)" +echo "===============================================================================" +payload='{ + "actionType": "delete", + "entities": [ + { + "id": "E", + "type": "T", + "A": { + "type": "Number", + "value": 1 + }, + "D": { + "type": "Number", + "value": 1 + } + }, + { + "id": "G", + "type": "T", + "A": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. POST /v2/op/update delete with entities F/G, see error (NotFound) +===================================================================== +HTTP/1.1 404 Not Found +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 93 + +{ + "description": "do not exist: F/T - [entity itself], G/T [entity itself]", + "error": "NotFound" +} + + +02. Create entity E/A-B +======================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E?type=T +Content-Length: 0 + + + +03. POST /v2/op/update delete with entities E{C,D}/G, see error (Unprocessable) +=============================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 91 + +{ + "description": "do not exist: E/T - [ C, D ], G/T [entity itself]", + "error": "Unprocessable" +} + + +04. POST /v2/op/update delete with entities E{A,D}/G, see error (PartialUpdate) +=============================================================================== +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 88 + +{ + "description": "do not exist: E/T - [ D ], G/T [entity itself]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09d_batch_update_append_strict.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09d_batch_update_append_strict.test new file mode 100644 index 0000000000..199614d018 --- /dev/null +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09d_batch_update_append_strict.test @@ -0,0 +1,230 @@ +# Copyright 2023 Telefonica Investigacion y Desarrollo, S.A.U +# +# This file is part of Orion Context Broker. +# +# Orion Context Broker is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# Orion Context Broker is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero +# General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Orion Context Broker. If not, see http://www.gnu.org/licenses/. +# +# For those usages not covered by this license please contact with +# iot_support at tid dot es + +# VALGRIND_READY - to mark the test ready for valgrindTestSuite.sh + +--NAME-- +Batch update (POST /v2/op/update) with replace appendStrict error responses + +--SHELL-INIT-- +dbInit CB +brokerStart CB + +--SHELL-- + +# From documentation: +# +# Response code: +# +# ... +# * Errors use a non-2xx code and error payload (see next subsection): +# ... +# * 422 Unprocessable Content for other cases +# +# Response payload: +# +# For action type `appendStrict`:` +# +# * If in *all* entities in `entities` there was a *full fail* due to existing attributes: +# +# { +# "description": "one or more of the attributes in the request already exist: E1/T - [ A, B ], E2/T - [ A, B ]", +# "error": "Unprocessable" +# } +# +# * If in *at least one entity* in `entities` in *at least* one attribute there was a success but not all entities in `entities` have +# a full success (partial update): +# +# { +# "description": "one or more of the attributes in the request already exist: E2/T - [ A, B ]", +# "error": "PartialUpdate" +# } +# + +# +# 01. Create entity E1{A-B} +# 02. Create entity E2{A-B} +# 03. POST /v2/op/update appendStrict with entities E1{A,B}/E2{A,B}, see error (Unprocessable) +# 04. POST /v2/op/update appendStrict with entities E1{C,D}/E2{A,B}, see error (PartialUpdate) +# + + +echo "01. Create entity E1{A-B}" +echo "=========================" +payload='{ + "id": "E1", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "02. Create entity E2{A-B}" +echo "=========================" +payload='{ + "id": "E2", + "type": "T", + "A": { + "value": 1, + "type": "Number" + }, + "B": { + "value": 1, + "type": "Number" + } +}' +orionCurl --url /v2/entities --payload "$payload" +echo +echo + + +echo "03. POST /v2/op/update appendStrict with entities E1{A,B}/E2{A,B}, see error (Unprocessable)" +echo "============================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": [ + { + "id": "E1", + "type": "T", + "A": { + "type": "Number", + "value": 1 + }, + "B": { + "type": "Number", + "value": 1 + } + }, + { + "id": "E2", + "type": "T", + "A": { + "type": "Number", + "value": 1 + }, + "B": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +echo "04. POST /v2/op/update appendStrict with entities E1{C,D}/E2{A,B}, see error (PartialUpdate)" +echo "============================================================================================" +payload='{ + "actionType": "appendStrict", + "entities": [ + { + "id": "E1", + "type": "T", + "C": { + "type": "Number", + "value": 1 + }, + "D": { + "type": "Number", + "value": 1 + } + }, + { + "id": "E2", + "type": "T", + "A": { + "type": "Number", + "value": 1 + }, + "B": { + "type": "Number", + "value": 1 + } + } + ] +}' +orionCurl --url /v2/op/update --payload "$payload" +echo +echo + + +--REGEXPECT-- +01. Create entity E1{A-B} +========================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E1?type=T +Content-Length: 0 + + + +02. Create entity E2{A-B} +========================= +HTTP/1.1 201 Created +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Location: /v2/entities/E2?type=T +Content-Length: 0 + + + +03. POST /v2/op/update appendStrict with entities E1{A,B}/E2{A,B}, see error (Unprocessable) +============================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 134 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ A, B ], E2/T - [ A, B ]", + "error": "Unprocessable" +} + + +04. POST /v2/op/update appendStrict with entities E1{C,D}/E2{A,B}, see error (PartialUpdate) +============================================================================================ +HTTP/1.1 422 Unprocessable Content +Date: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) +Content-Type: application/json +Content-Length: 117 + +{ + "description": "one or more of the attributes in the request already exist: E2/T - [ A, B ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file From b4baaac2b80c4369d4809f7c9e94f1bf34970e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 14:22:18 +0100 Subject: [PATCH 29/34] FIX typos --- doc/manuals/orion-api.md | 2 -- src/lib/mongoBackend/mongoUpdateContext.cpp | 2 +- .../error_responses_09a_batch_update_replace.test | 2 +- .../error_responses_09b_batch_update_update.test | 2 +- .../error_responses_09c_batch_update_delete.test | 2 +- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index 967a185cc3..a524ca2eed 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -4701,8 +4701,6 @@ For action type `appendStrict`:` "error": "Unprocessable" } -* If *in some (but not in all)* entities in `entities` there was a fail due to existing attributes (partial update): - * If in *at least one entity* in `entities` in *at least* one attribute there was a success but not all entities in `entities` have a full success (partial update): diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 4a19eaa863..a6e29ea78b 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -185,7 +185,7 @@ HttpStatusCode mongoUpdateContext break; case UC_FULL_ATTRS_FAIL: // If global UC is full attrs fail, we need also full attrs fail or not found entity in the processed entity to keep global full attrs fail - // Otherwise (success, partial, not found entity), the global UC changes to partial + // Otherwise (success, partial), the global UC changes to partial if ((entityUpdateCoverage != UC_FULL_ATTRS_FAIL) && (entityUpdateCoverage != UC_ENTITY_NOT_FOUND)) { updateCoverage = UC_PARTIAL; diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test index afa86653a0..0bd2d948dd 100644 --- a/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09a_batch_update_replace.test @@ -35,7 +35,7 @@ brokerStart CB # # ... # * Errors use a non-2xx code and error payload (see next subsection): -# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases # * 422 Unprocessable Content for other cases # # Response payload: diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test index da4ba04e0e..65df37a7e9 100644 --- a/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09b_batch_update_update.test @@ -35,7 +35,7 @@ brokerStart CB # # ... # * Errors use a non-2xx code and error payload (see next subsection): -# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases # * 422 Unprocessable Content for other cases # # Response payload: diff --git a/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test b/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test index b7467902c5..4a99978e6b 100644 --- a/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test +++ b/test/functionalTest/cases/0000_update_error_responses/error_responses_09c_batch_update_delete.test @@ -35,7 +35,7 @@ brokerStart CB # # ... # * Errors use a non-2xx code and error payload (see next subsection): -# * 404 Not Found if none of the entitys in the `entities` field exists in `update`, `delete` or `replace` cases +# * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases # * 422 Unprocessable Content for other cases # # Response payload: From 5ff4b26e09528ced9ee7fe67e36cfb3933e5fad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 14:36:51 +0100 Subject: [PATCH 30/34] FIX cleanup --- CHANGES_NEXT_RELEASE | 3 +++ src/lib/mongoBackend/MongoCommonUpdate.cpp | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index ef5fd3affb..6756a51fbd 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -6,6 +6,9 @@ - Fix: improve error traces (#4387) - Fix: on delete attributes operation, the lack of attribute in entity doesn't preclude the deletion of attributes which do exist (this way behaving same way as update attributes operation) - Fix: POST /v2/entities/E/attrs?options=append was wrongly creating entities +- Fix: provide more inforamtive error description in some error responses in update/delete operations +- Fix: proper use of "PartialUpdate" (instead of "Unprocessed") in responses in the case of partial updates/deletions (#3499) +- Fix: response 404 Not Found "NotFound" errors instead of 422 Unprocessable Content "Unprocessed" in the case of missing attribute in existing entity in attribute update operations - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) - Fix: improve logs in MongoDB query logic - Upgrade Debian version from 11.6 to 12.1 in Dockerfile diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index cea1c10471..273f613896 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -2448,7 +2448,6 @@ static bool updateContextAttributeItem " - offending attribute: " + targetAttr->getName(); cerP->statusCode.fill(SccInvalidParameter, details); - //oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); /* Although 'ca' has been already pushed into cerP, the pointer is still valid, of course */ ca->found = false; @@ -2613,12 +2612,9 @@ static bool deleteContextAttributeItem " - attribute not found"; cerP->statusCode.fill(SccInvalidParameter, details); - //oe->fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ATTRIBUTE, ERROR_NOT_FOUND); alarmMgr.badInput(clientIp, "attribute to be deleted is not found", targetAttr->getName()); ca->found = false; - - //return false; } return true; From a1cd4c5d1ebdc6d576324b07b800140957e5aa35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Wed, 13 Dec 2023 15:00:05 +0100 Subject: [PATCH 31/34] FIX simplify implementation --- src/lib/common/globals.h | 3 +-- src/lib/mongoBackend/MongoCommonUpdate.cpp | 4 ++-- src/lib/serviceRoutinesV2/postEntity.cpp | 6 +----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/lib/common/globals.h b/src/lib/common/globals.h index 2d385d9092..66cae65f1c 100644 --- a/src/lib/common/globals.h +++ b/src/lib/common/globals.h @@ -149,8 +149,7 @@ typedef enum Ngsiv2Flavour { NGSIV2_NO_FLAVOUR = 0, NGSIV2_FLAVOUR_ONCREATE = 1, - NGSIV2_FLAVOUR_ONAPPEND = 2, - NGSIV2_FLAVOUR_ONPUREAPPEND = 3 + NGSIV2_FLAVOUR_ONAPPEND = 2 } Ngsiv2Flavour; diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index 273f613896..9fb1f84c8f 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.cpp +++ b/src/lib/mongoBackend/MongoCommonUpdate.cpp @@ -4184,8 +4184,8 @@ unsigned int processContextElement } // This is the case of POST /v2/entities/, in order to check that entity previously exist - // both for regular case (NGSIV2_FLAVOUR_ONAPPEND) and when ?options=append is used (NGSIV2_FLAVOUR_ONPUREAPPEND) - if ((entitiesNumber == 0) && ((ngsiv2Flavour == NGSIV2_FLAVOUR_ONAPPEND)||(ngsiv2Flavour == NGSIV2_FLAVOUR_ONPUREAPPEND))) + // both for regular case and when ?options=append is used + if ((entitiesNumber == 0) && (ngsiv2Flavour == NGSIV2_FLAVOUR_ONAPPEND)) { buildGeneralErrorResponse(eP, NULL, responseP, SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY); responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, ERROR_NOT_FOUND); diff --git a/src/lib/serviceRoutinesV2/postEntity.cpp b/src/lib/serviceRoutinesV2/postEntity.cpp index c81b095cc9..1403cd93ea 100644 --- a/src/lib/serviceRoutinesV2/postEntity.cpp +++ b/src/lib/serviceRoutinesV2/postEntity.cpp @@ -64,7 +64,6 @@ std::string postEntity { Entity* eP = &parseDataP->ent.res; ActionType op; - Ngsiv2Flavour flavor; eP->id = compV[2]; eP->type = ciP->uriParam["type"]; @@ -76,23 +75,20 @@ std::string postEntity return oe.toJson(); } - // FIXME PR: maybe NGSIV2_FLAVOUR_ONPUREAPPEND and NGSIV2_FLAVOUR_ONAPPEND can be merged into a single one if (ciP->uriParamOptions[OPT_APPEND] == true) // pure-append { op = ActionTypeAppendStrict; - flavor = NGSIV2_FLAVOUR_ONPUREAPPEND; } else { op = ActionTypeAppend; // append or update - flavor = NGSIV2_FLAVOUR_ONAPPEND; } // Fill in UpdateContextRequest parseDataP->upcr.res.fill(eP, op); // Call standard op postUpdateContext - postUpdateContext(ciP, components, compV, parseDataP, flavor); + postUpdateContext(ciP, components, compV, parseDataP, NGSIV2_FLAVOUR_ONAPPEND); // Any error in the response? std::string answer = ""; From a4b8cc1407366e41ca6f54e5d594207beeb6b2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 8 Jan 2024 09:23:47 +0100 Subject: [PATCH 32/34] Update CHANGES_NEXT_RELEASE --- CHANGES_NEXT_RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 048209e15d..4e7879928f 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -6,7 +6,7 @@ - Fix: improve error traces (#4387) - Fix: on delete attributes operation, the lack of attribute in entity doesn't preclude the deletion of attributes which do exist (this way behaving same way as update attributes operation) - Fix: POST /v2/entities/E/attrs?options=append was wrongly creating entities -- Fix: provide more inforamtive error description in some error responses in update/delete operations +- Fix: provide more informative error description in some error responses in update/delete operations - Fix: proper use of "PartialUpdate" (instead of "Unprocessed") in responses in the case of partial updates/deletions (#3499) - Fix: response 404 Not Found "NotFound" errors instead of 422 Unprocessable Content "Unprocessed" in the case of missing attribute in existing entity in attribute update operations - Add: CLI parameter -dbUri / env var ORION_MONGO_URI (#3794) From c16bdc980fc0f5e86ee512e644ef79d92f41f814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 8 Jan 2024 14:47:14 +0100 Subject: [PATCH 33/34] FIX documentation --- doc/manuals/orion-api.md | 63 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index a524ca2eed..242895a2d2 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -2816,8 +2816,9 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 200 OK -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -2909,8 +2910,9 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 200 OK -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -3024,9 +3026,10 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity - * 422 Unprocessable Content for existing attributes when `append` options is used +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * 422 Unprocessable Content for existing attributes when `append` options is used (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3123,9 +3126,10 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity - * 422 Unprocessable Content for non existing attributes +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * 422 Unprocessable Content for non existing attributes (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3221,8 +3225,9 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3263,8 +3268,9 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3400,8 +3406,9 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity or not found attribute +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3452,8 +3459,9 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity or not found attribute +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3513,9 +3521,10 @@ _**Request headers**_ _**Response code**_ * Successful operation uses 200 OK -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity or not found attribute - * 406 Not Acceptable in the case of not acceptable content +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * 406 Not Acceptable in the case of not acceptable content (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -3631,8 +3640,9 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found for not found entity or not found attribute +* Errors use a non-2xx code and error payload: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -4636,9 +4646,10 @@ Example: _**Response code**_ * Successful operation uses 204 No Content -* Errors use a non-2xx code and error payload (see next subsection): - * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases - * 422 Unprocessable Content for other cases +* Errors use a non-2xx code and error payload: + * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases (see next subsection) + * 422 Unprocessable Content for other cases (see next subsection) + * Check addicional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ From b46c269bbdd40efb2c25091bae88ab89fc9fb97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferm=C3=ADn=20Gal=C3=A1n=20M=C3=A1rquez?= Date: Mon, 8 Jan 2024 14:52:12 +0100 Subject: [PATCH 34/34] FIX typo in doc --- doc/manuals/orion-api.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index 242895a2d2..671606686b 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -2818,7 +2818,7 @@ _**Response code**_ * Successful operation uses 200 OK * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -2912,7 +2912,7 @@ _**Response code**_ * Successful operation uses 200 OK * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -3029,7 +3029,7 @@ _**Response code**_ * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) * 422 Unprocessable Content for existing attributes when `append` options is used (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3129,7 +3129,7 @@ _**Response code**_ * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) * 422 Unprocessable Content for non existing attributes (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3227,7 +3227,7 @@ _**Response code**_ * Successful operation uses 204 No Content * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3270,7 +3270,7 @@ _**Response code**_ * Successful operation uses 204 No Content * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3408,7 +3408,7 @@ _**Response code**_ * Successful operation uses 204 No Content * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity or not found attribute (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3461,7 +3461,7 @@ _**Response code**_ * Successful operation uses 204 No Content * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity or not found attribute (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -3524,7 +3524,7 @@ _**Response code**_ * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity or not found attribute (see next subsection) * 406 Not Acceptable in the case of not acceptable content (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -3642,7 +3642,7 @@ _**Response code**_ * Successful operation uses 204 No Content * Errors use a non-2xx code and error payload: * 404 Not Found for not found entity or not found attribute (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_ @@ -4649,7 +4649,7 @@ _**Response code**_ * Errors use a non-2xx code and error payload: * 404 Not Found if none of the entities in the `entities` field exists in `update`, `delete` or `replace` cases (see next subsection) * 422 Unprocessable Content for other cases (see next subsection) - * Check addicional cases in [Error Responses](#error-responses) general documentation + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response payload**_