Add unit test for the lock management

- The idea behind this commit is to enable the unit test
for the lock management algorithm, and below are the unit
test cases that are written:

Testedby:

[----------] 20 tests from locktest
[ RUN      ] locktest.ValidationGoodTestCase
[       OK ] locktest.ValidationGoodTestCase (3 ms)
[ RUN      ] locktest.ValidationBadTestWithLocktype
[       OK ] locktest.ValidationBadTestWithLocktype (1 ms)
[ RUN      ] locktest.ValidationBadTestWithlockFlags
[       OK ] locktest.ValidationBadTestWithlockFlags (0 ms)
[ RUN      ] locktest.ValidationBadTestWithSegmentlength
[       OK ] locktest.ValidationBadTestWithSegmentlength (1 ms)
[ RUN      ] locktest.MultiRequestWithoutConflict
[       OK ] locktest.MultiRequestWithoutConflict (3 ms)
[ RUN      ] locktest.MultiRequestWithConflictduetoSameSegmentLength
[       OK ] locktest.MultiRequestWithConflictduetoSameSegmentLength (2 ms)
[ RUN      ] locktest.MultiRequestWithoutConflictduetoDifferentSegmentData
[       OK ] locktest.MultiRequestWithoutConflictduetoDifferentSegmentData (1 ms)
[ RUN      ] locktest.MultiRequestWithConflictduetoSameSegmentData
[       OK ] locktest.MultiRequestWithConflictduetoSameSegmentData (2 ms)
[ RUN      ] locktest.MultiRequestWithoutConflictduetoDifferentSegmentLength
[       OK ] locktest.MultiRequestWithoutConflictduetoDifferentSegmentLength (1 ms)
[ RUN      ] locktest.MultiRequestWithoutConflictduetoReadLocktype
[       OK ] locktest.MultiRequestWithoutConflictduetoReadLocktype (1 ms)
[ RUN      ] locktest.MultiRequestWithoutConflictduetoReadLocktypeAndLockall
[       OK ] locktest.MultiRequestWithoutConflictduetoReadLocktypeAndLockall (2 ms)
[ RUN      ] locktest.RequestConflictedWithLockTableEntries
[       OK ] locktest.RequestConflictedWithLockTableEntries (6 ms)
[ RUN      ] locktest.RequestNotConflictedWithLockTableEntries
[       OK ] locktest.RequestNotConflictedWithLockTableEntries (3 ms)
[ RUN      ] locktest.TestGenerateTransactionIDFunction
[       OK ] locktest.TestGenerateTransactionIDFunction (1 ms)
[ RUN      ] locktest.ValidateTransactionIDsGoodTestCase
[       OK ] locktest.ValidateTransactionIDsGoodTestCase (3 ms)
[ RUN      ] locktest.ValidateTransactionIDsBadTestCase
[       OK ] locktest.ValidateTransactionIDsBadTestCase (2 ms)
[ RUN      ] locktest.ValidateisItMyLockGoodTestCase
[       OK ] locktest.ValidateisItMyLockGoodTestCase (2 ms)
[ RUN      ] locktest.ValidateisItMyLockBadTestCase
[       OK ] locktest.ValidateisItMyLockBadTestCase (2 ms)
[ RUN      ] locktest.ValidateSessionIDForGetlocklistBadTestCase
[       OK ] locktest.ValidateSessionIDForGetlocklistBadTestCase (3 ms)
[ RUN      ] locktest.ValidateSessionIDForGetlocklistGoodTestCase
[       OK ] locktest.ValidateSessionIDForGetlocklistGoodTestCase (3 ms)
[----------] 20 tests from locktest (82 ms total)

Signed-off-by: manojkiraneda <manojkiran.eda@gmail.com>
Change-Id: Id274ee356adfa7ba03da02d83b609d37c8c99f8d
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9511cfd..ba52fad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -288,6 +288,12 @@
     link_directories (${CMAKE_BINARY_DIR}/sdbusplus-src/build)
 endif ()
 
+# Its an Out of tree build,enabling ibm management console for
+# unit-test purpose.
+if (NOT ${YOCTO_DEPENDENCIES})
+    add_definitions(-DBMCWEB_ENABLE_IBM_MANAGEMENT_CONSOLE)
+endif(NOT ${YOCTO_DEPENDENCIES})
+
 # Openssl
 find_package (OpenSSL REQUIRED)
 include_directories (SYSTEM ${OPENSSL_INCLUDE_DIR})
@@ -341,14 +347,10 @@
 file (COPY src/test_resources DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 
 # Unit Tests
-if (${BMCWEB_BUILD_UT})
-    set (UT_FILES src/crow_test.cpp src/gtest_main.cpp
-         src/token_authorization_middleware_test.cpp
-         src/security_headers_middleware_test.cpp src/webassets_test.cpp
-         src/crow_getroutes_test.cpp src/ast_jpeg_decoder_test.cpp
-         src/kvm_websocket_test.cpp src/msan_test.cpp
-         src/ast_video_puller_test.cpp src/openbmc_jtag_rest_test.cpp
+if (NOT ${YOCTO_DEPENDENCIES})
+    set (UT_FILES src/gtest_main.cpp src/msan_test.cpp
          redfish-core/ut/privileges_test.cpp
+         redfish-core/ut/lock_test.cpp
          ${CMAKE_BINARY_DIR}/include/bmcweb/blns.hpp) # big list of naughty
                                                       # strings
     add_custom_command (OUTPUT ${CMAKE_BINARY_DIR}/include/bmcweb/blns.hpp
@@ -378,7 +380,7 @@
     target_link_libraries (webtest -lstdc++fs)
     add_test (webtest webtest "--gtest_output=xml:webtest.xml")
 
-endif (${BMCWEB_BUILD_UT})
+endif (NOT ${YOCTO_DEPENDENCIES})
 
 install (DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/static/ DESTINATION share/www)
 
diff --git a/include/ibm/locks.hpp b/include/ibm/locks.hpp
index 79079c4..3c4f8ec 100644
--- a/include/ibm/locks.hpp
+++ b/include/ibm/locks.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <logging.h>
+
 #include <boost/algorithm/string.hpp>
 #include <boost/container/flat_map.hpp>
 #include <boost/endian/conversion.hpp>
@@ -43,69 +45,6 @@
     boost::container::flat_map<uint32_t, LockRequests> lockTable;
 
     /*
-     * This function implements the logic for validating an incoming
-     * lock request/requests.
-     *
-     * Returns : True (if Valid)
-     * Returns : False (if not a Valid lock request)
-     */
-
-    bool isValidLockRequest(const LockRequest);
-
-    /*
-     * This function implements the logic of checking if the incoming
-     * multi-lock request is not having conflicting requirements.
-     *
-     * Returns : True (if conflicting)
-     * Returns : False (if not conflicting)
-     */
-
-    bool isConflictRequest(const LockRequests);
-    /*
-     * Implements the core algorithm to find the conflicting
-     * lock requests.
-     *
-     * This functions takes two lock requests and check if both
-     * are conflicting to each other.
-     *
-     * Returns : True (if conflicting)
-     * Returns : False (if not conflicting)
-     */
-    bool isConflictRecord(const LockRequest, const LockRequest);
-
-    /*
-     * This function implements the logic of checking the conflicting
-     * locks from a incoming single/multi lock requests with the already
-     * existing lock request in the lock table.
-     *
-     */
-
-    Rc isConflictWithTable(const LockRequests);
-    /*
-     * This function implements the logic of checking the ownership of the
-     * lock from the releaselock request.
-     *
-     * Returns : True (if the requesting HMC & Session owns the lock(s))
-     * Returns : False (if the request HMC or Session does not own the lock(s))
-     */
-
-    RcRelaseLock isItMyLock(const ListOfTransactionIds &, const SessionFlags &);
-
-    /*
-     * This function validates the the list of transactionID's and returns false
-     * if the transaction ID is not valid & not present in the lock table
-     */
-
-    bool validateRids(const ListOfTransactionIds &);
-
-    /*
-     * This function releases the locks that are already obtained by the
-     * requesting Management console.
-     */
-
-    void releaseLock(const ListOfTransactionIds &);
-
-    /*
      * This API implements the logic to persist the locks that are contained in
      * the lock table into a json file.
      */
@@ -117,6 +56,79 @@
      */
     void loadLocks();
 
+    bool createPersistentLockFilePath();
+
+  protected:
+    /*
+     * This function implements the logic for validating an incoming
+     * lock request/requests.
+     *
+     * Returns : True (if Valid)
+     * Returns : False (if not a Valid lock request)
+     */
+
+    virtual bool isValidLockRequest(const LockRequest);
+
+    /*
+     * This function implements the logic of checking if the incoming
+     * multi-lock request is not having conflicting requirements.
+     *
+     * Returns : True (if conflicting)
+     * Returns : False (if not conflicting)
+     */
+
+    virtual bool isConflictRequest(const LockRequests);
+    /*
+     * Implements the core algorithm to find the conflicting
+     * lock requests.
+     *
+     * This functions takes two lock requests and check if both
+     * are conflicting to each other.
+     *
+     * Returns : True (if conflicting)
+     * Returns : False (if not conflicting)
+     */
+    virtual bool isConflictRecord(const LockRequest, const LockRequest);
+
+    /*
+     * This function implements the logic of checking the conflicting
+     * locks from a incoming single/multi lock requests with the already
+     * existing lock request in the lock table.
+     *
+     */
+
+    virtual Rc isConflictWithTable(const LockRequests);
+    /*
+     * This function implements the logic of checking the ownership of the
+     * lock from the releaselock request.
+     *
+     * Returns : True (if the requesting HMC & Session owns the lock(s))
+     * Returns : False (if the request HMC or Session does not own the lock(s))
+     */
+
+    virtual RcRelaseLock isItMyLock(const ListOfTransactionIds &,
+                                    const SessionFlags &);
+
+    /*
+     * This function validates the the list of transactionID's and returns false
+     * if the transaction ID is not valid & not present in the lock table
+     */
+
+    virtual bool validateRids(const ListOfTransactionIds &);
+
+    /*
+     * This function releases the locks that are already obtained by the
+     * requesting Management console.
+     */
+
+    void releaseLock(const ListOfTransactionIds &);
+
+    Lock()
+    {
+        loadLocks();
+        transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
+    }
+
     /*
      * This function implements the algorithm for checking the respective
      * bytes of the resource id based on the lock management algorithm.
@@ -129,9 +141,7 @@
      * number for every successful transaction. This number will be used by
      * the Management Console for debug.
      */
-    uint32_t generateTransactionId();
-
-    bool createPersistentLockFilePath();
+    virtual uint32_t generateTransactionId();
 
   public:
     /*
@@ -171,17 +181,15 @@
 
     void releaseLock(const std::string &);
 
-    Lock()
-    {
-        loadLocks();
-        transactionId = lockTable.empty() ? 0 : prev(lockTable.end())->first;
-    }
-
     static Lock &getInstance()
     {
         static Lock lockObject;
         return lockObject;
     }
+
+    virtual ~Lock()
+    {
+    }
 };
 
 inline bool Lock::createPersistentLockFilePath()
diff --git a/redfish-core/ut/lock_test.cpp b/redfish-core/ut/lock_test.cpp
new file mode 100644
index 0000000..0ecd8a9
--- /dev/null
+++ b/redfish-core/ut/lock_test.cpp
@@ -0,0 +1,356 @@
+#include "ibm/locks.hpp"
+#include "nlohmann/json.hpp"
+
+#include <string>
+#include <utils/json_utils.hpp>
+
+#include "gmock/gmock.h"
+
+namespace crow
+{
+namespace ibm_mc_lock
+{
+using SType = std::string;
+using LockRequest = std::tuple<SType, SType, SType, uint64_t, SegmentFlags>;
+using LockRequests = std::vector<LockRequest>;
+using Rc =
+    std::pair<bool, std::variant<uint32_t, std::pair<uint32_t, LockRequest>>>;
+using RcRelaseLock = std::pair<bool, std::pair<uint32_t, LockRequest>>;
+using RcGetLockList =
+    std::variant<std::string, std::vector<std::pair<uint32_t, LockRequests>>>;
+using ListOfTransactionIds = std::vector<uint32_t>;
+using RcAcquireLock = std::pair<bool, std::variant<Rc, std::pair<bool, int>>>;
+using RcReleaseLockApi = std::pair<bool, std::variant<bool, RcRelaseLock>>;
+using SessionFlags = std::pair<SType, SType>;
+using ListOfSessionIds = std::vector<std::string>;
+
+class LockTest : public ::testing::Test
+{
+  protected:
+    LockRequests request;
+    LockRequests request1, request2;
+    LockRequest record;
+
+  public:
+    LockTest()
+    {
+        record = {
+            "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}};
+        // lockrequest with multiple lockrequests
+        request = {{"xxxxx",
+                    "hmc-id",
+                    "Read",
+                    234,
+                    {{"DontLock", 2}, {"DontLock", 4}}},
+                   {"xxxxx",
+                    "hmc-id",
+                    "Read",
+                    234,
+                    {{"DontLock", 2}, {"DontLock", 4}}}};
+        request1 = {{"xxxxx",
+                     "hmc-id",
+                     "Read",
+                     234,
+                     {{"DontLock", 2}, {"DontLock", 4}}}};
+        request2 = {{"xxxxx",
+                     "hmc-id",
+                     "Write",
+                     234,
+                     {{"LockAll", 2}, {"DontLock", 4}}}};
+    }
+    ~LockTest()
+    {
+    }
+};
+
+class MockLock : public crow::ibm_mc_lock::Lock
+{
+  public:
+    bool isValidLockRequest(LockRequest record1) override
+    {
+        bool status = Lock::isValidLockRequest(record1);
+        return status;
+    }
+    bool isConflictRequest(LockRequests request) override
+    {
+        bool status = Lock::isConflictRequest(request);
+        return status;
+    }
+    Rc isConflictWithTable(LockRequests request) override
+    {
+        auto conflict = Lock::isConflictWithTable(request);
+        return conflict;
+    }
+    uint32_t generateTransactionId() override
+    {
+        uint32_t tid = Lock::generateTransactionId();
+        return tid;
+    }
+
+    bool validateRids(const ListOfTransactionIds& tids) override
+    {
+        bool status = Lock::validateRids(tids);
+        return status;
+    }
+    RcRelaseLock isItMyLock(const ListOfTransactionIds& tids,
+                            const SessionFlags& ids) override
+    {
+        auto status = Lock::isItMyLock(tids, ids);
+        return status;
+    }
+    RcGetLockList getList(std::vector<std::string>& listSessionid)
+    {
+        auto status = Lock::getLockList(listSessionid);
+        return status;
+    }
+    friend class LockTest;
+};
+
+TEST_F(LockTest, ValidationGoodTestCase)
+{
+    MockLock lockManager;
+    const LockRequest& t = record;
+    ASSERT_EQ(1, lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithLocktype)
+{
+    MockLock lockManager;
+    // Corrupt the lock type
+    std::get<2>(record) = "rwrite";
+    const LockRequest& t = record;
+    ASSERT_EQ(0, lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithlockFlags)
+{
+    MockLock lockManager;
+    // Corrupt the lockflag
+    std::get<4>(record)[0].first = "lock";
+    const LockRequest& t = record;
+    ASSERT_EQ(0, lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithSegmentlength)
+{
+    MockLock lockManager;
+    // Corrupt the Segment length
+    std::get<4>(record)[0].second = 7;
+    const LockRequest& t = record;
+    ASSERT_EQ(0, lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflict)
+{
+    MockLock lockManager;
+    const LockRequests& t = request;
+    ASSERT_EQ(0, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentLength)
+{
+    MockLock lockManager;
+    // Corrupt the locktype
+    std::get<2>(request[0]) = "Write";
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "LockAll";
+    const LockRequests& t = request;
+    ASSERT_EQ(1, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentData)
+{
+    MockLock lockManager;
+    // Corrupt the locktype
+    std::get<2>(request[0]) = "Write";
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "DontLock";
+    std::get<4>(request[0])[1].first = "LockAll";
+
+    // Change the resource id(2nd byte) of first record, so the locks are
+    // different so no conflict
+    std::get<3>(request[0]) = 216179379183550464; // HEX 03 00 06 00 00 00 00 00
+    std::get<3>(request[1]) = 288236973221478400; // HEX 04 00 06 00 00 00 00 00
+    const LockRequests& t = request;
+    ASSERT_EQ(0, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithConflictduetoSameSegmentData)
+{
+    MockLock lockManager;
+    // Corrupt the locktype
+    std::get<2>(request[0]) = "Write";
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "DontLock";
+    std::get<4>(request[0])[1].first = "LockAll";
+    // Dont Change the resource id(1st & 2nd byte) at all, so that the conflict
+    // occurs from the second segment which is trying to lock all the resources.
+    std::get<3>(request[0]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
+    std::get<3>(request[1]) = 216173882346831872; // 03 00 01 00 2B 00 00 00
+    const LockRequests& t = request;
+    ASSERT_EQ(1, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflictduetoDifferentSegmentLength)
+{
+    MockLock lockManager;
+    // Corrupt the locktype
+    std::get<2>(request[0]) = "Write";
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "LockSame";
+    // Change the segment length , so that the requests are trying to lock
+    // two different kind of resources
+    std::get<4>(request[0])[0].second = 3;
+    const LockRequests& t = request;
+    // Return No Conflict
+    ASSERT_EQ(0, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktype)
+{
+    MockLock lockManager;
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "LockAll";
+    const LockRequests& t = request;
+    // Return No Conflict
+    ASSERT_EQ(0, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflictduetoReadLocktypeAndLockall)
+{
+    MockLock lockManager;
+    // Match the segment lengths to points them to lock similar kind of
+    // resource
+    std::get<4>(request[0])[0].first = "LockAll";
+    std::get<4>(request[0])[1].first = "LockAll";
+    const LockRequests& t = request;
+    // Return No Conflict
+    ASSERT_EQ(0, lockManager.isConflictRequest(t));
+}
+
+TEST_F(LockTest, RequestConflictedWithLockTableEntries)
+{
+    MockLock lockManager;
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    // Corrupt the lock type
+    std::get<2>(request[0]) = "Write";
+    // Corrupt the lockflag
+    std::get<4>(request[0])[1].first = "LockAll";
+    const LockRequests& p = request;
+    auto rc2 = lockManager.isConflictWithTable(p);
+    // Return a Conflict
+    ASSERT_EQ(1, rc2.first);
+}
+
+TEST_F(LockTest, RequestNotConflictedWithLockTableEntries)
+{
+    MockLock lockManager;
+    const LockRequests& t = request1;
+    // Insert the request1 into the lock table
+    auto rc1 = lockManager.isConflictWithTable(t);
+    // Corrupt the lock type
+    std::get<2>(request[0]) = "Read";
+    // Corrupt the lockflag
+    std::get<4>(request[0])[1].first = "LockAll";
+    const LockRequests& p = request;
+    auto rc2 = lockManager.isConflictWithTable(p);
+    // Return No Conflict
+    ASSERT_EQ(0, rc2.first);
+}
+
+TEST_F(LockTest, TestGenerateTransactionIDFunction)
+{
+    MockLock lockManager;
+    uint32_t transactionid1 = lockManager.generateTransactionId();
+    uint32_t transactionid2 = lockManager.generateTransactionId();
+    EXPECT_TRUE(transactionid2 == ++transactionid1);
+}
+
+TEST_F(LockTest, ValidateTransactionIDsGoodTestCase)
+{
+    MockLock lockManager;
+    const LockRequests& t = request1;
+    // Insert the request1 into the lock table
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<uint32_t> tids = {1};
+    const std::vector<uint32_t>& p = tids;
+    ASSERT_EQ(1, lockManager.validateRids(p));
+}
+
+TEST_F(LockTest, ValidateTransactionIDsBadTestCase)
+{
+    MockLock lockManager;
+    // Insert the request1 into the lock table
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<uint32_t> tids = {3};
+    const std::vector<uint32_t>& p = tids;
+    ASSERT_EQ(0, lockManager.validateRids(p));
+}
+
+TEST_F(LockTest, ValidateisItMyLockGoodTestCase)
+{
+    MockLock lockManager;
+    // Insert the request1 into the lock table
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<uint32_t> tids = {1};
+    const std::vector<uint32_t>& p = tids;
+    std::string hmcid = "hmc-id";
+    std::string sessionid = "xxxxx";
+    std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
+    auto rc = lockManager.isItMyLock(p, ids);
+    ASSERT_EQ(1, rc.first);
+}
+
+TEST_F(LockTest, ValidateisItMyLockBadTestCase)
+{
+    MockLock lockManager;
+
+    // Corrupt the client identifier
+    std::get<1>(request1[0]) = "randomid";
+    // Insert the request1 into the lock table
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<uint32_t> tids = {1};
+    const std::vector<uint32_t>& p = tids;
+    std::string hmcid = "hmc-id";
+    std::string sessionid = "xxxxx";
+    std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
+    auto rc = lockManager.isItMyLock(p, ids);
+    ASSERT_EQ(0, rc.first);
+}
+
+TEST_F(LockTest, ValidateSessionIDForGetlocklistBadTestCase)
+{
+    MockLock lockManager;
+    // Insert the request1 into the lock table
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<std::string> sessionid = {"random"};
+    auto status = lockManager.getLockList(sessionid);
+    auto result =
+        std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
+    ASSERT_EQ(0, result.size());
+}
+
+TEST_F(LockTest, ValidateSessionIDForGetlocklistGoodTestCase)
+{
+    MockLock lockManager;
+    // Insert the request1 into the lock table
+    const LockRequests& t = request1;
+    auto rc1 = lockManager.isConflictWithTable(t);
+    std::vector<std::string> sessionid = {"xxxxx"};
+    auto status = lockManager.getLockList(sessionid);
+    auto result =
+        std::get<std::vector<std::pair<uint32_t, LockRequests>>>(status);
+    ASSERT_EQ(1, result.size());
+}
+} // namespace ibm_mc_lock
+} // namespace crow