3

I'm attempting to write an integration test to prove that a TCP client will correctly time out if an attempt to connect to the server is too slow. I have a FakeServer class that opens a Socket and listens for incoming connections:

public sealed class FakeServer : IDisposable
{
    ...

    public TimeSpan ConnectDelay
    {
        get; set;
    }

    public void Start()
    {
        this.CreateSocket();
        this.socket.Listen(int.MaxValue);

        this.socket.BeginAccept(this.OnSocketAccepted, null);
    }

    private void CreateSocket()
    {
        var ip = new IPAddress(new byte[] { 0, 0, 0, 0 });
        var endPoint = new IPEndPoint(ip, Port);
        this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        this.socket.Bind(endPoint);
    }

    private void OnSocketAccepted(IAsyncResult asyncResult)
    {
        Thread.Sleep(this.connectDelay);
        this.clientSocket = this.socket.EndAccept(asyncResult);
    }
}

Notice my attempt to delay the success of the connection via a call to Thread.Sleep(). Unfortunately, this does not work:

[Fact]
public void tcp_client_test()
{
    this.fakeServer.ConnectDelay = TimeSpan.FromSeconds(20);
    var tcpClient = new TcpClient();
    tcpClient.Connect("localhost", FakeServer.Port);
}

In the test above, the call to tcpClient.Connect() succeeds immediately, before the server-side OnSocketAccepted method is even called. I've had a look around the APIs and I can't see any obvious way for me to inject some server-side logic that must finish before the connection from the client is established.

Is there any way for me to fake a slow server/connection using TcpClient and Socket?

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108
Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 2
    +1 for actually testing bad/slow connections unlike the rest of the ignorant world :) – leppie Jul 16 '12 at 09:21
  • 1
    You could use a tool like NetLimiter to throttle the connection. Unfortunately not free. – leppie Jul 16 '12 at 09:22
  • There are quite a few questions on the SO/SE network that cover this topic. Many are specific to browsers or a particular OS (there are at least 2 for OS X), but [this one](http://stackoverflow.com/questions/1094760/network-tools-that-simulate-slow-network-connection), [this one](http://stackoverflow.com/questions/11488888/simulate-slow-internet-connection-on-a-real-device), and [this one](http://superuser.com/questions/297103/how-to-simulate-slow-internet-connection) should have solutions you might be able to use. – Lèse majesté Jul 16 '12 at 09:37
  • Some generic solutions here as well: http://webmasters.stackexchange.com/questions/861/how-can-i-simulate-a-slow-connection-for-page-load – Lèse majesté Jul 16 '12 at 09:40
  • I'm not after network tools, because this is running as an integration test. – Kent Boogaart Jul 16 '12 at 10:14
  • I see no reason why you couldn't use [one of the latency simulation methods mentioned here](http://stackoverflow.com/questions/130354/how-do-i-simulate-a-low-bandwidth-high-latency-environment), regardless of whether it's for an integration test or not. If you set up a low-bandwidth or high-latency bridge and route the connection requests through that for the integration test, wouldn't that allow you to test what you want? – Lèse majesté Jul 16 '12 at 12:22
  • @Lese: it's possible. The thing is, I'm trying to keep my tests simple and understandable. Introducing a dependency like this will make them more difficult to read and maintain. Seems to me this should be simple to do without an external tool, but perhaps it's not. – Kent Boogaart Jul 16 '12 at 12:30
  • @Kent: I'm guessing it probably _is_ possible. It just might involve more work. .NET isn't my thing, but the obvious approach would be to manually conduct a TCP handshake over raw sockets, so you can time the SYN, SYN-ACK, ACK messages as you see fit. But as I understand it, you can't send TCP data over raw sockets in Windows anymore, though I've also seen claims to the contrary. Or perhaps the WinPcap .NET wrapper could be of use here. – Lèse majesté Jul 16 '12 at 13:56
  • Wouldn't pinging a server be some sort of an assitance? Cool idea any way. – Daniel Lopez Jul 18 '12 at 16:04
  • @Daniel: ping would require a separate TCP connection. That would be less firewall-friendly and wasteful given that we've already got a TCP connection open. – Kent Boogaart Jul 18 '12 at 17:55

1 Answers1

0

Visual Studio comes with network emulator ( http://msdn.microsoft.com/en-us/library/dd505008.aspx )

user1578107
  • 645
  • 1
  • 5
  • 9