diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 0cfc39e90e..40fdb20979 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -6,6 +6,11 @@ - 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 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 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) - Fix: improve logs in MongoDB query logic - Fix: false positive in log deprecation logic when entity name (or other literal) includes the token "v1" (#4454) diff --git a/doc/manuals/orion-api.md b/doc/manuals/orion-api.md index d45e1305f6..671606686b 100644 --- a/doc/manuals/orion-api.md +++ b/doc/manuals/orion-api.md @@ -2816,7 +2816,9 @@ _**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: + * 404 Not Found for not found entity (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -2824,7 +2826,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 +2910,9 @@ _**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: + * 404 Not Found for not found entity (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -2908,7 +2920,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 +3026,45 @@ 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: + * 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 additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3126,45 @@ 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: + * 404 Not Found for not found entity (see next subsection) + * 422 Unprocessable Content for non existing attributes (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3225,20 @@ 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: + * 404 Not Found for not found entity (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3268,20 @@ _**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: + * 404 Not Found for not found entity (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3406,29 @@ 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: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3459,29 @@ _**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: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 +3520,11 @@ _**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: + * 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 additional cases in [Error Responses](#error-responses) general documentation _**Response headers**_ @@ -3369,7 +3532,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 +3640,29 @@ 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: + * 404 Not Found for not found entity or not found attribute (see next subsection) + * Check additional cases in [Error Responses](#error-responses) general documentation + +_**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 @@ -4442,9 +4645,86 @@ 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: + * 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 additional cases in [Error Responses](#error-responses) general documentation + +_**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 *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/common/errorMessages.h b/src/lib/common/errorMessages.h index 4a5333e75c..a638981806 100644 --- a/src/lib/common/errorMessages.h +++ b/src/lib/common/errorMessages.h @@ -98,7 +98,11 @@ #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_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/common/globals.h b/src/lib/common/globals.h index 73c68c7187..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_ONUPDATE = 3 + NGSIV2_FLAVOUR_ONAPPEND = 2 } Ngsiv2Flavour; diff --git a/src/lib/mongoBackend/MongoCommonUpdate.cpp b/src/lib/mongoBackend/MongoCommonUpdate.cpp index afdec2510f..9fb1f84c8f 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; @@ -3473,9 +3469,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 +3482,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; @@ -3616,53 +3612,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(eP->attributeVector[ix]->name)) - { - alarmMgr.badInput(clientIp, "attribute already exists", eP->attributeVector[ix]->name); - *attributeAlreadyExistsError = true; + (*attributeAlreadyExistsNumber)++;; - // - // 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)) - { - for (unsigned int ix = 0; ix < eP->attributeVector.size(); ++ix) + else // !attrs.hasField(dbEncode(eP->attributeVector[ix]->name)) { - if (!attrs.hasField (eP->attributeVector[ix]->name)) - { - *attributeNotExistingError = true; + (*attributeNotExistingNumber)++; - // 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 @@ -3702,9 +3690,9 @@ static unsigned int updateEntity // searchContextProviders(tenant, servicePathV, en, eP->attributeVector, cerP); - if (!(attributeAlreadyExistsError && (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); @@ -4115,9 +4103,16 @@ unsigned int processContextElement const bool& overrideMetadata, unsigned int notifStartCounter, ApiVersion apiVersion, - Ngsiv2Flavour ngsiv2Flavour + Ngsiv2Flavour ngsiv2Flavour, + 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 + if (updateCoverageP != NULL) + { + *updateCoverageP = UC_SUCCESS; + } + /* Check preconditions */ if (!contextElementPreconditionsCheck(eP, responseP, action, apiVersion)) { @@ -4128,14 +4123,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 @@ -4187,6 +4184,7 @@ unsigned int processContextElement } // This is the case of POST /v2/entities/, in order to check that entity previously exist + // 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); @@ -4263,11 +4261,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 */ @@ -4280,9 +4278,9 @@ unsigned int processContextElement xauthToken, eP, responseP, - &attributeAlreadyExistsError, + &attributeAlreadyExistsNumber, &attributeAlreadyExistsList, - &attributeNotExistingError, + &attributeNotExistingNumber, &attributeNotExistingList, forcedUpdate, overrideMetadata, @@ -4342,7 +4340,12 @@ unsigned int processContextElement } else { - responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, 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; + } } } } @@ -4350,8 +4353,13 @@ unsigned int processContextElement { cerP->statusCode.fill(SccContextElementNotFound); - responseP->oe.fill(SccContextElementNotFound, ERROR_DESC_NOT_FOUND_ENTITY, 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) + { + *updateCoverageP = UC_ENTITY_NOT_FOUND; + } } else /* APPEND or APPEND_STRICT */ { @@ -4449,18 +4457,51 @@ unsigned int processContextElement } } - if (attributeAlreadyExistsError == true) + if ((attributeAlreadyExistsNumber > 0) && (action == ActionTypeAppendStrict)) { - std::string details = "one or more of the attributes in the request already exist: " + attributeAlreadyExistsList; + std::string details = ERROR_DESC_UNPROCESSABLE_ATTR_ALREADY_EXISTS + enStr + " - " + attributeAlreadyExistsList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + enStr + " - " + attributeAlreadyExistsList, ERROR_UNPROCESSABLE); } - if (attributeNotExistingError == true) + if ((apiVersion == V2) && (attributeNotExistingNumber > 0) && ((action == ActionTypeUpdate) || (action == ActionTypeDelete))) { - std::string details = "one or more of the attributes in the request do not exist: " + attributeNotExistingList; + std::string details = ERROR_DESC_DO_NOT_EXIT + enStr + " - " + attributeNotExistingList; buildGeneralErrorResponse(eP, NULL, responseP, SccBadRequest, details); - responseP->oe.fill(SccInvalidModification, details, ERROR_UNPROCESSABLE); + responseP->oe.fillOrAppend(SccInvalidModification, details, ", " + enStr + " - " + attributeNotExistingList, ERROR_UNPROCESSABLE); + } + + if (updateCoverageP != NULL) + { + 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_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 + 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_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 + else if (attributeAlreadyExistsNumber > 0) + { + *updateCoverageP = UC_PARTIAL; + } + } } // Response in responseP diff --git a/src/lib/mongoBackend/MongoCommonUpdate.h b/src/lib/mongoBackend/MongoCommonUpdate.h index 5a22880c26..3873b7a4f8 100644 --- a/src/lib/mongoBackend/MongoCommonUpdate.h +++ b/src/lib/mongoBackend/MongoCommonUpdate.h @@ -36,6 +36,22 @@ #define MONGODB_ERROR_WRONGJSON "Can't extract geo keys" + +/* **************************************************************************** +* +* UpdateCoverage - +*/ +typedef enum UpdateCoverage +{ + UC_NONE = 0, + UC_SUCCESS = 1, + UC_FULL_ATTRS_FAIL = 2, + UC_ENTITY_NOT_FOUND = 3, + UC_PARTIAL = 4 +} UpdateCoverage; + + + /* **************************************************************************** * * processContextElement - @@ -55,7 +71,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_ diff --git a/src/lib/mongoBackend/mongoUpdateContext.cpp b/src/lib/mongoBackend/mongoUpdateContext.cpp index 5c6dabff7c..a6e29ea78b 100644 --- a/src/lib/mongoBackend/mongoUpdateContext.cpp +++ b/src/lib/mongoBackend/mongoUpdateContext.cpp @@ -150,8 +150,10 @@ HttpStatusCode mongoUpdateContext else { /* Process each ContextElement */ + UpdateCoverage updateCoverage = UC_NONE; for (unsigned int ix = 0; ix < requestP->entityVector.size(); ++ix) { + UpdateCoverage entityUpdateCoverage; notifSent += processContextElement(requestP->entityVector[ix], responseP, requestP->updateActionType, @@ -165,7 +167,62 @@ HttpStatusCode mongoUpdateContext overrideMetadata, notifSent, apiVersion, - ngsiv2Flavour); + ngsiv2Flavour, + &entityUpdateCoverage); + 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_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_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), the global UC changes to partial + if ((entityUpdateCoverage != UC_FULL_ATTRS_FAIL) && (entityUpdateCoverage != UC_ENTITY_NOT_FOUND)) + { + 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: + // If global UC is partial, we keep partial (no matter the result of processed entity) + 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 (updateCoverage == UC_PARTIAL) + { + responseP->oe.code = SccInvalidModification; + responseP->oe.reasonPhrase = ERROR_PARTIAL_UPDATE; } LM_T(LmtNotifier, ("total notifications sent during update: %d", notifSent)); diff --git a/src/lib/rest/OrionError.cpp b/src/lib/rest/OrionError.cpp index cbec3a9c9e..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,7 @@ void OrionError::fill(HttpStatusCode _code, const std::string& _details, const s code = _code; reasonPhrase = _reasonPhrase.empty()? httpStatusCodeString(code) : _reasonPhrase; details = _details; + filled = true; } @@ -94,6 +98,29 @@ void OrionError::fill(const StatusCode& sc) code = sc.code; reasonPhrase = (sc.reasonPhrase.empty())? httpStatusCodeString(code) : sc.reasonPhrase; details = sc.details; + filled = true; +} + + + +/* **************************************************************************** +* +* OrionError::fillOrAppend - +*/ +void OrionError::fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase) +{ + if (filled) + { + // Already filled by a previous operation. This can happen in batch update processing + details += appendDetail; + } + else + { + code = _code; + reasonPhrase = _reasonPhrase.empty()? httpStatusCodeString(code) : _reasonPhrase; + details = fullDetails; + filled = true; + } } diff --git a/src/lib/rest/OrionError.h b/src/lib/rest/OrionError.h index 47833a0dac..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); @@ -55,6 +56,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 fillOrAppend(HttpStatusCode _code, const std::string& fullDetails, const std::string& appendDetail, const std::string& _reasonPhrase); + private: void shrinkReasonPhrase(void); 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 { diff --git a/src/lib/serviceRoutinesV2/deleteEntity.cpp b/src/lib/serviceRoutinesV2/deleteEntity.cpp index 45015a83d4..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,6 +91,9 @@ std::string deleteEntity // Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); + ciP->outMimeType = JSON; // Check for potential error diff --git a/src/lib/serviceRoutinesV2/patchEntity.cpp b/src/lib/serviceRoutinesV2/patchEntity.cpp index 8c505d4bc0..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,6 +86,9 @@ std::string patchEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // 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/postEntity.cpp b/src/lib/serviceRoutinesV2/postEntity.cpp index 7797bc7e87..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,22 +75,20 @@ std::string postEntity return oe.toJson(); } - if (ciP->uriParamOptions["append"] == true) // pure-append + if (ciP->uriParamOptions[OPT_APPEND] == true) // pure-append { op = ActionTypeAppendStrict; - flavor = NGSIV2_FLAVOUR_ONUPDATE; } 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 = ""; diff --git a/src/lib/serviceRoutinesV2/putEntity.cpp b/src/lib/serviceRoutinesV2/putEntity.cpp index 5df120b028..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,6 +85,9 @@ std::string putEntity // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); +// Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), false); + // 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 59ca2e8d4e..25713cb229 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,6 +85,9 @@ std::string putEntityAttribute // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); + // 03. Check error std::string answer = ""; if (parseDataP->upcrs.res.oe.code != SccNone ) diff --git a/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp b/src/lib/serviceRoutinesV2/putEntityAttributeValue.cpp index ce14f00684..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,6 +92,9 @@ std::string putEntityAttributeValue // 02. Call standard op postUpdateContext postUpdateContext(ciP, components, compV, parseDataP); + // Adjust error code if needed + adaptErrorCodeForSingleEntityOperation(&(parseDataP->upcrs.res.oe), true); + // 03. Check output from mongoBackend std::string answer = ""; if (parseDataP->upcrs.res.oe.code != SccNone) 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/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 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..0bd2d948dd --- /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 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" +# } +# + +# +# 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..65df37a7e9 --- /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 entities 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..4a99978e6b --- /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 entities 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 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..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: 110 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: [ 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 56e7955391..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: 107 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", + "description": "do not exist: E1/T1 - [ 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..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 @@ -263,11 +263,11 @@ 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 ]", - "error": "Unprocessable" + "description": "one or more of the attributes in the request already exist: E1 - [ attr4 ]", + "error": "PartialUpdate" } 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..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: 108 +Content-Length: 116 { - "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/T2 - [ A3 ]", "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..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: 224 +Content-Length: 232 { "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/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: 388 +Content-Length: 396 { "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/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 c4dc659d5c..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: 107 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: [ 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 c4d4e2c97b..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: 113 +Content-Length: 79 { - "description": "one or more of the attributes in the request do not exist: [ dfgdfgdf ]", - "error": "Unprocessable" + "description": "The entity does not have such an attribute", + "error": "NotFound" } 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..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,17 +142,17 @@ 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}) Content-Type: application/json -Content-Length: 107 +Content-Length: 112 { - "description": "one or more of the attributes in the request already exist: [ A ]", - "error": "Unprocessable" + "description": "one or more of the attributes in the request already exist: E1 - [ A ]", + "error": "PartialUpdate" } 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..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: 108 +Content-Length: 116 { - "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/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 8568b6fbfb..f18c6bb798 100644 --- a/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE.test @@ -136,10 +136,10 @@ HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 74 { - "description": "The requested entity has not been found. Check type and id", + "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 8cd808c80b..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 @@ -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 @@ -229,25 +229,25 @@ 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: 69 { - "description": "The entity does not have such an attribute", - "error": "NotFound" + "description": "do not exist: E2/T - [ A2 ]", + "error": "PartialUpdate" } -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 new file mode 100644 index 0000000000..16a31aa672 --- /dev/null +++ b/test/functionalTest/cases/1715_batch_update/batch_update_DELETE_non_existing_and_existing_several_entities.test @@ -0,0 +1,332 @@ +# 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/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" +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/A3, E3/T/A3 and E4/T/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: 84 + +{ + "description": "do not exist: E2/T - [ A2 ], E4/T - [ A1 ]", + "error": "PartialUpdate" +} + + +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: 285 + +[ + { + "A3": { + "metadata": {}, + "type": "Number", + "value": 13 + }, + "id": "E1", + "type": "T" + }, + { + "A3": { + "metadata": {}, + "type": "Number", + "value": 23 + }, + "id": "E2", + "type": "T" + }, + { + "A3": { + "metadata": {}, + "type": "Number", + "value": 33 + }, + "id": "E3", + "type": "T" + }, + { + "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..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 @@ -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: 69 { - "description": "The entity does not have such an attribute", - "error": "NotFound" + "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 82454712f4..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: 107 +Content-Length: 70 { - "description": "one or more of the attributes in the request do not exist: [ 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 503dfb3356..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 @@ -90,10 +90,10 @@ HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 72 { - "description": "The requested entity has not been found. Check type and id", + "description": "do not exist: E/T - [entity itself]", "error": "NotFound" } @@ -104,10 +104,10 @@ HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 72 { - "description": "The requested entity has not been found. Check type and id", + "description": "do not exist: E/T - [entity itself]", "error": "NotFound" } @@ -118,10 +118,10 @@ HTTP/1.1 404 Not Found Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 95 +Content-Length: 72 { - "description": "The requested entity has not been found. Check type and id", + "description": "do not exist: E/T - [entity itself]", "error": "NotFound" } 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..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,11 +89,11 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 107 +Content-Length: 67 { - "description": "one or more of the attributes in the request do not exist: [ A2 ]", - "error": "Unprocessable" + "description": "do not exist: E1 - [ A2 ]", + "error": "PartialUpdate" } 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..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: 107 +Content-Length: 79 { - "description": "one or more of the attributes in the request do not exist: [ 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 ea20ea72ed..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 @@ -77,7 +79,7 @@ echo '03. PATCH /v2/entities/Room1/attrs, to update existing attribute (temperat echo '====================================================================================================================================================================' payload='{ "temperature": { - "value": 24, + "value": 25, "type": "Float" }, "temper": { @@ -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 @@ -117,11 +121,11 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 112 +Content-Length: 75 { - "description": "one or more of the attributes in the request do not exist: [ pressur ]", - "error": "Unprocessable" + "description": "do not exist: Room1 - [ pressur ]", + "error": "PartialUpdate" } @@ -131,11 +135,11 @@ HTTP/1.1 422 Unprocessable Content Date: REGEX(.*) Fiware-Correlator: REGEX([0-9a-f\-]{36}) Content-Type: application/json -Content-Length: 120 +Content-Length: 83 { - "description": "one or more of the attributes in the request do not exist: [ temper, pressur ]", - "error": "Unprocessable" + "description": "do not exist: Room1 - [ temper, pressur ]", + "error": "PartialUpdate" } @@ -158,7 +162,7 @@ Content-Length: 141 "temperature": { "metadata": {}, "type": "Float", - "value": 24 + "value": 25 }, "type": "Thing" } 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 new file mode 100644 index 0000000000..f8b2e1c410 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_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 in batch operation + +--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: 134 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ A, B ], E2/T - [ 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: 117 + +{ + "description": "one or more of the attributes in the request already exist: E2/T - [ 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: 114 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ 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: 131 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ A ], E2/T - [ 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: 128 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ A ], E2/T - [ A ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..4f807d90df --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_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 in batch operation + +--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): NotFound" +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: 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: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +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: 97 + +{ + "description": "do not exist: E3/T3 - [entity itself], E4/T3 [entity itself]", + "error": "NotFound" +} + + +04. Update E1-A/B (full success) + 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: 79 + +{ + "description": "do not exist: E3/T4 - [entity itself]", + "error": "PartialUpdate" +} + + +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: 69 + +{ + "description": "do not exist: E1/T5 - [ C ]", + "error": "PartialUpdate" +} + + +06. Update E1-A/C (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: 92 + +{ + "description": "do not exist: E1/T6 - [ C ], E3/T6 [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: 84 + +{ + "description": "do not exist: E1/T7 - [ C ], E2/T7 - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..1f95ea79e5 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_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 in batch operation + +--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): NotFound" +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: 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: REGEX(.*) +Fiware-Correlator: REGEX([0-9a-f\-]{36}) + + + +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: 95 + +{ + "description": "do not exist: E3/T - [entity itself], E4/T [entity itself]", + "error": "NotFound" +} + + +04. Update E1-A/B (full success) + 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: 78 + +{ + "description": "do not exist: E3/T - [entity itself]", + "error": "PartialUpdate" +} + + +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: 68 + +{ + "description": "do not exist: E1/T - [ 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: 90 + +{ + "description": "do not exist: E1/T - [ C ], E3/T [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: 82 + +{ + "description": "do not exist: E1/T - [ C ], E2/T - [ C ]", + "error": "PartialUpdate" +} + + +--TEARDOWN-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..6c15add5d7 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict.test @@ -0,0 +1,231 @@ +# 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 in batch operation + +--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-- +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: 113 + +{ + "description": "one or more of the attributes in the request already exist: E/T - [ A ]", + "error": "PartialUpdate" +} + + +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: 113 + +{ + "description": "one or more of the attributes in the request already exist: E/T - [ B ]", + "error": "PartialUpdate" +} + + +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-- +brokerStop CB +dbDrop 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 new file mode 100644 index 0000000000..5dc96ef8f6 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_appendstrict_several_entities.test @@ -0,0 +1,405 @@ +# 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 in batch operation + +--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 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 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 +# + +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 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": + [ + { + "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 E1/E2/E3 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-- +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: 151 + +{ + "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" +} + + +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: 142 + +{ + "description": "one or more of the attributes in the request already exist: E1/T - [ B ], E2/T - [ B ], E3/T - [ B ]", + "error": "PartialUpdate" +} + + +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 +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..c7add1534d --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete.test @@ -0,0 +1,205 @@ +# 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 in batch operation + +--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": "delete", + "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-- +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: 70 + +{ + "description": "do not exist: E/T - [ B, C ]", + "error": "PartialUpdate" +} + + +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: 67 + +{ + "description": "do not exist: E/T - [ B ]", + "error": "PartialUpdate" +} + + +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-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..4a8e4536c9 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_delete_several_entities.test @@ -0,0 +1,328 @@ +# 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 in batch operation + +--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 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 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" +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 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": + [ + { + "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 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": + [ + { + "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, 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: 85 + +{ + "description": "do not exist: E1/T - [ B, C ], E2/T - [ C ]", + "error": "PartialUpdate" +} + + +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: 96 + +{ + "description": "do not exist: E1/T - [ B ], E2/T - [ B ], E3/T - [ B ]", + "error": "PartialUpdate" +} + + +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-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..1728cf0292 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_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 in batch operation + +--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: 93 + +{ + "description": "do not exist: E1/T - [ B, C ], E2/T [entity itself]", + "error": "PartialUpdate" +} + + +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: 104 + +{ + "description": "do not exist: E1/T - [ B ], E2/T [entity itself], E3/T - [ B ]", + "error": "PartialUpdate" +} + + +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/batch_partial_update_action_update.test b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test new file mode 100644 index 0000000000..2ffe7c4fe8 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update.test @@ -0,0 +1,206 @@ +# 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 in batch operation + +--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-- +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: 70 + +{ + "description": "do not exist: E/T - [ B, C ]", + "error": "PartialUpdate" +} + + +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: 67 + +{ + "description": "do not exist: E/T - [ B ]", + "error": "PartialUpdate" +} + + +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-- +brokerStop CB +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..4543a819fb --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_partial_update_action_update_several_entities.test @@ -0,0 +1,360 @@ +# 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 in batch operation + +--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=30 +# + +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=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: 85 + +{ + "description": "do not exist: E1/T - [ B, C ], E2/T - [ C ]", + "error": "PartialUpdate" +} + + +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: 68 + +{ + "description": "do not exist: E1/T - [ B ]", + "error": "PartialUpdate" +} + + +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 +dbDrop CB \ No newline at end of file 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 new file mode 100644 index 0000000000..2073cc7391 --- /dev/null +++ b/test/functionalTest/cases/3499_partial_update_response/batch_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 in batch operation + +--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: 93 + +{ + "description": "do not exist: E1/T - [ B, C ], E2/T [entity itself]", + "error": "PartialUpdate" +} + + +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: 90 + +{ + "description": "do not exist: E1/T - [ B ], E2/T [entity itself]", + "error": "PartialUpdate" +} + + +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 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..1c8eb4281a --- /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 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" +} + + +03. DELETE /v2/entities/E/attrs/C?type=T (full fail) +==================================================== +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/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