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, dbLengthZero) 67 { 68 struct pldm_instance_db* db = nullptr; 69 70 std::filesystem::resize_file(dbPath, 0); 71 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), -EINVAL); 72 } 73 74 TEST_F(PldmInstanceDbTest, dbLengthShort) 75 { 76 struct pldm_instance_db* db = nullptr; 77 78 std::filesystem::resize_file(dbPath, 79 PLDM_MAX_TIDS * pldmMaxInstanceIds - 1); 80 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), -EINVAL); 81 } 82 83 TEST_F(PldmInstanceDbTest, dbInstance) 84 { 85 struct pldm_instance_db* db = nullptr; 86 87 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 88 EXPECT_EQ(pldm_instance_db_destroy(db), 0); 89 } 90 91 TEST_F(PldmInstanceDbTest, allocFreeOne) 92 { 93 struct pldm_instance_db* db = nullptr; 94 const pldm_tid_t tid = 1; 95 pldm_instance_id_t iid; 96 97 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 98 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); 99 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); 100 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 101 } 102 103 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialSameTid) 104 { 105 static constexpr pldm_tid_t tid = 1; 106 107 struct pldm_instance_db* db = nullptr; 108 pldm_instance_id_t first; 109 pldm_instance_id_t second; 110 111 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 112 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &first), 0); 113 EXPECT_EQ(pldm_instance_id_free(db, tid, first), 0); 114 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &second), 0); 115 EXPECT_EQ(pldm_instance_id_free(db, tid, second), 0); 116 EXPECT_NE(first, second); 117 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 118 } 119 120 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialDifferentTid) 121 { 122 struct 123 { 124 pldm_tid_t tid; 125 pldm_instance_id_t iid; 126 } instances[] = { 127 {1, 0}, 128 {2, 0}, 129 }; 130 131 struct pldm_instance_db* db = nullptr; 132 133 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 134 135 EXPECT_EQ(pldm_instance_id_alloc(db, instances[0].tid, &instances[0].iid), 136 0); 137 EXPECT_EQ(pldm_instance_id_alloc(db, instances[1].tid, &instances[1].iid), 138 0); 139 140 EXPECT_EQ(instances[0].iid, instances[1].iid); 141 142 EXPECT_EQ(pldm_instance_id_free(db, instances[1].tid, instances[1].iid), 0); 143 EXPECT_EQ(pldm_instance_id_free(db, instances[0].tid, instances[0].iid), 0); 144 145 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 146 } 147 148 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentSameTid) 149 { 150 static constexpr pldm_tid_t tid = 1; 151 152 struct 153 { 154 struct pldm_instance_db* db; 155 pldm_instance_id_t iid; 156 } connections[] = { 157 {nullptr, 0}, 158 {nullptr, 0}, 159 }; 160 161 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); 162 EXPECT_EQ( 163 pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0); 164 165 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); 166 EXPECT_EQ( 167 pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0); 168 169 EXPECT_NE(connections[0].iid, connections[1].iid); 170 171 EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid), 172 0); 173 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); 174 175 EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid), 176 0); 177 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); 178 } 179 180 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentDifferentTid) 181 { 182 struct 183 { 184 struct pldm_instance_db* db; 185 pldm_tid_t tid; 186 pldm_instance_id_t iid; 187 } connections[] = { 188 {nullptr, 1, 0}, 189 {nullptr, 2, 0}, 190 }; 191 192 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0); 193 EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, connections[0].tid, 194 &connections[0].iid), 195 0); 196 197 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0); 198 EXPECT_EQ(pldm_instance_id_alloc(connections[1].db, connections[1].tid, 199 &connections[1].iid), 200 0); 201 202 EXPECT_EQ(connections[0].iid, connections[1].iid); 203 204 EXPECT_EQ(pldm_instance_id_free(connections[1].db, connections[1].tid, 205 connections[1].iid), 206 0); 207 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0); 208 209 EXPECT_EQ(pldm_instance_id_free(connections[0].db, connections[0].tid, 210 connections[0].iid), 211 0); 212 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0); 213 } 214 215 TEST_F(PldmInstanceDbTest, allocAllInstanceIds) 216 { 217 static constexpr pldm_tid_t tid = 1; 218 219 struct pldm_instance_db* db = nullptr; 220 std::array<pldm_instance_id_t, pldmMaxInstanceIds> iids = {}; 221 pldm_instance_id_t extra; 222 223 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 224 225 for (auto& iid : iids) 226 { 227 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0); 228 } 229 230 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN); 231 232 for (auto& iid : iids) 233 { 234 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0); 235 } 236 237 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0); 238 239 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 240 } 241 242 TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId) 243 { 244 struct pldm_instance_db* db = nullptr; 245 const pldm_tid_t tid = 1; 246 247 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0); 248 EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0); 249 ASSERT_EQ(pldm_instance_db_destroy(db), 0); 250 } 251