示例#1
0
async def test_empty_content():
    stream = encode()
    content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {}
    assert content == b""
示例#2
0
async def test_bytes_content():
    stream = encode(data=b"Hello, world!")
    content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {"Content-Length": "13"}
    assert content == b"Hello, world!"
示例#3
0
def test_multipart_encode():
    data = {
        "a": "1",
        "b": b"C",
        "c": ["11", "22", "33"],
        "d": {
            "ff": ["1", b"2", "3"],
            "fff": ["11", b"22", "33"]
        },
        "f": "",
    }
    files = {"file": ("name.txt", io.BytesIO(b"<file content>"))}

    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")
        stream = encode(data=data, files=files)
        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="a"\r\n\r\n1\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="b"\r\n\r\nC\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n11\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n22\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="c"\r\n\r\n33\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="d"\r\n\r\nff\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="d"\r\n\r\nfff\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="f"\r\n\r\n\r\n'
            '--{0}\r\nContent-Disposition: form-data; name="file";'
            ' filename="name.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<file content>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("ascii"))
async def test_multipart_files_content():
    files = {"file": io.BytesIO(b"<file content>")}
    stream = encode(files=files, boundary=b"+++")
    sync_content = b"".join([part for part in stream])
    async_content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "138",
        "Content-Type": "multipart/form-data; boundary=+++",
    }
    assert sync_content == b"".join([
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
        b"Content-Type: application/octet-stream\r\n",
        b"\r\n",
        b"<file content>\r\n",
        b"--+++--\r\n",
    ])
    assert async_content == b"".join([
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
        b"Content-Type: application/octet-stream\r\n",
        b"\r\n",
        b"<file content>\r\n",
        b"--+++--\r\n",
    ])
示例#5
0
async def test_urlencoded_content():
    stream = encode(data={"Hello": "world!"})
    content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "14",
        "Content-Type": "application/x-www-form-urlencoded",
    }
    assert content == b"Hello=world%21"
示例#6
0
async def test_json_content():
    stream = encode(json={"Hello": "world!"})
    content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "19",
        "Content-Type": "application/json",
    }
    assert content == b'{"Hello": "world!"}'
示例#7
0
async def test_aiterator_content():
    async def hello_world():
        yield b"Hello, "
        yield b"world!"

    stream = encode(data=hello_world())
    content = b"".join([part async for part in stream])

    assert not stream.can_replay()
    assert stream.get_headers() == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"
示例#8
0
def test_multipart_encode_files_allows_filenames_as_none():
    files = {"file": (None, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="file"\r\n\r\n'
            "<file content>\r\n--{0}--\r\n"
            "".format(boundary).encode("ascii"))
示例#9
0
async def test_aiterator_is_stream_consumed():
    async def hello_world():
        yield b"Hello, "
        yield b"world!"

    stream = encode(data=hello_world())
    b"".join([part async for part in stream])

    assert stream.is_stream_consumed

    with pytest.raises(StreamConsumed) as _:
        b"".join([part async for part in stream])
示例#10
0
def test_multipart_encode_files_allows_str_content():
    files = {"file": ("test.txt", "<string content>", "text/plain")}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            '--{0}\r\nContent-Disposition: form-data; name="file"; '
            'filename="test.txt"\r\n'
            "Content-Type: text/plain\r\n\r\n<string content>\r\n"
            "--{0}--\r\n"
            "".format(boundary).encode("ascii"))
示例#11
0
def test_multipart_encode_files_guesses_correct_content_type(
        file_name, expected_content_type):
    files = {"file": (file_name, io.BytesIO(b"<file content>"))}
    with mock.patch("os.urandom", return_value=os.urandom(16)):
        boundary = binascii.hexlify(os.urandom(16)).decode("ascii")

        stream = encode(data={}, files=files)

        assert stream.content_type == f"multipart/form-data; boundary={boundary}"
        assert stream.body == (
            f'--{boundary}\r\nContent-Disposition: form-data; name="file"; '
            f'filename="{file_name}"\r\nContent-Type: '
            f"{expected_content_type}\r\n\r\n<file content>\r\n--{boundary}--\r\n"
            "".encode("ascii"))
async def test_aiterator_content():
    async def hello_world():
        yield b"Hello, "
        yield b"world!"

    stream = encode(data=hello_world())
    content = b"".join([part async for part in stream])

    assert not stream.can_replay()
    assert stream.get_headers() == {"Transfer-Encoding": "chunked"}
    assert content == b"Hello, world!"

    with pytest.raises(RuntimeError):
        [part for part in stream]

    with pytest.raises(StreamConsumed):
        [part async for part in stream]
示例#13
0
async def test_multipart_data_and_files_content():
    data = {"message": "Hello, world!"}
    files = {"file": io.BytesIO(b"<file content>")}
    stream = encode(data=data, files=files, boundary=b"+++")
    content = b"".join([part async for part in stream])

    assert stream.can_replay()
    assert stream.get_headers() == {
        "Content-Length": "210",
        "Content-Type": "multipart/form-data; boundary=+++",
    }
    assert content == b"".join([
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="message"\r\n',
        b"\r\n",
        b"Hello, world!\r\n",
        b"--+++\r\n",
        b'Content-Disposition: form-data; name="file"; filename="upload"\r\n',
        b"Content-Type: application/octet-stream\r\n",
        b"\r\n",
        b"<file content>\r\n",
        b"--+++--\r\n",
    ])
示例#14
0
    def add_response(
        self,
        status_code: int = 200,
        http_version: str = "HTTP/1.1",
        headers: dict = None,
        data: content_streams.RequestData = None,
        files: content_streams.RequestFiles = None,
        json: Any = None,
        boundary: bytes = None,
        **matchers,
    ):
        """
        Mock the response that will be sent if a request match.

        :param status_code: HTTP status code of the response to send. Default to 200 (OK).
        :param http_version: HTTP protocol version of the response to send. Default to HTTP/1.1
        :param headers: HTTP headers of the response to send. Default to no headers.
        :param data: HTTP body of the response, can be an iterator to stream content, bytes, str of the full body or
        a dictionary in case of a multipart.
        :param files: Multipart files.
        :param json: HTTP body of the response (if JSON should be used as content type) if data is not provided.
        :param boundary: Multipart boundary if files is provided.
        :param url: Full URL identifying the request(s) to match. Can be a str, a re.Pattern instance or a httpx.URL instance.
        :param method: HTTP method identifying the request(s) to match.
        :param match_headers: HTTP headers identifying the request(s) to match. Must be a dictionary.
        :param match_content: Full HTTP body identifying the request(s) to match. Must be bytes.
        """
        response = Response(
            status_code=status_code,
            http_version=http_version,
            headers=list(headers.items()) if headers else [],
            stream=content_streams.encode(
                data=data, files=files, json=json, boundary=boundary
            ),
            request=None,  # Will be set upon reception of the actual request
        )
        self._responses.append((_RequestMatcher(**matchers), response))
def test_invalid_argument():
    with pytest.raises(TypeError):
        encode(123)