//Cred DELETE request
TEST(CredEntityHandlerTest, CredEntityHandlerDeleteTest)
{
    OCEntityHandlerRequest ehReq =  OCEntityHandlerRequest();
    static OCPersistentStorage ps =  OCPersistentStorage();
    const OicSecCred_t* subjectCred1 = NULL;
    const OicSecCred_t* subjectCred2 = NULL;
    char *jsonStr = NULL;
    OCEntityHandlerResult ehRet = OC_EH_ERROR;
    char query[] = "sub=c3ViamVjdDE=";

    SetPersistentHandler(&ps, true);

    OicSecCred_t *cred = getCredList();
    VERIFY_NON_NULL(TAG, cred, ERROR);

    jsonStr = BinToCredJSON(cred);
    VERIFY_NON_NULL(TAG, jsonStr, ERROR);

    // Create Entity Handler POST request payload
    ehReq.method = OC_REST_POST;
    ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
    ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
    EXPECT_TRUE(OC_EH_ERROR == ehRet);

    // Verify if SRM contains Credential for the subject
    subjectCred1 = GetCredResourceData(&cred->subject);
    EXPECT_TRUE(NULL != subjectCred1);

    // Create Entity Handler DELETE request
    ehReq.method = OC_REST_DELETE;
    ehReq.query = (char*)OICMalloc(strlen(query)+1);
    VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
    OICStrcpy(ehReq.query, strlen(query)+1, query);

    ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
    EXPECT_TRUE(OC_EH_ERROR == ehRet);

    // Verify if SRM has deleted ACE for the subject
    subjectCred2 = GetCredResourceData(&cred->subject);
    EXPECT_TRUE(NULL == subjectCred2);

exit:
    // Perform cleanup
    OICFree(ehReq.query);
    OICFree(jsonStr);
    OCPayloadDestroy(ehReq.payload);
    if(NULL != cred)
    {
        DeInitCredResource();
        DeleteCredList(cred);
    }
}
static OCStackResult RemoveDeviceInfoFromLocal(const OCProvisionDev_t* pTargetDev)
{
    // Remove credential of revoked device from SVR database
    OCStackResult res = OC_STACK_ERROR;
    const OicSecCred_t *cred = NULL;
    cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
    if (cred == NULL)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to get credential of remove device.");
        goto error;
    }

    res = RemoveCredential(&cred->subject);
    if (res != OC_STACK_RESOURCE_DELETED)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to remove credential.");
        goto error;
    }

    /**
     * Change the device status as stale status.
     * If all request are successed, this device information will be deleted.
     */
    res = PDMSetDeviceStale(&pTargetDev->doxm->deviceID);
    if (res != OC_STACK_OK)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to set device status as stale");
        goto error;
    }

    // TODO: We need to add new mechanism to clean up the stale state of the device.

    //Close the DTLS session of the removed device.
    CAEndpoint_t* endpoint = (CAEndpoint_t *)&pTargetDev->endpoint;
    endpoint->port = pTargetDev->securePort;
    CAResult_t caResult = CACloseDtlsSession(endpoint);
    if(CA_STATUS_OK != caResult)
    {
        OIC_LOG_V(WARNING, TAG, "OCRemoveDevice : Failed to close DTLS session : %d", caResult);
    }

error:
    return res;
}
TEST(GenerateAndAddCredentialTest, GenerateAndAddCredentialValidInput)
{
    OicUuid_t owners[1];
    OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId11");

    OicUuid_t subject = {{0}};
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");

    char privateKey[] = "My private Key11";

    OicSecCred_t * cred1  = NULL;
    OicSecCred_t * headCred = NULL;

    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               privateKey, 1, owners);

    EXPECT_EQ(OC_STACK_ERROR, AddCredential(cred1));
    headCred = cred1;

    OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId22");
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject22");
    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               privateKey, 1, owners);
    EXPECT_EQ(OC_STACK_ERROR, AddCredential(cred1));

    OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId33");
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject33");
    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               privateKey, 1, owners);
    EXPECT_EQ(OC_STACK_ERROR, AddCredential(cred1));

    const OicSecCred_t* credList = GetCredResourceData(&headCred->subject);

    printCred(credList);

    DeleteCredList(headCred);

}
TEST(CredResourceTest, GenerateAndAddCredentialValidInput)
{
    OicUuid_t rownerID = {{0}};
    OICStrcpy((char *)rownerID.id, sizeof(rownerID.id), "ownersId11");

    OicUuid_t subject = {{0}};
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");

    uint8_t privateKey[] = "My private Key11";
    OicSecKey_t key = {privateKey, sizeof(privateKey)};

    OicSecCred_t *cred1  = NULL;
    OicSecCred_t *headCred = NULL;

    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               &key, &rownerID);

    EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));
    headCred = cred1;

    OICStrcpy((char *)rownerID.id, sizeof(rownerID.id), "ownersId22");
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject22");
    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               &key, &rownerID);
    EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));

    OICStrcpy((char *)rownerID.id, sizeof(rownerID.id), "ownersId33");
    OICStrcpy((char *)subject.id, sizeof(subject.id), "subject33");
    cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
                               &key, &rownerID);
    EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));

    const OicSecCred_t* credList = GetCredResourceData(&headCred->subject);

    printCred(credList);

    DeleteCredList(headCred);
}
TEST(CredGetResourceDataTest, GetCredResourceDataValidSubject)
{
    OicSecCred_t* cred = getCredList();
    EXPECT_TRUE(NULL != GetCredResourceData(cred->subject));
}
//GetCredResourceData Test
TEST(CredGetResourceDataTest, GetCredResourceDataNULLSubject)
{
    EXPECT_TRUE(NULL == GetCredResourceData(NULL));
}
/*
* Function to device revocation
* This function will remove credential of target device from all devices in subnet.
*
* @param[in] ctx Application context would be returned in result callback
* @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
* @param[in] pTargetDev Device information to be revoked.
* @param[in] resultCallback callback provided by API user, callback will be called when
*            credential revocation is finished.
 * @return  OC_STACK_OK in case of success and other value otherwise.
*/
OCStackResult OCRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
                            const OCProvisionDev_t* pTargetDev,
                            OCProvisionResultCB resultCallback)
{
    OIC_LOG(INFO, TAG, "IN OCRemoveDevice");
    OCStackResult res = OC_STACK_ERROR;
    if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
    {
        OIC_LOG(INFO, TAG, "OCRemoveDevice : Invalied parameters");
        return OC_STACK_INVALID_PARAM;
    }
    if (!resultCallback)
    {
        OIC_LOG(INFO, TAG, "OCRemoveDevice : NULL Callback");
        return OC_STACK_INVALID_CALLBACK;
    }

    // Send DELETE requests to linked devices
    OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
    resReq = SRPRemoveDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
    if (OC_STACK_OK != resReq)
    {
        if (OC_STACK_CONTINUE == resReq)
        {
            OIC_LOG(DEBUG, TAG, "OCRemoveDevice : Revoked device has no linked device except PT.");
        }
        else
        {
            OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to invoke SRPRemoveDevice");
            res = resReq;
            goto error;
        }
    }

    // Remove credential of revoked device from SVR database
    const OicSecCred_t *cred = NULL;
    cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
    if (cred == NULL)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to get credential of remove device.");
        goto error;
    }

    res = RemoveCredential(&cred->subject);
    if (res != OC_STACK_RESOURCE_DELETED)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to remove credential.");
        goto error;
    }

    /**
     * Change the device status as stale status.
     * If all request are successed, this device information will be deleted.
     */
    res = PDMSetDeviceStale(&pTargetDev->doxm->deviceID);
    if (res != OC_STACK_OK)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to set device status as stale");
        goto error;
    }

    // TODO: We need to add new mechanism to clean up the stale state of the device.

    res = resReq;

    //Close the DTLS session of the removed device.
    CAEndpoint_t* endpoint = (CAEndpoint_t *)&pTargetDev->endpoint;
    endpoint->port = pTargetDev->securePort;
    CAResult_t caResult = CACloseDtlsSession(endpoint);
    if(CA_STATUS_OK != caResult)
    {
        OIC_LOG_V(WARNING, TAG, "OCRemoveDevice : Failed to close DTLS session : %d", caResult);
    }

    /**
     * If there is no linked device, PM does not send any request.
     * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
     */
    if(OC_STACK_CONTINUE == res)
    {
        if(resultCallback)
        {
            resultCallback(ctx, 0, NULL, false);
        }
        res = OC_STACK_OK;
    }

error:
    OIC_LOG(INFO, TAG, "OUT OCRemoveDevice");
    return res;
}
//GetCredResourceData Test
TEST(CredResourceTest, GetCredResourceDataNULLSubject)
{
    EXPECT_EQ(NULL, GetCredResourceData(NULL));
}
//Cred DELETE request
TEST(CredResourceTest, CredEntityHandlerDeleteTest)
{
    OCEntityHandlerRequest ehReq =  OCEntityHandlerRequest();
    static OCPersistentStorage ps =  OCPersistentStorage();
    const OicSecCred_t* subjectCred1 = NULL;
    const OicSecCred_t* subjectCred2 = NULL;
    OCEntityHandlerResult ehRet = OC_EH_ERROR;
    char query[] = "subjectuuid=31313131-3131-3131-3131-313131313131"; //canonical uuid of subject1

    SetPersistentHandler(&ps, true);

    OicSecCred_t *cred = getCredList();
    ASSERT_TRUE(NULL != cred);
    uint8_t *payload = NULL;
    size_t size = 0;
    EXPECT_EQ(OC_STACK_OK, CredToCBORPayload(cred, &payload, &size));
    if (!payload)
    {
        DeleteCredList(cred);
    }
    ASSERT_TRUE(NULL != payload);

    // Create Entity Handler POST request payload
    ehReq.method = OC_REST_POST;
    ehReq.payload = (OCPayload *)OCSecurityPayloadCreate(payload, size);
    if (!ehReq.payload)
    {
        OICFree(payload);
        DeleteCredList(cred);
    }
    ASSERT_TRUE( NULL != ehReq.payload);
    EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OC_REQUEST_FLAG, &ehReq, NULL));

    // Verify if SRM contains Credential for the subject
    subjectCred1 = GetCredResourceData(&cred->subject);
    EXPECT_TRUE(NULL != subjectCred1);

    // Create Entity Handler DELETE request
    ehReq.method = OC_REST_DELETE;
    ehReq.query = (char *)OICCalloc(1, strlen(query)+1);
    if (!ehReq.query)
    {
        OICFree(payload);
        DeleteCredList(cred);
    }
    ASSERT_TRUE(NULL != ehReq.query);
    OICStrcpy(ehReq.query, strlen(query)+1, query);

    ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq, NULL);
    EXPECT_EQ(OC_EH_ERROR, ehRet);

    // Verify if SRM has deleted ACE for the subject
    subjectCred2 = GetCredResourceData(&cred->subject);
    EXPECT_TRUE(NULL == subjectCred2);

    // Perform cleanup
    OICFree(ehReq.query);
    OICFree(payload);
    DeInitCredResource();
    DeleteCredList(cred);
    OCPayloadDestroy((OCPayload *)ehReq.payload);
}