#include "libpldm/instance-id.h" #include #include #include #include #include "libpldm/base.h" #include static constexpr auto pldmMaxInstanceIds = 32; static const std::filesystem::path nonexistentDb = {"remove-this-file"}; TEST(InstanceId, dbInstanceNullDb) { ASSERT_FALSE(std::filesystem::exists(nonexistentDb)); EXPECT_EQ(::pldm_instance_db_init(nullptr, nonexistentDb.c_str()), -EINVAL); } TEST(InstanceId, dbInstanceNonNullDerefDb) { struct pldm_instance_db* db = (struct pldm_instance_db*)8; ASSERT_FALSE(std::filesystem::exists(nonexistentDb)); EXPECT_EQ(::pldm_instance_db_init(&db, nonexistentDb.c_str()), -EINVAL); } TEST(InstanceId, dbInstanceInvalidPath) { struct pldm_instance_db* db = nullptr; EXPECT_NE(::pldm_instance_db_init(&db, ""), 0); } class PldmInstanceDbTest : public ::testing::Test { protected: void SetUp() override { static const char dbTmpl[] = "db.XXXXXX"; char dbName[sizeof(dbTmpl)] = {}; int fd; ::strncpy(dbName, dbTmpl, sizeof(dbName)); fd = ::mkstemp(dbName); ASSERT_NE(fd, -1); dbPath = std::filesystem::path(dbName); std::filesystem::resize_file( dbPath, (uintmax_t)(PLDM_MAX_TIDS)*pldmMaxInstanceIds); } void TearDown() override { std::filesystem::remove(dbPath); ::close(fd); } std::filesystem::path dbPath; private: int fd; }; TEST_F(PldmInstanceDbTest, dbInstance) { struct pldm_instance_db* db = nullptr; EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_db_destroy(db), 0); } TEST_F(PldmInstanceDbTest, allocFreeOne) { struct pldm_instance_db* db = nullptr; const pldm_tid_t tid = 1; pldm_instance_id_t iid; ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); ASSERT_EQ(pldm_instance_db_destroy(db), 0); } TEST_F(PldmInstanceDbTest, allocFreeTwoSerialSameTid) { static constexpr pldm_tid_t tid = 1; struct pldm_instance_db* db = nullptr; pldm_instance_id_t first; pldm_instance_id_t second; ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_id_alloc(db, tid, &first), 0); EXPECT_EQ(pldm_instance_id_free(db, tid, first), 0); EXPECT_EQ(pldm_instance_id_alloc(db, tid, &second), 0); EXPECT_EQ(pldm_instance_id_free(db, tid, second), 0); EXPECT_NE(first, second); ASSERT_EQ(pldm_instance_db_destroy(db), 0); } TEST_F(PldmInstanceDbTest, allocFreeTwoSerialDifferentTid) { struct { pldm_tid_t tid; pldm_instance_id_t iid; } instances[] = { {1, 0}, {2, 0}, }; struct pldm_instance_db* db = nullptr; ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_id_alloc(db, instances[0].tid, &instances[0].iid), 0); EXPECT_EQ(pldm_instance_id_alloc(db, instances[1].tid, &instances[1].iid), 0); EXPECT_EQ(instances[0].iid, instances[1].iid); EXPECT_EQ(pldm_instance_id_free(db, instances[1].tid, instances[1].iid), 0); EXPECT_EQ(pldm_instance_id_free(db, instances[0].tid, instances[0].iid), 0); ASSERT_EQ(pldm_instance_db_destroy(db), 0); } TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentSameTid) { static constexpr pldm_tid_t tid = 1; struct { struct pldm_instance_db* db; pldm_instance_id_t iid; } connections[] = { {nullptr, 0}, {nullptr, 0}, }; ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); EXPECT_EQ( pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0); ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); EXPECT_EQ( pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0); EXPECT_NE(connections[0].iid, connections[1].iid); EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid), 0); ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid), 0); ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); } TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentDifferentTid) { struct { struct pldm_instance_db* db; pldm_tid_t tid; pldm_instance_id_t iid; } connections[] = { {nullptr, 1, 0}, {nullptr, 2, 0}, }; ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, connections[0].tid, &connections[0].iid), 0); ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); EXPECT_EQ(pldm_instance_id_alloc(connections[1].db, connections[1].tid, &connections[1].iid), 0); EXPECT_EQ(connections[0].iid, connections[1].iid); EXPECT_EQ(pldm_instance_id_free(connections[1].db, connections[1].tid, connections[1].iid), 0); ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); EXPECT_EQ(pldm_instance_id_free(connections[0].db, connections[0].tid, connections[0].iid), 0); ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); } TEST_F(PldmInstanceDbTest, allocAllInstanceIds) { static constexpr pldm_tid_t tid = 1; struct pldm_instance_db* db = nullptr; std::array iids = {}; pldm_instance_id_t extra; ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); for (auto& iid : iids) { EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); } EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN); for (auto& iid : iids) { EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); } EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0); ASSERT_EQ(pldm_instance_db_destroy(db), 0); } TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId) { struct pldm_instance_db* db = nullptr; const pldm_tid_t tid = 1; ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0); ASSERT_EQ(pldm_instance_db_destroy(db), 0); }