def test_returns_buffer_if_exists(self, monkeypatch):

        mocked_socket = MagicMock()

        mocked_select = MagicMock(return_value=[True, False, False])

        socket_received_data = b"I'm the mocked out data!"
        mocked_recv = MagicMock(return_value=socket_received_data)
        mocked_socket.recv = mocked_recv

        conn = Connection()

        monkeypatch.setattr(conn, "socket", mocked_socket)
        monkeypatch.setattr("faktory._proto.select.select", mocked_select)

        data = conn.select_data(buffer_size=5_000)
        mocked_recv.assert_called_once()
        assert data == b"I'm the mocked out data!"
    def test_raises_handshake_error_on_misc_error(self, monkeypatch):
        payload = {"key": "value"}
        mocked_socket = MagicMock()
        mocked_reply = MagicMock()
        mocked_get_message = MagicMock(
            return_value=iter(["ERR: A different, non auth error occurred"]))

        mocked_close = MagicMock()
        mocked_socket.close = mocked_close

        conn = Connection()
        monkeypatch.setattr(conn, "socket", mocked_socket)
        monkeypatch.setattr(conn, "reply", mocked_reply)
        monkeypatch.setattr(conn, "get_message", mocked_get_message)
        with pytest.raises(FaktoryHandshakeError):
            conn._validate_handshake(payload)

        mocked_close.assert_called_once()
    def test_raises_auth_error_on_bad_password(self, monkeypatch):
        payload = {"key": "value"}
        mocked_socket = MagicMock()
        mocked_reply = MagicMock()
        # Minimum error message we need to get it to raise the error
        err_message = "ERR: invalid password"
        mocked_get_message = MagicMock(return_value=iter([err_message]))
        mocked_close = MagicMock()
        mocked_socket.close = mocked_close

        conn = Connection()
        monkeypatch.setattr(conn, "socket", mocked_socket)
        monkeypatch.setattr(conn, "reply", mocked_reply)
        monkeypatch.setattr(conn, "get_message", mocked_get_message)
        with pytest.raises(FaktoryAuthenticationError):
            conn._validate_handshake(payload)

        mocked_close.assert_called_once()
    def test_uses_nonce_if_available(self, nonce: Optional[str], monkeypatch):
        """
        This test should ensure if a nonce is present while initializing
        the connection to the server, its used as they key to sign the
        password.
        """
        server_payload = {"v": 2, "s": nonce}
        host_name = "testing host"
        pid = 5
        worker_id = "unit test worker"
        mocked_socket = MagicMock()
        password = "******"
        faktory_url = "tcp://:{}@localhost:7419".format(password)

        mocked_get_message = MagicMock(
            return_value=iter(["HI {}".format(json.dumps(server_payload))])
        )
        mocked_validate_handshake = MagicMock()

        conn = Connection(faktory_url, labels=["test suite"])
        monkeypatch.setattr(conn, "socket", mocked_socket)
        monkeypatch.setattr(conn, "get_message", mocked_get_message)
        monkeypatch.setattr(conn, "_validate_handshake", mocked_validate_handshake)
        # Mocked calls based on environment
        monkeypatch.setattr(
            "faktory._proto.socket.gethostname", MagicMock(return_value=host_name)
        )
        monkeypatch.setattr("faktory._proto.os.getpid", MagicMock(return_value=pid))

        conn.validate_connection()

        handshake_response = mocked_validate_handshake.call_args[0][0]

        if not nonce:
            assert "pwdhash" not in handshake_response
        else:
            assert "pwdhash" in handshake_response
            hashed_pw = handshake_response["pwdhash"]
            assert hashed_pw != password
            expected_password = hashlib.sha256(
                password.encode() + nonce.encode()
            ).hexdigest()
            assert expected_password == hashed_pw
    def test_raises_error_if_socket_not_ready(self, monkeypatch):
        mocked_socket = MagicMock()
        mocked_disconnect = MagicMock()

        mocked_select = MagicMock(return_value=[False, False, False])

        socket_received_data = b"I'm the mocked out data!"
        mocked_recv = MagicMock(return_value=socket_received_data)
        mocked_socket.recv = mocked_recv

        conn = Connection()

        monkeypatch.setattr(conn, "socket", mocked_socket)
        monkeypatch.setattr("faktory._proto.select.select", mocked_select)
        monkeypatch.setattr(conn, "disconnect", mocked_disconnect)

        with pytest.raises(FaktoryConnectionResetError):
            data = conn.select_data(buffer_size=5_000)

        mocked_recv.assert_not_called()
        mocked_disconnect.assert_called_once()
    def test_returns_deserialized_job_info_if_present(self, monkeypatch):

        data = {
            "wid": "test worker",
            "pid": 500,
            "labels": ["tests"],
            "hostname": "test suite",
        }
        serialized_data = json.dumps(data)
        mock_reply = MagicMock()
        mock_get_message = MagicMock(return_value=iter([serialized_data]))
        conn = Connection()

        monkeypatch.setattr(conn, "reply", mock_reply)
        monkeypatch.setattr(conn, "get_message", mock_get_message)

        queues = ["default"]
        result = conn.fetch(queues)

        mock_reply.assert_called_once()
        mock_get_message.assert_called_once()
        assert result == data
    def test_init(self):

        server_url = "tcp://a-server:7419"
        timeout = 45
        buffer_size = 2048
        worker_id = "a custom worker id"
        labels = ["label 1", "label 2"]

        conn = Connection(
            faktory=server_url,
            timeout=timeout,
            buffer_size=buffer_size,
            worker_id=worker_id,
            labels=labels,
        )
        assert conn.host == "a-server"
        assert conn.port == 7419
        assert conn.password is None
        assert conn.timeout == timeout
        assert conn.buffer_size == buffer_size
        assert conn.worker_id == worker_id
        assert conn.labels == labels
    def test_parses_server_information_from_url(self):

        conn = Connection("tcp://:Password123!@localhost:7419")
        assert conn.host == "localhost"
        assert conn.password == "Password123!"
        assert conn.port == 7419
    def test_uses_empty_list_when_not_given_labels(self):

        conn = Connection()
        assert conn.labels == []
    def test_unsupported_version(self, version: int):

        conn = Connection()

        result = conn.is_supported_server_version(version)
        assert result == False
    def test_supported_version(self):

        conn = Connection()

        result = conn.is_supported_server_version(2)
        assert result == True