from __future__ import with_statement

import os
import sys
import subprocess
import signal
import time
import socket
import errno
import atexit

from os.path import join as pjoin


def waitForStartUp(process, pid, address, timeout=10):
    # connect to it, with a timeout in case something went wrong
    start = time.time()
    while time.time() < start + timeout:
        try:
            s = socket.create_connection(address)
            s.close()
            break
        except:
            time.sleep(0.1)
    else:
        # see if process is still alive
        process.poll()

        if pid and process.returncode is None:
            os.kill(pid, signal.SIGKILL)
        raise RuntimeError("Couldn't connect to server; aborting test")


class ProcessRunner(object):
    def setUp(self, *args, **kwargs):
        # clean up old.
        p = self.getPid()
        if p != None:
            try:
                # remember, process may already be dead.
                os.kill(p, 9)
                time.sleep(0.01)
            except:
                pass

    def tearDown(self, *args, **kwargs):
        spid = self.getPid()
        if spid:
            max_wait = 1
            os.kill(spid, signal.SIGTERM)
            slept = 0
            while (slept < max_wait):
                time.sleep(0.5)
                if not self.isAlive(spid):
                    if os.path.exists(self.pid_fname):
                        os.unlink(self.pid_fname)
                    break
                slept += 0.5
            if (slept > max_wait and self.isAlive(spid)):
                os.kill(spid, signal.SIGKILL)
                if os.path.exists(self.pid_fname):
                    os.unlink(self.pid_fname)
                raise Exception('Server did not shut down correctly')
        else:
            print 'Unable to locate pid file (%s)!' % self.pid_fname

    def isAlive(self, pid):
        try:
            os.kill(pid, 0)
            return 1
        except OSError, err:
            return err.errno == errno.EPERM

    def getPid(self):
        if self.process:
            return self.process.pid
        elif os.path.exists(self.pid_fname):
            return int(open(self.pid_fname, 'r').read())
        return None


class MockAPIServerRunner(ProcessRunner):
    def __init__(self, port=8881):
        self.port = port

    def setUp(self, *args, **kwargs):
        self.cwd = os.getcwd()
        self.process = None
        self.base_dir = pjoin(self.cwd)
        self.pid_fname = pjoin(self.cwd, 'mock_api_server.pid')
        self.log_path = pjoin(self.cwd, 'mock_api_server.log')

        super(MockAPIServerRunner, self).setUp(*args, **kwargs)
        script = pjoin(os.path.dirname(__file__), 'mock_http_server.py')

        with open(self.log_path, 'a+') as log_fp:
            args = '%s --port=%s' % (script, str(self.port))
            self.process = subprocess.Popen(args, shell=True,
                    cwd=self.base_dir, stdout=log_fp, stderr=log_fp)
            waitForStartUp(self.process, self.getPid(),
                           ('127.0.0.1', self.port), 10)
        atexit.register(self.tearDown)

@@ -206,13 +206,8 @@
 ess,
- pid,
  add
@@ -588,18 +588,22 @@
     if p
-id
+rocess
  and pro
@@ -643,35 +643,26 @@
     
-os.kill(pid, signal.SIGKILL
+process.terminate(
 )%0A  
@@ -812,1423 +812,116 @@
     
-# clean up old.%0A        p = self.getPid()%0A        if p != None:%0A            try:%0A                # remember, process may already be dead.%0A                os.kill(p, 9)%0A                time.sleep(0.01)%0A            except:%0A                pass%0A%0A    def tearDown(self, *args, **kwargs):%0A        spid = self.getPid()%0A        if spid:%0A            max_wait = 1%0A            os.kill(spid, signal.SIGTERM)%0A            slept = 0%0A            while (slept %3C max_wait):%0A                time.sleep(0.5)%0A                if not self.isAlive(spid):%0A                    if os.path.exists(self.pid_fname):%0A                        os.unlink(self.pid_fname)%0A                    break%0A                slept += 0.5%0A            if (slept %3E max_wait and self.isAlive(spid)):%0A                os.kill(spid, signal.SIGKILL)%0A                if os.path.exists(self.pid_fname):%0A                    os.unlink(self.pid_fname)%0A                raise Exception('Server did not shut down correctly')%0A        else:%0A            print 'Unable to locate pid file (%25s)!' %25 self.pid_fname%0A%0A    def isAlive(self, pid):%0A        try:%0A            os.kill(pid, 0)%0A            return 1%0A        except OSError, err:%0A            return err.errno == errno.EPERM%0A%0A    def getPid(self):%0A        if self.process:%0A            return self.process.pid%0A        elif os.path.exists(self.pid_fname):%0A            return int(open(self.pid_fname, 'r').read())%0A        return None
+pass%0A%0A    def tearDown(self, *args, **kwargs):%0A        if self.process:%0A            self.process.terminate()
 %0A%0A%0Ac
@@ -1163,72 +1163,8 @@
 wd)%0A
-        self.pid_fname = pjoin(self.cwd, 'mock_api_server.pid')%0A
     
@@ -1472,16 +1472,72 @@
 .port))%0A
+            args = %5Bscript, '--port=%25s' %25 (self.port)%5D%0A%0A
         
@@ -1588,11 +1588,12 @@
 ell=
-Tru
+Fals
 e,%0A 
@@ -1704,50 +1704,8 @@
 ess,
- self.getPid(),%0A                          
  ('1

Simplify mock api server runner and properly kill the spawned process.