📄 main.py
字号:
#!/usr/bin/env python## main.py: a shared, automated test suite for Subversion## Subversion is a tool for revision control.# See http://subversion.tigris.org for more information.## ====================================================================# Copyright (c) 2000-2004 CollabNet. All rights reserved.## This software is licensed as described in the file COPYING, which# you should have received as part of this distribution. The terms# are also available at http://subversion.tigris.org/license-1.html.# If newer versions of this license are posted there, you may use a# newer version instead, at your option.#######################################################################import sys # for argv[]import os # for popen2()import shutil # for rmtree()import reimport stat # for ST_MODEimport string # for atof()import copy # for deepcopy()import time # for time()import traceback # for print_exc()import getopttry: my_getopt = getopt.gnu_getoptexcept AttributeError: my_getopt = getopt.getoptfrom svntest import Failurefrom svntest import Skipfrom svntest import testcasefrom svntest import wc######################################################################## HOW TO USE THIS MODULE:## Write a new python script that## 1) imports this 'svntest' package## 2) contains a number of related 'test' routines. (Each test# routine should take no arguments, and return None on success# or throw a Failure exception on failure. Each test should# also contain a short docstring.)## 3) places all the tests into a list that begins with None.## 4) calls svntest.main.client_test() on the list.## Also, your tests will probably want to use some of the common# routines in the 'Utilities' section below.####################################################################### Global stuff### Grandfather in SVNTreeUnequal, which used to live here. If you're# ever feeling saucy, you could go through the testsuite and change# main.SVNTreeUnequal to test.SVNTreeUnequal.import treeSVNTreeUnequal = tree.SVNTreeUnequalclass SVNProcessTerminatedBySignal(Failure): "Exception raised if a spawned process segfaulted, aborted, etc." passclass SVNLineUnequal(Failure): "Exception raised if two lines are unequal" passclass SVNUnmatchedError(Failure): "Exception raised if an expected error is not found" passclass SVNCommitFailure(Failure): "Exception raised if a commit failed" passclass SVNRepositoryCopyFailure(Failure): "Exception raised if unable to copy a repository" passclass SVNRepositoryCreateFailure(Failure): "Exception raised if unable to create a repository" pass# Windows specificsif sys.platform == 'win32': windows = 1 file_scheme_prefix = 'file:///' _exe = '.exe'else: windows = 0 file_scheme_prefix = 'file://' _exe = ''# os.wait() specificstry: from os import wait platform_with_os_wait = 1except ImportError: platform_with_os_wait = 0# The locations of the svn, svnadmin and svnlook binaries, relative to# the only scripts that import this file right now (they live in ../).svn_binary = os.path.abspath('../../svn/svn' + _exe)svnadmin_binary = os.path.abspath('../../svnadmin/svnadmin' + _exe)svnlook_binary = os.path.abspath('../../svnlook/svnlook' + _exe)svnsync_binary = os.path.abspath('../../svnsync/svnsync' + _exe)svnversion_binary = os.path.abspath('../../svnversion/svnversion' + _exe)# Username and password used by the working copieswc_author = 'jrandom'wc_passwd = 'rayjandom'# Username and password used by the working copies for "second user"# scenarioswc_author2 = 'jconstant' # use the same password as wc_author# Global variable indicating if we want verbose output.verbose_mode = 0# Global variable indicating if we want test data cleaned up after successcleanup_mode = 0# Global URL to testing area. Default to ra_local, current working dir.test_area_url = file_scheme_prefix + os.path.abspath(os.getcwd())if windows == 1: test_area_url = string.replace(test_area_url, '\\', '/')# Global variable indicating the FS type for repository creations.fs_type = None# All temporary repositories and working copies are created underneath# this dir, so there's one point at which to mount, e.g., a ramdisk.work_dir = "svn-test-work"# Where we want all the repositories and working copies to live.# Each test will have its own!general_repo_dir = os.path.join(work_dir, "repositories")general_wc_dir = os.path.join(work_dir, "working_copies")# A relative path that will always point to latest repositorycurrent_repo_dir = Nonecurrent_repo_url = None# temp directory in which we will create our 'pristine' local# repository and other scratch data. This should be removed when we# quit and when we startup.temp_dir = os.path.join(work_dir, 'local_tmp')# (derivatives of the tmp dir.)pristine_dir = os.path.join(temp_dir, "repos")greek_dump_dir = os.path.join(temp_dir, "greekfiles")config_dir = os.path.abspath(os.path.join(temp_dir, "config"))default_config_dir = config_dir## Our pristine greek-tree state.## If a test wishes to create an "expected" working-copy tree, it should# call main.greek_state.copy(). That method will return a copy of this# State object which can then be edited.#_item = wc.StateItemgreek_state = wc.State('', { 'iota' : _item("This is the file 'iota'.\n"), 'A' : _item(), 'A/mu' : _item("This is the file 'mu'.\n"), 'A/B' : _item(), 'A/B/lambda' : _item("This is the file 'lambda'.\n"), 'A/B/E' : _item(), 'A/B/E/alpha' : _item("This is the file 'alpha'.\n"), 'A/B/E/beta' : _item("This is the file 'beta'.\n"), 'A/B/F' : _item(), 'A/C' : _item(), 'A/D' : _item(), 'A/D/gamma' : _item("This is the file 'gamma'.\n"), 'A/D/G' : _item(), 'A/D/G/pi' : _item("This is the file 'pi'.\n"), 'A/D/G/rho' : _item("This is the file 'rho'.\n"), 'A/D/G/tau' : _item("This is the file 'tau'.\n"), 'A/D/H' : _item(), 'A/D/H/chi' : _item("This is the file 'chi'.\n"), 'A/D/H/psi' : _item("This is the file 'psi'.\n"), 'A/D/H/omega' : _item("This is the file 'omega'.\n"), })####################################################################### Utilities shared by the testsdef get_admin_name(): "Return name of SVN administrative subdirectory." if (windows or sys.platform == 'cygwin') \ and os.environ.has_key('SVN_ASP_DOT_NET_HACK'): return '_svn' else: return '.svn'def get_start_commit_hook_path(repo_dir): "Return the path of the start-commit-hook conf file in REPO_DIR." return os.path.join(repo_dir, "hooks", "start-commit")def get_pre_commit_hook_path(repo_dir): "Return the path of the pre-commit-hook conf file in REPO_DIR." return os.path.join(repo_dir, "hooks", "pre-commit")def get_post_commit_hook_path(repo_dir): "Return the path of the post-commit-hook conf file in REPO_DIR." return os.path.join(repo_dir, "hooks", "post-commit")def get_pre_revprop_change_hook_path(repo_dir): "Return the path of the pre-revprop-change hook script in REPO_DIR." return os.path.join(repo_dir, "hooks", "pre-revprop-change")def get_svnserve_conf_file_path(repo_dir): "Return the path of the svnserve.conf file in REPO_DIR." return os.path.join(repo_dir, "conf", "svnserve.conf")# Run any binary, logging the command line (TODO: and return code)def run_command(command, error_expected, binary_mode=0, *varargs): """Run COMMAND with VARARGS; return stdout, stderr as lists of lines. If ERROR_EXPECTED is None, any stderr also will be printed.""" return run_command_stdin(command, error_expected, binary_mode, None, *varargs)# Run any binary, supplying input text, logging the command linedef run_command_stdin(command, error_expected, binary_mode=0, stdin_lines=None, *varargs): """Run COMMAND with VARARGS; input STDIN_LINES (a list of strings which should include newline characters) to program via stdin - this should not be very large, as if the program outputs more than the OS is willing to buffer, this will deadlock, with both Python and COMMAND waiting to write to each other for ever. Return stdout, stderr as lists of lines. If ERROR_EXPECTED is None, any stderr also will be printed.""" args = '' for arg in varargs: # build the command string arg = str(arg) if os.name != 'nt': arg = arg.replace('$', '\$') args = args + ' "' + arg + '"' # Log the command line if verbose_mode: print 'CMD:', os.path.basename(command) + args, if binary_mode: mode = 'b' else: mode = 't' start = time.time() infile, outfile, errfile = os.popen3(command + args, mode) if stdin_lines: map(infile.write, stdin_lines) infile.close() stdout_lines = outfile.readlines() stderr_lines = errfile.readlines() outfile.close() errfile.close() if platform_with_os_wait: pid, wait_code = os.wait() exit_code = int(wait_code / 256) exit_signal = wait_code % 256 if exit_signal != 0: raise SVNProcessTerminatedBySignal if verbose_mode: stop = time.time() print '<TIME = %.6f>' % (stop - start) if (not error_expected) and (stderr_lines): map(sys.stdout.write, stderr_lines) raise Failure return stdout_lines, stderr_linesdef set_config_dir(cfgdir): "Set the config directory." global config_dir config_dir = cfgdirdef reset_config_dir(): "Reset the config directory to the default value." global config_dir global default_config_dir config_dir = default_config_dirdef create_config_dir(cfgdir, config_contents = '#\n', server_contents = '#\n'): "Create config directories and files" # config file names cfgfile_cfg = os.path.join(cfgdir, 'config') cfgfile_srv = os.path.join(cfgdir, 'server') # create the directory if not os.path.isdir(cfgdir): os.makedirs(cfgdir) fd = open(cfgfile_cfg, 'w') fd.write(config_contents) fd.close() fd = open(cfgfile_srv, 'w') fd.write(server_contents) fd.close()# For running subversion and returning the outputdef run_svn(error_expected, *varargs): """Run svn with VARARGS; return stdout, stderr as lists of lines. If ERROR_EXPECTED is None, any stderr also will be printed. If you're just checking that something does/doesn't come out of stdout/stderr, you might want to use actions.run_and_verify_svn().""" global config_dir return run_command(svn_binary, error_expected, 0, *varargs + ('--config-dir', config_dir))# For running svnadmin. Ignores the output.def run_svnadmin(*varargs): "Run svnadmin with VARARGS, returns stdout, stderr as list of lines." return run_command(svnadmin_binary, 1, 0, *varargs)# For running svnlook. Ignores the output.def run_svnlook(*varargs): "Run svnlook with VARARGS, returns stdout, stderr as list of lines." return run_command(svnlook_binary, 1, 0, *varargs)def run_svnsync(*varargs): "Run svnsync with VARARGS, returns stdout, stderr as list of lines." return run_command(svnsync_binary, 1, 0, *varargs)def run_svnversion(*varargs): "Run svnversion with VARARGS, returns stdout, stderr as list of lines." return run_command(svnversion_binary, 1, 0, *varargs)# Chmod recursively on a whole subtreedef chmod_tree(path, mode, mask): def visit(arg, dirname, names): mode, mask = arg for name in names: fullname = os.path.join(dirname, name) if not os.path.islink(fullname): new_mode = (os.stat(fullname)[stat.ST_MODE] & ~mask) | mode os.chmod(fullname, new_mode) os.path.walk(path, visit, (mode, mask))# For clearing away working copiesdef safe_rmtree(dirname, retry=0): "Remove the tree at DIRNAME, making it writable first" def rmtree(dirname): chmod_tree(dirname, 0666, 0666) shutil.rmtree(dirname) if not os.path.exists(dirname): return if retry: for delay in (0.5, 1, 2, 4): try: rmtree(dirname) break except: time.sleep(delay) else: rmtree(dirname) else: rmtree(dirname)# For making local mods to filesdef file_append(path, new_text): "Append NEW_TEXT to file at PATH" fp = open(path, 'a') # open in (a)ppend mode fp.write(new_text) fp.close()# For making local mods to filesdef file_write(path, new_text): "Replace contents of file at PATH with NEW_TEXT" fp = open(path, 'w') # open in (w)rite mode fp.write(new_text) fp.close()# For creating blank new repositoriesdef create_repos(path): """Create a brand-new SVN repository at PATH. If PATH does not yet exist, create it.""" if not(os.path.exists(path)): os.makedirs(path) # this creates all the intermediate dirs, if neccessary opts = ("--bdb-txn-nosync",) if fs_type is not None: opts += ("--fs-type=" + fs_type,) stdout, stderr = run_command(svnadmin_binary, 1, 0, "create", path, *opts) # Skip tests if we can't create the repository. if stderr: for line in stderr: if line.find('Unknown FS type') != -1: raise Skip # If the FS type is known, assume the repos couldn't be created # (e.g. due to a missing 'svnadmin' binary). raise SVNRepositoryCreateFailure("".join(stderr).rstrip()) # Allow unauthenticated users to write to the repos, for ra_svn testing. file_append(os.path.join(path, "conf", "svnserve.conf"), "[general]\nauth-access = write\npassword-db = passwd\n"); file_append(os.path.join(path, "conf", "passwd"), "[users]\njrandom = rayjandom\njconstant = rayjandom\n"); # make the repos world-writeable, for mod_dav_svn's sake.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -