Merge pull request #1167 from meejah/3852.json-welcome-page

3852.json welcome page
This commit is contained in:
meejah 2022-01-07 11:49:04 -07:00 committed by GitHub
commit 451d79af83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 136 additions and 27 deletions

View File

@ -0,0 +1 @@

View File

@ -11,6 +11,7 @@ if PY2:
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
import time
import json
from urllib.parse import (
quote,
@ -24,14 +25,23 @@ from twisted.web.template import Tag
from twisted.web.test.requesthelper import DummyRequest
from twisted.application import service
from testtools.twistedsupport import succeeded
from twisted.internet.defer import inlineCallbacks
from twisted.internet.defer import (
inlineCallbacks,
succeed,
)
from ...storage_client import (
NativeStorageServer,
StorageFarmBroker,
)
from ...web.root import RootElement
from ...web.root import (
RootElement,
Root,
)
from ...util.connection_status import ConnectionStatus
from ...crypto.ed25519 import (
create_signing_keypair,
)
from allmydata.web.root import URIHandler
from allmydata.client import _Client
@ -47,6 +57,7 @@ from ..common import (
from ..common import (
SyncTestCase,
AsyncTestCase,
)
from testtools.matchers import (
@ -138,3 +149,94 @@ class RenderServiceRow(SyncTestCase):
self.assertThat(item.slotData.get("version"), Equals(""))
self.assertThat(item.slotData.get("nickname"), Equals(""))
class RenderRoot(AsyncTestCase):
@inlineCallbacks
def test_root_json(self):
"""
The 'welcome' / root page renders properly with ?t=json when some
servers show None for available_space while others show a
valid int
See also https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3852
"""
ann = {
"anonymous-storage-FURL": "pb://w2hqnbaa25yw4qgcvghl5psa3srpfgw3@tcp:127.0.0.1:51309/vucto2z4fxment3vfxbqecblbf6zyp6x",
"permutation-seed-base32": "w2hqnbaa25yw4qgcvghl5psa3srpfgw3",
}
srv0 = NativeStorageServer(b"server_id0", ann, None, {}, EMPTY_CLIENT_CONFIG)
srv0.get_connection_status = lambda: ConnectionStatus(False, "summary0", {}, 0, 0)
srv1 = NativeStorageServer(b"server_id1", ann, None, {}, EMPTY_CLIENT_CONFIG)
srv1.get_connection_status = lambda: ConnectionStatus(False, "summary1", {}, 0, 0)
# arrange for this server to have some valid available space
srv1.get_available_space = lambda: 12345
class FakeClient(_Client):
history = []
stats_provider = object()
nickname = ""
nodeid = b"asdf"
_node_public_key = create_signing_keypair()[1]
introducer_clients = []
helper = None
def __init__(self):
service.MultiService.__init__(self)
self.storage_broker = StorageFarmBroker(
permute_peers=True,
tub_maker=None,
node_config=EMPTY_CLIENT_CONFIG,
)
self.storage_broker.test_add_server(b"test-srv0", srv0)
self.storage_broker.test_add_server(b"test-srv1", srv1)
root = Root(FakeClient(), now_fn=time.time)
lines = []
req = DummyRequest(b"")
req.fields = {}
req.args = {
b"t": [b"json"],
}
# for some reason, DummyRequest is already finished when we
# try to add a notifyFinish handler, so override that
# behavior.
def nop():
return succeed(None)
req.notifyFinish = nop
req.write = lines.append
yield root.render(req)
raw_js = b"".join(lines).decode("utf8")
js = json.loads(raw_js)
servers = js["servers"]
self.assertEquals(len(servers), 2)
self.assertIn(
{
"connection_status": "summary0",
"nodeid": "server_id0",
"last_received_data": 0,
"version": None,
"available_space": None,
"nickname": ""
},
servers
)
self.assertIn(
{
"connection_status": "summary1",
"nodeid": "server_id1",
"last_received_data": 0,
"version": None,
"available_space": 12345,
"nickname": ""
},
servers
)

View File

@ -820,29 +820,37 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, testutil.ReallyEqualMixi
"""
d = self.GET("/?t=json")
def _check(res):
"""
Check that the results are correct.
We can't depend on the order of servers in the output
"""
decoded = json.loads(res)
expected = {
u'introducers': {
u'statuses': [],
self.assertEqual(decoded['introducers'], {u'statuses': []})
actual_servers = decoded[u"servers"]
self.assertEquals(len(actual_servers), 2)
self.assertIn(
{
u"nodeid": u'other_nodeid',
u'available_space': 123456,
u'connection_status': u'summary',
u'last_received_data': 30,
u'nickname': u'other_nickname \u263b',
u'version': u'1.0',
},
u'servers': sorted([
{u"nodeid": u'other_nodeid',
u'available_space': 123456,
u'connection_status': u'summary',
u'last_received_data': 30,
u'nickname': u'other_nickname \u263b',
u'version': u'1.0',
},
{u"nodeid": u'disconnected_nodeid',
u'available_space': 123456,
u'connection_status': u'summary',
u'last_received_data': 35,
u'nickname': u'disconnected_nickname \u263b',
u'version': u'1.0',
},
], key=lambda o: sorted(o.items())),
}
self.assertEqual(expected, decoded)
actual_servers
)
self.assertIn(
{
u"nodeid": u'disconnected_nodeid',
u'available_space': 123456,
u'connection_status': u'summary',
u'last_received_data': 35,
u'nickname': u'disconnected_nickname \u263b',
u'version': u'1.0',
},
actual_servers
)
d.addCallback(_check)
return d

View File

@ -297,14 +297,12 @@ class Root(MultiFormatResource):
}
return json.dumps(result, indent=1) + "\n"
def _describe_known_servers(self, broker):
return sorted(list(
return list(
self._describe_server(server)
for server
in broker.get_known_servers()
), key=lambda o: sorted(o.items()))
)
def _describe_server(self, server):
status = server.get_connection_status()