Unit tests for BLE layer class (#33359)
* Unit tests for BLE layer class
* Check for mBleTransport NULL before dereference
* Return false in case of handle error in BLE layer
* Check for NULL UUIDs match
* Test for exceeding max number of BLE connections
* Fix compilation on ESP32
* More compilation fixes
* Mark SetUp and TearDown as overrides
* Update includes
diff --git a/src/ble/BLEEndPoint.cpp b/src/ble/BLEEndPoint.cpp
index ba6400f..0e69e59 100644
--- a/src/ble/BLEEndPoint.cpp
+++ b/src/ble/BLEEndPoint.cpp
@@ -346,7 +346,7 @@
DoCloseCallback(oldState, flags, err);
}
- if ((flags & kBleCloseFlag_SuppressCallback) != 0)
+ if (mBleTransport != nullptr && (flags & kBleCloseFlag_SuppressCallback) != 0)
{
mBleTransport->OnEndPointConnectionClosed(this, err);
}
@@ -367,7 +367,7 @@
DoCloseCallback(oldState, flags, err);
}
- if ((flags & kBleCloseFlag_SuppressCallback) != 0)
+ if (mBleTransport != nullptr && (flags & kBleCloseFlag_SuppressCallback) != 0)
{
mBleTransport->OnEndPointConnectionClosed(this, err);
}
@@ -1290,7 +1290,7 @@
// Take ownership of message buffer
System::PacketBufferHandle full_packet = mBtpEngine.TakeRxPacket();
- ChipLogDebugBleEndPoint(Ble, "reassembled whole msg, len = %d", full_packet->DataLength());
+ ChipLogDebugBleEndPoint(Ble, "reassembled whole msg, len = %u", static_cast<unsigned>(full_packet->DataLength()));
// If we have a message received callback, and end point is not closing...
if (mBleTransport != nullptr && mState != kState_Closing)
diff --git a/src/ble/BleLayer.cpp b/src/ble/BleLayer.cpp
index d4a1e32..de1f845 100644
--- a/src/ble/BleLayer.cpp
+++ b/src/ble/BleLayer.cpp
@@ -22,7 +22,7 @@
* a platform's Bluetooth Low Energy (BLE) implementation and the CHIP
* stack.
*
- * The BleLayer obect accepts BLE data and control input from the
+ * The BleLayer object accepts BLE data and control input from the
* application via a functional interface. It performs the fragmentation
* and reassembly required to transmit CHIP message via a BLE GATT
* characteristic interface, and drives incoming messages up the CHIP
@@ -485,43 +485,24 @@
bool BleLayer::HandleWriteReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
PacketBufferHandle && pBuf)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write received on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId), false, ChipLogError(Ble, "Write received on unknown char"));
+ VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Write received null buffer"));
+
+ // Find matching connection end point.
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+
+ if (endPoint != nullptr)
{
- ChipLogError(Ble, "ble write rcvd on unknown svc id");
- return true;
- }
-
- if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
- {
- if (pBuf.IsNull())
- {
- ChipLogError(Ble, "rcvd null ble write");
- return true;
- }
-
- // Find matching connection end point.
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
-
- if (endPoint != nullptr)
- {
- CHIP_ERROR status = endPoint->Receive(std::move(pBuf));
- if (status != CHIP_NO_ERROR)
- {
- ChipLogError(Ble, "BLEEndPoint rcv failed, err = %" CHIP_ERROR_FORMAT, status.Format());
- }
- }
- else
- {
- CHIP_ERROR status = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
- if (status != CHIP_NO_ERROR)
- {
- ChipLogError(Ble, "failed handle new chip BLE connection, status = %" CHIP_ERROR_FORMAT, status.Format());
- }
- }
+ CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
+ VerifyOrReturnError(err == CHIP_NO_ERROR, false,
+ ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}
else
{
- ChipLogError(Ble, "ble write rcvd on unknown char");
+ CHIP_ERROR err = HandleBleTransportConnectionInitiated(connObj, std::move(pBuf));
+ VerifyOrReturnError(err == CHIP_NO_ERROR, false,
+ ChipLogError(Ble, "Handle new BLE connection failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}
return true;
@@ -530,197 +511,102 @@
bool BleLayer::HandleIndicationReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
PacketBufferHandle && pBuf)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication received on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId), false, ChipLogError(Ble, "Indication received on unknown char"));
+ VerifyOrReturnError(!pBuf.IsNull(), false, ChipLogError(Ble, "Indication received null buffer"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
- {
- if (pBuf.IsNull())
- {
- ChipLogError(Ble, "rcvd null ble indication");
- return true;
- }
+ // Find matching connection end point.
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received indication"));
- // find matching connection end point.
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
-
- if (endPoint != nullptr)
- {
- CHIP_ERROR status = endPoint->Receive(std::move(pBuf));
- if (status != CHIP_NO_ERROR)
- {
- ChipLogError(Ble, "BLEEndPoint rcv failed, err = %" CHIP_ERROR_FORMAT, status.Format());
- }
- }
- else
- {
- ChipLogDetail(Ble, "no endpoint for rcvd indication");
- }
- }
- else
- {
- ChipLogError(Ble, "ble ind rcvd on unknown char");
- }
+ CHIP_ERROR err = endPoint->Receive(std::move(pBuf));
+ VerifyOrReturnError(err == CHIP_NO_ERROR, false, ChipLogError(Ble, "Receive failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
return true;
}
bool BleLayer::HandleWriteConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Write confirmation on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId), false, ChipLogError(Ble, "Write confirmation on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_1_ID, charId))
- {
- HandleAckReceived(connObj);
- }
- else
- {
- ChipLogError(Ble, "ble write con rcvd on unknown char");
- }
-
+ HandleAckReceived(connObj);
return true;
}
bool BleLayer::HandleIndicationConfirmation(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Indication confirmation on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId), false,
+ ChipLogError(Ble, "Indication confirmation on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId))
- {
- HandleAckReceived(connObj);
- }
- else
- {
- ChipLogError(Ble, "ble ind con rcvd on unknown char");
- }
-
+ HandleAckReceived(connObj);
return true;
}
void BleLayer::HandleAckReceived(BLE_CONNECTION_OBJECT connObj)
{
- // find matching connection end point.
+ // Find matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for received ack"));
- if (endPoint != nullptr)
- {
- CHIP_ERROR status = endPoint->HandleGattSendConfirmationReceived();
-
- if (status != CHIP_NO_ERROR)
- {
- ChipLogError(Ble, "endpoint conf recvd failed, err = %" CHIP_ERROR_FORMAT, status.Format());
- }
- }
- else
- {
- ChipLogError(Ble, "no endpoint for BLE sent data ack");
- }
+ CHIP_ERROR err = endPoint->HandleGattSendConfirmationReceived();
+ VerifyOrReturn(err == CHIP_NO_ERROR,
+ ChipLogError(Ble, "Send ack confirmation failed, err = %" CHIP_ERROR_FORMAT, err.Format()));
}
bool BleLayer::HandleSubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe received on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
+ ChipLogError(Ble, "Subscribe received on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
- {
- // Find end point already associated with BLE connection, if any.
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ // Find end point already associated with BLE connection, if any.
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for received subscribe"));
- if (endPoint != nullptr)
- {
- endPoint->HandleSubscribeReceived();
- }
- else
- {
- ChipLogError(Ble, "no endpoint for sub recvd");
- }
- }
-
+ endPoint->HandleSubscribeReceived();
return true;
}
bool BleLayer::HandleSubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Subscribe complete on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
+ ChipLogError(Ble, "Subscribe complete on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
- {
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for subscribe complete"));
- if (endPoint != nullptr)
- {
- endPoint->HandleSubscribeComplete();
- }
- else
- {
- ChipLogError(Ble, "no endpoint for sub complete");
- }
- }
-
+ endPoint->HandleSubscribeComplete();
return true;
}
bool BleLayer::HandleUnsubscribeReceived(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe received on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
+ ChipLogError(Ble, "Unsubscribe received on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
- {
- // Find end point already associated with BLE connection, if any.
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ // Find end point already associated with BLE connection, if any.
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe received"));
- if (endPoint != nullptr)
- {
- endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
- }
- else
- {
- ChipLogError(Ble, "no endpoint for unsub recvd");
- }
- }
-
+ endPoint->DoClose(kBleCloseFlag_AbortTransmission, BLE_ERROR_CENTRAL_UNSUBSCRIBED);
return true;
}
bool BleLayer::HandleUnsubscribeComplete(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId)
{
- if (!UUIDsMatch(&CHIP_BLE_SVC_ID, svcId))
- {
- return false;
- }
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_SVC_ID, svcId), false, ChipLogError(Ble, "Unsubscribe complete on unknown svc"));
+ VerifyOrReturnError(UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId), false,
+ ChipLogError(Ble, "Unsubscribe complete on unknown char"));
- if (UUIDsMatch(&CHIP_BLE_CHAR_2_ID, charId) || UUIDsMatch(&CHIP_BLE_CHAR_3_ID, charId))
- {
- // Find end point already associated with BLE connection, if any.
- BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ // Find end point already associated with BLE connection, if any.
+ BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturnError(endPoint != nullptr, false, ChipLogDetail(Ble, "No endpoint for unsubscribe complete"));
- if (endPoint != nullptr)
- {
- endPoint->HandleUnsubscribeComplete();
- }
- else
- {
- ChipLogError(Ble, "no endpoint for unsub complete");
- }
- }
-
+ endPoint->HandleUnsubscribeComplete();
return true;
}
@@ -728,19 +614,17 @@
{
// BLE connection has failed somehow, we must find and abort matching connection end point.
BLEEndPoint * endPoint = sBLEEndPointPool.Find(connObj);
+ VerifyOrReturn(endPoint != nullptr, ChipLogDetail(Ble, "No endpoint for connection error"));
- if (endPoint != nullptr)
+ if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
{
- if (err == BLE_ERROR_GATT_UNSUBSCRIBE_FAILED && endPoint->IsUnsubscribePending())
- {
- // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
- // stops unsubscribe timer.
- endPoint->Free();
- }
- else
- {
- endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
- }
+ // If end point was already closed and just waiting for unsubscribe to complete, free it. Call to Free()
+ // stops unsubscribe timer.
+ endPoint->Free();
+ }
+ else
+ {
+ endPoint->DoClose(kBleCloseFlag_AbortTransmission, err);
}
}
diff --git a/src/ble/BleLayer.h b/src/ble/BleLayer.h
index bad3ab3..e7d619f 100644
--- a/src/ble/BleLayer.h
+++ b/src/ble/BleLayer.h
@@ -327,7 +327,6 @@
// Private functions:
void HandleAckReceived(BLE_CONNECTION_OBJECT connObj);
- void DriveSending();
CHIP_ERROR HandleBleTransportConnectionInitiated(BLE_CONNECTION_OBJECT connObj, System::PacketBufferHandle && pBuf);
static BleTransportProtocolVersion GetHighestSupportedProtocolVersion(const BleTransportCapabilitiesRequestMessage & reqMsg);
diff --git a/src/ble/tests/BUILD.gn b/src/ble/tests/BUILD.gn
index 687ad7b..ac897ab 100644
--- a/src/ble/tests/BUILD.gn
+++ b/src/ble/tests/BUILD.gn
@@ -22,11 +22,15 @@
test_sources = [
"TestBleErrorStr.cpp",
+ "TestBleLayer.cpp",
"TestBleUUID.cpp",
"TestBtpEngine.cpp",
]
cflags = [ "-Wconversion" ]
- public_deps = [ "${chip_root}/src/ble" ]
+ public_deps = [
+ "${chip_root}/src/ble",
+ "${chip_root}/src/platform",
+ ]
}
diff --git a/src/ble/tests/TestBleLayer.cpp b/src/ble/tests/TestBleLayer.cpp
new file mode 100644
index 0000000..9b79037
--- /dev/null
+++ b/src/ble/tests/TestBleLayer.cpp
@@ -0,0 +1,400 @@
+/*
+ *
+ * Copyright (c) 2024 Project CHIP Authors
+ *
+ * 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 <cstring>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include <gtest/gtest.h>
+
+#include <lib/core/CHIPError.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/Span.h>
+#include <lib/support/TypeTraits.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <system/SystemLayer.h>
+#include <system/SystemPacketBuffer.h>
+
+#define _CHIP_BLE_BLE_H
+#include <ble/BleApplicationDelegate.h>
+#include <ble/BleLayer.h>
+#include <ble/BleLayerDelegate.h>
+#include <ble/BlePlatformDelegate.h>
+
+namespace chip {
+namespace Ble {
+
+namespace {
+
+constexpr ChipBleUUID uuidZero{};
+constexpr ChipBleUUID uuidSvc = { { 0x00, 0x00, 0xFF, 0xF6, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34,
+ 0xFB } };
+constexpr ChipBleUUID uuidChar1 = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D,
+ 0x11 } };
+constexpr ChipBleUUID uuidChar2 = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F, 0x9D,
+ 0x12 } };
+constexpr ChipBleUUID uuidChar3 = { { 0x64, 0x63, 0x02, 0x38, 0x87, 0x72, 0x45, 0xF2, 0xB8, 0x7D, 0x74, 0x8A, 0x83, 0x21, 0x8F,
+ 0x04 } };
+
+}; // namespace
+
+class TestBleLayer : public BleLayer,
+ private BleApplicationDelegate,
+ private BleLayerDelegate,
+ private BlePlatformDelegate,
+ public ::testing::Test
+{
+public:
+ static void SetUpTestSuite()
+ {
+ ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR);
+ ASSERT_EQ(DeviceLayer::SystemLayer().Init(), CHIP_NO_ERROR);
+ }
+
+ static void TearDownTestSuite()
+ {
+ DeviceLayer::SystemLayer().Shutdown();
+ chip::Platform::MemoryShutdown();
+ }
+
+ void SetUp() override
+ {
+ ASSERT_EQ(Init(this, this, &DeviceLayer::SystemLayer()), CHIP_NO_ERROR);
+ mBleTransport = this;
+ }
+
+ void TearDown() override
+ {
+ mBleTransport = nullptr;
+ Shutdown();
+ }
+
+ // Return unique BLE connection object for each call.
+ template <typename T = BLE_CONNECTION_OBJECT>
+ BLE_CONNECTION_OBJECT GetConnectionObject()
+ {
+ T conn = BLE_CONNECTION_UNINITIALIZED;
+
+ if constexpr (std::is_pointer_v<T>)
+ {
+ conn = reinterpret_cast<T>(&mNumConnection + mNumConnection);
+ }
+ else
+ {
+ conn = static_cast<T>(mNumConnection);
+ }
+
+ mNumConnection++;
+ return conn;
+ }
+
+ // Passing capabilities request message to HandleWriteReceived should create
+ // new BLE endpoint which later can be used to receive more data.
+ bool HandleWriteReceivedCapabilitiesRequest(BLE_CONNECTION_OBJECT connObj)
+ {
+ constexpr uint8_t capReq[] = { 0x65, 0x6c, 0x54, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x06 };
+ auto buf = System::PacketBufferHandle::NewWithData(capReq, sizeof(capReq));
+ return HandleWriteReceived(connObj, &uuidSvc, &uuidChar1, std::move(buf));
+ }
+
+ // Processing subscription request after capabilities request should finalize
+ // connection establishment.
+ bool HandleSubscribeReceivedOnChar2(BLE_CONNECTION_OBJECT connObj)
+ {
+ return HandleSubscribeReceived(connObj, &uuidSvc, &uuidChar2);
+ }
+
+ ///
+ // Implementation of BleApplicationDelegate
+
+ void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT connObj) override {}
+
+ ///
+ // Implementation of BleLayerDelegate
+
+ void OnBleConnectionComplete(BLEEndPoint * endpoint) override {}
+ void OnBleConnectionError(CHIP_ERROR err) override {}
+ void OnEndPointConnectComplete(BLEEndPoint * endPoint, CHIP_ERROR err) override {}
+ void OnEndPointMessageReceived(BLEEndPoint * endPoint, System::PacketBufferHandle && msg) override {}
+ void OnEndPointConnectionClosed(BLEEndPoint * endPoint, CHIP_ERROR err) override {}
+ CHIP_ERROR SetEndPoint(BLEEndPoint * endPoint) override { return CHIP_NO_ERROR; }
+
+ ///
+ // Implementation of BlePlatformDelegate
+
+ bool SubscribeCharacteristic(BLE_CONNECTION_OBJECT, const ChipBleUUID *, const ChipBleUUID *) override { return true; }
+ bool UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT, const ChipBleUUID *, const ChipBleUUID *) override { return true; }
+ bool CloseConnection(BLE_CONNECTION_OBJECT connObj) override { return true; }
+ uint16_t GetMTU(BLE_CONNECTION_OBJECT connObj) const override { return 0; }
+ bool SendIndication(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle pBuf) override
+ {
+ return true;
+ }
+ bool SendWriteRequest(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle pBuf) override
+ {
+ return true;
+ }
+ bool SendReadRequest(BLE_CONNECTION_OBJECT connObj, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+ PacketBufferHandle pBuf) override
+ {
+ return true;
+ }
+ bool SendReadResponse(BLE_CONNECTION_OBJECT connObj, BLE_READ_REQUEST_CONTEXT requestContext, const ChipBleUUID * svcId,
+ const ChipBleUUID * charId) override
+ {
+ return true;
+ }
+
+private:
+ unsigned int mNumConnection = 0;
+};
+
+TEST_F(TestBleLayer, CheckBleTransportCapabilitiesRequestMessage)
+{
+ auto buf = System::PacketBufferHandle::New(100);
+ ASSERT_FALSE(buf.IsNull());
+
+ BleTransportCapabilitiesRequestMessage msg{};
+ msg.SetSupportedProtocolVersion(0, CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION);
+ msg.SetSupportedProtocolVersion(1, CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION + 1);
+ msg.mMtu = 200;
+ msg.mWindowSize = BLE_MAX_RECEIVE_WINDOW_SIZE;
+
+ ASSERT_EQ(msg.Encode(buf), CHIP_NO_ERROR);
+ ChipLogByteSpan(Test, ByteSpan(buf->Start(), buf->DataLength()));
+
+ BleTransportCapabilitiesRequestMessage msgVerify;
+ ASSERT_EQ(BleTransportCapabilitiesRequestMessage::Decode(buf, msgVerify), CHIP_NO_ERROR);
+ EXPECT_EQ(memcmp(msg.mSupportedProtocolVersions, msgVerify.mSupportedProtocolVersions, sizeof(msg.mSupportedProtocolVersions)),
+ 0);
+ EXPECT_EQ(msg.mMtu, msgVerify.mMtu);
+ EXPECT_EQ(msg.mWindowSize, msgVerify.mWindowSize);
+}
+
+TEST_F(TestBleLayer, CheckBleTransportCapabilitiesResponseMessage)
+{
+ auto buf = System::PacketBufferHandle::New(100);
+ ASSERT_FALSE(buf.IsNull());
+
+ BleTransportCapabilitiesResponseMessage msg{};
+ msg.mSelectedProtocolVersion = CHIP_BLE_TRANSPORT_PROTOCOL_MIN_SUPPORTED_VERSION;
+ msg.mFragmentSize = 200;
+ msg.mWindowSize = BLE_MAX_RECEIVE_WINDOW_SIZE;
+
+ EXPECT_EQ(msg.Encode(buf), CHIP_NO_ERROR);
+ ChipLogByteSpan(Test, ByteSpan(buf->Start(), buf->DataLength()));
+
+ BleTransportCapabilitiesResponseMessage msgVerify;
+ ASSERT_EQ(BleTransportCapabilitiesResponseMessage::Decode(buf, msgVerify), CHIP_NO_ERROR);
+ EXPECT_EQ(msg.mSelectedProtocolVersion, msgVerify.mSelectedProtocolVersion);
+ EXPECT_EQ(msg.mFragmentSize, msgVerify.mFragmentSize);
+ EXPECT_EQ(msg.mWindowSize, msgVerify.mWindowSize);
+}
+
+TEST_F(TestBleLayer, HandleWriteReceivedCapabilitiesRequest)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+}
+
+TEST_F(TestBleLayer, HandleSubscribeReceivedInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleSubscribeReceived(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleSubscribeReceived(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleSubscribeReceived)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ EXPECT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+}
+
+TEST_F(TestBleLayer, HandleSubscribeCompleteInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleSubscribeComplete(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleSubscribeComplete(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleSubscribeComplete)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ ASSERT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+
+ EXPECT_TRUE(HandleSubscribeComplete(connObj, &uuidSvc, &uuidChar2));
+}
+
+TEST_F(TestBleLayer, HandleUnsubscribeReceivedInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleUnsubscribeReceived(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleUnsubscribeReceived(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleUnsubscribeReceived)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ ASSERT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+
+ EXPECT_TRUE(HandleUnsubscribeReceived(connObj, &uuidSvc, &uuidChar2));
+}
+
+TEST_F(TestBleLayer, HandleUnsubscribeCompleteInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleUnsubscribeComplete(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleUnsubscribeComplete(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleUnsubscribeComplete)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ ASSERT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+
+ EXPECT_TRUE(HandleUnsubscribeComplete(connObj, &uuidSvc, &uuidChar2));
+}
+
+TEST_F(TestBleLayer, HandleWriteReceivedInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ auto buf = System::PacketBufferHandle::New(0);
+ ASSERT_FALSE(buf.IsNull());
+
+ EXPECT_FALSE(HandleWriteReceived(connObj, &uuidZero, &uuidZero, buf.Retain()));
+ EXPECT_FALSE(HandleWriteReceived(connObj, &uuidSvc, &uuidChar3, std::move(buf)));
+}
+
+TEST_F(TestBleLayer, HandleWriteReceived)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ ASSERT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+
+ constexpr uint8_t data[] = { to_underlying(BtpEngine::HeaderFlags::kStartMessage) |
+ to_underlying(BtpEngine::HeaderFlags::kEndMessage),
+ 0x00, 0x01, 0x00, 0xff };
+ auto buf = System::PacketBufferHandle::NewWithData(data, sizeof(data));
+ ASSERT_FALSE(buf.IsNull());
+
+ EXPECT_TRUE(HandleWriteReceived(connObj, &uuidSvc, &uuidChar1, std::move(buf)));
+}
+
+TEST_F(TestBleLayer, HandleWriteConfirmationInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleWriteConfirmation(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleWriteConfirmation(connObj, &uuidSvc, &uuidChar2));
+}
+
+TEST_F(TestBleLayer, HandleWriteConfirmationUninitialized)
+{
+ ASSERT_FALSE(HandleWriteReceivedCapabilitiesRequest(BLE_CONNECTION_UNINITIALIZED));
+}
+
+TEST_F(TestBleLayer, HandleWriteConfirmation)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+
+ EXPECT_TRUE(HandleWriteConfirmation(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleIndicationReceivedInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ auto buf = System::PacketBufferHandle::New(0);
+ ASSERT_FALSE(buf.IsNull());
+
+ EXPECT_FALSE(HandleIndicationReceived(connObj, &uuidZero, &uuidZero, buf.Retain()));
+ EXPECT_FALSE(HandleIndicationReceived(connObj, &uuidSvc, &uuidChar1, std::move(buf)));
+}
+
+TEST_F(TestBleLayer, HandleIndicationReceived)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+ ASSERT_TRUE(HandleSubscribeReceivedOnChar2(connObj));
+
+ constexpr uint8_t data[] = { to_underlying(BtpEngine::HeaderFlags::kStartMessage) |
+ to_underlying(BtpEngine::HeaderFlags::kEndMessage),
+ 0x00, 0x01, 0x00, 0xff };
+ auto buf = System::PacketBufferHandle::NewWithData(data, sizeof(data));
+ ASSERT_FALSE(buf.IsNull());
+
+ EXPECT_TRUE(HandleIndicationReceived(connObj, &uuidSvc, &uuidChar2, std::move(buf)));
+}
+
+TEST_F(TestBleLayer, HandleIndicationConfirmationInvalidUUID)
+{
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleIndicationConfirmation(connObj, &uuidZero, &uuidZero));
+ EXPECT_FALSE(HandleIndicationConfirmation(connObj, &uuidSvc, &uuidChar1));
+}
+
+TEST_F(TestBleLayer, HandleIndicationConfirmation)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+
+ EXPECT_TRUE(HandleIndicationConfirmation(connObj, &uuidSvc, &uuidChar2));
+}
+
+TEST_F(TestBleLayer, HandleConnectionError)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+
+ HandleConnectionError(connObj, CHIP_ERROR_ACCESS_DENIED);
+}
+
+TEST_F(TestBleLayer, CloseBleConnectionUninitialized)
+{
+ CloseBleConnection(BLE_CONNECTION_UNINITIALIZED);
+}
+
+TEST_F(TestBleLayer, CloseBleConnection)
+{
+ auto connObj = GetConnectionObject();
+ ASSERT_TRUE(HandleWriteReceivedCapabilitiesRequest(connObj));
+
+ CloseBleConnection(connObj);
+}
+
+TEST_F(TestBleLayer, ExceedBleConnectionEndPointLimit)
+{
+ for (size_t i = 0; i < BLE_LAYER_NUM_BLE_ENDPOINTS; i++)
+ {
+ // Saturate BLE end-point pool
+ EXPECT_TRUE(HandleWriteReceivedCapabilitiesRequest(GetConnectionObject()));
+ }
+
+ auto connObj = GetConnectionObject();
+ EXPECT_FALSE(HandleWriteReceivedCapabilitiesRequest(connObj));
+}
+
+}; // namespace Ble
+}; // namespace chip
diff --git a/src/ble/tests/TestBleUUID.cpp b/src/ble/tests/TestBleUUID.cpp
index 40e425d..4dbc6dd 100644
--- a/src/ble/tests/TestBleUUID.cpp
+++ b/src/ble/tests/TestBleUUID.cpp
@@ -34,6 +34,12 @@
namespace {
+TEST(TestBleUUID, CheckUUIDsMatch_NULL)
+{
+ // Test that NULL pointer UUIDs are not equal
+ EXPECT_FALSE(UUIDsMatch(nullptr, nullptr));
+}
+
TEST(TestBleUUID, CheckStringToUUID_ChipUUID)
{
// Test positive scenario - CHIP Service UUID