xref: /openbmc/libpldm/tests/instance-id.cpp (revision efb40069)
1 #include <libpldm/base.h>
2 #include <libpldm/instance-id.h>
3 
4 #include <cerrno>
5 #include <cstdlib>
6 #include <cstring>
7 #include <filesystem>
8 
9 #include <gtest/gtest.h>
10 
11 static constexpr auto pldmMaxInstanceIds = 32;
12 static const std::filesystem::path nonexistentDb = {"remove-this-file"};
13 
14 TEST(InstanceId, dbInstanceNullDb)
15 {
16     ASSERT_FALSE(std::filesystem::exists(nonexistentDb));
17     EXPECT_EQ(::pldm_instance_db_init(nullptr, nonexistentDb.c_str()), -EINVAL);
18 }
19 
20 TEST(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 
28 TEST(InstanceId, dbInstanceInvalidPath)
29 {
30     struct pldm_instance_db* db = nullptr;
31 
32     EXPECT_NE(::pldm_instance_db_init(&db, ""), 0);
33 }
34 
35 class PldmInstanceDbTest : public ::testing::Test
36 {
37   protected:
38     void SetUp() override
39     {
40         static const char dbTmpl[] = "db.XXXXXX";
41         char dbName[sizeof(dbTmpl)] = {};
42 
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 
64 TEST_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 
72 TEST_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 
81 TEST_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 
89 TEST_F(PldmInstanceDbTest, allocFreeOne)
90 {
91     struct pldm_instance_db* db = nullptr;
92     const pldm_tid_t tid = 1;
93     pldm_instance_id_t iid;
94 
95     ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
96     EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0);
97     EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0);
98     ASSERT_EQ(pldm_instance_db_destroy(db), 0);
99 }
100 
101 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialSameTid)
102 {
103     static constexpr pldm_tid_t tid = 1;
104 
105     struct pldm_instance_db* db = nullptr;
106     pldm_instance_id_t first;
107     pldm_instance_id_t second;
108 
109     ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
110     EXPECT_EQ(pldm_instance_id_alloc(db, tid, &first), 0);
111     EXPECT_EQ(pldm_instance_id_free(db, tid, first), 0);
112     EXPECT_EQ(pldm_instance_id_alloc(db, tid, &second), 0);
113     EXPECT_EQ(pldm_instance_id_free(db, tid, second), 0);
114     EXPECT_NE(first, second);
115     ASSERT_EQ(pldm_instance_db_destroy(db), 0);
116 }
117 
118 TEST_F(PldmInstanceDbTest, allocFreeTwoSerialDifferentTid)
119 {
120     struct
121     {
122         pldm_tid_t tid;
123         pldm_instance_id_t iid;
124     } instances[] = {
125         {1, 0},
126         {2, 0},
127     };
128 
129     struct pldm_instance_db* db = nullptr;
130 
131     ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
132 
133     EXPECT_EQ(pldm_instance_id_alloc(db, instances[0].tid, &instances[0].iid),
134               0);
135     EXPECT_EQ(pldm_instance_id_alloc(db, instances[1].tid, &instances[1].iid),
136               0);
137 
138     EXPECT_EQ(instances[0].iid, instances[1].iid);
139 
140     EXPECT_EQ(pldm_instance_id_free(db, instances[1].tid, instances[1].iid), 0);
141     EXPECT_EQ(pldm_instance_id_free(db, instances[0].tid, instances[0].iid), 0);
142 
143     ASSERT_EQ(pldm_instance_db_destroy(db), 0);
144 }
145 
146 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentSameTid)
147 {
148     static constexpr pldm_tid_t tid = 1;
149 
150     struct
151     {
152         struct pldm_instance_db* db;
153         pldm_instance_id_t iid;
154     } connections[] = {
155         {nullptr, 0},
156         {nullptr, 0},
157     };
158 
159     ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0);
160     EXPECT_EQ(
161         pldm_instance_id_alloc(connections[0].db, tid, &connections[0].iid), 0);
162 
163     ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0);
164     EXPECT_EQ(
165         pldm_instance_id_alloc(connections[1].db, tid, &connections[1].iid), 0);
166 
167     EXPECT_NE(connections[0].iid, connections[1].iid);
168 
169     EXPECT_EQ(pldm_instance_id_free(connections[1].db, tid, connections[1].iid),
170               0);
171     ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0);
172 
173     EXPECT_EQ(pldm_instance_id_free(connections[0].db, tid, connections[0].iid),
174               0);
175     ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
176 }
177 
178 TEST_F(PldmInstanceDbTest, allocFreeTwoConcurrentDifferentTid)
179 {
180     struct
181     {
182         struct pldm_instance_db* db;
183         pldm_tid_t tid;
184         pldm_instance_id_t iid;
185     } connections[] = {
186         {nullptr, 1, 0},
187         {nullptr, 2, 0},
188     };
189 
190     ASSERT_EQ(pldm_instance_db_init(&connections[0].db, dbPath.c_str()), 0);
191     EXPECT_EQ(pldm_instance_id_alloc(connections[0].db, connections[0].tid,
192                                      &connections[0].iid),
193               0);
194 
195     ASSERT_EQ(pldm_instance_db_init(&connections[1].db, dbPath.c_str()), 0);
196     EXPECT_EQ(pldm_instance_id_alloc(connections[1].db, connections[1].tid,
197                                      &connections[1].iid),
198               0);
199 
200     EXPECT_EQ(connections[0].iid, connections[1].iid);
201 
202     EXPECT_EQ(pldm_instance_id_free(connections[1].db, connections[1].tid,
203                                     connections[1].iid),
204               0);
205     ASSERT_EQ(pldm_instance_db_destroy(connections[1].db), 0);
206 
207     EXPECT_EQ(pldm_instance_id_free(connections[0].db, connections[0].tid,
208                                     connections[0].iid),
209               0);
210     ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
211 }
212 
213 TEST_F(PldmInstanceDbTest, allocAllInstanceIds)
214 {
215     static constexpr pldm_tid_t tid = 1;
216 
217     struct pldm_instance_db* db = nullptr;
218     std::array<pldm_instance_id_t, pldmMaxInstanceIds> iids = {};
219     pldm_instance_id_t extra;
220 
221     ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
222 
223     for (auto& iid : iids)
224     {
225         EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0);
226     }
227 
228     EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN);
229 
230     for (auto& iid : iids)
231     {
232         EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0);
233     }
234 
235     EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0);
236 
237     ASSERT_EQ(pldm_instance_db_destroy(db), 0);
238 }
239 
240 TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId)
241 {
242     struct pldm_instance_db* db = nullptr;
243     const pldm_tid_t tid = 1;
244 
245     ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
246     EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0);
247     ASSERT_EQ(pldm_instance_db_destroy(db), 0);
248 }
249