tests/test-wireproto.py
author Gregory Szorc <gregory.szorc@gmail.com>
Thu, 01 Mar 2018 08:27:30 -0800
changeset 36530 bde0bd50f368
parent 36074 2f7290555c96
child 36555 c28de190e20a
permissions -rw-r--r--
debugcommands: allow sending of simple commands with debugwireproto Previously, we only had support for low-level "raw" operations. A goal of `hg debugwireproto` is to allow easily performing higher-level primitives, such as sending a wire protocol command and reading its response. We implement a "command" action that does just this. Currently, we only support simple commands (those without payloads). We have basic support for sending command arguments. We don't yet support sending dictionary arguments. This will be implemented later. To prove it works, we add tests to test-ssh-proto.t that send some "listkeys" commands. Note: we don't observe/report os.read() events because these may not be deterministic. We instead observe/report the read() and readline() operations on the bufferedinputpipe. These *should* be deterministic. Differential Revision: https://phab.mercurial-scm.org/D2406

from __future__ import absolute_import, print_function

from mercurial import (
    error,
    util,
    wireproto,
    wireprototypes,
)
stringio = util.stringio

class proto(object):
    def __init__(self, args):
        self.args = args
    def getargs(self, spec):
        args = self.args
        args.setdefault('*', {})
        names = spec.split()
        return [args[n] for n in names]

class clientpeer(wireproto.wirepeer):
    def __init__(self, serverrepo):
        self.serverrepo = serverrepo

    @property
    def ui(self):
        return self.serverrepo.ui

    def url(self):
        return 'test'

    def local(self):
        return None

    def peer(self):
        return self

    def canpush(self):
        return True

    def close(self):
        pass

    def capabilities(self):
        return ['batch']

    def _call(self, cmd, **args):
        res = wireproto.dispatch(self.serverrepo, proto(args), cmd)
        if isinstance(res, wireprototypes.bytesresponse):
            return res.data
        elif isinstance(res, bytes):
            return res
        else:
            raise error.Abort('dummy client does not support response type')

    def _callstream(self, cmd, **args):
        return stringio(self._call(cmd, **args))

    @wireproto.batchable
    def greet(self, name):
        f = wireproto.future()
        yield {'name': mangle(name)}, f
        yield unmangle(f.value)

class serverrepo(object):
    def greet(self, name):
        return "Hello, " + name

    def filtered(self, name):
        return self

def mangle(s):
    return ''.join(chr(ord(c) + 1) for c in s)
def unmangle(s):
    return ''.join(chr(ord(c) - 1) for c in s)

def greet(repo, proto, name):
    return mangle(repo.greet(unmangle(name)))

wireproto.commands['greet'] = (greet, 'name',)

srv = serverrepo()
clt = clientpeer(srv)

print(clt.greet("Foobar"))
b = clt.iterbatch()
map(b.greet, ('Fo, =;:<o', 'Bar'))
b.submit()
print([r for r in b.results()])