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