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