test(util): cover command stream line delivery and EOF flushing
Add focused coverage for the new GLib command stream helper. These tests verify that complete lines are emitted as they arrive and that EOF flushes a final unterminated line without duplicating a newline-terminated one. That behavior is the contract the custom module will rely on when its continuous command handling moves onto this helper. Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
This commit is contained in:
committed by
Austin Horstman
parent
2355486cb3
commit
560f02509b
@@ -0,0 +1,69 @@
|
|||||||
|
#if __has_include(<catch2/catch_test_macros.hpp>)
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#else
|
||||||
|
#include <catch2/catch.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glibmm/main.h>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "util/command_line_stream.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct StreamResult {
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
std::optional<int> exit_code;
|
||||||
|
bool timed_out = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto run_stream_command(const std::string& cmd) -> StreamResult {
|
||||||
|
StreamResult result;
|
||||||
|
auto loop = Glib::MainLoop::create();
|
||||||
|
|
||||||
|
auto timeout = Glib::signal_timeout().connect(
|
||||||
|
[&]() {
|
||||||
|
result.timed_out = true;
|
||||||
|
loop->quit();
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
3000);
|
||||||
|
|
||||||
|
waybar::util::command::LineStream stream(
|
||||||
|
"",
|
||||||
|
[&](const std::string& line) { result.lines.push_back(line); },
|
||||||
|
[&](int exit_code) {
|
||||||
|
result.exit_code = exit_code;
|
||||||
|
loop->quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.start(cmd);
|
||||||
|
loop->run();
|
||||||
|
timeout.disconnect();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("command::LineStream emits complete lines and flushes trailing output",
|
||||||
|
"[util][command_line_stream]") {
|
||||||
|
const auto result = run_stream_command("printf 'first\\nsecond'");
|
||||||
|
|
||||||
|
REQUIRE_FALSE(result.timed_out);
|
||||||
|
REQUIRE(result.exit_code.has_value());
|
||||||
|
REQUIRE(*result.exit_code == 0);
|
||||||
|
REQUIRE(result.lines == std::vector<std::string>{"first", "second"});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("command::LineStream does not emit an extra line after newline-terminated output",
|
||||||
|
"[util][command_line_stream]") {
|
||||||
|
const auto result = run_stream_command("printf 'first\\nsecond\\n'");
|
||||||
|
|
||||||
|
REQUIRE_FALSE(result.timed_out);
|
||||||
|
REQUIRE(result.exit_code.has_value());
|
||||||
|
REQUIRE(*result.exit_code == 0);
|
||||||
|
REQUIRE(result.lines == std::vector<std::string>{"first", "second"});
|
||||||
|
}
|
||||||
@@ -6,9 +6,15 @@
|
|||||||
class GlibTestsFixture : public sigc::trackable {
|
class GlibTestsFixture : public sigc::trackable {
|
||||||
public:
|
public:
|
||||||
GlibTestsFixture() : main_loop_{Glib::MainLoop::create()} {}
|
GlibTestsFixture() : main_loop_{Glib::MainLoop::create()} {}
|
||||||
|
~GlibTestsFixture() { timeout_.disconnect(); }
|
||||||
|
|
||||||
void setTimeout(int timeout) {
|
void setTimeout(int timeout) {
|
||||||
Glib::signal_timeout().connect_once([]() { throw std::runtime_error("Test timed out"); },
|
timeout_.disconnect();
|
||||||
|
timeout_ = Glib::signal_timeout().connect(
|
||||||
|
[]() {
|
||||||
|
throw std::runtime_error("Test timed out");
|
||||||
|
return false;
|
||||||
|
},
|
||||||
timeout);
|
timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,4 +27,5 @@ class GlibTestsFixture : public sigc::trackable {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Glib::RefPtr<Glib::MainLoop> main_loop_;
|
Glib::RefPtr<Glib::MainLoop> main_loop_;
|
||||||
|
sigc::connection timeout_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ test_src = files(
|
|||||||
'SafeSignal.cpp',
|
'SafeSignal.cpp',
|
||||||
'sleeper_thread.cpp',
|
'sleeper_thread.cpp',
|
||||||
'command.cpp',
|
'command.cpp',
|
||||||
|
'command_line_stream.cpp',
|
||||||
'css_reload_helper.cpp',
|
'css_reload_helper.cpp',
|
||||||
'../../src/util/css_reload_helper.cpp',
|
'../../src/util/css_reload_helper.cpp',
|
||||||
|
'../../src/util/command_line_stream.cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
if tz_dep.found()
|
if tz_dep.found()
|
||||||
|
|||||||
Reference in New Issue
Block a user