diff --git a/services/tunnelbroker/src/Constants.h b/services/tunnelbroker/src/Constants.h index 5b9da6f5a..06f5d8ba4 100644 --- a/services/tunnelbroker/src/Constants.h +++ b/services/tunnelbroker/src/Constants.h @@ -1,55 +1,57 @@ #pragma once #include #include #include namespace comm { namespace network { // AWS DynamoDB const std::string DEVICE_SESSIONS_TABLE_NAME = "tunnelbroker-device-session"; const std::string DEVICE_SESSIONS_VERIFICATION_MESSAGES_TABLE_NAME = "tunnelbroker-verification-message"; const std::string DEVICE_PUBLIC_KEY_TABLE_NAME = "tunnelbroker-public-key"; const std::string MESSAGES_TABLE_NAME = "tunnelbroker-message"; // Sessions const size_t SIGNATURE_REQUEST_LENGTH = 64; const size_t SESSION_ID_LENGTH = 64; const size_t SESSION_RECORD_TTL = 30 * 24 * 3600; // 30 days const size_t SESSION_SIGN_RECORD_TTL = 24 * 3600; // 24 hours const std::regex SESSION_ID_FORMAT_REGEX( "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); // gRPC Server const std::string SERVER_LISTEN_ADDRESS = "0.0.0.0:50051"; // AMQP (RabbitMQ) const std::string AMQP_FANOUT_EXCHANGE_NAME = "allBrokers"; -// message TTL +// Message broker queue message TTL const size_t AMQP_MESSAGE_TTL = 300 * 1000; // 5 min // queue TTL in case of no consumers (tunnelbroker is down) const size_t AMQP_QUEUE_TTL = 24 * 3600 * 1000; // 24 hours // routing message headers name const std::string AMQP_HEADER_FROM_DEVICEID = "fromDeviceID"; const std::string AMQP_HEADER_TO_DEVICEID = "toDeviceID"; const std::string AMQP_HEADER_MESSAGEID = "messageID"; const int64_t AMQP_SHORTEST_RECONNECTION_ATTEMPT_INTERVAL = 1000 * 60; // 1 min // DeviceID const size_t DEVICEID_CHAR_LENGTH = 64; const std::regex DEVICEID_FORMAT_REGEX( "^(ks|mobile|web):[a-zA-Z0-9]{" + std::to_string(DEVICEID_CHAR_LENGTH) + "}$"); // Config const std::string CONFIG_FILE_PATH = std::string(std::getenv("HOME")) + "/tunnelbroker/tunnelbroker.ini"; // DeliveryBroker const size_t DELIVERY_BROKER_MAX_QUEUE_SIZE = 100; +// Database messages TTL +const size_t MESSAGE_RECORD_TTL = 300 * 24 * 60 * 60; // 300 days } // namespace network } // namespace comm diff --git a/services/tunnelbroker/src/Database/DatabaseManager.cpp b/services/tunnelbroker/src/Database/DatabaseManager.cpp index 33375e205..f23dd9434 100644 --- a/services/tunnelbroker/src/Database/DatabaseManager.cpp +++ b/services/tunnelbroker/src/Database/DatabaseManager.cpp @@ -1,238 +1,239 @@ #include "DatabaseManager.h" namespace comm { namespace network { namespace database { DatabaseManager &DatabaseManager::getInstance() { static DatabaseManager instance; return instance; } bool DatabaseManager::isTableAvailable(const std::string &tableName) { Aws::DynamoDB::Model::DescribeTableRequest request; request.SetTableName(tableName); // Check table availability by invoking DescribeTable const Aws::DynamoDB::Model::DescribeTableOutcome &result = getDynamoDBClient()->DescribeTable(request); return result.IsSuccess(); } void DatabaseManager::innerPutItem( std::shared_ptr item, const Aws::DynamoDB::Model::PutItemRequest &request) { const Aws::DynamoDB::Model::PutItemOutcome outcome = getDynamoDBClient()->PutItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } template std::shared_ptr DatabaseManager::innerFindItem(Aws::DynamoDB::Model::GetItemRequest &request) { std::shared_ptr item = createItemByType(); request.SetTableName(item->getTableName()); const Aws::DynamoDB::Model::GetItemOutcome &outcome = getDynamoDBClient()->GetItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const AttributeValues &outcomeItem = outcome.GetResult().GetItem(); if (!outcomeItem.size()) { return nullptr; } item->assignItemFromDatabase(outcomeItem); return std::move(item); } void DatabaseManager::innerRemoveItem( const Item &item, const std::string &key) { Aws::DynamoDB::Model::DeleteItemRequest request; request.SetTableName(item.getTableName()); request.AddKey( item.getPrimaryKey(), Aws::DynamoDB::Model::AttributeValue(key)); const Aws::DynamoDB::Model::DeleteItemOutcome &outcome = getDynamoDBClient()->DeleteItem(request); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } } void DatabaseManager::putSessionItem(const DeviceSessionItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(item.getTableName()); request.AddItem( DeviceSessionItem::FIELD_SESSION_ID, Aws::DynamoDB::Model::AttributeValue(item.getSessionID())); request.AddItem( DeviceSessionItem::FIELD_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(item.getDeviceID())); request.AddItem( DeviceSessionItem::FIELD_PUBKEY, Aws::DynamoDB::Model::AttributeValue(item.getPubKey())); request.AddItem( DeviceSessionItem::FIELD_NOTIFY_TOKEN, Aws::DynamoDB::Model::AttributeValue(item.getNotifyToken())); request.AddItem( DeviceSessionItem::FIELD_DEVICE_TYPE, Aws::DynamoDB::Model::AttributeValue(item.getDeviceType())); request.AddItem( DeviceSessionItem::FIELD_APP_VERSION, Aws::DynamoDB::Model::AttributeValue(item.getAppVersion())); request.AddItem( DeviceSessionItem::FIELD_DEVICE_OS, Aws::DynamoDB::Model::AttributeValue(item.getDeviceOs())); request.AddItem( DeviceSessionItem::FIELD_CHECKPOINT_TIME, Aws::DynamoDB::Model::AttributeValue( std::to_string(item.getCheckpointTime()))); request.AddItem( DeviceSessionItem::FIELD_EXPIRE, Aws::DynamoDB::Model::AttributeValue(std::to_string( static_cast(std::time(0)) + SESSION_RECORD_TTL))); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findSessionItem(const std::string &sessionID) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( DeviceSessionItem::FIELD_SESSION_ID, Aws::DynamoDB::Model::AttributeValue(sessionID)); return std::move(this->innerFindItem(request)); } void DatabaseManager::removeSessionItem(const std::string &sessionID) { this->innerRemoveItem(*(createItemByType()), sessionID); } void DatabaseManager::putSessionSignItem(const SessionSignItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(item.getTableName()); request.AddItem( SessionSignItem::FIELD_SESSION_VERIFICATION, Aws::DynamoDB::Model::AttributeValue(item.getSign())); request.AddItem( SessionSignItem::FIELD_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(item.getDeviceID())); request.AddItem( SessionSignItem::FIELD_EXPIRE, Aws::DynamoDB::Model::AttributeValue(std::to_string( static_cast(std::time(0)) + SESSION_SIGN_RECORD_TTL))); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findSessionSignItem(const std::string &deviceID) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( SessionSignItem::FIELD_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(deviceID)); return std::move(this->innerFindItem(request)); } void DatabaseManager::removeSessionSignItem(const std::string &deviceID) { this->innerRemoveItem(*(createItemByType()), deviceID); } void DatabaseManager::putPublicKeyItem(const PublicKeyItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(item.getTableName()); request.AddItem( PublicKeyItem::FIELD_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(item.getDeviceID())); request.AddItem( PublicKeyItem::FIELD_PUBLIC_KEY, Aws::DynamoDB::Model::AttributeValue(item.getPublicKey())); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findPublicKeyItem(const std::string &deviceID) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( PublicKeyItem::FIELD_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(deviceID)); return std::move(this->innerFindItem(request)); } void DatabaseManager::removePublicKeyItem(const std::string &deviceID) { this->innerRemoveItem(*(createItemByType()), deviceID); } void DatabaseManager::putMessageItem(const MessageItem &item) { Aws::DynamoDB::Model::PutItemRequest request; request.SetTableName(item.getTableName()); request.AddItem( MessageItem::FIELD_MESSAGE_ID, Aws::DynamoDB::Model::AttributeValue(item.getMessageID())); request.AddItem( MessageItem::FIELD_FROM_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(item.getFromDeviceID())); request.AddItem( MessageItem::FIELD_TO_DEVICE_ID, Aws::DynamoDB::Model::AttributeValue(item.getToDeviceID())); request.AddItem( MessageItem::FIELD_PAYLOAD, Aws::DynamoDB::Model::AttributeValue(item.getPayload())); request.AddItem( MessageItem::FIELD_BLOB_HASHES, Aws::DynamoDB::Model::AttributeValue(item.getBlobHashes())); request.AddItem( MessageItem::FIELD_EXPIRE, - Aws::DynamoDB::Model::AttributeValue(std::to_string(item.getExpire()))); + Aws::DynamoDB::Model::AttributeValue(std::to_string( + static_cast(std::time(0) + MESSAGE_RECORD_TTL)))); request.AddItem( MessageItem::FIELD_CREATED_AT, Aws::DynamoDB::Model::AttributeValue( std::to_string(tools::getCurrentTimestamp()))); this->innerPutItem(std::make_shared(item), request); } std::shared_ptr DatabaseManager::findMessageItem(const std::string &messageID) { Aws::DynamoDB::Model::GetItemRequest request; request.AddKey( MessageItem::FIELD_MESSAGE_ID, Aws::DynamoDB::Model::AttributeValue(messageID)); return std::move(this->innerFindItem(request)); } std::vector> DatabaseManager::findMessageItemsByReceiver(const std::string &toDeviceID) { std::vector> result; Aws::DynamoDB::Model::QueryRequest req; req.SetTableName(MessageItem().getTableName()); req.SetKeyConditionExpression( MessageItem::FIELD_TO_DEVICE_ID + " = :valueToMatch"); AttributeValues attributeValues; attributeValues.emplace(":valueToMatch", toDeviceID); req.SetExpressionAttributeValues(attributeValues); req.SetIndexName(MessageItem::INDEX_TO_DEVICE_ID); const Aws::DynamoDB::Model::QueryOutcome &outcome = getDynamoDBClient()->Query(req); if (!outcome.IsSuccess()) { throw std::runtime_error(outcome.GetError().GetMessage()); } const Aws::Vector &items = outcome.GetResult().GetItems(); for (auto &item : items) { result.push_back(std::make_shared(item)); } return result; } void DatabaseManager::removeMessageItem(const std::string &messageID) { this->innerRemoveItem(*(createItemByType()), messageID); } } // namespace database } // namespace network } // namespace comm diff --git a/services/tunnelbroker/src/Database/MessageItem.cpp b/services/tunnelbroker/src/Database/MessageItem.cpp index 92c063682..347d2db22 100644 --- a/services/tunnelbroker/src/Database/MessageItem.cpp +++ b/services/tunnelbroker/src/Database/MessageItem.cpp @@ -1,108 +1,105 @@ #include "MessageItem.h" #include "ConfigManager.h" #include "Tools.h" #include namespace comm { namespace network { namespace database { const std::string MessageItem::FIELD_MESSAGE_ID = "MessageID"; const std::string MessageItem::FIELD_FROM_DEVICE_ID = "FromDeviceID"; const std::string MessageItem::FIELD_TO_DEVICE_ID = "ToDeviceID"; const std::string MessageItem::FIELD_PAYLOAD = "Payload"; const std::string MessageItem::FIELD_BLOB_HASHES = "BlobHashes"; const std::string MessageItem::FIELD_EXPIRE = "Expire"; const std::string MessageItem::FIELD_CREATED_AT = "CreatedAt"; const std::string MessageItem::INDEX_TO_DEVICE_ID = "ToDeviceID-index"; MessageItem::MessageItem( const std::string messageID, const std::string fromDeviceID, const std::string toDeviceID, const std::string payload, - const std::string blobHashes, - const uint64_t expire) + const std::string blobHashes) : messageID(messageID), fromDeviceID(fromDeviceID), toDeviceID(toDeviceID), payload(payload), - blobHashes(blobHashes), - expire(expire) { + blobHashes(blobHashes) { this->validate(); } MessageItem::MessageItem(const AttributeValues &itemFromDB) { this->assignItemFromDatabase(itemFromDB); } void MessageItem::validate() const { if (!tools::validateDeviceID(this->fromDeviceID)) { throw std::runtime_error("Error: FromDeviceID format is wrong."); } if (!tools::validateDeviceID(this->toDeviceID)) { throw std::runtime_error("Error: ToDeviceID format is wrong."); } tools::checkIfNotEmpty("messageID", this->messageID); - tools::checkIfNotZero("expire", this->expire); } void MessageItem::assignItemFromDatabase(const AttributeValues &itemFromDB) { try { this->messageID = itemFromDB.at(MessageItem::FIELD_MESSAGE_ID).GetS(); this->fromDeviceID = itemFromDB.at(MessageItem::FIELD_FROM_DEVICE_ID).GetS(); this->toDeviceID = itemFromDB.at(MessageItem::FIELD_TO_DEVICE_ID).GetS(); this->payload = itemFromDB.at(MessageItem::FIELD_PAYLOAD).GetS(); this->blobHashes = itemFromDB.at(MessageItem::FIELD_BLOB_HASHES).GetS(); this->expire = std::stoull(itemFromDB.at(MessageItem::FIELD_EXPIRE).GetS()); this->createdAt = std::stoull(itemFromDB.at(MessageItem::FIELD_CREATED_AT).GetS()); } catch (const std::exception &e) { throw std::runtime_error( "Got an exception at MessageItem: " + std::string(e.what())); } this->validate(); } std::string MessageItem::getTableName() const { return config::ConfigManager::getInstance().getParameter( config::ConfigManager::OPTION_DYNAMODB_MESSAGES_TABLE); } std::string MessageItem::getPrimaryKey() const { return MessageItem::FIELD_MESSAGE_ID; } std::string MessageItem::getMessageID() const { return this->messageID; } std::string MessageItem::getFromDeviceID() const { return this->fromDeviceID; } std::string MessageItem::getToDeviceID() const { return this->toDeviceID; } std::string MessageItem::getPayload() const { return this->payload; } std::string MessageItem::getBlobHashes() const { return this->blobHashes; } uint64_t MessageItem::getExpire() const { return this->expire; } uint64_t MessageItem::getCreatedAt() const { return this->createdAt; } } // namespace database } // namespace network } // namespace comm diff --git a/services/tunnelbroker/src/Database/MessageItem.h b/services/tunnelbroker/src/Database/MessageItem.h index 5a70c78f3..3b370e7b2 100644 --- a/services/tunnelbroker/src/Database/MessageItem.h +++ b/services/tunnelbroker/src/Database/MessageItem.h @@ -1,57 +1,56 @@ #pragma once #include "Item.h" #include namespace comm { namespace network { namespace database { class MessageItem : public Item { std::string messageID; std::string fromDeviceID; std::string toDeviceID; std::string payload; std::string blobHashes; uint64_t expire; uint64_t createdAt; void validate() const override; public: static const std::string FIELD_MESSAGE_ID; static const std::string FIELD_FROM_DEVICE_ID; static const std::string FIELD_TO_DEVICE_ID; static const std::string FIELD_PAYLOAD; static const std::string FIELD_BLOB_HASHES; static const std::string FIELD_EXPIRE; static const std::string FIELD_CREATED_AT; static const std::string INDEX_TO_DEVICE_ID; std::string getPrimaryKey() const override; std::string getTableName() const override; std::string getMessageID() const; std::string getFromDeviceID() const; std::string getToDeviceID() const; std::string getPayload() const; std::string getBlobHashes() const; uint64_t getExpire() const; uint64_t getCreatedAt() const; MessageItem() { } MessageItem( const std::string messageID, const std::string fromDeviceID, const std::string toDeviceID, const std::string payload, - const std::string blobHashes, - const uint64_t expire); + const std::string blobHashes); MessageItem(const AttributeValues &itemFromDB); void assignItemFromDatabase(const AttributeValues &itemFromDB) override; }; } // namespace database } // namespace network } // namespace comm diff --git a/services/tunnelbroker/test/DatabaseManagerTest.cpp b/services/tunnelbroker/test/DatabaseManagerTest.cpp index 9bdf084a9..8c0f099b7 100644 --- a/services/tunnelbroker/test/DatabaseManagerTest.cpp +++ b/services/tunnelbroker/test/DatabaseManagerTest.cpp @@ -1,298 +1,299 @@ #include "DatabaseManager.h" #include "ConfigManager.h" #include "Constants.h" #include "Tools.h" #include #include #include #include using namespace comm::network; class DatabaseManagerTest : public testing::Test { protected: virtual void SetUp() { config::ConfigManager::getInstance().load(); Aws::InitAPI({}); } virtual void TearDown() { Aws::ShutdownAPI({}); } }; TEST_F(DatabaseManagerTest, PutAndFoundMessageItemsStaticDataIsSame) { const database::MessageItem item( "bc0c1aa2-bf09-11ec-9d64-0242ac120002", "mobile:EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm", "web:JouLWf84zqRIsjBdHLOcHS9M4eSCz7VF84wT1uOD83u1qxDAqmqI4swmxNINjuhd", "lYlNcO6RR4i9UW3G1DGjdJTRRGbqtPya2aj94ZRjIGZWoHwT5MB9ciAgnQf2VafYb9Tl" "8SZkX37tg4yZ9pOb4lqslY4g4h58OmWjumghVRvrPUZDalUuK8OLs1Qoengpu9wccxAk" "Bti2leDTNeiJDy36NnwS9aCIUc0ozsMvXfX1gWdBdmKbiRG1LvpNd6S7BNGG7Zly5zYj" "xz7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8G5" "RJ1NEDQq2q2FRfWjNHLhky92C2C7Nnfe4oVzSinfC1319uUkNLpSzI4MvEMi6g5Ukbl7" "iGhpnX7Hp4xpBL3h2IkvGviDRQ98UvW0ugwUuPxm1NOQpjLG5dPoqQ0jrMst0Bl5rgPw" "ajjNGsUWmp9r0ST0wRQXrQcY30PoSoqKSlCEgFMLzHWLrPQ86QFyCICismGSe7iBIqdD" "6d37StvXBzfJoZVU79UeOF2bFvb3DNoArEOe", - "7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8", - static_cast(std::time(0)) + 600); + "7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8"); const size_t currentTimestamp = tools::getCurrentTimestamp(); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putMessageItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findMessageItem( item.getMessageID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getFromDeviceID(), foundItem->getFromDeviceID()); EXPECT_EQ(item.getToDeviceID(), foundItem->getToDeviceID()); EXPECT_EQ(item.getPayload(), foundItem->getPayload()); EXPECT_EQ(item.getBlobHashes(), foundItem->getBlobHashes()); - EXPECT_EQ(item.getExpire(), foundItem->getExpire()); + EXPECT_EQ( + (foundItem->getExpire() >= static_cast(std::time(0))) && + (foundItem->getExpire() <= + static_cast(std::time(0) + MESSAGE_RECORD_TTL)), + true); EXPECT_EQ( foundItem->getCreatedAt() >= currentTimestamp && foundItem->getCreatedAt() <= tools::getCurrentTimestamp(), true); database::DatabaseManager::getInstance().removeMessageItem( item.getMessageID()); } TEST_F(DatabaseManagerTest, PutAndFoundMessageItemsGeneratedDataIsSame) { const database::MessageItem item( tools::generateUUID(), "mobile:" + tools::generateRandomString(DEVICEID_CHAR_LENGTH), "web:" + tools::generateRandomString(DEVICEID_CHAR_LENGTH), tools::generateRandomString(256), - tools::generateRandomString(256), - static_cast(std::time(0)) + 600); + tools::generateRandomString(256)); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putMessageItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findMessageItem( item.getMessageID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getFromDeviceID(), foundItem->getFromDeviceID()) << "Generated FromDeviceID \"" << item.getFromDeviceID() << "\" differs from what is found in the database " << foundItem->getFromDeviceID(); EXPECT_EQ(item.getToDeviceID(), foundItem->getToDeviceID()) << "Generated ToDeviceID \"" << item.getToDeviceID() << "\" differs from what is found in the database " << foundItem->getToDeviceID(); EXPECT_EQ(item.getPayload(), foundItem->getPayload()) << "Generated Payload \"" << item.getPayload() << "\" differs from what is found in the database " << foundItem->getPayload(); EXPECT_EQ(item.getBlobHashes(), foundItem->getBlobHashes()) << "Generated BlobHashes \"" << item.getBlobHashes() << "\" differs from what is found in the database " << foundItem->getBlobHashes(); - EXPECT_EQ(item.getExpire(), foundItem->getExpire()) - << "Generated Expire time \"" << item.getExpire() - << "\" differs from what is found in the database " - << foundItem->getExpire(); database::DatabaseManager::getInstance().removeMessageItem( item.getMessageID()); } TEST_F(DatabaseManagerTest, TestOperationsOnDeviceSessionItem) { const database::DeviceSessionItem item( "bc0c1aa2-bf09-11ec-9d64-0242ac120002", "mobile:EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm", "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9Q9wodsQdZNynbTnC35hA4mFW" "mwZf9BhbI93aGAwPF9au0eYsawRz0jtYi4lSFXC9KleyQDg+6J+UW1kiWvE3ZRYG" "ECqgx4zqajPTzVt7EAOGaIh/dPyQ6x2Ul1GlkkSYXUhhixEzExGp9g84eCyVkbCB" "U3SK6SNKyR7anAXDVQIDAQAB", "hbI93aGAwPF9au0eYsawRz0jtYi4lSFXC9KleyQDg+6J+UW1kiWvE3", "phone", "ios:1.1.1", "iOS 99.99.99"); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putSessionItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findSessionItem( item.getSessionID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getDeviceID(), foundItem->getDeviceID()); EXPECT_EQ(item.getPubKey(), foundItem->getPubKey()); EXPECT_EQ(item.getNotifyToken(), foundItem->getNotifyToken()); EXPECT_EQ(item.getDeviceType(), foundItem->getDeviceType()); EXPECT_EQ(item.getAppVersion(), foundItem->getAppVersion()); EXPECT_EQ(item.getDeviceOs(), foundItem->getDeviceOs()); database::DatabaseManager::getInstance().removeSessionItem( item.getSessionID()); } TEST_F(DatabaseManagerTest, TestOperationsOnDeviceSessionItemGenerated) { const database::DeviceSessionItem item( tools::generateUUID(), "mobile:" + tools::generateRandomString(DEVICEID_CHAR_LENGTH), tools::generateRandomString(451), tools::generateRandomString(64), tools::generateRandomString(12), tools::generateRandomString(12), tools::generateRandomString(12)); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putSessionItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findSessionItem( item.getSessionID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getDeviceID(), foundItem->getDeviceID()) << "Generated DeviceID \"" << item.getDeviceID() << "\" differs from what is found in the database " << foundItem->getDeviceID(); EXPECT_EQ(item.getPubKey(), foundItem->getPubKey()) << "Generated PubKey \"" << item.getPubKey() << "\" differs from what is found in the database " << foundItem->getPubKey(); EXPECT_EQ(item.getNotifyToken(), foundItem->getNotifyToken()) << "Generated NotifyToken \"" << item.getNotifyToken() << "\" differs from what is found in the database " << foundItem->getNotifyToken(); EXPECT_EQ(item.getDeviceType(), foundItem->getDeviceType()) << "Generated DeviceType \"" << item.getDeviceType() << "\" differs from what is found in the database " << foundItem->getDeviceType(); EXPECT_EQ(item.getAppVersion(), foundItem->getAppVersion()) << "Generated AppVersion \"" << item.getAppVersion() << "\" differs from what is found in the database " << foundItem->getAppVersion(); EXPECT_EQ(item.getDeviceOs(), foundItem->getDeviceOs()) << "Generated DeviceOS \"" << item.getDeviceOs() << "\" differs from what is found in the database " << foundItem->getDeviceOs(); database::DatabaseManager::getInstance().removeSessionItem( item.getSessionID()); } TEST_F(DatabaseManagerTest, TestOperationsOnSessionSignItem) { const database::SessionSignItem item( "bB3OSLdKlY60KPBpw6VoGKX7Lmw3SA07FmNhnqnclvVeaxXueAQ0dpQSpiQTtlGn", "mobile:" "EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm"); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putSessionSignItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findSessionSignItem( item.getDeviceID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getSign(), foundItem->getSign()); database::DatabaseManager::getInstance().removeSessionSignItem( item.getDeviceID()); } TEST_F(DatabaseManagerTest, TestOperationsOnSessionSignItemGenerated) { const database::SessionSignItem item( tools::generateRandomString(SIGNATURE_REQUEST_LENGTH), "mobile:" + tools::generateRandomString(DEVICEID_CHAR_LENGTH)); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putSessionSignItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findSessionSignItem( item.getDeviceID()); EXPECT_NE(foundItem, nullptr) << "Item with the key of deviceID \"" << item.getDeviceID() << "\" is not found"; EXPECT_EQ(item.getSign(), foundItem->getSign()) << "Generated signature value \"" << item.getSign() << "\" is not equal of \"" + foundItem->getSign() + "\" from the database value"; database::DatabaseManager::getInstance().removeSessionSignItem( item.getDeviceID()); } TEST_F(DatabaseManagerTest, PutAndFoundPublicKeyItemsStaticDataIsSame) { const database::PublicKeyItem item( "mobile:EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm", "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9Q9wodsQdZNynbTnC35hA4mFW" "mwZf9BhbI93aGAwPF9au0eYsawRz0jtYi4lSFXC9KleyQDg+6J+UW1kiWvE3ZRYG" "ECqgx4zqajPTzVt7EAOGaIh/dPyQ6x2Ul1GlkkSYXUhhixEzExGp9g84eCyVkbCB" "U3SK6SNKyR7anAXDVQIDAQAB"); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putPublicKeyItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findPublicKeyItem( item.getDeviceID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getPublicKey(), foundItem->getPublicKey()); database::DatabaseManager::getInstance().removePublicKeyItem( item.getDeviceID()); } TEST_F(DatabaseManagerTest, PutAndFoundPublicKeyItemsGeneratedDataIsSame) { const database::PublicKeyItem item( "mobile:" + tools::generateRandomString(DEVICEID_CHAR_LENGTH), tools::generateRandomString(451)); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putPublicKeyItem(item); std::shared_ptr foundItem = database::DatabaseManager::getInstance().findPublicKeyItem( item.getDeviceID()); EXPECT_NE(foundItem, nullptr); EXPECT_EQ(item.getPublicKey(), foundItem->getPublicKey()) << "Generated PublicKey \"" << item.getPublicKey() << "\" differs from what is found in the database " << foundItem->getPublicKey(); database::DatabaseManager::getInstance().removePublicKeyItem( item.getDeviceID()); } TEST_F(DatabaseManagerTest, PutAndFoundByReceiverMessageItemsDataIsSame) { const std::string receiverID = "mobile:EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm"; const database::MessageItem item( "bc0c1aa2-bf09-11ec-9d64-0242ac120002", "mobile:EMQNoQ7b2ueEmQ4QsevRWlXxFCNt055y20T1PHdoYAQRt0S6TLzZWNM6XSvdWqxm", receiverID, "lYlNcO6RR4i9UW3G1DGjdJTRRGbqtPya2aj94ZRjIGZWoHwT5MB9ciAgnQf2VafYb9Tl" "8SZkX37tg4yZ9pOb4lqslY4g4h58OmWjumghVRvrPUZDalUuK8OLs1Qoengpu9wccxAk" "Bti2leDTNeiJDy36NnwS9aCIUc0ozsMvXfX1gWdBdmKbiRG1LvpNd6S7BNGG7Zly5zYj" "xz7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8G5" "RJ1NEDQq2q2FRfWjNHLhky92C2C7Nnfe4oVzSinfC1319uUkNLpSzI4MvEMi6g5Ukbl7" "iGhpnX7Hp4xpBL3h2IkvGviDRQ98UvW0ugwUuPxm1NOQpjLG5dPoqQ0jrMst0Bl5rgPw" "ajjNGsUWmp9r0ST0wRQXrQcY30PoSoqKSlCEgFMLzHWLrPQ86QFyCICismGSe7iBIqdD" "6d37StvXBzfJoZVU79UeOF2bFvb3DNoArEOe", - "7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8", - static_cast(std::time(0)) + 600); + "7s6ZUSDoFfZe3eJWQ15ngYhgMw1TsfbECnMVQTYvY6OyqWPBQi5wiftFcluoxor8"); EXPECT_EQ( database::DatabaseManager::getInstance().isTableAvailable( item.getTableName()), true); database::DatabaseManager::getInstance().putMessageItem(item); std::vector> foundItems = database::DatabaseManager::getInstance().findMessageItemsByReceiver( receiverID); EXPECT_NE(foundItems.size(), 0); EXPECT_EQ(item.getFromDeviceID(), foundItems[0]->getFromDeviceID()); EXPECT_EQ(item.getToDeviceID(), foundItems[0]->getToDeviceID()); EXPECT_EQ(item.getPayload(), foundItems[0]->getPayload()); EXPECT_EQ(item.getBlobHashes(), foundItems[0]->getBlobHashes()); - EXPECT_EQ(item.getExpire(), foundItems[0]->getExpire()); + EXPECT_EQ( + (foundItems[0]->getExpire() >= static_cast(std::time(0))) && + (foundItems[0]->getExpire() <= + static_cast(std::time(0) + MESSAGE_RECORD_TTL)), + true); database::DatabaseManager::getInstance().removeMessageItem( item.getMessageID()); }