Check for required properties in POST request.
authorTodd Malsbary <todd.malsbary@intel.com>
Fri, 6 Oct 2017 18:11:19 +0000 (11:11 -0700)
committerTodd Malsbary <todd.malsbary@intel.com>
Thu, 12 Oct 2017 17:07:36 +0000 (17:07 +0000)
Bug: https://jira.iotivity.org/browse/IOT-2784
Change-Id: I0f7ff269693e50dee3c2ad870febdddcd5c69d8e
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
resource/csdk/resource-directory/src/internal/rd_database.c
resource/csdk/resource-directory/src/rd_server.c
resource/csdk/resource-directory/unittests/rdtests.cpp

index e899b8964bf91364e6f7af4fb8a8ec4938f17f93..8caf70990deedd56eb46fdea5c2975bce949cfd5 100644 (file)
@@ -95,6 +95,11 @@ static void errorCallback(void *arg, int errCode, const char *errMsg)
     OIC_LOG_V(ERROR, TAG, "SQLLite Error: %s : %d", errMsg, errCode);
 }
 
+static bool stringArgumentNonNullAndWithinBounds(const char* argument)
+{
+    return ((NULL != argument) && (strlen(argument) <= INT_MAX));
+}
+
 static bool stringArgumentWithinBounds(const char* argument)
 {
     return ((NULL == argument) || (strlen(argument) <= INT_MAX));
@@ -115,7 +120,7 @@ static bool stringArgumentsWithinBounds(const char** arguments, size_t count)
 
 static int storeResourceTypes(const char **resourceTypes, size_t size, sqlite3_int64 rowid)
 {
-    int res = 1;
+    int res = SQLITE_ERROR;
     sqlite3_stmt *stmt = NULL;
     if (!stringArgumentsWithinBounds(resourceTypes, size))
     {
@@ -129,7 +134,6 @@ static int storeResourceTypes(const char **resourceTypes, size_t size, sqlite3_i
     int deleteRTSize = (int)sizeof(deleteRT);
     int insertRTSize = (int)sizeof(insertRT);
 
-
     VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, deleteRT, deleteRTSize, &stmt, NULL));
     VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
     res = sqlite3_step(stmt);
@@ -172,7 +176,7 @@ exit:
 
 static int storeInterfaces(const char **interfaces, size_t size, sqlite3_int64 rowid)
 {
-    int res = 1;
+    int res = SQLITE_ERROR;
     sqlite3_stmt *stmt = NULL;
     if (!stringArgumentsWithinBounds(interfaces, size))
     {
@@ -288,182 +292,188 @@ exit:
     return res;
 }
 
-static int storeLinkPayload(const OCRepPayload *rdPayload, sqlite3_int64 rowid)
+static OCRepPayloadValue *getLinks(const OCRepPayload *rdPayload)
 {
-    int res = SQLITE_OK;
-
     /*
      * Iterate over the properties manually rather than OCRepPayloadGetPropObjectArray to avoid
      * the clone since we want to insert the 'ins' values into the payload.
      */
-    OCRepPayloadValue *links;
-    for (links = rdPayload->values; links; links = links->next)
+    OCRepPayloadValue *links = NULL;
+    if (rdPayload)
     {
-        if (0 == strcmp(links->name, OC_RSRVD_LINKS))
+        for (links = rdPayload->values; links; links = links->next)
         {
-            if (links->type != OCREP_PROP_ARRAY || links->arr.type != OCREP_PROP_OBJECT)
+            if (0 == strcmp(links->name, OC_RSRVD_LINKS))
             {
-                links = NULL;
+                if (links->type != OCREP_PROP_ARRAY || links->arr.type != OCREP_PROP_OBJECT)
+                {
+                    links = NULL;
+                }
+                break;
             }
-            break;
         }
     }
-    if (links != NULL)
-    {
-        sqlite3_stmt *stmt = NULL;
-        char *uri = NULL;
-        char *anchor = NULL;
-        OCRepPayload *p = NULL;
-        char **rt = NULL;
-        size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
-        char **itf = NULL;
-        size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
-        OCRepPayload** eps = NULL;
-        size_t epsDim[MAX_REP_ARRAY_DEPTH] = {0};
-
-        static const char insertDeviceLLList[] = "INSERT OR IGNORE INTO RD_DEVICE_LINK_LIST (ins, href, DEVICE_ID) "
-            "VALUES((SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri),@uri,@id)";
-        static const char updateDeviceLLList[] = "UPDATE RD_DEVICE_LINK_LIST SET anchor=@anchor,bm=@bm "
-            "WHERE DEVICE_ID=@id AND href=@uri";
-        int insertDeviceLLListSize = (int)sizeof(insertDeviceLLList);
-        int updateDeviceLLListSize = (int)sizeof(updateDeviceLLList);
-
-        for (size_t i = 0; (SQLITE_OK == res) && (i < links->arr.dimensions[0]); i++)
-        {
-            VERIFY_SQLITE(sqlite3_exec(gRDDB, "SAVEPOINT storeLinkPayload", NULL, NULL, NULL));
+    return links;
+}
 
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceLLList,
-                            insertDeviceLLListSize, &stmt, NULL));
+static int storeLinkPayload(OCRepPayloadValue *links, sqlite3_int64 rowid)
+{
+    int res = SQLITE_OK;
 
-            OCRepPayload *link = links->arr.objArray[i];
-            VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
-            if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
-            {
-                if (!stringArgumentWithinBounds(uri))
-                {
-                    return res;
-                }
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
-                                uri, (int)strlen(uri), SQLITE_STATIC));
-            }
-            res = sqlite3_step(stmt);
-            if (SQLITE_DONE != res)
+    sqlite3_stmt *stmt = NULL;
+    char *uri = NULL;
+    char *anchor = NULL;
+    OCRepPayload *p = NULL;
+    char **rt = NULL;
+    size_t rtDim[MAX_REP_ARRAY_DEPTH] = {0};
+    char **itf = NULL;
+    size_t itfDim[MAX_REP_ARRAY_DEPTH] = {0};
+    OCRepPayload** eps = NULL;
+    size_t epsDim[MAX_REP_ARRAY_DEPTH] = {0};
+
+    static const char insertDeviceLLList[] = "INSERT OR IGNORE INTO RD_DEVICE_LINK_LIST (ins, href, DEVICE_ID) "
+        "VALUES((SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri),@uri,@id)";
+    static const char updateDeviceLLList[] = "UPDATE RD_DEVICE_LINK_LIST SET anchor=@anchor,bm=@bm "
+        "WHERE DEVICE_ID=@id AND href=@uri";
+    int insertDeviceLLListSize = (int)sizeof(insertDeviceLLList);
+    int updateDeviceLLListSize = (int)sizeof(updateDeviceLLList);
+
+    assert(links);
+    for (size_t i = 0; (SQLITE_OK == res) && (i < links->arr.dimensions[0]); i++)
+    {
+        VERIFY_SQLITE(sqlite3_exec(gRDDB, "SAVEPOINT storeLinkPayload", NULL, NULL, NULL));
+
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceLLList,
+                        insertDeviceLLListSize, &stmt, NULL));
+
+        OCRepPayload *link = links->arr.objArray[i];
+        VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+        if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
+        {
+            if (!stringArgumentWithinBounds(uri))
             {
-                goto exit;
+                return SQLITE_ERROR;
             }
-            VERIFY_SQLITE(sqlite3_finalize(stmt));
-            stmt = NULL;
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                            uri, (int)strlen(uri), SQLITE_STATIC));
+        }
+        res = sqlite3_step(stmt);
+        if (SQLITE_DONE != res)
+        {
+            goto exit;
+        }
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+        stmt = NULL;
 
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, updateDeviceLLList,
-                            updateDeviceLLListSize, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
-            if (uri)
-            {
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
-                                uri, (int)strlen(uri), SQLITE_STATIC));
-            }
-            if (OCRepPayloadGetPropString(link, OC_RSRVD_URI, &anchor))
-            {
-                if (!stringArgumentWithinBounds(anchor))
-                {
-                    goto exit;
-                }
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@anchor"),
-                                anchor, (int)strlen(anchor), SQLITE_STATIC));
-            }
-            if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, updateDeviceLLList,
+                        updateDeviceLLListSize, &stmt, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+        if (uri)
+        {
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                            uri, (int)strlen(uri), SQLITE_STATIC));
+        }
+        if (OCRepPayloadGetPropString(link, OC_RSRVD_URI, &anchor))
+        {
+            if (!stringArgumentWithinBounds(anchor))
             {
-                sqlite3_int64 bm = 0;
-                if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, (int64_t *) &bm))
-                {
-                    VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@bm"), bm));
-                }
+                goto exit;
             }
-            res = sqlite3_step(stmt);
-            if (SQLITE_DONE != res)
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@anchor"),
+                            anchor, (int)strlen(anchor), SQLITE_STATIC));
+        }
+        if (OCRepPayloadGetPropObject(link, OC_RSRVD_POLICY, &p))
+        {
+            sqlite3_int64 bm = 0;
+            if (OCRepPayloadGetPropInt(p, OC_RSRVD_BITMAP, (int64_t *) &bm))
             {
-                goto exit;
+                VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@bm"), bm));
             }
-            VERIFY_SQLITE(sqlite3_finalize(stmt));
-            stmt = NULL;
+        }
+        res = sqlite3_step(stmt);
+        if (SQLITE_DONE != res)
+        {
+            goto exit;
+        }
+        VERIFY_SQLITE(sqlite3_finalize(stmt));
+        stmt = NULL;
 
-            static const char input[] = "SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri";
-            int inputSize = (int)sizeof(input);
+        static const char input[] = "SELECT ins FROM RD_DEVICE_LINK_LIST WHERE DEVICE_ID=@id AND href=@uri";
+        int inputSize = (int)sizeof(input);
 
-            VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
-            VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
-            if (uri)
-            {
-                VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
-                                uri, (int)strlen(uri), SQLITE_STATIC));
-            }
-            res = sqlite3_step(stmt);
-            if (res == SQLITE_ROW || res == SQLITE_DONE)
-            {
-                sqlite3_int64 ins = sqlite3_column_int64(stmt, 0);
-                VERIFY_SQLITE(sqlite3_finalize(stmt));
-                stmt = NULL;
-                if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
-                {
-                    OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
-                    return OC_STACK_ERROR;
-                }
-                OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
-                OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
-                OCRepPayloadGetPropObjectArray(link, OC_RSRVD_ENDPOINTS, &eps, epsDim);
-                VERIFY_SQLITE(storeResourceTypes((const char **) rt, rtDim[0], ins));
-                VERIFY_SQLITE(storeInterfaces((const char **) itf, itfDim[0], ins));
-                VERIFY_SQLITE(storeEndpoints(eps, epsDim[0], ins));
-            }
-            else
+        VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, inputSize, &stmt, NULL));
+        VERIFY_SQLITE(sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, "@id"), rowid));
+        if (uri)
+        {
+            VERIFY_SQLITE(sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, "@uri"),
+                            uri, (int)strlen(uri), SQLITE_STATIC));
+        }
+        res = sqlite3_step(stmt);
+        if (res == SQLITE_ROW || res == SQLITE_DONE)
+        {
+            sqlite3_int64 ins = sqlite3_column_int64(stmt, 0);
+            VERIFY_SQLITE(sqlite3_finalize(stmt));
+            stmt = NULL;
+            if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
             {
-                VERIFY_SQLITE(sqlite3_finalize(stmt));
-                stmt = NULL;
+                OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
+                return SQLITE_ERROR;
             }
+            OCRepPayloadGetStringArray(link, OC_RSRVD_RESOURCE_TYPE, &rt, rtDim);
+            OCRepPayloadGetStringArray(link, OC_RSRVD_INTERFACE, &itf, itfDim);
+            OCRepPayloadGetPropObjectArray(link, OC_RSRVD_ENDPOINTS, &eps, epsDim);
+            VERIFY_SQLITE(storeResourceTypes((const char **) rt, rtDim[0], ins));
+            VERIFY_SQLITE(storeInterfaces((const char **) itf, itfDim[0], ins));
+            VERIFY_SQLITE(storeEndpoints(eps, epsDim[0], ins));
+        }
+        else
+        {
+            VERIFY_SQLITE(sqlite3_finalize(stmt));
+            stmt = NULL;
+        }
 
-            VERIFY_SQLITE(sqlite3_exec(gRDDB, "RELEASE storeLinkPayload", NULL, NULL, NULL));
-            res = SQLITE_OK;
+        VERIFY_SQLITE(sqlite3_exec(gRDDB, "RELEASE storeLinkPayload", NULL, NULL, NULL));
+        res = SQLITE_OK;
 
-        exit:
-            if (eps)
-            {
-                for (size_t j = 0; j < epsDim[0]; j++)
-                {
-                    OCRepPayloadDestroy(eps[j]);
-                }
-                OICFree(eps);
-                eps = NULL;
-            }
-            if (itf)
+    exit:
+        if (eps)
+        {
+            for (size_t j = 0; j < epsDim[0]; j++)
             {
-                for (size_t j = 0; j < itfDim[0]; j++)
-                {
-                    OICFree(itf[j]);
-                }
-                OICFree(itf);
-                itf = NULL;
+                OCRepPayloadDestroy(eps[j]);
             }
-            if (rt)
+            OICFree(eps);
+            eps = NULL;
+        }
+        if (itf)
+        {
+            for (size_t j = 0; j < itfDim[0]; j++)
             {
-                for (size_t j = 0; j < rtDim[0]; j++)
-                {
-                    OICFree(rt[j]);
-                }
-                OICFree(rt);
-                rt = NULL;
+                OICFree(itf[j]);
             }
-            OCPayloadDestroy((OCPayload *)p);
-            p = NULL;
-            OICFree(anchor);
-            anchor = NULL;
-            OICFree(uri);
-            uri = NULL;
-            sqlite3_finalize(stmt);
-            stmt = NULL;
-            if (SQLITE_OK != res)
+            OICFree(itf);
+            itf = NULL;
+        }
+        if (rt)
+        {
+            for (size_t j = 0; j < rtDim[0]; j++)
             {
-                sqlite3_exec(gRDDB, "ROLLBACK TO storeLinkPayload", NULL, NULL, NULL);
+                OICFree(rt[j]);
             }
+            OICFree(rt);
+            rt = NULL;
+        }
+        OCPayloadDestroy((OCPayload *)p);
+        p = NULL;
+        OICFree(anchor);
+        anchor = NULL;
+        OICFree(uri);
+        uri = NULL;
+        sqlite3_finalize(stmt);
+        stmt = NULL;
+        if (SQLITE_OK != res)
+        {
+            sqlite3_exec(gRDDB, "ROLLBACK TO storeLinkPayload", NULL, NULL, NULL);
         }
     }
 
@@ -472,18 +482,31 @@ static int storeLinkPayload(const OCRepPayload *rdPayload, sqlite3_int64 rowid)
 
 static int storeResources(const OCRepPayload *payload, bool externalHost)
 {
-    char *deviceId = NULL;
     sqlite3_stmt *stmt = NULL;
+
+    /* di is a required property */
+    char *deviceId = NULL;
     OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceId);
-    if (!stringArgumentWithinBounds(deviceId))
+    if (!stringArgumentNonNullAndWithinBounds(deviceId))
     {
-        return OC_STACK_ERROR;
+        return SQLITE_ERROR;
     }
 
+    /* ttl is a required property */
     int64_t tmp = 0;
-    OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &tmp);
+    if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_DEVICE_TTL, &tmp))
+    {
+        return SQLITE_ERROR;
+    }
     sqlite3_int64 ttl = tmp;
 
+    /* links is a required property */
+    OCRepPayloadValue *links = getLinks(payload);
+    if (!links)
+    {
+        return SQLITE_ERROR;
+    }
+
     int res;
     VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
 
@@ -549,7 +572,7 @@ static int storeResources(const OCRepPayload *payload, bool externalHost)
         sqlite3_int64 rowid = sqlite3_column_int64(stmt, 0);
         VERIFY_SQLITE(sqlite3_finalize(stmt));
         stmt = NULL;
-        VERIFY_SQLITE(storeLinkPayload(payload, rowid));
+        VERIFY_SQLITE(storeLinkPayload(links, rowid));
     }
     else
     {
@@ -577,7 +600,7 @@ static int deleteResources(const char *deviceId, const int64_t *instanceIds, uin
     if (!stringArgumentWithinBounds(deviceId))
     {
         OIC_LOG_V(ERROR, TAG, "Query longer than %d: \n%s", INT_MAX, deviceId);
-        return OC_STACK_ERROR;
+        return SQLITE_ERROR;
     }
 
     int res;
index 4aafa416131e4a2f36478a2a98eb0c1f10e608f4..bce0185e34a09298bd819e9866fe8586d792e8ed 100644 (file)
@@ -149,7 +149,7 @@ static bool isRequestFromThisHost(const OCEntityHandlerRequest *ehRequest)
  */
 static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
 {
-    OCEntityHandlerResult ehResult = OC_EH_OK;
+    OCEntityHandlerResult ehResult;
 
     if (!ehRequest)
     {
@@ -161,48 +161,46 @@ static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *
 
     OCRepPayload *payload = (OCRepPayload *)ehRequest->payload;
     OCRepPayload *resPayload = NULL;
-    if (payload)
+    OCStackResult result;
+    OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
+    result = OCRDDatabaseInit();
+    if (OC_STACK_OK == result)
     {
-        OIC_LOG_PAYLOAD(DEBUG, (OCPayload *) payload);
-        if (OC_STACK_OK == OCRDDatabaseInit())
+        if (isRequestFromThisHost(ehRequest))
         {
-            OCStackResult result;
-            if (isRequestFromThisHost(ehRequest))
-            {
-                result = OCRDDatabaseStoreResourcesFromThisHost(payload);
-            }
-            else
-            {
-                result = OCRDDatabaseStoreResources(payload);
-            }
-            if (OC_STACK_OK == result)
-            {
-                OIC_LOG_V(DEBUG, TAG, "Stored resources.");
-                resPayload = payload;
-                ehResult = OC_EH_OK;
-            }
-            else
-            {
-                resPayload = (OCRepPayload *)OCRepPayloadCreate();
-                ehResult = OC_EH_ERROR;
-            }
+            result = OCRDDatabaseStoreResourcesFromThisHost(payload);
         }
-
-        // Send Response
-        if (OC_STACK_OK != sendResponse(ehRequest, resPayload, ehResult))
+        else
         {
-            OIC_LOG(ERROR, TAG, "Sending response failed.");
+            result = OCRDDatabaseStoreResources(payload);
         }
+    }
+    if (OC_STACK_OK == result)
+    {
+        OIC_LOG_V(DEBUG, TAG, "Stored resources.");
+        resPayload = payload;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        resPayload = (OCRepPayload *)OCRepPayloadCreate();
+        ehResult = OC_EH_ERROR;
+    }
+
+    // Send Response
+    if (OC_STACK_OK != sendResponse(ehRequest, resPayload, ehResult))
+    {
+        OIC_LOG(ERROR, TAG, "Sending response failed.");
+    }
 
-        if (OC_EH_OK == ehResult)
+    if (OC_EH_OK == ehResult)
+    {
+        OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
+        assert(handle);
+        result = OCNotifyAllObservers(handle, OC_NA_QOS);
+        if (OC_STACK_NO_OBSERVERS != result && OC_STACK_OK != result)
         {
-            OCResourceHandle handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
-            assert(handle);
-            OCStackResult result = OCNotifyAllObservers(handle, OC_NA_QOS);
-            if (OC_STACK_NO_OBSERVERS != result && OC_STACK_OK != result)
-            {
-                OIC_LOG(ERROR, TAG, "Notifying observers failed.");
-            }
+            OIC_LOG(ERROR, TAG, "Notifying observers failed.");
         }
     }
 
index 2e410cd77443d2b8c0ce281a1f5fd4de4eec3749..1eb2496d87855ced46d5f488f7c13ce4386d7b28 100644 (file)
@@ -298,6 +298,35 @@ TEST_F(RDTests, RDDeleteSpecificResource)
     EXPECT_EQ(OC_STACK_OK, OCRDDelete(NULL, "127.0.0.1", CT_ADAPTER_IP, &handle,
                                       1, &cbData, OC_LOW_QOS));
 }
+
+#endif
+
+#ifdef RD_SERVER
+
+static OCStackApplicationResult UpdateSelValueVerify(__attribute__((unused))void *ctx,
+                                                     __attribute__((unused)) OCDoHandle handle,
+                                                     OCClientResponse *clientResponse)
+{
+    EXPECT_GT(clientResponse->result, OC_STACK_RESOURCE_CHANGED);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDTests, UpdateSelValue)
+{
+    itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+    EXPECT_EQ(OC_STACK_OK, OCRDStart());
+
+    itst::Callback postCB(&UpdateSelValueVerify);
+    OCRepPayload *payload = OCRepPayloadCreate();
+    EXPECT_TRUE(payload != NULL);
+    EXPECT_TRUE(OCRepPayloadSetPropInt(payload, "sel", 90));
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_POST, "127.0.0.1/oic/rd?if=oic.if.baseline", NULL,
+            (OCPayload*) payload, CT_DEFAULT, OC_HIGH_QOS, postCB, NULL, 0));
+    EXPECT_EQ(OC_STACK_OK, postCB.Wait(100));
+
+    EXPECT_EQ(OC_STACK_OK, OCRDStop());
+}
+
 #endif
 
 #if (defined(RD_SERVER) && defined(RD_CLIENT))