BTP engine unit test  (#32897)

* Port BTP engine test from OpenWeave project

* Copyrights from origin project
diff --git a/src/ble/tests/BUILD.gn b/src/ble/tests/BUILD.gn
index 5bf0660..687ad7b 100644
--- a/src/ble/tests/BUILD.gn
+++ b/src/ble/tests/BUILD.gn
@@ -23,6 +23,7 @@
   test_sources = [
     "TestBleErrorStr.cpp",
     "TestBleUUID.cpp",
+    "TestBtpEngine.cpp",
   ]
 
   cflags = [ "-Wconversion" ]
diff --git a/src/ble/tests/TestBtpEngine.cpp b/src/ble/tests/TestBtpEngine.cpp
new file mode 100644
index 0000000..945c794
--- /dev/null
+++ b/src/ble/tests/TestBtpEngine.cpp
@@ -0,0 +1,181 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *    Copyright (c) 2018 Google LLC.
+ *    Copyright (c) 2018 Nest Labs, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <cstdint>
+#include <numeric>
+
+#include <ble/BleLayer.h>
+#include <ble/BtpEngine.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+#include <gtest/gtest.h>
+
+using namespace chip;
+using namespace chip::Ble;
+
+namespace {
+
+class TestBtpEngine : public ::testing::Test
+{
+public:
+    static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
+    static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
+
+    void SetUp()
+    {
+        ASSERT_EQ(mBtpEngine.Init(nullptr, false), CHIP_NO_ERROR);
+        ChipLogDetail(Test, "### Initial BTP Engine State:");
+        mBtpEngine.LogState();
+    }
+
+    void TearDown()
+    {
+        ChipLogDetail(Test, "### Final BTP Engine State:");
+        mBtpEngine.LogState();
+    }
+
+    Ble::BtpEngine mBtpEngine;
+};
+
+TEST_F(TestBtpEngine, HandleCharacteristicReceivedOnePacket)
+{
+    constexpr uint8_t packetData0[] = {
+        to_underlying(BtpEngine::HeaderFlags::kStartMessage) | to_underlying(BtpEngine::HeaderFlags::kEndMessage),
+        0x01,
+        0x01,
+        0x00,
+        0xff, // payload
+    };
+
+    auto packet0 = System::PacketBufferHandle::NewWithData(packetData0, sizeof(packetData0));
+    EXPECT_EQ(packet0->DataLength(), 5);
+
+    SequenceNumber_t receivedAck;
+    bool didReceiveAck;
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet0), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_Complete);
+}
+
+TEST_F(TestBtpEngine, HandleCharacteristicReceivedTwoPacket)
+{
+    constexpr uint8_t packetData0[] = { to_underlying(BtpEngine::HeaderFlags::kStartMessage), 0x01, 0x02, 0x00, 0xfe };
+    constexpr uint8_t packetData1[] = { to_underlying(BtpEngine::HeaderFlags::kEndMessage), 0x02, 0xff };
+
+    auto packet0 = System::PacketBufferHandle::NewWithData(packetData0, sizeof(packetData0));
+    EXPECT_EQ(packet0->DataLength(), 5);
+
+    SequenceNumber_t receivedAck;
+    bool didReceiveAck;
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet0), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_InProgress);
+
+    auto packet1 = System::PacketBufferHandle::NewWithData(packetData1, sizeof(packetData1));
+    EXPECT_EQ(packet1->DataLength(), 3);
+
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet1), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_Complete);
+}
+
+TEST_F(TestBtpEngine, HandleCharacteristicReceivedThreePacket)
+{
+    constexpr uint8_t packetData0[] = { to_underlying(BtpEngine::HeaderFlags::kStartMessage), 0x01, 0x03, 0x00, 0xfd };
+    constexpr uint8_t packetData1[] = { to_underlying(BtpEngine::HeaderFlags::kContinueMessage), 0x02, 0xfe };
+    constexpr uint8_t packetData2[] = { to_underlying(BtpEngine::HeaderFlags::kEndMessage), 0x03, 0xff };
+
+    auto packet0 = System::PacketBufferHandle::NewWithData(packetData0, sizeof(packetData0));
+    EXPECT_EQ(packet0->DataLength(), 5);
+
+    SequenceNumber_t receivedAck;
+    bool didReceiveAck;
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet0), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_InProgress);
+
+    auto packet1 = System::PacketBufferHandle::NewWithData(packetData1, sizeof(packetData1));
+    EXPECT_EQ(packet1->DataLength(), 3);
+
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet1), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_InProgress);
+
+    auto packet2 = System::PacketBufferHandle::NewWithData(packetData2, sizeof(packetData2));
+    EXPECT_EQ(packet2->DataLength(), 3);
+
+    EXPECT_EQ(mBtpEngine.HandleCharacteristicReceived(std::move(packet2), receivedAck, didReceiveAck), CHIP_NO_ERROR);
+    EXPECT_EQ(mBtpEngine.RxState(), BtpEngine::kState_Complete);
+}
+
+TEST_F(TestBtpEngine, HandleCharacteristicSendOnePacket)
+{
+    auto packet0 = System::PacketBufferHandle::New(10);
+    packet0->SetDataLength(1);
+
+    auto data0 = packet0->Start();
+    ASSERT_NE(data0, nullptr);
+    std::iota(data0, data0 + 1, 0);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(packet0.Retain(), false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_Complete);
+    EXPECT_EQ(packet0->DataLength(), 5);
+}
+
+TEST_F(TestBtpEngine, HandleCharacteristicSendTwoPacket)
+{
+    auto packet0 = System::PacketBufferHandle::New(30);
+    packet0->SetDataLength(30);
+
+    auto data0 = packet0->Start();
+    ASSERT_NE(data0, nullptr);
+    std::iota(data0, data0 + 30, 0);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(packet0.Retain(), false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_InProgress);
+    EXPECT_EQ(packet0->DataLength(), 20);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(nullptr, false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_Complete);
+    EXPECT_EQ(packet0->DataLength(), 16);
+}
+
+// Send 40-byte payload.
+// Packet0: 4 byte header + 16 byte payload
+// Packet1: 2 byte header + 18 byte payload
+// Packet2: 2 byte header + 6 byte payload
+TEST_F(TestBtpEngine, HandleCharacteristicSendThreePacket)
+{
+    auto packet0 = System::PacketBufferHandle::New(40);
+    packet0->SetDataLength(40);
+
+    auto data0 = packet0->Start();
+    ASSERT_NE(data0, nullptr);
+    std::iota(data0, data0 + 40, 0);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(packet0.Retain(), false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_InProgress);
+    EXPECT_EQ(packet0->DataLength(), 20);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(nullptr, false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_InProgress);
+    EXPECT_EQ(packet0->DataLength(), 20);
+
+    EXPECT_TRUE(mBtpEngine.HandleCharacteristicSend(nullptr, false));
+    EXPECT_EQ(mBtpEngine.TxState(), BtpEngine::kState_Complete);
+    EXPECT_EQ(packet0->DataLength(), 8);
+}
+
+} // namespace