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