treewide: reorganize unit tests

Like other C++ projects, unit tests normally are in a separate repo and
respect the folder structure of the file under test.

This commit deleted all "ut" folder and move tests to a "test" folder.
The test folder also has similar structure as the main folder.

This commit also made neccessary include changes to make codes compile.
Unused tests are untouched.

Tested: unit test passed.

Reference:
[1] https://github.com/grpc/grpc/tree/master/test
[2] https://github.com/boostorg/core/tree/414dfb466878af427d33b36e6ccf84d21c0e081b/test
[3] Many other OpenBMC repos: https://github.com/openbmc/entity-manager/tree/master/test
[4] https://stackoverflow.com/questions/2360734/whats-a-good-directory-structure-for-larger-c-projects-using-makefile

Signed-off-by: Nan Zhou <nanzhoumails@gmail.com>
Change-Id: I4521c7ef5fa03c47cca5c146d322bbb51365ee96
diff --git a/test/include/dbus_utility_test.cpp b/test/include/dbus_utility_test.cpp
new file mode 100644
index 0000000..71978d0
--- /dev/null
+++ b/test/include/dbus_utility_test.cpp
@@ -0,0 +1,48 @@
+#include "dbus_utility.hpp"
+
+#include <string>
+
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+
+namespace dbus::utility
+{
+namespace
+{
+
+TEST(GetNthStringFromPath, ParsingSucceedsAndReturnsNthArg)
+{
+    std::string path("/0th/1st/2nd/3rd");
+    std::string result;
+    EXPECT_TRUE(getNthStringFromPath(path, 0, result));
+    EXPECT_EQ(result, "0th");
+    EXPECT_TRUE(getNthStringFromPath(path, 1, result));
+    EXPECT_EQ(result, "1st");
+    EXPECT_TRUE(getNthStringFromPath(path, 2, result));
+    EXPECT_EQ(result, "2nd");
+    EXPECT_TRUE(getNthStringFromPath(path, 3, result));
+    EXPECT_EQ(result, "3rd");
+    EXPECT_FALSE(getNthStringFromPath(path, 4, result));
+
+    path = "////0th///1st//\2nd///3rd?/";
+    EXPECT_TRUE(getNthStringFromPath(path, 0, result));
+    EXPECT_EQ(result, "0th");
+    EXPECT_TRUE(getNthStringFromPath(path, 1, result));
+    EXPECT_EQ(result, "1st");
+    EXPECT_TRUE(getNthStringFromPath(path, 2, result));
+    EXPECT_EQ(result, "\2nd");
+    EXPECT_TRUE(getNthStringFromPath(path, 3, result));
+    EXPECT_EQ(result, "3rd?");
+}
+
+TEST(GetNthStringFromPath, InvalidIndexReturnsFalse)
+{
+    std::string path("////0th///1st//\2nd///3rd?/");
+    std::string result;
+    EXPECT_FALSE(getNthStringFromPath(path, -1, result));
+}
+} // namespace
+} // namespace dbus::utility
\ No newline at end of file
diff --git a/test/include/google/google_service_root_test.cpp b/test/include/google/google_service_root_test.cpp
new file mode 100644
index 0000000..32d4e52
--- /dev/null
+++ b/test/include/google/google_service_root_test.cpp
@@ -0,0 +1,39 @@
+#include "async_resp.hpp"
+#include "google/google_service_root.hpp"
+#include "http_request.hpp"
+#include "nlohmann/json.hpp"
+
+#include <gtest/gtest.h>
+
+namespace crow::google_api
+{
+namespace
+{
+
+void validateServiceRootGet(crow::Response& res)
+{
+    nlohmann::json& json = res.jsonValue;
+    EXPECT_EQ(json["@odata.id"], "/google/v1");
+    EXPECT_EQ(json["@odata.type"],
+              "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot");
+    EXPECT_EQ(json["@odata.id"], "/google/v1");
+    EXPECT_EQ(json["Id"], "Google Rest RootService");
+    EXPECT_EQ(json["Name"], "Google Service Root");
+    EXPECT_EQ(json["Version"], "1.0.0");
+    EXPECT_EQ(json["RootOfTrustCollection"]["@odata.id"],
+              "/google/v1/RootOfTrustCollection");
+}
+
+TEST(HandleGoogleV1Get, OnSuccess)
+{
+    std::error_code ec;
+    auto asyncResp = std::make_shared<bmcweb::AsyncResp>();
+
+    asyncResp->res.setCompleteRequestHandler(validateServiceRootGet);
+
+    crow::Request dummyRequest{{boost::beast::http::verb::get, "", 11}, ec};
+    handleGoogleV1Get(dummyRequest, asyncResp);
+}
+
+} // namespace
+} // namespace crow::google_api
\ No newline at end of file
diff --git a/test/include/http_utility_test.cpp b/test/include/http_utility_test.cpp
new file mode 100644
index 0000000..d1df6d1
--- /dev/null
+++ b/test/include/http_utility_test.cpp
@@ -0,0 +1,82 @@
+#include "http_utility.hpp"
+
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+
+namespace http_helpers
+{
+namespace
+{
+
+TEST(isContentTypeAllowed, PositiveTest)
+{
+    EXPECT_TRUE(isContentTypeAllowed("*/*, application/octet-stream",
+                                     ContentType::OctetStream));
+    EXPECT_TRUE(isContentTypeAllowed("application/octet-stream",
+                                     ContentType::OctetStream));
+    EXPECT_TRUE(isContentTypeAllowed("text/html", ContentType::HTML));
+    EXPECT_TRUE(isContentTypeAllowed("application/json", ContentType::JSON));
+    EXPECT_TRUE(isContentTypeAllowed("application/cbor", ContentType::CBOR));
+    EXPECT_TRUE(
+        isContentTypeAllowed("application/json, text/html", ContentType::HTML));
+}
+
+TEST(isContentTypeAllowed, NegativeTest)
+{
+    EXPECT_FALSE(
+        isContentTypeAllowed("application/octet-stream", ContentType::HTML));
+    EXPECT_FALSE(isContentTypeAllowed("application/html", ContentType::JSON));
+    EXPECT_FALSE(isContentTypeAllowed("application/json", ContentType::CBOR));
+    EXPECT_FALSE(isContentTypeAllowed("application/cbor", ContentType::HTML));
+    EXPECT_FALSE(isContentTypeAllowed("application/json, text/html",
+                                      ContentType::OctetStream));
+}
+
+TEST(isContentTypeAllowed, ContainsAnyMimeTypeReturnsTrue)
+{
+    EXPECT_TRUE(
+        isContentTypeAllowed("text/html, */*", ContentType::OctetStream));
+}
+
+TEST(isContentTypeAllowed, ContainsQFactorWeightingReturnsTrue)
+{
+    EXPECT_TRUE(
+        isContentTypeAllowed("text/html, */*;q=0.8", ContentType::OctetStream));
+}
+
+TEST(getPreferedContentType, PositiveTest)
+{
+    std::array<ContentType, 1> contentType{ContentType::HTML};
+    EXPECT_EQ(
+        getPreferedContentType("text/html, application/json", contentType),
+        ContentType::HTML);
+
+    std::array<ContentType, 2> htmlJson{ContentType::HTML, ContentType::JSON};
+    EXPECT_EQ(getPreferedContentType("text/html, application/json", htmlJson),
+              ContentType::HTML);
+
+    std::array<ContentType, 2> jsonHtml{ContentType::JSON, ContentType::HTML};
+    EXPECT_EQ(getPreferedContentType("text/html, application/json", jsonHtml),
+              ContentType::HTML);
+
+    std::array<ContentType, 2> cborJson{ContentType::CBOR, ContentType::JSON};
+    EXPECT_EQ(
+        getPreferedContentType("application/cbor, application::json", cborJson),
+        ContentType::CBOR);
+
+    EXPECT_EQ(getPreferedContentType("application/json", cborJson),
+              ContentType::JSON);
+}
+
+TEST(getPreferedContentType, NegativeTest)
+{
+    std::array<ContentType, 1> contentType{ContentType::CBOR};
+    EXPECT_EQ(
+        getPreferedContentType("text/html, application/json", contentType),
+        ContentType::NoMatch);
+}
+} // namespace
+} // namespace http_helpers
diff --git a/test/include/human_sort_test.cpp b/test/include/human_sort_test.cpp
new file mode 100644
index 0000000..be21a19
--- /dev/null
+++ b/test/include/human_sort_test.cpp
@@ -0,0 +1,58 @@
+#include "human_sort.hpp"
+
+#include <set>
+#include <string>
+
+#include <gmock/gmock.h> // IWYU pragma: keep
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+// IWYU pragma: no_include <gmock/gmock-matchers.h>
+
+namespace
+{
+
+using ::testing::ElementsAreArray;
+
+TEST(AlphaNum, NumberTests)
+{
+    // testcases for the algorithm
+    EXPECT_EQ(alphanumComp("", ""), 0);
+    EXPECT_LT(alphanumComp("", "a"), 0);
+    EXPECT_GT(alphanumComp("a", ""), 0);
+    EXPECT_EQ(alphanumComp("a", "a"), 0);
+    EXPECT_LT(alphanumComp("", "9"), 0);
+    EXPECT_GT(alphanumComp("9", ""), 0);
+    EXPECT_EQ(alphanumComp("1", "1"), 0);
+    EXPECT_LT(alphanumComp("1", "2"), 0);
+    EXPECT_GT(alphanumComp("3", "2"), 0);
+    EXPECT_EQ(alphanumComp("a1", "a1"), 0);
+    EXPECT_LT(alphanumComp("a1", "a2"), 0);
+    EXPECT_GT(alphanumComp("a2", "a1"), 0);
+    EXPECT_LT(alphanumComp("a1a2", "a1a3"), 0);
+    EXPECT_GT(alphanumComp("a1a2", "a1a0"), 0);
+    EXPECT_GT(alphanumComp("134", "122"), 0);
+    EXPECT_EQ(alphanumComp("12a3", "12a3"), 0);
+    EXPECT_GT(alphanumComp("12a1", "12a0"), 0);
+    EXPECT_LT(alphanumComp("12a1", "12a2"), 0);
+    EXPECT_LT(alphanumComp("a", "aa"), 0);
+    EXPECT_GT(alphanumComp("aaa", "aa"), 0);
+    EXPECT_EQ(alphanumComp("Alpha 2", "Alpha 2"), 0);
+    EXPECT_LT(alphanumComp("Alpha 2", "Alpha 2A"), 0);
+    EXPECT_GT(alphanumComp("Alpha 2 B", "Alpha 2"), 0);
+
+    std::string str("Alpha 2");
+    EXPECT_EQ(alphanumComp(str, "Alpha 2"), 0);
+    EXPECT_LT(alphanumComp(str, "Alpha 2A"), 0);
+    EXPECT_GT(alphanumComp("Alpha 2 B", str), 0);
+}
+
+TEST(AlphaNum, LessTest)
+{
+    std::set<std::string, AlphanumLess<std::string>> sorted{"Alpha 10",
+                                                            "Alpha 2"};
+    EXPECT_THAT(sorted, ElementsAreArray({"Alpha 2", "Alpha 10"}));
+}
+} // namespace
\ No newline at end of file
diff --git a/test/include/ibm/configfile_test.cpp b/test/include/ibm/configfile_test.cpp
new file mode 100644
index 0000000..1d95a79
--- /dev/null
+++ b/test/include/ibm/configfile_test.cpp
@@ -0,0 +1,56 @@
+#include "http_response.hpp"
+#include "ibm/management_console_rest.hpp"
+
+#include <string>
+
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+
+namespace crow
+{
+namespace ibm_mc
+{
+
+TEST(IsValidConfigFileName, FileNameValidCharReturnsTrue)
+{
+    crow::Response res;
+
+    EXPECT_TRUE(isValidConfigFileName("GoodConfigFile", res));
+}
+TEST(IsValidConfigFileName, FileNameInvalidCharReturnsFalse)
+{
+    crow::Response res;
+
+    EXPECT_FALSE(isValidConfigFileName("Bad@file", res));
+}
+TEST(IsValidConfigFileName, FileNameInvalidPathReturnsFalse)
+{
+    crow::Response res;
+
+    EXPECT_FALSE(isValidConfigFileName("/../../../../../etc/badpath", res));
+    EXPECT_FALSE(isValidConfigFileName("/../../etc/badpath", res));
+    EXPECT_FALSE(isValidConfigFileName("/mydir/configFile", res));
+}
+
+TEST(IsValidConfigFileName, EmptyFileNameReturnsFalse)
+{
+    crow::Response res;
+    EXPECT_FALSE(isValidConfigFileName("", res));
+}
+
+TEST(IsValidConfigFileName, SlashFileNameReturnsFalse)
+{
+    crow::Response res;
+    EXPECT_FALSE(isValidConfigFileName("/", res));
+}
+TEST(IsValidConfigFileName, FileNameMoreThan20CharReturnsFalse)
+{
+    crow::Response res;
+    EXPECT_FALSE(isValidConfigFileName("BadfileBadfileBadfile", res));
+}
+
+} // namespace ibm_mc
+} // namespace crow
diff --git a/test/include/ibm/lock_test.cpp b/test/include/ibm/lock_test.cpp
new file mode 100644
index 0000000..33c5354
--- /dev/null
+++ b/test/include/ibm/lock_test.cpp
@@ -0,0 +1,366 @@
+#include "ibm/locks.hpp"
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <variant>
+#include <vector>
+
+#include <gmock/gmock.h> // IWYU pragma: keep
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+
+namespace crow::ibm_mc_lock
+{
+namespace
+{
+
+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>;
+using ::testing::IsEmpty;
+
+class LockTest : public ::testing::Test
+{
+  protected:
+    LockRequests request;
+    LockRequests request1, request2;
+    LockRequest record;
+
+  public:
+    LockTest() :
+        // 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}}}},
+        record{
+            "xxxxx", "hmc-id", "Read", 234, {{"DontLock", 2}, {"DontLock", 4}}}
+    {}
+
+    ~LockTest() override = default;
+
+    LockTest(const LockTest&) = delete;
+    LockTest(LockTest&&) = delete;
+    LockTest& operator=(const LockTest&) = delete;
+    LockTest& operator=(const LockTest&&) = delete;
+};
+
+class MockLock : public crow::ibm_mc_lock::Lock
+{
+  public:
+    bool isValidLockRequest(const LockRequest& record1) override
+    {
+        bool status = Lock::isValidLockRequest(record1);
+        return status;
+    }
+    bool isConflictRequest(const LockRequests& request) override
+    {
+        bool status = Lock::isConflictRequest(request);
+        return status;
+    }
+    Rc isConflictWithTable(const 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;
+    }
+    friend class LockTest;
+};
+
+TEST_F(LockTest, ValidationGoodTestCase)
+{
+    MockLock lockManager;
+    const LockRequest& t = record;
+    EXPECT_TRUE(lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithLocktype)
+{
+    MockLock lockManager;
+    // Corrupt the lock type
+    std::get<2>(record) = "rwrite";
+    const LockRequest& t = record;
+    EXPECT_FALSE(lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithlockFlags)
+{
+    MockLock lockManager;
+    // Corrupt the lockflag
+    std::get<4>(record)[0].first = "lock";
+    const LockRequest& t = record;
+    EXPECT_FALSE(lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, ValidationBadTestWithSegmentlength)
+{
+    MockLock lockManager;
+    // Corrupt the Segment length
+    std::get<4>(record)[0].second = 7;
+    const LockRequest& t = record;
+    EXPECT_FALSE(lockManager.isValidLockRequest(t));
+}
+
+TEST_F(LockTest, MultiRequestWithoutConflict)
+{
+    MockLock lockManager;
+    const LockRequests& t = request;
+    EXPECT_FALSE(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;
+    EXPECT_TRUE(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;
+    EXPECT_FALSE(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;
+    EXPECT_TRUE(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
+    EXPECT_FALSE(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
+    EXPECT_FALSE(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
+    EXPECT_FALSE(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
+    EXPECT_TRUE(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
+    EXPECT_FALSE(rc2.first);
+}
+
+TEST_F(LockTest, TestGenerateTransactionIDFunction)
+{
+    MockLock lockManager;
+    uint32_t transactionId1 = lockManager.generateTransactionId();
+    uint32_t transactionId2 = lockManager.generateTransactionId();
+    EXPECT_EQ(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;
+    EXPECT_TRUE(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 = {10};
+    const std::vector<uint32_t>& p = tids;
+    EXPECT_FALSE(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);
+    EXPECT_TRUE(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 = "random";
+    std::pair<SType, SType> ids = std::make_pair(hmcid, sessionid);
+    auto rc = lockManager.isItMyLock(p, ids);
+    EXPECT_FALSE(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);
+    EXPECT_THAT(result, IsEmpty());
+}
+
+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);
+    EXPECT_EQ(result.size(), 1);
+}
+
+} // namespace
+} // namespace crow::ibm_mc_lock
diff --git a/test/include/multipart_test.cpp b/test/include/multipart_test.cpp
new file mode 100644
index 0000000..7ad7d98
--- /dev/null
+++ b/test/include/multipart_test.cpp
@@ -0,0 +1,256 @@
+#include "http/http_request.hpp"
+#include "multipart_parser.hpp"
+
+#include <boost/beast/http/fields.hpp>
+#include <boost/beast/http/message.hpp>
+#include <boost/beast/http/string_body.hpp>
+
+#include <memory>
+#include <string_view>
+#include <system_error>
+#include <vector>
+
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+// IWYU pragma: no_include <boost/beast/http/impl/fields.hpp>
+// IWYU pragma: no_include <boost/intrusive/detail/list_iterator.hpp>
+// IWYU pragma: no_include <boost/intrusive/detail/tree_iterator.hpp>
+
+namespace
+{
+using ::testing::Test;
+
+class MultipartTest : public Test
+{
+  public:
+    boost::beast::http::request<boost::beast::http::string_body> req{};
+    MultipartParser parser;
+    std::error_code ec;
+};
+
+TEST_F(MultipartTest, TestGoodMultipartParser)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "111111111111111111111111112222222222222222222222222222222\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "{\r\n-----------------------------d74496d66958873e123456\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test3\"\r\n\r\n"
+                 "{\r\n--------d74496d6695887}\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    ParserError rc = parser.parse(reqIn);
+    ASSERT_EQ(rc, ParserError::PARSER_SUCCESS);
+
+    EXPECT_EQ(parser.boundary,
+              "\r\n-----------------------------d74496d66958873e");
+    EXPECT_EQ(parser.mime_fields.size(), 3);
+
+    EXPECT_EQ(parser.mime_fields[0].fields.at("Content-Disposition"),
+              "form-data; name=\"Test1\"");
+    EXPECT_EQ(parser.mime_fields[0].content,
+              "111111111111111111111111112222222222222222222222222222222");
+
+    EXPECT_EQ(parser.mime_fields[1].fields.at("Content-Disposition"),
+              "form-data; name=\"Test2\"");
+    EXPECT_EQ(parser.mime_fields[1].content,
+              "{\r\n-----------------------------d74496d66958873e123456");
+    EXPECT_EQ(parser.mime_fields[2].fields.at("Content-Disposition"),
+              "form-data; name=\"Test3\"");
+    EXPECT_EQ(parser.mime_fields[2].content, "{\r\n--------d74496d6695887}");
+}
+
+TEST_F(MultipartTest, TestBadMultipartParser1)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "1234567890\r\n"
+                 "-----------------------------d74496d66958873e\r-\r\n";
+
+    crow::Request reqIn(req, ec);
+    ParserError rc = parser.parse(reqIn);
+    ASSERT_EQ(rc, ParserError::PARSER_SUCCESS);
+
+    EXPECT_EQ(parser.boundary,
+              "\r\n-----------------------------d74496d66958873e");
+    EXPECT_EQ(parser.mime_fields.size(), 1);
+}
+
+TEST_F(MultipartTest, TestBadMultipartParser2)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "abcd\r\n"
+                 "-----------------------------d74496d66958873e-\r\n";
+
+    crow::Request reqIn(req, ec);
+    ParserError rc = parser.parse(reqIn);
+    ASSERT_EQ(rc, ParserError::PARSER_SUCCESS);
+
+    EXPECT_EQ(parser.boundary,
+              "\r\n-----------------------------d74496d66958873e");
+    EXPECT_EQ(parser.mime_fields.size(), 1);
+}
+
+TEST_F(MultipartTest, TestErrorBoundaryFormat)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary+=-----------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "{\"Key1\": 11223333333333333333333333333333333333333333}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_FORMAT);
+}
+
+TEST_F(MultipartTest, TestErrorBoundaryCR)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_CR);
+}
+
+TEST_F(MultipartTest, TestErrorBoundaryLF)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_LF);
+}
+
+TEST_F(MultipartTest, TestErrorBoundaryData)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d7449sd6d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r\n"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_BOUNDARY_DATA);
+}
+
+TEST_F(MultipartTest, TestErrorEmptyHeader)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 ": form-data; name=\"Test1\"\r\n"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_EMPTY_HEADER);
+}
+
+TEST_F(MultipartTest, TestErrorHeaderName)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-!!Disposition: form-data; name=\"Test1\"\r\n"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_NAME);
+}
+
+TEST_F(MultipartTest, TestErrorHeaderValue)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_VALUE);
+}
+
+TEST_F(MultipartTest, TestErrorHeaderEnding)
+{
+    req.set("Content-Type",
+            "multipart/form-data; "
+            "boundary=---------------------------d74496d66958873e");
+
+    req.body() = "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test1\"\r\n\r"
+                 "{\"Key1\": 112233}\r\n"
+                 "-----------------------------d74496d66958873e\r\n"
+                 "Content-Disposition: form-data; name=\"Test2\"\r\n\r\n"
+                 "123456\r\n"
+                 "-----------------------------d74496d66958873e--\r\n";
+
+    crow::Request reqIn(req, ec);
+    EXPECT_EQ(parser.parse(reqIn), ParserError::ERROR_HEADER_ENDING);
+}
+} // namespace
\ No newline at end of file
diff --git a/test/include/openbmc_dbus_rest_test.cpp b/test/include/openbmc_dbus_rest_test.cpp
new file mode 100644
index 0000000..b01e92a
--- /dev/null
+++ b/test/include/openbmc_dbus_rest_test.cpp
@@ -0,0 +1,76 @@
+#include "openbmc_dbus_rest.hpp"
+
+#include <gmock/gmock.h> // IWYU pragma: keep
+#include <gtest/gtest.h> // IWYU pragma: keep
+
+// IWYU pragma: no_include <gtest/gtest-message.h>
+// IWYU pragma: no_include <gtest/gtest-test-part.h>
+// IWYU pragma: no_include "gtest/gtest_pred_impl.h"
+// IWYU pragma: no_include <gmock/gmock-matchers.h>
+
+namespace crow::openbmc_mapper
+{
+namespace
+{
+
+using ::testing::ElementsAre;
+// Also see redfish-core/ut/configfile_test.cpp
+TEST(OpenbmcDbusRestTest, ValidFilenameGood)
+{
+    EXPECT_TRUE(validateFilename("GoodConfigFile"));
+    EXPECT_TRUE(validateFilename("_Underlines_"));
+    EXPECT_TRUE(validateFilename("8675309"));
+    EXPECT_TRUE(validateFilename("-Dashes-"));
+    EXPECT_TRUE(validateFilename("With Spaces"));
+    EXPECT_TRUE(validateFilename("One.Dot"));
+    EXPECT_TRUE(validateFilename("trailingdot."));
+    EXPECT_TRUE(validateFilename("-_ o _-"));
+    EXPECT_TRUE(validateFilename(" "));
+    EXPECT_TRUE(validateFilename(" ."));
+}
+
+// There is no length test yet because validateFilename() does not care yet
+TEST(OpenbmcDbusRestTest, ValidFilenameBad)
+{
+    EXPECT_FALSE(validateFilename(""));
+    EXPECT_FALSE(validateFilename("Bad@file"));
+    EXPECT_FALSE(validateFilename("/../../../../../etc/badpath"));
+    EXPECT_FALSE(validateFilename("/../../etc/badpath"));
+    EXPECT_FALSE(validateFilename("/mydir/configFile"));
+    EXPECT_FALSE(validateFilename("/"));
+    EXPECT_FALSE(validateFilename(".leadingdot"));
+    EXPECT_FALSE(validateFilename("Two..Dots"));
+    EXPECT_FALSE(validateFilename("../../../../../../etc/shadow"));
+    EXPECT_FALSE(validateFilename("."));
+}
+
+TEST(OpenBmcDbusTest, TestArgSplit)
+{
+    // test the basic types
+    EXPECT_THAT(dbusArgSplit("x"), ElementsAre("x"));
+    EXPECT_THAT(dbusArgSplit("y"), ElementsAre("y"));
+    EXPECT_THAT(dbusArgSplit("b"), ElementsAre("b"));
+    EXPECT_THAT(dbusArgSplit("n"), ElementsAre("n"));
+    EXPECT_THAT(dbusArgSplit("q"), ElementsAre("q"));
+    EXPECT_THAT(dbusArgSplit("i"), ElementsAre("i"));
+    EXPECT_THAT(dbusArgSplit("u"), ElementsAre("u"));
+    EXPECT_THAT(dbusArgSplit("x"), ElementsAre("x"));
+    EXPECT_THAT(dbusArgSplit("t"), ElementsAre("t"));
+    EXPECT_THAT(dbusArgSplit("d"), ElementsAre("d"));
+    EXPECT_THAT(dbusArgSplit("h"), ElementsAre("h"));
+    // test arrays
+    EXPECT_THAT(dbusArgSplit("ai"), ElementsAre("ai"));
+    EXPECT_THAT(dbusArgSplit("ax"), ElementsAre("ax"));
+    // test tuples
+    EXPECT_THAT(dbusArgSplit("(sss)"), ElementsAre("(sss)"));
+    EXPECT_THAT(dbusArgSplit("(sss)b"), ElementsAre("(sss)", "b"));
+    EXPECT_THAT(dbusArgSplit("b(sss)"), ElementsAre("b", "(sss)"));
+
+    // Test nested types
+    EXPECT_THAT(dbusArgSplit("a{si}b"), ElementsAre("a{si}", "b"));
+    EXPECT_THAT(dbusArgSplit("a(sss)b"), ElementsAre("a(sss)", "b"));
+    EXPECT_THAT(dbusArgSplit("aa{si}b"), ElementsAre("aa{si}", "b"));
+    EXPECT_THAT(dbusArgSplit("i{si}b"), ElementsAre("i", "{si}", "b"));
+}
+} // namespace
+} // namespace crow::openbmc_mapper