summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--BUILD.txt51
-rw-r--r--cmake/FindXapian.cmake42
-rw-r--r--testing/Makefile3
-rw-r--r--testing/README.txt (renamed from testing/README)34
-rwxr-xr-xtesting/runtests.pl252
-rw-r--r--testing/runtests.py201
6 files changed, 311 insertions, 272 deletions
diff --git a/BUILD.txt b/BUILD.txt
new file mode 100644
index 0000000..8c6388c
--- /dev/null
+++ b/BUILD.txt
@@ -0,0 +1,51 @@
+Doxygen uses cmake (http://www.cmake.org/) to build executables for various platforms.
+
+The first step is to create a build directory where the output should be stored.
+Doxygen directory can be fully build outside of the source tree.
+
+The second step is to invoke cmake from within the build directory with the desired generator.
+
+For Linux/Unix systems do the following
+
+ mkdir build
+ cd build
+ cmake -G "Unix Makefiles" path/to/root/of/doxygen/source/tree
+ make
+
+This also works for MacOSX, but if XCode is installed you can also generate an XCode project file
+
+ cmake -G XCode path/to/root/of/doxygen/source/tree
+
+For Windows one can generate a Visual Studio project using
+
+ cmake -G "Visual Studio 12 2013" path\to\root\of\doxygen\source\tree
+
+(this is for Visual Studio 12, there are typically also generators for other versions of
+Visual Studio or other compiler environments like MinGW)
+
+Doxygen's cmake configuration provides a number of options:
+- build_wizard Build the GUI frontend for doxygen.
+- build_app Example showing how to embed doxygen in an application.
+- build_xmlparser Example showing how to parse doxygen's XML output.
+- build_search Build external search tools (doxysearch and doxyindexer)
+- build_doc Build user manual
+- use_sqlite3 Add support for sqlite3 output [experimental].
+- use_libclang Add support for libclang parsing.
+- win_static Link with /MT in stead of /MD on windows
+
+An option can be turned on, by adding -D<option>=ON as a command line option, this can be
+done when generating the initial build files, but also afterwards, i.e. to enable building
+of the documentation after an initial cmake -G run, do
+
+ cmake -Dbuild_doc=ON path/to/root/of/doxygen/source/tree
+
+To turn the option off use
+
+ cmake -Dbuild_doc=OFF path/to/root/of/doxygen/source/tree
+
+To see the current value is of the various options, you can run
+
+ cmake -L path/to/root/of/doxygen/source/tree
+
+The build target for building the documentation is 'doc' and the build target for
+the regression tests is 'tests'
diff --git a/cmake/FindXapian.cmake b/cmake/FindXapian.cmake
new file mode 100644
index 0000000..6109d7f
--- /dev/null
+++ b/cmake/FindXapian.cmake
@@ -0,0 +1,42 @@
+# Find Xapian search engine library
+#
+# XAPIAN_FOUND - system has Xapian
+# XAPIAN_INCLUDE_DIR - the Xapian include directory
+# XAPIAN_LIBRARIES - the libraries needed to use Xapian
+#
+# Copyright © 2010 Harald Sitter <apachelogger@ubuntu.com>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+if(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES)
+ # Already in cache, be silent
+ set(Xapian_FIND_QUIETLY TRUE)
+endif(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES)
+
+FIND_PATH(XAPIAN_INCLUDE_DIR xapian/version.h)
+
+FIND_LIBRARY(XAPIAN_LIBRARIES NAMES xapian)
+
+IF(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES)
+ SET(XAPIAN_FOUND TRUE)
+ELSE(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES)
+ SET(XAPIAN_FOUND FALSE)
+ENDIF(XAPIAN_INCLUDE_DIR AND XAPIAN_LIBRARIES)
+
+IF(XAPIAN_FOUND)
+ IF(NOT Xapian_FIND_QUIETLY)
+ MESSAGE(STATUS "Found Xapian: ${XAPIAN_LIBRARIES}")
+ ENDIF(NOT Xapian_FIND_QUIETLY)
+ELSE(XAPIAN_FOUND)
+ IF(Xapian_FIND_REQUIRED)
+ MESSAGE(FATAL_ERROR "Could not find Xapian")
+ ENDIF(Xapian_FIND_REQUIRED)
+ IF(NOT Xapian_FIND_QUIETLY)
+ MESSAGE(STATUS "Could not find Xapian")
+ ENDIF(NOT Xapian_FIND_QUIETLY)
+ENDIF(XAPIAN_FOUND)
+
+# show the XAPIAN_INCLUDE_DIR and XAPIAN_LIBRARIES variables only in the advanced view
+MARK_AS_ADVANCED(XAPIAN_INCLUDE_DIR XAPIAN_LIBRARIES)
+
diff --git a/testing/Makefile b/testing/Makefile
deleted file mode 100644
index f6beb40..0000000
--- a/testing/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-tests:
- @python runtests.py --doxygen ../build/bin/doxygen
-
diff --git a/testing/README b/testing/README.txt
index 993ff48..ee3de59 100644
--- a/testing/README
+++ b/testing/README.txt
@@ -1,18 +1,18 @@
Doxygen regession test suite
============================
-This directory contains a set of regression tests. Each test consists of a
-file starting with a 3 digit number and a corresponding directory whose name
-has the same 3 digit number. The directory contains one or more reference
-files that are compared against the XML output produced by doxygen. If the
-result is the same, there is no regression and the test passes. If there is a
+This directory contains a set of regression tests. Each test consists of a
+file starting with a 3 digit number and a corresponding directory whose name
+has the same 3 digit number. The directory contains one or more reference
+files that are compared against the XML output produced by doxygen. If the
+result is the same, there is no regression and the test passes. If there is a
difference the test fails and the difference (in diff -u format) will be shown.
-The runtest.pl script responsible for running the tests takes a number of
+The runtest.py script responsible for running the tests takes a number of
optional parameters:
--id n: run test with number n only (the option may be specified
+-id n: run test with number n only (the option may be specified
multiple times) default is to run all tests.
--updateref: update the reference files. Should be used in combination
+-updateref: update the reference files. Should be used in combination
with -id to update the reference file(s) for the given test.
-all: can be used in combination with -updateref to update the
reference files for all tests.
@@ -20,29 +20,29 @@ optional parameters:
-xmllint exe: run the specified xmllint executable.
The runtest.pl has the following dependenies on 3rd party tools:
-- perl to run the script
+- python to run the script
- xmllint to normalize the XML output
- diff to show the differences in case a test fails
-
+
Each test file can have a number of special comment lines that are extracted by
the runtest.pl script and take the form:
-// <identifier>: 'argument'
+// <identifier>: 'argument'
Where <identifier> can be one of:
- objective: 'argument' provides the objective for the test (i.e. its purpose)
-- check: 'argument' names a file that is generated by doxygen, which should
+- check: 'argument' names a file that is generated by doxygen, which should
be compared against the reference.
- config: 'argument' is a line that is added to the default Doxyfile used to
run doxygen on the test file.
Example to run all tests:
- perl runtest.pl
+ python runtest.py
Example to run a test
- perl runtest.pl -id 10
+ python runtest.py -id 10
Example to update the reference files for a test
- perl runtest.pl -updateref -id 10
+ python runtest.py -updateref -id 10
-There is also a Makefile, which can be used to run all tests by simply
-invoking make.
+There is also a CMakeLists.txt, which can be used from the build directory
+to run all tests by simply invoking 'make tests'.
diff --git a/testing/runtests.pl b/testing/runtests.pl
deleted file mode 100755
index 0e1938d..0000000
--- a/testing/runtests.pl
+++ /dev/null
@@ -1,252 +0,0 @@
-#!/usr/bin/perl
-
-# perl script to execute doxygen's regression test suite.
-#
-# Copyright (C) 1997-2014 by Dimitri van Heesch.
-#
-# Permission to use, copy, modify, and distribute this software and its
-# documentation under the terms of the GNU General Public License is hereby
-# granted. No representations are made about the suitability of this software
-# for any purpose. It is provided "as is" without express or implied warranty.
-# See the GNU General Public License for more details.
-#
-# Documents produced by Doxygen are derivative works derived from the
-# input used in their production; they are not affected by this license.
-
-use strict;
-use warnings;
-
-use Getopt::Long;
-use Test::More;
-use File::Path qw(make_path remove_tree);
-use File::Copy qw(copy);
-
-my $Test = Test::Builder->new;
-my $opt_doxygen_exe = 'doxygen';
-my $opt_xmllint_exe = 'xmllint';
-my $opt_updateref = '';
-my @opt_test_ids;
-my $opt_all = '';
-
-GetOptions( 'updateref' => \$opt_updateref,
- 'doxygen=s' => \$opt_doxygen_exe,
- 'xmllint=s' => \$opt_xmllint_exe,
- 'id=i' => \@opt_test_ids,
- 'all' => \$opt_all
- );
-
-sub read_two_files {
- my $first = shift;
- my $second = shift;
- my $filter = shift;
- my $success = 1;
- my @errors;
-
- unless (open FIRST, "$first") {
- $success = 0;
- push @errors, "$first absent";
- }
- unless (open SECOND, "$second") {
- $success = 0;
- push @errors, "$second absent";
- }
- return ($success, @errors) unless $success;
-
- my $first_lines = join "",<FIRST>;
- my $second_lines = join "",<SECOND>;
-
- close FIRST;
- close SECOND;
-
- return ($success, $first_lines, $second_lines);
-}
-
-sub compare_ok {
- my $got_file = shift;
- my $expected_file = shift;
- my $name = shift;
- my @read_result = read_two_files($got_file, $expected_file);
- my $files_exist = shift @read_result;
-
- if ($files_exist) {
- my ($got, $expected) = @read_result;
- my $diff = `diff -u $got_file $expected_file`;
- my $failed = length $diff;
- return ($failed,"Difference between generated output and reference:\n$diff");
- }
- else {
- return (1,join "\n", @read_result);
- }
-}
-
-sub chop_volatile {
- my $line = shift;
- $line =~ s/version="\d\.\d+\.\d+(\.\d+)?(\-\d+)?"/version=""/g; # strip version
- $line =~ s/file=".*\/(.*)"/file="$1"/g; # strip location
- return $line;
-}
-
-sub get_config {
- my $file = shift;
- my %config;
- open F,"<$file";
- while (<F>) {
- if (/\/\/\s*(\S+):\s*(.*)$/) {
- my $key = $1;
- my $val = $2;
- chomp $val;
- $config{$key} = [] unless defined $config{$key};
- push @{$config{$key}},$val;
- }
- }
- return %config;
-}
-
-sub perform_test {
- my $test_file = shift;
- my %config = get_config($test_file);
- my $test_name = "[$test_file]: $config{'objective'}[0]";
- my $test_id = $test_file;
- $test_id =~ s/^(\d+).*$/$1/;
- my $test_out = "test_output_${test_id}";
-
- if (scalar($config{'check'})==0) {
- $Test->ok(0, $test_name);
- $Test->diag("Test doesn't specify any files to check");
- return;
- }
-
- # prepare test environment
- remove_tree("$test_out");
- make_path("$test_out");
- copy("Doxyfile","$test_out");
- open(F,">>$test_out/Doxyfile");
- print F "INPUT = $test_file\n";
- print F "XML_OUTPUT = $test_out/out\n";
- foreach my $cfg (@{$config{'config'}}) {
- print F "$cfg\n";
- }
- close(F);
-
- # run doxygen
- if (system("$opt_doxygen_exe $test_out/Doxyfile")!=0) {
- $Test->ok(0, $test_name);
- $Test->diag("Failed to run doxygen");
- return;
- }
-
- # look for files to check against the reference
- foreach my $fn (@{$config{'check'}}) {
- if (!-f "$test_out/out/$fn") {
- $Test->ok(0, $test_name);
- $Test->diag("Non-existing file $test_out/out/$fn after 'check:' statement");
- return;
- }
- # run xmllint on the output file
- my @lines = `$opt_xmllint_exe --format --noblanks --nowarning $test_out/out/$fn`;
- if (scalar(@lines)>0 && open(F,">$test_out/$fn")) {
- foreach my $line (@lines) {
- print F chop_volatile($line);
- }
- close(F);
- } else {
- $Test->ok(0, $test_name);
- $Test->diag("Failed to run xmllint on the doxygen output file $test_out/out/$fn");
- }
- my ($failed,$msg) = compare_ok("$test_out/$fn","$test_id/$fn",$test_name);
- if ($failed) {
- $Test->ok(0, $test_name);
- $Test->diag($msg);
- return;
- }
- }
-
- # test passed
- remove_tree("$test_out");
- $Test->ok(1, $test_name);
-}
-
-sub update_test {
- my $test_file = shift;
- my %config = get_config($test_file);
- my $test_name = "[$test_file]: $config{'objective'}[0]";
- my $test_id = $test_file;
- $test_id =~ s/^(\d+).*$/$1/;
- my $test_out = $test_id;
-
- # prepare reference environment
- remove_tree("$test_out");
- make_path("$test_out");
- copy("Doxyfile","$test_out");
- open(F,">>$test_out/Doxyfile");
- print F "INPUT = $test_file\n";
- print F "XML_OUTPUT = $test_out/out\n";
- foreach my $cfg (@{$config{'config'}}) {
- print F "$cfg\n";
- }
- close(F);
-
- print "Updating reference for $test_name\n";
-
- # run doxygen
- if (system("$opt_doxygen_exe $test_out/Doxyfile")!=0) {
- print("Error: failed to run doxygen");
- return;
- }
- my $err=0;
-
- # look for files to prepare as reference
- foreach my $fn (@{$config{'check'}}) {
- if (!-f "$test_out/out/$fn") {
- printf("Error: Non-existing file $test_out/out/$fn after 'check:' statement\n");
- $err=1;
- }
- # run xmllint on the output file
- if (!$err) {
- my @lines = `$opt_xmllint_exe --format --noblanks --nowarning $test_out/out/$fn`;
- if (scalar(@lines)>0 && open(F,">$test_out/$fn")) {
- foreach my $line (@lines) {
- print F chop_volatile($line);
- }
- close(F);
- } else {
- printf("Error: Failed to run xmllint on the doxygen output file $test_out/out/$fn\n");
- $err=1;
- }
- }
- }
-
- if (!$err) {
- # clean-up
- remove_tree("$test_out/out");
- unlink("$test_out/Doxyfile");
- }
-}
-
-# get the tests
-my @tests;
-if (scalar(@opt_test_ids)==0 && $opt_updateref && !$opt_all) {
- printf("Error: updateref option requires -id to update a test or -all to update all\n");
- exit(1);
-}
-if (scalar(@opt_test_ids)>0) {
- foreach my $t (@opt_test_ids) {
- push @tests, glob("${t}_* 0${t}_* 00${t}_*");
- }
-} else {
- @tests = glob('[0-9][0-9][0-9]_*');
-}
-
-if ($opt_updateref) {
- # update reference
- foreach my $test (@tests) {
- update_test($test);
- }
-} else {
- # run tests
- plan tests => scalar(@tests);
- foreach my $test (@tests) {
- perform_test($test);
- }
-}
-
diff --git a/testing/runtests.py b/testing/runtests.py
new file mode 100644
index 0000000..d0e18dc
--- /dev/null
+++ b/testing/runtests.py
@@ -0,0 +1,201 @@
+#!/usr/bin/python
+
+from __future__ import print_function
+import argparse, glob, itertools, re, shutil, os, sys
+
+config_reg = re.compile('.*\/\/\s*(?P<name>\S+):\s*(?P<value>.*)$')
+
+class Tester:
+ def __init__(self,args,test):
+ self.args = args
+ self.test = test
+ self.update = args.updateref
+ self.config = self.get_config()
+ self.test_name = '[%s]: %s' % (self.test,self.config['objective'][0])
+ self.test_id = self.test.split('_')[0]
+ if self.update:
+ self.test_out = self.args.inputdir+'/'+self.test_id
+ else:
+ self.test_out = self.args.outputdir+'/test_output_'+self.test_id
+ self.prepare_test()
+
+ def compare_ok(self,got_file,expected_file,name):
+ if not os.path.isfile(got_file):
+ return (True,'%s absent' % got_file)
+ elif not os.path.isfile(expected_file):
+ return (True,'%s absent' % expected_file)
+ else:
+ diff = os.popen('diff -u %s %s' % (got_file,expected_file)).read()
+ if diff:
+ return (True,'Difference between generated output and reference:\n%s' % diff)
+ return (False,'')
+
+ def get_config(self):
+ config = {}
+ with open(self.args.inputdir+'/'+self.test,'r') as f:
+ for line in f.readlines():
+ m = config_reg.match(line)
+ if m:
+ key = m.group('name')
+ value = m.group('value')
+ if (key=='config'):
+ value = value.replace('$INPUTDIR',self.args.inputdir)
+ #print('key=%s value=%s' % (key,value))
+ if key in config:
+ config[key].append(value)
+ else:
+ config[key] = [value]
+ return config
+
+ def prepare_test(self):
+ # prepare test environment
+ shutil.rmtree(self.test_out,ignore_errors=True)
+ os.mkdir(self.test_out)
+ shutil.copy(self.args.inputdir+'/Doxyfile',self.test_out)
+ with open(self.test_out+'/Doxyfile','a') as f:
+ print('INPUT=%s/%s' % (self.args.inputdir,self.test), file=f)
+ print('STRIP_FROM_PATH=%s' % self.args.inputdir, file=f)
+ print('XML_OUTPUT=%s/out' % self.test_out, file=f)
+ print('EXAMPLE_PATH=%s' % self.args.inputdir, file=f)
+ if 'config' in self.config:
+ for option in self.config['config']:
+ print(option, file=f)
+
+ if 'check' not in self.config or not self.config['check']:
+ print('Test doesn\'t specify any files to check')
+ sys.exit(1)
+
+ # run doxygen
+ if os.system('%s %s/Doxyfile 2>/dev/null' % (self.args.doxygen,self.test_out))!=0:
+ print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out));
+ sys.exit(1)
+
+ # update the reference data for this test
+ def update_test(self,testmgr):
+ print('Updating reference for %s' % self.test_name)
+
+ if 'check' in self.config:
+ for check in self.config['check']:
+ check_file='%s/out/%s' % (self.test_out,check)
+ # check if the file we need to check is actually generated
+ if not os.path.isfile(check_file):
+ print('Non-existing file %s after \'check:\' statement' % check_file)
+ return
+ # convert output to canonical form
+ data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read()
+ if data:
+ # strip version
+ data = re.sub(r'xsd" version="[0-9.-]+"','xsd" version=""',data).rstrip('\n')
+ else:
+ print('Failed to run %s on the doxygen output file %s' % (self.args.xmllint,self.test_out))
+ return
+ out_file='%s/%s' % (self.test_out,check)
+ with open(out_file,'w') as f:
+ print(data,file=f)
+ shutil.rmtree(self.test_out+'/out',ignore_errors=True)
+ os.remove(self.test_out+'/Doxyfile')
+
+ # check the relevant files of a doxygen run with the reference material
+ def perform_test(self,testmgr):
+ # look for files to check against the reference
+ if 'check' in self.config:
+ for check in self.config['check']:
+ check_file='%s/out/%s' % (self.test_out,check)
+ # check if the file we need to check is actually generated
+ if not os.path.isfile(check_file):
+ testmgr.ok(False,self.test_name,msg='Non-existing file %s after \'check:\' statement' % check_file)
+ return
+ # convert output to canonical form
+ data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read()
+ if data:
+ # strip version
+ data = re.sub(r'xsd" version="[0-9.-]+"','xsd" version=""',data).rstrip('\n')
+ else:
+ testmgr.ok(False,self.test_name,msg='Failed to run %s on the doxygen output file %s' % (self.args.xmllint,self.test_out))
+ return
+ out_file='%s/%s' % (self.test_out,check)
+ with open(out_file,'w') as f:
+ print(data,file=f)
+ ref_file='%s/%s/%s' % (self.args.inputdir,self.test_id,check)
+ (failed,msg) = self.compare_ok(out_file,ref_file,self.test_name)
+ if failed:
+ testmgr.ok(False,self.test_name,msg)
+ return
+ shutil.rmtree(self.test_out,ignore_errors=True)
+ testmgr.ok(True,self.test_name)
+
+ def run(self,testmgr):
+ if self.update:
+ self.update_test(testmgr)
+ else:
+ self.perform_test(testmgr)
+
+class TestManager:
+ def __init__(self,args,tests):
+ self.args = args
+ self.tests = tests
+ self.num_tests = len(tests)
+ self.count=1
+ self.passed=0
+ print('1..%d' % self.num_tests)
+
+ def ok(self,result,test_name,msg='Ok'):
+ if result:
+ print('ok %s - %s' % (self.count,test_name))
+ self.passed = self.passed + 1
+ else:
+ print('not ok %s - %s' % (self.count,test_name))
+ print('-------------------------------------')
+ print(msg)
+ print('-------------------------------------')
+ self.count = self.count + 1
+
+ def result(self):
+ if self.passed==self.num_tests:
+ print('All tests passed!')
+ else:
+ print('%d out of %s tests failed' % (self.num_tests-self.passed,self.num_tests))
+ return 0 if self.passed==self.num_tests else 1
+
+ def perform_tests(self):
+ for test in self.tests:
+ tester = Tester(self.args,test)
+ tester.run(self)
+ return 0 if self.args.updateref else self.result()
+
+def main():
+ # argument handling
+ parser = argparse.ArgumentParser(description='run doxygen tests')
+ parser.add_argument('--updateref',help='update the reference data for a test',action="store_true")
+ parser.add_argument('--doxygen',nargs='?',default='doxygen',help='path/name of the doxygen executable')
+ parser.add_argument('--xmllint',nargs='?',default='xmllint',help='path/name of the xmllint executable')
+ parser.add_argument('--id',nargs='+',dest='ids',action='append',type=int,help='id of the test to perform')
+ parser.add_argument('--all',help='perform all tests',action="store_true")
+ parser.add_argument('--inputdir',nargs='?',default='.',help='input directory containing the tests')
+ parser.add_argument('--outputdir',nargs='?',default='.',help='output directory to write the doxygen output to')
+ args = parser.parse_args()
+
+ # sanity check
+ if (not args.updateref is None) and (args.ids is None) and (args.all is None):
+ parser.error('--updateref requires either --id or --all')
+
+ starting_directory = os.getcwd()
+ os.chdir(args.inputdir)
+ # find the tests to run
+ if args.ids: # test ids are given by user
+ tests = []
+ for id in list(itertools.chain.from_iterable(args.ids)):
+ tests.append(glob.glob('%s_*'%id))
+ tests.append(glob.glob('0%s_*'%id))
+ tests.append(glob.glob('00%s_*'%id))
+ tests = list(itertools.chain.from_iterable(tests))
+ else: # find all tests
+ tests = glob.glob('[0-9][0-9][0-9]_*')
+ os.chdir(starting_directory)
+
+ # create test manager to run the tests
+ testManager = TestManager(args,tests)
+ sys.exit(testManager.perform_tests())
+
+if __name__ == '__main__':
+ main()