blob: ed94c59d4b96dd0da1432eeeb9297f9fe17bca30 [file] [log] [blame]
Andrew Jefferyefb40062023-11-10 13:48:39 +10301#include <libpldm/base.h>
2#include <libpldm/instance-id.h>
Andrew Jefferyb27cebf2023-04-24 11:17:05 +09303
4#include <cerrno>
5#include <cstdlib>
6#include <cstring>
7#include <filesystem>
8
Andrew Jefferyb27cebf2023-04-24 11:17:05 +09309#include <gtest/gtest.h>
10
11static constexpr auto pldmMaxInstanceIds = 32;
12static const std::filesystem::path nonexistentDb = {"remove-this-file"};
13
14TEST(InstanceId, dbInstanceNullDb)
15{
16 ASSERT_FALSE(std::filesystem::exists(nonexistentDb));
17 EXPECT_EQ(::pldm_instance_db_init(nullptr, nonexistentDb.c_str()), -EINVAL);
18}
19
20TEST(InstanceId, dbInstanceNonNullDerefDb)
21{
22 struct pldm_instance_db* db = (struct pldm_instance_db*)8;
23
24 ASSERT_FALSE(std::filesystem::exists(nonexistentDb));
25 EXPECT_EQ(::pldm_instance_db_init(&db, nonexistentDb.c_str()), -EINVAL);
26}
27
28TEST(InstanceId, dbInstanceInvalidPath)
29{
30 struct pldm_instance_db* db = nullptr;
31
32 EXPECT_NE(::pldm_instance_db_init(&db, ""), 0);
33}
34
35class PldmInstanceDbTest : public ::testing::Test
36{
37 protected:
38 void SetUp() override
39 {
40 static const char dbTmpl[] = "db.XXXXXX";
41 char dbName[sizeof(dbTmpl)] = {};
Andrew Jefferyb27cebf2023-04-24 11:17:05 +093042
43 ::strncpy(dbName, dbTmpl, sizeof(dbName));
44 fd = ::mkstemp(dbName);
45 ASSERT_NE(fd, -1);
46
47 dbPath = std::filesystem::path(dbName);
48 std::filesystem::resize_file(
49 dbPath, (uintmax_t)(PLDM_MAX_TIDS)*pldmMaxInstanceIds);
50 }
51
52 void TearDown() override
53 {
54 std::filesystem::remove(dbPath);
55 ::close(fd);
56 }
57
58 std::filesystem::path dbPath;
59
60 private:
61 int fd;
62};
63
Andrew Jefferya6f0cf32023-04-24 11:40:43 +093064TEST_F(PldmInstanceDbTest, dbLengthZero)
65{
66 struct pldm_instance_db* db = nullptr;
67
68 std::filesystem::resize_file(dbPath, 0);
69 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), -EINVAL);
70}
71
72TEST_F(PldmInstanceDbTest, dbLengthShort)
73{
74 struct pldm_instance_db* db = nullptr;
75
76 std::filesystem::resize_file(dbPath,
77 PLDM_MAX_TIDS * pldmMaxInstanceIds - 1);
78 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), -EINVAL);
79}
80
Andrew Jefferyb27cebf2023-04-24 11:17:05 +093081TEST_F(PldmInstanceDbTest, dbInstance)
82{
83 struct pldm_instance_db* db = nullptr;
84
85 EXPECT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
86 EXPECT_EQ(pldm_instance_db_destroy(db), 0);
87}
88
Manojkiran Eda6c7ee4f2025-03-18 09:56:39 +053089TEST_F(PldmInstanceDbTest, allocOnNulldb)
90{
91 struct pldm_instance_db* db = nullptr;
92 const pldm_tid_t tid = 1;
93 pldm_instance_id_t iid;
94 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), -EINVAL);
95}
96
Andrew Jefferyb27cebf2023-04-24 11:17:05 +093097TEST_F(PldmInstanceDbTest, allocFreeOne)
98{
99 struct pldm_instance_db* db = nullptr;
100 const pldm_tid_t tid = 1;
101 pldm_instance_id_t iid;
102
103 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
104 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0);
105 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0);
106 ASSERT_EQ(pldm_instance_db_destroy(db), 0);
107}
108
109TEST_F(PldmInstanceDbTest, allocFreeTwoSerialSameTid)
110{
111 static constexpr pldm_tid_t tid = 1;
112
113 struct pldm_instance_db* db = nullptr;
114 pldm_instance_id_t first;
115 pldm_instance_id_t second;
116
117 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
118 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &first), 0);
119 EXPECT_EQ(pldm_instance_id_free(db, tid, first), 0);
120 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &second), 0);
121 EXPECT_EQ(pldm_instance_id_free(db, tid, second), 0);
122 EXPECT_NE(first, second);
123 ASSERT_EQ(pldm_instance_db_destroy(db), 0);
124}
125
126TEST_F(PldmInstanceDbTest, allocFreeTwoSerialDifferentTid)
127{
128 struct
129 {
130 pldm_tid_t tid;
131 pldm_instance_id_t iid;
132 } instances[] = {
133 {1, 0},
134 {2, 0},
135 };
136
137 struct pldm_instance_db* db = nullptr;
138
139 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
140
141 EXPECT_EQ(pldm_instance_id_alloc(db, instances[0].tid, &instances[0].iid),
142 0);
143 EXPECT_EQ(pldm_instance_id_alloc(db, instances[1].tid, &instances[1].iid),
144 0);
145
146 EXPECT_EQ(instances[0].iid, instances[1].iid);
147
148 EXPECT_EQ(pldm_instance_id_free(db, instances[1].tid, instances[1].iid), 0);
149 EXPECT_EQ(pldm_instance_id_free(db, instances[0].tid, instances[0].iid), 0);
150
151 ASSERT_EQ(pldm_instance_db_destroy(db), 0);
152}
153
154TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentSameTid)
155{
156 static constexpr pldm_tid_t tid = 1;
157
158 struct
159 {
160 struct pldm_instance_db* db;
161 pldm_instance_id_t iid;
162 } connections[] = {
163 {nullptr, 0},
164 {nullptr, 0},
165 };
166
167 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0);
168 EXPECT_EQ(
169 pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0);
170
171 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0);
172 EXPECT_EQ(
173 pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0);
174
175 EXPECT_NE(connections[0].iid, connections[1].iid);
176
177 EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid),
178 0);
179 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0);
180
181 EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid),
182 0);
183 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
184}
185
186TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentDifferentTid)
187{
188 struct
189 {
190 struct pldm_instance_db* db;
191 pldm_tid_t tid;
192 pldm_instance_id_t iid;
193 } connections[] = {
194 {nullptr, 1, 0},
195 {nullptr, 2, 0},
196 };
197
198 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0);
199 EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, connections[0].tid,
200 &connections[0].iid),
201 0);
202
203 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0);
204 EXPECT_EQ(pldm_instance_id_alloc(connections[1].db, connections[1].tid,
205 &connections[1].iid),
206 0);
207
208 EXPECT_EQ(connections[0].iid, connections[1].iid);
209
210 EXPECT_EQ(pldm_instance_id_free(connections[1].db, connections[1].tid,
211 connections[1].iid),
212 0);
213 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0);
214
215 EXPECT_EQ(pldm_instance_id_free(connections[0].db, connections[0].tid,
216 connections[0].iid),
217 0);
218 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
219}
Andrew Jeffery0aea7072023-04-24 11:16:35 +0930220
221TEST_F(PldmInstanceDbTest, allocAllInstanceIds)
222{
223 static constexpr pldm_tid_t tid = 1;
224
225 struct pldm_instance_db* db = nullptr;
226 std::array<pldm_instance_id_t, pldmMaxInstanceIds> iids = {};
227 pldm_instance_id_t extra;
228
229 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
230
231 for (auto& iid : iids)
232 {
233 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0);
234 }
235
236 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN);
237
238 for (auto& iid : iids)
239 {
240 EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0);
241 }
242
243 EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0);
244
245 ASSERT_EQ(pldm_instance_db_destroy(db), 0);
246}
247
Andrew Jefferye4240672024-06-28 14:52:55 +0930248TEST_F(PldmInstanceDbTest, releaseConflictedSameTid)
249{
250 static constexpr pldm_tid_t tid = 1;
251 struct
252 {
253 struct pldm_instance_db* db;
254 pldm_instance_id_t iid;
255 } connections[] = {
256 {nullptr, 0},
257 {nullptr, 0},
258 };
259 pldm_instance_id_t iid;
260
261 /* Allocate IID 0 for the TID to the first connection */
262 ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0);
263 EXPECT_EQ(
264 pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0);
265
266 /*
267 * On the second connection, allocate the first available IID for the TID.
268 * This should generate a conflict on IID 0 (allocated to the first
269 * connection), and result in IID 1 being provided.
270 *
271 * There should now be one read lock held on each of IID 0 and IID 1 for TID
272 * 1 (by the first and second connections respectively).
273 */
274 ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0);
275 EXPECT_EQ(
276 pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0);
277
278 /*
279 * Make sure the implementation hasn't allocated the connections a
280 * conflicting IID for the TID.
281 */
282 EXPECT_NE(connections[0].iid, connections[1].iid);
283
284 /*
285 * Now free the IID allocated to the first connection.
286 *
287 * We should be able to re-acquire this later.
288 */
289 EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid),
290 0);
291
292 /*
293 * Iterate through the IID space on the first connection to wrap it back
294 * around to IID 0.
295 *
296 * Note that:
297 *
298 * 1. The first connection has already allocated (and released) IID 0,
299 * eliminating one iteration
300 *
301 * 2. IID 1 is held by the second connection. This eliminates a second
302 * iteration as it must be skipped to avoid a conflict.
303 */
304 for (int i = 0; i < (pldmMaxInstanceIds - 1 - 1); i++)
305 {
306 EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, tid, &iid), 0);
307 EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, iid), 0);
308 }
309
310 /*
311 * The next IID allocated to the first connection should be the IID it
312 * allocated initially (which should be 0).
313 */
314 EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, tid, &iid), 0);
315 EXPECT_EQ(iid, connections[0].iid);
316
317 /* Now tidy up */
318 ASSERT_EQ(pldm_instance_id_free(connections[0].db, tid, iid), 0);
319
320 EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid),
321 0);
322 ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0);
323 ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
324}
325
Andrew Jeffery0aea7072023-04-24 11:16:35 +0930326TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId)
327{
328 struct pldm_instance_db* db = nullptr;
329 const pldm_tid_t tid = 1;
330
331 ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
332 EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0);
333 ASSERT_EQ(pldm_instance_db_destroy(db), 0);
334}