runner.py: improve test coverage further: implement --quiet with StringIOs

This commit is contained in:
Brian Warner 2007-06-26 16:19:18 -07:00
parent de24d3cd94
commit 912fc5a77e
2 changed files with 103 additions and 81 deletions

View File

@ -1,6 +1,7 @@
#! /usr/bin/env python #! /usr/bin/env python
import os, subprocess, sys, signal, time import os, subprocess, sys, signal, time
from cStringIO import StringIO
from twisted.python import usage from twisted.python import usage
from twisted.python.procutils import which from twisted.python.procutils import which
@ -104,17 +105,11 @@ class CreateClientOptions(NoDefaultBasedirMixin, usage.Options):
optParameters = [ optParameters = [
["basedir", "C", None, "which directory to create the client in"], ["basedir", "C", None, "which directory to create the client in"],
] ]
optFlags = [
["quiet", "q", "operate silently"],
]
class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options): class CreateIntroducerOptions(NoDefaultBasedirMixin, usage.Options):
optParameters = [ optParameters = [
["basedir", "C", None, "which directory to create the introducer in"], ["basedir", "C", None, "which directory to create the introducer in"],
] ]
optFlags = [
["quiet", "q", "operate silently"],
]
class DumpOptions(usage.Options): class DumpOptions(usage.Options):
optParameters = [ optParameters = [
@ -180,6 +175,10 @@ c.setServiceParent(application)
class Options(usage.Options): class Options(usage.Options):
synopsis = "Usage: allmydata <command> [command options]" synopsis = "Usage: allmydata <command> [command options]"
optFlags = [
["quiet", "q", "operate silently"],
]
subCommands = [ subCommands = [
["create-client", None, CreateClientOptions, "Create a client node."], ["create-client", None, CreateClientOptions, "Create a client node."],
["create-introducer", None, CreateIntroducerOptions, "Create a introducer node."], ["create-introducer", None, CreateIntroducerOptions, "Create a introducer node."],
@ -198,7 +197,7 @@ class Options(usage.Options):
if not hasattr(self, 'subOptions'): if not hasattr(self, 'subOptions'):
raise usage.UsageError("must specify a command") raise usage.UsageError("must specify a command")
def runner(argv, run_by_human=True): def runner(argv, run_by_human=True, stdout=sys.stdout, stderr=sys.stderr):
config = Options() config = Options()
try: try:
config.parseOptions(argv) config.parseOptions(argv)
@ -214,45 +213,48 @@ def runner(argv, run_by_human=True):
command = config.subCommand command = config.subCommand
so = config.subOptions so = config.subOptions
if config['quiet']:
stdout = StringIO()
rc = 0 rc = 0
if command == "create-client": if command == "create-client":
for basedir in so.basedirs: for basedir in so.basedirs:
rc = create_client(basedir, so) or rc rc = create_client(basedir, so, stdout, stderr) or rc
elif command == "create-introducer": elif command == "create-introducer":
for basedir in so.basedirs: for basedir in so.basedirs:
rc = create_introducer(basedir, so) or rc rc = create_introducer(basedir, so, stdout, stderr) or rc
elif command == "start": elif command == "start":
for basedir in so.basedirs: for basedir in so.basedirs:
rc = start(basedir, so) or rc rc = start(basedir, so, stdout, stderr) or rc
elif command == "stop": elif command == "stop":
for basedir in so.basedirs: for basedir in so.basedirs:
rc = stop(basedir, so) or rc rc = stop(basedir, so, stdout, stderr) or rc
elif command == "restart": elif command == "restart":
for basedir in so.basedirs: for basedir in so.basedirs:
rc = stop(basedir, so) or rc rc = stop(basedir, so, stdout, stderr) or rc
if rc: if rc:
print "not restarting" print >>stderr, "not restarting"
return rc return rc
for basedir in so.basedirs: for basedir in so.basedirs:
rc = start(basedir, so) or rc rc = start(basedir, so, stdout, stderr) or rc
elif command == "dump-uri-extension": elif command == "dump-uri-extension":
rc = dump_uri_extension(so) rc = dump_uri_extension(so, stdout, stderr)
elif command == "dump-root-dirnode": elif command == "dump-root-dirnode":
rc = dump_root_dirnode(so.basedirs[0], so) rc = dump_root_dirnode(so.basedirs[0], so, stdout, stderr)
elif command == "dump-dirnode": elif command == "dump-dirnode":
rc = dump_directory_node(so.basedirs[0], so) rc = dump_directory_node(so.basedirs[0], so, stdout, stderr)
return rc return rc
def run(): def run():
rc = runner(sys.argv[1:]) rc = runner(sys.argv[1:])
sys.exit(rc) sys.exit(rc)
def create_client(basedir, config): def create_client(basedir, config, out=sys.stdout, err=sys.stderr):
if os.path.exists(basedir): if os.path.exists(basedir):
if os.listdir(basedir): if os.listdir(basedir):
print "The base directory already exists: %s" % basedir print >>err, "The base directory already exists: %s" % basedir
print "To avoid clobbering anything, I am going to quit now" print >>err, "To avoid clobbering anything, I am going to quit now"
print "Please use a different directory, or delete this one" print >>err, "Please use a different directory, or delete this one"
return -1 return -1
# we're willing to use an empty directory # we're willing to use an empty directory
else: else:
@ -260,16 +262,15 @@ def create_client(basedir, config):
f = open(os.path.join(basedir, "client.tac"), "w") f = open(os.path.join(basedir, "client.tac"), "w")
f.write(client_tac) f.write(client_tac)
f.close() f.close()
if not config['quiet']: print >>out, "client created in %s" % basedir
print "client created in %s" % basedir print >>out, " please copy introducer.furl and vdrive.furl into the directory"
print " please copy introducer.furl and vdrive.furl into the directory"
def create_introducer(basedir, config): def create_introducer(basedir, config, out=sys.stdout, err=sys.stderr):
if os.path.exists(basedir): if os.path.exists(basedir):
if os.listdir(basedir): if os.listdir(basedir):
print "The base directory already exists: %s" % basedir print >>err, "The base directory already exists: %s" % basedir
print "To avoid clobbering anything, I am going to quit now" print >>err, "To avoid clobbering anything, I am going to quit now"
print "Please use a different directory, or delete this one" print >>err, "Please use a different directory, or delete this one"
return -1 return -1
# we're willing to use an empty directory # we're willing to use an empty directory
else: else:
@ -277,11 +278,10 @@ def create_introducer(basedir, config):
f = open(os.path.join(basedir, "introducer.tac"), "w") f = open(os.path.join(basedir, "introducer.tac"), "w")
f.write(introducer_tac) f.write(introducer_tac)
f.close() f.close()
if not config['quiet']: print >>out, "introducer created in %s" % basedir
print "introducer created in %s" % basedir
def start(basedir, config): def start(basedir, config, out=sys.stdout, err=sys.stderr):
print "STARTING", basedir print >>out, "STARTING", basedir
if os.path.exists(os.path.join(basedir, "client.tac")): if os.path.exists(os.path.join(basedir, "client.tac")):
tac = "client.tac" tac = "client.tac"
type = "client" type = "client"
@ -289,23 +289,23 @@ def start(basedir, config):
tac = "introducer.tac" tac = "introducer.tac"
type = "introducer" type = "introducer"
else: else:
print "%s does not look like a node directory" % basedir print >>err, "%s does not look like a node directory" % basedir
if not os.path.isdir(basedir): if not os.path.isdir(basedir):
print " in fact, it doesn't look like a directory at all!" print >>err, " in fact, it doesn't look like a directory at all!"
sys.exit(1) sys.exit(1)
rc = subprocess.call(["python", twistd, "-y", tac,], cwd=basedir) rc = subprocess.call(["python", twistd, "-y", tac,], cwd=basedir)
if rc == 0: if rc == 0:
print "%s node probably started" % type print >>out, "%s node probably started" % type
return 0 return 0
else: else:
print "%s node probably not started" % type print >>err, "%s node probably not started" % type
return 1 return 1
def stop(basedir, config): def stop(basedir, config, out=sys.stdout, err=sys.stderr):
print "STOPPING", basedir print >>out, "STOPPING", basedir
pidfile = os.path.join(basedir, "twistd.pid") pidfile = os.path.join(basedir, "twistd.pid")
if not os.path.exists(pidfile): if not os.path.exists(pidfile):
print "%s does not look like a running node directory (no twistd.pid)" % basedir print >>err, "%s does not look like a running node directory (no twistd.pid)" % basedir
return 1 return 1
pid = open(pidfile, "r").read() pid = open(pidfile, "r").read()
pid = int(pid) pid = int(pid)
@ -318,14 +318,14 @@ def stop(basedir, config):
try: try:
os.kill(pid, 0) os.kill(pid, 0)
except OSError: except OSError:
print "process %d is dead" % pid print >>out, "process %d is dead" % pid
return return
timer += 1 timer += 1
time.sleep(1) time.sleep(1)
print "never saw process go away" print >>err, "never saw process go away"
return 1 return 1
def dump_uri_extension(config, output=sys.stdout): def dump_uri_extension(config, out=sys.stdout, err=sys.stderr):
from allmydata import uri from allmydata import uri
filename = config['filename'] filename = config['filename']
@ -338,26 +338,26 @@ def dump_uri_extension(config, output=sys.stdout):
"share_root_hash") "share_root_hash")
for k in keys1: for k in keys1:
if k in unpacked: if k in unpacked:
print >>output, "%19s: %s" % (k, unpacked[k]) print >>out, "%19s: %s" % (k, unpacked[k])
print >>output print >>out
for k in keys2: for k in keys2:
if k in unpacked: if k in unpacked:
print >>output, "%19s: %s" % (k, unpacked[k]) print >>out, "%19s: %s" % (k, unpacked[k])
print >>output print >>out
for k in keys3: for k in keys3:
if k in unpacked: if k in unpacked:
print >>output, "%19s: %s" % (k, unpacked[k]) print >>out, "%19s: %s" % (k, unpacked[k])
leftover = set(unpacked.keys()) - set(keys1 + keys2 + keys3) leftover = set(unpacked.keys()) - set(keys1 + keys2 + keys3)
if leftover: if leftover:
print >>output print >>out
for k in sorted(leftover): for k in sorted(leftover):
print >>output, "%s: %s" % (k, unpacked[k]) print >>out, "%s: %s" % (k, unpacked[k])
print >>output print >>out
return 0 return 0
def dump_root_dirnode(basedir, config, output=sys.stdout): def dump_root_dirnode(basedir, config, out=sys.stdout, err=sys.stderr):
from allmydata import uri from allmydata import uri
root_dirnode_file = os.path.join(basedir, "vdrive", "root") root_dirnode_file = os.path.join(basedir, "vdrive", "root")
@ -365,14 +365,14 @@ def dump_root_dirnode(basedir, config, output=sys.stdout):
f = open(root_dirnode_file, "rb") f = open(root_dirnode_file, "rb")
key = f.read() key = f.read()
rooturi = uri.pack_dirnode_uri("fakeFURL", key) rooturi = uri.pack_dirnode_uri("fakeFURL", key)
print >>output, rooturi print >>out, rooturi
return 0 return 0
except EnvironmentError: except EnvironmentError:
print >>output, "unable to read root dirnode file from %s" % \ print >>out, "unable to read root dirnode file from %s" % \
root_dirnode_file root_dirnode_file
return 1 return 1
def dump_directory_node(basedir, config, f=sys.stdout): def dump_directory_node(basedir, config, out=sys.stdout, err=sys.stderr):
from allmydata import filetable, vdrive, uri from allmydata import filetable, vdrive, uri
from allmydata.util import hashutil, idlib from allmydata.util import hashutil, idlib
dir_uri = config['uri'] dir_uri = config['uri']
@ -386,43 +386,43 @@ def dump_directory_node(basedir, config, f=sys.stdout):
filename = os.path.join(basedir, "vdrive", idlib.b2a(index)) filename = os.path.join(basedir, "vdrive", idlib.b2a(index))
print >>f print >>out
print >>f, "dirnode uri: %s" % dir_uri print >>out, "dirnode uri: %s" % dir_uri
print >>f, "filename : %s" % filename print >>out, "filename : %s" % filename
print >>f, "index : %s" % idlib.b2a(index) print >>out, "index : %s" % idlib.b2a(index)
if wk: if wk:
print >>f, "writekey : %s" % idlib.b2a(wk) print >>out, "writekey : %s" % idlib.b2a(wk)
print >>f, "write_enabler: %s" % idlib.b2a(we) print >>out, "write_enabler: %s" % idlib.b2a(we)
else: else:
print >>f, "writekey : None" print >>out, "writekey : None"
print >>f, "write_enabler: None" print >>out, "write_enabler: None"
print >>f, "readkey : %s" % idlib.b2a(rk) print >>out, "readkey : %s" % idlib.b2a(rk)
print >>f print >>out
vds = filetable.VirtualDriveServer(os.path.join(basedir, "vdrive"), False) vds = filetable.VirtualDriveServer(os.path.join(basedir, "vdrive"), False)
data = vds._read_from_file(index) data = vds._read_from_file(index)
if we: if we:
if we != data[0]: if we != data[0]:
print >>f, "ERROR: write_enabler does not match" print >>out, "ERROR: write_enabler does not match"
for (H_key, E_key, E_write, E_read) in data[1]: for (H_key, E_key, E_write, E_read) in data[1]:
if verbose: if verbose:
print >>f, " H_key %s" % idlib.b2a(H_key) print >>out, " H_key %s" % idlib.b2a(H_key)
print >>f, " E_key %s" % idlib.b2a(E_key) print >>out, " E_key %s" % idlib.b2a(E_key)
print >>f, " E_write %s" % idlib.b2a(E_write) print >>out, " E_write %s" % idlib.b2a(E_write)
print >>f, " E_read %s" % idlib.b2a(E_read) print >>out, " E_read %s" % idlib.b2a(E_read)
key = vdrive.decrypt(rk, E_key) key = vdrive.decrypt(rk, E_key)
print >>f, " key %s" % key print >>out, " key %s" % key
if hashutil.dir_name_hash(rk, key) != H_key: if hashutil.dir_name_hash(rk, key) != H_key:
print >>f, " ERROR: H_key does not match" print >>out, " ERROR: H_key does not match"
if wk and E_write: if wk and E_write:
if len(E_write) < 14: if len(E_write) < 14:
print >>f, " ERROR: write data is short:", idlib.b2a(E_write) print >>out, " ERROR: write data is short:", idlib.b2a(E_write)
write = vdrive.decrypt(wk, E_write) write = vdrive.decrypt(wk, E_write)
print >>f, " write: %s" % write print >>out, " write: %s" % write
read = vdrive.decrypt(rk, E_read) read = vdrive.decrypt(rk, E_read)
print >>f, " read: %s" % read print >>out, " read: %s" % read
print >>f print >>out
return 0 return 0

View File

@ -16,13 +16,24 @@ class CreateNode(unittest.TestCase):
def test_client(self): def test_client(self):
basedir = self.workdir("test_client") basedir = self.workdir("test_client")
c1 = os.path.join(basedir, "c1") c1 = os.path.join(basedir, "c1")
argv = ["create-client", "--basedir", c1, "--quiet"] argv = ["--quiet", "create-client", "--basedir", c1]
runner.runner(argv) out,err = StringIO(), StringIO()
rc = runner.runner(argv, stdout=out, stderr=err)
self.failUnlessEqual(err.getvalue(), "")
self.failUnlessEqual(out.getvalue(), "")
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.exists(c1)) self.failUnless(os.path.exists(c1))
self.failUnless(os.path.exists(os.path.join(c1, "client.tac"))) self.failUnless(os.path.exists(os.path.join(c1, "client.tac")))
# creating the client a second time should throw an exception
out,err = StringIO(), StringIO()
rc = runner.runner(argv, stdout=out, stderr=err)
self.failIfEqual(rc, 0)
self.failUnlessEqual(out.getvalue(), "")
self.failUnless("The base directory already exists" in err.getvalue())
c2 = os.path.join(basedir, "c2") c2 = os.path.join(basedir, "c2")
argv = ["create-client", "--quiet", c2] argv = ["--quiet", "create-client", c2]
runner.runner(argv) runner.runner(argv)
self.failUnless(os.path.exists(c2)) self.failUnless(os.path.exists(c2))
self.failUnless(os.path.exists(os.path.join(c2, "client.tac"))) self.failUnless(os.path.exists(os.path.join(c2, "client.tac")))
@ -40,13 +51,24 @@ class CreateNode(unittest.TestCase):
def test_introducer(self): def test_introducer(self):
basedir = self.workdir("test_introducer") basedir = self.workdir("test_introducer")
c1 = os.path.join(basedir, "c1") c1 = os.path.join(basedir, "c1")
argv = ["create-introducer", "--basedir", c1, "--quiet"] argv = ["--quiet", "create-introducer", "--basedir", c1]
runner.runner(argv) out,err = StringIO(), StringIO()
rc = runner.runner(argv, stdout=out, stderr=err)
self.failUnlessEqual(err.getvalue(), "")
self.failUnlessEqual(out.getvalue(), "")
self.failUnlessEqual(rc, 0)
self.failUnless(os.path.exists(c1)) self.failUnless(os.path.exists(c1))
self.failUnless(os.path.exists(os.path.join(c1, "introducer.tac"))) self.failUnless(os.path.exists(os.path.join(c1, "introducer.tac")))
# creating the introducer a second time should throw an exception
out,err = StringIO(), StringIO()
rc = runner.runner(argv, stdout=out, stderr=err)
self.failIfEqual(rc, 0)
self.failUnlessEqual(out.getvalue(), "")
self.failUnless("The base directory already exists" in err.getvalue())
c2 = os.path.join(basedir, "c2") c2 = os.path.join(basedir, "c2")
argv = ["create-introducer", "--quiet", c2] argv = ["--quiet", "create-introducer", c2]
runner.runner(argv) runner.runner(argv)
self.failUnless(os.path.exists(c2)) self.failUnless(os.path.exists(c2))
self.failUnless(os.path.exists(os.path.join(c2, "introducer.tac"))) self.failUnless(os.path.exists(os.path.join(c2, "introducer.tac")))