Add write roundtrip test (#8169)
* Refactor TestWriteInteraction to use a MessagingContext.
This allows us to test more details of the messages being sent.
* Add a roundtrip test to TestWriteInteraction.
Various fixups needed for that:
1) Make InteractionModelEngine::Shutdown actually remove the object as
an unsolicited message handler.
2) Initialize WriteHandler's state properly so it's not random whether
we think we have available WriteHandlers.
3) Fix TestWriteInteraction::AddAttributeDataElement to use the right
tag (2, not 1) for its data.
4) Stop trying to run AppTests in QEMU, because of linking/compilation issues
in that setup.
diff --git a/scripts/tests/esp32_qemu_tests.sh b/scripts/tests/esp32_qemu_tests.sh
index da4bc96..92bc114 100755
--- a/scripts/tests/esp32_qemu_tests.sh
+++ b/scripts/tests/esp32_qemu_tests.sh
@@ -42,16 +42,16 @@
fi
really_run_suite() {
- idf scripts/tools/qemu_run_test.sh src/test_driver/esp32/build/chip "$1" "$2"
+ idf scripts/tools/qemu_run_test.sh src/test_driver/esp32/build/chip "$@"
}
run_suite() {
if [[ -d "${log_dir}" ]]; then
suite=${1%.a}
suite=${suite#lib}
- really_run_suite "$1" "$2" |& tee "$log_dir/$suite.log"
+ really_run_suite "$@" |& tee "$log_dir/$suite.log"
else
- really_run_suite "$1" "$2"
+ really_run_suite "$@"
fi
}
@@ -61,7 +61,15 @@
SUITES=(
)
-run_suite libAppTests.a
+# TODO: libAppTests depends on MessagingTestHelpers, which depends on
+# NetworkTestHelpers. That sort of depends on InetTestHelpers or
+# equivalent (to provide gSystemLayer, gInet, InitNetwork(),
+# ShutdownNetwork()) but there's only a POSIX implementation of that
+# last, which does not compile on ESP32. Need to figure out how to
+# make that work. See comments below for the transport layer tests,
+# which have the same issue.
+# run_suite libAppTests.a -lMessagingTestHelpers -lNetworkTestHelpers
+
run_suite libASN1Tests.a
run_suite libBleLayerTests.a
run_suite libCoreTests.a
diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp
index 7697bfe..73b87bb 100644
--- a/src/app/InteractionModelEngine.cpp
+++ b/src/app/InteractionModelEngine.cpp
@@ -116,6 +116,8 @@
}
mpNextAvailableClusterInfo = nullptr;
+
+ mpExchangeMgr->UnregisterUnsolicitedMessageHandlerForProtocol(Protocols::InteractionModel::Id);
}
CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apCommandSender)
diff --git a/src/app/WriteHandler.h b/src/app/WriteHandler.h
index cd731f9..2f47665 100644
--- a/src/app/WriteHandler.h
+++ b/src/app/WriteHandler.h
@@ -106,7 +106,7 @@
InteractionModelDelegate * mpDelegate = nullptr;
WriteResponse::Builder mWriteResponseBuilder;
System::PacketBufferTLVWriter mMessageWriter;
- State mState;
+ State mState = State::Uninitialized;
};
} // namespace app
} // namespace chip
diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn
index 738f4dd..5305388 100644
--- a/src/app/tests/BUILD.gn
+++ b/src/app/tests/BUILD.gn
@@ -41,7 +41,9 @@
"${chip_root}/src/app",
"${chip_root}/src/app/util:device_callbacks_manager",
"${chip_root}/src/lib/core",
+ "${chip_root}/src/messaging/tests:helpers",
"${chip_root}/src/protocols",
+ "${chip_root}/src/transport/raw/tests:helpers",
"${nlunit_test_root}:nlunit-test",
]
}
diff --git a/src/app/tests/TestWriteInteraction.cpp b/src/app/tests/TestWriteInteraction.cpp
index 3396786..84fcfc5 100644
--- a/src/app/tests/TestWriteInteraction.cpp
+++ b/src/app/tests/TestWriteInteraction.cpp
@@ -24,6 +24,7 @@
#include <messaging/ExchangeContext.h>
#include <messaging/ExchangeMgr.h>
#include <messaging/Flags.h>
+#include <messaging/tests/MessagingContext.h>
#include <platform/CHIPDeviceLayer.h>
#include <protocols/secure_channel/MessageCounterManager.h>
#include <protocols/secure_channel/PASESession.h>
@@ -33,16 +34,17 @@
#include <system/TLVPacketBufferBackingStore.h>
#include <transport/SecureSessionMgr.h>
#include <transport/raw/UDP.h>
+#include <transport/raw/tests/NetworkTestHelpers.h>
#include <nlunit-test.h>
namespace {
-chip::System::Layer gSystemLayer;
-chip::SecureSessionMgr gSessionManager;
-chip::Messaging::ExchangeManager gExchangeManager;
-chip::TransportMgr<chip::Transport::UDP> gTransportManager;
-chip::secure_channel::MessageCounterManager gMessageCounterManager;
-chip::Transport::AdminId gAdminId = 0;
+chip::TransportMgrBase gTransportManager;
+chip::Test::LoopbackTransport gLoopback;
+
+using TestContext = chip::Test::MessagingContext;
+TestContext sContext;
+
} // namespace
namespace chip {
namespace app {
@@ -51,6 +53,7 @@
public:
static void TestWriteClient(nlTestSuite * apSuite, void * apContext);
static void TestWriteHandler(nlTestSuite * apSuite, void * apContext);
+ static void TestWriteRoundtrip(nlTestSuite * apSuite, void * apContext);
private:
static void AddAttributeDataElement(nlTestSuite * apSuite, void * apContext, WriteClient & aWriteClient);
@@ -86,7 +89,7 @@
chip::TLV::TLVWriter * writer = aWriteClient.GetAttributeDataElementTLVWriter();
- err = writer->PutBoolean(chip::TLV::ContextTag(1), true);
+ err = writer->PutBoolean(chip::TLV::ContextTag(chip::app::AttributeDataElement::kCsTag_Data), true);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
err = aWriteClient.FinishAttribute();
@@ -198,18 +201,21 @@
void TestWriteInteraction::TestWriteClient(nlTestSuite * apSuite, void * apContext)
{
+ TestContext & ctx = *static_cast<TestContext *>(apContext);
+
CHIP_ERROR err = CHIP_NO_ERROR;
app::WriteClient writeClient;
chip::app::InteractionModelDelegate delegate;
System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
- err = writeClient.Init(&gExchangeManager, &delegate);
+ err = writeClient.Init(&ctx.GetExchangeManager(), &delegate);
NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
AddAttributeDataElement(apSuite, apContext, writeClient);
- err = writeClient.SendWriteRequest(kTestDeviceNodeId, gAdminId, nullptr);
- NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED);
+ SecureSessionHandle session = ctx.GetSessionLocalToPeer();
+ err = writeClient.SendWriteRequest(ctx.GetDestinationNodeId(), ctx.GetAdminId(), &session);
+ NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
GenerateWriteResponse(apSuite, apContext, buf);
@@ -221,6 +227,8 @@
void TestWriteInteraction::TestWriteHandler(nlTestSuite * apSuite, void * apContext)
{
+ TestContext & ctx = *static_cast<TestContext *>(apContext);
+
CHIP_ERROR err = CHIP_NO_ERROR;
app::WriteHandler writeHandler;
@@ -236,43 +244,72 @@
AddAttributeStatus(apSuite, apContext, writeHandler);
- writeHandler.mpExchangeCtx = gExchangeManager.NewContext({ 0, 0, 0 }, nullptr);
TestExchangeDelegate delegate;
- writeHandler.mpExchangeCtx->SetDelegate(&delegate);
- err = writeHandler.SendWriteResponse();
- NL_TEST_ASSERT(apSuite, err == CHIP_ERROR_NOT_CONNECTED);
+ writeHandler.mpExchangeCtx = ctx.NewExchangeToLocal(&delegate);
+ err = writeHandler.SendWriteResponse();
+ NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
writeHandler.Shutdown();
}
+
+CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * aWriteHandler)
+{
+ return aWriteHandler->AddAttributeStatusCode(
+ AttributePathParams(aClusterInfo.mNodeId, aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId,
+ aClusterInfo.mListIndex, AttributePathParams::Flags::kFieldIdValid),
+ Protocols::SecureChannel::GeneralStatusCode::kSuccess, Protocols::SecureChannel::Id,
+ Protocols::InteractionModel::ProtocolCode::Success);
+}
+
+class RoundtripDelegate : public chip::app::InteractionModelDelegate
+{
+public:
+ CHIP_ERROR WriteResponseStatus(const WriteClient * apWriteClient,
+ const Protocols::SecureChannel::GeneralStatusCode aGeneralCode, const uint32_t aProtocolId,
+ const uint16_t aProtocolCode, AttributePathParams & aAttributePathParams,
+ uint8_t aCommandIndex) override
+ {
+ mGotResponse = true;
+ return CHIP_NO_ERROR;
+ }
+
+ bool mGotResponse = false;
+};
+
+void TestWriteInteraction::TestWriteRoundtrip(nlTestSuite * apSuite, void * apContext)
+{
+ TestContext & ctx = *static_cast<TestContext *>(apContext);
+
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ RoundtripDelegate delegate;
+ auto * engine = chip::app::InteractionModelEngine::GetInstance();
+ err = engine->Init(&ctx.GetExchangeManager(), &delegate);
+ NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+
+ app::WriteClient * writeClient;
+ err = engine->NewWriteClient(&writeClient);
+ NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+
+ System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
+ AddAttributeDataElement(apSuite, apContext, *writeClient);
+
+ NL_TEST_ASSERT(apSuite, !delegate.mGotResponse);
+
+ SecureSessionHandle session = ctx.GetSessionLocalToPeer();
+ err = writeClient->SendWriteRequest(ctx.GetDestinationNodeId(), ctx.GetAdminId(), &session);
+ NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
+
+ NL_TEST_ASSERT(apSuite, delegate.mGotResponse);
+
+ engine->Shutdown();
+}
+
} // namespace app
} // namespace chip
namespace {
-void InitializeChip(nlTestSuite * apSuite)
-{
- CHIP_ERROR err = CHIP_NO_ERROR;
- chip::Optional<chip::Transport::PeerAddress> peer(chip::Transport::Type::kUndefined);
- chip::Transport::AdminPairingTable admins;
- chip::Transport::AdminPairingInfo * adminInfo = admins.AssignAdminId(gAdminId, chip::kTestDeviceNodeId);
-
- NL_TEST_ASSERT(apSuite, adminInfo != nullptr);
-
- err = chip::Platform::MemoryInit();
- NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
-
- gSystemLayer.Init(nullptr);
-
- err = gSessionManager.Init(chip::kTestDeviceNodeId, &gSystemLayer, &gTransportManager, &admins, &gMessageCounterManager);
- NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
-
- err = gExchangeManager.Init(&gSessionManager);
- NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
-
- err = gMessageCounterManager.Init(&gExchangeManager);
- NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
-}
-
/**
* Test Suite. It lists all the test functions.
*/
@@ -282,28 +319,59 @@
{
NL_TEST_DEF("CheckWriteClient", chip::app::TestWriteInteraction::TestWriteClient),
NL_TEST_DEF("CheckWriteHandler", chip::app::TestWriteInteraction::TestWriteHandler),
+ NL_TEST_DEF("CheckWriteRoundtrip", chip::app::TestWriteInteraction::TestWriteRoundtrip),
NL_TEST_SENTINEL()
};
// clang-format on
+
+int Initialize(void * aContext);
+int Finalize(void * aContext);
+
+// clang-format off
+nlTestSuite sSuite =
+{
+ "TestWriteInteraction",
+ &sTests[0],
+ Initialize,
+ Finalize
+};
+// clang-format on
+
+int Initialize(void * aContext)
+{
+ CHIP_ERROR err = chip::Platform::MemoryInit();
+ if (err != CHIP_NO_ERROR)
+ {
+ return FAILURE;
+ }
+
+ gTransportManager.Init(&gLoopback);
+
+ auto * ctx = static_cast<TestContext *>(aContext);
+ err = ctx->Init(&sSuite, &gTransportManager);
+ if (err != CHIP_NO_ERROR)
+ {
+ return FAILURE;
+ }
+
+ gTransportManager.SetSecureSessionMgr(&ctx->GetSecureSessionManager());
+ return SUCCESS;
+}
+
+int Finalize(void * aContext)
+{
+ CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
+ chip::Platform::MemoryShutdown();
+ return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
+}
+
} // namespace
int TestWriteInteraction()
{
- // clang-format off
- nlTestSuite theSuite =
- {
- "TestWriteInteraction",
- &sTests[0],
- nullptr,
- nullptr
- };
- // clang-format on
+ nlTestRunner(&sSuite, &sContext);
- InitializeChip(&theSuite);
-
- nlTestRunner(&theSuite, nullptr);
-
- return (nlTestRunnerStats(&theSuite));
+ return (nlTestRunnerStats(&sSuite));
}
CHIP_REGISTER_TEST_SUITE(TestWriteInteraction)