From 346608871759ffcbf03444bd46aed48c574a660f Mon Sep 17 00:00:00 2001 From: meejah Date: Mon, 16 Jan 2017 14:20:23 -0700 Subject: [PATCH] add --json option for 'tahoe list-aliases' some new tests to cover previously-uncovered code that changed --- src/allmydata/scripts/cli.py | 1 + src/allmydata/scripts/tahoe_add_alias.py | 41 +++++++-- src/allmydata/test/cli/test_alias.py | 104 +++++++++++++++++++++++ 3 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 src/allmydata/test/cli/test_alias.py diff --git a/src/allmydata/scripts/cli.py b/src/allmydata/scripts/cli.py index 9e4e0f3c6..b68e80bf6 100644 --- a/src/allmydata/scripts/cli.py +++ b/src/allmydata/scripts/cli.py @@ -85,6 +85,7 @@ class ListAliasesOptions(FileStoreOptions): description = """Display a table of all configured aliases.""" optFlags = [ ("readonly-uri", None, "Show read-only dircaps instead of readwrite"), + ("json", None, "Show JSON output"), ] class ListOptions(FileStoreOptions): diff --git a/src/allmydata/scripts/tahoe_add_alias.py b/src/allmydata/scripts/tahoe_add_alias.py index eb91fff61..a9da056af 100644 --- a/src/allmydata/scripts/tahoe_add_alias.py +++ b/src/allmydata/scripts/tahoe_add_alias.py @@ -1,6 +1,7 @@ import os.path import codecs +import json from allmydata.util.assertutil import precondition @@ -95,24 +96,46 @@ def create_alias(options): print >>stdout, "Alias %s created" % (quote_output(alias),) return 0 + +def _get_alias_details(nodedir): + aliases = get_aliases(nodedir) + alias_names = sorted(aliases.keys()) + data = {} + for name in alias_names: + dircap = uri.from_string(aliases[name]) + data[name] = { + "readwrite": dircap.to_string(), + "readonly": dircap.get_readonly().to_string(), + } + return data + + def list_aliases(options): nodedir = options['node-directory'] stdout = options.stdout stderr = options.stderr - aliases = get_aliases(nodedir) - alias_names = sorted(aliases.keys()) - max_width = max([len(quote_output(name)) for name in alias_names] + [0]) + + data = _get_alias_details(nodedir) + + max_width = max([len(quote_output(name)) for name in data.keys()] + [0]) fmt = "%" + str(max_width) + "s: %s" rc = 0 - for name in alias_names: - dircap = uri.from_string(aliases[name]) - if options['readonly-uri']: - dircap = dircap.get_readonly() + + if options['json']: try: - print >>stdout, fmt % (unicode_to_output(name), unicode_to_output(dircap.to_string().decode('utf-8'))) + # XXX why are we presuming utf-8 output? + print >>stdout, json.dumps(data, indent=4).decode('utf-8') except (UnicodeEncodeError, UnicodeDecodeError): - print >>stderr, fmt % (quote_output(name), quote_output(aliases[name])) + print >>stderr, json.dumps(data, indent=4) rc = 1 + else: + for name, details in data.items(): + dircap = details['readonly'] if options['readonly-uri'] else details['readwrite'] + try: + print >>stdout, fmt % (unicode_to_output(name), unicode_to_output(dircap.decode('utf-8'))) + except (UnicodeEncodeError, UnicodeDecodeError): + print >>stderr, fmt % (quote_output(name), quote_output(dircap)) + rc = 1 if rc == 1: print >>stderr, "\nThis listing included aliases or caps that could not be converted to the terminal" \ diff --git a/src/allmydata/test/cli/test_alias.py b/src/allmydata/test/cli/test_alias.py new file mode 100644 index 000000000..3925a4af6 --- /dev/null +++ b/src/allmydata/test/cli/test_alias.py @@ -0,0 +1,104 @@ +import json +from mock import patch + +from twisted.trial import unittest +from twisted.internet.defer import inlineCallbacks + +from allmydata.util.encodingutil import unicode_to_argv +from allmydata.scripts.common import get_aliases +from allmydata.test.no_network import GridTestMixin +from .common import CLITestMixin + + +# see also test_create_alias + + +class ListAlias(GridTestMixin, CLITestMixin, unittest.TestCase): + + @inlineCallbacks + def test_list(self): + self.basedir = "cli/ListAlias/test_list" + self.set_up_grid(oneshare=True) + + rc, stdout, stderr = yield self.do_cli( + "create-alias", + unicode_to_argv(u"tahoe"), + ) + + self.failUnless(unicode_to_argv(u"Alias 'tahoe' created") in stdout) + self.failIf(stderr) + aliases = get_aliases(self.get_clientdir()) + self.failUnless(u"tahoe" in aliases) + self.failUnless(aliases[u"tahoe"].startswith("URI:DIR2:")) + + rc, stdout, stderr = yield self.do_cli("list-aliases", "--json") + + self.assertEqual(0, rc) + data = json.loads(stdout) + self.assertIn(u"tahoe", data) + data = data[u"tahoe"] + self.assertIn("readwrite", data) + self.assertIn("readonly", data) + + @inlineCallbacks + def test_list_unicode_mismatch_json(self): + """ + pretty hack-y test, but we want to cover the 'except' on Unicode + errors paths and I can't come up with a nicer way to trigger + this + """ + self.basedir = "cli/ListAlias/test_list_unicode_mismatch_json" + self.set_up_grid(oneshare=True) + + rc, stdout, stderr = yield self.do_cli( + "create-alias", + unicode_to_argv(u"tahoe\u263A"), + ) + + self.failUnless(unicode_to_argv(u"Alias 'tahoe\u263A' created") in stdout) + self.failIf(stderr) + + booms = [] + + def boom(out, indent=4): + if not len(booms): + booms.append(out) + raise UnicodeEncodeError("foo", u"foo", 3, 5, "foo") + return str(out) + + with patch("allmydata.scripts.tahoe_add_alias.json.dumps", boom): + aliases = get_aliases(self.get_clientdir()) + self.failUnless(u"tahoe\u263A" in aliases) + self.failUnless(aliases[u"tahoe\u263A"].startswith("URI:DIR2:")) + + rc, stdout, stderr = yield self.do_cli("list-aliases", "--json") + + self.assertEqual(1, rc) + self.assertIn("could not be converted", stderr) + + @inlineCallbacks + def test_list_unicode_mismatch(self): + self.basedir = "cli/ListAlias/test_list_unicode_mismatch" + self.set_up_grid(oneshare=True) + + rc, stdout, stderr = yield self.do_cli( + "create-alias", + unicode_to_argv(u"tahoe\u263A"), + ) + + def boom(out): + print("boom {}".format(out)) + return out + raise UnicodeEncodeError("foo", u"foo", 3, 5, "foo") + + with patch("allmydata.scripts.tahoe_add_alias.unicode_to_output", boom): + self.failUnless(unicode_to_argv(u"Alias 'tahoe\u263A' created") in stdout) + self.failIf(stderr) + aliases = get_aliases(self.get_clientdir()) + self.failUnless(u"tahoe\u263A" in aliases) + self.failUnless(aliases[u"tahoe\u263A"].startswith("URI:DIR2:")) + + rc, stdout, stderr = yield self.do_cli("list-aliases") + + self.assertEqual(1, rc) + self.assertIn("could not be converted", stderr)