Beispiel #1
0
def test_mixing_simple_messages_with_bulk_messages():
    def read(bufsize):
        return "+SIMPLE\r\n*1\r\n$4\r\nBULK\r\n+SIMPLE\r\n*1\r\n$4\r\nBULK\r\n"

    p = Parser(read)

    assert list(p.get_instructions()) == [['SIMPLE'], ['BULK'], ['SIMPLE'],
                                          ['BULK']]
Beispiel #2
0
def test_missing_crlf_after_string():
    responses = ["*1\r\n$4\r\nPING"]

    def read(bufsize):
        return responses.pop(0)

    p = Parser(read)

    with pytest.raises(StopIteration):
        next(p.get_instructions())

    responses.append("\r\n")
    assert next(p.get_instructions()) == ['PING']
Beispiel #3
0
def test_bulk_string_inside_array():
    def read(n):
        return "\
*5\r\n\
$4\r\n\
EVAL\r\n\
$69\r\n\
redis.call('set', KEYS[1], KEYS[2])\n\
return redis.call('get', KEYS[1])\r\n\
$1\r\n\
2\r\n\
$7\r\n\
testkey\r\n\
$9\r\n\
testvalue\r\n"

    p = Parser(read)
    assert list(p.get_instructions()) == [[
        'EVAL',
        '''redis.call('set', KEYS[1], KEYS[2])\nreturn redis.call('get', KEYS[1])''',
        '2', 'testkey', 'testvalue'
    ]]
Beispiel #4
0
class CommandHandler(asyncore.dispatcher):
    def __init__(self, *args, **kwargs):
        asyncore.dispatcher.__init__(self, *args, **kwargs)
        self._parser = Parser(self.recv)  # contains client message buffer
        self.keyspace = Keyspace()
        self.out_buffer = bytearray(
        )  # asyncore.py uses `str` instead of `bytearray`

    def handle_read(self):
        try:
            for cmd in self._parser.get_instructions():
                logger.debug('{} data = {}'.format(self.addr, repr(cmd)))
                execute_cmd(self.keyspace, self.debug_send, *cmd)
        except socket.error as exc:
            # try again later if no data is available
            if exc.errno == errno.EAGAIN:
                return
            else:
                raise

    def debug_send(self, *args):
        logger.debug("out={}".format(repr(args)))
        return self.buffered_send(*args)

    def handle_close(self):
        logger.debug("closing {}".format(self.addr))
        self.close()

    # buffer logic based on `asyncore.dispatcher_with_send`
    def handle_write(self):
        self.initiate_send()

    def initiate_send(self):
        num_sent = self.send(self.out_buffer)
        self.out_buffer = self.out_buffer[num_sent:]

    def buffered_send(self, data):
        self.out_buffer.extend(data)
        self.initiate_send()

    def writable(self):
        return (not self.connected) or len(self.out_buffer)
Beispiel #5
0
def test_parser_should_work_with_chunks_sent_separately():
    responses = ["*1"]

    def read(bufsize):
        return responses.pop(0)

    p = Parser(read)

    with pytest.raises(StopIteration):
        next(p.get_instructions())

    responses.append("\r\n$4\r")
    with pytest.raises(StopIteration):
        next(p.get_instructions())

    responses.append("\nPIN")
    with pytest.raises(StopIteration):
        next(p.get_instructions())

    responses.append("G\r\n")
    assert next(p.get_instructions()) == ['PING']
Beispiel #6
0
 def __init__(self, *args, **kwargs):
     asyncore.dispatcher.__init__(self, *args, **kwargs)
     self._parser = Parser(self.recv)  # contains client message buffer
     self.keyspace = Keyspace()
     self.out_buffer = bytearray(
     )  # asyncore.py uses `str` instead of `bytearray`
Beispiel #7
0
def test_parser_should_ignore_half_sent_commands(line):
    def read(bufsize):
        return line

    p = Parser(read)
    assert list(p.get_instructions()) == []
Beispiel #8
0
def test_parse_simple_string():
    def read(n):
        return "+PING\r\n"

    p = Parser(read)
    assert list(p.get_instructions()) == [['PING']]
Beispiel #9
0
def test_multiple_arrays():
    def read(n):
        return "*1\r\n$4\r\nPING\r\n*1\r\n$4\r\nPING\r\n"

    p = Parser(read)
    assert list(p.get_instructions()) == [['PING'], ['PING']]