mozilla / geckodriver

WebDriver for Firefox
https://firefox-source-docs.mozilla.org/testing/geckodriver/
Mozilla Public License 2.0
7.15k stars 1.52k forks source link

Listen on both IPv4 and IPv6 loopbacks by default #1496

Open jimevans opened 5 years ago

jimevans commented 5 years ago

System

Testcase

IWebDriver driver = new FirefoxDriver(); driver.Url = "https://the-internet.herokuapp.com/checkboxes"; driver.Quit();

Stacktrace

No stack trace; issue is one of performance.

Trace-level log

No log generated, though would be happy to do so if required.

When using .NET Core on Windows with a mixed IPv4 and IPv6 networking stack (the default for most systems), the language framework attempts to resolve “localhost” to ::1 first, then if that fails (after a delay of about a second) retries on 127.0.0.1. This makes each wire protocol command delay at least one second. Yes, this is a bug in .NET Core, but the problem only manifests in Firefox. All other Windows implementations (IE, Chrome, Edge) resolve the issue by opening two loopback sockets for listening, one bound to the IPv4 loopback, and the other to the IPv6 loopback.

While there is a workaround for Firefox users (specify --host ::1 on the geckodriver command line), this workaround is only required for Firefox. The friction of forcing .NET Core users into using this workaround encourages them to skip running against Firefox in favor of other implementations.

andreastt commented 5 years ago

geckodriver has two TCP sockets it operates on: one for the client-facing HTTPD, and another for communicating with Marionette which Firefox binds. You are concerned with the HTTPD here, yes?

The default in geckodriver is to bind the HTTPD to 127.0.0.1. This explicitly forces clients to use the IPv4 layer. AIUI --host ::1 will cause the HTTPD to only listen for incoming connections on the IPv6 layer.

Could you test if --host localhost works on your system? If the client HTTP library does the same, this should make both the client and the server resolve to the same things.

jimevans commented 5 years ago

If I pass --host localhost, yes it also resolves the issue. I suppose the .NET bindings should simply do this all the time to work around this issue. I vehemently oppose using this workaround, and strongly disagree that it should be required, but since geckodriver isn't my project, and I have little influence on its direction, I'll do so.

For others' edification who'd like to reproduce this issue on their own, the following C# code, running against .NET Core 2.0 or later will demonstrate the issue:

class Program
{
    static void Main(string[] args)
    {
        // Change the below path to the directory containing geckodriver.exe
        string geckoDriverDirectory = @"C:\Path\To\Directory\Containing\Executable";
        FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(geckoDriverDirectory);
        ExecuteTest("Default settings", service);

        service.Host = "::1";
        ExecuteTest("Using '::1'", service);

        service.Host = "127.0.0.1";
        ExecuteTest("Using '127.0.0.1'", service);

        service.Host = "localhost";
        ExecuteTest("Using 'localhost'", service);

        Console.WriteLine("Tests complete. Press <Enter> to exit.");
        Console.ReadLine();
    }

    private static void ExecuteTest(string testDescription, FirefoxDriverService service)
    {
        IWebDriver driver = new FirefoxDriver(service);

        Stopwatch timer = new Stopwatch();
        timer.Start();
        driver.Url = "https://the-internet.herokuapp.com/checkboxes";
        IWebElement element = driver.FindElement(By.CssSelector("#checkboxes input"));
        element.Click();
        bool isChecked = element.Selected;
        driver.Quit();
        timer.Stop();

        Console.WriteLine("Test: {0}, Elapsed time: {1} seconds", testDescription, timer.Elapsed.TotalSeconds);
    }
}

Running the above on my system yields the following results:

Test: Default settings, Elapsed time: 12.9698394 seconds
Test: Using '::1', Elapsed time: 3.3265998 seconds
Test: Using '127.0.0.1', Elapsed time: 4.0038315 seconds
Test: Using 'localhost', Elapsed time: 3.6523214 seconds
Tests complete. Press <Enter> to exit.
andreastt commented 5 years ago

Thanks for running that test!

Instead of hardcoding the HTTPD default to ::1, I think the right option would be to let the system decide. If the system defaults (e.g. the equivalent of /etc/hosts on Unix) are to listen on both IP layers, we can achieve this effect by using localhost.

I’ve filed https://bugzilla.mozilla.org/show_bug.cgi?id=1525659 to follow up on this.

AlexWFreitas commented 3 years ago

When I tried to use GeckoDriver 0.30 on a DotNet application with C# and tried to use the FirefoxDriverService.Host = "::1" it seems that it couldn't parse the Ipv6 Address and then threw an exception when I tried to start the FirefoxDriver.

image

Code was something like this:

string driversPath = "pathToGeckoDriver";
_firefoxOptions = new FirefoxOptions(); 
FirefoxDriverService geckoService = FirefoxDriverService.CreateDefaultService(driversPath);  
geckoService.Host = "::1";  
_firefoxOptions.AcceptInsecureCertificates = true;
Browser = new FirefoxDriver(geckoService, _firefoxOptions);

The message on the exception was something like this: "Cannot start the driver service on http://localhost:54140/"

So I wasn't able to launch geckodriver properly, when I moved back to version 0.29.1, it started working again. I am not sure why this is happening, but could someone test to see if this is reproducible?

Maybe I should make a new issue instead of posting here?

whimboo commented 3 years ago

@AlexWFreitas could you please file this as a new issue given that this is a regression? Thanks a lot!

gjakovaime commented 2 years ago

It seems that with the latest version, 0.30.0, the workaround to use host="::1" or host="localhost" will no longer a solution. I have a test that will run for 5 minutes and intermittently fail when no host is specified. When using geckodriver 0.29.1 or older and specifying host="::1", the same test will run for 12.6 seconds

This same test runs for 11s on chrome and edge drivers.

Any other recommendations on how to speed things up?

whimboo commented 2 years ago

@gjakovaime your issue doesn't seem to be related to this one. Can you please file a new one? And please attach the trace log. Thanks!