/** Separator for multiple query string.*/
#define OC_QUERY_SEPARATOR "&;"
+/** Delimeter for keys and values in query string.*/
+#define OC_KEY_VALUE_DELIMITER "="
+
/**
* OC_DEFAULT_PRESENCE_TTL_SECONDS sets the default time to live (TTL) for presence.
*/
OCStackResult OCRDDatabaseStoreResources(const OCRepPayload *payload, const OCDevAddr *address);
/**
- * Updates the RD resource
+ * Delete the RD resources
*
- * @param deviceId of the device for which resources will be update.
+ * @param deviceId of the device containing the resource(s) to be deleted.
+ * @param instanceIds the resource(s) to be deleted. If NULL then all resources
+ * belonging to the device will be deleted.
+ * @param nInstanceIds the number of instanceIds
*
* @return ::OC_STACK_OK in case of success or else other value.
*/
-OCStackResult OCRDDatabaseUpdateDevice(const char *deviceId);
-
-/**
- * Delete the RD resource
- *
- * @param deviceId of the device for which resources will be deleted.
- *
- * @return ::OC_STACK_OK in case of success or else other value.
- */
-OCStackResult OCRDDatabaseDeleteDevice(const char *deviceId);
+OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *instanceIds,
+ uint8_t nInstanceIds);
/**
* Close the RD publish database.
try
{
- // Update resource unique id in stack.
if (clientResponse)
{
- if (clientResponse->payload)
- {
- OCRepPayload *rdPayload = (OCRepPayload *) clientResponse->payload;
- OCRepPayload **links = NULL;
-
- size_t dimensions[MAX_REP_ARRAY_DEPTH];
- OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions);
- for(size_t i = 0; i < dimensions[0]; i++)
- {
- char *uri = NULL;
- OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri);
- OCResourceHandle handle = OCGetResourceHandleAtUri(uri);
- int64_t ins = 0;
- OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins);
- OCBindResourceInsToResource(handle, ins);
- }
- }
OCRepresentation rep = parseRDResponseCallback(clientResponse);
std::thread exec(context->callback, rep, clientResponse->result);
exec.detach();
if (link[i])
{
VERIFY_SQLITE(sqlite3_bind_text(stmtRT, rt_value_index, link[i],
- strlen(link[i])+1, SQLITE_STATIC));
+ strlen(link[i]), SQLITE_STATIC));
VERIFY_SQLITE(sqlite3_bind_int(stmtRT, rt_link_id_index, rowid));
}
if (link[i])
{
- VERIFY_SQLITE(sqlite3_bind_text(stmtIF, if_value_index, link[i], strlen(link[i])+1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmtIF, if_value_index, link[i], strlen(link[i]), SQLITE_STATIC));
VERIFY_SQLITE(sqlite3_bind_int(stmtIF, if_link_id_index, rowid));
}
if (sqlite3_step(stmtIF) != SQLITE_DONE)
static int storeLinkPayload(OCRepPayload *rdPayload, int64_t rowid)
{
- OCRepPayload **links = NULL;
- size_t dimensions[MAX_REP_ARRAY_DEPTH];
int res = 1 ;
size_t j = 0;
- if (OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions))
+ /*
+ * 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)
+ {
+ if (0 == strcmp(links->name, OC_RSRVD_LINKS))
+ {
+ if (links->type != OCREP_PROP_ARRAY || links->arr.type != OCREP_PROP_OBJECT)
+ {
+ links = NULL;
+ }
+ break;
+ }
+ }
+ if (links != NULL)
{
const char *insertDeviceLLList = "INSERT INTO RD_DEVICE_LINK_LIST VALUES(?,?,?,?,?,?,?,?)";
sqlite3_stmt *stmt = 0;
- for (size_t i = 0; i < dimensions[0]; i++)
+ for (size_t i = 0; i < links->arr.dimensions[0]; i++)
{
VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, insertDeviceLLList, strlen(insertDeviceLLList) + 1, &stmt, NULL));
VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
- OCRepPayload *link = links[i];
+ OCRepPayload *link = links->arr.objArray[i];
char *uri = NULL;
if (OCRepPayloadGetPropString(link, OC_RSRVD_HREF, &uri))
{
char **mediaType = NULL;
if (OCRepPayloadGetStringArray(link, OC_RSRVD_MEDIA_TYPE, &mediaType, mtDim))
{
- VERIFY_SQLITE(sqlite3_bind_text(stmt, mt_index, mediaType[0], mtDim[0], SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, mt_index, mediaType[0], strlen(mediaType[0]), SQLITE_STATIC));
}
VERIFY_SQLITE(sqlite3_bind_int(stmt, d_index, rowid));
VERIFY_SQLITE(sqlite3_exec(gRDDB, "COMMIT", NULL, NULL, NULL));
int64_t ins = sqlite3_last_insert_rowid(gRDDB);
+ if (!OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins))
+ {
+ OIC_LOG_V(ERROR, TAG, "Error setting 'ins' value");
+ return OC_STACK_ERROR;
+ }
VERIFY_SQLITE(storeResourceType(rt, rtDim[0], ins));
VERIFY_SQLITE(storeInterfaceType(itf, itfDim[0], ins));
OICFree(uri);
char *deviceid = NULL;
if (OCRepPayloadGetPropString(payload, OC_RSRVD_DEVICE_ID, &deviceid))
{
- VERIFY_SQLITE(sqlite3_bind_text(stmt, device_index, deviceid, strlen(deviceid) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, device_index, deviceid, strlen(deviceid), SQLITE_STATIC));
}
int64_t ttl = 0;
char rdAddress[MAX_URI_LENGTH];
snprintf(rdAddress, MAX_URI_LENGTH, "%s:%d", address->addr, address->port);
OIC_LOG_V(DEBUG, TAG, "Address: %s", rdAddress);
- VERIFY_SQLITE(sqlite3_bind_text(stmt, address_index, rdAddress, strlen(rdAddress) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, address_index, rdAddress, strlen(rdAddress), SQLITE_STATIC));
if (sqlite3_step(stmt) != SQLITE_DONE)
{
return OC_STACK_OK;
}
-OCStackResult OCRDDatabaseDeleteDevice(const char *deviceId)
+OCStackResult OCRDDatabaseDeleteResources(const char *deviceId, const uint8_t *instanceIds, uint8_t nInstanceIds)
{
CHECK_DATABASE_INIT;
- VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
+ VERIFY_SQLITE(sqlite3_exec(gRDDB, "BEGIN TRANSACTION", NULL, NULL, NULL));
sqlite3_stmt *stmt = 0;
- char *delDevice = "DELETE FROM RD_DEVICE_LIST WHERE "XSTR(OC_RSRVD_DEVICE_ID)" = ?";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, delDevice, strlen(delDevice) + 1, &stmt, NULL));
+ if (!instanceIds || !nInstanceIds)
+ {
+ char *delDevice = "DELETE FROM RD_DEVICE_LIST WHERE "XSTR(OC_RSRVD_DEVICE_ID)" = ?";
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, delDevice, strlen(delDevice) + 1, &stmt, NULL));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
+ }
+ else
+ {
+ const char pre[] = "DELETE FROM RD_DEVICE_LINK_LIST "
+ "WHERE ins IN ("
+ "SELECT RD_DEVICE_LINK_LIST.ins FROM RD_DEVICE_LINK_LIST "
+ "INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
+ "WHERE RD_DEVICE_LIST.di = ? AND RD_DEVICE_LINK_LIST.ins IN (";
+ size_t inLen = nInstanceIds + (nInstanceIds - 1);
+ const char post[] = "))";
+ size_t len = sizeof(pre) + inLen + sizeof(post);
+ char *delResource = OICCalloc(len, 1);
+ if (!delResource)
+ {
+ OIC_LOG(ERROR, TAG, "SQL query is NULL");
+ return OC_STACK_ERROR;
+ }
+ OICStrcat(delResource, len, pre);
+ OICStrcat(delResource, len, "?");
+ for (uint8_t i = 1; i < nInstanceIds; ++i)
+ {
+ OICStrcat(delResource, len, ",?");
+ }
+ OICStrcat(delResource, len, post);
+ int prepareResult = sqlite3_prepare_v2(gRDDB, delResource, strlen(delResource) + 1, &stmt, NULL);
+ OICFree(delResource);
+ VERIFY_SQLITE(prepareResult);
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, deviceId, strlen(deviceId), SQLITE_STATIC));
+ for (uint8_t i = 0; i < nInstanceIds; ++i)
+ {
+ VERIFY_SQLITE(sqlite3_bind_int(stmt, 2 + i, instanceIds[i]));
+ }
+ }
if (sqlite3_step(stmt) != SQLITE_DONE)
{
sqlite3_exec(gRDDB, "ROLLBACK", NULL, NULL, NULL);
cbBiasFactor, NULL, 0);
}
+static void RDPublishContextDeleter(void *ctx)
+{
+ OCCallbackData *cbData = (OCCallbackData*)ctx;
+ if (cbData->cd)
+ {
+ cbData->cd(cbData->context);
+ }
+ OICFree(cbData);
+}
+
+OCStackApplicationResult RDPublishCallback(void *ctx,
+ OCDoHandle handle,
+ OCClientResponse *clientResponse)
+{
+ OCCallbackData *cbData = (OCCallbackData*)ctx;
+
+ // Update resource unique id in stack.
+ OCRepPayload **links = NULL;
+ size_t dimensions[MAX_REP_ARRAY_DEPTH] = {0};
+ if (clientResponse && clientResponse->payload)
+ {
+ OCRepPayload *rdPayload = (OCRepPayload *) clientResponse->payload;
+ if (!OCRepPayloadGetPropObjectArray(rdPayload, OC_RSRVD_LINKS, &links, dimensions))
+ {
+ OIC_LOG_V(DEBUG, TAG, "No links in publish response");
+ goto exit;
+ }
+ for(size_t i = 0; i < dimensions[0]; i++)
+ {
+ char *uri = NULL;
+ if (!OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri))
+ {
+ OIC_LOG_V(ERROR, TAG, "Missing 'href' in publish response");
+ goto next;
+ }
+ OCResourceHandle handle = OCGetResourceHandleAtUri(uri);
+ if (handle == NULL)
+ {
+ OIC_LOG_V(ERROR, TAG, "No resource exists with uri: %s", uri);
+ goto next;
+ }
+ int64_t ins = 0;
+ if (!OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins))
+ {
+ OIC_LOG_V(ERROR, TAG, "Missing 'ins' in publish response");
+ goto next;
+ }
+ OCBindResourceInsToResource(handle, ins);
+ next:
+ OICFree(uri);
+ }
+ }
+
+exit:
+ for (size_t i = 0; i < dimensions[0]; i++)
+ {
+ OCRepPayloadDestroy(links[i]);
+ }
+ OICFree(links);
+ return cbData->cb(cbData->context, handle, clientResponse);
+}
+
OCStackResult OCRDPublish(const char *host, OCConnectivityType connectivityType,
OCResourceHandle *resourceHandles, uint8_t nHandles,
OCCallbackData *cbData, OCQualityOfService qos)
OCRepPayloadSetStringArrayAsOwner(link, OC_RSRVD_INTERFACE, itf, ifDim);
}
- uint8_t ins = 0;
- if (OC_STACK_OK == OCGetResourceIns(handle, &ins))
- {
- OCRepPayloadSetPropInt(link, OC_RSRVD_INS, ins);
- }
-
size_t mtDim[MAX_REP_ARRAY_DEPTH] = {1, 0, 0};
char **mediaType = (char **)OICMalloc(sizeof(char *) * 1);
if (!mediaType)
}
OICFree(linkArr);
+ OCCallbackData *rdPublishContext = (OCCallbackData*)OICMalloc(sizeof(OCCallbackData));
+ if (!rdPublishContext)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(rdPublishContext, cbData, sizeof(OCCallbackData));
+ OCCallbackData rdPublishCbData;
+ rdPublishCbData.context = rdPublishContext;
+ rdPublishCbData.cb = RDPublishCallback;
+ rdPublishCbData.cd = RDPublishContextDeleter;
return OCDoResource(NULL, OC_REST_POST, targetUri, NULL, (OCPayload *)rdPayload,
- connectivityType, qos, cbData, NULL, 0);
+ connectivityType, qos, &rdPublishCbData, NULL, 0);
}
OCStackResult OCRDDelete(const char *host, OCConnectivityType connectivityType,
#include "rd_database.h"
+#include <string.h>
#include "payload_logging.h"
#include "ocpayload.h"
#include "octypes.h"
+#include "oic_string.h"
#define TAG PCF("OIC_RD_SERVER")
static OCEntityHandlerResult handleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
{
- OIC_LOG(DEBUG, TAG, "handleDeleteRequest - IN");
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ char *key = NULL;
+ char *value = NULL;
+ char *queryDup = NULL;
+ char *restOfQuery = NULL;
+ char *keyValuePair = NULL;
+ char *di = NULL;
+ size_t nIns = 0;
+ uint8_t *ins = NULL;
- (void) ehRequest; // eliminates release warning
+ if (!ehRequest)
+ {
+ OIC_LOG(DEBUG, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
- OCEntityHandlerResult ehResult = OC_EH_OK;
+ OIC_LOG_V(DEBUG, TAG, "Received OC_REST_DELETE from client with query: %s.", ehRequest->query);
+
+ if (OCRDDatabaseInit(NULL) != OC_STACK_OK)
+ {
+ goto exit;
+ }
+
+#define OC_RSRVD_INS_KEY OC_RSRVD_INS OC_KEY_VALUE_DELIMITER /* "ins=" */
+ keyValuePair = strstr(ehRequest->query, OC_RSRVD_INS_KEY);
+ while (keyValuePair)
+ {
+ ++nIns;
+ keyValuePair = strstr(keyValuePair + sizeof(OC_RSRVD_INS_KEY), OC_RSRVD_INS_KEY);
+ }
+ if (nIns)
+ {
+ ins = OICMalloc(nIns * sizeof(uint8_t));
+ if (!ins)
+ {
+ OIC_LOG_V(ERROR, TAG, "ins is NULL");
+ goto exit;
+ }
+ }
+
+ nIns = 0;
+ queryDup = OICStrdup(ehRequest->query);
+ if (NULL == queryDup)
+ {
+ OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!");
+ goto exit;
+ }
+ keyValuePair = strtok_r(queryDup, OC_QUERY_SEPARATOR, &restOfQuery);
+ while (keyValuePair)
+ {
+ key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value);
+ if (!key || !value)
+ {
+ OIC_LOG_V(ERROR, TAG, "Invalid query parameter!");
+ goto exit;
+ }
+ else if (strncasecmp(key, OC_RSRVD_DEVICE_ID, sizeof(OC_RSRVD_DEVICE_ID) - 1) == 0)
+ {
+ di = value;
+ }
+ else if (strncasecmp(key, OC_RSRVD_INS, sizeof(OC_RSRVD_INS) - 1) == 0)
+ {
+ char *endptr = NULL;
+ long int i = strtol(value, &endptr, 0);
+ if (*endptr != '\0' || i < 0 || i > UINT8_MAX)
+ {
+ OIC_LOG_V(ERROR, TAG, "Invalid ins query parameter: %s", value);
+ goto exit;
+ }
+ ins[nIns++] = i;
+ }
+
+ keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery);
+ }
+ if (!di)
+ {
+ OIC_LOG_V(ERROR, TAG, "Missing required di query parameter!");
+ goto exit;
+ }
+
+ if (OCRDDatabaseDeleteResources(di, ins, nIns) == OC_STACK_OK)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Deleted resource(s).");
+ ehResult = OC_EH_OK;
+ }
+
+exit:
+ OICFree(ins);
+ OICFree(queryDup);
+ if (sendResponse(ehRequest, NULL, ehResult) != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "Sending response failed.");
+ }
return ehResult;
}
protected:
virtual void SetUp()
{
+ remove("RD.db");
OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER);
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseInit(NULL));
}
virtual void TearDown()
{
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseClose());
OCStop();
}
};
-TEST_F(RDDatabaseTests, CreateDatabase)
+static OCRepPayload *CreateResources(const char *deviceId)
{
- itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
- EXPECT_EQ(OC_STACK_OK, OCRDDatabaseInit(NULL));
- EXPECT_EQ(OC_STACK_OK, OCRDDatabaseClose());
-}
-
-TEST_F(RDDatabaseTests, PublishDatabase)
-{
- // itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
- EXPECT_EQ(OC_STACK_OK, OCRDDatabaseInit(NULL));
OCRepPayload *repPayload = OCRepPayloadCreate();
- ASSERT_TRUE(repPayload != NULL);
- const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
- ASSERT_TRUE(deviceId != NULL);
+ EXPECT_TRUE(repPayload != NULL);
EXPECT_TRUE(OCRepPayloadSetPropString(repPayload, OC_RSRVD_DEVICE_ID, deviceId));
EXPECT_TRUE(OCRepPayloadSetPropInt(repPayload, OC_RSRVD_DEVICE_TTL, 86400));
OCDevAddr address;
OCRepPayloadSetPropObjectArray(repPayload, OC_RSRVD_LINKS, linkArr, dimensions);
OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)repPayload);
+ return repPayload;
+}
+
+TEST_F(RDDatabaseTests, Create)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+}
+
+TEST_F(RDDatabaseTests, StoreResources)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+ const char *deviceId = "7a960f46-a52e-4837-bd83-460b1a6dd56b";
+ OCRepPayload *repPayload = CreateResources(deviceId);
+ OCDevAddr address;
+ address.port = 54321;
+ OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(repPayload, &address));
OCDiscoveryPayloadDestroy(discPayload);
discPayload = NULL;
- EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDeleteDevice(deviceId));
- EXPECT_EQ(OC_STACK_OK, OCRDDatabaseClose());
+ OCPayloadDestroy((OCPayload *)repPayload);
+}
+
+TEST_F(RDDatabaseTests, DeleteResourcesDevice)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+ const char *deviceIds[2] =
+ {
+ "7a960f46-a52e-4837-bd83-460b1a6dd56b",
+ "983656a7-c7e5-49c2-a201-edbeb7606fb5",
+ };
+ OCRepPayload *payloads[2];
+ payloads[0] = CreateResources(deviceIds[0]);
+ payloads[1] = CreateResources(deviceIds[1]);
+ OCDevAddr address;
+ address.port = 54321;
+ OICStrcpy(address.addr,MAX_ADDR_STR_SIZE, "192.168.1.1");
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[0], &address));
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseStoreResources(payloads[1], &address));
+
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDeleteResources(deviceIds[0], NULL, 0));
+
+ OCDiscoveryPayload *discPayload = NULL;
+ EXPECT_EQ(OC_STACK_OK, OCRDDatabaseDiscoveryPayloadCreate(OC_RSRVD_INTERFACE_LL, NULL, &discPayload));
+ bool found0 = false;
+ bool found1 = false;
+ for (OCDiscoveryPayload *payload = discPayload; payload; payload = payload->next)
+ {
+ if (!strcmp((const char *) deviceIds[0], payload->sid))
+ {
+ found0 = true;
+ }
+ if (!strcmp((const char *) deviceIds[1], payload->sid))
+ {
+ found1 = true;
+ }
+ }
+ EXPECT_FALSE(found0);
+ EXPECT_TRUE(found1);
+ OCDiscoveryPayloadDestroy(discPayload);
+ discPayload = NULL;
+
+ OCPayloadDestroy((OCPayload *)payloads[0]);
+ OCPayloadDestroy((OCPayload *)payloads[1]);
}
#ifdef RD_CLIENT
static OCStackApplicationResult handlePublishCB(__attribute__((unused))void *ctx,
__attribute__((unused)) OCDoHandle handle,
- __attribute__((unused))
OCClientResponse *clientResponse)
{
OIC_LOG(DEBUG, TAG, "Successfully published resources.");
+ EXPECT_EQ(OC_STACK_RESOURCE_CHANGED, clientResponse->result);
+
return OC_STACK_DELETE_TRANSACTION;
}
static OCStackApplicationResult handleDeleteCB(__attribute__((unused))void *ctx,
__attribute__((unused)) OCDoHandle handle,
- __attribute__((unused))
OCClientResponse *clientResponse)
{
OIC_LOG(DEBUG, TAG, "Successfully delete resources.");
+ EXPECT_EQ(OC_STACK_RESOURCE_CHANGED, clientResponse->result);
+
return OC_STACK_DELETE_TRANSACTION;
}
#endif
OC_HIGH_QOS, discoverCB, NULL, 0));
discoverCB.Wait();
}
+
+static OCStackApplicationResult DeleteDeviceVerify(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ (void) ctx;
+ (void) handle;
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(response->payload != NULL);
+ if (response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+ for (OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload; payload;
+ payload = payload->next)
+ {
+ EXPECT_STRNE((const char *) RDDiscoverTests::di[0], payload->sid);
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DeleteDevice)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+ OCResourceHandle handles[1];
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+ "oic.if.baseline", "/a/light", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ Callback publishCB(&handlePublishCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+ 1, publishCB, OC_LOW_QOS));
+ publishCB.Wait();
+
+ Callback deleteCB(&handleDeleteCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDDeleteWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, nullptr, 0,
+ deleteCB, OC_HIGH_QOS));
+ deleteCB.Wait();
+
+ Callback discoverCB(&DeleteDeviceVerify);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
+ CT_DEFAULT,
+ OC_HIGH_QOS, discoverCB, NULL, 0));
+ discoverCB.Wait();
+}
+
+static OCStackApplicationResult Delete1Verify(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ (void) ctx;
+ (void) handle;
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(response->payload != NULL);
+ if (response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+ bool foundId = false;
+ bool foundLight = false;
+ bool foundLight2 = false;
+ for (OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload; payload;
+ payload = payload->next)
+ {
+ if (!strcmp((const char *) RDDiscoverTests::di[0], payload->sid))
+ {
+ foundId = true;
+ for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+ {
+ if (!strcmp("/a/light", resource->uri))
+ {
+ foundLight = true;
+ }
+ if (!strcmp("/a/light2", resource->uri))
+ {
+ foundLight2 = true;
+ }
+ }
+ }
+ }
+ EXPECT_TRUE(foundId);
+ EXPECT_FALSE(foundLight);
+ EXPECT_TRUE(foundLight2);
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, Delete1)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+ OCResourceHandle handles[2];
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+ "oic.if.baseline", "/a/light", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light",
+ "oic.if.baseline", "/a/light2", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ Callback publishCB(&handlePublishCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+ 2, publishCB, OC_LOW_QOS));
+ publishCB.Wait();
+
+ Callback deleteCB(&handleDeleteCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDDeleteWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles, 1,
+ deleteCB, OC_HIGH_QOS));
+ deleteCB.Wait();
+
+ Callback discoverCB(&Delete1Verify);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
+ CT_DEFAULT,
+ OC_HIGH_QOS, discoverCB, NULL, 0));
+ discoverCB.Wait();
+}
+
+static OCStackApplicationResult DeleteNVerify(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ (void) ctx;
+ (void) handle;
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(response->payload != NULL);
+ if (response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+ bool foundId = false;
+ bool foundLight = false;
+ bool foundLight2 = false;
+ bool foundLight3 = false;
+ for (OCDiscoveryPayload *payload = (OCDiscoveryPayload *) response->payload; payload;
+ payload = payload->next)
+ {
+ if (!strcmp((const char *) RDDiscoverTests::di[0], payload->sid))
+ {
+ foundId = true;
+ for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+ {
+ if (!strcmp("/a/light", resource->uri))
+ {
+ foundLight = true;
+ }
+ if (!strcmp("/a/light2", resource->uri))
+ {
+ foundLight2 = true;
+ }
+ if (!strcmp("/a/light3", resource->uri))
+ {
+ foundLight3 = true;
+ }
+ }
+ }
+ }
+ EXPECT_TRUE(foundId);
+ EXPECT_FALSE(foundLight);
+ EXPECT_FALSE(foundLight2);
+ EXPECT_TRUE(foundLight3);
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(RDDiscoverTests, DeleteN)
+{
+ itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
+
+ OCResourceHandle handles[3];
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[0], "core.light",
+ "oic.if.baseline", "/a/light", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[1], "core.light",
+ "oic.if.baseline", "/a/light2", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles[2], "core.light",
+ "oic.if.baseline", "/a/light3", rdEntityHandler,
+ NULL, (OC_DISCOVERABLE | OC_OBSERVABLE)));
+ Callback publishCB(&handlePublishCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDPublishWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles,
+ 3, publishCB, OC_LOW_QOS));
+ publishCB.Wait();
+
+ Callback deleteCB(&handleDeleteCB);
+ EXPECT_EQ(OC_STACK_OK, OCRDDeleteWithDeviceId("127.0.0.1", di[0], CT_ADAPTER_IP, handles, 2,
+ deleteCB, OC_HIGH_QOS));
+ deleteCB.Wait();
+
+ Callback discoverCB(&DeleteNVerify);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0,
+ CT_DEFAULT,
+ OC_HIGH_QOS, discoverCB, NULL, 0));
+ discoverCB.Wait();
+}
#endif
#define OC_JSON_SUFFIX_LEN (sizeof(OC_JSON_SUFFIX) - 1)
#define OC_JSON_SEPARATOR ','
#define OC_JSON_SEPARATOR_STR ","
-#define OC_KEY_VALUE_DELIMITER "="
/**
* Static values for various JSON attributes.
case OC_EH_OK:
case OC_EH_CHANGED: // 2.04
case OC_EH_CONTENT: // 2.05
- if (method == OC_REST_POST || method == OC_REST_PUT)
+ if (method == OC_REST_POST || method == OC_REST_PUT || method == OC_REST_DELETE)
{
caResult = CA_CHANGED;
}
sqlite3_stmt *stmtRT = 0;
const char *rt = "SELECT rt FROM RD_LINK_RT WHERE LINK_ID=?";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, -1, &stmtRT, NULL));
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, rt, strlen(rt) + 1, &stmtRT, NULL));
VERIFY_SQLITE(sqlite3_bind_int(stmtRT, 1, id));
while (SQLITE_ROW == sqlite3_step(stmtRT))
{
sqlite3_stmt *stmtIF = 0;
const char *itf = "SELECT if FROM RD_LINK_IF WHERE LINK_ID=?";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, -1, &stmtIF, NULL));
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, itf, strlen(itf) + 1, &stmtIF, NULL));
VERIFY_SQLITE(sqlite3_bind_int(stmtIF, 1, id));
while (SQLITE_ROW == sqlite3_step(stmtIF))
{
const uint8_t address_index = 1;
sqlite3_stmt *stmt1 = 0;
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, -1, &stmt1, NULL));
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, address, strlen(address) + 1, &stmt1, NULL));
VERIFY_SQLITE(sqlite3_bind_int(stmt1, 1, deviceId));
res = sqlite3_step(stmt1);
"INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
"INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
"WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
SQLITE_STATIC));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
}
else
{
"INNER JOIN RD_LINK_RT ON RD_DEVICE_LINK_LIST.INS=RD_LINK_RT.LINK_ID "
"INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
"WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_RT.rt LIKE ?2 AND RD_LINK_IF.if LIKE ?3";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
SQLITE_STATIC));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType) + 1, SQLITE_STATIC));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, resourceType, strlen(resourceType), SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 3, interfaceType, strlen(interfaceType), SQLITE_STATIC));
}
result = ResourcePayloadCreate(stmt, discPayload);
}
const char *input = "SELECT * FROM RD_DEVICE_LINK_LIST "
"INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
"WHERE RD_DEVICE_LIST.di LIKE ?1";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
SQLITE_STATIC));
}
else
"INNER JOIN RD_DEVICE_LIST ON RD_DEVICE_LINK_LIST.DEVICE_ID=RD_DEVICE_LIST.ID "
"INNER JOIN RD_LINK_IF ON RD_DEVICE_LINK_LIST.INS=RD_LINK_IF.LINK_ID "
"WHERE RD_DEVICE_LIST.di LIKE ?1 AND RD_LINK_IF.if LIKE ?2";
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid) + 1,
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 1, discPayload->sid, strlen(discPayload->sid),
SQLITE_STATIC));
- VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType) + 1, SQLITE_STATIC));
+ VERIFY_SQLITE(sqlite3_bind_text(stmt, 2, interfaceType, strlen(interfaceType), SQLITE_STATIC));
}
result = ResourcePayloadCreate(stmt, discPayload);
}
sqlite3_stmt *stmt = 0;
const char *input = "SELECT di FROM RD_DEVICE_LIST";
const uint8_t di_index = 0;
- VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, -1, &stmt, NULL));
+ VERIFY_SQLITE(sqlite3_prepare_v2(gRDDB, input, strlen(input) + 1, &stmt, NULL));
while (SQLITE_ROW == sqlite3_step(stmt))
{
const unsigned char *di = sqlite3_column_text(stmt, di_index);