diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2020-06-13 18:48:05 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2020-06-13 18:48:05 (GMT) |
commit | 12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1 (patch) | |
tree | 1b5e18df7e97929fb2d453a92156354991da2cd3 | |
parent | 07dd4ae9033c9872d70d68ff1d83ec46f1db7cb4 (diff) | |
parent | 65bf92c94f2118b0f6e6c19e62993c6e27ebbef9 (diff) | |
download | Doxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.zip Doxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.tar.gz Doxygen-12515664fe30dd79f48fca4b1e3d6cdd3c1a5ce1.tar.bz2 |
Merge branch 'master' of github.com:doxygen/doxygen
-rw-r--r-- | doc/CMakeLists.txt | 10 | ||||
-rw-r--r-- | doc/customize.doc | 3 | ||||
-rw-r--r-- | libmscgen/mscgen_api.c | 1 | ||||
-rw-r--r-- | src/cite.cpp | 6 | ||||
-rw-r--r-- | src/context.cpp | 2 | ||||
-rw-r--r-- | src/dirdef.cpp | 2 | ||||
-rw-r--r-- | src/dirdef.h | 4 | ||||
-rw-r--r-- | src/dotfilepatcher.cpp | 2 | ||||
-rw-r--r-- | src/dotgraph.cpp | 2 | ||||
-rw-r--r-- | src/latexgen.cpp | 10 | ||||
-rw-r--r-- | src/markdown.cpp | 7 | ||||
-rw-r--r-- | src/memberdef.cpp | 7 | ||||
-rw-r--r-- | src/template.cpp | 6 | ||||
-rw-r--r-- | src/translator.h | 5 | ||||
-rw-r--r-- | src/translator_gr.h | 24 | ||||
-rw-r--r-- | src/util.cpp | 20 | ||||
-rw-r--r-- | src/util.h | 1 | ||||
-rw-r--r-- | src/xmlgen.cpp | 7 | ||||
-rw-r--r-- | templates/xml/compound.xsd | 2 | ||||
-rw-r--r-- | testing/037/037__msc_8cpp.xml | 27 | ||||
-rw-r--r-- | testing/037/class_receiver.xml | 4 | ||||
-rw-r--r-- | testing/037/class_sender.xml | 4 | ||||
-rw-r--r-- | testing/037_msc.cpp | 18 | ||||
-rwxr-xr-x | testing/runtests.py | 68 |
24 files changed, 200 insertions, 42 deletions
diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 537089b..df9c2a6 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -212,12 +212,22 @@ install(FILES DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 ) +install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf\") + message(FATAL_ERROR \"\nTerminating:\n documentation has not been generated, \n create documentation by using the 'docs' target followed by an 'install'\n\") +endif()" +) + install(FILES "${PROJECT_BINARY_DIR}/latex/doxygen_manual.pdf" DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}" ) if (build_doc_chm) +install(CODE "if(NOT EXISTS \"${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm\") + message(FATAL_ERROR \"\nTerminating:\n CHM documentation has not been generated, \n create CHM documentation by using the 'docs_chm' target followed by an 'install'\n\") +endif()" +) + install(FILES "${PROJECT_BINARY_DIR}/chm/doxygen_manual.chm" DESTINATION "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}" diff --git a/doc/customize.doc b/doc/customize.doc index 7b2729d..52f8d7a 100644 --- a/doc/customize.doc +++ b/doc/customize.doc @@ -372,7 +372,8 @@ generated output! If the above two methods still do not provide enough flexibility, you can also use the XML output produced by doxygen as a basis to -generate the output you like. To do this set GENERATE_XML to YES. +generate the output you like. To do this set +\ref cfg_generate_xml "GENERATE_XML" to \c YES. The XML output consists of an index file named \c index.xml which lists all items extracted by doxygen with references to the other XML files diff --git a/libmscgen/mscgen_api.c b/libmscgen/mscgen_api.c index 376b9d8..e2cdcb9 100644 --- a/libmscgen/mscgen_api.c +++ b/libmscgen/mscgen_api.c @@ -457,6 +457,7 @@ static RowInfo *computeCanvasSize(Context *ctx, nextYmin = ymin = ctx->opts.entityHeadGap; yskipmax = 0; + ymax = 0; MscResetArcIterator(m); do { diff --git a/src/cite.cpp b/src/cite.cpp index 4adf6f2..82f9e6d 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -203,7 +203,11 @@ void CitationManager::generatePage() QCString bibOutputDir = outputDir+"/"+bibTmpDir; QCString bibOutputFiles = ""; QDir thisDir; - thisDir.mkdir(bibOutputDir); + if (!thisDir.exists(bibOutputDir) && !thisDir.mkdir(bibOutputDir)) + { + err("Failed to create temorary output directory '%s', skiping citations\n",bibOutputDir.data()); + return; + } int i = 0; for (const auto &bibdata : citeDataList) { diff --git a/src/context.cpp b/src/context.cpp index d21b1d0..3d71706 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -10343,7 +10343,7 @@ void generateTemplateFiles(const char *templateDir) QCString outDir = QCString(templateDir)+"/html"; if (!thisDir.exists(outDir) && !thisDir.mkdir(outDir)) { - err("Failed to create output directory '%s'\n",templateDir); + err("Failed to create output directory '%s'\n",outDir.data()); return; } ResourceMgr::instance().writeCategory("html",outDir); diff --git a/src/dirdef.cpp b/src/dirdef.cpp index 7f0b524..dd8444e 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -750,7 +750,7 @@ int FilePairDict::compareValues(const FilePair *left,const FilePair *right) cons //---------------------------------------------------------------------- -UsedDir::UsedDir(DirDef *dir,bool inherited) : +UsedDir::UsedDir(const DirDef *dir,bool inherited) : m_dir(dir), m_filePairs(7), m_inherited(inherited) { m_filePairs.setAutoDelete(TRUE); diff --git a/src/dirdef.h b/src/dirdef.h index 399e0c2..468901d 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -104,7 +104,7 @@ class FilePairDict : public SDict<FilePair> class UsedDir { public: - UsedDir(DirDef *dir,bool inherited); + UsedDir(const DirDef *dir,bool inherited); virtual ~UsedDir(); void addFileDep(FileDef *srcFd,FileDef *dstFd); FilePair *findFilePair(const char *name); @@ -114,7 +114,7 @@ class UsedDir void sort(); private: - DirDef *m_dir; + const DirDef *m_dir; FilePairDict m_filePairs; bool m_inherited; }; diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 20ce4c1..17f8cb7 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -460,7 +460,7 @@ bool DotFilePatcher::run() const convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context); if (!result.isEmpty()) { - t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl; + t << "<map name=\"" << map->label << "\" id=\"" << correctId(map->label) << "\">" << endl; t << result; t << "</map>" << endl; } diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index c0cc4fd..1ad85e1 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -236,7 +236,7 @@ void DotGraph::generateCode(FTextStream &t) else // add link to bitmap file with image map { if (!m_noDivTag) t << "<div class=\"center\">"; - t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << getMapLabel() << "\" alt=\"" << getImgAltText() << "\"/>"; + t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << correctId(getMapLabel()) << "\" alt=\"" << getImgAltText() << "\"/>"; if (!m_noDivTag) t << "</div>"; t << endl; if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) diff --git a/src/latexgen.cpp b/src/latexgen.cpp index f3cce3e..cb42863 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -560,11 +560,13 @@ static void writeDefaultHeaderPart1(FTextStream &t) { t << "\\usepackage[" << fontenc << "]{fontenc}\n"; } - t << "\\usepackage[scaled=.90]{helvet}\n" - "\\usepackage{courier}\n" - "\\usepackage{amssymb}\n" + QCString font = theTranslator->latexFont(); + if (!font.isEmpty()) + { + t << font; + } + t << "\\usepackage{amssymb}\n" "\\usepackage{sectsty}\n" - "\\renewcommand{\\familydefault}{\\sfdefault}\n" "\\allsectionsfont{%\n" " \\fontseries{bc}\\selectfont%\n" " \\color{darkgray}%\n" diff --git a/src/markdown.cpp b/src/markdown.cpp index c4dd9fb..06b714a 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -1501,8 +1501,11 @@ static bool isFencedCodeBlock(const char *data,int size,int refIndent, while (i<size && data[i]==' ') i++; if (i==size || data[i]=='\n') { - offset=i; - return endTildes==startTildes; + if (endTildes==startTildes) + { + offset=i; + return TRUE; + } } } i++; diff --git a/src/memberdef.cpp b/src/memberdef.cpp index d857fa6..1d7909b 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -2733,7 +2733,7 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const isFriend() || isRelated() || (isInline() && inlineInfo) || isSignal() || isSlot() || - isStatic() || + isStatic() || isExternal() || (getClassDef() && getClassDef()!=container && container->definitionType()==TypeClass) || (m_impl->memSpec & ~Entry::Inline)!=0 ) @@ -2745,7 +2745,7 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const //ol.docify(" ["); SrcLangExt lang = getLanguage(); bool optVhdl = lang==SrcLangExt_VHDL; - bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); + static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (optVhdl) { sl.append(theTranslator->trVhdlType(getMemberSpecifiers(),TRUE)); @@ -2756,7 +2756,8 @@ void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const else if (isRelated()) sl.append("related"); else { - if (Config_getBool(INLINE_INFO) && isInline()) sl.append("inline"); + if (isExternal()) sl.append("extern"); + if (inlineInfo && isInline()) sl.append("inline"); if (isExplicit()) sl.append("explicit"); if (isMutable()) sl.append("mutable"); if (isStatic()) sl.append("static"); diff --git a/src/template.cpp b/src/template.cpp index 1763eec..c836c6b 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -2843,7 +2843,11 @@ template<class T> class TemplateNodeCreator : public TemplateNode if (d.exists()) { bool ok = d.mkdir(fileName.mid(j,i-j)); - if (!ok) break; + if (!ok) + { + err("Failed to create directory '%s'\n",(fileName.mid(j,i-j)).data()); + break; + } QCString dirName = outputDir+'/'+fileName.left(i); d = QDir(dirName); j = i+1; diff --git a/src/translator.h b/src/translator.h index 188b775..991e637 100644 --- a/src/translator.h +++ b/src/translator.h @@ -50,6 +50,11 @@ class Translator * can be returned. */ virtual QCString latexFontenc() { return "T1"; } + virtual QCString latexFont() { + return "\\usepackage[scaled=.90]{helvet}\n" + "\\usepackage{courier}\n" + "\\renewcommand{\\familydefault}{\\sfdefault}\n"; + } /*! * Sets the commands to be inserted directly after the `\\begin{document}` * in the LaTeX document. diff --git a/src/translator_gr.h b/src/translator_gr.h index 6ed43db..854a956 100644 --- a/src/translator_gr.h +++ b/src/translator_gr.h @@ -59,8 +59,18 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 virtual QCString latexLanguageSupportCommand() { - return "\\usepackage[greek,english]{babel}\n" - "\\usepackage{alphabeta}\n"; + return "\\usepackage{fontspec}\n" + "\\usepackage[greek]{babel}\n"; + } + + virtual QCString latexFontenc() + { + return ""; + } + virtual QCString latexFont() + { + return "\\setmainfont{Libertinus Sans}\n" + "\\setmonofont{Courier New}\n"; } // --- Language translation methods ------------------- @@ -1159,6 +1169,16 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 return "1253"; } + virtual QCString latexCommandName() + { + QCString latex_command = Config_getString(LATEX_CMD_NAME); + if (latex_command.isEmpty()) latex_command = "latex"; + if (Config_getBool(USE_PDFLATEX)) + { + if (latex_command == "latex") latex_command = "xelatex"; + } + return latex_command; + } /*! Used as ansicpg for RTF fcharset */ diff --git a/src/util.cpp b/src/util.cpp index 7006f26..a298ace 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5022,10 +5022,16 @@ void createSubDirs(QDir &d) int l1,l2; for (l1=0;l1<16;l1++) { - d.mkdir(QCString().sprintf("d%x",l1)); + if (!d.mkdir(QCString().sprintf("d%x",l1))) + { + term("Failed to create output directory '%s'\n",(QCString().sprintf("d%x",l1)).data()); + } for (l2=0;l2<256;l2++) { - d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2)); + if (!d.mkdir(QCString().sprintf("d%x/d%02x",l1,l2))) + { + term("Failed to create output directory '%s'\n",(QCString().sprintf("d%x/d%02x",l1,l2)).data()); + } } } } @@ -5272,6 +5278,16 @@ QCString convertToId(const char *s) return growBuf.get(); } +/*! Some strings have been corrected but the requirement regarding the fact + * that an id cannot have a digit at the first position. To overcome problems + * with double labels we always place an "a" in front + */ +QCString correctId(QCString s) +{ + if (s.isEmpty()) return s; + return "a" + s; +} + /*! Converts a string to an XML-encoded string */ QCString convertToXML(const char *s, bool keepEntities) { @@ -278,6 +278,7 @@ QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &te QCString stripScope(const char *name); QCString convertToId(const char *s); +QCString correctId(QCString s); QCString convertToHtml(const char *s,bool keepEntities=TRUE); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 3a649e9..593f69a 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -1150,7 +1150,8 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) if (!nd->isHidden() && !nd->isAnonymous()) { t << " <innernamespace refid=\"" << nd->getOutputFileBase() - << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl; + << "\"" << (nd->isInline() ? " inline=\"yes\"" : "") + << ">" << convertToXML(nd->name()) << "</innernamespace>" << endl; } } } @@ -1458,7 +1459,9 @@ static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti) writeXMLHeader(t); t << " <compounddef id=\"" << nd->getOutputFileBase() - << "\" kind=\"namespace\" language=\"" + << "\" kind=\"namespace\" " + << (nd->isInline()?"inline=\"yes\" ":"") + << "language=\"" << langToString(nd->getLanguage()) << "\">" << endl; t << " <compoundname>"; writeXMLString(t,nd->name()); diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd index e17d2fa..4df19ce 100644 --- a/templates/xml/compound.xsd +++ b/templates/xml/compound.xsd @@ -43,6 +43,7 @@ <xsd:attribute name="language" type="DoxLanguage" use="optional"/> <xsd:attribute name="prot" type="DoxProtectionKind" /> <xsd:attribute name="final" type="DoxBool" use="optional"/> + <xsd:attribute name="inline" type="DoxBool" use="optional"/> <xsd:attribute name="sealed" type="DoxBool" use="optional"/> <xsd:attribute name="abstract" type="DoxBool" use="optional"/> </xsd:complexType> @@ -104,6 +105,7 @@ <xsd:extension base="xsd:string"> <xsd:attribute name="refid" type="xsd:string" /> <xsd:attribute name="prot" type="DoxProtectionKind" use="optional"/> + <xsd:attribute name="inline" type="DoxBool" use="optional"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType> diff --git a/testing/037/037__msc_8cpp.xml b/testing/037/037__msc_8cpp.xml new file mode 100644 index 0000000..3de730d --- /dev/null +++ b/testing/037/037__msc_8cpp.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<doxygen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="compound.xsd" version=""> + <compounddef id="037__msc_8cpp" kind="file" language="C++"> + <compoundname>037_msc.cpp</compoundname> + <innerclass refid="class_sender" prot="public">Sender</innerclass> + <innerclass refid="class_receiver" prot="public">Receiver</innerclass> + <briefdescription> + </briefdescription> + <detaileddescription> + <para>A bit more complex msc diagram, with also parallel events. <msc> +Sender_1,Receiver_1,Sender1_1, +Sender,Receiver,Sender1, +Sender_2,Receiver_2,Sender1_2; + +Sender_1->Receiver_1 [label="Command()", URL="nref Receiver::Command()"], +Sender1_1<-Receiver_1 [label="Ack()", URL="nref Ack()", ID="1"]; + +Sender->Receiver [label="Command()", URL="nref Receiver::Command()"]; +Sender1<-Receiver [label="Ack()", URL="nref Ack()", ID="1"]; +Sender_2->Receiver_2 [label="Command()", URL="nref Receiver::Command()"], +Sender1_2<-Receiver_2 [label="Ack()", URL="nref Ack()", ID="1"]; +</msc> + </para> + </detaileddescription> + <location file="037_msc.cpp"/> + </compounddef> +</doxygen> diff --git a/testing/037/class_receiver.xml b/testing/037/class_receiver.xml index 24e82fd..b3c9c5a 100644 --- a/testing/037/class_receiver.xml +++ b/testing/037/class_receiver.xml @@ -19,7 +19,7 @@ </detaileddescription> <inbodydescription> </inbodydescription> - <location file="037_msc.cpp" line="32" column="10"/> + <location file="037_msc.cpp" line="50" column="10"/> </memberdef> </sectiondef> <briefdescription> @@ -32,7 +32,7 @@ </msc> </para> </detaileddescription> - <location file="037_msc.cpp" line="28" column="1" bodyfile="037_msc.cpp" bodystart="29" bodyend="33"/> + <location file="037_msc.cpp" line="46" column="1" bodyfile="037_msc.cpp" bodystart="47" bodyend="51"/> <listofallmembers> <member refid="class_receiver_1a162099741e0324e6254c9bc570566e40" prot="public" virt="non-virtual"> <scope>Receiver</scope> diff --git a/testing/037/class_sender.xml b/testing/037/class_sender.xml index 525ab0a..14f29d1 100644 --- a/testing/037/class_sender.xml +++ b/testing/037/class_sender.xml @@ -19,7 +19,7 @@ </detaileddescription> <inbodydescription> </inbodydescription> - <location file="037_msc.cpp" line="17" column="10"/> + <location file="037_msc.cpp" line="35" column="10"/> </memberdef> </sectiondef> <briefdescription> @@ -32,7 +32,7 @@ </msc> </para> </detaileddescription> - <location file="037_msc.cpp" line="13" column="1" bodyfile="037_msc.cpp" bodystart="14" bodyend="18"/> + <location file="037_msc.cpp" line="31" column="1" bodyfile="037_msc.cpp" bodystart="32" bodyend="36"/> <listofallmembers> <member refid="class_sender_1a8ad2c6f9baa4e798868fe4a4d45f8fda" prot="public" virt="non-virtual"> <scope>Sender</scope> diff --git a/testing/037_msc.cpp b/testing/037_msc.cpp index 84ffc55..a3c0e4b 100644 --- a/testing/037_msc.cpp +++ b/testing/037_msc.cpp @@ -1,6 +1,24 @@ // objective: test the \msc and \endmsc commands // check: class_sender.xml // check: class_receiver.xml +// check: 037__msc_8cpp.xml + +/** \file + * A bit more complex msc diagram, with also parallel events. + * \msc + * Sender_1,Receiver_1,Sender1_1, + * Sender,Receiver,Sender1, + * Sender_2,Receiver_2,Sender1_2; + * + * Sender_1->Receiver_1 [label="Command()", URL="nref Receiver::Command()"], + * Sender1_1<-Receiver_1 [label="Ack()", URL="nref Ack()", ID="1"]; + * + * Sender->Receiver [label="Command()", URL="nref Receiver::Command()"]; + * Sender1<-Receiver [label="Ack()", URL="nref Ack()", ID="1"]; + * Sender_2->Receiver_2 [label="Command()", URL="nref Receiver::Command()"], + * Sender1_2<-Receiver_2 [label="Ack()", URL="nref Ack()", ID="1"]; + * \endmsc + */ /** Sender class. Can be used to send a command to the server. * The receiver will acknowledge the command by calling Ack(). diff --git a/testing/runtests.py b/testing/runtests.py index 7896cdd..5d5cee1 100755 --- a/testing/runtests.py +++ b/testing/runtests.py @@ -150,11 +150,11 @@ class Tester: if (self.args.clang): print('CLANG_ASSISTED_PARSING=YES', file=f) if (self.args.cfgs): - for cfg in list(itertools.chain.from_iterable(self.args.cfgs)): - if cfg.find('=') == -1: + for cfg in self.args.cfgs: + if cfg[0].find('=') == -1: print("Not a doxygen configuration item, missing '=' sign: '%s'."%cfg) sys.exit(1) - print(cfg, file=f) + print(cfg[0], file=f) if 'check' not in self.config or not self.config['check']: print('Test doesn\'t specify any files to check') @@ -183,7 +183,7 @@ class Tester: # 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 + return False # convert output to canonical form data = xpopen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)) if data: @@ -191,12 +191,13 @@ class Tester: 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 + return False out_file='%s/%s' % (self.test_out,check) with xopen(out_file,'w') as f: print(data,file=f) shutil.rmtree(self.test_out+'/out',ignore_errors=True) os.remove(self.test_out+'/Doxyfile') + return True # check the relevant files of a doxygen run with the reference material def perform_test(self,testmgr): @@ -401,17 +402,22 @@ class Tester: if failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf or failed_xmlxsd: testmgr.ok(False,self.test_name,msg) - return + return False testmgr.ok(True,self.test_name) if not self.args.keep: shutil.rmtree(self.test_out,ignore_errors=True) + return True def run(self,testmgr): if self.update: - self.update_test(testmgr) + return self.update_test(testmgr) else: - self.perform_test(testmgr) + return self.perform_test(testmgr) + +def do_generation_work(test): + tester = Tester(test[0].args,test[1]) + return tester.run(test[0]) class TestManager: def __init__(self,args,tests): @@ -426,10 +432,10 @@ class TestManager: def ok(self,result,test_name,msg='Ok'): if result: - print('ok %s - %s' % (self.count,test_name)) + print('ok - %s' % (test_name)) self.passed = self.passed + 1 else: - print('not ok %s - %s' % (self.count,test_name)) + print('not ok - %s' % (test_name)) print('-------------------------------------') for o in msg: print(o) @@ -444,9 +450,20 @@ class TestManager: 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) + if (self.args.pool == 1): + passed = 0 + for test in self.tests: + tester = Tester(self.args,test) + passed += tester.run(self) + self.passed = passed + else: + dl = [] + for test in self.tests: + dl += [(self, test)] + import multiprocessing as mp + p = mp.Pool(processes=self.args.pool) + passed = p.map(do_generation_work, dl) + self.passed = sum(passed) res=self.result() if self.args.xhtml and self.args.inputdir!='.' and not res and not self.args.keep: shutil.rmtree("dtd",ignore_errors=True) @@ -457,6 +474,25 @@ class TestManager: shutil.rmtree("dtd",ignore_errors=True) shutil.copytree(self.args.inputdir+"/dtd", "dtd") +def split_and_keep(s, sep): + if not s: return [] + + # Find replacement character that is not used in string + # i.e. just use the highest available character plus one + # Note: This fails if ord(max(s)) = 0x10FFFF (ValueError) + p=chr(ord(max(s))+1) + + retVal = [] + for val in s.replace(sep, p+sep).split(p): + vv = val.split(" ",1) + if ((len(vv) == 1) and not vv[0] == ''): + retVal += vv + if ((len(vv) == 2) and not vv[1] == ''): + retVal += vv + if ((len(vv) == 2) and vv[1] == ''): + retVal += [vv[0]] + return retVal + def main(): # argument handling parser = argparse.ArgumentParser(description='run doxygen tests') @@ -483,6 +519,8 @@ def main(): 'output directory to write the doxygen output to') parser.add_argument('--noredir',help= 'disable redirection of doxygen warnings',action="store_true") + parser.add_argument('--pool',nargs='?',default='1',type=int,help= + 'pool size of multiprocess tests') parser.add_argument('--xml',help='create xml output and check', action="store_true") parser.add_argument('--rtf',help= @@ -505,7 +543,9 @@ def main(): parser.add_argument('--cfg',nargs='+',dest='cfgs',action='append',help= 'run test with extra doxygen configuration settings ' '(the option may be specified multiple times') - test_flags = os.getenv('TEST_FLAGS', default='').split() + + test_flags = split_and_keep(os.getenv('TEST_FLAGS', default=''), '--') + args = parser.parse_args(test_flags + sys.argv[1:]) # sanity check |