Parcourir la source

LibWebView+UI: Read and set echo server port in `HttpEchoServerFixture`

This commit adds a "echo_server_port" property to `WebContentOptions`.

Additionally, it makes `Application::web_content_options()` return a
mutable reference instead of a const reference so that we can set the
port value from the fixture.
rmg-x il y a 7 mois
Parent
commit
ece611718d

+ 1 - 1
Libraries/LibWebView/Application.h

@@ -34,7 +34,7 @@ public:
     static Application& the() { return *s_the; }
 
     static ChromeOptions const& chrome_options() { return the().m_chrome_options; }
-    static WebContentOptions const& web_content_options() { return the().m_web_content_options; }
+    static WebContentOptions& web_content_options() { return the().m_web_content_options; }
 
     static Requests::RequestClient& request_server_client() { return *the().m_request_server_client; }
     static ImageDecoderClient::Client& image_decoder_client() { return *the().m_image_decoder_client; }

+ 1 - 0
Libraries/LibWebView/Options.h

@@ -127,6 +127,7 @@ struct WebContentOptions {
     ForceFontconfig force_fontconfig { ForceFontconfig::No };
     EnableAutoplay enable_autoplay { EnableAutoplay::No };
     CollectGarbageOnEveryAllocation collect_garbage_on_every_allocation { CollectGarbageOnEveryAllocation::No };
+    Optional<u16> echo_server_port {};
 };
 
 }

+ 3 - 2
UI/Headless/Application.cpp

@@ -93,10 +93,11 @@ ErrorOr<void> Application::launch_test_fixtures()
 
     // FIXME: Add option to only run specific fixtures from command line by name
     //        And an option to not run any fixtures at all
-    for (auto& fixture : Fixture::all()) {
-        if (auto result = fixture->setup(); result.is_error())
+    for (auto const& fixture : Fixture::all()) {
+        if (auto result = fixture->setup(web_content_options()); result.is_error())
             return result;
     }
+
     return {};
 }
 

+ 34 - 15
UI/Headless/Fixture.cpp

@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <AK/ByteBuffer.h>
 #include <AK/LexicalPath.h>
 #include <LibCore/Process.h>
 #include <LibCore/StandardPaths.h>
@@ -19,7 +20,7 @@ Fixture::~Fixture() = default;
 
 Optional<Fixture&> Fixture::lookup(StringView name)
 {
-    for (auto& fixture : all()) {
+    for (auto const& fixture : all()) {
         if (fixture->name() == name)
             return *fixture;
     }
@@ -34,7 +35,7 @@ Vector<NonnullOwnPtr<Fixture>>& Fixture::all()
 
 class HttpEchoServerFixture final : public Fixture {
 public:
-    virtual ErrorOr<void> setup() override;
+    virtual ErrorOr<void> setup(WebView::WebContentOptions&) override;
     virtual void teardown_impl() override;
     virtual StringView name() const override { return "HttpEchoServer"sv; }
     virtual bool is_running() const override { return m_process.has_value(); }
@@ -44,26 +45,41 @@ private:
     Optional<Core::Process> m_process;
 };
 
-ErrorOr<void> HttpEchoServerFixture::setup()
+ErrorOr<void> HttpEchoServerFixture::setup(WebView::WebContentOptions& web_content_options)
 {
-    auto script_path = LexicalPath::join(s_fixtures_path, m_script_path);
+    auto const script_path = LexicalPath::join(s_fixtures_path, m_script_path);
+    auto const arguments = Vector { script_path.string(), "--directory", Ladybird::Application::the().test_root_path };
 
     // FIXME: Pick a more reasonable log path that is more observable
-    auto log_path = LexicalPath::join(Core::StandardPaths::tempfile_directory(), "http-test-server.log"sv).string();
+    auto const log_path = LexicalPath::join(Core::StandardPaths::tempfile_directory(), "http-test-server.log"sv).string();
+
+    auto stdout_fds = TRY(Core::System::pipe2(0));
 
-    auto arguments = Vector { script_path.string(), "start", "--directory", Ladybird::Application::the().test_root_path };
-    auto process_options = Core::ProcessSpawnOptions {
+    auto const process_options = Core::ProcessSpawnOptions {
         .executable = Ladybird::Application::the().python_executable_path,
         .search_for_executable_in_path = true,
         .arguments = arguments,
         .file_actions = {
-            Core::FileAction::OpenFile { ByteString::formatted("{}.stdout", log_path), Core::File::OpenMode::Write, STDOUT_FILENO },
             Core::FileAction::OpenFile { ByteString::formatted("{}.stderr", log_path), Core::File::OpenMode::Write, STDERR_FILENO },
-        }
+            Core::FileAction::DupFd { stdout_fds[1], STDOUT_FILENO } }
     };
 
     m_process = TRY(Core::Process::spawn(process_options));
 
+    TRY(Core::System::close(stdout_fds[1]));
+
+    auto const stdout_file = MUST(Core::File::adopt_fd(stdout_fds[0], Core::File::OpenMode::Read));
+
+    auto buffer = MUST(ByteBuffer::create_uninitialized(5));
+    TRY(stdout_file->read_some(buffer));
+
+    auto const raw_output = ByteString { buffer, AK::ShouldChomp::NoChomp };
+
+    if (auto const maybe_port = raw_output.to_number<u16>(); maybe_port.has_value())
+        web_content_options.echo_server_port = maybe_port.value();
+    else
+        warnln("Failed to read echo server port from buffer: '{}'", raw_output);
+
     return {};
 }
 
@@ -73,14 +89,17 @@ void HttpEchoServerFixture::teardown_impl()
 
     auto script_path = LexicalPath::join(s_fixtures_path, m_script_path);
 
-    auto ret = Core::System::kill(m_process->pid(), SIGINT);
-    if (ret.is_error() && ret.error().code() != ESRCH) {
-        warnln("Failed to kill http-test-server.py: {}", ret.error());
-        m_process = {};
-        return;
+    if (auto kill_or_error = Core::System::kill(m_process->pid(), SIGINT); kill_or_error.is_error()) {
+        if (kill_or_error.error().code() != ESRCH) {
+            warnln("Failed to kill HTTP echo server, error: {}", kill_or_error.error());
+            m_process = {};
+            return;
+        }
     }
 
-    MUST(m_process->wait_for_termination());
+    if (auto termination_or_error = m_process->wait_for_termination(); termination_or_error.is_error()) {
+        warnln("Failed to terminate HTTP echo server, error: {}", termination_or_error.error());
+    }
 
     m_process = {};
 }

+ 1 - 1
UI/Headless/Fixture.h

@@ -18,7 +18,7 @@ class Fixture {
 public:
     virtual ~Fixture();
 
-    virtual ErrorOr<void> setup() = 0;
+    virtual ErrorOr<void> setup(WebView::WebContentOptions&) = 0;
 
     void teardown()
     {