mindflayer / python-mocket

a socket mock framework - for all kinds of socket animals, web-clients included
BSD 3-Clause "New" or "Revised" License
279 stars 41 forks source link

Establishing connections against multiple hosts can cause true socket connection to get created against the wrong host #221

Closed ento closed 5 months ago

ento commented 5 months ago

I saw this issue in a project that uses Datadog's CI Visibility plugin for pytest, which makes HTTP requests against Datadog's API server in the background even during tests that use Mocket.

A test case that reproduces the issue:

import io
import socket

from mocket import Mocketizer

def test_multiple_socket_connections():
    redis_addr = ("localhost", 6379)
    httpbin_addr = ("localhost", 80)

    redis_buffer = io.BytesIO()

    with Mocketizer():
        redis_so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        redis_so.connect(redis_addr)

        httpbin_so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        httpbin_so.connect(httpbin_addr)

        # Creating another socket that connects to a different address
        # should not cause the first connection to go awry.
        redis_so.sendall(b"ping\r\n")
        redis_so.recv_into(redis_buffer)

    redis_buffer.seek(0)
    assert redis_buffer.read() == b"+PONG\r\n"

This fails like:

    def test_multiple_socket_connections():
        redis_addr = ("localhost", 6379)
        httpbin_addr = ("localhost", 80)

        redis_buffer = io.BytesIO()

        with Mocketizer():
            redis_so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            redis_so.connect(redis_addr)

            httpbin_so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            httpbin_so.connect(httpbin_addr)

            # Creating another socket that connects to a different address
            # should not cause the first connection to go awry.
            redis_so.sendall(b"ping\r\n")
            redis_so.recv_into(redis_buffer)

        redis_buffer.seek(0)
>       assert redis_buffer.read() == b"+PONG\r\n"
E       AssertionError: assert b'HTTP/1.1 40...close\r\n\r\n' == b'+PONG\r\n'
E         At index 0 diff: b'H' != b'+'
E         Full diff:
E         - b'+PONG\r\n'
E         + b'HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n'