Merge pull request #1016 from LeastAuthority/3650.tahoe-invite-regression
Fix regression in `tahoe invite` w/o shares parameters Fixes: ticket:3650
This commit is contained in:
commit
7ce7cf7f24
|
@ -0,0 +1 @@
|
||||||
|
``tahoe invite`` will now read share encoding/placement configuration values from a Tahoe client node configuration file if they are not given on the command line, instead of raising an unhandled exception.
|
|
@ -13,7 +13,7 @@ from wormhole import wormhole
|
||||||
from allmydata.util.encodingutil import argv_to_abspath
|
from allmydata.util.encodingutil import argv_to_abspath
|
||||||
from allmydata.util import jsonbytes as json
|
from allmydata.util import jsonbytes as json
|
||||||
from allmydata.scripts.common import get_default_nodedir, get_introducer_furl
|
from allmydata.scripts.common import get_default_nodedir, get_introducer_furl
|
||||||
from allmydata.node import read_config
|
from allmydata.client import read_config
|
||||||
|
|
||||||
|
|
||||||
class InviteOptions(usage.Options):
|
class InviteOptions(usage.Options):
|
||||||
|
@ -93,9 +93,9 @@ def invite(options):
|
||||||
nick = options['nick']
|
nick = options['nick']
|
||||||
|
|
||||||
remote_config = {
|
remote_config = {
|
||||||
"shares-needed": options["shares-needed"] or config.get('client', 'shares.needed'),
|
"shares-needed": options["shares-needed"] or config.get_config('client', 'shares.needed'),
|
||||||
"shares-total": options["shares-total"] or config.get('client', 'shares.total'),
|
"shares-total": options["shares-total"] or config.get_config('client', 'shares.total'),
|
||||||
"shares-happy": options["shares-happy"] or config.get('client', 'shares.happy'),
|
"shares-happy": options["shares-happy"] or config.get_config('client', 'shares.happy'),
|
||||||
"nickname": nick,
|
"nickname": nick,
|
||||||
"introducer": introducer_furl,
|
"introducer": introducer_furl,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ import mock
|
||||||
import json
|
import json
|
||||||
from os.path import join
|
from os.path import join
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Optional, Sequence
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
from twisted.trial import unittest
|
from twisted.trial import unittest
|
||||||
from twisted.internet import defer
|
from twisted.internet import defer
|
||||||
from ..common_util import run_cli
|
from ..common_util import run_cli
|
||||||
|
@ -163,17 +168,27 @@ class Invite(GridTestMixin, CLITestMixin, unittest.TestCase):
|
||||||
intro_dir,
|
intro_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
def _invite_success(self, extra_args=(), tahoe_config=None):
|
||||||
def test_invite_success(self):
|
# type: (Sequence[bytes], Optional[bytes]) -> defer.Deferred
|
||||||
"""
|
"""
|
||||||
successfully send an invite
|
Exercise an expected-success case of ``tahoe invite``.
|
||||||
|
|
||||||
|
:param extra_args: Positional arguments to pass to ``tahoe invite``
|
||||||
|
before the nickname.
|
||||||
|
|
||||||
|
:param tahoe_config: If given, bytes to write to the node's
|
||||||
|
``tahoe.cfg`` before running ``tahoe invite.
|
||||||
"""
|
"""
|
||||||
intro_dir = os.path.join(self.basedir, "introducer")
|
intro_dir = os.path.join(self.basedir, "introducer")
|
||||||
# we've never run the introducer, so it hasn't created
|
# we've never run the introducer, so it hasn't created
|
||||||
# introducer.furl yet
|
# introducer.furl yet
|
||||||
priv_dir = join(intro_dir, "private")
|
priv_dir = join(intro_dir, "private")
|
||||||
with open(join(priv_dir, "introducer.furl"), "w") as f:
|
with open(join(priv_dir, "introducer.furl"), "w") as fobj_intro:
|
||||||
f.write("pb://fooblam\n")
|
fobj_intro.write("pb://fooblam\n")
|
||||||
|
if tahoe_config is not None:
|
||||||
|
assert isinstance(tahoe_config, bytes)
|
||||||
|
with open(join(intro_dir, "tahoe.cfg"), "wb") as fobj_cfg:
|
||||||
|
fobj_cfg.write(tahoe_config)
|
||||||
|
|
||||||
with mock.patch('allmydata.scripts.tahoe_invite.wormhole') as w:
|
with mock.patch('allmydata.scripts.tahoe_invite.wormhole') as w:
|
||||||
fake_wh = _create_fake_wormhole([
|
fake_wh = _create_fake_wormhole([
|
||||||
|
@ -181,34 +196,79 @@ class Invite(GridTestMixin, CLITestMixin, unittest.TestCase):
|
||||||
])
|
])
|
||||||
w.create = mock.Mock(return_value=fake_wh)
|
w.create = mock.Mock(return_value=fake_wh)
|
||||||
|
|
||||||
rc, out, err = yield run_cli(
|
extra_args = tuple(extra_args)
|
||||||
|
|
||||||
|
d = run_cli(
|
||||||
"-d", intro_dir,
|
"-d", intro_dir,
|
||||||
"invite",
|
"invite",
|
||||||
"--shares-needed", "1",
|
*(extra_args + ("foo",))
|
||||||
"--shares-happy", "1",
|
|
||||||
"--shares-total", "1",
|
|
||||||
"foo",
|
|
||||||
)
|
)
|
||||||
self.assertEqual(2, len(fake_wh.messages))
|
|
||||||
self.assertEqual(
|
def done(result):
|
||||||
json.loads(fake_wh.messages[0]),
|
rc, out, err = result
|
||||||
{
|
self.assertEqual(2, len(fake_wh.messages))
|
||||||
"abilities":
|
self.assertEqual(
|
||||||
|
json.loads(fake_wh.messages[0]),
|
||||||
{
|
{
|
||||||
"server-v1": {}
|
"abilities":
|
||||||
|
{
|
||||||
|
"server-v1": {}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
)
|
||||||
)
|
invite = json.loads(fake_wh.messages[1])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
json.loads(fake_wh.messages[1]),
|
invite["nickname"], "foo",
|
||||||
{
|
)
|
||||||
"shares-needed": "1",
|
self.assertEqual(
|
||||||
"shares-total": "1",
|
invite["introducer"], "pb://fooblam",
|
||||||
"nickname": "foo",
|
)
|
||||||
"introducer": "pb://fooblam",
|
return invite
|
||||||
"shares-happy": "1",
|
d.addCallback(done)
|
||||||
},
|
return d
|
||||||
)
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_invite_success(self):
|
||||||
|
"""
|
||||||
|
successfully send an invite
|
||||||
|
"""
|
||||||
|
invite = yield self._invite_success((
|
||||||
|
b"--shares-needed", b"1",
|
||||||
|
b"--shares-happy", b"2",
|
||||||
|
b"--shares-total", b"3",
|
||||||
|
))
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-needed"], "1",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-happy"], "2",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-total"], "3",
|
||||||
|
)
|
||||||
|
|
||||||
|
@defer.inlineCallbacks
|
||||||
|
def test_invite_success_read_share_config(self):
|
||||||
|
"""
|
||||||
|
If ``--shares-{needed,happy,total}`` are not given on the command line
|
||||||
|
then the invitation is generated using the configured values.
|
||||||
|
"""
|
||||||
|
invite = yield self._invite_success(tahoe_config=b"""
|
||||||
|
[client]
|
||||||
|
shares.needed = 2
|
||||||
|
shares.happy = 4
|
||||||
|
shares.total = 6
|
||||||
|
""")
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-needed"], "2",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-happy"], "4",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
invite["shares-total"], "6",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def test_invite_no_furl(self):
|
def test_invite_no_furl(self):
|
||||||
|
|
Loading…
Reference in New Issue