instance-id: Track existing allocations for each db instance

OFD locking allows merging and splitting of locks, which means that it
won't fail an attempt to "recursively" lock the range. We were relying
on that to prevent double allocation when the available instance IDs for
a TID were exhausted.

Given that we can't rely on it, explicitly track the allocations in the
local state.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: Ic0f6903935ac712a86a7967d1cceb5a0c463878b
diff --git a/tests/instance-id.cpp b/tests/instance-id.cpp
index e26563f..99366b1 100644
--- a/tests/instance-id.cpp
+++ b/tests/instance-id.cpp
@@ -194,3 +194,40 @@
               0);
     ASSERT_EQ(pldm_instance_db_destroy(connections[0].db), 0);
 }
+
+TEST_F(PldmInstanceDbTest, allocAllInstanceIds)
+{
+    static constexpr pldm_tid_t tid = 1;
+
+    struct pldm_instance_db* db = nullptr;
+    std::array<pldm_instance_id_t, pldmMaxInstanceIds> iids = {};
+    pldm_instance_id_t extra;
+
+    ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
+
+    for (auto& iid : iids)
+    {
+        EXPECT_EQ(pldm_instance_id_alloc(db, tid, &iid), 0);
+    }
+
+    EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), -EAGAIN);
+
+    for (auto& iid : iids)
+    {
+        EXPECT_EQ(pldm_instance_id_free(db, tid, iid), 0);
+    }
+
+    EXPECT_EQ(pldm_instance_id_alloc(db, tid, &extra), 0);
+
+    ASSERT_EQ(pldm_instance_db_destroy(db), 0);
+}
+
+TEST_F(PldmInstanceDbTest, freeUnallocatedInstanceId)
+{
+    struct pldm_instance_db* db = nullptr;
+    const pldm_tid_t tid = 1;
+
+    ASSERT_EQ(pldm_instance_db_init(&db, dbPath.c_str()), 0);
+    EXPECT_NE(pldm_instance_id_free(db, tid, 0), 0);
+    ASSERT_EQ(pldm_instance_db_destroy(db), 0);
+}