From 71c62f8fcb823eb50fec2c8f560a460f58dc0e0e Mon Sep 17 00:00:00 2001
From: Brian Warner <warner@allmydata.com>
Date: Mon, 1 Dec 2008 17:47:21 -0700
Subject: [PATCH] #542 'tahoe create-key-generator': fix the .tac file this
 creates to be compatible with modern code, add a test

---
 src/allmydata/scripts/keygen.py   |  3 +-
 src/allmydata/test/test_runner.py | 77 +++++++++++++++++++++++++++++++
 2 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/src/allmydata/scripts/keygen.py b/src/allmydata/scripts/keygen.py
index ddc98b82..787ed271 100644
--- a/src/allmydata/scripts/keygen.py
+++ b/src/allmydata/scripts/keygen.py
@@ -14,7 +14,7 @@ keygen_tac = """
 from allmydata import key_generator
 from twisted.application import service
 
-k = key_generator.KeyGeneratorService(2048)
+k = key_generator.KeyGeneratorService(default_key_size=2048)
 #k.key_generator.verbose = False
 #k.key_generator.pool_size = 16
 #k.key_generator.pool_refresh_delay = 6
@@ -40,6 +40,7 @@ def create_key_generator(config, out=sys.stdout, err=sys.stderr):
     f = open(os.path.join(basedir, "tahoe-key-generator.tac"), "wb")
     f.write(keygen_tac)
     f.close()
+    return 0
 
 subCommands = [
     ["create-key-generator", None, CreateKeyGeneratorOptions, "Create a key generator service."],
diff --git a/src/allmydata/test/test_runner.py b/src/allmydata/test/test_runner.py
index 426163c0..6d694c59 100644
--- a/src/allmydata/test/test_runner.py
+++ b/src/allmydata/test/test_runner.py
@@ -312,4 +312,81 @@ class RunNode(unittest.TestCase, pollmixin.PollMixin):
         self.failUnless("does not look like a directory at all"
                         in err.getvalue(), err.getvalue())
 
+    def test_keygen(self):
+        if runtime.platformType == "win32":
+            # twistd on windows doesn't daemonize. cygwin works normally.
+            raise unittest.SkipTest("twistd does not fork under windows")
+        basedir = self.workdir("test_keygen")
+        c1 = os.path.join(basedir, "c1")
+        argv = ["--quiet", "create-key-generator", "--basedir", c1]
+        out,err = StringIO(), StringIO()
+        rc = runner.runner(argv, stdout=out, stderr=err)
+        self.failUnlessEqual(rc, 0)
+
+        TWISTD_PID_FILE = os.path.join(c1, "twistd.pid")
+
+        d = defer.succeed(None)
+        def _start(res):
+            argv = ["--quiet", "start", c1]
+            out,err = StringIO(), StringIO()
+            rc = runner.runner(argv, stdout=out, stderr=err)
+            outs = out.getvalue() ; errs = err.getvalue()
+            errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
+            self.failUnlessEqual(rc, 0, errstr)
+            self.failUnlessEqual(outs, "", errstr)
+            self.failUnlessEqual(errs, "", errstr)
+
+            # 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(_start)
+
+        KEYGEN_FURL_FILE = os.path.join(c1, "key_generator.furl")
+        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)
+            argv = ["--quiet", "restart", c1]
+            out,err = StringIO(), StringIO()
+            rc = runner.runner(argv, stdout=out, stderr=err)
+            outs = out.getvalue() ; errs = err.getvalue()
+            errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
+            self.failUnlessEqual(rc, 0, errstr)
+            self.failUnlessEqual(outs, "", errstr)
+            self.failUnlessEqual(errs, "", errstr)
+        d.addCallback(_started)
+
+        # 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))
+            argv = ["--quiet", "stop", c1]
+            out,err = StringIO(), StringIO()
+            rc = runner.runner(argv, stdout=out, stderr=err)
+            # the parent has exited by now
+            outs = out.getvalue() ; errs = err.getvalue()
+            errstr = "rc=%d, OUT: '%s', ERR: '%s'" % (rc, outs, errs)
+            self.failUnlessEqual(rc, 0, errstr)
+            self.failUnlessEqual(outs, "", errstr)
+            self.failUnlessEqual(errs, "", errstr)
+            # 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))
+        d.addCallback(_stop)
+        return d
-- 
2.45.2