Author: ivan
Date: Tue Jun 23 13:33:58 2026
New Revision: 1935586
Log:
On 'xml-schema-validation-improvements' branch:
Always use installed lxml and rnc2rng Python packages to validate XML output
of `svn --xml` in tests.
This change also makes these package mandatory for running tests unless new
option `--disable-xml-schema-validation` is specified.
* build/run_tests.py
(_init_py_tests): Remove `--python-venv`. Add
`--disable-xml-schema-validation`. Do not download Python packages and
do not update PYTHONPATH environment variable.
(create_parser): Remove `--python-venv`. Add
`--disable-xml-schema-validation`.
* Makefile.in
(check): Remove PYTHON_VENV argument handling. Add
DISABLE_XML_SCHEMA_VALIDATION.
* subversion/tests/cmdline/log_tests.py
(is_ra_local_and_is_bad_xml_fatal): Remove.
(log_with_merge_history_and_search, log_xml_with_merge_history): Use
is_xml_schema_validation_enabled() instead of is_bad_xml_fatal().
* subversion/tests/cmdline/prop_tests.py
(xml_unsafe_author2): Use is_xml_schema_validation_enabled() instead of
is_bad_xml_fatal().
* subversion/tests/cmdline/svntest/main.py
(): Do not import venv package.
(venv_create, venv_base, found_dependencies, SVN_TESTS_REQUIRE,
SVN_TESTS_DEPEND): Remove.
(is_bad_xml_fatal): Remove.
(is_xml_schema_validation_enabled): New.
(TestSpawningThread.run_one): Remove options.venv_base handling. Handle
options.disable_xml_schema_validation.
(_create_parser): Remove `--python-venv`. Add
`--disable-xml-schema-validation`.
(parse_options): Remove options.venv_base handling.
(_get_purelib_dir, ensure_dependencies, create_python_venv): Remove.
(execute_tests): Do not call ensure_dependencies().
* subversion/tests/cmdline/svntest/verify.py
(validate_xml_schema): Do not nothing if XML schema validation is disabled.
Consider XML schema validation errors as test failure.
Modified:
subversion/branches/xml-schema-validation-improvements/Makefile.in
subversion/branches/xml-schema-validation-improvements/build/run_tests.py
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/log_tests.py
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/prop_tests.py
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/main.py
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/verify.py
Modified: subversion/branches/xml-schema-validation-improvements/Makefile.in
==============================================================================
--- subversion/branches/xml-schema-validation-improvements/Makefile.in Tue Jun
23 12:54:08 2026 (r1935585)
+++ subversion/branches/xml-schema-validation-improvements/Makefile.in Tue Jun
23 13:33:58 2026 (r1935586)
@@ -642,9 +642,6 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
if test "$(SVN_BIN_DIR)" != ""; then \
flags="--bin $(SVN_BIN_DIR) $$flags"; \
fi; \
- if test "$(PYTHON_VENV)" != ""; then \
- flags="--python-venv $(PYTHON_VENV) $$flags"; \
- fi; \
if test "$(STORE_PRISTINE)" != ""; then \
flags="--store-pristine $(STORE_PRISTINE) $$flags"; \
fi; \
@@ -654,6 +651,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
if test "$(VALGRIND_OPTS)" != ""; then \
flags="--valgrind-opts $(VALGRIND_OPTS) $$flags"; \
fi; \
+ if test "$(DISABLE_XML_SCHEMA_VALIDATION)" != ""; then \
+ flags="--disable-xml-schema-validation $$flags"; \
+ fi; \
LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)' \
$(PYTHON) $(top_srcdir)/build/run_tests.py \
--config-file $(top_srcdir)/subversion/tests/tests.conf \
Modified:
subversion/branches/xml-schema-validation-improvements/build/run_tests.py
==============================================================================
--- subversion/branches/xml-schema-validation-improvements/build/run_tests.py
Tue Jun 23 12:54:08 2026 (r1935585)
+++ subversion/branches/xml-schema-validation-improvements/build/run_tests.py
Tue Jun 23 13:33:58 2026 (r1935586)
@@ -259,8 +259,6 @@ class TestHarness:
cmdline.append('--tools-bin=%s' % self.opts.tools_bin)
if self.opts.svn_bin is not None:
cmdline.append('--bin=%s' % self.opts.svn_bin)
- if self.opts.venv_base is not None:
- cmdline.append('--python-venv=%s' % self.opts.venv_base)
if self.opts.url is not None:
cmdline.append('--url=%s' % self.opts.url)
if self.opts.fs_type is not None:
@@ -317,6 +315,8 @@ class TestHarness:
cmdline.append('--valgrind=%s' % self.opts.valgrind)
if self.opts.valgrind_opts is not None:
cmdline.append('--valgrind-opts=%s' % self.opts.valgrind_opts)
+ if self.opts.disable_xml_schema_validation is not None:
+ cmdline.append('--disable-xml-schema-validation')
self.py_test_cmdline = cmdline
@@ -330,15 +330,6 @@ class TestHarness:
svntest = importlib.import_module('svntest')
svntest.main.parse_options(cmdline, optparse.SUPPRESS_USAGE)
svntest.testcase.TextColors.disable()
- dependency_path = svntest.main.ensure_dependencies()
-
- # We have to update PYTHONPATH, otherwise the whole setting up of a
- # virtualenv and installing dependencies will happen for every test case.
- if dependency_path:
- python_path = os.environ.get("PYTHONPATH")
- python_path = (dependency_path if not python_path
- else "%s:%s" % (dependency_path, python_path))
- os.environ["PYTHONPATH"] = python_path
finally:
os.chdir(old_cwd)
@@ -1041,9 +1032,6 @@ def create_parser():
help='Use the svn binaries installed in this path')
parser.add_option('--tools-bin', action='store', dest='tools_bin',
help='Use the svn tools installed in this path')
- parser.add_option('--python-venv', action='store', dest='venv_base',
- help=('Use the virtual environment inside this path to'
- ' find the dependencies used by the test suite.'))
parser.add_option('--fsfs-sharding', action='store', type='int',
help='Default shard size (for fsfs)')
parser.add_option('--fsfs-packing', action='store_true',
@@ -1103,6 +1091,8 @@ def create_parser():
help='programs to run under valgrind')
parser.add_option('--valgrind-opts', action='store',
help='options to pass valgrind')
+ parser.add_option('--disable-xml-schema-validation', action='store_true',
+ help='Disable extended XML schema validation')
parser.set_defaults(set_log_level=None)
return parser
Modified:
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/log_tests.py
==============================================================================
---
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/log_tests.py
Tue Jun 23 12:54:08 2026 (r1935585)
+++
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/log_tests.py
Tue Jun 23 13:33:58 2026 (r1935586)
@@ -2778,7 +2778,7 @@ def log_on_deleted_deep(sbox):
'',
'-q', '-c', '1-2')
-@XFail(svntest.main.is_bad_xml_fatal)
+@XFail(svntest.main.is_xml_schema_validation_enabled)
@Issue(4711)
def log_with_merge_history_and_search(sbox):
"log --use-merge-history --search"
@@ -2805,10 +2805,8 @@ def log_with_merge_history_and_search(sb
svntest.verify.validate_xml_schema('log', output)
-def is_ra_local_and_is_bad_xml_fatal():
- return svntest.main.is_ra_type_file() and svntest.main.is_bad_xml_fatal()
-
-@XFail(is_ra_local_and_is_bad_xml_fatal)
+@XFail(lambda: (svntest.main.is_xml_schema_validation_enabled()
+ and svntest.main.is_ra_type_file()))
@Issue(4856)
def log_xml_with_merge_history(sbox):
"log --use-merge-history --xml"
Modified:
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/prop_tests.py
==============================================================================
---
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/prop_tests.py
Tue Jun 23 12:54:08 2026 (r1935585)
+++
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/prop_tests.py
Tue Jun 23 13:33:58 2026 (r1935586)
@@ -2641,7 +2641,7 @@ def xml_unsafe_author(sbox):
@Issue(4415)
@Issue(4919)
-@XFail(lambda: (svntest.main.is_bad_xml_fatal()
+@XFail(lambda: (svntest.main.is_xml_schema_validation_enabled()
and not svntest.main.is_ra_type_dav()))
def xml_unsafe_author2(sbox):
"svn:author with XML unsafe chars 2"
Modified:
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/main.py
==============================================================================
---
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/main.py
Tue Jun 23 12:54:08 2026 (r1935585)
+++
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/main.py
Tue Jun 23 13:33:58 2026 (r1935586)
@@ -41,13 +41,6 @@ import zipfile
import codecs
import queue
-# Even though 'venv' is part of the Python3 standard library,
-# some environment don't provide it. The tests do not require it.
-try:
- import venv
-except ImportError:
- venv = None
-
from urllib.parse import quote as urllib_parse_quote
from urllib.parse import unquote as urllib_parse_unquote
from urllib.parse import urlparse
@@ -127,13 +120,11 @@ class SVNRepositoryCreateFailure(Failure
if sys.platform == 'win32':
windows = True
file_scheme_prefix = 'file:///'
- venv_bin = 'Scripts'
_exe = '.exe'
_bat = '.bat'
os.environ['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y'
else:
windows = False
- venv_bin = 'bin'
file_scheme_prefix = 'file://'
_exe = ''
_bat = ''
@@ -227,18 +218,6 @@ options = None
# this dir, so there's one point at which to mount, e.g., a ramdisk.
work_dir = "svn-test-work"
-# Directory for the Python virtual environment where we install
-# external dependencies of the test environment
-venv_create = venv is not None
-venv_base = work_dir
-def venv_path():
- return os.path.join(venv_base, "__venv__")
-
-# List of dependencies
-found_dependencies = set()
-SVN_TESTS_REQUIRE = ["lxml==6.1.0", "rnc2rng==2.7.0"] # for pip
-SVN_TESTS_DEPEND = ["lxml", "rnc2rng"] # for install_module
-
# Constant for the merge info property.
SVN_PROP_MERGEINFO = "svn:mergeinfo"
@@ -1764,12 +1743,8 @@ def is_httpd_authz_provider_enabled():
def is_remote_http_connection_allowed():
return options.allow_remote_http_connection
-# XML schema validation
-def is_bad_xml_fatal():
- """Are we treating invalid XML output as a fatal error?"""
- # Only if we have all the necessary dependencies.
- depends = {'lxml', 'rnc2rng'}
- return depends == (depends & found_dependencies)
+def is_xml_schema_validation_enabled():
+ return not options.disable_xml_schema_validation
def wc_format(ver=None):
@@ -1875,14 +1850,14 @@ class TestSpawningThread(threading.Threa
args.append('--allow-remote-http-connection')
if options.svn_bin:
args.append('--bin=' + options.svn_bin)
- if options.venv_base:
- args.append('--python-venv=' + options.venv_base)
if options.store_pristine:
args.append('--store-pristine=' + options.store_pristine)
if options.valgrind:
args.append('--valgrind=' + options.valgrind)
if options.valgrind_opts:
args.append('--valgrind-opts=' + options.valgrind_opts)
+ if options.disable_xml_schema_validation:
+ args.append('--disable-xml-schema-validation')
result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None,
*args)
@@ -2251,9 +2226,6 @@ def _create_parser(usage=None):
help='Whether to clean up')
parser.add_option('--enable-sasl', action='store_true',
help='Whether to enable SASL authentication')
- parser.add_option('--python-venv', action='store', dest='venv_base',
- help=('Use the virtual environment inside this path to'
- ' find the dependencies used by the test suite.'))
parser.add_option('--bin', action='store', dest='svn_bin',
help='Use the svn binaries installed in this path')
parser.add_option('--use-jsvn', action='store_true',
@@ -2330,6 +2302,8 @@ def _create_parser(usage=None):
help='programs to run under valgrind')
parser.add_option('--valgrind-opts', action='store',
help='options to pass to valgrind')
+ parser.add_option('--disable-xml-schema-validation', action='store_true',
+ help='Disable extended XML schema validation')
# most of the defaults are None, but some are other values, set them here
parser.set_defaults(
@@ -2360,8 +2334,6 @@ def parse_options(arglist=sys.argv[1:],
"""Parse the arguments in arg_list, and set the global options object with
the results"""
- global venv_base
- global venv_create
global options
parser = _create_parser(usage)
@@ -2411,10 +2383,6 @@ def parse_options(arglist=sys.argv[1:],
svn_wc__max_supported_format_version(),
options.wc_format_version))
- if options.venv_base:
- venv_base = options.venv_base
- venv_create = False
-
return (parser, args)
def tweak_options_for_precooked_repos():
@@ -2447,80 +2415,6 @@ def run_tests(test_list, serial_only = F
sys.exit(execute_tests(test_list, serial_only))
-def _get_purelib_dir(venv_dir):
- if sys.platform == 'win32':
- return os.path.join(venv_dir, "Lib", "site-packages")
- else:
- return os.path.join(venv_dir, "lib", "python%d.%d" % sys.version_info[:2],
- "site-packages")
-
-def ensure_dependencies():
- """Install the dependencies we need for running the tests.
-
- NOTE: this function des not handle the case where the Python
- version has changed. In theory, we could automagically
- upgrade the venv in that case. In practice, we won't.
- """
-
- venv_dir = os.path.abspath(venv_path())
- package_path = _get_purelib_dir(venv_dir)
-
- # Check if all our dependencies are installed. It doesn't matter if
- # they're installed in our venv, as long as they're available.
- found_dependencies.clear()
- saved_sys_path = sys.path[:]
- try:
- sys.path.insert(0, package_path)
- for package in SVN_TESTS_DEPEND:
- importlib.import_module(package)
- found_dependencies.add(package)
- have_required = True
- except ImportError:
- have_required = False
- finally:
- sys.path[:] = saved_sys_path
-
- if have_required:
- if package_path not in sys.path:
- sys.path.append(package_path)
- return package_path
-
- if venv_create:
- python_prog, python_path = create_python_venv(venv_dir)
- if python_prog is not None:
- assert python_path == package_path
- if package_path not in sys.path:
- sys.path.append(package_path)
- found_dependencies.update(set(SVN_TESTS_DEPEND))
- return package_path
- return None
-
-def create_python_venv(venv_dir, quiet=False):
- # We should never get this far if the 'venv' module isn't available.
- assert venv is not None
-
- try:
- # Create the virtual environment
- if not os.path.isdir(venv_dir):
- if os.path.exists(venv_dir):
- safe_rmtree(venv_dir)
- venv.create(venv_dir, with_pip=True)
-
- # Install the dependencies
- pip = os.path.join(venv_dir, venv_bin, "pip" + _exe)
- pip_options = ("--disable-pip-version-check", "--require-virtualenv")
- subprocess.run([pip, *pip_options, "install", *SVN_TESTS_REQUIRE],
- check=True, stdout=subprocess.PIPE if quiet else None)
- importlib.invalidate_caches()
-
- python_prog = os.path.join(venv_dir, venv_bin, "python" + _exe)
- python_path = _get_purelib_dir(venv_dir)
- return python_prog, python_path
- except Exception:
- if logger:
- logger.warning('Could not install test dependencies', exc_info=True)
- return None, None
-
def get_issue_details(issue_numbers):
"""For each issue number in ISSUE_NUMBERS query the issue
tracker and determine what the target milestone is and
@@ -2719,10 +2613,6 @@ def execute_tests(test_list, serial_only
wc_incomplete_tester_binary = os.path.join(options.tools_bin,
'wc-incomplete-tester' + _exe)
- assert options.venv_base is None or venv_base == options.venv_base, \
- 'venv_base=%s options.venv_base=%s' % (venv_base, options.venv_base)
- ensure_dependencies()
-
######################################################################
# Cleanup: if a previous run crashed or interrupted the python
Modified:
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/verify.py
==============================================================================
---
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/verify.py
Tue Jun 23 12:54:08 2026 (r1935585)
+++
subversion/branches/xml-schema-validation-improvements/subversion/tests/cmdline/svntest/verify.py
Tue Jun 23 13:33:58 2026 (r1935586)
@@ -1053,9 +1053,12 @@ __schema_dir = os.path.join(
os.path.abspath(__file__))))),
"svn", "schema")
def validate_xml_schema(name: str, lines: Iterable[str]) -> None:
+ if not svntest.main.is_xml_schema_validation_enabled():
+ logger.debug("XML schema validation is disabled.")
+ return
+
schema_name = name + ".rnc"
try:
- # Imported in this scope because sys.path may not have been updated yet.
from lxml import etree #type:ignore
schema_file = os.path.join(__schema_dir, schema_name)
schema = etree.RelaxNG(file=schema_file)
@@ -1065,11 +1068,8 @@ def validate_xml_schema(name: str, lines
raise SVNXMLSchemaValidationError(schema.error_log)
except ImportError:
logger.error("XML: Module lxml.etree not found")
- return
+ raise svntest.Failure
except Exception as ex:
logger.error("XML: " + str(ex))
logger.warning("XML:\n" + "\n".join(repr(line) for line in lines))
- if svntest.main.is_bad_xml_fatal():
- raise
- else:
- logger.warning("XML:", exc_info=True)
+ raise