# Path: src/petmail/web.py
# class SampleError(Exception):
#     pass
# 
# Path: src/petmail/test/common.py
# class BasedirMixin:
#     def make_basedir(self):
#         # TestCase.mktemp() creates _trial_temp/MODULE/CLASS/TEST/RANDOM and
#         # returns join(that,"temp"). We just want the part that ends with
#         # TEST. So we rmdir the RANDOM and return .../TEST
#         basedir = self.mktemp()
#         random = os.path.dirname(basedir)
#         os.rmdir(random)
#         test = os.path.dirname(random)
#         return test
# 
# class NodeRunnerMixin:
#     def setUp(self):
#         self.sparent = service.MultiService()
#         self.sparent.startService()
#         d = allocate_port()
#         def _allocated(port):
#             p = "tcp:%d:interface=127.0.0.1" % port
#             r = RelayServer(p, None, wormhole.__version__)
#             r.setServiceParent(self.sparent)
#             self.relay_url = "http://127.0.0.1:%d/wormhole-relay/" % port
#         d.addCallback(_allocated)
#         return d
# 
#     def tearDown(self):
#         return self.sparent.stopService()
# 
#     def createNode(self, basedir, type="agent", local_mailbox=True):
#         so = runner.CreateNodeOptions()
#         args = []
#         if local_mailbox:
#             args.append("--local-mailbox")
#         args.extend(["--relay-url", self.relay_url])
#         args.append(basedir)
#         so.parseOptions(args)
#         out,err = StringIO(), StringIO()
#         rc = create_node(so, out, err, [type])
#         self.failUnlessEqual(rc, 0, (rc, out, err))
#         return rc, out ,err
# 
#     def buildNode(self, basedir):
#         so = runner.StartNodeOptions()
#         so.parseOptions([basedir])
#         p = startstop.MyPlugin(basedir, os.path.join(basedir, "petmail.db"))
#         n = p.makeService(so)
#         return n
# 
#     def startNode(self, basedir):
#         n = self.buildNode(basedir)
#         n.setServiceParent(self.sparent)
#         return n
# 
# class CLIinThreadMixin:
#     def cli(self, *args, **kwargs):
#         stdout, stderr = StringIO(), StringIO()
#         d = threads.deferToThread(runner.run, list(args), stdout, stderr,
#                                   kwargs.get("petmail"))
#         def _done(rc):
#             return stdout.getvalue(), stderr.getvalue(), rc
#         d.addCallback(_done)
#         return d
#     def mustSucceed(self, (out, err, rc)):
#         if rc != 0:
#             self.fail("rc=%s out='%s' err='%s'" % (rc, out, err))
#         self.stderr = err
#         return out
# 
#     def cliMustSucceed(self, *args, **kwargs):
#         d = self.cli(*args, **kwargs)
#         d.addCallback(self.mustSucceed)
#         return d
# 
# class CLIinProcessMixin(CLIinThreadMixin):
#     def cli(self, *args, **kwargs):
#         d = getProcessOutputAndValue(sys.executable,
#                                      ["-m", "petmail.scripts.runner"] + list(args),
#                                      os.environ)
#         return d
# 
#     def anyways(self, res, cb, *args, **kwargs):
#         # always run the cleanup callback
#         d = defer.maybeDeferred(cb, *args, **kwargs)
#         if isinstance(res, failure.Failure):
#             # let the original failure passthrough
#             d.addBoth(lambda _: res)
#         # otherwise the original result was success, so just return the
#         # cleanup result
#         return d


import os
from twisted.trial import unittest
from ..web import SampleError
from .common import (BasedirMixin, NodeRunnerMixin,
                     CLIinThreadMixin, CLIinProcessMixin)

# most tests will just do Node.startService and invoke CLI commands by
# talking directly to the web handler: no network, no other processes.

# To cover the HTTP interface, we need a few tests which run the CLI command
# with deferToThread (to handle the time.sleep and blocking IO). These use
# CLIinThreadMixin.

# And we need one or two tests that exercise the daemonization in 'petmail
# start', which requires a subprocess. Those use CLIinProcessMixin

class Run(CLIinProcessMixin, BasedirMixin, unittest.TestCase):

    def test_node(self):
        basedir = os.path.join(self.make_basedir(), "node1")
        d = self.cliMustSucceed("create-node", basedir)
        d.addCallback(lambda _: self.cliMustSucceed("start", basedir))
        d.addCallback(lambda _: self.cliMustSucceed("open", "-n", "-d",basedir))
        def _check_url(out):
            self.failUnlessSubstring("Node appears to be running, opening browser", out)
            self.failUnlessSubstring("Please open: http://localhost:", out)
            self.failUnlessSubstring("/open-control?opener-token=", out)
        d.addCallback(_check_url)
        d.addBoth(self.anyways, self.cliMustSucceed, "stop", basedir)
        return d


# Path: src/petmail/web.py
# class SampleError(Exception):
#     pass
# 
# Path: src/petmail/test/common.py
# class BasedirMixin:
#     def make_basedir(self):
#         # TestCase.mktemp() creates _trial_temp/MODULE/CLASS/TEST/RANDOM and
#         # returns join(that,"temp"). We just want the part that ends with
#         # TEST. So we rmdir the RANDOM and return .../TEST
#         basedir = self.mktemp()
#         random = os.path.dirname(basedir)
#         os.rmdir(random)
#         test = os.path.dirname(random)
#         return test
# 
# class NodeRunnerMixin:
#     def setUp(self):
#         self.sparent = service.MultiService()
#         self.sparent.startService()
#         d = allocate_port()
#         def _allocated(port):
#             p = "tcp:%d:interface=127.0.0.1" % port
#             r = RelayServer(p, None, wormhole.__version__)
#             r.setServiceParent(self.sparent)
#             self.relay_url = "http://127.0.0.1:%d/wormhole-relay/" % port
#         d.addCallback(_allocated)
#         return d
# 
#     def tearDown(self):
#         return self.sparent.stopService()
# 
#     def createNode(self, basedir, type="agent", local_mailbox=True):
#         so = runner.CreateNodeOptions()
#         args = []
#         if local_mailbox:
#             args.append("--local-mailbox")
#         args.extend(["--relay-url", self.relay_url])
#         args.append(basedir)
#         so.parseOptions(args)
#         out,err = StringIO(), StringIO()
#         rc = create_node(so, out, err, [type])
#         self.failUnlessEqual(rc, 0, (rc, out, err))
#         return rc, out ,err
# 
#     def buildNode(self, basedir):
#         so = runner.StartNodeOptions()
#         so.parseOptions([basedir])
#         p = startstop.MyPlugin(basedir, os.path.join(basedir, "petmail.db"))
#         n = p.makeService(so)
#         return n
# 
#     def startNode(self, basedir):
#         n = self.buildNode(basedir)
#         n.setServiceParent(self.sparent)
#         return n
# 
# class CLIinThreadMixin:
#     def cli(self, *args, **kwargs):
#         stdout, stderr = StringIO(), StringIO()
#         d = threads.deferToThread(runner.run, list(args), stdout, stderr,
#                                   kwargs.get("petmail"))
#         def _done(rc):
#             return stdout.getvalue(), stderr.getvalue(), rc
#         d.addCallback(_done)
#         return d
#     def mustSucceed(self, (out, err, rc)):
#         if rc != 0:
#             self.fail("rc=%s out='%s' err='%s'" % (rc, out, err))
#         self.stderr = err
#         return out
# 
#     def cliMustSucceed(self, *args, **kwargs):
#         d = self.cli(*args, **kwargs)
#         d.addCallback(self.mustSucceed)
#         return d
# 
# class CLIinProcessMixin(CLIinThreadMixin):
#     def cli(self, *args, **kwargs):
#         d = getProcessOutputAndValue(sys.executable,
#                                      ["-m", "petmail.scripts.runner"] + list(args),
#                                      os.environ)
#         return d
# 
#     def anyways(self, res, cb, *args, **kwargs):
#         # always run the cleanup callback
#         d = defer.maybeDeferred(cb, *args, **kwargs)
#         if isinstance(res, failure.Failure):
#             # let the original failure passthrough
#             d.addBoth(lambda _: res)
#         # otherwise the original result was success, so just return the
#         # cleanup result
#         return d


# Path: src/petmail/test/test_node.py
import os
from twisted.trial import unittest
from ..web import SampleError
from .common import (BasedirMixin, NodeRunnerMixin,
                     CLIinThreadMixin, CLIinProcessMixin)


# most tests will just do Node.startService and invoke CLI commands by
# talking directly to the web handler: no network, no other processes.

# To cover the HTTP interface, we need a few tests which run the CLI command
# with deferToThread (to handle the time.sleep and blocking IO). These use
# CLIinThreadMixin.

# And we need one or two tests that exercise the daemonization in 'petmail
# start', which requires a subprocess. Those use CLIinProcessMixin

class Run(CLIinProcessMixin, BasedirMixin, unittest.TestCase):

    def test_node(self):
        basedir = os.path.join(self.make_basedir(), "node1")
        d = self.cliMustSucceed("create-node", basedir)
        d.addCallback(lambda _: self.cliMustSucceed("start", basedir))
        d.addCallback(lambda _: self.cliMustSucceed("open", "-n", "-d",basedir))
        def _check_url(out):
            self.failUnlessSubstring("Node appears to be running, opening browser", out)
            self.failUnlessSubstring("Please open: http://localhost:", out)
            self.failUnlessSubstring("/open-control?opener-token=", out)
        d.addCallback(_check_url)
        d.addBoth(self.anyways, self.cliMustSucceed, "stop", basedir)
        return d


class CLI(CLIinThreadMixin, BasedirMixin, NodeRunnerMixin, unittest.TestCase):