/* ****************************************************************************
*
* noPatternMultiAttr -
*
* Discover:  E1 - (A3, A4, A5)
* Result:    E1 - A3 - http://cr1.com
*            E1 - A4 - http://cr2.com
*/
TEST(mongoContextProvidersUpdateRequest, noPatternMultiAttr)
{
  HttpStatusCode         ms;
  UpdateContextRequest   req;
  UpdateContextResponse  res;

  /* Prepare database */
  utInit();
  prepareDatabase();

  /* Forge the request (from "inside" to "outside") */
  ContextElement ce;
  ce.entityId.fill("E1", "T1", "false");
  ContextAttribute ca1("A3", "TA3", "new_val");
  ContextAttribute ca2("A4", "TA4", "new_val");
  ContextAttribute ca3("A5", "TA5", "new_val");
  ce.contextAttributeVector.push_back(&ca1);
  ce.contextAttributeVector.push_back(&ca2);
  ce.contextAttributeVector.push_back(&ca3);
  req.contextElementVector.push_back(&ce);
  req.updateActionType.set("UPDATE");

  /* Invoke the function in mongoBackend library */
  ms = mongoUpdateContext(&req, &res, "", servicePathVector, uriParams);

  /* Check response is as expected */
  EXPECT_EQ(SccOk, ms);

  EXPECT_EQ(SccNone, res.errorCode.code);
  EXPECT_EQ(0, res.errorCode.reasonPhrase.size());
  EXPECT_EQ(0, res.errorCode.details.size());

  ASSERT_EQ(1, res.contextElementResponseVector.size());
  EXPECT_EQ("E1", RES_CER(0).entityId.id);
  EXPECT_EQ("T1", RES_CER(0).entityId.type);
  EXPECT_EQ("false", RES_CER(0).entityId.isPattern);
  ASSERT_EQ(3, RES_CER(0).contextAttributeVector.size());
  EXPECT_EQ("A3", RES_CER_ATTR(0, 0)->name);
  EXPECT_EQ("TA3", RES_CER_ATTR(0, 0)->type);
  EXPECT_EQ("A4", RES_CER_ATTR(0, 1)->name);
  EXPECT_EQ("TA4", RES_CER_ATTR(0, 1)->type);
  EXPECT_EQ("A5", RES_CER_ATTR(0, 2)->name);
  EXPECT_EQ("TA5", RES_CER_ATTR(0, 2)->type);
  EXPECT_EQ(SccFound, RES_CER_STATUS(0).code);
  EXPECT_EQ("Found", RES_CER_STATUS(0).reasonPhrase);
  EXPECT_EQ("http://cr1.com", RES_CER_STATUS(0).details);

  /* Release connection */
  mongoDisconnect();

  utExit();

}
/* ****************************************************************************
*
* entityTypeFilterNotExist -
*
*/
TEST(mongoQueryContextExistEntity, entityTypeFilterNotExist)
{
  HttpStatusCode         ms;
  QueryContextRequest   req;
  QueryContextResponse  res;

  utInit();

  /* Prepare database */
  prepareDatabase();

  /* Forge the request (from "inside" to "outside") */
  EntityId en("E1", "", "false");
  req.entityIdVector.push_back(&en);

  /* Define filter scope */
  Scope sc;
  sc.type = "FIWARE::Filter::Existence";
  sc.oper = "not";
  sc.value = "entity::type";
  req.restriction.scopeVector.push_back(&sc);

  /* Invoke the function in mongoBackend library */
  ms = mongoQueryContext(&req, &res, "", servicePathVector , uriParams);

  /* Check response is as expected */
  EXPECT_EQ(SccOk, ms);

  EXPECT_EQ(SccNone, res.errorCode.code);
  EXPECT_EQ("", res.errorCode.reasonPhrase);
  EXPECT_EQ("", res.errorCode.details);

  ASSERT_EQ(1, res.contextElementResponseVector.size());
  /* Context Element response # 1 */
  EXPECT_EQ("E1", RES_CER(0).entityId.id);
  EXPECT_EQ("", RES_CER(0).entityId.type);
  EXPECT_EQ("false", RES_CER(0).entityId.isPattern);
  ASSERT_EQ(1, RES_CER(0).contextAttributeVector.size());
  EXPECT_EQ("A1", RES_CER_ATTR(0, 0)->name);
  EXPECT_EQ("TA1", RES_CER_ATTR(0, 0)->type);
  EXPECT_EQ("val1b", RES_CER_ATTR(0, 0)->value);
  EXPECT_EQ(SccOk, RES_CER_STATUS(0).code);
  EXPECT_EQ("OK", RES_CER_STATUS(0).reasonPhrase);
  EXPECT_EQ(0, RES_CER_STATUS(0).details.size());

  /* Release connection */
  mongoDisconnect();

  utExit();
}
/* ****************************************************************************
*
* noPatternMultiEntity -
*
* Discover:  (E1, E2) - no attrs
* Result:    (E1, E2) - (A1, A2, A3) - http://cr1.com
*            E1       - (A1, A4)     - http://cr2.com
*            E2       - (A2, A3)     - http://cr3.com
*/
TEST(mongoContextProvidersUpdateRequest, noPatternMultiEntity)
{
  HttpStatusCode         ms;
  UpdateContextRequest   req;
  UpdateContextResponse  res;

  /* Prepare database */
  utInit();
  prepareDatabase();

  /* Forge the request (from "inside" to "outside") */
  /* Note that although it is a bit weird having an updateContext without attributes to update,
     * it is legal from the point of view of OMA spec */
  ContextElement ce1, ce2;
  ce1.entityId.fill("E1", "T1", "false");
  ce2.entityId.fill("E2", "T2", "false");
  req.contextElementVector.push_back(&ce1);
  req.contextElementVector.push_back(&ce2);
  req.updateActionType.set("UPDATE");

  /* Invoke the function in mongoBackend library */
  ms = mongoUpdateContext(&req, &res, "", servicePathVector, uriParams);

  /* Check response is as expected */
  EXPECT_EQ(SccOk, ms);

  EXPECT_EQ(SccNone, res.errorCode.code);
  EXPECT_EQ(0, res.errorCode.reasonPhrase.size());
  EXPECT_EQ(0, res.errorCode.details.size());

  ASSERT_EQ(2,res.contextElementResponseVector.size());
  /* Context element response #1 */
  EXPECT_EQ("E1", RES_CER(0).entityId.id);
  EXPECT_EQ("T1", RES_CER(0).entityId.type);
  EXPECT_EQ("false", RES_CER(0).entityId.isPattern);
  ASSERT_EQ(0, RES_CER(0).contextAttributeVector.size());
  EXPECT_EQ(SccFound, RES_CER_STATUS(0).code);
  EXPECT_EQ("Found", RES_CER_STATUS(0).reasonPhrase);
  EXPECT_EQ("http://cr1.com", RES_CER_STATUS(0).details);

  /* Context element response #2 */
  EXPECT_EQ("E2", RES_CER(1).entityId.id);
  EXPECT_EQ("T2", RES_CER(1).entityId.type);
  EXPECT_EQ("false", RES_CER(1).entityId.isPattern);
  ASSERT_EQ(0, RES_CER(1).contextAttributeVector.size());
  EXPECT_EQ(SccFound, RES_CER_STATUS(1).code);
  EXPECT_EQ("Found", RES_CER_STATUS(1).reasonPhrase);
  EXPECT_EQ("http://cr1.com", RES_CER_STATUS(1).details);

  /* Release connection */
  mongoDisconnect();

  utExit();

}
/* ****************************************************************************
*
* entityTypeWithoutFilter -
*
*/
TEST(mongoQueryContextExistEntity, entityTypeWithoutFilter)
{
    HttpStatusCode         ms;
    QueryContextRequest   req;
    QueryContextResponse  res;

    utInit();

    /* Prepare database */
    prepareDatabase();

    /* Forge the request (from "inside" to "outside") */
    EntityId en("E1", "", "false");
    req.entityIdVector.push_back(&en);

    /* Invoke the function in mongoBackend library */
    ms = mongoQueryContext(&req, &res, "", servicePathVector , uriParams);

    /* Check response is as expected */
    EXPECT_EQ(SccOk, ms);

    EXPECT_EQ(SccNone, res.errorCode.code);
    EXPECT_EQ("", res.errorCode.reasonPhrase);
    EXPECT_EQ("", res.errorCode.details);

    ASSERT_EQ(2, res.contextElementResponseVector.size());
    /* Context Element response # 1 */
    EXPECT_EQ("E1", RES_CER(0).entityId.id);
    EXPECT_EQ("T1", RES_CER(0).entityId.type);
    EXPECT_EQ("false", RES_CER(0).entityId.isPattern);
    ASSERT_EQ(1, RES_CER(0).contextAttributeVector.size());
    EXPECT_EQ("A1", RES_CER_ATTR(0, 0)->name);
    EXPECT_EQ("TA1", RES_CER_ATTR(0, 0)->type);
    EXPECT_EQ("val1", RES_CER_ATTR(0, 0)->stringValue);
    EXPECT_EQ(SccOk, RES_CER_STATUS(0).code);
    EXPECT_EQ("OK", RES_CER_STATUS(0).reasonPhrase);
    EXPECT_EQ("", RES_CER_STATUS(0).details);

    /* Context Element response # 2 */
    EXPECT_EQ("E1", RES_CER(1).entityId.id);
    EXPECT_EQ("", RES_CER(1).entityId.type);
    EXPECT_EQ("false", RES_CER(1).entityId.isPattern);
    ASSERT_EQ(1, RES_CER(1).contextAttributeVector.size());
    EXPECT_EQ("A1", RES_CER_ATTR(1, 0)->name);
    EXPECT_EQ("TA1", RES_CER_ATTR(1, 0)->type);
    EXPECT_EQ("val1b", RES_CER_ATTR(1, 0)->stringValue);
    EXPECT_EQ(SccOk, RES_CER_STATUS(1).code);
    EXPECT_EQ("OK", RES_CER_STATUS(1).reasonPhrase);
    EXPECT_EQ(0, RES_CER_STATUS(1).details.size());
 
    utExit();
}
/* ****************************************************************************
*
* withAttribute -
*
*/
TEST(mongoQueryContextRequest_filters, withAttribute)
{
  HttpStatusCode         ms;
  QueryContextRequest   req;
  QueryContextResponse  res;

  /* Prepare database */
  prepareDatabase(true);

  /* Forge the request (from "inside" to "outside") */
  EntityId en(".*", "", "true");
  Scope sc(SCOPE_TYPE_SIMPLE_QUERY, "+S");
  req.entityIdVector.push_back(&en);
  req.restriction.scopeVector.push_back(&sc);

  /* Invoke the function in mongoBackend library */
  servicePathVector.clear();
  ms = mongoQueryContext(&req, &res, "", servicePathVector, uriParams);

  /* Check response is as expected */
  EXPECT_EQ(SccOk, ms);

  EXPECT_EQ(SccNone, res.errorCode.code);
  EXPECT_EQ("", res.errorCode.reasonPhrase);
  EXPECT_EQ("", res.errorCode.details);

  /* Only entitie IDs are check (we have a bunch of tests in other places to check the query response itself */
  ASSERT_EQ(5, res.contextElementResponseVector.size());
  EXPECT_EQ("E1", RES_CER(0).entityId.id);
  EXPECT_EQ("E2", RES_CER(1).entityId.id);
  EXPECT_EQ("E3", RES_CER(2).entityId.id);
  EXPECT_EQ("E4", RES_CER(3).entityId.id);
  EXPECT_EQ("E5", RES_CER(4).entityId.id);

  /* Release dynamic memory used by response (mongoBackend allocates it) */
  res.contextElementResponseVector.release();

  /* Release connection */
  setMongoConnectionForUnitTest(NULL);
}