-import os, re
+import os, re, itertools
from base64 import b32decode
import simplejson
from twisted.trial import unittest
-from twisted.internet import defer
+from twisted.internet import defer, address
from twisted.python import log
from foolscap.api import Tub, Referenceable, fireEventually, flushEventualQueue
from allmydata.introducer import old
# test compatibility with old introducer .tac files
from allmydata.introducer import IntroducerNode
-from allmydata.util import pollmixin, keyutil
+from allmydata.web import introweb
+from allmydata.client import Client as TahoeClient
+from allmydata.util import pollmixin, keyutil, idlib, fileutil
import allmydata.test.common_util as testutil
class LoggingMultiService(service.MultiService):
def test_create(self):
ic = IntroducerClient(None, "introducer.furl", u"my_nickname",
- "my_version", "oldest_version", {})
+ "my_version", "oldest_version", {}, fakeseq)
self.failUnless(isinstance(ic, IntroducerClient))
def test_listen(self):
i = IntroducerService()
ic = IntroducerClient(None,
"introducer.furl", u"my_nickname",
- "my_version", "oldest_version", {})
+ "my_version", "oldest_version", {}, fakeseq)
sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s)
keyid = keyutil.remove_prefix(vk_s, "pub-v0-")
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
- ann_t = ic.create_announcement("storage", make_ann(furl1), sk)
+ ann_t = make_ann_t(ic, furl1, sk, 1)
i.remote_publish_v2(ann_t, Referenceable())
announcements = i.get_announcements()
self.failUnlessEqual(len(announcements), 1)
key1 = ("storage", "v0-"+keyid, None)
- self.failUnless(key1 in announcements)
- (ign, ign, ann1_out, ign) = announcements[key1]
+ self.failUnlessEqual(announcements[0].index, key1)
+ ann1_out = announcements[0].announcement
self.failUnlessEqual(ann1_out["anonymous-storage-FURL"], furl1)
furl2 = "pb://%s@127.0.0.1:36106/swissnum" % keyid
ann2 = (furl2, "storage", "RIStorage", "nick1", "ver23", "ver0")
i.remote_publish(ann2)
+ announcements = i.get_announcements()
self.failUnlessEqual(len(announcements), 2)
key2 = ("storage", None, keyid)
- self.failUnless(key2 in announcements)
- (ign, ign, ann2_out, ign) = announcements[key2]
+ wanted = [ad for ad in announcements if ad.index == key2]
+ self.failUnlessEqual(len(wanted), 1)
+ ann2_out = wanted[0].announcement
self.failUnlessEqual(ann2_out["anonymous-storage-FURL"], furl2)
+def fakeseq():
+ return 1, "nonce"
+
+seqnum_counter = itertools.count(1)
+def realseq():
+ return seqnum_counter.next(), str(os.randint(1,100000))
+
def make_ann(furl):
ann = { "anonymous-storage-FURL": furl,
"permutation-seed-base32": get_tubid_string(furl) }
return ann
-def make_ann_t(ic, furl, privkey):
- return ic.create_announcement("storage", make_ann(furl), privkey)
+def make_ann_t(ic, furl, privkey, seqnum):
+ ann_d = ic.create_announcement_dict("storage", make_ann(furl))
+ ann_d["seqnum"] = seqnum
+ ann_d["nonce"] = "nonce"
+ ann_t = sign_to_foolscap(ann_d, privkey)
+ return ann_t
class Client(unittest.TestCase):
def test_duplicate_receive_v1(self):
ic = IntroducerClient(None,
"introducer.furl", u"my_nickname",
- "my_version", "oldest_version", {})
+ "my_version", "oldest_version", {}, fakeseq)
announcements = []
ic.subscribe_to("storage",
lambda key_s,ann: announcements.append(ann))
def test_duplicate_receive_v2(self):
ic1 = IntroducerClient(None,
"introducer.furl", u"my_nickname",
- "ver23", "oldest_version", {})
+ "ver23", "oldest_version", {}, fakeseq)
# we use a second client just to create a different-looking
# announcement
ic2 = IntroducerClient(None,
"introducer.furl", u"my_nickname",
- "ver24","oldest_version",{})
+ "ver24","oldest_version",{}, fakeseq)
announcements = []
def _received(key_s, ann):
announcements.append( (key_s, ann) )
# ann1b: ic2, furl1
# ann2: ic2, furl2
- self.ann1 = make_ann_t(ic1, furl1, privkey)
- self.ann1a = make_ann_t(ic1, furl1a, privkey)
- self.ann1b = make_ann_t(ic2, furl1, privkey)
- self.ann2 = make_ann_t(ic2, furl2, privkey)
+ self.ann1 = make_ann_t(ic1, furl1, privkey, seqnum=10)
+ self.ann1old = make_ann_t(ic1, furl1, privkey, seqnum=9)
+ self.ann1noseqnum = make_ann_t(ic1, furl1, privkey, seqnum=None)
+ self.ann1b = make_ann_t(ic2, furl1, privkey, seqnum=11)
+ self.ann1a = make_ann_t(ic1, furl1a, privkey, seqnum=12)
+ self.ann2 = make_ann_t(ic2, furl2, privkey, seqnum=13)
ic1.remote_announce_v2([self.ann1]) # queues eventual-send
d = fireEventually()
self.failUnlessEqual(len(announcements), 1)
d.addCallback(_then2)
+ # an older announcement shouldn't fire the subscriber either
+ d.addCallback(lambda ign: ic1.remote_announce_v2([self.ann1old]))
+ d.addCallback(fireEventually)
+ def _then2a(ign):
+ self.failUnlessEqual(len(announcements), 1)
+ d.addCallback(_then2a)
+
+ # announcement with no seqnum cannot replace one with-seqnum
+ d.addCallback(lambda ign: ic1.remote_announce_v2([self.ann1noseqnum]))
+ d.addCallback(fireEventually)
+ def _then2b(ign):
+ self.failUnlessEqual(len(announcements), 1)
+ d.addCallback(_then2b)
+
# and a replacement announcement: same FURL, new other stuff. The
# subscriber *should* be fired.
d.addCallback(lambda ign: ic1.remote_announce_v2([self.ann1b]))
# not replace the other)
ic = IntroducerClient(None,
"introducer.furl", u"my_nickname",
- "my_version", "oldest_version", {})
+ "my_version", "oldest_version", {}, fakeseq)
announcements = []
ic.subscribe_to("storage",
lambda key_s,ann: announcements.append(ann))
keyid = keyutil.remove_prefix(vk_s, "pub-v0-")
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
furl2 = "pb://%s@127.0.0.1:36106/swissnum" % keyid
- ann_t = ic.create_announcement("storage", make_ann(furl1), sk)
+ ann_t = make_ann_t(ic, furl1, sk, 1)
ic.remote_announce_v2([ann_t])
d = fireEventually()
def _then(ign):
d.addCallback(_then2)
return d
+class Server(unittest.TestCase):
+ def test_duplicate(self):
+ i = IntroducerService()
+ ic1 = IntroducerClient(None,
+ "introducer.furl", u"my_nickname",
+ "ver23", "oldest_version", {}, realseq)
+ furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:36106/gydnp"
+
+ privkey_s, _ = keyutil.make_keypair()
+ privkey, _ = keyutil.parse_privkey(privkey_s)
+
+ ann1 = make_ann_t(ic1, furl1, privkey, seqnum=10)
+ ann1_old = make_ann_t(ic1, furl1, privkey, seqnum=9)
+ ann1_new = make_ann_t(ic1, furl1, privkey, seqnum=11)
+ ann1_noseqnum = make_ann_t(ic1, furl1, privkey, seqnum=None)
+ ann1_badseqnum = make_ann_t(ic1, furl1, privkey, seqnum="not an int")
+
+ i.remote_publish_v2(ann1, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 10)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 0)
+
+ i.remote_publish_v2(ann1, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 10)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 2)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 0)
+
+ i.remote_publish_v2(ann1_old, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 10)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 3)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 0)
+
+ i.remote_publish_v2(ann1_new, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 11)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 4)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 0)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 1)
+
+ i.remote_publish_v2(ann1_noseqnum, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 11)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 5)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 1)
+
+ i.remote_publish_v2(ann1_badseqnum, None)
+ all = i.get_announcements()
+ self.failUnlessEqual(len(all), 1)
+ self.failUnlessEqual(all[0].announcement["seqnum"], 11)
+ self.failUnlessEqual(i._debug_counts["inbound_message"], 6)
+ self.failUnlessEqual(i._debug_counts["inbound_duplicate"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_no_seqnum"], 2)
+ self.failUnlessEqual(i._debug_counts["inbound_old_replay"], 1)
+ self.failUnlessEqual(i._debug_counts["inbound_update"], 1)
+
+
+NICKNAME = u"n\u00EDickname-%s" # LATIN SMALL LETTER I WITH ACUTE
class SystemTestMixin(ServiceMixin, pollmixin.PollMixin):
tub2 = Tub()
tub2.setServiceParent(self.parent)
c = IntroducerClient(tub2, ifurl,
- u"nickname", "version", "oldest", {})
+ u"nickname", "version", "oldest", {}, fakeseq)
furl1 = "pb://onug64tu@127.0.0.1:123/short" # base32("short")
sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s)
return self.poll(_got_announcement)
d.addCallback(_offline)
def _done(ign):
- v = list(introducer.get_announcements().values())[0]
- (ign, ign, ann1_out, ign) = v
- self.failUnlessEqual(ann1_out["anonymous-storage-FURL"], furl1)
+ v = introducer.get_announcements()[0]
+ furl = v.announcement["anonymous-storage-FURL"]
+ self.failUnlessEqual(furl, furl1)
d.addCallback(_done)
# now let the ack get back
received_announcements = {}
subscribing_clients = []
publishing_clients = []
+ printable_serverids = {}
+ self.the_introducer = introducer
privkeys = {}
expected_announcements = [0 for c in range(NUM_CLIENTS)]
log.msg("creating client %d: %s" % (i, tub.getShortTubID()))
if i == 0:
c = old.IntroducerClient_v1(tub, self.introducer_furl,
- u"nickname-%d" % i,
+ NICKNAME % str(i),
"version", "oldest")
else:
c = IntroducerClient(tub, self.introducer_furl,
- u"nickname-%d" % i,
+ NICKNAME % str(i),
"version", "oldest",
- {"component": "component-v1"})
+ {"component": "component-v1"}, fakeseq)
received_announcements[c] = {}
def got(key_s_or_tubid, ann, announcements, i):
if i == 0:
if i < NUM_STORAGE:
if i == 0:
c.publish(node_furl, "storage", "ri_name")
+ printable_serverids[i] = get_tubid_string(node_furl)
elif i == 1:
# sign the announcement
privkey_s, pubkey_s = keyutil.make_keypair()
privkey, _ignored = keyutil.parse_privkey(privkey_s)
privkeys[c] = privkey
c.publish("storage", make_ann(node_furl), privkey)
+ if server_version == V1:
+ printable_serverids[i] = get_tubid_string(node_furl)
+ else:
+ assert pubkey_s.startswith("pub-")
+ printable_serverids[i] = pubkey_s[len("pub-"):]
else:
c.publish("storage", make_ann(node_furl))
+ printable_serverids[i] = get_tubid_string(node_furl)
publishing_clients.append(c)
else:
# the last one does not publish anything
for c in subscribing_clients + publishing_clients:
if c._debug_outstanding:
return False
- if introducer._debug_outstanding:
+ if self.the_introducer._debug_outstanding:
return False
return True
return self.poll(_idle)
def _check1(res):
log.msg("doing _check1")
- dc = introducer._debug_counts
+ dc = self.the_introducer._debug_counts
if server_version == V1:
# each storage server publishes a record, and (after its
# 'subscribe' has been ACKed) also publishes a "stub_client".
ann = anns[nodeid0]
nick = ann["nickname"]
self.failUnlessEqual(type(nick), unicode)
- self.failUnlessEqual(nick, u"nickname-0")
+ self.failUnlessEqual(nick, NICKNAME % "0")
if server_version == V1:
for c in publishing_clients:
cdc = c._debug_counts
]:
expected = 2
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"
+ text = ir.renderSynchronously().decode("utf-8")
+ self.failUnlessIn(NICKNAME % "0", text) # the v1 client
+ self.failUnlessIn(NICKNAME % "1", text) # a v2 client
+ for i in range(NUM_STORAGE):
+ self.failUnlessIn(printable_serverids[i], text,
+ (i,printable_serverids[i],text))
+ # make sure there isn't a double-base32ed string too
+ self.failIfIn(idlib.nodeid_b2a(printable_serverids[i]), text,
+ (i,printable_serverids[i],text))
log.msg("_check1 done")
d.addCallback(_check1)
c = subscribing_clients[i]
for k in c._debug_counts:
c._debug_counts[k] = 0
- for k in introducer._debug_counts:
- introducer._debug_counts[k] = 0
+ for k in self.the_introducer._debug_counts:
+ self.the_introducer._debug_counts[k] = 0
expected_announcements[i] += 1 # new 'storage' for everyone
self.create_tub(self.central_portnum)
- newfurl = self.central_tub.registerReference(introducer,
+ newfurl = self.central_tub.registerReference(self.the_introducer,
furlFile=iff)
assert newfurl == self.introducer_furl
d.addCallback(_restart_introducer_tub)
log.msg("doing _check2")
# assert that the introducer sent out new messages, one per
# subscriber
- dc = introducer._debug_counts
+ dc = self.the_introducer._debug_counts
self.failUnlessEqual(dc["outbound_announcements"],
NUM_STORAGE*NUM_CLIENTS)
self.failUnless(dc["outbound_message"] > 0)
introducer = old.IntroducerService_v1()
else:
introducer = IntroducerService()
- newfurl = self.central_tub.registerReference(introducer,
+ self.the_introducer = introducer
+ newfurl = self.central_tub.registerReference(self.the_introducer,
furlFile=iff)
assert newfurl == self.introducer_furl
d.addCallback(_restart_introducer)
def _check3(res):
log.msg("doing _check3")
- dc = introducer._debug_counts
+ dc = self.the_introducer._debug_counts
self.failUnlessEqual(dc["outbound_announcements"],
NUM_STORAGE*NUM_CLIENTS)
self.failUnless(dc["outbound_message"] > 0)
class FakeRemoteReference:
def notifyOnDisconnect(self, *args, **kwargs): pass
def getRemoteTubID(self): return "62ubehyunnyhzs7r6vdonnm2hpi52w6y"
+ def getLocationHints(self): return [("ipv4", "here.example.com", "1234"),
+ ("ipv4", "there.example.com", "2345")]
+ def getPeer(self): return address.IPv4Address("TCP", "remote.example.com",
+ 3456)
class ClientInfo(unittest.TestCase):
def test_client_v2(self):
introducer = IntroducerService()
tub = introducer_furl = None
app_versions = {"whizzy": "fizzy"}
- client_v2 = IntroducerClient(tub, introducer_furl, u"nick-v2",
- "my_version", "oldest", app_versions)
+ client_v2 = IntroducerClient(tub, introducer_furl, NICKNAME % u"v2",
+ "my_version", "oldest", app_versions,
+ fakeseq)
#furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
- #ann_s = make_ann_t(client_v2, furl1, None)
+ #ann_s = make_ann_t(client_v2, furl1, None, 10)
#introducer.remote_publish_v2(ann_s, Referenceable())
subscriber = FakeRemoteReference()
introducer.remote_subscribe_v2(subscriber, "storage",
client_v2._my_subscriber_info)
- s = introducer.get_subscribers()
- self.failUnlessEqual(len(s), 1)
- sn, when, si, rref = s[0]
- self.failUnlessIdentical(rref, subscriber)
- self.failUnlessEqual(sn, "storage")
- self.failUnlessEqual(si["version"], 0)
- self.failUnlessEqual(si["oldest-supported"], "oldest")
- self.failUnlessEqual(si["app-versions"], app_versions)
- self.failUnlessEqual(si["nickname"], u"nick-v2")
- self.failUnlessEqual(si["my-version"], "my_version")
+ subs = introducer.get_subscribers()
+ self.failUnlessEqual(len(subs), 1)
+ s0 = subs[0]
+ self.failUnlessEqual(s0.service_name, "storage")
+ self.failUnlessEqual(s0.app_versions, app_versions)
+ self.failUnlessEqual(s0.nickname, NICKNAME % u"v2")
+ self.failUnlessEqual(s0.version, "my_version")
def test_client_v1(self):
introducer = IntroducerService()
introducer.remote_subscribe(subscriber, "storage")
# the v1 subscribe interface had no subscriber_info: that was usually
# sent in a separate stub_client pseudo-announcement
- s = introducer.get_subscribers()
- self.failUnlessEqual(len(s), 1)
- sn, when, si, rref = s[0]
- # rref will be a WrapV1SubscriberInV2Interface around the real
- # subscriber
- self.failUnlessIdentical(rref.original, subscriber)
- self.failUnlessEqual(si, None) # not known yet
- self.failUnlessEqual(sn, "storage")
+ subs = introducer.get_subscribers()
+ self.failUnlessEqual(len(subs), 1)
+ s0 = subs[0]
+ self.failUnlessEqual(s0.nickname, u"?") # not known yet
+ self.failUnlessEqual(s0.service_name, "storage")
# now submit the stub_client announcement
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
ann = (furl1, "stub_client", "RIStubClient",
- u"nick-v1".encode("utf-8"), "my_version", "oldest")
+ (NICKNAME % u"v1").encode("utf-8"), "my_version", "oldest")
introducer.remote_publish(ann)
# the server should correlate the two
- s = introducer.get_subscribers()
- self.failUnlessEqual(len(s), 1)
- sn, when, si, rref = s[0]
- self.failUnlessIdentical(rref.original, subscriber)
- self.failUnlessEqual(sn, "storage")
-
- self.failUnlessEqual(si["version"], 0)
- self.failUnlessEqual(si["oldest-supported"], "oldest")
+ subs = introducer.get_subscribers()
+ self.failUnlessEqual(len(subs), 1)
+ s0 = subs[0]
+ self.failUnlessEqual(s0.service_name, "storage")
# v1 announcements do not contain app-versions
- self.failUnlessEqual(si["app-versions"], {})
- self.failUnlessEqual(si["nickname"], u"nick-v1")
- self.failUnlessEqual(si["my-version"], "my_version")
+ self.failUnlessEqual(s0.app_versions, {})
+ self.failUnlessEqual(s0.nickname, NICKNAME % u"v1")
+ self.failUnlessEqual(s0.version, "my_version")
# a subscription that arrives after the stub_client announcement
# should be correlated too
subscriber2 = FakeRemoteReference()
introducer.remote_subscribe(subscriber2, "thing2")
- s = introducer.get_subscribers()
- subs = dict([(sn, (si,rref)) for sn, when, si, rref in s])
+ subs = introducer.get_subscribers()
self.failUnlessEqual(len(subs), 2)
- (si,rref) = subs["thing2"]
- self.failUnlessIdentical(rref.original, subscriber2)
- self.failUnlessEqual(si["version"], 0)
- self.failUnlessEqual(si["oldest-supported"], "oldest")
+ s0 = [s for s in subs if s.service_name == "thing2"][0]
# v1 announcements do not contain app-versions
- self.failUnlessEqual(si["app-versions"], {})
- self.failUnlessEqual(si["nickname"], u"nick-v1")
- self.failUnlessEqual(si["my-version"], "my_version")
+ self.failUnlessEqual(s0.app_versions, {})
+ self.failUnlessEqual(s0.nickname, NICKNAME % u"v1")
+ self.failUnlessEqual(s0.version, "my_version")
class Announcements(unittest.TestCase):
def test_client_v2_unsigned(self):
tub = introducer_furl = None
app_versions = {"whizzy": "fizzy"}
client_v2 = IntroducerClient(tub, introducer_furl, u"nick-v2",
- "my_version", "oldest", app_versions)
+ "my_version", "oldest", app_versions,
+ fakeseq)
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
tubid = "62ubehyunnyhzs7r6vdonnm2hpi52w6y"
- ann_s0 = make_ann_t(client_v2, furl1, None)
+ ann_s0 = make_ann_t(client_v2, furl1, None, 10)
canary0 = Referenceable()
introducer.remote_publish_v2(ann_s0, canary0)
a = introducer.get_announcements()
self.failUnlessEqual(len(a), 1)
- (index, (ann_s, canary, ann, when)) = a.items()[0]
- self.failUnlessIdentical(canary, canary0)
- self.failUnlessEqual(index, ("storage", None, tubid))
- self.failUnlessEqual(ann["app-versions"], app_versions)
- self.failUnlessEqual(ann["nickname"], u"nick-v2")
- self.failUnlessEqual(ann["service-name"], "storage")
- self.failUnlessEqual(ann["my-version"], "my_version")
- self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
+ self.failUnlessIdentical(a[0].canary, canary0)
+ self.failUnlessEqual(a[0].index, ("storage", None, tubid))
+ self.failUnlessEqual(a[0].announcement["app-versions"], app_versions)
+ 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)
def test_client_v2_signed(self):
introducer = IntroducerService()
tub = introducer_furl = None
app_versions = {"whizzy": "fizzy"}
client_v2 = IntroducerClient(tub, introducer_furl, u"nick-v2",
- "my_version", "oldest", app_versions)
+ "my_version", "oldest", app_versions,
+ fakeseq)
furl1 = "pb://62ubehyunnyhzs7r6vdonnm2hpi52w6y@127.0.0.1:0/swissnum"
sk_s, vk_s = keyutil.make_keypair()
sk, _ignored = keyutil.parse_privkey(sk_s)
pks = keyutil.remove_prefix(vk_s, "pub-")
- ann_t0 = make_ann_t(client_v2, furl1, sk)
+ ann_t0 = make_ann_t(client_v2, furl1, sk, 10)
canary0 = Referenceable()
introducer.remote_publish_v2(ann_t0, canary0)
a = introducer.get_announcements()
self.failUnlessEqual(len(a), 1)
- (index, (ann_s, canary, ann, when)) = a.items()[0]
- self.failUnlessIdentical(canary, canary0)
- self.failUnlessEqual(index, ("storage", pks, None))
- self.failUnlessEqual(ann["app-versions"], app_versions)
- self.failUnlessEqual(ann["nickname"], u"nick-v2")
- self.failUnlessEqual(ann["service-name"], "storage")
- self.failUnlessEqual(ann["my-version"], "my_version")
- self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
+ self.failUnlessIdentical(a[0].canary, canary0)
+ self.failUnlessEqual(a[0].index, ("storage", pks, None))
+ self.failUnlessEqual(a[0].announcement["app-versions"], app_versions)
+ 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)
def test_client_v1(self):
introducer = IntroducerService()
a = introducer.get_announcements()
self.failUnlessEqual(len(a), 1)
- (index, (ann_s, canary, ann, when)) = a.items()[0]
- self.failUnlessEqual(canary, None)
- self.failUnlessEqual(index, ("storage", None, tubid))
- self.failUnlessEqual(ann["app-versions"], {})
- self.failUnlessEqual(ann["nickname"], u"nick-v1".encode("utf-8"))
- self.failUnlessEqual(ann["service-name"], "storage")
- self.failUnlessEqual(ann["my-version"], "my_version")
- self.failUnlessEqual(ann["anonymous-storage-FURL"], furl1)
+ self.failUnlessEqual(a[0].index, ("storage", None, tubid))
+ self.failUnlessEqual(a[0].canary, None)
+ self.failUnlessEqual(a[0].announcement["app-versions"], {})
+ self.failUnlessEqual(a[0].nickname, u"nick-v1".encode("utf-8"))
+ self.failUnlessEqual(a[0].service_name, "storage")
+ self.failUnlessEqual(a[0].version, "my_version")
+ self.failUnlessEqual(a[0].announcement["anonymous-storage-FURL"], furl1)
+
+class ClientSeqnums(unittest.TestCase):
+ def test_client(self):
+ basedir = "introducer/ClientSeqnums/test_client"
+ fileutil.make_dirs(basedir)
+ f = open(os.path.join(basedir, "tahoe.cfg"), "w")
+ f.write("[client]\n")
+ f.write("introducer.furl = nope\n")
+ f.close()
+ c = TahoeClient(basedir)
+ ic = c.introducer_client
+ outbound = ic._outbound_announcements
+ published = ic._published_announcements
+ def read_seqnum():
+ f = open(os.path.join(basedir, "announcement-seqnum"))
+ seqnum = f.read().strip()
+ f.close()
+ return int(seqnum)
+
+ ic.publish("sA", {"key": "value1"}, c._server_key)
+ self.failUnlessEqual(read_seqnum(), 1)
+ self.failUnless("sA" in outbound)
+ self.failUnlessEqual(outbound["sA"]["seqnum"], 1)
+ nonce1 = outbound["sA"]["nonce"]
+ self.failUnless(isinstance(nonce1, str))
+ self.failUnlessEqual(simplejson.loads(published["sA"][0]),
+ outbound["sA"])
+ # [1] is the signature, [2] is the pubkey
+
+ # publishing a second service causes both services to be
+ # re-published, with the next higher sequence number
+ ic.publish("sB", {"key": "value2"}, c._server_key)
+ self.failUnlessEqual(read_seqnum(), 2)
+ self.failUnless("sB" in outbound)
+ self.failUnlessEqual(outbound["sB"]["seqnum"], 2)
+ self.failUnless("sA" in outbound)
+ self.failUnlessEqual(outbound["sA"]["seqnum"], 2)
+ nonce2 = outbound["sA"]["nonce"]
+ self.failUnless(isinstance(nonce2, str))
+ self.failIfEqual(nonce1, nonce2)
+ self.failUnlessEqual(simplejson.loads(published["sA"][0]),
+ outbound["sA"])
+ self.failUnlessEqual(simplejson.loads(published["sB"][0]),
+ outbound["sB"])
+
class TooNewServer(IntroducerService):
tub.setLocation("localhost:%d" % portnum)
c = IntroducerClient(tub, self.introducer_furl,
- u"nickname-client", "version", "oldest", {})
+ u"nickname-client", "version", "oldest", {},
+ fakeseq)
announcements = {}
def got(key_s, ann):
announcements[key_s] = ann