Files
infix/package/rousette/0016-tests-processing-incomplete-events-in-SSE-client.patch
T
Joachim Wiberg 4dee5e4f1f package/rousette: silence rousette warnings in log
Add --log-level command line option to filter out log messages from
lower log levels.  Then fix the annoying CzechLight warning message
and useless "NACM config validation" log.  Then add audit trail as
we have in netopeer2-server, and finish off by stripping redundant
fields from log message: timestamp, identity, and log level.

Fixes #892

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2026-03-20 16:18:16 +01:00

122 lines
5.2 KiB
Diff

From fe57a9ac8024e4115c45d9c256d5048e17fe9fdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomas.pecka@cesnet.cz>
Date: Tue, 2 Sep 2025 15:33:43 +0200
Subject: [PATCH 16/42] tests: processing incomplete events in SSE client
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Organization: Wires
During my testing I noticed that I obtained incomplete message in
on_data callback. The message was split into two callbacks.
This commit fixes the FIXME by buffering the data and processing
a complete event, once available.
Change-Id: Ied07e69e8b518f20fcc82134a4c041e7ec3a06d6
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
---
tests/restconf_utils.cpp | 53 +++++++++++++++++++++++-----------------
tests/restconf_utils.h | 3 ++-
2 files changed, 33 insertions(+), 23 deletions(-)
diff --git a/tests/restconf_utils.cpp b/tests/restconf_utils.cpp
index 5b1ebe3..740b1fa 100644
--- a/tests/restconf_utils.cpp
+++ b/tests/restconf_utils.cpp
@@ -199,8 +199,8 @@ SSEClient::SSEClient(
req->on_response([&, silenceTimeout, reportIgnoredLines](const ng_client::response& res) {
requestSent.release();
res.on_data([&, silenceTimeout, reportIgnoredLines](const uint8_t* data, std::size_t len) {
- // not a production-ready code. In real-life condition the data received in one callback might probably be incomplete
- parseEvents(std::string(reinterpret_cast<const char*>(data), len), eventWatcher, reportIgnoredLines);
+ dataBuffer.append(std::string(reinterpret_cast<const char*>(data), len));
+ parseEvents(eventWatcher, reportIgnoredLines);
t.expires_from_now(silenceTimeout);
});
});
@@ -217,30 +217,39 @@ SSEClient::SSEClient(
});
}
-void SSEClient::parseEvents(const std::string& msg, const RestconfNotificationWatcher& eventWatcher, const ReportIgnoredLines reportIgnoredLines)
+void SSEClient::parseEvents(const RestconfNotificationWatcher& eventWatcher, const ReportIgnoredLines reportIgnoredLines)
{
static const std::string dataPrefix = "data:";
static const std::string ignorePrefix = ":";
- std::istringstream iss(msg);
- std::string line;
- std::string event;
-
- while (std::getline(iss, line)) {
- if (line.starts_with(ignorePrefix) && reportIgnoredLines == ReportIgnoredLines::Yes) {
- eventWatcher.commentEvent(line);
- } else if (line.starts_with(ignorePrefix)) {
- continue;
- } else if (line.starts_with(dataPrefix)) {
- event += line.substr(dataPrefix.size());
- } else if (line.empty() && !event.empty()) {
- eventWatcher.dataEvent(event);
- event.clear();
- } else if (line.empty()) {
- continue;
- } else {
- CAPTURE(msg);
- FAIL("Unprefixed response");
+ std::size_t pos = 0;
+ constexpr auto EVENT_SEPARATOR = "\n\n"; // FIXME: Not a production-ready code; does not deal with all possible newline combinations of CR and LF
+
+ while ((pos = dataBuffer.find(EVENT_SEPARATOR)) != std::string::npos) {
+ // extract event
+ auto rawEvent = dataBuffer.substr(0, pos + std::char_traits<char>::length(EVENT_SEPARATOR));
+ std::istringstream stream(rawEvent);
+ dataBuffer.erase(0, pos + std::char_traits<char>::length(EVENT_SEPARATOR));
+
+ // split on newlines
+ std::string line;
+ std::string event;
+ while (std::getline(stream, line)) {
+ if (line.starts_with(ignorePrefix) && reportIgnoredLines == ReportIgnoredLines::Yes) {
+ eventWatcher.commentEvent(line);
+ } else if (line.starts_with(ignorePrefix)) {
+ continue;
+ } else if (line.starts_with(dataPrefix)) {
+ event += line.substr(dataPrefix.size());
+ } else if (line.empty() && !event.empty()) {
+ eventWatcher.dataEvent(event);
+ event.clear();
+ } else if (line.empty()) {
+ continue;
+ } else {
+ CAPTURE(rawEvent);
+ FAIL("Unprefixed response");
+ }
}
}
}
diff --git a/tests/restconf_utils.h b/tests/restconf_utils.h
index 9dde10b..c35df54 100644
--- a/tests/restconf_utils.h
+++ b/tests/restconf_utils.h
@@ -87,6 +87,7 @@ void setupRealNacm(sysrepo::Session session);
struct SSEClient {
std::shared_ptr<ng_client::session> client;
boost::asio::deadline_timer t;
+ std::string dataBuffer;
enum class ReportIgnoredLines {
No,
@@ -104,7 +105,7 @@ struct SSEClient {
const boost::posix_time::seconds silenceTimeout = boost::posix_time::seconds(1), // test code; the server should respond "soon"
const ReportIgnoredLines reportIgnoredLines = ReportIgnoredLines::No);
- static void parseEvents(const std::string& msg, const RestconfNotificationWatcher& eventWatcher, const ReportIgnoredLines reportIgnoredLines);
+ void parseEvents(const RestconfNotificationWatcher& eventWatcher, const ReportIgnoredLines reportIgnoredLines);
};
#define PREPARE_LOOP_WITH_EXCEPTIONS \
--
2.43.0