From c92d4e28047e06ad35138a70d19f54320c15f1f6 Mon Sep 17 00:00:00 2001 From: EtiShkol Date: Wed, 24 Jul 2024 13:55:36 +0300 Subject: [PATCH 01/32] create a new project --- ...a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx | Bin 0 -> 316 bytes ...c1852dcc-6139-4d86-828e-e2a4ba862cf7.vsidx | Bin 0 -> 8102 bytes Storage/.vs/Storage/v17/.suo | Bin 0 -> 29184 bytes Storage/.vs/Storage/v17/Browse.VC.db | Bin 0 -> 401408 bytes Storage/Storage.sln | 31 ++++ Storage/Storage.vcxproj | 135 ++++++++++++++++++ Storage/Storage.vcxproj.filters | 22 +++ Storage/Storage.vcxproj.user | 4 + Storage/main.c | 3 + Storage/x64/Debug/Storage.exe.recipe | 11 ++ Storage/x64/Debug/Storage.ilk | Bin 0 -> 614336 bytes Storage/x64/Debug/Storage.log | 2 + Storage/x64/Debug/Storage.pdb | Bin 0 -> 913408 bytes .../x64/Debug/Storage.tlog/CL.command.1.tlog | Bin 0 -> 718 bytes Storage/x64/Debug/Storage.tlog/CL.read.1.tlog | Bin 0 -> 494 bytes .../x64/Debug/Storage.tlog/CL.write.1.tlog | Bin 0 -> 480 bytes Storage/x64/Debug/Storage.tlog/Cl.items.tlog | 1 + .../Debug/Storage.tlog/Storage.lastbuildstate | 2 + .../Debug/Storage.tlog/link.command.1.tlog | Bin 0 -> 1276 bytes .../x64/Debug/Storage.tlog/link.read.1.tlog | Bin 0 -> 3364 bytes .../x64/Debug/Storage.tlog/link.write.1.tlog | Bin 0 -> 518 bytes .../Storage.vcxproj.FileListAbsolute.txt | 1 + Storage/x64/Debug/vc143.idb | Bin 0 -> 19456 bytes Storage/x64/Debug/vc143.pdb | Bin 0 -> 69632 bytes 24 files changed, 212 insertions(+) create mode 100644 Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx create mode 100644 Storage/.vs/Storage/FileContentIndex/c1852dcc-6139-4d86-828e-e2a4ba862cf7.vsidx create mode 100644 Storage/.vs/Storage/v17/.suo create mode 100644 Storage/.vs/Storage/v17/Browse.VC.db create mode 100644 Storage/Storage.sln create mode 100644 Storage/Storage.vcxproj create mode 100644 Storage/Storage.vcxproj.filters create mode 100644 Storage/Storage.vcxproj.user create mode 100644 Storage/main.c create mode 100644 Storage/x64/Debug/Storage.exe.recipe create mode 100644 Storage/x64/Debug/Storage.ilk create mode 100644 Storage/x64/Debug/Storage.log create mode 100644 Storage/x64/Debug/Storage.pdb create mode 100644 Storage/x64/Debug/Storage.tlog/CL.command.1.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/CL.read.1.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/CL.write.1.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/Cl.items.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/Storage.lastbuildstate create mode 100644 Storage/x64/Debug/Storage.tlog/link.command.1.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/link.read.1.tlog create mode 100644 Storage/x64/Debug/Storage.tlog/link.write.1.tlog create mode 100644 Storage/x64/Debug/Storage.vcxproj.FileListAbsolute.txt create mode 100644 Storage/x64/Debug/vc143.idb create mode 100644 Storage/x64/Debug/vc143.pdb diff --git a/Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx b/Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx new file mode 100644 index 0000000000000000000000000000000000000000..fece554ff923fdfa4ddbdfa23fa0ce8cfdcab58b GIT binary patch literal 316 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 literal 0 HcmV?d00001 diff --git a/Storage/.vs/Storage/v17/.suo b/Storage/.vs/Storage/v17/.suo new file mode 100644 index 0000000000000000000000000000000000000000..bfb4b11c69a872f7eff4df68ef000ed16a3824cd GIT binary patch literal 29184 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 L=ueDl^Z)+?KE6V+ literal 0 HcmV?d00001 diff --git a/Storage/.vs/Storage/v17/Browse.VC.db b/Storage/.vs/Storage/v17/Browse.VC.db new file mode 100644 index 0000000000000000000000000000000000000000..6bc3edc086f9c9969f7cc7bc7dda3765b5b4594e GIT binary patch literal 401408 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 Qt<8 literal 0 HcmV?d00001 diff --git a/Storage/Storage.sln b/Storage/Storage.sln new file mode 100644 index 0000000..ac5ed1c --- /dev/null +++ b/Storage/Storage.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34024.191 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Storage", "Storage.vcxproj", "{87F686A2-A967-494F-83A5-EC11D3BEC4A6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Debug|x64.ActiveCfg = Debug|x64 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Debug|x64.Build.0 = Debug|x64 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Debug|x86.ActiveCfg = Debug|Win32 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Debug|x86.Build.0 = Debug|Win32 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Release|x64.ActiveCfg = Release|x64 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Release|x64.Build.0 = Release|x64 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Release|x86.ActiveCfg = Release|Win32 + {87F686A2-A967-494F-83A5-EC11D3BEC4A6}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F9B26603-5B16-4166-8E60-4C61D825ED23} + EndGlobalSection +EndGlobal diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj new file mode 100644 index 0000000..60771eb --- /dev/null +++ b/Storage/Storage.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {87f686a2-a967-494f-83a5-ec11d3bec4a6} + Storage + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + \ No newline at end of file diff --git a/Storage/Storage.vcxproj.filters b/Storage/Storage.vcxproj.filters new file mode 100644 index 0000000..decff76 --- /dev/null +++ b/Storage/Storage.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/Storage/Storage.vcxproj.user b/Storage/Storage.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/Storage/Storage.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Storage/main.c b/Storage/main.c new file mode 100644 index 0000000..ffc6dab --- /dev/null +++ b/Storage/main.c @@ -0,0 +1,3 @@ +int main() { + return 0; +} \ No newline at end of file diff --git a/Storage/x64/Debug/Storage.exe.recipe b/Storage/x64/Debug/Storage.exe.recipe new file mode 100644 index 0000000..b072f6b --- /dev/null +++ b/Storage/x64/Debug/Storage.exe.recipe @@ -0,0 +1,11 @@ + + + + + C:\Users\user1\Desktop\MultiDrone\Storage\x64\Debug\Storage.exe + + + + + + \ No newline at end of file diff --git a/Storage/x64/Debug/Storage.ilk b/Storage/x64/Debug/Storage.ilk new file mode 100644 index 0000000000000000000000000000000000000000..c1d49a3853a6c6731a708cf79eaffa99378a1c7a GIT binary patch literal 614336 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⋘Se>WY^<7pOhFmKF?ZiaGreUNV2 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 literal 0 HcmV?d00001 diff --git a/Storage/x64/Debug/Storage.log b/Storage/x64/Debug/Storage.log new file mode 100644 index 0000000..cc8f9ab --- /dev/null +++ b/Storage/x64/Debug/Storage.log @@ -0,0 +1,2 @@ + main.c + Storage.vcxproj -> C:\Users\user1\Desktop\MultiDrone\Storage\x64\Debug\Storage.exe diff --git a/Storage/x64/Debug/Storage.pdb b/Storage/x64/Debug/Storage.pdb new file mode 100644 index 0000000000000000000000000000000000000000..404ab40acbce90ce6b44d86396fcf3847c26af93 GIT binary patch literal 913408 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

#PNcWod*vv3%S%0G|E@d81 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

0W*ml6k&DipC2sQ4xwFJgUOIc0xXDZB&k{Fz z=?q%pChv++&kZK;*^!&P=R|Juo*TKzyE1SXaz)-pL~in)7rDuMe&idvW9@@2bd6-nz(5-ul2{Xcl=JA~$*I9H6z!YLl1F0w!+q(s{tdOQqdFgCm;wCSh4@}(Ty(E_35H;w=Hn^G>FK%DRPsyJ#v$`BXX1X%E(RLt0FgfJ0mxFyCOGvyCXMw zdm=Y^djnr*@@|gYDxM!m(HIiZt~I@)Wl6*I)|FL$xCNZ6E}J3 zJZj=5FP%v>zTV`ebE%1&ymU4-ag&$MrzURl(izpnO

unz+eJXH^q7dFi}r;wCSh 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�$fyG=o>DBx3{xHT)PV{Ha_`5?a_>P+x7#|ExpbTcfF*pJnB`q5c(Faj~^0&e%wj3VNo8fehqOR9N zz8YJmJ$kw&d8f}9!2#~;sPBic*X5kA?n6It*v5Ed8vW1xa8Z%xcR!}jZBJeK2W{1h z*z+*Em{^y7e;#~nlyh7^xcR;zEhlO3;Osh%&SPGMziJ*_u#4g4!)B*aR=JaH;+_W> zTfAf!$D6~=7Q|}F9NgRqFX}+}332!Rb?~re(N=AMzmqm{?LUa4Ieejvxni${H*Evs zrZmP36DW(>aHughxONzQYJcqeQMim((^sKKPgmM0jdrlRLmZ$D-`$I^VaWfdwDX~F zJH-0uVT`yM-n3@4yX)-Y*NJec;y-aeTq@``o_1+3{da5fIv#hC*ibojW$s7tFdn8a zZ^CNPe%k&5Y=Cz3^;MMLlk}+rZQ||Tb`eily{Qu!gh1rC!V#&3NeXrlV{K`^ZW{1k>4gAW87uq*=RMk#q$Vbrki>0 zIz~BDej(U&_m+eoz!;V1UF75GRzx+HcEkVAuK~XX{^K-IpS~=gx!V);N7GB03(!AZ z#oVtmbM(7tuL8Hyx1E94HPbFm;AZkW^ofjHI)||za3yU6XaZV*=AaE|1p+_^& zr@<-vH|DeSF%4*YU)#$VldwJq4ceni&;qmp9YH714KxJxL40jEE+2-ocs^XfjA4H| z07v+p@P*Exk9)!)Vur)nc?IJ)=3UL6WnChUb)+xQNf6^p#;WVb!!te^9`)VKi3o2b zxDkxH*(MJ3a)|cN(s%LusW;)t9tOudee1}T@Mkj?Im@^tnRl5$`W*%4(5FlP&6&sK z@XQDEz&&6wxK};b@%$L<0Y|~Rsc^e8KI{gXf+nB^2&2D|vf)4jH-g(&!XG`AdF4pH zIA@;w3S+n)ySO`scS#@xWP*`k49EjHVE3(XekS9Vc};9B)|$Fep0SJx^X%f~XR+&L z%&|{0<}GJlh5IH>cxf3YPh%YX&by574)aajY39jsj0u=0eS1G&ICX?~mp(Zey)StP zPI~4%bpss?e9(C}*2uycM~;KTlX1fe!h8h01$KjX!22LFpZUj^^s%Sl_Wa2%mN18! zd@u82`u9xcj1k!VdBzht&oO=>+}_M1>h*^M7Qc&+q7%j#d%mFW{*rq)9z<%#QXTR zxB=N<9QYFK0qxq6UeEz_2aP~F7!LBm60ib10v=M&P{x;w0vw{?DD{TA@y#*#<&QC5 zr+vF_G5poJtp8-gkIQ^2=6(295Y{G};ZEL} zx{KfOyq|$P8RjIOY@g}R76Gj3{X4x5Aco9B@$NH6iV zA^us+nKJo3_IBwIIq8xAL|^pgWMZ-UD0%dIHQsKPlRWXI~HqFde>?VGayJ zKz|Sl27rNJ5Eu-u1w+7fU?_+NF(4Mi0hW`*4ImyQfJBf4lEDbz1SudDqyd&OL0k!970d*;fmvWSm;-JHbHO}t2e=d51?~n5z)#Q$K}iy;yh?4&@gQfpdKLK=;Mq9j;Ji;rKges@{|M%ONSALl;i zoSA-o-pNx(sYXiFSB%}pE#e+%q6=Ls(iM3~=a4L*5`$e*PwB9FtW)_e4~YV5O}6iA zPe+>S06PISf6gAyMY&$Ithsm|O7Fa{EFyR4jaM z$2QHig7r#;GWr)xWe%T^b@YyXLT3Tv^$tEqWx)nhyZSM)K=+b8d5v1NfR}A9v2WxR z#{shqjdh}S{i4-=w literal 0 HcmV?d00001 diff --git a/Storage/x64/Debug/Storage.tlog/CL.read.1.tlog b/Storage/x64/Debug/Storage.tlog/CL.read.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..30a6935a2c259afb9ec808b82fba9d79425d99df GIT binary patch literal 494 zcmZ9IT~5O=5QOI$i96&36-f{v-Y7|fh0|1a+5)n;|0#fPmxxp-ioHLxGqe8w`qZ-? zRdiHVuf(~=HE~BZ>s7NR9mq$Jku1|#>_Gmy*wBq&SB-6o zsAbs9Lq#+bchn~Ejc)iGq8^=@Gw}w=Cv58zY=!#7XD&=3FV$MNY~SkM&qfam)0S!5 u?}Zstd($1r@^{y0wtNNdh?l^8M-(r1{Qr(w@6Oeu-@4zK*G#_k<@67X?nkKr literal 0 HcmV?d00001 diff --git a/Storage/x64/Debug/Storage.tlog/CL.write.1.tlog b/Storage/x64/Debug/Storage.tlog/CL.write.1.tlog new file mode 100644 index 0000000000000000000000000000000000000000..fcc3e5a5bd603383c3f28cc5a5f839a5d0ecd732 GIT binary patch literal 480 zcmc(bOA3QP5JYP&Ry*wxe|Fz8dS*f zo;U)(Q3q8T)v1R!Ox7@q=z5zL#M&A5H`!l;=IUsuzB0~Tm?@_O%K)s0eG0?u0|jck^H}FP zE4)KI+Rih;tEXd_p>A}j12x!>@NKF7Z#v3akI_43)m1}{>5IrCCeN7tkc`s8l2QfJ zxhuD7%mlAa5wk~*DXYz@fm)TVYN<|jLN!uu4Y6!qpp3Sub5dd6Ih{H0(RZ=8F(S@g zJW_5e#|c1h$tL>~E!VYEQ`KXt<4P2d1@6tt@ke0R6I(5PP9fDS^EPONlCq_N@_@=D zy5e4|sJ%!P8^N)Tt!tr~zE}%g=tvJ*>5g(Mo+Y$!XsGqeBh z9A96aZDbGDSZ$?cR`7kF_n41aEp2X=djm*>B*`eqo7CJ-xG`-5#V< zB&J?6L279+oT)w9rCl7(UVBYbFTb$JCh$3bZe&-svwO5%qhagi$H;FvF#=W2xkB8t z8@>)YJy0<#vGo~4em&;msKMW$u|+rMjKbf**#NHipyBV4b=C+A)fAiOfxT4g6D7X6 zVz_{8I0Dat7jt-jSawW6wINp5!CAAk88PV?VZE3}+LQbm!Lso-H^&y;mx&lo~ zwF%9uT2vz<@oQvV9r%l?{IS|LWHCoZOUWCmvwQy41*ij1{a5uDz4W!dqt!i3;B0$_ zm|X|&cj~J;jU0=q$B?!O+9R@74pn;$5wnW9YSIb}eJZ@_eZ!ecc2wKdSx7=X$_8x> z>usITi!Rt{S9^3TF*dmK-##5jtEuZKx{jff&|S~-?=bJ9yf)^w65c|6-Z>E)=8a^} z0Rb4*nU)RcuuGS*VYXcRu)~`uXsVWdVvY6kBYM1LbTYP zsuq@zS%{Uqa?n7kfg%AC=o5jD*?ekkr&&V~&Tsx&{ql6b^eH_#mfpHQ^+wKFLB)5q zVfmp|^Xjg)yr8DyX0=|?-A!LP?Xgj?9H_SerktJ&Bgc)`=vXb+RzA)t-jwU%KCHWP z5Zx1B6C>YvRa_8X7vB~qIml6|&xt3*&&A_nX!lhCOHm|10%s7wJ|21f-L5g~(r${2 zUFY$yfLKG^;RBBNL`PU=hG~l_CKW7)}Dn(>3MM|D5FY%nl6LK)-yqJ$mqS z@-A`vbc1la6mc`jhtu>M-^JneVO4w;wyHJ5o=CoFe)m)M2dgx3S4u(oK;7 z3G|Qv;vakb^YZ#h?Dp_hxHJinK%WUP|JP^Wyc`K!A_B<&nc|D&|FGvro}KwWfk2VK z024qipCSPgAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*_&*3713Qh! AB>(^b literal 0 HcmV?d00001 diff --git a/Storage/x64/Debug/vc143.pdb b/Storage/x64/Debug/vc143.pdb new file mode 100644 index 0000000000000000000000000000000000000000..01e55a93fcb4459a21c63457e8eedc3d22bf366f GIT binary patch literal 69632 zcmeI*&2JM&7{KANO+r5SNORzTdRRpWS|Pjsh#-o3p>`ZnNK)zqqG}~%*6Vat+iUIG zkP4|BxgaDY{(zh+PDmWMAuil{s<{JkPwGdO5iurn_aK7 zvop`m#$J17GU`~K>$~}ik^CZg_^>gWNgGEa(dh23{i%$S)T2~D7N1BA=*N;|6A1wX z5I_I{1Q0*~0R#|0009KHk-%>|UoVmnKmY**5I_I{1Q0*~0R#|0;KLT^`Rl{3AGJdO z0R#|0009ILKmY**5I_Kd#l^m3N_A!eDt|es#^*xn;H{AAI}lV?9x4^R6H-rJhE(rV zP~Dvis6)>J>gJ1(x>Qyw{Xj+q)CU6WQ5`*%MxO@;2Q(yDB7gt_2q1s}0tg_000Iag zuw?{#UIog_0tg_000IagfB*srAb$Z~P9*3)12`ENvHdjBpJ=xs~@!2JILL_z=o1Q0*~0R#|0 z009ILKwt|CG~fU4m7Dut{HA-CG}!qKCar9 zwj~G6N#FK-vnoGhX3F+|sJLZwv|6Y*DbFq0W~SnL*=buX%zOXt^Nr_Dd)cCqb_%v{ zjyjg-`fk2roOb+bwqRr`)tuv+@n}454wWjlSN0s=Hcuzb3D+&i4jEaE^+ys%BZ>Hc z{L(q6WFB|@%G8m5b4DV0GGfo@W4^8*Gi({*??#O9*P}@zTyhKUv}=UVBqXN7MmXnW zr%STCWBG%YTc{RGM%d34jPQ8Q2&c}bhQ68{)+@>JvCR0%A-y^|Hj*4q>DA@6;i6t!srTzkSP6`Yc+ zmTj--_`Y-AmR!^Bx}lfqpR&(Yr%kE}aJlFH=vg=i(if*wiwHoP@qiyzCc1l*EnzQ@X&R+f9sPjf!Q?^nl<}Gu5 zhkJLMJyxA@3QpGh(L9}5GgITUnSmppn`fL-&b{CpC!C6J#-ip(t=h60iALh_Bk@=y zYE~_;vI0V1mwzv$^1u-l*H#3iF@(u8C!p%j?aw zram?_k)Fz=PMH0Xfo1=y7Fxav{^u6{*5j!8u0ZYY?xy|ae50+u^}wwkZk0yAM((Y& zG~N2upY^uB_E~8u+jpGdR`OcD7&fWOwFa!)e4pB}PtWBOlGo!M5^WOg5<4Y2BswL2 z7Mm_vuGwH)sZP@+)MABJzm}%d{GR$b)bA@ImYPr3AHUaYmAvllSD}4vOYd0pHyyhq zc1v_iEX?coG9&~LKmY**J{E!I`+vUw|5(mC^+W&x1Q0*~0R#|0009IL_}B#cj>&fe znSjb)4yy6FkUDrPr1}m7)s=@zMel^vlb0dYI~7!S=K|``vw*t!BBU;rl}bO5-v9E+ zxlZ)|uQ~7&0R#|0009ILKmY**5I_Kdtt!y`{XhNx>Hoj#SdFG31oZ!Z*Kh;+|1Xb8 zSnl%tX5aW$x*D&yt3LhzH(}%y{r{T>)zJTcwed#u|KF-_>nIlj2q1s}0&5CfkHiAk z9?j;1@>^pU@3*~r8XTD|-M*K&@%(CIM?KG9W3Io(w#TOuD>pTsVu=6(2q1s}0tg_0 z00IagfB*tpOhC^Wr04(F^ZQNI%hu6Z>)Nm9`fHciBhf9fTSEU|fL#(K1Q0*~0R#|0 q009ILKmY**5ZFEfd$&(fDJcR7Ab Date: Wed, 24 Jul 2024 13:58:13 +0300 Subject: [PATCH 02/32] delete unwanted files --- .gitignore | 5 ++++ ...a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx | Bin 316 -> 0 bytes ...c1852dcc-6139-4d86-828e-e2a4ba862cf7.vsidx | Bin 8102 -> 0 bytes Storage/.vs/Storage/v17/.suo | Bin 29184 -> 0 bytes Storage/.vs/Storage/v17/Browse.VC.db | Bin 401408 -> 0 bytes Storage/Storage.vcxproj.filters | 22 ------------------ Storage/Storage.vcxproj.user | 4 ---- Storage/x64/Debug/Storage.exe.recipe | 11 --------- Storage/x64/Debug/Storage.ilk | Bin 614336 -> 0 bytes Storage/x64/Debug/Storage.log | 2 -- Storage/x64/Debug/Storage.pdb | Bin 913408 -> 0 bytes .../x64/Debug/Storage.tlog/CL.command.1.tlog | Bin 718 -> 0 bytes Storage/x64/Debug/Storage.tlog/CL.read.1.tlog | Bin 494 -> 0 bytes .../x64/Debug/Storage.tlog/CL.write.1.tlog | Bin 480 -> 0 bytes Storage/x64/Debug/Storage.tlog/Cl.items.tlog | 1 - .../Debug/Storage.tlog/Storage.lastbuildstate | 2 -- .../Debug/Storage.tlog/link.command.1.tlog | Bin 1276 -> 0 bytes .../x64/Debug/Storage.tlog/link.read.1.tlog | Bin 3364 -> 0 bytes .../x64/Debug/Storage.tlog/link.write.1.tlog | Bin 518 -> 0 bytes .../Storage.vcxproj.FileListAbsolute.txt | 1 - Storage/x64/Debug/vc143.idb | Bin 19456 -> 0 bytes Storage/x64/Debug/vc143.pdb | Bin 69632 -> 0 bytes 22 files changed, 5 insertions(+), 43 deletions(-) delete mode 100644 Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx delete mode 100644 Storage/.vs/Storage/FileContentIndex/c1852dcc-6139-4d86-828e-e2a4ba862cf7.vsidx delete mode 100644 Storage/.vs/Storage/v17/.suo delete mode 100644 Storage/.vs/Storage/v17/Browse.VC.db delete mode 100644 Storage/Storage.vcxproj.filters delete mode 100644 Storage/Storage.vcxproj.user delete mode 100644 Storage/x64/Debug/Storage.exe.recipe delete mode 100644 Storage/x64/Debug/Storage.ilk delete mode 100644 Storage/x64/Debug/Storage.log delete mode 100644 Storage/x64/Debug/Storage.pdb delete mode 100644 Storage/x64/Debug/Storage.tlog/CL.command.1.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/CL.read.1.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/CL.write.1.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/Cl.items.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/Storage.lastbuildstate delete mode 100644 Storage/x64/Debug/Storage.tlog/link.command.1.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/link.read.1.tlog delete mode 100644 Storage/x64/Debug/Storage.tlog/link.write.1.tlog delete mode 100644 Storage/x64/Debug/Storage.vcxproj.FileListAbsolute.txt delete mode 100644 Storage/x64/Debug/vc143.idb delete mode 100644 Storage/x64/Debug/vc143.pdb diff --git a/.gitignore b/.gitignore index 259148f..9830da2 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,8 @@ *.exe *.out *.app + +/Storage/x64 +/Storage/.vs +*.user +*.filters diff --git a/Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx b/Storage/.vs/Storage/FileContentIndex/a56e98ba-9bab-4e7e-97a6-5a8c9ceb3ee1.vsidx deleted file mode 100644 index fece554ff923fdfa4ddbdfa23fa0ce8cfdcab58b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 316 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 diff --git a/Storage/.vs/Storage/v17/.suo b/Storage/.vs/Storage/v17/.suo deleted file mode 100644 index bfb4b11c69a872f7eff4df68ef000ed16a3824cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29184 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 L=ueDl^Z)+?KE6V+ diff --git a/Storage/.vs/Storage/v17/Browse.VC.db b/Storage/.vs/Storage/v17/Browse.VC.db deleted file mode 100644 index 6bc3edc086f9c9969f7cc7bc7dda3765b5b4594e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 401408 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 Qt<8 diff --git a/Storage/Storage.vcxproj.filters b/Storage/Storage.vcxproj.filters deleted file mode 100644 index decff76..0000000 --- a/Storage/Storage.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/Storage/Storage.vcxproj.user b/Storage/Storage.vcxproj.user deleted file mode 100644 index 88a5509..0000000 --- a/Storage/Storage.vcxproj.user +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Storage/x64/Debug/Storage.exe.recipe b/Storage/x64/Debug/Storage.exe.recipe deleted file mode 100644 index b072f6b..0000000 --- a/Storage/x64/Debug/Storage.exe.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\user1\Desktop\MultiDrone\Storage\x64\Debug\Storage.exe - - - - - - \ No newline at end of file diff --git a/Storage/x64/Debug/Storage.ilk b/Storage/x64/Debug/Storage.ilk deleted file mode 100644 index c1d49a3853a6c6731a708cf79eaffa99378a1c7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 614336 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⋘Se>WY^<7pOhFmKF?ZiaGreUNV2 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 diff --git a/Storage/x64/Debug/Storage.log b/Storage/x64/Debug/Storage.log deleted file mode 100644 index cc8f9ab..0000000 --- a/Storage/x64/Debug/Storage.log +++ /dev/null @@ -1,2 +0,0 @@ - main.c - Storage.vcxproj -> C:\Users\user1\Desktop\MultiDrone\Storage\x64\Debug\Storage.exe diff --git a/Storage/x64/Debug/Storage.pdb b/Storage/x64/Debug/Storage.pdb deleted file mode 100644 index 404ab40acbce90ce6b44d86396fcf3847c26af93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 913408 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

#PNcWod*vv3%S%0G|E@d81 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

0W*ml6k&DipC2sQ4xwFJgUOIc0xXDZB&k{Fz z=?q%pChv++&kZK;*^!&P=R|Juo*TKzyE1SXaz)-pL~in)7rDuMe&idvW9@@2bd6-nz(5-ul2{Xcl=JA~$*I9H6z!YLl1F0w!+q(s{tdOQqdFgCm;wCSh4@}(Ty(E_35H;w=Hn^G>FK%DRPsyJ#v$`BXX1X%E(RLt0FgfJ0mxFyCOGvyCXMw zdm=Y^djnr*@@|gYDxM!m(HIiZt~I@)Wl6*I)|FL$xCNZ6E}J3 zJZj=5FP%v>zTV`ebE%1&ymU4-ag&$MrzURl(izpnO

unz+eJXH^q7dFi}r;wCSh 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�$fyG=o>DBx3{xHT)PV{Ha_`5?a_>P+x7#|ExpbTcfF*pJnB`q5c(Faj~^0&e%wj3VNo8fehqOR9N zz8YJmJ$kw&d8f}9!2#~;sPBic*X5kA?n6It*v5Ed8vW1xa8Z%xcR!}jZBJeK2W{1h z*z+*Em{^y7e;#~nlyh7^xcR;zEhlO3;Osh%&SPGMziJ*_u#4g4!)B*aR=JaH;+_W> zTfAf!$D6~=7Q|}F9NgRqFX}+}332!Rb?~re(N=AMzmqm{?LUa4Ieejvxni${H*Evs zrZmP36DW(>aHughxONzQYJcqeQMim((^sKKPgmM0jdrlRLmZ$D-`$I^VaWfdwDX~F zJH-0uVT`yM-n3@4yX)-Y*NJec;y-aeTq@``o_1+3{da5fIv#hC*ibojW$s7tFdn8a zZ^CNPe%k&5Y=Cz3^;MMLlk}+rZQ||Tb`eily{Qu!gh1rC!V#&3NeXrlV{K`^ZW{1k>4gAW87uq*=RMk#q$Vbrki>0 zIz~BDej(U&_m+eoz!;V1UF75GRzx+HcEkVAuK~XX{^K-IpS~=gx!V);N7GB03(!AZ z#oVtmbM(7tuL8Hyx1E94HPbFm;AZkW^ofjHI)||za3yU6XaZV*=AaE|1p+_^& zr@<-vH|DeSF%4*YU)#$VldwJq4ceni&;qmp9YH714KxJxL40jEE+2-ocs^XfjA4H| z07v+p@P*Exk9)!)Vur)nc?IJ)=3UL6WnChUb)+xQNf6^p#;WVb!!te^9`)VKi3o2b zxDkxH*(MJ3a)|cN(s%LusW;)t9tOudee1}T@Mkj?Im@^tnRl5$`W*%4(5FlP&6&sK z@XQDEz&&6wxK};b@%$L<0Y|~Rsc^e8KI{gXf+nB^2&2D|vf)4jH-g(&!XG`AdF4pH zIA@;w3S+n)ySO`scS#@xWP*`k49EjHVE3(XekS9Vc};9B)|$Fep0SJx^X%f~XR+&L z%&|{0<}GJlh5IH>cxf3YPh%YX&by574)aajY39jsj0u=0eS1G&ICX?~mp(Zey)StP zPI~4%bpss?e9(C}*2uycM~;KTlX1fe!h8h01$KjX!22LFpZUj^^s%Sl_Wa2%mN18! zd@u82`u9xcj1k!VdBzht&oO=>+}_M1>h*^M7Qc&+q7%j#d%mFW{*rq)9z<%#QXTR zxB=N<9QYFK0qxq6UeEz_2aP~F7!LBm60ib10v=M&P{x;w0vw{?DD{TA@y#*#<&QC5 zr+vF_G5poJtp8-gkIQ^2=6(295Y{G};ZEL} zx{KfOyq|$P8RjIOY@g}R76Gj3{X4x5Aco9B@$NH6iV zA^us+nKJo3_IBwIIq8xAL|^pgWMZ-UD0%dIHQsKPlRWXI~HqFde>?VGayJ zKz|Sl27rNJ5Eu-u1w+7fU?_+NF(4Mi0hW`*4ImyQfJBf4lEDbz1SudDqyd&OL0k!970d*;fmvWSm;-JHbHO}t2e=d51?~n5z)#Q$K}iy;yh?4&@gQfpdKLK=;Mq9j;Ji;rKges@{|M%ONSALl;i zoSA-o-pNx(sYXiFSB%}pE#e+%q6=Ls(iM3~=a4L*5`$e*PwB9FtW)_e4~YV5O}6iA zPe+>S06PISf6gAyMY&$Ithsm|O7Fa{EFyR4jaM z$2QHig7r#;GWr)xWe%T^b@YyXLT3Tv^$tEqWx)nhyZSM)K=+b8d5v1NfR}A9v2WxR z#{shqjdh}S{i4-=w diff --git a/Storage/x64/Debug/Storage.tlog/CL.read.1.tlog b/Storage/x64/Debug/Storage.tlog/CL.read.1.tlog deleted file mode 100644 index 30a6935a2c259afb9ec808b82fba9d79425d99df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 494 zcmZ9IT~5O=5QOI$i96&36-f{v-Y7|fh0|1a+5)n;|0#fPmxxp-ioHLxGqe8w`qZ-? zRdiHVuf(~=HE~BZ>s7NR9mq$Jku1|#>_Gmy*wBq&SB-6o zsAbs9Lq#+bchn~Ejc)iGq8^=@Gw}w=Cv58zY=!#7XD&=3FV$MNY~SkM&qfam)0S!5 u?}Zstd($1r@^{y0wtNNdh?l^8M-(r1{Qr(w@6Oeu-@4zK*G#_k<@67X?nkKr diff --git a/Storage/x64/Debug/Storage.tlog/CL.write.1.tlog b/Storage/x64/Debug/Storage.tlog/CL.write.1.tlog deleted file mode 100644 index fcc3e5a5bd603383c3f28cc5a5f839a5d0ecd732..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 480 zcmc(bOA3QP5JYP&Ry*wxe|Fz8dS*f zo;U)(Q3q8T)v1R!Ox7@q=z5zL#M&A5H`!l;=IUsuzB0~Tm?@_O%K)s0eG0?u0|jck^H}FP zE4)KI+Rih;tEXd_p>A}j12x!>@NKF7Z#v3akI_43)m1}{>5IrCCeN7tkc`s8l2QfJ zxhuD7%mlAa5wk~*DXYz@fm)TVYN<|jLN!uu4Y6!qpp3Sub5dd6Ih{H0(RZ=8F(S@g zJW_5e#|c1h$tL>~E!VYEQ`KXt<4P2d1@6tt@ke0R6I(5PP9fDS^EPONlCq_N@_@=D zy5e4|sJ%!P8^N)Tt!tr~zE}%g=tvJ*>5g(Mo+Y$!XsGqeBh z9A96aZDbGDSZ$?cR`7kF_n41aEp2X=djm*>B*`eqo7CJ-xG`-5#V< zB&J?6L279+oT)w9rCl7(UVBYbFTb$JCh$3bZe&-svwO5%qhagi$H;FvF#=W2xkB8t z8@>)YJy0<#vGo~4em&;msKMW$u|+rMjKbf**#NHipyBV4b=C+A)fAiOfxT4g6D7X6 zVz_{8I0Dat7jt-jSawW6wINp5!CAAk88PV?VZE3}+LQbm!Lso-H^&y;mx&lo~ zwF%9uT2vz<@oQvV9r%l?{IS|LWHCoZOUWCmvwQy41*ij1{a5uDz4W!dqt!i3;B0$_ zm|X|&cj~J;jU0=q$B?!O+9R@74pn;$5wnW9YSIb}eJZ@_eZ!ecc2wKdSx7=X$_8x> z>usITi!Rt{S9^3TF*dmK-##5jtEuZKx{jff&|S~-?=bJ9yf)^w65c|6-Z>E)=8a^} z0Rb4*nU)RcuuGS*VYXcRu)~`uXsVWdVvY6kBYM1LbTYP zsuq@zS%{Uqa?n7kfg%AC=o5jD*?ekkr&&V~&Tsx&{ql6b^eH_#mfpHQ^+wKFLB)5q zVfmp|^Xjg)yr8DyX0=|?-A!LP?Xgj?9H_SerktJ&Bgc)`=vXb+RzA)t-jwU%KCHWP z5Zx1B6C>YvRa_8X7vB~qIml6|&xt3*&&A_nX!lhCOHm|10%s7wJ|21f-L5g~(r${2 zUFY$yfLKG^;RBBNL`PU=hG~l_CKW7)}Dn(>3MM|D5FY%nl6LK)-yqJ$mqS z@-A`vbc1la6mc`jhtu>M-^JneVO4w;wyHJ5o=CoFe)m)M2dgx3S4u(oK;7 z3G|Qv;vakb^YZ#h?Dp_hxHJinK%WUP|JP^Wyc`K!A_B<&nc|D&|FGvro}KwWfk2VK z024qipCSPgAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*_&*3713Qh! AB>(^b diff --git a/Storage/x64/Debug/vc143.pdb b/Storage/x64/Debug/vc143.pdb deleted file mode 100644 index 01e55a93fcb4459a21c63457e8eedc3d22bf366f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69632 zcmeI*&2JM&7{KANO+r5SNORzTdRRpWS|Pjsh#-o3p>`ZnNK)zqqG}~%*6Vat+iUIG zkP4|BxgaDY{(zh+PDmWMAuil{s<{JkPwGdO5iurn_aK7 zvop`m#$J17GU`~K>$~}ik^CZg_^>gWNgGEa(dh23{i%$S)T2~D7N1BA=*N;|6A1wX z5I_I{1Q0*~0R#|0009KHk-%>|UoVmnKmY**5I_I{1Q0*~0R#|0;KLT^`Rl{3AGJdO z0R#|0009ILKmY**5I_Kd#l^m3N_A!eDt|es#^*xn;H{AAI}lV?9x4^R6H-rJhE(rV zP~Dvis6)>J>gJ1(x>Qyw{Xj+q)CU6WQ5`*%MxO@;2Q(yDB7gt_2q1s}0tg_000Iag zuw?{#UIog_0tg_000IagfB*srAb$Z~P9*3)12`ENvHdjBpJ=xs~@!2JILL_z=o1Q0*~0R#|0 z009ILKwt|CG~fU4m7Dut{HA-CG}!qKCar9 zwj~G6N#FK-vnoGhX3F+|sJLZwv|6Y*DbFq0W~SnL*=buX%zOXt^Nr_Dd)cCqb_%v{ zjyjg-`fk2roOb+bwqRr`)tuv+@n}454wWjlSN0s=Hcuzb3D+&i4jEaE^+ys%BZ>Hc z{L(q6WFB|@%G8m5b4DV0GGfo@W4^8*Gi({*??#O9*P}@zTyhKUv}=UVBqXN7MmXnW zr%STCWBG%YTc{RGM%d34jPQ8Q2&c}bhQ68{)+@>JvCR0%A-y^|Hj*4q>DA@6;i6t!srTzkSP6`Yc+ zmTj--_`Y-AmR!^Bx}lfqpR&(Yr%kE}aJlFH=vg=i(if*wiwHoP@qiyzCc1l*EnzQ@X&R+f9sPjf!Q?^nl<}Gu5 zhkJLMJyxA@3QpGh(L9}5GgITUnSmppn`fL-&b{CpC!C6J#-ip(t=h60iALh_Bk@=y zYE~_;vI0V1mwzv$^1u-l*H#3iF@(u8C!p%j?aw zram?_k)Fz=PMH0Xfo1=y7Fxav{^u6{*5j!8u0ZYY?xy|ae50+u^}wwkZk0yAM((Y& zG~N2upY^uB_E~8u+jpGdR`OcD7&fWOwFa!)e4pB}PtWBOlGo!M5^WOg5<4Y2BswL2 z7Mm_vuGwH)sZP@+)MABJzm}%d{GR$b)bA@ImYPr3AHUaYmAvllSD}4vOYd0pHyyhq zc1v_iEX?coG9&~LKmY**J{E!I`+vUw|5(mC^+W&x1Q0*~0R#|0009IL_}B#cj>&fe znSjb)4yy6FkUDrPr1}m7)s=@zMel^vlb0dYI~7!S=K|``vw*t!BBU;rl}bO5-v9E+ zxlZ)|uQ~7&0R#|0009ILKmY**5I_Kdtt!y`{XhNx>Hoj#SdFG31oZ!Z*Kh;+|1Xb8 zSnl%tX5aW$x*D&yt3LhzH(}%y{r{T>)zJTcwed#u|KF-_>nIlj2q1s}0&5CfkHiAk z9?j;1@>^pU@3*~r8XTD|-M*K&@%(CIM?KG9W3Io(w#TOuD>pTsVu=6(2q1s}0tg_0 z00IagfB*tpOhC^Wr04(F^ZQNI%hu6Z>)Nm9`fHciBhf9fTSEU|fL#(K1Q0*~0R#|0 q009ILKmY**5ZFEfd$&(fDJcR7Ab Date: Mon, 5 Aug 2024 12:50:32 +0300 Subject: [PATCH 03/32] add new branch --- Storage/Disk_Mng_Master.c | 0 Storage/Disk_Mng_Master.h | 1 + 2 files changed, 1 insertion(+) create mode 100644 Storage/Disk_Mng_Master.c create mode 100644 Storage/Disk_Mng_Master.h diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c new file mode 100644 index 0000000..e69de29 diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/Storage/Disk_Mng_Master.h @@ -0,0 +1 @@ +#pragma once From e4e0b249dec336803e2078a15e845a74c27daa65 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 5 Aug 2024 16:22:14 +0300 Subject: [PATCH 04/32] new changes --- Storage/{main.c => .c} | 0 Storage/Disk_Mng_Master.c | 94 + Storage/Disk_Mng_Master.h | 62 + Storage/Disk_Mng_Master_API.h | 0 Storage/Doctest.cpp | 83 + Storage/Storage.vcxproj | 8 +- Storage/doctest.h | 7164 +++++++++++++++++++++++++++++++++ 7 files changed, 7410 insertions(+), 1 deletion(-) rename Storage/{main.c => .c} (100%) create mode 100644 Storage/Disk_Mng_Master.c create mode 100644 Storage/Disk_Mng_Master.h create mode 100644 Storage/Disk_Mng_Master_API.h create mode 100644 Storage/Doctest.cpp create mode 100644 Storage/doctest.h diff --git a/Storage/main.c b/Storage/.c similarity index 100% rename from Storage/main.c rename to Storage/.c diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c new file mode 100644 index 0000000..67a7ffd --- /dev/null +++ b/Storage/Disk_Mng_Master.c @@ -0,0 +1,94 @@ + +#include "Disk_Mng_Master.h" +#pragma once +#include +#include +#include + + Disk_Managment_CB_t* disk_mng_CB; + +void disk_mng_initialize_CB() +{ + disk_mng_CB = (Disk_Managment_CB_t*)allocate_memory(sizeof(Disk_Managment_CB_t), "Failed to allocate memory for disk control block", "disk_mng_initialize_CB"); +} + +void disk_mng_initialize() +{ + disk_mng_initialize_CB(); + stack_initialize(); + +} +void stack_initialize() { + disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_initialize"); + disk_mng_CB->diskFreeIndexesInArray->top = NULL; + + //API call if its first time or ot +} + +bool stack_is_empty() { + return disk_mng_CB->diskFreeIndexesInArray->top == NULL; +} + +StackNode_t* stackNode_create(int index) +{ + StackNode_t* new_node = (StackNode_t*)allocate_memory(sizeof(StackNode_t), "Failed to allocate memory for max heap", "stack_push"); + new_node->freeIndex = index; + new_node->next = disk_mng_CB->diskFreeIndexesInArray->top; + return new_node; +} + + +void stack_push(StackNode_t* new_node) +{ + disk_mng_CB->diskFreeIndexesInArray->top = new_node; +} + +int stack_pop() { + if (stack_is_empty(disk_mng_CB->diskFreeIndexesInArray)) { + return -1; + } + StackNode_t* temp = disk_mng_CB->diskFreeIndexesInArray->top; + int value = temp->freeIndex; + disk_mng_CB->diskFreeIndexesInArray->top = disk_mng_CB->diskFreeIndexesInArray->top->next; + free(temp); + return value; +} + +int stack_top(DiskFreeIndexesInArray_t* stack) { + if (stack_is_empty(stack)) { + return -1; + } + return stack->top->freeIndex; +} + +void test_writeExceptionToFile(Exception exception, const char* source) { + FILE* file; + errno_t err = fopen_s(&file, "errors.log.txt", "a"); + if (err != 0) { + fprintf(stderr, "Error opening file for writing\n"); + return; + } + + const char* error_message; + switch (exception) { + case Error_When_Allocating_Memory_Space: + error_message = "Error: Error when allocating memory space."; + break; + default: + error_message = "Error: Unknown exception."; + break; + } + + fprintf(file, "%s:\n%s\n", source, error_message); + fclose(file); +} + +void* allocate_memory(size_t size, const char* description, const char* functionName) { + void* ptr = malloc(size); + if (ptr == NULL) { + test_writeExceptionToFile(Error_When_Allocating_Memory_Space, functionName); + perror(description); + return NULL; + } + return ptr; +} diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h new file mode 100644 index 0000000..43f76c5 --- /dev/null +++ b/Storage/Disk_Mng_Master.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +#include + +#define DISK_SIZE 1000 + +// Forward declarations + +typedef struct StackNode_s StackNode_t; +typedef struct DiskFreeIndexesInArray_s DiskFreeIndexesInArray_t; +typedef struct Disk_Management_CB_s Disk_Managment_CB_t; + +// Enum declaration +typedef enum { + Error_When_Allocating_Memory_Space + +}Exception; + +// Struct declarations + +struct StackNode_s { + int freeIndex; + StackNode_t* next; +}; + +struct DiskFreeIndexesInArray_s { + StackNode_t* top; +}; +struct Disk_Management_CB_s { + StackNode_t* stackNode; + DiskFreeIndexesInArray_t* diskFreeIndexesInArray; +}; +extern Disk_Managment_CB_t* disk_mng_CB; + +void* allocate_memory(size_t size, const char* description, const char* functionName); + +void test_writeExceptionToFile(Exception exception, char* source); + +//disk managment + +//initialize the disk managment CB + +void disk_mng_initialize_CB(); + +//initialize the cache mapping +void disk_mng_initialize(); + +//stack functions + +void stack_initialize(); + +bool stack_is_empty(); + +void stack_push(StackNode_t* new_node); + +StackNode_t* stackNode_create(int index); + +int stack_pop(); + +int stack_top(); + diff --git a/Storage/Disk_Mng_Master_API.h b/Storage/Disk_Mng_Master_API.h new file mode 100644 index 0000000..e69de29 diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp new file mode 100644 index 0000000..b05213a --- /dev/null +++ b/Storage/Doctest.cpp @@ -0,0 +1,83 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "doctest.h" +#include +#include + +extern "C" { +#include "Disk_Mng_Master.h" +#include "Disk_Mng_Master_API.h" +} +struct GlobalSetup { + GlobalSetup() { + srand(time(0)); + } +}; +GlobalSetup globalSetup; + +int generateRandomNumber() { + int lower = 0; + int upper = DISK_SIZE; + return (rand() % (upper - lower + 1)) + lower; +} +int index, popValue,value; +StackNode_t* newStackNode; + +//stack tests + +//TEST_CASE("test_stack_initilaizeWithEmptyIndexes") +//{ +// CHECK(disk_mng_CB->diskFreeIndexesInArray->top == NULL); +//} +TEST_CASE("test_stack_push") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + newStackNode = stackNode_create(index); + stack_push(newStackNode); + popValue = stack_pop(); + CHECK(popValue == index); + } + +} +TEST_CASE("test_stack_pop") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + newStackNode = stackNode_create(index); + stack_push(newStackNode); + value = stack_pop(); + CHECK(value !=stack_top()); + } +} +TEST_CASE("test_stack_top") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + newStackNode = stackNode_create(index); + stack_push(newStackNode); + value = stack_pop(); + CHECK(value == index); + } +} +TEST_CASE("test_stack_is_empty") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + newStackNode = stackNode_create(index); + stack_push(newStackNode); + } + for (size_t i = 0; i < DISK_SIZE; i++) + { + stack_pop(); + } + CHECK(stack_is_empty() == TRUE); + +} diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index 60771eb..b7c3950 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -127,7 +127,13 @@ - + + + + + + + diff --git a/Storage/doctest.h b/Storage/doctest.h new file mode 100644 index 0000000..b467be2 --- /dev/null +++ b/Storage/doctest.h @@ -0,0 +1,7164 @@ +#pragma once +// ====================================================================== lgtm [cpp/missing-header-guard] +// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == +// ====================================================================== +// +// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD +// +// Copyright (c) 2016-2023 Viktor Kirilov +// +// Distributed under the MIT Software License +// See accompanying file LICENSE.txt or copy at +// https://opensource.org/licenses/MIT +// +// The documentation can be found at the library's page: +// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= +// +// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2 +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt +// +// The concept of subcases (sections in Catch) and expression decomposition are from there. +// Some parts of the code are taken directly: +// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<> +// - the Approx() helper class for floating point comparison +// - colors in the console +// - breaking into a debugger +// - signal / SEH handling +// - timer +// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste) +// +// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= + +#ifndef DOCTEST_LIBRARY_INCLUDED +#define DOCTEST_LIBRARY_INCLUDED + +// ================================================================================================= +// == VERSION ====================================================================================== +// ================================================================================================= + +#define DOCTEST_VERSION_MAJOR 2 +#define DOCTEST_VERSION_MINOR 4 +#define DOCTEST_VERSION_PATCH 11 + +// util we need here +#define DOCTEST_TOSTR_IMPL(x) #x +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) + +#define DOCTEST_VERSION_STR \ + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) + +#define DOCTEST_VERSION \ + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + +// ================================================================================================= +// == COMPILER VERSION ============================================================================= +// ================================================================================================= + +// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect + +#ifdef _MSC_VER +#define DOCTEST_CPLUSPLUS _MSVC_LANG +#else +#define DOCTEST_CPLUSPLUS __cplusplus +#endif + +#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH)) + +// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl... +#if defined(_MSC_VER) && defined(_MSC_FULL_VER) +#if _MSC_VER == _MSC_FULL_VER / 10000 +#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) +#else // MSVC +#define DOCTEST_MSVC \ + DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) +#endif // MSVC +#endif // MSVC +#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ + !defined(__INTEL_COMPILER) +#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#endif // GCC +#if defined(__INTEL_COMPILER) +#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif // ICC + +#ifndef DOCTEST_MSVC +#define DOCTEST_MSVC 0 +#endif // DOCTEST_MSVC +#ifndef DOCTEST_CLANG +#define DOCTEST_CLANG 0 +#endif // DOCTEST_CLANG +#ifndef DOCTEST_GCC +#define DOCTEST_GCC 0 +#endif // DOCTEST_GCC +#ifndef DOCTEST_ICC +#define DOCTEST_ICC 0 +#endif // DOCTEST_ICC + +// ================================================================================================= +// == COMPILER WARNINGS HELPERS ==================================================================== +// ================================================================================================= + +#if DOCTEST_CLANG && !DOCTEST_ICC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) +#else // DOCTEST_CLANG +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_CLANG + +#if DOCTEST_GCC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") +#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) +#else // DOCTEST_GCC +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH +#define DOCTEST_GCC_SUPPRESS_WARNING(w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_GCC + +#if DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) +#else // DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_MSVC + +// ================================================================================================= +// == COMPILER WARNINGS ============================================================================ +// ================================================================================================= + +// both the header and the implementation suppress all of these, +// so it only makes sense to aggregate them like so +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* common ones */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") +DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP + +// ================================================================================================= +// == FEATURE DETECTION ============================================================================ +// ================================================================================================= + +// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support +// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx +// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html +// MSVC version table: +// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering +// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) +// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) +// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) +// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) +// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) +// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) +// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) +// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) +// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) + +// Universal Windows Platform support +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_WINDOWS_SEH +#endif // WINAPI_FAMILY +#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) +#define DOCTEST_CONFIG_WINDOWS_SEH +#endif // MSVC +#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH) +#undef DOCTEST_CONFIG_WINDOWS_SEH +#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH + +#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ + !defined(__EMSCRIPTEN__) && !defined(__wasi__) +#define DOCTEST_CONFIG_POSIX_SIGNALS +#endif // _WIN32 +#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) +#undef DOCTEST_CONFIG_POSIX_SIGNALS +#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ + || defined(__wasi__) +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // no exceptions +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS) +#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef __wasi__ +#define DOCTEST_CONFIG_NO_MULTITHREADING +#endif + +#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT) +#define DOCTEST_CONFIG_IMPLEMENT +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#if defined(_WIN32) || defined(__CYGWIN__) +#if DOCTEST_MSVC +#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport) +#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport) +#else // MSVC +#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport)) +#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport)) +#endif // MSVC +#else // _WIN32 +#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default"))) +#define DOCTEST_SYMBOL_IMPORT +#endif // _WIN32 + +#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#ifdef DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT +#else // DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT +#endif // DOCTEST_CONFIG_IMPLEMENT +#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#define DOCTEST_INTERFACE +#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL + +// needed for extern template instantiations +// see https://github.com/fmtlib/fmt/issues/2228 +#if DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL +#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE +#else // DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE +#define DOCTEST_INTERFACE_DEF +#endif // DOCTEST_MSVC + +#define DOCTEST_EMPTY + +#if DOCTEST_MSVC +#define DOCTEST_NOINLINE __declspec(noinline) +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) +#define DOCTEST_NOINLINE +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#else +#define DOCTEST_NOINLINE __attribute__((noinline)) +#define DOCTEST_UNUSED __attribute__((unused)) +#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) +#endif + +#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE +#define DOCTEST_INLINE_NOINLINE inline +#else +#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE +#endif + +#ifndef DOCTEST_NORETURN +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NORETURN +#else // DOCTEST_MSVC +#define DOCTEST_NORETURN [[noreturn]] +#endif // DOCTEST_MSVC +#endif // DOCTEST_NORETURN + +#ifndef DOCTEST_NOEXCEPT +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NOEXCEPT +#else // DOCTEST_MSVC +#define DOCTEST_NOEXCEPT noexcept +#endif // DOCTEST_MSVC +#endif // DOCTEST_NOEXCEPT + +#ifndef DOCTEST_CONSTEXPR +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_CONSTEXPR const +#define DOCTEST_CONSTEXPR_FUNC inline +#else // DOCTEST_MSVC +#define DOCTEST_CONSTEXPR constexpr +#define DOCTEST_CONSTEXPR_FUNC constexpr +#endif // DOCTEST_MSVC +#endif // DOCTEST_CONSTEXPR + +#ifndef DOCTEST_NO_SANITIZE_INTEGER +#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0) +#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer"))) +#else +#define DOCTEST_NO_SANITIZE_INTEGER +#endif +#endif // DOCTEST_NO_SANITIZE_INTEGER + +// ================================================================================================= +// == FEATURE DETECTION END ======================================================================== +// ================================================================================================= + +#define DOCTEST_DECLARE_INTERFACE(name) \ + virtual ~name(); \ + name() = default; \ + name(const name&) = delete; \ + name(name&&) = delete; \ + name& operator=(const name&) = delete; \ + name& operator=(name&&) = delete; + +#define DOCTEST_DEFINE_INTERFACE(name) \ + name::~name() = default; + +// internal macros for string concatenation and anonymous variable name generation +#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#ifdef __COUNTER__ // not standard and may be missing for some compilers +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) +#else // __COUNTER__ +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) +#endif // __COUNTER__ + +#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x& +#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x +#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE + +// not using __APPLE__ because... this is how Catch does it +#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED +#define DOCTEST_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define DOCTEST_PLATFORM_IPHONE +#elif defined(_WIN32) +#define DOCTEST_PLATFORM_WINDOWS +#elif defined(__wasi__) +#define DOCTEST_PLATFORM_WASI +#else // DOCTEST_PLATFORM +#define DOCTEST_PLATFORM_LINUX +#endif // DOCTEST_PLATFORM + +namespace doctest { + namespace detail { + static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } + } +} + +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#ifndef DOCTEST_BREAK_INTO_DEBUGGER +// should probably take a look at https://github.com/scottt/debugbreak +#ifdef DOCTEST_PLATFORM_LINUX +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +// Break at the location of the failing check if possible +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#else +#include +#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) +#endif +#elif defined(DOCTEST_PLATFORM_MAC) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#elif defined(__ppc__) || defined(__ppc64__) +// https://www.cocoawithlove.com/2008/03/break-into-debugger.html +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) +#else +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) +#endif +#elif DOCTEST_MSVC +#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() +#elif defined(__MINGW32__) +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") +extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() +#else // linux +#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) +#endif // linux +#endif // DOCTEST_BREAK_INTO_DEBUGGER + +// this is kept here for backwards compatibility since the config option was changed +#ifdef DOCTEST_CONFIG_USE_IOSFWD +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // DOCTEST_CONFIG_USE_IOSFWD + +// for clang - always include ciso646 (which drags some std stuff) because +// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in +// which case we don't want to forward declare stuff from std - for reference: +// https://github.com/doctest/doctest/issues/126 +// https://github.com/doctest/doctest/issues/356 +#if DOCTEST_CLANG +#include +#endif // clang + +#ifdef _LIBCPP_VERSION +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // _LIBCPP_VERSION + +#ifdef DOCTEST_CONFIG_USE_STD_HEADERS +#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN +#include +#include +#include +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END +#else // DOCTEST_CONFIG_USE_STD_HEADERS + +// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) + +namespace std { // NOLINT(cert-dcl58-cpp) + typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) + typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) + template + struct char_traits; + template <> + struct char_traits; + template + class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) + typedef basic_ostream> ostream; // NOLINT(modernize-use-using) + template + // NOLINTNEXTLINE + basic_ostream& operator<<(basic_ostream&, const char*); + template + class basic_istream; + typedef basic_istream> istream; // NOLINT(modernize-use-using) + template + class tuple; +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + template + class allocator; + template + class basic_string; + using string = basic_string, allocator>; +#endif // VS 2019 +} // namespace std + +DOCTEST_MSVC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_USE_STD_HEADERS + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#include +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + +namespace doctest { + + using std::size_t; + + DOCTEST_INTERFACE extern bool is_running_in_test; + +#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE +#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned +#endif + + // A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length + // of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: + // - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) + // - if small - capacity left before going on the heap - using the lowest 5 bits + // - if small - 2 bits are left unused - the second and third highest ones + // - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) + // and the "is small" bit remains "0" ("as well as the capacity left") so its OK + // Idea taken from this lecture about the string implementation of facebook/folly - fbstring + // https://www.youtube.com/watch?v=kPR8h4-qZdk + // TODO: + // - optimizations - like not deleting memory unnecessarily in operator= and etc. + // - resize/reserve/clear + // - replace + // - back/front + // - iterator stuff + // - find & friends + // - push_back/pop_back + // - assign/insert/erase + // - relational operators as free functions - taking const char* as one of the params + class DOCTEST_INTERFACE String + { + public: + using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; + + private: + static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + + struct view // len should be more than sizeof(view) - because of the final byte for flags + { + char* ptr; + size_type size; + size_type capacity; + }; + + union + { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; + }; + + char* allocate(size_type sz); + + bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } + void setOnHeap() noexcept; + void setLast(size_type in = last) noexcept; + void setSize(size_type sz) noexcept; + + void copy(const String& other); + + public: + static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); + + String() noexcept; + ~String(); + + // cppcheck-suppress noExplicitConstructor + String(const char* in); + String(const char* in, size_type in_size); + + String(std::istream& in, size_type in_size); + + String(const String& other); + String& operator=(const String& other); + + String& operator+=(const String& other); + + String(String&& other) noexcept; + String& operator=(String&& other) noexcept; + + char operator[](size_type i) const; + char& operator[](size_type i); + + // the only functions I'm willing to leave in the interface - available for inlining + const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT + char* c_str() { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; + } + + size_type size() const; + size_type capacity() const; + + String substr(size_type pos, size_type cnt = npos)&&; + String substr(size_type pos, size_type cnt = npos) const&; + + size_type find(char ch, size_type pos = 0) const; + size_type rfind(char ch, size_type pos = npos) const; + + int compare(const char* other, bool no_case = false) const; + int compare(const String& other, bool no_case = false) const; + + friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); + }; + + DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + + DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + + class DOCTEST_INTERFACE Contains { + public: + explicit Contains(const String& string); + + bool checkWith(const String& other) const; + + String string; + }; + + DOCTEST_INTERFACE String toString(const Contains& in); + + DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); + DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); + DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); + DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + + namespace Color { + enum Enum + { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); + } // namespace Color + + namespace assertType { + enum Enum + { + // macro traits + + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, + + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, + + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, + + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, + + is_ge = 2 * is_gt, + is_le = 2 * is_ge, + + // macro types + + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, + + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, + + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, + + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, + + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, + + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, + + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, + + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, + + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, + + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, + + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + }; + } // namespace assertType + + DOCTEST_INTERFACE const char* assertString(assertType::Enum at); + DOCTEST_INTERFACE const char* failureString(assertType::Enum at); + DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + + struct DOCTEST_INTERFACE TestCaseData + { + String m_file; // the file in which the test was registered (using String - see #350) + unsigned m_line; // the line where the test was registered + const char* m_name; // name of the test case + const char* m_test_suite; // the test suite in which the test was added + const char* m_description; + bool m_skip; + bool m_no_breaks; + bool m_no_output; + bool m_may_fail; + bool m_should_fail; + int m_expected_failures; + double m_timeout; + }; + + struct DOCTEST_INTERFACE AssertData + { + // common - for all asserts + const TestCaseData* m_test_case; + assertType::Enum m_at; + const char* m_file; + int m_line; + const char* m_expr; + bool m_failed; + + // exception-related - for all asserts + bool m_threw; + String m_exception; + + // for normal asserts + String m_decomp; + + // for specific exception-related asserts + bool m_threw_as; + const char* m_exception_type; + + class DOCTEST_INTERFACE StringContains { + private: + Contains content; + bool isContains; + + public: + StringContains(const String& str) : content(str), isContains(false) { } + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + + bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + + operator const String& () const { return content.string; } + + const char* c_str() const { return content.string.c_str(); } + } m_exception_string; + + AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string); + }; + + struct DOCTEST_INTERFACE MessageData + { + String m_string; + const char* m_file; + int m_line; + assertType::Enum m_severity; + }; + + struct DOCTEST_INTERFACE SubcaseSignature + { + String m_name; + const char* m_file; + int m_line; + + bool operator==(const SubcaseSignature& other) const; + bool operator<(const SubcaseSignature& other) const; + }; + + struct DOCTEST_INTERFACE IContextScope + { + DOCTEST_DECLARE_INTERFACE(IContextScope) + virtual void stringify(std::ostream*) const = 0; + }; + + namespace detail { + struct DOCTEST_INTERFACE TestCase; + } // namespace detail + + struct ContextOptions //!OCLINT too many fields + { + std::ostream* cout = nullptr; // stdout stream + String binary_name; // the test binary name + + const detail::TestCase* currentTest = nullptr; + + // == parameters from the command line + String out; // output filename + String order_by; // how tests should be ordered + unsigned rand_seed; // the seed for rand ordering + + unsigned first; // the first (matching) test to be executed + unsigned last; // the last (matching) test to be executed + + int abort_after; // stop tests after this many failed assertions + int subcase_filter_levels; // apply the subcase filters for the first N levels + + bool success; // include successful assertions in output + bool case_sensitive; // if filtering should be case sensitive + bool exit; // if the program should be exited after the tests are ran/whatever + bool duration; // print the time duration of each test case + bool minimal; // minimal console output (only test failures) + bool quiet; // no console output + bool no_throw; // to skip exceptions-related assertion macros + bool no_exitcode; // if the framework should return 0 as the exitcode + bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_intro; // to not print the intro of the framework + bool no_version; // to not print the version of the framework + bool no_colors; // if output to the console should be colorized + bool force_colors; // forces the use of colors even when a tty cannot be detected + bool no_breaks; // to not break into the debugger + bool no_skip; // don't skip test cases which are marked to be skipped + bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): + bool no_path_in_filenames; // if the path to files should be removed from the output + bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached + bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! + bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! + + bool help; // to print the help + bool version; // to print the version + bool count; // if only the count of matching tests is to be retrieved + bool list_test_cases; // to list all tests matching the filters + bool list_test_suites; // to list all suites matching the filters + bool list_reporters; // lists all registered reporters + }; + + namespace detail { + namespace types { +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + using namespace std; +#else + template + struct enable_if { }; + + template + struct enable_if { using type = T; }; + + struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; + struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; + + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + + template struct is_rvalue_reference : false_type { }; + template struct is_rvalue_reference : true_type { }; + + template struct remove_const { using type = T; }; + template struct remove_const { using type = T; }; + + // Compiler intrinsics + template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; + template struct underlying_type { using type = __underlying_type(T); }; + + template struct is_pointer : false_type { }; + template struct is_pointer : true_type { }; + + template struct is_array : false_type { }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type { }; +#endif + } + + // + template + T&& declval(); + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + struct deferred_false : types::false_type { }; + + // MSVS 2015 :( +#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 + template + struct has_global_insertion_operator : types::false_type { }; + + template + struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + + template + struct insert_hack; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + }; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + }; + + template + using insert_hack_t = insert_hack::value>; +#else + template + struct has_insertion_operator : types::false_type { }; +#endif + + template + struct has_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct should_stringify_as_underlying_type { + static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + }; + + DOCTEST_INTERFACE std::ostream* tlssPush(); + DOCTEST_INTERFACE String tlssPop(); + + template + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T)) { +#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES + static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); +#endif + return "{?}"; + } + }; + + template + struct filldata; + + template + void filloss(std::ostream* stream, const T& in) { + filldata::fill(stream, in); + } + + template + void filloss(std::ostream* stream, const T(&in)[N]) { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss::type>(stream, in); + } + + template + String toStream(const T& in) { + std::ostream* stream = tlssPush(); + filloss(stream, in); + return tlssPop(); + } + + template <> + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T) in) { + return toStream(in); + } + }; + } // namespace detail + + template + struct StringMaker : public detail::StringMakerBase< + detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> + {}; + +#ifndef DOCTEST_STRINGIFY +#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY +#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__)) +#else +#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__) +#endif +#endif + + template + String toString() { +#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 + String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) + String::size_type beginPos = ret.find('<'); + return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); +#else + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String::size_type begin = ret.find('=') + 2; + return ret.substr(begin, ret.size() - begin - 1); +#endif + } + + template ::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) { + return StringMaker::convert(value); + } + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + DOCTEST_INTERFACE String toString(const char* in); +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + DOCTEST_INTERFACE String toString(const std::string& in); +#endif // VS 2019 + + DOCTEST_INTERFACE String toString(String in); + + DOCTEST_INTERFACE String toString(std::nullptr_t); + + DOCTEST_INTERFACE String toString(bool in); + + DOCTEST_INTERFACE String toString(float in); + DOCTEST_INTERFACE String toString(double in); + DOCTEST_INTERFACE String toString(double long in); + + DOCTEST_INTERFACE String toString(char in); + DOCTEST_INTERFACE String toString(char signed in); + DOCTEST_INTERFACE String toString(char unsigned in); + DOCTEST_INTERFACE String toString(short in); + DOCTEST_INTERFACE String toString(short unsigned in); + DOCTEST_INTERFACE String toString(signed in); + DOCTEST_INTERFACE String toString(unsigned in); + DOCTEST_INTERFACE String toString(long in); + DOCTEST_INTERFACE String toString(long unsigned in); + DOCTEST_INTERFACE String toString(long long in); + DOCTEST_INTERFACE String toString(long long unsigned in); + + template ::value, bool>::type = true> + String toString(const DOCTEST_REF_WRAP(T) value) { + using UT = typename detail::types::underlying_type::type; + return (DOCTEST_STRINGIFY(static_cast(value))); + } + + namespace detail { + template + struct filldata + { + static void fill(std::ostream* stream, const T& in) { +#if defined(_MSC_VER) && _MSC_VER <= 1900 + insert_hack_t::insert(*stream, in); +#else + operator<<(*stream, in); +#endif + } + }; + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + // NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const T(&in)[N]) { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { *stream << ", "; } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; + } + }; + // NOLINTEND(*-avoid-c-arrays) + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // Specialized since we don't want the terminating null byte! + // NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const char(&in)[N]) { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + }; + // NOLINTEND(*-avoid-c-arrays) + + template <> + struct filldata { + static void fill(std::ostream* stream, const void* in); + }; + + template + struct filldata { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + static void fill(std::ostream* stream, const T* in) { + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, +#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) + reinterpret_cast(in) +#else + * reinterpret_cast(&in) +#endif + ); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + } + }; + } + + struct DOCTEST_INTERFACE Approx + { + Approx(double value); + + Approx operator()(double value) const; + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + explicit Approx(const T& value, + typename detail::types::enable_if::value>::type* = + static_cast(nullptr)) { + *this = static_cast(value); + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& epsilon(double newEpsilon); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type epsilon( + const T& newEpsilon) { + m_epsilon = static_cast(newEpsilon); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& scale(double newScale); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type scale( + const T& newScale) { + m_scale = static_cast(newScale); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format off + DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator==(const Approx& lhs, double rhs); + DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator!=(const Approx& lhs, double rhs); + DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator<=(const Approx& lhs, double rhs); + DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator>=(const Approx& lhs, double rhs); + DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator< (const Approx& lhs, double rhs); + DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx& rhs); + DOCTEST_INTERFACE friend bool operator> (const Approx& lhs, double rhs); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_APPROX_PREFIX \ + template friend typename std::enable_if::value, bool>::type + + DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } + DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } + DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } +#undef DOCTEST_APPROX_PREFIX +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format on + + double m_epsilon; + double m_scale; + double m_value; + }; + + DOCTEST_INTERFACE String toString(const Approx& in); + + DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + + template + struct DOCTEST_INTERFACE_DECL IsNaN + { + F value; bool flipped; + IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } + IsNaN operator!() const { return { value, !flipped }; } + operator bool() const; + }; +#ifndef __MINGW32__ + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; + extern template struct DOCTEST_INTERFACE_DECL IsNaN; +#endif + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + DOCTEST_INTERFACE String toString(IsNaN in); + +#ifndef DOCTEST_CONFIG_DISABLE + + namespace detail { + // clang-format off +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template struct decay_array { using type = T; }; + template struct decay_array { using type = T*; }; + template struct decay_array { using type = T*; }; + + template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + + template struct can_use_op : public not_char_pointer::type> {}; +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + + struct DOCTEST_INTERFACE TestFailureException + { + }; + + DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_INTERFACE void throwException(); + + struct DOCTEST_INTERFACE Subcase + { + SubcaseSignature m_signature; + bool m_entered = false; + + Subcase(const String& name, const char* file, int line); + Subcase(const Subcase&) = delete; + Subcase(Subcase&&) = delete; + Subcase& operator=(const Subcase&) = delete; + Subcase& operator=(Subcase&&) = delete; + ~Subcase(); + + operator bool() const; + + private: + bool checkFilters(); + }; + + template + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, + const DOCTEST_REF_WRAP(R) rhs) { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + } + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + + // This will check if there is any way it could find a operator like member or friend and uses it. + // If not it doesn't find the operator or if the operator at global scope is defined after + // this template, the template won't be instantiated due to SFINAE. Once the template is not + // instantiated it can look for global operator using normal conversions. +#ifdef __NVCC__ +#define SFINAE_OP(ret,op) ret +#else +#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#endif + +#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ + template \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ + if(m_at & assertType::is_false) \ + res = !res; \ + if(!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } + + // more checks could be added - like in Catch: + // https://github.com/catchorg/Catch2/pull/1480/files + // https://github.com/catchorg/Catch2/pull/1481/files +#define DOCTEST_FORBIT_EXPRESSION(rt, op) \ + template \ + rt& operator op(const R&) { \ + static_assert(deferred_false::value, \ + "Expression Too Complex Please Rewrite As Binary Comparison!"); \ + return *this; \ + } + + struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) + { + bool m_passed; + String m_decomp; + + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String& decomposition = String()); + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + DOCTEST_FORBIT_EXPRESSION(Result, ^) + DOCTEST_FORBIT_EXPRESSION(Result, | ) + DOCTEST_FORBIT_EXPRESSION(Result, &&) + DOCTEST_FORBIT_EXPRESSION(Result, || ) + DOCTEST_FORBIT_EXPRESSION(Result, == ) + DOCTEST_FORBIT_EXPRESSION(Result, != ) + DOCTEST_FORBIT_EXPRESSION(Result, < ) + DOCTEST_FORBIT_EXPRESSION(Result, > ) + DOCTEST_FORBIT_EXPRESSION(Result, <= ) + DOCTEST_FORBIT_EXPRESSION(Result, >= ) + DOCTEST_FORBIT_EXPRESSION(Result, =) + DOCTEST_FORBIT_EXPRESSION(Result, +=) + DOCTEST_FORBIT_EXPRESSION(Result, -=) + DOCTEST_FORBIT_EXPRESSION(Result, *=) + DOCTEST_FORBIT_EXPRESSION(Result, /=) + DOCTEST_FORBIT_EXPRESSION(Result, %=) + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + DOCTEST_FORBIT_EXPRESSION(Result, &=) + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + DOCTEST_FORBIT_EXPRESSION(Result, |=) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_GCC_SUPPRESS_WARNING_PUSH + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH + // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 + DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch + //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + // clang-format off +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE bool +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type + inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } + inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } + inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } + inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } + inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } + inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ + const DOCTEST_REF_WRAP(R) rhs) { \ + return lhs op rhs; \ + } + + DOCTEST_RELATIONAL_OP(eq, == ) + DOCTEST_RELATIONAL_OP(ne, != ) + DOCTEST_RELATIONAL_OP(lt, < ) + DOCTEST_RELATIONAL_OP(gt, > ) + DOCTEST_RELATIONAL_OP(le, <= ) + DOCTEST_RELATIONAL_OP(ge, >= ) + +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) l == r +#define DOCTEST_CMP_NE(l, r) l != r +#define DOCTEST_CMP_GT(l, r) l > r +#define DOCTEST_CMP_LT(l, r) l < r +#define DOCTEST_CMP_GE(l, r) l >= r +#define DOCTEST_CMP_LE(l, r) l <= r +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) eq(l, r) +#define DOCTEST_CMP_NE(l, r) ne(l, r) +#define DOCTEST_CMP_GT(l, r) gt(l, r) +#define DOCTEST_CMP_LT(l, r) lt(l, r) +#define DOCTEST_CMP_GE(l, r) ge(l, r) +#define DOCTEST_CMP_LE(l, r) le(l, r) +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + + template + // cppcheck-suppress copyCtorAndEqOperator + struct Expression_lhs + { + L lhs; + assertType::Enum m_at; + + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(static_cast(in)) + , m_at(at) {} + + DOCTEST_NOINLINE operator Result() { + // this is needed only for MSVC 2015 + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + res = !res; + } + + if (!res || getContextOptions()->success) { + return { res, (DOCTEST_STRINGIFY(lhs)) }; + } + return { res }; + } + + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } + + // clang-format off + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(== , " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!= , " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(> , " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(< , " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>= , " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<= , " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional + // clang-format on + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, | ) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, || ) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the + // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, << ) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >> ) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) + DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + + struct DOCTEST_INTERFACE ExpressionDecomposer + { + assertType::Enum m_at; + + ExpressionDecomposer(assertType::Enum at); + + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) + // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template + Expression_lhs operator<<(L&& operand) { + return Expression_lhs(static_cast(operand), m_at); + } + + template ::value, void >::type* = nullptr> + Expression_lhs operator<<(const L& operand) { + return Expression_lhs(operand, m_at); + } + }; + + struct DOCTEST_INTERFACE TestSuite + { + const char* m_test_suite = nullptr; + const char* m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; + + TestSuite& operator*(const char* in); + + template + TestSuite& operator*(const T& in) { + in.fill(*this); + return *this; + } + }; + + using funcType = void (*)(); + + struct DOCTEST_INTERFACE TestCase : public TestCaseData + { + funcType m_test; // a function pointer to the test case + + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated test case + String m_full_name; // contains the name (only for templated test cases!) + the template type + + TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type = String(), int template_id = -1); + + TestCase(const TestCase& other); + TestCase(TestCase&&) = delete; + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& operator=(const TestCase& other); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& operator=(TestCase&&) = delete; + + TestCase& operator*(const char* in); + + template + TestCase& operator*(const T& in) { + in.fill(*this); + return *this; + } + + bool operator<(const TestCase& other) const; + + ~TestCase() = default; + }; + + // forward declarations of functions used by the macros + DOCTEST_INTERFACE int regTest(const TestCase& tc); + DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); + DOCTEST_INTERFACE bool isDebuggerActive(); + + template + int instantiationHelper(const T&) { return 0; } + + namespace binaryAssertComparison { + enum Enum + { + eq = 0, + ne, + gt, + lt, + ge, + le + }; + } // namespace binaryAssertComparison + + // clang-format off + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R)) const { return false; } }; + +#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; + // clang-format on + + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) + + struct DOCTEST_INTERFACE ResultBuilder : public AssertData + { + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type = "", const String& exception_string = ""); + + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string); + + void setResult(const Result& res); + + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); + } + return !m_failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { + m_failed = !val; + + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + m_failed = !m_failed; + } + + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); + } + + return !m_failed; + } + + void translateException(); + + bool log(); + void react() const; + }; + + namespace assertAction { + enum Enum + { + nothing = 0, + dbgbreak = 1, + shouldthrow = 2 + }; + } // namespace assertAction + + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, + const char* expr, const Result& result); + +#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ + do { \ + if(!is_running_in_test) { \ + if(failed) { \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + rb.m_decomp = decomp; \ + failed_out_of_a_testing_context(rb); \ + if(isDebuggerActive() && !getContextOptions()->no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(checkIfShouldThrow(at)) \ + throwException(); \ + } \ + return !failed; \ + } \ + } while(false) + +#define DOCTEST_ASSERT_IN_TESTS(decomp) \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + if(rb.m_failed || getContextOptions()->success) \ + rb.m_decomp = decomp; \ + if(rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(rb.m_failed && checkIfShouldThrow(at)) \ + throwException() + + template + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + bool failed = !RelationalComparator()(lhs, rhs); + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) val) { + bool failed = !val; + + if (at & assertType::is_false) //!OCLINT bitwise operator in conditional + failed = !failed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; + } + + struct DOCTEST_INTERFACE IExceptionTranslator + { + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) + virtual bool translate(String&) const = 0; + }; + + template + class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + { + public: + explicit ExceptionTranslator(String(*translateFunction)(T)) + : m_translateFunction(translateFunction) {} + + bool translate(String& res) const override { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } + catch (const T& ex) { + res = m_translateFunction(ex); //!OCLINT parameter reassignment + return true; + } + catch (...) {} //!OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter + return false; + } + + private: + String(*m_translateFunction)(T); + }; + + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + + // ContextScope base class used to allow implementing methods of ContextScope + // that don't depend on the template parameter in doctest.cpp. + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { + ContextScopeBase(const ContextScopeBase&) = delete; + + ContextScopeBase& operator=(const ContextScopeBase&) = delete; + ContextScopeBase& operator=(ContextScopeBase&&) = delete; + + ~ContextScopeBase() override = default; + + protected: + ContextScopeBase(); + ContextScopeBase(ContextScopeBase&& other) noexcept; + + void destroy(); + bool need_to_destroy{ true }; + }; + + template class ContextScope : public ContextScopeBase + { + L lambda_; + + public: + explicit ContextScope(const L& lambda) : lambda_(lambda) {} + explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + + ContextScope(const ContextScope&) = delete; + ContextScope(ContextScope&&) noexcept = default; + + ContextScope& operator=(const ContextScope&) = delete; + ContextScope& operator=(ContextScope&&) = delete; + + void stringify(std::ostream* s) const override { lambda_(s); } + + ~ContextScope() override { + if (need_to_destroy) { + destroy(); + } + } + }; + + struct DOCTEST_INTERFACE MessageBuilder : public MessageData + { + std::ostream* m_stream; + bool logged = false; + + MessageBuilder(const char* file, int line, assertType::Enum severity); + + MessageBuilder(const MessageBuilder&) = delete; + MessageBuilder(MessageBuilder&&) = delete; + + MessageBuilder& operator=(const MessageBuilder&) = delete; + MessageBuilder& operator=(MessageBuilder&&) = delete; + + ~MessageBuilder(); + + // the preferred way of chaining parameters for stringification + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + template + MessageBuilder& operator,(const T& in) { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // kept here just for backwards-compatibility - the comma operator should be preferred now + template + MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template + MessageBuilder& operator*(const T& in) { return this->operator,(in); } + + bool log(); + void react(); + }; + + template + ContextScope MakeContextScope(const L& lambda) { + return ContextScope(lambda); + } + } // namespace detail + +#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ + struct name \ + { \ + type data; \ + name(type in = def) \ + : data(in) {} \ + void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + } + + DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); + DOCTEST_DEFINE_DECORATOR(description, const char*, ""); + DOCTEST_DEFINE_DECORATOR(skip, bool, true); + DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); + DOCTEST_DEFINE_DECORATOR(no_output, bool, true); + DOCTEST_DEFINE_DECORATOR(timeout, double, 0); + DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); + DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + + template + int registerExceptionTranslator(String(*translateFunction)(T)) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") + static detail::ExceptionTranslator exceptionTranslator(translateFunction); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + detail::registerExceptionTranslatorImpl(&exceptionTranslator); + return 0; + } + +} // namespace doctest + +// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro +// introduces an anonymous namespace in which getCurrentTestSuite gets overridden +namespace doctest_detail_test_suite_ns { + DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); +} // namespace doctest_detail_test_suite_ns + +namespace doctest { +#else // DOCTEST_CONFIG_DISABLE + template + int registerExceptionTranslator(String(*)(T)) { + return 0; + } +#endif // DOCTEST_CONFIG_DISABLE + + namespace detail { + using assert_handler = void (*)(const AssertData&); + struct ContextState; + } // namespace detail + + class DOCTEST_INTERFACE Context + { + detail::ContextState* p; + + void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + + public: + explicit Context(int argc = 0, const char* const* argv = nullptr); + + Context(const Context&) = delete; + Context(Context&&) = delete; + + Context& operator=(const Context&) = delete; + Context& operator=(Context&&) = delete; + + ~Context(); // NOLINT(performance-trivially-destructible) + + void applyCommandLine(int argc, const char* const* argv); + + void addFilter(const char* filter, const char* value); + void clearFilters(); + void setOption(const char* option, bool value); + void setOption(const char* option, int value); + void setOption(const char* option, const char* value); + + bool shouldExit(); + + void setAsDefaultForAssertsOutOfTestCases(); + + void setAssertHandler(detail::assert_handler ah); + + void setCout(std::ostream* out); + + int run(); + }; + + namespace TestCaseFailureReason { + enum Enum + { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; + } // namespace TestCaseFailureReason + + struct DOCTEST_INTERFACE CurrentTestCaseStats + { + int numAssertsCurrentTest; + int numAssertsFailedCurrentTest; + double seconds; + int failure_flags; // use TestCaseFailureReason::Enum + bool testCaseSuccess; + }; + + struct DOCTEST_INTERFACE TestCaseException + { + String error_string; + bool is_crash; + }; + + struct DOCTEST_INTERFACE TestRunStats + { + unsigned numTestCases; + unsigned numTestCasesPassingFilters; + unsigned numTestSuitesPassingFilters; + unsigned numTestCasesFailed; + int numAsserts; + int numAssertsFailed; + }; + + struct QueryData + { + const TestRunStats* run_stats = nullptr; + const TestCaseData** data = nullptr; + unsigned num_data = 0; + }; + + struct DOCTEST_INTERFACE IReporter + { + // The constructor has to accept "const ContextOptions&" as a single argument + // which has most of the options for the run + a pointer to the stdout stream + // Reporter(const ContextOptions& in) + + // called when a query should be reported (listing test cases, printing the version, etc.) + virtual void report_query(const QueryData&) = 0; + + // called when the whole test run starts + virtual void test_run_start() = 0; + // called when the whole test run ends (caching a pointer to the input doesn't make sense here) + virtual void test_run_end(const TestRunStats&) = 0; + + // called when a test case is started (safe to cache a pointer to the input) + virtual void test_case_start(const TestCaseData&) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) + virtual void test_case_reenter(const TestCaseData&) = 0; + // called when a test case has ended + virtual void test_case_end(const CurrentTestCaseStats&) = 0; + + // called when an exception is thrown from the test case (or it crashes) + virtual void test_case_exception(const TestCaseException&) = 0; + + // called whenever a subcase is entered (don't cache pointers to the input) + virtual void subcase_start(const SubcaseSignature&) = 0; + // called whenever a subcase is exited (don't cache pointers to the input) + virtual void subcase_end() = 0; + + // called for each assert (don't cache pointers to the input) + virtual void log_assert(const AssertData&) = 0; + // called for each message (don't cache pointers to the input) + virtual void log_message(const MessageData&) = 0; + + // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator + // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) + virtual void test_case_skipped(const TestCaseData&) = 0; + + DOCTEST_DECLARE_INTERFACE(IReporter) + + // can obtain all currently active contexts and stringify them if one wishes to do so + static int get_num_active_contexts(); + static const IContextScope* const* get_active_contexts(); + + // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + static int get_num_stringified_contexts(); + static const String* get_stringified_contexts(); + }; + + namespace detail { + using reporterCreatorFunc = IReporter * (*)(const ContextOptions&); + + DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + + template + IReporter* reporterCreator(const ContextOptions& o) { + return new Reporter(o); + } + } // namespace detail + + template + int registerReporter(const char* name, int priority, bool isReporter) { + detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); + return 0; + } +} // namespace doctest + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_EMPTY [] { return false; }() +#else +#define DOCTEST_FUNC_EMPTY (void)0 +#endif + +// if registering is not disabled +#ifndef DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_SCOPE_BEGIN [&] +#define DOCTEST_FUNC_SCOPE_END () +#define DOCTEST_FUNC_SCOPE_RET(v) return v +#else +#define DOCTEST_FUNC_SCOPE_BEGIN do +#define DOCTEST_FUNC_SCOPE_END while(false) +#define DOCTEST_FUNC_SCOPE_RET(v) (void)0 +#endif + +// common code in asserts - for convenience +#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ + if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ + b.react(); \ + DOCTEST_FUNC_SCOPE_RET(!b.m_failed) + +#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) x; +#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) \ + try { \ + x; \ + } catch(...) { DOCTEST_RB.translateException(); } +#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ + static_cast(__VA_ARGS__); \ + DOCTEST_GCC_SUPPRESS_WARNING_POP +#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; +#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS + +// registers the test by initializing a dummy var with a function +#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ + global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ + doctest::detail::regTest( \ + doctest::detail::TestCase( \ + f, __FILE__, __LINE__, \ + doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ + decorators)) + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ + namespace { /* NOLINT */ \ + struct der : public base \ + { \ + void f(); \ + }; \ + static DOCTEST_INLINE_NOINLINE void func() { \ + der v; \ + v.f(); \ + } \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + } \ + DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ + static void f(); \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ + static void f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ + static doctest::detail::funcType proxy() { return f; } \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ + static void f() + +// for registering tests +#define DOCTEST_TEST_CASE(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for registering tests in classes - requires C++17 for inline variables! +#if DOCTEST_CPLUSPLUS >= 201703L +#define DOCTEST_TEST_CASE_CLASS(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ + decorators) +#else // DOCTEST_TEST_CASE_CLASS +#define DOCTEST_TEST_CASE_CLASS(...) \ + TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER +#endif // DOCTEST_TEST_CASE_CLASS + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ + namespace doctest { \ + template <> \ + inline String toString<__VA_ARGS__>() { \ + return str; \ + } \ + } \ + static_assert(true, "") + +#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ + template \ + static void func(); \ + namespace { /* NOLINT */ \ + template \ + struct iter; \ + template \ + struct iter> \ + { \ + iter(const char* file, unsigned line, int index) { \ + doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::toString(), \ + int(line) * 1000 + index) \ + * dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> \ + struct iter> \ + { \ + iter(const char*, unsigned, int) {} \ + }; \ + } \ + template \ + static void func() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ + doctest::detail::instantiationHelper( \ + DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ + template \ + static void anon() + +#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) + +// for subcases +#define DOCTEST_SUBCASE(name) \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) + +// for grouping tests in test suites by using code blocks +#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ + namespace ns_name { namespace doctest_detail_test_suite_ns { \ + static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ + static bool inited = false; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + if(!inited) { \ + data* decorators; \ + inited = true; \ + } \ + return data; \ + } \ + } \ + } \ + namespace ns_name + +#define DOCTEST_TEST_SUITE(decorators) \ + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(decorators) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +// for registering exception translators +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ + inline doctest::String translatorName(signature); \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerExceptionTranslator(translatorName)) \ + doctest::String translatorName(signature) + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ + signature) + +// for registering reporters +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") + +// for registering listeners +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") + +// clang-format off +// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 +#define DOCTEST_INFO(...) \ + DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ + DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ + __VA_ARGS__) +// clang-format on + +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ + doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ + mb_name.m_stream = s_name; \ + mb_name * __VA_ARGS__; \ + }) + +#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) + +#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ + mb * __VA_ARGS__; \ + if(mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +// clang-format on + +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) + +#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. + +#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ + } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + +#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY( \ + DOCTEST_RB.binary_assert( \ + __VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +// necessary for _MESSAGE +#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + doctest::detail::decomp_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ + doctest::detail::binary_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) +#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) +#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) +#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) + +// clang-format off +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) +#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) +#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) +#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) +#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) +#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) +#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) +#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) +#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) +#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) +#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) +#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) +#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) +#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) +#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) +#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) +#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) + +#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #expr, #__VA_ARGS__, message); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(const typename doctest::detail::types::remove_const< \ + typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, expr_str, "", __VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") +#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") + +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) + +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// ================================================================================================= +// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == +// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == +// ================================================================================================= +#else // DOCTEST_CONFIG_DISABLE + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ + namespace /* NOLINT */ { \ + template \ + struct der : public base \ + { void f(); }; \ + } \ + template \ + inline void der::f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ + template \ + static inline void f() + +// for registering tests +#define DOCTEST_TEST_CASE(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests in classes +#define DOCTEST_TEST_CASE_CLASS(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") + +// for typed tests +#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") + +// for subcases +#define DOCTEST_SUBCASE(name) + +// for a testsuite block +#define DOCTEST_TEST_SUITE(name) namespace // NOLINT + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + template \ + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) + +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) + +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ + && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() + +namespace doctest { + namespace detail { +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + + DOCTEST_RELATIONAL_OP(eq, == ) + DOCTEST_RELATIONAL_OP(ne, != ) + DOCTEST_RELATIONAL_OP(lt, < ) + DOCTEST_RELATIONAL_OP(gt, > ) + DOCTEST_RELATIONAL_OP(le, <= ) + DOCTEST_RELATIONAL_OP(ge, >= ) + } // namespace detail +} // namespace doctest + +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() +#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY +#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ + "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() + +#undef DOCTEST_REQUIRE +#undef DOCTEST_REQUIRE_FALSE +#undef DOCTEST_REQUIRE_MESSAGE +#undef DOCTEST_REQUIRE_FALSE_MESSAGE +#undef DOCTEST_REQUIRE_EQ +#undef DOCTEST_REQUIRE_NE +#undef DOCTEST_REQUIRE_GT +#undef DOCTEST_REQUIRE_LT +#undef DOCTEST_REQUIRE_GE +#undef DOCTEST_REQUIRE_LE +#undef DOCTEST_REQUIRE_UNARY +#undef DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// clang-format off +// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS +#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ +#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ +#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ +#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE +#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE +#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE +#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT +#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT +#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT +#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT +#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT +#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT +#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE +#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE +#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE +#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE +#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE +#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE + +#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY +#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY +#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY +#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE +#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE +#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) +// clang-format on + +// BDD style macros +// clang-format off +#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name) +#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name) +#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) +#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) + +#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) +#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) +#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) +#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) +#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) +// clang-format on + +// == SHORT VERSIONS OF THE MACROS +#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) +#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) + +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) + +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +// KEPT FOR BACKWARDS COMPATIBILITY +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) + +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#ifndef DOCTEST_CONFIG_DISABLE + +// this is here to clear the 'current test suite' for the current translation unit - at the top +DOCTEST_TEST_SUITE_END(); + +#endif // DOCTEST_CONFIG_DISABLE + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_INCLUDED + +#ifndef DOCTEST_SINGLE_HEADER +#define DOCTEST_SINGLE_HEADER +#endif // DOCTEST_SINGLE_HEADER + +#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) + +#ifndef DOCTEST_SINGLE_HEADER +#include "doctest_fwd.h" +#endif // DOCTEST_SINGLE_HEADER + +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") + +#ifndef DOCTEST_LIBRARY_IMPLEMENTATION +#define DOCTEST_LIBRARY_IMPLEMENTATION + +DOCTEST_CLANG_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") +DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data +DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled +DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified +DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal +DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch +DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C +DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning) +DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN + +// required includes - will go only in one translation unit! +#include +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 +#ifdef __BORLANDC__ +#include +#endif // __BORLANDC__ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; +#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); +#else // DOCTEST_CONFIG_NO_MULTITHREADING +#define DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_DECLARE_STATIC_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) +#endif // DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DOCTEST_PLATFORM_MAC +#include +#include +#include +#endif // DOCTEST_PLATFORM_MAC + +#ifdef DOCTEST_PLATFORM_WINDOWS + +// defines for a leaner windows.h +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#define DOCTEST_UNDEF_NOMINMAX +#endif // NOMINMAX + +// not sure what AfxWin.h is for - here I do what Catch does +#ifdef __AFXDLL +#include +#else +#include +#endif +#include + +#else // DOCTEST_PLATFORM_WINDOWS + +#include +#include + +#endif // DOCTEST_PLATFORM_WINDOWS + +// this is a fix for https://github.com/doctest/doctest/issues/348 +// https://mail.gnome.org/archives/xml/2012-January/msg00000.html +#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) +#define STDOUT_FILENO fileno(stdout) +#endif // HAVE_UNISTD_H + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END + +// counts the number of elements in a C array +#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) + +#ifdef DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled +#else // DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled +#endif // DOCTEST_CONFIG_DISABLE + +#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX +#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-" +#endif + +#ifndef DOCTEST_THREAD_LOCAL +#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_THREAD_LOCAL +#else // DOCTEST_MSVC +#define DOCTEST_THREAD_LOCAL thread_local +#endif // DOCTEST_MSVC +#endif // DOCTEST_THREAD_LOCAL + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES +#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 +#endif + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE +#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 +#endif + +#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS +#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX +#else +#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + +#ifndef DOCTEST_CDECL +#define DOCTEST_CDECL __cdecl +#endif + + namespace doctest { + + bool is_running_in_test = false; + + namespace { + using namespace detail; + + template + DOCTEST_NORETURN void throw_exception(Ex const& e) { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS +#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION + DOCTEST_CONFIG_HANDLE_EXCEPTION(e); +#else // DOCTEST_CONFIG_HANDLE_EXCEPTION +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION + std::terminate(); +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } + +#ifndef DOCTEST_INTERNAL_ERROR +#define DOCTEST_INTERNAL_ERROR(msg) \ + throw_exception(std::logic_error( \ + __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) +#endif // DOCTEST_INTERNAL_ERROR + + // case insensitive strcmp + int stricmp(const char* a, const char* b) { + for (;; a++, b++) { + const int d = tolower(*a) - tolower(*b); + if (d != 0 || !*a) + return d; + } + } + + struct Endianness + { + enum Arch + { + Big, + Little + }; + + static Arch which() { + int x = 1; + // casting any data pointer to char* is allowed + auto ptr = reinterpret_cast(&x); + if (*ptr) + return Little; + return Big; + } + }; + } // namespace + + namespace detail { + DOCTEST_THREAD_LOCAL class + { + std::vector stack; + std::stringstream ss; + + public: + std::ostream* push() { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); + + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } + } g_oss; + + std::ostream* tlssPush() { + return g_oss.push(); + } + + String tlssPop() { + return g_oss.pop(); + } + +#ifndef DOCTEST_CONFIG_DISABLE + + namespace timer_large_integer + { + +#if defined(DOCTEST_PLATFORM_WINDOWS) + using type = ULONGLONG; +#else // DOCTEST_PLATFORM_WINDOWS + using type = std::uint64_t; +#endif // DOCTEST_PLATFORM_WINDOWS + } + + using ticks_t = timer_large_integer::type; + +#ifdef DOCTEST_CONFIG_GETCURRENTTICKS + ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } +#elif defined(DOCTEST_PLATFORM_WINDOWS) + ticks_t getCurrentTicks() { + static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; + if (!hz.QuadPart) { + QueryPerformanceFrequency(&hz); + QueryPerformanceCounter(&hzo); + } + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; + } +#else // DOCTEST_PLATFORM_WINDOWS + ticks_t getCurrentTicks() { + timeval t; + gettimeofday(&t, nullptr); + return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); + } +#endif // DOCTEST_PLATFORM_WINDOWS + + struct Timer + { + void start() { m_ticks = getCurrentTicks(); } + unsigned int getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + //unsigned int getElapsedMilliseconds() const { + // return static_cast(getElapsedMicroseconds() / 1000); + //} + double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } + + private: + ticks_t m_ticks = 0; + }; + +#ifdef DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = T; +#else // DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = std::atomic; +#endif // DOCTEST_CONFIG_NO_MULTITHREADING + +#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) + template + using MultiLaneAtomic = Atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + // Provides a multilane implementation of an atomic variable that supports add, sub, load, + // store. Instead of using a single atomic variable, this splits up into multiple ones, + // each sitting on a separate cache line. The goal is to provide a speedup when most + // operations are modifying. It achieves this with two properties: + // + // * Multiple atomics are used, so chance of congestion from the same atomic is reduced. + // * Each atomic sits on a separate cache line, so false sharing is reduced. + // + // The disadvantage is that there is a small overhead due to the use of TLS, and load/store + // is slower because all atomics have to be accessed. + template + class MultiLaneAtomic + { + struct CacheLineAlignedAtomic + { + Atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); + + public: + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_add(arg, order); + } + + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_sub(arg, order); + } + + operator T() const DOCTEST_NOEXCEPT { return load(); } + + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { + auto result = T(); + for (auto const& c : m_atomics) { + result += c.atomic.load(order); + } + return result; + } + + T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } + + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + // first value becomes desired", all others become 0. + for (auto& c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; + } + } + + private: + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + Atomic& myAtomic() DOCTEST_NOEXCEPT { + static Atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } + }; +#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + + // this holds both parameters from the command line and runtime data for tests + struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats + { + MultiLaneAtomic numAssertsCurrentTest_atomic; + MultiLaneAtomic numAssertsFailedCurrentTest_atomic; + + std::vector> filters = decltype(filters)(9); // 9 different filters + + std::vector reporters_currently_used; + + assert_handler ah = nullptr; + + Timer timer; + + std::vector stringifiedContexts; // logging from INFO() due to an exception + + // stuff for subcases + bool reachedLeaf; + std::vector subcaseStack; + std::vector nextSubcaseStack; + std::unordered_set fullyTraversedSubcases; + size_t currentSubcaseDepth; + Atomic shouldLogCurrentException; + + void resetRunData() { + numTestCases = 0; + numTestCasesPassingFilters = 0; + numTestSuitesPassingFilters = 0; + numTestCasesFailed = 0; + numAsserts = 0; + numAssertsFailed = 0; + numAssertsCurrentTest = 0; + numAssertsFailedCurrentTest = 0; + } + + void finalizeTestCaseData() { + seconds = timer.getElapsedSeconds(); + + // update the non-atomic counters + numAsserts += numAssertsCurrentTest_atomic; + numAssertsFailed += numAssertsFailedCurrentTest_atomic; + numAssertsCurrentTest = numAssertsCurrentTest_atomic; + numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; + + if (numAssertsFailedCurrentTest) + failure_flags |= TestCaseFailureReason::AssertFailure; + + if (Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && + Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) + failure_flags |= TestCaseFailureReason::Timeout; + + if (currentTest->m_should_fail) { + if (failure_flags) { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; + } + else { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; + } + } + else if (failure_flags && currentTest->m_may_fail) { + failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; + } + else if (currentTest->m_expected_failures > 0) { + if (numAssertsFailedCurrentTest == currentTest->m_expected_failures) { + failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; + } + else { + failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; + } + } + + bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); + + // if any subcase has failed - the whole test case has failed + testCaseSuccess = !(failure_flags && !ok_to_fail); + if (!testCaseSuccess) + numTestCasesFailed++; + } + }; + + ContextState* g_cs = nullptr; + + // used to avoid locks for the debug output + // TODO: figure out if this is indeed necessary/correct - seems like either there still + // could be a race or that there wouldn't be a race even if using the context directly + DOCTEST_THREAD_LOCAL bool g_no_colors; + +#endif // DOCTEST_CONFIG_DISABLE + } // namespace detail + + char* String::allocate(size_type sz) { + if (sz <= last) { + buf[sz] = '\0'; + setLast(last - sz); + return buf; + } + else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } + } + + void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } + void String::setLast(size_type in) noexcept { buf[last] = char(in); } + void String::setSize(size_type sz) noexcept { + if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } + else { data.ptr[sz] = '\0'; data.size = sz; } + } + + void String::copy(const String& other) { + if (other.isOnStack()) { + memcpy(buf, other.buf, len); + } + else { + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + } + } + + String::String() noexcept { + buf[0] = '\0'; + setLast(); + } + + String::~String() { + if (!isOnStack()) + delete[] data.ptr; + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + + String::String(const char* in) + : String(in, strlen(in)) {} + + String::String(const char* in, size_type in_size) { + memcpy(allocate(in_size), in, in_size); + } + + String::String(std::istream& in, size_type in_size) { + in.read(allocate(in_size), in_size); + } + + String::String(const String& other) { copy(other); } + + String& String::operator=(const String& other) { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; + + copy(other); + } + + return *this; + } + + String& String::operator+=(const String& other) { + const size_type my_old_size = size(); + const size_type other_size = other.size(); + const size_type total_size = my_old_size + other_size; + if (isOnStack()) { + if (total_size < len) { + // append to the current stack space + memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + setLast(last - total_size); + } + else { + // alloc new chunk + char* temp = new char[total_size + 1]; + // copy current data to new location before writing in the union + memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed + // update data in union + setOnHeap(); + data.size = total_size; + data.capacity = data.size + 1; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + else { + if (data.capacity > total_size) { + // append to the current heap block + data.size = total_size; + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + else { + // resize + data.capacity *= 2; + if (data.capacity <= total_size) + data.capacity = total_size + 1; + // alloc new chunk + char* temp = new char[data.capacity]; + // copy current data to new location before releasing it + memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed + // release old chunk + delete[] data.ptr; + // update the rest of the union members + data.size = total_size; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + + return *this; + } + + String::String(String&& other) noexcept { + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); + } + + String& String::operator=(String&& other) noexcept { + if (this != &other) { + if (!isOnStack()) + delete[] data.ptr; + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); + } + return *this; + } + + char String::operator[](size_type i) const { + return const_cast(this)->operator[](i); + } + + char& String::operator[](size_type i) { + if (isOnStack()) + return reinterpret_cast(buf)[i]; + return data.ptr[i]; + } + + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") + String::size_type String::size() const { + if (isOnStack()) + return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 + return data.size; + } + DOCTEST_GCC_SUPPRESS_WARNING_POP + + String::size_type String::capacity() const { + if (isOnStack()) + return len; + return data.capacity; + } + + String String::substr(size_type pos, size_type cnt)&& { + cnt = std::min(cnt, size() - 1 - pos); + char* cptr = c_str(); + memmove(cptr, cptr + pos, cnt); + setSize(cnt); + return std::move(*this); + } + + String String::substr(size_type pos, size_type cnt) const& { + cnt = std::min(cnt, size() - 1 - pos); + return String{ c_str() + pos, cnt }; + } + + String::size_type String::find(char ch, size_type pos) const { + const char* begin = c_str(); + const char* end = begin + size(); + const char* it = begin + pos; + for (; it < end && *it != ch; it++); + if (it < end) { return static_cast(it - begin); } + else { return npos; } + } + + String::size_type String::rfind(char ch, size_type pos) const { + const char* begin = c_str(); + const char* it = begin + std::min(pos, size() - 1); + for (; it >= begin && *it != ch; it--); + if (it >= begin) { return static_cast(it - begin); } + else { return npos; } + } + + int String::compare(const char* other, bool no_case) const { + if (no_case) + return doctest::stricmp(c_str(), other); + return std::strcmp(c_str(), other); + } + + int String::compare(const String& other, bool no_case) const { + return compare(other.c_str(), no_case); + } + + String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + + bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } + bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } + bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } + bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } + bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } + bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } + + std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } + + Contains::Contains(const String& str) : string(str) { } + + bool Contains::checkWith(const String& other) const { + return strstr(other.c_str(), string.c_str()) != nullptr; + } + + String toString(const Contains& in) { + return "Contains( " + in.string + " )"; + } + + bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } + bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } + bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } + bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + + namespace { + void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) + } // namespace + + namespace Color { + std::ostream& operator<<(std::ostream& s, Color::Enum code) { + color_to_stream(s, code); + return s; + } + } // namespace Color + + // clang-format off + const char* assertString(assertType::Enum at) { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled +#define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type +#define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) + switch (at) { + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); + + default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + } + // clang-format on + + const char* failureString(assertType::Enum at) { + if (at & assertType::is_warn) //!OCLINT bitwise operator in conditional + return "WARNING"; + if (at & assertType::is_check) //!OCLINT bitwise operator in conditional + return "ERROR"; + if (at & assertType::is_require) //!OCLINT bitwise operator in conditional + return "FATAL ERROR"; + return ""; + } + + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") + // depending on the current options this will remove the path of filenames + const char* skipPathFromFilename(const char* file) { +#ifndef DOCTEST_CONFIG_DISABLE + if (getContextOptions()->no_path_in_filenames) { + auto back = std::strrchr(file, '\\'); + auto forward = std::strrchr(file, '/'); + if (back || forward) { + if (back > forward) + forward = back; + return forward + 1; + } + } +#endif // DOCTEST_CONFIG_DISABLE + return file; + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + + bool SubcaseSignature::operator==(const SubcaseSignature& other) const { + return m_line == other.m_line + && std::strcmp(m_file, other.m_file) == 0 + && m_name == other.m_name; + } + + bool SubcaseSignature::operator<(const SubcaseSignature& other) const { + if (m_line != other.m_line) + return m_line < other.m_line; + if (std::strcmp(m_file, other.m_file) != 0) + return std::strcmp(m_file, other.m_file) < 0; + return m_name.compare(other.m_name) < 0; + } + + DOCTEST_DEFINE_INTERFACE(IContextScope) + + namespace detail { + void filldata::fill(std::ostream* stream, const void* in) { + if (in) { *stream << in; } + else { *stream << "nullptr"; } + } + + template + String toStreamLit(T t) { + std::ostream* os = tlssPush(); + os->operator<<(t); + return tlssPop(); + } + } + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) + // see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 + String toString(const std::string& in) { return in.c_str(); } +#endif // VS 2019 + + String toString(String in) { return in; } + + String toString(std::nullptr_t) { return "nullptr"; } + + String toString(bool in) { return in ? "true" : "false"; } + + String toString(float in) { return toStreamLit(in); } + String toString(double in) { return toStreamLit(in); } + String toString(double long in) { return toStreamLit(in); } + + String toString(char in) { return toStreamLit(static_cast(in)); } + String toString(char signed in) { return toStreamLit(static_cast(in)); } + String toString(char unsigned in) { return toStreamLit(static_cast(in)); } + String toString(short in) { return toStreamLit(in); } + String toString(short unsigned in) { return toStreamLit(in); } + String toString(signed in) { return toStreamLit(in); } + String toString(unsigned in) { return toStreamLit(in); } + String toString(long in) { return toStreamLit(in); } + String toString(long unsigned in) { return toStreamLit(in); } + String toString(long long in) { return toStreamLit(in); } + String toString(long long unsigned in) { return toStreamLit(in); } + + Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) + , m_scale(1.0) + , m_value(value) {} + + Approx Approx::operator()(double value) const { + Approx approx(value); + approx.epsilon(m_epsilon); + approx.scale(m_scale); + return approx; + } + + Approx& Approx::epsilon(double newEpsilon) { + m_epsilon = newEpsilon; + return *this; + } + Approx& Approx::scale(double newScale) { + m_scale = newScale; + return *this; + } + + bool operator==(double lhs, const Approx& rhs) { + // Thanks to Richard Harris for his help refining this formula + return std::fabs(lhs - rhs.m_value) < + rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); + } + bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } + bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } + bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } + bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } + bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } + bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } + bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } + bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } + bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } + bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } + bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } + + String toString(const Approx& in) { + return "Approx( " + doctest::toString(in.m_value) + " )"; + } + const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) + template + IsNaN::operator bool() const { + return std::isnan(value) ^ flipped; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template struct DOCTEST_INTERFACE_DEF IsNaN; + template + String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } + String toString(IsNaN in) { return toString(in); } + +} // namespace doctest + +#ifdef DOCTEST_CONFIG_DISABLE +namespace doctest { + Context::Context(int, const char* const*) {} + Context::~Context() = default; + void Context::applyCommandLine(int, const char* const*) {} + void Context::addFilter(const char*, const char*) {} + void Context::clearFilters() {} + void Context::setOption(const char*, bool) {} + void Context::setOption(const char*, int) {} + void Context::setOption(const char*, const char*) {} + bool Context::shouldExit() { return false; } + void Context::setAsDefaultForAssertsOutOfTestCases() {} + void Context::setAssertHandler(detail::assert_handler) {} + void Context::setCout(std::ostream*) {} + int Context::run() { return 0; } + + int IReporter::get_num_active_contexts() { return 0; } + const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } + int IReporter::get_num_stringified_contexts() { return 0; } + const String* IReporter::get_stringified_contexts() { return nullptr; } + + int registerReporter(const char*, int, IReporter*) { return 0; } + +} // namespace doctest +#else // DOCTEST_CONFIG_DISABLE + +#if !defined(DOCTEST_CONFIG_COLORS_NONE) +#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI) +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_CONFIG_COLORS_WINDOWS +#else // linux +#define DOCTEST_CONFIG_COLORS_ANSI +#endif // platform +#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI +#endif // DOCTEST_CONFIG_COLORS_NONE + +namespace doctest_detail_test_suite_ns { + // holds the current test suite + doctest::detail::TestSuite& getCurrentTestSuite() { + static doctest::detail::TestSuite data{}; + return data; + } +} // namespace doctest_detail_test_suite_ns + +namespace doctest { + namespace { + // the int (priority) is part of the key for automatic sorting - sadly one can register a + // reporter with a duplicate name and a different priority but hopefully that won't happen often :| + using reporterMap = std::map, reporterCreatorFunc>; + + reporterMap& getReporters() { + static reporterMap data; + return data; + } + reporterMap& getListeners() { + static reporterMap data; + return data; + } + } // namespace + namespace detail { +#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ + for(auto& curr_rep : g_cs->reporters_currently_used) \ + curr_rep->function(__VA_ARGS__) + + bool checkIfShouldThrow(assertType::Enum at) { + if (at & assertType::is_require) //!OCLINT bitwise operator in conditional + return true; + + if ((at & assertType::is_check) //!OCLINT bitwise operator in conditional + && getContextOptions()->abort_after > 0 && + (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= + getContextOptions()->abort_after) + return true; + + return false; + } + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN void throwException() { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) + } +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + void throwException() {} +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } // namespace detail + + namespace { + using namespace detail; + // matching of a string against a wildcard mask (case sensitivity configurable) taken from + // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing + int wildcmp(const char* str, const char* wild, bool caseSensitive) { + const char* cp = str; + const char* mp = wild; + + while ((*str) && (*wild != '*')) { + if ((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while (*str) { + if (*wild == '*') { + if (!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } + else if ((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; + } + else { + wild = mp; //!OCLINT parameter reassignment + str = cp++; //!OCLINT parameter reassignment + } + } + + while (*wild == '*') { + wild++; + } + return !*wild; + } + + // checks if the name matches any of the filters (and can be configured what to do when empty) + bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, + bool caseSensitive) { + if (filters.empty() && matchEmpty) + return true; + for (auto& curr : filters) + if (wildcmp(name, curr.c_str(), caseSensitive)) + return true; + return false; + } + + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(unsigned long long a, unsigned long long b) { + return (a << 5) + b; + } + + // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(const char* str) { + unsigned long long hash = 5381; + char c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + return hash; + } + + unsigned long long hash(const SubcaseSignature& sig) { + return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); + } + + unsigned long long hash(const std::vector& sigs, size_t count) { + unsigned long long running = 0; + auto end = sigs.begin() + count; + for (auto it = sigs.begin(); it != end; it++) { + running = hash(running, hash(*it)); + } + return running; + } + + unsigned long long hash(const std::vector& sigs) { + unsigned long long running = 0; + for (const SubcaseSignature& sig : sigs) { + running = hash(running, hash(sig)); + } + return running; + } + } // namespace + namespace detail { + bool Subcase::checkFilters() { + if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { + if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) + return true; + if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) + return true; + } + return false; + } + + Subcase::Subcase(const String& name, const char* file, int line) + : m_signature({ name, file, line }) { + if (!g_cs->reachedLeaf) { + if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() + || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { + // Going down. + if (checkFilters()) { return; } + + g_cs->subcaseStack.push_back(m_signature); + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + } + else { + if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { + // This subcase is reentered via control flow. + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth + && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) + == g_cs->fullyTraversedSubcases.end()) { + if (checkFilters()) { return; } + // This subcase is part of the one to be executed next. + g_cs->nextSubcaseStack.clear(); + g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), + g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); + g_cs->nextSubcaseStack.push_back(m_signature); + } + } + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + Subcase::~Subcase() { + if (m_entered) { + g_cs->currentSubcaseDepth--; + + if (!g_cs->reachedLeaf) { + // Leaf. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + g_cs->nextSubcaseStack.clear(); + g_cs->reachedLeaf = true; + } + else if (g_cs->nextSubcaseStack.empty()) { + // All children are finished. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + } + +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0 +#else + if (std::uncaught_exception() +#endif + && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS( + test_case_exception, { "exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false }); + g_cs->shouldLogCurrentException = false; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + Subcase::operator bool() const { return m_entered; } + + Result::Result(bool passed, const String& decomposition) + : m_passed(passed) + , m_decomp(decomposition) {} + + ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) + : m_at(at) {} + + TestSuite& TestSuite::operator*(const char* in) { + m_test_suite = in; + return *this; + } + + TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type, int template_id) { + m_file = file; + m_line = line; + m_name = nullptr; // will be later overridden in operator* + m_test_suite = test_suite.m_test_suite; + m_description = test_suite.m_description; + m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; + m_may_fail = test_suite.m_may_fail; + m_should_fail = test_suite.m_should_fail; + m_expected_failures = test_suite.m_expected_failures; + m_timeout = test_suite.m_timeout; + + m_test = test; + m_type = type; + m_template_id = template_id; + } + + TestCase::TestCase(const TestCase& other) + : TestCaseData() { + *this = other; + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& TestCase::operator=(const TestCase& other) { + TestCaseData::operator=(other); + m_test = other.m_test; + m_type = other.m_type; + m_template_id = other.m_template_id; + m_full_name = other.m_full_name; + + if (m_template_id != -1) + m_name = m_full_name.c_str(); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& TestCase::operator*(const char* in) { + m_name = in; + // make a new name with an appended type for templated test case + if (m_template_id != -1) { + m_full_name = String(m_name) + "<" + m_type + ">"; + // redirect the name to point to the newly constructed full name + m_name = m_full_name.c_str(); + } + return *this; + } + + bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting + if (m_line != other.m_line) + return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if (name_cmp != 0) + return name_cmp < 0; + const int file_cmp = m_file.compare(other.m_file); + if (file_cmp != 0) + return file_cmp < 0; + return m_template_id < other.m_template_id; + } + + // all the registered tests + std::set& getRegisteredTests() { + static std::set data; + return data; + } + } // namespace detail + namespace { + using namespace detail; + // for sorting tests by file/line + bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); + if (res != 0) + return res < 0; + if (lhs->m_line != rhs->m_line) + return lhs->m_line < rhs->m_line; + return lhs->m_template_id < rhs->m_template_id; + } + + // for sorting tests by suite/file/line + bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); + if (res != 0) + return res < 0; + return fileOrderComparator(lhs, rhs); + } + + // for sorting tests by name/suite/file/line + bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_name, rhs->m_name); + if (res != 0) + return res < 0; + return suiteOrderComparator(lhs, rhs); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + void color_to_stream(std::ostream& s, Color::Enum code) { + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE +#ifdef DOCTEST_CONFIG_COLORS_ANSI + if (g_no_colors || + (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) + return; + + auto col = ""; + // clang-format off + switch (code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement + case Color::Red: col = "[0;31m"; break; + case Color::Green: col = "[0;32m"; break; + case Color::Blue: col = "[0;34m"; break; + case Color::Cyan: col = "[0;36m"; break; + case Color::Yellow: col = "[0;33m"; break; + case Color::Grey: col = "[1;30m"; break; + case Color::LightGrey: col = "[0;37m"; break; + case Color::BrightRed: col = "[1;31m"; break; + case Color::BrightGreen: col = "[1;32m"; break; + case Color::BrightWhite: col = "[1;37m"; break; + case Color::Bright: // invalid + case Color::None: + case Color::White: + default: col = "[0m"; + } + // clang-format on + s << "\033" << col; +#endif // DOCTEST_CONFIG_COLORS_ANSI + +#ifdef DOCTEST_CONFIG_COLORS_WINDOWS + if (g_no_colors || + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) + return; + + static struct ConsoleHelper { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; + +#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) + + // clang-format off + switch (code) { + case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; + case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; + case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; + case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; + case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; + case Color::Grey: DOCTEST_SET_ATTR(0); break; + case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; + case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; + case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; + case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::None: + case Color::Bright: // invalid + default: DOCTEST_SET_ATTR(ch.origFgAttrs); + } + // clang-format on +#endif // DOCTEST_CONFIG_COLORS_WINDOWS + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + + std::vector& getExceptionTranslators() { + static std::vector data; + return data; + } + + String translateActiveException() { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + String res; + auto& translators = getExceptionTranslators(); + for (auto& curr : translators) + if (curr->translate(res)) + return res; + // clang-format off + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") + try { + throw; + } + catch (std::exception& ex) { + return ex.what(); + } + catch (std::string& msg) { + return msg.c_str(); + } + catch (const char* msg) { + return msg; + } + catch (...) { + return "unknown exception"; + } + DOCTEST_GCC_SUPPRESS_WARNING_POP + // clang-format on +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + return ""; +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } + } // namespace + + namespace detail { + // used by the macros for registering tests + int regTest(const TestCase& tc) { + getRegisteredTests().insert(tc); + return 0; + } + + // sets the current test suite + int setTestSuite(const TestSuite& ts) { + doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; + return 0; + } + +#ifdef DOCTEST_IS_DEBUGGER_ACTIVE + bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } +#else // DOCTEST_IS_DEBUGGER_ACTIVE +#ifdef DOCTEST_PLATFORM_LINUX + class ErrnoGuard { + public: + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + // See the comments in Catch2 for the reasoning behind this implementation: + // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 + bool isDebuggerActive() { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for (std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; + } +#elif defined(DOCTEST_PLATFORM_MAC) + // The following function is taken directly from the following technical note: + // https://developer.apple.com/library/archive/qa/qa1361/_index.html + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive() { + int mib[4]; + kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if (sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { + std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); + } +#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) + bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } +#else + bool isDebuggerActive() { return false; } +#endif // Platform +#endif // DOCTEST_IS_DEBUGGER_ACTIVE + + void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { + if (std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == + getExceptionTranslators().end()) + getExceptionTranslators().push_back(et); + } + + DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + + ContextScopeBase::ContextScopeBase() { + g_infoContexts.push_back(this); + } + + ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + // destroy cannot be inlined into the destructor because that would mean calling stringify after + // ContextScope has been destroyed (base class destructors run after derived class destructors). + // Instead, ContextScope calls this method directly from its destructor. + void ContextScopeBase::destroy() { +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if (std::uncaught_exceptions() > 0) { +#else + if (std::uncaught_exception()) { +#endif + std::ostringstream s; + this->stringify(&s); + g_cs->stringifiedContexts.push_back(s.str().c_str()); + } + g_infoContexts.pop_back(); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + } // namespace detail + namespace { + using namespace detail; + +#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) + struct FatalConditionHandler + { + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + }; +#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + + void reportFatal(const std::string&); + +#ifdef DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + DWORD id; + const char* name; + }; + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), + "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), + "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, + }; + + struct FatalConditionHandler + { + static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + DOCTEST_DECLARE_STATIC_MUTEX(mutex) + static bool execute = true; + { + DOCTEST_LOCK_MUTEX(mutex) + if (execute) { + bool reported = false; + for (size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if (reported == false) + reportFatal("Unhandled SEH exception caught"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + } + execute = false; + } + std::exit(EXIT_FAILURE); + } + + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + + FatalConditionHandler() { + isSet = true; + // 32k seems enough for doctest to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + // Register an unhandled exception filter + previousTop = SetUnhandledExceptionFilter(handleException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT{ + reportFatal("Terminate handler called"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT{ + if (signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if (isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } + + static void reset() { + if (isSet) { + // Unregister handler and restore the old guarantee + SetUnhandledExceptionFilter(previousTop); + SetThreadStackGuarantee(&guaranteeSize); + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); + isSet = false; + } + } + + ~FatalConditionHandler() { reset(); } + + private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void (DOCTEST_CDECL* prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; + static bool isSet; + static ULONG guaranteeSize; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; + }; + + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; + void (DOCTEST_CDECL* FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; + +#else // DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + int id; + const char* name; + }; + SignalDefs signalDefs[] = { {SIGINT, "SIGINT - Terminal interrupt signal"}, + {SIGILL, "SIGILL - Illegal instruction signal"}, + {SIGFPE, "SIGFPE - Floating point error signal"}, + {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, + {SIGTERM, "SIGTERM - Termination request signal"}, + {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"} }; + + struct FatalConditionHandler + { + static bool isSet; + static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; + static stack_t oldSigStack; + static size_t altStackSize; + static char* altStackMem; + + static void handleSignal(int sig) { + const char* name = ""; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + SignalDefs& def = signalDefs[i]; + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise(sig); + } + + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + + FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = altStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { reset(); } + static void reset() { + if (isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for (std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + }; + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; + +#endif // DOCTEST_PLATFORM_WINDOWS +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + + } // namespace + + namespace { + using namespace detail; + +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) +#else + // TODO: integration with XCode and other IDEs +#define DOCTEST_OUTPUT_DEBUG_STRING(text) +#endif // Platform + + void addAssert(assertType::Enum at) { + if ((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsCurrentTest_atomic++; + } + + void addFailedAssert(assertType::Enum at) { + if ((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsFailedCurrentTest_atomic++; + } + +#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) + void reportFatal(const std::string& message) { + g_cs->failure_flags |= TestCaseFailureReason::Crash; + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, { message.c_str(), true }); + + while (g_cs->subcaseStack.size()) { + g_cs->subcaseStack.pop_back(); + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + + g_cs->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + } // namespace + + AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) { +#if DOCTEST_MSVC + if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC + ++m_expr; +#endif // MSVC + } + + namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const String& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + void ResultBuilder::setResult(const Result& res) { + m_decomp = res.m_decomp; + m_failed = !res.m_passed; + } + + void ResultBuilder::translateException() { + m_threw = true; + m_exception = translateActiveException(); + } + + bool ResultBuilder::log() { + if (m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw; + } + else if ((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT + m_failed = !m_threw_as || !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw_as; + } + else if (m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + m_failed = !m_exception_string.check(m_exception); + } + else if (m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + m_failed = m_threw; + } + + if (m_exception.size()) + m_exception = "\"" + m_exception + "\""; + + if (is_running_in_test) { + addAssert(m_at); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); + + if (m_failed) + addFailedAssert(m_at); + } + else if (m_failed) { + failed_out_of_a_testing_context(*this); + } + + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void ResultBuilder::react() const { + if (m_failed && checkIfShouldThrow(m_at)) + throwException(); + } + + void failed_out_of_a_testing_context(const AssertData& ad) { + if (g_cs->ah) + g_cs->ah(ad); + else + std::abort(); + } + + bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, + const Result& result) { + bool failed = !result.m_passed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); + DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + return !failed; + } + + MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { + m_stream = tlssPush(); + m_file = file; + m_line = line; + m_severity = severity; + } + + MessageBuilder::~MessageBuilder() { + if (!logged) + tlssPop(); + } + + DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) + + bool MessageBuilder::log() { + if (!logged) { + m_string = tlssPop(); + logged = true; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); + + const bool isWarn = m_severity & assertType::is_warn; + + // warn is just a message in this context so we don't treat it as an assert + if (!isWarn) { + addAssert(m_severity); + addFailedAssert(m_severity); + } + + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void MessageBuilder::react() { + if (m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional + throwException(); + } + } // namespace detail + namespace { + using namespace detail; + + // clang-format off + + // ================================================================================================= + // The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp + // This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. + // ================================================================================================= + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode(std::string const& str, ForWhat forWhat = ForTextNodes); + + void encodeTo(std::ostream& os) const; + + friend std::ostream& operator << (std::ostream& os, XmlEncode const& xmlEncode); + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement(XmlWriter* writer); + + ScopedElement(ScopedElement&& other) DOCTEST_NOEXCEPT; + ScopedElement& operator=(ScopedElement&& other) DOCTEST_NOEXCEPT; + + ~ScopedElement(); + + ScopedElement& writeText(std::string const& text, bool indent = true); + + template + ScopedElement& writeAttribute(std::string const& name, T const& attribute) { + m_writer->writeAttribute(name, attribute); + return *this; + } + + private: + mutable XmlWriter* m_writer = nullptr; + }; + +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter(std::ostream& os = std::cout); +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter(std::ostream& os); +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + ~XmlWriter(); + + XmlWriter(XmlWriter const&) = delete; + XmlWriter& operator=(XmlWriter const&) = delete; + + XmlWriter& startElement(std::string const& name); + + ScopedElement scopedElement(std::string const& name); + + XmlWriter& endElement(); + + XmlWriter& writeAttribute(std::string const& name, std::string const& attribute); + + XmlWriter& writeAttribute(std::string const& name, const char* attribute); + + XmlWriter& writeAttribute(std::string const& name, bool attribute); + + template + XmlWriter& writeAttribute(std::string const& name, T const& attribute) { + std::stringstream rss; + rss << attribute; + return writeAttribute(name, rss.str()); + } + + XmlWriter& writeText(std::string const& text, bool indent = true); + + //XmlWriter& writeComment( std::string const& text ); + + //void writeStylesheetRef( std::string const& url ); + + //XmlWriter& writeBlankLine(); + + void ensureTagClosed(); + + void writeDeclaration(); + + private: + + void newlineIfNecessary(); + + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + }; + + // ================================================================================================= + // The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp + // This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. + // ================================================================================================= + + using uchar = unsigned char; + + namespace { + + size_t trailingBytes(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return 2; + } + if ((c & 0xF0) == 0xE0) { + return 3; + } + if ((c & 0xF8) == 0xF0) { + return 4; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + uint32_t headerValue(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return c & 0x1F; + } + if ((c & 0xF0) == 0xE0) { + return c & 0x0F; + } + if ((c & 0xF8) == 0xF0) { + return c & 0x07; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + void hexEscapeChar(std::ostream& os, unsigned char c) { + std::ios_base::fmtflags f(os.flags()); + os << "\\x" + << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast(c); + os.flags(f); + } + + } // anonymous namespace + + XmlEncode::XmlEncode(std::string const& str, ForWhat forWhat) + : m_str(str), + m_forWhat(forWhat) + {} + + void XmlEncode::encodeTo(std::ostream& os) const { + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: https://www.w3.org/TR/xml/#syntax) + + for (std::size_t idx = 0; idx < m_str.size(); ++idx) { + uchar c = m_str[idx]; + switch (c) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: https://www.w3.org/TR/xml/#syntax + if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') + os << ">"; + else + os << c; + break; + + case '\"': + if (m_forWhat == ForAttributes) + os << """; + else + os << c; + break; + + default: + // Check for control characters and invalid utf-8 + + // Escape control characters in standard ascii + // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { + hexEscapeChar(os, c); + break; + } + + // Plain ASCII: Write it to stream + if (c < 0x7F) { + os << c; + break; + } + + // UTF-8 territory + // Check if the encoding is valid and if it is not, hex escape bytes. + // Important: We do not check the exact decoded values for validity, only the encoding format + // First check that this bytes is a valid lead byte: + // This means that it is not encoded as 1111 1XXX + // Or as 10XX XXXX + if (c < 0xC0 || + c >= 0xF8) { + hexEscapeChar(os, c); + break; + } + + auto encBytes = trailingBytes(c); + // Are there enough bytes left to avoid accessing out-of-bounds memory? + if (idx + encBytes - 1 >= m_str.size()) { + hexEscapeChar(os, c); + break; + } + // The header is valid, check data + // The next encBytes bytes must together be a valid utf-8 + // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) + bool valid = true; + uint32_t value = headerValue(c); + for (std::size_t n = 1; n < encBytes; ++n) { + uchar nc = m_str[idx + n]; + valid &= ((nc & 0xC0) == 0x80); + value = (value << 6) | (nc & 0x3F); + } + + if ( + // Wrong bit pattern of following bytes + (!valid) || + // Overlong encodings + (value < 0x80) || + (value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant + (0x800 < value && value < 0x10000 && encBytes > 3) || + // Encoded value out of range + (value >= 0x110000) + ) { + hexEscapeChar(os, c); + break; + } + + // If we got here, this is in fact a valid(ish) utf-8 sequence + for (std::size_t n = 0; n < encBytes; ++n) { + os << m_str[idx + n]; + } + idx += encBytes - 1; + break; + } + } + } + + std::ostream& operator << (std::ostream& os, XmlEncode const& xmlEncode) { + xmlEncode.encodeTo(os); + return os; + } + + XmlWriter::ScopedElement::ScopedElement(XmlWriter* writer) + : m_writer(writer) + {} + + XmlWriter::ScopedElement::ScopedElement(ScopedElement&& other) DOCTEST_NOEXCEPT + : m_writer(other.m_writer) { + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=(ScopedElement&& other) DOCTEST_NOEXCEPT { + if (m_writer) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + + XmlWriter::ScopedElement::~ScopedElement() { + if (m_writer) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText(std::string const& text, bool indent) { + m_writer->writeText(text, indent); + return *this; + } + + XmlWriter::XmlWriter(std::ostream& os) : m_os(os) + { + // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627 + } + + XmlWriter::~XmlWriter() { + while (!m_tags.empty()) + endElement(); + } + + XmlWriter& XmlWriter::startElement(std::string const& name) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back(name); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement(std::string const& name) { + ScopedElement scoped(this); + startElement(name); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr(0, m_indent.size() - 2); + if (m_tagIsOpen) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute(std::string const& name, std::string const& attribute) { + if (!name.empty() && !attribute.empty()) + m_os << ' ' << name << "=\"" << XmlEncode(attribute, XmlEncode::ForAttributes) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute(std::string const& name, const char* attribute) { + if (!name.empty() && attribute && attribute[0] != '\0') + m_os << ' ' << name << "=\"" << XmlEncode(attribute, XmlEncode::ForAttributes) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute(std::string const& name, bool attribute) { + m_os << ' ' << name << "=\"" << (attribute ? "true" : "false") << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText(std::string const& text, bool indent) { + if (!text.empty()) { + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if (tagWasOpen && indent) + m_os << m_indent; + m_os << XmlEncode(text); + m_needsNewline = true; + } + return *this; + } + + //XmlWriter& XmlWriter::writeComment( std::string const& text ) { + // ensureTagClosed(); + // m_os << m_indent << ""; + // m_needsNewline = true; + // return *this; + //} + + //void XmlWriter::writeStylesheetRef( std::string const& url ) { + // m_os << "\n"; + //} + + //XmlWriter& XmlWriter::writeBlankLine() { + // ensureTagClosed(); + // m_os << '\n'; + // return *this; + //} + + void XmlWriter::ensureTagClosed() { + if (m_tagIsOpen) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if (m_needsNewline) { + m_os << std::endl; + m_needsNewline = false; + } + } + + // ================================================================================================= + // End of copy-pasted code from Catch + // ================================================================================================= + + // clang-format on + + struct XmlReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + XmlReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + std::stringstream ss; + for (int i = 0; i < num_contexts; ++i) { + contexts[i]->stringify(&ss); + xml.scopedElement("Info").writeText(ss.str()); + ss.str(""); + } + } + } + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + void test_case_start_impl(const TestCaseData& in) { + bool open_ts_tag = false; + if (tc != nullptr) { // we have already opened a test suite + if (std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { + xml.endElement(); + open_ts_tag = true; + } + } + else { + open_ts_tag = true; // first test case ==> first test suite + } + + if (open_ts_tag) { + xml.startElement("TestSuite"); + xml.writeAttribute("name", in.m_test_suite); + } + + tc = ∈ + xml.startElement("TestCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) + .writeAttribute("line", line(in.m_line)) + .writeAttribute("description", in.m_description); + + if (Approx(in.m_timeout) != 0) + xml.writeAttribute("timeout", in.m_timeout); + if (in.m_may_fail) + xml.writeAttribute("may_fail", true); + if (in.m_should_fail) + xml.writeAttribute("should_fail", true); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + test_run_start(); + if (opt.list_reporters) { + for (auto& curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + for (auto& curr : getReporters()) + xml.scopedElement("Reporter") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + } + else if (opt.count || opt.list_test_cases) { + for (unsigned i = 0; i < in.num_data; ++i) { + xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) + .writeAttribute("testsuite", in.data[i]->m_test_suite) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); + } + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + } + else if (opt.list_test_suites) { + for (unsigned i = 0; i < in.num_data; ++i) + xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + xml.scopedElement("OverallResultsTestSuites") + .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); + } + xml.endElement(); + } + + void test_run_start() override { + xml.writeDeclaration(); + + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + + xml.startElement("doctest").writeAttribute("binary", binary_name); + if (opt.no_version == false) + xml.writeAttribute("version", DOCTEST_VERSION_STR); + + // only the consequential ones (TODO: filters) + xml.scopedElement("Options") + .writeAttribute("order_by", opt.order_by.c_str()) + .writeAttribute("rand_seed", opt.rand_seed) + .writeAttribute("first", opt.first) + .writeAttribute("last", opt.last) + .writeAttribute("abort_after", opt.abort_after) + .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) + .writeAttribute("case_sensitive", opt.case_sensitive) + .writeAttribute("no_throw", opt.no_throw) + .writeAttribute("no_skip", opt.no_skip); + } + + void test_run_end(const TestRunStats& p) override { + if (tc) // the TestSuite tag - only if there has been at least 1 test case + xml.endElement(); + + xml.scopedElement("OverallResultsAsserts") + .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) + .writeAttribute("failures", p.numAssertsFailed); + + xml.startElement("OverallResultsTestCases") + .writeAttribute("successes", + p.numTestCasesPassingFilters - p.numTestCasesFailed) + .writeAttribute("failures", p.numTestCasesFailed); + if (opt.no_skipped_summary == false) + xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); + xml.endElement(); + + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + test_case_start_impl(in); + xml.ensureTagClosed(); + } + + void test_case_reenter(const TestCaseData&) override {} + + void test_case_end(const CurrentTestCaseStats& st) override { + xml.startElement("OverallResultsAsserts") + .writeAttribute("successes", + st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); + if (opt.duration) + xml.writeAttribute("duration", st.seconds); + if (tc->m_expected_failures) + xml.writeAttribute("expected_failures", tc->m_expected_failures); + xml.endElement(); + + xml.endElement(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.scopedElement("Exception") + .writeAttribute("crash", e.is_crash) + .writeText(e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + xml.startElement("SubCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("line", line(in.m_line)); + xml.ensureTagClosed(); + } + + void subcase_end() override { xml.endElement(); } + + void log_assert(const AssertData& rb) override { + if (!rb.m_failed && !opt.success) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Expression") + .writeAttribute("success", !rb.m_failed) + .writeAttribute("type", assertString(rb.m_at)) + .writeAttribute("filename", skipPathFromFilename(rb.m_file)) + .writeAttribute("line", line(rb.m_line)); + + xml.scopedElement("Original").writeText(rb.m_expr); + + if (rb.m_threw) + xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); + + if (rb.m_at & assertType::is_throws_as) + xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); + if (rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); + if ((rb.m_at & assertType::is_normal) && !rb.m_threw) + xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void log_message(const MessageData& mb) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Message") + .writeAttribute("type", failureString(mb.m_severity)) + .writeAttribute("filename", skipPathFromFilename(mb.m_file)) + .writeAttribute("line", line(mb.m_line)); + + xml.scopedElement("Text").writeText(mb.m_string.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void test_case_skipped(const TestCaseData& in) override { + if (opt.no_skipped_summary == false) { + test_case_start_impl(in); + xml.writeAttribute("skipped", "true"); + xml.endElement(); + } + } + }; + + DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); + + void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { + if ((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " + << Color::None; + + if (rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } + else if ((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //!OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\", " << rb.m_exception_type << " ) " << Color::None; + if (rb.m_threw) { + if (!rb.m_failed) { + s << "threw as expected!\n"; + } + else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } + } + else { + s << "did NOT throw at all!\n"; + } + } + else if (rb.m_at & + assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & + assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } + else if (rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan + << rb.m_exception << "\n"; + } + else { + s << (rb.m_threw ? "THREW exception: " : + (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if (rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } + } + + // TODO: + // - log_message() + // - respond to queries + // - honor remaining options + // - more attributes in tags + struct JUnitReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { + static std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS + + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; + + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + return std::string(timeStamp); + } + + struct JUnitTestMessage + { + JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) + : message(_message), type(_type), details(_details) {} + + JUnitTestMessage(const std::string& _message, const std::string& _details) + : message(_message), type(), details(_details) {} + + std::string message, type, details; + }; + + struct JUnitTestCase + { + JUnitTestCase(const std::string& _classname, const std::string& _name) + : classname(_classname), name(_name), time(0), failures() {} + + std::string classname, name; + double time; + std::vector failures, errors; + }; + + void add(const std::string& classname, const std::string& name) { + testcases.emplace_back(classname, name); + } + + void appendSubcaseNamesToLastTestcase(std::vector nameStack) { + for (auto& curr : nameStack) + if (curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); + } + + void addTime(double time) { + if (time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; + } + + void addFailure(const std::string& message, const std::string& type, const std::string& details) { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; + } + + void addError(const std::string& message, const std::string& details) { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; + } + + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; + + JUnitTestCaseData testCaseData; + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + JUnitReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData&) override { + xml.writeDeclaration(); + } + + void test_run_start() override { + xml.writeDeclaration(); + } + + void test_run_end(const TestRunStats& p) override { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if (binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite").writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if (opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if (opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for (const auto& testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if (opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for (const auto& failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for (const auto& error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData& in) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats&) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData& rb) override { + if (!rb.m_failed) // report only failures & ignore the `success` option + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + log_contexts(os); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData& mb) override { + if (mb.m_severity & assertType::is_warn) // report only failures + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + os << mb.m_string.c_str() << "\n"; + log_contexts(os); + + testCaseData.addFailure(mb.m_string.c_str(), + mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); + } + + void test_case_skipped(const TestCaseData&) override {} + + void log_contexts(std::ostringstream& s) { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } + }; + + DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); + + struct Whitespace + { + int nrSpaces; + explicit Whitespace(int nr) + : nrSpaces(nr) {} + }; + + std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { + if (ws.nrSpaces != 0) + out << std::setw(ws.nrSpaces) << ' '; + return out; + } + + struct ConsoleReporter : public IReporter + { + std::ostream& s; + bool hasLoggedCurrentTestStart; + std::vector subcasesStack; + size_t currentSubcaseLevel; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc; + + ConsoleReporter(const ContextOptions& co) + : s(*co.cout) + , opt(co) {} + + ConsoleReporter(const ContextOptions& co, std::ostream& ostr) + : s(ostr) + , opt(co) {} + + // ========================================================================================= + // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE + // ========================================================================================= + + void separator_to_stream() { + s << Color::Yellow + << "===============================================================================" + "\n"; + } + + const char* getSuccessOrFailString(bool success, assertType::Enum at, + const char* success_str) { + if (success) + return success_str; + return failureString(at); + } + + Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { + return success ? Color::BrightGreen : + (at & assertType::is_warn) ? Color::Yellow : Color::Red; + } + + void successOrFailColoredStringToStream(bool success, assertType::Enum at, + const char* success_str = "SUCCESS") { + s << getSuccessOrFailColor(success, at) + << getSuccessOrFailString(success, at, success_str) << ": "; + } + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if (num_contexts) { + auto contexts = get_active_contexts(); + + s << Color::None << " logged: "; + for (int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << "\n"; + } + } + + s << "\n"; + } + + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char* file, int line, + const char* tail = "") { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + + void logTestStart() { + if (hasLoggedCurrentTestStart) + return; + + separator_to_stream(); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); + if (tc->m_description) + s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; + if (tc->m_test_suite && tc->m_test_suite[0] != '\0') + s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; + if (strncmp(tc->m_name, " Scenario:", 11) != 0) + s << Color::Yellow << "TEST CASE: "; + s << Color::None << tc->m_name << "\n"; + + for (size_t i = 0; i < currentSubcaseLevel; ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if (currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; + for (size_t i = 0; i < subcasesStack.size(); ++i) { + if (subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } + + s << "\n"; + + hasLoggedCurrentTestStart = true; + } + + void printVersion() { + if (opt.no_version == false) + s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" + << DOCTEST_VERSION_STR << "\"\n"; + } + + void printIntro() { + if (opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } + } + + void printHelp() { + int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); + printVersion(); + // clang-format off + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filter values: \"str1,str2,str3\" (comma separated strings)\n"; + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filters use wildcards for matching strings\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "something passes a filter if any of the strings in a filter matches\n"; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n"; +#endif + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "Query flags - the program quits after them. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h " + << Whitespace(sizePrefixDisplay * 0) << "prints this message\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version " + << Whitespace(sizePrefixDisplay * 1) << "prints the version\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count " + << Whitespace(sizePrefixDisplay * 1) << "prints the number of matching tests\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases " + << Whitespace(sizePrefixDisplay * 1) << "lists all matching tests by name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites " + << Whitespace(sizePrefixDisplay * 1) << "lists all matching test suites\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters " + << Whitespace(sizePrefixDisplay * 1) << "lists all registered reporters\n\n"; + // ================================================================================== << 79 + s << Color::Cyan << "[doctest] " << Color::None; + s << "The available / options/filters are:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case= " + << Whitespace(sizePrefixDisplay * 1) << "filters tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude= " + << Whitespace(sizePrefixDisplay * 1) << "filters OUT tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file= " + << Whitespace(sizePrefixDisplay * 1) << "filters tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude= " + << Whitespace(sizePrefixDisplay * 1) << "filters OUT tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite= " + << Whitespace(sizePrefixDisplay * 1) << "filters tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude= " + << Whitespace(sizePrefixDisplay * 1) << "filters OUT tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase= " + << Whitespace(sizePrefixDisplay * 1) << "filters subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude= " + << Whitespace(sizePrefixDisplay * 1) << "filters OUT subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters= " + << Whitespace(sizePrefixDisplay * 1) << "reporters to use (console is default)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out= " + << Whitespace(sizePrefixDisplay * 1) << "output filename\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " + << Whitespace(sizePrefixDisplay * 1) << "how the tests should be ordered\n"; + s << Whitespace(sizePrefixDisplay * 3) << " - [file/suite/name/rand/none]\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " + << Whitespace(sizePrefixDisplay * 1) << "seed for random ordering\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " + << Whitespace(sizePrefixDisplay * 1) << "the first test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay * 3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last= " + << Whitespace(sizePrefixDisplay * 1) << "the last test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay * 3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after= " + << Whitespace(sizePrefixDisplay * 1) << "stop after failed assertions\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels= " + << Whitespace(sizePrefixDisplay * 1) << "apply filters for the first levels\n"; + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "Bool options - can be used like flags and true is assumed. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success= " + << Whitespace(sizePrefixDisplay * 1) << "include successful assertions in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive= " + << Whitespace(sizePrefixDisplay * 1) << "filters being treated as case sensitive\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit= " + << Whitespace(sizePrefixDisplay * 1) << "exits after the tests finish\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " + << Whitespace(sizePrefixDisplay * 1) << "prints the time duration of each test\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " + << Whitespace(sizePrefixDisplay * 1) << "minimal console output (only failures)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " + << Whitespace(sizePrefixDisplay * 1) << "no console output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " + << Whitespace(sizePrefixDisplay * 1) << "skips exceptions-related assert checks\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " + << Whitespace(sizePrefixDisplay * 1) << "returns (or exits) always with success\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " + << Whitespace(sizePrefixDisplay * 1) << "skips all runtime doctest operations\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " + << Whitespace(sizePrefixDisplay * 1) << "omit the framework intro in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " + << Whitespace(sizePrefixDisplay * 1) << "omit the framework version in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " + << Whitespace(sizePrefixDisplay * 1) << "disables colors in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors= " + << Whitespace(sizePrefixDisplay * 1) << "use colors even when not in a tty\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks= " + << Whitespace(sizePrefixDisplay * 1) << "disables breakpoints in debuggers\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip= " + << Whitespace(sizePrefixDisplay * 1) << "don't skip test cases marked as skip\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line= " + << Whitespace(sizePrefixDisplay * 1) << ":n: vs (n): for line numbers in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames= " + << Whitespace(sizePrefixDisplay * 1) << "only filenames and no paths in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " + << Whitespace(sizePrefixDisplay * 1) << "0 instead of real line numbers in output\n"; + // ================================================================================== << 79 + // clang-format on + + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "for more information visit the project documentation\n\n"; + } + + void printRegisteredReporters() { + printVersion(); + auto printReporters = [this](const reporterMap& reporters, const char* type) { + if (reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; + for (auto& curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + if (opt.version) { + printVersion(); + } + else if (opt.help) { + printHelp(); + } + else if (opt.list_reporters) { + printRegisteredReporters(); + } + else if (opt.count || opt.list_test_cases) { + if (opt.list_test_cases) { + s << Color::Cyan << "[doctest] " << Color::None + << "listing all test case names\n"; + separator_to_stream(); + } + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_name << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + + } + else if (opt.list_test_suites) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; + separator_to_stream(); + + for (unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_test_suite << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "test suites with unskipped test cases passing the current filters: " + << g_cs->numTestSuitesPassingFilters << "\n"; + } + } + + void test_run_start() override { + if (!opt.minimal) + printIntro(); + } + + void test_run_end(const TestRunStats& p) override { + if (opt.minimal && p.numTestCasesFailed == 0) + return; + + separator_to_stream(); + s << std::dec; + + auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); + auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); + auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); + const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) + << p.numTestCasesPassingFilters << " | " + << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : + Color::Green) + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" + << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) + << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; + if (opt.no_skipped_summary == false) { + const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped + << " skipped" << Color::None; + } + s << "\n"; + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) + << p.numAsserts << " | " + << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numAssertsFailed << " failed" << Color::None << " |\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) + << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; + } + + void test_case_start(const TestCaseData& in) override { + hasLoggedCurrentTestStart = false; + tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; + } + + void test_case_reenter(const TestCaseData&) override { + subcasesStack.clear(); + } + + void test_case_end(const CurrentTestCaseStats& st) override { + if (tc->m_no_output) + return; + + // log the preamble of the test case only if there is something + // else to print - something other than that an assert has failed + if (opt.duration || + (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) + logTestStart(); + + if (opt.duration) + s << Color::None << std::setprecision(6) << std::fixed << st.seconds + << " s: " << tc->m_name << "\n"; + + if (st.failure_flags & TestCaseFailureReason::Timeout) + s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) + << std::fixed << tc->m_timeout << "!\n"; + + if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { + s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { + s << Color::Yellow << "Failed as expected so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { + s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; + } + else if (st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { + s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures + << " times so marking it as failed!\n"; + } + else if (st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { + s << Color::Yellow << "Failed exactly " << tc->m_expected_failures + << " times as expected so marking it as not failed!\n"; + } + if (st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { + s << Color::Red << "Aborting - too many failed asserts!\n"; + } + s << Color::None; // lgtm [cpp/useless-expression] + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + if (tc->m_no_output) + return; + + logTestStart(); + + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); + successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : + assertType::is_check); + s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") + << Color::Cyan << e.error_string << "\n"; + + int num_stringified_contexts = get_num_stringified_contexts(); + if (num_stringified_contexts) { + auto stringified_contexts = get_stringified_contexts(); + s << Color::None << " logged: "; + for (int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") + << stringified_contexts[i - 1] << "\n"; + } + } + s << "\n" << Color::None; + } + + void subcase_start(const SubcaseSignature& subc) override { + subcasesStack.push_back(subc); + ++currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void subcase_end() override { + --currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void log_assert(const AssertData& rb) override { + if ((!rb.m_failed && !opt.success) || tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(rb.m_file, rb.m_line, " "); + successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); + + fulltext_log_assert_to_stream(s, rb); + + log_contexts(); + } + + void log_message(const MessageData& mb) override { + if (tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(mb.m_file, mb.m_line, " "); + s << getSuccessOrFailColor(false, mb.m_severity) + << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, + "MESSAGE") << ": "; + s << Color::None << mb.m_string << "\n"; + log_contexts(); + } + + void test_case_skipped(const TestCaseData&) override {} + }; + + DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); + +#ifdef DOCTEST_PLATFORM_WINDOWS + struct DebugOutputWindowReporter : public ConsoleReporter + { + DOCTEST_THREAD_LOCAL static std::ostringstream oss; + + DebugOutputWindowReporter(const ContextOptions& co) + : ConsoleReporter(co, oss) {} + +#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ + void func(type arg) override { \ + bool with_col = g_no_colors; \ + g_no_colors = false; \ + ConsoleReporter::func(arg); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ + g_no_colors = with_col; \ + } + + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) + }; + + DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; +#endif // DOCTEST_PLATFORM_WINDOWS + + // the implementation of parseOption() + bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { + // going from the end to the beginning and stopping on the first occurrence from the end + for (int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if (temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + auto curr = argv[index]; + while (curr != temp) { + if (*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if (noBadCharsFound && argv[index][0] == '-') { + if (value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if (len) { + *value = temp; + return true; + } + } + else { + // just a flag - no value + return true; + } + } + } + } + return false; + } + + // parses an option and returns the string after the '=' character + bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, + const String& defaultVal = String()) { + if (value) + *value = defaultVal; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + // offset (normally 3 for "dt-") to skip prefix + if (parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) + return true; +#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + return parseOptionImpl(argc, argv, pattern, value); + } + + // locates a flag on the command line + bool parseFlag(int argc, const char* const* argv, const char* pattern) { + return parseOption(argc, argv, pattern); + } + + // parses a comma separated list of words after a pattern in one of the arguments in argv + bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, + std::vector& res) { + String filtersString; + if (parseOption(argc, argv, pattern, &filtersString)) { + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if (string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; + + bool seenBackslash = false; + const char* current = filtersString.c_str(); + const char* end = current + strlen(current); + while (current != end) { + char character = *current++; + if (seenBackslash) { + seenBackslash = false; + if (character == ',' || character == '\\') { + s.put(character); + continue; + } + s.put('\\'); + } + if (character == '\\') { + seenBackslash = true; + } + else if (character == ',') { + flush(); + } + else { + s.put(character); + } + } + + if (seenBackslash) { + s.put('\\'); + } + flush(); + return true; + } + return false; + } + + enum optionType + { + option_bool, + option_int + }; + + // parses an int/bool option from the command line + bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, + int& res) { + String parsedValue; + if (!parseOption(argc, argv, pattern, &parsedValue)) + return false; + + if (type) { + // integer + // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... + int theInt = std::atoi(parsedValue.c_str()); + if (theInt != 0) { + res = theInt; //!OCLINT parameter reassignment + return true; + } + } + else { + // boolean + const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 + const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for (unsigned i = 0; i < 4; i++) { + if (parsedValue.compare(positive[i], true) == 0) { + res = 1; //!OCLINT parameter reassignment + return true; + } + if (parsedValue.compare(negative[i], true) == 0) { + res = 0; //!OCLINT parameter reassignment + return true; + } + } + } + return false; + } + } // namespace + + Context::Context(int argc, const char* const* argv) + : p(new detail::ContextState) { + parseArgs(argc, argv, true); + if (argc) + p->binary_name = argv[0]; + } + + Context::~Context() { + if (g_cs == p) + g_cs = nullptr; + delete p; + } + + void Context::applyCommandLine(int argc, const char* const* argv) { + parseArgs(argc, argv); + if (argc) + p->binary_name = argv[0]; + } + + // parses args + void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + using namespace detail; + + // clang-format off + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=", p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]); + // clang-format on + + int intRes = 0; + String strRes; + +#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ + p->var = static_cast(intRes); \ + else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ + p->var = true; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ + p->var = intRes; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ + if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ + withDefaults) \ + p->var = strRes + + // clang-format off + DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); + DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file"); + DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0); + + DOCTEST_PARSE_INT_OPTION("first", "f", first, 0); + DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX); + + DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0); + DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX); + + DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); + // clang-format on + + if (withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + p->list_reporters = false; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { + p->help = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { + p->version = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { + p->count = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { + p->list_test_suites = true; + p->exit = true; + } + if (parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { + p->list_reporters = true; + p->exit = true; + } + } + + // allows the user to add procedurally to the filters from the command line + void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + + // allows the user to clear all filters from the command line + void Context::clearFilters() { + for (auto& curr : p->filters) + curr.clear(); + } + + // allows the user to override procedurally the bool options from the command line + void Context::setOption(const char* option, bool value) { + setOption(option, value ? "true" : "false"); + } + + // allows the user to override procedurally the int options from the command line + void Context::setOption(const char* option, int value) { + setOption(option, toString(value).c_str()); + } + + // allows the user to override procedurally the string options from the command line + void Context::setOption(const char* option, const char* value) { + auto argv = String("-") + option + "=" + value; + auto lvalue = argv.c_str(); + parseArgs(1, &lvalue); + } + + // users should query this in their main() and exit the program if true + bool Context::shouldExit() { return p->exit; } + + void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } + + void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } + + void Context::setCout(std::ostream* out) { p->cout = out; } + + static class DiscardOStream : public std::ostream + { + private: + class : public std::streambuf + { + private: + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; + + protected: + std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + + int_type overflow(int_type ch) override { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } + } discardBuf; + + public: + DiscardOStream() + : std::ostream(&discardBuf) {} + } discardOut; + + // the main function that does all the filtering and test running + int Context::run() { + using namespace detail; + + // save the old context state in case such was setup - for using asserts out of a testing context + auto old_cs = g_cs; + // this is the current contest + g_cs = p; + is_running_in_test = true; + + g_no_colors = p->no_colors; + p->resetRunData(); + + std::fstream fstr; + if (p->cout == nullptr) { + if (p->quiet) { + p->cout = &discardOut; + } + else if (p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } + else { +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + // stdout by default + p->cout = &std::cout; +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + return EXIT_FAILURE; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + } + } + + FatalConditionHandler::allocateAltStackMem(); + + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + + if (fstr.is_open()) + fstr.close(); + + // restore context + g_cs = old_cs; + is_running_in_test = false; + + // we have to free the reporters which were allocated when the run started + for (auto& curr : p->reporters_currently_used) + delete curr; + p->reporters_currently_used.clear(); + + if (p->numTestCasesFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; + }; + + // setup default reporter if none is given through the command line + if (p->filters[8].empty()) + p->filters[8].push_back("console"); + + // check to see if any of the registered reporters has been selected + for (auto& curr : getReporters()) { + if (matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) + p->reporters_currently_used.push_back(curr.second(*g_cs)); + } + + // TODO: check if there is nothing in reporters_currently_used + + // prepend all listeners + for (auto& curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + +#ifdef DOCTEST_PLATFORM_WINDOWS + if (isDebuggerActive() && p->no_debug_output == false) + p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); +#endif // DOCTEST_PLATFORM_WINDOWS + + // handle version, help and no_run + if (p->no_run || p->version || p->help || p->list_reporters) { + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); + + return cleanup_and_return(); + } + + std::vector testArray; + for (auto& curr : getRegisteredTests()) + testArray.push_back(&curr); + p->numTestCases = testArray.size(); + + // sort the collected records + if (!testArray.empty()) { + if (p->order_by.compare("file", true) == 0) { + std::sort(testArray.begin(), testArray.end(), fileOrderComparator); + } + else if (p->order_by.compare("suite", true) == 0) { + std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); + } + else if (p->order_by.compare("name", true) == 0) { + std::sort(testArray.begin(), testArray.end(), nameOrderComparator); + } + else if (p->order_by.compare("rand", true) == 0) { + std::srand(p->rand_seed); + + // random_shuffle implementation + const auto first = &testArray[0]; + for (size_t i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = std::rand() % (i + 1); + + const auto temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } + else if (p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times + } + } + + std::set testSuitesPassingFilt; + + bool query_mode = p->count || p->list_test_cases || p->list_test_suites; + std::vector queryResults; + + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); + + // invoke the registered functions if they match the filter criteria (or just count them) + for (auto& curr : testArray) { + const auto& tc = *curr; + + bool skip_me = false; + if (tc.m_skip && !p->no_skip) + skip_me = true; + + if (!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) + skip_me = true; + if (!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) + skip_me = true; + if (matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) + skip_me = true; + + if (!skip_me) + p->numTestCasesPassingFilters++; + + // skip the test if it is not in the execution range + if ((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || + (p->first > p->numTestCasesPassingFilters)) + skip_me = true; + + if (skip_me) { + if (!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); + continue; + } + + // do not execute the test if we are to only count the number of filter passing tests + if (p->count) + continue; + + // print the name of the test and don't execute it + if (p->list_test_cases) { + queryResults.push_back(&tc); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if (p->list_test_suites) { + if ((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { + queryResults.push_back(&tc); + testSuitesPassingFilt.insert(tc.m_test_suite); + p->numTestSuitesPassingFilters++; + } + continue; + } + + // execute the test if it passes all the filtering + { + p->currentTest = &tc; + + p->failure_flags = TestCaseFailureReason::None; + p->seconds = 0; + + // reset atomic counters + p->numAssertsFailedCurrentTest_atomic = 0; + p->numAssertsCurrentTest_atomic = 0; + + p->fullyTraversedSubcases.clear(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); + + p->timer.start(); + + bool run_test = true; + + do { + // reset some of the fields for subcases (except for the set of fully passed ones) + p->reachedLeaf = false; + // May not be empty if previous subcase exited via exception. + p->subcaseStack.clear(); + p->currentSubcaseDepth = 0; + + p->shouldLogCurrentException = true; + + // reset stuff for logging with INFO() + p->stringifiedContexts.clear(); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + // MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable + FatalConditionHandler fatalConditionHandler; // Handle signals + // execute the test + tc.m_test(); + fatalConditionHandler.reset(); + DOCTEST_MSVC_SUPPRESS_WARNING_POP +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + } + catch (const TestFailureException&) { + p->failure_flags |= TestCaseFailureReason::AssertFailure; + } + catch (...) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + { translateActiveException(), false }); + p->failure_flags |= TestCaseFailureReason::Exception; + } +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + + // exit this loop if enough assertions have failed - even if there are more subcases + if (p->abort_after > 0 && + p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { + run_test = false; + p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; + } + + if (!p->nextSubcaseStack.empty() && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if (p->nextSubcaseStack.empty()) + run_test = false; + } while (run_test); + + p->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + p->currentTest = nullptr; + + // stop executing tests if enough assertions have failed + if (p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) + break; + } + } + + if (!query_mode) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } + else { + QueryData qdata; + qdata.run_stats = g_cs; + qdata.data = queryResults.data(); + qdata.num_data = unsigned(queryResults.size()); + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); + } + + return cleanup_and_return(); + } + + DOCTEST_DEFINE_INTERFACE(IReporter) + + int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } + const IContextScope* const* IReporter::get_active_contexts() { + return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; + } + + int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } + const String* IReporter::get_stringified_contexts() { + return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; + } + + namespace detail { + void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { + if (isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + } + } // namespace detail + + } // namespace doctest + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 +int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +DOCTEST_MSVC_SUPPRESS_WARNING_POP +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_IMPLEMENTATION +#endif // DOCTEST_CONFIG_IMPLEMENT + +#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN + +#ifdef DOCTEST_UNDEF_NOMINMAX +#undef NOMINMAX +#undef DOCTEST_UNDEF_NOMINMAX +#endif // DOCTEST_UNDEF_NOMINMAX From 4f0f6256c04fae978ccad062892d55edcb382eb8 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Tue, 6 Aug 2024 15:42:15 +0300 Subject: [PATCH 05/32] add array --- Storage/Disk_Mng_Master.c | 58 +++++++++++++++++++++----- Storage/Disk_Mng_Master.h | 40 +++++++++++++++++- Storage/Disk_Mng_Master_API.h | 4 ++ Storage/Doctest.cpp | 76 ++++++++++++++++++++++++----------- 4 files changed, 145 insertions(+), 33 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 67a7ffd..a67b901 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -15,14 +15,26 @@ void disk_mng_initialize_CB() void disk_mng_initialize() { disk_mng_initialize_CB(); - stack_initialize(); - + stack_firstInitialize(); + array_firstInitialize(); } -void stack_initialize() { - disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_initialize"); +//initialize on the first time we turn o the computer the stack will initialize with all the indexes. +void stack_firstInitialize() { + disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); disk_mng_CB->diskFreeIndexesInArray->top = NULL; + disk_mng_CB->diskFreeIndexesInArray->size = 0; + for (size_t i = 0; i < DISK_SIZE; i++) + { + StackNode_t* s= stackNode_create(i); + stack_push(s); + } +} - //API call if its first time or ot +void stack_normalInitialize() { + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); + int length = 0; + //disk_loadDataForInitializeDataStructers(length, 0, sizeof(int)); + //disk_loadDataForInitializeDataStructers(disk_mng_CB->diskFreeIndexesInArray, 4, length*sizeof(int)); } bool stack_is_empty() { @@ -40,27 +52,55 @@ StackNode_t* stackNode_create(int index) void stack_push(StackNode_t* new_node) { + + disk_mng_CB->diskFreeIndexesInArray->size++; disk_mng_CB->diskFreeIndexesInArray->top = new_node; } int stack_pop() { - if (stack_is_empty(disk_mng_CB->diskFreeIndexesInArray)) { + if (stack_is_empty()) { return -1; } StackNode_t* temp = disk_mng_CB->diskFreeIndexesInArray->top; int value = temp->freeIndex; disk_mng_CB->diskFreeIndexesInArray->top = disk_mng_CB->diskFreeIndexesInArray->top->next; + disk_mng_CB->diskFreeIndexesInArray->size--; free(temp); return value; } -int stack_top(DiskFreeIndexesInArray_t* stack) { - if (stack_is_empty(stack)) { +int stack_top() { + if (stack_is_empty()) { return -1; } - return stack->top->freeIndex; + return disk_mng_CB->diskFreeIndexesInArray->top->freeIndex; +} + +//array fuctions + +void array_firstInitialize() { + disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(DISK_SIZE*sizeof(ArrayInfo_t*), "Failed to allocate memory for stack ", "array_firstInitialize"); +} + +void array_normalInitialize() { + disk_mng_CB->diskFreeIndexesInArray = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for stack ", "array_normalInitialize"); + //disk_loadDataForInitializeDataStructers(disk_mng_CB->diskFreeIndexesInArray, 4+ disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int),DISK_SIZE*sizeof(ArrayInfo_t**)); } +void array_deleteFromArray(int index) +{ + disk_mng_CB->arrayForAllMApsInformation[index] = NULL; +} + +void array_deleteArrayInfo(ArrayInfo_t* arrayInfo) +{ + disk_deleteMap(arrayInfo->diskPointer); + free(arrayInfo); +} + + + + void test_writeExceptionToFile(Exception exception, const char* source) { FILE* file; errno_t err = fopen_s(&file, "errors.log.txt", "a"); diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 43f76c5..6f6e3b2 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -7,6 +7,9 @@ // Forward declarations +typedef struct Point_s Point_t; +typedef struct MapRange_s MapRange_t; +typedef struct ArrayInfo_s ArrayInfo_t; typedef struct StackNode_s StackNode_t; typedef struct DiskFreeIndexesInArray_s DiskFreeIndexesInArray_t; typedef struct Disk_Management_CB_s Disk_Managment_CB_t; @@ -19,15 +22,36 @@ typedef enum { // Struct declarations +struct Point_s { + int x; // longitude + int y; // latitude +}; + +struct MapRange_s { + Point_t topLeft; + Point_t bottomRight; +}; + +struct ArrayInfo_s { + int mapid; + int* diskPointer; + int size; + MapRange_t range; + //AVLNodeInfo_t avlInfo; + +}; + struct StackNode_s { int freeIndex; StackNode_t* next; }; struct DiskFreeIndexesInArray_s { + int size; StackNode_t* top; }; struct Disk_Management_CB_s { + ArrayInfo_t** arrayForAllMApsInformation; StackNode_t* stackNode; DiskFreeIndexesInArray_t* diskFreeIndexesInArray; }; @@ -48,7 +72,9 @@ void disk_mng_initialize(); //stack functions -void stack_initialize(); +void stack_firstInitialize(); + +void stack_normalInitialize(); bool stack_is_empty(); @@ -60,3 +86,15 @@ int stack_pop(); int stack_top(); +//array functions + +void array_normalInitialize(); + +void array_firstInitialize(); + +void array_deleteFromArray(int index); + +void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); + +void disk_deleteMap(int* diskPointer); + diff --git a/Storage/Disk_Mng_Master_API.h b/Storage/Disk_Mng_Master_API.h index e69de29..ca3012b 100644 --- a/Storage/Disk_Mng_Master_API.h +++ b/Storage/Disk_Mng_Master_API.h @@ -0,0 +1,4 @@ +#include "Disk_Mng_Master.h" + + + diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index b05213a..b7eca9d 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -2,6 +2,8 @@ #include "doctest.h" #include #include +#include + extern "C" { #include "Disk_Mng_Master.h" @@ -20,21 +22,51 @@ int generateRandomNumber() { return (rand() % (upper - lower + 1)) + lower; } int index, popValue,value; -StackNode_t* newStackNode; + +//mock functions + +//the function get pointer to map in the disk and delete this map from disk +void disk_deleteMap(int* diskPointer) {} + + +////the function fill in the structer all the data which save befoe the computer closed,the function get destenation,suorce,length; +void disk_loadDataForInitializeDataStructers(void* i,void* x,void* b) +{ +} //stack tests -//TEST_CASE("test_stack_initilaizeWithEmptyIndexes") -//{ -// CHECK(disk_mng_CB->diskFreeIndexesInArray->top == NULL); -//} +TEST_CASE("test_stack_firstInitialize") +{ + disk_mng_initialize(); + for (int i = 0; i < DISK_SIZE; i++) + { + StackNode_t* newNode = stackNode_create(i); + stack_push(newNode); + } + + for (int i =DISK_SIZE-1; i >0; i--) + { + CHECK( stack_pop() == i); + } + +} + + +TEST_CASE("test_stack_normalInitialize") +{ + disk_mng_initialize(); +//load + +} + TEST_CASE("test_stack_push") { disk_mng_initialize(); for (size_t i = 0; i < DISK_SIZE; i++) { index = generateRandomNumber(); - newStackNode = stackNode_create(index); + StackNode_t* newStackNode= stackNode_create(index); stack_push(newStackNode); popValue = stack_pop(); CHECK(popValue == index); @@ -44,11 +76,8 @@ TEST_CASE("test_stack_push") TEST_CASE("test_stack_pop") { disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) + for (size_t i = 4; i < 0; i++) { - index = generateRandomNumber(); - newStackNode = stackNode_create(index); - stack_push(newStackNode); value = stack_pop(); CHECK(value !=stack_top()); } @@ -56,28 +85,29 @@ TEST_CASE("test_stack_pop") TEST_CASE("test_stack_top") { disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) + for (size_t i = DISK_SIZE-1; i < 0; i--) { - index = generateRandomNumber(); - newStackNode = stackNode_create(index); - stack_push(newStackNode); - value = stack_pop(); - CHECK(value == index); + value = stack_top(); + stack_pop(); + CHECK(value == i); } } TEST_CASE("test_stack_is_empty") { disk_mng_initialize(); for (size_t i = 0; i < DISK_SIZE; i++) - { - index = generateRandomNumber(); - newStackNode = stackNode_create(index); - stack_push(newStackNode); - } - for (size_t i = 0; i < DISK_SIZE; i++) { stack_pop(); } - CHECK(stack_is_empty() == TRUE); + CHECK(stack_is_empty()); } + +////array tests +// +//TEST_CASE("test_array_normalInitialize") +//{ +// +////load +// +//} From 71a4b92db5874f2d9f55d6108fbacd91fe541dc6 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Tue, 6 Aug 2024 15:43:53 +0300 Subject: [PATCH 06/32] add the AVL tree with functions --- Storage/Disk_Mng_Master.c | 253 ++ Storage/Disk_Mng_Master.h | 68 + Storage/Doctest.cpp | 29 + Storage/Storage.vcxproj | 6 + Storage/doctest.h | 7106 +++++++++++++++++++++++++++++++++++++ 5 files changed, 7462 insertions(+) create mode 100644 Storage/Doctest.cpp create mode 100644 Storage/doctest.h diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index e69de29..fd96838 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -0,0 +1,253 @@ +#include "Disk_Mng_Master.h" + +// Global pointer to the Disk Management Control Block +Disk_Managment_CB_t* disk_mng_CB; + +void* allocate_memory(size_t size, const char* description, const char* functionName) { + void* ptr = malloc(size); + if (!ptr) { + perror(description); + exit(EXIT_FAILURE); + } + return ptr; +} +void test_writeExceptionToFile(Exception exception, const char* source) { + FILE* file; + errno_t err = fopen_s(&file, "errors.log.txt", "a"); + if (err != 0) { + fprintf(stderr, "Error opening file for writing\n"); + return; + } + + const char* error_message; + switch (exception) { + case Error_When_Allocating_Memory_Space: + error_message = "Error: Error when allocating memory space."; + break; + default: + error_message = "Error: Unknown exception."; + break; + } + + fprintf(file, "%s:\n%s\n", source, error_message); + fclose(file); +} + + +void disk_mng_initialize_CB() { + disk_mng_CB = (Disk_Managment_CB_t*)allocate_memory(sizeof(Disk_Managment_CB_t), "Failed to allocate memory for disk control block", "disk_mng_initialize_CB"); +} + +void disk_mng_initialize() { + disk_mng_initialize_CB(); + avlTree_firstInitialize(); +} + +int height(AVLNode_t* N) { + if (N == NULL) + return 0; + return N->height; +} + +//AVL node info +AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex, int lru) +{ + AVLNodeInfo_t* newAVLNodeInfo = (AVLNodeInfo_t*)allocate_memory(sizeof(AVLNodeInfo_t), "Failed to allocate memory for AVL node info", "avlNodeInfo_create"); + newAVLNodeInfo->mapSize = mapSize; + newAVLNodeInfo->arrayIndex = arrayIndex; + newAVLNodeInfo->lru = lru; + return newAVLNodeInfo; +} + +void avlNodeInfo_delete(AVLNodeInfo_t* nodeInfo) +{ + if (nodeInfo != NULL) { + free(nodeInfo); + } +} + +//AVL node +AVLNode_t* avlNode_create(AVLNodeInfo_t* avlNodeInfo) { + AVLNode_t* node = (AVLNode_t*)allocate_memory(sizeof(AVLNode_t), "Failed to allocate memory for AVL node", "avlTree_insert"); + node->avlNodeInfo = avlNodeInfo; + node->left = node->right = NULL; + node->height = 1; + return node; +} +void avlNode_delete(AVLNode_t* node) { + if (node != NULL) { + avlNodeInfo_delete(node->avlNodeInfo); + free(node); + } +} + + +AVLNode_t* rightRotate(AVLNode_t* y) { + AVLNode_t* x = y->left; + AVLNode_t* T2 = x->right; + x->right = y; + y->left = T2; + y->height = max(height(y->left), height(y->right)) + 1; + x->height = max(height(x->left), height(x->right)) + 1; + return x; +} + +AVLNode_t* leftRotate(AVLNode_t* x) { + AVLNode_t* y = x->right; + AVLNode_t* T2 = y->left; + y->left = x; + x->right = T2; + x->height = max(height(x->left), height(x->right)) + 1; + y->height = max(height(y->left), height(y->right)) + 1; + return y; +} + +int getBalance(AVLNode_t* N) { + if (N == NULL) + return 0; + return height(N->left) - height(N->right); +} + +AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter) { + if (node == NULL) + { + data->lru = lruCounter; + return newAVLNode(data); + } + + if (data->mapSize < node->avlNodeInfo->mapSize) + node->left = avlTree_insert(node->left, data, lruCounter); + else if (data->mapSize > node->avlNodeInfo->mapSize) + node->right = avlTree_insert(node->right, data, lruCounter); + else + return node; + + node->height = 1 + max(height(node->left), height(node->right)); + + int balance = getBalance(node); + + if (balance > 1 && data->mapSize < node->left->avlNodeInfo->mapSize) + return rightRotate(node); + + if (balance < -1 && data->mapSize > node->right->avlNodeInfo->mapSize) + return leftRotate(node); + + if (balance > 1 && data->mapSize > node->left->avlNodeInfo->mapSize) { + node->left = leftRotate(node->left); + return rightRotate(node); + } + + if (balance < -1 && data->mapSize < node->right->avlNodeInfo->mapSize) { + node->right = rightRotate(node->right); + return leftRotate(node); + } + + return node; +} + +void avlTree_firstInitialize() { + disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for AVL Tree", "avlTree_initialize"); + disk_mng_CB->disk_SortByMapSize->root = NULL; + disk_mng_CB->disk_SortByMapSize->totalElements = 0; + disk_mng_CB->disk_SortByMapSize->lruCounter = 0; +} + +void avlTree_insertElement(AVLNodeInfo_t* data) { + disk_mng_CB->disk_SortByMapSize->lruCounter++; + disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, data, disk_mng_CB->disk_SortByMapSize->lruCounter); + disk_mng_CB->disk_SortByMapSize->totalElements++; +} + + +AVLNode_t* findEligibleForDeletion(AVLNode_t* node) { + if (node == NULL) { + return NULL; + } + + AVLNode_t* eligibleNode = NULL; + + // Check the right subtree first for the largest node + AVLNode_t* rightResult = findEligibleForDeletion(node->right); + if (rightResult != NULL && rightResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { + eligibleNode = rightResult; + } + + // Check if the current node is eligible for deletion + if (node->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { + if (eligibleNode == NULL || node->avlNodeInfo->mapSize > eligibleNode->avlNodeInfo->mapSize) { + eligibleNode = node; + } + } + + // Check the left subtree if no eligible node found in the right subtree or current node + AVLNode_t* leftResult = findEligibleForDeletion(node->left); + if (leftResult != NULL && leftResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { + if (eligibleNode == NULL || leftResult->avlNodeInfo->mapSize > eligibleNode->avlNodeInfo->mapSize) { + eligibleNode = leftResult; + } + } + + return eligibleNode; +} +AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { + if (root == NULL) { + return root; + } + + // Traverse the tree to find the node + if (node->avlNodeInfo->mapSize < root->avlNodeInfo->mapSize) { + root->left = avlTree_deleteNode(root->left, node->avlNodeInfo->mapSize); + } + else if (node->avlNodeInfo->mapSize > root->avlNodeInfo->mapSize) { + root->right = avlTree_deleteNode(root->right, node->avlNodeInfo->mapSize); + } + else { + // Node with mapSize found + if ((root->left == NULL) || (root->right == NULL)) { + AVLNode_t* temp = root->left ? root->left : root->right; + if (temp == NULL) { + temp = root; + root = NULL; + } + else { + *root = *temp; + } + free(temp->avlNodeInfo); // Free AVLNodeInfo_t + free(temp); // Free AVLNode_t + } + else { + AVLNode_t* temp = avlTree_minValueNode(root->right); + root->avlNodeInfo = temp->avlNodeInfo; + root->right = avlTree_deleteNode(root->right, temp->avlNodeInfo->mapSize); + } + } + + if (root == NULL) { + return root; + } + + // Update height and balance the node + root->height = max(height(root->left), height(root->right)) + 1; + int balance = getBalance(root); + + if (balance > 1 && getBalance(root->left) >= 0) { + return rightRotate(root); + } + + if (balance > 1 && getBalance(root->left) < 0) { + root->left = leftRotate(root->left); + return rightRotate(root); + } + + if (balance < -1 && getBalance(root->right) <= 0) { + return leftRotate(root); + } + + if (balance < -1 && getBalance(root->right) > 0) { + root->right = rightRotate(root->right); + return leftRotate(root); + } + + return root; +} + diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 6f70f09..e2b17e7 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -1 +1,69 @@ #pragma once +#include +#include +#include +#include + +#define DISK_SIZE 1000 + +// Forward declarations +typedef struct AVLNode_s AVLNode_t; +typedef struct DiskSortByMapSize_s DiskSortByMapSize_t; +typedef struct AVLNodeInfo_s AVLNodeInfo_t; +typedef struct Disk_Managment_CB_s Disk_Managment_CB_t; + +// Enum declaration +typedef enum { + Error_When_Allocating_Memory_Space +} Exception; + +// Struct declarations +struct AVLNodeInfo_s { + int mapSize; + int arrayIndex; + int lru; +}; + +struct AVLNode_s { + AVLNodeInfo_t* avlNodeInfo; + AVLNode_t* left, * right; + int height; +}; + +struct DiskSortByMapSize_s { + AVLNode_t* root; + int totalElements; + int lruCounter; +}; + +struct Disk_Managment_CB_s { + DiskSortByMapSize_t* disk_SortByMapSize; +}; + +extern Disk_Managment_CB_t* disk_mng_CB; + + +// Function declarations + +void* allocate_memory(size_t size, const char* description, const char* functionName); +void test_writeExceptionToFile(Exception exception, const char* source); +void disk_mng_initialize_CB(); +void disk_mng_initialize(); + +AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex, int lru); +void avlNodeInfo_delete(AVLNodeInfo_t* nodeInfo); + +AVLNode_t* avlNode_create(AVLNodeInfo_t* avlNodeInfo); +void avlNode_delete(AVLNode_t* node); + +int height(AVLNode_t* N); +AVLNode_t* rightRotate(AVLNode_t* y); +AVLNode_t* leftRotate(AVLNode_t* x); +int getBalance(AVLNode_t* N); + +AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter); +void avlTree_firstInitialize(); +void avlTree_insertElement(AVLNodeInfo_t* data); + +AVLNode_t* findEligibleForDeletion(AVLNode_t* node); +AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node); \ No newline at end of file diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp new file mode 100644 index 0000000..253f1f2 --- /dev/null +++ b/Storage/Doctest.cpp @@ -0,0 +1,29 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "doctest.h" +#include +#include + +extern "C" { +#include "Disk_Mng_Master.h", +} + +struct GlobalSetup { + GlobalSetup() { + srand(time(0)); + } +}; +GlobalSetup globalSetup; + +int generateRandomNumber(int upper) { + int lower = 0; + return (rand() % (upper - lower + 1)) + lower; +} + + +//initialize + +TEST_CASE("test_disk_mng_initialize_CB") +{ + disk_mng_initialize_CB(); + CHECK(disk_mng_CB != NULL); +} diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index 60771eb..af8fa09 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -127,8 +127,14 @@ + + + + + + diff --git a/Storage/doctest.h b/Storage/doctest.h new file mode 100644 index 0000000..5c754cd --- /dev/null +++ b/Storage/doctest.h @@ -0,0 +1,7106 @@ +// ====================================================================== lgtm [cpp/missing-header-guard] +// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == +// ====================================================================== +// +// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD +// +// Copyright (c) 2016-2023 Viktor Kirilov +// +// Distributed under the MIT Software License +// See accompanying file LICENSE.txt or copy at +// https://opensource.org/licenses/MIT +// +// The documentation can be found at the library's page: +// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= +// +// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2 +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt +// +// The concept of subcases (sections in Catch) and expression decomposition are from there. +// Some parts of the code are taken directly: +// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<> +// - the Approx() helper class for floating point comparison +// - colors in the console +// - breaking into a debugger +// - signal / SEH handling +// - timer +// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste) +// +// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= + +#ifndef DOCTEST_LIBRARY_INCLUDED +#define DOCTEST_LIBRARY_INCLUDED + +// ================================================================================================= +// == VERSION ====================================================================================== +// ================================================================================================= + +#define DOCTEST_VERSION_MAJOR 2 +#define DOCTEST_VERSION_MINOR 4 +#define DOCTEST_VERSION_PATCH 11 + +// util we need here +#define DOCTEST_TOSTR_IMPL(x) #x +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) + +#define DOCTEST_VERSION_STR \ + DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ + DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) + +#define DOCTEST_VERSION \ + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + +// ================================================================================================= +// == COMPILER VERSION ============================================================================= +// ================================================================================================= + +// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect + +#ifdef _MSC_VER +#define DOCTEST_CPLUSPLUS _MSVC_LANG +#else +#define DOCTEST_CPLUSPLUS __cplusplus +#endif + +#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH)) + +// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl... +#if defined(_MSC_VER) && defined(_MSC_FULL_VER) +#if _MSC_VER == _MSC_FULL_VER / 10000 +#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) +#else // MSVC +#define DOCTEST_MSVC \ + DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) +#endif // MSVC +#endif // MSVC +#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ + !defined(__INTEL_COMPILER) +#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#endif // GCC +#if defined(__INTEL_COMPILER) +#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif // ICC + +#ifndef DOCTEST_MSVC +#define DOCTEST_MSVC 0 +#endif // DOCTEST_MSVC +#ifndef DOCTEST_CLANG +#define DOCTEST_CLANG 0 +#endif // DOCTEST_CLANG +#ifndef DOCTEST_GCC +#define DOCTEST_GCC 0 +#endif // DOCTEST_GCC +#ifndef DOCTEST_ICC +#define DOCTEST_ICC 0 +#endif // DOCTEST_ICC + +// ================================================================================================= +// == COMPILER WARNINGS HELPERS ==================================================================== +// ================================================================================================= + +#if DOCTEST_CLANG && !DOCTEST_ICC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) +#else // DOCTEST_CLANG +#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +#define DOCTEST_CLANG_SUPPRESS_WARNING(w) +#define DOCTEST_CLANG_SUPPRESS_WARNING_POP +#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_CLANG + +#if DOCTEST_GCC +#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") +#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) +#else // DOCTEST_GCC +#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH +#define DOCTEST_GCC_SUPPRESS_WARNING(w) +#define DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_GCC + +#if DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) +#else // DOCTEST_MSVC +#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +#define DOCTEST_MSVC_SUPPRESS_WARNING(w) +#define DOCTEST_MSVC_SUPPRESS_WARNING_POP +#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) +#endif // DOCTEST_MSVC + +// ================================================================================================= +// == COMPILER WARNINGS ============================================================================ +// ================================================================================================= + +// both the header and the implementation suppress all of these, +// so it only makes sense to aggregate them like so +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ + DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ + \ + DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ + DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ + \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + /* these 4 also disabled globally via cmake: */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ + /* common ones */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ + /* static analysis */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ + +#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") +DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ + DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ + DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ + +#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP + +// ================================================================================================= +// == FEATURE DETECTION ============================================================================ +// ================================================================================================= + +// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support +// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx +// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html +// MSVC version table: +// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering +// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) +// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) +// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) +// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) +// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) +// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) +// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) +// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) +// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) + +// Universal Windows Platform support +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_WINDOWS_SEH +#endif // WINAPI_FAMILY +#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) +#define DOCTEST_CONFIG_WINDOWS_SEH +#endif // MSVC +#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH) +#undef DOCTEST_CONFIG_WINDOWS_SEH +#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH + +#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ + !defined(__EMSCRIPTEN__) && !defined(__wasi__) +#define DOCTEST_CONFIG_POSIX_SIGNALS +#endif // _WIN32 +#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) +#undef DOCTEST_CONFIG_POSIX_SIGNALS +#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ + || defined(__wasi__) +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // no exceptions +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS +#define DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS) +#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef __wasi__ +#define DOCTEST_CONFIG_NO_MULTITHREADING +#endif + +#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT) +#define DOCTEST_CONFIG_IMPLEMENT +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +#if defined(_WIN32) || defined(__CYGWIN__) +#if DOCTEST_MSVC +#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport) +#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport) +#else // MSVC +#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport)) +#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport)) +#endif // MSVC +#else // _WIN32 +#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default"))) +#define DOCTEST_SYMBOL_IMPORT +#endif // _WIN32 + +#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#ifdef DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT +#else // DOCTEST_CONFIG_IMPLEMENT +#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT +#endif // DOCTEST_CONFIG_IMPLEMENT +#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL +#define DOCTEST_INTERFACE +#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL + +// needed for extern template instantiations +// see https://github.com/fmtlib/fmt/issues/2228 +#if DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL +#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE +#else // DOCTEST_MSVC +#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE +#define DOCTEST_INTERFACE_DEF +#endif // DOCTEST_MSVC + +#define DOCTEST_EMPTY + +#if DOCTEST_MSVC +#define DOCTEST_NOINLINE __declspec(noinline) +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) +#define DOCTEST_NOINLINE +#define DOCTEST_UNUSED +#define DOCTEST_ALIGNMENT(x) +#else +#define DOCTEST_NOINLINE __attribute__((noinline)) +#define DOCTEST_UNUSED __attribute__((unused)) +#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) +#endif + +#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE +#define DOCTEST_INLINE_NOINLINE inline +#else +#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE +#endif + +#ifndef DOCTEST_NORETURN +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NORETURN +#else // DOCTEST_MSVC +#define DOCTEST_NORETURN [[noreturn]] +#endif // DOCTEST_MSVC +#endif // DOCTEST_NORETURN + +#ifndef DOCTEST_NOEXCEPT +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_NOEXCEPT +#else // DOCTEST_MSVC +#define DOCTEST_NOEXCEPT noexcept +#endif // DOCTEST_MSVC +#endif // DOCTEST_NOEXCEPT + +#ifndef DOCTEST_CONSTEXPR +#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_CONSTEXPR const +#define DOCTEST_CONSTEXPR_FUNC inline +#else // DOCTEST_MSVC +#define DOCTEST_CONSTEXPR constexpr +#define DOCTEST_CONSTEXPR_FUNC constexpr +#endif // DOCTEST_MSVC +#endif // DOCTEST_CONSTEXPR + +#ifndef DOCTEST_NO_SANITIZE_INTEGER +#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0) +#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer"))) +#else +#define DOCTEST_NO_SANITIZE_INTEGER +#endif +#endif // DOCTEST_NO_SANITIZE_INTEGER + +// ================================================================================================= +// == FEATURE DETECTION END ======================================================================== +// ================================================================================================= + +#define DOCTEST_DECLARE_INTERFACE(name) \ + virtual ~name(); \ + name() = default; \ + name(const name&) = delete; \ + name(name&&) = delete; \ + name& operator=(const name&) = delete; \ + name& operator=(name&&) = delete; + +#define DOCTEST_DEFINE_INTERFACE(name) \ + name::~name() = default; + +// internal macros for string concatenation and anonymous variable name generation +#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#ifdef __COUNTER__ // not standard and may be missing for some compilers +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) +#else // __COUNTER__ +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) +#endif // __COUNTER__ + +#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x& +#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x +#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE + +// not using __APPLE__ because... this is how Catch does it +#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED +#define DOCTEST_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define DOCTEST_PLATFORM_IPHONE +#elif defined(_WIN32) +#define DOCTEST_PLATFORM_WINDOWS +#elif defined(__wasi__) +#define DOCTEST_PLATFORM_WASI +#else // DOCTEST_PLATFORM +#define DOCTEST_PLATFORM_LINUX +#endif // DOCTEST_PLATFORM + +namespace doctest { namespace detail { + static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } +}} + +#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ + static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#ifndef DOCTEST_BREAK_INTO_DEBUGGER +// should probably take a look at https://github.com/scottt/debugbreak +#ifdef DOCTEST_PLATFORM_LINUX +#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) +// Break at the location of the failing check if possible +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#else +#include +#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) +#endif +#elif defined(DOCTEST_PLATFORM_MAC) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) +#elif defined(__ppc__) || defined(__ppc64__) +// https://www.cocoawithlove.com/2008/03/break-into-debugger.html +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) +#else +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) +#endif +#elif DOCTEST_MSVC +#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() +#elif defined(__MINGW32__) +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") +extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +DOCTEST_GCC_SUPPRESS_WARNING_POP +#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() +#else // linux +#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) +#endif // linux +#endif // DOCTEST_BREAK_INTO_DEBUGGER + +// this is kept here for backwards compatibility since the config option was changed +#ifdef DOCTEST_CONFIG_USE_IOSFWD +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // DOCTEST_CONFIG_USE_IOSFWD + +// for clang - always include ciso646 (which drags some std stuff) because +// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in +// which case we don't want to forward declare stuff from std - for reference: +// https://github.com/doctest/doctest/issues/126 +// https://github.com/doctest/doctest/issues/356 +#if DOCTEST_CLANG +#include +#endif // clang + +#ifdef _LIBCPP_VERSION +#ifndef DOCTEST_CONFIG_USE_STD_HEADERS +#define DOCTEST_CONFIG_USE_STD_HEADERS +#endif +#endif // _LIBCPP_VERSION + +#ifdef DOCTEST_CONFIG_USE_STD_HEADERS +#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN +#include +#include +#include +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END +#else // DOCTEST_CONFIG_USE_STD_HEADERS + +// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) + +namespace std { // NOLINT(cert-dcl58-cpp) +typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) +typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) +template +struct char_traits; +template <> +struct char_traits; +template +class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) +typedef basic_ostream> ostream; // NOLINT(modernize-use-using) +template +// NOLINTNEXTLINE +basic_ostream& operator<<(basic_ostream&, const char*); +template +class basic_istream; +typedef basic_istream> istream; // NOLINT(modernize-use-using) +template +class tuple; +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +template +class allocator; +template +class basic_string; +using string = basic_string, allocator>; +#endif // VS 2019 +} // namespace std + +DOCTEST_MSVC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_USE_STD_HEADERS + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#include +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + +namespace doctest { + +using std::size_t; + +DOCTEST_INTERFACE extern bool is_running_in_test; + +#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE +#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned +#endif + +// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length +// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: +// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) +// - if small - capacity left before going on the heap - using the lowest 5 bits +// - if small - 2 bits are left unused - the second and third highest ones +// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) +// and the "is small" bit remains "0" ("as well as the capacity left") so its OK +// Idea taken from this lecture about the string implementation of facebook/folly - fbstring +// https://www.youtube.com/watch?v=kPR8h4-qZdk +// TODO: +// - optimizations - like not deleting memory unnecessarily in operator= and etc. +// - resize/reserve/clear +// - replace +// - back/front +// - iterator stuff +// - find & friends +// - push_back/pop_back +// - assign/insert/erase +// - relational operators as free functions - taking const char* as one of the params +class DOCTEST_INTERFACE String +{ +public: + using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; + +private: + static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members + static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members + + struct view // len should be more than sizeof(view) - because of the final byte for flags + { + char* ptr; + size_type size; + size_type capacity; + }; + + union + { + char buf[len]; // NOLINT(*-avoid-c-arrays) + view data; + }; + + char* allocate(size_type sz); + + bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } + void setOnHeap() noexcept; + void setLast(size_type in = last) noexcept; + void setSize(size_type sz) noexcept; + + void copy(const String& other); + +public: + static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); + + String() noexcept; + ~String(); + + // cppcheck-suppress noExplicitConstructor + String(const char* in); + String(const char* in, size_type in_size); + + String(std::istream& in, size_type in_size); + + String(const String& other); + String& operator=(const String& other); + + String& operator+=(const String& other); + + String(String&& other) noexcept; + String& operator=(String&& other) noexcept; + + char operator[](size_type i) const; + char& operator[](size_type i); + + // the only functions I'm willing to leave in the interface - available for inlining + const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT + char* c_str() { + if (isOnStack()) { + return reinterpret_cast(buf); + } + return data.ptr; + } + + size_type size() const; + size_type capacity() const; + + String substr(size_type pos, size_type cnt = npos) &&; + String substr(size_type pos, size_type cnt = npos) const &; + + size_type find(char ch, size_type pos = 0) const; + size_type rfind(char ch, size_type pos = npos) const; + + int compare(const char* other, bool no_case = false) const; + int compare(const String& other, bool no_case = false) const; + +friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); +}; + +DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); + +class DOCTEST_INTERFACE Contains { +public: + explicit Contains(const String& string); + + bool checkWith(const String& other) const; + + String string; +}; + +DOCTEST_INTERFACE String toString(const Contains& in); + +DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); +DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); +DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); + +namespace Color { + enum Enum + { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White + }; + + DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); +} // namespace Color + +namespace assertType { + enum Enum + { + // macro traits + + is_warn = 1, + is_check = 2 * is_warn, + is_require = 2 * is_check, + + is_normal = 2 * is_require, + is_throws = 2 * is_normal, + is_throws_as = 2 * is_throws, + is_throws_with = 2 * is_throws_as, + is_nothrow = 2 * is_throws_with, + + is_false = 2 * is_nothrow, + is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types + + is_eq = 2 * is_unary, + is_ne = 2 * is_eq, + + is_lt = 2 * is_ne, + is_gt = 2 * is_lt, + + is_ge = 2 * is_gt, + is_le = 2 * is_ge, + + // macro types + + DT_WARN = is_normal | is_warn, + DT_CHECK = is_normal | is_check, + DT_REQUIRE = is_normal | is_require, + + DT_WARN_FALSE = is_normal | is_false | is_warn, + DT_CHECK_FALSE = is_normal | is_false | is_check, + DT_REQUIRE_FALSE = is_normal | is_false | is_require, + + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, + + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + + DT_WARN_THROWS_WITH = is_throws_with | is_warn, + DT_CHECK_THROWS_WITH = is_throws_with | is_check, + DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, + + DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, + DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, + DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, + + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, + + DT_WARN_EQ = is_normal | is_eq | is_warn, + DT_CHECK_EQ = is_normal | is_eq | is_check, + DT_REQUIRE_EQ = is_normal | is_eq | is_require, + + DT_WARN_NE = is_normal | is_ne | is_warn, + DT_CHECK_NE = is_normal | is_ne | is_check, + DT_REQUIRE_NE = is_normal | is_ne | is_require, + + DT_WARN_GT = is_normal | is_gt | is_warn, + DT_CHECK_GT = is_normal | is_gt | is_check, + DT_REQUIRE_GT = is_normal | is_gt | is_require, + + DT_WARN_LT = is_normal | is_lt | is_warn, + DT_CHECK_LT = is_normal | is_lt | is_check, + DT_REQUIRE_LT = is_normal | is_lt | is_require, + + DT_WARN_GE = is_normal | is_ge | is_warn, + DT_CHECK_GE = is_normal | is_ge | is_check, + DT_REQUIRE_GE = is_normal | is_ge | is_require, + + DT_WARN_LE = is_normal | is_le | is_warn, + DT_CHECK_LE = is_normal | is_le | is_check, + DT_REQUIRE_LE = is_normal | is_le | is_require, + + DT_WARN_UNARY = is_normal | is_unary | is_warn, + DT_CHECK_UNARY = is_normal | is_unary | is_check, + DT_REQUIRE_UNARY = is_normal | is_unary | is_require, + + DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, + }; +} // namespace assertType + +DOCTEST_INTERFACE const char* assertString(assertType::Enum at); +DOCTEST_INTERFACE const char* failureString(assertType::Enum at); +DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); + +struct DOCTEST_INTERFACE TestCaseData +{ + String m_file; // the file in which the test was registered (using String - see #350) + unsigned m_line; // the line where the test was registered + const char* m_name; // name of the test case + const char* m_test_suite; // the test suite in which the test was added + const char* m_description; + bool m_skip; + bool m_no_breaks; + bool m_no_output; + bool m_may_fail; + bool m_should_fail; + int m_expected_failures; + double m_timeout; +}; + +struct DOCTEST_INTERFACE AssertData +{ + // common - for all asserts + const TestCaseData* m_test_case; + assertType::Enum m_at; + const char* m_file; + int m_line; + const char* m_expr; + bool m_failed; + + // exception-related - for all asserts + bool m_threw; + String m_exception; + + // for normal asserts + String m_decomp; + + // for specific exception-related asserts + bool m_threw_as; + const char* m_exception_type; + + class DOCTEST_INTERFACE StringContains { + private: + Contains content; + bool isContains; + + public: + StringContains(const String& str) : content(str), isContains(false) { } + StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } + + bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } + + operator const String&() const { return content.string; } + + const char* c_str() const { return content.string.c_str(); } + } m_exception_string; + + AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string); +}; + +struct DOCTEST_INTERFACE MessageData +{ + String m_string; + const char* m_file; + int m_line; + assertType::Enum m_severity; +}; + +struct DOCTEST_INTERFACE SubcaseSignature +{ + String m_name; + const char* m_file; + int m_line; + + bool operator==(const SubcaseSignature& other) const; + bool operator<(const SubcaseSignature& other) const; +}; + +struct DOCTEST_INTERFACE IContextScope +{ + DOCTEST_DECLARE_INTERFACE(IContextScope) + virtual void stringify(std::ostream*) const = 0; +}; + +namespace detail { + struct DOCTEST_INTERFACE TestCase; +} // namespace detail + +struct ContextOptions //!OCLINT too many fields +{ + std::ostream* cout = nullptr; // stdout stream + String binary_name; // the test binary name + + const detail::TestCase* currentTest = nullptr; + + // == parameters from the command line + String out; // output filename + String order_by; // how tests should be ordered + unsigned rand_seed; // the seed for rand ordering + + unsigned first; // the first (matching) test to be executed + unsigned last; // the last (matching) test to be executed + + int abort_after; // stop tests after this many failed assertions + int subcase_filter_levels; // apply the subcase filters for the first N levels + + bool success; // include successful assertions in output + bool case_sensitive; // if filtering should be case sensitive + bool exit; // if the program should be exited after the tests are ran/whatever + bool duration; // print the time duration of each test case + bool minimal; // minimal console output (only test failures) + bool quiet; // no console output + bool no_throw; // to skip exceptions-related assertion macros + bool no_exitcode; // if the framework should return 0 as the exitcode + bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_intro; // to not print the intro of the framework + bool no_version; // to not print the version of the framework + bool no_colors; // if output to the console should be colorized + bool force_colors; // forces the use of colors even when a tty cannot be detected + bool no_breaks; // to not break into the debugger + bool no_skip; // don't skip test cases which are marked to be skipped + bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): + bool no_path_in_filenames; // if the path to files should be removed from the output + bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached + bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! + bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! + + bool help; // to print the help + bool version; // to print the version + bool count; // if only the count of matching tests is to be retrieved + bool list_test_cases; // to list all tests matching the filters + bool list_test_suites; // to list all suites matching the filters + bool list_reporters; // lists all registered reporters +}; + +namespace detail { + namespace types { +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + using namespace std; +#else + template + struct enable_if { }; + + template + struct enable_if { using type = T; }; + + struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; + struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; + + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + template struct remove_reference { using type = T; }; + + template struct is_rvalue_reference : false_type { }; + template struct is_rvalue_reference : true_type { }; + + template struct remove_const { using type = T; }; + template struct remove_const { using type = T; }; + + // Compiler intrinsics + template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; + template struct underlying_type { using type = __underlying_type(T); }; + + template struct is_pointer : false_type { }; + template struct is_pointer : true_type { }; + + template struct is_array : false_type { }; + // NOLINTNEXTLINE(*-avoid-c-arrays) + template struct is_array : true_type { }; +#endif + } + + // + template + T&& declval(); + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { + return static_cast(t); + } + + template + struct deferred_false : types::false_type { }; + +// MSVS 2015 :( +#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 + template + struct has_global_insertion_operator : types::false_type { }; + + template + struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; + + template + struct insert_hack; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } + }; + + template + struct insert_hack { + static void insert(std::ostream& os, const T& t) { operator<<(os, t); } + }; + + template + using insert_hack_t = insert_hack::value>; +#else + template + struct has_insertion_operator : types::false_type { }; +#endif + + template + struct has_insertion_operator(), declval()), void())> : types::true_type { }; + + template + struct should_stringify_as_underlying_type { + static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; + }; + + DOCTEST_INTERFACE std::ostream* tlssPush(); + DOCTEST_INTERFACE String tlssPop(); + + template + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T)) { +#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES + static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); +#endif + return "{?}"; + } + }; + + template + struct filldata; + + template + void filloss(std::ostream* stream, const T& in) { + filldata::fill(stream, in); + } + + template + void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) + // T[N], T(&)[N], T(&&)[N] have same behaviour. + // Hence remove reference. + filloss::type>(stream, in); + } + + template + String toStream(const T& in) { + std::ostream* stream = tlssPush(); + filloss(stream, in); + return tlssPop(); + } + + template <> + struct StringMakerBase { + template + static String convert(const DOCTEST_REF_WRAP(T) in) { + return toStream(in); + } + }; +} // namespace detail + +template +struct StringMaker : public detail::StringMakerBase< + detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> +{}; + +#ifndef DOCTEST_STRINGIFY +#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY +#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__)) +#else +#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__) +#endif +#endif + +template +String toString() { +#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 + String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) + String::size_type beginPos = ret.find('<'); + return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); +#else + String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] + String::size_type begin = ret.find('=') + 2; + return ret.substr(begin, ret.size() - begin - 1); +#endif +} + +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + return StringMaker::convert(value); +} + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +DOCTEST_INTERFACE String toString(const char* in); +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +DOCTEST_INTERFACE String toString(const std::string& in); +#endif // VS 2019 + +DOCTEST_INTERFACE String toString(String in); + +DOCTEST_INTERFACE String toString(std::nullptr_t); + +DOCTEST_INTERFACE String toString(bool in); + +DOCTEST_INTERFACE String toString(float in); +DOCTEST_INTERFACE String toString(double in); +DOCTEST_INTERFACE String toString(double long in); + +DOCTEST_INTERFACE String toString(char in); +DOCTEST_INTERFACE String toString(char signed in); +DOCTEST_INTERFACE String toString(char unsigned in); +DOCTEST_INTERFACE String toString(short in); +DOCTEST_INTERFACE String toString(short unsigned in); +DOCTEST_INTERFACE String toString(signed in); +DOCTEST_INTERFACE String toString(unsigned in); +DOCTEST_INTERFACE String toString(long in); +DOCTEST_INTERFACE String toString(long unsigned in); +DOCTEST_INTERFACE String toString(long long in); +DOCTEST_INTERFACE String toString(long long unsigned in); + +template ::value, bool>::type = true> +String toString(const DOCTEST_REF_WRAP(T) value) { + using UT = typename detail::types::underlying_type::type; + return (DOCTEST_STRINGIFY(static_cast(value))); +} + +namespace detail { + template + struct filldata + { + static void fill(std::ostream* stream, const T& in) { +#if defined(_MSC_VER) && _MSC_VER <= 1900 + insert_hack_t::insert(*stream, in); +#else + operator<<(*stream, in); +#endif + } + }; + +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) +// NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const T(&in)[N]) { + *stream << "["; + for (size_t i = 0; i < N; i++) { + if (i != 0) { *stream << ", "; } + *stream << (DOCTEST_STRINGIFY(in[i])); + } + *stream << "]"; + } + }; +// NOLINTEND(*-avoid-c-arrays) +DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // Specialized since we don't want the terminating null byte! +// NOLINTBEGIN(*-avoid-c-arrays) + template + struct filldata { + static void fill(std::ostream* stream, const char (&in)[N]) { + *stream << String(in, in[N - 1] ? N : N - 1); + } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + }; +// NOLINTEND(*-avoid-c-arrays) + + template <> + struct filldata { + static void fill(std::ostream* stream, const void* in); + }; + + template + struct filldata { +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) + static void fill(std::ostream* stream, const T* in) { +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") + filldata::fill(stream, +#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) + reinterpret_cast(in) +#else + *reinterpret_cast(&in) +#endif + ); +DOCTEST_CLANG_SUPPRESS_WARNING_POP + } + }; +} + +struct DOCTEST_INTERFACE Approx +{ + Approx(double value); + + Approx operator()(double value) const; + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + explicit Approx(const T& value, + typename detail::types::enable_if::value>::type* = + static_cast(nullptr)) { + *this = static_cast(value); + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& epsilon(double newEpsilon); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type epsilon( + const T& newEpsilon) { + m_epsilon = static_cast(newEpsilon); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + Approx& scale(double newScale); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + template + typename std::enable_if::value, Approx&>::type scale( + const T& newScale) { + m_scale = static_cast(newScale); + return *this; + } +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format off + DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs); + DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs); + DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs); + +#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS +#define DOCTEST_APPROX_PREFIX \ + template friend typename std::enable_if::value, bool>::type + + DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } + DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } + DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } + DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } + DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } + DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } +#undef DOCTEST_APPROX_PREFIX +#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS + + // clang-format on + + double m_epsilon; + double m_scale; + double m_value; +}; + +DOCTEST_INTERFACE String toString(const Approx& in); + +DOCTEST_INTERFACE const ContextOptions* getContextOptions(); + +template +struct DOCTEST_INTERFACE_DECL IsNaN +{ + F value; bool flipped; + IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } + IsNaN operator!() const { return { value, !flipped }; } + operator bool() const; +}; +#ifndef __MINGW32__ +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +extern template struct DOCTEST_INTERFACE_DECL IsNaN; +#endif +DOCTEST_INTERFACE String toString(IsNaN in); +DOCTEST_INTERFACE String toString(IsNaN in); +DOCTEST_INTERFACE String toString(IsNaN in); + +#ifndef DOCTEST_CONFIG_DISABLE + +namespace detail { + // clang-format off +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template struct decay_array { using type = T; }; + template struct decay_array { using type = T*; }; + template struct decay_array { using type = T*; }; + + template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; + + template struct can_use_op : public not_char_pointer::type> {}; +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + + struct DOCTEST_INTERFACE TestFailureException + { + }; + + DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_INTERFACE void throwException(); + + struct DOCTEST_INTERFACE Subcase + { + SubcaseSignature m_signature; + bool m_entered = false; + + Subcase(const String& name, const char* file, int line); + Subcase(const Subcase&) = delete; + Subcase(Subcase&&) = delete; + Subcase& operator=(const Subcase&) = delete; + Subcase& operator=(Subcase&&) = delete; + ~Subcase(); + + operator bool() const; + + private: + bool checkFilters(); + }; + + template + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, + const DOCTEST_REF_WRAP(R) rhs) { + return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); + } + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") +#endif + +// This will check if there is any way it could find a operator like member or friend and uses it. +// If not it doesn't find the operator or if the operator at global scope is defined after +// this template, the template won't be instantiated due to SFINAE. Once the template is not +// instantiated it can look for global operator using normal conversions. +#ifdef __NVCC__ +#define SFINAE_OP(ret,op) ret +#else +#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) +#endif + +#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ + template \ + DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ + bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ + if(m_at & assertType::is_false) \ + res = !res; \ + if(!res || doctest::getContextOptions()->success) \ + return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ + return Result(res); \ + } + + // more checks could be added - like in Catch: + // https://github.com/catchorg/Catch2/pull/1480/files + // https://github.com/catchorg/Catch2/pull/1481/files +#define DOCTEST_FORBIT_EXPRESSION(rt, op) \ + template \ + rt& operator op(const R&) { \ + static_assert(deferred_false::value, \ + "Expression Too Complex Please Rewrite As Binary Comparison!"); \ + return *this; \ + } + + struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) + { + bool m_passed; + String m_decomp; + + Result() = default; // TODO: Why do we need this? (To remove NOLINT) + Result(bool passed, const String& decomposition = String()); + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Result, &) + DOCTEST_FORBIT_EXPRESSION(Result, ^) + DOCTEST_FORBIT_EXPRESSION(Result, |) + DOCTEST_FORBIT_EXPRESSION(Result, &&) + DOCTEST_FORBIT_EXPRESSION(Result, ||) + DOCTEST_FORBIT_EXPRESSION(Result, ==) + DOCTEST_FORBIT_EXPRESSION(Result, !=) + DOCTEST_FORBIT_EXPRESSION(Result, <) + DOCTEST_FORBIT_EXPRESSION(Result, >) + DOCTEST_FORBIT_EXPRESSION(Result, <=) + DOCTEST_FORBIT_EXPRESSION(Result, >=) + DOCTEST_FORBIT_EXPRESSION(Result, =) + DOCTEST_FORBIT_EXPRESSION(Result, +=) + DOCTEST_FORBIT_EXPRESSION(Result, -=) + DOCTEST_FORBIT_EXPRESSION(Result, *=) + DOCTEST_FORBIT_EXPRESSION(Result, /=) + DOCTEST_FORBIT_EXPRESSION(Result, %=) + DOCTEST_FORBIT_EXPRESSION(Result, <<=) + DOCTEST_FORBIT_EXPRESSION(Result, >>=) + DOCTEST_FORBIT_EXPRESSION(Result, &=) + DOCTEST_FORBIT_EXPRESSION(Result, ^=) + DOCTEST_FORBIT_EXPRESSION(Result, |=) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_PUSH + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_GCC_SUPPRESS_WARNING_PUSH + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") + DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") + //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") + + DOCTEST_MSVC_SUPPRESS_WARNING_PUSH + // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 + DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch + DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch + //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + // clang-format off +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE bool +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type + inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } + inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } + inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } + inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } + inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } + inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ + const DOCTEST_REF_WRAP(R) rhs) { \ + return lhs op rhs; \ + } + + DOCTEST_RELATIONAL_OP(eq, ==) + DOCTEST_RELATIONAL_OP(ne, !=) + DOCTEST_RELATIONAL_OP(lt, <) + DOCTEST_RELATIONAL_OP(gt, >) + DOCTEST_RELATIONAL_OP(le, <=) + DOCTEST_RELATIONAL_OP(ge, >=) + +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) l == r +#define DOCTEST_CMP_NE(l, r) l != r +#define DOCTEST_CMP_GT(l, r) l > r +#define DOCTEST_CMP_LT(l, r) l < r +#define DOCTEST_CMP_GE(l, r) l >= r +#define DOCTEST_CMP_LE(l, r) l <= r +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_CMP_EQ(l, r) eq(l, r) +#define DOCTEST_CMP_NE(l, r) ne(l, r) +#define DOCTEST_CMP_GT(l, r) gt(l, r) +#define DOCTEST_CMP_LT(l, r) lt(l, r) +#define DOCTEST_CMP_GE(l, r) ge(l, r) +#define DOCTEST_CMP_LE(l, r) le(l, r) +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + + template + // cppcheck-suppress copyCtorAndEqOperator + struct Expression_lhs + { + L lhs; + assertType::Enum m_at; + + explicit Expression_lhs(L&& in, assertType::Enum at) + : lhs(static_cast(in)) + , m_at(at) {} + + DOCTEST_NOINLINE operator Result() { +// this is needed only for MSVC 2015 +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool + bool res = static_cast(lhs); +DOCTEST_MSVC_SUPPRESS_WARNING_POP + if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + res = !res; + } + + if(!res || getContextOptions()->success) { + return { res, (DOCTEST_STRINGIFY(lhs)) }; + } + return { res }; + } + + /* This is required for user-defined conversions from Expression_lhs to L */ + operator L() const { return lhs; } + + // clang-format off + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional + DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional + // clang-format on + + // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) + // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the + // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) + DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) +DOCTEST_CLANG_SUPPRESS_WARNING_POP +#endif + + struct DOCTEST_INTERFACE ExpressionDecomposer + { + assertType::Enum m_at; + + ExpressionDecomposer(assertType::Enum at); + + // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) + // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... + // https://github.com/catchorg/Catch2/issues/870 + // https://github.com/catchorg/Catch2/issues/565 + template + Expression_lhs operator<<(L&& operand) { + return Expression_lhs(static_cast(operand), m_at); + } + + template ::value,void >::type* = nullptr> + Expression_lhs operator<<(const L &operand) { + return Expression_lhs(operand, m_at); + } + }; + + struct DOCTEST_INTERFACE TestSuite + { + const char* m_test_suite = nullptr; + const char* m_description = nullptr; + bool m_skip = false; + bool m_no_breaks = false; + bool m_no_output = false; + bool m_may_fail = false; + bool m_should_fail = false; + int m_expected_failures = 0; + double m_timeout = 0; + + TestSuite& operator*(const char* in); + + template + TestSuite& operator*(const T& in) { + in.fill(*this); + return *this; + } + }; + + using funcType = void (*)(); + + struct DOCTEST_INTERFACE TestCase : public TestCaseData + { + funcType m_test; // a function pointer to the test case + + String m_type; // for templated test cases - gets appended to the real name + int m_template_id; // an ID used to distinguish between the different versions of a templated test case + String m_full_name; // contains the name (only for templated test cases!) + the template type + + TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type = String(), int template_id = -1); + + TestCase(const TestCase& other); + TestCase(TestCase&&) = delete; + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& operator=(const TestCase& other); + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& operator=(TestCase&&) = delete; + + TestCase& operator*(const char* in); + + template + TestCase& operator*(const T& in) { + in.fill(*this); + return *this; + } + + bool operator<(const TestCase& other) const; + + ~TestCase() = default; + }; + + // forward declarations of functions used by the macros + DOCTEST_INTERFACE int regTest(const TestCase& tc); + DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); + DOCTEST_INTERFACE bool isDebuggerActive(); + + template + int instantiationHelper(const T&) { return 0; } + + namespace binaryAssertComparison { + enum Enum + { + eq = 0, + ne, + gt, + lt, + ge, + le + }; + } // namespace binaryAssertComparison + + // clang-format off + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; + +#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; + // clang-format on + + DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) + DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) + DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) + DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) + DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) + DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) + + struct DOCTEST_INTERFACE ResultBuilder : public AssertData + { + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type = "", const String& exception_string = ""); + + ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string); + + void setResult(const Result& res); + + template + DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + m_failed = !RelationalComparator()(lhs, rhs); + if (m_failed || getContextOptions()->success) { + m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); + } + return !m_failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { + m_failed = !val; + + if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional + m_failed = !m_failed; + } + + if (m_failed || getContextOptions()->success) { + m_decomp = (DOCTEST_STRINGIFY(val)); + } + + return !m_failed; + } + + void translateException(); + + bool log(); + void react() const; + }; + + namespace assertAction { + enum Enum + { + nothing = 0, + dbgbreak = 1, + shouldthrow = 2 + }; + } // namespace assertAction + + DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); + + DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, + const char* expr, const Result& result); + +#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ + do { \ + if(!is_running_in_test) { \ + if(failed) { \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + rb.m_decomp = decomp; \ + failed_out_of_a_testing_context(rb); \ + if(isDebuggerActive() && !getContextOptions()->no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(checkIfShouldThrow(at)) \ + throwException(); \ + } \ + return !failed; \ + } \ + } while(false) + +#define DOCTEST_ASSERT_IN_TESTS(decomp) \ + ResultBuilder rb(at, file, line, expr); \ + rb.m_failed = failed; \ + if(rb.m_failed || getContextOptions()->success) \ + rb.m_decomp = decomp; \ + if(rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + if(rb.m_failed && checkIfShouldThrow(at)) \ + throwException() + + template + DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + bool failed = !RelationalComparator()(lhs, rhs); + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); + return !failed; + } + + template + DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, + const char* expr, const DOCTEST_REF_WRAP(L) val) { + bool failed = !val; + + if(at & assertType::is_false) //!OCLINT bitwise operator in conditional + failed = !failed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); + DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); + return !failed; + } + + struct DOCTEST_INTERFACE IExceptionTranslator + { + DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) + virtual bool translate(String&) const = 0; + }; + + template + class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class + { + public: + explicit ExceptionTranslator(String (*translateFunction)(T)) + : m_translateFunction(translateFunction) {} + + bool translate(String& res) const override { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { + throw; // lgtm [cpp/rethrow-no-exception] + // cppcheck-suppress catchExceptionByValue + } catch(const T& ex) { + res = m_translateFunction(ex); //!OCLINT parameter reassignment + return true; + } catch(...) {} //!OCLINT - empty catch statement +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + static_cast(res); // to silence -Wunused-parameter + return false; + } + + private: + String (*m_translateFunction)(T); + }; + + DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); + + // ContextScope base class used to allow implementing methods of ContextScope + // that don't depend on the template parameter in doctest.cpp. + struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { + ContextScopeBase(const ContextScopeBase&) = delete; + + ContextScopeBase& operator=(const ContextScopeBase&) = delete; + ContextScopeBase& operator=(ContextScopeBase&&) = delete; + + ~ContextScopeBase() override = default; + + protected: + ContextScopeBase(); + ContextScopeBase(ContextScopeBase&& other) noexcept; + + void destroy(); + bool need_to_destroy{true}; + }; + + template class ContextScope : public ContextScopeBase + { + L lambda_; + + public: + explicit ContextScope(const L &lambda) : lambda_(lambda) {} + explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } + + ContextScope(const ContextScope&) = delete; + ContextScope(ContextScope&&) noexcept = default; + + ContextScope& operator=(const ContextScope&) = delete; + ContextScope& operator=(ContextScope&&) = delete; + + void stringify(std::ostream* s) const override { lambda_(s); } + + ~ContextScope() override { + if (need_to_destroy) { + destroy(); + } + } + }; + + struct DOCTEST_INTERFACE MessageBuilder : public MessageData + { + std::ostream* m_stream; + bool logged = false; + + MessageBuilder(const char* file, int line, assertType::Enum severity); + + MessageBuilder(const MessageBuilder&) = delete; + MessageBuilder(MessageBuilder&&) = delete; + + MessageBuilder& operator=(const MessageBuilder&) = delete; + MessageBuilder& operator=(MessageBuilder&&) = delete; + + ~MessageBuilder(); + + // the preferred way of chaining parameters for stringification +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) + template + MessageBuilder& operator,(const T& in) { + *m_stream << (DOCTEST_STRINGIFY(in)); + return *this; + } +DOCTEST_MSVC_SUPPRESS_WARNING_POP + + // kept here just for backwards-compatibility - the comma operator should be preferred now + template + MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template + MessageBuilder& operator*(const T& in) { return this->operator,(in); } + + bool log(); + void react(); + }; + + template + ContextScope MakeContextScope(const L &lambda) { + return ContextScope(lambda); + } +} // namespace detail + +#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ + struct name \ + { \ + type data; \ + name(type in = def) \ + : data(in) {} \ + void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ + } + +DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); +DOCTEST_DEFINE_DECORATOR(description, const char*, ""); +DOCTEST_DEFINE_DECORATOR(skip, bool, true); +DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); +DOCTEST_DEFINE_DECORATOR(no_output, bool, true); +DOCTEST_DEFINE_DECORATOR(timeout, double, 0); +DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); +DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); +DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); + +template +int registerExceptionTranslator(String (*translateFunction)(T)) { + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") + static detail::ExceptionTranslator exceptionTranslator(translateFunction); + DOCTEST_CLANG_SUPPRESS_WARNING_POP + detail::registerExceptionTranslatorImpl(&exceptionTranslator); + return 0; +} + +} // namespace doctest + +// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro +// introduces an anonymous namespace in which getCurrentTestSuite gets overridden +namespace doctest_detail_test_suite_ns { +DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); +} // namespace doctest_detail_test_suite_ns + +namespace doctest { +#else // DOCTEST_CONFIG_DISABLE +template +int registerExceptionTranslator(String (*)(T)) { + return 0; +} +#endif // DOCTEST_CONFIG_DISABLE + +namespace detail { + using assert_handler = void (*)(const AssertData&); + struct ContextState; +} // namespace detail + +class DOCTEST_INTERFACE Context +{ + detail::ContextState* p; + + void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + +public: + explicit Context(int argc = 0, const char* const* argv = nullptr); + + Context(const Context&) = delete; + Context(Context&&) = delete; + + Context& operator=(const Context&) = delete; + Context& operator=(Context&&) = delete; + + ~Context(); // NOLINT(performance-trivially-destructible) + + void applyCommandLine(int argc, const char* const* argv); + + void addFilter(const char* filter, const char* value); + void clearFilters(); + void setOption(const char* option, bool value); + void setOption(const char* option, int value); + void setOption(const char* option, const char* value); + + bool shouldExit(); + + void setAsDefaultForAssertsOutOfTestCases(); + + void setAssertHandler(detail::assert_handler ah); + + void setCout(std::ostream* out); + + int run(); +}; + +namespace TestCaseFailureReason { + enum Enum + { + None = 0, + AssertFailure = 1, // an assertion has failed in the test case + Exception = 2, // test case threw an exception + Crash = 4, // a crash... + TooManyFailedAsserts = 8, // the abort-after option + Timeout = 16, // see the timeout decorator + ShouldHaveFailedButDidnt = 32, // see the should_fail decorator + ShouldHaveFailedAndDid = 64, // see the should_fail decorator + DidntFailExactlyNumTimes = 128, // see the expected_failures decorator + FailedExactlyNumTimes = 256, // see the expected_failures decorator + CouldHaveFailedAndDid = 512 // see the may_fail decorator + }; +} // namespace TestCaseFailureReason + +struct DOCTEST_INTERFACE CurrentTestCaseStats +{ + int numAssertsCurrentTest; + int numAssertsFailedCurrentTest; + double seconds; + int failure_flags; // use TestCaseFailureReason::Enum + bool testCaseSuccess; +}; + +struct DOCTEST_INTERFACE TestCaseException +{ + String error_string; + bool is_crash; +}; + +struct DOCTEST_INTERFACE TestRunStats +{ + unsigned numTestCases; + unsigned numTestCasesPassingFilters; + unsigned numTestSuitesPassingFilters; + unsigned numTestCasesFailed; + int numAsserts; + int numAssertsFailed; +}; + +struct QueryData +{ + const TestRunStats* run_stats = nullptr; + const TestCaseData** data = nullptr; + unsigned num_data = 0; +}; + +struct DOCTEST_INTERFACE IReporter +{ + // The constructor has to accept "const ContextOptions&" as a single argument + // which has most of the options for the run + a pointer to the stdout stream + // Reporter(const ContextOptions& in) + + // called when a query should be reported (listing test cases, printing the version, etc.) + virtual void report_query(const QueryData&) = 0; + + // called when the whole test run starts + virtual void test_run_start() = 0; + // called when the whole test run ends (caching a pointer to the input doesn't make sense here) + virtual void test_run_end(const TestRunStats&) = 0; + + // called when a test case is started (safe to cache a pointer to the input) + virtual void test_case_start(const TestCaseData&) = 0; + // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) + virtual void test_case_reenter(const TestCaseData&) = 0; + // called when a test case has ended + virtual void test_case_end(const CurrentTestCaseStats&) = 0; + + // called when an exception is thrown from the test case (or it crashes) + virtual void test_case_exception(const TestCaseException&) = 0; + + // called whenever a subcase is entered (don't cache pointers to the input) + virtual void subcase_start(const SubcaseSignature&) = 0; + // called whenever a subcase is exited (don't cache pointers to the input) + virtual void subcase_end() = 0; + + // called for each assert (don't cache pointers to the input) + virtual void log_assert(const AssertData&) = 0; + // called for each message (don't cache pointers to the input) + virtual void log_message(const MessageData&) = 0; + + // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator + // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) + virtual void test_case_skipped(const TestCaseData&) = 0; + + DOCTEST_DECLARE_INTERFACE(IReporter) + + // can obtain all currently active contexts and stringify them if one wishes to do so + static int get_num_active_contexts(); + static const IContextScope* const* get_active_contexts(); + + // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown + static int get_num_stringified_contexts(); + static const String* get_stringified_contexts(); +}; + +namespace detail { + using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); + + DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); + + template + IReporter* reporterCreator(const ContextOptions& o) { + return new Reporter(o); + } +} // namespace detail + +template +int registerReporter(const char* name, int priority, bool isReporter) { + detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); + return 0; +} +} // namespace doctest + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_EMPTY [] { return false; }() +#else +#define DOCTEST_FUNC_EMPTY (void)0 +#endif + +// if registering is not disabled +#ifndef DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES +#define DOCTEST_FUNC_SCOPE_BEGIN [&] +#define DOCTEST_FUNC_SCOPE_END () +#define DOCTEST_FUNC_SCOPE_RET(v) return v +#else +#define DOCTEST_FUNC_SCOPE_BEGIN do +#define DOCTEST_FUNC_SCOPE_END while(false) +#define DOCTEST_FUNC_SCOPE_RET(v) (void)0 +#endif + +// common code in asserts - for convenience +#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ + if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ + b.react(); \ + DOCTEST_FUNC_SCOPE_RET(!b.m_failed) + +#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) x; +#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS +#define DOCTEST_WRAP_IN_TRY(x) \ + try { \ + x; \ + } catch(...) { DOCTEST_RB.translateException(); } +#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS + +#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ + static_cast(__VA_ARGS__); \ + DOCTEST_GCC_SUPPRESS_WARNING_POP +#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS +#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; +#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS + +// registers the test by initializing a dummy var with a function +#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ + global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ + doctest::detail::regTest( \ + doctest::detail::TestCase( \ + f, __FILE__, __LINE__, \ + doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ + decorators)) + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ + namespace { /* NOLINT */ \ + struct der : public base \ + { \ + void f(); \ + }; \ + static DOCTEST_INLINE_NOINLINE void func() { \ + der v; \ + v.f(); \ + } \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ + } \ + DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ + static void f(); \ + DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ + static void f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ + static doctest::detail::funcType proxy() { return f; } \ + DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ + static void f() + +// for registering tests +#define DOCTEST_TEST_CASE(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for registering tests in classes - requires C++17 for inline variables! +#if DOCTEST_CPLUSPLUS >= 201703L +#define DOCTEST_TEST_CASE_CLASS(decorators) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ + decorators) +#else // DOCTEST_TEST_CASE_CLASS +#define DOCTEST_TEST_CASE_CLASS(...) \ + TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER +#endif // DOCTEST_TEST_CASE_CLASS + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ + namespace doctest { \ + template <> \ + inline String toString<__VA_ARGS__>() { \ + return str; \ + } \ + } \ + static_assert(true, "") + +#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ + template \ + static void func(); \ + namespace { /* NOLINT */ \ + template \ + struct iter; \ + template \ + struct iter> \ + { \ + iter(const char* file, unsigned line, int index) { \ + doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ + doctest_detail_test_suite_ns::getCurrentTestSuite(), \ + doctest::toString(), \ + int(line) * 1000 + index) \ + * dec); \ + iter>(file, line, index + 1); \ + } \ + }; \ + template <> \ + struct iter> \ + { \ + iter(const char*, unsigned, int) {} \ + }; \ + } \ + template \ + static void func() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ + doctest::detail::instantiationHelper( \ + DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ + static_assert(true, "") + +#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ + DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ + template \ + static void anon() + +#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ + DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) + +// for subcases +#define DOCTEST_SUBCASE(name) \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) + +// for grouping tests in test suites by using code blocks +#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ + namespace ns_name { namespace doctest_detail_test_suite_ns { \ + static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ + static doctest::detail::TestSuite data{}; \ + static bool inited = false; \ + DOCTEST_MSVC_SUPPRESS_WARNING_POP \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP \ + DOCTEST_GCC_SUPPRESS_WARNING_POP \ + if(!inited) { \ + data* decorators; \ + inited = true; \ + } \ + return data; \ + } \ + } \ + } \ + namespace ns_name + +#define DOCTEST_TEST_SUITE(decorators) \ + DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(decorators) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ + static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ + using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +// for registering exception translators +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ + inline doctest::String translatorName(signature); \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerExceptionTranslator(translatorName)) \ + doctest::String translatorName(signature) + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ + signature) + +// for registering reporters +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, true)) \ + static_assert(true, "") + +// for registering listeners +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ + DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ + doctest::registerReporter(name, priority, false)) \ + static_assert(true, "") + +// clang-format off +// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 +#define DOCTEST_INFO(...) \ + DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ + DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ + __VA_ARGS__) +// clang-format on + +#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ + auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ + [&](std::ostream* s_name) { \ + doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ + mb_name.m_stream = s_name; \ + mb_name * __VA_ARGS__; \ + }) + +#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) + +#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ + mb * __VA_ARGS__; \ + if(mb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + mb.react(); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) +// clang-format on + +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) + +#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. + +#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ + DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ + } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + +#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY( \ + DOCTEST_RB.binary_assert( \ + __VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +// necessary for _MESSAGE +#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 + +#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ + doctest::detail::decomp_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ + doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ + << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP + +#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ + doctest::detail::binary_assert( \ + doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) + +#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ + doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ + #__VA_ARGS__, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) +#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) +#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) +#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) + +// clang-format off +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) +#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) +#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) +#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) +#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) +#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) +#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) +#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) +#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) +#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) +#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) +#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) +#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) +#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) +#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) +#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) +#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) + +#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #expr, #__VA_ARGS__, message); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(const typename doctest::detail::types::remove_const< \ + typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ + DOCTEST_RB.translateException(); \ + DOCTEST_RB.m_threw_as = true; \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + if(!doctest::getContextOptions()->no_throw) { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, expr_str, "", __VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(expr) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } else { /* NOLINT(*-else-after-return) */ \ + DOCTEST_FUNC_SCOPE_RET(false); \ + } \ + } DOCTEST_FUNC_SCOPE_END + +#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ + DOCTEST_FUNC_SCOPE_BEGIN { \ + doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ + __LINE__, #__VA_ARGS__); \ + try { \ + DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ + } catch(...) { DOCTEST_RB.translateException(); } \ + DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ + } DOCTEST_FUNC_SCOPE_END + +// clang-format off +#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") +#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") + +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) + +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END +// clang-format on + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// ================================================================================================= +// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == +// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == +// ================================================================================================= +#else // DOCTEST_CONFIG_DISABLE + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ + namespace /* NOLINT */ { \ + template \ + struct der : public base \ + { void f(); }; \ + } \ + template \ + inline void der::f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ + template \ + static inline void f() + +// for registering tests +#define DOCTEST_TEST_CASE(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests in classes +#define DOCTEST_TEST_CASE_CLASS(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) + +// for converting types to strings without the header and demangling +#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") +#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") + +// for typed tests +#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ + template \ + inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() + +#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") +#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") + +// for subcases +#define DOCTEST_SUBCASE(name) + +// for a testsuite block +#define DOCTEST_TEST_SUITE(name) namespace // NOLINT + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int + +#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ + template \ + static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) + +#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) + +#define DOCTEST_INFO(...) (static_cast(0)) +#define DOCTEST_CAPTURE(x) (static_cast(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) +#define DOCTEST_MESSAGE(...) (static_cast(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) +#define DOCTEST_FAIL(...) (static_cast(0)) + +#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ + && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) + +#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() + +namespace doctest { +namespace detail { +#define DOCTEST_RELATIONAL_OP(name, op) \ + template \ + bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } + + DOCTEST_RELATIONAL_OP(eq, ==) + DOCTEST_RELATIONAL_OP(ne, !=) + DOCTEST_RELATIONAL_OP(lt, <) + DOCTEST_RELATIONAL_OP(gt, >) + DOCTEST_RELATIONAL_OP(le, <=) + DOCTEST_RELATIONAL_OP(ge, >=) +} // namespace detail +} // namespace doctest + +#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() +#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() +#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() +#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() +#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() +#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() +#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() +#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() +#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() +#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) + +#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS + +#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY +#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS +#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ + "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() + +#undef DOCTEST_REQUIRE +#undef DOCTEST_REQUIRE_FALSE +#undef DOCTEST_REQUIRE_MESSAGE +#undef DOCTEST_REQUIRE_FALSE_MESSAGE +#undef DOCTEST_REQUIRE_EQ +#undef DOCTEST_REQUIRE_NE +#undef DOCTEST_REQUIRE_GT +#undef DOCTEST_REQUIRE_LT +#undef DOCTEST_REQUIRE_GE +#undef DOCTEST_REQUIRE_LE +#undef DOCTEST_REQUIRE_UNARY +#undef DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS + +#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC + +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + +// clang-format off +// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS +#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ +#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ +#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ +#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE +#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE +#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE +#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT +#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT +#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT +#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT +#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT +#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT +#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE +#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE +#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE +#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE +#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE +#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE + +#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY +#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY +#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY +#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE +#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE +#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE + +#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) +// clang-format on + +// BDD style macros +// clang-format off +#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name) +#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name) +#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) +#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) + +#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) +#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) +#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) +#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) +#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) +// clang-format on + +// == SHORT VERSIONS OF THE MACROS +#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#define TEST_CASE(name) DOCTEST_TEST_CASE(name) +#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) +#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) +#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) +#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) +#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) +#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) +#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) +#define SUBCASE(name) DOCTEST_SUBCASE(name) +#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) +#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) +#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) +#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) +#define INFO(...) DOCTEST_INFO(__VA_ARGS__) +#define CAPTURE(x) DOCTEST_CAPTURE(x) +#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) +#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) +#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) +#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) +#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) +#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) + +#define WARN(...) DOCTEST_WARN(__VA_ARGS__) +#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) +#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) +#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) +#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) +#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) +#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) +#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) +#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) +#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) +#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) +#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) +#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) +#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) +#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) + +#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) +#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) +#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) +#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) +#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) +#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) +#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) +#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) +#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) +#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) +#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) + +#define SCENARIO(name) DOCTEST_SCENARIO(name) +#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) +#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) +#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) +#define GIVEN(name) DOCTEST_GIVEN(name) +#define WHEN(name) DOCTEST_WHEN(name) +#define AND_WHEN(name) DOCTEST_AND_WHEN(name) +#define THEN(name) DOCTEST_THEN(name) +#define AND_THEN(name) DOCTEST_AND_THEN(name) + +#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) +#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) +#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) +#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) +#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) +#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) +#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) +#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) +#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) +#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) +#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) +#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) +#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) +#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) +#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) +#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) +#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) +#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) +#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) +#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) +#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) +#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) +#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +// KEPT FOR BACKWARDS COMPATIBILITY +#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) +#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) +#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) +#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) +#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) +#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) +#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) +#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) +#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) +#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) +#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) +#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) +#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) +#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) +#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) +#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) +#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) +#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) + +#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) +#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) +#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) +#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) +#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) +#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) + +#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) + +#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +#ifndef DOCTEST_CONFIG_DISABLE + +// this is here to clear the 'current test suite' for the current translation unit - at the top +DOCTEST_TEST_SUITE_END(); + +#endif // DOCTEST_CONFIG_DISABLE + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_INCLUDED + +#ifndef DOCTEST_SINGLE_HEADER +#define DOCTEST_SINGLE_HEADER +#endif // DOCTEST_SINGLE_HEADER + +#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) + +#ifndef DOCTEST_SINGLE_HEADER +#include "doctest_fwd.h" +#endif // DOCTEST_SINGLE_HEADER + +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") + +#ifndef DOCTEST_LIBRARY_IMPLEMENTATION +#define DOCTEST_LIBRARY_IMPLEMENTATION + +DOCTEST_CLANG_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH + +DOCTEST_CLANG_SUPPRESS_WARNING_PUSH +DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") +DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") + +DOCTEST_GCC_SUPPRESS_WARNING_PUSH +DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") +DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") +DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") +DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") +DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") +DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") + +DOCTEST_MSVC_SUPPRESS_WARNING_PUSH +DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data +DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled +DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified +DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal +DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch +DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C +DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning) +DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN + +// required includes - will go only in one translation unit! +#include +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 +#ifdef __BORLANDC__ +#include +#endif // __BORLANDC__ +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#include +#include +#include +#ifndef DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; +#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); +#else // DOCTEST_CONFIG_NO_MULTITHREADING +#define DOCTEST_DECLARE_MUTEX(name) +#define DOCTEST_DECLARE_STATIC_MUTEX(name) +#define DOCTEST_LOCK_MUTEX(name) +#endif // DOCTEST_CONFIG_NO_MULTITHREADING +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DOCTEST_PLATFORM_MAC +#include +#include +#include +#endif // DOCTEST_PLATFORM_MAC + +#ifdef DOCTEST_PLATFORM_WINDOWS + +// defines for a leaner windows.h +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // WIN32_LEAN_AND_MEAN +#ifndef NOMINMAX +#define NOMINMAX +#define DOCTEST_UNDEF_NOMINMAX +#endif // NOMINMAX + +// not sure what AfxWin.h is for - here I do what Catch does +#ifdef __AFXDLL +#include +#else +#include +#endif +#include + +#else // DOCTEST_PLATFORM_WINDOWS + +#include +#include + +#endif // DOCTEST_PLATFORM_WINDOWS + +// this is a fix for https://github.com/doctest/doctest/issues/348 +// https://mail.gnome.org/archives/xml/2012-January/msg00000.html +#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) +#define STDOUT_FILENO fileno(stdout) +#endif // HAVE_UNISTD_H + +DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END + +// counts the number of elements in a C array +#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) + +#ifdef DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled +#else // DOCTEST_CONFIG_DISABLE +#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled +#endif // DOCTEST_CONFIG_DISABLE + +#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX +#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-" +#endif + +#ifndef DOCTEST_THREAD_LOCAL +#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) +#define DOCTEST_THREAD_LOCAL +#else // DOCTEST_MSVC +#define DOCTEST_THREAD_LOCAL thread_local +#endif // DOCTEST_MSVC +#endif // DOCTEST_THREAD_LOCAL + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES +#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 +#endif + +#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE +#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 +#endif + +#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS +#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX +#else +#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" +#endif + +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS +#endif + +#ifndef DOCTEST_CDECL +#define DOCTEST_CDECL __cdecl +#endif + +namespace doctest { + +bool is_running_in_test = false; + +namespace { + using namespace detail; + + template + DOCTEST_NORETURN void throw_exception(Ex const& e) { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + throw e; +#else // DOCTEST_CONFIG_NO_EXCEPTIONS +#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION + DOCTEST_CONFIG_HANDLE_EXCEPTION(e); +#else // DOCTEST_CONFIG_HANDLE_EXCEPTION +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + std::cerr << "doctest will terminate because it needed to throw an exception.\n" + << "The message was: " << e.what() << '\n'; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM +#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION + std::terminate(); +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } + +#ifndef DOCTEST_INTERNAL_ERROR +#define DOCTEST_INTERNAL_ERROR(msg) \ + throw_exception(std::logic_error( \ + __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) +#endif // DOCTEST_INTERNAL_ERROR + + // case insensitive strcmp + int stricmp(const char* a, const char* b) { + for(;; a++, b++) { + const int d = tolower(*a) - tolower(*b); + if(d != 0 || !*a) + return d; + } + } + + struct Endianness + { + enum Arch + { + Big, + Little + }; + + static Arch which() { + int x = 1; + // casting any data pointer to char* is allowed + auto ptr = reinterpret_cast(&x); + if(*ptr) + return Little; + return Big; + } + }; +} // namespace + +namespace detail { + DOCTEST_THREAD_LOCAL class + { + std::vector stack; + std::stringstream ss; + + public: + std::ostream* push() { + stack.push_back(ss.tellp()); + return &ss; + } + + String pop() { + if (stack.empty()) + DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); + + std::streampos pos = stack.back(); + stack.pop_back(); + unsigned sz = static_cast(ss.tellp() - pos); + ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); + return String(ss, sz); + } + } g_oss; + + std::ostream* tlssPush() { + return g_oss.push(); + } + + String tlssPop() { + return g_oss.pop(); + } + +#ifndef DOCTEST_CONFIG_DISABLE + +namespace timer_large_integer +{ + +#if defined(DOCTEST_PLATFORM_WINDOWS) + using type = ULONGLONG; +#else // DOCTEST_PLATFORM_WINDOWS + using type = std::uint64_t; +#endif // DOCTEST_PLATFORM_WINDOWS +} + +using ticks_t = timer_large_integer::type; + +#ifdef DOCTEST_CONFIG_GETCURRENTTICKS + ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } +#elif defined(DOCTEST_PLATFORM_WINDOWS) + ticks_t getCurrentTicks() { + static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; + if(!hz.QuadPart) { + QueryPerformanceFrequency(&hz); + QueryPerformanceCounter(&hzo); + } + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; + } +#else // DOCTEST_PLATFORM_WINDOWS + ticks_t getCurrentTicks() { + timeval t; + gettimeofday(&t, nullptr); + return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); + } +#endif // DOCTEST_PLATFORM_WINDOWS + + struct Timer + { + void start() { m_ticks = getCurrentTicks(); } + unsigned int getElapsedMicroseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + //unsigned int getElapsedMilliseconds() const { + // return static_cast(getElapsedMicroseconds() / 1000); + //} + double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } + + private: + ticks_t m_ticks = 0; + }; + +#ifdef DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = T; +#else // DOCTEST_CONFIG_NO_MULTITHREADING + template + using Atomic = std::atomic; +#endif // DOCTEST_CONFIG_NO_MULTITHREADING + +#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) + template + using MultiLaneAtomic = Atomic; +#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + // Provides a multilane implementation of an atomic variable that supports add, sub, load, + // store. Instead of using a single atomic variable, this splits up into multiple ones, + // each sitting on a separate cache line. The goal is to provide a speedup when most + // operations are modifying. It achieves this with two properties: + // + // * Multiple atomics are used, so chance of congestion from the same atomic is reduced. + // * Each atomic sits on a separate cache line, so false sharing is reduced. + // + // The disadvantage is that there is a small overhead due to the use of TLS, and load/store + // is slower because all atomics have to be accessed. + template + class MultiLaneAtomic + { + struct CacheLineAlignedAtomic + { + Atomic atomic{}; + char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; + }; + CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; + + static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, + "guarantee one atomic takes exactly one cache line"); + + public: + T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } + + T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } + + T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_add(arg, order); + } + + T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + return myAtomic().fetch_sub(arg, order); + } + + operator T() const DOCTEST_NOEXCEPT { return load(); } + + T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { + auto result = T(); + for(auto const& c : m_atomics) { + result += c.atomic.load(order); + } + return result; + } + + T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] + store(desired); + return desired; + } + + void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { + // first value becomes desired", all others become 0. + for(auto& c : m_atomics) { + c.atomic.store(desired, order); + desired = {}; + } + } + + private: + // Each thread has a different atomic that it operates on. If more than NumLanes threads + // use this, some will use the same atomic. So performance will degrade a bit, but still + // everything will work. + // + // The logic here is a bit tricky. The call should be as fast as possible, so that there + // is minimal to no overhead in determining the correct atomic for the current thread. + // + // 1. A global static counter laneCounter counts continuously up. + // 2. Each successive thread will use modulo operation of that counter so it gets an atomic + // assigned in a round-robin fashion. + // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with + // little overhead. + Atomic& myAtomic() DOCTEST_NOEXCEPT { + static Atomic laneCounter; + DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = + laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; + + return m_atomics[tlsLaneIdx].atomic; + } + }; +#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS + + // this holds both parameters from the command line and runtime data for tests + struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats + { + MultiLaneAtomic numAssertsCurrentTest_atomic; + MultiLaneAtomic numAssertsFailedCurrentTest_atomic; + + std::vector> filters = decltype(filters)(9); // 9 different filters + + std::vector reporters_currently_used; + + assert_handler ah = nullptr; + + Timer timer; + + std::vector stringifiedContexts; // logging from INFO() due to an exception + + // stuff for subcases + bool reachedLeaf; + std::vector subcaseStack; + std::vector nextSubcaseStack; + std::unordered_set fullyTraversedSubcases; + size_t currentSubcaseDepth; + Atomic shouldLogCurrentException; + + void resetRunData() { + numTestCases = 0; + numTestCasesPassingFilters = 0; + numTestSuitesPassingFilters = 0; + numTestCasesFailed = 0; + numAsserts = 0; + numAssertsFailed = 0; + numAssertsCurrentTest = 0; + numAssertsFailedCurrentTest = 0; + } + + void finalizeTestCaseData() { + seconds = timer.getElapsedSeconds(); + + // update the non-atomic counters + numAsserts += numAssertsCurrentTest_atomic; + numAssertsFailed += numAssertsFailedCurrentTest_atomic; + numAssertsCurrentTest = numAssertsCurrentTest_atomic; + numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; + + if(numAssertsFailedCurrentTest) + failure_flags |= TestCaseFailureReason::AssertFailure; + + if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && + Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) + failure_flags |= TestCaseFailureReason::Timeout; + + if(currentTest->m_should_fail) { + if(failure_flags) { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; + } else { + failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; + } + } else if(failure_flags && currentTest->m_may_fail) { + failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; + } else if(currentTest->m_expected_failures > 0) { + if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) { + failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; + } else { + failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; + } + } + + bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || + (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); + + // if any subcase has failed - the whole test case has failed + testCaseSuccess = !(failure_flags && !ok_to_fail); + if(!testCaseSuccess) + numTestCasesFailed++; + } + }; + + ContextState* g_cs = nullptr; + + // used to avoid locks for the debug output + // TODO: figure out if this is indeed necessary/correct - seems like either there still + // could be a race or that there wouldn't be a race even if using the context directly + DOCTEST_THREAD_LOCAL bool g_no_colors; + +#endif // DOCTEST_CONFIG_DISABLE +} // namespace detail + +char* String::allocate(size_type sz) { + if (sz <= last) { + buf[sz] = '\0'; + setLast(last - sz); + return buf; + } else { + setOnHeap(); + data.size = sz; + data.capacity = data.size + 1; + data.ptr = new char[data.capacity]; + data.ptr[sz] = '\0'; + return data.ptr; + } +} + +void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } +void String::setLast(size_type in) noexcept { buf[last] = char(in); } +void String::setSize(size_type sz) noexcept { + if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } + else { data.ptr[sz] = '\0'; data.size = sz; } +} + +void String::copy(const String& other) { + if(other.isOnStack()) { + memcpy(buf, other.buf, len); + } else { + memcpy(allocate(other.data.size), other.data.ptr, other.data.size); + } +} + +String::String() noexcept { + buf[0] = '\0'; + setLast(); +} + +String::~String() { + if(!isOnStack()) + delete[] data.ptr; +} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) + +String::String(const char* in) + : String(in, strlen(in)) {} + +String::String(const char* in, size_type in_size) { + memcpy(allocate(in_size), in, in_size); +} + +String::String(std::istream& in, size_type in_size) { + in.read(allocate(in_size), in_size); +} + +String::String(const String& other) { copy(other); } + +String& String::operator=(const String& other) { + if(this != &other) { + if(!isOnStack()) + delete[] data.ptr; + + copy(other); + } + + return *this; +} + +String& String::operator+=(const String& other) { + const size_type my_old_size = size(); + const size_type other_size = other.size(); + const size_type total_size = my_old_size + other_size; + if(isOnStack()) { + if(total_size < len) { + // append to the current stack space + memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) + setLast(last - total_size); + } else { + // alloc new chunk + char* temp = new char[total_size + 1]; + // copy current data to new location before writing in the union + memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed + // update data in union + setOnHeap(); + data.size = total_size; + data.capacity = data.size + 1; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } else { + if(data.capacity > total_size) { + // append to the current heap block + data.size = total_size; + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } else { + // resize + data.capacity *= 2; + if(data.capacity <= total_size) + data.capacity = total_size + 1; + // alloc new chunk + char* temp = new char[data.capacity]; + // copy current data to new location before releasing it + memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed + // release old chunk + delete[] data.ptr; + // update the rest of the union members + data.size = total_size; + data.ptr = temp; + // transfer the rest of the data + memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); + } + } + + return *this; +} + +String::String(String&& other) noexcept { + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); +} + +String& String::operator=(String&& other) noexcept { + if(this != &other) { + if(!isOnStack()) + delete[] data.ptr; + memcpy(buf, other.buf, len); + other.buf[0] = '\0'; + other.setLast(); + } + return *this; +} + +char String::operator[](size_type i) const { + return const_cast(this)->operator[](i); +} + +char& String::operator[](size_type i) { + if(isOnStack()) + return reinterpret_cast(buf)[i]; + return data.ptr[i]; +} + +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") +String::size_type String::size() const { + if(isOnStack()) + return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 + return data.size; +} +DOCTEST_GCC_SUPPRESS_WARNING_POP + +String::size_type String::capacity() const { + if(isOnStack()) + return len; + return data.capacity; +} + +String String::substr(size_type pos, size_type cnt) && { + cnt = std::min(cnt, size() - 1 - pos); + char* cptr = c_str(); + memmove(cptr, cptr + pos, cnt); + setSize(cnt); + return std::move(*this); +} + +String String::substr(size_type pos, size_type cnt) const & { + cnt = std::min(cnt, size() - 1 - pos); + return String{ c_str() + pos, cnt }; +} + +String::size_type String::find(char ch, size_type pos) const { + const char* begin = c_str(); + const char* end = begin + size(); + const char* it = begin + pos; + for (; it < end && *it != ch; it++); + if (it < end) { return static_cast(it - begin); } + else { return npos; } +} + +String::size_type String::rfind(char ch, size_type pos) const { + const char* begin = c_str(); + const char* it = begin + std::min(pos, size() - 1); + for (; it >= begin && *it != ch; it--); + if (it >= begin) { return static_cast(it - begin); } + else { return npos; } +} + +int String::compare(const char* other, bool no_case) const { + if(no_case) + return doctest::stricmp(c_str(), other); + return std::strcmp(c_str(), other); +} + +int String::compare(const String& other, bool no_case) const { + return compare(other.c_str(), no_case); +} + +String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } + +bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } +bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } +bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } +bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } +bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } +bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } + +std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } + +Contains::Contains(const String& str) : string(str) { } + +bool Contains::checkWith(const String& other) const { + return strstr(other.c_str(), string.c_str()) != nullptr; +} + +String toString(const Contains& in) { + return "Contains( " + in.string + " )"; +} + +bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } +bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } +bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } +bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } + +namespace { + void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) +} // namespace + +namespace Color { + std::ostream& operator<<(std::ostream& s, Color::Enum code) { + color_to_stream(s, code); + return s; + } +} // namespace Color + +// clang-format off +const char* assertString(assertType::Enum at) { + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled + #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type + #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) + switch(at) { + DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK); + DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE); + + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); + DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); + + default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP +} +// clang-format on + +const char* failureString(assertType::Enum at) { + if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional + return "WARNING"; + if(at & assertType::is_check) //!OCLINT bitwise operator in conditional + return "ERROR"; + if(at & assertType::is_require) //!OCLINT bitwise operator in conditional + return "FATAL ERROR"; + return ""; +} + +DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") +DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") +// depending on the current options this will remove the path of filenames +const char* skipPathFromFilename(const char* file) { +#ifndef DOCTEST_CONFIG_DISABLE + if(getContextOptions()->no_path_in_filenames) { + auto back = std::strrchr(file, '\\'); + auto forward = std::strrchr(file, '/'); + if(back || forward) { + if(back > forward) + forward = back; + return forward + 1; + } + } +#endif // DOCTEST_CONFIG_DISABLE + return file; +} +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +bool SubcaseSignature::operator==(const SubcaseSignature& other) const { + return m_line == other.m_line + && std::strcmp(m_file, other.m_file) == 0 + && m_name == other.m_name; +} + +bool SubcaseSignature::operator<(const SubcaseSignature& other) const { + if(m_line != other.m_line) + return m_line < other.m_line; + if(std::strcmp(m_file, other.m_file) != 0) + return std::strcmp(m_file, other.m_file) < 0; + return m_name.compare(other.m_name) < 0; +} + +DOCTEST_DEFINE_INTERFACE(IContextScope) + +namespace detail { + void filldata::fill(std::ostream* stream, const void* in) { + if (in) { *stream << in; } + else { *stream << "nullptr"; } + } + + template + String toStreamLit(T t) { + std::ostream* os = tlssPush(); + os->operator<<(t); + return tlssPop(); + } +} + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + +#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) +// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 +String toString(const std::string& in) { return in.c_str(); } +#endif // VS 2019 + +String toString(String in) { return in; } + +String toString(std::nullptr_t) { return "nullptr"; } + +String toString(bool in) { return in ? "true" : "false"; } + +String toString(float in) { return toStreamLit(in); } +String toString(double in) { return toStreamLit(in); } +String toString(double long in) { return toStreamLit(in); } + +String toString(char in) { return toStreamLit(static_cast(in)); } +String toString(char signed in) { return toStreamLit(static_cast(in)); } +String toString(char unsigned in) { return toStreamLit(static_cast(in)); } +String toString(short in) { return toStreamLit(in); } +String toString(short unsigned in) { return toStreamLit(in); } +String toString(signed in) { return toStreamLit(in); } +String toString(unsigned in) { return toStreamLit(in); } +String toString(long in) { return toStreamLit(in); } +String toString(long unsigned in) { return toStreamLit(in); } +String toString(long long in) { return toStreamLit(in); } +String toString(long long unsigned in) { return toStreamLit(in); } + +Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) + , m_scale(1.0) + , m_value(value) {} + +Approx Approx::operator()(double value) const { + Approx approx(value); + approx.epsilon(m_epsilon); + approx.scale(m_scale); + return approx; +} + +Approx& Approx::epsilon(double newEpsilon) { + m_epsilon = newEpsilon; + return *this; +} +Approx& Approx::scale(double newScale) { + m_scale = newScale; + return *this; +} + +bool operator==(double lhs, const Approx& rhs) { + // Thanks to Richard Harris for his help refining this formula + return std::fabs(lhs - rhs.m_value) < + rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); +} +bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } +bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } +bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } +bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } +bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } +bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } +bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } +bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } +bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } +bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } +bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } + +String toString(const Approx& in) { + return "Approx( " + doctest::toString(in.m_value) + " )"; +} +const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } + +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) +template +IsNaN::operator bool() const { + return std::isnan(value) ^ flipped; +} +DOCTEST_MSVC_SUPPRESS_WARNING_POP +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template struct DOCTEST_INTERFACE_DEF IsNaN; +template +String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } +String toString(IsNaN in) { return toString(in); } +String toString(IsNaN in) { return toString(in); } +String toString(IsNaN in) { return toString(in); } + +} // namespace doctest + +#ifdef DOCTEST_CONFIG_DISABLE +namespace doctest { +Context::Context(int, const char* const*) {} +Context::~Context() = default; +void Context::applyCommandLine(int, const char* const*) {} +void Context::addFilter(const char*, const char*) {} +void Context::clearFilters() {} +void Context::setOption(const char*, bool) {} +void Context::setOption(const char*, int) {} +void Context::setOption(const char*, const char*) {} +bool Context::shouldExit() { return false; } +void Context::setAsDefaultForAssertsOutOfTestCases() {} +void Context::setAssertHandler(detail::assert_handler) {} +void Context::setCout(std::ostream*) {} +int Context::run() { return 0; } + +int IReporter::get_num_active_contexts() { return 0; } +const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } +int IReporter::get_num_stringified_contexts() { return 0; } +const String* IReporter::get_stringified_contexts() { return nullptr; } + +int registerReporter(const char*, int, IReporter*) { return 0; } + +} // namespace doctest +#else // DOCTEST_CONFIG_DISABLE + +#if !defined(DOCTEST_CONFIG_COLORS_NONE) +#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI) +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_CONFIG_COLORS_WINDOWS +#else // linux +#define DOCTEST_CONFIG_COLORS_ANSI +#endif // platform +#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI +#endif // DOCTEST_CONFIG_COLORS_NONE + +namespace doctest_detail_test_suite_ns { +// holds the current test suite +doctest::detail::TestSuite& getCurrentTestSuite() { + static doctest::detail::TestSuite data{}; + return data; +} +} // namespace doctest_detail_test_suite_ns + +namespace doctest { +namespace { + // the int (priority) is part of the key for automatic sorting - sadly one can register a + // reporter with a duplicate name and a different priority but hopefully that won't happen often :| + using reporterMap = std::map, reporterCreatorFunc>; + + reporterMap& getReporters() { + static reporterMap data; + return data; + } + reporterMap& getListeners() { + static reporterMap data; + return data; + } +} // namespace +namespace detail { +#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ + for(auto& curr_rep : g_cs->reporters_currently_used) \ + curr_rep->function(__VA_ARGS__) + + bool checkIfShouldThrow(assertType::Enum at) { + if(at & assertType::is_require) //!OCLINT bitwise operator in conditional + return true; + + if((at & assertType::is_check) //!OCLINT bitwise operator in conditional + && getContextOptions()->abort_after > 0 && + (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= + getContextOptions()->abort_after) + return true; + + return false; + } + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + DOCTEST_NORETURN void throwException() { + g_cs->shouldLogCurrentException = false; + throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) + } +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + void throwException() {} +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +} // namespace detail + +namespace { + using namespace detail; + // matching of a string against a wildcard mask (case sensitivity configurable) taken from + // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing + int wildcmp(const char* str, const char* wild, bool caseSensitive) { + const char* cp = str; + const char* mp = wild; + + while((*str) && (*wild != '*')) { + if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while(*str) { + if(*wild == '*') { + if(!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; + } else { + wild = mp; //!OCLINT parameter reassignment + str = cp++; //!OCLINT parameter reassignment + } + } + + while(*wild == '*') { + wild++; + } + return !*wild; + } + + // checks if the name matches any of the filters (and can be configured what to do when empty) + bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, + bool caseSensitive) { + if (filters.empty() && matchEmpty) + return true; + for (auto& curr : filters) + if (wildcmp(name, curr.c_str(), caseSensitive)) + return true; + return false; + } + + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(unsigned long long a, unsigned long long b) { + return (a << 5) + b; + } + + // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html + DOCTEST_NO_SANITIZE_INTEGER + unsigned long long hash(const char* str) { + unsigned long long hash = 5381; + char c; + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; // hash * 33 + c + return hash; + } + + unsigned long long hash(const SubcaseSignature& sig) { + return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); + } + + unsigned long long hash(const std::vector& sigs, size_t count) { + unsigned long long running = 0; + auto end = sigs.begin() + count; + for (auto it = sigs.begin(); it != end; it++) { + running = hash(running, hash(*it)); + } + return running; + } + + unsigned long long hash(const std::vector& sigs) { + unsigned long long running = 0; + for (const SubcaseSignature& sig : sigs) { + running = hash(running, hash(sig)); + } + return running; + } +} // namespace +namespace detail { + bool Subcase::checkFilters() { + if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { + if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) + return true; + if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) + return true; + } + return false; + } + + Subcase::Subcase(const String& name, const char* file, int line) + : m_signature({name, file, line}) { + if (!g_cs->reachedLeaf) { + if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() + || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { + // Going down. + if (checkFilters()) { return; } + + g_cs->subcaseStack.push_back(m_signature); + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } + } else { + if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { + // This subcase is reentered via control flow. + g_cs->currentSubcaseDepth++; + m_entered = true; + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); + } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth + && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) + == g_cs->fullyTraversedSubcases.end()) { + if (checkFilters()) { return; } + // This subcase is part of the one to be executed next. + g_cs->nextSubcaseStack.clear(); + g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), + g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); + g_cs->nextSubcaseStack.push_back(m_signature); + } + } + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + Subcase::~Subcase() { + if (m_entered) { + g_cs->currentSubcaseDepth--; + + if (!g_cs->reachedLeaf) { + // Leaf. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + g_cs->nextSubcaseStack.clear(); + g_cs->reachedLeaf = true; + } else if (g_cs->nextSubcaseStack.empty()) { + // All children are finished. + g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); + } + +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if(std::uncaught_exceptions() > 0 +#else + if(std::uncaught_exception() +#endif + && g_cs->shouldLogCurrentException) { + DOCTEST_ITERATE_THROUGH_REPORTERS( + test_case_exception, {"exception thrown in subcase - will translate later " + "when the whole test case has been exited (cannot " + "translate while there is an active exception)", + false}); + g_cs->shouldLogCurrentException = false; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + Subcase::operator bool() const { return m_entered; } + + Result::Result(bool passed, const String& decomposition) + : m_passed(passed) + , m_decomp(decomposition) {} + + ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) + : m_at(at) {} + + TestSuite& TestSuite::operator*(const char* in) { + m_test_suite = in; + return *this; + } + + TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, + const String& type, int template_id) { + m_file = file; + m_line = line; + m_name = nullptr; // will be later overridden in operator* + m_test_suite = test_suite.m_test_suite; + m_description = test_suite.m_description; + m_skip = test_suite.m_skip; + m_no_breaks = test_suite.m_no_breaks; + m_no_output = test_suite.m_no_output; + m_may_fail = test_suite.m_may_fail; + m_should_fail = test_suite.m_should_fail; + m_expected_failures = test_suite.m_expected_failures; + m_timeout = test_suite.m_timeout; + + m_test = test; + m_type = type; + m_template_id = template_id; + } + + TestCase::TestCase(const TestCase& other) + : TestCaseData() { + *this = other; + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function + TestCase& TestCase::operator=(const TestCase& other) { + TestCaseData::operator=(other); + m_test = other.m_test; + m_type = other.m_type; + m_template_id = other.m_template_id; + m_full_name = other.m_full_name; + + if(m_template_id != -1) + m_name = m_full_name.c_str(); + return *this; + } + DOCTEST_MSVC_SUPPRESS_WARNING_POP + + TestCase& TestCase::operator*(const char* in) { + m_name = in; + // make a new name with an appended type for templated test case + if(m_template_id != -1) { + m_full_name = String(m_name) + "<" + m_type + ">"; + // redirect the name to point to the newly constructed full name + m_name = m_full_name.c_str(); + } + return *this; + } + + bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting + if(m_line != other.m_line) + return m_line < other.m_line; + const int name_cmp = strcmp(m_name, other.m_name); + if(name_cmp != 0) + return name_cmp < 0; + const int file_cmp = m_file.compare(other.m_file); + if(file_cmp != 0) + return file_cmp < 0; + return m_template_id < other.m_template_id; + } + + // all the registered tests + std::set& getRegisteredTests() { + static std::set data; + return data; + } +} // namespace detail +namespace { + using namespace detail; + // for sorting tests by file/line + bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); + if(res != 0) + return res < 0; + if(lhs->m_line != rhs->m_line) + return lhs->m_line < rhs->m_line; + return lhs->m_template_id < rhs->m_template_id; + } + + // for sorting tests by suite/file/line + bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); + if(res != 0) + return res < 0; + return fileOrderComparator(lhs, rhs); + } + + // for sorting tests by name/suite/file/line + bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { + const int res = std::strcmp(lhs->m_name, rhs->m_name); + if(res != 0) + return res < 0; + return suiteOrderComparator(lhs, rhs); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + void color_to_stream(std::ostream& s, Color::Enum code) { + static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS + static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE +#ifdef DOCTEST_CONFIG_COLORS_ANSI + if(g_no_colors || + (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) + return; + + auto col = ""; + // clang-format off + switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement + case Color::Red: col = "[0;31m"; break; + case Color::Green: col = "[0;32m"; break; + case Color::Blue: col = "[0;34m"; break; + case Color::Cyan: col = "[0;36m"; break; + case Color::Yellow: col = "[0;33m"; break; + case Color::Grey: col = "[1;30m"; break; + case Color::LightGrey: col = "[0;37m"; break; + case Color::BrightRed: col = "[1;31m"; break; + case Color::BrightGreen: col = "[1;32m"; break; + case Color::BrightWhite: col = "[1;37m"; break; + case Color::Bright: // invalid + case Color::None: + case Color::White: + default: col = "[0m"; + } + // clang-format on + s << "\033" << col; +#endif // DOCTEST_CONFIG_COLORS_ANSI + +#ifdef DOCTEST_CONFIG_COLORS_WINDOWS + if(g_no_colors || + (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) + return; + + static struct ConsoleHelper { + HANDLE stdoutHandle; + WORD origFgAttrs; + WORD origBgAttrs; + + ConsoleHelper() { + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + } ch; + +#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) + + // clang-format off + switch (code) { + case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; + case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; + case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; + case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; + case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; + case Color::Grey: DOCTEST_SET_ATTR(0); break; + case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; + case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; + case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; + case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::None: + case Color::Bright: // invalid + default: DOCTEST_SET_ATTR(ch.origFgAttrs); + } + // clang-format on +#endif // DOCTEST_CONFIG_COLORS_WINDOWS + } + DOCTEST_CLANG_SUPPRESS_WARNING_POP + + std::vector& getExceptionTranslators() { + static std::vector data; + return data; + } + + String translateActiveException() { +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + String res; + auto& translators = getExceptionTranslators(); + for(auto& curr : translators) + if(curr->translate(res)) + return res; + // clang-format off + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") + try { + throw; + } catch(std::exception& ex) { + return ex.what(); + } catch(std::string& msg) { + return msg.c_str(); + } catch(const char* msg) { + return msg; + } catch(...) { + return "unknown exception"; + } + DOCTEST_GCC_SUPPRESS_WARNING_POP +// clang-format on +#else // DOCTEST_CONFIG_NO_EXCEPTIONS + return ""; +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + } +} // namespace + +namespace detail { + // used by the macros for registering tests + int regTest(const TestCase& tc) { + getRegisteredTests().insert(tc); + return 0; + } + + // sets the current test suite + int setTestSuite(const TestSuite& ts) { + doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; + return 0; + } + +#ifdef DOCTEST_IS_DEBUGGER_ACTIVE + bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } +#else // DOCTEST_IS_DEBUGGER_ACTIVE +#ifdef DOCTEST_PLATFORM_LINUX + class ErrnoGuard { + public: + ErrnoGuard() : m_oldErrno(errno) {} + ~ErrnoGuard() { errno = m_oldErrno; } + private: + int m_oldErrno; + }; + // See the comments in Catch2 for the reasoning behind this implementation: + // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 + bool isDebuggerActive() { + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for(std::string line; std::getline(in, line);) { + static const int PREFIX_LEN = 11; + if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + return false; + } +#elif defined(DOCTEST_PLATFORM_MAC) + // The following function is taken directly from the following technical note: + // https://developer.apple.com/library/archive/qa/qa1361/_index.html + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive() { + int mib[4]; + kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { + std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); + } +#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) + bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } +#else + bool isDebuggerActive() { return false; } +#endif // Platform +#endif // DOCTEST_IS_DEBUGGER_ACTIVE + + void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { + if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == + getExceptionTranslators().end()) + getExceptionTranslators().push_back(et); + } + + DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() + + ContextScopeBase::ContextScopeBase() { + g_infoContexts.push_back(this); + } + + ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { + if (other.need_to_destroy) { + other.destroy(); + } + other.need_to_destroy = false; + g_infoContexts.push_back(this); + } + + DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 + DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") + + // destroy cannot be inlined into the destructor because that would mean calling stringify after + // ContextScope has been destroyed (base class destructors run after derived class destructors). + // Instead, ContextScope calls this method directly from its destructor. + void ContextScopeBase::destroy() { +#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) + if(std::uncaught_exceptions() > 0) { +#else + if(std::uncaught_exception()) { +#endif + std::ostringstream s; + this->stringify(&s); + g_cs->stringifiedContexts.push_back(s.str().c_str()); + } + g_infoContexts.pop_back(); + } + + DOCTEST_CLANG_SUPPRESS_WARNING_POP + DOCTEST_GCC_SUPPRESS_WARNING_POP + DOCTEST_MSVC_SUPPRESS_WARNING_POP +} // namespace detail +namespace { + using namespace detail; + +#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) + struct FatalConditionHandler + { + static void reset() {} + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + }; +#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + + void reportFatal(const std::string&); + +#ifdef DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + DWORD id; + const char* name; + }; + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + SignalDefs signalDefs[] = { + {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), + "SIGILL - Illegal instruction signal"}, + {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast(EXCEPTION_ACCESS_VIOLATION), + "SIGSEGV - Segmentation violation signal"}, + {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, + }; + + struct FatalConditionHandler + { + static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + DOCTEST_DECLARE_STATIC_MUTEX(mutex) + static bool execute = true; + { + DOCTEST_LOCK_MUTEX(mutex) + if(execute) { + bool reported = false; + for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if(reported == false) + reportFatal("Unhandled SEH exception caught"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + } + execute = false; + } + std::exit(EXIT_FAILURE); + } + + static void allocateAltStackMem() {} + static void freeAltStackMem() {} + + FatalConditionHandler() { + isSet = true; + // 32k seems enough for doctest to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + // Register an unhandled exception filter + previousTop = SetUnhandledExceptionFilter(handleException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() DOCTEST_NOEXCEPT { + reportFatal("Terminate handler called"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { + if(signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + } + + static void reset() { + if(isSet) { + // Unregister handler and restore the old guarantee + SetUnhandledExceptionFilter(previousTop); + SetThreadStackGuarantee(&guaranteeSize); + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); + static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); + isSet = false; + } + } + + ~FatalConditionHandler() { reset(); } + + private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; + static bool isSet; + static ULONG guaranteeSize; + static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; + }; + + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; + void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; + bool FatalConditionHandler::isSet = false; + ULONG FatalConditionHandler::guaranteeSize = 0; + LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; + +#else // DOCTEST_PLATFORM_WINDOWS + + struct SignalDefs + { + int id; + const char* name; + }; + SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"}, + {SIGILL, "SIGILL - Illegal instruction signal"}, + {SIGFPE, "SIGFPE - Floating point error signal"}, + {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, + {SIGTERM, "SIGTERM - Termination request signal"}, + {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; + + struct FatalConditionHandler + { + static bool isSet; + static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; + static stack_t oldSigStack; + static size_t altStackSize; + static char* altStackMem; + + static void handleSignal(int sig) { + const char* name = ""; + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + SignalDefs& def = signalDefs[i]; + if(sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise(sig); + } + + static void allocateAltStackMem() { + altStackMem = new char[altStackSize]; + } + + static void freeAltStackMem() { + delete[] altStackMem; + } + + FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = altStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = {}; + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + ~FatalConditionHandler() { reset(); } + static void reset() { + if(isSet) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + }; + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; + char* FatalConditionHandler::altStackMem = nullptr; + +#endif // DOCTEST_PLATFORM_WINDOWS +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH + +} // namespace + +namespace { + using namespace detail; + +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) +#else + // TODO: integration with XCode and other IDEs +#define DOCTEST_OUTPUT_DEBUG_STRING(text) +#endif // Platform + + void addAssert(assertType::Enum at) { + if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsCurrentTest_atomic++; + } + + void addFailedAssert(assertType::Enum at) { + if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional + g_cs->numAssertsFailedCurrentTest_atomic++; + } + +#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) + void reportFatal(const std::string& message) { + g_cs->failure_flags |= TestCaseFailureReason::Crash; + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); + + while (g_cs->subcaseStack.size()) { + g_cs->subcaseStack.pop_back(); + DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); + } + + g_cs->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } +#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH +} // namespace + +AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const StringContains& exception_string) + : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), + m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), + m_exception_string(exception_string) { +#if DOCTEST_MSVC + if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC + ++m_expr; +#endif // MSVC +} + +namespace detail { + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const String& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, + const char* exception_type, const Contains& exception_string) + : AssertData(at, file, line, expr, exception_type, exception_string) { } + + void ResultBuilder::setResult(const Result& res) { + m_decomp = res.m_decomp; + m_failed = !res.m_passed; + } + + void ResultBuilder::translateException() { + m_threw = true; + m_exception = translateActiveException(); + } + + bool ResultBuilder::log() { + if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw; + } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT + m_failed = !m_threw_as || !m_exception_string.check(m_exception); + } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + m_failed = !m_threw_as; + } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + m_failed = !m_exception_string.check(m_exception); + } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + m_failed = m_threw; + } + + if(m_exception.size()) + m_exception = "\"" + m_exception + "\""; + + if(is_running_in_test) { + addAssert(m_at); + DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); + + if(m_failed) + addFailedAssert(m_at); + } else if(m_failed) { + failed_out_of_a_testing_context(*this); + } + + return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void ResultBuilder::react() const { + if(m_failed && checkIfShouldThrow(m_at)) + throwException(); + } + + void failed_out_of_a_testing_context(const AssertData& ad) { + if(g_cs->ah) + g_cs->ah(ad); + else + std::abort(); + } + + bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, + const Result& result) { + bool failed = !result.m_passed; + + // ################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ################################################################################### + DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); + DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + return !failed; + } + + MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { + m_stream = tlssPush(); + m_file = file; + m_line = line; + m_severity = severity; + } + + MessageBuilder::~MessageBuilder() { + if (!logged) + tlssPop(); + } + + DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) + + bool MessageBuilder::log() { + if (!logged) { + m_string = tlssPop(); + logged = true; + } + + DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); + + const bool isWarn = m_severity & assertType::is_warn; + + // warn is just a message in this context so we don't treat it as an assert + if(!isWarn) { + addAssert(m_severity); + addFailedAssert(m_severity); + } + + return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && + (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger + } + + void MessageBuilder::react() { + if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional + throwException(); + } +} // namespace detail +namespace { + using namespace detail; + + // clang-format off + +// ================================================================================================= +// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp +// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. +// ================================================================================================= + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + + void encodeTo( std::ostream& os ) const; + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ); + + ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT; + ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT; + + ~ScopedElement(); + + ScopedElement& writeText( std::string const& text, bool indent = true ); + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer = nullptr; + }; + +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter( std::ostream& os = std::cout ); +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + XmlWriter( std::ostream& os ); +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + ~XmlWriter(); + + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; + + XmlWriter& startElement( std::string const& name ); + + ScopedElement scopedElement( std::string const& name ); + + XmlWriter& endElement(); + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + + XmlWriter& writeAttribute( std::string const& name, const char* attribute ); + + XmlWriter& writeAttribute( std::string const& name, bool attribute ); + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + std::stringstream rss; + rss << attribute; + return writeAttribute( name, rss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ); + + //XmlWriter& writeComment( std::string const& text ); + + //void writeStylesheetRef( std::string const& url ); + + //XmlWriter& writeBlankLine(); + + void ensureTagClosed(); + + void writeDeclaration(); + + private: + + void newlineIfNecessary(); + + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + }; + +// ================================================================================================= +// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp +// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. +// ================================================================================================= + +using uchar = unsigned char; + +namespace { + + size_t trailingBytes(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return 2; + } + if ((c & 0xF0) == 0xE0) { + return 3; + } + if ((c & 0xF8) == 0xF0) { + return 4; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + uint32_t headerValue(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return c & 0x1F; + } + if ((c & 0xF0) == 0xE0) { + return c & 0x0F; + } + if ((c & 0xF8) == 0xF0) { + return c & 0x07; + } + DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + void hexEscapeChar(std::ostream& os, unsigned char c) { + std::ios_base::fmtflags f(os.flags()); + os << "\\x" + << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast(c); + os.flags(f); + } + +} // anonymous namespace + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: https://www.w3.org/TR/xml/#syntax) + + for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { + uchar c = m_str[idx]; + switch (c) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: https://www.w3.org/TR/xml/#syntax + if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') + os << ">"; + else + os << c; + break; + + case '\"': + if (m_forWhat == ForAttributes) + os << """; + else + os << c; + break; + + default: + // Check for control characters and invalid utf-8 + + // Escape control characters in standard ascii + // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { + hexEscapeChar(os, c); + break; + } + + // Plain ASCII: Write it to stream + if (c < 0x7F) { + os << c; + break; + } + + // UTF-8 territory + // Check if the encoding is valid and if it is not, hex escape bytes. + // Important: We do not check the exact decoded values for validity, only the encoding format + // First check that this bytes is a valid lead byte: + // This means that it is not encoded as 1111 1XXX + // Or as 10XX XXXX + if (c < 0xC0 || + c >= 0xF8) { + hexEscapeChar(os, c); + break; + } + + auto encBytes = trailingBytes(c); + // Are there enough bytes left to avoid accessing out-of-bounds memory? + if (idx + encBytes - 1 >= m_str.size()) { + hexEscapeChar(os, c); + break; + } + // The header is valid, check data + // The next encBytes bytes must together be a valid utf-8 + // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) + bool valid = true; + uint32_t value = headerValue(c); + for (std::size_t n = 1; n < encBytes; ++n) { + uchar nc = m_str[idx + n]; + valid &= ((nc & 0xC0) == 0x80); + value = (value << 6) | (nc & 0x3F); + } + + if ( + // Wrong bit pattern of following bytes + (!valid) || + // Overlong encodings + (value < 0x80) || + ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant + (0x800 < value && value < 0x10000 && encBytes > 3) || + // Encoded value out of range + (value >= 0x110000) + ) { + hexEscapeChar(os, c); + break; + } + + // If we got here, this is in fact a valid(ish) utf-8 sequence + for (std::size_t n = 0; n < encBytes; ++n) { + os << m_str[idx + n]; + } + idx += encBytes - 1; + break; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627 + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) { + if( !name.empty() && attribute && attribute[0] != '\0' ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + //XmlWriter& XmlWriter::writeComment( std::string const& text ) { + // ensureTagClosed(); + // m_os << m_indent << ""; + // m_needsNewline = true; + // return *this; + //} + + //void XmlWriter::writeStylesheetRef( std::string const& url ) { + // m_os << "\n"; + //} + + //XmlWriter& XmlWriter::writeBlankLine() { + // ensureTagClosed(); + // m_os << '\n'; + // return *this; + //} + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } + +// ================================================================================================= +// End of copy-pasted code from Catch +// ================================================================================================= + + // clang-format on + + struct XmlReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + XmlReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + std::stringstream ss; + for(int i = 0; i < num_contexts; ++i) { + contexts[i]->stringify(&ss); + xml.scopedElement("Info").writeText(ss.str()); + ss.str(""); + } + } + } + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + void test_case_start_impl(const TestCaseData& in) { + bool open_ts_tag = false; + if(tc != nullptr) { // we have already opened a test suite + if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { + xml.endElement(); + open_ts_tag = true; + } + } + else { + open_ts_tag = true; // first test case ==> first test suite + } + + if(open_ts_tag) { + xml.startElement("TestSuite"); + xml.writeAttribute("name", in.m_test_suite); + } + + tc = ∈ + xml.startElement("TestCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) + .writeAttribute("line", line(in.m_line)) + .writeAttribute("description", in.m_description); + + if(Approx(in.m_timeout) != 0) + xml.writeAttribute("timeout", in.m_timeout); + if(in.m_may_fail) + xml.writeAttribute("may_fail", true); + if(in.m_should_fail) + xml.writeAttribute("should_fail", true); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + test_run_start(); + if(opt.list_reporters) { + for(auto& curr : getListeners()) + xml.scopedElement("Listener") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + for(auto& curr : getReporters()) + xml.scopedElement("Reporter") + .writeAttribute("priority", curr.first.first) + .writeAttribute("name", curr.first.second); + } else if(opt.count || opt.list_test_cases) { + for(unsigned i = 0; i < in.num_data; ++i) { + xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) + .writeAttribute("testsuite", in.data[i]->m_test_suite) + .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) + .writeAttribute("line", line(in.data[i]->m_line)) + .writeAttribute("skipped", in.data[i]->m_skip); + } + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + } else if(opt.list_test_suites) { + for(unsigned i = 0; i < in.num_data; ++i) + xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); + xml.scopedElement("OverallResultsTestCases") + .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); + xml.scopedElement("OverallResultsTestSuites") + .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); + } + xml.endElement(); + } + + void test_run_start() override { + xml.writeDeclaration(); + + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if(binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + + xml.startElement("doctest").writeAttribute("binary", binary_name); + if(opt.no_version == false) + xml.writeAttribute("version", DOCTEST_VERSION_STR); + + // only the consequential ones (TODO: filters) + xml.scopedElement("Options") + .writeAttribute("order_by", opt.order_by.c_str()) + .writeAttribute("rand_seed", opt.rand_seed) + .writeAttribute("first", opt.first) + .writeAttribute("last", opt.last) + .writeAttribute("abort_after", opt.abort_after) + .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) + .writeAttribute("case_sensitive", opt.case_sensitive) + .writeAttribute("no_throw", opt.no_throw) + .writeAttribute("no_skip", opt.no_skip); + } + + void test_run_end(const TestRunStats& p) override { + if(tc) // the TestSuite tag - only if there has been at least 1 test case + xml.endElement(); + + xml.scopedElement("OverallResultsAsserts") + .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) + .writeAttribute("failures", p.numAssertsFailed); + + xml.startElement("OverallResultsTestCases") + .writeAttribute("successes", + p.numTestCasesPassingFilters - p.numTestCasesFailed) + .writeAttribute("failures", p.numTestCasesFailed); + if(opt.no_skipped_summary == false) + xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); + xml.endElement(); + + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + test_case_start_impl(in); + xml.ensureTagClosed(); + } + + void test_case_reenter(const TestCaseData&) override {} + + void test_case_end(const CurrentTestCaseStats& st) override { + xml.startElement("OverallResultsAsserts") + .writeAttribute("successes", + st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) + .writeAttribute("failures", st.numAssertsFailedCurrentTest) + .writeAttribute("test_case_success", st.testCaseSuccess); + if(opt.duration) + xml.writeAttribute("duration", st.seconds); + if(tc->m_expected_failures) + xml.writeAttribute("expected_failures", tc->m_expected_failures); + xml.endElement(); + + xml.endElement(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.scopedElement("Exception") + .writeAttribute("crash", e.is_crash) + .writeText(e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + xml.startElement("SubCase") + .writeAttribute("name", in.m_name) + .writeAttribute("filename", skipPathFromFilename(in.m_file)) + .writeAttribute("line", line(in.m_line)); + xml.ensureTagClosed(); + } + + void subcase_end() override { xml.endElement(); } + + void log_assert(const AssertData& rb) override { + if(!rb.m_failed && !opt.success) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Expression") + .writeAttribute("success", !rb.m_failed) + .writeAttribute("type", assertString(rb.m_at)) + .writeAttribute("filename", skipPathFromFilename(rb.m_file)) + .writeAttribute("line", line(rb.m_line)); + + xml.scopedElement("Original").writeText(rb.m_expr); + + if(rb.m_threw) + xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); + + if(rb.m_at & assertType::is_throws_as) + xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); + if(rb.m_at & assertType::is_throws_with) + xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); + if((rb.m_at & assertType::is_normal) && !rb.m_threw) + xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void log_message(const MessageData& mb) override { + DOCTEST_LOCK_MUTEX(mutex) + + xml.startElement("Message") + .writeAttribute("type", failureString(mb.m_severity)) + .writeAttribute("filename", skipPathFromFilename(mb.m_file)) + .writeAttribute("line", line(mb.m_line)); + + xml.scopedElement("Text").writeText(mb.m_string.c_str()); + + log_contexts(); + + xml.endElement(); + } + + void test_case_skipped(const TestCaseData& in) override { + if(opt.no_skipped_summary == false) { + test_case_start_impl(in); + xml.writeAttribute("skipped", "true"); + xml.endElement(); + } + } + }; + + DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); + + void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { + if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == + 0) //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " + << Color::None; + + if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; + } else if((rb.m_at & assertType::is_throws_as) && + (rb.m_at & assertType::is_throws_with)) { //!OCLINT + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\", " << rb.m_exception_type << " ) " << Color::None; + if(rb.m_threw) { + if(!rb.m_failed) { + s << "threw as expected!\n"; + } else { + s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; + } + } else { + s << "did NOT throw at all!\n"; + } + } else if(rb.m_at & + assertType::is_throws_as) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " + << rb.m_exception_type << " ) " << Color::None + << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & + assertType::is_throws_with) { //!OCLINT bitwise operator in conditional + s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" + << rb.m_exception_string.c_str() + << "\" ) " << Color::None + << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : + "threw a DIFFERENT exception: ") : + "did NOT throw at all!") + << Color::Cyan << rb.m_exception << "\n"; + } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional + s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan + << rb.m_exception << "\n"; + } else { + s << (rb.m_threw ? "THREW exception: " : + (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); + if(rb.m_threw) + s << rb.m_exception << "\n"; + else + s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; + } + } + + // TODO: + // - log_message() + // - respond to queries + // - honor remaining options + // - more attributes in tags + struct JUnitReporter : public IReporter + { + XmlWriter xml; + DOCTEST_DECLARE_MUTEX(mutex) + Timer timer; + std::vector deepestSubcaseStackNames; + + struct JUnitTestCaseData + { + static std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS + + char timeStamp[timeStampSize]; + const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; + + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); + return std::string(timeStamp); + } + + struct JUnitTestMessage + { + JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) + : message(_message), type(_type), details(_details) {} + + JUnitTestMessage(const std::string& _message, const std::string& _details) + : message(_message), type(), details(_details) {} + + std::string message, type, details; + }; + + struct JUnitTestCase + { + JUnitTestCase(const std::string& _classname, const std::string& _name) + : classname(_classname), name(_name), time(0), failures() {} + + std::string classname, name; + double time; + std::vector failures, errors; + }; + + void add(const std::string& classname, const std::string& name) { + testcases.emplace_back(classname, name); + } + + void appendSubcaseNamesToLastTestcase(std::vector nameStack) { + for(auto& curr: nameStack) + if(curr.size()) + testcases.back().name += std::string("/") + curr.c_str(); + } + + void addTime(double time) { + if(time < 1e-4) + time = 0; + testcases.back().time = time; + totalSeconds += time; + } + + void addFailure(const std::string& message, const std::string& type, const std::string& details) { + testcases.back().failures.emplace_back(message, type, details); + ++totalFailures; + } + + void addError(const std::string& message, const std::string& details) { + testcases.back().errors.emplace_back(message, details); + ++totalErrors; + } + + std::vector testcases; + double totalSeconds = 0; + int totalErrors = 0, totalFailures = 0; + }; + + JUnitTestCaseData testCaseData; + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc = nullptr; + + JUnitReporter(const ContextOptions& co) + : xml(*co.cout) + , opt(co) {} + + unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData&) override { + xml.writeDeclaration(); + } + + void test_run_start() override { + xml.writeDeclaration(); + } + + void test_run_end(const TestRunStats& p) override { + // remove .exe extension - mainly to have the same output on UNIX and Windows + std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); +#ifdef DOCTEST_PLATFORM_WINDOWS + if(binary_name.rfind(".exe") != std::string::npos) + binary_name = binary_name.substr(0, binary_name.length() - 4); +#endif // DOCTEST_PLATFORM_WINDOWS + xml.startElement("testsuites"); + xml.startElement("testsuite").writeAttribute("name", binary_name) + .writeAttribute("errors", testCaseData.totalErrors) + .writeAttribute("failures", testCaseData.totalFailures) + .writeAttribute("tests", p.numAsserts); + if(opt.no_time_in_output == false) { + xml.writeAttribute("time", testCaseData.totalSeconds); + xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); + } + if(opt.no_version == false) + xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); + + for(const auto& testCase : testCaseData.testcases) { + xml.startElement("testcase") + .writeAttribute("classname", testCase.classname) + .writeAttribute("name", testCase.name); + if(opt.no_time_in_output == false) + xml.writeAttribute("time", testCase.time); + // This is not ideal, but it should be enough to mimic gtest's junit output. + xml.writeAttribute("status", "run"); + + for(const auto& failure : testCase.failures) { + xml.scopedElement("failure") + .writeAttribute("message", failure.message) + .writeAttribute("type", failure.type) + .writeText(failure.details, false); + } + + for(const auto& error : testCase.errors) { + xml.scopedElement("error") + .writeAttribute("message", error.message) + .writeText(error.details); + } + + xml.endElement(); + } + xml.endElement(); + xml.endElement(); + } + + void test_case_start(const TestCaseData& in) override { + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + timer.start(); + } + + void test_case_reenter(const TestCaseData& in) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + + timer.start(); + testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); + } + + void test_case_end(const CurrentTestCaseStats&) override { + testCaseData.addTime(timer.getElapsedSeconds()); + testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); + deepestSubcaseStackNames.clear(); + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + testCaseData.addError("exception", e.error_string.c_str()); + } + + void subcase_start(const SubcaseSignature& in) override { + deepestSubcaseStackNames.push_back(in.m_name); + } + + void subcase_end() override {} + + void log_assert(const AssertData& rb) override { + if(!rb.m_failed) // report only failures & ignore the `success` option + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + fulltext_log_assert_to_stream(os, rb); + log_contexts(os); + testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); + } + + void log_message(const MessageData& mb) override { + if(mb.m_severity & assertType::is_warn) // report only failures + return; + + DOCTEST_LOCK_MUTEX(mutex) + + std::ostringstream os; + os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") + << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; + + os << mb.m_string.c_str() << "\n"; + log_contexts(os); + + testCaseData.addFailure(mb.m_string.c_str(), + mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); + } + + void test_case_skipped(const TestCaseData&) override {} + + void log_contexts(std::ostringstream& s) { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } + }; + + DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); + + struct Whitespace + { + int nrSpaces; + explicit Whitespace(int nr) + : nrSpaces(nr) {} + }; + + std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { + if(ws.nrSpaces != 0) + out << std::setw(ws.nrSpaces) << ' '; + return out; + } + + struct ConsoleReporter : public IReporter + { + std::ostream& s; + bool hasLoggedCurrentTestStart; + std::vector subcasesStack; + size_t currentSubcaseLevel; + DOCTEST_DECLARE_MUTEX(mutex) + + // caching pointers/references to objects of these types - safe to do + const ContextOptions& opt; + const TestCaseData* tc; + + ConsoleReporter(const ContextOptions& co) + : s(*co.cout) + , opt(co) {} + + ConsoleReporter(const ContextOptions& co, std::ostream& ostr) + : s(ostr) + , opt(co) {} + + // ========================================================================================= + // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE + // ========================================================================================= + + void separator_to_stream() { + s << Color::Yellow + << "===============================================================================" + "\n"; + } + + const char* getSuccessOrFailString(bool success, assertType::Enum at, + const char* success_str) { + if(success) + return success_str; + return failureString(at); + } + + Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { + return success ? Color::BrightGreen : + (at & assertType::is_warn) ? Color::Yellow : Color::Red; + } + + void successOrFailColoredStringToStream(bool success, assertType::Enum at, + const char* success_str = "SUCCESS") { + s << getSuccessOrFailColor(success, at) + << getSuccessOrFailString(success, at, success_str) << ": "; + } + + void log_contexts() { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << Color::None << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << "\n"; + } + } + + s << "\n"; + } + + // this was requested to be made virtual so users could override it + virtual void file_line_to_stream(const char* file, int line, + const char* tail = "") { + s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") + << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option + << (opt.gnu_file_line ? ":" : "):") << tail; + } + + void logTestStart() { + if(hasLoggedCurrentTestStart) + return; + + separator_to_stream(); + file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); + if(tc->m_description) + s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; + if(tc->m_test_suite && tc->m_test_suite[0] != '\0') + s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; + if(strncmp(tc->m_name, " Scenario:", 11) != 0) + s << Color::Yellow << "TEST CASE: "; + s << Color::None << tc->m_name << "\n"; + + for(size_t i = 0; i < currentSubcaseLevel; ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + + if(currentSubcaseLevel != subcasesStack.size()) { + s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; + for(size_t i = 0; i < subcasesStack.size(); ++i) { + if(subcasesStack[i].m_name[0] != '\0') + s << " " << subcasesStack[i].m_name << "\n"; + } + } + + s << "\n"; + + hasLoggedCurrentTestStart = true; + } + + void printVersion() { + if(opt.no_version == false) + s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" + << DOCTEST_VERSION_STR << "\"\n"; + } + + void printIntro() { + if(opt.no_intro == false) { + printVersion(); + s << Color::Cyan << "[doctest] " << Color::None + << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; + } + } + + void printHelp() { + int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); + printVersion(); + // clang-format off + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filter values: \"str1,str2,str3\" (comma separated strings)\n"; + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "filters use wildcards for matching strings\n"; + s << Color::Cyan << "[doctest] " << Color::None; + s << "something passes a filter if any of the strings in a filter matches\n"; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n"; +#endif + s << Color::Cyan << "[doctest]\n" << Color::None; + s << Color::Cyan << "[doctest] " << Color::None; + s << "Query flags - the program quits after them. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h " + << Whitespace(sizePrefixDisplay*0) << "prints this message\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version " + << Whitespace(sizePrefixDisplay*1) << "prints the version\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count " + << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases " + << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites " + << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters " + << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n"; + // ================================================================================== << 79 + s << Color::Cyan << "[doctest] " << Color::None; + s << "The available / options/filters are:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite= " + << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase= " + << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude= " + << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters= " + << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out= " + << Whitespace(sizePrefixDisplay*1) << "output filename\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " + << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; + s << Whitespace(sizePrefixDisplay*3) << " - [file/suite/name/rand/none]\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " + << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " + << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last= " + << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n"; + s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after= " + << Whitespace(sizePrefixDisplay*1) << "stop after failed assertions\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels= " + << Whitespace(sizePrefixDisplay*1) << "apply filters for the first levels\n"; + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "Bool options - can be used like flags and true is assumed. Available:\n\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success= " + << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive= " + << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit= " + << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " + << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " + << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " + << Whitespace(sizePrefixDisplay*1) << "no console output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " + << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " + << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " + << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " + << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " + << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " + << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors= " + << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks= " + << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip= " + << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line= " + << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames= " + << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n"; + s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " + << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; + // ================================================================================== << 79 + // clang-format on + + s << Color::Cyan << "\n[doctest] " << Color::None; + s << "for more information visit the project documentation\n\n"; + } + + void printRegisteredReporters() { + printVersion(); + auto printReporters = [this] (const reporterMap& reporters, const char* type) { + if(reporters.size()) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; + for(auto& curr : reporters) + s << "priority: " << std::setw(5) << curr.first.first + << " name: " << curr.first.second << "\n"; + } + }; + printReporters(getListeners(), "listeners"); + printReporters(getReporters(), "reporters"); + } + + // ========================================================================================= + // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE + // ========================================================================================= + + void report_query(const QueryData& in) override { + if(opt.version) { + printVersion(); + } else if(opt.help) { + printHelp(); + } else if(opt.list_reporters) { + printRegisteredReporters(); + } else if(opt.count || opt.list_test_cases) { + if(opt.list_test_cases) { + s << Color::Cyan << "[doctest] " << Color::None + << "listing all test case names\n"; + separator_to_stream(); + } + + for(unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_name << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + + } else if(opt.list_test_suites) { + s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; + separator_to_stream(); + + for(unsigned i = 0; i < in.num_data; ++i) + s << Color::None << in.data[i]->m_test_suite << "\n"; + + separator_to_stream(); + + s << Color::Cyan << "[doctest] " << Color::None + << "unskipped test cases passing the current filters: " + << g_cs->numTestCasesPassingFilters << "\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "test suites with unskipped test cases passing the current filters: " + << g_cs->numTestSuitesPassingFilters << "\n"; + } + } + + void test_run_start() override { + if(!opt.minimal) + printIntro(); + } + + void test_run_end(const TestRunStats& p) override { + if(opt.minimal && p.numTestCasesFailed == 0) + return; + + separator_to_stream(); + s << std::dec; + + auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); + auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); + auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); + const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; + s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) + << p.numTestCasesPassingFilters << " | " + << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : + Color::Green) + << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" + << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) + << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; + if(opt.no_skipped_summary == false) { + const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; + s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped + << " skipped" << Color::None; + } + s << "\n"; + s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) + << p.numAsserts << " | " + << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) + << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None + << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) + << p.numAssertsFailed << " failed" << Color::None << " |\n"; + s << Color::Cyan << "[doctest] " << Color::None + << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) + << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; + } + + void test_case_start(const TestCaseData& in) override { + hasLoggedCurrentTestStart = false; + tc = ∈ + subcasesStack.clear(); + currentSubcaseLevel = 0; + } + + void test_case_reenter(const TestCaseData&) override { + subcasesStack.clear(); + } + + void test_case_end(const CurrentTestCaseStats& st) override { + if(tc->m_no_output) + return; + + // log the preamble of the test case only if there is something + // else to print - something other than that an assert has failed + if(opt.duration || + (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) + logTestStart(); + + if(opt.duration) + s << Color::None << std::setprecision(6) << std::fixed << st.seconds + << " s: " << tc->m_name << "\n"; + + if(st.failure_flags & TestCaseFailureReason::Timeout) + s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) + << std::fixed << tc->m_timeout << "!\n"; + + if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { + s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; + } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { + s << Color::Yellow << "Failed as expected so marking it as not failed\n"; + } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { + s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; + } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { + s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures + << " times so marking it as failed!\n"; + } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { + s << Color::Yellow << "Failed exactly " << tc->m_expected_failures + << " times as expected so marking it as not failed!\n"; + } + if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { + s << Color::Red << "Aborting - too many failed asserts!\n"; + } + s << Color::None; // lgtm [cpp/useless-expression] + } + + void test_case_exception(const TestCaseException& e) override { + DOCTEST_LOCK_MUTEX(mutex) + if(tc->m_no_output) + return; + + logTestStart(); + + file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); + successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : + assertType::is_check); + s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") + << Color::Cyan << e.error_string << "\n"; + + int num_stringified_contexts = get_num_stringified_contexts(); + if(num_stringified_contexts) { + auto stringified_contexts = get_stringified_contexts(); + s << Color::None << " logged: "; + for(int i = num_stringified_contexts; i > 0; --i) { + s << (i == num_stringified_contexts ? "" : " ") + << stringified_contexts[i - 1] << "\n"; + } + } + s << "\n" << Color::None; + } + + void subcase_start(const SubcaseSignature& subc) override { + subcasesStack.push_back(subc); + ++currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void subcase_end() override { + --currentSubcaseLevel; + hasLoggedCurrentTestStart = false; + } + + void log_assert(const AssertData& rb) override { + if((!rb.m_failed && !opt.success) || tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(rb.m_file, rb.m_line, " "); + successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); + + fulltext_log_assert_to_stream(s, rb); + + log_contexts(); + } + + void log_message(const MessageData& mb) override { + if(tc->m_no_output) + return; + + DOCTEST_LOCK_MUTEX(mutex) + + logTestStart(); + + file_line_to_stream(mb.m_file, mb.m_line, " "); + s << getSuccessOrFailColor(false, mb.m_severity) + << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, + "MESSAGE") << ": "; + s << Color::None << mb.m_string << "\n"; + log_contexts(); + } + + void test_case_skipped(const TestCaseData&) override {} + }; + + DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); + +#ifdef DOCTEST_PLATFORM_WINDOWS + struct DebugOutputWindowReporter : public ConsoleReporter + { + DOCTEST_THREAD_LOCAL static std::ostringstream oss; + + DebugOutputWindowReporter(const ContextOptions& co) + : ConsoleReporter(co, oss) {} + +#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ + void func(type arg) override { \ + bool with_col = g_no_colors; \ + g_no_colors = false; \ + ConsoleReporter::func(arg); \ + if(oss.tellp() != std::streampos{}) { \ + DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ + oss.str(""); \ + } \ + g_no_colors = with_col; \ + } + + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) + DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) + }; + + DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; +#endif // DOCTEST_PLATFORM_WINDOWS + + // the implementation of parseOption() + bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { + // going from the end to the beginning and stopping on the first occurrence from the end + for(int i = argc; i > 0; --i) { + auto index = i - 1; + auto temp = std::strstr(argv[index], pattern); + if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + auto curr = argv[index]; + while(curr != temp) { + if(*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if(noBadCharsFound && argv[index][0] == '-') { + if(value) { + // parsing the value of an option + temp += strlen(pattern); + const unsigned len = strlen(temp); + if(len) { + *value = temp; + return true; + } + } else { + // just a flag - no value + return true; + } + } + } + } + return false; + } + + // parses an option and returns the string after the '=' character + bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, + const String& defaultVal = String()) { + if(value) + *value = defaultVal; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + // offset (normally 3 for "dt-") to skip prefix + if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) + return true; +#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + return parseOptionImpl(argc, argv, pattern, value); + } + + // locates a flag on the command line + bool parseFlag(int argc, const char* const* argv, const char* pattern) { + return parseOption(argc, argv, pattern); + } + + // parses a comma separated list of words after a pattern in one of the arguments in argv + bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, + std::vector& res) { + String filtersString; + if(parseOption(argc, argv, pattern, &filtersString)) { + // tokenize with "," as a separator, unless escaped with backslash + std::ostringstream s; + auto flush = [&s, &res]() { + auto string = s.str(); + if(string.size() > 0) { + res.push_back(string.c_str()); + } + s.str(""); + }; + + bool seenBackslash = false; + const char* current = filtersString.c_str(); + const char* end = current + strlen(current); + while(current != end) { + char character = *current++; + if(seenBackslash) { + seenBackslash = false; + if(character == ',' || character == '\\') { + s.put(character); + continue; + } + s.put('\\'); + } + if(character == '\\') { + seenBackslash = true; + } else if(character == ',') { + flush(); + } else { + s.put(character); + } + } + + if(seenBackslash) { + s.put('\\'); + } + flush(); + return true; + } + return false; + } + + enum optionType + { + option_bool, + option_int + }; + + // parses an int/bool option from the command line + bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, + int& res) { + String parsedValue; + if(!parseOption(argc, argv, pattern, &parsedValue)) + return false; + + if(type) { + // integer + // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... + int theInt = std::atoi(parsedValue.c_str()); + if (theInt != 0) { + res = theInt; //!OCLINT parameter reassignment + return true; + } + } else { + // boolean + const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 + const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for (unsigned i = 0; i < 4; i++) { + if (parsedValue.compare(positive[i], true) == 0) { + res = 1; //!OCLINT parameter reassignment + return true; + } + if (parsedValue.compare(negative[i], true) == 0) { + res = 0; //!OCLINT parameter reassignment + return true; + } + } + } + return false; + } +} // namespace + +Context::Context(int argc, const char* const* argv) + : p(new detail::ContextState) { + parseArgs(argc, argv, true); + if(argc) + p->binary_name = argv[0]; +} + +Context::~Context() { + if(g_cs == p) + g_cs = nullptr; + delete p; +} + +void Context::applyCommandLine(int argc, const char* const* argv) { + parseArgs(argc, argv); + if(argc) + p->binary_name = argv[0]; +} + +// parses args +void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + using namespace detail; + + // clang-format off + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]); + parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]); + // clang-format on + + int intRes = 0; + String strRes; + +#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ + p->var = static_cast(intRes); \ + else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ + p->var = true; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ + p->var = intRes; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ + if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ + parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ + withDefaults) \ + p->var = strRes + + // clang-format off + DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); + DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file"); + DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0); + + DOCTEST_PARSE_INT_OPTION("first", "f", first, 0); + DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX); + + DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0); + DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX); + + DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); + // clang-format on + + if(withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + p->list_reporters = false; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { + p->help = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { + p->version = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { + p->count = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { + p->list_test_suites = true; + p->exit = true; + } + if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || + parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { + p->list_reporters = true; + p->exit = true; + } +} + +// allows the user to add procedurally to the filters from the command line +void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + +// allows the user to clear all filters from the command line +void Context::clearFilters() { + for(auto& curr : p->filters) + curr.clear(); +} + +// allows the user to override procedurally the bool options from the command line +void Context::setOption(const char* option, bool value) { + setOption(option, value ? "true" : "false"); +} + +// allows the user to override procedurally the int options from the command line +void Context::setOption(const char* option, int value) { + setOption(option, toString(value).c_str()); +} + +// allows the user to override procedurally the string options from the command line +void Context::setOption(const char* option, const char* value) { + auto argv = String("-") + option + "=" + value; + auto lvalue = argv.c_str(); + parseArgs(1, &lvalue); +} + +// users should query this in their main() and exit the program if true +bool Context::shouldExit() { return p->exit; } + +void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } + +void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } + +void Context::setCout(std::ostream* out) { p->cout = out; } + +static class DiscardOStream : public std::ostream +{ +private: + class : public std::streambuf + { + private: + // allowing some buffering decreases the amount of calls to overflow + char buf[1024]; + + protected: + std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } + + int_type overflow(int_type ch) override { + setp(std::begin(buf), std::end(buf)); + return traits_type::not_eof(ch); + } + } discardBuf; + +public: + DiscardOStream() + : std::ostream(&discardBuf) {} +} discardOut; + +// the main function that does all the filtering and test running +int Context::run() { + using namespace detail; + + // save the old context state in case such was setup - for using asserts out of a testing context + auto old_cs = g_cs; + // this is the current contest + g_cs = p; + is_running_in_test = true; + + g_no_colors = p->no_colors; + p->resetRunData(); + + std::fstream fstr; + if(p->cout == nullptr) { + if(p->quiet) { + p->cout = &discardOut; + } else if(p->out.size()) { + // to a file if specified + fstr.open(p->out.c_str(), std::fstream::out); + p->cout = &fstr; + } else { +#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + // stdout by default + p->cout = &std::cout; +#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + return EXIT_FAILURE; +#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM + } + } + + FatalConditionHandler::allocateAltStackMem(); + + auto cleanup_and_return = [&]() { + FatalConditionHandler::freeAltStackMem(); + + if(fstr.is_open()) + fstr.close(); + + // restore context + g_cs = old_cs; + is_running_in_test = false; + + // we have to free the reporters which were allocated when the run started + for(auto& curr : p->reporters_currently_used) + delete curr; + p->reporters_currently_used.clear(); + + if(p->numTestCasesFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; + }; + + // setup default reporter if none is given through the command line + if(p->filters[8].empty()) + p->filters[8].push_back("console"); + + // check to see if any of the registered reporters has been selected + for(auto& curr : getReporters()) { + if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) + p->reporters_currently_used.push_back(curr.second(*g_cs)); + } + + // TODO: check if there is nothing in reporters_currently_used + + // prepend all listeners + for(auto& curr : getListeners()) + p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); + +#ifdef DOCTEST_PLATFORM_WINDOWS + if(isDebuggerActive() && p->no_debug_output == false) + p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); +#endif // DOCTEST_PLATFORM_WINDOWS + + // handle version, help and no_run + if(p->no_run || p->version || p->help || p->list_reporters) { + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); + + return cleanup_and_return(); + } + + std::vector testArray; + for(auto& curr : getRegisteredTests()) + testArray.push_back(&curr); + p->numTestCases = testArray.size(); + + // sort the collected records + if(!testArray.empty()) { + if(p->order_by.compare("file", true) == 0) { + std::sort(testArray.begin(), testArray.end(), fileOrderComparator); + } else if(p->order_by.compare("suite", true) == 0) { + std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); + } else if(p->order_by.compare("name", true) == 0) { + std::sort(testArray.begin(), testArray.end(), nameOrderComparator); + } else if(p->order_by.compare("rand", true) == 0) { + std::srand(p->rand_seed); + + // random_shuffle implementation + const auto first = &testArray[0]; + for(size_t i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = std::rand() % (i + 1); + + const auto temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } else if(p->order_by.compare("none", true) == 0) { + // means no sorting - beneficial for death tests which call into the executable + // with a specific test case in mind - we don't want to slow down the startup times + } + } + + std::set testSuitesPassingFilt; + + bool query_mode = p->count || p->list_test_cases || p->list_test_suites; + std::vector queryResults; + + if(!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); + + // invoke the registered functions if they match the filter criteria (or just count them) + for(auto& curr : testArray) { + const auto& tc = *curr; + + bool skip_me = false; + if(tc.m_skip && !p->no_skip) + skip_me = true; + + if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) + skip_me = true; + if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) + skip_me = true; + if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) + skip_me = true; + if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) + skip_me = true; + + if(!skip_me) + p->numTestCasesPassingFilters++; + + // skip the test if it is not in the execution range + if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || + (p->first > p->numTestCasesPassingFilters)) + skip_me = true; + + if(skip_me) { + if(!query_mode) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); + continue; + } + + // do not execute the test if we are to only count the number of filter passing tests + if(p->count) + continue; + + // print the name of the test and don't execute it + if(p->list_test_cases) { + queryResults.push_back(&tc); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if(p->list_test_suites) { + if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { + queryResults.push_back(&tc); + testSuitesPassingFilt.insert(tc.m_test_suite); + p->numTestSuitesPassingFilters++; + } + continue; + } + + // execute the test if it passes all the filtering + { + p->currentTest = &tc; + + p->failure_flags = TestCaseFailureReason::None; + p->seconds = 0; + + // reset atomic counters + p->numAssertsFailedCurrentTest_atomic = 0; + p->numAssertsCurrentTest_atomic = 0; + + p->fullyTraversedSubcases.clear(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); + + p->timer.start(); + + bool run_test = true; + + do { + // reset some of the fields for subcases (except for the set of fully passed ones) + p->reachedLeaf = false; + // May not be empty if previous subcase exited via exception. + p->subcaseStack.clear(); + p->currentSubcaseDepth = 0; + + p->shouldLogCurrentException = true; + + // reset stuff for logging with INFO() + p->stringifiedContexts.clear(); + +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + try { +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS +// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable + FatalConditionHandler fatalConditionHandler; // Handle signals + // execute the test + tc.m_test(); + fatalConditionHandler.reset(); +DOCTEST_MSVC_SUPPRESS_WARNING_POP +#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS + } catch(const TestFailureException&) { + p->failure_flags |= TestCaseFailureReason::AssertFailure; + } catch(...) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, + {translateActiveException(), false}); + p->failure_flags |= TestCaseFailureReason::Exception; + } +#endif // DOCTEST_CONFIG_NO_EXCEPTIONS + + // exit this loop if enough assertions have failed - even if there are more subcases + if(p->abort_after > 0 && + p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { + run_test = false; + p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; + } + + if(!p->nextSubcaseStack.empty() && run_test) + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); + if(p->nextSubcaseStack.empty()) + run_test = false; + } while(run_test); + + p->finalizeTestCaseData(); + + DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); + + p->currentTest = nullptr; + + // stop executing tests if enough assertions have failed + if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) + break; + } + } + + if(!query_mode) { + DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); + } else { + QueryData qdata; + qdata.run_stats = g_cs; + qdata.data = queryResults.data(); + qdata.num_data = unsigned(queryResults.size()); + DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); + } + + return cleanup_and_return(); +} + +DOCTEST_DEFINE_INTERFACE(IReporter) + +int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } +const IContextScope* const* IReporter::get_active_contexts() { + return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; +} + +int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } +const String* IReporter::get_stringified_contexts() { + return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; +} + +namespace detail { + void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { + if(isReporter) + getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + else + getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); + } +} // namespace detail + +} // namespace doctest + +#endif // DOCTEST_CONFIG_DISABLE + +#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 +int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +DOCTEST_MSVC_SUPPRESS_WARNING_POP +#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN + +DOCTEST_CLANG_SUPPRESS_WARNING_POP +DOCTEST_MSVC_SUPPRESS_WARNING_POP +DOCTEST_GCC_SUPPRESS_WARNING_POP + +DOCTEST_SUPPRESS_COMMON_WARNINGS_POP + +#endif // DOCTEST_LIBRARY_IMPLEMENTATION +#endif // DOCTEST_CONFIG_IMPLEMENT + +#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#undef WIN32_LEAN_AND_MEAN +#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN +#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN + +#ifdef DOCTEST_UNDEF_NOMINMAX +#undef NOMINMAX +#undef DOCTEST_UNDEF_NOMINMAX +#endif // DOCTEST_UNDEF_NOMINMAX From 7c610137d49b0b332b0e2c17564f8b1eefc28236 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Wed, 7 Aug 2024 13:40:24 +0300 Subject: [PATCH 07/32] changes in array and stack --- Storage/Disk_Mng_Master.c | 23 ++++++++++++++ Storage/Disk_Mng_Master.h | 8 ++++- Storage/Doctest.cpp | 66 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index a67b901..8dc592d 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -87,6 +87,19 @@ void array_normalInitialize() { //disk_loadDataForInitializeDataStructers(disk_mng_CB->diskFreeIndexesInArray, 4+ disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int),DISK_SIZE*sizeof(ArrayInfo_t**)); } +ArrayInfo_t* arrayInfo_create(int mapid, int* diskPointer, int size, MapRange_t* range + //,AVLNodeInfo_t* avlInfo// +) +{ + ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for max heap", "arrayInfo_create"); + arrayInfo->mapid = mapid; + arrayInfo ->diskPointer = diskPointer; + arrayInfo->size = size; + arrayInfo->range =range; + //arrayInfo->avlInfo = avlInfo; + return arrayInfo; +} + void array_deleteFromArray(int index) { disk_mng_CB->arrayForAllMApsInformation[index] = NULL; @@ -98,6 +111,16 @@ void array_deleteArrayInfo(ArrayInfo_t* arrayInfo) free(arrayInfo); } +//maprange functions + +MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft) +{ + MapRange_t* mapRange = (MapRange_t*)allocate_memory(sizeof(MapRange_t), "Failed to allocate memory for max heap", "mapRange_create"); + mapRange->bottomRight = bottomRight; + mapRange->topLeft = topLeft; + return mapRange; +} + diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 6f6e3b2..4090d79 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -36,7 +36,7 @@ struct ArrayInfo_s { int mapid; int* diskPointer; int size; - MapRange_t range; + MapRange_t* range; //AVLNodeInfo_t avlInfo; }; @@ -98,3 +98,9 @@ void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); void disk_deleteMap(int* diskPointer); +ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range +//,AVLNodeInfo_t* avlInfo// + ); + +MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft); + diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index b7eca9d..a5901ec 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -34,6 +34,16 @@ void disk_loadDataForInitializeDataStructers(void* i,void* x,void* b) { } +TEST_CASE("test_disk_mng_initialize_CB") +{ + disk_mng_initialize_CB(); +} + +TEST_CASE("test_disk_mng_initialize") +{ + disk_mng_initialize(); +} + //stack tests TEST_CASE("test_stack_firstInitialize") @@ -103,7 +113,61 @@ TEST_CASE("test_stack_is_empty") } -////array tests +TEST_CASE("test_stackNode_create") +{ + int index = generateRandomNumber(); + StackNode_t* new_node = stackNode_create(index); + CHECK(new_node->freeIndex == index); + CHECK(new_node->next == disk_mng_CB->diskFreeIndexesInArray->top); +} + +//array tests + +TEST_CASE("test_array_deleteFromArray") +{ + int index = generateRandomNumber(); + array_deleteFromArray(index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index]== NULL); +} + +TEST_CASE("test_arrayInfo_create") +{ + int mapid = generateRandomNumber();; + int * diskPointer = NULL; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + + + //arrayInfo->avlInfo = avlInfo; + ArrayInfo_t* arrayInfo= arrayInfo_create(mapid, diskPointer, size, mapRange); + CHECK(arrayInfo->mapid == mapid); + CHECK(arrayInfo->diskPointer == NULL); + CHECK(arrayInfo->size == size); + CHECK(arrayInfo->range == mapRange); +} + +//range functions +TEST_CASE("test_mapRange_create") +{ + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + CHECK(mapRange->bottomRight.x == bottomRight.x); + CHECK(mapRange->bottomRight.y == bottomRight.y); + CHECK(mapRange->topLeft.x == topLeft.x); + CHECK(mapRange->topLeft.y == topLeft.y); +} + // //TEST_CASE("test_array_normalInitialize") //{ From 32df7dc6e579625b37d56bc1b1e8da20019063c5 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Wed, 7 Aug 2024 15:11:34 +0300 Subject: [PATCH 08/32] fix the delete and insert functions --- Storage/Disk_Mng_Master.c | 9 ++++++++- Storage/Disk_Mng_Master.h | 1 + Storage/main.c | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index fd96838..2ea0ab8 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -107,12 +107,19 @@ int getBalance(AVLNode_t* N) { return 0; return height(N->left) - height(N->right); } +AVLNode_t* avlTree_minValueNode(AVLNode_t* node) { + AVLNode_t* current = node; + while (current->left != NULL) + current = current->left; + + return current; +} AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter) { if (node == NULL) { data->lru = lruCounter; - return newAVLNode(data); + return avlNode_create(data); } if (data->mapSize < node->avlNodeInfo->mapSize) diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index e2b17e7..466c606 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -60,6 +60,7 @@ int height(AVLNode_t* N); AVLNode_t* rightRotate(AVLNode_t* y); AVLNode_t* leftRotate(AVLNode_t* x); int getBalance(AVLNode_t* N); +AVLNode_t* avlTree_minValueNode(AVLNode_t* node); AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter); void avlTree_firstInitialize(); diff --git a/Storage/main.c b/Storage/main.c index ffc6dab..26eeb15 100644 --- a/Storage/main.c +++ b/Storage/main.c @@ -1,3 +1,3 @@ -int main() { - return 0; -} \ No newline at end of file +//int main() { +// return 0; +//} \ No newline at end of file From ed6957a79b0cf8cbe6e071ce51d76309dc04457a Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Wed, 7 Aug 2024 16:03:13 +0300 Subject: [PATCH 09/32] Adding comments to functions as well as adding tests --- Storage/Disk_Mng_Master.c | 76 ++++++++++++++--------------- Storage/Disk_Mng_Master.h | 50 ++++++++++++++++--- Storage/Doctest.cpp | 100 +++++++++++++++++++++++++++++++++++++- 3 files changed, 179 insertions(+), 47 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 2ea0ab8..74d5075 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -43,7 +43,7 @@ void disk_mng_initialize() { avlTree_firstInitialize(); } -int height(AVLNode_t* N) { +int avlNode_height(AVLNode_t* N) { if (N == NULL) return 0; return N->height; @@ -76,36 +76,36 @@ AVLNode_t* avlNode_create(AVLNodeInfo_t* avlNodeInfo) { } void avlNode_delete(AVLNode_t* node) { if (node != NULL) { - avlNodeInfo_delete(node->avlNodeInfo); + avlNodeInfo_delete(node->avlNodeInfo);//? free(node); } } -AVLNode_t* rightRotate(AVLNode_t* y) { +AVLNode_t* avlTree_rightRotate(AVLNode_t* y) { AVLNode_t* x = y->left; AVLNode_t* T2 = x->right; x->right = y; y->left = T2; - y->height = max(height(y->left), height(y->right)) + 1; - x->height = max(height(x->left), height(x->right)) + 1; + y->height = max(avlNode_height(y->left), avlNode_height(y->right)) + 1; + x->height = max(avlNode_height(x->left), avlNode_height(x->right)) + 1; return x; } -AVLNode_t* leftRotate(AVLNode_t* x) { +AVLNode_t* avlTree_leftRotate(AVLNode_t* x) { AVLNode_t* y = x->right; AVLNode_t* T2 = y->left; y->left = x; x->right = T2; - x->height = max(height(x->left), height(x->right)) + 1; - y->height = max(height(y->left), height(y->right)) + 1; + x->height = max(avlNode_height(x->left), avlNode_height(x->right)) + 1; + y->height = max(avlNode_height(y->left), avlNode_height(y->right)) + 1; return y; } -int getBalance(AVLNode_t* N) { +int avlTree_getBalance(AVLNode_t* N) { if (N == NULL) return 0; - return height(N->left) - height(N->right); + return avlNode_height(N->left) - avlNode_height(N->right); } AVLNode_t* avlTree_minValueNode(AVLNode_t* node) { AVLNode_t* current = node; @@ -129,24 +129,24 @@ AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter) else return node; - node->height = 1 + max(height(node->left), height(node->right)); + node->height = 1 + max(avlNode_height(node->left), avlNode_height(node->right)); - int balance = getBalance(node); + int balance = avlTree_getBalance(node); if (balance > 1 && data->mapSize < node->left->avlNodeInfo->mapSize) - return rightRotate(node); + return avlTree_rightRotate(node); if (balance < -1 && data->mapSize > node->right->avlNodeInfo->mapSize) - return leftRotate(node); + return avlTree_leftRotate(node); if (balance > 1 && data->mapSize > node->left->avlNodeInfo->mapSize) { - node->left = leftRotate(node->left); - return rightRotate(node); + node->left = avlTree_leftRotate(node->left); + return avlTree_rightRotate(node); } if (balance < -1 && data->mapSize < node->right->avlNodeInfo->mapSize) { - node->right = rightRotate(node->right); - return leftRotate(node); + node->right = avlTree_rightRotate(node->right); + return avlTree_leftRotate(node); } return node; @@ -166,7 +166,7 @@ void avlTree_insertElement(AVLNodeInfo_t* data) { } -AVLNode_t* findEligibleForDeletion(AVLNode_t* node) { +AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node) { if (node == NULL) { return NULL; } @@ -174,7 +174,7 @@ AVLNode_t* findEligibleForDeletion(AVLNode_t* node) { AVLNode_t* eligibleNode = NULL; // Check the right subtree first for the largest node - AVLNode_t* rightResult = findEligibleForDeletion(node->right); + AVLNode_t* rightResult = avlTree_FindingTheNodeThatIsSuitableForDeletion(node->right); if (rightResult != NULL && rightResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { eligibleNode = rightResult; } @@ -187,7 +187,7 @@ AVLNode_t* findEligibleForDeletion(AVLNode_t* node) { } // Check the left subtree if no eligible node found in the right subtree or current node - AVLNode_t* leftResult = findEligibleForDeletion(node->left); + AVLNode_t* leftResult = avlTree_FindingTheNodeThatIsSuitableForDeletion(node->left); if (leftResult != NULL && leftResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { if (eligibleNode == NULL || leftResult->avlNodeInfo->mapSize > eligibleNode->avlNodeInfo->mapSize) { eligibleNode = leftResult; @@ -203,29 +203,26 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { // Traverse the tree to find the node if (node->avlNodeInfo->mapSize < root->avlNodeInfo->mapSize) { - root->left = avlTree_deleteNode(root->left, node->avlNodeInfo->mapSize); + root->left = avlTree_deleteNode(root->left, node); } else if (node->avlNodeInfo->mapSize > root->avlNodeInfo->mapSize) { - root->right = avlTree_deleteNode(root->right, node->avlNodeInfo->mapSize); + root->right = avlTree_deleteNode(root->right, node); } else { // Node with mapSize found if ((root->left == NULL) || (root->right == NULL)) { AVLNode_t* temp = root->left ? root->left : root->right; if (temp == NULL) { - temp = root; root = NULL; } else { *root = *temp; } - free(temp->avlNodeInfo); // Free AVLNodeInfo_t - free(temp); // Free AVLNode_t } else { AVLNode_t* temp = avlTree_minValueNode(root->right); root->avlNodeInfo = temp->avlNodeInfo; - root->right = avlTree_deleteNode(root->right, temp->avlNodeInfo->mapSize); + root->right = avlTree_deleteNode(root->right, temp); } } @@ -234,27 +231,26 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { } // Update height and balance the node - root->height = max(height(root->left), height(root->right)) + 1; - int balance = getBalance(root); + root->height = max(avlNode_height(root->left), avlNode_height(root->right)) + 1; + int balance = avlTree_getBalance(root); - if (balance > 1 && getBalance(root->left) >= 0) { - return rightRotate(root); + if (balance > 1 && avlTree_getBalance(root->left) >= 0) { + return avlTree_rightRotate(root); } - if (balance > 1 && getBalance(root->left) < 0) { - root->left = leftRotate(root->left); - return rightRotate(root); + if (balance > 1 && avlTree_getBalance(root->left) < 0) { + root->left = avlTree_leftRotate(root->left); + return avlTree_rightRotate(root); } - if (balance < -1 && getBalance(root->right) <= 0) { - return leftRotate(root); + if (balance < -1 && avlTree_getBalance(root->right) <= 0) { + return avlTree_leftRotate(root); } - if (balance < -1 && getBalance(root->right) > 0) { - root->right = rightRotate(root->right); - return leftRotate(root); + if (balance < -1 && avlTree_getBalance(root->right) > 0) { + root->right = avlTree_rightRotate(root->right); + return avlTree_leftRotate(root); } return root; } - diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 466c606..a6b1624 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -45,26 +45,64 @@ extern Disk_Managment_CB_t* disk_mng_CB; // Function declarations +// allocate_memory-Allocates memory and logs the allocation with a description and function name void* allocate_memory(size_t size, const char* description, const char* functionName); + +// test_writeExceptionToFile-Writes exception details to a file void test_writeExceptionToFile(Exception exception, const char* source); + +//initialize + +// disk_mng_initialize_CB-Initializes the control block for disk management void disk_mng_initialize_CB(); + +// disk_mng_initialize-Initializes the disk management system void disk_mng_initialize(); +//AVL node info + +// avlNodeInfo_create-Creates and returns a new AVLNodeInfo_t structure AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex, int lru); + +// avlNodeInfo_delete-Deletes an AVLNodeInfo_t structure void avlNodeInfo_delete(AVLNodeInfo_t* nodeInfo); +//AVL node + +// avlNode_create-Creates and returns a new AVLNode_t structure AVLNode_t* avlNode_create(AVLNodeInfo_t* avlNodeInfo); + +// avlNode_delete-Deletes an AVLNode_t structure void avlNode_delete(AVLNode_t* node); -int height(AVLNode_t* N); -AVLNode_t* rightRotate(AVLNode_t* y); -AVLNode_t* leftRotate(AVLNode_t* x); -int getBalance(AVLNode_t* N); +// avlNode_height-Returns the height of a given AVLNode_t +int avlNode_height(AVLNode_t* N); + +//AVL tree + +// avlTree_rightRotate-Performs a right rotation on the given subtree +AVLNode_t* avlTree_rightRotate(AVLNode_t* y); + +// avlTree_leftRotate-Performs a left rotation on the given subtree +AVLNode_t* avlTree_leftRotate(AVLNode_t* x); + +// avlTree_getBalance-Returns the balance factor of the given AVLNode_t +int avlTree_getBalance(AVLNode_t* N); + +// avlTree_minValueNode-Finds and returns the node with the smallest value in the tree AVLNode_t* avlTree_minValueNode(AVLNode_t* node); +// avlTree_insert-Inserts a new node into the AVL tree AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter); + +// avlTree_firstInitialize-Initializes the AVL tree for the first time void avlTree_firstInitialize(); + +// avlTree_insertElement-Inserts a new element into the AVL tree void avlTree_insertElement(AVLNodeInfo_t* data); -AVLNode_t* findEligibleForDeletion(AVLNode_t* node); -AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node); \ No newline at end of file +// avlTree_FindingTheNodeThatIsSuitableForDeletion-Finds the node suitable for deletion according to conditions +AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node); + +// avlTree_deleteNode-Deletes a node from the AVL tree without freeing its memory +AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 253f1f2..314685c 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -14,7 +14,7 @@ struct GlobalSetup { }; GlobalSetup globalSetup; -int generateRandomNumber(int upper) { +int generateRandomNumber(int upper= DISK_SIZE) { int lower = 0; return (rand() % (upper - lower + 1)) + lower; } @@ -27,3 +27,101 @@ TEST_CASE("test_disk_mng_initialize_CB") disk_mng_initialize_CB(); CHECK(disk_mng_CB != NULL); } + +TEST_CASE("test_disk_mng_initialize") +{ + disk_mng_initialize(); +} + +TEST_CASE("test_avlNodeInfo_create") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + + CHECK(avlNodeInfo->mapSize == mapSize); + CHECK(avlNodeInfo->arrayIndex == indexArray); + CHECK(avlNodeInfo->lru == lru); +} + +TEST_CASE("test_avlNodeInfo_delete") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + avlNodeInfo_delete(avlNodeInfo); +} + +TEST_CASE("test_avlNode_create") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + + CHECK(avlNode->avlNodeInfo == avlNodeInfo); + CHECK(avlNode->height == 1); + CHECK(avlNode->left == NULL); + CHECK(avlNode->right == NULL); +} + +TEST_CASE("test_avlNode_delete") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + avlNode_delete(avlNode); +} + +TEST_CASE("test_avlNode_height") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + + CHECK(avlNode->height == avlNode_height(avlNode)); +} + +TEST_CASE("test_avlTree_rightRotate") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + + avlNode1->left = avlNode2; + avlNode2->left = avlNode3; + + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + + AVLNode_t* newRoot = avlTree_rightRotate(avlNode1); + + CHECK(newRoot == avlNode2); + CHECK(newRoot->right == avlNode1); + CHECK(newRoot->left == avlNode3); + CHECK(avlNode1->left == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); + +} \ No newline at end of file From 5282c24bdd85176db8f392e85b58c38237df8637 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Wed, 7 Aug 2024 16:04:17 +0300 Subject: [PATCH 10/32] adding notes --- Storage/Disk_Mng_Master.c | 2 +- Storage/Disk_Mng_Master.h | 21 ++++++++++++++++++++- Storage/Doctest.cpp | 3 +-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 8dc592d..a012350 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -43,7 +43,7 @@ bool stack_is_empty() { StackNode_t* stackNode_create(int index) { - StackNode_t* new_node = (StackNode_t*)allocate_memory(sizeof(StackNode_t), "Failed to allocate memory for max heap", "stack_push"); + StackNode_t* new_node = (StackNode_t*)allocate_memory(sizeof(StackNode_t), "Failed to allocate memory for max heap", "stackNode_create"); new_node->freeIndex = index; new_node->next = disk_mng_CB->diskFreeIndexesInArray->top; return new_node; diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 4090d79..6b668a3 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -57,8 +57,10 @@ struct Disk_Management_CB_s { }; extern Disk_Managment_CB_t* disk_mng_CB; +//the function aloocate memory to the object and check if fail void* allocate_memory(size_t size, const char* description, const char* functionName); +//in case the allocate fail this function write to logFile void test_writeExceptionToFile(Exception exception, char* source); //disk managment @@ -67,35 +69,52 @@ void test_writeExceptionToFile(Exception exception, char* source); void disk_mng_initialize_CB(); -//initialize the cache mapping +////initialize the disk managment mapping void disk_mng_initialize(); //stack functions +//initialize on the first time when we turn on the computer-fill in the stack all the index from 0-DISK_SIZE void stack_firstInitialize(); +//normal initialize each open of the computer the disk will fill in the structers all the saved data void stack_normalInitialize(); +//stack_is_empty check if the stack full bool stack_is_empty(); + +// Push a new node onto the stack void stack_push(StackNode_t* new_node); +// Create a new stack node with the given index value StackNode_t* stackNode_create(int index); +// Pop the top element from the stack int stack_pop(); +// Get the value of the top element of the stack without popping it int stack_top(); + //array functions + +// Initializes an array with default values or in a standard way. +// This function likely sets the array to a known starting state. void array_normalInitialize(); +//initialize on the first time when we turn on the computer just allocate memory to the array void array_firstInitialize(); +// Deletes an element from an array at a specific index. void array_deleteFromArray(int index); +// Frees or deletes information associated with an array. void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); + +//disk_deleteMap the function get pointer to map in the disk and delete this map from disk void disk_deleteMap(int* diskPointer); ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index a5901ec..70d8900 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -16,9 +16,8 @@ struct GlobalSetup { }; GlobalSetup globalSetup; -int generateRandomNumber() { +int generateRandomNumber(int upper = DISK_SIZE) { int lower = 0; - int upper = DISK_SIZE; return (rand() % (upper - lower + 1)) + lower; } int index, popValue,value; From 6a91fbd7c9036a78da36174fac2c25240d1a34c7 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Wed, 7 Aug 2024 16:32:08 +0300 Subject: [PATCH 11/32] add doctest --- Storage/Doctest.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 314685c..592ee29 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -123,5 +123,37 @@ TEST_CASE("test_avlTree_rightRotate") CHECK(avlNode1->left == nullptr); CHECK(avlNode1->height == 1); CHECK(newRoot->height == 2); +} +TEST_CASE("test_avlTree_leftRotate") +{ + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + + + + avlNode1->right = avlNode2; + avlNode2->right = avlNode3; + + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + + AVLNode_t* newRoot = avlTree_leftRotate(avlNode1); + + CHECK(newRoot == avlNode2); + CHECK(newRoot->left == avlNode1); + CHECK(newRoot->right == avlNode3); + CHECK(avlNode1->right == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); } \ No newline at end of file From f4ed89c8d638dabccc26837bb520ed06e8879170 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Thu, 8 Aug 2024 08:25:55 +0300 Subject: [PATCH 12/32] delete shared files --- Storage/doctest.h | 7106 --------------------------------------------- Storage/main.c | 3 - 2 files changed, 7109 deletions(-) delete mode 100644 Storage/doctest.h delete mode 100644 Storage/main.c diff --git a/Storage/doctest.h b/Storage/doctest.h deleted file mode 100644 index 5c754cd..0000000 --- a/Storage/doctest.h +++ /dev/null @@ -1,7106 +0,0 @@ -// ====================================================================== lgtm [cpp/missing-header-guard] -// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == -// ====================================================================== -// -// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD -// -// Copyright (c) 2016-2023 Viktor Kirilov -// -// Distributed under the MIT Software License -// See accompanying file LICENSE.txt or copy at -// https://opensource.org/licenses/MIT -// -// The documentation can be found at the library's page: -// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md -// -// ================================================================================================= -// ================================================================================================= -// ================================================================================================= -// -// The library is heavily influenced by Catch - https://github.com/catchorg/Catch2 -// which uses the Boost Software License - Version 1.0 -// see here - https://github.com/catchorg/Catch2/blob/master/LICENSE.txt -// -// The concept of subcases (sections in Catch) and expression decomposition are from there. -// Some parts of the code are taken directly: -// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<> -// - the Approx() helper class for floating point comparison -// - colors in the console -// - breaking into a debugger -// - signal / SEH handling -// - timer -// - XmlWriter class - thanks to Phil Nash for allowing the direct reuse (AKA copy/paste) -// -// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest -// which uses the Boost Software License - Version 1.0 -// see here - https://github.com/martinmoene/lest/blob/master/LICENSE.txt -// -// ================================================================================================= -// ================================================================================================= -// ================================================================================================= - -#ifndef DOCTEST_LIBRARY_INCLUDED -#define DOCTEST_LIBRARY_INCLUDED - -// ================================================================================================= -// == VERSION ====================================================================================== -// ================================================================================================= - -#define DOCTEST_VERSION_MAJOR 2 -#define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 11 - -// util we need here -#define DOCTEST_TOSTR_IMPL(x) #x -#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) - -#define DOCTEST_VERSION_STR \ - DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \ - DOCTEST_TOSTR(DOCTEST_VERSION_PATCH) - -#define DOCTEST_VERSION \ - (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) - -// ================================================================================================= -// == COMPILER VERSION ============================================================================= -// ================================================================================================= - -// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect - -#ifdef _MSC_VER -#define DOCTEST_CPLUSPLUS _MSVC_LANG -#else -#define DOCTEST_CPLUSPLUS __cplusplus -#endif - -#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH)) - -// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl... -#if defined(_MSC_VER) && defined(_MSC_FULL_VER) -#if _MSC_VER == _MSC_FULL_VER / 10000 -#define DOCTEST_MSVC DOCTEST_COMPILER(_MSC_VER / 100, _MSC_VER % 100, _MSC_FULL_VER % 10000) -#else // MSVC -#define DOCTEST_MSVC \ - DOCTEST_COMPILER(_MSC_VER / 100, (_MSC_FULL_VER / 100000) % 100, _MSC_FULL_VER % 100000) -#endif // MSVC -#endif // MSVC -#if defined(__clang__) && defined(__clang_minor__) && defined(__clang_patchlevel__) -#define DOCTEST_CLANG DOCTEST_COMPILER(__clang_major__, __clang_minor__, __clang_patchlevel__) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) && \ - !defined(__INTEL_COMPILER) -#define DOCTEST_GCC DOCTEST_COMPILER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#endif // GCC -#if defined(__INTEL_COMPILER) -#define DOCTEST_ICC DOCTEST_COMPILER(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif // ICC - -#ifndef DOCTEST_MSVC -#define DOCTEST_MSVC 0 -#endif // DOCTEST_MSVC -#ifndef DOCTEST_CLANG -#define DOCTEST_CLANG 0 -#endif // DOCTEST_CLANG -#ifndef DOCTEST_GCC -#define DOCTEST_GCC 0 -#endif // DOCTEST_GCC -#ifndef DOCTEST_ICC -#define DOCTEST_ICC 0 -#endif // DOCTEST_ICC - -// ================================================================================================= -// == COMPILER WARNINGS HELPERS ==================================================================== -// ================================================================================================= - -#if DOCTEST_CLANG && !DOCTEST_ICC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) -#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH _Pragma("clang diagnostic push") -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(clang diagnostic ignored w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP _Pragma("clang diagnostic pop") -#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH DOCTEST_CLANG_SUPPRESS_WARNING(w) -#else // DOCTEST_CLANG -#define DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -#define DOCTEST_CLANG_SUPPRESS_WARNING(w) -#define DOCTEST_CLANG_SUPPRESS_WARNING_POP -#define DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_CLANG - -#if DOCTEST_GCC -#define DOCTEST_PRAGMA_TO_STR(x) _Pragma(#x) -#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH _Pragma("GCC diagnostic push") -#define DOCTEST_GCC_SUPPRESS_WARNING(w) DOCTEST_PRAGMA_TO_STR(GCC diagnostic ignored w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP _Pragma("GCC diagnostic pop") -#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH DOCTEST_GCC_SUPPRESS_WARNING(w) -#else // DOCTEST_GCC -#define DOCTEST_GCC_SUPPRESS_WARNING_PUSH -#define DOCTEST_GCC_SUPPRESS_WARNING(w) -#define DOCTEST_GCC_SUPPRESS_WARNING_POP -#define DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_GCC - -#if DOCTEST_MSVC -#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH __pragma(warning(push)) -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) __pragma(warning(disable : w)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP __pragma(warning(pop)) -#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH DOCTEST_MSVC_SUPPRESS_WARNING(w) -#else // DOCTEST_MSVC -#define DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -#define DOCTEST_MSVC_SUPPRESS_WARNING(w) -#define DOCTEST_MSVC_SUPPRESS_WARNING_POP -#define DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(w) -#endif // DOCTEST_MSVC - -// ================================================================================================= -// == COMPILER WARNINGS ============================================================================ -// ================================================================================================= - -// both the header and the implementation suppress all of these, -// so it only makes sense to aggregate them like so -#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \ - DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \ - \ - DOCTEST_GCC_SUPPRESS_WARNING_PUSH \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \ - DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \ - \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - /* these 4 also disabled globally via cmake: */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \ - /* common ones */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5264) /* 'variable-name': 'const' variable is not used */ \ - /* static analysis */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */ - -#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH - -DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated") - -DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy") -DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo") - -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted - -#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \ - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \ - DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */ \ - DOCTEST_MSVC_SUPPRESS_WARNING(5262) /* implicit fall-through */ - -#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP - -// ================================================================================================= -// == FEATURE DETECTION ============================================================================ -// ================================================================================================= - -// general compiler feature support table: https://en.cppreference.com/w/cpp/compiler_support -// MSVC C++11 feature support table: https://msdn.microsoft.com/en-us/library/hh567368.aspx -// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html -// MSVC version table: -// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering -// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022) -// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019) -// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017) -// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015) -// MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013) -// MSVC++ 11.0 _MSC_VER == 1700 (Visual Studio 2012) -// MSVC++ 10.0 _MSC_VER == 1600 (Visual Studio 2010) -// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008) -// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005) - -// Universal Windows Platform support -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -#define DOCTEST_CONFIG_NO_WINDOWS_SEH -#endif // WINAPI_FAMILY -#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH) -#define DOCTEST_CONFIG_WINDOWS_SEH -#endif // MSVC -#if defined(DOCTEST_CONFIG_NO_WINDOWS_SEH) && defined(DOCTEST_CONFIG_WINDOWS_SEH) -#undef DOCTEST_CONFIG_WINDOWS_SEH -#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH - -#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \ - !defined(__EMSCRIPTEN__) && !defined(__wasi__) -#define DOCTEST_CONFIG_POSIX_SIGNALS -#endif // _WIN32 -#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS) -#undef DOCTEST_CONFIG_POSIX_SIGNALS -#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \ - || defined(__wasi__) -#define DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // no exceptions -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS -#define DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS - -#if defined(DOCTEST_CONFIG_NO_EXCEPTIONS) && !defined(DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS) -#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS - -#ifdef __wasi__ -#define DOCTEST_CONFIG_NO_MULTITHREADING -#endif - -#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT) -#define DOCTEST_CONFIG_IMPLEMENT -#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN - -#if defined(_WIN32) || defined(__CYGWIN__) -#if DOCTEST_MSVC -#define DOCTEST_SYMBOL_EXPORT __declspec(dllexport) -#define DOCTEST_SYMBOL_IMPORT __declspec(dllimport) -#else // MSVC -#define DOCTEST_SYMBOL_EXPORT __attribute__((dllexport)) -#define DOCTEST_SYMBOL_IMPORT __attribute__((dllimport)) -#endif // MSVC -#else // _WIN32 -#define DOCTEST_SYMBOL_EXPORT __attribute__((visibility("default"))) -#define DOCTEST_SYMBOL_IMPORT -#endif // _WIN32 - -#ifdef DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL -#ifdef DOCTEST_CONFIG_IMPLEMENT -#define DOCTEST_INTERFACE DOCTEST_SYMBOL_EXPORT -#else // DOCTEST_CONFIG_IMPLEMENT -#define DOCTEST_INTERFACE DOCTEST_SYMBOL_IMPORT -#endif // DOCTEST_CONFIG_IMPLEMENT -#else // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL -#define DOCTEST_INTERFACE -#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL - -// needed for extern template instantiations -// see https://github.com/fmtlib/fmt/issues/2228 -#if DOCTEST_MSVC -#define DOCTEST_INTERFACE_DECL -#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE -#else // DOCTEST_MSVC -#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE -#define DOCTEST_INTERFACE_DEF -#endif // DOCTEST_MSVC - -#define DOCTEST_EMPTY - -#if DOCTEST_MSVC -#define DOCTEST_NOINLINE __declspec(noinline) -#define DOCTEST_UNUSED -#define DOCTEST_ALIGNMENT(x) -#elif DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 5, 0) -#define DOCTEST_NOINLINE -#define DOCTEST_UNUSED -#define DOCTEST_ALIGNMENT(x) -#else -#define DOCTEST_NOINLINE __attribute__((noinline)) -#define DOCTEST_UNUSED __attribute__((unused)) -#define DOCTEST_ALIGNMENT(x) __attribute__((aligned(x))) -#endif - -#ifdef DOCTEST_CONFIG_NO_CONTRADICTING_INLINE -#define DOCTEST_INLINE_NOINLINE inline -#else -#define DOCTEST_INLINE_NOINLINE inline DOCTEST_NOINLINE -#endif - -#ifndef DOCTEST_NORETURN -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_NORETURN -#else // DOCTEST_MSVC -#define DOCTEST_NORETURN [[noreturn]] -#endif // DOCTEST_MSVC -#endif // DOCTEST_NORETURN - -#ifndef DOCTEST_NOEXCEPT -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_NOEXCEPT -#else // DOCTEST_MSVC -#define DOCTEST_NOEXCEPT noexcept -#endif // DOCTEST_MSVC -#endif // DOCTEST_NOEXCEPT - -#ifndef DOCTEST_CONSTEXPR -#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_CONSTEXPR const -#define DOCTEST_CONSTEXPR_FUNC inline -#else // DOCTEST_MSVC -#define DOCTEST_CONSTEXPR constexpr -#define DOCTEST_CONSTEXPR_FUNC constexpr -#endif // DOCTEST_MSVC -#endif // DOCTEST_CONSTEXPR - -#ifndef DOCTEST_NO_SANITIZE_INTEGER -#if DOCTEST_CLANG >= DOCTEST_COMPILER(3, 7, 0) -#define DOCTEST_NO_SANITIZE_INTEGER __attribute__((no_sanitize("integer"))) -#else -#define DOCTEST_NO_SANITIZE_INTEGER -#endif -#endif // DOCTEST_NO_SANITIZE_INTEGER - -// ================================================================================================= -// == FEATURE DETECTION END ======================================================================== -// ================================================================================================= - -#define DOCTEST_DECLARE_INTERFACE(name) \ - virtual ~name(); \ - name() = default; \ - name(const name&) = delete; \ - name(name&&) = delete; \ - name& operator=(const name&) = delete; \ - name& operator=(name&&) = delete; - -#define DOCTEST_DEFINE_INTERFACE(name) \ - name::~name() = default; - -// internal macros for string concatenation and anonymous variable name generation -#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 -#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) -#ifdef __COUNTER__ // not standard and may be missing for some compilers -#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) -#else // __COUNTER__ -#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) -#endif // __COUNTER__ - -#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x& -#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE -#define DOCTEST_REF_WRAP(x) x -#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE - -// not using __APPLE__ because... this is how Catch does it -#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED -#define DOCTEST_PLATFORM_MAC -#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) -#define DOCTEST_PLATFORM_IPHONE -#elif defined(_WIN32) -#define DOCTEST_PLATFORM_WINDOWS -#elif defined(__wasi__) -#define DOCTEST_PLATFORM_WASI -#else // DOCTEST_PLATFORM -#define DOCTEST_PLATFORM_LINUX -#endif // DOCTEST_PLATFORM - -namespace doctest { namespace detail { - static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; } -}} - -#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \ - static const int var = doctest::detail::consume(&var, __VA_ARGS__); \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#ifndef DOCTEST_BREAK_INTO_DEBUGGER -// should probably take a look at https://github.com/scottt/debugbreak -#ifdef DOCTEST_PLATFORM_LINUX -#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) -// Break at the location of the failing check if possible -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) -#else -#include -#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) -#endif -#elif defined(DOCTEST_PLATFORM_MAC) -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler) -#elif defined(__ppc__) || defined(__ppc64__) -// https://www.cocoawithlove.com/2008/03/break-into-debugger.html -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler) -#else -#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler) -#endif -#elif DOCTEST_MSVC -#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() -#elif defined(__MINGW32__) -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wredundant-decls") -extern "C" __declspec(dllimport) void __stdcall DebugBreak(); -DOCTEST_GCC_SUPPRESS_WARNING_POP -#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() -#else // linux -#define DOCTEST_BREAK_INTO_DEBUGGER() (static_cast(0)) -#endif // linux -#endif // DOCTEST_BREAK_INTO_DEBUGGER - -// this is kept here for backwards compatibility since the config option was changed -#ifdef DOCTEST_CONFIG_USE_IOSFWD -#ifndef DOCTEST_CONFIG_USE_STD_HEADERS -#define DOCTEST_CONFIG_USE_STD_HEADERS -#endif -#endif // DOCTEST_CONFIG_USE_IOSFWD - -// for clang - always include ciso646 (which drags some std stuff) because -// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in -// which case we don't want to forward declare stuff from std - for reference: -// https://github.com/doctest/doctest/issues/126 -// https://github.com/doctest/doctest/issues/356 -#if DOCTEST_CLANG -#include -#endif // clang - -#ifdef _LIBCPP_VERSION -#ifndef DOCTEST_CONFIG_USE_STD_HEADERS -#define DOCTEST_CONFIG_USE_STD_HEADERS -#endif -#endif // _LIBCPP_VERSION - -#ifdef DOCTEST_CONFIG_USE_STD_HEADERS -#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN -#include -#include -#include -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END -#else // DOCTEST_CONFIG_USE_STD_HEADERS - -// Forward declaring 'X' in namespace std is not permitted by the C++ Standard. -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643) - -namespace std { // NOLINT(cert-dcl58-cpp) -typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using) -typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using) -template -struct char_traits; -template <> -struct char_traits; -template -class basic_ostream; // NOLINT(fuchsia-virtual-inheritance) -typedef basic_ostream> ostream; // NOLINT(modernize-use-using) -template -// NOLINTNEXTLINE -basic_ostream& operator<<(basic_ostream&, const char*); -template -class basic_istream; -typedef basic_istream> istream; // NOLINT(modernize-use-using) -template -class tuple; -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -template -class allocator; -template -class basic_string; -using string = basic_string, allocator>; -#endif // VS 2019 -} // namespace std - -DOCTEST_MSVC_SUPPRESS_WARNING_POP - -#endif // DOCTEST_CONFIG_USE_STD_HEADERS - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#include -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - -namespace doctest { - -using std::size_t; - -DOCTEST_INTERFACE extern bool is_running_in_test; - -#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE -#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned -#endif - -// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length -// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for: -// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128) -// - if small - capacity left before going on the heap - using the lowest 5 bits -// - if small - 2 bits are left unused - the second and third highest ones -// - if small - acts as a null terminator if strlen() is 23 (24 including the null terminator) -// and the "is small" bit remains "0" ("as well as the capacity left") so its OK -// Idea taken from this lecture about the string implementation of facebook/folly - fbstring -// https://www.youtube.com/watch?v=kPR8h4-qZdk -// TODO: -// - optimizations - like not deleting memory unnecessarily in operator= and etc. -// - resize/reserve/clear -// - replace -// - back/front -// - iterator stuff -// - find & friends -// - push_back/pop_back -// - assign/insert/erase -// - relational operators as free functions - taking const char* as one of the params -class DOCTEST_INTERFACE String -{ -public: - using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE; - -private: - static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members - static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members - - struct view // len should be more than sizeof(view) - because of the final byte for flags - { - char* ptr; - size_type size; - size_type capacity; - }; - - union - { - char buf[len]; // NOLINT(*-avoid-c-arrays) - view data; - }; - - char* allocate(size_type sz); - - bool isOnStack() const noexcept { return (buf[last] & 128) == 0; } - void setOnHeap() noexcept; - void setLast(size_type in = last) noexcept; - void setSize(size_type sz) noexcept; - - void copy(const String& other); - -public: - static DOCTEST_CONSTEXPR size_type npos = static_cast(-1); - - String() noexcept; - ~String(); - - // cppcheck-suppress noExplicitConstructor - String(const char* in); - String(const char* in, size_type in_size); - - String(std::istream& in, size_type in_size); - - String(const String& other); - String& operator=(const String& other); - - String& operator+=(const String& other); - - String(String&& other) noexcept; - String& operator=(String&& other) noexcept; - - char operator[](size_type i) const; - char& operator[](size_type i); - - // the only functions I'm willing to leave in the interface - available for inlining - const char* c_str() const { return const_cast(this)->c_str(); } // NOLINT - char* c_str() { - if (isOnStack()) { - return reinterpret_cast(buf); - } - return data.ptr; - } - - size_type size() const; - size_type capacity() const; - - String substr(size_type pos, size_type cnt = npos) &&; - String substr(size_type pos, size_type cnt = npos) const &; - - size_type find(char ch, size_type pos = 0) const; - size_type rfind(char ch, size_type pos = npos) const; - - int compare(const char* other, bool no_case = false) const; - int compare(const String& other, bool no_case = false) const; - -friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in); -}; - -DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs); - -DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs); - -class DOCTEST_INTERFACE Contains { -public: - explicit Contains(const String& string); - - bool checkWith(const String& other) const; - - String string; -}; - -DOCTEST_INTERFACE String toString(const Contains& in); - -DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs); -DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs); -DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs); - -namespace Color { - enum Enum - { - None = 0, - White, - Red, - Green, - Blue, - Cyan, - Yellow, - Grey, - - Bright = 0x10, - - BrightRed = Bright | Red, - BrightGreen = Bright | Green, - LightGrey = Bright | Grey, - BrightWhite = Bright | White - }; - - DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, Color::Enum code); -} // namespace Color - -namespace assertType { - enum Enum - { - // macro traits - - is_warn = 1, - is_check = 2 * is_warn, - is_require = 2 * is_check, - - is_normal = 2 * is_require, - is_throws = 2 * is_normal, - is_throws_as = 2 * is_throws, - is_throws_with = 2 * is_throws_as, - is_nothrow = 2 * is_throws_with, - - is_false = 2 * is_nothrow, - is_unary = 2 * is_false, // not checked anywhere - used just to distinguish the types - - is_eq = 2 * is_unary, - is_ne = 2 * is_eq, - - is_lt = 2 * is_ne, - is_gt = 2 * is_lt, - - is_ge = 2 * is_gt, - is_le = 2 * is_ge, - - // macro types - - DT_WARN = is_normal | is_warn, - DT_CHECK = is_normal | is_check, - DT_REQUIRE = is_normal | is_require, - - DT_WARN_FALSE = is_normal | is_false | is_warn, - DT_CHECK_FALSE = is_normal | is_false | is_check, - DT_REQUIRE_FALSE = is_normal | is_false | is_require, - - DT_WARN_THROWS = is_throws | is_warn, - DT_CHECK_THROWS = is_throws | is_check, - DT_REQUIRE_THROWS = is_throws | is_require, - - DT_WARN_THROWS_AS = is_throws_as | is_warn, - DT_CHECK_THROWS_AS = is_throws_as | is_check, - DT_REQUIRE_THROWS_AS = is_throws_as | is_require, - - DT_WARN_THROWS_WITH = is_throws_with | is_warn, - DT_CHECK_THROWS_WITH = is_throws_with | is_check, - DT_REQUIRE_THROWS_WITH = is_throws_with | is_require, - - DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn, - DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check, - DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require, - - DT_WARN_NOTHROW = is_nothrow | is_warn, - DT_CHECK_NOTHROW = is_nothrow | is_check, - DT_REQUIRE_NOTHROW = is_nothrow | is_require, - - DT_WARN_EQ = is_normal | is_eq | is_warn, - DT_CHECK_EQ = is_normal | is_eq | is_check, - DT_REQUIRE_EQ = is_normal | is_eq | is_require, - - DT_WARN_NE = is_normal | is_ne | is_warn, - DT_CHECK_NE = is_normal | is_ne | is_check, - DT_REQUIRE_NE = is_normal | is_ne | is_require, - - DT_WARN_GT = is_normal | is_gt | is_warn, - DT_CHECK_GT = is_normal | is_gt | is_check, - DT_REQUIRE_GT = is_normal | is_gt | is_require, - - DT_WARN_LT = is_normal | is_lt | is_warn, - DT_CHECK_LT = is_normal | is_lt | is_check, - DT_REQUIRE_LT = is_normal | is_lt | is_require, - - DT_WARN_GE = is_normal | is_ge | is_warn, - DT_CHECK_GE = is_normal | is_ge | is_check, - DT_REQUIRE_GE = is_normal | is_ge | is_require, - - DT_WARN_LE = is_normal | is_le | is_warn, - DT_CHECK_LE = is_normal | is_le | is_check, - DT_REQUIRE_LE = is_normal | is_le | is_require, - - DT_WARN_UNARY = is_normal | is_unary | is_warn, - DT_CHECK_UNARY = is_normal | is_unary | is_check, - DT_REQUIRE_UNARY = is_normal | is_unary | is_require, - - DT_WARN_UNARY_FALSE = is_normal | is_false | is_unary | is_warn, - DT_CHECK_UNARY_FALSE = is_normal | is_false | is_unary | is_check, - DT_REQUIRE_UNARY_FALSE = is_normal | is_false | is_unary | is_require, - }; -} // namespace assertType - -DOCTEST_INTERFACE const char* assertString(assertType::Enum at); -DOCTEST_INTERFACE const char* failureString(assertType::Enum at); -DOCTEST_INTERFACE const char* skipPathFromFilename(const char* file); - -struct DOCTEST_INTERFACE TestCaseData -{ - String m_file; // the file in which the test was registered (using String - see #350) - unsigned m_line; // the line where the test was registered - const char* m_name; // name of the test case - const char* m_test_suite; // the test suite in which the test was added - const char* m_description; - bool m_skip; - bool m_no_breaks; - bool m_no_output; - bool m_may_fail; - bool m_should_fail; - int m_expected_failures; - double m_timeout; -}; - -struct DOCTEST_INTERFACE AssertData -{ - // common - for all asserts - const TestCaseData* m_test_case; - assertType::Enum m_at; - const char* m_file; - int m_line; - const char* m_expr; - bool m_failed; - - // exception-related - for all asserts - bool m_threw; - String m_exception; - - // for normal asserts - String m_decomp; - - // for specific exception-related asserts - bool m_threw_as; - const char* m_exception_type; - - class DOCTEST_INTERFACE StringContains { - private: - Contains content; - bool isContains; - - public: - StringContains(const String& str) : content(str), isContains(false) { } - StringContains(Contains cntn) : content(static_cast(cntn)), isContains(true) { } - - bool check(const String& str) { return isContains ? (content == str) : (content.string == str); } - - operator const String&() const { return content.string; } - - const char* c_str() const { return content.string.c_str(); } - } m_exception_string; - - AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string); -}; - -struct DOCTEST_INTERFACE MessageData -{ - String m_string; - const char* m_file; - int m_line; - assertType::Enum m_severity; -}; - -struct DOCTEST_INTERFACE SubcaseSignature -{ - String m_name; - const char* m_file; - int m_line; - - bool operator==(const SubcaseSignature& other) const; - bool operator<(const SubcaseSignature& other) const; -}; - -struct DOCTEST_INTERFACE IContextScope -{ - DOCTEST_DECLARE_INTERFACE(IContextScope) - virtual void stringify(std::ostream*) const = 0; -}; - -namespace detail { - struct DOCTEST_INTERFACE TestCase; -} // namespace detail - -struct ContextOptions //!OCLINT too many fields -{ - std::ostream* cout = nullptr; // stdout stream - String binary_name; // the test binary name - - const detail::TestCase* currentTest = nullptr; - - // == parameters from the command line - String out; // output filename - String order_by; // how tests should be ordered - unsigned rand_seed; // the seed for rand ordering - - unsigned first; // the first (matching) test to be executed - unsigned last; // the last (matching) test to be executed - - int abort_after; // stop tests after this many failed assertions - int subcase_filter_levels; // apply the subcase filters for the first N levels - - bool success; // include successful assertions in output - bool case_sensitive; // if filtering should be case sensitive - bool exit; // if the program should be exited after the tests are ran/whatever - bool duration; // print the time duration of each test case - bool minimal; // minimal console output (only test failures) - bool quiet; // no console output - bool no_throw; // to skip exceptions-related assertion macros - bool no_exitcode; // if the framework should return 0 as the exitcode - bool no_run; // to not run the tests at all (can be done with an "*" exclude) - bool no_intro; // to not print the intro of the framework - bool no_version; // to not print the version of the framework - bool no_colors; // if output to the console should be colorized - bool force_colors; // forces the use of colors even when a tty cannot be detected - bool no_breaks; // to not break into the debugger - bool no_skip; // don't skip test cases which are marked to be skipped - bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): - bool no_path_in_filenames; // if the path to files should be removed from the output - bool no_line_numbers; // if source code line numbers should be omitted from the output - bool no_debug_output; // no output in the debug console when a debugger is attached - bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! - bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! - - bool help; // to print the help - bool version; // to print the version - bool count; // if only the count of matching tests is to be retrieved - bool list_test_cases; // to list all tests matching the filters - bool list_test_suites; // to list all suites matching the filters - bool list_reporters; // lists all registered reporters -}; - -namespace detail { - namespace types { -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - using namespace std; -#else - template - struct enable_if { }; - - template - struct enable_if { using type = T; }; - - struct true_type { static DOCTEST_CONSTEXPR bool value = true; }; - struct false_type { static DOCTEST_CONSTEXPR bool value = false; }; - - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - template struct remove_reference { using type = T; }; - - template struct is_rvalue_reference : false_type { }; - template struct is_rvalue_reference : true_type { }; - - template struct remove_const { using type = T; }; - template struct remove_const { using type = T; }; - - // Compiler intrinsics - template struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); }; - template struct underlying_type { using type = __underlying_type(T); }; - - template struct is_pointer : false_type { }; - template struct is_pointer : true_type { }; - - template struct is_array : false_type { }; - // NOLINTNEXTLINE(*-avoid-c-arrays) - template struct is_array : true_type { }; -#endif - } - - // - template - T&& declval(); - - template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type& t) DOCTEST_NOEXCEPT { - return static_cast(t); - } - - template - DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference::type&& t) DOCTEST_NOEXCEPT { - return static_cast(t); - } - - template - struct deferred_false : types::false_type { }; - -// MSVS 2015 :( -#if !DOCTEST_CLANG && defined(_MSC_VER) && _MSC_VER <= 1900 - template - struct has_global_insertion_operator : types::false_type { }; - - template - struct has_global_insertion_operator(), declval()), void())> : types::true_type { }; - - template - struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator::value; }; - - template - struct insert_hack; - - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); } - }; - - template - struct insert_hack { - static void insert(std::ostream& os, const T& t) { operator<<(os, t); } - }; - - template - using insert_hack_t = insert_hack::value>; -#else - template - struct has_insertion_operator : types::false_type { }; -#endif - - template - struct has_insertion_operator(), declval()), void())> : types::true_type { }; - - template - struct should_stringify_as_underlying_type { - static DOCTEST_CONSTEXPR bool value = detail::types::is_enum::value && !doctest::detail::has_insertion_operator::value; - }; - - DOCTEST_INTERFACE std::ostream* tlssPush(); - DOCTEST_INTERFACE String tlssPop(); - - template - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T)) { -#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES - static_assert(deferred_false::value, "No stringification detected for type T. See string conversion manual"); -#endif - return "{?}"; - } - }; - - template - struct filldata; - - template - void filloss(std::ostream* stream, const T& in) { - filldata::fill(stream, in); - } - - template - void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays) - // T[N], T(&)[N], T(&&)[N] have same behaviour. - // Hence remove reference. - filloss::type>(stream, in); - } - - template - String toStream(const T& in) { - std::ostream* stream = tlssPush(); - filloss(stream, in); - return tlssPop(); - } - - template <> - struct StringMakerBase { - template - static String convert(const DOCTEST_REF_WRAP(T) in) { - return toStream(in); - } - }; -} // namespace detail - -template -struct StringMaker : public detail::StringMakerBase< - detail::has_insertion_operator::value || detail::types::is_pointer::value || detail::types::is_array::value> -{}; - -#ifndef DOCTEST_STRINGIFY -#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY -#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__)) -#else -#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__) -#endif -#endif - -template -String toString() { -#if DOCTEST_CLANG == 0 && DOCTEST_GCC == 0 && DOCTEST_ICC == 0 - String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString(void) - String::size_type beginPos = ret.find('<'); - return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast(sizeof(">(void)"))); -#else - String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE] - String::size_type begin = ret.find('=') + 2; - return ret.substr(begin, ret.size() - begin - 1); -#endif -} - -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { - return StringMaker::convert(value); -} - -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -DOCTEST_INTERFACE String toString(const char* in); -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -DOCTEST_INTERFACE String toString(const std::string& in); -#endif // VS 2019 - -DOCTEST_INTERFACE String toString(String in); - -DOCTEST_INTERFACE String toString(std::nullptr_t); - -DOCTEST_INTERFACE String toString(bool in); - -DOCTEST_INTERFACE String toString(float in); -DOCTEST_INTERFACE String toString(double in); -DOCTEST_INTERFACE String toString(double long in); - -DOCTEST_INTERFACE String toString(char in); -DOCTEST_INTERFACE String toString(char signed in); -DOCTEST_INTERFACE String toString(char unsigned in); -DOCTEST_INTERFACE String toString(short in); -DOCTEST_INTERFACE String toString(short unsigned in); -DOCTEST_INTERFACE String toString(signed in); -DOCTEST_INTERFACE String toString(unsigned in); -DOCTEST_INTERFACE String toString(long in); -DOCTEST_INTERFACE String toString(long unsigned in); -DOCTEST_INTERFACE String toString(long long in); -DOCTEST_INTERFACE String toString(long long unsigned in); - -template ::value, bool>::type = true> -String toString(const DOCTEST_REF_WRAP(T) value) { - using UT = typename detail::types::underlying_type::type; - return (DOCTEST_STRINGIFY(static_cast(value))); -} - -namespace detail { - template - struct filldata - { - static void fill(std::ostream* stream, const T& in) { -#if defined(_MSC_VER) && _MSC_VER <= 1900 - insert_hack_t::insert(*stream, in); -#else - operator<<(*stream, in); -#endif - } - }; - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const T(&in)[N]) { - *stream << "["; - for (size_t i = 0; i < N; i++) { - if (i != 0) { *stream << ", "; } - *stream << (DOCTEST_STRINGIFY(in[i])); - } - *stream << "]"; - } - }; -// NOLINTEND(*-avoid-c-arrays) -DOCTEST_MSVC_SUPPRESS_WARNING_POP - - // Specialized since we don't want the terminating null byte! -// NOLINTBEGIN(*-avoid-c-arrays) - template - struct filldata { - static void fill(std::ostream* stream, const char (&in)[N]) { - *stream << String(in, in[N - 1] ? N : N - 1); - } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - }; -// NOLINTEND(*-avoid-c-arrays) - - template <> - struct filldata { - static void fill(std::ostream* stream, const void* in); - }; - - template - struct filldata { -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4180) - static void fill(std::ostream* stream, const T* in) { -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wmicrosoft-cast") - filldata::fill(stream, -#if DOCTEST_GCC == 0 || DOCTEST_GCC >= DOCTEST_COMPILER(4, 9, 0) - reinterpret_cast(in) -#else - *reinterpret_cast(&in) -#endif - ); -DOCTEST_CLANG_SUPPRESS_WARNING_POP - } - }; -} - -struct DOCTEST_INTERFACE Approx -{ - Approx(double value); - - Approx operator()(double value) const; - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - explicit Approx(const T& value, - typename detail::types::enable_if::value>::type* = - static_cast(nullptr)) { - *this = static_cast(value); - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - Approx& epsilon(double newEpsilon); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, Approx&>::type epsilon( - const T& newEpsilon) { - m_epsilon = static_cast(newEpsilon); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - Approx& scale(double newScale); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - template - typename std::enable_if::value, Approx&>::type scale( - const T& newScale) { - m_scale = static_cast(newScale); - return *this; - } -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - // clang-format off - DOCTEST_INTERFACE friend bool operator==(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator==(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator!=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator!=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator<=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator<=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator>=(double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator>=(const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator< (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator< (const Approx & lhs, double rhs); - DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs); - DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs); - -#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS -#define DOCTEST_APPROX_PREFIX \ - template friend typename std::enable_if::value, bool>::type - - DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast(lhs), rhs); } - DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); } - DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); } - DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) || lhs == rhs; } - DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast(lhs) < rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast(rhs) && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast(lhs) > rhs.m_value && lhs != rhs; } - DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast(rhs) && lhs != rhs; } -#undef DOCTEST_APPROX_PREFIX -#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS - - // clang-format on - - double m_epsilon; - double m_scale; - double m_value; -}; - -DOCTEST_INTERFACE String toString(const Approx& in); - -DOCTEST_INTERFACE const ContextOptions* getContextOptions(); - -template -struct DOCTEST_INTERFACE_DECL IsNaN -{ - F value; bool flipped; - IsNaN(F f, bool flip = false) : value(f), flipped(flip) { } - IsNaN operator!() const { return { value, !flipped }; } - operator bool() const; -}; -#ifndef __MINGW32__ -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -extern template struct DOCTEST_INTERFACE_DECL IsNaN; -#endif -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); -DOCTEST_INTERFACE String toString(IsNaN in); - -#ifndef DOCTEST_CONFIG_DISABLE - -namespace detail { - // clang-format off -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - template struct decay_array { using type = T; }; - template struct decay_array { using type = T*; }; - template struct decay_array { using type = T*; }; - - template struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 1; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; - template<> struct not_char_pointer { static DOCTEST_CONSTEXPR int value = 0; }; - - template struct can_use_op : public not_char_pointer::type> {}; -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - // clang-format on - - struct DOCTEST_INTERFACE TestFailureException - { - }; - - DOCTEST_INTERFACE bool checkIfShouldThrow(assertType::Enum at); - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_NORETURN -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_INTERFACE void throwException(); - - struct DOCTEST_INTERFACE Subcase - { - SubcaseSignature m_signature; - bool m_entered = false; - - Subcase(const String& name, const char* file, int line); - Subcase(const Subcase&) = delete; - Subcase(Subcase&&) = delete; - Subcase& operator=(const Subcase&) = delete; - Subcase& operator=(Subcase&&) = delete; - ~Subcase(); - - operator bool() const; - - private: - bool checkFilters(); - }; - - template - String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, - const DOCTEST_REF_WRAP(R) rhs) { - return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs)); - } - -#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison") -#endif - -// This will check if there is any way it could find a operator like member or friend and uses it. -// If not it doesn't find the operator or if the operator at global scope is defined after -// this template, the template won't be instantiated due to SFINAE. Once the template is not -// instantiated it can look for global operator using normal conversions. -#ifdef __NVCC__ -#define SFINAE_OP(ret,op) ret -#else -#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval() op doctest::detail::declval()),ret{}) -#endif - -#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \ - template \ - DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \ - bool res = op_macro(doctest::detail::forward(lhs), doctest::detail::forward(rhs)); \ - if(m_at & assertType::is_false) \ - res = !res; \ - if(!res || doctest::getContextOptions()->success) \ - return Result(res, stringifyBinaryExpr(lhs, op_str, rhs)); \ - return Result(res); \ - } - - // more checks could be added - like in Catch: - // https://github.com/catchorg/Catch2/pull/1480/files - // https://github.com/catchorg/Catch2/pull/1481/files -#define DOCTEST_FORBIT_EXPRESSION(rt, op) \ - template \ - rt& operator op(const R&) { \ - static_assert(deferred_false::value, \ - "Expression Too Complex Please Rewrite As Binary Comparison!"); \ - return *this; \ - } - - struct DOCTEST_INTERFACE Result // NOLINT(*-member-init) - { - bool m_passed; - String m_decomp; - - Result() = default; // TODO: Why do we need this? (To remove NOLINT) - Result(bool passed, const String& decomposition = String()); - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Result, &) - DOCTEST_FORBIT_EXPRESSION(Result, ^) - DOCTEST_FORBIT_EXPRESSION(Result, |) - DOCTEST_FORBIT_EXPRESSION(Result, &&) - DOCTEST_FORBIT_EXPRESSION(Result, ||) - DOCTEST_FORBIT_EXPRESSION(Result, ==) - DOCTEST_FORBIT_EXPRESSION(Result, !=) - DOCTEST_FORBIT_EXPRESSION(Result, <) - DOCTEST_FORBIT_EXPRESSION(Result, >) - DOCTEST_FORBIT_EXPRESSION(Result, <=) - DOCTEST_FORBIT_EXPRESSION(Result, >=) - DOCTEST_FORBIT_EXPRESSION(Result, =) - DOCTEST_FORBIT_EXPRESSION(Result, +=) - DOCTEST_FORBIT_EXPRESSION(Result, -=) - DOCTEST_FORBIT_EXPRESSION(Result, *=) - DOCTEST_FORBIT_EXPRESSION(Result, /=) - DOCTEST_FORBIT_EXPRESSION(Result, %=) - DOCTEST_FORBIT_EXPRESSION(Result, <<=) - DOCTEST_FORBIT_EXPRESSION(Result, >>=) - DOCTEST_FORBIT_EXPRESSION(Result, &=) - DOCTEST_FORBIT_EXPRESSION(Result, ^=) - DOCTEST_FORBIT_EXPRESSION(Result, |=) - }; - -#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - - DOCTEST_CLANG_SUPPRESS_WARNING_PUSH - DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") - DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_CLANG_SUPPRESS_WARNING("-Wfloat-equal") - - DOCTEST_GCC_SUPPRESS_WARNING_PUSH - DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") - DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-compare") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wdouble-promotion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") - //DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal") - - DOCTEST_MSVC_SUPPRESS_WARNING_PUSH - // https://stackoverflow.com/questions/39479163 what's the difference between 4018 and 4389 - DOCTEST_MSVC_SUPPRESS_WARNING(4388) // signed/unsigned mismatch - DOCTEST_MSVC_SUPPRESS_WARNING(4389) // 'operator' : signed/unsigned mismatch - DOCTEST_MSVC_SUPPRESS_WARNING(4018) // 'expression' : signed/unsigned mismatch - //DOCTEST_MSVC_SUPPRESS_WARNING(4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation - -#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - - // clang-format off -#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_COMPARISON_RETURN_TYPE bool -#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if::value || can_use_op::value, bool>::type - inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } - inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } - inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } - inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } - inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } - inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - // clang-format on - -#define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - DOCTEST_COMPARISON_RETURN_TYPE name(const DOCTEST_REF_WRAP(L) lhs, \ - const DOCTEST_REF_WRAP(R) rhs) { \ - return lhs op rhs; \ - } - - DOCTEST_RELATIONAL_OP(eq, ==) - DOCTEST_RELATIONAL_OP(ne, !=) - DOCTEST_RELATIONAL_OP(lt, <) - DOCTEST_RELATIONAL_OP(gt, >) - DOCTEST_RELATIONAL_OP(le, <=) - DOCTEST_RELATIONAL_OP(ge, >=) - -#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_CMP_EQ(l, r) l == r -#define DOCTEST_CMP_NE(l, r) l != r -#define DOCTEST_CMP_GT(l, r) l > r -#define DOCTEST_CMP_LT(l, r) l < r -#define DOCTEST_CMP_GE(l, r) l >= r -#define DOCTEST_CMP_LE(l, r) l <= r -#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -#define DOCTEST_CMP_EQ(l, r) eq(l, r) -#define DOCTEST_CMP_NE(l, r) ne(l, r) -#define DOCTEST_CMP_GT(l, r) gt(l, r) -#define DOCTEST_CMP_LT(l, r) lt(l, r) -#define DOCTEST_CMP_GE(l, r) ge(l, r) -#define DOCTEST_CMP_LE(l, r) le(l, r) -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - - template - // cppcheck-suppress copyCtorAndEqOperator - struct Expression_lhs - { - L lhs; - assertType::Enum m_at; - - explicit Expression_lhs(L&& in, assertType::Enum at) - : lhs(static_cast(in)) - , m_at(at) {} - - DOCTEST_NOINLINE operator Result() { -// this is needed only for MSVC 2015 -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool - bool res = static_cast(lhs); -DOCTEST_MSVC_SUPPRESS_WARNING_POP - if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - res = !res; - } - - if(!res || getContextOptions()->success) { - return { res, (DOCTEST_STRINGIFY(lhs)) }; - } - return { res }; - } - - /* This is required for user-defined conversions from Expression_lhs to L */ - operator L() const { return lhs; } - - // clang-format off - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(!=, " != ", DOCTEST_CMP_NE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>, " > ", DOCTEST_CMP_GT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<, " < ", DOCTEST_CMP_LT) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(>=, " >= ", DOCTEST_CMP_GE) //!OCLINT bitwise operator in conditional - DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(<=, " <= ", DOCTEST_CMP_LE) //!OCLINT bitwise operator in conditional - // clang-format on - - // forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &&) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ||) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, =) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, +=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, -=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, *=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, /=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, %=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, &=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, ^=) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, |=) - // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the - // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, <<) - DOCTEST_FORBIT_EXPRESSION(Expression_lhs, >>) - }; - -#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_MSVC_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP - -#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION - -#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0) -DOCTEST_CLANG_SUPPRESS_WARNING_POP -#endif - - struct DOCTEST_INTERFACE ExpressionDecomposer - { - assertType::Enum m_at; - - ExpressionDecomposer(assertType::Enum at); - - // The right operator for capturing expressions is "<=" instead of "<<" (based on the operator precedence table) - // but then there will be warnings from GCC about "-Wparentheses" and since "_Pragma()" is problematic this will stay for now... - // https://github.com/catchorg/Catch2/issues/870 - // https://github.com/catchorg/Catch2/issues/565 - template - Expression_lhs operator<<(L&& operand) { - return Expression_lhs(static_cast(operand), m_at); - } - - template ::value,void >::type* = nullptr> - Expression_lhs operator<<(const L &operand) { - return Expression_lhs(operand, m_at); - } - }; - - struct DOCTEST_INTERFACE TestSuite - { - const char* m_test_suite = nullptr; - const char* m_description = nullptr; - bool m_skip = false; - bool m_no_breaks = false; - bool m_no_output = false; - bool m_may_fail = false; - bool m_should_fail = false; - int m_expected_failures = 0; - double m_timeout = 0; - - TestSuite& operator*(const char* in); - - template - TestSuite& operator*(const T& in) { - in.fill(*this); - return *this; - } - }; - - using funcType = void (*)(); - - struct DOCTEST_INTERFACE TestCase : public TestCaseData - { - funcType m_test; // a function pointer to the test case - - String m_type; // for templated test cases - gets appended to the real name - int m_template_id; // an ID used to distinguish between the different versions of a templated test case - String m_full_name; // contains the name (only for templated test cases!) + the template type - - TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type = String(), int template_id = -1); - - TestCase(const TestCase& other); - TestCase(TestCase&&) = delete; - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& operator=(const TestCase& other); - DOCTEST_MSVC_SUPPRESS_WARNING_POP - - TestCase& operator=(TestCase&&) = delete; - - TestCase& operator*(const char* in); - - template - TestCase& operator*(const T& in) { - in.fill(*this); - return *this; - } - - bool operator<(const TestCase& other) const; - - ~TestCase() = default; - }; - - // forward declarations of functions used by the macros - DOCTEST_INTERFACE int regTest(const TestCase& tc); - DOCTEST_INTERFACE int setTestSuite(const TestSuite& ts); - DOCTEST_INTERFACE bool isDebuggerActive(); - - template - int instantiationHelper(const T&) { return 0; } - - namespace binaryAssertComparison { - enum Enum - { - eq = 0, - ne, - gt, - lt, - ge, - le - }; - } // namespace binaryAssertComparison - - // clang-format off - template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; - -#define DOCTEST_BINARY_RELATIONAL_OP(n, op) \ - template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return op(lhs, rhs); } }; - // clang-format on - - DOCTEST_BINARY_RELATIONAL_OP(0, doctest::detail::eq) - DOCTEST_BINARY_RELATIONAL_OP(1, doctest::detail::ne) - DOCTEST_BINARY_RELATIONAL_OP(2, doctest::detail::gt) - DOCTEST_BINARY_RELATIONAL_OP(3, doctest::detail::lt) - DOCTEST_BINARY_RELATIONAL_OP(4, doctest::detail::ge) - DOCTEST_BINARY_RELATIONAL_OP(5, doctest::detail::le) - - struct DOCTEST_INTERFACE ResultBuilder : public AssertData - { - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type = "", const String& exception_string = ""); - - ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string); - - void setResult(const Result& res); - - template - DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - m_failed = !RelationalComparator()(lhs, rhs); - if (m_failed || getContextOptions()->success) { - m_decomp = stringifyBinaryExpr(lhs, ", ", rhs); - } - return !m_failed; - } - - template - DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) { - m_failed = !val; - - if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional - m_failed = !m_failed; - } - - if (m_failed || getContextOptions()->success) { - m_decomp = (DOCTEST_STRINGIFY(val)); - } - - return !m_failed; - } - - void translateException(); - - bool log(); - void react() const; - }; - - namespace assertAction { - enum Enum - { - nothing = 0, - dbgbreak = 1, - shouldthrow = 2 - }; - } // namespace assertAction - - DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad); - - DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line, - const char* expr, const Result& result); - -#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \ - do { \ - if(!is_running_in_test) { \ - if(failed) { \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - rb.m_decomp = decomp; \ - failed_out_of_a_testing_context(rb); \ - if(isDebuggerActive() && !getContextOptions()->no_breaks) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(checkIfShouldThrow(at)) \ - throwException(); \ - } \ - return !failed; \ - } \ - } while(false) - -#define DOCTEST_ASSERT_IN_TESTS(decomp) \ - ResultBuilder rb(at, file, line, expr); \ - rb.m_failed = failed; \ - if(rb.m_failed || getContextOptions()->success) \ - rb.m_decomp = decomp; \ - if(rb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - if(rb.m_failed && checkIfShouldThrow(at)) \ - throwException() - - template - DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) lhs, - const DOCTEST_REF_WRAP(R) rhs) { - bool failed = !RelationalComparator()(lhs, rhs); - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs)); - return !failed; - } - - template - DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line, - const char* expr, const DOCTEST_REF_WRAP(L) val) { - bool failed = !val; - - if(at & assertType::is_false) //!OCLINT bitwise operator in conditional - failed = !failed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val))); - DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val))); - return !failed; - } - - struct DOCTEST_INTERFACE IExceptionTranslator - { - DOCTEST_DECLARE_INTERFACE(IExceptionTranslator) - virtual bool translate(String&) const = 0; - }; - - template - class ExceptionTranslator : public IExceptionTranslator //!OCLINT destructor of virtual class - { - public: - explicit ExceptionTranslator(String (*translateFunction)(T)) - : m_translateFunction(translateFunction) {} - - bool translate(String& res) const override { -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { - throw; // lgtm [cpp/rethrow-no-exception] - // cppcheck-suppress catchExceptionByValue - } catch(const T& ex) { - res = m_translateFunction(ex); //!OCLINT parameter reassignment - return true; - } catch(...) {} //!OCLINT - empty catch statement -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - static_cast(res); // to silence -Wunused-parameter - return false; - } - - private: - String (*m_translateFunction)(T); - }; - - DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et); - - // ContextScope base class used to allow implementing methods of ContextScope - // that don't depend on the template parameter in doctest.cpp. - struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope { - ContextScopeBase(const ContextScopeBase&) = delete; - - ContextScopeBase& operator=(const ContextScopeBase&) = delete; - ContextScopeBase& operator=(ContextScopeBase&&) = delete; - - ~ContextScopeBase() override = default; - - protected: - ContextScopeBase(); - ContextScopeBase(ContextScopeBase&& other) noexcept; - - void destroy(); - bool need_to_destroy{true}; - }; - - template class ContextScope : public ContextScopeBase - { - L lambda_; - - public: - explicit ContextScope(const L &lambda) : lambda_(lambda) {} - explicit ContextScope(L&& lambda) : lambda_(static_cast(lambda)) { } - - ContextScope(const ContextScope&) = delete; - ContextScope(ContextScope&&) noexcept = default; - - ContextScope& operator=(const ContextScope&) = delete; - ContextScope& operator=(ContextScope&&) = delete; - - void stringify(std::ostream* s) const override { lambda_(s); } - - ~ContextScope() override { - if (need_to_destroy) { - destroy(); - } - } - }; - - struct DOCTEST_INTERFACE MessageBuilder : public MessageData - { - std::ostream* m_stream; - bool logged = false; - - MessageBuilder(const char* file, int line, assertType::Enum severity); - - MessageBuilder(const MessageBuilder&) = delete; - MessageBuilder(MessageBuilder&&) = delete; - - MessageBuilder& operator=(const MessageBuilder&) = delete; - MessageBuilder& operator=(MessageBuilder&&) = delete; - - ~MessageBuilder(); - - // the preferred way of chaining parameters for stringification -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866) - template - MessageBuilder& operator,(const T& in) { - *m_stream << (DOCTEST_STRINGIFY(in)); - return *this; - } -DOCTEST_MSVC_SUPPRESS_WARNING_POP - - // kept here just for backwards-compatibility - the comma operator should be preferred now - template - MessageBuilder& operator<<(const T& in) { return this->operator,(in); } - - // the `,` operator has the lowest operator precedence - if `<<` is used by the user then - // the `,` operator will be called last which is not what we want and thus the `*` operator - // is used first (has higher operator precedence compared to `<<`) so that we guarantee that - // an operator of the MessageBuilder class is called first before the rest of the parameters - template - MessageBuilder& operator*(const T& in) { return this->operator,(in); } - - bool log(); - void react(); - }; - - template - ContextScope MakeContextScope(const L &lambda) { - return ContextScope(lambda); - } -} // namespace detail - -#define DOCTEST_DEFINE_DECORATOR(name, type, def) \ - struct name \ - { \ - type data; \ - name(type in = def) \ - : data(in) {} \ - void fill(detail::TestCase& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - void fill(detail::TestSuite& state) const { state.DOCTEST_CAT(m_, name) = data; } \ - } - -DOCTEST_DEFINE_DECORATOR(test_suite, const char*, ""); -DOCTEST_DEFINE_DECORATOR(description, const char*, ""); -DOCTEST_DEFINE_DECORATOR(skip, bool, true); -DOCTEST_DEFINE_DECORATOR(no_breaks, bool, true); -DOCTEST_DEFINE_DECORATOR(no_output, bool, true); -DOCTEST_DEFINE_DECORATOR(timeout, double, 0); -DOCTEST_DEFINE_DECORATOR(may_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(should_fail, bool, true); -DOCTEST_DEFINE_DECORATOR(expected_failures, int, 0); - -template -int registerExceptionTranslator(String (*translateFunction)(T)) { - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") - static detail::ExceptionTranslator exceptionTranslator(translateFunction); - DOCTEST_CLANG_SUPPRESS_WARNING_POP - detail::registerExceptionTranslatorImpl(&exceptionTranslator); - return 0; -} - -} // namespace doctest - -// in a separate namespace outside of doctest because the DOCTEST_TEST_SUITE macro -// introduces an anonymous namespace in which getCurrentTestSuite gets overridden -namespace doctest_detail_test_suite_ns { -DOCTEST_INTERFACE doctest::detail::TestSuite& getCurrentTestSuite(); -} // namespace doctest_detail_test_suite_ns - -namespace doctest { -#else // DOCTEST_CONFIG_DISABLE -template -int registerExceptionTranslator(String (*)(T)) { - return 0; -} -#endif // DOCTEST_CONFIG_DISABLE - -namespace detail { - using assert_handler = void (*)(const AssertData&); - struct ContextState; -} // namespace detail - -class DOCTEST_INTERFACE Context -{ - detail::ContextState* p; - - void parseArgs(int argc, const char* const* argv, bool withDefaults = false); - -public: - explicit Context(int argc = 0, const char* const* argv = nullptr); - - Context(const Context&) = delete; - Context(Context&&) = delete; - - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; - - ~Context(); // NOLINT(performance-trivially-destructible) - - void applyCommandLine(int argc, const char* const* argv); - - void addFilter(const char* filter, const char* value); - void clearFilters(); - void setOption(const char* option, bool value); - void setOption(const char* option, int value); - void setOption(const char* option, const char* value); - - bool shouldExit(); - - void setAsDefaultForAssertsOutOfTestCases(); - - void setAssertHandler(detail::assert_handler ah); - - void setCout(std::ostream* out); - - int run(); -}; - -namespace TestCaseFailureReason { - enum Enum - { - None = 0, - AssertFailure = 1, // an assertion has failed in the test case - Exception = 2, // test case threw an exception - Crash = 4, // a crash... - TooManyFailedAsserts = 8, // the abort-after option - Timeout = 16, // see the timeout decorator - ShouldHaveFailedButDidnt = 32, // see the should_fail decorator - ShouldHaveFailedAndDid = 64, // see the should_fail decorator - DidntFailExactlyNumTimes = 128, // see the expected_failures decorator - FailedExactlyNumTimes = 256, // see the expected_failures decorator - CouldHaveFailedAndDid = 512 // see the may_fail decorator - }; -} // namespace TestCaseFailureReason - -struct DOCTEST_INTERFACE CurrentTestCaseStats -{ - int numAssertsCurrentTest; - int numAssertsFailedCurrentTest; - double seconds; - int failure_flags; // use TestCaseFailureReason::Enum - bool testCaseSuccess; -}; - -struct DOCTEST_INTERFACE TestCaseException -{ - String error_string; - bool is_crash; -}; - -struct DOCTEST_INTERFACE TestRunStats -{ - unsigned numTestCases; - unsigned numTestCasesPassingFilters; - unsigned numTestSuitesPassingFilters; - unsigned numTestCasesFailed; - int numAsserts; - int numAssertsFailed; -}; - -struct QueryData -{ - const TestRunStats* run_stats = nullptr; - const TestCaseData** data = nullptr; - unsigned num_data = 0; -}; - -struct DOCTEST_INTERFACE IReporter -{ - // The constructor has to accept "const ContextOptions&" as a single argument - // which has most of the options for the run + a pointer to the stdout stream - // Reporter(const ContextOptions& in) - - // called when a query should be reported (listing test cases, printing the version, etc.) - virtual void report_query(const QueryData&) = 0; - - // called when the whole test run starts - virtual void test_run_start() = 0; - // called when the whole test run ends (caching a pointer to the input doesn't make sense here) - virtual void test_run_end(const TestRunStats&) = 0; - - // called when a test case is started (safe to cache a pointer to the input) - virtual void test_case_start(const TestCaseData&) = 0; - // called when a test case is reentered because of unfinished subcases (safe to cache a pointer to the input) - virtual void test_case_reenter(const TestCaseData&) = 0; - // called when a test case has ended - virtual void test_case_end(const CurrentTestCaseStats&) = 0; - - // called when an exception is thrown from the test case (or it crashes) - virtual void test_case_exception(const TestCaseException&) = 0; - - // called whenever a subcase is entered (don't cache pointers to the input) - virtual void subcase_start(const SubcaseSignature&) = 0; - // called whenever a subcase is exited (don't cache pointers to the input) - virtual void subcase_end() = 0; - - // called for each assert (don't cache pointers to the input) - virtual void log_assert(const AssertData&) = 0; - // called for each message (don't cache pointers to the input) - virtual void log_message(const MessageData&) = 0; - - // called when a test case is skipped either because it doesn't pass the filters, has a skip decorator - // or isn't in the execution range (between first and last) (safe to cache a pointer to the input) - virtual void test_case_skipped(const TestCaseData&) = 0; - - DOCTEST_DECLARE_INTERFACE(IReporter) - - // can obtain all currently active contexts and stringify them if one wishes to do so - static int get_num_active_contexts(); - static const IContextScope* const* get_active_contexts(); - - // can iterate through contexts which have been stringified automatically in their destructors when an exception has been thrown - static int get_num_stringified_contexts(); - static const String* get_stringified_contexts(); -}; - -namespace detail { - using reporterCreatorFunc = IReporter* (*)(const ContextOptions&); - - DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter); - - template - IReporter* reporterCreator(const ContextOptions& o) { - return new Reporter(o); - } -} // namespace detail - -template -int registerReporter(const char* name, int priority, bool isReporter) { - detail::registerReporterImpl(name, priority, detail::reporterCreator, isReporter); - return 0; -} -} // namespace doctest - -#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_EMPTY [] { return false; }() -#else -#define DOCTEST_FUNC_EMPTY (void)0 -#endif - -// if registering is not disabled -#ifndef DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES -#define DOCTEST_FUNC_SCOPE_BEGIN [&] -#define DOCTEST_FUNC_SCOPE_END () -#define DOCTEST_FUNC_SCOPE_RET(v) return v -#else -#define DOCTEST_FUNC_SCOPE_BEGIN do -#define DOCTEST_FUNC_SCOPE_END while(false) -#define DOCTEST_FUNC_SCOPE_RET(v) (void)0 -#endif - -// common code in asserts - for convenience -#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \ - if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \ - b.react(); \ - DOCTEST_FUNC_SCOPE_RET(!b.m_failed) - -#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#define DOCTEST_WRAP_IN_TRY(x) x; -#else // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS -#define DOCTEST_WRAP_IN_TRY(x) \ - try { \ - x; \ - } catch(...) { DOCTEST_RB.translateException(); } -#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS - -#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(...) \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wuseless-cast") \ - static_cast(__VA_ARGS__); \ - DOCTEST_GCC_SUPPRESS_WARNING_POP -#else // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS -#define DOCTEST_CAST_TO_VOID(...) __VA_ARGS__; -#endif // DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS - -// registers the test by initializing a dummy var with a function -#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \ - global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \ - doctest::detail::regTest( \ - doctest::detail::TestCase( \ - f, __FILE__, __LINE__, \ - doctest_detail_test_suite_ns::getCurrentTestSuite()) * \ - decorators)) - -#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \ - namespace { /* NOLINT */ \ - struct der : public base \ - { \ - void f(); \ - }; \ - static DOCTEST_INLINE_NOINLINE void func() { \ - der v; \ - v.f(); \ - } \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \ - } \ - DOCTEST_INLINE_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers) - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \ - static void f(); \ - DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, f, decorators) \ - static void f() - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \ - static doctest::detail::funcType proxy() { return f; } \ - DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \ - static void f() - -// for registering tests -#define DOCTEST_TEST_CASE(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) - -// for registering tests in classes - requires C++17 for inline variables! -#if DOCTEST_CPLUSPLUS >= 201703L -#define DOCTEST_TEST_CASE_CLASS(decorators) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \ - decorators) -#else // DOCTEST_TEST_CASE_CLASS -#define DOCTEST_TEST_CASE_CLASS(...) \ - TEST_CASES_CAN_BE_REGISTERED_IN_CLASSES_ONLY_IN_CPP17_MODE_OR_WITH_VS_2017_OR_NEWER -#endif // DOCTEST_TEST_CASE_CLASS - -// for registering tests with a fixture -#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators) - -// for converting types to strings without the header and demangling -#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \ - namespace doctest { \ - template <> \ - inline String toString<__VA_ARGS__>() { \ - return str; \ - } \ - } \ - static_assert(true, "") - -#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__) - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \ - template \ - static void func(); \ - namespace { /* NOLINT */ \ - template \ - struct iter; \ - template \ - struct iter> \ - { \ - iter(const char* file, unsigned line, int index) { \ - doctest::detail::regTest(doctest::detail::TestCase(func, file, line, \ - doctest_detail_test_suite_ns::getCurrentTestSuite(), \ - doctest::toString(), \ - int(line) * 1000 + index) \ - * dec); \ - iter>(file, line, index + 1); \ - } \ - }; \ - template <> \ - struct iter> \ - { \ - iter(const char*, unsigned, int) {} \ - }; \ - } \ - template \ - static void func() - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)) - -#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \ - doctest::detail::instantiationHelper( \ - DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0))) - -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \ - static_assert(true, "") - -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \ - static_assert(true, "") - -#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \ - DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(anon, anon, std::tuple<__VA_ARGS__>) \ - template \ - static void anon() - -#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \ - DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) - -// for subcases -#define DOCTEST_SUBCASE(name) \ - if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \ - doctest::detail::Subcase(name, __FILE__, __LINE__)) - -// for grouping tests in test suites by using code blocks -#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \ - namespace ns_name { namespace doctest_detail_test_suite_ns { \ - static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \ - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \ - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \ - static doctest::detail::TestSuite data{}; \ - static bool inited = false; \ - DOCTEST_MSVC_SUPPRESS_WARNING_POP \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP \ - DOCTEST_GCC_SUPPRESS_WARNING_POP \ - if(!inited) { \ - data* decorators; \ - inited = true; \ - } \ - return data; \ - } \ - } \ - } \ - namespace ns_name - -#define DOCTEST_TEST_SUITE(decorators) \ - DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_)) - -// for starting a testsuite block -#define DOCTEST_TEST_SUITE_BEGIN(decorators) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \ - static_assert(true, "") - -// for ending a testsuite block -#define DOCTEST_TEST_SUITE_END \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \ - using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int - -// for registering exception translators -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \ - inline doctest::String translatorName(signature); \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerExceptionTranslator(translatorName)) \ - doctest::String translatorName(signature) - -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \ - signature) - -// for registering reporters -#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, true)) \ - static_assert(true, "") - -// for registering listeners -#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \ - DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \ - doctest::registerReporter(name, priority, false)) \ - static_assert(true, "") - -// clang-format off -// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557 -#define DOCTEST_INFO(...) \ - DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \ - __VA_ARGS__) -// clang-format on - -#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \ - auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \ - [&](std::ostream* s_name) { \ - doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ - mb_name.m_stream = s_name; \ - mb_name * __VA_ARGS__; \ - }) - -#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) - -#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb * __VA_ARGS__; \ - if(mb.log()) \ - DOCTEST_BREAK_INTO_DEBUGGER(); \ - mb.react(); \ - } DOCTEST_FUNC_SCOPE_END - -// clang-format off -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__) -// clang-format on - -#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) -#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) - -#define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. - -#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \ - DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \ - } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY( \ - DOCTEST_RB.binary_assert( \ - __VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END - -#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -// necessary for _MESSAGE -#define DOCTEST_ASSERT_IMPLEMENT_2 DOCTEST_ASSERT_IMPLEMENT_1 - -#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \ - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \ - doctest::detail::decomp_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, \ - doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \ - << __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP - -#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \ - doctest::detail::binary_assert( \ - doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__) - -#define DOCTEST_UNARY_ASSERT(assert_type, ...) \ - doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \ - #__VA_ARGS__, __VA_ARGS__) - -#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS - -#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__) -#define DOCTEST_CHECK(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK, __VA_ARGS__) -#define DOCTEST_REQUIRE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE, __VA_ARGS__) -#define DOCTEST_WARN_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_CHECK_FALSE, __VA_ARGS__) -#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) - -// clang-format off -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END -// clang-format on - -#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__) -#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__) -#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__) -#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__) -#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__) -#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__) -#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__) -#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__) -#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__) -#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__) -#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__) -#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__) -#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__) -#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__) -#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__) -#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__) -#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__) -#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__) - -#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__) -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__) -#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__) - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #expr, #__VA_ARGS__, message); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(const typename doctest::detail::types::remove_const< \ - typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\ - DOCTEST_RB.translateException(); \ - DOCTEST_RB.m_threw_as = true; \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - if(!doctest::getContextOptions()->no_throw) { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, expr_str, "", __VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(expr) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } else { /* NOLINT(*-else-after-return) */ \ - DOCTEST_FUNC_SCOPE_RET(false); \ - } \ - } DOCTEST_FUNC_SCOPE_END - -#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \ - DOCTEST_FUNC_SCOPE_BEGIN { \ - doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \ - __LINE__, #__VA_ARGS__); \ - try { \ - DOCTEST_CAST_TO_VOID(__VA_ARGS__) \ - } catch(...) { DOCTEST_RB.translateException(); } \ - DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \ - } DOCTEST_FUNC_SCOPE_END - -// clang-format off -#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "") -#define DOCTEST_CHECK_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_CHECK_THROWS, "") -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_REQUIRE_THROWS, "") - -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_AS, "", __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_AS, "", __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_AS, "", __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_WARN_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_CHECK_THROWS_WITH, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_ASSERT_THROWS_WITH(expr, #expr, DT_REQUIRE_THROWS_WITH, __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_WARN_THROWS_WITH_AS, message, __VA_ARGS__) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_CHECK_THROWS_WITH_AS, message, __VA_ARGS__) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, message, ...) DOCTEST_ASSERT_THROWS_AS(expr, DT_REQUIRE_THROWS_WITH_AS, message, __VA_ARGS__) - -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_WARN_NOTHROW, __VA_ARGS__) -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END -// clang-format on - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -// ================================================================================================= -// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == -// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == -// ================================================================================================= -#else // DOCTEST_CONFIG_DISABLE - -#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ - namespace /* NOLINT */ { \ - template \ - struct der : public base \ - { void f(); }; \ - } \ - template \ - inline void der::f() - -#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ - template \ - static inline void f() - -// for registering tests -#define DOCTEST_TEST_CASE(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) - -// for registering tests in classes -#define DOCTEST_TEST_CASE_CLASS(name) \ - DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) - -// for registering tests with a fixture -#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ - DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \ - DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name) - -// for converting types to strings without the header and demangling -#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "") -#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "") - -// for typed tests -#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() - -#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \ - template \ - inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)() - -#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "") -#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "") - -// for subcases -#define DOCTEST_SUBCASE(name) - -// for a testsuite block -#define DOCTEST_TEST_SUITE(name) namespace // NOLINT - -// for starting a testsuite block -#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "") - -// for ending a testsuite block -#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int - -#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \ - template \ - static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature) - -#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) - -#define DOCTEST_INFO(...) (static_cast(0)) -#define DOCTEST_CAPTURE(x) (static_cast(0)) -#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast(0)) -#define DOCTEST_MESSAGE(...) (static_cast(0)) -#define DOCTEST_FAIL_CHECK(...) (static_cast(0)) -#define DOCTEST_FAIL(...) (static_cast(0)) - -#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \ - && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES) - -#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }() - -#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }() -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }() - -namespace doctest { -namespace detail { -#define DOCTEST_RELATIONAL_OP(name, op) \ - template \ - bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; } - - DOCTEST_RELATIONAL_OP(eq, ==) - DOCTEST_RELATIONAL_OP(ne, !=) - DOCTEST_RELATIONAL_OP(lt, <) - DOCTEST_RELATIONAL_OP(gt, >) - DOCTEST_RELATIONAL_OP(le, <=) - DOCTEST_RELATIONAL_OP(ge, >=) -} // namespace detail -} // namespace doctest - -#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }() -#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }() -#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }() -#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }() -#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }() -#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }() -#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }() -#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() -#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }() - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }() -#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,) - -#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }() -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }() -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }() - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED - -#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - -#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED - -#endif // DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS - -#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY -#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS -#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \ - "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }() - -#undef DOCTEST_REQUIRE -#undef DOCTEST_REQUIRE_FALSE -#undef DOCTEST_REQUIRE_MESSAGE -#undef DOCTEST_REQUIRE_FALSE_MESSAGE -#undef DOCTEST_REQUIRE_EQ -#undef DOCTEST_REQUIRE_NE -#undef DOCTEST_REQUIRE_GT -#undef DOCTEST_REQUIRE_LT -#undef DOCTEST_REQUIRE_GE -#undef DOCTEST_REQUIRE_LE -#undef DOCTEST_REQUIRE_UNARY -#undef DOCTEST_REQUIRE_UNARY_FALSE - -#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS - -#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC - -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - -// clang-format off -// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS -#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ -#define DOCTEST_FAST_CHECK_EQ DOCTEST_CHECK_EQ -#define DOCTEST_FAST_REQUIRE_EQ DOCTEST_REQUIRE_EQ -#define DOCTEST_FAST_WARN_NE DOCTEST_WARN_NE -#define DOCTEST_FAST_CHECK_NE DOCTEST_CHECK_NE -#define DOCTEST_FAST_REQUIRE_NE DOCTEST_REQUIRE_NE -#define DOCTEST_FAST_WARN_GT DOCTEST_WARN_GT -#define DOCTEST_FAST_CHECK_GT DOCTEST_CHECK_GT -#define DOCTEST_FAST_REQUIRE_GT DOCTEST_REQUIRE_GT -#define DOCTEST_FAST_WARN_LT DOCTEST_WARN_LT -#define DOCTEST_FAST_CHECK_LT DOCTEST_CHECK_LT -#define DOCTEST_FAST_REQUIRE_LT DOCTEST_REQUIRE_LT -#define DOCTEST_FAST_WARN_GE DOCTEST_WARN_GE -#define DOCTEST_FAST_CHECK_GE DOCTEST_CHECK_GE -#define DOCTEST_FAST_REQUIRE_GE DOCTEST_REQUIRE_GE -#define DOCTEST_FAST_WARN_LE DOCTEST_WARN_LE -#define DOCTEST_FAST_CHECK_LE DOCTEST_CHECK_LE -#define DOCTEST_FAST_REQUIRE_LE DOCTEST_REQUIRE_LE - -#define DOCTEST_FAST_WARN_UNARY DOCTEST_WARN_UNARY -#define DOCTEST_FAST_CHECK_UNARY DOCTEST_CHECK_UNARY -#define DOCTEST_FAST_REQUIRE_UNARY DOCTEST_REQUIRE_UNARY -#define DOCTEST_FAST_WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE -#define DOCTEST_FAST_CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE -#define DOCTEST_FAST_REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE - -#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id,__VA_ARGS__) -// clang-format on - -// BDD style macros -// clang-format off -#define DOCTEST_SCENARIO(name) DOCTEST_TEST_CASE(" Scenario: " name) -#define DOCTEST_SCENARIO_CLASS(name) DOCTEST_TEST_CASE_CLASS(" Scenario: " name) -#define DOCTEST_SCENARIO_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(" Scenario: " name, T, __VA_ARGS__) -#define DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(" Scenario: " name, T, id) - -#define DOCTEST_GIVEN(name) DOCTEST_SUBCASE(" Given: " name) -#define DOCTEST_WHEN(name) DOCTEST_SUBCASE(" When: " name) -#define DOCTEST_AND_WHEN(name) DOCTEST_SUBCASE("And when: " name) -#define DOCTEST_THEN(name) DOCTEST_SUBCASE(" Then: " name) -#define DOCTEST_AND_THEN(name) DOCTEST_SUBCASE(" And: " name) -// clang-format on - -// == SHORT VERSIONS OF THE MACROS -#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES - -#define TEST_CASE(name) DOCTEST_TEST_CASE(name) -#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name) -#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name) -#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__) -#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__) -#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id) -#define TEST_CASE_TEMPLATE_INVOKE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, __VA_ARGS__) -#define TEST_CASE_TEMPLATE_APPLY(id, ...) DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, __VA_ARGS__) -#define SUBCASE(name) DOCTEST_SUBCASE(name) -#define TEST_SUITE(decorators) DOCTEST_TEST_SUITE(decorators) -#define TEST_SUITE_BEGIN(name) DOCTEST_TEST_SUITE_BEGIN(name) -#define TEST_SUITE_END DOCTEST_TEST_SUITE_END -#define REGISTER_EXCEPTION_TRANSLATOR(signature) DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) -#define REGISTER_REPORTER(name, priority, reporter) DOCTEST_REGISTER_REPORTER(name, priority, reporter) -#define REGISTER_LISTENER(name, priority, reporter) DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define INFO(...) DOCTEST_INFO(__VA_ARGS__) -#define CAPTURE(x) DOCTEST_CAPTURE(x) -#define ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_MESSAGE_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_FAIL_CHECK_AT(file, line, __VA_ARGS__) -#define ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_FAIL_AT(file, line, __VA_ARGS__) -#define MESSAGE(...) DOCTEST_MESSAGE(__VA_ARGS__) -#define FAIL_CHECK(...) DOCTEST_FAIL_CHECK(__VA_ARGS__) -#define FAIL(...) DOCTEST_FAIL(__VA_ARGS__) -#define TO_LVALUE(...) DOCTEST_TO_LVALUE(__VA_ARGS__) - -#define WARN(...) DOCTEST_WARN(__VA_ARGS__) -#define WARN_FALSE(...) DOCTEST_WARN_FALSE(__VA_ARGS__) -#define WARN_THROWS(...) DOCTEST_WARN_THROWS(__VA_ARGS__) -#define WARN_THROWS_AS(expr, ...) DOCTEST_WARN_THROWS_AS(expr, __VA_ARGS__) -#define WARN_THROWS_WITH(expr, ...) DOCTEST_WARN_THROWS_WITH(expr, __VA_ARGS__) -#define WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_WARN_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define WARN_NOTHROW(...) DOCTEST_WARN_NOTHROW(__VA_ARGS__) -#define CHECK(...) DOCTEST_CHECK(__VA_ARGS__) -#define CHECK_FALSE(...) DOCTEST_CHECK_FALSE(__VA_ARGS__) -#define CHECK_THROWS(...) DOCTEST_CHECK_THROWS(__VA_ARGS__) -#define CHECK_THROWS_AS(expr, ...) DOCTEST_CHECK_THROWS_AS(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH(expr, ...) DOCTEST_CHECK_THROWS_WITH(expr, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define CHECK_NOTHROW(...) DOCTEST_CHECK_NOTHROW(__VA_ARGS__) -#define REQUIRE(...) DOCTEST_REQUIRE(__VA_ARGS__) -#define REQUIRE_FALSE(...) DOCTEST_REQUIRE_FALSE(__VA_ARGS__) -#define REQUIRE_THROWS(...) DOCTEST_REQUIRE_THROWS(__VA_ARGS__) -#define REQUIRE_THROWS_AS(expr, ...) DOCTEST_REQUIRE_THROWS_AS(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH(expr, ...) DOCTEST_REQUIRE_THROWS_WITH(expr, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, __VA_ARGS__) -#define REQUIRE_NOTHROW(...) DOCTEST_REQUIRE_NOTHROW(__VA_ARGS__) - -#define WARN_MESSAGE(cond, ...) DOCTEST_WARN_MESSAGE(cond, __VA_ARGS__) -#define WARN_FALSE_MESSAGE(cond, ...) DOCTEST_WARN_FALSE_MESSAGE(cond, __VA_ARGS__) -#define WARN_THROWS_MESSAGE(expr, ...) DOCTEST_WARN_THROWS_MESSAGE(expr, __VA_ARGS__) -#define WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_WARN_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define CHECK_MESSAGE(cond, ...) DOCTEST_CHECK_MESSAGE(cond, __VA_ARGS__) -#define CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_CHECK_FALSE_MESSAGE(cond, __VA_ARGS__) -#define CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_CHECK_THROWS_MESSAGE(expr, __VA_ARGS__) -#define CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_CHECK_NOTHROW_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_MESSAGE(cond, ...) DOCTEST_REQUIRE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_REQUIRE_FALSE_MESSAGE(cond, __VA_ARGS__) -#define REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_REQUIRE_THROWS_MESSAGE(expr, __VA_ARGS__) -#define REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, __VA_ARGS__) -#define REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, __VA_ARGS__) -#define REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, __VA_ARGS__) - -#define SCENARIO(name) DOCTEST_SCENARIO(name) -#define SCENARIO_CLASS(name) DOCTEST_SCENARIO_CLASS(name) -#define SCENARIO_TEMPLATE(name, T, ...) DOCTEST_SCENARIO_TEMPLATE(name, T, __VA_ARGS__) -#define SCENARIO_TEMPLATE_DEFINE(name, T, id) DOCTEST_SCENARIO_TEMPLATE_DEFINE(name, T, id) -#define GIVEN(name) DOCTEST_GIVEN(name) -#define WHEN(name) DOCTEST_WHEN(name) -#define AND_WHEN(name) DOCTEST_AND_WHEN(name) -#define THEN(name) DOCTEST_THEN(name) -#define AND_THEN(name) DOCTEST_AND_THEN(name) - -#define WARN_EQ(...) DOCTEST_WARN_EQ(__VA_ARGS__) -#define CHECK_EQ(...) DOCTEST_CHECK_EQ(__VA_ARGS__) -#define REQUIRE_EQ(...) DOCTEST_REQUIRE_EQ(__VA_ARGS__) -#define WARN_NE(...) DOCTEST_WARN_NE(__VA_ARGS__) -#define CHECK_NE(...) DOCTEST_CHECK_NE(__VA_ARGS__) -#define REQUIRE_NE(...) DOCTEST_REQUIRE_NE(__VA_ARGS__) -#define WARN_GT(...) DOCTEST_WARN_GT(__VA_ARGS__) -#define CHECK_GT(...) DOCTEST_CHECK_GT(__VA_ARGS__) -#define REQUIRE_GT(...) DOCTEST_REQUIRE_GT(__VA_ARGS__) -#define WARN_LT(...) DOCTEST_WARN_LT(__VA_ARGS__) -#define CHECK_LT(...) DOCTEST_CHECK_LT(__VA_ARGS__) -#define REQUIRE_LT(...) DOCTEST_REQUIRE_LT(__VA_ARGS__) -#define WARN_GE(...) DOCTEST_WARN_GE(__VA_ARGS__) -#define CHECK_GE(...) DOCTEST_CHECK_GE(__VA_ARGS__) -#define REQUIRE_GE(...) DOCTEST_REQUIRE_GE(__VA_ARGS__) -#define WARN_LE(...) DOCTEST_WARN_LE(__VA_ARGS__) -#define CHECK_LE(...) DOCTEST_CHECK_LE(__VA_ARGS__) -#define REQUIRE_LE(...) DOCTEST_REQUIRE_LE(__VA_ARGS__) -#define WARN_UNARY(...) DOCTEST_WARN_UNARY(__VA_ARGS__) -#define CHECK_UNARY(...) DOCTEST_CHECK_UNARY(__VA_ARGS__) -#define REQUIRE_UNARY(...) DOCTEST_REQUIRE_UNARY(__VA_ARGS__) -#define WARN_UNARY_FALSE(...) DOCTEST_WARN_UNARY_FALSE(__VA_ARGS__) -#define CHECK_UNARY_FALSE(...) DOCTEST_CHECK_UNARY_FALSE(__VA_ARGS__) -#define REQUIRE_UNARY_FALSE(...) DOCTEST_REQUIRE_UNARY_FALSE(__VA_ARGS__) - -// KEPT FOR BACKWARDS COMPATIBILITY -#define FAST_WARN_EQ(...) DOCTEST_FAST_WARN_EQ(__VA_ARGS__) -#define FAST_CHECK_EQ(...) DOCTEST_FAST_CHECK_EQ(__VA_ARGS__) -#define FAST_REQUIRE_EQ(...) DOCTEST_FAST_REQUIRE_EQ(__VA_ARGS__) -#define FAST_WARN_NE(...) DOCTEST_FAST_WARN_NE(__VA_ARGS__) -#define FAST_CHECK_NE(...) DOCTEST_FAST_CHECK_NE(__VA_ARGS__) -#define FAST_REQUIRE_NE(...) DOCTEST_FAST_REQUIRE_NE(__VA_ARGS__) -#define FAST_WARN_GT(...) DOCTEST_FAST_WARN_GT(__VA_ARGS__) -#define FAST_CHECK_GT(...) DOCTEST_FAST_CHECK_GT(__VA_ARGS__) -#define FAST_REQUIRE_GT(...) DOCTEST_FAST_REQUIRE_GT(__VA_ARGS__) -#define FAST_WARN_LT(...) DOCTEST_FAST_WARN_LT(__VA_ARGS__) -#define FAST_CHECK_LT(...) DOCTEST_FAST_CHECK_LT(__VA_ARGS__) -#define FAST_REQUIRE_LT(...) DOCTEST_FAST_REQUIRE_LT(__VA_ARGS__) -#define FAST_WARN_GE(...) DOCTEST_FAST_WARN_GE(__VA_ARGS__) -#define FAST_CHECK_GE(...) DOCTEST_FAST_CHECK_GE(__VA_ARGS__) -#define FAST_REQUIRE_GE(...) DOCTEST_FAST_REQUIRE_GE(__VA_ARGS__) -#define FAST_WARN_LE(...) DOCTEST_FAST_WARN_LE(__VA_ARGS__) -#define FAST_CHECK_LE(...) DOCTEST_FAST_CHECK_LE(__VA_ARGS__) -#define FAST_REQUIRE_LE(...) DOCTEST_FAST_REQUIRE_LE(__VA_ARGS__) - -#define FAST_WARN_UNARY(...) DOCTEST_FAST_WARN_UNARY(__VA_ARGS__) -#define FAST_CHECK_UNARY(...) DOCTEST_FAST_CHECK_UNARY(__VA_ARGS__) -#define FAST_REQUIRE_UNARY(...) DOCTEST_FAST_REQUIRE_UNARY(__VA_ARGS__) -#define FAST_WARN_UNARY_FALSE(...) DOCTEST_FAST_WARN_UNARY_FALSE(__VA_ARGS__) -#define FAST_CHECK_UNARY_FALSE(...) DOCTEST_FAST_CHECK_UNARY_FALSE(__VA_ARGS__) -#define FAST_REQUIRE_UNARY_FALSE(...) DOCTEST_FAST_REQUIRE_UNARY_FALSE(__VA_ARGS__) - -#define TEST_CASE_TEMPLATE_INSTANTIATE(id, ...) DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE(id, __VA_ARGS__) - -#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES - -#ifndef DOCTEST_CONFIG_DISABLE - -// this is here to clear the 'current test suite' for the current translation unit - at the top -DOCTEST_TEST_SUITE_END(); - -#endif // DOCTEST_CONFIG_DISABLE - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_POP - -#endif // DOCTEST_LIBRARY_INCLUDED - -#ifndef DOCTEST_SINGLE_HEADER -#define DOCTEST_SINGLE_HEADER -#endif // DOCTEST_SINGLE_HEADER - -#if defined(DOCTEST_CONFIG_IMPLEMENT) || !defined(DOCTEST_SINGLE_HEADER) - -#ifndef DOCTEST_SINGLE_HEADER -#include "doctest_fwd.h" -#endif // DOCTEST_SINGLE_HEADER - -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros") - -#ifndef DOCTEST_LIBRARY_IMPLEMENTATION -#define DOCTEST_LIBRARY_IMPLEMENTATION - -DOCTEST_CLANG_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH - -DOCTEST_CLANG_SUPPRESS_WARNING_PUSH -DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function") -DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path") - -DOCTEST_GCC_SUPPRESS_WARNING_PUSH -DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum") -DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations") -DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast") -DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function") -DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance") -DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute") - -DOCTEST_MSVC_SUPPRESS_WARNING_PUSH -DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data -DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled -DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified -DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal -DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch -DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C -DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning) -DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed - -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN - -// required includes - will go only in one translation unit! -#include -#include -#include -// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37 -#ifdef __BORLANDC__ -#include -#endif // __BORLANDC__ -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM -#include -#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM -#include -#include -#include -#ifndef DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#define DOCTEST_DECLARE_MUTEX(name) std::mutex name; -#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) std::lock_guard DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name); -#else // DOCTEST_CONFIG_NO_MULTITHREADING -#define DOCTEST_DECLARE_MUTEX(name) -#define DOCTEST_DECLARE_STATIC_MUTEX(name) -#define DOCTEST_LOCK_MUTEX(name) -#endif // DOCTEST_CONFIG_NO_MULTITHREADING -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DOCTEST_PLATFORM_MAC -#include -#include -#include -#endif // DOCTEST_PLATFORM_MAC - -#ifdef DOCTEST_PLATFORM_WINDOWS - -// defines for a leaner windows.h -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#define DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN -#endif // WIN32_LEAN_AND_MEAN -#ifndef NOMINMAX -#define NOMINMAX -#define DOCTEST_UNDEF_NOMINMAX -#endif // NOMINMAX - -// not sure what AfxWin.h is for - here I do what Catch does -#ifdef __AFXDLL -#include -#else -#include -#endif -#include - -#else // DOCTEST_PLATFORM_WINDOWS - -#include -#include - -#endif // DOCTEST_PLATFORM_WINDOWS - -// this is a fix for https://github.com/doctest/doctest/issues/348 -// https://mail.gnome.org/archives/xml/2012-January/msg00000.html -#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO) -#define STDOUT_FILENO fileno(stdout) -#endif // HAVE_UNISTD_H - -DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END - -// counts the number of elements in a C array -#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) - -#ifdef DOCTEST_CONFIG_DISABLE -#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_disabled -#else // DOCTEST_CONFIG_DISABLE -#define DOCTEST_BRANCH_ON_DISABLED(if_disabled, if_not_disabled) if_not_disabled -#endif // DOCTEST_CONFIG_DISABLE - -#ifndef DOCTEST_CONFIG_OPTIONS_PREFIX -#define DOCTEST_CONFIG_OPTIONS_PREFIX "dt-" -#endif - -#ifndef DOCTEST_THREAD_LOCAL -#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0)) -#define DOCTEST_THREAD_LOCAL -#else // DOCTEST_MSVC -#define DOCTEST_THREAD_LOCAL thread_local -#endif // DOCTEST_MSVC -#endif // DOCTEST_THREAD_LOCAL - -#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES -#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32 -#endif - -#ifndef DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE -#define DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE 64 -#endif - -#ifdef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS -#define DOCTEST_OPTIONS_PREFIX_DISPLAY DOCTEST_CONFIG_OPTIONS_PREFIX -#else -#define DOCTEST_OPTIONS_PREFIX_DISPLAY "" -#endif - -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS -#endif - -#ifndef DOCTEST_CDECL -#define DOCTEST_CDECL __cdecl -#endif - -namespace doctest { - -bool is_running_in_test = false; - -namespace { - using namespace detail; - - template - DOCTEST_NORETURN void throw_exception(Ex const& e) { -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - throw e; -#else // DOCTEST_CONFIG_NO_EXCEPTIONS -#ifdef DOCTEST_CONFIG_HANDLE_EXCEPTION - DOCTEST_CONFIG_HANDLE_EXCEPTION(e); -#else // DOCTEST_CONFIG_HANDLE_EXCEPTION -#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - std::cerr << "doctest will terminate because it needed to throw an exception.\n" - << "The message was: " << e.what() << '\n'; -#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM -#endif // DOCTEST_CONFIG_HANDLE_EXCEPTION - std::terminate(); -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - } - -#ifndef DOCTEST_INTERNAL_ERROR -#define DOCTEST_INTERNAL_ERROR(msg) \ - throw_exception(std::logic_error( \ - __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg)) -#endif // DOCTEST_INTERNAL_ERROR - - // case insensitive strcmp - int stricmp(const char* a, const char* b) { - for(;; a++, b++) { - const int d = tolower(*a) - tolower(*b); - if(d != 0 || !*a) - return d; - } - } - - struct Endianness - { - enum Arch - { - Big, - Little - }; - - static Arch which() { - int x = 1; - // casting any data pointer to char* is allowed - auto ptr = reinterpret_cast(&x); - if(*ptr) - return Little; - return Big; - } - }; -} // namespace - -namespace detail { - DOCTEST_THREAD_LOCAL class - { - std::vector stack; - std::stringstream ss; - - public: - std::ostream* push() { - stack.push_back(ss.tellp()); - return &ss; - } - - String pop() { - if (stack.empty()) - DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!"); - - std::streampos pos = stack.back(); - stack.pop_back(); - unsigned sz = static_cast(ss.tellp() - pos); - ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out); - return String(ss, sz); - } - } g_oss; - - std::ostream* tlssPush() { - return g_oss.push(); - } - - String tlssPop() { - return g_oss.pop(); - } - -#ifndef DOCTEST_CONFIG_DISABLE - -namespace timer_large_integer -{ - -#if defined(DOCTEST_PLATFORM_WINDOWS) - using type = ULONGLONG; -#else // DOCTEST_PLATFORM_WINDOWS - using type = std::uint64_t; -#endif // DOCTEST_PLATFORM_WINDOWS -} - -using ticks_t = timer_large_integer::type; - -#ifdef DOCTEST_CONFIG_GETCURRENTTICKS - ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); } -#elif defined(DOCTEST_PLATFORM_WINDOWS) - ticks_t getCurrentTicks() { - static LARGE_INTEGER hz = { {0} }, hzo = { {0} }; - if(!hz.QuadPart) { - QueryPerformanceFrequency(&hz); - QueryPerformanceCounter(&hzo); - } - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return ((t.QuadPart - hzo.QuadPart) * LONGLONG(1000000)) / hz.QuadPart; - } -#else // DOCTEST_PLATFORM_WINDOWS - ticks_t getCurrentTicks() { - timeval t; - gettimeofday(&t, nullptr); - return static_cast(t.tv_sec) * 1000000 + static_cast(t.tv_usec); - } -#endif // DOCTEST_PLATFORM_WINDOWS - - struct Timer - { - void start() { m_ticks = getCurrentTicks(); } - unsigned int getElapsedMicroseconds() const { - return static_cast(getCurrentTicks() - m_ticks); - } - //unsigned int getElapsedMilliseconds() const { - // return static_cast(getElapsedMicroseconds() / 1000); - //} - double getElapsedSeconds() const { return static_cast(getCurrentTicks() - m_ticks) / 1000000.0; } - - private: - ticks_t m_ticks = 0; - }; - -#ifdef DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = T; -#else // DOCTEST_CONFIG_NO_MULTITHREADING - template - using Atomic = std::atomic; -#endif // DOCTEST_CONFIG_NO_MULTITHREADING - -#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING) - template - using MultiLaneAtomic = Atomic; -#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS - // Provides a multilane implementation of an atomic variable that supports add, sub, load, - // store. Instead of using a single atomic variable, this splits up into multiple ones, - // each sitting on a separate cache line. The goal is to provide a speedup when most - // operations are modifying. It achieves this with two properties: - // - // * Multiple atomics are used, so chance of congestion from the same atomic is reduced. - // * Each atomic sits on a separate cache line, so false sharing is reduced. - // - // The disadvantage is that there is a small overhead due to the use of TLS, and load/store - // is slower because all atomics have to be accessed. - template - class MultiLaneAtomic - { - struct CacheLineAlignedAtomic - { - Atomic atomic{}; - char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic)]; - }; - CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES]; - - static_assert(sizeof(CacheLineAlignedAtomic) == DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE, - "guarantee one atomic takes exactly one cache line"); - - public: - T operator++() DOCTEST_NOEXCEPT { return fetch_add(1) + 1; } - - T operator++(int) DOCTEST_NOEXCEPT { return fetch_add(1); } - - T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_add(arg, order); - } - - T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - return myAtomic().fetch_sub(arg, order); - } - - operator T() const DOCTEST_NOEXCEPT { return load(); } - - T load(std::memory_order order = std::memory_order_seq_cst) const DOCTEST_NOEXCEPT { - auto result = T(); - for(auto const& c : m_atomics) { - result += c.atomic.load(order); - } - return result; - } - - T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this] - store(desired); - return desired; - } - - void store(T desired, std::memory_order order = std::memory_order_seq_cst) DOCTEST_NOEXCEPT { - // first value becomes desired", all others become 0. - for(auto& c : m_atomics) { - c.atomic.store(desired, order); - desired = {}; - } - } - - private: - // Each thread has a different atomic that it operates on. If more than NumLanes threads - // use this, some will use the same atomic. So performance will degrade a bit, but still - // everything will work. - // - // The logic here is a bit tricky. The call should be as fast as possible, so that there - // is minimal to no overhead in determining the correct atomic for the current thread. - // - // 1. A global static counter laneCounter counts continuously up. - // 2. Each successive thread will use modulo operation of that counter so it gets an atomic - // assigned in a round-robin fashion. - // 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with - // little overhead. - Atomic& myAtomic() DOCTEST_NOEXCEPT { - static Atomic laneCounter; - DOCTEST_THREAD_LOCAL size_t tlsLaneIdx = - laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES; - - return m_atomics[tlsLaneIdx].atomic; - } - }; -#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS - - // this holds both parameters from the command line and runtime data for tests - struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats - { - MultiLaneAtomic numAssertsCurrentTest_atomic; - MultiLaneAtomic numAssertsFailedCurrentTest_atomic; - - std::vector> filters = decltype(filters)(9); // 9 different filters - - std::vector reporters_currently_used; - - assert_handler ah = nullptr; - - Timer timer; - - std::vector stringifiedContexts; // logging from INFO() due to an exception - - // stuff for subcases - bool reachedLeaf; - std::vector subcaseStack; - std::vector nextSubcaseStack; - std::unordered_set fullyTraversedSubcases; - size_t currentSubcaseDepth; - Atomic shouldLogCurrentException; - - void resetRunData() { - numTestCases = 0; - numTestCasesPassingFilters = 0; - numTestSuitesPassingFilters = 0; - numTestCasesFailed = 0; - numAsserts = 0; - numAssertsFailed = 0; - numAssertsCurrentTest = 0; - numAssertsFailedCurrentTest = 0; - } - - void finalizeTestCaseData() { - seconds = timer.getElapsedSeconds(); - - // update the non-atomic counters - numAsserts += numAssertsCurrentTest_atomic; - numAssertsFailed += numAssertsFailedCurrentTest_atomic; - numAssertsCurrentTest = numAssertsCurrentTest_atomic; - numAssertsFailedCurrentTest = numAssertsFailedCurrentTest_atomic; - - if(numAssertsFailedCurrentTest) - failure_flags |= TestCaseFailureReason::AssertFailure; - - if(Approx(currentTest->m_timeout).epsilon(DBL_EPSILON) != 0 && - Approx(seconds).epsilon(DBL_EPSILON) > currentTest->m_timeout) - failure_flags |= TestCaseFailureReason::Timeout; - - if(currentTest->m_should_fail) { - if(failure_flags) { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedAndDid; - } else { - failure_flags |= TestCaseFailureReason::ShouldHaveFailedButDidnt; - } - } else if(failure_flags && currentTest->m_may_fail) { - failure_flags |= TestCaseFailureReason::CouldHaveFailedAndDid; - } else if(currentTest->m_expected_failures > 0) { - if(numAssertsFailedCurrentTest == currentTest->m_expected_failures) { - failure_flags |= TestCaseFailureReason::FailedExactlyNumTimes; - } else { - failure_flags |= TestCaseFailureReason::DidntFailExactlyNumTimes; - } - } - - bool ok_to_fail = (TestCaseFailureReason::ShouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::CouldHaveFailedAndDid & failure_flags) || - (TestCaseFailureReason::FailedExactlyNumTimes & failure_flags); - - // if any subcase has failed - the whole test case has failed - testCaseSuccess = !(failure_flags && !ok_to_fail); - if(!testCaseSuccess) - numTestCasesFailed++; - } - }; - - ContextState* g_cs = nullptr; - - // used to avoid locks for the debug output - // TODO: figure out if this is indeed necessary/correct - seems like either there still - // could be a race or that there wouldn't be a race even if using the context directly - DOCTEST_THREAD_LOCAL bool g_no_colors; - -#endif // DOCTEST_CONFIG_DISABLE -} // namespace detail - -char* String::allocate(size_type sz) { - if (sz <= last) { - buf[sz] = '\0'; - setLast(last - sz); - return buf; - } else { - setOnHeap(); - data.size = sz; - data.capacity = data.size + 1; - data.ptr = new char[data.capacity]; - data.ptr[sz] = '\0'; - return data.ptr; - } -} - -void String::setOnHeap() noexcept { *reinterpret_cast(&buf[last]) = 128; } -void String::setLast(size_type in) noexcept { buf[last] = char(in); } -void String::setSize(size_type sz) noexcept { - if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); } - else { data.ptr[sz] = '\0'; data.size = sz; } -} - -void String::copy(const String& other) { - if(other.isOnStack()) { - memcpy(buf, other.buf, len); - } else { - memcpy(allocate(other.data.size), other.data.ptr, other.data.size); - } -} - -String::String() noexcept { - buf[0] = '\0'; - setLast(); -} - -String::~String() { - if(!isOnStack()) - delete[] data.ptr; -} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks) - -String::String(const char* in) - : String(in, strlen(in)) {} - -String::String(const char* in, size_type in_size) { - memcpy(allocate(in_size), in, in_size); -} - -String::String(std::istream& in, size_type in_size) { - in.read(allocate(in_size), in_size); -} - -String::String(const String& other) { copy(other); } - -String& String::operator=(const String& other) { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; - - copy(other); - } - - return *this; -} - -String& String::operator+=(const String& other) { - const size_type my_old_size = size(); - const size_type other_size = other.size(); - const size_type total_size = my_old_size + other_size; - if(isOnStack()) { - if(total_size < len) { - // append to the current stack space - memcpy(buf + my_old_size, other.c_str(), other_size + 1); - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) - setLast(last - total_size); - } else { - // alloc new chunk - char* temp = new char[total_size + 1]; - // copy current data to new location before writing in the union - memcpy(temp, buf, my_old_size); // skip the +1 ('\0') for speed - // update data in union - setOnHeap(); - data.size = total_size; - data.capacity = data.size + 1; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } else { - if(data.capacity > total_size) { - // append to the current heap block - data.size = total_size; - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } else { - // resize - data.capacity *= 2; - if(data.capacity <= total_size) - data.capacity = total_size + 1; - // alloc new chunk - char* temp = new char[data.capacity]; - // copy current data to new location before releasing it - memcpy(temp, data.ptr, my_old_size); // skip the +1 ('\0') for speed - // release old chunk - delete[] data.ptr; - // update the rest of the union members - data.size = total_size; - data.ptr = temp; - // transfer the rest of the data - memcpy(data.ptr + my_old_size, other.c_str(), other_size + 1); - } - } - - return *this; -} - -String::String(String&& other) noexcept { - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); -} - -String& String::operator=(String&& other) noexcept { - if(this != &other) { - if(!isOnStack()) - delete[] data.ptr; - memcpy(buf, other.buf, len); - other.buf[0] = '\0'; - other.setLast(); - } - return *this; -} - -char String::operator[](size_type i) const { - return const_cast(this)->operator[](i); -} - -char& String::operator[](size_type i) { - if(isOnStack()) - return reinterpret_cast(buf)[i]; - return data.ptr[i]; -} - -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized") -String::size_type String::size() const { - if(isOnStack()) - return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32 - return data.size; -} -DOCTEST_GCC_SUPPRESS_WARNING_POP - -String::size_type String::capacity() const { - if(isOnStack()) - return len; - return data.capacity; -} - -String String::substr(size_type pos, size_type cnt) && { - cnt = std::min(cnt, size() - 1 - pos); - char* cptr = c_str(); - memmove(cptr, cptr + pos, cnt); - setSize(cnt); - return std::move(*this); -} - -String String::substr(size_type pos, size_type cnt) const & { - cnt = std::min(cnt, size() - 1 - pos); - return String{ c_str() + pos, cnt }; -} - -String::size_type String::find(char ch, size_type pos) const { - const char* begin = c_str(); - const char* end = begin + size(); - const char* it = begin + pos; - for (; it < end && *it != ch; it++); - if (it < end) { return static_cast(it - begin); } - else { return npos; } -} - -String::size_type String::rfind(char ch, size_type pos) const { - const char* begin = c_str(); - const char* it = begin + std::min(pos, size() - 1); - for (; it >= begin && *it != ch; it--); - if (it >= begin) { return static_cast(it - begin); } - else { return npos; } -} - -int String::compare(const char* other, bool no_case) const { - if(no_case) - return doctest::stricmp(c_str(), other); - return std::strcmp(c_str(), other); -} - -int String::compare(const String& other, bool no_case) const { - return compare(other.c_str(), no_case); -} - -String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; } - -bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } -bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } -bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } -bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } -bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } -bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } - -std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); } - -Contains::Contains(const String& str) : string(str) { } - -bool Contains::checkWith(const String& other) const { - return strstr(other.c_str(), string.c_str()) != nullptr; -} - -String toString(const Contains& in) { - return "Contains( " + in.string + " )"; -} - -bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); } -bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); } -bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); } -bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); } - -namespace { - void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;) -} // namespace - -namespace Color { - std::ostream& operator<<(std::ostream& s, Color::Enum code) { - color_to_stream(s, code); - return s; - } -} // namespace Color - -// clang-format off -const char* assertString(assertType::Enum at) { - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitly handled - #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type - #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \ - DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type) - switch(at) { - DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN); - DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK); - DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE); - - DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY); - DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE); - - default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!"); - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP -} -// clang-format on - -const char* failureString(assertType::Enum at) { - if(at & assertType::is_warn) //!OCLINT bitwise operator in conditional - return "WARNING"; - if(at & assertType::is_check) //!OCLINT bitwise operator in conditional - return "ERROR"; - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return "FATAL ERROR"; - return ""; -} - -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") -// depending on the current options this will remove the path of filenames -const char* skipPathFromFilename(const char* file) { -#ifndef DOCTEST_CONFIG_DISABLE - if(getContextOptions()->no_path_in_filenames) { - auto back = std::strrchr(file, '\\'); - auto forward = std::strrchr(file, '/'); - if(back || forward) { - if(back > forward) - forward = back; - return forward + 1; - } - } -#endif // DOCTEST_CONFIG_DISABLE - return file; -} -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -bool SubcaseSignature::operator==(const SubcaseSignature& other) const { - return m_line == other.m_line - && std::strcmp(m_file, other.m_file) == 0 - && m_name == other.m_name; -} - -bool SubcaseSignature::operator<(const SubcaseSignature& other) const { - if(m_line != other.m_line) - return m_line < other.m_line; - if(std::strcmp(m_file, other.m_file) != 0) - return std::strcmp(m_file, other.m_file) < 0; - return m_name.compare(other.m_name) < 0; -} - -DOCTEST_DEFINE_INTERFACE(IContextScope) - -namespace detail { - void filldata::fill(std::ostream* stream, const void* in) { - if (in) { *stream << in; } - else { *stream << "nullptr"; } - } - - template - String toStreamLit(T t) { - std::ostream* os = tlssPush(); - os->operator<<(t); - return tlssPop(); - } -} - -#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING -String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } -#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING - -#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0) -// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183 -String toString(const std::string& in) { return in.c_str(); } -#endif // VS 2019 - -String toString(String in) { return in; } - -String toString(std::nullptr_t) { return "nullptr"; } - -String toString(bool in) { return in ? "true" : "false"; } - -String toString(float in) { return toStreamLit(in); } -String toString(double in) { return toStreamLit(in); } -String toString(double long in) { return toStreamLit(in); } - -String toString(char in) { return toStreamLit(static_cast(in)); } -String toString(char signed in) { return toStreamLit(static_cast(in)); } -String toString(char unsigned in) { return toStreamLit(static_cast(in)); } -String toString(short in) { return toStreamLit(in); } -String toString(short unsigned in) { return toStreamLit(in); } -String toString(signed in) { return toStreamLit(in); } -String toString(unsigned in) { return toStreamLit(in); } -String toString(long in) { return toStreamLit(in); } -String toString(long unsigned in) { return toStreamLit(in); } -String toString(long long in) { return toStreamLit(in); } -String toString(long long unsigned in) { return toStreamLit(in); } - -Approx::Approx(double value) - : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) - , m_scale(1.0) - , m_value(value) {} - -Approx Approx::operator()(double value) const { - Approx approx(value); - approx.epsilon(m_epsilon); - approx.scale(m_scale); - return approx; -} - -Approx& Approx::epsilon(double newEpsilon) { - m_epsilon = newEpsilon; - return *this; -} -Approx& Approx::scale(double newScale) { - m_scale = newScale; - return *this; -} - -bool operator==(double lhs, const Approx& rhs) { - // Thanks to Richard Harris for his help refining this formula - return std::fabs(lhs - rhs.m_value) < - rhs.m_epsilon * (rhs.m_scale + std::max(std::fabs(lhs), std::fabs(rhs.m_value))); -} -bool operator==(const Approx& lhs, double rhs) { return operator==(rhs, lhs); } -bool operator!=(double lhs, const Approx& rhs) { return !operator==(lhs, rhs); } -bool operator!=(const Approx& lhs, double rhs) { return !operator==(rhs, lhs); } -bool operator<=(double lhs, const Approx& rhs) { return lhs < rhs.m_value || lhs == rhs; } -bool operator<=(const Approx& lhs, double rhs) { return lhs.m_value < rhs || lhs == rhs; } -bool operator>=(double lhs, const Approx& rhs) { return lhs > rhs.m_value || lhs == rhs; } -bool operator>=(const Approx& lhs, double rhs) { return lhs.m_value > rhs || lhs == rhs; } -bool operator<(double lhs, const Approx& rhs) { return lhs < rhs.m_value && lhs != rhs; } -bool operator<(const Approx& lhs, double rhs) { return lhs.m_value < rhs && lhs != rhs; } -bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs != rhs; } -bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } - -String toString(const Approx& in) { - return "Approx( " + doctest::toString(in.m_value) + " )"; -} -const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } - -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738) -template -IsNaN::operator bool() const { - return std::isnan(value) ^ flipped; -} -DOCTEST_MSVC_SUPPRESS_WARNING_POP -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template struct DOCTEST_INTERFACE_DEF IsNaN; -template -String toString(IsNaN in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } -String toString(IsNaN in) { return toString(in); } - -} // namespace doctest - -#ifdef DOCTEST_CONFIG_DISABLE -namespace doctest { -Context::Context(int, const char* const*) {} -Context::~Context() = default; -void Context::applyCommandLine(int, const char* const*) {} -void Context::addFilter(const char*, const char*) {} -void Context::clearFilters() {} -void Context::setOption(const char*, bool) {} -void Context::setOption(const char*, int) {} -void Context::setOption(const char*, const char*) {} -bool Context::shouldExit() { return false; } -void Context::setAsDefaultForAssertsOutOfTestCases() {} -void Context::setAssertHandler(detail::assert_handler) {} -void Context::setCout(std::ostream*) {} -int Context::run() { return 0; } - -int IReporter::get_num_active_contexts() { return 0; } -const IContextScope* const* IReporter::get_active_contexts() { return nullptr; } -int IReporter::get_num_stringified_contexts() { return 0; } -const String* IReporter::get_stringified_contexts() { return nullptr; } - -int registerReporter(const char*, int, IReporter*) { return 0; } - -} // namespace doctest -#else // DOCTEST_CONFIG_DISABLE - -#if !defined(DOCTEST_CONFIG_COLORS_NONE) -#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI) -#ifdef DOCTEST_PLATFORM_WINDOWS -#define DOCTEST_CONFIG_COLORS_WINDOWS -#else // linux -#define DOCTEST_CONFIG_COLORS_ANSI -#endif // platform -#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI -#endif // DOCTEST_CONFIG_COLORS_NONE - -namespace doctest_detail_test_suite_ns { -// holds the current test suite -doctest::detail::TestSuite& getCurrentTestSuite() { - static doctest::detail::TestSuite data{}; - return data; -} -} // namespace doctest_detail_test_suite_ns - -namespace doctest { -namespace { - // the int (priority) is part of the key for automatic sorting - sadly one can register a - // reporter with a duplicate name and a different priority but hopefully that won't happen often :| - using reporterMap = std::map, reporterCreatorFunc>; - - reporterMap& getReporters() { - static reporterMap data; - return data; - } - reporterMap& getListeners() { - static reporterMap data; - return data; - } -} // namespace -namespace detail { -#define DOCTEST_ITERATE_THROUGH_REPORTERS(function, ...) \ - for(auto& curr_rep : g_cs->reporters_currently_used) \ - curr_rep->function(__VA_ARGS__) - - bool checkIfShouldThrow(assertType::Enum at) { - if(at & assertType::is_require) //!OCLINT bitwise operator in conditional - return true; - - if((at & assertType::is_check) //!OCLINT bitwise operator in conditional - && getContextOptions()->abort_after > 0 && - (g_cs->numAssertsFailed + g_cs->numAssertsFailedCurrentTest_atomic) >= - getContextOptions()->abort_after) - return true; - - return false; - } - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - DOCTEST_NORETURN void throwException() { - g_cs->shouldLogCurrentException = false; - throw TestFailureException(); // NOLINT(hicpp-exception-baseclass) - } -#else // DOCTEST_CONFIG_NO_EXCEPTIONS - void throwException() {} -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -} // namespace detail - -namespace { - using namespace detail; - // matching of a string against a wildcard mask (case sensitivity configurable) taken from - // https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing - int wildcmp(const char* str, const char* wild, bool caseSensitive) { - const char* cp = str; - const char* mp = wild; - - while((*str) && (*wild != '*')) { - if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && - (*wild != '?')) { - return 0; - } - wild++; - str++; - } - - while(*str) { - if(*wild == '*') { - if(!*++wild) { - return 1; - } - mp = wild; - cp = str + 1; - } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || - (*wild == '?')) { - wild++; - str++; - } else { - wild = mp; //!OCLINT parameter reassignment - str = cp++; //!OCLINT parameter reassignment - } - } - - while(*wild == '*') { - wild++; - } - return !*wild; - } - - // checks if the name matches any of the filters (and can be configured what to do when empty) - bool matchesAny(const char* name, const std::vector& filters, bool matchEmpty, - bool caseSensitive) { - if (filters.empty() && matchEmpty) - return true; - for (auto& curr : filters) - if (wildcmp(name, curr.c_str(), caseSensitive)) - return true; - return false; - } - - DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(unsigned long long a, unsigned long long b) { - return (a << 5) + b; - } - - // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html - DOCTEST_NO_SANITIZE_INTEGER - unsigned long long hash(const char* str) { - unsigned long long hash = 5381; - char c; - while ((c = *str++)) - hash = ((hash << 5) + hash) + c; // hash * 33 + c - return hash; - } - - unsigned long long hash(const SubcaseSignature& sig) { - return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line); - } - - unsigned long long hash(const std::vector& sigs, size_t count) { - unsigned long long running = 0; - auto end = sigs.begin() + count; - for (auto it = sigs.begin(); it != end; it++) { - running = hash(running, hash(*it)); - } - return running; - } - - unsigned long long hash(const std::vector& sigs) { - unsigned long long running = 0; - for (const SubcaseSignature& sig : sigs) { - running = hash(running, hash(sig)); - } - return running; - } -} // namespace -namespace detail { - bool Subcase::checkFilters() { - if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) { - if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive)) - return true; - if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive)) - return true; - } - return false; - } - - Subcase::Subcase(const String& name, const char* file, int line) - : m_signature({name, file, line}) { - if (!g_cs->reachedLeaf) { - if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size() - || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) { - // Going down. - if (checkFilters()) { return; } - - g_cs->subcaseStack.push_back(m_signature); - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } - } else { - if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) { - // This subcase is reentered via control flow. - g_cs->currentSubcaseDepth++; - m_entered = true; - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature); - } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth - && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature))) - == g_cs->fullyTraversedSubcases.end()) { - if (checkFilters()) { return; } - // This subcase is part of the one to be executed next. - g_cs->nextSubcaseStack.clear(); - g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(), - g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth); - g_cs->nextSubcaseStack.push_back(m_signature); - } - } - } - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - - Subcase::~Subcase() { - if (m_entered) { - g_cs->currentSubcaseDepth--; - - if (!g_cs->reachedLeaf) { - // Leaf. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - g_cs->nextSubcaseStack.clear(); - g_cs->reachedLeaf = true; - } else if (g_cs->nextSubcaseStack.empty()) { - // All children are finished. - g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack)); - } - -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0 -#else - if(std::uncaught_exception() -#endif - && g_cs->shouldLogCurrentException) { - DOCTEST_ITERATE_THROUGH_REPORTERS( - test_case_exception, {"exception thrown in subcase - will translate later " - "when the whole test case has been exited (cannot " - "translate while there is an active exception)", - false}); - g_cs->shouldLogCurrentException = false; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } - } - - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP - DOCTEST_MSVC_SUPPRESS_WARNING_POP - - Subcase::operator bool() const { return m_entered; } - - Result::Result(bool passed, const String& decomposition) - : m_passed(passed) - , m_decomp(decomposition) {} - - ExpressionDecomposer::ExpressionDecomposer(assertType::Enum at) - : m_at(at) {} - - TestSuite& TestSuite::operator*(const char* in) { - m_test_suite = in; - return *this; - } - - TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite, - const String& type, int template_id) { - m_file = file; - m_line = line; - m_name = nullptr; // will be later overridden in operator* - m_test_suite = test_suite.m_test_suite; - m_description = test_suite.m_description; - m_skip = test_suite.m_skip; - m_no_breaks = test_suite.m_no_breaks; - m_no_output = test_suite.m_no_output; - m_may_fail = test_suite.m_may_fail; - m_should_fail = test_suite.m_should_fail; - m_expected_failures = test_suite.m_expected_failures; - m_timeout = test_suite.m_timeout; - - m_test = test; - m_type = type; - m_template_id = template_id; - } - - TestCase::TestCase(const TestCase& other) - : TestCaseData() { - *this = other; - } - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function - TestCase& TestCase::operator=(const TestCase& other) { - TestCaseData::operator=(other); - m_test = other.m_test; - m_type = other.m_type; - m_template_id = other.m_template_id; - m_full_name = other.m_full_name; - - if(m_template_id != -1) - m_name = m_full_name.c_str(); - return *this; - } - DOCTEST_MSVC_SUPPRESS_WARNING_POP - - TestCase& TestCase::operator*(const char* in) { - m_name = in; - // make a new name with an appended type for templated test case - if(m_template_id != -1) { - m_full_name = String(m_name) + "<" + m_type + ">"; - // redirect the name to point to the newly constructed full name - m_name = m_full_name.c_str(); - } - return *this; - } - - bool TestCase::operator<(const TestCase& other) const { - // this will be used only to differentiate between test cases - not relevant for sorting - if(m_line != other.m_line) - return m_line < other.m_line; - const int name_cmp = strcmp(m_name, other.m_name); - if(name_cmp != 0) - return name_cmp < 0; - const int file_cmp = m_file.compare(other.m_file); - if(file_cmp != 0) - return file_cmp < 0; - return m_template_id < other.m_template_id; - } - - // all the registered tests - std::set& getRegisteredTests() { - static std::set data; - return data; - } -} // namespace detail -namespace { - using namespace detail; - // for sorting tests by file/line - bool fileOrderComparator(const TestCase* lhs, const TestCase* rhs) { - // this is needed because MSVC gives different case for drive letters - // for __FILE__ when evaluated in a header and a source file - const int res = lhs->m_file.compare(rhs->m_file, bool(DOCTEST_MSVC)); - if(res != 0) - return res < 0; - if(lhs->m_line != rhs->m_line) - return lhs->m_line < rhs->m_line; - return lhs->m_template_id < rhs->m_template_id; - } - - // for sorting tests by suite/file/line - bool suiteOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_test_suite, rhs->m_test_suite); - if(res != 0) - return res < 0; - return fileOrderComparator(lhs, rhs); - } - - // for sorting tests by name/suite/file/line - bool nameOrderComparator(const TestCase* lhs, const TestCase* rhs) { - const int res = std::strcmp(lhs->m_name, rhs->m_name); - if(res != 0) - return res < 0; - return suiteOrderComparator(lhs, rhs); - } - - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - void color_to_stream(std::ostream& s, Color::Enum code) { - static_cast(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS - static_cast(code); // for DOCTEST_CONFIG_COLORS_NONE -#ifdef DOCTEST_CONFIG_COLORS_ANSI - if(g_no_colors || - (isatty(STDOUT_FILENO) == false && getContextOptions()->force_colors == false)) - return; - - auto col = ""; - // clang-format off - switch(code) { //!OCLINT missing break in switch statement / unnecessary default statement in covered switch statement - case Color::Red: col = "[0;31m"; break; - case Color::Green: col = "[0;32m"; break; - case Color::Blue: col = "[0;34m"; break; - case Color::Cyan: col = "[0;36m"; break; - case Color::Yellow: col = "[0;33m"; break; - case Color::Grey: col = "[1;30m"; break; - case Color::LightGrey: col = "[0;37m"; break; - case Color::BrightRed: col = "[1;31m"; break; - case Color::BrightGreen: col = "[1;32m"; break; - case Color::BrightWhite: col = "[1;37m"; break; - case Color::Bright: // invalid - case Color::None: - case Color::White: - default: col = "[0m"; - } - // clang-format on - s << "\033" << col; -#endif // DOCTEST_CONFIG_COLORS_ANSI - -#ifdef DOCTEST_CONFIG_COLORS_WINDOWS - if(g_no_colors || - (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false)) - return; - - static struct ConsoleHelper { - HANDLE stdoutHandle; - WORD origFgAttrs; - WORD origBgAttrs; - - ConsoleHelper() { - stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); - CONSOLE_SCREEN_BUFFER_INFO csbiInfo; - GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); - origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | - BACKGROUND_BLUE | BACKGROUND_INTENSITY); - origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | - FOREGROUND_BLUE | FOREGROUND_INTENSITY); - } - } ch; - -#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs) - - // clang-format off - switch (code) { - case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; - case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; - case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; - case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; - case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; - case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; - case Color::Grey: DOCTEST_SET_ATTR(0); break; - case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; - case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; - case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; - case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; - case Color::None: - case Color::Bright: // invalid - default: DOCTEST_SET_ATTR(ch.origFgAttrs); - } - // clang-format on -#endif // DOCTEST_CONFIG_COLORS_WINDOWS - } - DOCTEST_CLANG_SUPPRESS_WARNING_POP - - std::vector& getExceptionTranslators() { - static std::vector data; - return data; - } - - String translateActiveException() { -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - String res; - auto& translators = getExceptionTranslators(); - for(auto& curr : translators) - if(curr->translate(res)) - return res; - // clang-format off - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wcatch-value") - try { - throw; - } catch(std::exception& ex) { - return ex.what(); - } catch(std::string& msg) { - return msg.c_str(); - } catch(const char* msg) { - return msg; - } catch(...) { - return "unknown exception"; - } - DOCTEST_GCC_SUPPRESS_WARNING_POP -// clang-format on -#else // DOCTEST_CONFIG_NO_EXCEPTIONS - return ""; -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - } -} // namespace - -namespace detail { - // used by the macros for registering tests - int regTest(const TestCase& tc) { - getRegisteredTests().insert(tc); - return 0; - } - - // sets the current test suite - int setTestSuite(const TestSuite& ts) { - doctest_detail_test_suite_ns::getCurrentTestSuite() = ts; - return 0; - } - -#ifdef DOCTEST_IS_DEBUGGER_ACTIVE - bool isDebuggerActive() { return DOCTEST_IS_DEBUGGER_ACTIVE(); } -#else // DOCTEST_IS_DEBUGGER_ACTIVE -#ifdef DOCTEST_PLATFORM_LINUX - class ErrnoGuard { - public: - ErrnoGuard() : m_oldErrno(errno) {} - ~ErrnoGuard() { errno = m_oldErrno; } - private: - int m_oldErrno; - }; - // See the comments in Catch2 for the reasoning behind this implementation: - // https://github.com/catchorg/Catch2/blob/v2.13.1/include/internal/catch_debugger.cpp#L79-L102 - bool isDebuggerActive() { - ErrnoGuard guard; - std::ifstream in("/proc/self/status"); - for(std::string line; std::getline(in, line);) { - static const int PREFIX_LEN = 11; - if(line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) { - return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; - } - } - return false; - } -#elif defined(DOCTEST_PLATFORM_MAC) - // The following function is taken directly from the following technical note: - // https://developer.apple.com/library/archive/qa/qa1361/_index.html - // Returns true if the current process is being debugged (either - // running under the debugger or has a debugger attached post facto). - bool isDebuggerActive() { - int mib[4]; - kinfo_proc info; - size_t size; - // Initialize the flags so that, if sysctl fails for some bizarre - // reason, we get a predictable result. - info.kp_proc.p_flag = 0; - // Initialize mib, which tells sysctl the info we want, in this case - // we're looking for information about a specific process ID. - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = getpid(); - // Call sysctl. - size = sizeof(info); - if(sysctl(mib, DOCTEST_COUNTOF(mib), &info, &size, 0, 0) != 0) { - std::cerr << "\nCall to sysctl failed - unable to determine if debugger is active **\n"; - return false; - } - // We're being debugged if the P_TRACED flag is set. - return ((info.kp_proc.p_flag & P_TRACED) != 0); - } -#elif DOCTEST_MSVC || defined(__MINGW32__) || defined(__MINGW64__) - bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } -#else - bool isDebuggerActive() { return false; } -#endif // Platform -#endif // DOCTEST_IS_DEBUGGER_ACTIVE - - void registerExceptionTranslatorImpl(const IExceptionTranslator* et) { - if(std::find(getExceptionTranslators().begin(), getExceptionTranslators().end(), et) == - getExceptionTranslators().end()) - getExceptionTranslators().push_back(et); - } - - DOCTEST_THREAD_LOCAL std::vector g_infoContexts; // for logging with INFO() - - ContextScopeBase::ContextScopeBase() { - g_infoContexts.push_back(this); - } - - ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept { - if (other.need_to_destroy) { - other.destroy(); - } - other.need_to_destroy = false; - g_infoContexts.push_back(this); - } - - DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17 - DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") - - // destroy cannot be inlined into the destructor because that would mean calling stringify after - // ContextScope has been destroyed (base class destructors run after derived class destructors). - // Instead, ContextScope calls this method directly from its destructor. - void ContextScopeBase::destroy() { -#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200) - if(std::uncaught_exceptions() > 0) { -#else - if(std::uncaught_exception()) { -#endif - std::ostringstream s; - this->stringify(&s); - g_cs->stringifiedContexts.push_back(s.str().c_str()); - } - g_infoContexts.pop_back(); - } - - DOCTEST_CLANG_SUPPRESS_WARNING_POP - DOCTEST_GCC_SUPPRESS_WARNING_POP - DOCTEST_MSVC_SUPPRESS_WARNING_POP -} // namespace detail -namespace { - using namespace detail; - -#if !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && !defined(DOCTEST_CONFIG_WINDOWS_SEH) - struct FatalConditionHandler - { - static void reset() {} - static void allocateAltStackMem() {} - static void freeAltStackMem() {} - }; -#else // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - - void reportFatal(const std::string&); - -#ifdef DOCTEST_PLATFORM_WINDOWS - - struct SignalDefs - { - DWORD id; - const char* name; - }; - // There is no 1-1 mapping between signals and windows exceptions. - // Windows can easily distinguish between SO and SigSegV, - // but SigInt, SigTerm, etc are handled differently. - SignalDefs signalDefs[] = { - {static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), - "SIGILL - Illegal instruction signal"}, - {static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, - {static_cast(EXCEPTION_ACCESS_VIOLATION), - "SIGSEGV - Segmentation violation signal"}, - {static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, - }; - - struct FatalConditionHandler - { - static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the - // console just once no matter how many threads have crashed. - DOCTEST_DECLARE_STATIC_MUTEX(mutex) - static bool execute = true; - { - DOCTEST_LOCK_MUTEX(mutex) - if(execute) { - bool reported = false; - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - reported = true; - break; - } - } - if(reported == false) - reportFatal("Unhandled SEH exception caught"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - } - execute = false; - } - std::exit(EXIT_FAILURE); - } - - static void allocateAltStackMem() {} - static void freeAltStackMem() {} - - FatalConditionHandler() { - isSet = true; - // 32k seems enough for doctest to handle stack overflow, - // but the value was found experimentally, so there is no strong guarantee - guaranteeSize = 32 * 1024; - // Register an unhandled exception filter - previousTop = SetUnhandledExceptionFilter(handleException); - // Pass in guarantee size to be filled - SetThreadStackGuarantee(&guaranteeSize); - - // On Windows uncaught exceptions from another thread, exceptions from - // destructors, or calls to std::terminate are not a SEH exception - - // The terminal handler gets called when: - // - std::terminate is called FROM THE TEST RUNNER THREAD - // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD - original_terminate_handler = std::get_terminate(); - std::set_terminate([]() DOCTEST_NOEXCEPT { - reportFatal("Terminate handler called"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well - }); - - // SIGABRT is raised when: - // - std::terminate is called FROM A DIFFERENT THREAD - // - an exception is thrown from a destructor FROM A DIFFERENT THREAD - // - an uncaught exception is thrown FROM A DIFFERENT THREAD - prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) DOCTEST_NOEXCEPT { - if(signal == SIGABRT) { - reportFatal("SIGABRT - Abort (abnormal termination) signal"); - if(isDebuggerActive() && !g_cs->no_breaks) - DOCTEST_BREAK_INTO_DEBUGGER(); - std::exit(EXIT_FAILURE); - } - }); - - // The following settings are taken from google test, and more - // specifically from UnitTest::Run() inside of gtest.cc - - // the user does not want to see pop-up dialogs about crashes - prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | - SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); - // This forces the abort message to go to stderr in all circumstances. - prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); - // In the debug version, Visual Studio pops up a separate dialog - // offering a choice to debug the aborted program - we want to disable that. - prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - // In debug mode, the Windows CRT can crash with an assertion over invalid - // input (e.g. passing an invalid file descriptor). The default handling - // for these assertions is to pop up a dialog and wait for user input. - // Instead ask the CRT to dump such assertions to stderr non-interactively. - prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); - prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } - - static void reset() { - if(isSet) { - // Unregister handler and restore the old guarantee - SetUnhandledExceptionFilter(previousTop); - SetThreadStackGuarantee(&guaranteeSize); - std::set_terminate(original_terminate_handler); - std::signal(SIGABRT, prev_sigabrt_handler); - SetErrorMode(prev_error_mode_1); - _set_error_mode(prev_error_mode_2); - _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); - static_cast(_CrtSetReportMode(_CRT_ASSERT, prev_report_mode)); - static_cast(_CrtSetReportFile(_CRT_ASSERT, prev_report_file)); - isSet = false; - } - } - - ~FatalConditionHandler() { reset(); } - - private: - static UINT prev_error_mode_1; - static int prev_error_mode_2; - static unsigned int prev_abort_behavior; - static int prev_report_mode; - static _HFILE prev_report_file; - static void (DOCTEST_CDECL *prev_sigabrt_handler)(int); - static std::terminate_handler original_terminate_handler; - static bool isSet; - static ULONG guaranteeSize; - static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; - }; - - UINT FatalConditionHandler::prev_error_mode_1; - int FatalConditionHandler::prev_error_mode_2; - unsigned int FatalConditionHandler::prev_abort_behavior; - int FatalConditionHandler::prev_report_mode; - _HFILE FatalConditionHandler::prev_report_file; - void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int); - std::terminate_handler FatalConditionHandler::original_terminate_handler; - bool FatalConditionHandler::isSet = false; - ULONG FatalConditionHandler::guaranteeSize = 0; - LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; - -#else // DOCTEST_PLATFORM_WINDOWS - - struct SignalDefs - { - int id; - const char* name; - }; - SignalDefs signalDefs[] = {{SIGINT, "SIGINT - Terminal interrupt signal"}, - {SIGILL, "SIGILL - Illegal instruction signal"}, - {SIGFPE, "SIGFPE - Floating point error signal"}, - {SIGSEGV, "SIGSEGV - Segmentation violation signal"}, - {SIGTERM, "SIGTERM - Termination request signal"}, - {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}}; - - struct FatalConditionHandler - { - static bool isSet; - static struct sigaction oldSigActions[DOCTEST_COUNTOF(signalDefs)]; - static stack_t oldSigStack; - static size_t altStackSize; - static char* altStackMem; - - static void handleSignal(int sig) { - const char* name = ""; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - SignalDefs& def = signalDefs[i]; - if(sig == def.id) { - name = def.name; - break; - } - } - reset(); - reportFatal(name); - raise(sig); - } - - static void allocateAltStackMem() { - altStackMem = new char[altStackSize]; - } - - static void freeAltStackMem() { - delete[] altStackMem; - } - - FatalConditionHandler() { - isSet = true; - stack_t sigStack; - sigStack.ss_sp = altStackMem; - sigStack.ss_size = altStackSize; - sigStack.ss_flags = 0; - sigaltstack(&sigStack, &oldSigStack); - struct sigaction sa = {}; - sa.sa_handler = handleSignal; - sa.sa_flags = SA_ONSTACK; - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); - } - } - - ~FatalConditionHandler() { reset(); } - static void reset() { - if(isSet) { - // Set signals back to previous values -- hopefully nobody overwrote them in the meantime - for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); - } - // Return the old stack - sigaltstack(&oldSigStack, nullptr); - isSet = false; - } - } - }; - - bool FatalConditionHandler::isSet = false; - struct sigaction FatalConditionHandler::oldSigActions[DOCTEST_COUNTOF(signalDefs)] = {}; - stack_t FatalConditionHandler::oldSigStack = {}; - size_t FatalConditionHandler::altStackSize = 4 * SIGSTKSZ; - char* FatalConditionHandler::altStackMem = nullptr; - -#endif // DOCTEST_PLATFORM_WINDOWS -#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH - -} // namespace - -namespace { - using namespace detail; - -#ifdef DOCTEST_PLATFORM_WINDOWS -#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text) -#else - // TODO: integration with XCode and other IDEs -#define DOCTEST_OUTPUT_DEBUG_STRING(text) -#endif // Platform - - void addAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsCurrentTest_atomic++; - } - - void addFailedAssert(assertType::Enum at) { - if((at & assertType::is_warn) == 0) //!OCLINT bitwise operator in conditional - g_cs->numAssertsFailedCurrentTest_atomic++; - } - -#if defined(DOCTEST_CONFIG_POSIX_SIGNALS) || defined(DOCTEST_CONFIG_WINDOWS_SEH) - void reportFatal(const std::string& message) { - g_cs->failure_flags |= TestCaseFailureReason::Crash; - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true}); - - while (g_cs->subcaseStack.size()) { - g_cs->subcaseStack.pop_back(); - DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY); - } - - g_cs->finalizeTestCaseData(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); - } -#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH -} // namespace - -AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const StringContains& exception_string) - : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr), - m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type), - m_exception_string(exception_string) { -#if DOCTEST_MSVC - if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC - ++m_expr; -#endif // MSVC -} - -namespace detail { - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const String& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } - - ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr, - const char* exception_type, const Contains& exception_string) - : AssertData(at, file, line, expr, exception_type, exception_string) { } - - void ResultBuilder::setResult(const Result& res) { - m_decomp = res.m_decomp; - m_failed = !res.m_passed; - } - - void ResultBuilder::translateException() { - m_threw = true; - m_exception = translateActiveException(); - } - - bool ResultBuilder::log() { - if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw; - } else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT - m_failed = !m_threw_as || !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - m_failed = !m_threw_as; - } else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - m_failed = !m_exception_string.check(m_exception); - } else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - m_failed = m_threw; - } - - if(m_exception.size()) - m_exception = "\"" + m_exception + "\""; - - if(is_running_in_test) { - addAssert(m_at); - DOCTEST_ITERATE_THROUGH_REPORTERS(log_assert, *this); - - if(m_failed) - addFailedAssert(m_at); - } else if(m_failed) { - failed_out_of_a_testing_context(*this); - } - - return m_failed && isDebuggerActive() && !getContextOptions()->no_breaks && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger - } - - void ResultBuilder::react() const { - if(m_failed && checkIfShouldThrow(m_at)) - throwException(); - } - - void failed_out_of_a_testing_context(const AssertData& ad) { - if(g_cs->ah) - g_cs->ah(ad); - else - std::abort(); - } - - bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr, - const Result& result) { - bool failed = !result.m_passed; - - // ################################################################################### - // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT - // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED - // ################################################################################### - DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); - DOCTEST_ASSERT_IN_TESTS(result.m_decomp); - return !failed; - } - - MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { - m_stream = tlssPush(); - m_file = file; - m_line = line; - m_severity = severity; - } - - MessageBuilder::~MessageBuilder() { - if (!logged) - tlssPop(); - } - - DOCTEST_DEFINE_INTERFACE(IExceptionTranslator) - - bool MessageBuilder::log() { - if (!logged) { - m_string = tlssPop(); - logged = true; - } - - DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this); - - const bool isWarn = m_severity & assertType::is_warn; - - // warn is just a message in this context so we don't treat it as an assert - if(!isWarn) { - addAssert(m_severity); - addFailedAssert(m_severity); - } - - return isDebuggerActive() && !getContextOptions()->no_breaks && !isWarn && - (g_cs->currentTest == nullptr || !g_cs->currentTest->m_no_breaks); // break into debugger - } - - void MessageBuilder::react() { - if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional - throwException(); - } -} // namespace detail -namespace { - using namespace detail; - - // clang-format off - -// ================================================================================================= -// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp -// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. -// ================================================================================================= - - class XmlEncode { - public: - enum ForWhat { ForTextNodes, ForAttributes }; - - XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); - - void encodeTo( std::ostream& os ) const; - - friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); - - private: - std::string m_str; - ForWhat m_forWhat; - }; - - class XmlWriter { - public: - - class ScopedElement { - public: - ScopedElement( XmlWriter* writer ); - - ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT; - ScopedElement& operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT; - - ~ScopedElement(); - - ScopedElement& writeText( std::string const& text, bool indent = true ); - - template - ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { - m_writer->writeAttribute( name, attribute ); - return *this; - } - - private: - mutable XmlWriter* m_writer = nullptr; - }; - -#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - XmlWriter( std::ostream& os = std::cout ); -#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - XmlWriter( std::ostream& os ); -#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - ~XmlWriter(); - - XmlWriter( XmlWriter const& ) = delete; - XmlWriter& operator=( XmlWriter const& ) = delete; - - XmlWriter& startElement( std::string const& name ); - - ScopedElement scopedElement( std::string const& name ); - - XmlWriter& endElement(); - - XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); - - XmlWriter& writeAttribute( std::string const& name, const char* attribute ); - - XmlWriter& writeAttribute( std::string const& name, bool attribute ); - - template - XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - std::stringstream rss; - rss << attribute; - return writeAttribute( name, rss.str() ); - } - - XmlWriter& writeText( std::string const& text, bool indent = true ); - - //XmlWriter& writeComment( std::string const& text ); - - //void writeStylesheetRef( std::string const& url ); - - //XmlWriter& writeBlankLine(); - - void ensureTagClosed(); - - void writeDeclaration(); - - private: - - void newlineIfNecessary(); - - bool m_tagIsOpen = false; - bool m_needsNewline = false; - std::vector m_tags; - std::string m_indent; - std::ostream& m_os; - }; - -// ================================================================================================= -// The following code has been taken verbatim from Catch2/include/internal/catch_xmlwriter.h/cpp -// This is done so cherry-picking bug fixes is trivial - even the style/formatting is untouched. -// ================================================================================================= - -using uchar = unsigned char; - -namespace { - - size_t trailingBytes(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return 2; - } - if ((c & 0xF0) == 0xE0) { - return 3; - } - if ((c & 0xF8) == 0xF0) { - return 4; - } - DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - uint32_t headerValue(unsigned char c) { - if ((c & 0xE0) == 0xC0) { - return c & 0x1F; - } - if ((c & 0xF0) == 0xE0) { - return c & 0x0F; - } - if ((c & 0xF8) == 0xF0) { - return c & 0x07; - } - DOCTEST_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); - } - - void hexEscapeChar(std::ostream& os, unsigned char c) { - std::ios_base::fmtflags f(os.flags()); - os << "\\x" - << std::uppercase << std::hex << std::setfill('0') << std::setw(2) - << static_cast(c); - os.flags(f); - } - -} // anonymous namespace - - XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) - : m_str( str ), - m_forWhat( forWhat ) - {} - - void XmlEncode::encodeTo( std::ostream& os ) const { - // Apostrophe escaping not necessary if we always use " to write attributes - // (see: https://www.w3.org/TR/xml/#syntax) - - for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { - uchar c = m_str[idx]; - switch (c) { - case '<': os << "<"; break; - case '&': os << "&"; break; - - case '>': - // See: https://www.w3.org/TR/xml/#syntax - if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') - os << ">"; - else - os << c; - break; - - case '\"': - if (m_forWhat == ForAttributes) - os << """; - else - os << c; - break; - - default: - // Check for control characters and invalid utf-8 - - // Escape control characters in standard ascii - // see https://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 - if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { - hexEscapeChar(os, c); - break; - } - - // Plain ASCII: Write it to stream - if (c < 0x7F) { - os << c; - break; - } - - // UTF-8 territory - // Check if the encoding is valid and if it is not, hex escape bytes. - // Important: We do not check the exact decoded values for validity, only the encoding format - // First check that this bytes is a valid lead byte: - // This means that it is not encoded as 1111 1XXX - // Or as 10XX XXXX - if (c < 0xC0 || - c >= 0xF8) { - hexEscapeChar(os, c); - break; - } - - auto encBytes = trailingBytes(c); - // Are there enough bytes left to avoid accessing out-of-bounds memory? - if (idx + encBytes - 1 >= m_str.size()) { - hexEscapeChar(os, c); - break; - } - // The header is valid, check data - // The next encBytes bytes must together be a valid utf-8 - // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) - bool valid = true; - uint32_t value = headerValue(c); - for (std::size_t n = 1; n < encBytes; ++n) { - uchar nc = m_str[idx + n]; - valid &= ((nc & 0xC0) == 0x80); - value = (value << 6) | (nc & 0x3F); - } - - if ( - // Wrong bit pattern of following bytes - (!valid) || - // Overlong encodings - (value < 0x80) || - ( value < 0x800 && encBytes > 2) || // removed "0x80 <= value &&" because redundant - (0x800 < value && value < 0x10000 && encBytes > 3) || - // Encoded value out of range - (value >= 0x110000) - ) { - hexEscapeChar(os, c); - break; - } - - // If we got here, this is in fact a valid(ish) utf-8 sequence - for (std::size_t n = 0; n < encBytes; ++n) { - os << m_str[idx + n]; - } - idx += encBytes - 1; - break; - } - } - } - - std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { - xmlEncode.encodeTo( os ); - return os; - } - - XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) - : m_writer( writer ) - {} - - XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) DOCTEST_NOEXCEPT - : m_writer( other.m_writer ){ - other.m_writer = nullptr; - } - XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) DOCTEST_NOEXCEPT { - if ( m_writer ) { - m_writer->endElement(); - } - m_writer = other.m_writer; - other.m_writer = nullptr; - return *this; - } - - - XmlWriter::ScopedElement::~ScopedElement() { - if( m_writer ) - m_writer->endElement(); - } - - XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { - m_writer->writeText( text, indent ); - return *this; - } - - XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) - { - // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627 - } - - XmlWriter::~XmlWriter() { - while( !m_tags.empty() ) - endElement(); - } - - XmlWriter& XmlWriter::startElement( std::string const& name ) { - ensureTagClosed(); - newlineIfNecessary(); - m_os << m_indent << '<' << name; - m_tags.push_back( name ); - m_indent += " "; - m_tagIsOpen = true; - return *this; - } - - XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { - ScopedElement scoped( this ); - startElement( name ); - return scoped; - } - - XmlWriter& XmlWriter::endElement() { - newlineIfNecessary(); - m_indent = m_indent.substr( 0, m_indent.size()-2 ); - if( m_tagIsOpen ) { - m_os << "/>"; - m_tagIsOpen = false; - } - else { - m_os << m_indent << ""; - } - m_os << std::endl; - m_tags.pop_back(); - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, const char* attribute ) { - if( !name.empty() && attribute && attribute[0] != '\0' ) - m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { - m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; - return *this; - } - - XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { - if( !text.empty() ){ - bool tagWasOpen = m_tagIsOpen; - ensureTagClosed(); - if( tagWasOpen && indent ) - m_os << m_indent; - m_os << XmlEncode( text ); - m_needsNewline = true; - } - return *this; - } - - //XmlWriter& XmlWriter::writeComment( std::string const& text ) { - // ensureTagClosed(); - // m_os << m_indent << ""; - // m_needsNewline = true; - // return *this; - //} - - //void XmlWriter::writeStylesheetRef( std::string const& url ) { - // m_os << "\n"; - //} - - //XmlWriter& XmlWriter::writeBlankLine() { - // ensureTagClosed(); - // m_os << '\n'; - // return *this; - //} - - void XmlWriter::ensureTagClosed() { - if( m_tagIsOpen ) { - m_os << ">" << std::endl; - m_tagIsOpen = false; - } - } - - void XmlWriter::writeDeclaration() { - m_os << "\n"; - } - - void XmlWriter::newlineIfNecessary() { - if( m_needsNewline ) { - m_os << std::endl; - m_needsNewline = false; - } - } - -// ================================================================================================= -// End of copy-pasted code from Catch -// ================================================================================================= - - // clang-format on - - struct XmlReporter : public IReporter - { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - XmlReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - std::stringstream ss; - for(int i = 0; i < num_contexts; ++i) { - contexts[i]->stringify(&ss); - xml.scopedElement("Info").writeText(ss.str()); - ss.str(""); - } - } - } - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - void test_case_start_impl(const TestCaseData& in) { - bool open_ts_tag = false; - if(tc != nullptr) { // we have already opened a test suite - if(std::strcmp(tc->m_test_suite, in.m_test_suite) != 0) { - xml.endElement(); - open_ts_tag = true; - } - } - else { - open_ts_tag = true; // first test case ==> first test suite - } - - if(open_ts_tag) { - xml.startElement("TestSuite"); - xml.writeAttribute("name", in.m_test_suite); - } - - tc = ∈ - xml.startElement("TestCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file.c_str())) - .writeAttribute("line", line(in.m_line)) - .writeAttribute("description", in.m_description); - - if(Approx(in.m_timeout) != 0) - xml.writeAttribute("timeout", in.m_timeout); - if(in.m_may_fail) - xml.writeAttribute("may_fail", true); - if(in.m_should_fail) - xml.writeAttribute("should_fail", true); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - test_run_start(); - if(opt.list_reporters) { - for(auto& curr : getListeners()) - xml.scopedElement("Listener") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - for(auto& curr : getReporters()) - xml.scopedElement("Reporter") - .writeAttribute("priority", curr.first.first) - .writeAttribute("name", curr.first.second); - } else if(opt.count || opt.list_test_cases) { - for(unsigned i = 0; i < in.num_data; ++i) { - xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name) - .writeAttribute("testsuite", in.data[i]->m_test_suite) - .writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str())) - .writeAttribute("line", line(in.data[i]->m_line)) - .writeAttribute("skipped", in.data[i]->m_skip); - } - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - } else if(opt.list_test_suites) { - for(unsigned i = 0; i < in.num_data; ++i) - xml.scopedElement("TestSuite").writeAttribute("name", in.data[i]->m_test_suite); - xml.scopedElement("OverallResultsTestCases") - .writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters); - xml.scopedElement("OverallResultsTestSuites") - .writeAttribute("unskipped", in.run_stats->numTestSuitesPassingFilters); - } - xml.endElement(); - } - - void test_run_start() override { - xml.writeDeclaration(); - - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); -#ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); -#endif // DOCTEST_PLATFORM_WINDOWS - - xml.startElement("doctest").writeAttribute("binary", binary_name); - if(opt.no_version == false) - xml.writeAttribute("version", DOCTEST_VERSION_STR); - - // only the consequential ones (TODO: filters) - xml.scopedElement("Options") - .writeAttribute("order_by", opt.order_by.c_str()) - .writeAttribute("rand_seed", opt.rand_seed) - .writeAttribute("first", opt.first) - .writeAttribute("last", opt.last) - .writeAttribute("abort_after", opt.abort_after) - .writeAttribute("subcase_filter_levels", opt.subcase_filter_levels) - .writeAttribute("case_sensitive", opt.case_sensitive) - .writeAttribute("no_throw", opt.no_throw) - .writeAttribute("no_skip", opt.no_skip); - } - - void test_run_end(const TestRunStats& p) override { - if(tc) // the TestSuite tag - only if there has been at least 1 test case - xml.endElement(); - - xml.scopedElement("OverallResultsAsserts") - .writeAttribute("successes", p.numAsserts - p.numAssertsFailed) - .writeAttribute("failures", p.numAssertsFailed); - - xml.startElement("OverallResultsTestCases") - .writeAttribute("successes", - p.numTestCasesPassingFilters - p.numTestCasesFailed) - .writeAttribute("failures", p.numTestCasesFailed); - if(opt.no_skipped_summary == false) - xml.writeAttribute("skipped", p.numTestCases - p.numTestCasesPassingFilters); - xml.endElement(); - - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override { - test_case_start_impl(in); - xml.ensureTagClosed(); - } - - void test_case_reenter(const TestCaseData&) override {} - - void test_case_end(const CurrentTestCaseStats& st) override { - xml.startElement("OverallResultsAsserts") - .writeAttribute("successes", - st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest) - .writeAttribute("failures", st.numAssertsFailedCurrentTest) - .writeAttribute("test_case_success", st.testCaseSuccess); - if(opt.duration) - xml.writeAttribute("duration", st.seconds); - if(tc->m_expected_failures) - xml.writeAttribute("expected_failures", tc->m_expected_failures); - xml.endElement(); - - xml.endElement(); - } - - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.scopedElement("Exception") - .writeAttribute("crash", e.is_crash) - .writeText(e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override { - xml.startElement("SubCase") - .writeAttribute("name", in.m_name) - .writeAttribute("filename", skipPathFromFilename(in.m_file)) - .writeAttribute("line", line(in.m_line)); - xml.ensureTagClosed(); - } - - void subcase_end() override { xml.endElement(); } - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed && !opt.success) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Expression") - .writeAttribute("success", !rb.m_failed) - .writeAttribute("type", assertString(rb.m_at)) - .writeAttribute("filename", skipPathFromFilename(rb.m_file)) - .writeAttribute("line", line(rb.m_line)); - - xml.scopedElement("Original").writeText(rb.m_expr); - - if(rb.m_threw) - xml.scopedElement("Exception").writeText(rb.m_exception.c_str()); - - if(rb.m_at & assertType::is_throws_as) - xml.scopedElement("ExpectedException").writeText(rb.m_exception_type); - if(rb.m_at & assertType::is_throws_with) - xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str()); - if((rb.m_at & assertType::is_normal) && !rb.m_threw) - xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void log_message(const MessageData& mb) override { - DOCTEST_LOCK_MUTEX(mutex) - - xml.startElement("Message") - .writeAttribute("type", failureString(mb.m_severity)) - .writeAttribute("filename", skipPathFromFilename(mb.m_file)) - .writeAttribute("line", line(mb.m_line)); - - xml.scopedElement("Text").writeText(mb.m_string.c_str()); - - log_contexts(); - - xml.endElement(); - } - - void test_case_skipped(const TestCaseData& in) override { - if(opt.no_skipped_summary == false) { - test_case_start_impl(in); - xml.writeAttribute("skipped", "true"); - xml.endElement(); - } - } - }; - - DOCTEST_REGISTER_REPORTER("xml", 0, XmlReporter); - - void fulltext_log_assert_to_stream(std::ostream& s, const AssertData& rb) { - if((rb.m_at & (assertType::is_throws_as | assertType::is_throws_with)) == - 0) //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << " ) " - << Color::None; - - if(rb.m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "threw as expected!" : "did NOT throw at all!") << "\n"; - } else if((rb.m_at & assertType::is_throws_as) && - (rb.m_at & assertType::is_throws_with)) { //!OCLINT - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\", " << rb.m_exception_type << " ) " << Color::None; - if(rb.m_threw) { - if(!rb.m_failed) { - s << "threw as expected!\n"; - } else { - s << "threw a DIFFERENT exception! (contents: " << rb.m_exception << ")\n"; - } - } else { - s << "did NOT throw at all!\n"; - } - } else if(rb.m_at & - assertType::is_throws_as) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", " - << rb.m_exception_type << " ) " << Color::None - << (rb.m_threw ? (rb.m_threw_as ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & - assertType::is_throws_with) { //!OCLINT bitwise operator in conditional - s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \"" - << rb.m_exception_string.c_str() - << "\" ) " << Color::None - << (rb.m_threw ? (!rb.m_failed ? "threw as expected!" : - "threw a DIFFERENT exception: ") : - "did NOT throw at all!") - << Color::Cyan << rb.m_exception << "\n"; - } else if(rb.m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional - s << (rb.m_threw ? "THREW exception: " : "didn't throw!") << Color::Cyan - << rb.m_exception << "\n"; - } else { - s << (rb.m_threw ? "THREW exception: " : - (!rb.m_failed ? "is correct!\n" : "is NOT correct!\n")); - if(rb.m_threw) - s << rb.m_exception << "\n"; - else - s << " values: " << assertString(rb.m_at) << "( " << rb.m_decomp << " )\n"; - } - } - - // TODO: - // - log_message() - // - respond to queries - // - honor remaining options - // - more attributes in tags - struct JUnitReporter : public IReporter - { - XmlWriter xml; - DOCTEST_DECLARE_MUTEX(mutex) - Timer timer; - std::vector deepestSubcaseStackNames; - - struct JUnitTestCaseData - { - static std::string getCurrentTimestamp() { - // Beware, this is not reentrant because of backward compatibility issues - // Also, UTC only, again because of backward compatibility (%z is C++11) - time_t rawtime; - std::time(&rawtime); - auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - - std::tm timeInfo; -#ifdef DOCTEST_PLATFORM_WINDOWS - gmtime_s(&timeInfo, &rawtime); -#else // DOCTEST_PLATFORM_WINDOWS - gmtime_r(&rawtime, &timeInfo); -#endif // DOCTEST_PLATFORM_WINDOWS - - char timeStamp[timeStampSize]; - const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - - std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); - return std::string(timeStamp); - } - - struct JUnitTestMessage - { - JUnitTestMessage(const std::string& _message, const std::string& _type, const std::string& _details) - : message(_message), type(_type), details(_details) {} - - JUnitTestMessage(const std::string& _message, const std::string& _details) - : message(_message), type(), details(_details) {} - - std::string message, type, details; - }; - - struct JUnitTestCase - { - JUnitTestCase(const std::string& _classname, const std::string& _name) - : classname(_classname), name(_name), time(0), failures() {} - - std::string classname, name; - double time; - std::vector failures, errors; - }; - - void add(const std::string& classname, const std::string& name) { - testcases.emplace_back(classname, name); - } - - void appendSubcaseNamesToLastTestcase(std::vector nameStack) { - for(auto& curr: nameStack) - if(curr.size()) - testcases.back().name += std::string("/") + curr.c_str(); - } - - void addTime(double time) { - if(time < 1e-4) - time = 0; - testcases.back().time = time; - totalSeconds += time; - } - - void addFailure(const std::string& message, const std::string& type, const std::string& details) { - testcases.back().failures.emplace_back(message, type, details); - ++totalFailures; - } - - void addError(const std::string& message, const std::string& details) { - testcases.back().errors.emplace_back(message, details); - ++totalErrors; - } - - std::vector testcases; - double totalSeconds = 0; - int totalErrors = 0, totalFailures = 0; - }; - - JUnitTestCaseData testCaseData; - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc = nullptr; - - JUnitReporter(const ContextOptions& co) - : xml(*co.cout) - , opt(co) {} - - unsigned line(unsigned l) const { return opt.no_line_numbers ? 0 : l; } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData&) override { - xml.writeDeclaration(); - } - - void test_run_start() override { - xml.writeDeclaration(); - } - - void test_run_end(const TestRunStats& p) override { - // remove .exe extension - mainly to have the same output on UNIX and Windows - std::string binary_name = skipPathFromFilename(opt.binary_name.c_str()); -#ifdef DOCTEST_PLATFORM_WINDOWS - if(binary_name.rfind(".exe") != std::string::npos) - binary_name = binary_name.substr(0, binary_name.length() - 4); -#endif // DOCTEST_PLATFORM_WINDOWS - xml.startElement("testsuites"); - xml.startElement("testsuite").writeAttribute("name", binary_name) - .writeAttribute("errors", testCaseData.totalErrors) - .writeAttribute("failures", testCaseData.totalFailures) - .writeAttribute("tests", p.numAsserts); - if(opt.no_time_in_output == false) { - xml.writeAttribute("time", testCaseData.totalSeconds); - xml.writeAttribute("timestamp", JUnitTestCaseData::getCurrentTimestamp()); - } - if(opt.no_version == false) - xml.writeAttribute("doctest_version", DOCTEST_VERSION_STR); - - for(const auto& testCase : testCaseData.testcases) { - xml.startElement("testcase") - .writeAttribute("classname", testCase.classname) - .writeAttribute("name", testCase.name); - if(opt.no_time_in_output == false) - xml.writeAttribute("time", testCase.time); - // This is not ideal, but it should be enough to mimic gtest's junit output. - xml.writeAttribute("status", "run"); - - for(const auto& failure : testCase.failures) { - xml.scopedElement("failure") - .writeAttribute("message", failure.message) - .writeAttribute("type", failure.type) - .writeText(failure.details, false); - } - - for(const auto& error : testCase.errors) { - xml.scopedElement("error") - .writeAttribute("message", error.message) - .writeText(error.details); - } - - xml.endElement(); - } - xml.endElement(); - xml.endElement(); - } - - void test_case_start(const TestCaseData& in) override { - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - timer.start(); - } - - void test_case_reenter(const TestCaseData& in) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); - - timer.start(); - testCaseData.add(skipPathFromFilename(in.m_file.c_str()), in.m_name); - } - - void test_case_end(const CurrentTestCaseStats&) override { - testCaseData.addTime(timer.getElapsedSeconds()); - testCaseData.appendSubcaseNamesToLastTestcase(deepestSubcaseStackNames); - deepestSubcaseStackNames.clear(); - } - - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - testCaseData.addError("exception", e.error_string.c_str()); - } - - void subcase_start(const SubcaseSignature& in) override { - deepestSubcaseStackNames.push_back(in.m_name); - } - - void subcase_end() override {} - - void log_assert(const AssertData& rb) override { - if(!rb.m_failed) // report only failures & ignore the `success` option - return; - - DOCTEST_LOCK_MUTEX(mutex) - - std::ostringstream os; - os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; - - fulltext_log_assert_to_stream(os, rb); - log_contexts(os); - testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); - } - - void log_message(const MessageData& mb) override { - if(mb.m_severity & assertType::is_warn) // report only failures - return; - - DOCTEST_LOCK_MUTEX(mutex) - - std::ostringstream os; - os << skipPathFromFilename(mb.m_file) << (opt.gnu_file_line ? ":" : "(") - << line(mb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; - - os << mb.m_string.c_str() << "\n"; - log_contexts(os); - - testCaseData.addFailure(mb.m_string.c_str(), - mb.m_severity & assertType::is_check ? "FAIL_CHECK" : "FAIL", os.str()); - } - - void test_case_skipped(const TestCaseData&) override {} - - void log_contexts(std::ostringstream& s) { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - - s << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << std::endl; - } - } - } - }; - - DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); - - struct Whitespace - { - int nrSpaces; - explicit Whitespace(int nr) - : nrSpaces(nr) {} - }; - - std::ostream& operator<<(std::ostream& out, const Whitespace& ws) { - if(ws.nrSpaces != 0) - out << std::setw(ws.nrSpaces) << ' '; - return out; - } - - struct ConsoleReporter : public IReporter - { - std::ostream& s; - bool hasLoggedCurrentTestStart; - std::vector subcasesStack; - size_t currentSubcaseLevel; - DOCTEST_DECLARE_MUTEX(mutex) - - // caching pointers/references to objects of these types - safe to do - const ContextOptions& opt; - const TestCaseData* tc; - - ConsoleReporter(const ContextOptions& co) - : s(*co.cout) - , opt(co) {} - - ConsoleReporter(const ContextOptions& co, std::ostream& ostr) - : s(ostr) - , opt(co) {} - - // ========================================================================================= - // WHAT FOLLOWS ARE HELPERS USED BY THE OVERRIDES OF THE VIRTUAL METHODS OF THE INTERFACE - // ========================================================================================= - - void separator_to_stream() { - s << Color::Yellow - << "===============================================================================" - "\n"; - } - - const char* getSuccessOrFailString(bool success, assertType::Enum at, - const char* success_str) { - if(success) - return success_str; - return failureString(at); - } - - Color::Enum getSuccessOrFailColor(bool success, assertType::Enum at) { - return success ? Color::BrightGreen : - (at & assertType::is_warn) ? Color::Yellow : Color::Red; - } - - void successOrFailColoredStringToStream(bool success, assertType::Enum at, - const char* success_str = "SUCCESS") { - s << getSuccessOrFailColor(success, at) - << getSuccessOrFailString(success, at, success_str) << ": "; - } - - void log_contexts() { - int num_contexts = get_num_active_contexts(); - if(num_contexts) { - auto contexts = get_active_contexts(); - - s << Color::None << " logged: "; - for(int i = 0; i < num_contexts; ++i) { - s << (i == 0 ? "" : " "); - contexts[i]->stringify(&s); - s << "\n"; - } - } - - s << "\n"; - } - - // this was requested to be made virtual so users could override it - virtual void file_line_to_stream(const char* file, int line, - const char* tail = "") { - s << Color::LightGrey << skipPathFromFilename(file) << (opt.gnu_file_line ? ":" : "(") - << (opt.no_line_numbers ? 0 : line) // 0 or the real num depending on the option - << (opt.gnu_file_line ? ":" : "):") << tail; - } - - void logTestStart() { - if(hasLoggedCurrentTestStart) - return; - - separator_to_stream(); - file_line_to_stream(tc->m_file.c_str(), tc->m_line, "\n"); - if(tc->m_description) - s << Color::Yellow << "DESCRIPTION: " << Color::None << tc->m_description << "\n"; - if(tc->m_test_suite && tc->m_test_suite[0] != '\0') - s << Color::Yellow << "TEST SUITE: " << Color::None << tc->m_test_suite << "\n"; - if(strncmp(tc->m_name, " Scenario:", 11) != 0) - s << Color::Yellow << "TEST CASE: "; - s << Color::None << tc->m_name << "\n"; - - for(size_t i = 0; i < currentSubcaseLevel; ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - - if(currentSubcaseLevel != subcasesStack.size()) { - s << Color::Yellow << "\nDEEPEST SUBCASE STACK REACHED (DIFFERENT FROM THE CURRENT ONE):\n" << Color::None; - for(size_t i = 0; i < subcasesStack.size(); ++i) { - if(subcasesStack[i].m_name[0] != '\0') - s << " " << subcasesStack[i].m_name << "\n"; - } - } - - s << "\n"; - - hasLoggedCurrentTestStart = true; - } - - void printVersion() { - if(opt.no_version == false) - s << Color::Cyan << "[doctest] " << Color::None << "doctest version is \"" - << DOCTEST_VERSION_STR << "\"\n"; - } - - void printIntro() { - if(opt.no_intro == false) { - printVersion(); - s << Color::Cyan << "[doctest] " << Color::None - << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n"; - } - } - - void printHelp() { - int sizePrefixDisplay = static_cast(strlen(DOCTEST_OPTIONS_PREFIX_DISPLAY)); - printVersion(); - // clang-format off - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"; - s << Color::Cyan << "[doctest] " << Color::None; - s << "filter values: \"str1,str2,str3\" (comma separated strings)\n"; - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "filters use wildcards for matching strings\n"; - s << Color::Cyan << "[doctest] " << Color::None; - s << "something passes a filter if any of the strings in a filter matches\n"; -#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"" DOCTEST_CONFIG_OPTIONS_PREFIX "\" PREFIX!!!\n"; -#endif - s << Color::Cyan << "[doctest]\n" << Color::None; - s << Color::Cyan << "[doctest] " << Color::None; - s << "Query flags - the program quits after them. Available:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "?, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "help, -" DOCTEST_OPTIONS_PREFIX_DISPLAY "h " - << Whitespace(sizePrefixDisplay*0) << "prints this message\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "v, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "version " - << Whitespace(sizePrefixDisplay*1) << "prints the version\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "c, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "count " - << Whitespace(sizePrefixDisplay*1) << "prints the number of matching tests\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ltc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-cases " - << Whitespace(sizePrefixDisplay*1) << "lists all matching tests by name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-test-suites " - << Whitespace(sizePrefixDisplay*1) << "lists all matching test suites\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "lr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "list-reporters " - << Whitespace(sizePrefixDisplay*1) << "lists all registered reporters\n\n"; - // ================================================================================== << 79 - s << Color::Cyan << "[doctest] " << Color::None; - s << "The available / options/filters are:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-case-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their file\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sfe, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "source-file-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their file\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ts, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite= " - << Whitespace(sizePrefixDisplay*1) << "filters tests by their test suite\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "tse, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "test-suite-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT tests by their test suite\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase= " - << Whitespace(sizePrefixDisplay*1) << "filters subcases by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "sce, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-exclude= " - << Whitespace(sizePrefixDisplay*1) << "filters OUT subcases by their name\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "r, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "reporters= " - << Whitespace(sizePrefixDisplay*1) << "reporters to use (console is default)\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "o, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "out= " - << Whitespace(sizePrefixDisplay*1) << "output filename\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ob, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "order-by= " - << Whitespace(sizePrefixDisplay*1) << "how the tests should be ordered\n"; - s << Whitespace(sizePrefixDisplay*3) << " - [file/suite/name/rand/none]\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "rs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "rand-seed= " - << Whitespace(sizePrefixDisplay*1) << "seed for random ordering\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "f, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "first= " - << Whitespace(sizePrefixDisplay*1) << "the first test passing the filters to\n"; - s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "l, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "last= " - << Whitespace(sizePrefixDisplay*1) << "the last test passing the filters to\n"; - s << Whitespace(sizePrefixDisplay*3) << " execute - for range-based execution\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "aa, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "abort-after= " - << Whitespace(sizePrefixDisplay*1) << "stop after failed assertions\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "scfl,--" DOCTEST_OPTIONS_PREFIX_DISPLAY "subcase-filter-levels= " - << Whitespace(sizePrefixDisplay*1) << "apply filters for the first levels\n"; - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "Bool options - can be used like flags and true is assumed. Available:\n\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "s, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "success= " - << Whitespace(sizePrefixDisplay*1) << "include successful assertions in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "cs, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "case-sensitive= " - << Whitespace(sizePrefixDisplay*1) << "filters being treated as case sensitive\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "e, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "exit= " - << Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration= " - << Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal= " - << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet= " - << Whitespace(sizePrefixDisplay*1) << "no console output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw= " - << Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode= " - << Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run= " - << Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro= " - << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version= " - << Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors= " - << Whitespace(sizePrefixDisplay*1) << "disables colors in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "fc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "force-colors= " - << Whitespace(sizePrefixDisplay*1) << "use colors even when not in a tty\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nb, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-breaks= " - << Whitespace(sizePrefixDisplay*1) << "disables breakpoints in debuggers\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ns, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-skip= " - << Whitespace(sizePrefixDisplay*1) << "don't skip test cases marked as skip\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "gfl, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "gnu-file-line= " - << Whitespace(sizePrefixDisplay*1) << ":n: vs (n): for line numbers in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "npf, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-path-filenames= " - << Whitespace(sizePrefixDisplay*1) << "only filenames and no paths in output\n"; - s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nln, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-line-numbers= " - << Whitespace(sizePrefixDisplay*1) << "0 instead of real line numbers in output\n"; - // ================================================================================== << 79 - // clang-format on - - s << Color::Cyan << "\n[doctest] " << Color::None; - s << "for more information visit the project documentation\n\n"; - } - - void printRegisteredReporters() { - printVersion(); - auto printReporters = [this] (const reporterMap& reporters, const char* type) { - if(reporters.size()) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all registered " << type << "\n"; - for(auto& curr : reporters) - s << "priority: " << std::setw(5) << curr.first.first - << " name: " << curr.first.second << "\n"; - } - }; - printReporters(getListeners(), "listeners"); - printReporters(getReporters(), "reporters"); - } - - // ========================================================================================= - // WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE - // ========================================================================================= - - void report_query(const QueryData& in) override { - if(opt.version) { - printVersion(); - } else if(opt.help) { - printHelp(); - } else if(opt.list_reporters) { - printRegisteredReporters(); - } else if(opt.count || opt.list_test_cases) { - if(opt.list_test_cases) { - s << Color::Cyan << "[doctest] " << Color::None - << "listing all test case names\n"; - separator_to_stream(); - } - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_name << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - - } else if(opt.list_test_suites) { - s << Color::Cyan << "[doctest] " << Color::None << "listing all test suites\n"; - separator_to_stream(); - - for(unsigned i = 0; i < in.num_data; ++i) - s << Color::None << in.data[i]->m_test_suite << "\n"; - - separator_to_stream(); - - s << Color::Cyan << "[doctest] " << Color::None - << "unskipped test cases passing the current filters: " - << g_cs->numTestCasesPassingFilters << "\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "test suites with unskipped test cases passing the current filters: " - << g_cs->numTestSuitesPassingFilters << "\n"; - } - } - - void test_run_start() override { - if(!opt.minimal) - printIntro(); - } - - void test_run_end(const TestRunStats& p) override { - if(opt.minimal && p.numTestCasesFailed == 0) - return; - - separator_to_stream(); - s << std::dec; - - auto totwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters, static_cast(p.numAsserts))) + 1))); - auto passwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesPassingFilters - p.numTestCasesFailed, static_cast(p.numAsserts - p.numAssertsFailed))) + 1))); - auto failwidth = int(std::ceil(log10(static_cast(std::max(p.numTestCasesFailed, static_cast(p.numAssertsFailed))) + 1))); - const bool anythingFailed = p.numTestCasesFailed > 0 || p.numAssertsFailed > 0; - s << Color::Cyan << "[doctest] " << Color::None << "test cases: " << std::setw(totwidth) - << p.numTestCasesPassingFilters << " | " - << ((p.numTestCasesPassingFilters == 0 || anythingFailed) ? Color::None : - Color::Green) - << std::setw(passwidth) << p.numTestCasesPassingFilters - p.numTestCasesFailed << " passed" - << Color::None << " | " << (p.numTestCasesFailed > 0 ? Color::Red : Color::None) - << std::setw(failwidth) << p.numTestCasesFailed << " failed" << Color::None << " |"; - if(opt.no_skipped_summary == false) { - const int numSkipped = p.numTestCases - p.numTestCasesPassingFilters; - s << " " << (numSkipped == 0 ? Color::None : Color::Yellow) << numSkipped - << " skipped" << Color::None; - } - s << "\n"; - s << Color::Cyan << "[doctest] " << Color::None << "assertions: " << std::setw(totwidth) - << p.numAsserts << " | " - << ((p.numAsserts == 0 || anythingFailed) ? Color::None : Color::Green) - << std::setw(passwidth) << (p.numAsserts - p.numAssertsFailed) << " passed" << Color::None - << " | " << (p.numAssertsFailed > 0 ? Color::Red : Color::None) << std::setw(failwidth) - << p.numAssertsFailed << " failed" << Color::None << " |\n"; - s << Color::Cyan << "[doctest] " << Color::None - << "Status: " << (p.numTestCasesFailed > 0 ? Color::Red : Color::Green) - << ((p.numTestCasesFailed > 0) ? "FAILURE!" : "SUCCESS!") << Color::None << std::endl; - } - - void test_case_start(const TestCaseData& in) override { - hasLoggedCurrentTestStart = false; - tc = ∈ - subcasesStack.clear(); - currentSubcaseLevel = 0; - } - - void test_case_reenter(const TestCaseData&) override { - subcasesStack.clear(); - } - - void test_case_end(const CurrentTestCaseStats& st) override { - if(tc->m_no_output) - return; - - // log the preamble of the test case only if there is something - // else to print - something other than that an assert has failed - if(opt.duration || - (st.failure_flags && st.failure_flags != static_cast(TestCaseFailureReason::AssertFailure))) - logTestStart(); - - if(opt.duration) - s << Color::None << std::setprecision(6) << std::fixed << st.seconds - << " s: " << tc->m_name << "\n"; - - if(st.failure_flags & TestCaseFailureReason::Timeout) - s << Color::Red << "Test case exceeded time limit of " << std::setprecision(6) - << std::fixed << tc->m_timeout << "!\n"; - - if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedButDidnt) { - s << Color::Red << "Should have failed but didn't! Marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::ShouldHaveFailedAndDid) { - s << Color::Yellow << "Failed as expected so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::CouldHaveFailedAndDid) { - s << Color::Yellow << "Allowed to fail so marking it as not failed\n"; - } else if(st.failure_flags & TestCaseFailureReason::DidntFailExactlyNumTimes) { - s << Color::Red << "Didn't fail exactly " << tc->m_expected_failures - << " times so marking it as failed!\n"; - } else if(st.failure_flags & TestCaseFailureReason::FailedExactlyNumTimes) { - s << Color::Yellow << "Failed exactly " << tc->m_expected_failures - << " times as expected so marking it as not failed!\n"; - } - if(st.failure_flags & TestCaseFailureReason::TooManyFailedAsserts) { - s << Color::Red << "Aborting - too many failed asserts!\n"; - } - s << Color::None; // lgtm [cpp/useless-expression] - } - - void test_case_exception(const TestCaseException& e) override { - DOCTEST_LOCK_MUTEX(mutex) - if(tc->m_no_output) - return; - - logTestStart(); - - file_line_to_stream(tc->m_file.c_str(), tc->m_line, " "); - successOrFailColoredStringToStream(false, e.is_crash ? assertType::is_require : - assertType::is_check); - s << Color::Red << (e.is_crash ? "test case CRASHED: " : "test case THREW exception: ") - << Color::Cyan << e.error_string << "\n"; - - int num_stringified_contexts = get_num_stringified_contexts(); - if(num_stringified_contexts) { - auto stringified_contexts = get_stringified_contexts(); - s << Color::None << " logged: "; - for(int i = num_stringified_contexts; i > 0; --i) { - s << (i == num_stringified_contexts ? "" : " ") - << stringified_contexts[i - 1] << "\n"; - } - } - s << "\n" << Color::None; - } - - void subcase_start(const SubcaseSignature& subc) override { - subcasesStack.push_back(subc); - ++currentSubcaseLevel; - hasLoggedCurrentTestStart = false; - } - - void subcase_end() override { - --currentSubcaseLevel; - hasLoggedCurrentTestStart = false; - } - - void log_assert(const AssertData& rb) override { - if((!rb.m_failed && !opt.success) || tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(rb.m_file, rb.m_line, " "); - successOrFailColoredStringToStream(!rb.m_failed, rb.m_at); - - fulltext_log_assert_to_stream(s, rb); - - log_contexts(); - } - - void log_message(const MessageData& mb) override { - if(tc->m_no_output) - return; - - DOCTEST_LOCK_MUTEX(mutex) - - logTestStart(); - - file_line_to_stream(mb.m_file, mb.m_line, " "); - s << getSuccessOrFailColor(false, mb.m_severity) - << getSuccessOrFailString(mb.m_severity & assertType::is_warn, mb.m_severity, - "MESSAGE") << ": "; - s << Color::None << mb.m_string << "\n"; - log_contexts(); - } - - void test_case_skipped(const TestCaseData&) override {} - }; - - DOCTEST_REGISTER_REPORTER("console", 0, ConsoleReporter); - -#ifdef DOCTEST_PLATFORM_WINDOWS - struct DebugOutputWindowReporter : public ConsoleReporter - { - DOCTEST_THREAD_LOCAL static std::ostringstream oss; - - DebugOutputWindowReporter(const ContextOptions& co) - : ConsoleReporter(co, oss) {} - -#define DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(func, type, arg) \ - void func(type arg) override { \ - bool with_col = g_no_colors; \ - g_no_colors = false; \ - ConsoleReporter::func(arg); \ - if(oss.tellp() != std::streampos{}) { \ - DOCTEST_OUTPUT_DEBUG_STRING(oss.str().c_str()); \ - oss.str(""); \ - } \ - g_no_colors = with_col; \ - } - - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_run_end, const TestRunStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_start, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_reenter, const TestCaseData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_exception, const TestCaseException&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_start, const SubcaseSignature&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_assert, const AssertData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(log_message, const MessageData&, in) - DOCTEST_DEBUG_OUTPUT_REPORTER_OVERRIDE(test_case_skipped, const TestCaseData&, in) - }; - - DOCTEST_THREAD_LOCAL std::ostringstream DebugOutputWindowReporter::oss; -#endif // DOCTEST_PLATFORM_WINDOWS - - // the implementation of parseOption() - bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String* value) { - // going from the end to the beginning and stopping on the first occurrence from the end - for(int i = argc; i > 0; --i) { - auto index = i - 1; - auto temp = std::strstr(argv[index], pattern); - if(temp && (value || strlen(temp) == strlen(pattern))) { //!OCLINT prefer early exits and continue - // eliminate matches in which the chars before the option are not '-' - bool noBadCharsFound = true; - auto curr = argv[index]; - while(curr != temp) { - if(*curr++ != '-') { - noBadCharsFound = false; - break; - } - } - if(noBadCharsFound && argv[index][0] == '-') { - if(value) { - // parsing the value of an option - temp += strlen(pattern); - const unsigned len = strlen(temp); - if(len) { - *value = temp; - return true; - } - } else { - // just a flag - no value - return true; - } - } - } - } - return false; - } - - // parses an option and returns the string after the '=' character - bool parseOption(int argc, const char* const* argv, const char* pattern, String* value = nullptr, - const String& defaultVal = String()) { - if(value) - *value = defaultVal; -#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - // offset (normally 3 for "dt-") to skip prefix - if(parseOptionImpl(argc, argv, pattern + strlen(DOCTEST_CONFIG_OPTIONS_PREFIX), value)) - return true; -#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS - return parseOptionImpl(argc, argv, pattern, value); - } - - // locates a flag on the command line - bool parseFlag(int argc, const char* const* argv, const char* pattern) { - return parseOption(argc, argv, pattern); - } - - // parses a comma separated list of words after a pattern in one of the arguments in argv - bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, - std::vector& res) { - String filtersString; - if(parseOption(argc, argv, pattern, &filtersString)) { - // tokenize with "," as a separator, unless escaped with backslash - std::ostringstream s; - auto flush = [&s, &res]() { - auto string = s.str(); - if(string.size() > 0) { - res.push_back(string.c_str()); - } - s.str(""); - }; - - bool seenBackslash = false; - const char* current = filtersString.c_str(); - const char* end = current + strlen(current); - while(current != end) { - char character = *current++; - if(seenBackslash) { - seenBackslash = false; - if(character == ',' || character == '\\') { - s.put(character); - continue; - } - s.put('\\'); - } - if(character == '\\') { - seenBackslash = true; - } else if(character == ',') { - flush(); - } else { - s.put(character); - } - } - - if(seenBackslash) { - s.put('\\'); - } - flush(); - return true; - } - return false; - } - - enum optionType - { - option_bool, - option_int - }; - - // parses an int/bool option from the command line - bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, - int& res) { - String parsedValue; - if(!parseOption(argc, argv, pattern, &parsedValue)) - return false; - - if(type) { - // integer - // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse... - int theInt = std::atoi(parsedValue.c_str()); - if (theInt != 0) { - res = theInt; //!OCLINT parameter reassignment - return true; - } - } else { - // boolean - const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1 - const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1 - - // if the value matches any of the positive/negative possibilities - for (unsigned i = 0; i < 4; i++) { - if (parsedValue.compare(positive[i], true) == 0) { - res = 1; //!OCLINT parameter reassignment - return true; - } - if (parsedValue.compare(negative[i], true) == 0) { - res = 0; //!OCLINT parameter reassignment - return true; - } - } - } - return false; - } -} // namespace - -Context::Context(int argc, const char* const* argv) - : p(new detail::ContextState) { - parseArgs(argc, argv, true); - if(argc) - p->binary_name = argv[0]; -} - -Context::~Context() { - if(g_cs == p) - g_cs = nullptr; - delete p; -} - -void Context::applyCommandLine(int argc, const char* const* argv) { - parseArgs(argc, argv); - if(argc) - p->binary_name = argv[0]; -} - -// parses args -void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { - using namespace detail; - - // clang-format off - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file=", p->filters[0]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sf=", p->filters[0]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "source-file-exclude=",p->filters[1]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sfe=", p->filters[1]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite=", p->filters[2]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ts=", p->filters[2]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-suite-exclude=", p->filters[3]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tse=", p->filters[3]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case=", p->filters[4]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tc=", p->filters[4]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "test-case-exclude=", p->filters[5]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "tce=", p->filters[5]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase=", p->filters[6]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sc=", p->filters[6]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "subcase-exclude=", p->filters[7]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "sce=", p->filters[7]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "reporters=", p->filters[8]); - parseCommaSepArgs(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "r=", p->filters[8]); - // clang-format on - - int intRes = 0; - String strRes; - -#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_bool, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_bool, intRes)) \ - p->var = static_cast(intRes); \ - else if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name) || \ - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname)) \ - p->var = true; \ - else if(withDefaults) \ - p->var = default - -#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ - if(parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", option_int, intRes) || \ - parseIntOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", option_int, intRes)) \ - p->var = intRes; \ - else if(withDefaults) \ - p->var = default - -#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ - if(parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX name "=", &strRes, default) || \ - parseOption(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX sname "=", &strRes, default) || \ - withDefaults) \ - p->var = strRes - - // clang-format off - DOCTEST_PARSE_STR_OPTION("out", "o", out, ""); - DOCTEST_PARSE_STR_OPTION("order-by", "ob", order_by, "file"); - DOCTEST_PARSE_INT_OPTION("rand-seed", "rs", rand_seed, 0); - - DOCTEST_PARSE_INT_OPTION("first", "f", first, 0); - DOCTEST_PARSE_INT_OPTION("last", "l", last, UINT_MAX); - - DOCTEST_PARSE_INT_OPTION("abort-after", "aa", abort_after, 0); - DOCTEST_PARSE_INT_OPTION("subcase-filter-levels", "scfl", subcase_filter_levels, INT_MAX); - - DOCTEST_PARSE_AS_BOOL_OR_FLAG("success", "s", success, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-breaks", "nb", no_breaks, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skip", "ns", no_skip, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); - DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); - // clang-format on - - if(withDefaults) { - p->help = false; - p->version = false; - p->count = false; - p->list_test_cases = false; - p->list_test_suites = false; - p->list_reporters = false; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "help") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "h") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "?")) { - p->help = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "version") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "v")) { - p->version = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "count") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "c")) { - p->count = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-cases") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "ltc")) { - p->list_test_cases = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-test-suites") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lts")) { - p->list_test_suites = true; - p->exit = true; - } - if(parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "list-reporters") || - parseFlag(argc, argv, DOCTEST_CONFIG_OPTIONS_PREFIX "lr")) { - p->list_reporters = true; - p->exit = true; - } -} - -// allows the user to add procedurally to the filters from the command line -void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } - -// allows the user to clear all filters from the command line -void Context::clearFilters() { - for(auto& curr : p->filters) - curr.clear(); -} - -// allows the user to override procedurally the bool options from the command line -void Context::setOption(const char* option, bool value) { - setOption(option, value ? "true" : "false"); -} - -// allows the user to override procedurally the int options from the command line -void Context::setOption(const char* option, int value) { - setOption(option, toString(value).c_str()); -} - -// allows the user to override procedurally the string options from the command line -void Context::setOption(const char* option, const char* value) { - auto argv = String("-") + option + "=" + value; - auto lvalue = argv.c_str(); - parseArgs(1, &lvalue); -} - -// users should query this in their main() and exit the program if true -bool Context::shouldExit() { return p->exit; } - -void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; } - -void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; } - -void Context::setCout(std::ostream* out) { p->cout = out; } - -static class DiscardOStream : public std::ostream -{ -private: - class : public std::streambuf - { - private: - // allowing some buffering decreases the amount of calls to overflow - char buf[1024]; - - protected: - std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; } - - int_type overflow(int_type ch) override { - setp(std::begin(buf), std::end(buf)); - return traits_type::not_eof(ch); - } - } discardBuf; - -public: - DiscardOStream() - : std::ostream(&discardBuf) {} -} discardOut; - -// the main function that does all the filtering and test running -int Context::run() { - using namespace detail; - - // save the old context state in case such was setup - for using asserts out of a testing context - auto old_cs = g_cs; - // this is the current contest - g_cs = p; - is_running_in_test = true; - - g_no_colors = p->no_colors; - p->resetRunData(); - - std::fstream fstr; - if(p->cout == nullptr) { - if(p->quiet) { - p->cout = &discardOut; - } else if(p->out.size()) { - // to a file if specified - fstr.open(p->out.c_str(), std::fstream::out); - p->cout = &fstr; - } else { -#ifndef DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - // stdout by default - p->cout = &std::cout; -#else // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - return EXIT_FAILURE; -#endif // DOCTEST_CONFIG_NO_INCLUDE_IOSTREAM - } - } - - FatalConditionHandler::allocateAltStackMem(); - - auto cleanup_and_return = [&]() { - FatalConditionHandler::freeAltStackMem(); - - if(fstr.is_open()) - fstr.close(); - - // restore context - g_cs = old_cs; - is_running_in_test = false; - - // we have to free the reporters which were allocated when the run started - for(auto& curr : p->reporters_currently_used) - delete curr; - p->reporters_currently_used.clear(); - - if(p->numTestCasesFailed && !p->no_exitcode) - return EXIT_FAILURE; - return EXIT_SUCCESS; - }; - - // setup default reporter if none is given through the command line - if(p->filters[8].empty()) - p->filters[8].push_back("console"); - - // check to see if any of the registered reporters has been selected - for(auto& curr : getReporters()) { - if(matchesAny(curr.first.second.c_str(), p->filters[8], false, p->case_sensitive)) - p->reporters_currently_used.push_back(curr.second(*g_cs)); - } - - // TODO: check if there is nothing in reporters_currently_used - - // prepend all listeners - for(auto& curr : getListeners()) - p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); - -#ifdef DOCTEST_PLATFORM_WINDOWS - if(isDebuggerActive() && p->no_debug_output == false) - p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); -#endif // DOCTEST_PLATFORM_WINDOWS - - // handle version, help and no_run - if(p->no_run || p->version || p->help || p->list_reporters) { - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, QueryData()); - - return cleanup_and_return(); - } - - std::vector testArray; - for(auto& curr : getRegisteredTests()) - testArray.push_back(&curr); - p->numTestCases = testArray.size(); - - // sort the collected records - if(!testArray.empty()) { - if(p->order_by.compare("file", true) == 0) { - std::sort(testArray.begin(), testArray.end(), fileOrderComparator); - } else if(p->order_by.compare("suite", true) == 0) { - std::sort(testArray.begin(), testArray.end(), suiteOrderComparator); - } else if(p->order_by.compare("name", true) == 0) { - std::sort(testArray.begin(), testArray.end(), nameOrderComparator); - } else if(p->order_by.compare("rand", true) == 0) { - std::srand(p->rand_seed); - - // random_shuffle implementation - const auto first = &testArray[0]; - for(size_t i = testArray.size() - 1; i > 0; --i) { - int idxToSwap = std::rand() % (i + 1); - - const auto temp = first[i]; - - first[i] = first[idxToSwap]; - first[idxToSwap] = temp; - } - } else if(p->order_by.compare("none", true) == 0) { - // means no sorting - beneficial for death tests which call into the executable - // with a specific test case in mind - we don't want to slow down the startup times - } - } - - std::set testSuitesPassingFilt; - - bool query_mode = p->count || p->list_test_cases || p->list_test_suites; - std::vector queryResults; - - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_start, DOCTEST_EMPTY); - - // invoke the registered functions if they match the filter criteria (or just count them) - for(auto& curr : testArray) { - const auto& tc = *curr; - - bool skip_me = false; - if(tc.m_skip && !p->no_skip) - skip_me = true; - - if(!matchesAny(tc.m_file.c_str(), p->filters[0], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_file.c_str(), p->filters[1], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_test_suite, p->filters[2], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_test_suite, p->filters[3], false, p->case_sensitive)) - skip_me = true; - if(!matchesAny(tc.m_name, p->filters[4], true, p->case_sensitive)) - skip_me = true; - if(matchesAny(tc.m_name, p->filters[5], false, p->case_sensitive)) - skip_me = true; - - if(!skip_me) - p->numTestCasesPassingFilters++; - - // skip the test if it is not in the execution range - if((p->last < p->numTestCasesPassingFilters && p->first <= p->last) || - (p->first > p->numTestCasesPassingFilters)) - skip_me = true; - - if(skip_me) { - if(!query_mode) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_skipped, tc); - continue; - } - - // do not execute the test if we are to only count the number of filter passing tests - if(p->count) - continue; - - // print the name of the test and don't execute it - if(p->list_test_cases) { - queryResults.push_back(&tc); - continue; - } - - // print the name of the test suite if not done already and don't execute it - if(p->list_test_suites) { - if((testSuitesPassingFilt.count(tc.m_test_suite) == 0) && tc.m_test_suite[0] != '\0') { - queryResults.push_back(&tc); - testSuitesPassingFilt.insert(tc.m_test_suite); - p->numTestSuitesPassingFilters++; - } - continue; - } - - // execute the test if it passes all the filtering - { - p->currentTest = &tc; - - p->failure_flags = TestCaseFailureReason::None; - p->seconds = 0; - - // reset atomic counters - p->numAssertsFailedCurrentTest_atomic = 0; - p->numAssertsCurrentTest_atomic = 0; - - p->fullyTraversedSubcases.clear(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc); - - p->timer.start(); - - bool run_test = true; - - do { - // reset some of the fields for subcases (except for the set of fully passed ones) - p->reachedLeaf = false; - // May not be empty if previous subcase exited via exception. - p->subcaseStack.clear(); - p->currentSubcaseDepth = 0; - - p->shouldLogCurrentException = true; - - // reset stuff for logging with INFO() - p->stringifiedContexts.clear(); - -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - try { -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS -// MSVC 2015 diagnoses fatalConditionHandler as unused (because reset() is a static method) -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4101) // unreferenced local variable - FatalConditionHandler fatalConditionHandler; // Handle signals - // execute the test - tc.m_test(); - fatalConditionHandler.reset(); -DOCTEST_MSVC_SUPPRESS_WARNING_POP -#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS - } catch(const TestFailureException&) { - p->failure_flags |= TestCaseFailureReason::AssertFailure; - } catch(...) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, - {translateActiveException(), false}); - p->failure_flags |= TestCaseFailureReason::Exception; - } -#endif // DOCTEST_CONFIG_NO_EXCEPTIONS - - // exit this loop if enough assertions have failed - even if there are more subcases - if(p->abort_after > 0 && - p->numAssertsFailed + p->numAssertsFailedCurrentTest_atomic >= p->abort_after) { - run_test = false; - p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts; - } - - if(!p->nextSubcaseStack.empty() && run_test) - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc); - if(p->nextSubcaseStack.empty()) - run_test = false; - } while(run_test); - - p->finalizeTestCaseData(); - - DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_end, *g_cs); - - p->currentTest = nullptr; - - // stop executing tests if enough assertions have failed - if(p->abort_after > 0 && p->numAssertsFailed >= p->abort_after) - break; - } - } - - if(!query_mode) { - DOCTEST_ITERATE_THROUGH_REPORTERS(test_run_end, *g_cs); - } else { - QueryData qdata; - qdata.run_stats = g_cs; - qdata.data = queryResults.data(); - qdata.num_data = unsigned(queryResults.size()); - DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata); - } - - return cleanup_and_return(); -} - -DOCTEST_DEFINE_INTERFACE(IReporter) - -int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); } -const IContextScope* const* IReporter::get_active_contexts() { - return get_num_active_contexts() ? &detail::g_infoContexts[0] : nullptr; -} - -int IReporter::get_num_stringified_contexts() { return detail::g_cs->stringifiedContexts.size(); } -const String* IReporter::get_stringified_contexts() { - return get_num_stringified_contexts() ? &detail::g_cs->stringifiedContexts[0] : nullptr; -} - -namespace detail { - void registerReporterImpl(const char* name, int priority, reporterCreatorFunc c, bool isReporter) { - if(isReporter) - getReporters().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); - else - getListeners().insert(reporterMap::value_type(reporterMap::key_type(priority, name), c)); - } -} // namespace detail - -} // namespace doctest - -#endif // DOCTEST_CONFIG_DISABLE - -#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) // 'function' : must be 'attribute' - see issue #182 -int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } -DOCTEST_MSVC_SUPPRESS_WARNING_POP -#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN - -DOCTEST_CLANG_SUPPRESS_WARNING_POP -DOCTEST_MSVC_SUPPRESS_WARNING_POP -DOCTEST_GCC_SUPPRESS_WARNING_POP - -DOCTEST_SUPPRESS_COMMON_WARNINGS_POP - -#endif // DOCTEST_LIBRARY_IMPLEMENTATION -#endif // DOCTEST_CONFIG_IMPLEMENT - -#ifdef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN -#undef WIN32_LEAN_AND_MEAN -#undef DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN -#endif // DOCTEST_UNDEF_WIN32_LEAN_AND_MEAN - -#ifdef DOCTEST_UNDEF_NOMINMAX -#undef NOMINMAX -#undef DOCTEST_UNDEF_NOMINMAX -#endif // DOCTEST_UNDEF_NOMINMAX diff --git a/Storage/main.c b/Storage/main.c deleted file mode 100644 index 26eeb15..0000000 --- a/Storage/main.c +++ /dev/null @@ -1,3 +0,0 @@ -//int main() { -// return 0; -//} \ No newline at end of file From f709a581bc8b8803d39707419431953734c2e382 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Thu, 8 Aug 2024 08:59:20 +0300 Subject: [PATCH 13/32] fix errors after merge --- Storage/Disk_Mng_Master.h | 88 ++++++++++++++++----------------------- Storage/Storage.vcxproj | 10 ----- 2 files changed, 35 insertions(+), 63 deletions(-) diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index d46ab9d..54d8a35 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -41,6 +41,41 @@ struct DiskSortByMapSize_s { int lruCounter; }; +struct Point_s { + int x; // longitude + int y; // latitude +}; + +struct MapRange_s { + Point_t topLeft; + Point_t bottomRight; +}; + +struct ArrayInfo_s { + int mapid; + int* diskPointer; + int size; + MapRange_t* range; + //AVLNodeInfo_t avlInfo; + +}; + +struct StackNode_s { + int freeIndex; + StackNode_t* next; +}; + +struct DiskFreeIndexesInArray_s { + int size; + StackNode_t* top; +}; +struct Disk_Management_CB_s { + ArrayInfo_t** arrayForAllMApsInformation; + StackNode_t* stackNode; + DiskFreeIndexesInArray_t* diskFreeIndexesInArray; + DiskSortByMapSize_t* disk_SortByMapSize; +}; +extern Disk_Management_CB_t* disk_mng_CB; // Function declarations @@ -106,59 +141,6 @@ AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node); // avlTree_deleteNode-Deletes a node from the AVL tree without freeing its memory AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node); -// Struct declarations - -struct Point_s { - int x; // longitude - int y; // latitude -}; - -struct MapRange_s { - Point_t topLeft; - Point_t bottomRight; -}; - -struct ArrayInfo_s { - int mapid; - int* diskPointer; - int size; - MapRange_t* range; - //AVLNodeInfo_t avlInfo; - -}; - -struct StackNode_s { - int freeIndex; - StackNode_t* next; -}; - -struct DiskFreeIndexesInArray_s { - int size; - StackNode_t* top; -}; -struct Disk_Management_CB_s { - ArrayInfo_t** arrayForAllMApsInformation; - StackNode_t* stackNode; - DiskFreeIndexesInArray_t* diskFreeIndexesInArray; - DiskSortByMapSize_t* disk_SortByMapSize; -}; -extern Disk_Management_CB_t* disk_mng_CB; - -//the function aloocate memory to the object and check if fail -void* allocate_memory(size_t size, const char* description, const char* functionName); - -//in case the allocate fail this function write to logFile -void test_writeExceptionToFile(Exception exception, char* source); - -//disk managment - -//initialize the disk managment CB - -void disk_mng_initialize_CB(); - -////initialize the disk managment mapping -void disk_mng_initialize(); - //stack functions //initialize on the first time when we turn on the computer-fill in the stack all the index from 0-DISK_SIZE diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index 12fd91c..e6ef62e 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -129,19 +129,9 @@ -<<<<<<< HEAD - -======= - - ->>>>>>> origin/disk_managment_master - - - - From be04c725f17fc7e326cb7149a1485b5b6c9e7a13 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Thu, 8 Aug 2024 13:51:32 +0300 Subject: [PATCH 14/32] save and intialize disk functions --- Storage/Disk_Mng_Master.c | 113 +++++++++++++++++++++++++++++++++++--- Storage/Disk_Mng_Master.h | 39 ++++++++++--- Storage/Doctest.cpp | 53 +++++++++++++++++- 3 files changed, 187 insertions(+), 18 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index dda5cdf..cdc3d88 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -5,7 +5,7 @@ #include Disk_Management_CB_t* disk_mng_CB; - + int length, startAdress, howManyToLoad; void disk_mng_initialize_CB() { disk_mng_CB = (Disk_Management_CB_t*)allocate_memory(sizeof(Disk_Management_CB_t), "Failed to allocate memory for disk control block", "disk_mng_initialize_CB"); @@ -13,11 +13,46 @@ void disk_mng_initialize_CB() void disk_mng_initialize() { + int startAdress = 0; + int howManyToLoad = sizeof(int); + int address=0;// + disk_loadDataForInitializeDataStructers(&address, &startAdress,&howManyToLoad); + if (address != 1)// + { + ////restart the first address int disk with 1 to know if its first time or not + disk_saveDataFromStructersToDisk(&address, &startAdress, &howManyToLoad); + disk_mng_firstInitialize(); + } + else + { + disk_mng_normalInitialize(); + } +} + +void disk_mng_saveData() +{ + stack_saveData(); + array_saveData(); + avlTree_saveData(); + +} + +void disk_mng_firstInitialize() +{ disk_mng_initialize_CB(); stack_firstInitialize(); array_firstInitialize(); avlTree_firstInitialize(); } + +void disk_mng_normalInitialize() +{ + disk_mng_initialize_CB(); + stack_normalInitialize(); + array_normalInitialize(); + avlTree_normalInitialize(); +} + //initialize on the first time we turn o the computer the stack will initialize with all the indexes. void stack_firstInitialize() { disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); @@ -33,8 +68,27 @@ void stack_firstInitialize() { void stack_normalInitialize() { disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); int length = 0; - //disk_loadDataForInitializeDataStructers(length, 0, sizeof(int)); - //disk_loadDataForInitializeDataStructers(disk_mng_CB->diskFreeIndexesInArray, 4, length*sizeof(int)); + int startAdress = 4; + int howManyToLoad = sizeof(int); + //load the second address in disk with stack size + disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); + startAdress = 12; + howManyToLoad = length * sizeof(int); + //load all the data from stack + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress,&howManyToLoad) ; +} + +void stack_saveData() +{ + int startAdress = 4; + int howManyToLoad = 4+sizeof(int); + ////save size of stack in the second address in the disk + disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray->size), &startAdress, &howManyToLoad); + + startAdress = 12; + howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); + //save all the data from stack + disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress, &howManyToLoad); } bool stack_is_empty() { @@ -84,19 +138,31 @@ void array_firstInitialize() { void array_normalInitialize() { disk_mng_CB->diskFreeIndexesInArray = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for stack ", "array_normalInitialize"); - //disk_loadDataForInitializeDataStructers(disk_mng_CB->diskFreeIndexesInArray, 4+ disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int),DISK_SIZE*sizeof(ArrayInfo_t**)); + int startAdress = 12 + disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int); + int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t**); + //load all the data from array + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress, &howManyToLoad); + + + } -ArrayInfo_t* arrayInfo_create(int mapid, int* diskPointer, int size, MapRange_t* range - //,AVLNodeInfo_t* avlInfo// -) +void array_saveData() { - ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for max heap", "arrayInfo_create"); + int startAdress = 12+disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int)+DISK_SIZE * sizeof(ArrayInfo_t**); + int howManyToLoad =DISK_SIZE* (sizeof(ArrayInfo_t**)); + //save all the data from array + disk_saveDataFromStructersToDisk(&(disk_mng_CB->arrayForAllMApsInformation), &startAdress, &howManyToLoad); +} + + +ArrayInfo_t* arrayInfo_create(int mapid, int* diskPointer, int size, MapRange_t* range) +{ + ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for avlTree", "arrayInfo_create"); arrayInfo->mapid = mapid; arrayInfo ->diskPointer = diskPointer; arrayInfo->size = size; arrayInfo->range =range; - //arrayInfo->avlInfo = avlInfo; return arrayInfo; } @@ -262,6 +328,35 @@ void avlTree_firstInitialize() { disk_mng_CB->disk_SortByMapSize->lruCounter = 0; } +void avlTree_normalInitialize() +{ + disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t**)allocate_memory(sizeof(DiskSortByMapSize_t*), "Failed to allocate memory for stack ", "avlTree_normalInitialize"); + int length = 0; + int startAdress = 8; + int howManyToLoad = sizeof(int); + //load the third address in disk with avlTree size + disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); + startAdress = 12+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); + howManyToLoad = length * sizeof(DiskSortByMapSize_t**); + //load all the data from avlTree + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startAdress, &howManyToLoad); +} + +void avlTree_saveData() +{ + int startAdress = 8; + int howManyToLoad = sizeof(int); + ////save size of avkTree in the third address in the disk + disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->totalElements), &startAdress, &howManyToLoad); + + + startAdress = 12+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**) + DISK_SIZE * (sizeof(ArrayInfo_t**)); + howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); + //save all the data from stack + disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startAdress, &howManyToLoad); +} + + void avlTree_insertElement(AVLNodeInfo_t* data) { disk_mng_CB->disk_SortByMapSize->lruCounter++; disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, data, disk_mng_CB->disk_SortByMapSize->lruCounter); diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 54d8a35..ee51892 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -56,7 +56,6 @@ struct ArrayInfo_s { int* diskPointer; int size; MapRange_t* range; - //AVLNodeInfo_t avlInfo; }; @@ -93,6 +92,13 @@ void disk_mng_initialize_CB(); // disk_mng_initialize-Initializes the disk management system void disk_mng_initialize(); +// disk_mng_firstInitialize-Initializes the disk management system at the first time +void disk_mng_firstInitialize(); + +// disk_mng_normalInitialize-Initializes the disk management system each time the computer opened +void disk_mng_normalInitialize(); + + //AVL node info // avlNodeInfo_create-Creates and returns a new AVLNodeInfo_t structure @@ -113,6 +119,14 @@ void avlNode_delete(AVLNode_t* node); int avlNode_height(AVLNode_t* N); //AVL tree +// avlTree_firstInitialize-Initializes the AVL tree for the first time +void avlTree_firstInitialize(); + +// avlTree_firstInitialize-Initializes the AVL tree each time the computer opened +void avlTree_normalInitialize(); + +//save data from avlTree each closed +void avlTree_saveData(); // avlTree_rightRotate-Performs a right rotation on the given subtree AVLNode_t* avlTree_rightRotate(AVLNode_t* y); @@ -129,8 +143,7 @@ AVLNode_t* avlTree_minValueNode(AVLNode_t* node); // avlTree_insert-Inserts a new node into the AVL tree AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter); -// avlTree_firstInitialize-Initializes the AVL tree for the first time -void avlTree_firstInitialize(); + // avlTree_insertElement-Inserts a new element into the AVL tree void avlTree_insertElement(AVLNodeInfo_t* data); @@ -149,6 +162,9 @@ void stack_firstInitialize(); //normal initialize each open of the computer the disk will fill in the structers all the saved data void stack_normalInitialize(); +//save data from stack each closed +void stack_saveData(); + //stack_is_empty check if the stack full bool stack_is_empty(); @@ -168,13 +184,15 @@ int stack_top(); //array functions +//initialize on the first time when we turn on the computer just allocate memory to the array +void array_firstInitialize(); // Initializes an array with default values or in a standard way. // This function likely sets the array to a known starting state. void array_normalInitialize(); -//initialize on the first time when we turn on the computer just allocate memory to the array -void array_firstInitialize(); +//save data from array each closed +void array_saveData(); // Deletes an element from an array at a specific index. void array_deleteFromArray(int index); @@ -186,9 +204,14 @@ void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); //disk_deleteMap the function get pointer to map in the disk and delete this map from disk void disk_deleteMap(int* diskPointer); -ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range -//,AVLNodeInfo_t* avlInfo// - ); +//create a new arrayInfo with all the parameters +ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range); +//create a new range with 2 point which given MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft); +//disk_loadDataForInitializeDataStructers the function get destination where to load and from where and how many to load +void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad); + +//disk_loadDataForInitializeDataStructers the function get data where to save and from where and how many to save +void disk_saveDataFromStructersToDisk(void* data, void* startAddress, void* howManyToLoad); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 3d4495c..2553612 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -29,7 +29,11 @@ void disk_deleteMap(int* diskPointer) {} //the function fill in the structer all the data which save befoe the computer closed,the function get destenation,suorce,length; -void disk_loadDataForInitializeDataStructers(void* i,void* x,void* b) +void disk_loadDataForInitializeDataStructers(void* destination,void* startAddress,void* howManyToLoad) +{ +} + +void disk_saveDataFromStructersToDisk(void* data, void* startAddress, void* endAddrehowManyToLoadss) { } @@ -44,6 +48,8 @@ TEST_CASE("test_disk_mng_initialize") disk_mng_initialize(); } +//avlNode tests + TEST_CASE("test_avlNodeInfo_create") { int mapSize = generateRandomNumber(); @@ -105,6 +111,23 @@ TEST_CASE("test_avlNode_height") CHECK(avlNode->height == avlNode_height(avlNode)); } +//avlTree tests + +TEST_CASE("avlTree_firstInitialize") +{ + +} + +TEST_CASE("avlTree_normalInitialize") +{ + +} + +TEST_CASE("avlTree_saveData") +{ + +} + TEST_CASE("test_avlTree_rightRotate") { int mapSize = generateRandomNumber(); @@ -192,6 +215,19 @@ TEST_CASE("test_stack_normalInitialize") disk_mng_initialize(); } +TEST_CASE("stack_firstInitialize") +{ + +} +TEST_CASE("stack_normalInitialize") +{ + +} +TEST_CASE("stack_saveData()") +{ + +} + TEST_CASE("test_stack_push") { disk_mng_initialize(); @@ -245,6 +281,21 @@ TEST_CASE("test_stackNode_create") //array tests +TEST_CASE("array_firstInitialize") +{ + +} + +TEST_CASE("array_normalInitialize") +{ + +} + +TEST_CASE("array_saveData") +{ + +} + TEST_CASE("test_array_deleteFromArray") { int index = generateRandomNumber(); From df9f93f83e4cd3ccbc418bf164267ae3375be6b7 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Thu, 8 Aug 2024 15:03:44 +0300 Subject: [PATCH 15/32] add doctests for all the avl tree functions --- Storage/Disk_Mng_Master.c | 60 +++-- Storage/Disk_Mng_Master.h | 10 +- Storage/Doctest.cpp | 479 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 499 insertions(+), 50 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index dda5cdf..b8fa90c 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -153,12 +153,12 @@ int avlNode_height(AVLNode_t* N) { } //AVL node info -AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex, int lru) +AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex) { AVLNodeInfo_t* newAVLNodeInfo = (AVLNodeInfo_t*)allocate_memory(sizeof(AVLNodeInfo_t), "Failed to allocate memory for AVL node info", "avlNodeInfo_create"); newAVLNodeInfo->mapSize = mapSize; newAVLNodeInfo->arrayIndex = arrayIndex; - newAVLNodeInfo->lru = lru; + newAVLNodeInfo->lru = disk_mng_CB->disk_SortByMapSize->lruCounter+1; return newAVLNodeInfo; } @@ -218,36 +218,33 @@ AVLNode_t* avlTree_minValueNode(AVLNode_t* node) { return current; } -AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter) { - if (node == NULL) +AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNode_t* newNode) { + if (node == NULL) { - data->lru = lruCounter; - return avlNode_create(data); + return newNode; } - if (data->mapSize < node->avlNodeInfo->mapSize) - node->left = avlTree_insert(node->left, data, lruCounter); - else if (data->mapSize > node->avlNodeInfo->mapSize) - node->right = avlTree_insert(node->right, data, lruCounter); + if (newNode->avlNodeInfo->mapSize < node->avlNodeInfo->mapSize) + node->left = avlTree_insert(node->left, newNode); else - return node; + node->right = avlTree_insert(node->right, newNode); node->height = 1 + max(avlNode_height(node->left), avlNode_height(node->right)); int balance = avlTree_getBalance(node); - if (balance > 1 && data->mapSize < node->left->avlNodeInfo->mapSize) + if (balance > 1 && newNode->avlNodeInfo->mapSize < node->left->avlNodeInfo->mapSize) return avlTree_rightRotate(node); - if (balance < -1 && data->mapSize > node->right->avlNodeInfo->mapSize) + if (balance < -1 && newNode->avlNodeInfo->mapSize > node->right->avlNodeInfo->mapSize) return avlTree_leftRotate(node); - if (balance > 1 && data->mapSize > node->left->avlNodeInfo->mapSize) { + if (balance > 1 && newNode->avlNodeInfo->mapSize > node->left->avlNodeInfo->mapSize) { node->left = avlTree_leftRotate(node->left); return avlTree_rightRotate(node); } - if (balance < -1 && data->mapSize < node->right->avlNodeInfo->mapSize) { + if (balance < -1 && newNode->avlNodeInfo->mapSize < node->right->avlNodeInfo->mapSize) { node->right = avlTree_rightRotate(node->right); return avlTree_leftRotate(node); } @@ -262,9 +259,9 @@ void avlTree_firstInitialize() { disk_mng_CB->disk_SortByMapSize->lruCounter = 0; } -void avlTree_insertElement(AVLNodeInfo_t* data) { +void avlTree_insertElement(AVLNode_t* newNode) { disk_mng_CB->disk_SortByMapSize->lruCounter++; - disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, data, disk_mng_CB->disk_SortByMapSize->lruCounter); + disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, newNode); disk_mng_CB->disk_SortByMapSize->totalElements++; } @@ -275,11 +272,19 @@ AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node) { } AVLNode_t* eligibleNode = NULL; + AVLNode_t* largestNode = node; // Check the right subtree first for the largest node AVLNode_t* rightResult = avlTree_FindingTheNodeThatIsSuitableForDeletion(node->right); - if (rightResult != NULL && rightResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { - eligibleNode = rightResult; + if (rightResult != NULL) { + if (rightResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { + if (eligibleNode == NULL || rightResult->avlNodeInfo->mapSize > (eligibleNode ? eligibleNode->avlNodeInfo->mapSize : 0)) { + eligibleNode = rightResult; + } + } + if (rightResult->avlNodeInfo->mapSize > largestNode->avlNodeInfo->mapSize) { + largestNode = rightResult; + } } // Check if the current node is eligible for deletion @@ -288,16 +293,25 @@ AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node) { eligibleNode = node; } } + if (node->avlNodeInfo->mapSize > largestNode->avlNodeInfo->mapSize) { + largestNode = node; + } // Check the left subtree if no eligible node found in the right subtree or current node AVLNode_t* leftResult = avlTree_FindingTheNodeThatIsSuitableForDeletion(node->left); - if (leftResult != NULL && leftResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { - if (eligibleNode == NULL || leftResult->avlNodeInfo->mapSize > eligibleNode->avlNodeInfo->mapSize) { - eligibleNode = leftResult; + if (leftResult != NULL) { + if (leftResult->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7) { + if (eligibleNode == NULL || leftResult->avlNodeInfo->mapSize > eligibleNode->avlNodeInfo->mapSize) { + eligibleNode = leftResult; + } + } + if (leftResult->avlNodeInfo->mapSize > largestNode->avlNodeInfo->mapSize) { + largestNode = leftResult; } } - return eligibleNode; + // Return the eligible node if found, otherwise return the node with the largest mapSize + return eligibleNode ? eligibleNode : largestNode; } AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { if (root == NULL) { diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 54d8a35..f65a4c5 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -96,7 +96,7 @@ void disk_mng_initialize(); //AVL node info // avlNodeInfo_create-Creates and returns a new AVLNodeInfo_t structure -AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex, int lru); +AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex); // avlNodeInfo_delete-Deletes an AVLNodeInfo_t structure void avlNodeInfo_delete(AVLNodeInfo_t* nodeInfo); @@ -126,14 +126,14 @@ int avlTree_getBalance(AVLNode_t* N); // avlTree_minValueNode-Finds and returns the node with the smallest value in the tree AVLNode_t* avlTree_minValueNode(AVLNode_t* node); -// avlTree_insert-Inserts a new node into the AVL tree -AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNodeInfo_t* data, int lruCounter); - // avlTree_firstInitialize-Initializes the AVL tree for the first time void avlTree_firstInitialize(); +// avlTree_insert-Inserts a new node into the AVL tree +AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNode_t* newNode); + // avlTree_insertElement-Inserts a new element into the AVL tree -void avlTree_insertElement(AVLNodeInfo_t* data); +void avlTree_insertElement(AVLNode_t* newNode); // avlTree_FindingTheNodeThatIsSuitableForDeletion-Finds the node suitable for deletion according to conditions AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 3d4495c..3d6fd84 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -3,8 +3,10 @@ #include #include #include - - +#include +#include +#include +#include extern "C" { #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" @@ -20,12 +22,118 @@ int generateRandomNumber(int upper = DISK_SIZE) { int lower = 0; return (rand() % (upper - lower + 1)) + lower; } +void printTreeDetails(AVLNode_t* node) { + if (node == NULL) { + return; + } + + // Print current node details + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); + printf("Height: %d\n\n", node->height); + + // Recurse on the left and right subtrees + printTreeDetails(node->left); + printTreeDetails(node->right); +} + +void printNode(AVLNode_t* node) { + if (node == NULL) { + printf("Node is NULL\n"); + return; + } + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); + + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); +} +void printTree(AVLNode_t* root) { + if (root == nullptr) { + return; + } + + // Queue for level order traversal + std::queue q; + q.push(root); + + // Vector to store levels of the tree + std::vector> levels; + + // Traverse the tree level by level + while (!q.empty()) { + int nodeCount = q.size(); + std::vector currentLevel; + + while (nodeCount > 0) { + AVLNode_t* node = q.front(); + q.pop(); + currentLevel.push_back(node); + + if (node != nullptr) { + q.push(node->left); + q.push(node->right); + } + nodeCount--; + } + + // Add level only if there are nodes at this level + if (std::any_of(currentLevel.begin(), currentLevel.end(), [](AVLNode_t* n) { return n != nullptr; })) { + levels.push_back(currentLevel); + } + } + + int maxLevel = levels.size(); + int width = 1 << (maxLevel - 1); // Maximum width of the tree at the last level + + for (int i = 0; i < maxLevel; ++i) { + std::vector currentLevel = levels[i]; + int numNodes = currentLevel.size(); + int spacing = width / (numNodes + 1); + int offset = spacing / 2; + + // Print leading spaces + std::cout << std::setw(offset) << ""; + + // Print nodes at current level + for (AVLNode_t* node : currentLevel) { + if (node == nullptr) { + std::cout << std::setw(width) << ""; + } + else { + std::cout << std::setw(width) << node->avlNodeInfo->mapSize; + } + std::cout << std::setw(offset) << ""; + } + std::cout << std::endl; + + // Print level separators + if (i < maxLevel - 1) { + std::cout << std::setw(width / 2) << ""; + for (AVLNode_t* node : currentLevel) { + if (node == nullptr) { + std::cout << std::setw(width) << ""; + } + else { + std::cout << std::setw(width / 2) << (node->left != nullptr ? "/" : " "); + std::cout << std::setw(width / 2) << (node->right != nullptr ? "\\" : " "); + } + std::cout << std::setw(width / 2) << ""; + } + std::cout << std::endl; + } + } +} int index, popValue,value; //mock functions //the function get pointer to map in the disk and delete this map from disk -void disk_deleteMap(int* diskPointer) {} +void disk_deleteMap(int* diskPointer) +{ +} //the function fill in the structer all the data which save befoe the computer closed,the function get destenation,suorce,length; @@ -46,34 +154,37 @@ TEST_CASE("test_disk_mng_initialize") TEST_CASE("test_avlNodeInfo_create") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); CHECK(avlNodeInfo->mapSize == mapSize); CHECK(avlNodeInfo->arrayIndex == indexArray); - CHECK(avlNodeInfo->lru == lru); + CHECK(avlNodeInfo->lru == 1); } TEST_CASE("test_avlNodeInfo_delete") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); avlNodeInfo_delete(avlNodeInfo); } TEST_CASE("test_avlNode_create") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode = avlNode_create(avlNodeInfo); CHECK(avlNode->avlNodeInfo == avlNodeInfo); @@ -84,22 +195,24 @@ TEST_CASE("test_avlNode_create") TEST_CASE("test_avlNode_delete") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode = avlNode_create(avlNodeInfo); avlNode_delete(avlNode); } TEST_CASE("test_avlNode_height") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode = avlNode_create(avlNodeInfo); CHECK(avlNode->height == avlNode_height(avlNode)); @@ -107,17 +220,18 @@ TEST_CASE("test_avlNode_height") TEST_CASE("test_avlTree_rightRotate") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); avlNode1->left = avlNode2; @@ -138,17 +252,18 @@ TEST_CASE("test_avlTree_rightRotate") TEST_CASE("test_avlTree_leftRotate") { + disk_mng_initialize(); + int mapSize = generateRandomNumber(); int indexArray = generateRandomNumber(); - int lru = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray, lru); + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); @@ -169,6 +284,326 @@ TEST_CASE("test_avlTree_leftRotate") CHECK(newRoot->height == 2); } +TEST_CASE("avlTree_getBalance") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize, indexArray); + + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* root = avlNode_create(info3); + + SUBCASE("Node is NULL") { + CHECK(avlTree_getBalance(nullptr) == 0); + } + + SUBCASE("Balance factor of a node with children having different heights") { + root->left = node1; + root->right = node2; + node1->height = 3; + node2->height = 1; + root->height = 4; + CHECK(avlTree_getBalance(root) == 2); + } + + SUBCASE("Balance factor of a node with both children having the same height") { + root->left = node1; + root->right = node2; + node1->height = 2; + node2->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 0); + } + + SUBCASE("Balance factor of a node with one child") { + root->left = node1; + root->right = nullptr; + node1->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 2); + } +} +TEST_CASE("test_avlTree_minValueNode") { + disk_mng_initialize(); + + int mapSize1 = generateRandomNumber(); + int indexArray1 = generateRandomNumber(); + + int mapSize2 = generateRandomNumber(); + int indexArray2 = generateRandomNumber(); + + int mapSize3 = generateRandomNumber(); + int indexArray3 = generateRandomNumber(); + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize1, indexArray1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize2, indexArray2); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize3, indexArray3); + + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* node3 = avlNode_create(info3); + + SUBCASE("Node with no left child") { + CHECK(avlTree_minValueNode(node1) == node1); + } + node1->left = node2; + node2->left = node3; + + SUBCASE("Node with left child") { + CHECK(avlTree_minValueNode(node1) == node3); + } +} +TEST_CASE("test_avlTree_insert") { + disk_mng_initialize(); + + SUBCASE("Insert into an empty tree") { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + AVLNode_t* node = avlNode_create(info); + + avlTree_insertElement(node); + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); + printf("first tree\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printf("\n"); + } + + SUBCASE("Insert nodes and check balancing") { + + for (int i = 0; i < 7; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + AVLNode_t* node = avlNode_create(info); + avlTree_insertElement(node); + } + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + printf("second tree\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printf("\n"); + + } + + SUBCASE("Insert duplicate mapSize") { + int mapSize = generateRandomNumber(); + int arrayIndex1 = generateRandomNumber(); + int arrayIndex2 = generateRandomNumber(); + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); + + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + + avlTree_insertElement(node1); + avlTree_insertElement(node2); + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->left == nullptr); + + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); + printf("third tree\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printf("\n"); + } +} +TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { + disk_mng_initialize(); + + SUBCASE("Find eligible node for deletion") { + // Insert nodes into the AVL tree with different LRU values + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + AVLNode_t* node = avlNode_create(info); + avlTree_insertElement(node); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + printf("Node suitable for deletion:\n"); + printNode(result); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); + + printf("\n"); + + } + + SUBCASE("All nodes are eligible for deletion") { + // Insert nodes with LRU values such that all are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + AVLNode_t* node = avlNode_create(info); + avlTree_insertElement(node); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + printf("Node suitable for deletion:\n"); + printNode(result); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); + + printf("\n"); + + } + + SUBCASE("No node is eligible for deletion") { + // Insert nodes with LRU values such that none are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + AVLNode_t* node = avlNode_create(info); + avlTree_insertElement(node); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); + printf("Node with largest mapSize:\n"); + printNode(result); + printTree(disk_mng_CB->disk_SortByMapSize->root); + printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); + + printf("\n"); + + } +} +//TEST_CASE("test_avlTree_deleteNode") { +// disk_mng_initialize(); +// +// SUBCASE("Delete a leaf node") { +// // Insert random nodes +// for (int i = 0; i < 5; i++) +// { +// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node1 = avlNode_create(info1); +// avlTree_insertElement(node1); +// } +// printf("Tree before deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// +// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); +// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); +// +// printf("Tree after deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// } +// +// SUBCASE("Delete a node with one child") { +// // Insert random nodes +// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node1 = avlNode_create(info1); +// avlTree_insertElement(node1); +// +// AVLNodeInfo_t* info2 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node2 = avlNode_create(info2); +// avlTree_insertElement(node2); +// +// AVLNodeInfo_t* info3 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node3 = avlNode_create(info3); +// avlTree_insertElement(node3); +// +// AVLNodeInfo_t* info4 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node4 = avlNode_create(info4); +// avlTree_insertElement(node4); +// +// // Make node4 a child of node3 +// node3->left = node4; +// +// printf("Tree before deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// +// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); +// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); +// +// printf("Tree after deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// } +// +// SUBCASE("Delete a node with two children") { +// // Insert random nodes +// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node1 = avlNode_create(info1); +// avlTree_insertElement(node1); +// +// AVLNodeInfo_t* info2 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node2 = avlNode_create(info2); +// avlTree_insertElement(node2); +// +// AVLNodeInfo_t* info3 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node3 = avlNode_create(info3); +// avlTree_insertElement(node3); +// +// AVLNodeInfo_t* info4 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node4 = avlNode_create(info4); +// avlTree_insertElement(node4); +// +// AVLNodeInfo_t* info5 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node5 = avlNode_create(info5); +// avlTree_insertElement(node5); +// +// AVLNodeInfo_t* info6 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node6 = avlNode_create(info6); +// avlTree_insertElement(node6); +// +// AVLNodeInfo_t* info7 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); +// AVLNode_t* node7 = avlNode_create(info7); +// avlTree_insertElement(node7); +// +// // Construct a more complex tree +// node4->left = node5; +// node4->right = node6; +// node2->right = node4; +// node1->left = node2; +// node1->right = node3; +// node3->left = node7; +// +// printf("Tree before deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// +// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); +// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); +// +// printf("Tree after deletion:\n"); +// printTree(disk_mng_CB->disk_SortByMapSize->root); +// printf("cghvjbk"); +// } +//} + + //stack tests TEST_CASE("test_stack_firstInitialize") From 457112dbc1b49c513c09d56d391f5cfc24e8ef50 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Sun, 11 Aug 2024 14:04:06 +0300 Subject: [PATCH 16/32] add addFunction --- Storage/Disk_Mng_Master.c | 60 +++++++++++++++++++++++++-- Storage/Disk_Mng_Master.h | 29 +++++++++---- Storage/Disk_Mng_Master_API.h | 3 ++ Storage/Doctest.cpp | 77 +++++++++++++++++++++-------------- Storage/Storage.vcxproj | 1 + 5 files changed, 128 insertions(+), 42 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index c76a6ef..76252c3 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -1,4 +1,6 @@ #include "Disk_Mng_Master.h" +#include "Disk_Mng_Master_API.h" + #pragma once #include #include @@ -29,6 +31,9 @@ void disk_mng_initialize() } } + + + void disk_mng_saveData() { stack_saveData(); @@ -43,6 +48,8 @@ void disk_mng_firstInitialize() stack_firstInitialize(); array_firstInitialize(); avlTree_firstInitialize(); + disk_mng_CB->mapIdIndex = 0; + } void disk_mng_normalInitialize() @@ -76,6 +83,7 @@ void stack_normalInitialize() { howManyToLoad = length * sizeof(int); //load all the data from stack disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress,&howManyToLoad) ; + } void stack_saveData() @@ -156,16 +164,21 @@ void array_saveData() } -ArrayInfo_t* arrayInfo_create(int mapid, int* diskPointer, int size, MapRange_t* range) +ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range) { ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for avlTree", "arrayInfo_create"); - arrayInfo->mapid = mapid; + arrayInfo->mapid = disk_mng_CB->mapIdIndex++; arrayInfo ->diskPointer = diskPointer; arrayInfo->size = size; arrayInfo->range =range; return arrayInfo; } +void array_addToArray(ArrayInfo_t* arrayInfo, int index) +{ + disk_mng_CB->arrayForAllMApsInformation[index] = arrayInfo; +} + void array_deleteFromArray(int index) { disk_mng_CB->arrayForAllMApsInformation[index] = NULL; @@ -354,8 +367,9 @@ void avlTree_saveData() } -void avlTree_insertElement(AVLNode_t* newNode) { +void avlTree_insertElement(AVLNodeInfo_t* nodeInfo) { disk_mng_CB->disk_SortByMapSize->lruCounter++; + AVLNode_t* newNode = avlNode_create(nodeInfo); disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, newNode); disk_mng_CB->disk_SortByMapSize->totalElements++; } @@ -475,3 +489,43 @@ void* allocate_memory(size_t size, const char* description, const char* function } return ptr; } +void disk_mng_addMap(MapRange_t* range, int size, int* map) +{ + + int* diskPointer = disk_addMap(map); + if (diskPointer != NULL)//success + { + if (stack_is_empty) + { + void disk_mng_delete(int size); + } + int index = stack_pop(); + disk_mng_addMapToDiskManagementDataStructures(range, size, diskPointer, index); + } + else + { + test_writeExceptionToFile(Error_When_Adding_Map_To_Disk, disk_mng_addMap); + } +} + +void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int* diskPointer, int index) +{ + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer,size,range); + array_addToArray(arrayInfo,index); + AVLNodeInfo_t* avlNode = avlNodeInfo_create(size, index); + avlTree_insertElement(avlNode); + +} + +bool disk_mng_checkDataStructures(MapRange_t* range, int size, int* map) +{ + if (map == NULL) + { + test_writeExceptionToFile(Error_Worng_Map_Variable, disk_mng_checkDataStructures); + } + if (size >0) + { + test_writeExceptionToFile(Error_Worng_Size_Variable, disk_mng_checkDataStructures); + } + //check range +} diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 3afeb1a..18958a5 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -3,6 +3,8 @@ #include #include #include +#include "Disk_Mng_Master_API.h" + #define DISK_SIZE 1000 @@ -19,7 +21,10 @@ typedef struct Disk_Management_CB_s Disk_Management_CB_t; // Enum declaration typedef enum { - Error_When_Allocating_Memory_Space + Error_When_Allocating_Memory_Space, + Error_When_Adding_Map_To_Disk, + Error_Worng_Size_Variable, + Error_Worng_Map_Variable } Exception; // Struct declarations @@ -38,7 +43,7 @@ struct AVLNode_s { struct DiskSortByMapSize_s { AVLNode_t* root; int totalElements; - int lruCounter; + int lruCounter; }; struct Point_s { @@ -69,6 +74,7 @@ struct DiskFreeIndexesInArray_s { StackNode_t* top; }; struct Disk_Management_CB_s { + int mapIdIndex; ArrayInfo_t** arrayForAllMApsInformation; StackNode_t* stackNode; DiskFreeIndexesInArray_t* diskFreeIndexesInArray; @@ -77,7 +83,7 @@ struct Disk_Management_CB_s { extern Disk_Management_CB_t* disk_mng_CB; // Function declarations - + // allocate_memory-Allocates memory and logs the allocation with a description and function name void* allocate_memory(size_t size, const char* description, const char* functionName); @@ -147,7 +153,7 @@ void avlTree_firstInitialize(); AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNode_t* newNode); // avlTree_insertElement-Inserts a new element into the AVL tree -void avlTree_insertElement(AVLNode_t* newNode); +void avlTree_insertElement(AVLNodeInfo_t* newNode); // avlTree_FindingTheNodeThatIsSuitableForDeletion-Finds the node suitable for deletion according to conditions AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node); @@ -201,13 +207,13 @@ void array_deleteFromArray(int index); // Frees or deletes information associated with an array. void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); +//create a new arrayInfo with all the parameters +ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range); + +void array_addToArray(ArrayInfo_t* arrayInfo, int index); //disk_deleteMap the function get pointer to map in the disk and delete this map from disk void disk_deleteMap(int* diskPointer); - -//create a new arrayInfo with all the parameters -ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range); - //create a new range with 2 point which given MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft); @@ -216,3 +222,10 @@ void disk_loadDataForInitializeDataStructers(void* destination, void* startAddre //disk_loadDataForInitializeDataStructers the function get data where to save and from where and how many to save void disk_saveDataFromStructersToDisk(void* data, void* startAddress, void* howManyToLoad); + +void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int* diskPointer, int index); + +int* disk_addMap(int* map); +void disk_mng_addMap(MapRange_t* range, int size, int* map); + + diff --git a/Storage/Disk_Mng_Master_API.h b/Storage/Disk_Mng_Master_API.h index ca3012b..72ac057 100644 --- a/Storage/Disk_Mng_Master_API.h +++ b/Storage/Disk_Mng_Master_API.h @@ -1,4 +1,7 @@ +#pragma once + #include "Disk_Mng_Master.h" +//function get pointer and load to disk return diskPointer if success and null if not diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 12c3408..2bdfba1 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -130,6 +130,17 @@ int index, popValue,value; //mock functions +int* disk_addMap(int* map) +{ + int num = generateRandomNumber(10000000); + if (num % 2 == 0) + { + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for disk control block", "disk_addMap"); + return map; + } + return NULL; +} + //the function get pointer to map in the disk and delete this map from disk void disk_deleteMap(int* diskPointer) { @@ -391,9 +402,7 @@ TEST_CASE("test_avlTree_insert") { int arrayIndex = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - - avlTree_insertElement(node); + avlTree_insertElement(info); CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); @@ -410,8 +419,7 @@ TEST_CASE("test_avlTree_insert") { int arrayIndex = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); @@ -429,11 +437,8 @@ TEST_CASE("test_avlTree_insert") { AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - - avlTree_insertElement(node1); - avlTree_insertElement(node2); + avlTree_insertElement(info1); + avlTree_insertElement(info2); CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); @@ -457,8 +462,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -482,8 +486,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -507,8 +510,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -650,15 +652,7 @@ TEST_CASE("test_stack_normalInitialize") disk_mng_initialize(); } -TEST_CASE("stack_firstInitialize") -{ - -} -TEST_CASE("stack_normalInitialize") -{ - -} -TEST_CASE("stack_saveData()") +TEST_CASE("stack_saveData") { } @@ -708,6 +702,7 @@ TEST_CASE("test_stack_is_empty") TEST_CASE("test_stackNode_create") { + disk_mng_initialize(); int index = generateRandomNumber(); StackNode_t* new_node = stackNode_create(index); CHECK(new_node->freeIndex == index); @@ -733,6 +728,7 @@ TEST_CASE("array_saveData") TEST_CASE("test_array_deleteFromArray") { + disk_mng_initialize(); int index = generateRandomNumber(); array_deleteFromArray(index); CHECK(disk_mng_CB->arrayForAllMApsInformation[index]== NULL); @@ -740,7 +736,7 @@ TEST_CASE("test_array_deleteFromArray") TEST_CASE("test_arrayInfo_create") { - int mapid = generateRandomNumber();; + disk_mng_initialize(); int * diskPointer = NULL; int size = generateRandomNumber(); Point_t topLeft; @@ -750,19 +746,38 @@ TEST_CASE("test_arrayInfo_create") bottomRight.x = generateRandomNumber(); bottomRight.y = generateRandomNumber(); MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - - - //arrayInfo->avlInfo = avlInfo; - ArrayInfo_t* arrayInfo= arrayInfo_create(mapid, diskPointer, size, mapRange); - CHECK(arrayInfo->mapid == mapid); + ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange); + CHECK(arrayInfo->mapid == 0); CHECK(arrayInfo->diskPointer == NULL); CHECK(arrayInfo->size == size); CHECK(arrayInfo->range == mapRange); } +TEST_CASE("test_array_addToArray") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + int* diskPointer = NULL; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange); + int index = stack_pop(); + array_addToArray(arrayInfo, index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); + } +} + //range functions TEST_CASE("test_mapRange_create") { + disk_mng_initialize(); Point_t topLeft; topLeft.x = generateRandomNumber(); topLeft.y = generateRandomNumber(); diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index e6ef62e..e43783f 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -132,6 +132,7 @@ + From 662abf5b5bc043db4fb67d0500ff18a7802a1779 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Sun, 11 Aug 2024 14:07:12 +0300 Subject: [PATCH 17/32] add delete functions --- Storage/Disk_Mng_Master.c | 75 +++++++++++++++--- Storage/Disk_Mng_Master.h | 20 +++-- Storage/Doctest.cpp | 162 +++++++++----------------------------- 3 files changed, 117 insertions(+), 140 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index b8fa90c..42eeea5 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -50,9 +50,9 @@ StackNode_t* stackNode_create(int index) } -void stack_push(StackNode_t* new_node) +void stack_push(int index) { - + StackNode_t* new_node = stackNode_create(index); disk_mng_CB->diskFreeIndexesInArray->size++; disk_mng_CB->diskFreeIndexesInArray->top = new_node; } @@ -146,10 +146,33 @@ void test_writeExceptionToFile(Exception exception, const char* source) { fclose(file); } -int avlNode_height(AVLNode_t* N) { - if (N == NULL) - return 0; - return N->height; +int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) +{ + AVLNodeInfo_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root);//find the suitable map to delete + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root,nodeToDelete);//delete the map from the AVL tree + ArrayInfo_t* arrayInfo = disk_mng_CB->arrayForAllMApsInformation[nodeToDelete->arrayIndex];//finding the object that corresponds to deletion in the array + bool isDeleteSuccess=disk_deleteMap(arrayInfo->diskPointer);//send API to the disk to delete the map + if (isDeleteSuccess) + { + cache_deleteMap(arrayInfo->mapid);//send API to the cache to delete the map + stack_push(nodeToDelete->arrayIndex);//push the index to the stack of free indexes + sizeToFree -= arrayInfo->size;//reducing the size that needs to be deleted + array_deleteFromArray(nodeToDelete->arrayIndex);//delete the map from the array + array_deleteArrayInfo(arrayInfo);//delete the array object + avlNode_delete(nodeToDelete);//delete the avl node + } + else + { + test_writeExceptionToFile(Error_When_Deleting_Map_from_Disk,"disk_mng_deleteMapFromDiskManagementDataStructures"); + } +} + +void disk_mng_delete(int mapSize) +{ + while (mapSize>0) + { + mapSize = disk_mng_deleteMapFromDiskManagementDataStructures(mapSize); + } } //AVL node info @@ -184,6 +207,13 @@ void avlNode_delete(AVLNode_t* node) { } } +int avlNode_height(AVLNode_t* N) { + if (N == NULL) + return 0; + return N->height; +} + + AVLNode_t* avlTree_rightRotate(AVLNode_t* y) { AVLNode_t* x = y->left; @@ -259,8 +289,9 @@ void avlTree_firstInitialize() { disk_mng_CB->disk_SortByMapSize->lruCounter = 0; } -void avlTree_insertElement(AVLNode_t* newNode) { +void avlTree_insertElement(AVLNodeInfo_t* nodeInfo) { disk_mng_CB->disk_SortByMapSize->lruCounter++; + AVLNode_t* newNode = avlNode_create(nodeInfo); disk_mng_CB->disk_SortByMapSize->root = avlTree_insert(disk_mng_CB->disk_SortByMapSize->root, newNode); disk_mng_CB->disk_SortByMapSize->totalElements++; } @@ -318,7 +349,7 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { return root; } - // Traverse the tree to find the node + // STEP 1: PERFORM STANDARD BST DELETE if (node->avlNodeInfo->mapSize < root->avlNodeInfo->mapSize) { root->left = avlTree_deleteNode(root->left, node); } @@ -326,44 +357,66 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { root->right = avlTree_deleteNode(root->right, node); } else { - // Node with mapSize found + // This is the node to be deleted if ((root->left == NULL) || (root->right == NULL)) { AVLNode_t* temp = root->left ? root->left : root->right; + + // No child case if (temp == NULL) { + // Simply remove the current node root = NULL; } else { + // One child case + // Update root to point to the non-empty child *root = *temp; + // Make sure to set the child pointers of the old node to NULL + root->left = temp->left; + root->right = temp->right; } } else { + // Node with two children: Get the inorder successor (smallest in the right subtree) AVLNode_t* temp = avlTree_minValueNode(root->right); + + // Copy the inorder successor's data to this node root->avlNodeInfo = temp->avlNodeInfo; + + // Delete the inorder successor root->right = avlTree_deleteNode(root->right, temp); } } + // If the tree had only one node then return if (root == NULL) { return root; } - // Update height and balance the node - root->height = max(avlNode_height(root->left), avlNode_height(root->right)) + 1; + // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE + root->height = 1 + max(avlNode_height(root->left), avlNode_height(root->right)); + + // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this node became unbalanced) int balance = avlTree_getBalance(root); + // If this node becomes unbalanced, then there are 4 cases + + // Left Left Case if (balance > 1 && avlTree_getBalance(root->left) >= 0) { return avlTree_rightRotate(root); } + // Left Right Case if (balance > 1 && avlTree_getBalance(root->left) < 0) { root->left = avlTree_leftRotate(root->left); return avlTree_rightRotate(root); } + // Right Right Case if (balance < -1 && avlTree_getBalance(root->right) <= 0) { return avlTree_leftRotate(root); } + // Right Left Case if (balance < -1 && avlTree_getBalance(root->right) > 0) { root->right = avlTree_rightRotate(root->right); return avlTree_leftRotate(root); diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index f65a4c5..59a79ac 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -19,7 +19,8 @@ typedef struct Disk_Management_CB_s Disk_Management_CB_t; // Enum declaration typedef enum { - Error_When_Allocating_Memory_Space + Error_When_Allocating_Memory_Space, + Error_When_Deleting_Map_from_Disk } Exception; // Struct declarations @@ -85,6 +86,12 @@ void* allocate_memory(size_t size, const char* description, const char* function // test_writeExceptionToFile-Writes exception details to a file void test_writeExceptionToFile(Exception exception, const char* source); +//disk_mng_DeleteMapFromDiskManagementDataStructures- delete map from the disk +int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree); + +//disk_mng_delete-Deleting maps until there is enough space to add a new map with the resulting size to disk +void disk_mng_delete(int mapSize); + //initialize // disk_mng_initialize_CB-Initializes the control block for disk management @@ -133,7 +140,7 @@ void avlTree_firstInitialize(); AVLNode_t* avlTree_insert(AVLNode_t* node, AVLNode_t* newNode); // avlTree_insertElement-Inserts a new element into the AVL tree -void avlTree_insertElement(AVLNode_t* newNode); +void avlTree_insertElement(AVLNodeInfo_t* nodeInfo); // avlTree_FindingTheNodeThatIsSuitableForDeletion-Finds the node suitable for deletion according to conditions AVLNode_t* avlTree_FindingTheNodeThatIsSuitableForDeletion(AVLNode_t* node); @@ -153,8 +160,8 @@ void stack_normalInitialize(); bool stack_is_empty(); -// Push a new node onto the stack -void stack_push(StackNode_t* new_node); +// Push a new node into the stack +void stack_push(int index); // Create a new stack node with the given index value StackNode_t* stackNode_create(int index); @@ -182,9 +189,10 @@ void array_deleteFromArray(int index); // Frees or deletes information associated with an array. void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); - //disk_deleteMap the function get pointer to map in the disk and delete this map from disk -void disk_deleteMap(int* diskPointer); +bool disk_deleteMap(int* diskPointer); + +void cache_deleteMap(int mapId); ArrayInfo_t* arrayInfo_create(int mapid,int* diskPointer,int size,MapRange_t* range //,AVLNodeInfo_t* avlInfo// diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 3d6fd84..429e353 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -131,11 +131,13 @@ int index, popValue,value; //mock functions //the function get pointer to map in the disk and delete this map from disk -void disk_deleteMap(int* diskPointer) +bool disk_deleteMap(int* diskPointer) +{ + return true; +} +void cache_deleteMap(int mapId) { } - - //the function fill in the structer all the data which save befoe the computer closed,the function get destenation,suorce,length; void disk_loadDataForInitializeDataStructers(void* i,void* x,void* b) { @@ -368,9 +370,8 @@ TEST_CASE("test_avlTree_insert") { int arrayIndex = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); @@ -387,8 +388,7 @@ TEST_CASE("test_avlTree_insert") { int arrayIndex = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); @@ -406,11 +406,8 @@ TEST_CASE("test_avlTree_insert") { AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - - avlTree_insertElement(node1); - avlTree_insertElement(node2); + avlTree_insertElement(info1); + avlTree_insertElement(info2); CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); @@ -434,8 +431,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -459,8 +455,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -484,8 +479,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - AVLNode_t* node = avlNode_create(info); - avlTree_insertElement(node); + avlTree_insertElement(info); } AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); @@ -501,107 +495,30 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { } } -//TEST_CASE("test_avlTree_deleteNode") { -// disk_mng_initialize(); -// -// SUBCASE("Delete a leaf node") { -// // Insert random nodes -// for (int i = 0; i < 5; i++) -// { -// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node1 = avlNode_create(info1); -// avlTree_insertElement(node1); -// } -// printf("Tree before deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// -// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); -// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); -// -// printf("Tree after deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// } -// -// SUBCASE("Delete a node with one child") { -// // Insert random nodes -// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node1 = avlNode_create(info1); -// avlTree_insertElement(node1); -// -// AVLNodeInfo_t* info2 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node2 = avlNode_create(info2); -// avlTree_insertElement(node2); -// -// AVLNodeInfo_t* info3 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node3 = avlNode_create(info3); -// avlTree_insertElement(node3); -// -// AVLNodeInfo_t* info4 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node4 = avlNode_create(info4); -// avlTree_insertElement(node4); -// -// // Make node4 a child of node3 -// node3->left = node4; -// -// printf("Tree before deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// -// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); -// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); -// -// printf("Tree after deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// } -// -// SUBCASE("Delete a node with two children") { -// // Insert random nodes -// AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node1 = avlNode_create(info1); -// avlTree_insertElement(node1); -// -// AVLNodeInfo_t* info2 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node2 = avlNode_create(info2); -// avlTree_insertElement(node2); -// -// AVLNodeInfo_t* info3 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node3 = avlNode_create(info3); -// avlTree_insertElement(node3); -// -// AVLNodeInfo_t* info4 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node4 = avlNode_create(info4); -// avlTree_insertElement(node4); -// -// AVLNodeInfo_t* info5 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node5 = avlNode_create(info5); -// avlTree_insertElement(node5); -// -// AVLNodeInfo_t* info6 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node6 = avlNode_create(info6); -// avlTree_insertElement(node6); -// -// AVLNodeInfo_t* info7 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); -// AVLNode_t* node7 = avlNode_create(info7); -// avlTree_insertElement(node7); -// -// // Construct a more complex tree -// node4->left = node5; -// node4->right = node6; -// node2->right = node4; -// node1->left = node2; -// node1->right = node3; -// node3->left = node7; -// -// printf("Tree before deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// -// AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); -// disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); -// -// printf("Tree after deletion:\n"); -// printTree(disk_mng_CB->disk_SortByMapSize->root); -// printf("cghvjbk"); -// } -//} +TEST_CASE("test_avlTree_deleteNode") { + disk_mng_initialize(); + + for (int i = 0; i < 10; i++) + { + AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); + avlTree_insertElement(info1); + } + printf("Tree before deletion:\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); + + AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + if (nodeToDelete!=NULL) + { + printf("the node to delete:\n"); + printNode(nodeToDelete); + + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); + + printf("Tree after deletion:\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); + + } +} //stack tests @@ -611,8 +528,8 @@ TEST_CASE("test_stack_firstInitialize") disk_mng_initialize(); for (int i = 0; i < DISK_SIZE; i++) { - StackNode_t* newNode = stackNode_create(i); - stack_push(newNode); + + stack_push(i); } for (int i =DISK_SIZE-1; i >0; i--) @@ -633,8 +550,7 @@ TEST_CASE("test_stack_push") for (size_t i = 0; i < DISK_SIZE; i++) { index = generateRandomNumber(); - StackNode_t* newStackNode= stackNode_create(index); - stack_push(newStackNode); + stack_push(index); popValue = stack_pop(); CHECK(popValue == index); } From d4dcbc5e6a6a276a56dab5a854c9a753e6ec70ef Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Wed, 14 Aug 2024 10:37:16 +0300 Subject: [PATCH 18/32] fix the errors in delete function --- Storage/Disk_Mng_Master.c | 39 ++++++++++++++++++----- Storage/Disk_Mng_Master.h | 4 +++ Storage/Doctest.cpp | 66 +++++++++++++++++++++++---------------- Storage/errors.log.txt | 10 ++++++ 4 files changed, 84 insertions(+), 35 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 090bdd0..e3c64cc 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -140,11 +140,15 @@ int stack_top() { //array fuctions void array_firstInitialize() { - disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(DISK_SIZE*sizeof(ArrayInfo_t*), "Failed to allocate memory for stack ", "array_firstInitialize"); + disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(DISK_SIZE*sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); + if (disk_mng_CB->arrayForAllMApsInformation != NULL) { + for (int i = 0; i < DISK_SIZE; i++) { + disk_mng_CB->arrayForAllMApsInformation[i] = NULL; + } + } } - void array_normalInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for stack ", "array_normalInitialize"); + disk_mng_CB->diskFreeIndexesInArray = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); int startAdress = 12 + disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int); int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t**); //load all the data from array @@ -227,18 +231,33 @@ void test_writeExceptionToFile(Exception exception, const char* source) { int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) { - AVLNodeInfo_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root);//find the suitable map to delete - disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root,nodeToDelete);//delete the map from the AVL tree - ArrayInfo_t* arrayInfo = disk_mng_CB->arrayForAllMApsInformation[nodeToDelete->arrayIndex];//finding the object that corresponds to deletion in the array + printTree(disk_mng_CB->disk_SortByMapSize->root); + + AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root);//find the suitable map to delete + printNode(nodeToDelete); + ArrayInfo_t* arrayInfo = disk_mng_CB->arrayForAllMApsInformation[nodeToDelete->avlNodeInfo->arrayIndex];//finding the object that corresponds to deletion in the array + for (int i = 0; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) + { + printf("size %d index %d ", disk_mng_CB->arrayForAllMApsInformation[i]->size,i); + + } + + } + bool isDeleteSuccess=disk_deleteMap(arrayInfo->diskPointer);//send API to the disk to delete the map if (isDeleteSuccess) { cache_deleteMap(arrayInfo->mapid);//send API to the cache to delete the map - stack_push(nodeToDelete->arrayIndex);//push the index to the stack of free indexes + stack_push(nodeToDelete->avlNodeInfo->arrayIndex);//push the index to the stack of free indexes sizeToFree -= arrayInfo->size;//reducing the size that needs to be deleted - array_deleteFromArray(nodeToDelete->arrayIndex);//delete the map from the array + array_deleteFromArray(nodeToDelete->avlNodeInfo->arrayIndex);//delete the map from the array array_deleteArrayInfo(arrayInfo);//delete the array object + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete);//delete the map from the AVL tree + disk_mng_CB->disk_SortByMapSize->totalElements--; avlNode_delete(nodeToDelete);//delete the avl node + } else { @@ -473,6 +492,7 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { if (temp == NULL) { // Simply remove the current node root = NULL; + } else { // One child case @@ -481,7 +501,9 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { // Make sure to set the child pointers of the old node to NULL root->left = temp->left; root->right = temp->right; + } + } else { // Node with two children: Get the inorder successor (smallest in the right subtree) @@ -492,6 +514,7 @@ AVLNode_t* avlTree_deleteNode(AVLNode_t* root, AVLNode_t* node) { // Delete the inorder successor root->right = avlTree_deleteNode(root->right, temp); + } } diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index de06946..0fa805b 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -83,6 +83,10 @@ struct Disk_Management_CB_s { DiskSortByMapSize_t* disk_SortByMapSize; }; extern Disk_Management_CB_t* disk_mng_CB; +void printTree(AVLNode_t* root); +void printNode(AVLNode_t* node); + + // Function declarations diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 2c5a4b7..c085539 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -756,8 +756,18 @@ TEST_CASE("test_disk_mng_addMap") printf("mapIdIndex%d\n", disk_mng_CB->mapIdIndex); } + for (int i = 0; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) + { + printf("%d ", disk_mng_CB->arrayForAllMApsInformation[i]->size); + + } + + } + printf("\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 20); } @@ -778,6 +788,17 @@ TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { disk_mng_addMap(mapRange, size, map); // Add maps to the disk printf("%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); } + for (int i = 0; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) + { + printf("%d ", disk_mng_CB->arrayForAllMApsInformation[i]->size); + + } + + } + printf("\n"); + printTree(disk_mng_CB->disk_SortByMapSize->root); // Verify that the disk is full and needs deletion REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); @@ -786,36 +807,27 @@ TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { int sizeToFree = generateRandomNumber(); // Random size to free disk_mng_delete(sizeToFree); - // Ensure that space has been freed - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); - } + printf("\n"); -} + //printTree(disk_mng_CB->disk_SortByMapSize->root); -TEST_CASE("Test disk_mng_delete") { - disk_mng_initialize(); // Initialize the disk management control block + printf("\n"); + + for (int i = 0; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) + { + printf("size %d index %d ", disk_mng_CB->arrayForAllMApsInformation[i]->size, i); + + } - SUBCASE("Delete multiple maps until sufficient space is freed") { - // Add maps until the disk is full - for (int i = 0; i < 10; i++) { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); // Add maps to the disk } - // Perform multiple deletions to free space - int totalSizeToFree = generateRandomNumber(); - disk_mng_delete(totalSizeToFree); - // Ensure that sufficient space has been freed - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 10); - REQUIRE(totalSizeToFree <= 0); // Verify that enough space was freed + // Ensure that space has been freed + REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); + } -} \ No newline at end of file + +} + diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 669fcea..30f2a5d 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -266,3 +266,13 @@ Error: Unknown exception. Error: Unknown exception. disk_mng_checkDataStructures_mapSize: Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Unknown exception. From ba463c9f1528b17aff08e4f79e754371947f45e5 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Wed, 14 Aug 2024 12:10:22 +0300 Subject: [PATCH 19/32] add check range and write exception-without errors --- Storage/Disk_Mng_Master.c | 83 ++++++++++++++++++++++++--------------- Storage/Disk_Mng_Master.h | 6 ++- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index e3c64cc..2dfc39a 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -148,14 +148,11 @@ void array_firstInitialize() { } } void array_normalInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); + disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); int startAdress = 12 + disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int); int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t**); //load all the data from array - disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress, &howManyToLoad); - - - + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->arrayForAllMApsInformation), &startAdress, &howManyToLoad); } void array_saveData() @@ -203,32 +200,6 @@ MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft) mapRange->topLeft = topLeft; return mapRange; } - - - - -void test_writeExceptionToFile(Exception exception, const char* source) { - FILE* file; - errno_t err = fopen_s(&file, "errors.log.txt", "a"); - if (err != 0) { - fprintf(stderr, "Error opening file for writing\n"); - return; - } - - const char* error_message; - switch (exception) { - case Error_When_Allocating_Memory_Space: - error_message = "Error: Error when allocating memory space."; - break; - default: - error_message = "Error: Unknown exception."; - break; - } - - fprintf(file, "%s:\n%s\n", source, error_message); - fclose(file); -} - int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) { printTree(disk_mng_CB->disk_SortByMapSize->root); @@ -607,10 +578,58 @@ bool disk_mng_isTheDataCorrect(MapRange_t* range, int size, int* map) test_writeExceptionToFile(Error_Worng_Size_Variable, "disk_mng_checkDataStructures_mapSize"); return false; } - if (false) + if (isCorrectRange(range)) { test_writeExceptionToFile(Error_Worng_Map_Range, "disk_mng_checkDataStructures_range"); return false; } return true; } +void test_writeExceptionToFile(Exception exception, const char* source) { + FILE* file; + errno_t err = fopen_s(&file, "errors.log.txt", "a"); + if (err != 0) { + fprintf(stderr, "Error opening file for writing\n"); + return; + } + const char* error_message; + switch (exception) { + case Error_When_Allocating_Memory_Space: + error_message = "Error: Error when allocating memory space."; + break; + case Error_When_Deleting_Map_from_Disk: + error_message = "Error: Error when deleting map from disk."; + break; + case Error_When_Adding_Map_To_Disk: + error_message = "Error: Error when adding map to disk."; + break; + case Error_Worng_Size_Variable: + error_message = "Error: Error worng size variable."; + break; + case Error_Worng_Map_Variable: + error_message = "Error: Error worng map variable."; + break; + case Error_Worng_Map_Range: + error_message = "Error: Error worng map range."; + break; + default: + error_message = "Error: Unknown exception."; + break; + } + + fprintf(file, "%s:\n%s\n", source, error_message); + fclose(file); +} +bool isCorrectRange(MapRange_t* range) +{ + + if (range->topLeft.x < 0 || range->topLeft.y < 0 || range->bottomRight.x<0 || range->bottomRight.y<0//negetavie + || range->topLeft.x > range->bottomRight.x || range->topLeft.y > range->bottomRight.y //worng + || range->topLeft.xtopLeft.ybottomRight.x>POINT_BR_RANGE.x || range->bottomRight.y>POINT_BR_RANGE.y)//not in disk range + { + return false; + } + + return true; +} \ No newline at end of file diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 0fa805b..d25e245 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -5,7 +5,8 @@ #include #include "Disk_Mng_Master_API.h" - +#define POINT_BR_RANGE (Point_t){100, 100} +#define POINT_TL_RANGE (Point_t){0, 0} #define DISK_SIZE 1000 // Forward declarations @@ -78,7 +79,6 @@ struct DiskFreeIndexesInArray_s { struct Disk_Management_CB_s { int mapIdIndex; ArrayInfo_t** arrayForAllMApsInformation; - StackNode_t* stackNode; DiskFreeIndexesInArray_t* diskFreeIndexesInArray; DiskSortByMapSize_t* disk_SortByMapSize; }; @@ -251,3 +251,5 @@ int* disk_addMap(int* map); void disk_mng_addMap(MapRange_t* range, int size, int* map); bool disk_isThereEnoughSpace(int mapSize); + +bool isCorrectRange(MapRange_t* range); From b0cd5d4c8cc334e435bf64742d931854fde61ea0 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Thu, 15 Aug 2024 09:16:06 +0300 Subject: [PATCH 20/32] Adding a pointer to the tree and correcting the functions after adding --- Storage/Disk_Mng_Master.c | 13 +++++++------ Storage/Disk_Mng_Master.h | 4 ++-- Storage/Doctest.cpp | 7 +++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 2dfc39a..c0ee540 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -164,7 +164,7 @@ void array_saveData() } -ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range) +ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range,AVLNodeInfo_t* avlNodeInfo) { ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for avlTree", "arrayInfo_create"); disk_mng_CB->mapIdIndex++; @@ -172,6 +172,7 @@ ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range) arrayInfo ->diskPointer = diskPointer; arrayInfo->size = size; arrayInfo->range =range; + arrayInfo->avlNodeInfo = avlNodeInfo; return arrayInfo; } @@ -559,11 +560,11 @@ void disk_mng_addMap(MapRange_t* range, int size, int* map) void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int* diskPointer) { int index = stack_pop(); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer,size,range); - array_addToArray(arrayInfo,index); - AVLNodeInfo_t* avlNode = avlNodeInfo_create(size, index); - avlTree_insertElement(avlNode); - + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(size, index); + avlTree_insertElement(avlNodeInfo); + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, range,avlNodeInfo); + array_addToArray(arrayInfo, index); + } bool disk_mng_isTheDataCorrect(MapRange_t* range, int size, int* map) diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index d25e245..689f574 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -64,7 +64,7 @@ struct ArrayInfo_s { int* diskPointer; int size; MapRange_t* range; - + AVLNodeInfo_t* avlNodeInfo; }; struct StackNode_s { @@ -231,7 +231,7 @@ void cache_deleteMap(int mapId); //create a new arrayInfo with all the parameters -ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range); +ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range,AVLNodeInfo_t* avlNodeInfo); void array_addToArray(ArrayInfo_t* arrayInfo, int index); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index c085539..f76f2f3 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -690,7 +690,9 @@ TEST_CASE("test_arrayInfo_create") bottomRight.x = generateRandomNumber(); bottomRight.y = generateRandomNumber(); MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange,nodeInfo); CHECK(arrayInfo->mapid == 1); CHECK(arrayInfo->diskPointer == NULL); CHECK(arrayInfo->size == size); @@ -711,8 +713,9 @@ TEST_CASE("test_array_addToArray") bottomRight.x = generateRandomNumber(); bottomRight.y = generateRandomNumber(); MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange); int index = stack_pop(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange,nodeInfo); array_addToArray(arrayInfo, index); CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); printf("mapId%d\n", disk_mng_CB->mapIdIndex); From 170f5b44324de3f8978d0cf1b920c4756a5a3f41 Mon Sep 17 00:00:00 2001 From: sariDaitch Date: Thu, 15 Aug 2024 14:30:50 +0300 Subject: [PATCH 21/32] add array for maps in loaded and more few functions+ tests --- Storage/Disk_Mng_Master.c | 108 ++++++++++++++++----- Storage/Disk_Mng_Master.h | 66 ++++++++++--- Storage/Doctest.cpp | 199 +++++++++++++++++++++----------------- 3 files changed, 246 insertions(+), 127 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index c0ee540..376faf7 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -29,6 +29,7 @@ void disk_mng_initialize() { disk_mng_normalInitialize(); } + arrayInLoaded_initialize(); } @@ -60,6 +61,24 @@ void disk_mng_normalInitialize() avlTree_normalInitialize(); } +void arrayInLoaded_initialize() +{ + disk_mng_CB->disk_MapsInLoadedToCache = (DiskMapsInLoadedToCache_t**)allocate_memory(CACHE_SIZE *sizeof(DiskMapsInLoadedToCache_t*), "Failed to allocate memory for array in loaded ", "arrayInLoaded_initialize"); + if (disk_mng_CB->disk_MapsInLoadedToCache != NULL) { + for (int i = 0; i < CACHE_SIZE; i++) { + disk_mng_CB->disk_MapsInLoadedToCache[i] = NULL; + } + } +} + +DiskMapsInLoadedToCache_t* arrayInLoaded_create(int mapId, int index) +{ + DiskMapsInLoadedToCache_t* arrayInfo = (DiskMapsInLoadedToCache_t*)allocate_memory(sizeof(DiskMapsInLoadedToCache_t), "Failed to allocate memory for array in loaded info", "arrayInLoaded_create"); + arrayInfo->mapId = mapId; + arrayInfo->index = index; + return arrayInfo; +} + //initialize on the first time we turn o the computer the stack will initialize with all the indexes. void stack_firstInitialize() { disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); @@ -203,38 +222,29 @@ MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft) } int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) { - printTree(disk_mng_CB->disk_SortByMapSize->root); - AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root);//find the suitable map to delete - printNode(nodeToDelete); ArrayInfo_t* arrayInfo = disk_mng_CB->arrayForAllMApsInformation[nodeToDelete->avlNodeInfo->arrayIndex];//finding the object that corresponds to deletion in the array - for (int i = 0; i < DISK_SIZE; i++) + if (disk_mng_searchForSuitableMapInLoadingArray(arrayInfo->mapid)==-1)//check if the map not in loaded to the cache { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) + bool isDeleteSuccess = disk_deleteMap(arrayInfo->diskPointer);//send API to the disk to delete the map + if (isDeleteSuccess) { - printf("size %d index %d ", disk_mng_CB->arrayForAllMApsInformation[i]->size,i); + cache_deleteMap(arrayInfo->mapid);//send API to the cache to delete the map + stack_push(nodeToDelete->avlNodeInfo->arrayIndex);//push the index to the stack of free indexes + sizeToFree -= arrayInfo->size;//reducing the size that needs to be deleted + array_deleteFromArray(nodeToDelete->avlNodeInfo->arrayIndex);//delete the map from the array + array_deleteArrayInfo(arrayInfo);//delete the array object + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete);//delete the map from the AVL tree + disk_mng_CB->disk_SortByMapSize->totalElements--; + avlNode_delete(nodeToDelete);//delete the avl node } + else + { + test_writeExceptionToFile(Error_When_Deleting_Map_from_Disk, "disk_mng_deleteMapFromDiskManagementDataStructures"); + } } - - bool isDeleteSuccess=disk_deleteMap(arrayInfo->diskPointer);//send API to the disk to delete the map - if (isDeleteSuccess) - { - cache_deleteMap(arrayInfo->mapid);//send API to the cache to delete the map - stack_push(nodeToDelete->avlNodeInfo->arrayIndex);//push the index to the stack of free indexes - sizeToFree -= arrayInfo->size;//reducing the size that needs to be deleted - array_deleteFromArray(nodeToDelete->avlNodeInfo->arrayIndex);//delete the map from the array - array_deleteArrayInfo(arrayInfo);//delete the array object - disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete);//delete the map from the AVL tree - disk_mng_CB->disk_SortByMapSize->totalElements--; - avlNode_delete(nodeToDelete);//delete the avl node - - } - else - { - test_writeExceptionToFile(Error_When_Deleting_Map_from_Disk,"disk_mng_deleteMapFromDiskManagementDataStructures"); - } } void disk_mng_delete(int mapSize) @@ -633,4 +643,52 @@ bool isCorrectRange(MapRange_t* range) } return true; -} \ No newline at end of file +} + +bool disk_mng_isTheMapInRange(MapRange_t* rangeFromCache, MapRange_t* range) +{ + if ((range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || + (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y) || + (range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || + (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y) ) + { + return true; + } + return false; +} + + +bool disk_mng_loadMapFromDiskToCache(int mapId, int offset, int size, int* freeAddress) +{ + int* diskPointer; + int startAddress; + bool isLoadedSuccess=false; + int index = disk_mng_searchForSuitableMapInLoadingArray(mapId); + if (index!=-1)//Checking whether the map was found in the loading array + { + diskPointer = disk_mng_CB->arrayForAllMApsInformation[index]->diskPointer;//Finding the appropriate disk pointer + disk_mng_CB->arrayForAllMApsInformation[index] = NULL; + startAddress = diskPointer+(offset*sizeof(int)); + isLoadedSuccess = disk_loadMapToCache(startAddress, size, freeAddress); + if (!isLoadedSuccess) + { + test_writeExceptionToFile(Error_When_Load_Map_From_Disk_To_Cache, "disk_mng_loadMapFromDiskToCache"); + } + + } + return isLoadedSuccess; +} + +int disk_mng_searchForSuitableMapInLoadingArray(int mapId) +{ + DiskMapsInLoadedToCache_t* map; + for (int i = 0; i < CACHE_SIZE; i++) + { + map = disk_mng_CB->disk_MapsInLoadedToCache[i]; + if (map!=NULL&&mapId == map->mapId) + { + return map->index; + } + } + return -1; +} diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 689f574..6a37cff 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -8,6 +8,7 @@ #define POINT_BR_RANGE (Point_t){100, 100} #define POINT_TL_RANGE (Point_t){0, 0} #define DISK_SIZE 1000 +#define CACHE_SIZE 1000 // Forward declarations typedef struct AVLNode_s AVLNode_t; @@ -19,6 +20,7 @@ typedef struct ArrayInfo_s ArrayInfo_t; typedef struct StackNode_s StackNode_t; typedef struct DiskFreeIndexesInArray_s DiskFreeIndexesInArray_t; typedef struct Disk_Management_CB_s Disk_Management_CB_t; +typedef struct DiskMapsInLoadedToCache_s DiskMapsInLoadedToCache_t; // Enum declaration typedef enum { @@ -27,7 +29,8 @@ typedef enum { Error_When_Adding_Map_To_Disk, Error_Worng_Size_Variable, Error_Worng_Map_Variable, - Error_Worng_Map_Range + Error_Worng_Map_Range, + Error_When_Load_Map_From_Disk_To_Cache } Exception; // Struct declarations @@ -76,11 +79,19 @@ struct DiskFreeIndexesInArray_s { int size; StackNode_t* top; }; + +struct DiskMapsInLoadedToCache_s +{ + int mapId; + int index; +}; + struct Disk_Management_CB_s { int mapIdIndex; ArrayInfo_t** arrayForAllMApsInformation; DiskFreeIndexesInArray_t* diskFreeIndexesInArray; DiskSortByMapSize_t* disk_SortByMapSize; + DiskMapsInLoadedToCache_t** disk_MapsInLoadedToCache; }; extern Disk_Management_CB_t* disk_mng_CB; void printTree(AVLNode_t* root); @@ -102,9 +113,17 @@ int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree); //disk_mng_delete-Deleting maps until there is enough space to add a new map with the resulting size to disk void disk_mng_delete(int mapSize); -//disk_mng_checkDataStructures-check +//disk_mng_checkDataStructures-check if the data from the master is valid data bool disk_mng_isTheDataCorrect(MapRange_t* range, int size, int* map); +//disk_mng_isTheMapInRange-check if the map in range +bool disk_mng_isTheMapInRange(MapRange_t* rangeFromCache, MapRange_t* range); + +//disk_mng_loadMapFromDiskToCache- get mapId ,offset,size ,freeAddress load the map to the free address return completion +bool disk_mng_loadMapFromDiskToCache(int mapId,int offset, int size, int* freeAddress); + +//disk_mng_searchForSuitableMapInLoadingArray-Search for a suitable map in the loading array +int disk_mng_searchForSuitableMapInLoadingArray(int mapId); //initialize @@ -120,6 +139,13 @@ void disk_mng_firstInitialize(); // disk_mng_normalInitialize-Initializes the disk management system each time the computer opened void disk_mng_normalInitialize(); +//Array- range in loaded to the cache + +//arrayInLoaded_initialize-initialize the array to the cache size +void arrayInLoaded_initialize(); + +//arrayInLoaded_create- create new object to the array +DiskMapsInLoadedToCache_t* arrayInLoaded_create(int mapId,int index); //AVL node info @@ -224,32 +250,44 @@ void array_deleteFromArray(int index); // Frees or deletes information associated with an array. void array_deleteArrayInfo(ArrayInfo_t* arrayInfo); -//disk_deleteMap the function get pointer to map in the disk and delete this map from disk -bool disk_deleteMap(int* diskPointer); - -void cache_deleteMap(int mapId); - - //create a new arrayInfo with all the parameters ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range,AVLNodeInfo_t* avlNodeInfo); +//array_addToArray- add map to the array void array_addToArray(ArrayInfo_t* arrayInfo, int index); //create a new range with 2 point which given MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft); +//check if the range correct +bool isCorrectRange(MapRange_t* range); + +//disk_mng_addMapToDiskManagementDataStructures-add new map to the data structers +void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int* diskPointer); + +//disk_mng_addMap- add map to the disk managment +void disk_mng_addMap(MapRange_t* range, int size, int* map); + +//disk-mock functions + +//disk_addMap-add map to the disk +int* disk_addMap(int* map); + +//disk_isThereEnoughSpace- get size , check if there is enough space for this size +bool disk_isThereEnoughSpace(int mapSize); + //disk_loadDataForInitializeDataStructers the function get destination where to load and from where and how many to load void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad); //disk_loadDataForInitializeDataStructers the function get data where to save and from where and how many to save void disk_saveDataFromStructersToDisk(void* data, void* startAddress, void* howManyToLoad); -void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int* diskPointer); - -int* disk_addMap(int* map); +//disk_deleteMap the function get pointer to map in the disk and delete this map from disk +bool disk_deleteMap(int* diskPointer); -void disk_mng_addMap(MapRange_t* range, int size, int* map); +bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress); -bool disk_isThereEnoughSpace(int mapSize); +//cache - mock functions -bool isCorrectRange(MapRange_t* range); +//cache_deleteMap- delete map from the cache +void cache_deleteMap(int mapId); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index f76f2f3..34d78c4 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -18,10 +18,18 @@ struct GlobalSetup { }; GlobalSetup globalSetup; -int generateRandomNumber(int upper = DISK_SIZE) { - int lower = 0; +int generateRandomNumber(int lower=0,int upper = DISK_SIZE) { return (rand() % (upper - lower + 1)) + lower; } +void printPoint(const char* label, const Point_t& point) { + printf("%s: x = %d, y = %d\n", label, point.x, point.y); +} + +// Function to print map ranges for debugging +void printMapRange(const char* label, const MapRange_t* range) { + printf("%s: TopLeft (x = %d, y = %d), BottomRight (x = %d, y = %d)\n", + label, range->topLeft.x, range->topLeft.y, range->bottomRight.x, range->bottomRight.y); +} void printTreeDetails(AVLNode_t* node) { if (node == NULL) { return; @@ -146,6 +154,10 @@ bool disk_deleteMap(int* diskPointer) { return true; } +bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) +{ + return true; +} void cache_deleteMap(int mapId) { } @@ -421,10 +433,6 @@ TEST_CASE("test_avlTree_insert") { CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 1); - - printf("first tree\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printf("\n"); } SUBCASE("Insert nodes and check balancing") { @@ -439,11 +447,6 @@ TEST_CASE("test_avlTree_insert") { CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 7); - - printf("second tree\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printf("\n"); - } SUBCASE("Insert duplicate mapSize") { @@ -464,10 +467,6 @@ TEST_CASE("test_avlTree_insert") { CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 2); - - printf("third tree\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printf("\n"); } } TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { @@ -488,14 +487,6 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { CHECK(result != nullptr); CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); - printf("Node suitable for deletion:\n"); - printNode(result); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); - printf("%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); - - printf("\n"); - } SUBCASE("All nodes are eligible for deletion") { @@ -513,14 +504,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { CHECK(result != nullptr); CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); - printf("Node suitable for deletion:\n"); - printNode(result); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); - printf("%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); - - printf("\n"); - + } SUBCASE("No node is eligible for deletion") { @@ -538,13 +522,7 @@ TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { CHECK(result != nullptr); CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); - printf("Node with largest mapSize:\n"); - printNode(result); - printTree(disk_mng_CB->disk_SortByMapSize->root); - printTreeDetails(disk_mng_CB->disk_SortByMapSize->root); - printf("%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); - - printf("\n"); + } } @@ -556,20 +534,11 @@ TEST_CASE("test_avlTree_deleteNode") { AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); avlTree_insertElement(info1); } - printf("Tree before deletion:\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); if (nodeToDelete!=NULL) { - printf("the node to delete:\n"); - printNode(nodeToDelete); - disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); - - printf("Tree after deletion:\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - } } @@ -718,7 +687,6 @@ TEST_CASE("test_array_addToArray") ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange,nodeInfo); array_addToArray(arrayInfo, index); CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); - printf("mapId%d\n", disk_mng_CB->mapIdIndex); } } @@ -755,22 +723,8 @@ TEST_CASE("test_disk_mng_addMap") int size = generateRandomNumber(); int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); disk_mng_addMap(mapRange, size, map); - printf("totalElements%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); - printf("mapIdIndex%d\n", disk_mng_CB->mapIdIndex); - - } - for (int i = 0; i < DISK_SIZE; i++) - { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) - { - printf("%d ", disk_mng_CB->arrayForAllMApsInformation[i]->size); - - } } - printf("\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - } @@ -789,20 +743,7 @@ TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { int size = generateRandomNumber(); int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); disk_mng_addMap(mapRange, size, map); // Add maps to the disk - printf("%d\n", disk_mng_CB->disk_SortByMapSize->totalElements); - } - for (int i = 0; i < DISK_SIZE; i++) - { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) - { - printf("%d ", disk_mng_CB->arrayForAllMApsInformation[i]->size); - - } - } - printf("\n"); - printTree(disk_mng_CB->disk_SortByMapSize->root); - // Verify that the disk is full and needs deletion REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); @@ -810,27 +751,109 @@ TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { int sizeToFree = generateRandomNumber(); // Random size to free disk_mng_delete(sizeToFree); - printf("\n"); + // Ensure that space has been freed + REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); - //printTree(disk_mng_CB->disk_SortByMapSize->root); + } - printf("\n"); +} - for (int i = 0; i < DISK_SIZE; i++) - { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) - { - printf("size %d index %d ", disk_mng_CB->arrayForAllMApsInformation[i]->size, i); +TEST_CASE("test_arrayInLoaded_initialize") +{ + arrayInLoaded_initialize(); + CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); + for (int i = 0; i < CACHE_SIZE; i++) { + CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); + } +} - } +TEST_CASE("arrayInLoaded_create") { + int mapId = generateRandomNumber(); + int index = generateRandomNumber(); + DiskMapsInLoadedToCache_t* obj = arrayInLoaded_create(mapId, index); - } + CHECK(obj != NULL); + CHECK(obj->mapId == mapId); + CHECK(obj->index == index); +} +TEST_CASE("test_disk_mng_isTheMapInRange") { - // Ensure that space has been freed - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); + disk_mng_initialize(); + int x1 = generateRandomNumber(100); + int y1 = generateRandomNumber(100); + int x2 = generateRandomNumber(200, x1); + int y2 = generateRandomNumber(200, y1); + Point_t cacheTopLeft = { x1, y1 }; + Point_t cacheBottomRight = { x2, y2 }; + //MapRange_t* rangeFromCache = mapRange_create(cacheBottomRight, cacheTopLeft); + + int x3 = generateRandomNumber(100); + int y3 = generateRandomNumber(100); + int x4 = generateRandomNumber(200, x3); + int y4 = generateRandomNumber(200, y3); + Point_t rangeTopLeft = { x3, y3 }; + Point_t rangeBottomRight = { x4, y4 }; + //MapRange_t* range = mapRange_create(rangeBottomRight, rangeTopLeft); + MapRange_t* range = mapRange_create({ 224,140 }, { 148,160 }); + MapRange_t* rangeFromCache = mapRange_create({250,130}, {170,170}); + + printMapRange("Range From Cache", rangeFromCache); + printMapRange("Range To Check", range); + + bool result = disk_mng_isTheMapInRange(rangeFromCache, range); + + bool expected = ( + (range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->bottomRight.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->topLeft.y) || + (range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->bottomRight.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->topLeft.y) || + (range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->bottomRight.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->topLeft.y) || + (range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->bottomRight.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->topLeft.y)); + printf("Result: %s\n", result ? "true" : "false"); + printf("Expected: %s\n", expected ? "true" : "false"); + CHECK(result == expected); +} + +TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { + disk_mng_initialize(); + + for (int i = 0; i < CACHE_SIZE; i++) { + int mapId = generateRandomNumber(); + int index = generateRandomNumber(); + + DiskMapsInLoadedToCache_t* map = arrayInLoaded_create(mapId, index); + disk_mng_CB->disk_MapsInLoadedToCache[i] = map; } -} + int testMapId = disk_mng_CB->disk_MapsInLoadedToCache[0]->mapId; + int testIndex= disk_mng_CB->disk_MapsInLoadedToCache[0]->index; + + int* diskPointer = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for diskPointer", "test_disk_mng_loadMapFromDiskToCache");; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + + disk_mng_CB->arrayForAllMApsInformation[testIndex] = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); + disk_mng_CB->arrayForAllMApsInformation[testIndex]->mapid = testMapId; + + int offset = generateRandomNumber(); + int length = generateRandomNumber(); + int freeAddress = generateRandomNumber(); + + bool result = disk_mng_loadMapFromDiskToCache(testMapId, offset, length, &freeAddress); + + // Check results + CHECK(result == true); +} \ No newline at end of file From 5a6a9b04505126782b6f42e1ec4f1c579c372442 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 2 Sep 2024 11:11:33 +0300 Subject: [PATCH 22/32] fix the save and intialize functions --- Storage/Disk_Mng_Master.c | 130 ++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 376faf7..957c877 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -1,3 +1,4 @@ + #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" @@ -6,8 +7,8 @@ #include #include - Disk_Management_CB_t* disk_mng_CB; - int length, startAdress, howManyToLoad; +Disk_Management_CB_t* disk_mng_CB; +int startSructers = 20; void disk_mng_initialize_CB() { disk_mng_CB = (Disk_Management_CB_t*)allocate_memory(sizeof(Disk_Management_CB_t), "Failed to allocate memory for disk control block", "disk_mng_initialize_CB"); @@ -16,12 +17,13 @@ void disk_mng_initialize_CB() void disk_mng_initialize() { int startAdress = 0; + int address = 0; int howManyToLoad = sizeof(int); - int address=0;// - disk_loadDataForInitializeDataStructers(&address, &startAdress,&howManyToLoad); - if (address != 1)// + disk_loadDataForInitializeDataStructers(&address, &startAdress, &howManyToLoad); + if (address != 1) { ////restart the first address int disk with 1 to know if its first time or not + address = 1; disk_saveDataFromStructersToDisk(&address, &startAdress, &howManyToLoad); disk_mng_firstInitialize(); } @@ -40,11 +42,16 @@ void disk_mng_saveData() stack_saveData(); array_saveData(); avlTree_saveData(); + int mapIdIndex = 0; + int startAdress = 16; + int howManyToLoad = sizeof(int); + //load the fifth address in disk with mapIdIndex + disk_saveDataFromStructersToDisk(&mapIdIndex, &startAdress, &howManyToLoad); } void disk_mng_firstInitialize() -{ +{ disk_mng_initialize_CB(); stack_firstInitialize(); array_firstInitialize(); @@ -59,11 +66,16 @@ void disk_mng_normalInitialize() stack_normalInitialize(); array_normalInitialize(); avlTree_normalInitialize(); + int mapIdIndex = 0;//stack size + int startAdress = 16; + int howManyToLoad = sizeof(int); + //load the fifth address in disk with mapIdIndex + disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAdress, &howManyToLoad); } void arrayInLoaded_initialize() { - disk_mng_CB->disk_MapsInLoadedToCache = (DiskMapsInLoadedToCache_t**)allocate_memory(CACHE_SIZE *sizeof(DiskMapsInLoadedToCache_t*), "Failed to allocate memory for array in loaded ", "arrayInLoaded_initialize"); + disk_mng_CB->disk_MapsInLoadedToCache = (DiskMapsInLoadedToCache_t**)allocate_memory(CACHE_SIZE * sizeof(DiskMapsInLoadedToCache_t*), "Failed to allocate memory for array in loaded ", "arrayInLoaded_initialize"); if (disk_mng_CB->disk_MapsInLoadedToCache != NULL) { for (int i = 0; i < CACHE_SIZE; i++) { disk_mng_CB->disk_MapsInLoadedToCache[i] = NULL; @@ -81,7 +93,7 @@ DiskMapsInLoadedToCache_t* arrayInLoaded_create(int mapId, int index) //initialize on the first time we turn o the computer the stack will initialize with all the indexes. void stack_firstInitialize() { - disk_mng_CB->diskFreeIndexesInArray=(DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); disk_mng_CB->diskFreeIndexesInArray->top = NULL; disk_mng_CB->diskFreeIndexesInArray->size = 0; for (size_t i = 0; i < DISK_SIZE; i++) @@ -92,29 +104,27 @@ void stack_firstInitialize() { void stack_normalInitialize() { disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); - int length = 0; + int size = 0;//stack size int startAdress = 4; int howManyToLoad = sizeof(int); //load the second address in disk with stack size - disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); - startAdress = 12; - howManyToLoad = length * sizeof(int); + disk_loadDataForInitializeDataStructers(&size, &startAdress, &howManyToLoad); + howManyToLoad = size * sizeof(int); //load all the data from stack - disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress,&howManyToLoad) ; - + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); + } void stack_saveData() { int startAdress = 4; - int howManyToLoad = 4+sizeof(int); + int howManyToLoad = sizeof(int); ////save size of stack in the second address in the disk disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray->size), &startAdress, &howManyToLoad); - startAdress = 12; howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); //save all the data from stack - disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray), &startAdress, &howManyToLoad); + disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); } bool stack_is_empty() { @@ -122,7 +132,7 @@ bool stack_is_empty() { } StackNode_t* stackNode_create(int index) -{ +{ StackNode_t* new_node = (StackNode_t*)allocate_memory(sizeof(StackNode_t), "Failed to allocate memory for max heap", "stackNode_create"); new_node->freeIndex = index; new_node->next = disk_mng_CB->diskFreeIndexesInArray->top; @@ -130,7 +140,7 @@ StackNode_t* stackNode_create(int index) } -void stack_push(int index) +void stack_push(int index) { StackNode_t* new_node = stackNode_create(index); disk_mng_CB->diskFreeIndexesInArray->size++; @@ -159,7 +169,7 @@ int stack_top() { //array fuctions void array_firstInitialize() { - disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(DISK_SIZE*sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); + disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); if (disk_mng_CB->arrayForAllMApsInformation != NULL) { for (int i = 0; i < DISK_SIZE; i++) { disk_mng_CB->arrayForAllMApsInformation[i] = NULL; @@ -168,29 +178,29 @@ void array_firstInitialize() { } void array_normalInitialize() { disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); - int startAdress = 12 + disk_mng_CB->diskFreeIndexesInArray->size* sizeof(int); + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t**); //load all the data from array - disk_loadDataForInitializeDataStructers(&(disk_mng_CB->arrayForAllMApsInformation), &startAdress, &howManyToLoad); + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); } void array_saveData() { - int startAdress = 12+disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int)+DISK_SIZE * sizeof(ArrayInfo_t**); - int howManyToLoad =DISK_SIZE* (sizeof(ArrayInfo_t**)); + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); + int howManyToLoad = DISK_SIZE * (sizeof(ArrayInfo_t**)); //save all the data from array - disk_saveDataFromStructersToDisk(&(disk_mng_CB->arrayForAllMApsInformation), &startAdress, &howManyToLoad); + disk_saveDataFromStructersToDisk(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); } -ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range,AVLNodeInfo_t* avlNodeInfo) +ArrayInfo_t* arrayInfo_create(int* diskPointer, int size, MapRange_t* range, AVLNodeInfo_t* avlNodeInfo) { ArrayInfo_t* arrayInfo = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for avlTree", "arrayInfo_create"); disk_mng_CB->mapIdIndex++; arrayInfo->mapid = disk_mng_CB->mapIdIndex; - arrayInfo ->diskPointer = diskPointer; + arrayInfo->diskPointer = diskPointer; arrayInfo->size = size; - arrayInfo->range =range; + arrayInfo->range = range; arrayInfo->avlNodeInfo = avlNodeInfo; return arrayInfo; } @@ -213,7 +223,7 @@ void array_deleteArrayInfo(ArrayInfo_t* arrayInfo) //maprange functions -MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft) +MapRange_t* mapRange_create(Point_t bottomRight, Point_t topLeft) { MapRange_t* mapRange = (MapRange_t*)allocate_memory(sizeof(MapRange_t), "Failed to allocate memory for max heap", "mapRange_create"); mapRange->bottomRight = bottomRight; @@ -224,7 +234,7 @@ int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) { AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root);//find the suitable map to delete ArrayInfo_t* arrayInfo = disk_mng_CB->arrayForAllMApsInformation[nodeToDelete->avlNodeInfo->arrayIndex];//finding the object that corresponds to deletion in the array - if (disk_mng_searchForSuitableMapInLoadingArray(arrayInfo->mapid)==-1)//check if the map not in loaded to the cache + if (disk_mng_searchForSuitableMapInLoadingArray(arrayInfo->mapid) == -1)//check if the map not in loaded to the cache { bool isDeleteSuccess = disk_deleteMap(arrayInfo->diskPointer);//send API to the disk to delete the map if (isDeleteSuccess) @@ -249,7 +259,7 @@ int disk_mng_deleteMapFromDiskManagementDataStructures(int sizeToFree) void disk_mng_delete(int mapSize) { - while (mapSize>0) + while (mapSize > 0) { mapSize = disk_mng_deleteMapFromDiskManagementDataStructures(mapSize); } @@ -261,7 +271,7 @@ AVLNodeInfo_t* avlNodeInfo_create(int mapSize, int arrayIndex) AVLNodeInfo_t* newAVLNodeInfo = (AVLNodeInfo_t*)allocate_memory(sizeof(AVLNodeInfo_t), "Failed to allocate memory for AVL node info", "avlNodeInfo_create"); newAVLNodeInfo->mapSize = mapSize; newAVLNodeInfo->arrayIndex = arrayIndex; - newAVLNodeInfo->lru = disk_mng_CB->disk_SortByMapSize->lruCounter+1; + newAVLNodeInfo->lru = disk_mng_CB->disk_SortByMapSize->lruCounter + 1; return newAVLNodeInfo; } @@ -272,7 +282,7 @@ void avlNodeInfo_delete(AVLNodeInfo_t* nodeInfo) } } -//AVL node +//AVL node AVLNode_t* avlNode_create(AVLNodeInfo_t* avlNodeInfo) { AVLNode_t* node = (AVLNode_t*)allocate_memory(sizeof(AVLNode_t), "Failed to allocate memory for AVL node", "avlTree_insert"); node->avlNodeInfo = avlNodeInfo; @@ -369,7 +379,7 @@ void avlTree_firstInitialize() { disk_mng_CB->disk_SortByMapSize->lruCounter = 0; } -void avlTree_normalInitialize() +void avlTree_normalInitialize() { disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t**)allocate_memory(sizeof(DiskSortByMapSize_t*), "Failed to allocate memory for stack ", "avlTree_normalInitialize"); int length = 0; @@ -377,24 +387,36 @@ void avlTree_normalInitialize() int howManyToLoad = sizeof(int); //load the third address in disk with avlTree size disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); - startAdress = 12+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); + + int lru = 0; + startAdress = 12; + howManyToLoad = sizeof(int); + //load the forth address in disk with avlTree lru + disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); + + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); howManyToLoad = length * sizeof(DiskSortByMapSize_t**); //load all the data from avlTree - disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startAdress, &howManyToLoad); + disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); } -void avlTree_saveData() +void avlTree_saveData() { int startAdress = 8; - int howManyToLoad = sizeof(int); - ////save size of avkTree in the third address in the disk - disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->totalElements), &startAdress, &howManyToLoad); + int howManyToLoad = sizeof(int); + ////save size of avlTree in the third address in the disk + disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->totalElements), &startAdress, &howManyToLoad); + startAdress = 12; + howManyToLoad = sizeof(int); + ////save lruCounter of avlTree in the forth address in the disk + disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->lruCounter), &startAdress, &howManyToLoad); - startAdress = 12+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**) + DISK_SIZE * (sizeof(ArrayInfo_t**)); - howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); - //save all the data from stack - disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startAdress, &howManyToLoad); + + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); + howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); + //save all the data from stack + disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); } @@ -548,7 +570,7 @@ void* allocate_memory(size_t size, const char* description, const char* function } void disk_mng_addMap(MapRange_t* range, int size, int* map) { - if (disk_mng_isTheDataCorrect(range,size,map)) + if (disk_mng_isTheDataCorrect(range, size, map)) { int* diskPointer = disk_addMap(map); if (diskPointer != NULL)//success @@ -572,9 +594,9 @@ void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, int index = stack_pop(); AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(size, index); avlTree_insertElement(avlNodeInfo); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, range,avlNodeInfo); + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, range, avlNodeInfo); array_addToArray(arrayInfo, index); - + } bool disk_mng_isTheDataCorrect(MapRange_t* range, int size, int* map) @@ -584,7 +606,7 @@ bool disk_mng_isTheDataCorrect(MapRange_t* range, int size, int* map) test_writeExceptionToFile(Error_Worng_Map_Variable, "disk_mng_checkDataStructures_map"); return true; } - if (size <=0) + if (size <= 0) { test_writeExceptionToFile(Error_Worng_Size_Variable, "disk_mng_checkDataStructures_mapSize"); return false; @@ -650,9 +672,9 @@ bool disk_mng_isTheMapInRange(MapRange_t* rangeFromCache, MapRange_t* range) if ((range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y) || (range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || - (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y) ) + (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y)) { - return true; + return true; } return false; } @@ -662,13 +684,13 @@ bool disk_mng_loadMapFromDiskToCache(int mapId, int offset, int size, int* freeA { int* diskPointer; int startAddress; - bool isLoadedSuccess=false; + bool isLoadedSuccess = false; int index = disk_mng_searchForSuitableMapInLoadingArray(mapId); - if (index!=-1)//Checking whether the map was found in the loading array + if (index != -1)//Checking whether the map was found in the loading array { diskPointer = disk_mng_CB->arrayForAllMApsInformation[index]->diskPointer;//Finding the appropriate disk pointer disk_mng_CB->arrayForAllMApsInformation[index] = NULL; - startAddress = diskPointer+(offset*sizeof(int)); + startAddress = diskPointer + (offset * sizeof(int)); isLoadedSuccess = disk_loadMapToCache(startAddress, size, freeAddress); if (!isLoadedSuccess) { @@ -685,7 +707,7 @@ int disk_mng_searchForSuitableMapInLoadingArray(int mapId) for (int i = 0; i < CACHE_SIZE; i++) { map = disk_mng_CB->disk_MapsInLoadedToCache[i]; - if (map!=NULL&&mapId == map->mapId) + if (map != NULL && mapId == map->mapId) { return map->index; } From fe5165021d912264bf63230e2c1845d90ca31e3e Mon Sep 17 00:00:00 2001 From: shifi325 Date: Wed, 4 Sep 2024 13:52:31 +0300 Subject: [PATCH 23/32] fix range function --- Storage/CMakeLists.txt | 11 +++++++++++ Storage/Disk_Mng_Master.c | 24 ++++++++++++++++-------- Storage/Doctest.cpp | 23 +++++++++++++++-------- Storage/cmake | 0 Storage/errors.log.txt | 6 ++++++ 5 files changed, 48 insertions(+), 16 deletions(-) create mode 100644 Storage/CMakeLists.txt create mode 100644 Storage/cmake diff --git a/Storage/CMakeLists.txt b/Storage/CMakeLists.txt new file mode 100644 index 0000000..6e1403e --- /dev/null +++ b/Storage/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION "3.30.2") + +project("Disk_MNG_Master") + +add_executable("${PROJECT_NAME}" "Doctest.cpp" "Disk_Mng_Master.c" "Disk_Mng_Master.h" "Disk_Mng_Master_API.h" "doctest.h") + +add_custom_target(cpu-gpu DEPENDS ${TARGET_NAME}) + +install(TARGETS "${PROJECT_NAME}" DESTINATION bin) #$ (CMAKE_INSTALL_PREFIX)/bin + +install(FILES "Doctest.cpp" DESTINATION src) #$ (CMAKE_INSTALL_PREFIX)/src \ No newline at end of file diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 957c877..af8baa9 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -667,19 +667,27 @@ bool isCorrectRange(MapRange_t* range) return true; } -bool disk_mng_isTheMapInRange(MapRange_t* rangeFromCache, MapRange_t* range) -{ - if ((range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || - (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y) || - (range->bottomRight.x >= rangeFromCache->topLeft.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->topLeft.y >= range->bottomRight.y) || - (range->bottomRight.x >= rangeFromCache->bottomRight.x >= range->topLeft.x) && (range->topLeft.y >= rangeFromCache->bottomRight.y >= range->bottomRight.y)) - { +bool disk_mng_isTheMapInRange(MapRange_t* rangeFromCache, MapRange_t* range) { + if ( + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || + (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) + ) { return true; } return false; } - bool disk_mng_loadMapFromDiskToCache(int mapId, int offset, int size, int* freeAddress) { int* diskPointer; diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 34d78c4..9d6b15b 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -805,14 +805,21 @@ TEST_CASE("test_disk_mng_isTheMapInRange") { bool result = disk_mng_isTheMapInRange(rangeFromCache, range); bool expected = ( - (range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->bottomRight.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->topLeft.y) || - (range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->bottomRight.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->topLeft.y) || - (range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->bottomRight.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->topLeft.y) || - (range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->bottomRight.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->topLeft.y)); + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || + (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) + ); printf("Result: %s\n", result ? "true" : "false"); printf("Expected: %s\n", expected ? "true" : "false"); CHECK(result == expected); diff --git a/Storage/cmake b/Storage/cmake new file mode 100644 index 0000000..e69de29 diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 30f2a5d..3b45bcd 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -276,3 +276,9 @@ disk_mng_checkDataStructures_mapSize: Error: Unknown exception. disk_mng_checkDataStructures_mapSize: Error: Unknown exception. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. From b58c80dea5b237df1c67d5870eb6c2ca9baad0c1 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Sun, 8 Sep 2024 15:36:36 +0300 Subject: [PATCH 24/32] add mock function and test for save+initilaize --- Storage/.c | 3 - Storage/CMakeLists.txt | 21 +- Storage/Disk_Mng_Master.c | 22 +- Storage/Disk_Mng_Master.h | 11 +- Storage/Disk_Mng_Master_Sycl.cpp | 38 + Storage/Doctest.cpp | 136 +- Storage/Storage.vcxproj | 1 + Storage/cmake | 0 Storage/errors.log.txt | 226 ++++ .../v1/query/client-MicrosoftVS/query.json | 1 + .../reply/cache-v2-c6b0909de86cc2bf9261.json | 1111 +++++++++++++++++ .../cmakeFiles-v1-eb6628758082e940393c.json | 155 +++ .../codemodel-v2-72887b5d7c5362aed235.json | 60 + ...irectory-.-Debug-d0094a50bb2071803777.json | 14 + .../reply/index-2024-09-05T08-34-28-0480.json | 132 ++ ...Mng_Master-Debug-3d41b6a5a5149b767ab9.json | 181 +++ .../toolchains-v1-80a25452cfdaac2fe07b.json | 78 ++ Storage/out/build/x64-Debug/CMakeCache.txt | 344 +++++ .../3.27.2-msvc1/CMakeCCompiler.cmake | 74 ++ .../3.27.2-msvc1/CMakeCXXCompiler.cmake | 85 ++ .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 52736 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 52736 bytes .../3.27.2-msvc1/CMakeRCCompiler.cmake | 6 + .../CMakeFiles/3.27.2-msvc1/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 866 +++++++++++++ .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 855 +++++++++++++ .../CMakeFiles/CMakeConfigureLog.yaml | 151 +++ .../x64-Debug/CMakeFiles/ShowIncludes/foo.h | 1 + .../x64-Debug/CMakeFiles/ShowIncludes/main.c | 2 + .../CMakeFiles/TargetDirectories.txt | 3 + .../x64-Debug/CMakeFiles/cmake.check_cache | 1 + .../build/x64-Debug/CMakeFiles/rules.ninja | 78 ++ .../x64-Debug/Testing/Temporary/LastTest.log | 3 + .../build/x64-Debug/VSInheritEnvironments.txt | 1 + Storage/out/build/x64-Debug/build.ninja | 171 +++ .../out/build/x64-Debug/cmake_install.cmake | 44 + 36 files changed, 4864 insertions(+), 26 deletions(-) delete mode 100644 Storage/.c create mode 100644 Storage/Disk_Mng_Master_Sycl.cpp delete mode 100644 Storage/cmake create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/cache-v2-c6b0909de86cc2bf9261.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/cmakeFiles-v1-eb6628758082e940393c.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/codemodel-v2-72887b5d7c5362aed235.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/directory-.-Debug-d0094a50bb2071803777.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/index-2024-09-05T08-34-28-0480.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/target-Disk_Mng_Master-Debug-3d41b6a5a5149b767ab9.json create mode 100644 Storage/out/build/x64-Debug/.cmake/api/v1/reply/toolchains-v1-80a25452cfdaac2fe07b.json create mode 100644 Storage/out/build/x64-Debug/CMakeCache.txt create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCCompiler.cmake create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCXXCompiler.cmake create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeDetermineCompilerABI_C.bin create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeDetermineCompilerABI_CXX.bin create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeRCCompiler.cmake create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeSystem.cmake create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdC/CMakeCCompilerId.c create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/CMakeConfigureLog.yaml create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/foo.h create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/main.c create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/TargetDirectories.txt create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/cmake.check_cache create mode 100644 Storage/out/build/x64-Debug/CMakeFiles/rules.ninja create mode 100644 Storage/out/build/x64-Debug/Testing/Temporary/LastTest.log create mode 100644 Storage/out/build/x64-Debug/VSInheritEnvironments.txt create mode 100644 Storage/out/build/x64-Debug/build.ninja create mode 100644 Storage/out/build/x64-Debug/cmake_install.cmake diff --git a/Storage/.c b/Storage/.c deleted file mode 100644 index ffc6dab..0000000 --- a/Storage/.c +++ /dev/null @@ -1,3 +0,0 @@ -int main() { - return 0; -} \ No newline at end of file diff --git a/Storage/CMakeLists.txt b/Storage/CMakeLists.txt index 6e1403e..723a0db 100644 --- a/Storage/CMakeLists.txt +++ b/Storage/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION "3.30.2") +cmake_minimum_required(VERSION "3.0") -project("Disk_MNG_Master") +project(Disk_Mng_Master) -add_executable("${PROJECT_NAME}" "Doctest.cpp" "Disk_Mng_Master.c" "Disk_Mng_Master.h" "Disk_Mng_Master_API.h" "doctest.h") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) -add_custom_target(cpu-gpu DEPENDS ${TARGET_NAME}) +file(GLOB C "./Disk_Mng_Master.c") +file(GLOB SYCL "./Disk_Mng_Master_Sycl.cpp") +file(GLOB DOCTEST "./Doctest.cpp") +set(SOURCE_FILES "doctest.h") +list(APPEND SOURCE_FILES ${C} ${SYCL} ${DOCTEST}) -install(TARGETS "${PROJECT_NAME}" DESTINATION bin) #$ (CMAKE_INSTALL_PREFIX)/bin -install(FILES "Doctest.cpp" DESTINATION src) #$ (CMAKE_INSTALL_PREFIX)/src \ No newline at end of file + +add_executable(Disk_Mng_Master ${SOURCE_FILES}) + +target_include_directories(Disk_Mng_Master PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(Disk_Mng_Master PRIVATE DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) + diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index af8baa9..b2afa54 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -16,9 +16,12 @@ void disk_mng_initialize_CB() void disk_mng_initialize() { + disk_mng_initialize_CB(); + int startAdress = 0; int address = 0; int howManyToLoad = sizeof(int); + disk_mng_CB->mockDisk = allocate_memory(1000000* sizeof(void*), "Failed to allocate memory for mock disk ", "disk_mng_initialize"); disk_loadDataForInitializeDataStructers(&address, &startAdress, &howManyToLoad); if (address != 1) { @@ -42,17 +45,16 @@ void disk_mng_saveData() stack_saveData(); array_saveData(); avlTree_saveData(); - int mapIdIndex = 0; int startAdress = 16; int howManyToLoad = sizeof(int); //load the fifth address in disk with mapIdIndex - disk_saveDataFromStructersToDisk(&mapIdIndex, &startAdress, &howManyToLoad); + disk_saveDataFromStructersToDisk(&disk_mng_CB->mapIdIndex, &startAdress, &howManyToLoad); } void disk_mng_firstInitialize() { - disk_mng_initialize_CB(); + //disk_mng_initialize_CB(); stack_firstInitialize(); array_firstInitialize(); avlTree_firstInitialize(); @@ -62,7 +64,7 @@ void disk_mng_firstInitialize() void disk_mng_normalInitialize() { - disk_mng_initialize_CB(); + //disk_mng_initialize_CB(); stack_normalInitialize(); array_normalInitialize(); avlTree_normalInitialize(); @@ -122,7 +124,7 @@ void stack_saveData() ////save size of stack in the second address in the disk disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray->size), &startAdress, &howManyToLoad); - howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); + howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t); //save all the data from stack disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); } @@ -179,7 +181,7 @@ void array_firstInitialize() { void array_normalInitialize() { disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); - int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t**); + int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t*); //load all the data from array disk_loadDataForInitializeDataStructers(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); } @@ -187,7 +189,7 @@ void array_normalInitialize() { void array_saveData() { startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); - int howManyToLoad = DISK_SIZE * (sizeof(ArrayInfo_t**)); + int howManyToLoad = DISK_SIZE * (sizeof(ArrayInfo_t*)); //save all the data from array disk_saveDataFromStructersToDisk(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); } @@ -394,8 +396,8 @@ void avlTree_normalInitialize() //load the forth address in disk with avlTree lru disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); - howManyToLoad = length * sizeof(DiskSortByMapSize_t**); + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t*); + howManyToLoad = length * sizeof(DiskSortByMapSize_t*); //load all the data from avlTree disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); } @@ -413,7 +415,7 @@ void avlTree_saveData() disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->lruCounter), &startAdress, &howManyToLoad); - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t**); + startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t*); howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); //save all the data from stack disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 6a37cff..0ed54d2 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -7,8 +7,8 @@ #define POINT_BR_RANGE (Point_t){100, 100} #define POINT_TL_RANGE (Point_t){0, 0} -#define DISK_SIZE 1000 -#define CACHE_SIZE 1000 +#define DISK_SIZE 100 +#define CACHE_SIZE 100 // Forward declarations typedef struct AVLNode_s AVLNode_t; @@ -87,6 +87,7 @@ struct DiskMapsInLoadedToCache_s }; struct Disk_Management_CB_s { + void* mockDisk; int mapIdIndex; ArrayInfo_t** arrayForAllMApsInformation; DiskFreeIndexesInArray_t* diskFreeIndexesInArray; @@ -268,6 +269,10 @@ void disk_mng_addMapToDiskManagementDataStructures(MapRange_t* range, int size, //disk_mng_addMap- add map to the disk managment void disk_mng_addMap(MapRange_t* range, int size, int* map); +// disk_mng_saveData-save all the data from the data structers to disk before clothing the computer +void disk_mng_saveData(); + + //disk-mock functions //disk_addMap-add map to the disk @@ -291,3 +296,5 @@ bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress); //cache_deleteMap- delete map from the cache void cache_deleteMap(int mapId); + +//int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) diff --git a/Storage/Disk_Mng_Master_Sycl.cpp b/Storage/Disk_Mng_Master_Sycl.cpp new file mode 100644 index 0000000..3dab19e --- /dev/null +++ b/Storage/Disk_Mng_Master_Sycl.cpp @@ -0,0 +1,38 @@ +//#include +//#include +//#include +//#include "Disk_Mng_Master_API.h" +//#include "Disk_Mng_Master.h" +//using namespace cl::sycl; +//extern "C" { +//#include "Disk_Mng_Master_API.h" +//#include "Disk_Mng_Master.h" +//} +//int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) { +// int count = 0; +// +// +// queue q; +// buffer bufferCount(&count, 1); +// buffer bufferInputArray(disk_mng_CB->arrayForAllMApsInformation, range<1>(arraySize)); +// buffer bufferOutputArray(*arrayOfMapsIdsInRange, range<1>(arraySize)); +// +// q.submit([&](handler& h) { +// auto inputArrayAccess = bufferInputArray.get_access(h); +// auto outputArrayAccess = bufferOutputArray.get_access(h); +// auto countAccess = bufferCount.get_access(h); +// +// h.parallel_for(range<1>(arraySize), [=](id<1> i) { +// if (inputArrayAccess[i].range != NULL && +// disk_mng_isTheMapInRange(rangeFromCache, inputArrayAccess[i].range)) { +// int idx = atomic_fetch_add(countAccess[0], 1); +// outputArrayAccess[idx] = inputArrayAccess[i]; +// disk_mng_CB->disk_MapsInLoadedToCache[idx] = arrayInLoaded_create(inputArrayAccess[i]->mapid, i); +// } +// }); +// }).wait(); +// +// count = bufferCount.get_access()[0]; +// +// return count; +//} \ No newline at end of file diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 9d6b15b..1489ecb 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -7,6 +7,8 @@ #include #include #include +#include + extern "C" { #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" @@ -161,13 +163,21 @@ bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) void cache_deleteMap(int mapId) { } -//the function fill in the structer all the data which save befoe the computer closed,the function get destenation,suorce,length; -void disk_loadDataForInitializeDataStructers(void* destination,void* startAddress,void* howManyToLoad) + +void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad) { + int start = *(int*)startAddress; + int sizeToLoad = *(int*)howManyToLoad; + + memcpy(destination, (char*)disk_mng_CB->mockDisk + start, sizeToLoad); } -void disk_saveDataFromStructersToDisk(void* data, void* startAddress, void* endAddrehowManyToLoadss) +void disk_saveDataFromStructersToDisk(void* source, void* startAddress, void* howManyToLoad) { + int start = *(int*)startAddress; + int sizeToSave = *(int*)howManyToLoad; + + memcpy((char*)disk_mng_CB->mockDisk + start, source, sizeToSave); } bool disk_isThereEnoughSpace(int mapSize) { @@ -745,7 +755,7 @@ TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { disk_mng_addMap(mapRange, size, map); // Add maps to the disk } // Verify that the disk is full and needs deletion - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); + //REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); // Perform deletion int sizeToFree = generateRandomNumber(); // Random size to free @@ -863,4 +873,120 @@ TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { // Check results CHECK(result == true); -} \ No newline at end of file +} +//TEST_CASE("test_disk_mng_getMapsIdsInRange") { +// disk_mng_initialize(); +// +// for (int i = 0; i < 20; i++) +// { +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// int size = generateRandomNumber(); +// int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); +// disk_mng_addMap(mapRange, size, map); +// +// } +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// +// ArrayInfo_t** arrayOfMapsInRange = (ArrayInfo_t**)allocate_memory(CACHE_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for arrayOfMapsInRange ", "test_disk_mng_getMapsIdsInRange"); +// +// int count = disk_mng_getMapsIdsInRange(mapRange, arrayOfMapsInRange, CACHE_SIZE); +//} + +TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { + + SUBCASE("check the first initialize") { + disk_mng_initialize(); + int expectedAddressValue = 1; + int loadedValue = 0; + + int startAddress = 0; + int howManyToLoad = sizeof(int); + + disk_loadDataForInitializeDataStructers(&loadedValue, &startAddress, &howManyToLoad); + + CHECK(loadedValue == expectedAddressValue); + } + SUBCASE("check the normal initilaize") + { + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int size = generateRandomNumber(); + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); + disk_mng_addMap(mapRange, size, map); + + disk_mng_saveData(); + + int stackSize; + int startAddressForStackSize=4; + int lengthStackSize = sizeof(int); + disk_loadDataForInitializeDataStructers(&stackSize, &startAddressForStackSize, &lengthStackSize); + CHECK(stackSize == disk_mng_CB->diskFreeIndexesInArray->size); + + int avlSize; + int startAddressForAVL = 8; + int lengthAVLSize = sizeof(int); + disk_loadDataForInitializeDataStructers(&avlSize, &startAddressForAVL, &lengthAVLSize); + CHECK(avlSize == disk_mng_CB->disk_SortByMapSize->totalElements); + + int avllruCounter; + int startAddressForAVLLruCounter = 12; + int lengthAVLLruCounter = sizeof(int); + disk_loadDataForInitializeDataStructers(&avllruCounter, &startAddressForAVLLruCounter, &lengthAVLLruCounter); + CHECK(avllruCounter == disk_mng_CB->disk_SortByMapSize->lruCounter); + + int mapIdIndex; + int startAddressFormapIdIndex = 16; + int lengthmapIdIndex = sizeof(int); + disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); + CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); + + + //DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + //int startAddressForStack = 20; + //int lengthStack = sizeof(StackNode_t) * stackSize; + //printf(" %d\n\n", lengthStack); + + //disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); + //printf(" %d\n\n", lengthStack); + + //CHECK(disk_mng_CB->diskFreeIndexesInArray->top == stackForTest->top); + //printf(" %d\n\n",lengthStack); + //ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*)*DISK_SIZE, "Failed to allocate memory for array ", "test array load"); + //int startAddressForArray = 20 + lengthStack; + //int lengthForArray = DISK_SIZE * sizeof(ArrayInfo_t*); + //disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); + //for (int i = 0; i < DISK_SIZE; i++) + //{ + // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); + // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); + + //} + + + } + + + + + +} diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index e43783f..47a925b 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -128,6 +128,7 @@ + diff --git a/Storage/cmake b/Storage/cmake deleted file mode 100644 index e69de29..0000000 diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 3b45bcd..71e1288 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -282,3 +282,229 @@ disk_mng_checkDataStructures_mapSize: Error: Error worng size variable. disk_mng_checkDataStructures_mapSize: Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json b/Storage/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json new file mode 100644 index 0000000..7d776af --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json @@ -0,0 +1 @@ +{"requests":[{"kind":"cache","version":2},{"kind":"cmakeFiles","version":1},{"kind":"codemodel","version":2},{"kind":"toolchains","version":1}]} \ No newline at end of file diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cache-v2-c6b0909de86cc2bf9261.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cache-v2-c6b0909de86cc2bf9261.json new file mode 100644 index 0000000..8eb1593 --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cache-v2-c6b0909de86cc2bf9261.json @@ -0,0 +1,1111 @@ +{ + "entries" : + [ + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/lib.exe" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "c:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "27" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "2" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cmake.exe" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cpack.exe" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/ctest.exe" + }, + { + "name" : "CMAKE_CXX_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during all build types." + } + ], + "type" : "STRING", + "value" : "/DWIN32 /D_WINDOWS /W3 /GR /EHsc" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "/MDd /Zi /Ob0 /Od /RTC1" + }, + { + "name" : "CMAKE_CXX_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "/MD /O1 /Ob1 /DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "/MD /O2 /Ob2 /DNDEBUG" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the CXX compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "/MD /Zi /O2 /Ob1 /DNDEBUG" + }, + { + "name" : "CMAKE_CXX_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C++ applications." + } + ], + "type" : "STRING", + "value" : "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib" + }, + { + "name" : "CMAKE_C_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during all build types." + } + ], + "type" : "STRING", + "value" : "/DWIN32 /D_WINDOWS /W3" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "/MDd /Zi /Ob0 /Od /RTC1" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "/MD /O1 /Ob1 /DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "/MD /O2 /Ob2 /DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "/MD /Zi /O2 /Ob1 /DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "Unknown" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during all build types." + } + ], + "type" : "STRING", + "value" : "/machine:x64" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Enable/Disable output of compile commands during generation." + } + ], + "type" : "BOOL", + "value" : "" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_FIND_PACKAGE_REDIRECTS_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake." + } + ], + "type" : "STATIC", + "value" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/pkgRedirects" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "PATH", + "value" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/install/x64-Debug" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/link.exe" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "make program" + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during all build types." + } + ], + "type" : "STRING", + "value" : "/machine:x64" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_MT", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/mt.exe" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "Disk_Mng_Master" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "noop for ranlib" + } + ], + "type" : "INTERNAL", + "value" : ":" + }, + { + "name" : "CMAKE_RC_COMPILER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "RC compiler" + } + ], + "type" : "FILEPATH", + "value" : "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/rc.exe" + }, + { + "name" : "CMAKE_RC_COMPILER_WORKS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_RC_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags for Windows Resource Compiler during all build types." + } + ], + "type" : "STRING", + "value" : "-DWIN32" + }, + { + "name" : "CMAKE_RC_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags for Windows Resource Compiler during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "-D_DEBUG" + }, + { + "name" : "CMAKE_RC_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags for Windows Resource Compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_RC_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags for Windows Resource Compiler during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_RC_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags for Windows Resource Compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during all build types." + } + ], + "type" : "STRING", + "value" : "/machine:x64" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "/INCREMENTAL:NO" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "/debug /INCREMENTAL" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "/machine:x64" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "Disk_Mng_Master_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug" + }, + { + "name" : "Disk_Mng_Master_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "Disk_Mng_Master_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cmakeFiles-v1-eb6628758082e940393c.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cmakeFiles-v1-eb6628758082e940393c.json new file mode 100644 index 0000000..696042c --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/cmakeFiles-v1-eb6628758082e940393c.json @@ -0,0 +1,155 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isGenerated" : true, + "path" : "out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows-Initialize.cmake" + }, + { + "isGenerated" : true, + "path" : "out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCCompiler.cmake" + }, + { + "isGenerated" : true, + "path" : "out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCXXCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/WindowsPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/MSVC-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/MSVC.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows-MSVC-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows-MSVC.cmake" + }, + { + "isGenerated" : true, + "path" : "out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeRCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeRCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeCXXInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/MSVC-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/MSVC.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows-MSVC-CXX.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/Platform/Windows-MSVC.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeCommonLanguageInclude.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug", + "source" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/codemodel-v2-72887b5d7c5362aed235.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/codemodel-v2-72887b5d7c5362aed235.json new file mode 100644 index 0000000..cb3b344 --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/codemodel-v2-72887b5d7c5362aed235.json @@ -0,0 +1,60 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-d0094a50bb2071803777.json", + "minimumCMakeVersion" : + { + "string" : "3.0" + }, + "projectIndex" : 0, + "source" : ".", + "targetIndexes" : + [ + 0 + ] + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "Disk_Mng_Master", + "targetIndexes" : + [ + 0 + ] + } + ], + "targets" : + [ + { + "directoryIndex" : 0, + "id" : "Disk_Mng_Master::@6890427a1f51a3e7e1df", + "jsonFile" : "target-Disk_Mng_Master-Debug-3d41b6a5a5149b767ab9.json", + "name" : "Disk_Mng_Master", + "projectIndex" : 0 + } + ] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug", + "source" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + }, + "version" : + { + "major" : 2, + "minor" : 6 + } +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/directory-.-Debug-d0094a50bb2071803777.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/directory-.-Debug-d0094a50bb2071803777.json new file mode 100644 index 0000000..3a67af9 --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/directory-.-Debug-d0094a50bb2071803777.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/index-2024-09-05T08-34-28-0480.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/index-2024-09-05T08-34-28-0480.json new file mode 100644 index 0000000..2082d60 --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/index-2024-09-05T08-34-28-0480.json @@ -0,0 +1,132 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cmake.exe", + "cpack" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cpack.exe", + "ctest" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/ctest.exe", + "root" : "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 27, + "patch" : 2, + "string" : "3.27.2-msvc1", + "suffix" : "msvc1" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-72887b5d7c5362aed235.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 6 + } + }, + { + "jsonFile" : "cache-v2-c6b0909de86cc2bf9261.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-eb6628758082e940393c.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + { + "jsonFile" : "toolchains-v1-80a25452cfdaac2fe07b.json", + "kind" : "toolchains", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-MicrosoftVS" : + { + "query.json" : + { + "requests" : + [ + { + "kind" : "cache", + "version" : 2 + }, + { + "kind" : "cmakeFiles", + "version" : 1 + }, + { + "kind" : "codemodel", + "version" : 2 + }, + { + "kind" : "toolchains", + "version" : 1 + } + ], + "responses" : + [ + { + "jsonFile" : "cache-v2-c6b0909de86cc2bf9261.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-eb6628758082e940393c.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + { + "jsonFile" : "codemodel-v2-72887b5d7c5362aed235.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 6 + } + }, + { + "jsonFile" : "toolchains-v1-80a25452cfdaac2fe07b.json", + "kind" : "toolchains", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ] + } + } + } +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/target-Disk_Mng_Master-Debug-3d41b6a5a5149b767ab9.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/target-Disk_Mng_Master-Debug-3d41b6a5a5149b767ab9.json new file mode 100644 index 0000000..5fcf296 --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/target-Disk_Mng_Master-Debug-3d41b6a5a5149b767ab9.json @@ -0,0 +1,181 @@ +{ + "artifacts" : + [ + { + "path" : "Disk_Mng_Master.exe" + }, + { + "path" : "Disk_Mng_Master.pdb" + } + ], + "backtrace" : 1, + "backtraceGraph" : + { + "commands" : + [ + "add_executable", + "target_include_directories" + ], + "files" : + [ + "CMakeLists.txt" + ], + "nodes" : + [ + { + "file" : 0 + }, + { + "command" : 0, + "file" : 0, + "line" : 16, + "parent" : 0 + }, + { + "command" : 1, + "file" : 0, + "line" : 18, + "parent" : 0 + }, + { + "command" : 1, + "file" : 0, + "line" : 19, + "parent" : 0 + } + ] + }, + "compileGroups" : + [ + { + "compileCommandFragments" : + [ + { + "fragment" : "/DWIN32 /D_WINDOWS /W3 /MDd /Zi /Ob0 /Od /RTC1" + } + ], + "includes" : + [ + { + "backtrace" : 2, + "path" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + }, + { + "backtrace" : 3, + "path" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN" + } + ], + "language" : "C", + "sourceIndexes" : + [ + 1 + ] + }, + { + "compileCommandFragments" : + [ + { + "fragment" : "/DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 -std:c++17" + } + ], + "includes" : + [ + { + "backtrace" : 2, + "path" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage" + }, + { + "backtrace" : 3, + "path" : "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN" + } + ], + "language" : "CXX", + "languageStandard" : + { + "backtraces" : + [ + 1 + ], + "standard" : "17" + }, + "sourceIndexes" : + [ + 2, + 3 + ] + } + ], + "id" : "Disk_Mng_Master::@6890427a1f51a3e7e1df", + "link" : + { + "commandFragments" : + [ + { + "fragment" : "/DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1", + "role" : "flags" + }, + { + "fragment" : "/machine:x64 /debug /INCREMENTAL /subsystem:console", + "role" : "flags" + }, + { + "fragment" : "kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib", + "role" : "libraries" + } + ], + "language" : "CXX" + }, + "name" : "Disk_Mng_Master", + "nameOnDisk" : "Disk_Mng_Master.exe", + "paths" : + { + "build" : ".", + "source" : "." + }, + "sourceGroups" : + [ + { + "name" : "Header Files", + "sourceIndexes" : + [ + 0 + ] + }, + { + "name" : "Source Files", + "sourceIndexes" : + [ + 1, + 2, + 3 + ] + } + ], + "sources" : + [ + { + "backtrace" : 1, + "path" : "doctest.h", + "sourceGroupIndex" : 0 + }, + { + "backtrace" : 1, + "compileGroupIndex" : 0, + "path" : "Disk_Mng_Master.c", + "sourceGroupIndex" : 1 + }, + { + "backtrace" : 1, + "compileGroupIndex" : 1, + "path" : "Disk_Mng_Master_Sycl.cpp", + "sourceGroupIndex" : 1 + }, + { + "backtrace" : 1, + "compileGroupIndex" : 1, + "path" : "Doctest.cpp", + "sourceGroupIndex" : 1 + } + ], + "type" : "EXECUTABLE" +} diff --git a/Storage/out/build/x64-Debug/.cmake/api/v1/reply/toolchains-v1-80a25452cfdaac2fe07b.json b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/toolchains-v1-80a25452cfdaac2fe07b.json new file mode 100644 index 0000000..b06a14e --- /dev/null +++ b/Storage/out/build/x64-Debug/.cmake/api/v1/reply/toolchains-v1-80a25452cfdaac2fe07b.json @@ -0,0 +1,78 @@ +{ + "kind" : "toolchains", + "toolchains" : + [ + { + "compiler" : + { + "id" : "MSVC", + "implicit" : + { + "includeDirectories" : [], + "linkDirectories" : [], + "linkFrameworkDirectories" : [], + "linkLibraries" : [] + }, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe", + "version" : "19.38.33135.0" + }, + "language" : "C", + "sourceFileExtensions" : + [ + "c", + "m" + ] + }, + { + "compiler" : + { + "id" : "MSVC", + "implicit" : + { + "includeDirectories" : [], + "linkDirectories" : [], + "linkFrameworkDirectories" : [], + "linkLibraries" : [] + }, + "path" : "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe", + "version" : "19.38.33135.0" + }, + "language" : "CXX", + "sourceFileExtensions" : + [ + "C", + "M", + "c++", + "cc", + "cpp", + "cxx", + "mm", + "mpp", + "CPP", + "ixx", + "cppm", + "ccm", + "cxxm", + "c++m" + ] + }, + { + "compiler" : + { + "implicit" : {}, + "path" : "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/rc.exe" + }, + "language" : "RC", + "sourceFileExtensions" : + [ + "rc", + "RC" + ] + } + ], + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/Storage/out/build/x64-Debug/CMakeCache.txt b/Storage/out/build/x64-Debug/CMakeCache.txt new file mode 100644 index 0000000..3df348b --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeCache.txt @@ -0,0 +1,344 @@ +# This is the CMakeCache file. +# For build in directory: c:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug +# It was generated by CMake: C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cmake.exe +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_AR:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/lib.exe + +//No help, variable specified on the command line. +CMAKE_BUILD_TYPE:STRING=Debug + +//No help, variable specified on the command line. +CMAKE_CXX_COMPILER:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe + +//Flags used by the CXX compiler during all build types. +CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc + +//Flags used by the CXX compiler during DEBUG builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1 + +//Flags used by the CXX compiler during MINSIZEREL builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG + +//Flags used by the CXX compiler during RELEASE builds. +CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG + +//Flags used by the CXX compiler during RELWITHDEBINFO builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG + +//Libraries linked by default with all C++ applications. +CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + +//No help, variable specified on the command line. +CMAKE_C_COMPILER:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe + +//Flags used by the C compiler during all build types. +CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 + +//Flags used by the C compiler during DEBUG builds. +CMAKE_C_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1 + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG + +//Flags used by the C compiler during RELEASE builds. +CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + +//Flags used by the linker during all build types. +CMAKE_EXE_LINKER_FLAGS:STRING=/machine:x64 + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL= + +//Value Computed by CMake. +CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/pkgRedirects + +//No help, variable specified on the command line. +CMAKE_INSTALL_PREFIX:PATH=C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/install/x64-Debug + +//Path to a program. +CMAKE_LINKER:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/link.exe + +//make program +CMAKE_MAKE_PROGRAM:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe + +//Flags used by the linker during the creation of modules during +// all build types. +CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:x64 + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//Path to a program. +CMAKE_MT:FILEPATH=C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/mt.exe + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Disk_Mng_Master + +//RC compiler +CMAKE_RC_COMPILER:FILEPATH=C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/rc.exe + +//Flags for Windows Resource Compiler during all build types. +CMAKE_RC_FLAGS:STRING=-DWIN32 + +//Flags for Windows Resource Compiler during DEBUG builds. +CMAKE_RC_FLAGS_DEBUG:STRING=-D_DEBUG + +//Flags for Windows Resource Compiler during MINSIZEREL builds. +CMAKE_RC_FLAGS_MINSIZEREL:STRING= + +//Flags for Windows Resource Compiler during RELEASE builds. +CMAKE_RC_FLAGS_RELEASE:STRING= + +//Flags for Windows Resource Compiler during RELWITHDEBINFO builds. +CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING= + +//Flags used by the linker during the creation of shared libraries +// during all build types. +CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:x64 + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:x64 + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Value Computed by CMake +Disk_Mng_Master_BINARY_DIR:STATIC=C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug + +//Value Computed by CMake +Disk_Mng_Master_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +Disk_Mng_Master_SOURCE_DIR:STATIC=C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=c:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=27 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=2 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cmake.exe +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/cpack.exe +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin/ctest.exe +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES +CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MT +CMAKE_MT-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//noop for ranlib +CMAKE_RANLIB:INTERNAL=: +//ADVANCED property for variable: CMAKE_RC_COMPILER +CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 +CMAKE_RC_COMPILER_WORKS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS +CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG +CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL +CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE +CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO +CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCCompiler.cmake b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCCompiler.cmake new file mode 100644 index 0000000..f8d7386 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCCompiler.cmake @@ -0,0 +1,74 @@ +set(CMAKE_C_COMPILER "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "MSVC") +set(CMAKE_C_COMPILER_VERSION "19.38.33135.0") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "90") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "OFF") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "") + +set(CMAKE_C_PLATFORM_ID "Windows") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "MSVC") +set(CMAKE_C_SIMULATE_VERSION "") +set(CMAKE_C_COMPILER_ARCHITECTURE_ID x64) + +set(MSVC_C_ARCHITECTURE_ID x64) + +set(CMAKE_AR "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/lib.exe") +set(CMAKE_C_COMPILER_AR "") +set(CMAKE_RANLIB ":") +set(CMAKE_C_COMPILER_RANLIB "") +set(CMAKE_LINKER "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/link.exe") +set(CMAKE_MT "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/mt.exe") +set(CMAKE_TAPI "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) +set(CMAKE_C_LINKER_DEPFILE_SUPPORTED ) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "Note: including file: ") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCXXCompiler.cmake b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCXXCompiler.cmake new file mode 100644 index 0000000..6e118cb --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeCXXCompiler.cmake @@ -0,0 +1,85 @@ +set(CMAKE_CXX_COMPILER "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "MSVC") +set(CMAKE_CXX_COMPILER_VERSION "19.38.33135.0") +set(CMAKE_CXX_COMPILER_VERSION_INTERNAL "") +set(CMAKE_CXX_COMPILER_WRAPPER "") +set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT "14") +set(CMAKE_CXX_EXTENSIONS_COMPUTED_DEFAULT "OFF") +set(CMAKE_CXX_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters;cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates;cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates;cxx_std_17;cxx_std_20;cxx_std_23") +set(CMAKE_CXX98_COMPILE_FEATURES "cxx_std_98;cxx_template_template_parameters") +set(CMAKE_CXX11_COMPILE_FEATURES "cxx_std_11;cxx_alias_templates;cxx_alignas;cxx_alignof;cxx_attributes;cxx_auto_type;cxx_constexpr;cxx_decltype;cxx_decltype_incomplete_return_types;cxx_default_function_template_args;cxx_defaulted_functions;cxx_defaulted_move_initializers;cxx_delegating_constructors;cxx_deleted_functions;cxx_enum_forward_declarations;cxx_explicit_conversions;cxx_extended_friend_declarations;cxx_extern_templates;cxx_final;cxx_func_identifier;cxx_generalized_initializers;cxx_inheriting_constructors;cxx_inline_namespaces;cxx_lambdas;cxx_local_type_template_args;cxx_long_long_type;cxx_noexcept;cxx_nonstatic_member_init;cxx_nullptr;cxx_override;cxx_range_for;cxx_raw_string_literals;cxx_reference_qualified_functions;cxx_right_angle_brackets;cxx_rvalue_references;cxx_sizeof_member;cxx_static_assert;cxx_strong_enums;cxx_thread_local;cxx_trailing_return_types;cxx_unicode_literals;cxx_uniform_initialization;cxx_unrestricted_unions;cxx_user_literals;cxx_variadic_macros;cxx_variadic_templates") +set(CMAKE_CXX14_COMPILE_FEATURES "cxx_std_14;cxx_aggregate_default_initializers;cxx_attribute_deprecated;cxx_binary_literals;cxx_contextual_conversions;cxx_decltype_auto;cxx_digit_separators;cxx_generic_lambdas;cxx_lambda_init_captures;cxx_relaxed_constexpr;cxx_return_type_deduction;cxx_variable_templates") +set(CMAKE_CXX17_COMPILE_FEATURES "cxx_std_17") +set(CMAKE_CXX20_COMPILE_FEATURES "cxx_std_20") +set(CMAKE_CXX23_COMPILE_FEATURES "cxx_std_23") + +set(CMAKE_CXX_PLATFORM_ID "Windows") +set(CMAKE_CXX_SIMULATE_ID "") +set(CMAKE_CXX_COMPILER_FRONTEND_VARIANT "MSVC") +set(CMAKE_CXX_SIMULATE_VERSION "") +set(CMAKE_CXX_COMPILER_ARCHITECTURE_ID x64) + +set(MSVC_CXX_ARCHITECTURE_ID x64) + +set(CMAKE_AR "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/lib.exe") +set(CMAKE_CXX_COMPILER_AR "") +set(CMAKE_RANLIB ":") +set(CMAKE_CXX_COMPILER_RANLIB "") +set(CMAKE_LINKER "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/link.exe") +set(CMAKE_MT "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x64/mt.exe") +set(CMAKE_TAPI "") +set(CMAKE_COMPILER_IS_GNUCXX ) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;mpp;CPP;ixx;cppm;ccm;cxxm;c++m) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) + +foreach (lang C OBJC OBJCXX) + if (CMAKE_${lang}_COMPILER_ID_RUN) + foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS) + list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension}) + endforeach() + endif() +endforeach() + +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) +set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED ) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "") +set(CMAKE_CXX_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX "Note: including file: ") +if(CMAKE_CXX_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_CXX_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES "") +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeDetermineCompilerABI_C.bin b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CMakeDetermineCompilerABI_C.bin new file mode 100644 index 0000000000000000000000000000000000000000..ddcbdba9e3e1c41d0430d4f671333a71b134d40e GIT binary patch literal 52736 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 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdCXX/CMakeCXXCompilerId.cpp b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..52d56e2 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,855 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__COMO__) +# define COMPILER_ID "Comeau" + /* __COMO_VERSION__ = VRR */ +# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) +# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) + +#elif defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L +# if defined(__INTEL_CXX11_MODE__) +# if defined(__cpp_aggregate_nsdmi) +# define CXX_STD 201402L +# else +# define CXX_STD 201103L +# endif +# else +# define CXX_STD 199711L +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# define CXX_STD _MSVC_LANG +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > 202002L + "23" +#elif CXX_STD > 201703L + "20" +#elif CXX_STD >= 201703L + "17" +#elif CXX_STD >= 201402L + "14" +#elif CXX_STD >= 201103L + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/Storage/out/build/x64-Debug/CMakeFiles/CMakeConfigureLog.yaml b/Storage/out/build/x64-Debug/CMakeFiles/CMakeConfigureLog.yaml new file mode 100644 index 0000000..90815d9 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/CMakeConfigureLog.yaml @@ -0,0 +1,151 @@ + +--- +events: + - + kind: "message-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineSystem.cmake:211 (message)" + - "CMakeLists.txt:3 (project)" + message: | + The system is: Windows - 10.0.22631 - AMD64 + - + kind: "message-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. + Compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe + Build flags: + Id flags: + + The output was: + 0 + Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33135 for x64 + Copyright (C) Microsoft Corporation. All rights reserved. + + CMakeCCompilerId.c + Microsoft (R) Incremental Linker Version 14.38.33135.0 + Copyright (C) Microsoft Corporation. All rights reserved. + + /out:CMakeCCompilerId.exe + CMakeCCompilerId.obj + + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.exe" + + Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.obj" + + The C compiler identification is MSVC, found in: + C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdC/CMakeCCompilerId.exe + + - + kind: "message-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:1158 (message)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:221 (CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCCompiler.cmake:123 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Detecting C compiler /showIncludes prefix: + main.c + Note: including file: C:\\Users\\שיפי וינגרטן\\Pictures\\Saved Pictures\\סמינר\\כיתה יד\\תכנות\\פרקטיקום\\MultiDrone\\Storage\\out\\build\\x64-Debug\\CMakeFiles\\ShowIncludes\\foo.h + + Found prefix "Note: including file: " + - + kind: "message-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:17 (message)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:64 (__determine_compiler_id_test)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. + Compiler: C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.38.33130/bin/Hostx64/x64/cl.exe + Build flags: + Id flags: + + The output was: + 0 + Microsoft (R) C/C++ Optimizing Compiler Version 19.38.33135 for x64 + Copyright (C) Microsoft Corporation. All rights reserved. + + CMakeCXXCompilerId.cpp + Microsoft (R) Incremental Linker Version 14.38.33135.0 + Copyright (C) Microsoft Corporation. All rights reserved. + + /out:CMakeCXXCompilerId.exe + CMakeCXXCompilerId.obj + + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CMakeCXXCompilerId.exe" + + Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "CMakeCXXCompilerId.obj" + + The CXX compiler identification is MSVC, found in: + C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/3.27.2-msvc1/CompilerIdCXX/CMakeCXXCompilerId.exe + + - + kind: "message-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:1158 (message)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerId.cmake:221 (CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCXXCompiler.cmake:126 (CMAKE_DETERMINE_COMPILER_ID)" + - "CMakeLists.txt:3 (project)" + message: | + Detecting CXX compiler /showIncludes prefix: + main.c + Note: including file: C:\\Users\\שיפי וינגרטן\\Pictures\\Saved Pictures\\סמינר\\כיתה יד\\תכנות\\פרקטיקום\\MultiDrone\\Storage\\out\\build\\x64-Debug\\CMakeFiles\\ShowIncludes\\foo.h + + Found prefix "Note: including file: " + - + kind: "try_compile-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeTestCCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + checks: + - "Detecting C compiler ABI info" + directories: + source: "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ow8r92" + binary: "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ow8r92" + cmakeVariables: + CMAKE_C_FLAGS: "/DWIN32 /D_WINDOWS /W3" + buildResult: + variable: "CMAKE_C_ABI_COMPILED" + cached: true + stdout: | + Change Dir: 'C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ow8r92' + + Run Build Command(s): "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe" -v cmTC_d7826 + [1/2] "C:\\PROGRA~1\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\Hostx64\\x64\\cl.exe" /nologo /DWIN32 /D_WINDOWS /W3 /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\\cmTC_d7826.dir\\CMakeCCompilerABI.c.obj /FdCMakeFiles\\cmTC_d7826.dir\\ /FS -c "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\share\\cmake-3.27\\Modules\\CMakeCCompilerABI.c" + [2/2] cmd.exe /C "cd . && "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin\\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\\cmTC_d7826.dir --rc=C:\\PROGRA~2\\WI3CF2~1\\10\\bin\\10.0.22621.0\\x64\\rc.exe --mt=C:\\PROGRA~2\\WI3CF2~1\\10\\bin\\10.0.22621.0\\x64\\mt.exe --manifests -- "C:\\PROGRA~1\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\Hostx64\\x64\\link.exe" /nologo CMakeFiles\\cmTC_d7826.dir\\CMakeCCompilerABI.c.obj /out:cmTC_d7826.exe /implib:cmTC_d7826.lib /pdb:cmTC_d7826.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." + + exitCode: 0 + - + kind: "try_compile-v1" + backtrace: + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeDetermineCompilerABI.cmake:57 (try_compile)" + - "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.27/Modules/CMakeTestCXXCompiler.cmake:26 (CMAKE_DETERMINE_COMPILER_ABI)" + - "CMakeLists.txt:3 (project)" + checks: + - "Detecting CXX compiler ABI info" + directories: + source: "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ti79ar" + binary: "C:/Users/\u05e9\u05d9\u05e4\u05d9 \u05d5\u05d9\u05e0\u05d2\u05e8\u05d8\u05df/Pictures/Saved Pictures/\u05e1\u05de\u05d9\u05e0\u05e8/\u05db\u05d9\u05ea\u05d4 \u05d9\u05d3/\u05ea\u05db\u05e0\u05d5\u05ea/\u05e4\u05e8\u05e7\u05d8\u05d9\u05e7\u05d5\u05dd/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ti79ar" + cmakeVariables: + CMAKE_CXX_FLAGS: "/DWIN32 /D_WINDOWS /W3 /GR /EHsc" + buildResult: + variable: "CMAKE_CXX_ABI_COMPILED" + cached: true + stdout: | + Change Dir: 'C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/CMakeScratch/TryCompile-ti79ar' + + Run Build Command(s): "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe" -v cmTC_6692f + [1/2] "C:\\PROGRA~1\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\Hostx64\\x64\\cl.exe" /nologo /TP /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 /showIncludes /FoCMakeFiles\\cmTC_6692f.dir\\CMakeCXXCompilerABI.cpp.obj /FdCMakeFiles\\cmTC_6692f.dir\\ /FS -c "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\share\\cmake-3.27\\Modules\\CMakeCXXCompilerABI.cpp" + [2/2] cmd.exe /C "cd . && "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Common7\\IDE\\CommonExtensions\\Microsoft\\CMake\\CMake\\bin\\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\\cmTC_6692f.dir --rc=C:\\PROGRA~2\\WI3CF2~1\\10\\bin\\10.0.22621.0\\x64\\rc.exe --mt=C:\\PROGRA~2\\WI3CF2~1\\10\\bin\\10.0.22621.0\\x64\\mt.exe --manifests -- "C:\\PROGRA~1\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\Hostx64\\x64\\link.exe" /nologo CMakeFiles\\cmTC_6692f.dir\\CMakeCXXCompilerABI.cpp.obj /out:cmTC_6692f.exe /implib:cmTC_6692f.lib /pdb:cmTC_6692f.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ." + + exitCode: 0 +... diff --git a/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/foo.h b/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/foo.h new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/foo.h @@ -0,0 +1 @@ + diff --git a/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/main.c b/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/main.c new file mode 100644 index 0000000..cd3cbc1 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/ShowIncludes/main.c @@ -0,0 +1,2 @@ +#include "foo.h" +int main(){} diff --git a/Storage/out/build/x64-Debug/CMakeFiles/TargetDirectories.txt b/Storage/out/build/x64-Debug/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000..41b2001 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/Disk_Mng_Master.dir +C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/edit_cache.dir +C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/CMakeFiles/rebuild_cache.dir diff --git a/Storage/out/build/x64-Debug/CMakeFiles/cmake.check_cache b/Storage/out/build/x64-Debug/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000..3dccd73 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/Storage/out/build/x64-Debug/CMakeFiles/rules.ninja b/Storage/out/build/x64-Debug/CMakeFiles/rules.ninja new file mode 100644 index 0000000..2d9f299 --- /dev/null +++ b/Storage/out/build/x64-Debug/CMakeFiles/rules.ninja @@ -0,0 +1,78 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.27 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: Disk_Mng_Master +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# localized /showIncludes string + +msvc_deps_prefix = Note: including file: + + +############################################# +# Rule for compiling C files. + +rule C_COMPILER__Disk_Mng_Master_unscanned_Debug + deps = msvc + command = ${LAUNCHER}${CODE_CHECK}"C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64\cl.exe" /nologo $DEFINES $INCLUDES $FLAGS /showIncludes /Fo$out /Fd$TARGET_COMPILE_PDB /FS -c $in + description = Building C object $out + + +############################################# +# Rule for compiling CXX files. + +rule CXX_COMPILER__Disk_Mng_Master_unscanned_Debug + deps = msvc + command = ${LAUNCHER}${CODE_CHECK}"C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64\cl.exe" /nologo /TP $DEFINES $INCLUDES $FLAGS /showIncludes /Fo$out /Fd$TARGET_COMPILE_PDB /FS -c $in + description = Building CXX object $out + + +############################################# +# Rule for linking CXX executable. + +rule CXX_EXECUTABLE_LINKER__Disk_Mng_Master_Debug + command = cmd.exe /C "$PRE_LINK && "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=$OBJECT_DIR --rc=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.22621.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.22621.0\x64\mt.exe --manifests $MANIFESTS -- "C:\PROGRA~1\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\bin\Hostx64\x64\link.exe" /nologo $in /out:$TARGET_FILE /implib:$TARGET_IMPLIB /pdb:$TARGET_PDB /version:0.0 $LINK_FLAGS $LINK_PATH $LINK_LIBRARIES && $POST_BUILD" + description = Linking CXX executable $TARGET_FILE + restat = $RESTAT + + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --regenerate-during-build -S"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage" -B"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\out\build\x64-Debug" + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" -t targets + description = All primary targets available: + diff --git a/Storage/out/build/x64-Debug/Testing/Temporary/LastTest.log b/Storage/out/build/x64-Debug/Testing/Temporary/LastTest.log new file mode 100644 index 0000000..cc82748 --- /dev/null +++ b/Storage/out/build/x64-Debug/Testing/Temporary/LastTest.log @@ -0,0 +1,3 @@ +Start testing: Sep 05 11:34 +---------------------------------------------------------- +End testing: Sep 05 11:34 diff --git a/Storage/out/build/x64-Debug/VSInheritEnvironments.txt b/Storage/out/build/x64-Debug/VSInheritEnvironments.txt new file mode 100644 index 0000000..f8cc9d8 --- /dev/null +++ b/Storage/out/build/x64-Debug/VSInheritEnvironments.txt @@ -0,0 +1 @@ +msvc_x64_x64 \ No newline at end of file diff --git a/Storage/out/build/x64-Debug/build.ninja b/Storage/out/build/x64-Debug/build.ninja new file mode 100644 index 0000000..21c1329 --- /dev/null +++ b/Storage/out/build/x64-Debug/build.ninja @@ -0,0 +1,171 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.27 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: Disk_Mng_Master +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles\rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\out\build\x64-Debug\ +# ============================================================================= +# Object build statements for EXECUTABLE target Disk_Mng_Master + + +############################################# +# Order-only phony target for Disk_Mng_Master + +build cmake_object_order_depends_target_Disk_Mng_Master: phony || CMakeFiles\Disk_Mng_Master.dir + +build CMakeFiles\Disk_Mng_Master.dir\Disk_Mng_Master.c.obj: C_COMPILER__Disk_Mng_Master_unscanned_Debug C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\Disk_Mng_Master.c || cmake_object_order_depends_target_Disk_Mng_Master + FLAGS = /DWIN32 /D_WINDOWS /W3 /MDd /Zi /Ob0 /Od /RTC1 + INCLUDES = -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage" -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN" + OBJECT_DIR = CMakeFiles\Disk_Mng_Master.dir + OBJECT_FILE_DIR = CMakeFiles\Disk_Mng_Master.dir + TARGET_COMPILE_PDB = CMakeFiles\Disk_Mng_Master.dir\ + TARGET_PDB = Disk_Mng_Master.pdb + +build CMakeFiles\Disk_Mng_Master.dir\Disk_Mng_Master_Sycl.cpp.obj: CXX_COMPILER__Disk_Mng_Master_unscanned_Debug C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\Disk_Mng_Master_Sycl.cpp || cmake_object_order_depends_target_Disk_Mng_Master + FLAGS = /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 -std:c++17 + INCLUDES = -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage" -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN" + OBJECT_DIR = CMakeFiles\Disk_Mng_Master.dir + OBJECT_FILE_DIR = CMakeFiles\Disk_Mng_Master.dir + TARGET_COMPILE_PDB = CMakeFiles\Disk_Mng_Master.dir\ + TARGET_PDB = Disk_Mng_Master.pdb + +build CMakeFiles\Disk_Mng_Master.dir\Doctest.cpp.obj: CXX_COMPILER__Disk_Mng_Master_unscanned_Debug C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\Doctest.cpp || cmake_object_order_depends_target_Disk_Mng_Master + FLAGS = /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 -std:c++17 + INCLUDES = -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage" -I"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN" + OBJECT_DIR = CMakeFiles\Disk_Mng_Master.dir + OBJECT_FILE_DIR = CMakeFiles\Disk_Mng_Master.dir + TARGET_COMPILE_PDB = CMakeFiles\Disk_Mng_Master.dir\ + TARGET_PDB = Disk_Mng_Master.pdb + + +# ============================================================================= +# Link build statements for EXECUTABLE target Disk_Mng_Master + + +############################################# +# Link the executable Disk_Mng_Master.exe + +build Disk_Mng_Master.exe: CXX_EXECUTABLE_LINKER__Disk_Mng_Master_Debug CMakeFiles\Disk_Mng_Master.dir\Disk_Mng_Master.c.obj CMakeFiles\Disk_Mng_Master.dir\Disk_Mng_Master_Sycl.cpp.obj CMakeFiles\Disk_Mng_Master.dir\Doctest.cpp.obj + FLAGS = /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MDd /Zi /Ob0 /Od /RTC1 + LINK_FLAGS = /machine:x64 /debug /INCREMENTAL /subsystem:console + LINK_LIBRARIES = kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib + OBJECT_DIR = CMakeFiles\Disk_Mng_Master.dir + POST_BUILD = cd . + PRE_LINK = cd . + TARGET_COMPILE_PDB = CMakeFiles\Disk_Mng_Master.dir\ + TARGET_FILE = Disk_Mng_Master.exe + TARGET_IMPLIB = Disk_Mng_Master.lib + TARGET_PDB = Disk_Mng_Master.pdb + + +############################################# +# Utility command for edit_cache + +build CMakeFiles\edit_cache.util: CUSTOM_COMMAND + COMMAND = cmd.exe /C "cd /D "C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\out\build\x64-Debug" && "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E echo "No interactive CMake dialog available."" + DESC = No interactive CMake dialog available... + restat = 1 + +build edit_cache: phony CMakeFiles\edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles\rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cmd.exe /C "cd /D "C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\out\build\x64-Debug" && "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --regenerate-during-build -S"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage" -B"C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\MultiDrone\Storage\out\build\x64-Debug"" + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles\rebuild_cache.util + +# ============================================================================= +# Target aliases. + +build Disk_Mng_Master: phony Disk_Mng_Master.exe + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug + +build all: phony Disk_Mng_Master.exe + +# ============================================================================= +# Unknown Build Time Dependencies. +# Tell Ninja that they may appear as side effects of build rules +# otherwise ordered by order-only dependencies. + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCXXInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCommonLanguageInclude.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeGenericSystem.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeInitializeConfigs.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeLanguageInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeRCInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeSystemSpecificInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeSystemSpecificInitialize.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\CMakeCommonCompilerMacros.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC-C.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC-CXX.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-Initialize.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC-C.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC-CXX.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\WindowsPaths.cmake C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\CMakeLists.txt CMakeCache.txt CMakeFiles\3.27.2-msvc1\CMakeCCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeCXXCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeRCCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCXXInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeCommonLanguageInclude.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeGenericSystem.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeInitializeConfigs.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeLanguageInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeRCInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeSystemSpecificInformation.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\CMakeSystemSpecificInitialize.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\CMakeCommonCompilerMacros.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC-C.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC-CXX.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Compiler\MSVC.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-Initialize.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC-C.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC-CXX.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows-MSVC.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\Windows.cmake C$:\Program$ Files\Microsoft$ Visual$ Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\share\cmake-3.27\Modules\Platform\WindowsPaths.cmake C$:\Users\שיפי$ וינגרטן\Pictures\Saved$ Pictures\סמינר\כיתה$ יד\תכנות\פרקטיקום\MultiDrone\Storage\CMakeLists.txt CMakeCache.txt CMakeFiles\3.27.2-msvc1\CMakeCCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeCXXCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeRCCompiler.cmake CMakeFiles\3.27.2-msvc1\CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/Storage/out/build/x64-Debug/cmake_install.cmake b/Storage/out/build/x64-Debug/cmake_install.cmake new file mode 100644 index 0000000..13ad5a0 --- /dev/null +++ b/Storage/out/build/x64-Debug/cmake_install.cmake @@ -0,0 +1,44 @@ +# Install script for directory: C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/install/x64-Debug") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "C:/Users/שיפי וינגרטן/Pictures/Saved Pictures/סמינר/כיתה יד/תכנות/פרקטיקום/MultiDrone/Storage/out/build/x64-Debug/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") From fb81e2032f55269c800367b79a06c274ed391f69 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 9 Sep 2024 10:31:25 +0300 Subject: [PATCH 25/32] fix --- Storage/.c | 3 --- Storage/CMakeLists.txt | 11 --------- Storage/Disk_Mng_Master.h | 2 ++ Storage/Disk_Mng_Master_Sycl.cpp | 38 ++++++++++++++++++++++++++++++++ Storage/Doctest.cpp | 33 +++++++++++++++++++++++++-- Storage/Storage.vcxproj | 1 + Storage/cmake | 0 7 files changed, 72 insertions(+), 16 deletions(-) delete mode 100644 Storage/.c delete mode 100644 Storage/CMakeLists.txt create mode 100644 Storage/Disk_Mng_Master_Sycl.cpp delete mode 100644 Storage/cmake diff --git a/Storage/.c b/Storage/.c deleted file mode 100644 index ffc6dab..0000000 --- a/Storage/.c +++ /dev/null @@ -1,3 +0,0 @@ -int main() { - return 0; -} \ No newline at end of file diff --git a/Storage/CMakeLists.txt b/Storage/CMakeLists.txt deleted file mode 100644 index 6e1403e..0000000 --- a/Storage/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION "3.30.2") - -project("Disk_MNG_Master") - -add_executable("${PROJECT_NAME}" "Doctest.cpp" "Disk_Mng_Master.c" "Disk_Mng_Master.h" "Disk_Mng_Master_API.h" "doctest.h") - -add_custom_target(cpu-gpu DEPENDS ${TARGET_NAME}) - -install(TARGETS "${PROJECT_NAME}" DESTINATION bin) #$ (CMAKE_INSTALL_PREFIX)/bin - -install(FILES "Doctest.cpp" DESTINATION src) #$ (CMAKE_INSTALL_PREFIX)/src \ No newline at end of file diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 6a37cff..c0fe32c 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -291,3 +291,5 @@ bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress); //cache_deleteMap- delete map from the cache void cache_deleteMap(int mapId); + +//int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) diff --git a/Storage/Disk_Mng_Master_Sycl.cpp b/Storage/Disk_Mng_Master_Sycl.cpp new file mode 100644 index 0000000..3dab19e --- /dev/null +++ b/Storage/Disk_Mng_Master_Sycl.cpp @@ -0,0 +1,38 @@ +//#include +//#include +//#include +//#include "Disk_Mng_Master_API.h" +//#include "Disk_Mng_Master.h" +//using namespace cl::sycl; +//extern "C" { +//#include "Disk_Mng_Master_API.h" +//#include "Disk_Mng_Master.h" +//} +//int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) { +// int count = 0; +// +// +// queue q; +// buffer bufferCount(&count, 1); +// buffer bufferInputArray(disk_mng_CB->arrayForAllMApsInformation, range<1>(arraySize)); +// buffer bufferOutputArray(*arrayOfMapsIdsInRange, range<1>(arraySize)); +// +// q.submit([&](handler& h) { +// auto inputArrayAccess = bufferInputArray.get_access(h); +// auto outputArrayAccess = bufferOutputArray.get_access(h); +// auto countAccess = bufferCount.get_access(h); +// +// h.parallel_for(range<1>(arraySize), [=](id<1> i) { +// if (inputArrayAccess[i].range != NULL && +// disk_mng_isTheMapInRange(rangeFromCache, inputArrayAccess[i].range)) { +// int idx = atomic_fetch_add(countAccess[0], 1); +// outputArrayAccess[idx] = inputArrayAccess[i]; +// disk_mng_CB->disk_MapsInLoadedToCache[idx] = arrayInLoaded_create(inputArrayAccess[i]->mapid, i); +// } +// }); +// }).wait(); +// +// count = bufferCount.get_access()[0]; +// +// return count; +//} \ No newline at end of file diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 9d6b15b..9e19538 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -10,7 +10,7 @@ extern "C" { #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" -} + struct GlobalSetup { GlobalSetup() { srand(time(0)); @@ -863,4 +863,33 @@ TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { // Check results CHECK(result == true); -} \ No newline at end of file +}} +//TEST_CASE("test_disk_mng_getMapsIdsInRange") { +// disk_mng_initialize(); +// +// for (int i = 0; i < 20; i++) +// { +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// int size = generateRandomNumber(); +// int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); +// disk_mng_addMap(mapRange, size, map); +// +// } +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// +// ArrayInfo_t** arrayOfMapsInRange = (ArrayInfo_t**)allocate_memory(CACHE_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for arrayOfMapsInRange ", "test_disk_mng_getMapsIdsInRange"); +// +// int count = disk_mng_getMapsIdsInRange(mapRange, arrayOfMapsInRange, CACHE_SIZE); +//} \ No newline at end of file diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index e43783f..47a925b 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -128,6 +128,7 @@ + diff --git a/Storage/cmake b/Storage/cmake deleted file mode 100644 index e69de29..0000000 From 9ba1492c4f5507d4b8edddf7f461e319b8963230 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 9 Sep 2024 10:44:10 +0300 Subject: [PATCH 26/32] add changes --- Storage/Doctest.cpp | 1390 ++++++++++++++++++++----------------------- 1 file changed, 637 insertions(+), 753 deletions(-) diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 0533c4c..f135c4b 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -12,654 +12,677 @@ extern "C" { #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" -} - struct GlobalSetup { - GlobalSetup() { - srand(time(0)); - } - }; - GlobalSetup globalSetup; - int generateRandomNumber(int lower = 0, int upper = DISK_SIZE) { - return (rand() % (upper - lower + 1)) + lower; - } - void printPoint(const char* label, const Point_t& point) { - printf("%s: x = %d, y = %d\n", label, point.x, point.y); +struct GlobalSetup { + GlobalSetup() { + srand(time(0)); } +}; +GlobalSetup globalSetup; - // Function to print map ranges for debugging - void printMapRange(const char* label, const MapRange_t* range) { - printf("%s: TopLeft (x = %d, y = %d), BottomRight (x = %d, y = %d)\n", - label, range->topLeft.x, range->topLeft.y, range->bottomRight.x, range->bottomRight.y); +int generateRandomNumber(int lower=0,int upper = DISK_SIZE) { + return (rand() % (upper - lower + 1)) + lower; +} +void printPoint(const char* label, const Point_t& point) { + printf("%s: x = %d, y = %d\n", label, point.x, point.y); +} + +// Function to print map ranges for debugging +void printMapRange(const char* label, const MapRange_t* range) { + printf("%s: TopLeft (x = %d, y = %d), BottomRight (x = %d, y = %d)\n", + label, range->topLeft.x, range->topLeft.y, range->bottomRight.x, range->bottomRight.y); +} +void printTreeDetails(AVLNode_t* node) { + if (node == NULL) { + return; } - void printTreeDetails(AVLNode_t* node) { - if (node == NULL) { - return; - } - // Print current node details - printf("Node details:\n"); - printf("Map Size: %d\n", node->avlNodeInfo->mapSize); - printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); - printf("LRU: %d\n", node->avlNodeInfo->lru); - printf("Height: %d\n\n", node->height); + // Print current node details + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); + printf("Height: %d\n\n", node->height); - // Recurse on the left and right subtrees - printTreeDetails(node->left); - printTreeDetails(node->right); - } + // Recurse on the left and right subtrees + printTreeDetails(node->left); + printTreeDetails(node->right); +} - void printNode(AVLNode_t* node) { - if (node == NULL) { - printf("Node is NULL\n"); - return; - } - printf("Node details:\n"); - printf("Map Size: %d\n", node->avlNodeInfo->mapSize); +void printNode(AVLNode_t* node) { + if (node == NULL) { + printf("Node is NULL\n"); + return; + } + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); - printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); - printf("LRU: %d\n", node->avlNodeInfo->lru); + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); +} +void printTree(AVLNode_t* root) { + if (root == nullptr) { + return; } - void printTree(AVLNode_t* root) { - if (root == nullptr) { - return; - } - // Queue for level order traversal - std::queue q; - q.push(root); + // Queue for level order traversal + std::queue q; + q.push(root); - // Vector to store levels of the tree - std::vector> levels; + // Vector to store levels of the tree + std::vector> levels; - // Traverse the tree level by level - while (!q.empty()) { - int nodeCount = q.size(); - std::vector currentLevel; + // Traverse the tree level by level + while (!q.empty()) { + int nodeCount = q.size(); + std::vector currentLevel; - while (nodeCount > 0) { - AVLNode_t* node = q.front(); - q.pop(); - currentLevel.push_back(node); + while (nodeCount > 0) { + AVLNode_t* node = q.front(); + q.pop(); + currentLevel.push_back(node); - if (node != nullptr) { - q.push(node->left); - q.push(node->right); - } - nodeCount--; + if (node != nullptr) { + q.push(node->left); + q.push(node->right); } + nodeCount--; + } - // Add level only if there are nodes at this level - if (std::any_of(currentLevel.begin(), currentLevel.end(), [](AVLNode_t* n) { return n != nullptr; })) { - levels.push_back(currentLevel); - } + // Add level only if there are nodes at this level + if (std::any_of(currentLevel.begin(), currentLevel.end(), [](AVLNode_t* n) { return n != nullptr; })) { + levels.push_back(currentLevel); } + } + + int maxLevel = levels.size(); + int width = 1 << (maxLevel - 1); // Maximum width of the tree at the last level - int maxLevel = levels.size(); - int width = 1 << (maxLevel - 1); // Maximum width of the tree at the last level + for (int i = 0; i < maxLevel; ++i) { + std::vector currentLevel = levels[i]; + int numNodes = currentLevel.size(); + int spacing = width / (numNodes + 1); + int offset = spacing / 2; - for (int i = 0; i < maxLevel; ++i) { - std::vector currentLevel = levels[i]; - int numNodes = currentLevel.size(); - int spacing = width / (numNodes + 1); - int offset = spacing / 2; + // Print leading spaces + std::cout << std::setw(offset) << ""; - // Print leading spaces + // Print nodes at current level + for (AVLNode_t* node : currentLevel) { + if (node == nullptr) { + std::cout << std::setw(width) << ""; + } + else { + std::cout << std::setw(width) << node->avlNodeInfo->mapSize; + } std::cout << std::setw(offset) << ""; + } + std::cout << std::endl; - // Print nodes at current level + // Print level separators + if (i < maxLevel - 1) { + std::cout << std::setw(width / 2) << ""; for (AVLNode_t* node : currentLevel) { if (node == nullptr) { std::cout << std::setw(width) << ""; } else { - std::cout << std::setw(width) << node->avlNodeInfo->mapSize; + std::cout << std::setw(width / 2) << (node->left != nullptr ? "/" : " "); + std::cout << std::setw(width / 2) << (node->right != nullptr ? "\\" : " "); } - std::cout << std::setw(offset) << ""; - } - std::cout << std::endl; - - // Print level separators - if (i < maxLevel - 1) { std::cout << std::setw(width / 2) << ""; - for (AVLNode_t* node : currentLevel) { - if (node == nullptr) { - std::cout << std::setw(width) << ""; - } - else { - std::cout << std::setw(width / 2) << (node->left != nullptr ? "/" : " "); - std::cout << std::setw(width / 2) << (node->right != nullptr ? "\\" : " "); - } - std::cout << std::setw(width / 2) << ""; - } - std::cout << std::endl; } + std::cout << std::endl; } } - int index, popValue, value; +} +int index, popValue,value; - //mock functions +//mock functions - int* disk_addMap(int* map) - { - //int num = generateRandomNumber(10000000); - //if (num % 2 == 0) - //{ +int* disk_addMap(int* map) +{ + //int num = generateRandomNumber(10000000); + //if (num % 2 == 0) + //{ int* map1 = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for disk control block", "disk_addMap"); return map1; - //} - //return NULL; - } + //} + //return NULL; +} - //the function get pointer to map in the disk and delete this map from disk - bool disk_deleteMap(int* diskPointer) - { - return true; - } - bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) - { - return true; - } - void cache_deleteMap(int mapId) - { - } +//the function get pointer to map in the disk and delete this map from disk +bool disk_deleteMap(int* diskPointer) +{ + return true; +} +bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) +{ + return true; +} +void cache_deleteMap(int mapId) +{ +} - void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad) - { - int start = *(int*)startAddress; - int sizeToLoad = *(int*)howManyToLoad; +void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad) +{ + int start = *(int*)startAddress; + int sizeToLoad = *(int*)howManyToLoad; - memcpy(destination, (char*)disk_mng_CB->mockDisk + start, sizeToLoad); - } + memcpy(destination, (char*)disk_mng_CB->mockDisk + start, sizeToLoad); +} - void disk_saveDataFromStructersToDisk(void* source, void* startAddress, void* howManyToLoad) - { - int start = *(int*)startAddress; - int sizeToSave = *(int*)howManyToLoad; +void disk_saveDataFromStructersToDisk(void* source, void* startAddress, void* howManyToLoad) +{ + int start = *(int*)startAddress; + int sizeToSave = *(int*)howManyToLoad; - memcpy((char*)disk_mng_CB->mockDisk + start, source, sizeToSave); - } - bool disk_isThereEnoughSpace(int mapSize) - { - //int num = generateRandomNumber(10000000); - //if (num % 2 == 0) - //{ - // return true; - //} - //return false; - return true; + memcpy((char*)disk_mng_CB->mockDisk + start, source, sizeToSave); +} +bool disk_isThereEnoughSpace(int mapSize) +{ + //int num = generateRandomNumber(10000000); + //if (num % 2 == 0) + //{ + // return true; + //} + //return false; + return true; - } +} - TEST_CASE("test_disk_mng_initialize_CB") - { - disk_mng_initialize_CB(); - CHECK(disk_mng_CB != NULL); - } +TEST_CASE("test_disk_mng_initialize_CB") +{ + disk_mng_initialize_CB(); + CHECK(disk_mng_CB != NULL); +} - TEST_CASE("test_disk_mng_initialize") - { - disk_mng_initialize(); - } +TEST_CASE("test_disk_mng_initialize") +{ + disk_mng_initialize(); +} - //avlNode tests +//avlNode tests - TEST_CASE("test_avlNodeInfo_create") - { - disk_mng_initialize(); +TEST_CASE("test_avlNodeInfo_create") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - CHECK(avlNodeInfo->mapSize == mapSize); - CHECK(avlNodeInfo->arrayIndex == indexArray); - CHECK(avlNodeInfo->lru == 1); - } + CHECK(avlNodeInfo->mapSize == mapSize); + CHECK(avlNodeInfo->arrayIndex == indexArray); + CHECK(avlNodeInfo->lru == 1); +} - TEST_CASE("test_avlNodeInfo_delete") - { - disk_mng_initialize(); +TEST_CASE("test_avlNodeInfo_delete") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - avlNodeInfo_delete(avlNodeInfo); - } + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + avlNodeInfo_delete(avlNodeInfo); +} - TEST_CASE("test_avlNode_create") - { - disk_mng_initialize(); +TEST_CASE("test_avlNode_create") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - CHECK(avlNode->avlNodeInfo == avlNodeInfo); - CHECK(avlNode->height == 1); - CHECK(avlNode->left == NULL); - CHECK(avlNode->right == NULL); - } + CHECK(avlNode->avlNodeInfo == avlNodeInfo); + CHECK(avlNode->height == 1); + CHECK(avlNode->left == NULL); + CHECK(avlNode->right == NULL); +} - TEST_CASE("test_avlNode_delete") - { - disk_mng_initialize(); +TEST_CASE("test_avlNode_delete") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - avlNode_delete(avlNode); - } + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + avlNode_delete(avlNode); +} - TEST_CASE("test_avlNode_height") - { - disk_mng_initialize(); +TEST_CASE("test_avlNode_height") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - CHECK(avlNode->height == avlNode_height(avlNode)); - } + CHECK(avlNode->height == avlNode_height(avlNode)); +} - //avlTree tests +//avlTree tests - TEST_CASE("avlTree_firstInitialize") - { +TEST_CASE("avlTree_firstInitialize") +{ - } +} - TEST_CASE("avlTree_normalInitialize") - { +TEST_CASE("avlTree_normalInitialize") +{ - } +} - TEST_CASE("avlTree_saveData") - { +TEST_CASE("avlTree_saveData") +{ - } +} - TEST_CASE("test_avlTree_rightRotate") - { - disk_mng_initialize(); +TEST_CASE("test_avlTree_rightRotate") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); - avlNode1->left = avlNode2; - avlNode2->left = avlNode3; + avlNode1->left = avlNode2; + avlNode2->left = avlNode3; - avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; - avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; - AVLNode_t* newRoot = avlTree_rightRotate(avlNode1); + AVLNode_t* newRoot = avlTree_rightRotate(avlNode1); - CHECK(newRoot == avlNode2); - CHECK(newRoot->right == avlNode1); - CHECK(newRoot->left == avlNode3); - CHECK(avlNode1->left == nullptr); - CHECK(avlNode1->height == 1); - CHECK(newRoot->height == 2); - } + CHECK(newRoot == avlNode2); + CHECK(newRoot->right == avlNode1); + CHECK(newRoot->left == avlNode3); + CHECK(avlNode1->left == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); +} - TEST_CASE("test_avlTree_leftRotate") - { - disk_mng_initialize(); +TEST_CASE("test_avlTree_leftRotate") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); - avlNode1->right = avlNode2; - avlNode2->right = avlNode3; + avlNode1->right = avlNode2; + avlNode2->right = avlNode3; - avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; - avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; - AVLNode_t* newRoot = avlTree_leftRotate(avlNode1); + AVLNode_t* newRoot = avlTree_leftRotate(avlNode1); - CHECK(newRoot == avlNode2); - CHECK(newRoot->left == avlNode1); - CHECK(newRoot->right == avlNode3); - CHECK(avlNode1->right == nullptr); - CHECK(avlNode1->height == 1); - CHECK(newRoot->height == 2); - } + CHECK(newRoot == avlNode2); + CHECK(newRoot->left == avlNode1); + CHECK(newRoot->right == avlNode3); + CHECK(avlNode1->right == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); +} - TEST_CASE("avlTree_getBalance") - { - disk_mng_initialize(); +TEST_CASE("avlTree_getBalance") +{ + disk_mng_initialize(); - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, indexArray); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, indexArray); - AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - AVLNode_t* root = avlNode_create(info3); + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* root = avlNode_create(info3); - SUBCASE("Node is NULL") { - CHECK(avlTree_getBalance(nullptr) == 0); - } + SUBCASE("Node is NULL") { + CHECK(avlTree_getBalance(nullptr) == 0); + } - SUBCASE("Balance factor of a node with children having different heights") { - root->left = node1; - root->right = node2; - node1->height = 3; - node2->height = 1; - root->height = 4; - CHECK(avlTree_getBalance(root) == 2); - } + SUBCASE("Balance factor of a node with children having different heights") { + root->left = node1; + root->right = node2; + node1->height = 3; + node2->height = 1; + root->height = 4; + CHECK(avlTree_getBalance(root) == 2); + } - SUBCASE("Balance factor of a node with both children having the same height") { - root->left = node1; - root->right = node2; - node1->height = 2; - node2->height = 2; - root->height = 3; - CHECK(avlTree_getBalance(root) == 0); - } + SUBCASE("Balance factor of a node with both children having the same height") { + root->left = node1; + root->right = node2; + node1->height = 2; + node2->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 0); + } - SUBCASE("Balance factor of a node with one child") { - root->left = node1; - root->right = nullptr; - node1->height = 2; - root->height = 3; - CHECK(avlTree_getBalance(root) == 2); - } + SUBCASE("Balance factor of a node with one child") { + root->left = node1; + root->right = nullptr; + node1->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 2); } - TEST_CASE("test_avlTree_minValueNode") { - disk_mng_initialize(); +} +TEST_CASE("test_avlTree_minValueNode") { + disk_mng_initialize(); - int mapSize1 = generateRandomNumber(); - int indexArray1 = generateRandomNumber(); + int mapSize1 = generateRandomNumber(); + int indexArray1 = generateRandomNumber(); - int mapSize2 = generateRandomNumber(); - int indexArray2 = generateRandomNumber(); + int mapSize2 = generateRandomNumber(); + int indexArray2 = generateRandomNumber(); - int mapSize3 = generateRandomNumber(); - int indexArray3 = generateRandomNumber(); + int mapSize3 = generateRandomNumber(); + int indexArray3 = generateRandomNumber(); - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize1, indexArray1); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize2, indexArray2); - AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize3, indexArray3); + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize1, indexArray1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize2, indexArray2); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize3, indexArray3); - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - AVLNode_t* node3 = avlNode_create(info3); + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* node3 = avlNode_create(info3); - SUBCASE("Node with no left child") { - CHECK(avlTree_minValueNode(node1) == node1); - } - node1->left = node2; - node2->left = node3; + SUBCASE("Node with no left child") { + CHECK(avlTree_minValueNode(node1) == node1); + } + node1->left = node2; + node2->left = node3; - SUBCASE("Node with left child") { - CHECK(avlTree_minValueNode(node1) == node3); - } + SUBCASE("Node with left child") { + CHECK(avlTree_minValueNode(node1) == node3); } - TEST_CASE("test_avlTree_insert") { - disk_mng_initialize(); +} +TEST_CASE("test_avlTree_insert") { + disk_mng_initialize(); + + SUBCASE("Insert into an empty tree") { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); - SUBCASE("Insert into an empty tree") { + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 1); + } + + SUBCASE("Insert nodes and check balancing") { + + for (int i = 0; i < 7; ++i) { int mapSize = generateRandomNumber(); int arrayIndex = generateRandomNumber(); AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); avlTree_insertElement(info); - - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); - CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 1); } - SUBCASE("Insert nodes and check balancing") { - - for (int i = 0; i < 7; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } - - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 7); - } + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 7); + } - SUBCASE("Insert duplicate mapSize") { - int mapSize = generateRandomNumber(); - int arrayIndex1 = generateRandomNumber(); - int arrayIndex2 = generateRandomNumber(); + SUBCASE("Insert duplicate mapSize") { + int mapSize = generateRandomNumber(); + int arrayIndex1 = generateRandomNumber(); + int arrayIndex2 = generateRandomNumber(); - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); - avlTree_insertElement(info1); - avlTree_insertElement(info2); + avlTree_insertElement(info1); + avlTree_insertElement(info2); - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->left == nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->left == nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); - CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 2); - } + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 2); } - TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { - disk_mng_initialize(); - - SUBCASE("Find eligible node for deletion") { - // Insert nodes into the AVL tree with different LRU values - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } +} +TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { + disk_mng_initialize(); - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + SUBCASE("Find eligible node for deletion") { + // Insert nodes into the AVL tree with different LRU values + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); } - SUBCASE("All nodes are eligible for deletion") { - // Insert nodes with LRU values such that all are eligible for deletion - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + } - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + SUBCASE("All nodes are eligible for deletion") { + // Insert nodes with LRU values such that all are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = generateRandomNumber(); + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); } - SUBCASE("No node is eligible for deletion") { - // Insert nodes with LRU values such that none are eligible for deletion - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + + } - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + SUBCASE("No node is eligible for deletion") { + // Insert nodes with LRU values such that none are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + } + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); + - } } - TEST_CASE("test_avlTree_deleteNode") { - disk_mng_initialize(); +} +TEST_CASE("test_avlTree_deleteNode") { + disk_mng_initialize(); - for (int i = 0; i < 10; i++) - { - AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); - avlTree_insertElement(info1); - } + for (int i = 0; i < 10; i++) + { + AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); + avlTree_insertElement(info1); + } - AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - if (nodeToDelete != NULL) - { - disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); - } + AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + if (nodeToDelete!=NULL) + { + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); } +} - //stack tests +//stack tests - TEST_CASE("test_stack_firstInitialize") +TEST_CASE("test_stack_firstInitialize") +{ + disk_mng_initialize(); + for (int i = 0; i < DISK_SIZE; i++) { - disk_mng_initialize(); - for (int i = 0; i < DISK_SIZE; i++) - { - - stack_push(i); - } - - for (int i = DISK_SIZE - 1; i > 0; i--) - { - CHECK(stack_pop() == i); - } + + stack_push(i); } - - TEST_CASE("test_stack_normalInitialize") + for (int i =DISK_SIZE-1; i >0; i--) { - disk_mng_initialize(); + CHECK( stack_pop() == i); } +} - TEST_CASE("stack_saveData") - { - } +TEST_CASE("test_stack_normalInitialize") +{ + disk_mng_initialize(); +} - TEST_CASE("test_stack_push") - { - disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) - { - index = generateRandomNumber(); - stack_push(index); - popValue = stack_pop(); - CHECK(popValue == index); - } +TEST_CASE("stack_saveData") +{ + +} +TEST_CASE("test_stack_push") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + stack_push(index); + popValue = stack_pop(); + CHECK(popValue == index); } - TEST_CASE("test_stack_pop") + +} +TEST_CASE("test_stack_pop") +{ + disk_mng_initialize(); + for (size_t i = 4; i < 0; i++) { - disk_mng_initialize(); - for (size_t i = 4; i < 0; i++) - { - value = stack_pop(); - CHECK(value != stack_top()); - } + value = stack_pop(); + CHECK(value !=stack_top()); } - TEST_CASE("test_stack_top") +} +TEST_CASE("test_stack_top") +{ + disk_mng_initialize(); + for (size_t i = DISK_SIZE-1; i < 0; i--) { - disk_mng_initialize(); - for (size_t i = DISK_SIZE - 1; i < 0; i--) - { - value = stack_top(); - stack_pop(); - CHECK(value == i); - } + value = stack_top(); + stack_pop(); + CHECK(value == i); } - TEST_CASE("test_stack_is_empty") +} +TEST_CASE("test_stack_is_empty") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) { - disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) - { - stack_pop(); - } - CHECK(stack_is_empty()); - + stack_pop(); } + CHECK(stack_is_empty()); - TEST_CASE("test_stackNode_create") - { - disk_mng_initialize(); - int index = generateRandomNumber(); - StackNode_t* new_node = stackNode_create(index); - CHECK(new_node->freeIndex == index); - CHECK(new_node->next == disk_mng_CB->diskFreeIndexesInArray->top); - } +} - //array tests +TEST_CASE("test_stackNode_create") +{ + disk_mng_initialize(); + int index = generateRandomNumber(); + StackNode_t* new_node = stackNode_create(index); + CHECK(new_node->freeIndex == index); + CHECK(new_node->next == disk_mng_CB->diskFreeIndexesInArray->top); +} - TEST_CASE("array_firstInitialize") - { +//array tests - } +TEST_CASE("array_firstInitialize") +{ - TEST_CASE("array_normalInitialize") - { +} - } +TEST_CASE("array_normalInitialize") +{ - TEST_CASE("array_saveData") - { +} - } +TEST_CASE("array_saveData") +{ - TEST_CASE("test_array_deleteFromArray") - { - disk_mng_initialize(); - int index = generateRandomNumber(); - array_deleteFromArray(index); - CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == NULL); - } +} + +TEST_CASE("test_array_deleteFromArray") +{ + disk_mng_initialize(); + int index = generateRandomNumber(); + array_deleteFromArray(index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index]== NULL); +} + +TEST_CASE("test_arrayInfo_create") +{ + disk_mng_initialize(); + int * diskPointer = NULL; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange,nodeInfo); + CHECK(arrayInfo->mapid == 1); + CHECK(arrayInfo->diskPointer == NULL); + CHECK(arrayInfo->size == size); + CHECK(arrayInfo->range == mapRange); +} - TEST_CASE("test_arrayInfo_create") +TEST_CASE("test_array_addToArray") +{ + disk_mng_initialize(); + for (int i = 0; i < DISK_SIZE; i++) { - disk_mng_initialize(); int* diskPointer = NULL; int size = generateRandomNumber(); Point_t topLeft; @@ -669,42 +692,37 @@ extern "C" { bottomRight.x = generateRandomNumber(); bottomRight.y = generateRandomNumber(); MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int index = generateRandomNumber(); + int index = stack_pop(); AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); - CHECK(arrayInfo->mapid == 1); - CHECK(arrayInfo->diskPointer == NULL); - CHECK(arrayInfo->size == size); - CHECK(arrayInfo->range == mapRange); - } + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange,nodeInfo); + array_addToArray(arrayInfo, index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); - TEST_CASE("test_array_addToArray") - { - disk_mng_initialize(); - for (int i = 0; i < DISK_SIZE; i++) - { - int* diskPointer = NULL; - int size = generateRandomNumber(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int index = stack_pop(); - AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); - array_addToArray(arrayInfo, index); - CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); - - } } +} + +//range functions +TEST_CASE("test_mapRange_create") +{ + disk_mng_initialize(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + CHECK(mapRange->bottomRight.x == bottomRight.x); + CHECK(mapRange->bottomRight.y == bottomRight.y); + CHECK(mapRange->topLeft.x == topLeft.x); + CHECK(mapRange->topLeft.y == topLeft.y); +} - //range functions - TEST_CASE("test_mapRange_create") +TEST_CASE("test_disk_mng_addMap") +{ + disk_mng_initialize(); + for (int i = 0; i < 20; i++) { - disk_mng_initialize(); Point_t topLeft; topLeft.x = generateRandomNumber(); topLeft.y = generateRandomNumber(); @@ -712,17 +730,19 @@ extern "C" { bottomRight.x = generateRandomNumber(); bottomRight.y = generateRandomNumber(); MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - CHECK(mapRange->bottomRight.x == bottomRight.x); - CHECK(mapRange->bottomRight.y == bottomRight.y); - CHECK(mapRange->topLeft.x == topLeft.x); - CHECK(mapRange->topLeft.y == topLeft.y); + int size = generateRandomNumber(); + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); + disk_mng_addMap(mapRange, size, map); + } - TEST_CASE("test_disk_mng_addMap") - { - disk_mng_initialize(); - for (int i = 0; i < 20; i++) - { +} + +TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { + disk_mng_initialize(); + SUBCASE("Delete a single map when disk is full") { + // Add maps until the disk is full + for (int i = 0; i < 5; i++) { Point_t topLeft; topLeft.x = generateRandomNumber(); topLeft.y = generateRandomNumber(); @@ -732,261 +752,125 @@ extern "C" { MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); int size = generateRandomNumber(); int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); - + disk_mng_addMap(mapRange, size, map); // Add maps to the disk } + // Verify that the disk is full and needs deletion + //REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); - } - - TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { - disk_mng_initialize(); - SUBCASE("Delete a single map when disk is full") { - // Add maps until the disk is full - for (int i = 0; i < 5; i++) { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); // Add maps to the disk - } - // Verify that the disk is full and needs deletion - //REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); - - // Perform deletion - int sizeToFree = generateRandomNumber(); // Random size to free - disk_mng_delete(sizeToFree); + // Perform deletion + int sizeToFree = generateRandomNumber(); // Random size to free + disk_mng_delete(sizeToFree); - // Ensure that space has been freed - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); - - } - - } + // Ensure that space has been freed + REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); - TEST_CASE("test_arrayInLoaded_initialize") - { - arrayInLoaded_initialize(); - CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); - for (int i = 0; i < CACHE_SIZE; i++) { - CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); - } } - TEST_CASE("arrayInLoaded_create") { - int mapId = generateRandomNumber(); - int index = generateRandomNumber(); - DiskMapsInLoadedToCache_t* obj = arrayInLoaded_create(mapId, index); - - CHECK(obj != NULL); - CHECK(obj->mapId == mapId); - CHECK(obj->index == index); +} +TEST_CASE("test_arrayInLoaded_initialize") +{ + arrayInLoaded_initialize(); + CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); + for (int i = 0; i < CACHE_SIZE; i++) { + CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); } - TEST_CASE("test_disk_mng_isTheMapInRange") { - - disk_mng_initialize(); - - int x1 = generateRandomNumber(100); - int y1 = generateRandomNumber(100); - int x2 = generateRandomNumber(200, x1); - int y2 = generateRandomNumber(200, y1); - Point_t cacheTopLeft = { x1, y1 }; - Point_t cacheBottomRight = { x2, y2 }; - //MapRange_t* rangeFromCache = mapRange_create(cacheBottomRight, cacheTopLeft); - - int x3 = generateRandomNumber(100); - int y3 = generateRandomNumber(100); - int x4 = generateRandomNumber(200, x3); - int y4 = generateRandomNumber(200, y3); - Point_t rangeTopLeft = { x3, y3 }; - Point_t rangeBottomRight = { x4, y4 }; - //MapRange_t* range = mapRange_create(rangeBottomRight, rangeTopLeft); - MapRange_t* range = mapRange_create({ 224,140 }, { 148,160 }); - MapRange_t* rangeFromCache = mapRange_create({ 250,130 }, { 170,170 }); - - printMapRange("Range From Cache", rangeFromCache); - printMapRange("Range To Check", range); - - bool result = disk_mng_isTheMapInRange(rangeFromCache, range); - - bool expected = ( - - ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || - (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || - (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) - ); - printf("Result: %s\n", result ? "true" : "false"); - printf("Expected: %s\n", expected ? "true" : "false"); - CHECK(result == expected); - } - - TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { - disk_mng_initialize(); +} - for (int i = 0; i < CACHE_SIZE; i++) { - int mapId = generateRandomNumber(); - int index = generateRandomNumber(); +TEST_CASE("arrayInLoaded_create") { + int mapId = generateRandomNumber(); + int index = generateRandomNumber(); + DiskMapsInLoadedToCache_t* obj = arrayInLoaded_create(mapId, index); - DiskMapsInLoadedToCache_t* map = arrayInLoaded_create(mapId, index); - disk_mng_CB->disk_MapsInLoadedToCache[i] = map; - } + CHECK(obj != NULL); + CHECK(obj->mapId == mapId); + CHECK(obj->index == index); +} +TEST_CASE("test_disk_mng_isTheMapInRange") { + + disk_mng_initialize(); + + int x1 = generateRandomNumber(100); + int y1 = generateRandomNumber(100); + int x2 = generateRandomNumber(200, x1); + int y2 = generateRandomNumber(200, y1); + Point_t cacheTopLeft = { x1, y1 }; + Point_t cacheBottomRight = { x2, y2 }; + //MapRange_t* rangeFromCache = mapRange_create(cacheBottomRight, cacheTopLeft); + + int x3 = generateRandomNumber(100); + int y3 = generateRandomNumber(100); + int x4 = generateRandomNumber(200, x3); + int y4 = generateRandomNumber(200, y3); + Point_t rangeTopLeft = { x3, y3 }; + Point_t rangeBottomRight = { x4, y4 }; + //MapRange_t* range = mapRange_create(rangeBottomRight, rangeTopLeft); + MapRange_t* range = mapRange_create({ 224,140 }, { 148,160 }); + MapRange_t* rangeFromCache = mapRange_create({250,130}, {170,170}); + + printMapRange("Range From Cache", rangeFromCache); + printMapRange("Range To Check", range); + + bool result = disk_mng_isTheMapInRange(rangeFromCache, range); + + bool expected = ( + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || + (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) + ); + printf("Result: %s\n", result ? "true" : "false"); + printf("Expected: %s\n", expected ? "true" : "false"); + CHECK(result == expected); +} - int testMapId = disk_mng_CB->disk_MapsInLoadedToCache[0]->mapId; - int testIndex = disk_mng_CB->disk_MapsInLoadedToCache[0]->index; +TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { + disk_mng_initialize(); - int* diskPointer = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for diskPointer", "test_disk_mng_loadMapFromDiskToCache");; - int size = generateRandomNumber(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + for (int i = 0; i < CACHE_SIZE; i++) { + int mapId = generateRandomNumber(); int index = generateRandomNumber(); - AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - - disk_mng_CB->arrayForAllMApsInformation[testIndex] = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); - disk_mng_CB->arrayForAllMApsInformation[testIndex]->mapid = testMapId; - - int offset = generateRandomNumber(); - int length = generateRandomNumber(); - int freeAddress = generateRandomNumber(); - - bool result = disk_mng_loadMapFromDiskToCache(testMapId, offset, length, &freeAddress); - // Check results - CHECK(result == true); - - } - //TEST_CASE("test_disk_mng_getMapsIdsInRange") { - // disk_mng_initialize(); - // - // for (int i = 0; i < 20; i++) - // { - // Point_t topLeft; - // topLeft.x = generateRandomNumber(); - // topLeft.y = generateRandomNumber(); - // Point_t bottomRight; - // bottomRight.x = generateRandomNumber(); - // bottomRight.y = generateRandomNumber(); - // MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - // int size = generateRandomNumber(); - // int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - // disk_mng_addMap(mapRange, size, map); - // - // } - // Point_t topLeft; - // topLeft.x = generateRandomNumber(); - // topLeft.y = generateRandomNumber(); - // Point_t bottomRight; - // bottomRight.x = generateRandomNumber(); - // bottomRight.y = generateRandomNumber(); - // MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - // - // ArrayInfo_t** arrayOfMapsInRange = (ArrayInfo_t**)allocate_memory(CACHE_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for arrayOfMapsInRange ", "test_disk_mng_getMapsIdsInRange"); - // - // int count = disk_mng_getMapsIdsInRange(mapRange, arrayOfMapsInRange, CACHE_SIZE);} - -TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { - - SUBCASE("check the first initialize") { - disk_mng_initialize(); - int expectedAddressValue = 1; - int loadedValue = 0; - - int startAddress = 0; - int howManyToLoad = sizeof(int); - - disk_loadDataForInitializeDataStructers(&loadedValue, &startAddress, &howManyToLoad); - - CHECK(loadedValue == expectedAddressValue); + DiskMapsInLoadedToCache_t* map = arrayInLoaded_create(mapId, index); + disk_mng_CB->disk_MapsInLoadedToCache[i] = map; } - SUBCASE("check the normal initilaize") - { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); - - disk_mng_saveData(); - - int stackSize; - int startAddressForStackSize=4; - int lengthStackSize = sizeof(int); - disk_loadDataForInitializeDataStructers(&stackSize, &startAddressForStackSize, &lengthStackSize); - CHECK(stackSize == disk_mng_CB->diskFreeIndexesInArray->size); - - int avlSize; - int startAddressForAVL = 8; - int lengthAVLSize = sizeof(int); - disk_loadDataForInitializeDataStructers(&avlSize, &startAddressForAVL, &lengthAVLSize); - CHECK(avlSize == disk_mng_CB->disk_SortByMapSize->totalElements); - - int avllruCounter; - int startAddressForAVLLruCounter = 12; - int lengthAVLLruCounter = sizeof(int); - disk_loadDataForInitializeDataStructers(&avllruCounter, &startAddressForAVLLruCounter, &lengthAVLLruCounter); - CHECK(avllruCounter == disk_mng_CB->disk_SortByMapSize->lruCounter); - - int mapIdIndex; - int startAddressFormapIdIndex = 16; - int lengthmapIdIndex = sizeof(int); - disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); - CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); - - - //DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); - //int startAddressForStack = 20; - //int lengthStack = sizeof(StackNode_t) * stackSize; - //printf(" %d\n\n", lengthStack); - - //disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); - //printf(" %d\n\n", lengthStack); - - //CHECK(disk_mng_CB->diskFreeIndexesInArray->top == stackForTest->top); - //printf(" %d\n\n",lengthStack); - //ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*)*DISK_SIZE, "Failed to allocate memory for array ", "test array load"); - //int startAddressForArray = 20 + lengthStack; - //int lengthForArray = DISK_SIZE * sizeof(ArrayInfo_t*); - //disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); - //for (int i = 0; i < DISK_SIZE; i++) - //{ - // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); - // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); - - //} - } + int testMapId = disk_mng_CB->disk_MapsInLoadedToCache[0]->mapId; + int testIndex= disk_mng_CB->disk_MapsInLoadedToCache[0]->index; + int* diskPointer = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for diskPointer", "test_disk_mng_loadMapFromDiskToCache");; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + disk_mng_CB->arrayForAllMApsInformation[testIndex] = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); + disk_mng_CB->arrayForAllMApsInformation[testIndex]->mapid = testMapId; + int offset = generateRandomNumber(); + int length = generateRandomNumber(); + int freeAddress = generateRandomNumber(); + bool result = disk_mng_loadMapFromDiskToCache(testMapId, offset, length, &freeAddress); -} + // Check results + CHECK(result == true); +} \ No newline at end of file From 170ff4cf7f30006946acf29047b1922a5bc8e6ae Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 9 Sep 2024 10:59:13 +0300 Subject: [PATCH 27/32] add changes in doctest file --- Storage/errors.log.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 71e1288..bdbd9fa 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -508,3 +508,29 @@ disk_mng_checkDataStructures_mapSize: Error: Error worng size variable. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. From 5d08973cf3541a56d20a3481186fa415dcd73c0b Mon Sep 17 00:00:00 2001 From: shifi325 Date: Mon, 9 Sep 2024 11:02:05 +0300 Subject: [PATCH 28/32] fix changes --- Storage/errors.log.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index bdbd9fa..32c6ae0 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -534,3 +534,11 @@ disk_mng_checkDataStructures_range: Error: Error worng map range. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. From c177be99ef466e699e2b59ecf8fa3f5580ae5c1c Mon Sep 17 00:00:00 2001 From: shifi325 Date: Tue, 10 Sep 2024 10:07:05 +0300 Subject: [PATCH 29/32] add test for stack-save data --- Storage/Disk_Mng_Master.c | 36 +- Storage/Doctest.cpp | 59 +- .../Doctest.cpp | 995 ++++++++++++ Storage/errors.log.txt | 1418 +++++++++++++++++ 4 files changed, 2462 insertions(+), 46 deletions(-) create mode 100644 Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index b2afa54..872b171 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -8,7 +8,7 @@ #include Disk_Management_CB_t* disk_mng_CB; -int startSructers = 20; +int startSructers = 5 * sizeof(int); void disk_mng_initialize_CB() { disk_mng_CB = (Disk_Management_CB_t*)allocate_memory(sizeof(Disk_Management_CB_t), "Failed to allocate memory for disk control block", "disk_mng_initialize_CB"); @@ -45,7 +45,7 @@ void disk_mng_saveData() stack_saveData(); array_saveData(); avlTree_saveData(); - int startAdress = 16; + int startAdress = 4*sizeof(int); int howManyToLoad = sizeof(int); //load the fifth address in disk with mapIdIndex disk_saveDataFromStructersToDisk(&disk_mng_CB->mapIdIndex, &startAdress, &howManyToLoad); @@ -69,7 +69,7 @@ void disk_mng_normalInitialize() array_normalInitialize(); avlTree_normalInitialize(); int mapIdIndex = 0;//stack size - int startAdress = 16; + int startAdress = 4 * sizeof(int);; int howManyToLoad = sizeof(int); //load the fifth address in disk with mapIdIndex disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAdress, &howManyToLoad); @@ -95,7 +95,7 @@ DiskMapsInLoadedToCache_t* arrayInLoaded_create(int mapId, int index) //initialize on the first time we turn o the computer the stack will initialize with all the indexes. void stack_firstInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t)*DISK_SIZE, "Failed to allocate memory for stack ", "stack_firstInitialize"); disk_mng_CB->diskFreeIndexesInArray->top = NULL; disk_mng_CB->diskFreeIndexesInArray->size = 0; for (size_t i = 0; i < DISK_SIZE; i++) @@ -105,13 +105,13 @@ void stack_firstInitialize() { } void stack_normalInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t)*DISK_SIZE, "Failed to allocate memory for stack ", "stack_normalInitialize"); int size = 0;//stack size - int startAdress = 4; + int startAdress = sizeof(int);; int howManyToLoad = sizeof(int); //load the second address in disk with stack size disk_loadDataForInitializeDataStructers(&size, &startAdress, &howManyToLoad); - howManyToLoad = size * sizeof(int); + howManyToLoad = size * sizeof(StackNode_t*); //load all the data from stack disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); @@ -119,12 +119,12 @@ void stack_normalInitialize() { void stack_saveData() { - int startAdress = 4; + int startAdress = sizeof(int);; int howManyToLoad = sizeof(int); ////save size of stack in the second address in the disk disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray->size), &startAdress, &howManyToLoad); - howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t); + howManyToLoad = disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); //save all the data from stack disk_saveDataFromStructersToDisk(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); } @@ -180,7 +180,7 @@ void array_firstInitialize() { } void array_normalInitialize() { disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); + startSructers =5* sizeof(int)+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t*); //load all the data from array disk_loadDataForInitializeDataStructers(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); @@ -188,7 +188,7 @@ void array_normalInitialize() { void array_saveData() { - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int); + startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); int howManyToLoad = DISK_SIZE * (sizeof(ArrayInfo_t*)); //save all the data from array disk_saveDataFromStructersToDisk(&(disk_mng_CB->arrayForAllMApsInformation), &startSructers, &howManyToLoad); @@ -383,20 +383,20 @@ void avlTree_firstInitialize() { void avlTree_normalInitialize() { - disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t**)allocate_memory(sizeof(DiskSortByMapSize_t*), "Failed to allocate memory for stack ", "avlTree_normalInitialize"); + disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for stack ", "avlTree_normalInitialize"); int length = 0; - int startAdress = 8; + int startAdress = 2 * sizeof(int);; int howManyToLoad = sizeof(int); //load the third address in disk with avlTree size disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); int lru = 0; - startAdress = 12; + startAdress = 3*sizeof(int); howManyToLoad = sizeof(int); //load the forth address in disk with avlTree lru disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t*); + startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * (sizeof(ArrayInfo_t*)); howManyToLoad = length * sizeof(DiskSortByMapSize_t*); //load all the data from avlTree disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); @@ -404,18 +404,18 @@ void avlTree_normalInitialize() void avlTree_saveData() { - int startAdress = 8; + int startAdress = 2* sizeof(int);; int howManyToLoad = sizeof(int); ////save size of avlTree in the third address in the disk disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->totalElements), &startAdress, &howManyToLoad); - startAdress = 12; + startAdress = 3* sizeof(int);; howManyToLoad = sizeof(int); ////save lruCounter of avlTree in the forth address in the disk disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize->lruCounter), &startAdress, &howManyToLoad); - startSructers += disk_mng_CB->diskFreeIndexesInArray->size * sizeof(int) + DISK_SIZE * sizeof(ArrayInfo_t*); + startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * (sizeof(ArrayInfo_t*)); howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); //save all the data from stack disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 90bed25..85f0b12 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -683,6 +683,7 @@ TEST_CASE("test_array_addToArray") { disk_mng_initialize(); for (int i = 0; i < DISK_SIZE; i++) + for (int i = 0; i < DISK_SIZE; i++) { int* diskPointer = NULL; int size = generateRandomNumber(); @@ -935,60 +936,62 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { disk_mng_saveData(); int stackSize; - int startAddressForStackSize = 4; + int startAddressForStackSize = sizeof(int); int lengthStackSize = sizeof(int); disk_loadDataForInitializeDataStructers(&stackSize, &startAddressForStackSize, &lengthStackSize); CHECK(stackSize == disk_mng_CB->diskFreeIndexesInArray->size); int avlSize; - int startAddressForAVL = 8; + int startAddressForAVL = 2*sizeof(int); int lengthAVLSize = sizeof(int); disk_loadDataForInitializeDataStructers(&avlSize, &startAddressForAVL, &lengthAVLSize); CHECK(avlSize == disk_mng_CB->disk_SortByMapSize->totalElements); int avllruCounter; - int startAddressForAVLLruCounter = 12; + int startAddressForAVLLruCounter = 3* sizeof(int);; int lengthAVLLruCounter = sizeof(int); disk_loadDataForInitializeDataStructers(&avllruCounter, &startAddressForAVLLruCounter, &lengthAVLLruCounter); CHECK(avllruCounter == disk_mng_CB->disk_SortByMapSize->lruCounter); int mapIdIndex; - int startAddressFormapIdIndex = 16; + int startAddressFormapIdIndex = 4* sizeof(int);; int lengthmapIdIndex = sizeof(int); disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); - //DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); - //int startAddressForStack = 20; - //int lengthStack = sizeof(StackNode_t) * stackSize; - //printf(" %d\n\n", lengthStack); - - //disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); - //printf(" %d\n\n", lengthStack); - - //CHECK(disk_mng_CB->diskFreeIndexesInArray->top == stackForTest->top); - //printf(" %d\n\n",lengthStack); - //ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*)*DISK_SIZE, "Failed to allocate memory for array ", "test array load"); - //int startAddressForArray = 20 + lengthStack; - //int lengthForArray = DISK_SIZE * sizeof(ArrayInfo_t*); - //disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); - //for (int i = 0; i < DISK_SIZE; i++) - //{ - // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); - // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); - // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); - - //} + DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + int startAddressForStack = 5* sizeof(int); + int lengthStack = sizeof(StackNode_t*) * stackSize; + printf(" %d\n\n", lengthStack); + disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); + printf(" %d\n\n", lengthStack); - } + CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); + ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); + int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); + int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); + disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); + printf("-------------------"); + for (int i = 96; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) { + ArrayInfo_t* a = disk_mng_CB->arrayForAllMApsInformation[i]; + ArrayInfo_t* a2= arrayForTest[i]; + printf(" %d\n\n", a2->mapid); + CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); + CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); + } + } + } } diff --git a/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp b/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp new file mode 100644 index 0000000..632b798 --- /dev/null +++ b/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp @@ -0,0 +1,995 @@ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "doctest.h" +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "Disk_Mng_Master.h" +#include "Disk_Mng_Master_API.h" + +} +struct GlobalSetup { + GlobalSetup() { + srand(time(0)); + } +}; +GlobalSetup globalSetup; + +int generateRandomNumber(int lower=0,int upper = DISK_SIZE) { + return (rand() % (upper - lower + 1)) + lower; +} +void printPoint(const char* label, const Point_t& point) { + printf("%s: x = %d, y = %d\n", label, point.x, point.y); +} + +// Function to print map ranges for debugging +void printMapRange(const char* label, const MapRange_t* range) { + printf("%s: TopLeft (x = %d, y = %d), BottomRight (x = %d, y = %d)\n", + label, range->topLeft.x, range->topLeft.y, range->bottomRight.x, range->bottomRight.y); +} +void printTreeDetails(AVLNode_t* node) { + if (node == NULL) { + return; + } + + // Print current node details + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); + printf("Height: %d\n\n", node->height); + + // Recurse on the left and right subtrees + printTreeDetails(node->left); + printTreeDetails(node->right); +} + +void printNode(AVLNode_t* node) { + if (node == NULL) { + printf("Node is NULL\n"); + return; + } + printf("Node details:\n"); + printf("Map Size: %d\n", node->avlNodeInfo->mapSize); + + printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); + printf("LRU: %d\n", node->avlNodeInfo->lru); +} +void printTree(AVLNode_t* root) { + if (root == nullptr) { + return; + } + + // Queue for level order traversal + std::queue q; + q.push(root); + + // Vector to store levels of the tree + std::vector> levels; + + // Traverse the tree level by level + while (!q.empty()) { + int nodeCount = q.size(); + std::vector currentLevel; + + while (nodeCount > 0) { + AVLNode_t* node = q.front(); + q.pop(); + currentLevel.push_back(node); + + if (node != nullptr) { + q.push(node->left); + q.push(node->right); + } + nodeCount--; + } + + // Add level only if there are nodes at this level + if (std::any_of(currentLevel.begin(), currentLevel.end(), [](AVLNode_t* n) { return n != nullptr; })) { + levels.push_back(currentLevel); + } + } + + int maxLevel = levels.size(); + int width = 1 << (maxLevel - 1); // Maximum width of the tree at the last level + + for (int i = 0; i < maxLevel; ++i) { + std::vector currentLevel = levels[i]; + int numNodes = currentLevel.size(); + int spacing = width / (numNodes + 1); + int offset = spacing / 2; + + // Print leading spaces + std::cout << std::setw(offset) << ""; + + // Print nodes at current level + for (AVLNode_t* node : currentLevel) { + if (node == nullptr) { + std::cout << std::setw(width) << ""; + } + else { + std::cout << std::setw(width) << node->avlNodeInfo->mapSize; + } + std::cout << std::setw(offset) << ""; + } + std::cout << std::endl; + + // Print level separators + if (i < maxLevel - 1) { + std::cout << std::setw(width / 2) << ""; + for (AVLNode_t* node : currentLevel) { + if (node == nullptr) { + std::cout << std::setw(width) << ""; + } + else { + std::cout << std::setw(width / 2) << (node->left != nullptr ? "/" : " "); + std::cout << std::setw(width / 2) << (node->right != nullptr ? "\\" : " "); + } + std::cout << std::setw(width / 2) << ""; + } + std::cout << std::endl; + } + } +} +int index, popValue,value; + +//mock functions + +int* disk_addMap(int* map) +{ + //int num = generateRandomNumber(10000000); + //if (num % 2 == 0) + //{ + int* map1 = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for disk control block", "disk_addMap"); + return map1; + //} + //return NULL; +} + +//the function get pointer to map in the disk and delete this map from disk +bool disk_deleteMap(int* diskPointer) +{ + return true; +} +bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) +{ + return true; +} +void cache_deleteMap(int mapId) +{ +} + +void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad) +{ + int start = *(int*)startAddress; + int sizeToLoad = *(int*)howManyToLoad; + + memcpy(destination, (char*)disk_mng_CB->mockDisk + start, sizeToLoad); +} + +void disk_saveDataFromStructersToDisk(void* source, void* startAddress, void* howManyToLoad) +{ + int start = *(int*)startAddress; + int sizeToSave = *(int*)howManyToLoad; + + memcpy((char*)disk_mng_CB->mockDisk + start, source, sizeToSave); +} +bool disk_isThereEnoughSpace(int mapSize) +{ + //int num = generateRandomNumber(10000000); + //if (num % 2 == 0) + //{ + // return true; + //} + //return false; + return true; + +} + +TEST_CASE("test_disk_mng_initialize_CB") +{ + disk_mng_initialize_CB(); + CHECK(disk_mng_CB != NULL); +} + +TEST_CASE("test_disk_mng_initialize") +{ + disk_mng_initialize(); +} + +//avlNode tests + +TEST_CASE("test_avlNodeInfo_create") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + + CHECK(avlNodeInfo->mapSize == mapSize); + CHECK(avlNodeInfo->arrayIndex == indexArray); + CHECK(avlNodeInfo->lru == 1); +} + +TEST_CASE("test_avlNodeInfo_delete") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + avlNodeInfo_delete(avlNodeInfo); +} + +TEST_CASE("test_avlNode_create") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + + CHECK(avlNode->avlNodeInfo == avlNodeInfo); + CHECK(avlNode->height == 1); + CHECK(avlNode->left == NULL); + CHECK(avlNode->right == NULL); +} + +TEST_CASE("test_avlNode_delete") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + avlNode_delete(avlNode); +} + +TEST_CASE("test_avlNode_height") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode = avlNode_create(avlNodeInfo); + + CHECK(avlNode->height == avlNode_height(avlNode)); +} + +//avlTree tests + +TEST_CASE("avlTree_firstInitialize") +{ + +} + +TEST_CASE("avlTree_normalInitialize") +{ + +} + +TEST_CASE("avlTree_saveData") +{ + +} + +TEST_CASE("test_avlTree_rightRotate") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + + avlNode1->left = avlNode2; + avlNode2->left = avlNode3; + + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + + AVLNode_t* newRoot = avlTree_rightRotate(avlNode1); + + CHECK(newRoot == avlNode2); + CHECK(newRoot->right == avlNode1); + CHECK(newRoot->left == avlNode3); + CHECK(avlNode1->left == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); +} + +TEST_CASE("test_avlTree_leftRotate") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); + + AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); + + AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); + AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); + + + + avlNode1->right = avlNode2; + avlNode2->right = avlNode3; + + avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; + avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; + + AVLNode_t* newRoot = avlTree_leftRotate(avlNode1); + + CHECK(newRoot == avlNode2); + CHECK(newRoot->left == avlNode1); + CHECK(newRoot->right == avlNode3); + CHECK(avlNode1->right == nullptr); + CHECK(avlNode1->height == 1); + CHECK(newRoot->height == 2); +} + +TEST_CASE("avlTree_getBalance") +{ + disk_mng_initialize(); + + int mapSize = generateRandomNumber(); + int indexArray = generateRandomNumber(); + + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, indexArray); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize, indexArray); + + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* root = avlNode_create(info3); + + SUBCASE("Node is NULL") { + CHECK(avlTree_getBalance(nullptr) == 0); + } + + SUBCASE("Balance factor of a node with children having different heights") { + root->left = node1; + root->right = node2; + node1->height = 3; + node2->height = 1; + root->height = 4; + CHECK(avlTree_getBalance(root) == 2); + } + + SUBCASE("Balance factor of a node with both children having the same height") { + root->left = node1; + root->right = node2; + node1->height = 2; + node2->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 0); + } + + SUBCASE("Balance factor of a node with one child") { + root->left = node1; + root->right = nullptr; + node1->height = 2; + root->height = 3; + CHECK(avlTree_getBalance(root) == 2); + } +} +TEST_CASE("test_avlTree_minValueNode") { + disk_mng_initialize(); + + int mapSize1 = generateRandomNumber(); + int indexArray1 = generateRandomNumber(); + + int mapSize2 = generateRandomNumber(); + int indexArray2 = generateRandomNumber(); + + int mapSize3 = generateRandomNumber(); + int indexArray3 = generateRandomNumber(); + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize1, indexArray1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize2, indexArray2); + AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize3, indexArray3); + + AVLNode_t* node1 = avlNode_create(info1); + AVLNode_t* node2 = avlNode_create(info2); + AVLNode_t* node3 = avlNode_create(info3); + + SUBCASE("Node with no left child") { + CHECK(avlTree_minValueNode(node1) == node1); + } + node1->left = node2; + node2->left = node3; + + SUBCASE("Node with left child") { + CHECK(avlTree_minValueNode(node1) == node3); + } +} +TEST_CASE("test_avlTree_insert") { + disk_mng_initialize(); + + SUBCASE("Insert into an empty tree") { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 1); + } + + SUBCASE("Insert nodes and check balancing") { + + for (int i = 0; i < 7; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + } + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 7); + } + + SUBCASE("Insert duplicate mapSize") { + int mapSize = generateRandomNumber(); + int arrayIndex1 = generateRandomNumber(); + int arrayIndex2 = generateRandomNumber(); + + AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); + AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); + + avlTree_insertElement(info1); + avlTree_insertElement(info2); + + CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); + CHECK(disk_mng_CB->disk_SortByMapSize->root->left == nullptr); + + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); + CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); + CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 2); + } +} +TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { + disk_mng_initialize(); + + SUBCASE("Find eligible node for deletion") { + // Insert nodes into the AVL tree with different LRU values + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + } + + SUBCASE("All nodes are eligible for deletion") { + // Insert nodes with LRU values such that all are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = generateRandomNumber(); + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); + + } + + SUBCASE("No node is eligible for deletion") { + // Insert nodes with LRU values such that none are eligible for deletion + for (int i = 0; i < 5; ++i) { + int mapSize = generateRandomNumber(); + int arrayIndex = generateRandomNumber(); + int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; + + AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); + avlTree_insertElement(info); + } + + AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + + CHECK(result != nullptr); + CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); + + + } +} +TEST_CASE("test_avlTree_deleteNode") { + disk_mng_initialize(); + + for (int i = 0; i < 10; i++) + { + AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); + avlTree_insertElement(info1); + } + + AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); + if (nodeToDelete!=NULL) + { + disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); + } +} + + +//stack tests + +TEST_CASE("test_stack_firstInitialize") +{ + disk_mng_initialize(); + for (int i = 0; i < DISK_SIZE; i++) + { + + stack_push(i); + } + + for (int i =DISK_SIZE-1; i >0; i--) + { + CHECK( stack_pop() == i); + } +} + + +TEST_CASE("test_stack_normalInitialize") +{ + disk_mng_initialize(); +} + +TEST_CASE("stack_saveData") +{ + +} + +TEST_CASE("test_stack_push") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + index = generateRandomNumber(); + stack_push(index); + popValue = stack_pop(); + CHECK(popValue == index); + } + +} +TEST_CASE("test_stack_pop") +{ + disk_mng_initialize(); + for (size_t i = 4; i < 0; i++) + { + value = stack_pop(); + CHECK(value !=stack_top()); + } +} +TEST_CASE("test_stack_top") +{ + disk_mng_initialize(); + for (size_t i = DISK_SIZE-1; i < 0; i--) + { + value = stack_top(); + stack_pop(); + CHECK(value == i); + } +} +TEST_CASE("test_stack_is_empty") +{ + disk_mng_initialize(); + for (size_t i = 0; i < DISK_SIZE; i++) + { + stack_pop(); + } + CHECK(stack_is_empty()); + +} + +TEST_CASE("test_stackNode_create") +{ + disk_mng_initialize(); + int index = generateRandomNumber(); + StackNode_t* new_node = stackNode_create(index); + CHECK(new_node->freeIndex == index); + CHECK(new_node->next == disk_mng_CB->diskFreeIndexesInArray->top); +} + +//array tests + +TEST_CASE("array_firstInitialize") +{ + +} + +TEST_CASE("array_normalInitialize") +{ + +} + +TEST_CASE("array_saveData") +{ + +} + +TEST_CASE("test_array_deleteFromArray") +{ + disk_mng_initialize(); + int index = generateRandomNumber(); + array_deleteFromArray(index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index]== NULL); +} + +TEST_CASE("test_arrayInfo_create") +{ + disk_mng_initialize(); + int * diskPointer = NULL; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange,nodeInfo); + CHECK(arrayInfo->mapid == 1); + CHECK(arrayInfo->diskPointer == NULL); + CHECK(arrayInfo->size == size); + CHECK(arrayInfo->range == mapRange); +} + +TEST_CASE("test_array_addToArray") +{ + disk_mng_initialize(); + for (int i = 0; i < DISK_SIZE; i++) + for (int i = 0; i < DISK_SIZE; i++) + { + int* diskPointer = NULL; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = stack_pop(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange,nodeInfo); + array_addToArray(arrayInfo, index); + CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); + + } +} + +//range functions +TEST_CASE("test_mapRange_create") +{ + disk_mng_initialize(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + CHECK(mapRange->bottomRight.x == bottomRight.x); + CHECK(mapRange->bottomRight.y == bottomRight.y); + CHECK(mapRange->topLeft.x == topLeft.x); + CHECK(mapRange->topLeft.y == topLeft.y); +} + +TEST_CASE("test_disk_mng_addMap") +{ + disk_mng_initialize(); + for (int i = 0; i < 20; i++) + { + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int size = generateRandomNumber(); + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); + disk_mng_addMap(mapRange, size, map); + + } + +} + +TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { + disk_mng_initialize(); + SUBCASE("Delete a single map when disk is full") { + // Add maps until the disk is full + for (int i = 0; i < 5; i++) { + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int size = generateRandomNumber(); + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); + disk_mng_addMap(mapRange, size, map); // Add maps to the disk + } + // Verify that the disk is full and needs deletion + //REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); + + // Perform deletion + int sizeToFree = generateRandomNumber(); // Random size to free + disk_mng_delete(sizeToFree); + + // Ensure that space has been freed + REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); + + } + +} + +TEST_CASE("test_arrayInLoaded_initialize") +{ + arrayInLoaded_initialize(); + CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); + for (int i = 0; i < CACHE_SIZE; i++) { + CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); + } +} + +TEST_CASE("arrayInLoaded_create") { + int mapId = generateRandomNumber(); + int index = generateRandomNumber(); + DiskMapsInLoadedToCache_t* obj = arrayInLoaded_create(mapId, index); + + CHECK(obj != NULL); + CHECK(obj->mapId == mapId); + CHECK(obj->index == index); + +} +TEST_CASE("test_disk_mng_isTheMapInRange") { + + disk_mng_initialize(); + + int x1 = generateRandomNumber(100); + int y1 = generateRandomNumber(100); + int x2 = generateRandomNumber(200, x1); + int y2 = generateRandomNumber(200, y1); + Point_t cacheTopLeft = { x1, y1 }; + Point_t cacheBottomRight = { x2, y2 }; + //MapRange_t* rangeFromCache = mapRange_create(cacheBottomRight, cacheTopLeft); + + int x3 = generateRandomNumber(100); + int y3 = generateRandomNumber(100); + int x4 = generateRandomNumber(200, x3); + int y4 = generateRandomNumber(200, y3); + Point_t rangeTopLeft = { x3, y3 }; + Point_t rangeBottomRight = { x4, y4 }; + //MapRange_t* range = mapRange_create(rangeBottomRight, rangeTopLeft); + MapRange_t* range = mapRange_create({ 224,140 }, { 148,160 }); + MapRange_t* rangeFromCache = mapRange_create({250,130}, {170,170}); + + printMapRange("Range From Cache", rangeFromCache); + printMapRange("Range To Check", range); + + bool result = disk_mng_isTheMapInRange(rangeFromCache, range); + + bool expected = ( + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || + + ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && + (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || + (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || + (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) + ); + printf("Result: %s\n", result ? "true" : "false"); + printf("Expected: %s\n", expected ? "true" : "false"); + CHECK(result == expected); +} + +TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { + disk_mng_initialize(); + + for (int i = 0; i < CACHE_SIZE; i++) { + int mapId = generateRandomNumber(); + int index = generateRandomNumber(); + + DiskMapsInLoadedToCache_t* map = arrayInLoaded_create(mapId, index); + disk_mng_CB->disk_MapsInLoadedToCache[i] = map; + } + + + int testMapId = disk_mng_CB->disk_MapsInLoadedToCache[0]->mapId; + int testIndex= disk_mng_CB->disk_MapsInLoadedToCache[0]->index; + + int* diskPointer = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for diskPointer", "test_disk_mng_loadMapFromDiskToCache");; + int size = generateRandomNumber(); + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int index = generateRandomNumber(); + AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); + + disk_mng_CB->arrayForAllMApsInformation[testIndex] = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); + disk_mng_CB->arrayForAllMApsInformation[testIndex]->mapid = testMapId; + + int offset = generateRandomNumber(); + int length = generateRandomNumber(); + int freeAddress = generateRandomNumber(); + + bool result = disk_mng_loadMapFromDiskToCache(testMapId, offset, length, &freeAddress); + + // Check results + CHECK(result == true); +} +//TEST_CASE("test_disk_mng_getMapsIdsInRange") { +// disk_mng_initialize(); +// +// for (int i = 0; i < 20; i++) +// { +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// int size = generateRandomNumber(); +// int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); +// disk_mng_addMap(mapRange, size, map); +// +// } +// Point_t topLeft; +// topLeft.x = generateRandomNumber(); +// topLeft.y = generateRandomNumber(); +// Point_t bottomRight; +// bottomRight.x = generateRandomNumber(); +// bottomRight.y = generateRandomNumber(); +// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); +// +// ArrayInfo_t** arrayOfMapsInRange = (ArrayInfo_t**)allocate_memory(CACHE_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for arrayOfMapsInRange ", "test_disk_mng_getMapsIdsInRange"); +// +// int count = disk_mng_getMapsIdsInRange(mapRange, arrayOfMapsInRange, CACHE_SIZE); +//} + +TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { + + SUBCASE("check the first initialize") { + disk_mng_initialize(); + int expectedAddressValue = 1; + int loadedValue = 0; + + int startAddress = 0; + int howManyToLoad = sizeof(int); + + disk_loadDataForInitializeDataStructers(&loadedValue, &startAddress, &howManyToLoad); + + CHECK(loadedValue == expectedAddressValue); + } + SUBCASE("check the normal initilaize") + { + Point_t topLeft; + topLeft.x = generateRandomNumber(); + topLeft.y = generateRandomNumber(); + Point_t bottomRight; + bottomRight.x = generateRandomNumber(); + bottomRight.y = generateRandomNumber(); + MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); + int size = generateRandomNumber(); + int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); + disk_mng_addMap(mapRange, size, map); + + disk_mng_saveData(); + + int stackSize; + int startAddressForStackSize = sizeof(int); + int lengthStackSize = sizeof(int); + disk_loadDataForInitializeDataStructers(&stackSize, &startAddressForStackSize, &lengthStackSize); + CHECK(stackSize == disk_mng_CB->diskFreeIndexesInArray->size); + + int avlSize; + int startAddressForAVL = 2*sizeof(int); + int lengthAVLSize = sizeof(int); + disk_loadDataForInitializeDataStructers(&avlSize, &startAddressForAVL, &lengthAVLSize); + CHECK(avlSize == disk_mng_CB->disk_SortByMapSize->totalElements); + + int avllruCounter; + int startAddressForAVLLruCounter = 3* sizeof(int);; + int lengthAVLLruCounter = sizeof(int); + disk_loadDataForInitializeDataStructers(&avllruCounter, &startAddressForAVLLruCounter, &lengthAVLLruCounter); + CHECK(avllruCounter == disk_mng_CB->disk_SortByMapSize->lruCounter); + + int mapIdIndex; + int startAddressFormapIdIndex = 4* sizeof(int);; + int lengthmapIdIndex = sizeof(int); + disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); + CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); + + + DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + int startAddressForStack = 5* sizeof(int); + int lengthStack = sizeof(StackNode_t*) * stackSize; + printf(" %d\n\n", lengthStack); + + disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); + printf(" %d\n\n", lengthStack); + + CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); + + + ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); + int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); + int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); + disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); + printf("-------------------"); + + for (int i = 96; i < DISK_SIZE; i++) + { + if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) { + ArrayInfo_t* a = disk_mng_CB->arrayForAllMApsInformation[i]; + ArrayInfo_t* a2= arrayForTest[i]; + printf(" %d\n\n", a2->mapid); + CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); + CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); + //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); + } + } + } +} + diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 902ceaf..10475a5 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -569,3 +569,1421 @@ disk_mng_checkDataStructures_mapSize: Error: Error worng size variable. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. From c4dcdbf5a9313ffb7c029a00e2580fd9da340266 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Tue, 10 Sep 2024 10:31:24 +0300 Subject: [PATCH 30/32] add test for avl tree save data --- Storage/Disk_Mng_Master.c | 6 +- Storage/Doctest.cpp | 8 +- .../Doctest.cpp | 995 ------------------ Storage/errors.log.txt | 72 ++ 4 files changed, 81 insertions(+), 1000 deletions(-) delete mode 100644 Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 872b171..2d86917 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -383,7 +383,7 @@ void avlTree_firstInitialize() { void avlTree_normalInitialize() { - disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for stack ", "avlTree_normalInitialize"); + disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); int length = 0; int startAdress = 2 * sizeof(int);; int howManyToLoad = sizeof(int); @@ -397,7 +397,7 @@ void avlTree_normalInitialize() disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * (sizeof(ArrayInfo_t*)); - howManyToLoad = length * sizeof(DiskSortByMapSize_t*); + howManyToLoad = length * sizeof(AVLNode_t*); //load all the data from avlTree disk_loadDataForInitializeDataStructers(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); } @@ -416,7 +416,7 @@ void avlTree_saveData() startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * (sizeof(ArrayInfo_t*)); - howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(int); + howManyToLoad = disk_mng_CB->disk_SortByMapSize->totalElements * sizeof(AVLNode_t*); //save all the data from stack disk_saveDataFromStructersToDisk(&(disk_mng_CB->disk_SortByMapSize), &startSructers, &howManyToLoad); } diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 85f0b12..67f501c 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -971,7 +971,7 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); - ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); + ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_test"); int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); @@ -990,7 +990,11 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); } } - + DiskSortByMapSize_t* avlTreeForTest = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for avlTree ", "avlTree_test"); + int startAddressForAVLTree = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * sizeof(ArrayInfo_t*); + int lengthforAVLTree = avlSize * sizeof(AVLNode_t*); + disk_loadDataForInitializeDataStructers(&avlTreeForTest, &startAddressForAVL, &lengthforAVLTree); + CHECK(avlTreeForTest->root->avlNodeInfo->arrayIndex == disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->arrayIndex); } } diff --git a/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp b/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp deleted file mode 100644 index 632b798..0000000 --- a/Storage/enc_temp_folder/bad79efee345d3565a90a8a58987bba7/Doctest.cpp +++ /dev/null @@ -1,995 +0,0 @@ -#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include "doctest.h" -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" { -#include "Disk_Mng_Master.h" -#include "Disk_Mng_Master_API.h" - -} -struct GlobalSetup { - GlobalSetup() { - srand(time(0)); - } -}; -GlobalSetup globalSetup; - -int generateRandomNumber(int lower=0,int upper = DISK_SIZE) { - return (rand() % (upper - lower + 1)) + lower; -} -void printPoint(const char* label, const Point_t& point) { - printf("%s: x = %d, y = %d\n", label, point.x, point.y); -} - -// Function to print map ranges for debugging -void printMapRange(const char* label, const MapRange_t* range) { - printf("%s: TopLeft (x = %d, y = %d), BottomRight (x = %d, y = %d)\n", - label, range->topLeft.x, range->topLeft.y, range->bottomRight.x, range->bottomRight.y); -} -void printTreeDetails(AVLNode_t* node) { - if (node == NULL) { - return; - } - - // Print current node details - printf("Node details:\n"); - printf("Map Size: %d\n", node->avlNodeInfo->mapSize); - printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); - printf("LRU: %d\n", node->avlNodeInfo->lru); - printf("Height: %d\n\n", node->height); - - // Recurse on the left and right subtrees - printTreeDetails(node->left); - printTreeDetails(node->right); -} - -void printNode(AVLNode_t* node) { - if (node == NULL) { - printf("Node is NULL\n"); - return; - } - printf("Node details:\n"); - printf("Map Size: %d\n", node->avlNodeInfo->mapSize); - - printf("Array Index: %d\n", node->avlNodeInfo->arrayIndex); - printf("LRU: %d\n", node->avlNodeInfo->lru); -} -void printTree(AVLNode_t* root) { - if (root == nullptr) { - return; - } - - // Queue for level order traversal - std::queue q; - q.push(root); - - // Vector to store levels of the tree - std::vector> levels; - - // Traverse the tree level by level - while (!q.empty()) { - int nodeCount = q.size(); - std::vector currentLevel; - - while (nodeCount > 0) { - AVLNode_t* node = q.front(); - q.pop(); - currentLevel.push_back(node); - - if (node != nullptr) { - q.push(node->left); - q.push(node->right); - } - nodeCount--; - } - - // Add level only if there are nodes at this level - if (std::any_of(currentLevel.begin(), currentLevel.end(), [](AVLNode_t* n) { return n != nullptr; })) { - levels.push_back(currentLevel); - } - } - - int maxLevel = levels.size(); - int width = 1 << (maxLevel - 1); // Maximum width of the tree at the last level - - for (int i = 0; i < maxLevel; ++i) { - std::vector currentLevel = levels[i]; - int numNodes = currentLevel.size(); - int spacing = width / (numNodes + 1); - int offset = spacing / 2; - - // Print leading spaces - std::cout << std::setw(offset) << ""; - - // Print nodes at current level - for (AVLNode_t* node : currentLevel) { - if (node == nullptr) { - std::cout << std::setw(width) << ""; - } - else { - std::cout << std::setw(width) << node->avlNodeInfo->mapSize; - } - std::cout << std::setw(offset) << ""; - } - std::cout << std::endl; - - // Print level separators - if (i < maxLevel - 1) { - std::cout << std::setw(width / 2) << ""; - for (AVLNode_t* node : currentLevel) { - if (node == nullptr) { - std::cout << std::setw(width) << ""; - } - else { - std::cout << std::setw(width / 2) << (node->left != nullptr ? "/" : " "); - std::cout << std::setw(width / 2) << (node->right != nullptr ? "\\" : " "); - } - std::cout << std::setw(width / 2) << ""; - } - std::cout << std::endl; - } - } -} -int index, popValue,value; - -//mock functions - -int* disk_addMap(int* map) -{ - //int num = generateRandomNumber(10000000); - //if (num % 2 == 0) - //{ - int* map1 = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for disk control block", "disk_addMap"); - return map1; - //} - //return NULL; -} - -//the function get pointer to map in the disk and delete this map from disk -bool disk_deleteMap(int* diskPointer) -{ - return true; -} -bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress) -{ - return true; -} -void cache_deleteMap(int mapId) -{ -} - -void disk_loadDataForInitializeDataStructers(void* destination, void* startAddress, void* howManyToLoad) -{ - int start = *(int*)startAddress; - int sizeToLoad = *(int*)howManyToLoad; - - memcpy(destination, (char*)disk_mng_CB->mockDisk + start, sizeToLoad); -} - -void disk_saveDataFromStructersToDisk(void* source, void* startAddress, void* howManyToLoad) -{ - int start = *(int*)startAddress; - int sizeToSave = *(int*)howManyToLoad; - - memcpy((char*)disk_mng_CB->mockDisk + start, source, sizeToSave); -} -bool disk_isThereEnoughSpace(int mapSize) -{ - //int num = generateRandomNumber(10000000); - //if (num % 2 == 0) - //{ - // return true; - //} - //return false; - return true; - -} - -TEST_CASE("test_disk_mng_initialize_CB") -{ - disk_mng_initialize_CB(); - CHECK(disk_mng_CB != NULL); -} - -TEST_CASE("test_disk_mng_initialize") -{ - disk_mng_initialize(); -} - -//avlNode tests - -TEST_CASE("test_avlNodeInfo_create") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - - CHECK(avlNodeInfo->mapSize == mapSize); - CHECK(avlNodeInfo->arrayIndex == indexArray); - CHECK(avlNodeInfo->lru == 1); -} - -TEST_CASE("test_avlNodeInfo_delete") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - avlNodeInfo_delete(avlNodeInfo); -} - -TEST_CASE("test_avlNode_create") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - - CHECK(avlNode->avlNodeInfo == avlNodeInfo); - CHECK(avlNode->height == 1); - CHECK(avlNode->left == NULL); - CHECK(avlNode->right == NULL); -} - -TEST_CASE("test_avlNode_delete") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - avlNode_delete(avlNode); -} - -TEST_CASE("test_avlNode_height") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode = avlNode_create(avlNodeInfo); - - CHECK(avlNode->height == avlNode_height(avlNode)); -} - -//avlTree tests - -TEST_CASE("avlTree_firstInitialize") -{ - -} - -TEST_CASE("avlTree_normalInitialize") -{ - -} - -TEST_CASE("avlTree_saveData") -{ - -} - -TEST_CASE("test_avlTree_rightRotate") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); - - avlNode1->left = avlNode2; - avlNode2->left = avlNode3; - - avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; - avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; - - AVLNode_t* newRoot = avlTree_rightRotate(avlNode1); - - CHECK(newRoot == avlNode2); - CHECK(newRoot->right == avlNode1); - CHECK(newRoot->left == avlNode3); - CHECK(avlNode1->left == nullptr); - CHECK(avlNode1->height == 1); - CHECK(newRoot->height == 2); -} - -TEST_CASE("test_avlTree_leftRotate") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - AVLNodeInfo_t* avlNodeInfo1 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode1 = avlNode_create(avlNodeInfo1); - - AVLNodeInfo_t* avlNodeInfo2 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode2 = avlNode_create(avlNodeInfo2); - - AVLNodeInfo_t* avlNodeInfo3 = avlNodeInfo_create(mapSize, indexArray); - AVLNode_t* avlNode3 = avlNode_create(avlNodeInfo3); - - - - avlNode1->right = avlNode2; - avlNode2->right = avlNode3; - - avlNode2->height = std::max(avlNode_height(avlNode2->left), avlNode_height(avlNode2->right)) + 1; - avlNode1->height = std::max(avlNode_height(avlNode1->left), avlNode_height(avlNode1->right)) + 1; - - AVLNode_t* newRoot = avlTree_leftRotate(avlNode1); - - CHECK(newRoot == avlNode2); - CHECK(newRoot->left == avlNode1); - CHECK(newRoot->right == avlNode3); - CHECK(avlNode1->right == nullptr); - CHECK(avlNode1->height == 1); - CHECK(newRoot->height == 2); -} - -TEST_CASE("avlTree_getBalance") -{ - disk_mng_initialize(); - - int mapSize = generateRandomNumber(); - int indexArray = generateRandomNumber(); - - - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, indexArray); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, indexArray); - AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize, indexArray); - - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - AVLNode_t* root = avlNode_create(info3); - - SUBCASE("Node is NULL") { - CHECK(avlTree_getBalance(nullptr) == 0); - } - - SUBCASE("Balance factor of a node with children having different heights") { - root->left = node1; - root->right = node2; - node1->height = 3; - node2->height = 1; - root->height = 4; - CHECK(avlTree_getBalance(root) == 2); - } - - SUBCASE("Balance factor of a node with both children having the same height") { - root->left = node1; - root->right = node2; - node1->height = 2; - node2->height = 2; - root->height = 3; - CHECK(avlTree_getBalance(root) == 0); - } - - SUBCASE("Balance factor of a node with one child") { - root->left = node1; - root->right = nullptr; - node1->height = 2; - root->height = 3; - CHECK(avlTree_getBalance(root) == 2); - } -} -TEST_CASE("test_avlTree_minValueNode") { - disk_mng_initialize(); - - int mapSize1 = generateRandomNumber(); - int indexArray1 = generateRandomNumber(); - - int mapSize2 = generateRandomNumber(); - int indexArray2 = generateRandomNumber(); - - int mapSize3 = generateRandomNumber(); - int indexArray3 = generateRandomNumber(); - - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize1, indexArray1); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize2, indexArray2); - AVLNodeInfo_t* info3 = avlNodeInfo_create(mapSize3, indexArray3); - - AVLNode_t* node1 = avlNode_create(info1); - AVLNode_t* node2 = avlNode_create(info2); - AVLNode_t* node3 = avlNode_create(info3); - - SUBCASE("Node with no left child") { - CHECK(avlTree_minValueNode(node1) == node1); - } - node1->left = node2; - node2->left = node3; - - SUBCASE("Node with left child") { - CHECK(avlTree_minValueNode(node1) == node3); - } -} -TEST_CASE("test_avlTree_insert") { - disk_mng_initialize(); - - SUBCASE("Insert into an empty tree") { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->mapSize == mapSize); - CHECK(disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->lru == 1); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 1); - } - - SUBCASE("Insert nodes and check balancing") { - - for (int i = 0; i < 7; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } - - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 7); - } - - SUBCASE("Insert duplicate mapSize") { - int mapSize = generateRandomNumber(); - int arrayIndex1 = generateRandomNumber(); - int arrayIndex2 = generateRandomNumber(); - - AVLNodeInfo_t* info1 = avlNodeInfo_create(mapSize, arrayIndex1); - AVLNodeInfo_t* info2 = avlNodeInfo_create(mapSize, arrayIndex2); - - avlTree_insertElement(info1); - avlTree_insertElement(info2); - - CHECK(disk_mng_CB->disk_SortByMapSize->root != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->right != nullptr); - CHECK(disk_mng_CB->disk_SortByMapSize->root->left == nullptr); - - CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->mapSize == mapSize); - CHECK(disk_mng_CB->disk_SortByMapSize->root->right->avlNodeInfo->arrayIndex == arrayIndex2); - CHECK(disk_mng_CB->disk_SortByMapSize->totalElements == 2); - } -} -TEST_CASE("test_avlTree_FindingTheNodeThatIsSuitableForDeletion") { - disk_mng_initialize(); - - SUBCASE("Find eligible node for deletion") { - // Insert nodes into the AVL tree with different LRU values - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = (i == 3) ? disk_mng_CB->disk_SortByMapSize->lruCounter * 0.6 : generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } - - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); - } - - SUBCASE("All nodes are eligible for deletion") { - // Insert nodes with LRU values such that all are eligible for deletion - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = generateRandomNumber(); - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } - - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->lru <= disk_mng_CB->disk_SortByMapSize->lruCounter * 0.7); - - } - - SUBCASE("No node is eligible for deletion") { - // Insert nodes with LRU values such that none are eligible for deletion - for (int i = 0; i < 5; ++i) { - int mapSize = generateRandomNumber(); - int arrayIndex = generateRandomNumber(); - int lru = disk_mng_CB->disk_SortByMapSize->lruCounter * 0.8; - - AVLNodeInfo_t* info = avlNodeInfo_create(mapSize, arrayIndex); - avlTree_insertElement(info); - } - - AVLNode_t* result = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - - CHECK(result != nullptr); - CHECK(result->avlNodeInfo->mapSize == avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root)->avlNodeInfo->mapSize); - - - } -} -TEST_CASE("test_avlTree_deleteNode") { - disk_mng_initialize(); - - for (int i = 0; i < 10; i++) - { - AVLNodeInfo_t* info1 = avlNodeInfo_create(generateRandomNumber(), generateRandomNumber()); - avlTree_insertElement(info1); - } - - AVLNode_t* nodeToDelete = avlTree_FindingTheNodeThatIsSuitableForDeletion(disk_mng_CB->disk_SortByMapSize->root); - if (nodeToDelete!=NULL) - { - disk_mng_CB->disk_SortByMapSize->root = avlTree_deleteNode(disk_mng_CB->disk_SortByMapSize->root, nodeToDelete); - } -} - - -//stack tests - -TEST_CASE("test_stack_firstInitialize") -{ - disk_mng_initialize(); - for (int i = 0; i < DISK_SIZE; i++) - { - - stack_push(i); - } - - for (int i =DISK_SIZE-1; i >0; i--) - { - CHECK( stack_pop() == i); - } -} - - -TEST_CASE("test_stack_normalInitialize") -{ - disk_mng_initialize(); -} - -TEST_CASE("stack_saveData") -{ - -} - -TEST_CASE("test_stack_push") -{ - disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) - { - index = generateRandomNumber(); - stack_push(index); - popValue = stack_pop(); - CHECK(popValue == index); - } - -} -TEST_CASE("test_stack_pop") -{ - disk_mng_initialize(); - for (size_t i = 4; i < 0; i++) - { - value = stack_pop(); - CHECK(value !=stack_top()); - } -} -TEST_CASE("test_stack_top") -{ - disk_mng_initialize(); - for (size_t i = DISK_SIZE-1; i < 0; i--) - { - value = stack_top(); - stack_pop(); - CHECK(value == i); - } -} -TEST_CASE("test_stack_is_empty") -{ - disk_mng_initialize(); - for (size_t i = 0; i < DISK_SIZE; i++) - { - stack_pop(); - } - CHECK(stack_is_empty()); - -} - -TEST_CASE("test_stackNode_create") -{ - disk_mng_initialize(); - int index = generateRandomNumber(); - StackNode_t* new_node = stackNode_create(index); - CHECK(new_node->freeIndex == index); - CHECK(new_node->next == disk_mng_CB->diskFreeIndexesInArray->top); -} - -//array tests - -TEST_CASE("array_firstInitialize") -{ - -} - -TEST_CASE("array_normalInitialize") -{ - -} - -TEST_CASE("array_saveData") -{ - -} - -TEST_CASE("test_array_deleteFromArray") -{ - disk_mng_initialize(); - int index = generateRandomNumber(); - array_deleteFromArray(index); - CHECK(disk_mng_CB->arrayForAllMApsInformation[index]== NULL); -} - -TEST_CASE("test_arrayInfo_create") -{ - disk_mng_initialize(); - int * diskPointer = NULL; - int size = generateRandomNumber(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int index = generateRandomNumber(); - AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - ArrayInfo_t* arrayInfo= arrayInfo_create(diskPointer, size, mapRange,nodeInfo); - CHECK(arrayInfo->mapid == 1); - CHECK(arrayInfo->diskPointer == NULL); - CHECK(arrayInfo->size == size); - CHECK(arrayInfo->range == mapRange); -} - -TEST_CASE("test_array_addToArray") -{ - disk_mng_initialize(); - for (int i = 0; i < DISK_SIZE; i++) - for (int i = 0; i < DISK_SIZE; i++) - { - int* diskPointer = NULL; - int size = generateRandomNumber(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int index = stack_pop(); - AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - ArrayInfo_t* arrayInfo = arrayInfo_create(diskPointer, size, mapRange,nodeInfo); - array_addToArray(arrayInfo, index); - CHECK(disk_mng_CB->arrayForAllMApsInformation[index] == arrayInfo); - - } -} - -//range functions -TEST_CASE("test_mapRange_create") -{ - disk_mng_initialize(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - CHECK(mapRange->bottomRight.x == bottomRight.x); - CHECK(mapRange->bottomRight.y == bottomRight.y); - CHECK(mapRange->topLeft.x == topLeft.x); - CHECK(mapRange->topLeft.y == topLeft.y); -} - -TEST_CASE("test_disk_mng_addMap") -{ - disk_mng_initialize(); - for (int i = 0; i < 20; i++) - { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); - - } - -} - -TEST_CASE("Test disk_mng_deleteMapFromDiskManagementDataStructures") { - disk_mng_initialize(); - SUBCASE("Delete a single map when disk is full") { - // Add maps until the disk is full - for (int i = 0; i < 5; i++) { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); // Add maps to the disk - } - // Verify that the disk is full and needs deletion - //REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements == 5); - - // Perform deletion - int sizeToFree = generateRandomNumber(); // Random size to free - disk_mng_delete(sizeToFree); - - // Ensure that space has been freed - REQUIRE(disk_mng_CB->disk_SortByMapSize->totalElements < 5); - - } - -} - -TEST_CASE("test_arrayInLoaded_initialize") -{ - arrayInLoaded_initialize(); - CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); - for (int i = 0; i < CACHE_SIZE; i++) { - CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); - } -} - -TEST_CASE("arrayInLoaded_create") { - int mapId = generateRandomNumber(); - int index = generateRandomNumber(); - DiskMapsInLoadedToCache_t* obj = arrayInLoaded_create(mapId, index); - - CHECK(obj != NULL); - CHECK(obj->mapId == mapId); - CHECK(obj->index == index); - -} -TEST_CASE("test_disk_mng_isTheMapInRange") { - - disk_mng_initialize(); - - int x1 = generateRandomNumber(100); - int y1 = generateRandomNumber(100); - int x2 = generateRandomNumber(200, x1); - int y2 = generateRandomNumber(200, y1); - Point_t cacheTopLeft = { x1, y1 }; - Point_t cacheBottomRight = { x2, y2 }; - //MapRange_t* rangeFromCache = mapRange_create(cacheBottomRight, cacheTopLeft); - - int x3 = generateRandomNumber(100); - int y3 = generateRandomNumber(100); - int x4 = generateRandomNumber(200, x3); - int y4 = generateRandomNumber(200, y3); - Point_t rangeTopLeft = { x3, y3 }; - Point_t rangeBottomRight = { x4, y4 }; - //MapRange_t* range = mapRange_create(rangeBottomRight, rangeTopLeft); - MapRange_t* range = mapRange_create({ 224,140 }, { 148,160 }); - MapRange_t* rangeFromCache = mapRange_create({250,130}, {170,170}); - - printMapRange("Range From Cache", rangeFromCache); - printMapRange("Range To Check", range); - - bool result = disk_mng_isTheMapInRange(rangeFromCache, range); - - bool expected = ( - - ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->bottomRight.x && rangeFromCache->bottomRight.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->topLeft.y && rangeFromCache->topLeft.y >= range->bottomRight.y)) || - - ((range->bottomRight.x >= rangeFromCache->topLeft.x && rangeFromCache->topLeft.x >= range->topLeft.x) && - (range->topLeft.y >= rangeFromCache->bottomRight.y && rangeFromCache->bottomRight.y >= range->bottomRight.y)) || - (range->topLeft.y< rangeFromCache->topLeft.y && range->bottomRight.y>rangeFromCache->bottomRight.y) || - (range->topLeft.x > rangeFromCache->topLeft.x && range->bottomRight.x < rangeFromCache->bottomRight.x) - ); - printf("Result: %s\n", result ? "true" : "false"); - printf("Expected: %s\n", expected ? "true" : "false"); - CHECK(result == expected); -} - -TEST_CASE("test_disk_mng_loadMapFromDiskToCache") { - disk_mng_initialize(); - - for (int i = 0; i < CACHE_SIZE; i++) { - int mapId = generateRandomNumber(); - int index = generateRandomNumber(); - - DiskMapsInLoadedToCache_t* map = arrayInLoaded_create(mapId, index); - disk_mng_CB->disk_MapsInLoadedToCache[i] = map; - } - - - int testMapId = disk_mng_CB->disk_MapsInLoadedToCache[0]->mapId; - int testIndex= disk_mng_CB->disk_MapsInLoadedToCache[0]->index; - - int* diskPointer = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for diskPointer", "test_disk_mng_loadMapFromDiskToCache");; - int size = generateRandomNumber(); - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int index = generateRandomNumber(); - AVLNodeInfo_t* nodeInfo = avlNodeInfo_create(size, index); - - disk_mng_CB->arrayForAllMApsInformation[testIndex] = arrayInfo_create(diskPointer, size, mapRange, nodeInfo); - disk_mng_CB->arrayForAllMApsInformation[testIndex]->mapid = testMapId; - - int offset = generateRandomNumber(); - int length = generateRandomNumber(); - int freeAddress = generateRandomNumber(); - - bool result = disk_mng_loadMapFromDiskToCache(testMapId, offset, length, &freeAddress); - - // Check results - CHECK(result == true); -} -//TEST_CASE("test_disk_mng_getMapsIdsInRange") { -// disk_mng_initialize(); -// -// for (int i = 0; i < 20; i++) -// { -// Point_t topLeft; -// topLeft.x = generateRandomNumber(); -// topLeft.y = generateRandomNumber(); -// Point_t bottomRight; -// bottomRight.x = generateRandomNumber(); -// bottomRight.y = generateRandomNumber(); -// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); -// int size = generateRandomNumber(); -// int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); -// disk_mng_addMap(mapRange, size, map); -// -// } -// Point_t topLeft; -// topLeft.x = generateRandomNumber(); -// topLeft.y = generateRandomNumber(); -// Point_t bottomRight; -// bottomRight.x = generateRandomNumber(); -// bottomRight.y = generateRandomNumber(); -// MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); -// -// ArrayInfo_t** arrayOfMapsInRange = (ArrayInfo_t**)allocate_memory(CACHE_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for arrayOfMapsInRange ", "test_disk_mng_getMapsIdsInRange"); -// -// int count = disk_mng_getMapsIdsInRange(mapRange, arrayOfMapsInRange, CACHE_SIZE); -//} - -TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { - - SUBCASE("check the first initialize") { - disk_mng_initialize(); - int expectedAddressValue = 1; - int loadedValue = 0; - - int startAddress = 0; - int howManyToLoad = sizeof(int); - - disk_loadDataForInitializeDataStructers(&loadedValue, &startAddress, &howManyToLoad); - - CHECK(loadedValue == expectedAddressValue); - } - SUBCASE("check the normal initilaize") - { - Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); - Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); - MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); - int size = generateRandomNumber(); - int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); - disk_mng_addMap(mapRange, size, map); - - disk_mng_saveData(); - - int stackSize; - int startAddressForStackSize = sizeof(int); - int lengthStackSize = sizeof(int); - disk_loadDataForInitializeDataStructers(&stackSize, &startAddressForStackSize, &lengthStackSize); - CHECK(stackSize == disk_mng_CB->diskFreeIndexesInArray->size); - - int avlSize; - int startAddressForAVL = 2*sizeof(int); - int lengthAVLSize = sizeof(int); - disk_loadDataForInitializeDataStructers(&avlSize, &startAddressForAVL, &lengthAVLSize); - CHECK(avlSize == disk_mng_CB->disk_SortByMapSize->totalElements); - - int avllruCounter; - int startAddressForAVLLruCounter = 3* sizeof(int);; - int lengthAVLLruCounter = sizeof(int); - disk_loadDataForInitializeDataStructers(&avllruCounter, &startAddressForAVLLruCounter, &lengthAVLLruCounter); - CHECK(avllruCounter == disk_mng_CB->disk_SortByMapSize->lruCounter); - - int mapIdIndex; - int startAddressFormapIdIndex = 4* sizeof(int);; - int lengthmapIdIndex = sizeof(int); - disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); - CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); - - - DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); - int startAddressForStack = 5* sizeof(int); - int lengthStack = sizeof(StackNode_t*) * stackSize; - printf(" %d\n\n", lengthStack); - - disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); - printf(" %d\n\n", lengthStack); - - CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); - - - ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_firstInitialize"); - int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); - int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); - disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); - printf("-------------------"); - - for (int i = 96; i < DISK_SIZE; i++) - { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) { - ArrayInfo_t* a = disk_mng_CB->arrayForAllMApsInformation[i]; - ArrayInfo_t* a2= arrayForTest[i]; - printf(" %d\n\n", a2->mapid); - CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); - CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); - } - } - } -} - diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 10475a5..7f8c0e7 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -1987,3 +1987,75 @@ disk_mng_checkDataStructures_range: Error: Error worng map range. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. From 4826f7be24c6bb951c46eb9ee1c69fa0264f3384 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Tue, 10 Sep 2024 10:54:22 +0300 Subject: [PATCH 31/32] add test for avl save --- Storage/Doctest.cpp | 10 ++-- Storage/errors.log.txt | 114 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index 67f501c..e61acec 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -726,11 +726,11 @@ TEST_CASE("test_disk_mng_addMap") for (int i = 0; i < 20; i++) { Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); + topLeft.x = 148; + topLeft.y = 160; Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); + bottomRight.x = 224; + bottomRight.y = 140; MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); int size = generateRandomNumber(); int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); @@ -993,7 +993,7 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { DiskSortByMapSize_t* avlTreeForTest = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for avlTree ", "avlTree_test"); int startAddressForAVLTree = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * sizeof(ArrayInfo_t*); int lengthforAVLTree = avlSize * sizeof(AVLNode_t*); - disk_loadDataForInitializeDataStructers(&avlTreeForTest, &startAddressForAVL, &lengthforAVLTree); + disk_loadDataForInitializeDataStructers(&avlTreeForTest, &startAddressForAVLTree, &lengthforAVLTree); CHECK(avlTreeForTest->root->avlNodeInfo->arrayIndex == disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->arrayIndex); } diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index 7f8c0e7..a6f44c4 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -2059,3 +2059,117 @@ disk_mng_checkDataStructures_range: Error: Error worng map range. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. From b535a2d8143663f65d38c5416ed05b2c5f893797 Mon Sep 17 00:00:00 2001 From: shifi325 Date: Sun, 15 Sep 2024 08:56:43 +0300 Subject: [PATCH 32/32] merge --- Storage/CMakeLists.txt => CMakeLists.txt | 0 Storage/Disk_Mng_Master.c | 29 ++- Storage/Disk_Mng_Master.h | 5 +- Storage/Disk_Mng_Master_Sycl.cpp | 32 +-- Storage/Doctest.cpp | 89 ++++--- Storage/Storage.vcxproj | 11 + Storage/cpp.hint | 4 + Storage/errors.log.txt | 296 +++++++++++++++++++++++ 8 files changed, 403 insertions(+), 63 deletions(-) rename Storage/CMakeLists.txt => CMakeLists.txt (100%) create mode 100644 Storage/cpp.hint diff --git a/Storage/CMakeLists.txt b/CMakeLists.txt similarity index 100% rename from Storage/CMakeLists.txt rename to CMakeLists.txt diff --git a/Storage/Disk_Mng_Master.c b/Storage/Disk_Mng_Master.c index 2d86917..771d990 100644 --- a/Storage/Disk_Mng_Master.c +++ b/Storage/Disk_Mng_Master.c @@ -80,7 +80,9 @@ void arrayInLoaded_initialize() disk_mng_CB->disk_MapsInLoadedToCache = (DiskMapsInLoadedToCache_t**)allocate_memory(CACHE_SIZE * sizeof(DiskMapsInLoadedToCache_t*), "Failed to allocate memory for array in loaded ", "arrayInLoaded_initialize"); if (disk_mng_CB->disk_MapsInLoadedToCache != NULL) { for (int i = 0; i < CACHE_SIZE; i++) { - disk_mng_CB->disk_MapsInLoadedToCache[i] = NULL; + disk_mng_CB->disk_MapsInLoadedToCache[i] =(DiskMapsInLoadedToCache_t*) allocate_memory(sizeof(DiskMapsInLoadedToCache_t), "Failed to allocate memory for array in loade info","arrayInLoaded_initialize"); + disk_mng_CB->disk_MapsInLoadedToCache[i]->index = -1; + disk_mng_CB->disk_MapsInLoadedToCache[i]->mapId = -1; } } } @@ -95,7 +97,7 @@ DiskMapsInLoadedToCache_t* arrayInLoaded_create(int mapId, int index) //initialize on the first time we turn o the computer the stack will initialize with all the indexes. void stack_firstInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t)*DISK_SIZE, "Failed to allocate memory for stack ", "stack_firstInitialize"); + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); disk_mng_CB->diskFreeIndexesInArray->top = NULL; disk_mng_CB->diskFreeIndexesInArray->size = 0; for (size_t i = 0; i < DISK_SIZE; i++) @@ -105,12 +107,15 @@ void stack_firstInitialize() { } void stack_normalInitialize() { - disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t)*DISK_SIZE, "Failed to allocate memory for stack ", "stack_normalInitialize"); + int size = 0;//stack size int startAdress = sizeof(int);; int howManyToLoad = sizeof(int); //load the second address in disk with stack size disk_loadDataForInitializeDataStructers(&size, &startAdress, &howManyToLoad); + disk_mng_CB->diskFreeIndexesInArray = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); + disk_mng_CB->diskFreeIndexesInArray->top= (StackNode_t*)allocate_memory(sizeof(StackNode_t)*size, "Failed to allocate memory for stack ", "stack_normalInitialize"); + howManyToLoad = size * sizeof(StackNode_t*); //load all the data from stack disk_loadDataForInitializeDataStructers(&(disk_mng_CB->diskFreeIndexesInArray), &startSructers, &howManyToLoad); @@ -179,7 +184,11 @@ void array_firstInitialize() { } } void array_normalInitialize() { - disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_normalInitialize"); + disk_mng_CB->arrayForAllMApsInformation = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*)*DISK_SIZE, "Failed to allocate memory for array ", "array_normalInitialize"); + for (size_t i = 0; i < DISK_SIZE; i++) + { + disk_mng_CB->arrayForAllMApsInformation[i]= (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for array ", "array_normalInitialize"); + } startSructers =5* sizeof(int)+ disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); int howManyToLoad = DISK_SIZE * sizeof(ArrayInfo_t*); //load all the data from array @@ -383,7 +392,7 @@ void avlTree_firstInitialize() { void avlTree_normalInitialize() { - disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); + int length = 0; int startAdress = 2 * sizeof(int);; int howManyToLoad = sizeof(int); @@ -396,6 +405,11 @@ void avlTree_normalInitialize() //load the forth address in disk with avlTree lru disk_loadDataForInitializeDataStructers(&length, &startAdress, &howManyToLoad); + disk_mng_CB->disk_SortByMapSize = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); + + + disk_mng_CB->disk_SortByMapSize->root= (AVLNode_t*)allocate_memory(sizeof(AVLNode_t)*length, "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); + startSructers = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * (sizeof(ArrayInfo_t*)); howManyToLoad = length * sizeof(AVLNode_t*); //load all the data from avlTree @@ -699,7 +713,8 @@ bool disk_mng_loadMapFromDiskToCache(int mapId, int offset, int size, int* freeA if (index != -1)//Checking whether the map was found in the loading array { diskPointer = disk_mng_CB->arrayForAllMApsInformation[index]->diskPointer;//Finding the appropriate disk pointer - disk_mng_CB->arrayForAllMApsInformation[index] = NULL; + disk_mng_CB->disk_MapsInLoadedToCache[index]->index = -1; + disk_mng_CB->disk_MapsInLoadedToCache[index]->mapId = -1; startAddress = diskPointer + (offset * sizeof(int)); isLoadedSuccess = disk_loadMapToCache(startAddress, size, freeAddress); if (!isLoadedSuccess) @@ -717,7 +732,7 @@ int disk_mng_searchForSuitableMapInLoadingArray(int mapId) for (int i = 0; i < CACHE_SIZE; i++) { map = disk_mng_CB->disk_MapsInLoadedToCache[i]; - if (map != NULL && mapId == map->mapId) + if (map->index!=-1&&map->mapId!=-1 && mapId == map->mapId) { return map->index; } diff --git a/Storage/Disk_Mng_Master.h b/Storage/Disk_Mng_Master.h index 0ed54d2..3d77ef2 100644 --- a/Storage/Disk_Mng_Master.h +++ b/Storage/Disk_Mng_Master.h @@ -1,3 +1,4 @@ +//#include "C:\Users\ \Pictures\Saved Pictures\\ \\\Sycl_DLL\Sycl_DLL/Disk_Mng_Master.h" #pragma once #include #include @@ -7,7 +8,7 @@ #define POINT_BR_RANGE (Point_t){100, 100} #define POINT_TL_RANGE (Point_t){0, 0} -#define DISK_SIZE 100 +#define DISK_SIZE 10 #define CACHE_SIZE 100 // Forward declarations @@ -298,3 +299,5 @@ bool disk_loadMapToCache(int startAddress, int length, int* chacheFreeAddress); void cache_deleteMap(int mapId); //int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) + + diff --git a/Storage/Disk_Mng_Master_Sycl.cpp b/Storage/Disk_Mng_Master_Sycl.cpp index 3dab19e..52e7bbe 100644 --- a/Storage/Disk_Mng_Master_Sycl.cpp +++ b/Storage/Disk_Mng_Master_Sycl.cpp @@ -1,38 +1,38 @@ -//#include +//#include //#include //#include //#include "Disk_Mng_Master_API.h" //#include "Disk_Mng_Master.h" -//using namespace cl::sycl; +// //extern "C" { //#include "Disk_Mng_Master_API.h" //#include "Disk_Mng_Master.h" //} +// //int disk_mng_getMapsIdsInRange(MapRange_t* rangeFromCache, ArrayInfo_t** arrayOfMapsIdsInRange, int arraySize) { // int count = 0; // +// sycl::queue q; +// sycl::buffer bufferCount(&count, sycl::range<1>(1)); +// sycl::buffer bufferInputArray(disk_mng_CB->arrayForAllMApsInformation, sycl::range<1>(arraySize)); +// sycl::buffer bufferOutputArray(*arrayOfMapsIdsInRange, sycl::range<1>(arraySize)); // -// queue q; -// buffer bufferCount(&count, 1); -// buffer bufferInputArray(disk_mng_CB->arrayForAllMApsInformation, range<1>(arraySize)); -// buffer bufferOutputArray(*arrayOfMapsIdsInRange, range<1>(arraySize)); +// q.submit([&](sycl::handler& h) { +// auto inputArrayAccess = bufferInputArray.get_access(h); +// auto outputArrayAccess = bufferOutputArray.get_access(h); +// auto countAccess = bufferCount.get_access(h); // -// q.submit([&](handler& h) { -// auto inputArrayAccess = bufferInputArray.get_access(h); -// auto outputArrayAccess = bufferOutputArray.get_access(h); -// auto countAccess = bufferCount.get_access(h); -// -// h.parallel_for(range<1>(arraySize), [=](id<1> i) { +// h.parallel_for(sycl::range<1>(arraySize), [=](sycl::id<1> i) { // if (inputArrayAccess[i].range != NULL && // disk_mng_isTheMapInRange(rangeFromCache, inputArrayAccess[i].range)) { -// int idx = atomic_fetch_add(countAccess[0], 1); +// int idx = sycl::atomic_ref(countAccess[0]).fetch_add(1); // outputArrayAccess[idx] = inputArrayAccess[i]; -// disk_mng_CB->disk_MapsInLoadedToCache[idx] = arrayInLoaded_create(inputArrayAccess[i]->mapid, i); +// disk_mng_CB->disk_MapsInLoadedToCache[idx] = arrayInLoaded_create(inputArrayAccess[i].mapid, i); // } // }); // }).wait(); // -// count = bufferCount.get_access()[0]; +// count = bufferCount.get_access()[0]; // // return count; -//} \ No newline at end of file +//} diff --git a/Storage/Doctest.cpp b/Storage/Doctest.cpp index e61acec..f219bea 100644 --- a/Storage/Doctest.cpp +++ b/Storage/Doctest.cpp @@ -7,18 +7,19 @@ #include #include #include -#include +#include extern "C" { #include "Disk_Mng_Master.h" #include "Disk_Mng_Master_API.h" - } + struct GlobalSetup { GlobalSetup() { srand(time(0)); } }; + GlobalSetup globalSetup; int generateRandomNumber(int lower=0,int upper = DISK_SIZE) { @@ -775,7 +776,8 @@ TEST_CASE("test_arrayInLoaded_initialize") arrayInLoaded_initialize(); CHECK(disk_mng_CB->disk_MapsInLoadedToCache != NULL); for (int i = 0; i < CACHE_SIZE; i++) { - CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i] == NULL); + CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i]->index == -1); + CHECK(disk_mng_CB->disk_MapsInLoadedToCache[i]->mapId == -1); } } @@ -923,11 +925,11 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { SUBCASE("check the normal initilaize") { Point_t topLeft; - topLeft.x = generateRandomNumber(); - topLeft.y = generateRandomNumber(); + topLeft.x = 148; + topLeft.y = 160; Point_t bottomRight; - bottomRight.x = generateRandomNumber(); - bottomRight.y = generateRandomNumber(); + bottomRight.x = 224; + bottomRight.y =140; MapRange_t* mapRange = mapRange_create(bottomRight, topLeft); int size = generateRandomNumber(); int* map = (int*)allocate_memory(sizeof(int*), "Failed to allocate memory for map", "test_disk_mng_addMap"); @@ -959,42 +961,51 @@ TEST_CASE("Test if disk is initialized correctly after disk_mng_initialize") { disk_loadDataForInitializeDataStructers(&mapIdIndex, &startAddressFormapIdIndex, &lengthmapIdIndex); CHECK(mapIdIndex == disk_mng_CB->mapIdIndex); - - DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_firstInitialize"); + DiskFreeIndexesInArray_t* stackForTest = (DiskFreeIndexesInArray_t*)allocate_memory(sizeof(DiskFreeIndexesInArray_t), "Failed to allocate memory for stack ", "stack_normalInitialize"); + stackForTest->top = (StackNode_t*)allocate_memory(sizeof(StackNode_t) * stackSize, "Failed to allocate memory for stack ", "stack_normalInitialize"); + int startAddressForStack = 5* sizeof(int); int lengthStack = sizeof(StackNode_t*) * stackSize; printf(" %d\n\n", lengthStack); - disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); - printf(" %d\n\n", lengthStack); - - CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); - - - ArrayInfo_t** arrayForTest= (ArrayInfo_t**)allocate_memory(DISK_SIZE * sizeof(ArrayInfo_t*), "Failed to allocate memory for array ", "array_test"); - int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); - int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); - disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); - printf("-------------------"); - - for (int i = 96; i < DISK_SIZE; i++) - { - if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) { - ArrayInfo_t* a = disk_mng_CB->arrayForAllMApsInformation[i]; - ArrayInfo_t* a2= arrayForTest[i]; - printf(" %d\n\n", a2->mapid); - CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); - CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); - //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); - } - } - DiskSortByMapSize_t* avlTreeForTest = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for avlTree ", "avlTree_test"); - int startAddressForAVLTree = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * sizeof(ArrayInfo_t*); - int lengthforAVLTree = avlSize * sizeof(AVLNode_t*); - disk_loadDataForInitializeDataStructers(&avlTreeForTest, &startAddressForAVLTree, &lengthforAVLTree); - CHECK(avlTreeForTest->root->avlNodeInfo->arrayIndex == disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->arrayIndex); + //disk_loadDataForInitializeDataStructers(&stackForTest, &startAddressForStack, &lengthStack); + //printf(" %d\n\n", lengthStack); + + //CHECK(disk_mng_CB->diskFreeIndexesInArray->top->freeIndex == stackForTest->top->freeIndex); + + + //ArrayInfo_t** arrayForTest = (ArrayInfo_t**)allocate_memory(sizeof(ArrayInfo_t*)*DISK_SIZE, "Failed to allocate memory for array ", "array_normalInitialize"); + //for (size_t i = 0; i < DISK_SIZE; i++) + //{ + // arrayForTest[i] = (ArrayInfo_t*)allocate_memory(sizeof(ArrayInfo_t), "Failed to allocate memory for array ", "array_normalInitialize"); + //} + //int startAddressForArray = 5* sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*); + //int lengthForArray = DISK_SIZE* sizeof(ArrayInfo_t*); + //disk_loadDataForInitializeDataStructers(&arrayForTest, &startAddressForArray, &lengthForArray); + //printf("-------------------"); + + //for (int i = 96; i < DISK_SIZE; i++) + //{ + // if (disk_mng_CB->arrayForAllMApsInformation[i] != NULL) { + // ArrayInfo_t* a = disk_mng_CB->arrayForAllMApsInformation[i]; + // ArrayInfo_t* a2= arrayForTest[i]; + // printf(" %d\n\n", a2->mapid); + // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->mapid == arrayForTest[i]->mapid); + // CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->size == arrayForTest[i]->size); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->avlNodeInfo == arrayForTest[i]->avlNodeInfo); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->diskPointer == arrayForTest[i]->diskPointer); + // //CHECK(disk_mng_CB->arrayForAllMApsInformation[i]->range == arrayForTest[i]->range); + // } + //} + //DiskSortByMapSize_t* avlTreeForTest = (DiskSortByMapSize_t*)allocate_memory(sizeof(DiskSortByMapSize_t), "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); + + + //avlTreeForTest->root = (AVLNode_t*)allocate_memory(sizeof(AVLNode_t) * avlSize, "Failed to allocate memory for AVL Tree ", "avlTree_normalInitialize"); + + //int startAddressForAVLTree = 5 * sizeof(int) + disk_mng_CB->diskFreeIndexesInArray->size * sizeof(StackNode_t*) + DISK_SIZE * sizeof(ArrayInfo_t*); + //int lengthforAVLTree = avlSize * sizeof(AVLNode_t*); + //disk_loadDataForInitializeDataStructers(&avlTreeForTest, &startAddressForAVLTree, &lengthforAVLTree); + //CHECK(avlTreeForTest->root->avlNodeInfo->arrayIndex == disk_mng_CB->disk_SortByMapSize->root->avlNodeInfo->arrayIndex); } } diff --git a/Storage/Storage.vcxproj b/Storage/Storage.vcxproj index 47a925b..8572832 100644 --- a/Storage/Storage.vcxproj +++ b/Storage/Storage.vcxproj @@ -70,6 +70,9 @@ + + C:\Program Files (x86)\Intel\oneAPI\compiler\latest\include;$(IncludePath) + Level3 @@ -104,10 +107,15 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + C:\Program Files (x86)\Intel\oneAPI\compiler\latest\include;%(AdditionalIncludeDirectories) + stdcpp20 + true Console true + C:\Users\שיפי וינגרטן\Pictures\Saved Pictures\סמינר\כיתה יד\תכנות\פרקטיקום\Sycl_DLL\x64\Debug + $(CoreLibraryDependencies);%(AdditionalDependencies);Sycl_DLL.lib @@ -135,6 +143,9 @@ + + + diff --git a/Storage/cpp.hint b/Storage/cpp.hint new file mode 100644 index 0000000..f26ee03 --- /dev/null +++ b/Storage/cpp.hint @@ -0,0 +1,4 @@ +// Hint files help the Visual Studio IDE interpret Visual C++ identifiers +// such as names of functions and macros. +// For more information see https://go.microsoft.com/fwlink/?linkid=865984 +#define CACHE_SIZE diff --git a/Storage/errors.log.txt b/Storage/errors.log.txt index a6f44c4..7617c74 100644 --- a/Storage/errors.log.txt +++ b/Storage/errors.log.txt @@ -2173,3 +2173,299 @@ disk_mng_checkDataStructures_mapSize: Error: Error worng size variable. disk_mng_checkDataStructures_range: Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_mapSize: +Error: Error worng size variable. +disk_mng_checkDataStructures_range: +Error: Error worng map range. +disk_mng_checkDataStructures_range: +Error: Error worng map range.