Doxygen XLinks
by
V: 2511R0
Website: doxygen
Loading...
Searching...
No Matches
unittests.cpp
1//==================================================================================================
2// This implementation-file is part of DoxygenXLinks - A doxygen post-processor that allows to
3// define smarter <b>Doxygen</b>-links.
4//
5// \emoji :copyright: 2025-2026 A-Worx GmbH, Germany.
6// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#include "ALib.Lang.H"
9#if ALIB_DEBUG
10
11#include "index.hpp"
12#include "dxl.hpp"
13#include "expressions.hpp"
14
15using namespace alib;
16using namespace std;
17
19#include "ALib.Bootstrap.H"
20namespace dxl {
22#define TRUE(cond ,...) ALIB_ASSERT_ERROR( cond, "DXL/UNIT_TESTS", "Unit test failed: " __VA_ARGS__ )
23#define FALSE(cond,...) ALIB_ASSERT_ERROR(!cond, "DXL/UNIT_TESTS", "Unit test failed: " __VA_ARGS__ )
24#define EQ(a, b,...) ALIB_ASSERT_ERROR( a==b, "DXL/UNIT_TESTS", "Unit test failed: {} != {} ({} != {})", \
25 a, b, ALIB_STRINGIFY(a), ALIB_STRINGIFY(b) __VA_ARGS__ )
27
28void DbgUnitTests(DoxygenXLinks*);
29void DbgUnitTests(DoxygenXLinks* dxl) {
30
31 // unit tests are only run if the DoxygenXLinks documentation is processed.
32 if ( dxl->Indices.size()!=2
33 || !dxl->Indices[0]->FileName.Equals("alib.doxygen.tag")
34 || !dxl->Indices[1]->FileName.Equals("doxygenxlinks.tag"))
35 return;
36 app::Get<DXLApp>().cOut->Add("================================ Running unit tests... ================================ ");
37 app::Get<DXLApp>().onSdOutput();
38
39
40 // --------------- inherited members ---------------
41 {
42 String searchString= "Index::Node";
43 auto* xl= dxl->GetXLink(searchString, File());
44 TRUE(xl->IsResolved())
45 }
46
47 // --------------- inherited members ---------------
48 {
49 XLink xl; xl.MA.DbgCriticalSectionsPH.Construct(nullptr);
50 xl.DbgReset(); xl.LinkString= "AnsiConsoleLogger::CntLogs"; xl.Parse(); dxl->Indices[0]->Search(xl); EQ(5, xl.BaseTypes->size())
51 }
52 // -------------- file links -----------
53 {
54 XLink xl; xl.DbgReset();
55 auto kh= Target::File;
56 xl.MA.Reset(); xl.LinkString= "F;'dxl.hpp'" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(1, xl.scopeSize)EQ("dxl.hpp" ,xl.Name())
57 xl.MA.Reset(); xl.LinkString= "F;'dxl.hpp'" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(1, xl.scopeSize)EQ("dxl.hpp" ,xl.Name())
58 xl.MA.Reset(); xl.LinkString= "F;'dx l.hpp'" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(1, xl.scopeSize)EQ("dx l.hpp",xl.Name())
59 xl.MA.Reset(); xl.LinkString= "F;dx l.hpp" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(1, xl.scopeHintsSize)EQ(2, xl.scopeSize)EQ("l.hpp" ,xl.Name()) EQ("dx" ,xl.scope[0])
60 xl.MA.Reset(); xl.LinkString= "F;abc/def.h" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(2, xl.scopeSize)EQ("def.h" ,xl.Name()) EQ("abc" ,xl.scope[0])
61 xl.MA.Reset(); xl.LinkString= "F;ab/c/def.h" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(3, xl.scopeSize)EQ("def.h" ,xl.Name()) EQ("ab" ,xl.scope[0]) EQ("c" ,xl.scope[1])
62 xl.MA.Reset(); xl.LinkString= "F;'ab/c/def.h'" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(0, xl.scopeHintsSize)EQ(3, xl.scopeSize)EQ("def.h" ,xl.Name()) EQ("ab" ,xl.scope[0]) EQ("c" ,xl.scope[1])
63 xl.MA.Reset(); xl.LinkString= "F;uv xyz 'ab/c/def.h'" ; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(2, xl.scopeHintsSize)EQ(5, xl.scopeSize)EQ("def.h" ,xl.Name()) EQ("uv" ,xl.scope[0]) EQ("xyz" ,xl.scope[1]) EQ("ab" ,xl.scope[2]) EQ("c" ,xl.scope[3])
64 xl.MA.Reset(); xl.LinkString= "F;'uv' 'x yz' ab/c/def.h"; xl.Parse(); TRUE(xl.KindSpec==kh)EQ(2, xl.scopeHintsSize)EQ(5, xl.scopeSize)EQ("def.h" ,xl.Name()) EQ("uv" ,xl.scope[0]) EQ("x yz",xl.scope[1]) EQ("ab" ,xl.scope[2]) EQ("c" ,xl.scope[3])
65 }
66
67 // -------------- requested display paths -----------
68 {
69 XLink xl; xl.MA.DbgCriticalSectionsPH.Construct(nullptr);
70 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::DoxyfilePath;1" ; xl.Parse(); dxl->Indices[1]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("DoxyfilePath" ,xl.Display)
71 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::DoxyfilePath;2" ; xl.Parse(); dxl->Indices[1]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("DXLApp::DoxyfilePath" ,xl.Display)
72 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::DoxyfilePath;3" ; xl.Parse(); dxl->Indices[1]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("dxl::DXLApp::DoxyfilePath" ,xl.Display)
73 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::DoxyfilePath;4" ; xl.Parse(); dxl->Indices[1]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("dxl::DXLApp::DoxyfilePath" ,xl.Display)
74 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::bsConfigureCLI;1"; xl.Parse(); dxl->Indices[0]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("bsConfigureCLI" ,xl.Display)
75 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::bsConfigureCLI;2"; xl.Parse(); dxl->Indices[0]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("DXLApp::bsConfigureCLI" ,xl.Display)
76 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::bsConfigureCLI;3"; xl.Parse(); dxl->Indices[0]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("dxl::DXLApp::bsConfigureCLI" ,xl.Display)
77 xl.DbgReset(); xl.LinkString= "dxl::DXLApp::bsConfigureCLI;4"; xl.Parse(); dxl->Indices[0]->Search(xl); EQ(1,xl.Targets.size()) xl.AssembleDisplay(); EQ("dxl::DXLApp::bsConfigureCLI" ,xl.Display)
78 }
79
80 // -------------- Expressions -----------
81 {
82 XLink xlValid; xlValid.MA.DbgCriticalSectionsPH.Construct(nullptr);
83 xlValid.LinkString= "lib expr detail::VirtualMachine::run(Program&);3*";
84 xlValid.Parse();
85 dxl->Indices[0]->Search(xlValid);
86 EQ(1,xlValid.Targets.size()) xlValid.AssembleDisplay(); TRUE(xlValid.Display.IndexOf("run")>0)
87 { DXLExpression expr("Name * \"run*\""); EQ(true, expr.Includes(&xlValid)) }
88 { DXLExpression expr("KinSp == uS"); EQ(true, expr.Includes(&xlValid)) }
89 { DXLExpression expr("dep == 5"); EQ(true, expr.Includes(&xlValid)) }
90 { DXLExpression expr("EndsWith(HTMLFile,\".html\")"); EQ(true, expr.Includes(&xlValid)) }
91 { DXLExpression expr("Length(HTMLAnch) >10"); EQ(true, expr.Includes(&xlValid)) }
92 { DXLExpression expr("TagFilePath == \"/tmp/alib.doxygen.tag\""); EQ(true, expr.Includes(&xlValid)) }
93
94 XLink xlInValid; xlInValid.MA.DbgCriticalSectionsPH.Construct(nullptr);
95 xlInValid.LinkString= "InvalidType";
96 xlInValid.Parse();
97 dxl->Indices[0]->Search(xlInValid);
98 EQ(0,xlInValid.Targets.size()) EQ("InvalidType", xlInValid.Name())
99 {
100 DXLScope dxlScope;
101
102 // lamda function that creates a formatter and test the result
103 auto testByFormatting = [&]( const String& expInvalid, const String& exp,
104 const String& expressionFormatter ) {
105 String256 buffer;
106 DXLExpressionFormatter exprFormatter( expressionFormatter );
107 dxlScope.Xlink = &xlInValid;
108 {ALIB_LOCK_RECURSIVE_WITH(Formatter::DEFAULT_LOCK)
109 exprFormatter.Format( buffer, dxlScope );}
110 EQ(expInvalid, static_cast<AString&>(buffer))
111
112 buffer.Reset();
113 dxlScope.Xlink = &xlValid;
114 {ALIB_LOCK_RECURSIVE_WITH(Formatter::DEFAULT_LOCK)
115 exprFormatter.Format( buffer, dxlScope );}
116 EQ(exp, static_cast<AString&>(buffer))
117 };
118
119 //{ DXLExpression expr("EndsWith(HTMLFile,\".html\")"); EQ(true, expr.Includes(lsValid, &xlValid)) }
120 //{ DXLExpression expr("Length(HTMLAnch) >10"); EQ(true, expr.Includes(lsValid, &xlValid)) }
121 //{ DXLExpression expr("TagFilePath == \" /tmp/alib.doxygen.tag\""); EQ(true, expr.Includes(lsValid, &xlValid)) }
122
123
124 testByFormatting("", "/tmp/alib.doxygen.tag" , "{TagFilePath}" );
125 testByFormatting("", "/tmp/alib.doxygen.tag" , "{TagFilePath(parent)}" );
126 testByFormatting("", "alib.doxygen.tag" , "{TagFileName}" );
127 testByFormatting("", "alib.doxygen.tag" , "{TagFileName(parent)}" );
128 // testByFormatting("-1","44109" , "{TagFileLine}" );
129 // testByFormatting("-1","44078" , "{TagFileLine(parent)}" );
130 testByFormatting("", "structalib_1_1expressions_1_1detail_1_1VirtualMachine.html" , "{HTMLFile}" );
131 testByFormatting("", "structalib_1_1expressions_1_1detail_1_1VirtualMachine.html" , "{HTMLFile(parent)}" );
132 testByFormatting("", "namespacealib_1_1expressions_1_1detail.html" , "{HTMLFile(parent(parent))}" );
133 testByFormatting("", "a9907a52e783937722617faa91fbee12b" , "{HTMLAnc}" );
134 testByFormatting("0", "0" , "{countSourcLocs}" );
135 testByFormatting("0", "0" , "{countHTMLLocs}" );
136
137
138 testByFormatting("InvalidType", "lib expr detail::VirtualMachine::run(Program&);3*" , "{LinkString}" );
139 testByFormatting("InvalidType", "lib expr detail::VirtualMachine::run(Program&);3*" , "{ls}" );
140 testByFormatting("InvalidType", "lib expr detail::VirtualMachine::run(Program&)" , "{LinkTarget}" );
141 testByFormatting("InvalidType", "lib expr detail::VirtualMachine::run(Program&)" , "{lt}" );
142 testByFormatting("" , "3*" , "{LinkDisplay}" );
143 testByFormatting("" , "3*" , "{LD}" );
144 testByFormatting("-1","5" , "{Depth}" );
145 testByFormatting("0", "2" , "{CountScopeHints}" );
146 testByFormatting("", "lib" , "{ScopeHint(0)}" );
147 testByFormatting("", "expr" , "{ScopeHint(1)}" );
148 testByFormatting("-1","1" , "{CountScope}" );
149 testByFormatting("", "run(Program&, Scope&)", "{name}" );
150 testByFormatting("", "run(Program&, Scope&)", "{Name(Parent(0))}" );
151 testByFormatting("", "VirtualMachine" , "{Name(Parent(1))}" );
152 testByFormatting("", "detail" , "{Name(Parent(2))}" );
153 testByFormatting("", "expressions" , "{Name(Parent(3))}" );
154 testByFormatting("", "alib" , "{Name(Parent(4))}" );
155 testByFormatting("", "" , "{Name(Parent(5))}" );
156
157
158 testByFormatting("", "alib::expressions::detail::VirtualMachine::run(Program&, Scope&)" , "{Path}" );
159 testByFormatting("", "alib::expressions::detail::VirtualMachine" , "{Path(Parent)}" );
160 testByFormatting("", "alib::expressions::detail" , "{Path(Parent(Parent))}" );
161 testByFormatting("", "alib::expressions" , "{Path(Parent(Parent(Parent)))}" );
162 testByFormatting("", "alib" , "{Path(Parent(Parent(Parent(Parent))))}" );
163 testByFormatting("", "" , "{Path(Parent(Parent(Parent(Parent(Parent)))))}" );
164 testByFormatting("", "" , "{Path(Parent(Parent(Parent(Parent(Parent(Parent))))))}" );
165 testByFormatting("", "alib::expressions::detail::VirtualMachine::run(Program&, Scope&)" , "{Path(Parent(0))}" );
166 testByFormatting("", "alib::expressions::detail::VirtualMachine" , "{Path(Parent(1))}" );
167 testByFormatting("", "alib::expressions::detail" , "{Path(Parent(2))}" );
168 testByFormatting("", "alib::expressions" , "{Path(Parent(3))}" );
169 testByFormatting("", "alib" , "{Path(Parent(4))}" );
170 testByFormatting("", "" , "{Path(Parent(5))}" );
171 testByFormatting("", "" , "{Path(Parent(6))}" );
172
173 testByFormatting("-1", "1" , "{CountParams}" );
174 testByFormatting("" , "(Program&)" , "{Params}" );
175 testByFormatting("-1", "2" , "{CountParams(Targ)}" );
176 testByFormatting("" , "(Program&, Scope&)" , "{Params(Targ)}" );
177 testByFormatting("-1", "-1" , "{CountTemplateParams}" );
178 testByFormatting("" , "" , "{TemplateParams}" );
179 testByFormatting("-1", "-1" , "{CountTemplateParams(Targ)}" );
180 testByFormatting("" , "" , "{TemplateParams(Targ)}" );
181 testByFormatting("-1", "-1" , "{CountTemplateSpecParams}" );
182 testByFormatting("" , "" , "{TemplateSpecParams}" );
183 testByFormatting("-1", "-1" , "{CountTemplateSpecParams(Targ)}");
184 testByFormatting("" , "" , "{TemplateSpecParams(Targ)}" );
185
186 // linking to a template type
187 xlValid.DbgReset(); xlValid.MA.DbgCriticalSectionsPH.Construct(nullptr);
188 xlValid.LinkString= "<typename TApp, typename TCh>strings::AppendableTraits;3*";
189 xlValid.Parse();
190 dxl->Indices[0]->Search(xlValid);
191 EQ(1,xlValid.Targets.size()) xlValid.AssembleDisplay();
192 TRUE(xlValid.Display.IndexOf("AppendableTraits")>0)
193 { DXLExpression expr("Name(target) * \"AppendableTraits\""); EQ(true, expr.Includes(&xlValid)) }
194
195 testByFormatting("-1", "-1" , "{CountParams}" );
196 testByFormatting("" , "" , "{Params}" );
197 testByFormatting("-1", "-1" , "{CountParams(Targ)}" );
198 testByFormatting("" , "" , "{Params(Targ)}" );
199 testByFormatting("-1", "2" , "{CountTemplateParams}" );
200 testByFormatting("" ,
201"<typename TApp, typename TCh>" , "{TemplateParams}" );
202 testByFormatting("-1", "3" , "{CountTemplateParams(Targ)}" );
203 testByFormatting("" ,
204"<typename TAppendable, typename TChar, typename TAllocator>" , "{TemplateParams(Targ)}" );
205 testByFormatting("-1", "-1" , "{CountTemplateSpecParams}" );
206 testByFormatting("" , "" , "{TemplateSpecParams}" );
207 testByFormatting("-1", "-1" , "{CountTemplateSpecParams(Targ)}");
208 testByFormatting("" , "" , "{TemplateSpecParams(Targ)}" );
209
210
211 // linking to a templated specialized type. Orig C++ code:
212 // template<typename TEnum, typename TChar, typename TAllocator>
213 // struct AppendableTraits<TEnum, TChar, TAllocator>
214
215 xlValid.DbgReset(); xlValid.MA.DbgCriticalSectionsPH.Construct(nullptr);
216 xlValid.LinkString= "R;<typename TEnum, typename TAllocator>AppendableTraits;3*";
217 xlValid.Parse();
218 dxl->Indices[0]->Search(xlValid);
219 EQ(1,xlValid.Targets.size()) xlValid.AssembleDisplay(); TRUE(xlValid.Display.IndexOf("AppendableTraits")>0)
220 { DXLExpression expr("Name(target) * \"AppendableTraits<*\""); EQ(true, expr.Includes(&xlValid)) }
221
222 testByFormatting("0", "0" , "{countSourcLocs}" );
223 testByFormatting("0", "0" , "{countHTMLLocs}" );
224 testByFormatting("UNSPECIFIED", "struct,class,union" , "{KindSpec}" );
225 testByFormatting("-1", "-1" , "{CountParams}" );
226 testByFormatting("" , "" , "{Params}" );
227 testByFormatting("-1", "-1" , "{CountParams(Targ)}" );
228 testByFormatting("" , "" , "{Params(Targ)}" );
229 testByFormatting("-1", "2" , "{CountTemplateParams}" );
230 testByFormatting("" ,
231"<typename TEnum, typename TAllocator>" , "{TemplateParams}" );
232 testByFormatting("-1", "3" , "{CountTemplateParams(Targ)}" );
233 testByFormatting("" ,
234"<typename TEnum, typename TChar, typename TAllocator>" , "{TemplateParams(Targ)}" );
235 testByFormatting("-1", "-1" , "{CountTemplateSpecParams}" );
236 testByFormatting("" , "" , "{TemplateSpecParams}" );
237 testByFormatting("-1", "3" , "{CountTemplateSpecParams(Targ)}");
238 testByFormatting("" ,
239"<TEnum, TChar, TAllocator>" , "{TemplateSpecParams(Targ)}" );
240
241
242 //------------- get a "real-life" link from the current dxl-run ---------------
243 String xls= "VirtualMachine";
244 dxlScope.Xlink= dxl->GetXLink(xls, File());
245 // lamda function that creates a formatter and test the result
246// auto testDXLLink = [&]( const String& exp, const String& expressionFormatter ) {
247// String256 buffer;
248// DXLExpressionFormatter exprFormatter( expressionFormatter );
249// {ALIB_LOCK_RECURSIVE_WITH(Formatter::DEFAULT_LOCK)
250// exprFormatter.Format( buffer, dxlScope );}
251// EQ(exp, static_cast<AString&>(buffer))
252// };
253//
254// testDXLLink("2" , "{countSourceLocs}" );
255// testDXLLink("2" , "{countHTMLLocs}" );
256 }
257 }
258
259//Shutdown();
260//exit(42);
261
262 app::Get<DXLApp>().cOut->Add("================================ ...unit tests done ================================ ");
263
264}
265
266} //namespace [dxl]
267
268#endif // ALIB_DEBUG
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_POP_ALLOWANCE
#define ALIB_ALLOW_UNUSED_MACRO
lang::Placeholder< lang::DbgCriticalSections > DbgCriticalSectionsPH
@ File
Denotes a source file.
Definition target.hpp:31
files::File File
strings::TString< character > String
LocalString< 256 > String256
strings::TAString< character, lang::HeapAllocator > AString
todox
Definition doxyfile.cpp:20