2009-05-07 22:31:51 +00:00
2007-04-20 01:56:45 +00:00
from twisted . trial import unittest
2009-02-09 09:26:17 +00:00
from twisted . python import usage , runtime
2009-01-22 22:52:13 +00:00
from twisted . internet import utils
2009-01-27 21:37:17 +00:00
import os . path , re , sys
2009-02-09 09:26:17 +00:00
from cStringIO import StringIO
2008-10-29 04:15:48 +00:00
from allmydata . util import fileutil , pollmixin
2010-08-02 06:09:02 +00:00
from allmydata . util . encodingutil import unicode_to_argv , unicode_to_output , get_filesystem_encoding
2009-02-09 09:26:17 +00:00
from allmydata . scripts import runner
2007-04-20 01:56:45 +00:00
2009-01-22 22:38:18 +00:00
from allmydata . test import common_util
2009-01-22 22:52:40 +00:00
import allmydata
2010-08-06 04:26:01 +00:00
timeout = 240
2010-08-02 04:55:35 +00:00
srcfile = allmydata . __file__
2010-08-08 18:50:05 +00:00
srcdir = os . path . dirname ( os . path . dirname ( os . path . normcase ( os . path . realpath ( srcfile ) ) ) )
2010-08-08 04:28:17 +00:00
2010-08-02 04:55:35 +00:00
rootdir = os . path . dirname ( srcdir )
2010-08-08 18:50:05 +00:00
if os . path . basename ( srcdir ) == ' site-packages ' :
if re . search ( r ' python.+ \ ..+ ' , os . path . basename ( rootdir ) ) :
2010-08-08 17:13:40 +00:00
rootdir = os . path . dirname ( rootdir )
rootdir = os . path . dirname ( rootdir )
2010-11-02 03:59:05 +00:00
elif os . path . basename ( rootdir ) == ' src ' :
rootdir = os . path . dirname ( rootdir )
2010-08-02 04:55:35 +00:00
bintahoe = os . path . join ( rootdir , ' bin ' , ' tahoe ' )
2010-07-25 18:20:08 +00:00
if sys . platform == " win32 " :
bintahoe + = " .pyscript "
2010-08-08 04:28:17 +00:00
if not os . path . exists ( bintahoe ) :
alt_bintahoe = os . path . join ( rootdir , ' Scripts ' , ' tahoe.pyscript ' )
if os . path . exists ( alt_bintahoe ) :
bintahoe = alt_bintahoe
2009-01-24 01:34:37 +00:00
2010-01-16 20:45:56 +00:00
class SkipMixin :
def skip_if_cannot_run_bintahoe ( self ) :
2009-02-09 09:34:00 +00:00
if " cygwin " in sys . platform . lower ( ) :
raise unittest . SkipTest ( " We don ' t know how to make this test work on cygwin: spawnProcess seems to hang forever. We don ' t know if ' bin/tahoe start ' can be run on cygwin. " )
2010-01-16 20:45:56 +00:00
if not os . path . exists ( bintahoe ) :
raise unittest . SkipTest ( " The bin/tahoe script isn ' t to be found in the expected location ( %s ), and I don ' t want to test a ' tahoe ' executable that I find somewhere else, in case it isn ' t the right executable for this version of Tahoe. Perhaps running ' setup.py build ' again will help. " % ( bintahoe , ) )
def skip_if_cannot_daemonize ( self ) :
self . skip_if_cannot_run_bintahoe ( )
if runtime . platformType == " win32 " :
# twistd on windows doesn't daemonize. cygwin should work normally.
raise unittest . SkipTest ( " twistd does not fork under windows " )
2009-02-09 09:34:00 +00:00
2010-01-16 20:45:56 +00:00
2010-07-20 01:13:45 +00:00
class BinTahoe ( common_util . SignalMixin , unittest . TestCase , SkipMixin ) :
2010-08-02 04:55:35 +00:00
def test_the_right_code ( self ) :
2010-08-08 18:50:05 +00:00
cwd = os . path . normcase ( os . path . realpath ( " . " ) )
root_from_cwd = os . path . dirname ( cwd )
2010-11-02 03:59:05 +00:00
if os . path . basename ( root_from_cwd ) == ' src ' :
root_from_cwd = os . path . dirname ( root_from_cwd )
2010-08-02 04:55:35 +00:00
2010-08-08 18:50:05 +00:00
same = ( root_from_cwd == rootdir )
2010-08-02 04:55:35 +00:00
if not same :
try :
2010-08-08 18:50:05 +00:00
same = os . path . samefile ( root_from_cwd , rootdir )
2010-08-02 04:55:35 +00:00
except AttributeError , e :
e # hush pyflakes
if not same :
msg = ( " We seem to be testing the code at %r , \n "
" (according to the source filename %r ), \n "
" but expected to be testing the code at %r . \n "
2010-08-08 18:50:05 +00:00
% ( rootdir , srcfile , root_from_cwd ) )
2010-11-02 03:59:05 +00:00
root_from_cwdu = os . path . normcase ( os . path . normpath ( os . getcwdu ( ) ) )
if os . path . basename ( root_from_cwdu ) == u ' src ' :
root_from_cwdu = os . path . dirname ( root_from_cwdu )
if not isinstance ( root_from_cwd , unicode ) and root_from_cwd . decode ( get_filesystem_encoding ( ) , ' replace ' ) != root_from_cwdu :
2010-08-02 04:55:35 +00:00
msg + = ( " However, this may be a false alarm because the current directory path \n "
" is not representable in the filesystem encoding. Please run the tests \n "
" from the root of the Tahoe-LAFS distribution at a non-Unicode path. " )
raise unittest . SkipTest ( msg )
else :
msg + = " Please run the tests from the root of the Tahoe-LAFS distribution. "
self . fail ( msg )
2009-01-22 22:52:40 +00:00
def test_path ( self ) :
2010-01-16 20:45:56 +00:00
self . skip_if_cannot_run_bintahoe ( )
2009-01-24 01:34:37 +00:00
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --version-and-path " ] , env = os . environ )
2009-01-22 22:52:40 +00:00
def _cb ( res ) :
out , err , rc_or_sig = res
2010-08-02 01:35:26 +00:00
self . failUnlessEqual ( rc_or_sig , 0 , str ( res ) )
2009-01-22 22:52:40 +00:00
2010-09-10 15:41:35 +00:00
# Fail unless the allmydata-tahoe package is *this* version *and*
# was loaded from *this* source directory.
verstr = str ( allmydata . __version__ )
2010-09-11 22:19:13 +00:00
self . failIfEqual ( verstr , " unknown " ,
" We don ' t know our version, because this distribution didn ' t come "
" with a _version.py and ' setup.py darcsver ' hasn ' t been run. " )
2010-09-10 15:41:35 +00:00
# The Python "rational version numbering" convention
# disallows "-r$REV" but allows ".post$REV"
# instead. Eventually we'll probably move to that. When we
# do, this test won't go red:
ix = verstr . rfind ( ' -r ' )
if ix != - 1 :
altverstr = verstr [ : ix ] + ' .post ' + verstr [ ix + 2 : ]
else :
ix = verstr . rfind ( ' .post ' )
if ix != - 1 :
altverstr = verstr [ : ix ] + ' -r ' + verstr [ ix + 5 : ]
else :
altverstr = verstr
2010-09-11 22:19:13 +00:00
required_ver_and_path = " %s : %s ( %s ) " % ( allmydata . __appname__ , verstr , srcdir )
alt_required_ver_and_path = " %s : %s ( %s ) " % ( allmydata . __appname__ , altverstr , srcdir )
2010-09-10 15:41:35 +00:00
self . failUnless ( out . startswith ( required_ver_and_path ) or out . startswith ( alt_required_ver_and_path ) , ( out , err , rc_or_sig , required_ver_and_path ) )
2009-01-22 22:52:40 +00:00
d . addCallback ( _cb )
return d
2009-01-22 22:38:18 +00:00
2010-07-25 08:32:16 +00:00
def test_unicode_arguments_and_output ( self ) :
self . skip_if_cannot_run_bintahoe ( )
tricky = u " \u2621 "
try :
tricky_arg = unicode_to_argv ( tricky , mangle = True )
tricky_out = unicode_to_output ( tricky )
except UnicodeEncodeError :
raise unittest . SkipTest ( " A non-ASCII argument/output could not be encoded on this platform. " )
d = utils . getProcessOutputAndValue ( bintahoe , args = [ tricky_arg ] , env = os . environ )
def _cb ( res ) :
out , err , rc_or_sig = res
2010-08-02 04:55:35 +00:00
self . failUnlessEqual ( rc_or_sig , 1 , str ( res ) )
2010-07-25 08:32:16 +00:00
self . failUnlessIn ( " Unknown command: " + tricky_out , out )
d . addCallback ( _cb )
return d
2010-08-02 06:25:58 +00:00
def test_run_with_python_options ( self ) :
self . skip_if_cannot_run_bintahoe ( )
# -t is a harmless option that warns about tabs.
d = utils . getProcessOutputAndValue ( sys . executable , args = [ ' -t ' , bintahoe , ' --version ' ] ,
env = os . environ )
def _cb ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 0 , str ( res ) )
self . failUnless ( out . startswith ( allmydata . __appname__ + ' : ' ) , str ( res ) )
d . addCallback ( _cb )
return d
2010-07-20 01:13:45 +00:00
def test_version_no_noise ( self ) :
self . skip_if_cannot_run_bintahoe ( )
import pkg_resources
try :
pkg_resources . require ( " Twisted>=9.0.0 " )
except pkg_resources . VersionConflict :
raise unittest . SkipTest ( " We pass this test only with Twisted >= v9.0.0 " )
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --version " ] , env = os . environ )
def _cb ( res ) :
out , err , rc_or_sig = res
2010-08-02 01:35:26 +00:00
self . failUnlessEqual ( rc_or_sig , 0 , str ( res ) )
self . failUnless ( out . startswith ( allmydata . __appname__ + ' : ' ) , str ( res ) )
self . failIfIn ( " DeprecationWarning " , out , str ( res ) )
2010-10-29 19:18:04 +00:00
errlines = err . split ( " \n " )
2010-10-29 20:42:46 +00:00
self . failIf ( [ True for line in errlines if ( line != " " and " UserWarning: Unbuilt egg for setuptools " not in line
2010-10-29 22:11:23 +00:00
and " from pkg_resources import load_entry_point " not in line ) ] , str ( res ) )
2010-10-29 19:18:04 +00:00
if err != " " :
raise unittest . SkipTest ( " This test is known not to pass on Ubuntu Lucid; see #1235. " )
2010-07-20 01:13:45 +00:00
d . addCallback ( _cb )
return d
2010-01-16 20:45:56 +00:00
2009-02-09 09:26:17 +00:00
class CreateNode ( unittest . TestCase ) :
2010-01-16 05:20:55 +00:00
# exercise "tahoe create-node", create-introducer,
2009-02-09 09:26:17 +00:00
# create-key-generator, and create-stats-gatherer, by calling the
# corresponding code as a subroutine.
2007-04-20 01:56:45 +00:00
def workdir ( self , name ) :
2007-09-17 09:25:31 +00:00
basedir = os . path . join ( " test_runner " , " CreateNode " , name )
2007-04-20 01:56:45 +00:00
fileutil . make_dirs ( basedir )
return basedir
2009-02-09 09:26:17 +00:00
def run_tahoe ( self , argv ) :
out , err = StringIO ( ) , StringIO ( )
rc = runner . runner ( argv , stdout = out , stderr = err )
return rc , out . getvalue ( ) , err . getvalue ( )
2010-08-03 08:54:16 +00:00
def do_create ( self , kind ) :
basedir = self . workdir ( " test_ " + kind )
command = " create- " + kind
is_client = kind in ( " node " , " client " )
tac = is_client and " tahoe-client.tac " or ( " tahoe- " + kind + " .tac " )
n1 = os . path . join ( basedir , command + " -n1 " )
argv = [ " --quiet " , command , " --basedir " , n1 ]
2009-02-09 09:26:17 +00:00
rc , out , err = self . run_tahoe ( argv )
self . failUnlessEqual ( err , " " )
self . failUnlessEqual ( out , " " )
self . failUnlessEqual ( rc , 0 )
2010-08-03 08:54:16 +00:00
self . failUnless ( os . path . exists ( n1 ) )
self . failUnless ( os . path . exists ( os . path . join ( n1 , tac ) ) )
if is_client :
# tahoe.cfg should exist, and should have storage enabled for
# 'create-node', and disabled for 'create-client'.
tahoe_cfg = os . path . join ( n1 , " tahoe.cfg " )
self . failUnless ( os . path . exists ( tahoe_cfg ) )
content = open ( tahoe_cfg ) . read ( )
if kind == " client " :
self . failUnless ( " \n [storage] \n enabled = false \n " in content )
else :
self . failUnless ( " \n [storage] \n enabled = true \n " in content )
2011-01-16 20:58:22 +00:00
self . failUnless ( " \n reserved_space = 1G \n " in content )
2010-08-03 08:54:16 +00:00
# creating the node a second time should be rejected
2009-02-09 09:26:17 +00:00
rc , out , err = self . run_tahoe ( argv )
self . failIfEqual ( rc , 0 , str ( ( out , err , rc ) ) )
self . failUnlessEqual ( out , " " )
self . failUnless ( " is not empty. " in err )
# Fail if there is a non-empty line that doesn't end with a
# punctuation mark.
for line in err . splitlines ( ) :
self . failIf ( re . search ( " [ \ S][^ \ .!?]$ " , line ) , ( line , ) )
# test that the non --basedir form works too
2010-08-03 08:54:16 +00:00
n2 = os . path . join ( basedir , command + " -n2 " )
argv = [ " --quiet " , command , n2 ]
2009-02-09 09:26:17 +00:00
rc , out , err = self . run_tahoe ( argv )
2010-08-03 08:54:16 +00:00
self . failUnlessEqual ( err , " " )
2009-02-09 09:26:17 +00:00
self . failUnlessEqual ( out , " " )
self . failUnlessEqual ( rc , 0 )
2010-08-03 08:54:16 +00:00
self . failUnless ( os . path . exists ( n2 ) )
self . failUnless ( os . path . exists ( os . path . join ( n2 , tac ) ) )
2009-02-09 09:26:17 +00:00
2010-08-03 08:54:16 +00:00
# test the --node-directory form
n3 = os . path . join ( basedir , command + " -n3 " )
argv = [ " --quiet " , command , " --node-directory " , n3 ]
2009-02-09 09:26:17 +00:00
rc , out , err = self . run_tahoe ( argv )
2010-08-03 08:54:16 +00:00
self . failUnlessEqual ( err , " " )
2009-02-09 09:26:17 +00:00
self . failUnlessEqual ( out , " " )
self . failUnlessEqual ( rc , 0 )
2010-08-03 08:54:16 +00:00
self . failUnless ( os . path . exists ( n3 ) )
self . failUnless ( os . path . exists ( os . path . join ( n3 , tac ) ) )
2009-02-09 09:26:17 +00:00
2010-11-27 08:38:09 +00:00
# make sure it rejects too many arguments
2010-08-03 08:54:16 +00:00
argv = [ command , " basedir " , " extraarg " ]
2009-02-09 09:26:17 +00:00
self . failUnlessRaises ( usage . UsageError ,
runner . runner , argv ,
run_by_human = False )
2010-08-03 08:54:16 +00:00
# when creating a non-client, there is no default for the basedir
if not is_client :
argv = [ command ]
self . failUnlessRaises ( usage . UsageError ,
runner . runner , argv ,
run_by_human = False )
2009-02-09 09:26:17 +00:00
2010-08-03 08:54:16 +00:00
def test_node ( self ) :
self . do_create ( " node " )
2009-02-09 09:26:17 +00:00
2010-08-03 08:54:16 +00:00
def test_client ( self ) :
# create-client should behave like create-node --no-storage.
self . do_create ( " client " )
2009-02-09 09:26:17 +00:00
2010-08-03 08:54:16 +00:00
def test_introducer ( self ) :
self . do_create ( " introducer " )
2009-02-09 09:26:17 +00:00
2010-08-03 08:54:16 +00:00
def test_key_generator ( self ) :
self . do_create ( " key-generator " )
def test_stats_gatherer ( self ) :
self . do_create ( " stats-gatherer " )
2009-02-09 09:26:17 +00:00
def test_subcommands ( self ) :
# no arguments should trigger a command listing, via UsageError
self . failUnlessRaises ( usage . UsageError ,
runner . runner ,
[ ] ,
run_by_human = False )
2009-01-22 22:38:18 +00:00
2009-02-23 21:43:12 +00:00
class RunNode ( common_util . SignalMixin , unittest . TestCase , pollmixin . PollMixin ,
2010-01-16 20:45:56 +00:00
SkipMixin ) :
2009-02-09 09:34:00 +00:00
# exercise "tahoe start", for both introducer, client node, and
# key-generator, by spawning "tahoe start" as a subprocess. This doesn't
# get us figleaf-based line-level coverage, but it does a better job of
# confirming that the user can actually run "./bin/tahoe start" and
# expect it to work. This verifies that bin/tahoe sets up PYTHONPATH and
# the like correctly.
# This doesn't work on cygwin (it hangs forever), so we skip this test
# when we're on cygwin. It is likely that "tahoe start" itself doesn't
# work on cygwin: twisted seems unable to provide a version of
# spawnProcess which really works there.
2007-09-17 09:25:31 +00:00
def workdir ( self , name ) :
basedir = os . path . join ( " test_runner " , " RunNode " , name )
fileutil . make_dirs ( basedir )
return basedir
2008-02-18 07:28:56 +00:00
def test_introducer ( self ) :
2010-01-16 20:45:56 +00:00
self . skip_if_cannot_daemonize ( )
2008-02-18 07:28:56 +00:00
basedir = self . workdir ( " test_introducer " )
c1 = os . path . join ( basedir , " c1 " )
HOTLINE_FILE = os . path . join ( c1 , " suicide_prevention_hotline " )
TWISTD_PID_FILE = os . path . join ( c1 , " twistd.pid " )
2009-01-22 22:38:18 +00:00
INTRODUCER_FURL_FILE = os . path . join ( c1 , " introducer.furl " )
2009-01-24 01:34:37 +00:00
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " create-introducer " , " --basedir " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
def _cb ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 0 )
# by writing this file, we get ten seconds before the node will
# exit. This insures that even if the test fails (and the 'stop'
# command doesn't work), the client should still terminate.
open ( HOTLINE_FILE , " w " ) . write ( " " )
# now it's safe to start the node
d . addCallback ( _cb )
def _then_start_the_node ( res ) :
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _then_start_the_node )
def _cb2 ( res ) :
out , err , rc_or_sig = res
2008-02-18 07:28:56 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
2009-01-22 22:38:18 +00:00
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2008-02-18 07:28:56 +00:00
# the parent (twistd) has exited. However, twistd writes the pid
# from the child, not the parent, so we can't expect twistd.pid
# to exist quite yet.
# the node is running, but it might not have made it past the
# first reactor turn yet, and if we kill it too early, it won't
# remove the twistd.pid file. So wait until it does something
# that we know it won't do until after the first turn.
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb2 )
2008-02-18 07:28:56 +00:00
def _node_has_started ( ) :
return os . path . exists ( INTRODUCER_FURL_FILE )
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
def _started ( res ) :
open ( HOTLINE_FILE , " w " ) . write ( " " )
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) )
# rm this so we can detect when the second incarnation is ready
os . unlink ( INTRODUCER_FURL_FILE )
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " restart " , c1 ] , env = os . environ )
2008-02-18 07:28:56 +00:00
d . addCallback ( _started )
2009-01-22 22:38:18 +00:00
def _then ( res ) :
out , err , rc_or_sig = res
open ( HOTLINE_FILE , " w " ) . write ( " " )
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2009-01-22 22:38:18 +00:00
d . addCallback ( _then )
2008-02-18 07:28:56 +00:00
# again, the second incarnation of the node might not be ready yet,
# so poll until it is
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
# now we can kill it. TODO: On a slow machine, the node might kill
# itself before we get a chance too, especially if spawning the
# 'tahoe stop' command takes a while.
def _stop ( res ) :
open ( HOTLINE_FILE , " w " ) . write ( " " )
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) )
2009-01-22 22:38:18 +00:00
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " stop " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _stop )
def _after_stopping ( res ) :
out , err , rc_or_sig = res
2008-02-18 07:28:56 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
# the parent has exited by now
2009-01-22 22:38:18 +00:00
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2008-02-18 07:28:56 +00:00
# the parent was supposed to poll and wait until it sees
# twistd.pid go away before it exits, so twistd.pid should be
# gone by now.
self . failIf ( os . path . exists ( TWISTD_PID_FILE ) )
2009-01-22 22:38:18 +00:00
d . addCallback ( _after_stopping )
2008-02-18 07:28:56 +00:00
def _remove_hotline ( res ) :
os . unlink ( HOTLINE_FILE )
return res
d . addBoth ( _remove_hotline )
return d
2011-01-01 10:01:01 +00:00
test_introducer . timeout = 480 # This hit the 120-second timeout on "Francois Lenny-armv5tel", then it hit a 240-second timeout on our feisty2.5 buildslave: http://allmydata.org/buildbot/builders/feisty2.5/builds/2381/steps/test/logs/test.log
2008-02-18 07:28:56 +00:00
2010-02-01 00:44:29 +00:00
def test_client_no_noise ( self ) :
self . skip_if_cannot_daemonize ( )
2010-02-01 05:23:23 +00:00
import pkg_resources
try :
pkg_resources . require ( " Twisted>=9.0.0 " )
except pkg_resources . VersionConflict :
raise unittest . SkipTest ( " We pass this test only with Twisted >= v9.0.0 " )
2010-02-01 00:44:29 +00:00
basedir = self . workdir ( " test_client_no_noise " )
c1 = os . path . join ( basedir , " c1 " )
HOTLINE_FILE = os . path . join ( c1 , " suicide_prevention_hotline " )
TWISTD_PID_FILE = os . path . join ( c1 , " twistd.pid " )
PORTNUMFILE = os . path . join ( c1 , " client.port " )
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " create-client " , " --basedir " , c1 , " --webport " , " 0 " ] , env = os . environ )
def _cb ( res ) :
out , err , rc_or_sig = res
errstr = " cc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
assert rc_or_sig == 0 , errstr
self . failUnlessEqual ( rc_or_sig , 0 )
# By writing this file, we get forty seconds before the client will exit. This insures
# that even if the 'stop' command doesn't work (and the test fails), the client should
# still terminate.
open ( HOTLINE_FILE , " w " ) . write ( " " )
open ( os . path . join ( c1 , " introducer.furl " ) , " w " ) . write ( " pb://xrndsskn2zuuian5ltnxrte7lnuqdrkz@127.0.0.1:55617/introducer \n " )
# now it's safe to start the node
d . addCallback ( _cb )
def _start ( res ) :
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , c1 ] , env = os . environ )
d . addCallback ( _start )
def _cb2 ( res ) :
out , err , rc_or_sig = res
errstr = " cc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
open ( HOTLINE_FILE , " w " ) . write ( " " )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr ) # If you emit noise, you fail this test.
2010-10-29 19:18:04 +00:00
errlines = err . split ( " \n " )
2010-10-29 20:42:46 +00:00
self . failIf ( [ True for line in errlines if ( line != " " and " UserWarning: Unbuilt egg for setuptools " not in line
and " from pkg_resources import load_entry_point " not in line ) ] , errstr )
2010-10-29 19:18:04 +00:00
if err != " " :
raise unittest . SkipTest ( " This test is known not to pass on Ubuntu Lucid; see #1235. " )
2010-02-01 00:44:29 +00:00
# the parent (twistd) has exited. However, twistd writes the pid
# from the child, not the parent, so we can't expect twistd.pid
# to exist quite yet.
# the node is running, but it might not have made it past the
# first reactor turn yet, and if we kill it too early, it won't
# remove the twistd.pid file. So wait until it does something
# that we know it won't do until after the first turn.
d . addCallback ( _cb2 )
def _node_has_started ( ) :
return os . path . exists ( PORTNUMFILE )
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
# now we can kill it. TODO: On a slow machine, the node might kill
2010-11-28 17:45:07 +00:00
# itself before we get a chance to, especially if spawning the
2010-02-01 00:44:29 +00:00
# 'tahoe stop' command takes a while.
def _stop ( res ) :
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) , ( TWISTD_PID_FILE , os . listdir ( os . path . dirname ( TWISTD_PID_FILE ) ) ) )
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " stop " , c1 ] , env = os . environ )
d . addCallback ( _stop )
return d
2007-09-17 09:25:31 +00:00
def test_client ( self ) :
2010-01-16 20:45:56 +00:00
self . skip_if_cannot_daemonize ( )
2007-09-17 09:25:31 +00:00
basedir = self . workdir ( " test_client " )
c1 = os . path . join ( basedir , " c1 " )
2007-09-18 22:17:26 +00:00
HOTLINE_FILE = os . path . join ( c1 , " suicide_prevention_hotline " )
TWISTD_PID_FILE = os . path . join ( c1 , " twistd.pid " )
2009-01-22 22:38:18 +00:00
PORTNUMFILE = os . path . join ( c1 , " client.port " )
2010-01-16 05:20:55 +00:00
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " create-node " , " --basedir " , c1 , " --webport " , " 0 " ] , env = os . environ )
2009-01-22 22:38:18 +00:00
def _cb ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 0 )
2009-02-12 22:21:31 +00:00
# By writing this file, we get sixty seconds before the client will exit. This insures
2009-01-22 22:38:18 +00:00
# that even if the 'stop' command doesn't work (and the test fails), the client should
# still terminate.
open ( HOTLINE_FILE , " w " ) . write ( " " )
open ( os . path . join ( c1 , " introducer.furl " ) , " w " ) . write ( " pb://xrndsskn2zuuian5ltnxrte7lnuqdrkz@127.0.0.1:55617/introducer \n " )
# now it's safe to start the node
d . addCallback ( _cb )
2007-09-18 22:17:26 +00:00
2007-09-19 20:56:00 +00:00
def _start ( res ) :
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _start )
def _cb2 ( res ) :
out , err , rc_or_sig = res
2007-09-19 20:56:00 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
2009-05-20 03:36:20 +00:00
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
2009-01-22 22:38:18 +00:00
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2007-09-17 09:25:31 +00:00
2007-09-19 20:56:00 +00:00
# the parent (twistd) has exited. However, twistd writes the pid
# from the child, not the parent, so we can't expect twistd.pid
# to exist quite yet.
2007-09-18 22:17:26 +00:00
2007-09-19 20:56:00 +00:00
# the node is running, but it might not have made it past the
# first reactor turn yet, and if we kill it too early, it won't
# remove the twistd.pid file. So wait until it does something
# that we know it won't do until after the first turn.
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb2 )
2007-09-19 20:56:00 +00:00
2007-09-18 22:17:26 +00:00
def _node_has_started ( ) :
return os . path . exists ( PORTNUMFILE )
2007-09-19 20:56:00 +00:00
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
2007-09-18 22:17:26 +00:00
def _started ( res ) :
2007-09-19 20:56:00 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
2007-09-18 22:17:26 +00:00
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) )
# rm this so we can detect when the second incarnation is ready
os . unlink ( PORTNUMFILE )
2009-01-22 22:38:18 +00:00
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " restart " , c1 ] , env = os . environ )
2007-09-18 22:17:26 +00:00
d . addCallback ( _started )
2009-01-22 22:38:18 +00:00
def _cb3 ( res ) :
out , err , rc_or_sig = res
open ( HOTLINE_FILE , " w " ) . write ( " " )
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb3 )
2007-09-18 22:17:26 +00:00
# again, the second incarnation of the node might not be ready yet,
# so poll until it is
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
2007-09-19 20:56:00 +00:00
# now we can kill it. TODO: On a slow machine, the node might kill
# itself before we get a chance too, especially if spawning the
2007-10-11 10:38:24 +00:00
# 'tahoe stop' command takes a while.
2007-09-18 22:17:26 +00:00
def _stop ( res ) :
2007-09-19 20:56:00 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
2008-12-21 22:07:52 +00:00
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) , ( TWISTD_PID_FILE , os . listdir ( os . path . dirname ( TWISTD_PID_FILE ) ) ) )
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " stop " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _stop )
def _cb4 ( res ) :
out , err , rc_or_sig = res
2007-09-19 20:56:00 +00:00
open ( HOTLINE_FILE , " w " ) . write ( " " )
2007-09-18 22:17:26 +00:00
# the parent has exited by now
2009-01-22 22:38:18 +00:00
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2007-09-18 22:17:26 +00:00
# the parent was supposed to poll and wait until it sees
# twistd.pid go away before it exits, so twistd.pid should be
# gone by now.
self . failIf ( os . path . exists ( TWISTD_PID_FILE ) )
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb4 )
2007-09-19 20:56:00 +00:00
def _remove_hotline ( res ) :
os . unlink ( HOTLINE_FILE )
return res
d . addBoth ( _remove_hotline )
2007-09-18 22:17:26 +00:00
return d
2007-09-17 09:25:31 +00:00
2007-09-19 08:50:27 +00:00
def test_baddir ( self ) :
2010-01-16 20:45:56 +00:00
self . skip_if_cannot_daemonize ( )
2007-09-19 08:50:27 +00:00
basedir = self . workdir ( " test_baddir " )
fileutil . make_dirs ( basedir )
2009-01-22 22:38:18 +00:00
2009-01-24 01:34:37 +00:00
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , " --basedir " , basedir ] , env = os . environ )
2009-01-22 22:38:18 +00:00
def _cb ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 1 )
2010-05-21 12:20:52 +00:00
self . failUnless ( " does not look like a node directory " in err , err )
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb )
2009-01-27 21:32:45 +00:00
def _then_stop_it ( res ) :
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " stop " , " --basedir " , basedir ] , env = os . environ )
d . addCallback ( _then_stop_it )
def _cb2 ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 2 )
self . failUnless ( " does not look like a running node directory " in err )
d . addCallback ( _cb2 )
def _then_start_in_bogus_basedir ( res ) :
not_a_dir = os . path . join ( basedir , " bogus " )
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , " --basedir " , not_a_dir ] , env = os . environ )
d . addCallback ( _then_start_in_bogus_basedir )
def _cb3 ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 1 )
self . failUnless ( " does not look like a directory at all " in err , err )
d . addCallback ( _cb3 )
return d
2007-09-19 08:50:27 +00:00
2008-12-02 00:47:21 +00:00
def test_keygen ( self ) :
2010-01-16 20:45:56 +00:00
self . skip_if_cannot_daemonize ( )
2008-12-02 00:47:21 +00:00
basedir = self . workdir ( " test_keygen " )
c1 = os . path . join ( basedir , " c1 " )
TWISTD_PID_FILE = os . path . join ( c1 , " twistd.pid " )
2009-01-22 22:38:18 +00:00
KEYGEN_FURL_FILE = os . path . join ( c1 , " key_generator.furl " )
2009-01-24 01:34:37 +00:00
d = utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " create-key-generator " , " --basedir " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
def _cb ( res ) :
out , err , rc_or_sig = res
self . failUnlessEqual ( rc_or_sig , 0 )
d . addCallback ( _cb )
2008-12-02 00:47:21 +00:00
def _start ( res ) :
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " start " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _start )
def _cb2 ( res ) :
out , err , rc_or_sig = res
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2008-12-02 00:47:21 +00:00
# the parent (twistd) has exited. However, twistd writes the pid
# from the child, not the parent, so we can't expect twistd.pid
# to exist quite yet.
# the node is running, but it might not have made it past the
# first reactor turn yet, and if we kill it too early, it won't
# remove the twistd.pid file. So wait until it does something
# that we know it won't do until after the first turn.
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb2 )
2007-09-17 09:25:31 +00:00
2008-12-02 00:47:21 +00:00
def _node_has_started ( ) :
return os . path . exists ( KEYGEN_FURL_FILE )
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
def _started ( res ) :
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) )
# rm this so we can detect when the second incarnation is ready
os . unlink ( KEYGEN_FURL_FILE )
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " restart " , c1 ] , env = os . environ )
2008-12-02 00:47:21 +00:00
d . addCallback ( _started )
2009-01-22 22:38:18 +00:00
def _cb3 ( res ) :
out , err , rc_or_sig = res
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb3 )
2008-12-02 00:47:21 +00:00
# again, the second incarnation of the node might not be ready yet,
# so poll until it is
d . addCallback ( lambda res : self . poll ( _node_has_started ) )
# now we can kill it. TODO: On a slow machine, the node might kill
# itself before we get a chance too, especially if spawning the
# 'tahoe stop' command takes a while.
def _stop ( res ) :
self . failUnless ( os . path . exists ( TWISTD_PID_FILE ) )
2009-01-24 01:34:37 +00:00
return utils . getProcessOutputAndValue ( bintahoe , args = [ " --quiet " , " stop " , c1 ] , env = os . environ )
2009-01-22 22:38:18 +00:00
d . addCallback ( _stop )
def _cb4 ( res ) :
out , err , rc_or_sig = res
2008-12-02 00:47:21 +00:00
# the parent has exited by now
2009-01-22 22:38:18 +00:00
errstr = " rc= %d , OUT: ' %s ' , ERR: ' %s ' " % ( rc_or_sig , out , err )
self . failUnlessEqual ( rc_or_sig , 0 , errstr )
self . failUnlessEqual ( out , " " , errstr )
2009-01-27 00:30:46 +00:00
# self.failUnlessEqual(err, "", errstr) # See test_client_no_noise -- for now we ignore noise.
2008-12-02 00:47:21 +00:00
# the parent was supposed to poll and wait until it sees
# twistd.pid go away before it exits, so twistd.pid should be
# gone by now.
self . failIf ( os . path . exists ( TWISTD_PID_FILE ) )
2009-01-22 22:38:18 +00:00
d . addCallback ( _cb4 )
2008-12-02 00:47:21 +00:00
return d