- Stop the error response on invalid multicast /oic/res request.
- An error message is sent in case of unicast.
- In case of empty query for interface and resource type,, it sends an error message.
- Add unit tests to test the callback returned value.
BUG: https://jira.iotivity.org/browse/IOT-1650
Change-Id: I2f5902f46030d28ebcc8dc28c7e2f4fbcb6a1716
Signed-off-by: Habib Virji <habib.virji@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/15197
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
/** Name */
char *name;
- /** HREF */
- char *uri;
-
/** Resource Type */
OCStringLL *type;
}
}
+static void OCStringLLPrint(LogLevel level, OCStringLL *type)
+{
+ for (OCStringLL *strll = type; strll; strll = strll->next)
+ {
+ OIC_LOG_V(level, PL_TAG, "\t\t %s", strll->value);
+ }
+}
+
INLINE_API void OCPayloadLogDiscovery(LogLevel level, OCDiscoveryPayload* payload)
{
OIC_LOG(level, PL_TAG, "Payload Type: Discovery");
while(payload && payload->resources)
{
- OIC_LOG_V(level, PL_TAG, "\tSID: %s", payload->sid);
+ OIC_LOG_V(level, PL_TAG, "\tDI: %s", payload->sid);
if (payload->baseURI)
{
OIC_LOG_V(level, PL_TAG, "\tBase URI:%s", payload->baseURI);
{
OIC_LOG_V(level, PL_TAG, "\tNAME: %s", payload->name);
}
- if (payload->uri)
- {
- OIC_LOG_V(level, PL_TAG, "\tURI: %s", payload->uri);
- }
+
if (payload->type)
{
- for (OCStringLL *strll = payload->type; strll; strll = strll->next)
- {
- OIC_LOG_V(level, PL_TAG, "\tResource Type: %s", strll->value);
- }
+ OIC_LOG(level, PL_TAG, "\tResource Type:");
+ OCStringLLPrint(level, payload->type);
}
- OIC_LOG(level, PL_TAG, "\tInterface:");
- for (OCStringLL *itf = payload->iface; itf; itf = itf->next)
+
+ if (payload->iface)
{
- OIC_LOG_V(level, PL_TAG, "\t\t%s", itf->value);
+ OIC_LOG(level, PL_TAG, "\tInterface:");
+ OCStringLLPrint(level, payload->iface);
}
OCResourcePayload* res = payload->resources;
uint32_t i = 1;
while(res)
{
- OIC_LOG_V(level, PL_TAG, "\tResource #%d", i);
+ OIC_LOG_V(level, PL_TAG, "\tLink#%d", i);
OIC_LOG_V(level, PL_TAG, "\tURI:%s", res->uri);
OIC_LOG(level, PL_TAG, "\tResource Types:");
OCStringLL* strll = res->types;
}
OICFree(payload->sid);
OICFree(payload->baseURI);
- OICFree(payload->uri);
OCFreeOCStringLL(payload->type);
OICFree(payload->name);
OCFreeOCStringLL(payload->iface);
if (err == CborNoError)
{
- if ((curSize < INIT_SIZE) &&
+ if ((curSize < INIT_SIZE) &&
(PAYLOAD_TYPE_SECURITY != payload->type))
{
uint8_t *out2 = (uint8_t *)OICRealloc(out, curSize);
VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
}
- // HREF - Not a mandatory field
- err = cbor_value_map_find_value(&rootMap, OC_RSRVD_HREF, &curVal);
- if (cbor_value_is_text_string(&curVal))
- {
- err = cbor_value_dup_text_string(&curVal, &(temp->uri), &len, NULL);
- VERIFY_CBOR_SUCCESS(TAG, err, "to find uri value");
- }
-
// RT - Not a mandatory field
err = cbor_value_map_find_value(&rootMap, OC_RSRVD_RESOURCE_TYPE, &curVal);
if (cbor_value_is_valid(&curVal))
{
err = OCParseStringLL(&rootMap, OC_RSRVD_RESOURCE_TYPE, &temp->type);
- VERIFY_CBOR_SUCCESS(TAG, err, "to find base uri value");
+ VERIFY_CBOR_SUCCESS(TAG, err, "to find resource type");
}
// IF - Not a mandatory field
if (cbor_value_is_valid(&curVal))
{
err = OCParseStringLL(&rootMap, OC_RSRVD_INTERFACE, &temp->iface);
- }
- if (!temp->iface)
- {
- if (!OCResourcePayloadAddStringLL(&temp->iface, OC_RSRVD_INTERFACE_LL))
- {
- err = CborErrorOutOfMemory;
- }
+ VERIFY_CBOR_SUCCESS(TAG, err, "to find interface");
}
// Name - Not a mandatory field
size_t fileSize = 0;
OCStackResult ret = OC_STACK_ERROR;
OCPersistentStorage *ps = NULL;
-
+
if (!data || *data || !size)
{
return OC_STACK_INVALID_PARAM;
if (fileSize)
{
// allocate one more byte to accomodate null terminator for string we are reading.
- fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
+ fsData = (uint8_t *)OICCalloc(1, fileSize + 1);
if (!fsData)
{
OIC_LOG(ERROR, TAG, "Could not allocate memory for introspection data");
result = OC_STACK_ERROR;
goto exit;
}
-
+
exit:
if (result != OC_STACK_OK)
{
}
if (cur)
{
- // The intent of the protocol list is to collect all unique protocols available on this
- // endpoint. Set an error that can be used to skip processing this protocol further as
+ // The intent of the protocol list is to collect all unique protocols available on this
+ // endpoint. Set an error that can be used to skip processing this protocol further as
// it already exists in the list.
return OC_STACK_INVALID_PARAM;
}
proto = proto->next;
i++;
}
- if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
- OC_RSRVD_INTROSPECTION_URL_INFO,
- urlInfoPayload,
+ if (!OCRepPayloadSetPropObjectArrayAsOwner(tempPayload,
+ OC_RSRVD_INTROSPECTION_URL_INFO,
+ urlInfoPayload,
dimensions))
{
OIC_LOG_V(ERROR, TAG, "Unable to add urlInfo object to introspection payload ");
}
}
FreeProtocolLL(protoLL);
-
+
return OC_STACK_OK;
}
return false;
}
- // Null or empty is analogous to no filter.
- if (resourceTypeFilter == NULL || *resourceTypeFilter == 0)
+ // Null is analogous to no filter.i.e. query is of form /oic/res?if=oic.if.baseline or /oic/res,
+ // without rt query.
+ if (NULL == resourceTypeFilter)
{
return true;
}
+ // Empty resourceType filter is analogous to error query
+ // It is an error as query is of form /oic/res?rt=
+ if (0 == strlen(resourceTypeFilter))
+ {
+ return false;
+ }
+
for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next)
{
if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter))
return false;
}
- // Null or empty is analogous to no filter.
- if (interfaceFilter == NULL || *interfaceFilter == 0)
+ // Null is analogous to no filter i.e. query is of form /oic/res?rt=core.light or /oic/res,
+ // without if query.
+ if (NULL == interfaceFilter)
{
return true;
}
+ // Empty interface filter is analogous to error query
+ // It is an error as query is of form /oic/res?if=
+ if (0 == strlen(interfaceFilter))
+ {
+ return false;
+ }
+
for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next)
{
if (0 == strcmp(ifPtr->name, interfaceFilter) ||
{
if (*payload)
{
- OIC_LOG_V(DEBUG, TAG, "Payload is already allocated");
+ OIC_LOG(DEBUG, TAG, "Payload is already allocated");
return OC_STACK_OK;
}
*/
static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload)
{
- discPayload->uri = OICStrdup(OC_RSRVD_WELL_KNOWN_URI);
- VERIFY_PARAM_NON_NULL(TAG, discPayload->uri, "Failed adding href to discovery payload.");
+ if (!discPayload)
+ {
+ OIC_LOG(ERROR, TAG, "Payload is not allocated");
+ return OC_STACK_INVALID_PARAM;
+ }
- OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, "deviceName", (void **)&discPayload->name);
+ OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name);
discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL));
VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload.");
return OC_STACK_NO_MEMORY;
}
+static bool isUnicast(OCServerRequest *request)
+{
+ bool isMulticast = request->devAddr.flags & OC_MULTICAST;
+ return (isMulticast == false &&
+ (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
+ (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE));
+}
+
static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
{
if (!request || !resource)
#endif
)
{
- if (request->method == OC_REST_PUT || request->method == OC_REST_POST ||
- request->method == OC_REST_DELETE)
- {
- OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
- request->resourceUrl, request->method);
- discoveryResult = OC_STACK_UNAUTHORIZED_REQ;
- goto exit;
- }
-
char *interfaceQuery = NULL;
char *resourceTypeQuery = NULL;
discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
&interfaceQuery, &resourceTypeQuery);
VERIFY_SUCCESS(discoveryResult);
+
if (!interfaceQuery && !resourceTypeQuery)
{
// If no query is sent, default interface is used i.e. oic.if.ll.
interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL);
}
- bool baselineQuery = false;
- if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
- {
- baselineQuery = true;
- }
-
discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
VERIFY_SUCCESS(discoveryResult);
OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
- if (baselineQuery)
+ if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT))
{
discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
VERIFY_SUCCESS(discoveryResult);
#endif
for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
{
- discoveryResult = OC_STACK_NO_RESOURCE;
-#ifdef RD_SERVER
- discoveryResult = findResourceAtRD(resource, interfaceQuery, resourceTypeQuery,
- discPayload);
-#endif
- if (OC_STACK_NO_RESOURCE == discoveryResult)
+ // This case will handle when no resource type and it is oic.if.ll.
+ // Do not assume check if the query is ll
+ if (!resourceTypeQuery &&
+ (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
{
- // This case will handle when no resource type and it is oic.if.ll.
- if (!resourceTypeQuery && !baselineQuery && (resource->resourceProperties & prop))
- {
- discoveryResult = BuildVirtualResourceResponse(resource,
- discPayload,
- &request->devAddr,
- networkInfo,
- infoSize);
- }
- else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
+ // Only include discoverable type
+ if (resource->resourceProperties & prop)
{
discoveryResult = BuildVirtualResourceResponse(resource,
discPayload,
networkInfo,
infoSize);
}
- else
- {
- discoveryResult = OC_STACK_OK;
- }
+ }
+ else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
+ {
+ discoveryResult = BuildVirtualResourceResponse(resource,
+ discPayload,
+ &request->devAddr,
+ networkInfo,
+ infoSize);
+ }
+ else
+ {
+ discoveryResult = OC_STACK_OK;
}
}
if (discPayload->resources == NULL)
OIC_LOG_PAYLOAD(DEBUG, payload);
if(discoveryResult == OC_STACK_OK)
{
+
SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
}
- else if(((request->devAddr.flags & OC_MULTICAST) == false) &&
- (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) &&
- (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE))
+ else // Error handling
{
- OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
- discoveryResult, virtualUriInRequest);
- SendNonPersistantDiscoveryResponse(request, resource, NULL,
- (discoveryResult == OC_STACK_NO_RESOURCE) ?
+ if (isUnicast(request))
+ {
+ OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request",
+ discoveryResult, virtualUriInRequest);
+ SendNonPersistantDiscoveryResponse(request, resource, NULL,
+ (discoveryResult == OC_STACK_NO_RESOURCE) ?
OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR);
- }
- else
- {
- // Ignoring the discovery request as per RFC 7252, Section #8.2
- OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
- // the request should be removed.
- // since it never remove and causes a big memory waste.
- FindAndDeleteServerRequest(request);
+ }
+ else // Multicast
+ {
+ // Ignoring the discovery request as per RFC 7252, Section #8.2
+ OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send.");
+ // the request should be removed.
+ // since it never remove and causes a big memory waste.
+ FindAndDeleteServerRequest(request);
+ }
+ discoveryResult = OC_STACK_CONTINUE;
}
}
{
OICFree(dataModelVersions);
}
+ // To ignore the message, OC_STACK_CONTINUE is sent
return discoveryResult;
}
OIC_LOG(ERROR, TAG, "Allocating memory for response failed");
return;
}
-
+
response->devAddr.adapter = OC_DEFAULT_ADAPTER;
response->sequenceNumber = MAX_SEQUENCE_NUMBER + 1;
CopyEndpointToDevAddr(endPoint, &response->devAddr);
OICFree(response);
return;
}
-
- if(OC_STACK_OK != OCParsePayload(&response->payload,
+ // In case of error, still want application to receive the error message.
+ if (OCResultToSuccess(response->result))
+ {
+ if (OC_STACK_OK != OCParsePayload(&response->payload,
type,
responseInfo->info.payload,
responseInfo->info.payloadSize))
+ {
+ OIC_LOG(ERROR, TAG, "Error converting payload");
+ OCPayloadDestroy(response->payload);
+ return;
+ }
+ }
+ else
{
- OIC_LOG(ERROR, TAG, "Error converting payload");
- OCPayloadDestroy(response->payload);
- OICFree(response);
- return;
+ response->resourceUri = OICStrdup(cbNode->requestUri);
}
}
if (OC_REST_DISCOVER == cbNode->method)
{
OCDiscoveryPayload *payload = (OCDiscoveryPayload*) response->payload;
- if (!payload)
+ // Payload can be empty in case of error message.
+ if (payload && payload->sid)
{
- OIC_LOG(INFO, TAG, "discovery payload is invalid");
- return;
+ OICStrcpy(response->devAddr.remoteId, sizeof(response->devAddr.remoteId),
+ payload->sid);
+ OIC_LOG_V(INFO, TAG, "Device ID of response : %s",
+ response->devAddr.remoteId);
}
-
- OICStrcpy(response->devAddr.remoteId, sizeof(response->devAddr.remoteId),
- payload->sid);
- OIC_LOG_V(INFO, TAG, "Device ID of response : %s",
- response->devAddr.remoteId);
}
OCStackApplicationResult appFeedback = cbNode->callBack(cbNode->context,
deleteResourceElements(temp);
OICFree(temp);
+ temp = NULL;
return OC_STACK_OK;
}
else
return;
}
- OICFree(resource->uri);
- deleteResourceType(resource->rsrcType);
- deleteResourceInterface(resource->rsrcInterface);
- OCDeleteResourceAttributes(resource->rsrcAttributes);
+ if (resource->uri)
+ {
+ OICFree(resource->uri);
+ }
+ if (resource->rsrcType)
+ {
+ deleteResourceType(resource->rsrcType);
+ }
+ if (resource->rsrcInterface)
+ {
+ deleteResourceInterface(resource->rsrcInterface);
+ }
+ if (resource->rsrcChildResourcesHead)
+ {
+ OICFree(resource->rsrcChildResourcesHead);
+ }
+ if (resource->rsrcAttributes)
+ {
+ OCDeleteResourceAttributes(resource->rsrcAttributes);
+ }
}
void deleteResourceType(OCResourceType *resourceType)
{
- OCResourceType *pointer = resourceType;
OCResourceType *next = NULL;
- while (pointer)
+ for (OCResourceType *pointer = resourceType; pointer; pointer = next)
{
next = pointer->next;
- OICFree(pointer->resourcetypename);
+ if (pointer->resourcetypename)
+ {
+ OICFree(pointer->resourcetypename);
+ }
OICFree(pointer);
- pointer = next;
}
}
void deleteResourceInterface(OCResourceInterface *resourceInterface)
{
- OCResourceInterface *pointer = resourceInterface;
OCResourceInterface *next = NULL;
-
- while (pointer)
+ for (OCResourceInterface *pointer = resourceInterface; pointer; pointer = next)
{
next = pointer->next;
- OICFree(pointer->name);
+ if (pointer->name)
+ {
+ OICFree(pointer->name);
+ }
OICFree(pointer);
- pointer = next;
}
}
{
OCFreeOCStringLL((OCStringLL *)pointer->attrValue);
}
- else
+ else if (pointer->attrValue)
{
OICFree(pointer->attrValue);
}
- OICFree(pointer->attrName);
+ if (pointer->attrName)
+ {
+ OICFree(pointer->attrName);
+ }
OICFree(pointer);
}
}
}
return ret;
}
-
#include "logger.h"
#include "oic_malloc.h"
#include "oic_string.h"
+ #include "oic_time.h"
}
#include "gtest/gtest.h"
static OCDPDev_t peer;
std::chrono::seconds const SHORT_TEST_TIMEOUT = std::chrono::seconds(5);
+std::chrono::seconds const LONG_TEST_TIMEOUT = std::chrono::seconds(450);
//-----------------------------------------------------------------------------
// Callback functions
return 0;
#endif
}
+
+class Callback
+{
+ public:
+ Callback(OCClientResponseHandler cb) : m_cb(cb), m_called(false)
+ {
+ m_cbData.cb = &Callback::handler;
+ m_cbData.cd = NULL;
+ m_cbData.context = this;
+ }
+ void Wait(long waitTime)
+ {
+ uint64_t startTime = OICGetCurrentTime(TIME_IN_MS);
+ while (!m_called)
+ {
+ uint64_t currTime = OICGetCurrentTime(TIME_IN_MS);
+ long elapsed = (long)((currTime - startTime) / MS_PER_SEC);
+ if (elapsed > waitTime)
+ {
+ m_called = true;
+ }
+ OCProcess();
+ }
+ }
+ operator OCCallbackData *()
+ {
+ return &m_cbData;
+ }
+ private:
+ OCCallbackData m_cbData;
+ OCClientResponseHandler m_cb;
+ bool m_called;
+ static OCStackApplicationResult handler(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
+ {
+ Callback *callback = (Callback *) ctx;
+ OCStackApplicationResult result = callback->m_cb(NULL, handle, clientResponse);
+ callback->m_called = true;
+ return result;
+ }
+};
+
+class OCDiscoverTests : public testing::Test
+{
+ protected:
+ virtual void SetUp()
+ {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
+ }
+
+ virtual void TearDown()
+ {
+ OCStop();
+ }
+};
//-----------------------------------------------------------------------------
// Tests
//-----------------------------------------------------------------------------
EXPECT_EQ(OC_STACK_OK, OCStop());
}
+
+static OCStackApplicationResult DiscoverBaselineResource(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ OC_UNUSED(ctx);
+ OC_UNUSED(handle);
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(NULL != response->payload);
+ if (NULL != response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+
+ OCDiscoveryPayload *payload = (OCDiscoveryPayload *)response->payload;
+ EXPECT_TRUE(NULL != payload->sid);
+ EXPECT_STREQ("StackTest", payload->name);
+ EXPECT_STREQ(OC_RSRVD_RESOURCE_TYPE_RES, payload->type->value);
+ EXPECT_STREQ(OC_RSRVD_INTERFACE_LL, payload->iface->value);
+ EXPECT_STREQ(OC_RSRVD_INTERFACE_DEFAULT, payload->iface->next->value);
+
+ for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+ {
+ if (0 == strcmp("/a/light", resource->uri))
+ {
+ EXPECT_STREQ("/a/light", resource->uri);
+ EXPECT_STREQ("core.light", resource->types->value);
+ EXPECT_EQ(NULL, resource->types->next);
+ EXPECT_STREQ("oic.if.baseline", resource->interfaces->value);
+ EXPECT_EQ(NULL, resource->interfaces->next);
+ EXPECT_TRUE(resource->bitmap & OC_DISCOVERABLE);
+ EXPECT_FALSE(resource->secure);
+ EXPECT_EQ(0, resource->port);
+ EXPECT_EQ(NULL, resource->next);
+ }
+ }
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackApplicationResult DiscoverLinkedListResource(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ OC_UNUSED(ctx);
+ OC_UNUSED(handle);
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(NULL != response->payload);
+ if (NULL != response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+
+ OCDiscoveryPayload *payload = (OCDiscoveryPayload *)response->payload;
+ EXPECT_NE((char *)NULL, payload->sid);
+ EXPECT_EQ(NULL, payload->name);
+ EXPECT_EQ(NULL, payload->type);
+ EXPECT_EQ(NULL, payload->iface);
+
+ for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+ {
+ if (0 == strcmp("/a/light", resource->uri))
+ {
+ EXPECT_STREQ("/a/light", resource->uri);
+ EXPECT_STREQ("core.light", resource->types->value);
+ EXPECT_EQ(NULL, resource->types->next);
+ EXPECT_STREQ("oic.if.baseline", resource->interfaces->value);
+ EXPECT_EQ(NULL, resource->interfaces->next);
+ EXPECT_TRUE(resource->bitmap & OC_DISCOVERABLE);
+ EXPECT_FALSE(resource->secure);
+ EXPECT_EQ(0, resource->port);
+ EXPECT_EQ(NULL, resource->next);
+ }
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+static OCStackApplicationResult DiscoverResourceTypeResponse(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ OC_UNUSED(ctx);
+ OC_UNUSED(handle);
+ EXPECT_EQ(OC_STACK_OK, response->result);
+ EXPECT_TRUE(NULL != response->payload);
+ if (NULL != response->payload)
+ {
+ EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+
+ OCDiscoveryPayload *payload = (OCDiscoveryPayload *)response->payload;
+ EXPECT_NE((char *)NULL, payload->sid);
+ EXPECT_EQ(NULL, payload->name);
+ EXPECT_EQ(NULL, payload->type);
+ EXPECT_EQ(NULL, payload->iface);
+ EXPECT_TRUE(NULL != payload->resources);
+
+ OCResourcePayload *resource = payload->resources;
+
+ if (0 == strcmp("/a/light", resource->uri))
+ {
+ EXPECT_STREQ("/a/light", resource->uri);
+ EXPECT_STREQ("core.light", resource->types->value);
+ EXPECT_EQ(NULL, resource->types->next);
+ EXPECT_STREQ("oic.if.baseline", resource->interfaces->value);
+ EXPECT_EQ(NULL, resource->interfaces->next);
+ EXPECT_TRUE(resource->bitmap & OC_DISCOVERABLE);
+ EXPECT_FALSE(resource->secure);
+ EXPECT_EQ(0, resource->port);
+ EXPECT_EQ(NULL, resource->next);
+ }
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+static OCStackApplicationResult DiscoverUnicastErrorResponse(void *ctx, OCDoHandle handle,
+ OCClientResponse *response)
+{
+ OC_UNUSED(ctx);
+ OC_UNUSED(handle);
+ EXPECT_NE(OC_STACK_OK, response->result);
+ EXPECT_TRUE(NULL == response->payload);
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+TEST_F(OCDiscoverTests, DiscoverResourceWithValidQueries)
+{
+ itst::DeadmanTimer killSwitch(LONG_TEST_TIMEOUT);
+
+ OCResourceHandle handles;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles, "core.light", "oic.if.baseline", "/a/light",
+ entityHandler, NULL, OC_DISCOVERABLE));
+ OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, "StackTest");
+
+ Callback discoverBaselineCB(&DiscoverBaselineResource);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.baseline", NULL,
+ 0, CT_DEFAULT, OC_HIGH_QOS, discoverBaselineCB, NULL, 0));
+ discoverBaselineCB.Wait(100);
+
+ Callback discoverDefaultCB(&DiscoverLinkedListResource);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL, 0, CT_DEFAULT,
+ OC_HIGH_QOS, discoverDefaultCB, NULL, 0));
+ discoverDefaultCB.Wait(100);
+
+ Callback discoverLinkedListCB(&DiscoverLinkedListResource);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=oic.if.ll", NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverLinkedListCB, NULL, 0));
+ discoverLinkedListCB.Wait(100);
+
+ Callback discoverRTCB(&DiscoverResourceTypeResponse);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=core.light", NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverRTCB, NULL, 0));
+ discoverRTCB.Wait(100);
+}
+
+TEST_F(OCDiscoverTests, DiscoverResourceWithInvalidQueries)
+{
+ itst::DeadmanTimer killSwitch(LONG_TEST_TIMEOUT);
+
+ OCResourceHandle handles;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handles, "core.light", "oic.if.baseline", "/a/light",
+ entityHandler, NULL, OC_DISCOVERABLE));
+ OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, "deviceName", "StackTest");
+
+ Callback discoverRTInvalidCB(&DiscoverUnicastErrorResponse);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=invalid", NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverRTInvalidCB, NULL, 0));
+ discoverRTInvalidCB.Wait(10);
+
+ Callback discoverRTEmptyCB(&DiscoverUnicastErrorResponse);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?rt=", NULL, 0, CT_DEFAULT,
+ OC_HIGH_QOS, discoverRTEmptyCB, NULL, 0));
+ discoverRTEmptyCB.Wait(10);
+
+ Callback discoverIfInvalidCB(&DiscoverUnicastErrorResponse);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=invalid", NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverIfInvalidCB, NULL, 0));
+ discoverIfInvalidCB.Wait(10);
+
+ Callback discoverIfEmptyCB(&DiscoverUnicastErrorResponse);
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res?if=", NULL, 0, CT_DEFAULT,
+ OC_HIGH_QOS, discoverIfEmptyCB, NULL, 0));
+ discoverIfEmptyCB.Wait(10);
+
+ // Unicast
+ char targetUri[MAX_URI_LENGTH * 2] ={ 0, };
+
+ Callback discoverUnicastIfInvalidCB(&DiscoverUnicastErrorResponse);
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "127.0.0.1/oic/res?if=invalid");
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, targetUri, NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverUnicastIfInvalidCB, NULL, 0));
+ discoverUnicastIfInvalidCB.Wait(10);
+
+ Callback discoverUnicastIfEmptyCB(&DiscoverUnicastErrorResponse);
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "127.0.0.1/oic/res?if=");
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, targetUri, NULL, 0, CT_DEFAULT,
+ OC_HIGH_QOS, discoverUnicastIfEmptyCB, NULL, 0));
+ discoverUnicastIfEmptyCB.Wait(10);
+
+ Callback discoverUnicastRTInvalidCB(&DiscoverUnicastErrorResponse);
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "127.0.0.1/oic/res?rt=invalid");
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, targetUri, NULL, 0,
+ CT_DEFAULT, OC_HIGH_QOS, discoverUnicastRTInvalidCB, NULL, 0));
+ discoverUnicastRTInvalidCB.Wait(10);
+
+ Callback discoverUnicastRTEmptyCB(&DiscoverUnicastErrorResponse);
+ snprintf(targetUri, MAX_URI_LENGTH * 2, "127.0.0.1/oic/res?rt=");
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, targetUri, NULL, 0, CT_DEFAULT,
+ OC_HIGH_QOS, discoverUnicastRTEmptyCB, NULL, 0));
+ discoverUnicastRTEmptyCB.Wait(10);
+}