/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include "acsdkBluetooth/SQLiteBluetoothStorage.h" namespace alexaClientSDK { namespace acsdkBluetooth { namespace test { using namespace ::testing; using namespace avsCommon::utils; using namespace avsCommon::utils::configuration; /// Test Database file name. Can be changed if there are conflicts. static const std::string TEST_DATABASE = "SQLiteBluetoothStorageTestDatabase.db"; // clang-format off static const std::string BLUETOOTH_JSON = R"( { "bluetooth" : { "databaseFilePath":")" + TEST_DATABASE + R"(" } } )"; // clang-format on /// Error message for when the file already exists. static const std::string FILE_EXISTS_ERROR = "Database File " + TEST_DATABASE + " already exists."; /// Test MAC Address. static const std::string TEST_MAC = "01:23:45:67:89:ab"; /// Second Test MAC Address. static const std::string TEST_MAC_2 = "11:23:45:67:89:ab"; /// Test UUID. static const std::string TEST_UUID = "650f973b-c2ab-4c6e-bff4-3788cd521340"; /// Second Test UUID. static const std::string TEST_UUID_2 = "750f973b-c2ab-4c6e-bff4-3788cd521340"; /// Test Unknown MAC/Category. static const std::string TEST_UNKNOWN = "UNKNOWN"; /// Test Other Category. static const std::string TEST_OTHER = "OTHER"; /// Test Phone Category. static const std::string TEST_PHONE = "PHONE"; /// Table name. static const std::string UUID_TABLE_NAME = "uuidMapping"; /// The UUID column. static const std::string COLUMN_UUID = "uuid"; /// The MAC address column. static const std::string COLUMN_MAC = "mac"; /** * Checks whether a file exists in the file system. * * @param file The file name. * @return Whether the file exists. */ static bool fileExists(const std::string& file) { std::ifstream dbFile(file); return dbFile.good(); } class SQLiteBluetoothStorageTest : public ::testing::Test { public: /// SetUp before each test case. void SetUp(); /// TearDown after each test case. void TearDown(); protected: /// Cleanup function to close and delete the database. void closeAndDeleteDB(); /// Function to create legacy database. bool createLegacyDatabase(); /// Insert Entry for legacy database. bool insertEntryLegacy(const std::string& uuid, const std::string& mac); /** * Helper function to setup database. * * @param migrated Whether using migrated database. * @return bool Whether database setup successful. */ bool setupDatabase(bool migratedDatabase); /** * Helper function that abstracts the test logic for getOrderedMac teste cases. * * @param ascending Whether we're testing the ascending or descending case. */ void getOrderedMacHelper(bool ascending); /** * Helper function that abstracts the logic for getMacToUuid and getUuidToMac test cases. * * @param retrieveRows Either the getMacToUuid or getUuidToMac function. * @param macToUuids A map of macToUuids to initialize the database with. * @param expected The expected results. */ void getRowsHelper( std::function*)> retrieveRows, const std::unordered_map& macToUuids, const std::unordered_map& expected); /** * Helper function that abstracts the logic for insertByMac given a macToUuids map and * verifies the expected value with the one returned by the retrieveValue function. * * @param retrieveValue function to retrieve value from database (getMac/getUuid/getCategory). * @param key The key (either the mac or uuid). * @param expectedValue The expected value from the given retrieveValue function call. * @param macToUuids A map of macToUuids to initialize the database with. */ void getRetrieveValueHelper( std::function retrieveValue, const std::string& key, const std::string& expectedValue, const std::unordered_map& macToUuids); /// The database instance. Protected because it needs to be accessed in test cases. std::unique_ptr m_db; /// SQLiteDatabase instance. std::unique_ptr m_sqLiteDb; }; void SQLiteBluetoothStorageTest::closeAndDeleteDB() { if (m_db) { m_db->close(); } if (m_sqLiteDb) { m_sqLiteDb->close(); } m_db.reset(); m_sqLiteDb.reset(); if (fileExists(TEST_DATABASE)) { remove(TEST_DATABASE.c_str()); } } bool SQLiteBluetoothStorageTest::createLegacyDatabase() { m_sqLiteDb = std::unique_ptr( new alexaClientSDK::storage::sqliteStorage::SQLiteDatabase(TEST_DATABASE)); if (!m_sqLiteDb || !m_sqLiteDb->initialize()) { return false; } if (!m_sqLiteDb->performQuery( "CREATE TABLE " + UUID_TABLE_NAME + "(" + COLUMN_UUID + " text not null unique, " + COLUMN_MAC + " text not null unique);")) { m_sqLiteDb->close(); return false; } return true; } bool SQLiteBluetoothStorageTest::insertEntryLegacy(const std::string& uuid, const std::string& mac) { // clang-format off const std::string sqlString = "INSERT INTO " + UUID_TABLE_NAME + " (" + COLUMN_UUID + "," + COLUMN_MAC + ") VALUES (?,?);"; // clang-format on auto statement = m_sqLiteDb->createStatement(sqlString); if (!statement) { return false; } const int UUID_INDEX = 1; const int MAC_INDEX = 2; if (!statement->bindStringParameter(UUID_INDEX, uuid) || !statement->bindStringParameter(MAC_INDEX, mac)) { return false; } // This could be due to a mac or uuid already existing in the db. if (!statement->step()) { return false; } return true; } bool SQLiteBluetoothStorageTest::setupDatabase(bool migratedDatabase) { if (migratedDatabase) { // Create legacy database and migrate. createLegacyDatabase(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); if (!m_db || !(m_db->open())) { return false; } } else { // Create a new database. m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); if (!m_db || !(m_db->createDatabase())) { return false; } } return true; } void SQLiteBluetoothStorageTest::SetUp() { // Ensure the db file does not exist already. We don't want to overwrite anything. if (fileExists(TEST_DATABASE)) { ADD_FAILURE() << FILE_EXISTS_ERROR; exit(1); } // Initialize Global ConfigurationNode with valid value. auto json = std::shared_ptr(new std::stringstream()); *json << BLUETOOTH_JSON; std::vector> jsonStream; jsonStream.push_back(json); ASSERT_TRUE(ConfigurationNode::initialize(jsonStream)); } void SQLiteBluetoothStorageTest::TearDown() { configuration::ConfigurationNode::uninitialize(); closeAndDeleteDB(); } void SQLiteBluetoothStorageTest::getOrderedMacHelper(bool ascending) { ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_TRUE(m_db->insertByMac(TEST_MAC_2, TEST_UUID_2)); std::list expected; if (ascending) { expected.push_back(TEST_MAC); expected.push_back(TEST_MAC_2); } else { expected.push_back(TEST_MAC_2); expected.push_back(TEST_MAC); } std::list rows; ASSERT_TRUE(m_db->getOrderedMac(ascending, &rows)); ASSERT_THAT(rows, Eq(expected)); } void SQLiteBluetoothStorageTest::getRowsHelper( std::function*)> retrieveRows, const std::unordered_map& macToUuids, const std::unordered_map& expected) { for (const auto& macAndUuid : macToUuids) { ASSERT_TRUE(m_db->insertByMac(macAndUuid.first, macAndUuid.second)); } std::unordered_map rows; ASSERT_TRUE(retrieveRows(*m_db, &rows)); ASSERT_THAT(rows, Eq(expected)); } void SQLiteBluetoothStorageTest::getRetrieveValueHelper( std::function retrieveValue, const std::string& key, const std::string& expectedValue, const std::unordered_map& macToUuids) { for (const auto& macAndUuid : macToUuids) { ASSERT_TRUE(m_db->insertByMac(macAndUuid.first, macAndUuid.second)); } std::string value; ASSERT_TRUE(retrieveValue(*m_db, key, &value)); ASSERT_THAT(value, Eq(expectedValue)); } /// Test database not created yet, open should fail. TEST_F(SQLiteBluetoothStorageTest, uninitializedDatabase) { m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_FALSE(m_db->open()); } /// Test if 2.0 database already created, open should succeed. TEST_F(SQLiteBluetoothStorageTest, openDatabase) { m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->createDatabase()); m_db->close(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); } /// Test if 1.0 database already created, open should succeed. TEST_F(SQLiteBluetoothStorageTest, openLegacyDatabase) { createLegacyDatabase(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); } /// Test retrieving category for a UUID that does not exist after database migration. TEST_F(SQLiteBluetoothStorageTest, retrieveCategoryforUnknownUUID) { createLegacyDatabase(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); std::string category; ASSERT_FALSE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq("")); } /// Test insertByMac after database migration. TEST_F(SQLiteBluetoothStorageTest, insertByMacPostDatabaseUpgrade) { createLegacyDatabase(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); std::string category; ASSERT_TRUE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq(TEST_UNKNOWN)); } /// Test retrieving mac for a UUID saved before migration after database migration. TEST_F(SQLiteBluetoothStorageTest, retrieveMacforKnownUUID) { createLegacyDatabase(); insertEntryLegacy(TEST_UUID, TEST_MAC); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); std::string mac; ASSERT_TRUE(m_db->getMac(TEST_UUID, &mac)); ASSERT_THAT(mac, Eq(TEST_MAC)); } /// Test retrieving category for a UUID saved before migration after database migration. TEST_F(SQLiteBluetoothStorageTest, retrieveCategoryforKnownUUID) { createLegacyDatabase(); insertEntryLegacy(TEST_UUID, TEST_MAC); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); std::string category; ASSERT_TRUE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq(TEST_OTHER)); } /// Test retrieving category for multiple UUIDs saved before migration after database migration. TEST_F(SQLiteBluetoothStorageTest, retrieveCategoryforKnownMultipleUUID) { createLegacyDatabase(); insertEntryLegacy(TEST_UUID, TEST_MAC); insertEntryLegacy(TEST_UUID_2, TEST_MAC_2); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); std::string category; ASSERT_TRUE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq(TEST_OTHER)); ASSERT_TRUE(m_db->getCategory(TEST_UUID_2, &category)); ASSERT_THAT(category, Eq(TEST_OTHER)); } /// Test when a database is empty. TEST_F(SQLiteBluetoothStorageTest, testEmptyDatabase) { m_sqLiteDb = std::unique_ptr( new alexaClientSDK::storage::sqliteStorage::SQLiteDatabase(TEST_DATABASE)); // Setup raw database. ASSERT_THAT(m_sqLiteDb, NotNull()); ASSERT_TRUE(m_sqLiteDb->initialize()); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_FALSE(m_sqLiteDb->tableExists(UUID_TABLE_NAME)); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->open()); ASSERT_TRUE(m_sqLiteDb->tableExists(UUID_TABLE_NAME)); } /// Parameterized tests to test both migrated and newly created databases. class SQLiteBluetoothStorageParameterizedTests : public SQLiteBluetoothStorageTest , public ::testing::WithParamInterface {}; INSTANTIATE_TEST_CASE_P(Parameterized, SQLiteBluetoothStorageParameterizedTests, ::testing::Values(true, false)); /// Tests the create function with an invalid root. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_createInvalidConfigurationRoot) { ASSERT_TRUE(setupDatabase(GetParam())); ConfigurationNode::uninitialize(); std::vector> empty; ConfigurationNode::initialize(empty); ASSERT_THAT(SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()), IsNull()); } /// Tests creating a database object. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_createValidConfigurationRoot) { ASSERT_TRUE(setupDatabase(GetParam())); // SQLite allows simultaneous access to the database. ASSERT_THAT(SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()), NotNull()); } /// Test creating a valid DB. This is implicitly tested in the SetUp() function, but we formally test it here. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_createDatabaseSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); closeAndDeleteDB(); m_db = SQLiteBluetoothStorage::create(ConfigurationNode::getRoot()); ASSERT_THAT(m_db, NotNull()); ASSERT_TRUE(m_db->createDatabase()); } /// Test that creating an existing DB fails. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_createExistingDatabaseFails) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_FALSE(m_db->createDatabase()); } /// Test opening an existing database. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_openExistingDatabaseSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); m_db->close(); ASSERT_TRUE(m_db->open()); } /// Test clearing the table with one row. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_clearOnOneRowSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_TRUE(m_db->clear()); std::unordered_map rows; ASSERT_TRUE(m_db->getUuidToMac(&rows)); ASSERT_THAT(rows.size(), Eq(0U)); } /// Test clearing the table with multiple rows. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_clearOnMultipleRowsSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_TRUE(m_db->insertByMac(TEST_MAC_2, TEST_UUID_2)); ASSERT_TRUE(m_db->clear()); std::unordered_map rows; ASSERT_TRUE(m_db->getUuidToMac(&rows)); ASSERT_THAT(rows.size(), Eq(0U)); } /// Test clearing the table when it's already empty. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_clearOnEmptySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->clear()); std::unordered_map rows; ASSERT_TRUE(m_db->getUuidToMac(&rows)); ASSERT_THAT(rows.size(), Eq(0U)); } /// Test getUuid with one row containing UUID. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidWithOneSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getUuid, TEST_MAC, TEST_UUID, data); } /// Test getUuid with multiple rows, one of which contains the UUID. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidWithMultipleSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getUuid, TEST_MAC, TEST_UUID, data); } /// Test getUuid with no matching UUID. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidNoMatchingFails) { ASSERT_TRUE(setupDatabase(GetParam())); std::string uuid; ASSERT_FALSE(m_db->getUuid(TEST_MAC, &uuid)); } /// Test getMac with one row containing MAC. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacWithOneSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getMac, TEST_UUID, TEST_MAC, data); } /// Test getMac with multiple rows, one of which contains the MAC. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacWithMultipleSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getMac, TEST_UUID, TEST_MAC, data); } /// Test getMac with no matching MAC. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacNoMatchingFails) { ASSERT_TRUE(setupDatabase(GetParam())); std::string mac; ASSERT_FALSE(m_db->getMac(TEST_UUID, &mac)); } /// Test getCategory with one row containing Unknown Category. TEST_P(SQLiteBluetoothStorageParameterizedTests, getCategoryWithOneSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getCategory, TEST_UUID, TEST_UNKNOWN, data); } /// Test getCategory with multiple rows, two of which contains UNKNOWN, one is updated to PHONE. TEST_P(SQLiteBluetoothStorageParameterizedTests, getCategoryWithMultipleSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getCategory, TEST_UUID, TEST_UNKNOWN, data); ASSERT_TRUE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); std::string category; ASSERT_TRUE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq(TEST_PHONE)); } /// Test getCategory with multiple rows, two of which contains UNKNOWN, one is updated to PHONE, /// verify insertByMac preserves the category. TEST_P(SQLiteBluetoothStorageParameterizedTests, getCategoryWithMultipleInsertByMacSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; getRetrieveValueHelper(&SQLiteBluetoothStorage::getCategory, TEST_UUID, TEST_UNKNOWN, data); ASSERT_TRUE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); getRetrieveValueHelper(&SQLiteBluetoothStorage::getCategory, TEST_UUID, TEST_PHONE, data); } /// Test getCategory with no matching category for given uuid. TEST_P(SQLiteBluetoothStorageParameterizedTests, getCategoryNoMatchingFails) { ASSERT_TRUE(setupDatabase(GetParam())); std::string category; ASSERT_FALSE(m_db->getCategory(TEST_UUID, &category)); } /// Test getMacToUuid with one row. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacToUuidWithOneRowSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; getRowsHelper(&SQLiteBluetoothStorage::getMacToUuid, data, data); } /// Test getMacToUuid with multiple expected. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacToUuidWithMultipleRowsSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; getRowsHelper(&SQLiteBluetoothStorage::getMacToUuid, data, data); } /// Test getMacToUuid when empty. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getMacToUuidWithEmptySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); std::unordered_map data; getRowsHelper(&SQLiteBluetoothStorage::getMacToUuid, data, data); } /// Test getUuidToMac with one row. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidToMacWithOneRowSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; const std::unordered_map expected{{TEST_UUID, TEST_MAC}}; getRowsHelper(&SQLiteBluetoothStorage::getUuidToMac, data, expected); } /// Test getUuidToMac with multiple expected. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidToMacWithMultipleRowsSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; const std::unordered_map expected{{TEST_UUID, TEST_MAC}, {TEST_UUID_2, TEST_MAC_2}}; getRowsHelper(&SQLiteBluetoothStorage::getUuidToMac, data, expected); } /// Test getUuidToMac when empty. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getUuidToMacWithEmptySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); std::unordered_map data; getRowsHelper(&SQLiteBluetoothStorage::getUuidToMac, data, data); } /// Test getUuidToCategory with one row. TEST_P(SQLiteBluetoothStorageParameterizedTests, getUuidToCategoryWithOneRowSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; const std::unordered_map expected{{TEST_UUID, TEST_UNKNOWN}}; getRowsHelper(&SQLiteBluetoothStorage::getUuidToCategory, data, expected); } /// Test getUuidToCategory with one row, updated category to PHONE. TEST_P(SQLiteBluetoothStorageParameterizedTests, getUuidToCategoryWithOneRowUpdateCategorySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; const std::unordered_map expected{{TEST_UUID, TEST_UNKNOWN}}; const std::unordered_map expectedUpdate{{TEST_UUID, TEST_PHONE}}; getRowsHelper(&SQLiteBluetoothStorage::getUuidToCategory, data, expected); ASSERT_TRUE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); getRowsHelper(&SQLiteBluetoothStorage::getUuidToCategory, data, expectedUpdate); } /// Test getUuidToCategory with multiple expected. TEST_P(SQLiteBluetoothStorageParameterizedTests, getUuidToCategoryWithMultipleRowsSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; const std::unordered_map expected{{TEST_UUID, TEST_UNKNOWN}, {TEST_UUID_2, TEST_UNKNOWN}}; getRowsHelper(&SQLiteBluetoothStorage::getUuidToCategory, data, expected); } /// Test getUuidToCategory when empty. TEST_P(SQLiteBluetoothStorageParameterizedTests, getUuidToCategoryWithEmptySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); std::unordered_map data; getRowsHelper(&SQLiteBluetoothStorage::getUuidToCategory, data, data); } /// Test getMacToCategory with one row. TEST_P(SQLiteBluetoothStorageParameterizedTests, getMacToCategoryWithOneRowSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; const std::unordered_map expected{{TEST_MAC, TEST_UNKNOWN}}; getRowsHelper(&SQLiteBluetoothStorage::getMacToCategory, data, expected); } /// Test getMacToCategory with one row, updated category to PHONE. TEST_P(SQLiteBluetoothStorageParameterizedTests, getMacToCategoryWithOneRowUpdateCategorySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}}; const std::unordered_map expected{{TEST_MAC, TEST_UNKNOWN}}; const std::unordered_map expectedUpdate{{TEST_MAC, TEST_PHONE}}; getRowsHelper(&SQLiteBluetoothStorage::getMacToCategory, data, expected); ASSERT_TRUE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); getRowsHelper(&SQLiteBluetoothStorage::getMacToCategory, data, expectedUpdate); } /// Test getMacToCategory with multiple expected. TEST_P(SQLiteBluetoothStorageParameterizedTests, getMacToCategoryWithMultipleRowsSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map data{{TEST_MAC, TEST_UUID}, {TEST_MAC_2, TEST_UUID_2}}; const std::unordered_map expected{{TEST_MAC, TEST_UNKNOWN}, {TEST_MAC_2, TEST_UNKNOWN}}; getRowsHelper(&SQLiteBluetoothStorage::getMacToCategory, data, expected); } /// Test getMacToCategory when empty. TEST_P(SQLiteBluetoothStorageParameterizedTests, getMacToCategoryWithEmptySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); std::unordered_map data; getRowsHelper(&SQLiteBluetoothStorage::getMacToCategory, data, data); } /// Test getOrderedMac and retrieve the macs in ascending insertion order (oldest first). TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getOrderedMacAscending) { ASSERT_TRUE(setupDatabase(GetParam())); getOrderedMacHelper(true); } /// Test getOrderedMac and retrieve the macs in descending insertion order (newest first). TEST_P(SQLiteBluetoothStorageParameterizedTests, test_getOrderedMacDescending) { ASSERT_TRUE(setupDatabase(GetParam())); getOrderedMacHelper(false); } /// Test updateByCategory succeeds. TEST_P(SQLiteBluetoothStorageParameterizedTests, updateByCategorySucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_TRUE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); std::string category; ASSERT_TRUE(m_db->getCategory(TEST_UUID, &category)); ASSERT_THAT(category, Eq(TEST_PHONE)); } /// Test updateByCategory with no matching uuid. TEST_P(SQLiteBluetoothStorageParameterizedTests, updateByCategoryNoMatchingFails) { ASSERT_TRUE(setupDatabase(GetParam())); std::string category; ASSERT_FALSE(m_db->updateByCategory(TEST_UUID, TEST_PHONE)); } /// Test insertByMac succeeds. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_insertByMacSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map expected{{TEST_MAC, TEST_UUID}}; ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); std::unordered_map rows; ASSERT_TRUE(m_db->getMacToUuid(&rows)); ASSERT_THAT(rows, Eq(expected)); } /// Test insertByMac existing fails. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_insertByMacDuplicateFails) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_FALSE(m_db->insertByMac(TEST_MAC, TEST_UUID, false)); } /// Test insertByMac with overwrite succeeds. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_insertByMacOverwriteSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); const std::unordered_map expected{{TEST_MAC, TEST_UUID}}; ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID_2)); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); std::unordered_map rows; ASSERT_TRUE(m_db->getMacToUuid(&rows)); ASSERT_THAT(rows, Eq(expected)); } /// Test remove succeeds. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_removeExistingSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->insertByMac(TEST_MAC, TEST_UUID)); ASSERT_TRUE(m_db->remove(TEST_MAC)); std::unordered_map rows; ASSERT_TRUE(m_db->getMacToUuid(&rows)); ASSERT_THAT(rows.size(), Eq(0U)); } /// Test remove on non-existing record succeeds. TEST_P(SQLiteBluetoothStorageParameterizedTests, test_removeNonExistingSucceeds) { ASSERT_TRUE(setupDatabase(GetParam())); ASSERT_TRUE(m_db->remove(TEST_MAC)); std::unordered_map rows; ASSERT_TRUE(m_db->getMacToUuid(&rows)); ASSERT_THAT(rows.size(), Eq(0U)); } } // namespace test } // namespace acsdkBluetooth } // namespace alexaClientSDK