Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable dual-mode socket tests that were disabled on Linux\Mac #1481

Closed
steveharter opened this issue Apr 18, 2017 · 4 comments · Fixed by #80715
Closed

Re-enable dual-mode socket tests that were disabled on Linux\Mac #1481

steveharter opened this issue Apr 18, 2017 · 4 comments · Fixed by #80715
Assignees
Labels
area-System.Net.Sockets disabled-test The test is disabled in source code against the issue os-linux Linux OS (any supported distro) os-mac-os-x macOS aka OSX test-enhancement Improvements of test source code test-run-core Test failures in .NET Core test runs
Milestone

Comments

@steveharter
Copy link
Member

We should re-enable tests that were disabled on Linux\Mac. The tests would randomly fail because of the way that port allocation is different than on Windows. On Linux\Mac, when asking for an available free port, the returned port number is a random unused port. On Windows, it is incremental and eventually rolls over.

These tests are negative tests that connect to a V4 port and then send\listen on a V6 port (or vise-versa) of the same number expecting an unused port and thus failure case. However, in Linux\Mac there is a chance that the port is active instead of unused, causing the test to succeed, and\or interfering with a 'good' test. The port may be active on Windows too, causing similar problems, but the odds are much less as any given test run should not have active ports open that longs.

Two options to re-enable these tests:

  1. Enable a test mode where a given test is flagged an runs serially
  2. Move the tests to a new assembly with the CollectionBehavior attribute (DisableTestParallelization=true, MaxParallelThreads=1)

For these to work, all other tests should be done running, including tests in other assemblies (at least those tests which use sockets).

An alternative way to re-enable these tests is to keep them in the current assembly, but change the logic to something like this to preserve the original intent of making sure the socket is isn't 'dual mode':

  1. Bind to address family with port 0 so we get unused port
  2. Bind to the other address family + same port
  3. The bind should succeed (otherwise retry by going back to step 1)
  4. Unbind (so we can do the receive on it)
  5. Do the actual receive on that unbound port
  6. Should fail (as these tests are negative tests)

This alternative approach will increase reliability but there is a small chance between 4 and 5 another test grabbed that port.
However, if 3 succeeds then it probably proves that the socket wasn't dual mode because you can't bind to the same port + family twice; thus perhaps the test can stop there and not include 4-6.

See issues dotnet/corefx#16548, dotnet/corefx#9017, dotnet/corefx#13213, dotnet/corefx#17362, dotnet/corefx#17154, dotnet/corefx#13967

Tests that were disabled below, located in DualModeSocketTest.cs. Note history should be checked for each of the commits as there are cases of Linux vs. Mac differences in the original test code which needs to be accounted for when the tests are enabled again.

https://github.com/dotnet/corefx/blob/master/src/System.Net.Sockets/tests/FunctionalTests/DualModeSocketTest.cs

DualModeConnect_IPAddressListToHost_Throws
BeginAcceptV6BoundToSpecificV4_CantConnect
BeginAcceptV4BoundToSpecificV6_CantConnect
BeginAcceptV6BoundToAnyV4_CantConnect
AcceptAsyncV6BoundToSpecificV4_CantConnect
AcceptAsyncV4BoundToSpecificV6_CantConnect
AcceptAsyncV6BoundToAnyV4_CantConnect
SendToV4IPEndPointToV6Host_NotReceived
SendToV6IPEndPointToV4Host_NotReceived
SendToAsyncV4IPEndPointToV6Host_NotReceived
SendToAsyncV6IPEndPointToV4Host_NotReceived
ReceiveMessageFromV6BoundToAnyV4_NotReceived
ReceiveFromV6BoundToSpecificV4_NotReceived
ReceiveFromV4BoundToSpecificV6_NotReceived
ReceiveFromV6BoundToAnyV4_NotReceived
BeginReceiveFromV6BoundToSpecificV4_NotReceived
BeginReceiveFromV4BoundToSpecificV6_NotReceived
BeginReceiveFromV6BoundToAnyV4_NotReceived
ReceiveMessageFromV6BoundToSpecificV4_NotReceived
ReceiveMessageFromV4BoundToSpecificV6_NotReceived
@karelz
Copy link
Member

karelz commented Dec 6, 2017

These tests are skipped on Linux/Mac, we should revisit them for 2.1.

@karelz karelz transferred this issue from dotnet/corefx Jan 9, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Net.Sockets untriaged New issue has not been triaged by the area owner labels Jan 9, 2020
@karelz karelz added disabled-test The test is disabled in source code against the issue os-linux Linux OS (any supported distro) os-mac-os-x macOS aka OSX test-enhancement Improvements of test source code test-run-core Test failures in .NET Core test runs and removed untriaged New issue has not been triaged by the area owner labels Jan 9, 2020
@karelz karelz added this to the 5.0 milestone Jan 9, 2020
@antonfirsov antonfirsov self-assigned this Jan 27, 2020
@antonfirsov
Copy link
Member

Related: #1712

Third option: introduce centralized logic to distribute non-ephemeral ports to test cases in a thread-safe way.

antonfirsov added a commit to antonfirsov/runtime that referenced this issue Feb 7, 2020
@karelz karelz modified the milestones: 5.0, Future May 7, 2020
@antonfirsov antonfirsov modified the milestones: Future, 6.0.0 Nov 4, 2020
@karelz
Copy link
Member

karelz commented Jul 22, 2021

Triage: It needs a test refactor we postponed for years, we don't see urgency to do it in final weeks of 6.0. (Unless we expect to discover critical dual-stack bugs during the process, but this is super unlikely)
Moving to 7.0

@karelz karelz modified the milestones: 6.0.0, 7.0.0 Jul 22, 2021
MichalStrehovsky added a commit to MichalStrehovsky/runtime that referenced this issue Dec 9, 2021
* We have new exports that are needed.
* Unshare IDynamicInterfaceCastableSupport. I thought it would be shareable, but it uses SR and throws various exceptions. Maybe not so shareable after all.
@antonfirsov antonfirsov self-assigned this Jun 2, 2022
@karelz karelz removed this from the 7.0.0 milestone Jul 19, 2022
@antonfirsov
Copy link
Member

antonfirsov commented Dec 16, 2022

Maybe a utility like this would do the trick?

public class PortBlocker : IDisposable
{
    private Socket _ipv4Socket;
    private Socket _ipv6Socket;
    
    public int Port { get; private set; }

    public PortBlocker(SocketType socketType = SocketType.Stream, ProtocolType protocolType = ProtocolType.Tcp)
    {
        // This is just a sketch.
        // _ipv6Socket.Bind() may fail, so the code block below has to run in a loop until both binds are succesful!
        _ipv4Socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
        Port = _ipv4Socket.BindToAnonymousPort(IPAddress.Loopback);
        _ipv6Socket = new Socket(AddressFamily.InterNetworkV6, socketType, protocolType);
        _ipv6Socket.Bind(new IPEndPoint(IPAddress.Loopback, Port));
    }

    // This could help solving the race condition between step 4-5 mentioned by the OP.
    // Instead of creating a new socket, a test could just take the one created by this class.
    // This will ensure that the port of the other address family is still blocked.
    public Socket GetSocket(AddressFamily addressFamily)
        => addressFamily == AddressFamily.InterNetwork ? _ipv4Socket : _ipv6Socket;

    public void Dispose()
    {
        _ipv4Socket.Dispose();
        _ipv6Socket.Dispose();
    }
}

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jan 16, 2023
@antonfirsov antonfirsov added in-pr There is an active PR which will close this issue when it is merged and removed in-pr There is an active PR which will close this issue when it is merged labels Jan 16, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 7, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Mar 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Net.Sockets disabled-test The test is disabled in source code against the issue os-linux Linux OS (any supported distro) os-mac-os-x macOS aka OSX test-enhancement Improvements of test source code test-run-core Test failures in .NET Core test runs
Projects
None yet
4 participants