xref: /openbmc/libpldm/tests/instance-id.cpp (revision a6f0cf3e)
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