HEX
Server: Apache
System: Linux pdx1-shared-a1-38 6.6.104-grsec-jammy+ #3 SMP Tue Sep 16 00:28:11 UTC 2025 x86_64
User: mmickelson (3396398)
PHP: 8.1.31
Disabled: NONE
Upload Files
File: /home/mmickelson/trac_theflexguy_com_trac/trac/tests/functional/testenv.py
#!/usr/bin/python
"""Object for creating and destroying a Trac environment for testing purposes.
Provides some Trac environment-wide utility functions, and a way to call
trac-admin."""

import os
import time
import signal
import sys
import errno
import locale

from subprocess import call, Popen, PIPE
from trac.tests.functional.compat import rmtree, close_fds
from trac.tests.functional import logfile
from trac.tests.functional.better_twill import tc, ConnectError
from trac.env import open_environment

# TODO: refactor to support testing multiple frontends, backends (and maybe
# repositories and authentication).
# Frontends:
# tracd, ap2+mod_python, ap2+mod_wsgi, ap2+mod_fastcgi, ap2+cgi,
# lighty+fastcgi, lighty+cgi, cherrypy+wsgi
# Backends:
# sqlite2+pysqlite, sqlite3+pysqlite2, postgres python bindings #1,
# postgres python bindings #2, mysql with server v4, mysql with server v5
# (those need to test search escaping, among many other things like long
# paths in browser and unicode chars being allowed/translating...)
class FunctionalTestEnvironment(object):
    """Provides a way to work with a test environment in a simpler way."""
    # TODO: Need to see if we can remove the limitation that the tests have
    # to have the cwd be the top of the trac source tree... that limits the
    # places we can put the test environment data.

    def __init__(self, dirname, port, url):
        """A functional test environment requires a directory name in which
        to create the test repository and Trac environment, and a port
        number to use for the webserver."""
        self.url = url
        self.command_cwd = os.path.normpath(os.path.join(dirname, '..'))
        self.dirname = os.path.abspath(dirname)
        self.repodir = os.path.join(self.dirname, "repo")
        self.tracdir = os.path.join(self.dirname, "trac")
        self.htpasswd = os.path.join(self.dirname, "htpasswd")
        self.port = port
        self.pid = None
        self.destroy()
        self.create()
        locale.setlocale(locale.LC_ALL, '')

    def destroy(self):
        """Remove all of the test environment data."""
        if os.path.exists(self.dirname):
            rmtree(self.dirname)

    def create(self):
        """Create a new test environment; Trac, Subversion,
        authentication."""
        if os.mkdir(self.dirname):
            raise Exception('unable to create test environment')
        if call(["svnadmin", "create", self.repodir], stdout=logfile,
                stderr=logfile, close_fds=close_fds):
            raise Exception('unable to create subversion repository')
        self._tracadmin('initenv', 'testenv%s' % self.port,
                        'sqlite:db/trac.db', 'svn', self.repodir)
        if call([sys.executable, "./contrib/htpasswd.py", "-c", "-b",
                 self.htpasswd, "admin", "admin"], close_fds=close_fds,
                 cwd=self.command_cwd):
            raise Exception('Unable to setup admin password')
        self.adduser('user')
        self._tracadmin('permission', 'add', 'admin', 'TRAC_ADMIN')
        # Setup Trac logging
        env = self.get_trac_environment()
        env.config.set('logging', 'log_type', 'file')
        env.config.save()

    def adduser(self, user):
        """Add a user to the environment.  Password is the username."""
        if call([sys.executable, './contrib/htpasswd.py', '-b', self.htpasswd,
                 user, user], close_fds=close_fds, cwd=self.command_cwd):
            raise Exception('Unable to setup password for user "%s"' % user)

    def _tracadmin(self, *args):
        """Internal utility method for calling trac-admin"""
        retval = call([sys.executable, "./trac/admin/console.py", self.tracdir]
                      + list(args), stdout=logfile, stderr=logfile,
                      close_fds=close_fds, cwd=self.command_cwd)
        if retval:
            raise Exception('Failed with exitcode %s running trac-admin ' \
                            'with %r' % (retval, args))

    def start(self):
        """Starts the webserver"""
        if 'FIGLEAF' in os.environ:
            exe = os.environ['FIGLEAF']
        else:
            exe = sys.executable
        server = Popen([exe, "./trac/web/standalone.py",
                        "--port=%s" % self.port, "-s",
                        "--hostname=127.0.0.1",
                        "--basic-auth=trac,%s," % self.htpasswd,
                        self.tracdir],
                       stdout=logfile, stderr=logfile,
                       close_fds=close_fds,
                       cwd=self.command_cwd,
                      )
        self.pid = server.pid
        # Verify that the url is ok
        timeout = 30
        while timeout:
            try:
                tc.go(self.url)
                break
            except ConnectError:
                time.sleep(1)
            timeout -= 1
        else:
            raise Exception('Timed out waiting for server to start.')
        tc.url(self.url)

    def stop(self):
        """Stops the webserver"""
        if self.pid:
            if os.name == 'nt':
                # Untested
                call(["taskkill", "/f", "/pid", str(self.pid)],
                     stdin=PIPE, stdout=PIPE, stderr=PIPE)
            else:
                os.kill(self.pid, signal.SIGINT)
                try:
                    os.waitpid(self.pid, 0)
                except OSError, e:
                    if e.errno != errno.ESRCH:
                        raise

    def restart(self):
        """Restarts the webserver"""
        self.stop()
        self.start()

    def repo_url(self):
        """Returns the url of the Subversion repository for this test
        environment.
        """
        if os.name == 'nt':
            return 'file:///' + self.repodir.replace("\\", "/")
        else:
            return 'file://' + self.repodir

    def get_trac_environment(self):
        """Returns a Trac environment object"""
        return open_environment(self.tracdir, use_cache=True)