from twisted.trial import unittest
from twisted.internet import defer
from twisted.internet import threads # CLI tests use deferToThread
-from twisted.internet import utils
import allmydata
from allmydata import uri
from allmydata.monitor import Monitor
from allmydata.mutable.common import NotWriteableError
from allmydata.mutable import layout as mutable_layout
-from foolscap.api import DeadReferenceError
+from allmydata.mutable.publish import MutableData
+from foolscap.api import DeadReferenceError, fireEventually
from twisted.python.failure import Failure
from twisted.web.client import getPage
from twisted.web.error import Error
from allmydata.test.common import SystemTestMixin
-# TODO: move these to common or common_util
-from allmydata.test.test_runner import bintahoe, SkipMixin
+# TODO: move this to common or common_util
+from allmydata.test.test_runner import RunBinTahoeMixin
LARGE_DATA = """
This is some data to publish to the remote grid.., which needs to be large
self.interrupt_after_d.callback(self)
return upload.Data.read(self, length)
-class SystemTest(SystemTestMixin, SkipMixin, unittest.TestCase):
+class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase):
timeout = 3600 # It takes longer than 960 seconds on Zandr's ARM box.
def test_connections(self):
all_peerids = c.get_storage_broker().get_all_serverids()
self.failUnlessEqual(len(all_peerids), self.numclients+1)
sb = c.storage_broker
- permuted_peers = sb.get_servers_for_index("a")
+ permuted_peers = sb.get_servers_for_psi("a")
self.failUnlessEqual(len(permuted_peers), self.numclients+1)
d.addCallback(_check)
all_peerids = c.get_storage_broker().get_all_serverids()
self.failUnlessEqual(len(all_peerids), self.numclients)
sb = c.storage_broker
- permuted_peers = sb.get_servers_for_index("a")
+ permuted_peers = sb.get_servers_for_psi("a")
self.failUnlessEqual(len(permuted_peers), self.numclients)
d.addCallback(_check_connections)
return d1
d.addCallback(_do_upload)
def _upload_done(results):
- theuri = results.uri
+ theuri = results.get_uri()
log.msg("upload finished: uri is %s" % (theuri,))
self.uri = theuri
assert isinstance(self.uri, str), self.uri
facility="tahoe.tests")
d1 = download_to_data(badnode)
def _baduri_should_fail(res):
- log.msg("finished downloading non-existend URI",
+ log.msg("finished downloading non-existent URI",
level=log.UNUSUAL, facility="tahoe.tests")
self.failUnless(isinstance(res, Failure))
self.failUnless(res.check(NoSharesError),
self.extra_node.DEFAULT_ENCODING_PARAMETERS['happy'] = 5
d.addCallback(_added)
+ def _has_helper():
+ uploader = self.extra_node.getServiceNamed("uploader")
+ furl, connected = uploader.get_helper_info()
+ return connected
+ d.addCallback(lambda ign: self.poll(_has_helper))
+
HELPER_DATA = "Data that needs help to upload" * 1000
def _upload_with_helper(res):
u = upload.Data(HELPER_DATA, convergence=convergence)
d = self.extra_node.upload(u)
def _uploaded(results):
- n = self.clients[1].create_node_from_uri(results.uri)
+ n = self.clients[1].create_node_from_uri(results.get_uri())
return download_to_data(n)
d.addCallback(_uploaded)
def _check(newdata):
u.debug_stash_RemoteEncryptedUploadable = True
d = self.extra_node.upload(u)
def _uploaded(results):
- n = self.clients[1].create_node_from_uri(results.uri)
+ n = self.clients[1].create_node_from_uri(results.get_uri())
return download_to_data(n)
d.addCallback(_uploaded)
def _check(newdata):
if convergence is not None:
d.addCallback(_upload_duplicate_with_helper)
+ d.addCallback(fireEventually)
+
def _upload_resumable(res):
DATA = "Data that needs help to upload and gets interrupted" * 1000
u1 = CountingDataUploadable(DATA, convergence=convergence)
u2 = CountingDataUploadable(DATA, convergence=convergence)
# we interrupt the connection after about 5kB by shutting down
- # the helper, then restartingit.
+ # the helper, then restarting it.
u1.interrupt_after = 5000
u1.interrupt_after_d = defer.Deferred()
- u1.interrupt_after_d.addCallback(lambda res:
- self.bounce_client(0))
+ bounced_d = defer.Deferred()
+ def _do_bounce(res):
+ d = self.bounce_client(0)
+ d.addBoth(bounced_d.callback)
+ u1.interrupt_after_d.addCallback(_do_bounce)
# sneak into the helper and reduce its chunk size, so that our
# debug_interrupt will sever the connection on about the fifth
# this same test run, but I'm not currently worried about it.
offloaded.CHKCiphertextFetcher.CHUNK_SIZE = 1000
- d = self.extra_node.upload(u1)
-
- def _should_not_finish(res):
- self.fail("interrupted upload should have failed, not finished"
- " with result %s" % (res,))
- def _interrupted(f):
- f.trap(DeadReferenceError)
-
- # make sure we actually interrupted it before finishing the
- # file
- self.failUnless(u1.bytes_read < len(DATA),
- "read %d out of %d total" % (u1.bytes_read,
- len(DATA)))
-
- log.msg("waiting for reconnect", level=log.NOISY,
- facility="tahoe.test.test_system")
- # now, we need to give the nodes a chance to notice that this
- # connection has gone away. When this happens, the storage
- # servers will be told to abort their uploads, removing the
- # partial shares. Unfortunately this involves TCP messages
- # going through the loopback interface, and we can't easily
- # predict how long that will take. If it were all local, we
- # could use fireEventually() to stall. Since we don't have
- # the right introduction hooks, the best we can do is use a
- # fixed delay. TODO: this is fragile.
- u1.interrupt_after_d.addCallback(self.stall, 2.0)
- return u1.interrupt_after_d
- d.addCallbacks(_should_not_finish, _interrupted)
+ upload_d = self.extra_node.upload(u1)
+ # The upload will start, and bounce_client() will be called after
+ # about 5kB. bounced_d will fire after bounce_client() finishes
+ # shutting down and restarting the node.
+ d = bounced_d
+ def _bounced(ign):
+ # By this point, the upload should have failed because of the
+ # interruption. upload_d will fire in a moment
+ def _should_not_finish(res):
+ self.fail("interrupted upload should have failed, not"
+ " finished with result %s" % (res,))
+ def _interrupted(f):
+ f.trap(DeadReferenceError)
+ # make sure we actually interrupted it before finishing
+ # the file
+ self.failUnless(u1.bytes_read < len(DATA),
+ "read %d out of %d total" %
+ (u1.bytes_read, len(DATA)))
+ upload_d.addCallbacks(_should_not_finish, _interrupted)
+ return upload_d
+ d.addCallback(_bounced)
def _disconnected(res):
# check to make sure the storage servers aren't still hanging
self.failIf(os.path.exists(incdir) and os.listdir(incdir))
d.addCallback(_disconnected)
- # then we need to give the reconnector a chance to
- # reestablish the connection to the helper.
d.addCallback(lambda res:
- log.msg("wait_for_connections", level=log.NOISY,
+ log.msg("wait_for_helper", level=log.NOISY,
facility="tahoe.test.test_system"))
- d.addCallback(lambda res: self.wait_for_connections())
-
+ # then we need to wait for the extra node to reestablish its
+ # connection to the helper.
+ d.addCallback(lambda ign: self.poll(_has_helper))
d.addCallback(lambda res:
log.msg("uploading again", level=log.NOISY,
d.addCallback(lambda res: self.extra_node.upload(u2))
def _uploaded(results):
- cap = results.uri
+ cap = results.get_uri()
log.msg("Second upload complete", level=log.NOISY,
facility="tahoe.test.test_system")
# this is really bytes received rather than sent, but it's
# convenient and basically measures the same thing
- bytes_sent = results.ciphertext_fetched
+ bytes_sent = results.get_ciphertext_fetched()
self.failUnless(isinstance(bytes_sent, (int, long)), bytes_sent)
# We currently don't support resumption of upload if the data is
def test_mutable(self):
self.basedir = "system/SystemTest/test_mutable"
DATA = "initial contents go here." # 25 bytes % 3 != 0
+ DATA_uploadable = MutableData(DATA)
NEWDATA = "new contents yay"
+ NEWDATA_uploadable = MutableData(NEWDATA)
NEWERDATA = "this is getting old"
+ NEWERDATA_uploadable = MutableData(NEWERDATA)
d = self.set_up_nodes(use_key_generator=True)
def _create_mutable(res):
c = self.clients[0]
log.msg("starting create_mutable_file")
- d1 = c.create_mutable_file(DATA)
+ d1 = c.create_mutable_file(DATA_uploadable)
def _done(res):
log.msg("DONE: %s" % (res,))
self._mutable_node_1 = res
self.failUnlessEqual(res, DATA)
# replace the data
log.msg("starting replace1")
- d1 = newnode.overwrite(NEWDATA)
+ d1 = newnode.overwrite(NEWDATA_uploadable)
d1.addCallback(lambda res: newnode.download_best_version())
return d1
d.addCallback(_check_download_3)
newnode2 = self.clients[3].create_node_from_uri(uri)
self._newnode3 = self.clients[3].create_node_from_uri(uri)
log.msg("starting replace2")
- d1 = newnode1.overwrite(NEWERDATA)
+ d1 = newnode1.overwrite(NEWERDATA_uploadable)
d1.addCallback(lambda res: newnode2.download_best_version())
return d1
d.addCallback(_check_download_4)
def _check_empty_file(res):
# make sure we can create empty files, this usually screws up the
# segsize math
- d1 = self.clients[2].create_mutable_file("")
+ d1 = self.clients[2].create_mutable_file(MutableData(""))
d1.addCallback(lambda newnode: newnode.download_best_version())
d1.addCallback(lambda res: self.failUnlessEqual("", res))
return d1
self.key_generator_svc.key_generator.pool_size + size_delta)
d.addCallback(check_kg_poolsize, 0)
- d.addCallback(lambda junk: self.clients[3].create_mutable_file('hello, world'))
+ d.addCallback(lambda junk:
+ self.clients[3].create_mutable_file(MutableData('hello, world')))
d.addCallback(check_kg_poolsize, -1)
d.addCallback(lambda junk: self.clients[3].create_dirnode())
d.addCallback(check_kg_poolsize, -2)
newappverstr = "%s: %s" % (allmydata.__appname__, altverstr)
self.failUnless((appverstr in res) or (newappverstr in res), (appverstr, newappverstr, res))
- self.failUnless("Announcement Summary: storage: 5, stub_client: 5" in res)
+ self.failUnless("Announcement Summary: storage: 5" in res)
self.failUnless("Subscription Summary: storage: 5" in res)
+ self.failUnless("tahoe.css" in res)
except unittest.FailTest:
print
print "GET %s output was:" % self.introweb_url
print res
raise
d.addCallback(_check)
+ # make sure it serves the CSS too
+ d.addCallback(lambda res:
+ getPage(self.introweb_url+"tahoe.css", method="GET"))
d.addCallback(lambda res:
getPage(self.introweb_url + "?t=json",
method="GET", followRedirect=True))
self.failUnlessEqual(data["subscription_summary"],
{"storage": 5})
self.failUnlessEqual(data["announcement_summary"],
- {"storage": 5, "stub_client": 5})
+ {"storage": 5})
self.failUnlessEqual(data["announcement_distinct_hosts"],
- {"storage": 1, "stub_client": 1})
+ {"storage": 1})
except unittest.FailTest:
print
print "GET %s?t=json output was:" % self.introweb_url
d.addCallback(lambda res: getPage(base + public + "/subdir1"))
def _got_subdir1(page):
# there ought to be an href for our file
- self.failUnless(("<td>%d</td>" % len(self.data)) in page)
+ self.failUnlessIn('<td align="right">%d</td>' % len(self.data), page)
self.failUnless(">mydata567</a>" in page)
d.addCallback(_got_subdir1)
d.addCallback(self.log, "done with _got_subdir1")
return self.GET("status/publish-%d" % self._publish_status)
d.addCallback(_got_update)
def _got_publish(res):
+ self.failUnlessIn("Publish Results", res)
return self.GET("status/retrieve-%d" % self._retrieve_status)
d.addCallback(_got_publish)
+ def _got_retrieve(res):
+ self.failUnlessIn("Retrieve Results", res)
+ d.addCallback(_got_retrieve)
# check that the helper status page exists
d.addCallback(lambda res:
self.failUnlessEqual(data, expected_data)
d.addCallback(_check)
d.addCallback(lambda res: rref.callRemote("speed_test", 1, 200, False))
- if sys.platform == "linux2":
+ if sys.platform in ("linux2", "linux3"):
d.addCallback(lambda res: rref.callRemote("get_memory_usage"))
d.addCallback(lambda res: rref.callRemote("measure_peer_response_time"))
return d
d.addCallback(run, "put", files[1], "subdir/tahoe-file1")
# tahoe put bar tahoe:FOO
d.addCallback(run, "put", files[2], "tahoe:file2")
- d.addCallback(run, "put", "--mutable", files[3], "tahoe:file3")
+ d.addCallback(run, "put", "--format=SDMF", files[3], "tahoe:file3")
def _check_put_mutable((out,err)):
self._mutable_file3_uri = out.strip()
d.addCallback(_check_put_mutable)
d.addCallback(_check_ls_rouri)
- d.addCallback(run, "mv", "tahoe-file-stdin", "tahoe-moved-first-time")
+ d.addCallback(run, "mv", "tahoe-file-stdin", "tahoe-moved")
d.addCallback(run, "ls")
- d.addCallback(_check_ls, ["tahoe-moved-first-time"], ["tahoe-file-stdin"])
-
- def _mv_with_http_proxy(ign):
- env = os.environ
- env['http_proxy'] = env['HTTP_PROXY'] = "http://127.0.0.0:12345" # invalid address
- return self._run_cli_in_subprocess(["mv"] + nodeargs + ["tahoe-moved-first-time", "tahoe-moved"], env=env)
- d.addCallback(_mv_with_http_proxy)
-
- def _check_mv_with_http_proxy(res):
- out, err, rc_or_sig = res
- self.failUnlessEqual(rc_or_sig, 0, str(res))
- d.addCallback(_check_mv_with_http_proxy)
-
- d.addCallback(run, "ls")
- d.addCallback(_check_ls, ["tahoe-moved"], ["tahoe-moved-firsttime"])
+ d.addCallback(_check_ls, ["tahoe-moved"], ["tahoe-file-stdin"])
d.addCallback(run, "ln", "tahoe-moved", "newlink")
d.addCallback(run, "ls")
return d
+ def test_filesystem_with_cli_in_subprocess(self):
+ # We do this in a separate test so that test_filesystem doesn't skip if we can't run bin/tahoe.
+
+ self.basedir = "system/SystemTest/test_filesystem_with_cli_in_subprocess"
+ d = self.set_up_nodes()
+ def _new_happy_semantics(ign):
+ for c in self.clients:
+ c.DEFAULT_ENCODING_PARAMETERS['happy'] = 1
+ d.addCallback(_new_happy_semantics)
+
+ def _run_in_subprocess(ignored, verb, *args, **kwargs):
+ stdin = kwargs.get("stdin")
+ env = kwargs.get("env")
+ newargs = [verb, "--node-directory", self.getdir("client0")] + list(args)
+ return self.run_bintahoe(newargs, stdin=stdin, env=env)
+
+ def _check_succeeded(res, check_stderr=True):
+ out, err, rc_or_sig = res
+ self.failUnlessEqual(rc_or_sig, 0, str(res))
+ if check_stderr:
+ self.failUnlessEqual(err, "")
+
+ d.addCallback(_run_in_subprocess, "create-alias", "newalias")
+ d.addCallback(_check_succeeded)
+
+ STDIN_DATA = "This is the file to upload from stdin."
+ d.addCallback(_run_in_subprocess, "put", "-", "newalias:tahoe-file", stdin=STDIN_DATA)
+ d.addCallback(_check_succeeded, check_stderr=False)
+
+ def _mv_with_http_proxy(ign):
+ env = os.environ
+ env['http_proxy'] = env['HTTP_PROXY'] = "http://127.0.0.0:12345" # invalid address
+ return _run_in_subprocess(None, "mv", "newalias:tahoe-file", "newalias:tahoe-moved", env=env)
+ d.addCallback(_mv_with_http_proxy)
+ d.addCallback(_check_succeeded)
+
+ d.addCallback(_run_in_subprocess, "ls", "newalias:")
+ def _check_ls(res):
+ out, err, rc_or_sig = res
+ self.failUnlessEqual(rc_or_sig, 0, str(res))
+ self.failUnlessEqual(err, "", str(res))
+ self.failUnlessIn("tahoe-moved", out)
+ self.failIfIn("tahoe-file", out)
+ d.addCallback(_check_ls)
+ return d
+
def test_debug_trial(self):
def _check_for_line(lines, result, test):
for l in lines:
self.failUnlessIn(outcome, out, "output (prefixed with '##') does not contain %r:\n## %s"
% (outcome, "\n## ".join(lines)))
- d = self._run_cli_in_subprocess(['debug', 'trial', '--reporter=verbose',
- 'allmydata.test.trialtest'])
+ d = self.run_bintahoe(['debug', 'trial', '--reporter=verbose',
+ 'allmydata.test.trialtest'])
def _check_failure( (out, err, rc) ):
self.failUnlessEqual(rc, 1)
lines = out.split('\n')
d.addCallback(_check_failure)
# the --quiet argument regression-tests a problem in finding which arguments to pass to trial
- d.addCallback(lambda ign: self._run_cli_in_subprocess(['--quiet', 'debug', 'trial', '--reporter=verbose',
- 'allmydata.test.trialtest.Success']))
+ d.addCallback(lambda ign: self.run_bintahoe(['--quiet', 'debug', 'trial', '--reporter=verbose',
+ 'allmydata.test.trialtest.Success']))
def _check_success( (out, err, rc) ):
self.failUnlessEqual(rc, 0)
lines = out.split('\n')
d.addCallback(_done)
return d
- def _run_cli_in_subprocess(self, argv, env=None):
- self.skip_if_cannot_run_bintahoe()
-
- if env is None:
- env = os.environ
- d = utils.getProcessOutputAndValue(sys.executable, args=[bintahoe] + argv,
- env=env)
- return d
-
def _test_checker(self, res):
ut = upload.Data("too big to be literal" * 200, convergence=None)
d = self._personal_node.add_file(u"big file", ut)
return d
d.addCallback(_got_lit_filenode)
return d
+
+class Connections(SystemTestMixin, unittest.TestCase):
+ def test_rref(self):
+ self.basedir = "system/Connections/rref"
+ d = self.set_up_nodes(2)
+ def _start(ign):
+ self.c0 = self.clients[0]
+ for s in self.c0.storage_broker.get_connected_servers():
+ if "pub-"+s.get_longname() != self.c0.node_key_s:
+ break
+ self.s1 = s # s1 is the server, not c0
+ self.s1_rref = s.get_rref()
+ self.failIfEqual(self.s1_rref, None)
+ self.failUnless(self.s1.is_connected())
+ d.addCallback(_start)
+
+ # now shut down the server
+ d.addCallback(lambda ign: self.clients[1].disownServiceParent())
+ # and wait for the client to notice
+ def _poll():
+ return len(self.c0.storage_broker.get_connected_servers()) < 2
+ d.addCallback(lambda ign: self.poll(_poll))
+
+ def _down(ign):
+ self.failIf(self.s1.is_connected())
+ rref = self.s1.get_rref()
+ self.failUnless(rref)
+ self.failUnlessIdentical(rref, self.s1_rref)
+ d.addCallback(_down)
+ return d