1 #include "libpldm/instance-id.h" 2 3 #include <cerrno> 4 #include <cstdlib> 5 #include <cstring> 6 #include <filesystem> 7 8 #include "libpldm/base.h" 9 10 #include <gtest/gtest.h> 11 12 static constexpr auto pldmMaxInstanceIds = 32; 13 static const std::filesystem::path nonexistentDb = {"remove-this-file"}; 14 15 TEST(InstanceId, dbInstanceNullDb) 16 { 17 ASSERT_FALSE(std::filesystem::exists(nonexistentDb)); 18 EXPECT_EQ(::pldm_instance_db_init(nullptr, nonexistentDb.c_str()), -EINVAL); 19 } 20 21 TEST(InstanceId, dbInstanceNonNullDerefDb) 22 { 23 struct pldm_instance_db* db = (struct pldm_instance_db*)8; 24 25 ASSERT_FALSE(std::filesystem::exists(nonexistentDb)); 26 EXPECT_EQ(::pldm_instance_db_init(&db, nonexistentDb.c_str()), -EINVAL); 27 } 28 29 TEST(InstanceId, dbInstanceInvalidPath) 30 { 31 struct pldm_instance_db* db = nullptr; 32 33 EXPECT_NE(::pldm_instance_db_init(&db, ""), 0); 34 } 35 36 class PldmInstanceDbTest : public ::testing::Test 37 { 38 protected: 39 void SetUp() override 40 { 41 static const char dbTmpl[] = "db.XXXXXX"; 42 char dbName[sizeof(dbTmpl)] = {}; 43 int fd; 44 45 ::strncpy(dbName, dbTmpl, sizeof(dbName)); 46 fd = ::mkstemp(dbName); 47 ASSERT_NE(fd, -1); 48 49 dbPath = std::filesystem::path(dbName); 50 std::filesystem::resize_file( 51 dbPath, (uintmax_t)(PLDM_MAX_TIDS)*pldmMaxInstanceIds); 52 } 53 54 void TearDown() override 55 { 56 std::filesystem::remove(dbPath); 57 ::close(fd); 58 } 59 60 std::filesystem::path dbPath; 61 62 private: 63 int fd; 64 }; 65 66 TEST_F(PldmInstanceDbTest, dbInstance) 67 { 68 struct pldm_instance_db* db = nullptr; 69 70 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 71 EXPECT_EQ(pldm_instance_db_destroy(db), 0); 72 } 73 74 TEST_F(PldmInstanceDbTest, allocFreeOne) 75 { 76 struct pldm_instance_db* db = nullptr; 77 const pldm_tid_t tid = 1; 78 pldm_instance_id_t iid; 79 80 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 81 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); 82 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); 83 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 84 } 85 86 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialSameTid) 87 { 88 static constexpr pldm_tid_t tid = 1; 89 90 struct pldm_instance_db* db = nullptr; 91 pldm_instance_id_t first; 92 pldm_instance_id_t second; 93 94 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 95 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &first), 0); 96 EXPECT_EQ(pldm_instance_id_free(db, tid, first), 0); 97 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &second), 0); 98 EXPECT_EQ(pldm_instance_id_free(db, tid, second), 0); 99 EXPECT_NE(first, second); 100 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 101 } 102 103 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialDifferentTid) 104 { 105 struct 106 { 107 pldm_tid_t tid; 108 pldm_instance_id_t iid; 109 } instances[] = { 110 {1, 0}, 111 {2, 0}, 112 }; 113 114 struct pldm_instance_db* db = nullptr; 115 116 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 117 118 EXPECT_EQ(pldm_instance_id_alloc(db, instances[0].tid, &instances[0].iid), 119 0); 120 EXPECT_EQ(pldm_instance_id_alloc(db, instances[1].tid, &instances[1].iid), 121 0); 122 123 EXPECT_EQ(instances[0].iid, instances[1].iid); 124 125 EXPECT_EQ(pldm_instance_id_free(db, instances[1].tid, instances[1].iid), 0); 126 EXPECT_EQ(pldm_instance_id_free(db, instances[0].tid, instances[0].iid), 0); 127 128 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 129 } 130 131 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentSameTid) 132 { 133 static constexpr pldm_tid_t tid = 1; 134 135 struct 136 { 137 struct pldm_instance_db* db; 138 pldm_instance_id_t iid; 139 } connections[] = { 140 {nullptr, 0}, 141 {nullptr, 0}, 142 }; 143 144 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); 145 EXPECT_EQ( 146 pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0); 147 148 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); 149 EXPECT_EQ( 150 pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0); 151 152 EXPECT_NE(connections[0].iid, connections[1].iid); 153 154 EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid), 155 0); 156 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); 157 158 EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid), 159 0); 160 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); 161 } 162 163 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentDifferentTid) 164 { 165 struct 166 { 167 struct pldm_instance_db* db; 168 pldm_tid_t tid; 169 pldm_instance_id_t iid; 170 } connections[] = { 171 {nullptr, 1, 0}, 172 {nullptr, 2, 0}, 173 }; 174 175 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); 176 EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, connections[0].tid, 177 &connections[0].iid), 178 0); 179 180 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); 181 EXPECT_EQ(pldm_instance_id_alloc(connections[1].db, connections[1].tid, 182 &connections[1].iid), 183 0); 184 185 EXPECT_EQ(connections[0].iid, connections[1].iid); 186 187 EXPECT_EQ(pldm_instance_id_free(connections[1].db, connections[1].tid, 188 connections[1].iid), 189 0); 190 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); 191 192 EXPECT_EQ(pldm_instance_id_free(connections[0].db, connections[0].tid, 193 connections[0].iid), 194 0); 195 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); 196 } 197 198 TEST_F(PldmInstanceDbTest, allocAllInstanceIds) 199 { 200 static constexpr pldm_tid_t tid = 1; 201 202 struct pldm_instance_db* db = nullptr; 203 std::array<pldm_instance_id_t, pldmMaxInstanceIds> iids = {}; 204 pldm_instance_id_t extra; 205 206 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 207 208 for (auto& iid : iids) 209 { 210 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); 211 } 212 213 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN); 214 215 for (auto& iid : iids) 216 { 217 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); 218 } 219 220 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0); 221 222 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 223 } 224 225 TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId) 226 { 227 struct pldm_instance_db* db = nullptr; 228 const pldm_tid_t tid = 1; 229 230 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 231 EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0); 232 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 233 } 234