Author: philip
Date: Mon Mar 20 01:22:52 2023
New Revision: 1908546

URL: http://svn.apache.org/viewvc?rev=1908546&view=rev
Log:
Add suport for running valgrind during 'make check'.

* Makefile.in (check): Add options.

* build/run_tests.py
  (_init_c_tests, _init_py_tests): Add options.
  (_maybe_prepend_valgrind): New.
  (_run_c_test): Prepend valgrind.
  (create_parser): Add options.

* subversion/tests/cmdline/svntest/main.py
  (libtool_script): New variable.
  (open_pipe): Prepend valgrind.
  (TestSpawningThread): Add options.
  (_create_parser): Add options.

* subversion/tests/README: Describe valgrind testing..

Modified:
    subversion/trunk/Makefile.in
    subversion/trunk/build/run_tests.py
    subversion/trunk/subversion/tests/README
    subversion/trunk/subversion/tests/cmdline/svntest/main.py

Modified: subversion/trunk/Makefile.in
URL: 
http://svn.apache.org/viewvc/subversion/trunk/Makefile.in?rev=1908546&r1=1908545&r2=1908546&view=diff
==============================================================================
--- subversion/trunk/Makefile.in (original)
+++ subversion/trunk/Makefile.in Mon Mar 20 01:22:52 2023
@@ -632,6 +632,12 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $
          if test "$(STORE_PRISTINE)" != ""; then                            \
            flags="--store-pristine $(STORE_PRISTINE) $$flags";              \
          fi;                                                                \
+         if test "$(VALGRIND)" != ""; then                                  \
+           flags="--valgrind $(VALGRIND) $$flags";                          \
+         fi;                                                                \
+         if test "$(VALGRIND_OPTS)" != ""; then                             \
+           flags="--valgrind-opts $(VALGRIND_OPTS) $$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/trunk/build/run_tests.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/build/run_tests.py?rev=1908546&r1=1908545&r2=1908546&view=diff
==============================================================================
--- subversion/trunk/build/run_tests.py (original)
+++ subversion/trunk/build/run_tests.py Mon Mar 20 01:22:52 2023
@@ -266,6 +266,10 @@ class TestHarness:
       cmdline.append('--parallel')
     if self.opts.store_pristine is not None:
       cmdline.append('--store-pristine=%s' % self.opts.store_pristine)
+    if self.opts.valgrind is not None:
+      cmdline.append('--valgrind=%s' % self.opts.valgrind)
+    if self.opts.valgrind_opts is not None:
+      cmdline.append('--valgrind-opts=%s' % self.opts.valgrind_opts)
 
     self.c_test_cmdline = cmdline
 
@@ -335,6 +339,10 @@ class TestHarness:
       cmdline.append('--allow-remote-http-connection')
     if self.opts.store_pristine is not None:
       cmdline.append('--store-pristine=%s' % self.opts.store_pristine)
+    if self.opts.valgrind is not None:
+      cmdline.append('--valgrind=%s' % self.opts.valgrind)
+    if self.opts.valgrind_opts is not None:
+      cmdline.append('--valgrind-opts=%s' % self.opts.valgrind_opts)
 
     self.py_test_cmdline = cmdline
 
@@ -814,6 +822,17 @@ class TestHarness:
         log.write('FAIL:  %s: Unknown test failure (%s).\n'
                   % (progbase, test_failed))
 
+  def _maybe_prepend_valgrind(self, cmdline, progbase):
+    if self.opts.valgrind:
+      if (progbase in self.opts.valgrind.split(',')
+          or 'C' in self.opts.valgrind.split(',')):
+        valgrind = [os.path.join(self.builddir, 'libtool'), '--mode=execute',
+                    'valgrind', '--quiet', '--error-exitcode=1']
+        if self.opts.valgrind_opts:
+          valgrind += self.opts.valgrind_opts.split(' ')
+        cmdline = valgrind + cmdline
+    return cmdline
+
   def _run_c_test(self, progabs, progdir, progbase, test_nums, dot_count):
     'Run a c test, escaping parameters as required.'
     if self.opts.list_tests and self.opts.milestone_filter:
@@ -849,6 +868,7 @@ class TestHarness:
       self.dots_written = dots
 
     tests_completed = 0
+    cmdline = self._maybe_prepend_valgrind(cmdline, progbase)
     with Popen(cmdline, stdout=subprocess.PIPE, stderr=self.log) as prog:
       line = prog.stdout.readline()
       while line:
@@ -1095,6 +1115,10 @@ def create_parser():
                     help='Run tests that connect to remote HTTP(S) servers')
   parser.add_option('--store-pristine', action='store', type='str',
                     help='Set the WC pristine mode')
+  parser.add_option('--valgrind', action='store',
+                    help='programs to run under valgrind')
+  parser.add_option('--valgrind-opts', action='store',
+                    help='options to pass valgrind')
 
   parser.set_defaults(set_log_level=None)
   return parser

Modified: subversion/trunk/subversion/tests/README
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/README?rev=1908546&r1=1908545&r2=1908546&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/README (original)
+++ subversion/trunk/subversion/tests/README Mon Mar 20 01:22:52 2023
@@ -261,6 +261,72 @@ Testing Over DAV
 Please see subversion/tests/cmdline/README for how to run the
 command-line client test suite against a remote repository.
 
+
+Testing with valgrind
+---------------------
+
+The test suite has support for valgrind. For this to be useful
+Subversion must be compiled with pool debugging enabled by
+adding -DAPR_POOL_DEBUG to CFLAGS. It is sufficient to compile
+just Subversion with pool debugging but compiling apr, apr-util
+and serf will cause more of the code to be checked.
+
+Valgrind can be used on the C test programs, and/or on svn,
+svnlook, svnadmin, etc. invoked during the python tests. To test
+the C programs use:
+
+   make check VALGRIND=C
+
+To test svn during the python tests use:
+
+  make check SKIP_C_TESTS=1 VALGRIND=svn
+
+To test svnlook during the python tests use:
+
+  make check VALGRIND=svnlook TESTS=subversion/tests/cmdline/svnlook_tests.py
+
+The VALGRIND settings can be combined:
+
+  make check PARALLEL=1 VALGRIND=C,svn,svnlook
+
+Any valgrind error causes diagnostic output on stderr but the program
+will continue to run. For the C tests valgrind is invoked with the
+option --error-exitcode=1 so that the although the individual
+tests within each C test program may PASS the test as a whole will
+FAIL. For the python tests the test harness parses stderr and detects
+the valgrind diagnostic, so individual tests will FAIL. In both cases
+the stderr diagnostic output from valgrind is available in tests.log.
+
+If valgind is producing unwanted diagnostics in some of the system
+libraries then create a suppression file and pass it as:
+
+  make check VALGRIND=svn VALGRIND_OPTS=--suppressions=$PWD/vg.supp
+
+Running valgrind in the testsuite will only check the client-side code.
+To check the server-side code invoke the server using valgrind and
+arrange for it to remain in the foreground so valgrind output will
+appear on stderr in the terminal. For svnserve something like:
+
+  ./libtool --mode=execute valgrind \
+       subversion/svnserve/svnserve -Tdr subversion/tests/cmdline --foreground
+  make check BASE_URL=svn://localhost   # in another terminal
+
+For apache use a threaded MPM and then something like:
+
+  valgrind httpd -X -f /path/to/cfg
+  make check BASE_URL=http://localhost:8888   # in another terminal
+
+Note that using valgrind will make the testsuite much slower; expect more
+than an order of magnitude slowdown if using valgrind on svn during the
+python tests.  Using the ASAN/MSAN/LSAN sanitizers in gcc/clang is an
+alternative; they will catch similar types of bugs and are much faster.
+The sanitizers also benefit from pool debugging.
+
+Debian's 1:3.19.0-1 version of valgrind seems to have a problem with
+the Dwarf 5 debugging info produced by Debian's compilers, so compile
+with -gdwarf-4 if using -g.
+
+
 Conclusion
 ----------
 

Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1908546&r1=1908545&r2=1908546&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Mon Mar 20 
01:22:52 2023
@@ -211,6 +211,9 @@ svnauthz_validate_binary = os.path.abspa
 )
 svnmover_binary = os.path.abspath('../../../tools/dev/svnmover/svnmover' + 
_exe)
 
+# Where to find the libtool script created during build
+libtool_script = os.path.abspath('../../../libtool')
+
 # Location to the pristine repository, will be calculated from test_area_url
 # when we know what the user specified for --url.
 pristine_greek_repos_url = None
@@ -508,6 +511,13 @@ def open_pipe(command, bufsize=-1, stdin
   if command[0].endswith('.py'):
     command.insert(0, sys.executable)
 
+  if options.valgrind:
+    if os.path.basename(command[0]) in options.valgrind.split(','):
+      valgrind = [libtool_script, '--mode=execute', 'valgrind', '--quiet']
+      if options.valgrind_opts is not None:
+        valgrind += options.valgrind_opts.split(' ')
+      command = valgrind + command
+
   command_string = command[0] + ' ' + ' '.join(map(_quote_arg, command[1:]))
 
   if not stdin:
@@ -1856,6 +1866,10 @@ class TestSpawningThread(threading.Threa
       args.append('--bin=' + options.svn_bin)
     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)
 
     result, stdout_lines, stderr_lines = spawn_process(command, 0, False, None,
                                                        *args)
@@ -2297,6 +2311,10 @@ def _create_parser(usage=None):
                     help='Run tests that connect to remote HTTP(S) servers')
   parser.add_option('--store-pristine', action='store', type='str',
                     help='Set the WC pristine mode')
+  parser.add_option('--valgrind', action='store',
+                    help='programs to run under valgrind')
+  parser.add_option('--valgrind-opts', action='store',
+                    help='options to pass to valgrind')
 
   # most of the defaults are None, but some are other values, set them here
   parser.set_defaults(


Reply via email to