Merge pull request #905 from tahoe-lafs/3514.test-introducer-python-3

Port test_introducer.py to Python 3

Fixes ticket:3514
This commit is contained in:
Itamar Turner-Trauring 2020-12-02 15:24:17 -05:00 committed by GitHub
commit 71d287c1c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 134 additions and 85 deletions

0
newsfragments/3514.minor Normal file
View File

View File

@ -1,3 +1,5 @@
from past.builtins import unicode
import os, stat, time, weakref
from base64 import urlsafe_b64encode
from functools import partial
@ -728,10 +730,14 @@ class _Client(node.Node, pollmixin.PollMixin):
return { 'node.uptime': time.time() - self.started_timestamp }
def init_secrets(self):
lease_s = self.config.get_or_create_private_config("secret", _make_secret)
# configs are always unicode
def _unicode_make_secret():
return unicode(_make_secret(), "ascii")
lease_s = self.config.get_or_create_private_config(
"secret", _unicode_make_secret).encode("utf-8")
lease_secret = base32.a2b(lease_s)
convergence_s = self.config.get_or_create_private_config('convergence',
_make_secret)
convergence_s = self.config.get_or_create_private_config(
'convergence', _unicode_make_secret).encode("utf-8")
self.convergence = base32.a2b(convergence_s)
self._secret_holder = SecretHolder(lease_secret, self.convergence)
@ -740,9 +746,11 @@ class _Client(node.Node, pollmixin.PollMixin):
# existing key
def _make_key():
private_key, _ = ed25519.create_signing_keypair()
return ed25519.string_from_signing_key(private_key) + b"\n"
# Config values are always unicode:
return unicode(ed25519.string_from_signing_key(private_key) + b"\n", "utf-8")
private_key_str = self.config.get_or_create_private_config("node.privkey", _make_key)
private_key_str = self.config.get_or_create_private_config(
"node.privkey", _make_key).encode("utf-8")
private_key, public_key = ed25519.signing_keypair_from_string(private_key_str)
public_key_str = ed25519.string_from_verifying_key(public_key)
self.config.write_config_file("node.pubkey", public_key_str + b"\n", "wb")

View File

@ -1,4 +1,5 @@
from past.builtins import unicode
from past.builtins import unicode, long
from six import ensure_text
import time
from zope.interface import implementer
@ -17,7 +18,7 @@ from allmydata.util.assertutil import precondition
class InvalidCacheError(Exception):
pass
V2 = "http://allmydata.org/tahoe/protocols/introducer/v2"
V2 = b"http://allmydata.org/tahoe/protocols/introducer/v2"
@implementer(RIIntroducerSubscriberClient_v2, IIntroducerClient)
class IntroducerClient(service.Service, Referenceable):
@ -26,6 +27,8 @@ class IntroducerClient(service.Service, Referenceable):
nickname, my_version, oldest_supported,
sequencer, cache_filepath):
self._tub = tub
if isinstance(introducer_furl, unicode):
introducer_furl = introducer_furl.encode("utf-8")
self.introducer_furl = introducer_furl
assert type(nickname) is unicode
@ -35,11 +38,11 @@ class IntroducerClient(service.Service, Referenceable):
self._sequencer = sequencer
self._cache_filepath = cache_filepath
self._my_subscriber_info = { "version": 0,
"nickname": self._nickname,
"app-versions": [],
"my-version": self._my_version,
"oldest-supported": self._oldest_supported,
self._my_subscriber_info = { b"version": 0,
b"nickname": self._nickname,
b"app-versions": [],
b"my-version": self._my_version,
b"oldest-supported": self._oldest_supported,
}
self._outbound_announcements = {} # not signed
@ -113,19 +116,24 @@ class IntroducerClient(service.Service, Referenceable):
announcements = []
for _, value in self._inbound_announcements.items():
ann, key_s, time_stamp = value
# On Python 2, bytes strings are encoded into YAML Unicode strings.
# On Python 3, bytes are encoded as YAML bytes. To minimize
# changes, Python 3 for now ensures the same is true.
server_params = {
"ann" : ann,
"key_s" : key_s,
"key_s" : ensure_text(key_s),
}
announcements.append(server_params)
announcement_cache_yaml = yamlutil.safe_dump(announcements)
if isinstance(announcement_cache_yaml, unicode):
announcement_cache_yaml = announcement_cache_yaml.encode("utf-8")
self._cache_filepath.setContent(announcement_cache_yaml)
def _got_introducer(self, publisher):
self.log("connected to introducer, getting versions")
default = { "http://allmydata.org/tahoe/protocols/introducer/v1":
default = { b"http://allmydata.org/tahoe/protocols/introducer/v1":
{ },
"application-version": "unknown: no get_version()",
b"application-version": b"unknown: no get_version()",
}
d = add_version_to_remote_reference(publisher, default)
d.addCallback(self._got_versioned_introducer)
@ -138,6 +146,7 @@ class IntroducerClient(service.Service, Referenceable):
def _got_versioned_introducer(self, publisher):
self.log("got introducer version: %s" % (publisher.version,))
# we require an introducer that speaks at least V2
assert all(type(V2) == type(v) for v in publisher.version)
if V2 not in publisher.version:
raise InsufficientVersionError("V2", publisher.version)
self._publisher = publisher
@ -162,7 +171,7 @@ class IntroducerClient(service.Service, Referenceable):
self._subscribed_service_names.add(service_name)
self._maybe_subscribe()
for index,(ann,key_s,when) in self._inbound_announcements.items():
precondition(isinstance(key_s, str), key_s)
precondition(isinstance(key_s, bytes), key_s)
servicename = index[0]
if servicename == service_name:
eventually(cb, key_s, ann, *args, **kwargs)
@ -238,7 +247,7 @@ class IntroducerClient(service.Service, Referenceable):
# this might raise UnknownKeyError or bad-sig error
ann, key_s = unsign_from_foolscap(ann_t)
# key is "v0-base32abc123"
precondition(isinstance(key_s, str), key_s)
precondition(isinstance(key_s, bytes), key_s)
except BadSignature:
self.log("bad signature on inbound announcement: %s" % (ann_t,),
parent=lp, level=log.WEIRD, umid="ZAU15Q")
@ -248,7 +257,7 @@ class IntroducerClient(service.Service, Referenceable):
self._process_announcement(ann, key_s)
def _process_announcement(self, ann, key_s):
precondition(isinstance(key_s, str), key_s)
precondition(isinstance(key_s, bytes), key_s)
self._debug_counts["inbound_announcement"] += 1
service_name = str(ann["service-name"])
if service_name not in self._subscribed_service_names:
@ -257,7 +266,7 @@ class IntroducerClient(service.Service, Referenceable):
self._debug_counts["wrong_service"] += 1
return
# for ASCII values, simplejson might give us unicode *or* bytes
if "nickname" in ann and isinstance(ann["nickname"], str):
if "nickname" in ann and isinstance(ann["nickname"], bytes):
ann["nickname"] = unicode(ann["nickname"])
nick_s = ann.get("nickname",u"").encode("utf-8")
lp2 = self.log(format="announcement for nickname '%(nick)s', service=%(svc)s: %(ann)s",
@ -266,11 +275,11 @@ class IntroducerClient(service.Service, Referenceable):
# how do we describe this node in the logs?
desc_bits = []
assert key_s
desc_bits.append("serverid=" + key_s[:20])
desc_bits.append(b"serverid=" + key_s[:20])
if "anonymous-storage-FURL" in ann:
tubid_s = get_tubid_string_from_ann(ann)
desc_bits.append("tubid=" + tubid_s[:8])
description = "/".join(desc_bits)
desc_bits.append(b"tubid=" + tubid_s[:8])
description = b"/".join(desc_bits)
# the index is used to track duplicates
index = (service_name, key_s)
@ -320,7 +329,7 @@ class IntroducerClient(service.Service, Referenceable):
self._deliver_announcements(key_s, ann)
def _deliver_announcements(self, key_s, ann):
precondition(isinstance(key_s, str), key_s)
precondition(isinstance(key_s, bytes), key_s)
service_name = str(ann["service-name"])
for (service_name2,cb,args,kwargs) in self._local_subscribers:
if service_name2 == service_name:

View File

@ -1,16 +1,19 @@
from past.builtins import unicode
import re
import json
from allmydata.crypto.util import remove_prefix
from allmydata.crypto import ed25519
from allmydata.util import base32, rrefutil
from allmydata.util import base32, rrefutil, jsonbytes as json
def get_tubid_string_from_ann(ann):
return get_tubid_string(str(ann.get("anonymous-storage-FURL")
or ann.get("FURL")))
furl = ann.get("anonymous-storage-FURL") or ann.get("FURL")
if isinstance(furl, unicode):
furl = furl.encode("utf-8")
return get_tubid_string(furl)
def get_tubid_string(furl):
m = re.match(r'pb://(\w+)@', furl)
m = re.match(br'pb://(\w+)@', furl)
assert m
return m.group(1).lower()

View File

@ -1,3 +1,5 @@
from past.builtins import long
from six import ensure_str, ensure_text
import time, os.path, textwrap
from zope.interface import implementer
@ -7,7 +9,7 @@ from twisted.python.failure import Failure
from foolscap.api import Referenceable
import allmydata
from allmydata import node
from allmydata.util import log, rrefutil
from allmydata.util import log, rrefutil, dictutil
from allmydata.util.i2p_provider import create as create_i2p_provider
from allmydata.util.tor_provider import create as create_tor_provider
from allmydata.introducer.interfaces import \
@ -122,7 +124,7 @@ class _IntroducerNode(node.Node):
from allmydata.webish import IntroducerWebishServer
nodeurl_path = self.config.get_config_path(u"node.url")
config_staticdir = self.get_config("node", "web.static", "public_html").decode('utf-8')
config_staticdir = self.get_config("node", "web.static", "public_html")
staticdir = self.config.get_config_path(config_staticdir)
ws = IntroducerWebishServer(self, webport, nodeurl_path, staticdir)
ws.setServiceParent(self)
@ -133,8 +135,8 @@ class IntroducerService(service.MultiService, Referenceable):
# v1 is the original protocol, added in 1.0 (but only advertised starting
# in 1.3), removed in 1.12. v2 is the new signed protocol, added in 1.10
VERSION = { #"http://allmydata.org/tahoe/protocols/introducer/v1": { },
"http://allmydata.org/tahoe/protocols/introducer/v2": { },
"application-version": str(allmydata.__full_version__),
b"http://allmydata.org/tahoe/protocols/introducer/v2": { },
b"application-version": allmydata.__full_version__.encode("utf-8"),
}
def __init__(self):
@ -279,6 +281,10 @@ class IntroducerService(service.MultiService, Referenceable):
def remote_subscribe_v2(self, subscriber, service_name, subscriber_info):
self.log("introducer: subscription[%s] request at %s"
% (service_name, subscriber), umid="U3uzLg")
service_name = ensure_str(service_name)
subscriber_info = dictutil.UnicodeKeyDict({
ensure_text(k): v for (k, v) in subscriber_info.items()
})
return self.add_subscriber(subscriber, service_name, subscriber_info)
def add_subscriber(self, subscriber, service_name, subscriber_info):
@ -302,6 +308,10 @@ class IntroducerService(service.MultiService, Referenceable):
subscriber.notifyOnDisconnect(_remove)
# now tell them about any announcements they're interested in
assert {type(service_name)}.issuperset(
set(type(k[0]) for k in self._announcements)), (
service_name, self._announcements.keys()
)
announcements = set( [ ann_t
for idx,(ann_t,canary,ann,when)
in self._announcements.items()

View File

@ -914,7 +914,7 @@ class Publish(object):
def log_goal(self, goal, message=""):
logmsg = [message]
for (shnum, server) in sorted([(s,p) for (p,s) in goal]):
for (shnum, server) in sorted([(s,p) for (p,s) in goal], key=lambda t: (id(t[0]), id(t[1]))):
logmsg.append("sh%d to [%s]" % (shnum, server.get_name()))
self.log("current goal: %s" % (", ".join(logmsg)), level=log.NOISY)
self.log("we are planning to push new seqnum=#%d" % self._new_seqnum,

View File

@ -1,3 +1,16 @@
"""
Ported to Python 3.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from future.utils import PY2
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
from six import ensure_binary, ensure_text
import os, re, itertools
from base64 import b32decode
@ -100,7 +113,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, AsyncTestCase):
q1 = yield create_introducer(basedir)
del q1
# new nodes create unguessable furls in private/introducer.furl
ifurl = fileutil.read(private_fn)
ifurl = fileutil.read(private_fn, mode="r")
self.failUnless(ifurl)
ifurl = ifurl.strip()
self.failIf(ifurl.endswith("/introducer"), ifurl)
@ -120,7 +133,7 @@ class Node(testutil.SignalMixin, testutil.ReallyEqualMixin, AsyncTestCase):
q2 = yield create_introducer(basedir)
del q2
self.failIf(os.path.exists(public_fn))
ifurl2 = fileutil.read(private_fn)
ifurl2 = fileutil.read(private_fn, mode="r")
self.failUnless(ifurl2)
self.failUnlessEqual(ifurl2.strip(), guessable)
@ -169,7 +182,7 @@ def fakeseq():
seqnum_counter = itertools.count(1)
def realseq():
return seqnum_counter.next(), str(os.randint(1,100000))
return next(seqnum_counter), str(os.randint(1,100000))
def make_ann(furl):
ann = { "anonymous-storage-FURL": furl,
@ -200,13 +213,13 @@ class Client(AsyncTestCase):
def _received(key_s, ann):
announcements.append( (key_s, ann) )
ic1.subscribe_to("storage", _received)
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
furl1a = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:7777/gydnp"
furl2 = "pb://ttwwooyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/ttwwoo"
furl1 = b"pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
furl1a = b"pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:7777/gydnp"
furl2 = b"pb://ttwwooyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/ttwwoo"
private_key, public_key = ed25519.create_signing_keypair()
public_key_str = ed25519.string_from_verifying_key(public_key)
pubkey_s = remove_prefix(public_key_str, "pub-")
pubkey_s = remove_prefix(public_key_str, b"pub-")
# ann1: ic1, furl1
# ann1a: ic1, furl1a (same SturdyRef, different connection hints)
@ -226,7 +239,7 @@ class Client(AsyncTestCase):
self.failUnlessEqual(len(announcements), 1)
key_s,ann = announcements[0]
self.failUnlessEqual(key_s, pubkey_s)
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl1)
self.failUnlessEqual(ann["my-version"], "ver23")
d.addCallback(_then1)
@ -260,7 +273,7 @@ class Client(AsyncTestCase):
self.failUnlessEqual(len(announcements), 2)
key_s,ann = announcements[-1]
self.failUnlessEqual(key_s, pubkey_s)
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl1)
self.failUnlessEqual(ann["my-version"], "ver24")
d.addCallback(_then3)
@ -272,7 +285,7 @@ class Client(AsyncTestCase):
self.failUnlessEqual(len(announcements), 3)
key_s,ann = announcements[-1]
self.failUnlessEqual(key_s, pubkey_s)
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1a)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl1a)
self.failUnlessEqual(ann["my-version"], "ver23")
d.addCallback(_then4)
@ -288,7 +301,7 @@ class Client(AsyncTestCase):
self.failUnlessEqual(len(announcements2), 1)
key_s,ann = announcements2[-1]
self.failUnlessEqual(key_s, pubkey_s)
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1a)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl1a)
self.failUnlessEqual(ann["my-version"], "ver23")
d.addCallback(_then5)
return d
@ -300,7 +313,7 @@ class Server(AsyncTestCase):
"introducer.furl", u"my_nickname",
"ver23", "oldest_version", realseq,
FilePath(self.mktemp()))
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
furl1 = b"pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
private_key, _ = ed25519.create_signing_keypair()
@ -398,7 +411,7 @@ class Queue(SystemTestMixin, AsyncTestCase):
c = IntroducerClient(tub2, ifurl,
u"nickname", "version", "oldest", fakeseq,
FilePath(self.mktemp()))
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
furl1 = b"pb://onug64tu@127.0.0.1:123/short" # base32("short")
private_key, _ = ed25519.create_signing_keypair()
d = introducer.disownServiceParent()
@ -420,7 +433,7 @@ class Queue(SystemTestMixin, AsyncTestCase):
def _done(ign):
v = introducer.get_announcements()[0]
furl = v.announcement["anonymous-storage-FURL"]
self.failUnlessEqual(furl, furl1)
self.failUnlessEqual(ensure_binary(furl), furl1)
d.addCallback(_done)
# now let the ack get back
@ -446,7 +459,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
iff = os.path.join(self.basedir, "introducer.furl")
tub = self.central_tub
ifurl = self.central_tub.registerReference(introducer, furlFile=iff)
self.introducer_furl = ifurl
self.introducer_furl = ifurl.encode("utf-8")
# we have 5 clients who publish themselves as storage servers, and a
# sixth which does which not. All 6 clients subscriber to hear about
@ -487,7 +500,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
subscribing_clients.append(c)
expected_announcements[i] += 1 # all expect a 'storage' announcement
node_furl = tub.registerReference(Referenceable())
node_furl = tub.registerReference(Referenceable()).encode("utf-8")
private_key, public_key = ed25519.create_signing_keypair()
public_key_str = ed25519.string_from_verifying_key(public_key)
privkeys[i] = private_key
@ -504,7 +517,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
if i == 2:
# also publish something that nobody cares about
boring_furl = tub.registerReference(Referenceable())
boring_furl = tub.registerReference(Referenceable()).encode("utf-8")
c.publish("boring", make_ann(boring_furl), private_key)
c.setServiceParent(self.parent)
@ -581,7 +594,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
serverid0 = printable_serverids[0]
ann = anns[serverid0]
nick = ann["nickname"]
self.failUnlessEqual(type(nick), unicode)
self.assertIsInstance(nick, str)
self.failUnlessEqual(nick, NICKNAME % "0")
for c in publishing_clients:
cdc = c._debug_counts
@ -592,7 +605,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
self.failUnlessEqual(cdc["outbound_message"], expected)
# now check the web status, make sure it renders without error
ir = introweb.IntroducerRoot(self.parent)
self.parent.nodeid = "NODEID"
self.parent.nodeid = b"NODEID"
log.msg("_check1 done")
return flattenString(None, ir._create_element())
d.addCallback(_check1)
@ -602,7 +615,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
self.assertIn(NICKNAME % "0", text) # a v2 client
self.assertIn(NICKNAME % "1", text) # another v2 client
for i in range(NUM_STORAGE):
self.assertIn(printable_serverids[i], text,
self.assertIn(ensure_text(printable_serverids[i]), text,
(i,printable_serverids[i],text))
# make sure there isn't a double-base32ed string too
self.assertNotIn(idlib.nodeid_b2a(printable_serverids[i]), text,
@ -642,7 +655,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
self.create_tub(self.central_portnum)
newfurl = self.central_tub.registerReference(self.the_introducer,
furlFile=iff)
assert newfurl == self.introducer_furl
assert ensure_binary(newfurl) == self.introducer_furl
d.addCallback(_restart_introducer_tub)
d.addCallback(_wait_for_connected)
@ -694,7 +707,7 @@ class SystemTest(SystemTestMixin, AsyncTestCase):
self.the_introducer = introducer
newfurl = self.central_tub.registerReference(self.the_introducer,
furlFile=iff)
assert newfurl == self.introducer_furl
assert ensure_binary(newfurl) == self.introducer_furl
d.addCallback(_restart_introducer)
d.addCallback(_wait_for_connected)
@ -740,7 +753,7 @@ class ClientInfo(AsyncTestCase):
client_v2 = IntroducerClient(tub, introducer_furl, NICKNAME % u"v2",
"my_version", "oldest",
fakeseq, FilePath(self.mktemp()))
#furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
#furl1 = b"pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
#ann_s = make_ann_t(client_v2, furl1, None, 10)
#introducer.remote_publish_v2(ann_s, Referenceable())
subscriber = FakeRemoteReference()
@ -761,10 +774,10 @@ class Announcements(AsyncTestCase):
client_v2 = IntroducerClient(tub, introducer_furl, u"nick-v2",
"my_version", "oldest",
fakeseq, FilePath(self.mktemp()))
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
furl1 = b"pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
private_key, public_key = ed25519.create_signing_keypair()
public_key_str = remove_prefix(ed25519.string_from_verifying_key(public_key), "pub-")
public_key_str = remove_prefix(ed25519.string_from_verifying_key(public_key), b"pub-")
ann_t0 = make_ann_t(client_v2, furl1, private_key, 10)
canary0 = Referenceable()
@ -776,7 +789,7 @@ class Announcements(AsyncTestCase):
self.failUnlessEqual(a[0].nickname, u"nick-v2")
self.failUnlessEqual(a[0].service_name, "storage")
self.failUnlessEqual(a[0].version, "my_version")
self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
self.failUnlessEqual(ensure_binary(a[0].announcement["anonymous-storage-FURL"]), furl1)
def _load_cache(self, cache_filepath):
with cache_filepath.open() as f:
@ -802,8 +815,8 @@ class Announcements(AsyncTestCase):
c = yield create_client(basedir)
ic = c.introducer_clients[0]
private_key, public_key = ed25519.create_signing_keypair()
public_key_str = remove_prefix(ed25519.string_from_verifying_key(public_key), "pub-")
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
public_key_str = remove_prefix(ed25519.string_from_verifying_key(public_key), b"pub-")
furl1 = b"pb://onug64tu@127.0.0.1:123/short" # base32("short")
ann_t = make_ann_t(ic, furl1, private_key, 1)
ic.got_announcements([ann_t])
@ -812,29 +825,29 @@ class Announcements(AsyncTestCase):
# check the cache for the announcement
announcements = self._load_cache(cache_filepath)
self.failUnlessEqual(len(announcements), 1)
self.failUnlessEqual(announcements[0]['key_s'], public_key_str)
self.failUnlessEqual(ensure_binary(announcements[0]['key_s']), public_key_str)
ann = announcements[0]["ann"]
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl1)
self.failUnlessEqual(ann["seqnum"], 1)
# a new announcement that replaces the first should replace the
# cached entry, not duplicate it
furl2 = furl1 + "er"
furl2 = furl1 + b"er"
ann_t2 = make_ann_t(ic, furl2, private_key, 2)
ic.got_announcements([ann_t2])
yield flushEventualQueue()
announcements = self._load_cache(cache_filepath)
self.failUnlessEqual(len(announcements), 1)
self.failUnlessEqual(announcements[0]['key_s'], public_key_str)
self.failUnlessEqual(ensure_binary(announcements[0]['key_s']), public_key_str)
ann = announcements[0]["ann"]
self.failUnlessEqual(ann["anonymous-storage-FURL"], furl2)
self.failUnlessEqual(ensure_binary(ann["anonymous-storage-FURL"]), furl2)
self.failUnlessEqual(ann["seqnum"], 2)
# but a third announcement with a different key should add to the
# cache
private_key2, public_key2 = ed25519.create_signing_keypair()
public_key_str2 = remove_prefix(ed25519.string_from_verifying_key(public_key2), "pub-")
furl3 = "pb://onug64tu@127.0.0.1:456/short"
public_key_str2 = remove_prefix(ed25519.string_from_verifying_key(public_key2), b"pub-")
furl3 = b"pb://onug64tu@127.0.0.1:456/short"
ann_t3 = make_ann_t(ic, furl3, private_key2, 1)
ic.got_announcements([ann_t3])
yield flushEventualQueue()
@ -842,9 +855,9 @@ class Announcements(AsyncTestCase):
announcements = self._load_cache(cache_filepath)
self.failUnlessEqual(len(announcements), 2)
self.failUnlessEqual(set([public_key_str, public_key_str2]),
set([a["key_s"] for a in announcements]))
set([ensure_binary(a["key_s"]) for a in announcements]))
self.failUnlessEqual(set([furl2, furl3]),
set([a["ann"]["anonymous-storage-FURL"]
set([ensure_binary(a["ann"]["anonymous-storage-FURL"])
for a in announcements]))
# test loading
@ -860,9 +873,9 @@ class Announcements(AsyncTestCase):
yield flushEventualQueue()
self.failUnless(public_key_str in announcements)
self.failUnlessEqual(announcements[public_key_str]["anonymous-storage-FURL"],
self.failUnlessEqual(ensure_binary(announcements[public_key_str]["anonymous-storage-FURL"]),
furl2)
self.failUnlessEqual(announcements[public_key_str2]["anonymous-storage-FURL"],
self.failUnlessEqual(ensure_binary(announcements[public_key_str2]["anonymous-storage-FURL"]),
furl3)
c2 = yield create_client(basedir)
@ -903,7 +916,9 @@ class ClientSeqnums(AsyncBrokenTestCase):
self.failUnless("sA" in outbound)
self.failUnlessEqual(outbound["sA"]["seqnum"], 1)
nonce1 = outbound["sA"]["nonce"]
self.failUnless(isinstance(nonce1, str))
self.failUnless(isinstance(nonce1, bytes))
# Make nonce unicode, to match JSON:
outbound["sA"]["nonce"] = str(nonce1, "utf-8")
self.failUnlessEqual(json.loads(published["sA"][0]),
outbound["sA"])
# [1] is the signature, [2] is the pubkey
@ -917,8 +932,11 @@ class ClientSeqnums(AsyncBrokenTestCase):
self.failUnless("sA" in outbound)
self.failUnlessEqual(outbound["sA"]["seqnum"], 2)
nonce2 = outbound["sA"]["nonce"]
self.failUnless(isinstance(nonce2, str))
self.failUnless(isinstance(nonce2, bytes))
self.failIfEqual(nonce1, nonce2)
# Make nonce unicode, to match JSON:
outbound["sA"]["nonce"] = str(nonce2, "utf-8")
outbound["sB"]["nonce"] = str(outbound["sB"]["nonce"], "utf-8")
self.failUnlessEqual(json.loads(published["sA"][0]),
outbound["sA"])
self.failUnlessEqual(json.loads(published["sB"][0]),
@ -975,11 +993,11 @@ class DecodeFurl(SyncTestCase):
def test_decode(self):
# make sure we have a working base64.b32decode. The one in
# python2.4.[01] was broken.
furl = 'pb://t5g7egomnnktbpydbuijt6zgtmw4oqi5@127.0.0.1:51857/hfzv36i'
m = re.match(r'pb://(\w+)@', furl)
furl = b'pb://t5g7egomnnktbpydbuijt6zgtmw4oqi5@127.0.0.1:51857/hfzv36i'
m = re.match(br'pb://(\w+)@', furl)
assert m
nodeid = b32decode(m.group(1).upper())
self.failUnlessEqual(nodeid, "\x9fM\xf2\x19\xcckU0\xbf\x03\r\x10\x99\xfb&\x9b-\xc7A\x1d")
self.failUnlessEqual(nodeid, b"\x9fM\xf2\x19\xcckU0\xbf\x03\r\x10\x99\xfb&\x9b-\xc7A\x1d")
class Signatures(SyncTestCase):
@ -991,11 +1009,11 @@ class Signatures(SyncTestCase):
(msg, sig, key) = ann_t
self.failUnlessEqual(type(msg), type("".encode("utf-8"))) # bytes
self.failUnlessEqual(json.loads(msg.decode("utf-8")), ann)
self.failUnless(sig.startswith("v0-"))
self.failUnless(key.startswith("v0-"))
self.failUnless(sig.startswith(b"v0-"))
self.failUnless(key.startswith(b"v0-"))
(ann2,key2) = unsign_from_foolscap(ann_t)
self.failUnlessEqual(ann2, ann)
self.failUnlessEqual("pub-" + key2, public_key_str)
self.failUnlessEqual(b"pub-" + key2, public_key_str)
# not signed
self.failUnlessRaises(UnknownKeyError,
@ -1010,16 +1028,16 @@ class Signatures(SyncTestCase):
# unrecognized signatures
self.failUnlessRaises(UnknownKeyError,
unsign_from_foolscap, (bad_msg, "v999-sig", key))
unsign_from_foolscap, (bad_msg, b"v999-sig", key))
self.failUnlessRaises(UnknownKeyError,
unsign_from_foolscap, (bad_msg, sig, "v999-key"))
unsign_from_foolscap, (bad_msg, sig, b"v999-key"))
def test_unsigned_announcement(self):
ed25519.verifying_key_from_string(b"pub-v0-wodst6ly4f7i7akt2nxizsmmy2rlmer6apltl56zctn67wfyu5tq")
mock_tub = Mock()
ic = IntroducerClient(
mock_tub,
u"pb://",
b"pb://",
u"fake_nick",
"0.0.0",
"1.2.3",
@ -1028,7 +1046,7 @@ class Signatures(SyncTestCase):
)
self.assertEqual(0, ic._debug_counts["inbound_announcement"])
ic.got_announcements([
("message", "v0-aaaaaaa", "v0-wodst6ly4f7i7akt2nxizsmmy2rlmer6apltl56zctn67wfyu5tq")
(b"message", b"v0-aaaaaaa", b"v0-wodst6ly4f7i7akt2nxizsmmy2rlmer6apltl56zctn67wfyu5tq")
])
# we should have rejected this announcement due to a bad signature
self.assertEqual(0, ic._debug_counts["inbound_announcement"])

View File

@ -141,6 +141,7 @@ PORTED_TEST_MODULES = [
"allmydata.test.test_helper",
"allmydata.test.test_humanreadable",
"allmydata.test.test_immutable",
"allmydata.test.test_introducer",
"allmydata.test.test_iputil",
"allmydata.test.test_log",
"allmydata.test.test_monitor",

View File

@ -104,7 +104,7 @@ class IntroducerRootElement(Element):
if ad.service_name not in services:
services[ad.service_name] = 0
services[ad.service_name] += 1
service_names = services.keys()
service_names = list(services.keys())
service_names.sort()
return u", ".join(u"{}: {}".format(service_name, services[service_name])
for service_name in service_names)