From d42ee2a69c74588d5bba7fbfd97dc9ac278c8320 Mon Sep 17 00:00:00 2001 From: Lorenzo Dee Date: Fri, 15 Jul 2022 13:50:53 +0800 Subject: [PATCH 01/45] Fix git-publish plugin version not found Version 3.0.0 not found since JCenter was deprecated in 2021 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 04e74d9c..ac8b2231 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { id 'net.nemerosa.versioning' version '2.14.0' id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' id 'net.researchgate.release' version '2.8.1' - id 'org.ajoberstar.git-publish' version '3.0.0' + id 'org.ajoberstar.git-publish' version '3.0.1' } description = 'Concordion is an open source framework for Java that lets you turn a plain English description of a requirement into an automated test' From c1ba0b17326d1dfd9ca55e965f0a853d2b5363c3 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Fri, 15 Jul 2022 18:41:12 +1200 Subject: [PATCH 02/45] Update from JDK 16 to JDK 17 LTS --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b97adcdc..3ca7608d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '8', '11', '16' ] + java: [ '8', '11', '17' ] name: Java ${{ matrix.Java }} steps: From 461a3887e22ccf0f4c3d38f7381eeb025ad94682 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Fri, 15 Jul 2022 19:03:59 +1200 Subject: [PATCH 03/45] Update Gradle to 7.5 to support JDK 17 --- gradle/wrapper/gradle-wrapper.jar | Bin 56177 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 282 ++++++++++++++--------- gradlew.bat | 43 ++-- 4 files changed, 197 insertions(+), 130 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 29953ea141f55e3b8fc691d31b5ca8816d89fa87..41d9927a4d4fb3f96a785543079b8df6723c946b 100644 GIT binary patch delta 51682 zcmY&i&8-_)JiC&6% z<9g%z4dlNA+7Z9~N8kp=|9!J!{ZDin#Zr0aHxLjUFc1)?lpA8q6yZ~1eQtVtZHeVBK2JWk@K z9k6HWktQ@4Xajc^HzK#$<<6(sIiqa=#5<-J+OcFALr*P^|^om!YO8kZ-yPSc-6Xj1xUK`yUqmVC1G zM9RSG$BEba6*b$krtygpbs9ELt@@`FDsXIo%(tRms0NUY|2 z@<+79_o*o^t$M_ERDYPaE^_1d0D|u~6~oa%r~g>||K24w-{@nTe((e1^IHm>=uk?*PVlPaHC)x&EMrOAnE#qH=w>v%wG)swyjK z2Z3?0;6LLucHlQO{v5QVEt0k${g4QyHd&su8^f4c8TE@l_Dc6?PEu#+&SYHI9Rzkx zy4%{Chc51Urd%fxd#A0tvOL%~b|1OL3hC?N!J^Mj87>miIoVq>XL;KkF~QGHi95pSEuRE5q6^`%HPp&n_5%hkvf>N3OT4L@@G0arM z(-!R%uQWg%PJrBIlL!%q7+hd&-X5$V z?nm#s6y_QH;`J@-V)BkcWTI`grc#*;jX^?T7551yhcvm}FqRhN-htonXaG))Df(Xd z;RwQH=H%5xUr1dWu|ZJ9J&x1}uCk zIO=W75f4Qf2p$hCeXaDfb}+(ZRY_q8AM9m}8AuK43c7!Y62|6mz$D`jugSA=bppFd zFdEe29X5Z(I$GTj)eTh*2*7AZ4#H^H?zGf*ku5^wZ*d=N-=HypejP4*tUCO+13ifC z-QbX`o1pS@j7a;Ps1TxSvf+6;TIPGf2EgXFO&j6x+$K*_ms~F0V9~l+i84QLdF^9q{Yl%%F&!!r{=DTBkO2x+*{6md$)Mh&9sK!L&_fliw7$uu-6us=IiuL z+ItX}yzpJCZNH7Xf3>aIleYTa%=MI}<}2PxoH14Ac-3z7lrh)}Tqn0xCRJAYurR?x z>8pSWkHpWHq(1nvNB!u*U>+w1~T zvDtwF#UviLBG8j_u&hZ7ZLV7EK1x{u`?5AtGqz` z{-SDm&#L(4*vB8OY17&J3i7dvOyj=JEQs*q>=~H+w zkKp6b+!N-TecVbXVCH*QUTWcA|4E|%jic5op8>`H*mm*XL-rqh={yacvIdC;`hzy* z5|RkO`HO(m_hfiAjy8ZR206w|Om5}pmbHnci#n#af$bpCM?Y$SOv#sGa|TzE(A>A4 zOF}YTtESJBWH*6FRV~Z=ImMtEwlIi&!l~=cBtYU&(}5{@vs9Lw`Q#HUqnfE^qJRXk|8(Tc3AaE~m8M4572d!FrO=>*wXxG9#>JJTKo_r>rRYT1VC?Q#6aI=2 zeEyZucbu|>WyDJ+>QNrBl=VsW>AQfFx8Ncv@Pr!Z4$DoDGSSKPwCUD&)qQmShYA2b zpaMne5J^1L$HSH?$bLZ0?x+{mE6&J?Bx=)pHpc;RQ6*R_R4W^!O^f!N%M_ zR>xSJmOc0l`%e8ZjMQr&x^bbk!U+u@M`JFQt2g|@j8Gj125!TE70-(u{^7%4z&G%G zxMrtx68_V)Xgjw-&(XB?#gJ>O=MXVE28f1{Je|vpTOfc1pMG5<;*!NBbT!wwe;QtM ztIXxs?s9cukQ>wu?mGj(@n7K8kt0!chwvnrh16 zltoq$$zy8{iSDhwEG~MO9t`FQU`~ZSU3b80mWnLfPWj?$;G*j4(JnhkSA2ZP4f9Ja zN86z+`zqyVEqh`|!FyxspkmA^W5m_ikFm+RB86cY|1{ZZNZpXuOKk^YbFCO>yQt%b zIc6{J=z;wNYgd|;GN|tHkOrIsw|x--0cJws(hvVp4o_v}KF!Yp=#v)wLgInXpi^mV0kI zFY-5h{N84+w#JLZ&2~TUkO^`V9)Y>W;{NgDXL%6|`CG&o^GmmL>N(46yYLxqeDpo9 zb{Bw9bU%RG+S(Rz4TiC-(1yUfc180D#l9ysa*amvA@5yS5F^C|B-EU77CC2S%N!uj zRB@eo7m$e>8JAYvTvl+Wexj~>F)s-??0OuVUu}t{Vu~>&H5gCJJhewn6&2(nEg%P* zm(ggB8-M=@XM8h)Ipb1&;v@M8{`MYi@?Q44ESjyzp#^VHPMXG(?3m0+dggVx?_2iS zJnD_6ZuwD-;)_fk;L7M&-tD)#fX$URN+M9TJuG92sd!qjTX~TCi^~}G;yF6f8rFm{ z@7D?XRf&)I7v#bVVgNzYI1>6ZGD_$|FaYX{B_|etc|k7pZ3$66~C-btzmk~=c77f{0W$Tj>r1V1J0vdnZ)FjZqE)WUI8RP+4R)$R*wjB??OmjbBar z3tK@qa`Nu?9=5#Q%ua+3*m$#xr?~}B;E|@egLnm>wVrp-hSxS)Q%dvD`A#l*y8GQ8 zbGLcApBC;40wJAoDZr#yaLaaEg9UqPezB?aL_Ve62L~g$tPEg}0Uo(*$QnV^f-yTi z*-Y;Hq?GRZF@?y3r3q7zzRsh|1;-uL`?z8m{f-(bJ`usiXK8L0N~!i)8`t7x zq`jM^-Mhc*spHYEa}TvYeIf?crObV!N%WoNl8Y*=d0e|553}zvN3s>@qKoZd{ban; z7x7|EFhDP6d@p-vfavUgMuKhD@GD>V_v(G=2IE*;4OGhQlj8$JD0DAC=e5PWZ`Zf1 zTwuxrTd{m`w0qAk$*r_tgGijv6ywm#N{<5N_wON^qrU-ju9M&~$UnUlRxP6-pGT`p zpUv+2nENwP(}=YQ3Rv}zr;WzprNDfD`1x?evF37v%otC10~~XyTJ)pt_EvN?tUKNa z<2(sPMluo!G}FhKhtKeC_;=d#O+TB$&UhW2>GvtcjQsv)*rppK6OO}bo;032p5hnK z4eQ~zyF`*~IsSC!-Wa2!E&!_@Bxx)!=HO8zo%sF%d<;0dKZUi$2Peq0hN;H9a(gW0 zzE@M$n720S04k+zCslvTZF$JoLQ40@jUdOJtvwz8jgTEYn7J$t+WnT z?$NP2*2J=CkM{Gru5$?N0h3b)OtPDG6%zhdiL^lVplw{*^;sMp2UcQ9lHj|tC9nJ4 zZ&~BkRb1v@U9xM`j?!qvCzI}F6U^5BNh{ypYitt72c8{G47}0usW?weWXrT*f8D=@ zwWvxnnS9^c74)sq;jec@ks+}@RaK$tS6s(gWY3PDo=2Kz)q@U@%Z~Vl+YJrIKZeJC zE6nK(>a>8bnfK@Vn#sl_+b)ZDXnS{_t5N#2T8zoEFY*y2DKd)DX%M@*gm2KMlI)QT z(e4>S08kt5H?=3y?!n*`xW(&2l`1D9ZQ|!w9jDVf?o}G>^A(bohVYB&qaL_I-$Q#1 z;xBWWXUiQW(jG172<?EP~-0Y(eNG>Vu?m zIQCPq#QB7Yu;}`gIiTt5KkEwrt#A^Zm8NO_$%sly5D=38cbpM{Q5_g>z2!8)aow$! zd;AUAJ#iUm&}ME!8EBZ_#!&=NbT`S`o*`(W-c9)q6wTzN74)eTspWp!u&wlE?nPl` z^Yf@YgTjRjFn%ZY?vE#}c{FU(eV*25pHF>MI?drSM>$tH{x<*Wnl4~e94RrkmoDvDg7T3$TPdu*26S|WXp9jU>oPN?dmeTb4qMth~=)1Zy5;jO-l zoq`!R8fUJju2dF>zSMaZPa;6Tu{!=VUhE>!!-E45DdJYCTajDf8k^q+yYK9Dwepyb zO#du&9223xy4w2nr=`wsb>(qOxv>JzKF{wyz}HMY5rHdW+MJwob6R}`GqFrwz|wKK z#Ks!a>bC9C>G%9rHy!%s*6fG~lnMvS%=+ern}(Agb!$x>STn(p*?fInMR#{^9TMO9 zDV!(p#PJa1**4Bk`*I*SQjJO=CP8A@@RM(Y67Dw^f=KJGR{&QyLYo$ zV?9nBulpW6Q&uc#H`B2^MR{j$Xl<$-&yyD@gJ9jvkT6AQ39tI$8&Q%U--@A^mFsZR zNTMD;5_frj>`1m&ag~5Ov~VLL(50ayIr5v5cP0rM(Q{V5EjZ>5a=$5{QPetHCSB_& z&)2osXOvy76J+>6#DAmiYEv|UA{ky#iB!p7!{vk-w+G@GE+NE>K;ArYMPEL!Pt6zb zykdcz`Fn!Co7()n3h8o`mquYXY-p7Z9@``DPw?FO8`s?N{We6iRm(nl1M~p@?N{Z1 zj;>5)Cp0pC3_RIl`Cks4>jc}u(g=q?-$U$$M&VnU`njy9;z#hf#ET@=ZR!$ zzhg`=+LumCPp1piI5QBh2O7^yN6F9w^*=9h;<6-J%cYu#^H`J5A`tih(7Ns=F)>n@ zv~%mxv8H?L29nhKY!|gePuwOGH*%$9l-Xo&GEttKsr5aZCWvCpwjjg1yX8yq$%Jpc z%CNYsoB~d+yy!%mc9{W5DrEVbZj+&N!7hxG&I9?aS<*SoJw=J8UF4`!5VV#+Xw$n4 zMHv##$HX!En@90ZIXWkXB3+Nt?guQ- z4J8T43Q`jZm2oAm-L`15 zivwYaUNLN*j}P5}L9v?RfW^!%~_ow;=fY z-YuKcXX^JaiiORJn~(P($$llEaDnMq;8~GcpXsLjCiLAxpTr87H`tGSro$DY&u+L~ zW&h*_#P+40b6|z4Z&U*1_s3t_YTLz8&nLoh9UFC6f z-x&gB_bXmDAmY#6}Mfb0uHwxZRU~q4EIW%>bk}Bg4CeLSyAtRD+7J|mM53MBJ z@S~}jONUK&%Yy)$3G`F*@6NZOI{PfaEoj9&G>RX&$MLa$eb}{cK<&B2SS3Akel=i? z!uTC3%x)2TKxf_viz=1J1^rG5loT4LP~MZ<$9h3u+I2Yd?GF8;1@Wr3$4n3qkORj0 z0}9s7k2rzPS~ziVmc|U3D|o>C6*I?t$_gYFR7=JSYG?omU~T4O@WutrDS<@o)=rNZ zhzWLg999O~)3?V`l5}jOi{4NbE%7=T$L$|svU?Z!6pW)o{6h@dUZk-C6AuhDfOw~@ z5uvbCEZF*I&;1UXHR>jBH%(9bc-u>_xCpql3mR&$eaG!be0z9usO%Tt=X#z2?K@vw zlYj+N6IKS0*zvLBInNVDh7is?)VN&C99tZpP&HwonHiRKUBFPe9`at4=}cGEje!yT ztU;$Fbz)2|uqt;_lyS~o5NoI;V=%mS&%sMUI(EGC`PN$n4HB0Y15NP0?ZsyYl;dVa z_VbpS2+PECTV+QCDJmLS{$*nf8YEu`bAy%ma5+FNUQR9ew5-bV1&}b*+9$f@lh%@8 zm2nQZT=bchmvN=2x1eUQfUqH|D8Pr>1wG3XtoV&bhS%rGJMF5_**54t>cs!TL!UmL zUx3C7SGdHL9Cy`jsOA>Cg$LV2MHIog==Z$TIVr7&1WlG&YG@rEjfhuj`+Nedz3t){=-ASblnekf z%%>>>QBmcMPZ&eBIgLB)HCgdTym0n+LBB~e(|t*jjUPhM9g+uo>>@U7Uy)<*@W}CG zk_Mp*-m?6)qvr6%XLF~~mfQK+71vlW#Z~VdY-S`GG-W?zciZQ8qDXAxLjtAvEp&Tl zDgjR=tV{GxOSyGqjg{ETh*Cj*+HF84x@Bm~UG^Gim$$xv{Cu#sg@tZzTXUqLOXR9- zaxA~AOn^7-3g$nk&^tzcZAVps3CP8qcesz#hcDG0F@qcAn>G^G0SM>x{S2kmj(ze*qHeDC0@l91%(x|AR7>eQ8?%u;+;}j@#lD^|7rAYm) zzYU(j;f3^Iz`f~&xxnvvcdl698<5ci~{qQhjf8y2%cF1>56eE1~ zm!_}{hN&-9?Lu|bl>*!LU?xdf^nhomDhO zsb#?-(7;(`3b^m$DxK&$ovgF=Pc>Lt9}Z+MCP&&F!RV$H#a>o4yXXq+bbH6GW*JZPp(IO%At;p_70`p$`!noPPq=R;Wsm*Ut>?Sxh9&R6$Pov3m>Y7w}}vHfy) z-xHD7c+F;W&)W9LR_~`1%UCTa&wqvgfnSzDDPjMwSg%EDzxtxf_KR}1eQPzrFoN?r zjiu{UUCqaZBnEkpN$3HdUNCm6{3%$?zZ3N_pulRX0U`(r*?TCDq7~t|3s--`hUG$B z_!9JQeThaXS*91*YAEyt^8=^@7<*h6iZUrXxKUPXhGQ{xvn76|;((RRhz_hE$BADn z(c8B46%evNcWn6zgZ$}czVLKH{6Y2yM8WYu!X2$ZitCP*cZ9>8j%(hb2X#%;_^+U` z83yV)_6p5!9tA4s7r1VHxw+s9^z0F9d;z5UHMzMZxTr4@>nBoQ3+{0o-tdFJBaT?} zQ}a?N(vzmh0(havI@t8Pa3^o~V6MVYZL3`!`GBDadgpiO4B@>R;Zo>0ub+IuGn44m zYL#L|tLVN4MO^5#ra-ti)|3#HapRRwY&-ENW^(k{flu zMR+r(gJL0wm9aOeX9>@D!Zq(e5G8J4IHJ-uji3Ihd64QMa!L8^1BkuQIVj+>4BV%6((6Np zs{^2SgE!;%RNv==2Hw=}a|@@XP@mnroxwTVtlNvX-XT6He0!zYf$;o+pGmoOiPGJB z5z%t%O2-XFC5_GuY4XN?kzp*L$3O)sXs7nJOtPzP1(?Wg!Z6&s4hU3UW+jgDe8)Sh2?jPmI38J6TwDQLzJ{nu}t`8atHgB z>3%VghLM&k~b1RD?^0#89dKZ>Cg4;7Vf4O2j7ra7O7hffcua7amp6<)&FW^ zA>r|dZi55?2}{|*;RCcb-0-w;z6f*{*K0idZK^eA6clx7`I^!oWn=6`@mCcO<#NXo z^fJD?GvxioYw#Sk#TegI%NEt6Zf~1cHuf$;f@iysuOau2xUZUK9>#+Qz9k0ihT~u} z_qWjT^ijwQJg&L*-Tmp`e!6&7`ug}F0>K|_aOaP)(k(+uqm58fy`*WxQrBGLYIq2 z>dm30x2#baP9UgKQMDO*h6nwwEc|K3#mEhK`V9tx(egD%@Z-%yQ4<{5%grvFnw6B~ z?HsIof)OiIjt;Ql{$DJqI_-?ZD2u5&a{{`TkRtr;!17M>~{+fMV7NM0d9`w7bOuN?9uU z4NYy^N%xi*0tz=DMZ`5n2|>}GWX+4fN%r?sLhq!^r^ut=X z1lYC)?CW)Nu-0{T@Kx2}n|Inkr`etSvPxaACVB9%nBy{IIl-zD7Qf9as{yCR;?gK2 z_7Z?)z*I+^-6y?a1J)285om0TS^+`WgGUcRx|JMEv?m1_7*~Mpjcdi;3H&ZkCEA@_80SOkaIn$7pp^vyNm8H z6Z|`>md-q%NJDH}02?U8<0hJG{9E@AH8P-k12GQ4P@c*AQnfN!I}ZlMpZBLnX6>W= z(_fq7q{CF5y~A1gC(ls6`uSb-=&b3LvpQ6d#;TkBZW5WDfi{5-5tQEe49w`L#)W)1 z%L)`tANZae#ogn-7X6)g`Lp4wLcLe%G2rk=vkT)PC8)M z@g?;nVLzZP5xWWn$$}_Lzl(5z`+CO^2P<+2cU-Bnh0Rf4y?#IR&8*P5Wv{{tm_vxl zHy|QjY@GdaKbIkAq6{kH#5jL(3(7HO zN5A8+w1VzMV~ATJtsv`(_&-9jJLcF~pU68`4R!>tsP*>DNT@B~dg_mxovuA%qMoh= z5*W}OXVy)5da6ckK5>|PZDDq1{v5@b{1CVzbDiO@j@Fl}K1{?`Z!LX%-QWhgLJsVm zj=;FCjTzHpmcLJqs@>oc!eVQEWyfrf)T_tAX|Nk~NB_C14XjkZujlHG+L@g9b6>$OX|hJj+d78K>R)0>=8jP%?*SF)9`^q2sK=1LYhLOf(x=2t54+ zwNdyP<>|{YAg%Bo-((mVC^gbyk#3BH>XI${FR5@65 zSsL=z5s39gIEi9oVN(56;ZlAHN*##MCbIFOVx#3)@Ji``bFu!aYTmOjIbx&(6U)bg z^J$*5KSE!DpPD5U^wB$E5wKEDX1C zVLB0?7G@SMTt8Bb6qo?Uinw>jG3le#Hcog*1`lJxoGu4m3W0sUbhXz3X7`+oZAB*s zypufrz&}4(-03?NN4W@u?AA3DKd!FhXYAu~^V{*KjEt@0shZ&(XkEQ~6?0}|VsjCkodxrKfh+jhgKFK?*yOI za?S|BdcF}AG9-s#(!4?K`IYDv*dsqUrJ*h}M%yFG*rz&L<7_xsqcQC=(V%jp+oKrM ztB3gXbN7Mvaug4}XCaa6<;D^N)Jf%96T`zhCq}o&V31FpJ`MD8ln-O`XuMlJ?Aj6I zYVhOstk>1M0DtRh9O}KJuoxXc`uPH-;SY^e{miUNE6Gy6M@p#5T)#s`%ek8z!{@w~ zNas2%_2I2ONOpT?=6bVFD;TVlzN_}!8Zsw6D^(_)EEGF8v3p0`7sOQkjM`VbLr3em zR|D$ib#7+^*G_bD;kfNpT4Ja5mQ*hwkY~^h0lK^YO4G|yJsyeM?LY^h64_#AuGx;E zwGp;Ioh_7-Ak+WeTG?7!#Bp?*`dOvea(;1Pe>I_u^;a2=GtE9>gzOPBxLElk@S9N$ zkFW#AuJq>byf^~3TEY+QU*9FOKYZQ$9VHI<74FxDlfnj?8*LCc5OrRKe_8W8oRE=4 zEO!iN5jtCS-%IBzzL>rP7@26i>c`C`2JI2l4eMq)!U}R*ReGR@j8Y@^n}pH0`V2%( z@{H>!WF$18F&5dLdSN{jWL;^@&ng)XRsj3rZ`(0bUw>iV?(yBC!o@(gz?hJO2!t2B zt~pA3vNoy`S~=mf5za~FX%xPpXP-*5lD$^%er#|ZABil#BSwcty3-{}QupqoR z?SX@{W2UPW>)wwde%(O*n#FVrx*B+l#+MR#B^z@}j=hLKzq=b!>_Vs+CP_RC;x}Hi z;>-?UEG;%2TR5r#DpZHD9ZxnKBI|Z~sHm(zZCik8hTtA~e@FvdErJ5U7N}agqTSMi zX_aS=OwG3QoxkFsh#mt5D-pkVYgWa+iW<>;Bhnw-d{8|x(DaBBV@dD|UP9cyU?YutN&2_S>JJlwC8zY={H(>ipcDtVmeH38<^a6QFcs=7kUoM~Q{zO9a z*JAI|gNYpP;E61;lqoG@O7Lt^xPdVRG|!z8Mmrg}q~6&PD7n9!@s+f$=@9zIoWTG3 zbu81Ixw22HT{7mDPuP(c_RmN-hX9F=NbTgPl5sj_GJV?I|Q(N&4shszh4~z?9iT#Tuj5+MGNc9rUQFM zuG{?>{Pnv+-lBs52QN7~ix`^3P(_rfLaK8N#43-7xGgKyBgMWaxurQKjnOlQ3T@pr z!lJiAWwE@mTn%Ajj;HfLVG2tG^KYiPKhQU@h}nQ9bG*!V2qA9ktR`b2zaayAJ+V~XS=E8;M;1mdUTn?qDF{Ke7>~2cj(PZTh_b#>QEX=Nj zmPo)*N?fb_m%`{UI?f6j!-_Ji<;X>q{M661csFL&)Yi;gIXGMWBDUstEWSFQt}XA! z*;)rh7vmyA*7I{u7N=qZbWb&kKj#o_3MI5wGA0l<^>aCJ)3>T*OvEzX5}I+s)JEVe zl{sAqOHhPSU@v*|4B%&Qy2q`rzV*XC0_6ZR_7+wfo~Rnf^YE(1zJ?){Z|ae)B8vw) zb;LeeF!w>4cs}hW>}BU)jUWPnSOJ3>sM0|(^T4H3V?l|-_`2+9UGKEX@mA)UT<}!} zLPahxSvI%w9r5NP!+eb9^OeH@m6o`qN=7Fn&5-vT(WRIl8PkVL8?x%OlvRp{9tJ?g z5@#%Dja1HwAp9w1oDy@X=7``%=G+p$%Fl+0-6669mP>|crb5uFl$unoD_y(V&{XtU zeR{T4#rD+595*??%)@EUJk)}58m6MV=D|~(w&|r?%#%X0;nhDv_T240`{t^NsD*25 z?~Yz}^+M8+m?4?71Aq2{KS>e=43mJIizY4Iy~hS_Hl;S3qsE2QVv^w#&`w4L@5~wb zg~GgALCE z{>hjm{sIC_*n;LZixt6qR895QQ6owaMc8p!j z;npdxkr-@Cw(J;lw@j6aGy{M$j^8}3U}6Z%!J(hEeQ*>5EMsH-JQ*rqOf%E|Rk~7% zuwQvmLqia`gWW-bj6WK`UwKA$M~#_iI>DW;y3&lEuH@T?_AOxw#yzTUr39aj8H=t7 zx~7q^W+9jZ{GQUZDd8#)f!UdD))?(l9PM(*GS@6~){Kr&vLqHidR%e;@v=AT{M6W?4iUOdl)w47+KRCg>sPEtL_&ZO*>=g6`ixx`Oe|V z#L^o-=T$RqFP%<(0o_{B>vBi^k zgOGBCP_rg;9Q7n!m2E9`n8GHVZ-yl-07+EkK(i)6QjLmsp>xr z<{s7I@XEK0fvLB9=bdT@m*@6+sCusnaViLjPb^U%Bp6f-m(_T|RN&h@G6z%MK&F;6 zdHa)js7+7Brz&>*-7>LAZAd#6!#&g%ilsm#KdfbCLR`xR<+)bnP>ie2QcYLkh1*lr z7eXU`ukHO&t!-n|_3`docnZa+QwIn8|>4Mu|0 z4hsD(!oftMAvF9MIwO`1B?U;rv7#bQL7S)#q2REx_Ha)cwTEAm<{M4(G41Y_@#F9B zdg93R$V+k=&JGjYIa3)98hK54Qy7ktH>BU-ZW0XHW!-y_^yFLgij3jiP;U9SQCtq{ zWnS0y`0G)adizoAc|#$Yk!((FT&3PH_UMg)=p~K#d3!g6J%wL?A_IcRLr`MR-{UC# zGm!*`78B&2E8{#mlqiveD0lZ!6{VlUgqKa0wN12HmXBA}xXvOd8w=gE1!^Td=qAq) zK-1*WR+kjJ9pUIF8|(v!_m9&%$2rS0`(i!Q4#9)$v58##hKPF$A+N(nHaTSSe~clD`_%_){l-J zL3hf3CT!Mf)_EJ;asnS!g-@6jP@O7IS|z7yEN{$5ZC%%uk^yQtjij!{1KKXB70%L8 zNpkOTU9V1%=p( zjXIU3#$Vhlk7z54r-dtqF&v{!s(I@sGsOJKcN+Qbyj;b3;&LH&F=AfqX-Gy6Fc)Kc z&i15RF9Hd;c)(gwxjrULL9(;z(1-a&>WK|Z1vujz)Y8oHY_JK#Sl7|RF^rlAD`(XP zYf9k&NOgktSR2PubejsYjscF}0U@2)I6IT{%O*PuPOxPT4qNR%t2y#7yp9V@f#x;H z7>51u3@m4{#vmnOe&`Hrn{iDDXDi+B1o{bD^|BpyPXLCVCj59M&T)i8ZxDQz+8f!5 zra@sPDrD~3mrt-}heV$C86TpiS8M;k9OA%wlBdA_MeE8{ipofucJbo z%v6WG(EYKt(V*GO)HhVF1Kxw;Cc%Q-SDS~3WS^5lh}c$@uGL_K)UMs$MF)M}RR9=aLYrYbpp}%qXe@o*72P zL31o>H9K7`hs9}0?T5PXj|7PnYgA|tJKJ?uJ?T@UwcY;RE7<&z(t*X3V-G8NDJ5Gq zQ69~MAw|U7+qIaq)(lh0ok<-LGUpG9bZfyApmRmSp}PaW@+$Fhr^R$-@o1;YlJ)jgF_SkA$F*xz&2HM<5xa$T<~nYvck3Ma612UR>B z9GWFhEBixZ#W<4j+cxm}_*A>MvX5?6rS_xXzu9sDbd?nXd|1hOdXS6hNiMAh)okLy zfQlIlg96qvZC5p_TVF`bpG+~U*(!s7XltdWH$Aa+;Iqo?^rD}B#4uy=t=TW3oFKm5 zwZL*C9BYK}cADgiokPd?0im|jV>UaMq^U9vQB*ZX3v$=Tg{M?GB-F)`I(6E@;+N94 z7V5T!pM9R=zVr=PQT@F`s@K_=6}U_kQxi&!1SIImXWS;Nu}P5)(Wu1FdqQ)_c`>&bE6+&o{27Z*)hd!obU;K|P=EN9nbI`gLgzOv8gcFvXBz zEJw1(RCaiX!QK*r@b$#Djv;|~L9AmN0$c0aB{Rbj<1gi{rI^7vsaIKM#LGbZhFn{{ zSAi^iSH3BaMCw(}mBhEy@-y$`k9a>yz!}n3d3HmM6Lw^!6TXzh$E3^i z>F}q^^Vx8)3;5~qpbPk!l2}&(Kuveej~hCIwD|0gYiFHEUWjH8^fsD(EHbDB%1b8D z7Yf~&5Bowd8t{NrNE+*7Me>v6hV)fU+%?p@!H&B4}XT&TuC@=yN=v* zLO`EAaL9*C)#wdRl5MM)KZKgy@RL;jUd~UTX!%L>mMC(2Ro3ncJl%rj%3nLb+NwHGm56Yu$M2WS4e@3 zm^7vE_R>pw)1j-nZ%Mku(I_#$k^_(_<1tjQ?|Ex5S%WS@bs#7loXG z-AT74D3_|>%41h-id9p6Vt+k%d=4ea$hRbPnpc)9FBT81`XU!L(y&d-AxA2b_Q=NW z#A{yRCY$TL^%msXAh4Ht&ZS1oj!V>nRa}skSL#Om;VU{U{W) z)+2wZL_#(6sM%o}&XGN)kkyBEYK3&#d@&M-O|FFdWnYsf@c;_+E`?q z6bMy$cut_>#N`-d)?Gik>O5qx%}AirJQ-s2+Dxb748OXgt&@hL(>H9;)l-kch@`HIWw>zI$K)UJ<6Ot1{?~Q2rt#40&dspct_}&sl0pfuZc~$( z#F(t2L674y?U3ITUA^maW2fHVe6qXiV!)7(rS6Skqx>K6_;n4NRF4z!c~rcFnN&k9 zR#dTOIb8CnyJW&f>}P}@o%5PTl4Q^Hnn^owbOtm|APtwp*Yi$HW5L3=tOf5TW4ve| zgJ6;yTR;n6EpUHhkey$jFI=Lc_E}6nt;wTF8PhB|ToX;dz;EP%VR3=bQi$6N0btN* z&>)j39rw}`C?Zb25oC2loU!toVqbatsjXporkLz~VgHb^kYB`0E5u?7X>}KFX>AoV z3vqRY;w?&L5Glbiei!%8IqVnts#V9L89O9si;-jJ3f1VS#g4FVCL)=8Mb6JB1$QKE z9{k>@pp!brLMxP9z!Q;PARu`!2jHcYqZ*&hYoowC;+LFBWe|8wi!bIymZ?&_|t{;+rT zUVA-j{hk6M{+IeGo|rp*+AoZChtqW`%XzX+GG42?Z2@nUD+UQca4PVxE?fB{T_nB|Is=GDeQ<_lfXVrA}Zos*+2kPlj~?axpV9 z9u@NL_bgVaHr>Ky89u#pbxZ9lv#vb+zpL2%lH@IJt#b&E;Y<&w@6;F#Y}oAQXvWNV z>W;*7a6NL~yA?D4EwITImU#r_F)p-gm2&=d;cpuQ?otXmq<#W;9QM=&9a1vvNI%?2 zY!@rycmAHZow-|ftCV5*G>kYbT2ZtP?QWEGh-T^yjwY87_+2F@FvI|2x;{1!PV{l0 z&zeISQ;u13{AP_}$Z#c&SW6ehHp>>F{K7^Yb2wn05VCKY0D_4NY*s!U@*5s)BOg3S zHy8^*-3pbg={^B7ECj~|?S#Fe}BDAD&*lM9UpLr4n@8N4aOCEL?LvnTdel$M{#q=?W}bFOKg#=(P?9=S!->vQkkU4I&Z7Bm~iM_>fWq|&6>}xROcm( zd|YCdvk!;qEAQEYrveD>j32^{dU;iIEoL8Uc9&IB*}H|*RBkyo)y+m~uvbY{Kez*j z-6V#Xo1(1z7zRsQDm>RpW}CgwNsNoh=(A_1TMV5!5HNGh{<()HMa&(obSnO-yuN5g zjfgQ{Qf*W_+Mn}SfHXYO!H5jKSeA8Q^aJnN)=W}~(re5aUqn7{OfTgKD^!fyuHmlSf$3CPchM{6~IJ zN)Rb_E{$InW~^q6<|t?scZG`s0VcKr8-_G zDRiPIVo>mMMs(OkKxNENs{9U)B@+tU8z*--cvzM$4zagH4!6dsa8aF6kZy-{N)^IC zyr@jmxx~x36cJpV%N)Fn8E?R&!y;SYYnYp;QJ`8_F^gV> z3*5JfgJ*#kn-D0lO#}5S(k>$+zOixqdIem~Imb7nKJAs<#Z&pb)vKeVOqtV)$hPFy>`BY(ua>TF(egmTjvF z|8&!TPg*&x%O&RTMn94i+0*e9)+)Ur0mM0-&h!=HJEN2}1-a!`R0n^2ZfQK^>Y@A- z>n}$93}-RH?OXQ~6iG=?{IT(85h6PwqMBF_5X-A;0jX<88AK4nkGf0gcM6#Hi?!-roj@RgMJuP#x2{Gz?ouIH_3T5*bJfBxhANO zoKK^<#Ru1*Pe~xlDer?`kbo!=$0_)OP!M5(1j72{kA_>E<+aAsD5x!ABKA}BLC8}X zsGZ3$c!8-Wt9P@PTa2LV6QQ6m4`j7#y!;;RbOPpQYC#Z;Ms`tcYdr&l0OjdjBR}L0 z8gCA|@Bz?H;GM{O{lMsR`#{`{P!Q44XgsMimOL(SdAIKN07`H`0rwqU5HP)p@CmhJ zal?5gR;q_Z>lw5*EcZ)E$ylkL&YU7}KAk``#xASCaxNOtpFTE_m{O~ab6S-6RNc0Sn<1=4)y9#8CNaiy=h2 zTqOr@K-0apWWXM6=8~t3S{vQ&N4xWa=v07Voo5HeMSZp990!@Naw~*;*v0llVR`55 zZ!)1S;A-={=71Qt16@?0?=3dwI=Ij&GqE=}a*d==GYdOX5LAgdTqvp{FT+aEWS6Pb zT(n5DDj`JYl3T^mz?BC**xR35Q(?ZnKPnmgD(5a(*1JVt}NdAGjhW8$|h6gVv+KomL^ZmGEseAg+<$C|j&X;7&FsINeM zw&%2Wx*#CHpf3RY3^D?yhYVeAxPi%o&~e#fLcrzZhBlIu)NmsJ z{j|o8`yAIQZVeDV@xHcpfs$AB+36U&^^$yK!NN%J1Ekfgh zUrWyhP+vOuMZ>5m%FmYXL_r2daU*rO?*;-!H{aROQg>dAngKEf7TpV{0`v*3cASUG zNxOEwU&WK>cO?M60&P~^%whpfZ}>Ezfe*iXHx)-r1;2&G$^Hcm*FegTymptMk7!0B zn|2EeEjIjCuc=?Y-9Ok(mu56EL}}N8l`ANzm-UfZpwwdU(VdB{oKp5O$?0E=vqw@` zlx^DK1rWRQ-qVe=T{1DSYSGWEr0~iMY-ZjINMjgEex-&wZ|^!1<0Y(x*kG0cYkF?~ z*q>PQnb~dyzfA^9;)6$2M-mLX)D~)N#U4s4Z!VGhG6WrYF$*_rnXH+#OA{g|cL)2zyAb?UHD z%ggBOSvlzrqt)HT|AFmT(NcvAB+mA?nc|7`sp&^G4ZHmS|T{6#8l}@l`(kgV*VRXUCvOv_Ncy=Uad$nc;Na!k&)o*(u z3U`7o=*(N5x-pRD6zTfPDWyQ_0$F_?N=2nfe{iB})JKWggaT&1BcAM2(~8qJ46agA zZ_AOSluUGsKq-EF;@5y1lNc?)Ua@h`b+@=WY|#UrqF}rU_j5hGu8*DCCfHFUv`QoSiRD-N2zIHk50Qh3vXrv7_2B%m%$^C~l&p zI$$J`sWr?^n54=^{(FJczO_i)V5WJ?d`vtfXz1s#xjH4|l(eFWLAu3>A5_AJd9-|q zK8V>8qtZro?u&X3N+J~>rgY?Hx}Vl`C8A?x#cw9=l<5ZSl@><0_OE@W8 z5BCG|hEx1?5em`65|Exad-Bq!gS067LLbkue)ryP>+(aQy1#y(0yd<{z32sB^#Wl*o)U79VCJG8fC8OLn25M&g^CDtr{PYBr)z~( zcHohOr)=e1|BCJgk`HM|DynQzvR`Fa=kAKk#l8k}4(g0=w#-VopV#h|7+?wKVOCy# z$wNeh{gP_ic7q(84LhU@0?L^0wcM4m)(TE8%CRIJXv~?vh=heSx8?!~D5R^%-i~n9 z7>Zv78ZIv{h5PaMglV7hSc5b1o_hT)dNLkHNbf)a*#d6^{>n~ndE9#wn6qvUN}W$*rmNk^a-7zGg@up71}}TFQXKc=M*wB9zwjm@fW$&_Gmt}? zV|wNfXP1$}1J%hB_hzGAIwgrAG>?fz=@GsMu3EWle(}hSI>ZF}1Y%k*-N4Eb9!yA_ z&a37}`bv$0@FnOeK>cY{gbY-l|*`sh*Mk zRGsq)uFM6Q-**&cQSy}>C+^jh^t5yc-6jecX;VZ_r51Z$F}jB{%8{#|Wq_CyD5*;X zGMO~lL#n77#0|7E{8|$;D5)DT#~QqgGg%Q)Fx*y5P3fRwrfSWSzCuG^I<07up99lG zipndkE8BmtvL(N=D)-3#D>E5ZUb><}63}5Ps0LmnvvHSZC0*0F;)Vp3+Sck#r@axN zrqr~;D@(TyzD>gO^=A+MFTUKhzo`2>kh~KQ^a+RSnlO4NYRL%+**$#)1oBNa|5a5I z2(IlZ)Dzen!6?OpfOCm=szb{>kp@vAZG4j^>%nB>_BWr_S%yioUiY(1t%^1Mdop27G{QBrzA?chO-#$<1N$|{kobNPR zpA(S9YMHz~CRyha1+EA!vB0Pxw9nNT@Q7>A5Bk-rvsaI{!^279B?Oo(GlG0|B3Ze z2A~(L))(kt4{=#{#)-WFgq!`$%+)Xi(gy{MsxlQBi}8HafO&%|UtF^oI*|7PA>LjW z1xEUyVpc34ykj^lCCOX@k4CKMZ zjaK~b@zUp>>2#LHxSBXw2JsL%OmKD<^xXPU=S;TX2YOfXW7I4KtA0M}&lM6I0^an9 zI>iHO_KgKPGqCvRVOF+2#s7{X+WVI@K=C9V?_Bzf@u3m5hr#5I=e3HZBi)^)!=T6~ z=5yp;9~3R^J%vUM2+kL{!y{>rTdL3fAp+oxBUG z;z}z#s2Nc02-;Piu+^OF+Z^<DT#(7It{?<6z7%K29~7jHpWL7aF}^XW_Ux>+>l zYL6ENw3p@rn^!Gq_hn4{VrEvU!F1yc?=KYNr7XmQl%M%Ni6*>LbSovt@KH7-(@u8L zWj9EQp;?GVA2Hr6ADQ&la=+xMG*Tv*IYqB|)V-*Ke$ynjdNNq?#U0g9&3Z0N!egp_x>#BcZHVWu1#uuE!OkG8%5SIgr97v619oZrT&r-4WUj|s=z zKM9{K;mcXlXTdih*@B|#--NjwQ2--<%F&m#l%L1+j{R5%l?kg=B=+s<1A@)wU9eYn zl%eRS?F_CuQc9CG$^-v(f|D_lJRg(IKN1nPdE&gZCzd*6aMTHPv;e`_! z!-8JyHx&TsWN4ua7+x9o6QD_11tyAhL&#AUPC~K6 zy^A`0QE)0zHYzx)W!7_>RXGsnlc)R6E}(h9HT<#RQRf@@m+WC@k_CJWZ zXQ+nhvERhp>u+U)>py&)8F@;e(uVZVPh|eA;+UHG6^}l;XT>UPcC#R zjgl?gq)xfzS!G2CqIVEM>Fh1c2HJ2&R%i3$sq8ghZ=fe+ee4UpGWKl$KrlxVL#f^r zQ@h%lG=pi9QT@^`Ctti{J)=m&8sJiDIDR`ZLADj=7_LXI$MPk5U@Zn%6-c6yn80Og zkP^akbQI6xM^k%q6HQm)$azNYx@L^c(!#G@X4;W6#$|kiSSVS(72l>EsLk=6XMkiM zt}1}G$8g{XfsOT4-YIy+Kv0np44p&plOs1!InMSmdU>nS`dg$i7v3+msg5xZ>NlIn zK7AiQP#q@FPPp((Z;BaM{bfK1!%QnoxExsIB%+E6)s=7HxL0STS*##CKdXJy0u|{4 z2=7J^e{D21EO(xL-{;?D}!hj zQeOUlAmV>`i1~Z1yb#}bGCD*M5X%2|%n*`xXQ6;8>SsW_Wek230NLaL6`E>aQR4*Y@6vm5q~Q5aV*-r&>Vvp_EN z0jgjBN)oC4&3y&a>n$77Y`BN|Z)Xxdq7e{3?7_G{FOY=#hd%|)fDVfV~93}E(_ zk@eyBTpxiVzq7#Xvli~1taRA{BGYTBl{P@I;^9Sjqp6V49v4mFj@hyBU+=qe0NOY9=Gs_0~{ z`mO4-@z7>>Y~dOfN)4?tE%-LA*G5lL!qw$s8}V!IE~m~Yu|CK2nltY!)L@yRR z$w_i%+U7ALkg(^OcA>RR%~!IASZu)iYB+1Le%XtrA8!?3#@QZ;CE z1%ws@h=aLhW(>wBFzTpz5K5{I)F@Zz#aIc}J~E3^fBuEWS(vMW&=>+`M3VzHD8n^n z=#d+GVnr+WY;*R|c!W&+{H+5vh|Vb&c8ovPe+9U(L*iXOzlF4mP;8Mej?!!D|KjMY%)bf8C|bGRsFi=LGK@@S_0Z!v&?E z(LU+-7@w6x^jo|FLPa_lV}Qf^2% z$~C)7rPwEqez8bXV5v=)*XYeZ*u?UD6>cFMvvS*~Z=@b~?>`Q=(;@l|T&D^D4t2vk z%_WFoyj;?CueK_KLQ5MW zkYmH9;+E-@{Vl4ZuY?JNSL+Wr-fvNyVXZ1H>j^5RTUlMl1H6ffTgGOfhMV4DWXdpt2r?7&Y z9g9R|jjZs>iL4FW*Qj9+=A3I)4H9j7q~#&aVS9MCDle=G-H?ak@Fm;ud9uBCtu{4L z`31fu!yk}qh~T|?-tmuA@__gVgKS0Qk3wN=La>b_54U`0_Br=-eOEOKaIArdQ>!m}Ou{3^4IH&PORm?u?M0?!)?J=X=+IHK@aMDXGu&?N4k+4?xe zYEJm3*6{q>+qMvKL+;H#HRdtgm)7KSZl3lqXfxQ$=02s`E!SpypCKW%aT6FU=<%Ts zr1i7b-x{DuPcZA_%-&LEnjGU2&JQkv0aU9=AD=QnHF);9C#8{meDLHvQ5-iVd6bC) zN9`V0s2&gWI23UZ?}iKXBvB$P=UZ-FZIX8^6qK}dL_J>)a%qvw=;ow9E67(++ zzjFW+OG6P5c38Wv%*!zESgd*}A^B!XZ@)IVeppVS2NCN73)_=9h{**tqHW2;Ev zTrSOk#kW9}Y}nrYWU3D+n&|_}52F7a{{#c4&j-Ir!am>qLQMZzIjQCdzUSH2f5C&l z^b+ey=mB$J2n(1|fIZflNLA(fRH%qM3L)x$MGQt+^ub&0Ysvc>AAT1}2eQ65(*ro8 z8Lx?mEGDBGU&ZSUpI4L!tJC&UeDFI+yF5+oYv5;1N+ z_O>Duj=ut~2`IIPiu^V(aXmTE3X&Dp9NhA|BAJ`J7ckt7ehZ>XFZs;-PxH4jKf`_` z`lM4rdtjAcH(tNDhe0G#aXaNa(TWLrW*|nu@w1Z;36HOxy`NhwDGy4Q@WE21n+RMP zJ1b5sZ>td{85qJr>NgF3QEO>|TQC1H&`^BP4y;?trCaxX#fL_WyDj8PR0)OxxI&OEm9{RH$9*>okyKI+Kw!S_! zQIG?#Cu5E^)+ht`;JNY-K)G;XYA?c>;}mPIvGNcsvQ!{j!H|&~dba@aH!2*UPPtY| z&mO0 zoyvk0_;98xc<&X^p3;Qo6;K>Y<>I3lTIm5=2ATP|lCcDAq^T_-jY#gFw?>C)<}a9L z$tf^KIHz4;xlN$`z_i?{@)EG%842y3T~qHUk>MumsoVh5Q`%^~n3+ztcPj#-(%(F!%8 zp8&kZTE_$#84;XRY<~m)>Sq=;O0Vep#Ds?U)f&0mH&UDYA3hTXFG@u}7USvSjo&D3 zx<|3_j{wmJ^$NpESb+UUix1;|Cs|wHSL_@*%>i(I_&EmEv&QUZw3tO)%4!YggK}Pf zkzk^Vo?j>?h5fGacC9t%B607gw^{Wd!LCy7+*}##PYX7qFGpJ(ge$b-SR|XOe63P9$*w3SXB2!`1_inIID4m z9SVq2s0s)2ke_Bk@H(e}9yDxlg9`KB8kKqEeIxttc<%$Hx3{b7W?qrE2hJ=brW`pev0&*HxMs}wM#M0eg5Y|!SRqM8;h6<;WYTuuR}i|p@jP!DHCgbka_@b zyKIS^;cvW$W5?GW!@V=_&CQeapth1h^V~w^6w|EI1Q;!$p!$VLGU`{llS-+vK*{95p#>i0Ja*WK*%I4WF5c%S7P96 zY*@LP|c$`$)1Qv8#&Gk5-PHviAo3xgeU= z9WL1{E1i}@*Xk2z_13<;gaNu#O&5xDG6{r=~t$*xS8}N-v3Q=8hRk7@CG*3Mz z10+Gh?v;LHboX%oW|+Y*tDI5g3aS6bF!I)-RWqG3rnqDO)^A3t&#mRI{it=`tnWeU zo`-$1zrJ5Ve8Sg`GNtEo@qs$h-muY@iz8~bJ&zhykhh&(k9m)3eFKhLx$(){<1*-7k*s91(eh}2+HM}%OuSSc3!honS-ZGs+(lFKlKykkdk)`e zDlYnau;zT~_e5GLIwU4W|MxPs&7sfb^h!bvi%+JEIUjlzJDQF#qU)tbePPRBlhA0gz}~?aqvq6|J9OI+&38Wwfcs8?|u+VI1fzxM1nW4N^gqwfpa>q zf6DfY=J%BCJ9;yde6Zu4H#L!%PB3V*XSh-EK|H*96jP|+&wSu7WZf{lQylTO-;|hM zl?dsAKfl}r=ouie_5+-6?Xa=-F)pr(?44iHAK=jWr{wdG<+%#5T_a%7=X>Tx(Ed1L zkW&W9(h6M-@?%KKLeUhBT!0EAiQp;F3bEmsio-Y=AQX-hJC|2HfQ-Y&(@>1%!?V;u z&{POPnZ=7O(f^YL8Hb5)L?tH);?oFBw~h~nZ;Z@rAtd$$WvPLXnjluA7z1aQREApn zIh{pF3<=7DW^Mj|6B!ckFwf#zvu26%K)k#@+WxHe-e!C_gQ-L}?%$a4o$dF`a8TG{5(}M`<`Xq{IcTcL+k0}`G_8mRXCtX7! z>;``J#M6T#IPT_Mi4qvCL4>r2#s^FcQwX`ipUpeoV`UM*8$8hrfSdaCgmgcEtKP@* z{70eh%N<--|2oS$1jkb9>6bgMFxCz%H{|V|IIN?QJU|W7S7!>+g4DSAhpeAGSKr6W z%{8~h%=Tw%hm(bEjx`bcRKW!S9#IDR=^Hy^eTf6$-OgJbJz85{5H3L!aq;xK#u+8Il=+mJ{U=|N2;IFpYi|MB*tlNJTYpA5@I zVUfYT)ri2)XjD<;HNe4g8L`h@(UfGrY%lK zo2RHPudx|_%SP~GDkrea(5ltQ{7iW(-6|pbz-waLL6a?WB{{fe-sxt8#4Tq<1+r7z zFhHJFE)#IU+~{Rs(0=W*A0mN4)vJ0U7h63`&UNNTuBU=`@|n!ZXlJuH{MLxW&3pK8Hr9nRd%w5v|(Qc@^X3Btz;8^SyqVMpVNg#nVU> zNjNYt2o~Ejw91a8tr%r;oRuAUvA4=J*>0ga!dk9yY3ZDh1tl}#OTx&tp-~%+mm_@w zCI&SyVB?3}=CaANP7;7`n}&*Z)lu8kn^1zjYHh}4uWaILd(PML2@9|3>SLRyy1duW zXW@*hV+%y|iUnmA)UlG#xu%jh8Z>p(4RVuL?025VfVC=eF-+c;_ToZPjz(yh>8~!g zF<6HN>2UQM-VF}-u7;&6RrviZ^7XpTj7I=rsHzX%PQi#?qbD#wz9mMgN7EWrTQ7%{ z;${q+22HDvqfa1_!zzpYGTbk-(t<2S4yFp2%$pKaBHmR3xC8XKI){O`mJ;>R@x-0U!P72&-z7r(}h8q%|g;L zAAIYKq`?BbHI+VP$7s6`cJME#KDAq3{SQKk3Z;_COv_LVN}{|FUox%DSgE=)PIo@v zII(x3VWL|q4B)XW_NWpLQ0Z3VU2bGY?H&9pxxQ{TIvgk(m(6k!F$Uv15#b?FRu;`H zq974nT}Q*|6qINbqET?Dy0Rkg{jPknm^A6b#buOHmi<)qd*fP2Q&p=Pb>+F&!E7tg z%iJ}26gQ#Sv!SH3w&27?x#`0@q^*l5;&R9B?*|XTxORG-k0GYSqyg7)WtB%L*L`_p zQE%bjJ3ru53UYQ4=RHr^B%Mc8%g^F>fE4T&kMSYCqx5!{BQ;{Xj3Y@~D6uc=)bIHn+u^vw9Mcag4@9-0hF|~a!JMHHXA8|S@0$J3%jS)A!ysZRonai1=UT9- z!D4|Tn9VDH;Du+6U+}HNhNO2XrtoTGDe8Xa48K>=)2lNSX^(0CWJM;6=E|HqPFVh% znSkD{j3)PB$Rk|xb|&mEUux2%`LiDm#$(=$KDI?)oC~urx|7SwnNVRwr_NC70#(Ue zNie9y7)O6(5k7Uc&do<=nc$twS}l zV(`->@7EC2D1xJ#$OgT!24mtU3SWo?vMa${fEb%Ssm;pV*YLEa@K*-jDUun)26gF1 zgcH)R?~kidd0AsD!eRT)zBJ^=UB0VfIP|aJUq=3qGLFz;Au?rW-(EcG7m`xdTq2dg zV41YSzk(3Tasx?96pMZ8nME!Wb$l`3fe=%br9H{Xu=iL|%__G8wFN_gJ(QhGV}g?f z)aBx>vg8mcOHOb*(L2n%>>XOH=!nxl*nI{*f6hexYB}hID$CUIE6#a_pJimfeXGmI z!S~@wA@*)cacp}LDKNL$q5xqhznbRJqn<0uMJw;S!N%o(|B%Q+_G7CFR9*P)$v>~?5O|66gvsE|M zv_?ny2%$R&NshCxOmhNI>P^y-2?wy)tv z4wryn*p?u0D`193qKZ(5GfYSVsq~7$gHdlS zLn#zIzBQ3iN=q$d0Ms&cXOcoZnviYFT7V{)!d4oHX^vzV0vvMyUaUewR#R=6qGVm1 zryPxYAgiA-t@?Xuqx^*Sw0{>4|B~(j0>AdY!2Wk8WXUWFj_6xWAowrmCy*qPd5WZd zD}3l9u>aN?zI_?lXucm=I2oDRngQIMjDGzxa{~M_ax$_rbNRlq|2{i2{Bm;mzU^XV z<_!M-y_fWCg#!xPglZiL_CLCJSA$xbG`}-17qCh7wjw|sjsJ3Ml4lw3XF5WKku1Qd zUkWb%EhEz+r6gSu6B<<-_y?C)Hk1k3e18gJPvQAWyZ24opwOkJ^Y!BERw%8_SDpbG z)oOx8i~Hol_i_7#_s#9@d`AHYdc)DH#1#Ex=96y-eecs=WC-exLBCH(C3sl%2D|Vq zIWRi*UCNG|4&t?vW4~!Ga%1w#wMX4-!Px zGl|E%=pL9$V+NRXbhlY?AvI5vItt_HtVY^onmBciBzM~_nzd&%R5x^Sf?u8BM0I@!HVmh{wg`lXdPz4jxcv?_5~;{ zRST1zbC;?S&nIBccZHT^h>^`Qt(ea)6EvAO=(N=UniSoj?^F-j{-DjNvyW2fZlVk% zYO>1qYUUPSt}9tcX(S{xS8M3?|0;uwVagCJNU7#2y2u#*ov1D?t}u_@ktio*Xa&1a z>j-Qw#h4t~7aC{Q)%Xe9a$l+odC@Ag8R;)X!%jM$bifu^aD2!`zl?S$-eg&cAx&oy z3$H)smDwwUI~W@s24Qsjle044jIS`?d^)hileB!Nw;7LD6qTRq^Nj!;HIpujH}s04 zsD?iDo5Z5gl_;G9$0$*4df8Zn_asZ$stL4!u zraGX*h!et1^07ecjON=Z0CA|GHq;5N_%^4cjr^lxG*H^zTT>WZhm$`TP&Fu$f%KM4 zA(y6xGR#)8+2Mt<^+K^JE9UCsl8K#Z(Z=j3?7B^p`~*K~L(V+(9Q6vzzA`qn;sF%n zwPLowu6xpQ)p0(rFR!c<)E^$amYiphBk=Xz90u>&lR&zRjh%W(?id z<(m2Q!cx(PXSIA)pW@PGmb+vcR|J$V+vsiDljQAX69VFf4hXVfGkW4OqNe0$Sfd4; z<@Ng&haeTPK|!)cGv9P#fVBrt`jg-G5+6sb^Nm|1dJlRYre8}J5B+z?<|IR@-;`?M9K&@AZ)?bs6IKNEsG zlD@?;?T)@8VN*;HA*v$dCJcg}IYQPgwSK;Ee+J9PL;RgQRF3B?9YbS13~?Vrx({{; zisvWQeTQ0wS%f!!h*`9bJT<;$CLZ z&J5m4DKjZ4DL8Jd;NDnpUYj54E+|)TZLd7Kc+v6HUq4*Lk&$S_F_KiDEDW11A4>-|i+(kxYE3czeT)n)u>O*z%bL)(9+^|N5>bfBs;aVP zU@bXm)*1~zaNsIB0sv~(wZ(-e({mRuhfs|j^IoKMnwHE&@GcGFk?}cMGbJ&M%p&Mpuf%2Yu2xS zn={>OC#Wad8Av*eAQA$8sW(}y(lpU*8;E4~EPEqlM^u-Gm@w#&!;jjOFZ3nY5>$3j zoi-O#dGF&XtN8e_9J-AN?v?#L{^vnAzHV$4QaCW?Wg{PlzTnunBaO6Ha*A3B7NWpV&Pi4fj-m>hD^dco7yZs6{n)8~W*S5MWX3(ze61P#z zr~MO$NA9~eXw_0LOb3K*H3^H(g0(kl3)C|{9Yut^-fInfVlLVR_n|Im>V#(zP`+Un zFq)spSMdsHj$kJa4D9g`8Xy-?ixsIs|VxZ*;S%iH|L7cdzKoS@V4xGIWX@4sT zth;FmEZshfat4*;vtPX1g(?`mZ^b9i)z)lTHzwP~c0$vE2u-^_x61&k6 zSpd#|I->sC177rSMqVOi-7OiD^I(LI(k=Rx70mdKi3sXqpwe6b0m~G`AFbEu<$%&imO26)sPXgmR@m z#WgW`%DFBo=ABptsg`Ve_tJ)c*~Z-!CKUO1`7vqwj+{ zX+EAjY1a!C*aGWz)ERCQq+dV{9T`X!eyOOl0Fn52PuBwkiK4XKWe@&74C(r7_3aj- zeuPUD+gLPw_SoEcTRjq{X^JgoX}EX6Cvl}gZ{>~wW-(?a#W95eX;WVgg_LqC1|Vi- zR-k!Ui7L1^9Lcn1HO-;2!0i@Xe2ymlR~es?{RBY5`k|3jO#E<@(`(>?Ww;CUFIXKj zxWM`APyYIU>V?QL%)Mp4Ee-o%zGH8Uq+b!JNmJhBK>m7wq9XEjI7R`W84{)5UpOTS z9ac!{W~Wu}TzHLQL(B&+wb%9 z4x^t~ot%wqK~h9j7>*Rx82iB(`iU!)`wDKl93qxE_6Pm}YIk}v@gB)2Su71y+>0~- zq7Z%yD77^v<`kMeO_w06A4C371JIhJRFl(6jR`dVJ?^Eutm>R-)VjL%?f@r~4QPmZ zs$p(N^HMjmLsdeN)6BfczuQO&&CPXXBQAYMS zb%?Mbo3s{>s)*6Unpvkwro)E4F1q5s)UzyW&^rA?|91_)+m?`k{G6Cz?EtkFWF_(yh&Ya2 zo5YFtkD!NmlT86au>T*-)s4kc*9}5$$>+5tFNgtBLMh4E<9xe2h}8$k_CLk+*4|GM zvBg|5^*Kv4LtB&@TbN7w5D=Y)atJ#r302Bpa9g56)%J@MVxVCt{RD$&Bv#;m7$La$ z`~uc=$g@am`uEfyF1Wnn{Eb;D^lP6J=wb!HELLbOhZ)sLoT#qab_TKg%`(fz?O6Gn zc%+#|h9}PAs4S5kU9LKazAr^oE2SLoQz2!>F;@g1hG` z(=CgL(|8psUl}~z#y>e7frBgtE&1ebSocZYZ>W8Y6mZgt$@IGC!S3ZS=GsHJVp8~z z)A&(Ls9dEhlM}gld@z3ORay1D>!;tM{=bfgEb-9Kh6TFMR2>E^cAMq2*m6L$0~2{W zu)5-K9TUfk4@KxS-R#t6V!FKfR0RQ#V2r?c7;An+{p332#e%P4KSFTX^mD?nLB;O& zwlKj(*F;lbkYM!xsqC$z;#!tBP=W+^*Wm8%1PJc#7Cg8+0|a*%+}+)s;O_3O!3h!| za|U_clwYi6Lk7nQgh zc%MF%P{tgAQ1_`NON{0R7B!zo& zg>9Uuo8$O4N=PkurU_r*tP9S;7vUW*#}mLJ#p2zoRhx~&$?d_y>1RTN8&83V%#iMeJn1Cl%()&X1_8i`2O5CXp4{FgLZ$aZ)AiV`U_~PaDfL-#!`W*ixL99I;@(y#dN?*2=iPsOq$6kM%;RwWBD5))srl0EqkNKjLfSZEB3aVti zL+Flyb1!N8aY=rkIdf;K^=zg7`Mg-5{Ksv!fiDDeNC>OE@iio(3~O-Ba2$}tNJ|_m zxepZQLhvqp0&b{Gv7HhiI_MIOPqMz>Lb1mw7|-J865SC=&B+Z%;D-B@X&33~9c)Bz zw~{D3px#{WDPE43%2BSaGI8Evbn2$oUbV(EtIsLh*V=3EG;8p~1yQ48BQH69)g*SY z!X|Sk0mYjAlj%lRaZ)*X*dc>lrEOUg$-P`I`8F#;-)8 zd8zDEXBBWYk7?LlLlnbOlTYznMBbbp0U}AuS#^zu-xXnO|1r>LTF0yFc$!2<2l!p$ zwE0s}Sz4m(Of6!4{MQ88@1mDAayS8HdZ_a*%lUTZtxq4~o3D^8bS&1)JY72M+-ri$ zMCOK+R`yR|dSMy?O->R%XTG}8qQc01RNV?6E;nShMuMJgQ!SWwX(L_iVGfNLfU$ zmodu{IFsz*iG)=(U?E3#tNEyb$FbpDCA9F(j3~n@Et10tK(0s8nUd^R8+QHF&n~)8 ztOb7{(ROI>UHM*2%Y7b)@q2KCujKo_4dg&QS}g3JIu6HBu}6*vVV}O9`yuhA@V#0U zOB`lbNl-=?_t$Kyh@IXkjg%Fg+pMt~vsS#|zK@pZ4M%-I) zb7Kh_ZaQMn0GK4mfNOmeYX_9<9ZuKouY;rb)B=@I?HclA)nvJj@}*iTVM&FI-0uh` z=6z3yP8~HKpZl^K?z{Z}tv|a%fP;(!09Lv&BdVeoKf2n)pw`-*WS_$2Zh3qZPQr>Z0=K5_>l!%q7LJb@2; zxmT?82*#S&miVp&WLCb=9h*BC6Y8im+3aP?T|ZTqgfp@ujntZbz_&zmFC1zy1?lcx zRhkq=K?xJ=&rJ6y422Q}8rpUOP7r8{TV$XzT99lJN=bbY<=ttYqj?&?nClJ^+%kH7Z1jV_SZY09Z3%p^)E5iwGEC})Czii$A%EJZ zkDo`Hf>DV>`Hxa@Ux~kICXyIiB#}JL)#jmTSv_X1Gg`H&^`kVwiD( z0#K;(yYP{K+jFgAv+`I-IBBSwg)o*oOHp8noNU^BOhMp7F5&66Yx1~l7+~P%mk6em zM?>%XcevMklNWD4i&^c89!;);Lg&2X&4mCzuTZ~Ga>Car(HM@?^Q?1>3E<06c3S6~ z84nE7l5`h(W7?pzjxFekG@&|E808fLyuW)-Zvj0e&O9<`nggP*T!YjPGbrn4=rGX^ z@ktZpgc5v9NL|R+;?#YsQNJMvVJYRn%FjI%+Pae>P=L0pfNDFsZ#edxJ$D~9wKjOv zo4YHV&Ye$0O>ha=2vgu6oOS&Ao&a_U-FHeZ_HIYEafGACr~n+$cZ>_3p=VbIsH*ut$+0@;tFZ=auz z0Y6uq&ccX$=fyzV+2wDL$`)Ok0H`ePU*5~iWi$Kqq_Z%YydcPF;)qSzF24jhU;>=9 zGzX~!dAuEY(1vu+1uEP+Y8Cf6?Bc&cC3{?wgURNM$3+HN)|xpd8GD%CL8hL!HV;n_ zru*Ed)TgGDTBCf!^xzfq@9N2Y$701$DyubNi^t|r%vyCbxrw`cOGOgrIW%P1~}6Dx^K96;dr;TZvUPh*e_IF(Qn_A{DT?n9T;@U$lpYODfrmI$-lF zS8RK(BmWFOdgOBFKJ8=!7TADWe&0`i*j#sexT65P+}<^VXez0~;JEwoIQ7uJf1>Zde0ONiU8UuN2|+eJ*Kxv}Dj8 zl8p7^GOaQG#a{Ze>3SqI&UFtA(Z}I?xb=V#504MM`QATp421OkscQ6kfwE5tfyEU3 zWI39mRYs|uRW>P7uv4fe=a4Wyu4zTKZUyW^Glc$0jAQamh@}dm%b3>$HDF;>q%8iilA{C~PA;%h=#AAPOc0Q1 z5np-VWUCP_DqA+y)mhbZRx}pqkuA)cax-ouKHy2IIL&dg=<^?V7XHkf9XF9Nbi=RL zu}leGqqNWQ4c4c-C0&b`he#m(FreR4p0l6^hCA!lsB=6#g;MBRTVz5uWes~ z;W$DgII7*@&Ec{5R8o5UyxE1rprn`@Nm{X`n)}>#0;j8!eYqK&8qAqz`d#gy9z8`Y z^qOH~Rnc(6Iy%U#UEoPQSrt`NTgW)I9@ysf`EZ|}rqZsZj|~t_9iq(ZRXQ%iGpajA zIDOtITuLpf&&`(YaRS6XC#ECsAT|mK#D?;H{&}S9aAvBnpJc5!I>xH6?V&X}23OT* zX-^#Tpl!)lWngD-Sbl4t#zTmq8d*yIp)yC4I{IA98wXQ4hFPzaZl ztJdSFo3|}qfeHxC)XtPet60Tb`dq?@T$QfuT>Ye{T&c4=UkWSZraI@Srm>b+o>poW z-<+zg!sxMNyIwIQRiAtfSKchsQ@+elQ@5dd*F)l_lO#(xL*O#p6dV;2HOgwBbozk6Q!k~q`4h&C|CF9HV7b#q}|gIV87_`&f&av@`Do8 z^L0^RGe$?08%9UO1{~710Mw-u`D)u7%~B5DSe@%U>c(R6#0#;Y;uVR`PgKFIeV1-s z4DVi~pBULvkGk&})cN6%c51#9nlGb6X%}lv07DNk{5U2`7+}~Z3yPpV6)%;QARd)f z%q`eVG+G1j9tYsHb8PV{CoT!*?JW^iDxf(|yOXg~$iKE1VPPO9gF}4O&jm%KskEg! zL-T88&fijXBfwNppsAFweYC(*oe8y2D6EJ(OUQ|%#hs+B+L|j$v@8DdWcl!&&9W0y zo4<;0a@UkDNg4Sfy(O89~w8Yb1K!Jx=#6a*6;AjE8s)grmL%usIPX-9D3M#zA#B` zxec8_!{j!5I$M}m^(16H<(ts{Md->M>p}(|y=B(d)6de~+<3=BvbbgL{WGQE#Tm_W zIk&EWG?z_zClpl$XT}~(m^tY^Ah8Cj3Du8Bn*2^q+UPuTPlUoB5~#cZbrxqZy)%Pk zv3YV5C}ERShTn~1B=9TYN#1;98to@i4PRnW=no&iHwCsjmdE?)uXP?Pq!bfS)%j^hCuOqdS@DJ>};{K`@OM+ueZKTK=PX z^*VxG?!$096!a|>Rlpa4U5Uuh>>8PuNTqA|&UoKGhig7xG{CloL+`Cdf_GiSO;h@= zZus7QE77Rx&gqm4iww6g*0F=04TZ1eFrwPExm$6I!?%cQ=}rnWSVg2Rh!J18`g`h0z6&ecffQ4Vgi>9jn|C_4 z4I|!wnnL`VGQc*IWYkpjz-^zhFNX|?c(I+h?fvst-%(V$=w;+YUgj<64aZBuLqop? zGG1AtFy4i%iOK<%p{t_mu!nn^XC2hU zswc0#b~tK@}0~h2&=QIm$NWj<`nS>LMy(8Xzkr?0x-tK9|V%902)zx)=F{`Aea& zN(+_F|FRaj!{lfj)~^fJ(JB+qvHf#}2zKBu(57XG%OU57DJYfx+K(CU0A8dB{*=0 zJsq%Kl}Nv4GMq%9#5508%`qM@Qv;{aYCo}h`feOebl%IdwKbLK7)kdzC-&HMtf_+! z0r|G)%JBO&oT$k{sZyQP$+87Ud6D~IIpPgM0>Ni4T3yZA`%KhSM$xB{CUc(qQ6%gx z?Ug;Efku}#&Vf&#+pDBng1*o@b*3KcsmK9dn?A);boe0jDRzAe?>-EA+x#`Cj*7m$ zi~Ti&WL!*-avifEiTgg-_#Fy)G`Uwdwx0c<#N1hNRP9}g-7}{0n7jhevP$p>ptLfe9l^NADJ$J(%3<6Qxh(@0&-)awdV#3p8nXII zeC%b+M6Io~ZN7A8omqBiVq#*Nfk^cdAhQ-7L!6 z18<1ZgbeqaK-63kJg`38I_W@|xwKgTm1~dlJtm2dBleEMtJbtucs;!;X8`$_QK+|N z_zbT06vTPvJPhg)6vFd(go%u*YW8EmaENFZ^+3-JA^(hM7B%B8+5j#i+1~A0PIVOR zX*MclnV|Lx*M}{VPH0mVZB~)gp-r;ZkjEmsvUh8CbR23UUy4wS=Lp+C^$+u;tGyEM z;Y9LdFlhB*R$OPvxFyQvEy<5PIMMP_qUlh-|D0hF3+1k4BX`W#i&*}b&n$&vd%PW_ z)@2~I=KB5HasQ}+4- zE2%Y9K(J6ClkXd{u$}s!gCz!0M@@+GoHUGjQ)51pP8R}4-+X`EeTVlGOQ0}eCd>l%mcZx!bYBJ6EpC;Vo+H-@fAV;uQvD_YzquQ!nJQKoU7{G=W z3kt5Y$TyjoWw#(Frghlxn=YE&XUcxA%8hX`+$j`t?ZVee%_~n>wz}*Uj_?Vs#`$Kc zj17N$KlnB)EGJdF(`czrq-ko(;sI(h8~s{$5Ua`ZstN$ga--uk)q02wKgVq{e>$w4 zN%bOqOJa<`ghRPkHt4X2Q23MRM>i6dYqU{|&R2`@y`cc@CFU1qSf2<8s6rcrPr=oC zUP-Y*Mg;=hrZZV0ZR8VziJgk)O`AU3?1fIO)!qU##S14&w9d7r$8GsC;f(L!zzRB= zAjTKQn~(!k*vuup$tnCvJRj_-o`a2M4^aG2*GWd)Bl5P9KO~X1vU-K@^8_}ZA(Sc{ zxB9iHoY_~xA4xj3yV=Te2RS>YR=$%WeT^o$hw!*(8*U?DmC$N+#eN9Ltk@Q`-}5~^8BUTK1rT6v!Py5&QHWYS0DRkqAA6o zDiQf0*D&{AD*hHIw}c8vjNg*R7seRuuGgw>E5iH9zRUFUgW0G3o6MbGauY)uT2AH{(v*gLFo3 z2f+9O^G_b$Qw!7p8W-B1Ufk^>D6elCT0g>RI^<@ILV&pjzw$8G9Cg8^YpvQft-?%Z;yYT!5qS+;!0$WRx*8p34mg_O z)ju+|bNs1ei#&<(=o8{0)K6-adY4$AZ2s>@+IfQyV&x#C)dU4p08jyumJxtN8PEXL zpYot*R7#+3TAiSevtBVj11L1hrDk{#VUtuB!AV|LLWnaIJz zCz{!j8N$=Z<@rxf%w?C--c=%7mgk&@O8=~36MHmX1^Y`%R5$k!` zF@mV!S(1BgcKE7ys)D@`V2KuS>c#+TFJ#U97fTh5+|EB%!9^9OLpQz@Pvm`VzXlnW zu8ryqWleKMI^hK)98FgrbJOCklR&%2qN7k*|A|f)qBapb+y(csD4a;O)EZdPQ}`{n z-teLP;an9f9vCZihJCfETI;DsTH(&gA7zr)X(4gwhw_6eZ%)$Cg`Dz(hlBvtSG)(U zDNN3^4FHD2`w)!|k`s%Tso3z(hqb}b2uxF|Zf?G&EBFU<6)2`8hd7SrVaCUMP3Iq! zs`!Oub`oEB+GlF*eHfNuZH`*$f|=KYnaM;Dbl(rY$NDV7&(7?Jz`~S>KyMglv=3M> z=Bv_h5rK%QG1=xF#KGY)=t%(t4{PQ6Cx+ zbUN)Z1m_|F89IvTrtlGms?j#&k!*_8C+26bZ9g!}Pcg|UXym#oGg&5MG8A#p*nG~3 zkY0Uj39Ah~E=oRr;!|Sg@XlHx7-@tV)9{;TN`QXS`?OLV%4c^r1hN(Y!f>W!-@ZJ# zvW3E&MPXP05`EfMju{a8_Ax9p_xm_b?7nkrxyB53rB) zS?o5s>lSvuHNB}6e@97qAr|2$R&Fnw2F>gmQ*K3yOBEY0R}fk9B2MR?cvA+xlEFwM zvcg9gy~Vn2-A2Imq3=VvGzp&VXmF?=5>V1axh1HS(@gcmR^ph<3>{5dSbr2;{J`<2g(rI_7zt@*Y%LIT-)hST6BgU(l>spX0JZ3Jf_WO!y zWfL0WzyuUY^ms}&*-w(+I1}WwbX`X-k{+wSjHD;)cf8LFn<)nXS-MuLsIe-qr#*xY z(;vDXT+F(?y?&y8Ays$&W-K1Uh>hq0(q`51k%PEkk5;+G`I?;E{#e~+Jw8xM&P|Zs z+eX0dxekIT$68}nQ}jLk&(>upYBt?lyxtYeE`~ks(qL%UFR?2;NH$ZIAzkO3bel7^ zS7OKC5yTf<7`k^uiECh*)o)*lR=y2%8K)u+al(3$uluZ=rCvddP3akwj^}XXg{DpJ zTZQa?NQt&jH-px?n8YY^9*ihUB!6c7a&QkI4MQPt_m$+nzma&qqAGw9rJ>O8z<-`N z$mbQJPDbx$4yT3~f!cCZQ&^Xf(XDSd`~yBMx7(IW54EWP=_}yl9GuP23(cnI!x_FR zXraW=ZDh0N*dVLX?%^@)=bzwDL2u^?prn5|(TJ@BSKL`XE3zebHeB(KZAs4J+I(=)_8_8B-Jj5HT$L!0*@YUrf?P1YA;1=2AN*;~Q=)@ZbM zU(gi90+aaUj74VKgVs<-7}iN*&|4`YcNiDONkhE$OZWZdsiNfWG2ecz@brur#Elu! zqUaFeL22>3Z(H;ak#BtQ|V}P-Rk)7!ZfJPN$4+)9O z9F(gwPPmkK)3+}t>E0GoM3WO*d-qL4uUG1@u^j_4gF(u?(7CRkrMA6+w~m zG#KzserxkQn5bMh_zRu5k(6k1vcqNpD}9@c(>06-i|el9KdB77XZoRkg8ii4Yh_5^ zAQnz*IFjhT&AiN5dwspV#rA_}urX1pj}v8x8R9&3|7bKM@;TOPM~cZ)YM4E32(lhO zQn&Zh6!2o_yUBJL^2cp}Q_(DZaIX;7=-f5CrFgNvBy|Tit+SdC8Y)%9Wr4HW61LIt z&6q2bqOo~J|FBzT?j_HLAuFn50Ux=`ovKHOVp=E@L^2sBp-*JTd$dLTPPS_)?ygwl z;&(I((R>r=BAf6`#JIVG+6M^HHE6>a=|Pma8IKyy+2fY1#pk;K2QyG~AxUhAe+SC5 z=O(|*B~2{NFg{ORjm)wo{h`O=jD(H1uXM>zqZ~AHGR(mS9f=+*kz&v%u_-w+{?N*Pf6d_ zk9MmgJ=GZ=WBS@k&u(EHhDpHI@5~NGnE%(ORR&BWd8K zwW*DGhkU=oo6wf6k9&`nw%i`Xfr4JOCok)bot{Cp-mbb7ZroK(w{*xWS?BH-;-JMbDAX(0lshmKLs3M60HqT*bke zRaB00l`w_NmsEQ znWH~;VLG^$Q#-1Dq&9W?vs9FFQGN^F0LPogGpVW2-Qf4n0J4)LM7Kl;@F$2h&UFfz zq%m>y$#_?m=F`?9 zy@LGvmpAH$$ISIpDkXbVk|vuCa(2RBBneHe<)^i8PdNOq;#G1E+qg{&l~|Nfrxar(nl_8Y3 zc`0)&F*-`q=~+LHib& z23m8RllaYPc9t4>QKLic1grH05Z$3BjfvkMf)}K%i0)62Ts`pCXhRqfo0e^B-HbYH zzZ2xvk}KJe91!~{9+2(!zWzOrE@{>ZNuw*uDnK+L!}CiCOT=TC>vefmp?hK?0vBT6{k6MErk16l z?m*nDbXqExr)QJtN}YhA^$x_>B$lR{0~J9qTp7-!+BoEKP0x67qN&hS)Fy6`mR{6o zlxRbAaDT%P$beQ8c>fi-mR_{s3$*2lI-`}(0)B`j)?hX&Oms?2@pJ-VMO0O?D{5t>&gIq0E8I zDA>=cNDGrzh`3Df<_Ecpw@WC2F7uMLl*OkhbSmtrWh3l_x2A2;+B|YflhXwshCX@< zOS{aMCgRb|73dB*Qe4@j?kB@}iqS4eCmNJ3FtVvRwK3N3BXFcuj%0XOB;j>ul#b|f zWE3}5+>Ln`J^;YG=~cV2E$cKT*r3MH2o5Aq-62OS%y6qml)LFwTp5;X)znL7w0wDV zJdOzTPE89Lk49;`*%i^VLfB91v=<)__#0c)ft3DA@4`}QO?M3WZ3m(D)ZHjVW+YWe zvBDdeA})^M1_Qz@WPvULBVz#$^@3zM&S9x?^-yd@X#5*aqJ&b*-$z*4?cQEsr& z(pXz%Gyuv(clo+lskufCQ*nx*k5+LZAK1IVQopgT)=8O?qaOD?KuJkwrBFZ$H-EMS zKR~Zw#0suaA|UJnhe0>4we8C*E|U0axy_qf4Kd^Mh4WfNtK|w?*pM>9HT59UqRO)u zu>>Ao93%-h&Oq1H%IJ2;(I=Kg??Dd-({Xl8LKeW+r5i>576$9tur8=vN$Oh3SRLh2 zr*HHTO=;4Ai}~eF<8)k|Vi>5P@;ru~t0zPH0$)C0)(45u_+sy%wx;^hie{N8Nb@9X zJZn44Cdi0N4ml)>{bq!h0v^VXp;C0NjVUA3E2Jqp@#1Pzx60wjc6@!x%hwf#_p##g z_!xkrgk3hW%19d`S%J^QX_4#)ir9A)Ia(EKJ}sa1@%E2E(1?WEgH!8c z<4UGjQhbJN4XU<<)t-2bf%*f#G5rh^h7+#IBkE z?o689iha;h$&6a=pu^}X(B~q0o3Ur!TBuF@rh)#m{Cm!=2?VYew}ULUZ=E~6#Uo;A zkQ^)G9T$cgCSeEpTB0Z!f*Zmux4l{v6!|gEkm7q9SPJ9-tF51% zOM;tqCt{bPtXzs)_&8QDQlj&dxDI)d?kp_CpSVg-?G-&he@Ej9$<=h(< z7wWVJY+8cUBH1)r3(F!Mvft_gMoz88=&_=39ix;zU$z@yf^^gdVb0sstJwB+96L$4 zs3q2^HEK^bx2DJl-ddb95dLJ&d+Wi%Q{Rg zjnnn{jXk}^9jNsQ5QfGL0agkQbeF54E82w(kF}1sWWg^V3PsNA49U^tFramGBJwRe zgm1*-*%&zG_)#M%!rg+=2nX0`%~f$9v8tB#i-Y-TV=Qmj5|Na8ij1V`qs4m#1{h`} zNpZpzXR4wN0}uN}7zP*!`D?L)H8ZYD@9Wws*~+?D4bS_Q_8mm;0d!)NN!I$_-w&(C zPJ0u)28!lO9KR;jDT`*sQk~3`7>7|j#FK;tdkaqCEBA-#&-R76J-9U)E-nEw5ugJV zuEew1_~{A1nY^4m69^ zLg8Yqw+DqrfmyIP0epH|IynXMr5(bnW_t!2rfBm=cybHAeQ?p-hE&Tb`#RJvl-^qB zgJU{6ja;AmF1=W%9TRCWz*L_4;MM{6kYY+iAelGdTHHya_o=GKa}2%KH`{)O7*IX4GcMf+;XiS64{S~h(HuRK&TGq0<>+|`PkH0ysZ0n{y^*<$|WSc z*9i0vae9J9elvVxfJfOzaq*tsW36}NI(mN~?tp*OuMa`)XodgM>Ld-fzG{02eX+8R z*;YbXdm-yum>)`q<*O1Ou?4P7CuMIjt|bebw@E$Mvh1xMIT!gslr*sDbwzmCf@3c? zWhKp108k2fc^I(Rd)$!KZ4fudn0@O&%Ug@(hfP&lmYh#;Cmy^_Y4u|BdfjRrWvAxT z19?}scZpiCgP(Tp_T38Ak!RO&<&FF3(~gZG*cRKcNAGUO=gLW<6bR(QUHNE)bRxGM z+k1`cRv%=Vgo>auOdEZz@4^e)}#`Cc;|yeRa;}VAwM3z4{`Bh z=1;G4S$q^6aDR$hT1W0|J+s{ZMq*$OHuxse;&^EIunvyLPbuoahk6^n7yas+QG;P~ zN0oR`KzDD7ww>vhwTRmGgId4lniA|i*ZiD!d+C^80|$K^-xWi2a$9oAlbU{!*#&yB z)Gh+BukLm+&~)Vkq_Bk5zUb7{U<0kZIZaV%!ZAVnIDo$#v<~kIB+8ltEyD+#%f!B3 z^A=#>Up*;11GD?*1*l2y*p)AZeT9l{spY-=>B-CPXzC%l1jmPS+Xrd11kEL6_&N@T zs}|^`CvrQ=>fTXcsA_92MmUP;ZbrZ@C{zIMpkF#m)}wm;ge)1=dgMN}mCfh?H4=(- z)qfBl&eFaryJ9Y#rjoiy6l9@kEx6lco$&FWZTQh8I&Q_1yEz8luUHp`X?u(K!gN-NAf>Xxan+mV>MDk!;Qo-PneWXb=m) z9|eECv>a}*N7^AX`cQ+IoewoMLrZ2j>fSIyW0CyPS(1kLK-M~$GSC#=Rgx-iHi)qm z9D7VIbVR@ZKc}pAes845Nct2I|ctg#yr`qw}&VgY_gzW{l{0$1Pp}XvK#F z!7+Ue^v(XKu+iE5Do6wqJCP!AmE*Svj$`-cxzm-ZuTAV2vjl8`bXBA#v7vm_yYkqm z8Z4YywPK;kO;#Ce6<3E~W*iAz>O^JN`-|=o9b#F~siR_>T8&-dCh}Qvp9RM!dxEVx zBcHd_z8OX5)Xu&oiL7>JE)gdIsE9F5uDiW_uJhN->Qw>%u|stzw_7@4V$j#Z9dp#- zf7BIcUi2+fZh|UznrGtnaY+W@8?}InW*aUv1N|Kv`qLFXgM3!5z}ytBOR&lg&!plv z%j5a0jNqdcxQ%P5B0{D5XJlj2RHPlKHHy|Ld%oV9m$G+G>0`)-L=MeK0C)cG)T`EQ zFf2~>BEMGTh~o%f`l8FEc~4pfw|TS|f)LPs6)oZ2l)_74Ml+y^B3+`Hgi)6vqK<;b zt|P5aJQY``A4Oojg!!cEMf4@XZwoQw$sQ}{yl>zCAg^a^=;7^4komiQp7kKwdAeFA zvaR?|Xzd+od3SJ+H=W2wfJ54+)JPbYz6xbdx^r(@JoOLrl9QuPH zA1w*SXA?haRd!5=aA37JejmXMI`YUGT0PWloF=z89pJ@duO_ve`p#Y$YSG$d|Jf#i z>vPA-o@4`V%+@$}$99-1g8t~R@^QkDJ1p~@3@$}|%{!}^>`s+IS9=bY&YH2=S8ouka_28ug ziVl+MT{(|TcemoiWilEso^y&(harj3*(p|NH|6&1J?zL$WM)JrM~)b;%z$M2HjaXo zF@h_HcYPv~QSG{+$$+rWX>f}s`u5*sItCRdf!Nnv?wMLBvBlSPH%A|n)+4wyc|A(5 zZ{2}fM~!vj2kDg~)hcN(3@j6yJD1$%W5)_3k6xZCrb~!89t4f@uAPNORf&e(M%w=F z9pF#fP>39hk2Vpu) z)zee-I+ZM+!ObCGQ=v3mR(yQ^h*1OoYWst-Izemc>U8Ff()3TA#b?6$P<@uS!Ei3v zc1ro{V$adteUGj7V0~p6+|#~7o4Z+dDl={{Ox*_zKNR}w-NMYf`_ML?Lb^wPYzQ{v0iSRL z&uqGvIW^j1{VDCe6#;O%66mj2$>LVsRCKUVvW+Spb{hS>tfjP{s`j<<{l?b>1%F>_ z8^(@dDFM4VVMt^{e9(SpObjD;i)VLKMznT~cX>WBqH};aIj71Hw}Gf1C6?+7H*W&* zXz7<_x_K$pir)7dpB$7*ew^}B=SZ;f=nfVWxFQ+cCEKKYSFiX}K;Qw^Do0@^SZLR= zN-s)?WlYdK8X&y?J>J8M+Xc>e#%P09zbd-sMskBTM7epC+$;X5&6ih%B&hmzLoo7rlPqgqk(T_%=&23tr(2Frk_>c>|ZtTIUt@?n*s<=)X{15uMd9w%g2NlaUeJX z^09(}{7jU<>|V0J{7Z=%mTvgwn7-m`!#DjArxdP0RXJmwqywCIuxsV!==50bCY9a6 zK^g|xim(dRMe6)G^yUOcMT?bOYs(cb2-sMRctc0cuAUvft;fOaoQ#Z=BOh~enZ*_s ziKFrLhe@C8hs`5Kwx^*^p;z25Z(bM!TvKRoP#+BeizHzYv=uM`lX=99P2nFQU82oe ziO^eAV}LF6jC8bF8rLF_a?E5F{ZwDCNf}EYRR#2W$Ba7ib{AlpeRu<~yu}BsP@Q`b z_UdOOT<6d`kj@RjCTR@iw~ce=j5EfLj9L+i+Xk}OboA{DNo zV}Bf0T-dukVOC>qqu%Y7i0P|eX9|t`^5XWKI)}`BlY4DWP9^VrqBqTYAJIM8gPVdP zpxbzG5j)E`Q;HgMOZ}P3xCZ6PaBr`mBdv6@wWhmo&9+KR31t-= z`c^YCc4=5H&1edI0^$KJHuTNPt1GD00E+?#wsa0G@~w|<#*4BFcw^#C>!~)IgK%hB z$W1UEThFqW(^IyjWf&Xx&t*I|%Mx622^OWEwC2)oQH~K{uE(VbA2Jr|#f;&fw5obc zk30y^Wdeo18hQP^`6<-9kl~=sTU~Aj?vXRMG#shbfE8(sJ9BTtarGQDhljKW2Y}rm zK55a{G>Nb}9(qlKCisrG83TcbwBr{5&6yRgmDEKFvv~E!Td_~aU8m3OS^#lt2pOaQ z;)unmQ9zLW1w}~t+PJCLY*FpyL!ZJm8x-`$H8;jrT5{tBrgst=KZ4QPXuqf&G1dff zWb^{@e52L6Y@1TB;k-vuf(^El2>{pvcty;WMhHjjFK`-ax^v7i^?1HfTlNhave5UE z+EYm#yq+FC_8!Y8j~HK1XutJ477@ze9^v|Y>K?{4eyI%p+ETXjHf!bzscJD^r;ngL z-<2^jfz?OZGCgweU9vHcih6_Eo#KdMq|{`lr6b)#O(_IVYYEXFQd~oHjX7XUrMMMt z?t8KdD}WUJ%Uyg1+H4M>!rD~q@zshF*0U{`d(OVjzXNk zlxDsvGJi=#zT8V=(AR&r|1=FK;?U{ncttt&5Q-EY74>695>oxNDY+gT-vY7qV)JN6 z`kqCS#TorH7^g^6g2fU2&c|vRLzZHxMzjYrqhLB`yV@e7>oeslJ2KRh9Z6d-GzJ0` zUqF?ftmJHsDRsi5061Z8^cOtsA1OL|KbKCQ__$1B`)-5+2Cb+xDqp$)cKP#@Q`eaY z--Tb%mxFN6f};f7F_CvT`mcDU@OGj_UyzOR-^6^xAkilLV(gwljsAhK5B2T1Jxeqd z7!Bb7%j~VuDBflCA$K8q!UIW-{NxL5JT0Z_>*W^#=W+|xnf?X9^bZ5H6GgrefefmS zc+HHR74S-?RjeoU)uSJ<0P*t8!O7I`ekflHaWFn=h63IXxxkW%xHY+s*b@{#>4x}x z9Oh~5Ywrkg7xID5GaqVbLfa(>+!gnFZ6hqHC|fJs^!n8DJp&p1|uGm6DkH zg%0SGCM4{da?j=-{wmS(j9`|U5CsWS&cpSl@@h*|RjgQ~?UJ-8??BJFB@&Pzp0UKZ zM^$oty_s>`9<-d1lkUua*4M~djcQ3ey32B6nO>iJX27C<$HzLnVj`VG8JTc>Vp#ITaEf;=*N;iw+@lu3hsGSo|`-rUzUyn$CCnGjA&+6ox z;JZxgH0f7FzRMgd!BxUo(@iSc@0^~m@fc$J$w(5W1vK{s!hrAmnR@hmI_G(PDiD0S z-zpT^u!0@21+2LRwTQ#}w*2+x;a z_45?|K_m~wJwMeMyz`M*mx%tZ%-(_HqN@{<&}q`L;mVBgiN2Vyn5H7Ek|JD^$#Cmm zHHPcMddVQ(z{RiP)(;M}fhtJV`wvaOfqDau0Raapizf!EI{epx0(LI^>!X~QsxX6; zyf~Ah%x@GJ7z_;PYhf^(T0w#Lpie@e7Y69{_fg;v)EgxP|1FOY^t}JCo(0l-fS%z8gU+3;!0lJ%I(% zD&P(yE~pp(ISTv{c!0TFSU@Bur2n}_OICziX8Gcwkr;CKwntNEeC!XjnxI zB!d*VH3{|WOb#bWKqIc8^ZN{mr%?YnB7baM_J@pTJz$R_DR505=YKl?$KF|gkhTm! zBk~jYUUs#LH$P?tag8K z@cxPavv}u!2?hR9?x0ehwEwXzBEJfF{(ThqpS%D6DChZK^FxjNw}{{7htuOf_USM4 zV{C2tw+RA<&-}VprXIlR8Sa1f_P?b+!NBHtE`)~D)|0H?+-LC?F zgE(OByy!nW^+y{1-$2lNfq!G-?*D}SN6LBoD2kD_tGC%?T-l3KN`uZ{0}Glf2Y z6|MZbw*sa?-!cAuGsds}`mSgWNU|oNMNknex H*I)k+3{@?X delta 48268 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 SuAZPD0}yG#BS;tw?Ee8_(p5YF diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 69a97150..8049c684 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d5..1b6c7873 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6..ac1b06f9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell From 84145769cb83eeb7020ab62d1dff7ee2954faed8 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Fri, 15 Jul 2022 19:35:34 +1200 Subject: [PATCH 04/45] Only publish from main branch --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ca7608d..32f9dfc4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,7 @@ jobs: - name: Publish Specifications uses: peaceiris/actions-gh-pages@v3 + if: ${{ github.ref == 'refs/heads/main' }} with: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} external_repository: concordion/concordion-specifications From 96b9ee856ffde0fcdb21a51c3803eecf940708c6 Mon Sep 17 00:00:00 2001 From: Lorenzo Dee Date: Wed, 29 Jun 2022 14:54:58 +0800 Subject: [PATCH 05/45] Update to JUnit 5 and using JUnit Vintage - Specs were failing with JUnit Vintage because the ConcordionRunner was instantiating the fixture object too soon in its constructor. After modifying the ConcordionRunner, the specs (as-is, without changes) are now working on JUnit 4 and JUnit Vintage. - Also fixed ResourceFinder which was failing on Windows --- build.gradle | 17 +++- .../integration/junit4/ConcordionRunner.java | 81 ++++++++++++------- .../internal/ConcordionBuilder.java | 11 ++- .../concordion/internal/ResourceFinder.java | 7 +- .../extension/FixtureExtensionLoader.java | 25 +++++- 5 files changed, 105 insertions(+), 36 deletions(-) diff --git a/build.gradle b/build.gradle index ac8b2231..c5a60def 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { } ext { + junitJupiterVersion = '5.8.2' flexmarkVersion = '0.62.2' githubUrl = "https://github.com/concordion/${project.name}" issuesUrl = "${githubUrl}/issues" @@ -34,8 +35,14 @@ ext { } dependencies { - api 'junit:junit:4.13.2', - "com.vladsch.flexmark:flexmark:$flexmarkVersion", + api (platform("org.junit:junit-bom:$junitJupiterVersion")) + api 'org.junit.jupiter:junit-jupiter' + api 'junit:junit:4.13.2' + testRuntimeOnly("org.junit.vintage:junit-vintage-engine") { + because 'allows JUnit 3 and JUnit 4 tests to run' + } + + api "com.vladsch.flexmark:flexmark:$flexmarkVersion", "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:$flexmarkVersion", "com.vladsch.flexmark:flexmark-ext-tables:$flexmarkVersion" @@ -78,6 +85,7 @@ targetCompatibility = 8 test { systemProperties['concordion.output.dir'] = "${reporting.baseDir}" + useJUnitPlatform() } compileTestJava.dependsOn compileTestDummiesJava @@ -165,6 +173,11 @@ publishing { id = 'wangyizhuo' roles = ['Developer'] } + developer { + id = 'lorenzodee' + name = 'Lorenzo Dee' + roles = ['Developer'] + } } } versionMapping { diff --git a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java index 887b2e6e..65b4bbc7 100644 --- a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java +++ b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java @@ -13,6 +13,7 @@ import org.concordion.api.SpecificationLocator; import org.concordion.internal.*; import org.concordion.internal.cache.RunResultsCache; +import org.concordion.internal.extension.FixtureExtensionLoader; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; @@ -33,42 +34,34 @@ public void invoke(ConcordionFrameworkMethod concordionFrameworkMethod, Object t }; private final Class fixtureClass; - private final Fixture setupFixture; - private final FixtureRunner fixtureRunner; - private final Concordion concordion; private final List concordionFrameworkMethods; + private Fixture setupFixture; + private FixtureRunner fixtureRunner; + private Concordion concordion; + private FailFastException failFastException = null; private static AtomicInteger suiteDepth = new AtomicInteger(); private boolean firstTest = true; + private boolean setUpDone = false; public ConcordionRunner(Class fixtureClass) throws InitializationError { super(fixtureClass); this.fixtureClass = fixtureClass; try { - setupFixture = createFixture(super.createTest()); - // needs to be called so extensions have access to scoped variables - } catch (Exception e) { - throw new InitializationError(e); - } - - if (suiteDepth.getAndIncrement() == 0) { - setupFixture.beforeSuite(); - } - - try { - fixtureRunner = new FixtureRunner(setupFixture, getSpecificationLocator()); - } catch (UnableToBuildConcordionException e) { - throw new InitializationError(e); - } - concordion = fixtureRunner.getConcordion(); - - try { - concordion.checkValidStatus(setupFixture.getFixtureType()); - - List examples = concordion.getExampleNames(setupFixture.getFixtureType()); + FixtureType fixtureType = new FixtureType(fixtureClass); + // Avoiding the instantiation of the fixture object at this point + ConcordionBuilder localBuilder = new ConcordionBuilder() + .withFixtureType(fixtureType) + .withSpecificationLocator(getSpecificationLocator()); + new FixtureExtensionLoader().addExtensions(fixtureType, localBuilder); + new FixtureOptionsLoader().addOptions(fixtureType, localBuilder); + Concordion localConcordion = localBuilder.build(); + localConcordion.checkValidStatus(fixtureType); + + List examples = localConcordion.getExampleNames(fixtureType); verifyUniqueExampleMethods(examples); @@ -76,16 +69,18 @@ public ConcordionRunner(Class fixtureClass) throws InitializationError { for (String example: examples) { concordionFrameworkMethods.add(new ConcordionFrameworkMethod(concordionRunnerInterface, example)); } + } catch (UnableToBuildConcordionException e) { + throw new InitializationError(e); } catch (IOException e) { throw new InitializationError(e); } } protected SpecificationLocator getSpecificationLocator() { - return new ClassNameBasedSpecificationLocator(); - } + return new ClassNameBasedSpecificationLocator(); + } - private void verifyUniqueExampleMethods(List exampleNames) throws InitializationError { + private void verifyUniqueExampleMethods(List exampleNames) throws InitializationError { // use a hash set to store examples - gives us quick lookup and add. Set setOfExamples = new HashSet(); @@ -136,6 +131,8 @@ protected Fixture createFixture(Object fixtureObject) { @Override public void run(RunNotifier notifier) { + setUp(); + try { // we figure out if the spec has been run before by checking if there are any // prior results in the cache @@ -172,6 +169,36 @@ public void run(RunNotifier notifier) { } } + private void setUp() { + if (setUpDone) return; + + try { + setupFixture = createFixture(super.createTest()); + // needs to be called so extensions have access to scoped variables + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (suiteDepth.getAndIncrement() == 0) { + setupFixture.beforeSuite(); + } + + try { + fixtureRunner = new FixtureRunner(setupFixture, getSpecificationLocator()); + } catch (UnableToBuildConcordionException e) { + throw new RuntimeException(e); + } + concordion = fixtureRunner.getConcordion(); + try { + concordion.getExampleNames(setupFixture.getFixtureType()); // (force) load specification from resource + // needs to be called so extensions are initialized + } catch (IOException e) { + throw new RuntimeException(e); + } + + setUpDone = true; + } + @Override protected List getChildren() { // downcast from ConcordionFrameworkMethod to FrameworkMethod diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 0988253a..20254f9e 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -416,8 +416,8 @@ public ConcordionBuilder withFailFast(Class[] failFastExcep return this; } - public ConcordionBuilder withFixture(Fixture fixture) { - this.fixtureType = fixture.getFixtureType(); + public ConcordionBuilder withFixtureType(FixtureType fixtureType) { + this.fixtureType = fixtureType; withResources(fixtureType); @@ -427,6 +427,13 @@ public ConcordionBuilder withFixture(Fixture fixture) { if (fixtureType.declaresFullOGNL()) { withEvaluatorFactory(new OgnlEvaluatorFactory()); } + + return this; + } + + public ConcordionBuilder withFixture(Fixture fixture) { + withFixtureType(fixture.getFixtureType()); + flexmarkOptions = new FlexmarkOptionsLoader().getFlexmarkOptionsForFixture(fixture); if (flexmarkOptions != null) { configureWith(flexmarkOptions); diff --git a/src/main/java/org/concordion/internal/ResourceFinder.java b/src/main/java/org/concordion/internal/ResourceFinder.java index a2875d2a..3a209b96 100644 --- a/src/main/java/org/concordion/internal/ResourceFinder.java +++ b/src/main/java/org/concordion/internal/ResourceFinder.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FilenameFilter; import java.lang.annotation.Annotation; +import java.nio.file.InvalidPathException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -125,7 +126,11 @@ private File getAbsoluteSearchPath(File root, String packageName, String sourceF search = new File(root, packageName); search = new File(search, sourceFile); } - return search.toPath().normalize().toFile(); + try { + return search.toPath().normalize().toFile(); + } catch (InvalidPathException e) { + return search; // as fallback + } } private boolean isSearchRoot(String sourceFile) { diff --git a/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java b/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java index 296e470f..1bcc802f 100644 --- a/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java +++ b/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java @@ -12,25 +12,42 @@ import org.concordion.api.extension.Extension; import org.concordion.api.extension.Extensions; import org.concordion.internal.ConcordionBuilder; +import org.concordion.internal.FixtureType; import org.concordion.internal.util.SimpleFormatter; public class FixtureExtensionLoader { - + public void addExtensions(Fixture fixture, ConcordionBuilder concordionBuilder) { for (ConcordionExtension concordionExtension : getExtensionsForFixture(fixture)) { concordionExtension.addTo(concordionBuilder); } } + public void addExtensions(FixtureType fixtureType, ConcordionBuilder concordionBuilder) { + for (ConcordionExtension concordionExtension : getExtensionsForFixtureType(fixtureType)) { + concordionExtension.addTo(concordionBuilder); + } + } + public List getExtensionsForFixture(Fixture fixture) { - final List extensions = new ArrayList(); + final List extensions = getExtensionsForFixtureType(fixture.getFixtureType()); List> classes = fixture.getFixtureType().getClassHierarchyParentFirst(); for (Class class1 : classes) { - extensions.addAll(getExtensionsFromClassAnnotation(class1)); extensions.addAll(getExtensionsFromAnnotatedFields(fixture, class1)); } - + + return extensions; + } + + public List getExtensionsForFixtureType(FixtureType fixtureType) { + final List extensions = new ArrayList(); + + List> classes = fixtureType.getClassHierarchyParentFirst(); + for (Class class1 : classes) { + extensions.addAll(getExtensionsFromClassAnnotation(class1)); + } + return extensions; } From 43dbe86830a5477956d2d4c4118cd6f26c41845f Mon Sep 17 00:00:00 2001 From: Lorenzo Dee Date: Thu, 3 Nov 2022 20:00:59 +0800 Subject: [PATCH 06/45] Add initial TestEngine for Concordion Started converting some fixtures (under spec.examples package) to use the (JUnit Platform) ConcordionTestEngine by replacing @RunWith(ConcordionRunner.class) with @ConcordionFixture To support the run-command, the DefaultConcordionRunner was modified to use JUnit Platform engines (e.g. "junit-vintage", "concordion") instead of JUnit 4. --- build.gradle | 13 +- gradle.properties | 2 +- .../org/concordion/api/ConcordionFixture.java | 31 +++ .../engine/ConcordionEngineDescriptor.java | 20 ++ .../ConcordionEngineExecutionContext.java | 37 +++ .../platform/engine/ConcordionTestEngine.java | 133 ++++++++++ .../platform/engine/ExampleDescriptor.java | 96 +++++++ .../engine/FixtureBasedTestDescriptor.java | 53 ++++ .../engine/JUnit5FrameworkProvider.java | 15 ++ .../engine/SpecificationDescriptor.java | 132 ++++++++++ .../runner/DefaultConcordionRunner.java | 140 +++++++++-- ...ncordion.integration.TestFrameworkProvider | 1 + .../org.junit.platform.engine.TestEngine | 1 + .../engine/ConcordionTestEngineTests.java | 97 ++++++++ .../runner/DefaultConcordionRunnerTest.java | 169 ++++++++----- .../internal/runner/StubResult.java | 45 ---- .../runner/StubTestExecutionSummary.java | 234 ++++++++++++++++++ src/test/java/spec/examples/DemoTest.java | 6 +- .../spec/examples/PartialMatchesTest.java | 6 +- src/test/java/spec/examples/SpikeTest.java | 6 +- 20 files changed, 1095 insertions(+), 142 deletions(-) create mode 100644 src/main/java/org/concordion/api/ConcordionFixture.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineDescriptor.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineExecutionContext.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/FixtureBasedTestDescriptor.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/JUnit5FrameworkProvider.java create mode 100644 src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java create mode 100644 src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine create mode 100644 src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java delete mode 100644 src/test/java/org/concordion/internal/runner/StubResult.java create mode 100644 src/test/java/org/concordion/internal/runner/StubTestExecutionSummary.java diff --git a/build.gradle b/build.gradle index c5a60def..826c50cc 100644 --- a/build.gradle +++ b/build.gradle @@ -38,8 +38,17 @@ dependencies { api (platform("org.junit:junit-bom:$junitJupiterVersion")) api 'org.junit.jupiter:junit-jupiter' api 'junit:junit:4.13.2' - testRuntimeOnly("org.junit.vintage:junit-vintage-engine") { - because 'allows JUnit 3 and JUnit 4 tests to run' + testRuntimeOnly('org.junit.vintage:junit-vintage-engine') { + because 'allows JUnit 4 tests to run' + } + api('org.junit.platform:junit-platform-engine') { + because 'allows creation of custom Concordion TestEngine' + } + api('org.junit.platform:junit-platform-launcher') { + because 'allows run-command to use JUnit Platform' + } + testImplementation('org.junit.platform:junit-platform-testkit') { + because 'allows testing of Concordion TestEngine' } api "com.vladsch.flexmark:flexmark:$flexmarkVersion", diff --git a/gradle.properties b/gradle.properties index acfb1e28..1ec35fa8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ group=org.concordion -version=3.1.3 +version=4.0.0-SNAPSHOT diff --git a/src/main/java/org/concordion/api/ConcordionFixture.java b/src/main/java/org/concordion/api/ConcordionFixture.java new file mode 100644 index 00000000..c59fb608 --- /dev/null +++ b/src/main/java/org/concordion/api/ConcordionFixture.java @@ -0,0 +1,31 @@ +package org.concordion.api; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.junit.platform.commons.annotation.Testable; + +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Marks the class (with a class name that ends with Fixture or + * Test) as a fixture for a specification. + *

+ * This allows it to be discovered by + * {@link org.concordion.integration.junit.platform.engine.ConcordionTestEngine + * Concordion's JUnit Platform TestEngine}. + *

+ *

+ * This must not be used with JUnit Jupiter's + * {@literal @}{@link org.junit.jupiter.api.extension.ExtendWith + * ExtendWith}. + *

+ * + * @since 4.0 + */ +@Retention(RUNTIME) +@Target(TYPE) +@Testable +public @interface ConcordionFixture { +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineDescriptor.java new file mode 100644 index 00000000..4c3398eb --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineDescriptor.java @@ -0,0 +1,20 @@ +package org.concordion.integration.junit.platform.engine; + +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.descriptor.EngineDescriptor; +import org.junit.platform.engine.support.hierarchical.Node; + +/** + * An {@code EngineDescriptor} for {@link ConcordionTestEngine}. + * + * @see SpecificationDescriptor + * @see ExampleDescriptor + * @since 4.0 + */ +public class ConcordionEngineDescriptor extends EngineDescriptor implements Node { + + public ConcordionEngineDescriptor(UniqueId uniqueId, String displayName) { + super(uniqueId, displayName); + } + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineExecutionContext.java b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineExecutionContext.java new file mode 100644 index 00000000..c1a39aa3 --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionEngineExecutionContext.java @@ -0,0 +1,37 @@ +package org.concordion.integration.junit.platform.engine; + +import org.concordion.internal.cache.RunResultsCache; +import org.junit.platform.engine.ConfigurationParameters; +import org.junit.platform.engine.EngineExecutionListener; +import org.junit.platform.engine.ExecutionRequest; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.support.hierarchical.EngineExecutionContext; + +public class ConcordionEngineExecutionContext implements EngineExecutionContext { + + private final ExecutionRequest request; + + private final RunResultsCache runResultsCache = RunResultsCache.SINGLETON; + + public ConcordionEngineExecutionContext(ExecutionRequest request) { + super(); + this.request = request; + } + + public RunResultsCache getRunResultsCache() { + return runResultsCache; + } + + public TestDescriptor getRootTestDescriptor() { + return request.getRootTestDescriptor(); + } + + public EngineExecutionListener getEngineExecutionListener() { + return request.getEngineExecutionListener(); + } + + public ConfigurationParameters getConfigurationParameters() { + return request.getConfigurationParameters(); + } + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java new file mode 100644 index 00000000..92bbe8ce --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java @@ -0,0 +1,133 @@ +package org.concordion.integration.junit.platform.engine; + +import java.io.IOException; +import java.util.List; +import java.util.function.Predicate; + +import org.concordion.api.ConcordionFixture; +import org.concordion.api.SpecificationLocator; +import org.concordion.internal.ClassNameBasedSpecificationLocator; +import org.junit.platform.commons.support.AnnotationSupport; +import org.junit.platform.commons.support.ReflectionSupport; +import org.junit.platform.engine.EngineDiscoveryRequest; +import org.junit.platform.engine.ExecutionRequest; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.discovery.ClassSelector; +import org.junit.platform.engine.discovery.PackageSelector; +import org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine; + +/** + * The Concordion {@link org.junit.platform.engine.TestEngine TestEngine}. + *

+ * Supports discovery and execution of specifications through + * {@link ConcordionFixture fixtures} using the following selectors: + *

+ *
    + *
  • {@link ClassSelector}
  • + *
  • {@link PackageSelector}
  • + *
+ * + * @see ConcordionFixture + * @see SpecificationDescriptor + * @see ExampleDescriptor + * @since 4.0 + */ +public class ConcordionTestEngine extends HierarchicalTestEngine { + + public static final String ENGINE_ID = "concordion"; + + public static final String ENDS_WITH_FIXTURE_OR_TEST_REGEX = ".*(Fixture|Test)$"; + private static final Predicate> IS_FIXTURE_CLASS = (clazz) -> { + return AnnotationSupport.findAnnotation( + clazz, ConcordionFixture.class).isPresent() + && clazz.getName().matches(ENDS_WITH_FIXTURE_OR_TEST_REGEX); + }; + + @Override + public String getId() { + return ENGINE_ID; + } + + @Override + public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { + TestDescriptor rootTestDescriptor = new ConcordionEngineDescriptor(uniqueId, "Concordion for JUnit Platform"); + SpecificationLocator specificationLocator = new ClassNameBasedSpecificationLocator(); + + // Include fixtures with @org.concordion.api.ConcordionFixture annotation + final Predicate> predicate = IS_FIXTURE_CLASS; + + // @formatter:off + discoveryRequest.getSelectorsByType(ClassSelector.class) + .stream() + // .peek(selector -> System.out.println(selector.getJavaClass().getName())) + .map(selector -> selector.getJavaClass()) + .filter(predicate) + // .peek(clazz -> System.out.println(clazz.getName())) + .forEach(fixtureClass -> { + appendFixtureBasedTestDescriptor( + fixtureClass, specificationLocator, rootTestDescriptor); + }); + discoveryRequest.getSelectorsByType(PackageSelector.class) + .stream() + // .peek(selector -> System.out.println(selector.getPackageName())) + .map(selector -> ReflectionSupport.findAllClassesInPackage( + selector.getPackageName(), predicate, className -> true)) + .flatMap(List::stream) + // .peek(clazz -> System.out.println(clazz.getName())) + .forEach(fixtureClass -> { + appendFixtureBasedTestDescriptor( + fixtureClass, specificationLocator, rootTestDescriptor); + }); + // @formatter:on + + return rootTestDescriptor; + } + + protected void appendFixtureBasedTestDescriptor( + Class fixtureClass, SpecificationLocator specificationLocator, TestDescriptor parentTestDescriptor) { + try { + // Create a SpecificationTestDescriptor and append to parent + SpecificationDescriptor specificationTestDescriptor = + appendSpecificationTestDescriptor(fixtureClass, specificationLocator, parentTestDescriptor); + List exampleNames = specificationTestDescriptor.getExampleNames(); + // System.out.println(exampleNames); + for (String exampleName : exampleNames) { + // Create an ExampleTestDescriptor and append to SpecificationTestDescriptor + appendExampleTestDescriptor(exampleName, fixtureClass, specificationTestDescriptor); + } + } catch (IOException ex) { + // System.out.println(fixtureClass); + throw new RuntimeException( + "Error occured while loading specification examples (with [" + fixtureClass.getName() + "] fixture)", ex); + } + } + + protected SpecificationDescriptor appendSpecificationTestDescriptor( + Class fixtureClass, SpecificationLocator specificationLocator, TestDescriptor parentTestDescriptor) { + SpecificationDescriptor newTestDescriptor = new SpecificationDescriptor( + parentTestDescriptor.getUniqueId(), + fixtureClass, specificationLocator); + // System.out.println("Added " + newTestDescriptor.getClass().getSimpleName() + " for " + newTestDescriptor.getFixtureClass().getSimpleName()); + parentTestDescriptor.addChild(newTestDescriptor); + return newTestDescriptor; + } + + protected ExampleDescriptor appendExampleTestDescriptor( + String exampleName, Class fixtureClass, TestDescriptor parentTestDescriptor) { + ExampleDescriptor newTestDescriptor = new ExampleDescriptor( + parentTestDescriptor.getUniqueId().append( + ExampleDescriptor.SEGMENT_TYPE, exampleName), + fixtureClass, + exampleName); + // System.out.println("Added " + newTestDescriptor.getClass().getSimpleName() + " for " + newTestDescriptor.getExampleName()); + parentTestDescriptor.addChild(newTestDescriptor); + return newTestDescriptor; + } + + @Override + protected ConcordionEngineExecutionContext createExecutionContext(ExecutionRequest request) { + return new ConcordionEngineExecutionContext(request); + } + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java new file mode 100644 index 00000000..0e3cf93e --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java @@ -0,0 +1,96 @@ +package org.concordion.integration.junit.platform.engine; + +import org.concordion.api.ResultSummary; +import org.concordion.internal.FixtureInstance; +import org.concordion.internal.FixtureRunner; +import org.concordion.internal.FixtureType; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.hierarchical.Node; + +/** + * A concrete {@link FixtureBasedTestDescriptor fixture-based descriptor} for an + * example in a specification. + * + * @see SpecificationDescriptor + * @since 4.0 + */ +public class ExampleDescriptor extends FixtureBasedTestDescriptor + implements Node { + + public static final String SEGMENT_TYPE = "example"; + + private final String exampleName; + + ExampleDescriptor(UniqueId parentUniqueId, Class fixtureClass, String exampleName) { + super(parentUniqueId.append( + ExampleDescriptor.SEGMENT_TYPE, + exampleName), + fixtureClass, + exampleName); + this.exampleName = exampleName; + } + + public String getExampleName() { + return exampleName; + } + + @Override + public Type getType() { + return Type.TEST; + } + + protected SpecificationDescriptor getParentSpecificationTestDescriptor() { + TestDescriptor parentTestDescriptor = getParent().orElse(null); + if (parentTestDescriptor == null + || !SpecificationDescriptor.class.isInstance(parentTestDescriptor)) { + throw new IllegalStateException( + "Parent must be a [" + SpecificationDescriptor.class.getName() + "]"); + } + return (SpecificationDescriptor) parentTestDescriptor; + } + + @Override + public final FixtureType getFixtureType() { + return getParentSpecificationTestDescriptor().getFixtureType(); + } + + @Override + public final FixtureInstance getFixtureInstance() { + return getParentSpecificationTestDescriptor().getFixtureInstance(); + } + + @Override + public final FixtureRunner getFixtureRunner() { + return getParentSpecificationTestDescriptor().getFixtureRunner(); + } + + /* + @Override + public ConcordionEngineExecutionContext before(ConcordionEngineExecutionContext context) throws Exception { + // This is already done via FixtureRunner#run(String, Fixture) + // getFixtureInstance().beforeExample(this.exampleName); + return context; + } + */ + + @Override + public ConcordionEngineExecutionContext execute(ConcordionEngineExecutionContext context, + DynamicTestExecutor dynamicTestExecutor) throws Exception { + FixtureRunner runner = getFixtureRunner(); + + ResultSummary result = runner.run(getExampleName(), getFixtureInstance()); + result.assertIsSatisfied(getFixtureType()); + + return context; + } + + /* + @Override + public void after(ConcordionEngineExecutionContext context) throws Exception { + // This is already done via FixtureRunner#run(String, Fixture) + // getFixtureInstance().afterExample(this.exampleName); + } + */ + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/FixtureBasedTestDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/FixtureBasedTestDescriptor.java new file mode 100644 index 00000000..e718d658 --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/FixtureBasedTestDescriptor.java @@ -0,0 +1,53 @@ +package org.concordion.integration.junit.platform.engine; + +import org.concordion.internal.FixtureInstance; +import org.concordion.internal.FixtureRunner; +import org.concordion.internal.FixtureSpecificationMapper; +import org.concordion.internal.FixtureType; +import org.junit.platform.engine.TestDescriptor; +import org.junit.platform.engine.TestSource; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; +import org.junit.platform.engine.support.descriptor.ClassSource; + +/** + * Abstract fixture-based implementation of {@link TestDescriptor}. + * + * @since 4.0 + */ +public abstract class FixtureBasedTestDescriptor extends AbstractTestDescriptor { + + private final Class fixtureClass; + + FixtureBasedTestDescriptor(UniqueId uniqueId, Class fixtureClass) { + this(uniqueId, + fixtureClass, + FixtureSpecificationMapper + .removeSuffixFromFixtureName(fixtureClass.getName())); + } + + FixtureBasedTestDescriptor( + UniqueId uniqueId, Class fixtureClass, String displayName) { + this(uniqueId, + fixtureClass, + displayName, + ClassSource.from(fixtureClass)); + } + + FixtureBasedTestDescriptor( + UniqueId uniqueId, Class fixtureClass, String displayName, TestSource source) { + super(uniqueId, displayName, source); + this.fixtureClass = fixtureClass; + } + + public Class getFixtureClass() { + return fixtureClass; + } + + public abstract FixtureType getFixtureType(); + + public abstract FixtureInstance getFixtureInstance(); + + public abstract FixtureRunner getFixtureRunner(); + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/JUnit5FrameworkProvider.java b/src/main/java/org/concordion/integration/junit/platform/engine/JUnit5FrameworkProvider.java new file mode 100644 index 00000000..368e0dde --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/JUnit5FrameworkProvider.java @@ -0,0 +1,15 @@ +package org.concordion.integration.junit.platform.engine; + +import org.concordion.api.ConcordionFixture; +import org.concordion.integration.TestFrameworkProvider; +import org.junit.platform.commons.support.AnnotationSupport; + +public class JUnit5FrameworkProvider implements TestFrameworkProvider { + + @Override + public boolean isConcordionFixture(Class clazz) { + return AnnotationSupport.findAnnotation( + clazz, ConcordionFixture.class).isPresent(); + } + +} diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java new file mode 100644 index 00000000..76292c8d --- /dev/null +++ b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java @@ -0,0 +1,132 @@ +package org.concordion.integration.junit.platform.engine; + +import java.io.IOException; +import java.util.List; + +import org.concordion.api.SpecificationLocator; +import org.concordion.internal.FixtureInstance; +import org.concordion.internal.FixtureRunner; +import org.concordion.internal.FixtureType; +import org.concordion.internal.RunOutput; +import org.concordion.internal.UnableToBuildConcordionException; +import org.junit.platform.commons.support.ReflectionSupport; +import org.junit.platform.engine.UniqueId; +import org.junit.platform.engine.support.hierarchical.Node; + +/** + * A concrete {@link FixtureBasedTestDescriptor fixture-based descriptor} for a + * specification. + * + * @see ExampleDescriptor + * @since 4.0 + */ +public class SpecificationDescriptor extends FixtureBasedTestDescriptor + implements Node { + + public static final String SEGMENT_TYPE = "specification"; + + private final SpecificationLocator specificationLocator; + + private FixtureType fixtureType; + private Object fixtureObject; + private FixtureInstance fixtureInstance; + private FixtureRunner fixtureRunner; + + SpecificationDescriptor(UniqueId parentUniqueId, + Class fixtureClass, SpecificationLocator specificationLocator) { + super(parentUniqueId.append( + SpecificationDescriptor.SEGMENT_TYPE, fixtureClass.getName()), + fixtureClass); + this.specificationLocator = specificationLocator; + } + + public List getExampleNames() throws IOException { + return getFixtureRunner().getConcordion().getExampleNames(getFixtureType()); + } + + @Override + public FixtureType getFixtureType() { + if (fixtureType == null) { + fixtureType = getFixtureInstance().getFixtureType(); + } + return fixtureType; + } + + @Override + public FixtureInstance getFixtureInstance() { + if (fixtureInstance == null) { + fixtureInstance = createFixtureInstance(); + } + return fixtureInstance; + } + + protected FixtureInstance createFixtureInstance() { + return new FixtureInstance(createFixtureObject()); + } + + protected Object createFixtureObject() { + if (fixtureObject == null) { + fixtureObject = ReflectionSupport.newInstance(getFixtureClass()); + } + return fixtureObject; + } + + public FixtureRunner getFixtureRunner() { + if (fixtureRunner == null) { + try { + fixtureRunner = createFixtureRunner(); + } catch (UnableToBuildConcordionException ex) { + throw new RuntimeException(ex); + } + } + return fixtureRunner; + } + + protected FixtureRunner createFixtureRunner() throws UnableToBuildConcordionException { + return new FixtureRunner(getFixtureInstance(), specificationLocator); + } + + @Override + public Type getType() { + return Type.CONTAINER; + } + + @Override + public ConcordionEngineExecutionContext prepare(ConcordionEngineExecutionContext context) throws Exception { + FixtureRunner runner = getFixtureRunner(); // create FixtureRunner + // (which can result into a RuntimeException with a nested UnableToBuildConcordionException) + runner.getConcordion().checkValidStatus(getFixtureType()); + // Child ExampleDescriptor(s) shall access the FixtureRunner via getFixtureRunner() + return context; + } + + @Override + public void around(ConcordionEngineExecutionContext context, + Invocation invocation) throws Exception { + boolean isFirstRun = null == context.getRunResultsCache().getFromCache(getFixtureClass(), null); + + if (isFirstRun) { + context.getRunResultsCache().startFixtureRun( + getFixtureType(), + getFixtureRunner().getConcordion().getSpecificationDescription()); + // getFixtureInstance().beforeSuite(); + getFixtureInstance().beforeSpecification(); + } + + Node.super.around(context, invocation); + + if (isFirstRun) { + getFixtureInstance().afterSpecification(); + getFixtureRunner().getConcordion().finish(); + // getFixtureInstance().afterSuite(); + } + + RunOutput results = context.getRunResultsCache().getFromCache(getFixtureClass(), null); + if (results != null) { + synchronized (System.out) { + results.getActualResultSummary().print(System.out, getFixtureType()); + } + } + } + +} diff --git a/src/main/java/org/concordion/internal/runner/DefaultConcordionRunner.java b/src/main/java/org/concordion/internal/runner/DefaultConcordionRunner.java index ce31c1bc..684bcd29 100644 --- a/src/main/java/org/concordion/internal/runner/DefaultConcordionRunner.java +++ b/src/main/java/org/concordion/internal/runner/DefaultConcordionRunner.java @@ -1,17 +1,45 @@ package org.concordion.internal.runner; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.util.List; +import java.util.Optional; import org.concordion.api.*; +import org.concordion.integration.junit.platform.engine.ConcordionTestEngine; +import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.FailFastException; import org.concordion.internal.FixtureSpecificationMapper; import org.concordion.internal.FixtureType; import org.concordion.internal.SummarizingResultRecorder; import org.concordion.internal.RunOutput; import org.concordion.internal.cache.RunResultsCache; -import org.junit.runner.JUnitCore; -import org.junit.runner.notification.Failure; - +import org.junit.platform.commons.support.AnnotationSupport; +import org.junit.platform.commons.support.ReflectionSupport; +import org.junit.platform.engine.discovery.DiscoverySelectors; +import org.junit.platform.launcher.EngineFilter; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; +import org.junit.platform.launcher.listeners.SummaryGeneratingListener; +import org.junit.platform.launcher.listeners.TestExecutionSummary; + +/** + * A {@link org.concordion.api.Runner run-command runner} that uses JUnit + * Platform engines (e.g. "concordion", "junit-vintage") to run the fixture + * class' specification/examples. The fixture class is usually annotated with + * {@link org.concordion.api.ConcordionFixture @ConcordionFixture} + * or {@literal @}RunWith(ConcordionRunner.class). + * + *

+ * Not to be confused with + * {@link org.concordion.integration.junit4.ConcordionRunner ConcordionRunner} + * which is a {@link org.junit.runner.Runner Runner} used with + * {@link org.junit.runner.RunWith @RunWith} annotation. + *

+ */ public class DefaultConcordionRunner implements Runner { public ResultSummary execute(Resource resource, String href) throws Exception { @@ -40,12 +68,12 @@ protected ResultSummary runTestClass(Class fixtureClass) throws Exception { ResultSummary summary = null; // we always run the test to ensure that the FixtureRunner class - // has an opportuinity to print out any necessary debugging information. - org.junit.runner.Result jUnitResult = runJUnitClass(fixtureClass); + // has an opportunity to print out any necessary debugging information. + TestExecutionSummary jUnitResult = runJUnitPlatformEngine(fixtureClass, resolveEngineId(fixtureClass)); - // we always decode the jUnut summary because it handles specification exceptions - // (as opposed to exceptions that occured in a specification) better. - ResultSummary jUnitSummary = decodeJUnitResult(new FixtureType(fixtureClass), jUnitResult); + // we always decode the jUnit summary because it handles specification exceptions + // (as opposed to exceptions that occurred in a specification) better. + ResultSummary jUnitSummary = decodeJUnitPlatformEngineResult(jUnitResult, fixtureClass); // check the cache - if the test was a concordion test, it will have stuck the results // in the cache. Use "null" for the example to get the accumulated values from all examples @@ -68,31 +96,91 @@ protected ResultSummary runTestClass(Class fixtureClass) throws Exception { return summary; } - private void processTestException(FixtureType fixtureDeclaration, - Throwable exception) throws AssertionError, Exception { - logExceptionIfNotAssertionError(exception); - rethrowExceptionIfWarranted(fixtureDeclaration, exception); - } + String resolveEngineId(Class fixtureClass) { + // Use JUnit Platform to: + // - Use "junit-vintage" engine when fixture class has @RunWith(ConcordionRunner.class) + // - Use "concordion" engine otherwise (usually fixture class has @ConcordionFixture) + return hasRunWithConcordionRunner(fixtureClass) + ? "junit-vintage" // See: org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID + : ConcordionTestEngine.ENGINE_ID; + } + + @SuppressWarnings("unchecked") + boolean hasRunWithConcordionRunner(Class fixtureClass) { + // All this to avoid compile/build-time dependencies on JUnit 4.x + if (isJUnit4RunWithAnnotationPresent()) { + Class runWithAnnotationClass; + try { + runWithAnnotationClass = + (Class) Class.forName(JUNIT4_RUNWITH_ANNOTATION); + Optional runWithAnnotation = + AnnotationSupport.findAnnotation(fixtureClass, runWithAnnotationClass); + return runWithAnnotation.isPresent() + && ConcordionRunner.class.isAssignableFrom( + (Class) getAttribute(runWithAnnotation.get(), "value")); + } catch (ClassNotFoundException e) { + return false; + } + } + return false; + } + + private static final String JUNIT4_RUNWITH_ANNOTATION = "org.junit.runner.RunWith"; + + private boolean isJUnit4RunWithAnnotationPresent() { + return isPresent(JUNIT4_RUNWITH_ANNOTATION); + } + + private boolean isPresent(String className) { + try { + Class.forName(className); + return true; + } catch (ClassNotFoundException ex) { + return false; + } + } - protected org.junit.runner.Result runJUnitClass(Class fixtureClass) { - org.junit.runner.Result jUnitResult = JUnitCore.runClasses(fixtureClass); - return jUnitResult; + private Object getAttribute(Annotation annotation, String attributeName) { + try { + Method method = annotation.annotationType().getDeclaredMethod(attributeName); + return ReflectionSupport.invokeMethod(method, annotation); + } catch (NoSuchMethodException e) { + return null; + } } - protected ResultSummary decodeJUnitResult(FixtureType fixtureDeclaration, org.junit.runner.Result jUnitResult) throws Exception { + protected TestExecutionSummary runJUnitPlatformEngine(Class fixtureClass, String engineId) { + // See: https://junit.org/junit5/docs/current/user-guide/#launcher-api-execution + LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() + .filters(EngineFilter.includeEngines(engineId)) + .selectors(DiscoverySelectors.selectClass(fixtureClass)) + .build(); + SummaryGeneratingListener listener = new SummaryGeneratingListener(); + try (LauncherSession session = LauncherFactory.openSession()) { + Launcher launcher = session.getLauncher(); + launcher.registerTestExecutionListeners(listener); + launcher.execute(request); + } + return listener.getSummary(); + } + + protected ResultSummary decodeJUnitPlatformEngineResult(TestExecutionSummary summary, Class fixtureClass) + throws AssertionError, Exception { Result result = Result.FAILURE; - if (jUnitResult.wasSuccessful()) { + FixtureType fixtureDeclaration = new FixtureType(fixtureClass); + if (summary.getTestsFailedCount() == 0) { result = Result.SUCCESS; if (onlyPartiallyImplemented(fixtureDeclaration)) { result = Result.IGNORED; } - if (jUnitResult.getIgnoreCount() > 0) { + if (summary.getTestsSkippedCount() > 0) { result = Result.IGNORED; } - } else { - List failures = jUnitResult.getFailures(); - for (Failure failure : failures) { - processTestException(fixtureDeclaration, failure.getException()); + } + else { + List failures = summary.getFailures(); + for (TestExecutionSummary.Failure failure : failures) { + processTestException(fixtureDeclaration, failure.getException()); } } @@ -102,6 +190,12 @@ protected ResultSummary decodeJUnitResult(FixtureType fixtureDeclaration, org.ju return recorder; } + private void processTestException(FixtureType fixtureDeclaration, + Throwable exception) throws AssertionError, Exception { + logExceptionIfNotAssertionError(exception); + rethrowExceptionIfWarranted(fixtureDeclaration, exception); + } + private void logExceptionIfNotAssertionError(Throwable exception) { if (!(exception instanceof AssertionError)) { System.err.println(exception.getClass().getName() + ": " + exception.getLocalizedMessage()); diff --git a/src/main/resources/META-INF/services/org.concordion.integration.TestFrameworkProvider b/src/main/resources/META-INF/services/org.concordion.integration.TestFrameworkProvider index b0f06616..842cfa05 100644 --- a/src/main/resources/META-INF/services/org.concordion.integration.TestFrameworkProvider +++ b/src/main/resources/META-INF/services/org.concordion.integration.TestFrameworkProvider @@ -1 +1,2 @@ org.concordion.integration.junit4.JUnit4FrameworkProvider +org.concordion.integration.junit.platform.engine.JUnit5FrameworkProvider diff --git a/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine b/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine new file mode 100644 index 00000000..ae4d79bf --- /dev/null +++ b/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine @@ -0,0 +1 @@ +org.concordion.integration.junit.platform.engine.ConcordionTestEngine \ No newline at end of file diff --git a/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java b/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java new file mode 100644 index 00000000..bf0fe903 --- /dev/null +++ b/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java @@ -0,0 +1,97 @@ +package org.concordion.integration.junit.platform.engine; + +import org.concordion.internal.FixtureType; +import org.concordion.internal.cache.RunResultsCache; +import org.junit.jupiter.api.Test; +import org.junit.platform.engine.discovery.DiscoverySelectors; +import org.junit.platform.launcher.EngineFilter; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.LauncherSession; +import org.junit.platform.launcher.TestPlan; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; +import org.junit.platform.testkit.engine.EngineExecutionResults; +import org.junit.platform.testkit.engine.EngineTestKit; + +import spec.examples.DemoTest; +import spec.examples.PartialMatchesTest; +import spec.examples.SpikeTest; + +import static org.junit.jupiter.api.Assertions.*; + +class ConcordionTestEngineTests { + + @Test + void id() throws Exception { + assertEquals("concordion", new ConcordionTestEngine().getId()); + } + + @Test + void engineLoads() throws Exception { + // See: META-INF/services/org.junit.platform.engine.TestEngine + EngineTestKit.engine("concordion"); + } + + @Test + void engineRunsConcordion() throws Exception { + RunResultsCache runResultsCache = RunResultsCache.SINGLETON; + FixtureType demoFixtureType = new FixtureType(DemoTest.class); + runResultsCache.removeAllFromCache(demoFixtureType); + FixtureType partialMatchesFixtureType = new FixtureType(PartialMatchesTest.class); + runResultsCache.removeAllFromCache(partialMatchesFixtureType); + FixtureType spikeFixtureType = new FixtureType(SpikeTest.class); + runResultsCache.removeAllFromCache(spikeFixtureType); + + try { + EngineExecutionResults executionResults = + EngineTestKit.engine("concordion") + .selectors( + DiscoverySelectors.selectClass(DemoTest.class), + DiscoverySelectors.selectClass(PartialMatchesTest.class), + DiscoverySelectors.selectClass(SpikeTest.class)) + .execute(); + executionResults + .containerEvents() + .assertStatistics(stats -> stats.started(1 + 3)); + executionResults + .testEvents() + .assertStatistics(stats -> stats.started(3).succeeded(3)); + + assertNotNull(runResultsCache.getFromCache(demoFixtureType, null)); + assertNotNull(runResultsCache.getFromCache(partialMatchesFixtureType, null)); + assertNotNull(runResultsCache.getFromCache(spikeFixtureType, null)); + } finally { + runResultsCache.removeAllFromCache(demoFixtureType); + runResultsCache.removeAllFromCache(partialMatchesFixtureType); + runResultsCache.removeAllFromCache(spikeFixtureType); + } + } + + @Test + void engineDiscoversClasses() throws Exception { + LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() + .filters(EngineFilter.includeEngines("concordion")) + .selectors(DiscoverySelectors.selectClass(DemoTest.class)) + .build(); + try (LauncherSession session = LauncherFactory.openSession()) { + Launcher launcher = session.getLauncher(); + TestPlan testPlan = launcher.discover(request); + assertTrue(testPlan.containsTests()); + } + } + + @Test + void engineDiscoversPackages() throws Exception { + LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() + .filters(EngineFilter.includeEngines("concordion")) + .selectors(DiscoverySelectors.selectPackage(DemoTest.class.getPackage().getName())) + .build(); + try (LauncherSession session = LauncherFactory.openSession()) { + Launcher launcher = session.getLauncher(); + TestPlan testPlan = launcher.discover(request); + assertTrue(testPlan.containsTests()); + } + } + +} diff --git a/src/test/java/org/concordion/internal/runner/DefaultConcordionRunnerTest.java b/src/test/java/org/concordion/internal/runner/DefaultConcordionRunnerTest.java index 7b265c88..a1d2b39f 100644 --- a/src/test/java/org/concordion/internal/runner/DefaultConcordionRunnerTest.java +++ b/src/test/java/org/concordion/internal/runner/DefaultConcordionRunnerTest.java @@ -1,98 +1,108 @@ package org.concordion.internal.runner; -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - import java.io.IOException; import org.concordion.api.ExpectedToFail; import org.concordion.api.ResultSummary; import org.concordion.api.Unimplemented; -import org.concordion.internal.FixtureType; -import org.concordion.internal.runner.DefaultConcordionRunner; import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.SystemErrRule; -import org.junit.runner.Result; + +import static org.junit.Assert.*; public class DefaultConcordionRunnerTest { @Rule public final SystemErrRule systemErrRule = - new SystemErrRule().enableLog().muteForSuccessfulTests(); // Ensure error log messages don't appear on console + new SystemErrRule().enableLog().muteForSuccessfulTests(); // Ensure error log messages don't appear on console - private final TestDefaultConcordionRunner runner = new TestDefaultConcordionRunner(); + private final DefaultConcordionRunner runner = new DefaultConcordionRunner(); @Test public void returnsFailureOnJUnitFailure() throws Exception { - ResultSummary myresult = runner.decodeJUnitResult(UnannotatedClass.class, StubResult.FAILURE); - assertThat(myresult.getFailureCount(), is(1L)); - assertThat(myresult.getIgnoredCount(), is(0L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(0L)); + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + StubTestExecutionSummary.FAILURE, UnannotatedClass.class); + assertEquals(1, myresult.getFailureCount()); + assertEquals(0, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(0, myresult.getSuccessCount()); } @Test public void returnsSuccessOnJUnitSuccess() throws Exception { - ResultSummary myresult = runner.decodeJUnitResult(UnannotatedClass.class, StubResult.SUCCESS); - assertThat(myresult.getFailureCount(), is(0L)); - assertThat(myresult.getIgnoredCount(), is(0L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(1L)); - } + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + StubTestExecutionSummary.SUCCESS, UnannotatedClass.class); + assertEquals(0, myresult.getFailureCount()); + assertEquals(0, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(1, myresult.getSuccessCount()); + } // JUnit success is reported when an ExpectedToFail test does fail @Test public void returnsIgnoredOnJUnitSuccessWhenExpectedToFail() throws Exception { - ResultSummary myresult = runner.decodeJUnitResult(ExpectedToFailClass.class, StubResult.SUCCESS); - assertThat(myresult.getFailureCount(), is(0L)); - assertThat(myresult.getIgnoredCount(), is(1L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(0L)); + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + StubTestExecutionSummary.SUCCESS, ExpectedToFailClass.class); + assertEquals(0, myresult.getFailureCount()); + assertEquals(1, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(0, myresult.getSuccessCount()); } // JUnit success is reported when an Unimplemented test is unimplemented @Test public void returnsIgnoredOnJUnitSuccessWhenUnimplemented() throws Exception { - ResultSummary myresult = runner.decodeJUnitResult(UnimplementedClass.class, StubResult.SUCCESS); - assertThat(myresult.getFailureCount(), is(0L)); - assertThat(myresult.getIgnoredCount(), is(1L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(0L)); + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + StubTestExecutionSummary.SUCCESS, UnimplementedClass.class); + assertEquals(0, myresult.getFailureCount()); + assertEquals(1, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(0, myresult.getSuccessCount()); } // JUnit failure is reported when an ExpectedToFail test does not fail. @Test(expected = AssertionError.class) public void throwsAssertionErrorOnJUnitFailureWhenExpectedToFail() throws Exception { - runner.decodeJUnitResult(ExpectedToFailClass.class, StubResult.FAILURE); + runner.decodeJUnitPlatformEngineResult(StubTestExecutionSummary.FAILURE, ExpectedToFailClass.class); } // JUnit failure is reported when an Unimplemented test is implemented @Test(expected = AssertionError.class) public void throwsAssertionErrorOnJUnitFailureWhenUnimplemented() throws Exception { - runner.decodeJUnitResult(UnimplementedClass.class, StubResult.FAILURE); + runner.decodeJUnitPlatformEngineResult(StubTestExecutionSummary.FAILURE, UnimplementedClass.class); } @Test public void doesNotThrowExceptionOnAssertionErrorWhenExpectedToPass() throws Exception { Throwable error = new AssertionError(); - ResultSummary myresult = runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); - assertThat(myresult.getFailureCount(), is(1L)); - assertThat(myresult.getIgnoredCount(), is(0L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(0L)); + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); + assertEquals(1, myresult.getFailureCount()); + assertEquals(0, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(0, myresult.getSuccessCount()); } @Test public void throwsExceptionOnCheckedException() throws Exception { Throwable error = new IOException("dummy exception"); try { - runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); fail("expected IOException"); } catch (IOException e) { - assertThat(e.getMessage(), is("dummy exception")); + assertEquals("dummy exception", e.getMessage()); } } @@ -100,10 +110,16 @@ public void throwsExceptionOnCheckedException() throws Exception { public void throwsWrappedExceptionOnThrowable() throws Exception { Throwable error = new InternalError("dummy throwable"); try { - runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); fail("expected InternalError"); } catch (RuntimeException e) { - assertThat(e.getCause().getMessage(), is("dummy throwable")); + assertEquals("dummy throwable", e.getCause().getMessage()); } } @@ -111,57 +127,91 @@ public void throwsWrappedExceptionOnThrowable() throws Exception { public void throwsRuntimeExceptionOnRuntimeException() throws Exception { Throwable error = new IllegalArgumentException("dummy runtime exception"); try { - runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); fail("expected IllegalArgumentException"); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), is("dummy runtime exception")); + assertEquals("dummy runtime exception", e.getMessage()); } } @Test public void returnsIgnoredOnJUnitSuccessWhenIgnoredCountGreaterThanZero() throws Exception { - ResultSummary myresult = runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withIgnoreCount(1)); - assertThat(myresult.getFailureCount(), is(0L)); - assertThat(myresult.getIgnoredCount(), is(1L)); - assertThat(myresult.getExceptionCount(), is(0L)); - assertThat(myresult.getSuccessCount(), is(0L)); + ResultSummary myresult = runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsSkippedCount(1), + UnannotatedClass.class); + assertEquals(0, myresult.getFailureCount()); + assertEquals(1, myresult.getIgnoredCount()); + assertEquals(0, myresult.getExceptionCount()); + assertEquals(0, myresult.getSuccessCount()); } @Test public void logsExceptions() throws Exception { Throwable error = new IOException("dummy IO exception"); try { - runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); } catch (IOException e) { } - assertThat(systemErrRule.getLog(), containsString("java.io.IOException: dummy IO exception")); + assertTrue(systemErrRule.getLog().contains("java.io.IOException: dummy IO exception")); } @Test public void doesNotLogAssertionErrors() throws Exception { Throwable error = new AssertionError("dummy assertion error"); - runner.decodeJUnitResult(UnannotatedClass.class, new StubResult().withFailure(error)); - assertThat(systemErrRule.getLog(), is("")); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnannotatedClass.class); + assertEquals("", systemErrRule.getLog()); } @Test public void doesNotLogAssertionErrorsWhenExpectedToFailEither() throws Exception { Throwable error = new AssertionError("dummy assertion error"); try { - runner.decodeJUnitResult(ExpectedToFailClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + ExpectedToFailClass.class); } catch (AssertionError e) { } - assertThat(systemErrRule.getLog(), is("")); + assertEquals("", systemErrRule.getLog()); } @Test public void doesNotLogAssertionErrorsWhenUnimplementedEither() throws Exception { Throwable error = new AssertionError("dummy assertion error"); try { - runner.decodeJUnitResult(ExpectedToFailClass.class, new StubResult().withFailure(error)); + runner.decodeJUnitPlatformEngineResult( + new StubTestExecutionSummary() + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(error), + UnimplementedClass.class); } catch (AssertionError e) { } - assertThat(systemErrRule.getLog(), is("")); + assertEquals("", systemErrRule.getLog()); } private static final class UnannotatedClass { @@ -175,9 +225,4 @@ private static final class ExpectedToFailClass { private static final class UnimplementedClass { } - private static final class TestDefaultConcordionRunner extends DefaultConcordionRunner { - protected ResultSummary decodeJUnitResult(Class fixtureClass, Result jUnitResult) throws Exception { - return super.decodeJUnitResult(new FixtureType(fixtureClass), jUnitResult); - } - } } \ No newline at end of file diff --git a/src/test/java/org/concordion/internal/runner/StubResult.java b/src/test/java/org/concordion/internal/runner/StubResult.java deleted file mode 100644 index f0124c6c..00000000 --- a/src/test/java/org/concordion/internal/runner/StubResult.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.concordion.internal.runner; - -import java.util.ArrayList; -import java.util.List; -import org.junit.runner.Description; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; - -/** - * Stub for {@link Result}. Defaults to a successful result. - */ -class StubResult extends Result { - - private static final long serialVersionUID = 6102153773248794468L; - public static final StubResult SUCCESS = new StubResult(); - public static final StubResult FAILURE = new StubResult().withFailure(new AssertionError("Dummy test failure")); - - private List failures = new ArrayList(); - private int ignoreCount; - - public StubResult withFailure(Throwable error) { - failures.add(new Failure(Description.EMPTY, error)); - return this; - } - - public StubResult withIgnoreCount(int ignoreCount) { - this.ignoreCount = ignoreCount; - return this; - } - - @Override - public boolean wasSuccessful() { - return failures.size() == 0; - } - - @Override - public List getFailures() { - return failures; - } - - @Override - public int getIgnoreCount() { - return ignoreCount; - } -} \ No newline at end of file diff --git a/src/test/java/org/concordion/internal/runner/StubTestExecutionSummary.java b/src/test/java/org/concordion/internal/runner/StubTestExecutionSummary.java new file mode 100644 index 00000000..8b12b02d --- /dev/null +++ b/src/test/java/org/concordion/internal/runner/StubTestExecutionSummary.java @@ -0,0 +1,234 @@ +package org.concordion.internal.runner; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.junit.platform.launcher.TestIdentifier; +import org.junit.platform.launcher.listeners.TestExecutionSummary; + +public class StubTestExecutionSummary implements TestExecutionSummary { + + public static final StubTestExecutionSummary FAILURE = new StubTestExecutionSummary() + .withContainersFoundCount(1) + .withContainersStartedCount(1) + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsFailedCount(1) + .withFailure(new AssertionError("Stub exception")); + public static final StubTestExecutionSummary SUCCESS = new StubTestExecutionSummary() + .withContainersFoundCount(1) + .withContainersStartedCount(1) + .withTestsFoundCount(1) + .withTestsStartedCount(1) + .withTestsSuccededCount(1); + + private long timeStarted = 0; + private long timeFinished = 0; + + private long containersFoundCount = 0; + private long containersStartedCount = 0; + private long containersSkippedCount = 0; + private long containersAbortedCount = 0; + private long containersSucceededCount = 0; + private long containersFailedCount = 0; + + private long testsFoundCount = 0; + private long testsStartedCount = 0; + private long testsSkippedCount = 0; + private long testsAbortedCount = 0; + private long testsSucceededCount = 0; + private long testsFailedCount = 0; + + private List failures = new ArrayList<>(); + + @Override + public long getTimeStarted() { + return timeStarted; + } + + public StubTestExecutionSummary withTimeStarted(long timeStarted) { + this.timeStarted = timeStarted; + return this; + } + + @Override + public long getTimeFinished() { + return timeFinished; + } + + public StubTestExecutionSummary withTimeFinished(long timeFinished) { + this.timeFinished = timeFinished; + return this; + } + + @Override + public long getTotalFailureCount() { + return getTestsFailedCount() + getContainersFailedCount(); + } + + @Override + public long getContainersFoundCount() { + return containersFoundCount; + } + + public StubTestExecutionSummary withContainersFoundCount(long containersFoundCount) { + this.containersFoundCount = containersFoundCount; + return this; + } + + @Override + public long getContainersStartedCount() { + return containersStartedCount; + } + + public StubTestExecutionSummary withContainersStartedCount(long containersStartedCount) { + this.containersStartedCount = containersStartedCount; + return this; + } + + @Override + public long getContainersSkippedCount() { + return containersSkippedCount; + } + + public StubTestExecutionSummary withContainersSkippedCount(long containersSkippedCount) { + this.containersSkippedCount = containersSkippedCount; + return this; + } + + @Override + public long getContainersAbortedCount() { + return containersAbortedCount; + } + + public StubTestExecutionSummary withContainersAbortedCount(long containersAbortedCount) { + this.containersAbortedCount = containersAbortedCount; + return this; + } + + @Override + public long getContainersSucceededCount() { + return containersSucceededCount; + } + + public StubTestExecutionSummary withContainersSucceededCount(long containersSucceededCount) { + this.containersSucceededCount = containersSucceededCount; + return this; + } + + @Override + public long getContainersFailedCount() { + return containersFailedCount; + } + + public StubTestExecutionSummary withContainersFailedCount(long containersFailedCount) { + this.containersFailedCount = containersFailedCount; + return this; + } + + @Override + public long getTestsFoundCount() { + return testsFoundCount; + } + + public StubTestExecutionSummary withTestsFoundCount(long testsFoundCount) { + this.testsFoundCount = testsFoundCount; + return this; + } + + @Override + public long getTestsStartedCount() { + return testsStartedCount; + } + + public StubTestExecutionSummary withTestsStartedCount(long testsStartedCount) { + this.testsStartedCount = testsStartedCount; + return this; + } + + @Override + public long getTestsSkippedCount() { + return testsSkippedCount; + } + + public StubTestExecutionSummary withTestsSkippedCount(long testsSkippedCount) { + this.testsSkippedCount = testsSkippedCount; + return this; + } + + @Override + public long getTestsAbortedCount() { + return testsAbortedCount; + } + + public StubTestExecutionSummary withTestsAbortedCount(long testsAbortedCount) { + this.testsAbortedCount = testsAbortedCount; + return this; + } + + @Override + public long getTestsSucceededCount() { + return testsSucceededCount; + } + + public StubTestExecutionSummary withTestsSuccededCount(long testsSucceededCount) { + this.testsSucceededCount = testsSucceededCount; + return this; + } + + @Override + public long getTestsFailedCount() { + return testsFailedCount; + } + + public StubTestExecutionSummary withTestsFailedCount(long testsFailedCount) { + this.testsFailedCount = testsFailedCount; + return this; + } + + @Override + public void printTo(PrintWriter writer) { + // TODO Auto-generated method stub + } + + @Override + public void printFailuresTo(PrintWriter writer) { + // TODO Auto-generated method stub + } + + @Override + public List getFailures() { + return failures; + } + + public StubTestExecutionSummary withFailure(Throwable error) { + failures.add(new StubFailure(null, error)); + return this; + } + + @SuppressWarnings("serial") + private static class StubFailure implements Failure { + + private final TestIdentifier testIdentifier; + private final Throwable exception; + + public StubFailure(TestIdentifier testIdentifier, Throwable exception) { + super(); + this.testIdentifier = testIdentifier; + this.exception = exception; + } + + @Override + public TestIdentifier getTestIdentifier() { + return testIdentifier; + } + + @Override + public Throwable getException() { + return exception; + } + + } + +} diff --git a/src/test/java/spec/examples/DemoTest.java b/src/test/java/spec/examples/DemoTest.java index a3a0818f..1ee0d6e9 100644 --- a/src/test/java/spec/examples/DemoTest.java +++ b/src/test/java/spec/examples/DemoTest.java @@ -1,10 +1,10 @@ package spec.examples; +import org.concordion.api.ConcordionFixture; import org.concordion.api.ConcordionResources; -import org.concordion.integration.junit4.ConcordionRunner; -import org.junit.runner.RunWith; -@RunWith(ConcordionRunner.class) +// @RunWith(ConcordionRunner.class) +@ConcordionFixture @ConcordionResources(value="/concordion.css", includeDefaultStyling = false) public class DemoTest { diff --git a/src/test/java/spec/examples/PartialMatchesTest.java b/src/test/java/spec/examples/PartialMatchesTest.java index f0f58fe0..2a3c98be 100644 --- a/src/test/java/spec/examples/PartialMatchesTest.java +++ b/src/test/java/spec/examples/PartialMatchesTest.java @@ -5,10 +5,10 @@ import java.util.SortedSet; import java.util.TreeSet; -import org.concordion.integration.junit4.ConcordionRunner; -import org.junit.runner.RunWith; +import org.concordion.api.ConcordionFixture; -@RunWith(ConcordionRunner.class) +// @RunWith(ConcordionRunner.class) +@ConcordionFixture public class PartialMatchesTest { private Set usernamesInSystem = new HashSet(); diff --git a/src/test/java/spec/examples/SpikeTest.java b/src/test/java/spec/examples/SpikeTest.java index 94091438..c6f48a0f 100644 --- a/src/test/java/spec/examples/SpikeTest.java +++ b/src/test/java/spec/examples/SpikeTest.java @@ -3,12 +3,12 @@ import java.util.ArrayList; import java.util.Collection; +import org.concordion.api.ConcordionFixture; import org.concordion.api.ExpectedToPass; -import org.concordion.integration.junit4.ConcordionRunner; -import org.junit.runner.RunWith; @ExpectedToPass -@RunWith(ConcordionRunner.class) +// @RunWith(ConcordionRunner.class) +@ConcordionFixture public class SpikeTest { public String getGreetingFor(String name) { From e63d29edaa46c10ea80d69c3bd2f089170abdd71 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Tue, 18 Apr 2023 18:53:39 +1200 Subject: [PATCH 07/45] Added JDK 20 --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32f9dfc4..190719a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '8', '11', '17' ] + java: [ '8', '11', '17', '20' ] name: Java ${{ matrix.Java }} steps: @@ -56,10 +56,10 @@ jobs: - name: Publish Specifications uses: peaceiris/actions-gh-pages@v3 - if: ${{ github.ref == 'refs/heads/main' }} + if: ${{ github.ref == 'refs/heads/master' }} with: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} external_repository: concordion/concordion-specifications - publish_branch: main + publish_branch: master publish_dir: artifacts/reports-java-8/reports/spec/concordion destination_dir: concordion From 4443ec3b166767e60749d68b64fa06ef5a1dfcd2 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 09:49:59 +1200 Subject: [PATCH 08/45] Ignore asdf tool-versions --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f260970b..e6ed9dd3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,7 @@ out/ .vscode/ # Infer -infer-out/ \ No newline at end of file +infer-out/ + +# asdf +.tool-versions \ No newline at end of file From a2829b6235cc513cd374e32c267db368a561053c Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 09:51:16 +1200 Subject: [PATCH 09/45] Add boolean to ConcordionBuilder.build() to control whether notifications are generated --- .../org/concordion/integration/junit4/ConcordionRunner.java | 2 +- .../java/org/concordion/internal/ConcordionBuilder.java | 6 ++++-- src/main/java/org/concordion/internal/FixtureRunner.java | 2 +- src/test/java/test/concordion/TestRig.java | 4 +--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java index 65b4bbc7..799a6f26 100644 --- a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java +++ b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java @@ -58,7 +58,7 @@ public ConcordionRunner(Class fixtureClass) throws InitializationError { .withSpecificationLocator(getSpecificationLocator()); new FixtureExtensionLoader().addExtensions(fixtureType, localBuilder); new FixtureOptionsLoader().addOptions(fixtureType, localBuilder); - Concordion localConcordion = localBuilder.build(); + Concordion localConcordion = localBuilder.build(false); localConcordion.checkValidStatus(fixtureType); List examples = localConcordion.getExampleNames(fixtureType); diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 20254f9e..500d91e0 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -257,7 +257,7 @@ public ConcordionBuilder withLinkedJavaScript(String jsPath, Resource targetReso return this; } - public Concordion build() throws UnableToBuildConcordionException { + public Concordion build(boolean fullBuild) throws UnableToBuildConcordionException { Check.isFalse(builtAlready, "ConcordionBuilder currently does not support calling build() twice"); builtAlready = true; @@ -317,7 +317,9 @@ public Concordion build() throws UnableToBuildConcordionException { exampleCommand.setSpecificationDescriber(exporter); runCommand.setRunnerFactory(runnerFactory); - announceBuildCompleted(); + if (fullBuild) { + announceBuildCompleted(); + } try { return new Concordion(specificationTypes, specificationLocator, specificationReader, evaluatorFactory, fixtureType); diff --git a/src/main/java/org/concordion/internal/FixtureRunner.java b/src/main/java/org/concordion/internal/FixtureRunner.java index cb5c1502..d8ea6a41 100644 --- a/src/main/java/org/concordion/internal/FixtureRunner.java +++ b/src/main/java/org/concordion/internal/FixtureRunner.java @@ -18,7 +18,7 @@ public FixtureRunner(Fixture fixture, SpecificationLocator specificationLocator) ConcordionBuilder concordionBuilder = new ConcordionBuilder().withFixture(fixture).withSpecificationLocator(specificationLocator); new FixtureExtensionLoader().addExtensions(fixture, concordionBuilder); new FixtureOptionsLoader().addOptions(fixture.getFixtureType(), concordionBuilder); - concordion = concordionBuilder.build(); + concordion = concordionBuilder.build(true); } public ResultSummary run(String example, Fixture fixture) throws IOException { diff --git a/src/test/java/test/concordion/TestRig.java b/src/test/java/test/concordion/TestRig.java index 5bd0062e..37425e02 100644 --- a/src/test/java/test/concordion/TestRig.java +++ b/src/test/java/test/concordion/TestRig.java @@ -1,10 +1,8 @@ package test.concordion; import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.List; -import java.util.Map; import com.vladsch.flexmark.util.data.DataSet; import org.concordion.Concordion; @@ -83,7 +81,7 @@ public ProcessingResult process(Resource resource) { } Concordion concordion = null; try { - concordion = concordionBuilder.build(); + concordion = concordionBuilder.build(true); } catch (UnableToBuildConcordionException e) { throw new RuntimeException("Test rig failed to build concordion", e); } From b2632630bd315ed651e205c409ed59b2a782848c Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 10:00:52 +1200 Subject: [PATCH 10/45] Reduce amount of work for partial build --- .../internal/ConcordionBuilder.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 500d91e0..8bdc975f 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -283,8 +283,10 @@ public Concordion build(boolean fullBuild) throws UnableToBuildConcordionExcepti Source resourceSource = sources.get(SourceType.RESOURCE); Source specificationSource = sources.get(SourceType.SPECIFICATION); - withThrowableListener(0, new ThrowableRenderer(resourceSource)); - withRunListener(new RunResultRenderer(resourceSource)); + if (fullBuild) { + withThrowableListener(0, new ThrowableRenderer(resourceSource)); + withRunListener(new RunResultRenderer(resourceSource)); + } FixtureExampleHook fixtureExampleHook = new FixtureExampleHook(); withOuterExampleListener(fixtureExampleHook); @@ -302,16 +304,22 @@ public Concordion build(boolean fullBuild) throws UnableToBuildConcordionExcepti specificationCommand.addSpecificationListener(pageFooterRenderer); specificationReader = new XMLSpecificationReader(specificationSource, xmlParser, documentParser); - specificationReader.setCopySourceHtmlTarget(copySourceHtmlTarget); + if (fullBuild) { + specificationReader.setCopySourceHtmlTarget(copySourceHtmlTarget); + } addExtensions(); copyResources(resourceSource); - addSpecificationListeners(); - addThrowableListeners(); + if (fullBuild) { + addSpecificationListeners(); + addThrowableListeners(); + } SpecificationExporter exporter = new SpecificationExporter(target); - specificationCommand.addSpecificationListener(exporter); + if (fullBuild) { + specificationCommand.addSpecificationListener(exporter); + } specificationCommand.setSpecificationDescriber(exporter); exampleCommand.setSpecificationDescriber(exporter); From e6dc5e50481e813351ee73347365fc7bd960d86a Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 11:54:12 +1200 Subject: [PATCH 11/45] Add manual trigger to ci.yml --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32f9dfc4..408ea5c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: Build and Test Concordion on: + workflow_dispatch push: branches: [ master ] pull_request: From 01e4b91cbc2d333dd038de7f6b040ae71b9d7118 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 12:02:35 +1200 Subject: [PATCH 12/45] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 408ea5c2..72ca927d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ name: Build and Test Concordion on: - workflow_dispatch + workflow_dispatch: push: branches: [ master ] pull_request: From c23a86736d9fd2dc9dcea931e9994a6089f11308 Mon Sep 17 00:00:00 2001 From: Lorenzo Dee Date: Wed, 29 Jun 2022 14:54:58 +0800 Subject: [PATCH 13/45] Update to JUnit 5 and using JUnit Vintage - Specs were failing with JUnit Vintage because the ConcordionRunner was instantiating the fixture object too soon in its constructor. After modifying the ConcordionRunner, the specs (as-is, without changes) are now working on JUnit 4 and JUnit Vintage. - Also fixed ResourceFinder which was failing on Windows --- build.gradle | 17 +++- .../integration/junit4/ConcordionRunner.java | 81 ++++++++++++------- .../internal/ConcordionBuilder.java | 11 ++- .../concordion/internal/ResourceFinder.java | 7 +- .../extension/FixtureExtensionLoader.java | 25 +++++- 5 files changed, 105 insertions(+), 36 deletions(-) diff --git a/build.gradle b/build.gradle index ac8b2231..c5a60def 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ repositories { } ext { + junitJupiterVersion = '5.8.2' flexmarkVersion = '0.62.2' githubUrl = "https://github.com/concordion/${project.name}" issuesUrl = "${githubUrl}/issues" @@ -34,8 +35,14 @@ ext { } dependencies { - api 'junit:junit:4.13.2', - "com.vladsch.flexmark:flexmark:$flexmarkVersion", + api (platform("org.junit:junit-bom:$junitJupiterVersion")) + api 'org.junit.jupiter:junit-jupiter' + api 'junit:junit:4.13.2' + testRuntimeOnly("org.junit.vintage:junit-vintage-engine") { + because 'allows JUnit 3 and JUnit 4 tests to run' + } + + api "com.vladsch.flexmark:flexmark:$flexmarkVersion", "com.vladsch.flexmark:flexmark-ext-gfm-strikethrough:$flexmarkVersion", "com.vladsch.flexmark:flexmark-ext-tables:$flexmarkVersion" @@ -78,6 +85,7 @@ targetCompatibility = 8 test { systemProperties['concordion.output.dir'] = "${reporting.baseDir}" + useJUnitPlatform() } compileTestJava.dependsOn compileTestDummiesJava @@ -165,6 +173,11 @@ publishing { id = 'wangyizhuo' roles = ['Developer'] } + developer { + id = 'lorenzodee' + name = 'Lorenzo Dee' + roles = ['Developer'] + } } } versionMapping { diff --git a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java index 887b2e6e..65b4bbc7 100644 --- a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java +++ b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java @@ -13,6 +13,7 @@ import org.concordion.api.SpecificationLocator; import org.concordion.internal.*; import org.concordion.internal.cache.RunResultsCache; +import org.concordion.internal.extension.FixtureExtensionLoader; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; @@ -33,42 +34,34 @@ public void invoke(ConcordionFrameworkMethod concordionFrameworkMethod, Object t }; private final Class fixtureClass; - private final Fixture setupFixture; - private final FixtureRunner fixtureRunner; - private final Concordion concordion; private final List concordionFrameworkMethods; + private Fixture setupFixture; + private FixtureRunner fixtureRunner; + private Concordion concordion; + private FailFastException failFastException = null; private static AtomicInteger suiteDepth = new AtomicInteger(); private boolean firstTest = true; + private boolean setUpDone = false; public ConcordionRunner(Class fixtureClass) throws InitializationError { super(fixtureClass); this.fixtureClass = fixtureClass; try { - setupFixture = createFixture(super.createTest()); - // needs to be called so extensions have access to scoped variables - } catch (Exception e) { - throw new InitializationError(e); - } - - if (suiteDepth.getAndIncrement() == 0) { - setupFixture.beforeSuite(); - } - - try { - fixtureRunner = new FixtureRunner(setupFixture, getSpecificationLocator()); - } catch (UnableToBuildConcordionException e) { - throw new InitializationError(e); - } - concordion = fixtureRunner.getConcordion(); - - try { - concordion.checkValidStatus(setupFixture.getFixtureType()); - - List examples = concordion.getExampleNames(setupFixture.getFixtureType()); + FixtureType fixtureType = new FixtureType(fixtureClass); + // Avoiding the instantiation of the fixture object at this point + ConcordionBuilder localBuilder = new ConcordionBuilder() + .withFixtureType(fixtureType) + .withSpecificationLocator(getSpecificationLocator()); + new FixtureExtensionLoader().addExtensions(fixtureType, localBuilder); + new FixtureOptionsLoader().addOptions(fixtureType, localBuilder); + Concordion localConcordion = localBuilder.build(); + localConcordion.checkValidStatus(fixtureType); + + List examples = localConcordion.getExampleNames(fixtureType); verifyUniqueExampleMethods(examples); @@ -76,16 +69,18 @@ public ConcordionRunner(Class fixtureClass) throws InitializationError { for (String example: examples) { concordionFrameworkMethods.add(new ConcordionFrameworkMethod(concordionRunnerInterface, example)); } + } catch (UnableToBuildConcordionException e) { + throw new InitializationError(e); } catch (IOException e) { throw new InitializationError(e); } } protected SpecificationLocator getSpecificationLocator() { - return new ClassNameBasedSpecificationLocator(); - } + return new ClassNameBasedSpecificationLocator(); + } - private void verifyUniqueExampleMethods(List exampleNames) throws InitializationError { + private void verifyUniqueExampleMethods(List exampleNames) throws InitializationError { // use a hash set to store examples - gives us quick lookup and add. Set setOfExamples = new HashSet(); @@ -136,6 +131,8 @@ protected Fixture createFixture(Object fixtureObject) { @Override public void run(RunNotifier notifier) { + setUp(); + try { // we figure out if the spec has been run before by checking if there are any // prior results in the cache @@ -172,6 +169,36 @@ public void run(RunNotifier notifier) { } } + private void setUp() { + if (setUpDone) return; + + try { + setupFixture = createFixture(super.createTest()); + // needs to be called so extensions have access to scoped variables + } catch (Exception e) { + throw new RuntimeException(e); + } + + if (suiteDepth.getAndIncrement() == 0) { + setupFixture.beforeSuite(); + } + + try { + fixtureRunner = new FixtureRunner(setupFixture, getSpecificationLocator()); + } catch (UnableToBuildConcordionException e) { + throw new RuntimeException(e); + } + concordion = fixtureRunner.getConcordion(); + try { + concordion.getExampleNames(setupFixture.getFixtureType()); // (force) load specification from resource + // needs to be called so extensions are initialized + } catch (IOException e) { + throw new RuntimeException(e); + } + + setUpDone = true; + } + @Override protected List getChildren() { // downcast from ConcordionFrameworkMethod to FrameworkMethod diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 0988253a..20254f9e 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -416,8 +416,8 @@ public ConcordionBuilder withFailFast(Class[] failFastExcep return this; } - public ConcordionBuilder withFixture(Fixture fixture) { - this.fixtureType = fixture.getFixtureType(); + public ConcordionBuilder withFixtureType(FixtureType fixtureType) { + this.fixtureType = fixtureType; withResources(fixtureType); @@ -427,6 +427,13 @@ public ConcordionBuilder withFixture(Fixture fixture) { if (fixtureType.declaresFullOGNL()) { withEvaluatorFactory(new OgnlEvaluatorFactory()); } + + return this; + } + + public ConcordionBuilder withFixture(Fixture fixture) { + withFixtureType(fixture.getFixtureType()); + flexmarkOptions = new FlexmarkOptionsLoader().getFlexmarkOptionsForFixture(fixture); if (flexmarkOptions != null) { configureWith(flexmarkOptions); diff --git a/src/main/java/org/concordion/internal/ResourceFinder.java b/src/main/java/org/concordion/internal/ResourceFinder.java index a2875d2a..3a209b96 100644 --- a/src/main/java/org/concordion/internal/ResourceFinder.java +++ b/src/main/java/org/concordion/internal/ResourceFinder.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FilenameFilter; import java.lang.annotation.Annotation; +import java.nio.file.InvalidPathException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -125,7 +126,11 @@ private File getAbsoluteSearchPath(File root, String packageName, String sourceF search = new File(root, packageName); search = new File(search, sourceFile); } - return search.toPath().normalize().toFile(); + try { + return search.toPath().normalize().toFile(); + } catch (InvalidPathException e) { + return search; // as fallback + } } private boolean isSearchRoot(String sourceFile) { diff --git a/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java b/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java index 296e470f..1bcc802f 100644 --- a/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java +++ b/src/main/java/org/concordion/internal/extension/FixtureExtensionLoader.java @@ -12,25 +12,42 @@ import org.concordion.api.extension.Extension; import org.concordion.api.extension.Extensions; import org.concordion.internal.ConcordionBuilder; +import org.concordion.internal.FixtureType; import org.concordion.internal.util.SimpleFormatter; public class FixtureExtensionLoader { - + public void addExtensions(Fixture fixture, ConcordionBuilder concordionBuilder) { for (ConcordionExtension concordionExtension : getExtensionsForFixture(fixture)) { concordionExtension.addTo(concordionBuilder); } } + public void addExtensions(FixtureType fixtureType, ConcordionBuilder concordionBuilder) { + for (ConcordionExtension concordionExtension : getExtensionsForFixtureType(fixtureType)) { + concordionExtension.addTo(concordionBuilder); + } + } + public List getExtensionsForFixture(Fixture fixture) { - final List extensions = new ArrayList(); + final List extensions = getExtensionsForFixtureType(fixture.getFixtureType()); List> classes = fixture.getFixtureType().getClassHierarchyParentFirst(); for (Class class1 : classes) { - extensions.addAll(getExtensionsFromClassAnnotation(class1)); extensions.addAll(getExtensionsFromAnnotatedFields(fixture, class1)); } - + + return extensions; + } + + public List getExtensionsForFixtureType(FixtureType fixtureType) { + final List extensions = new ArrayList(); + + List> classes = fixtureType.getClassHierarchyParentFirst(); + for (Class class1 : classes) { + extensions.addAll(getExtensionsFromClassAnnotation(class1)); + } + return extensions; } From 4bd31e5625695d9d0e0989421af910a3b92c6889 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 09:49:59 +1200 Subject: [PATCH 14/45] Ignore asdf tool-versions --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f260970b..e6ed9dd3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,7 @@ out/ .vscode/ # Infer -infer-out/ \ No newline at end of file +infer-out/ + +# asdf +.tool-versions \ No newline at end of file From 68431c7ca2b61502ecce36d88f6d63a8945c299a Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 09:51:16 +1200 Subject: [PATCH 15/45] Add boolean to ConcordionBuilder.build() to control whether notifications are generated --- .../org/concordion/integration/junit4/ConcordionRunner.java | 2 +- .../java/org/concordion/internal/ConcordionBuilder.java | 6 ++++-- src/main/java/org/concordion/internal/FixtureRunner.java | 2 +- src/test/java/test/concordion/TestRig.java | 4 +--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java index 65b4bbc7..799a6f26 100644 --- a/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java +++ b/src/main/java/org/concordion/integration/junit4/ConcordionRunner.java @@ -58,7 +58,7 @@ public ConcordionRunner(Class fixtureClass) throws InitializationError { .withSpecificationLocator(getSpecificationLocator()); new FixtureExtensionLoader().addExtensions(fixtureType, localBuilder); new FixtureOptionsLoader().addOptions(fixtureType, localBuilder); - Concordion localConcordion = localBuilder.build(); + Concordion localConcordion = localBuilder.build(false); localConcordion.checkValidStatus(fixtureType); List examples = localConcordion.getExampleNames(fixtureType); diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 20254f9e..500d91e0 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -257,7 +257,7 @@ public ConcordionBuilder withLinkedJavaScript(String jsPath, Resource targetReso return this; } - public Concordion build() throws UnableToBuildConcordionException { + public Concordion build(boolean fullBuild) throws UnableToBuildConcordionException { Check.isFalse(builtAlready, "ConcordionBuilder currently does not support calling build() twice"); builtAlready = true; @@ -317,7 +317,9 @@ public Concordion build() throws UnableToBuildConcordionException { exampleCommand.setSpecificationDescriber(exporter); runCommand.setRunnerFactory(runnerFactory); - announceBuildCompleted(); + if (fullBuild) { + announceBuildCompleted(); + } try { return new Concordion(specificationTypes, specificationLocator, specificationReader, evaluatorFactory, fixtureType); diff --git a/src/main/java/org/concordion/internal/FixtureRunner.java b/src/main/java/org/concordion/internal/FixtureRunner.java index cb5c1502..d8ea6a41 100644 --- a/src/main/java/org/concordion/internal/FixtureRunner.java +++ b/src/main/java/org/concordion/internal/FixtureRunner.java @@ -18,7 +18,7 @@ public FixtureRunner(Fixture fixture, SpecificationLocator specificationLocator) ConcordionBuilder concordionBuilder = new ConcordionBuilder().withFixture(fixture).withSpecificationLocator(specificationLocator); new FixtureExtensionLoader().addExtensions(fixture, concordionBuilder); new FixtureOptionsLoader().addOptions(fixture.getFixtureType(), concordionBuilder); - concordion = concordionBuilder.build(); + concordion = concordionBuilder.build(true); } public ResultSummary run(String example, Fixture fixture) throws IOException { diff --git a/src/test/java/test/concordion/TestRig.java b/src/test/java/test/concordion/TestRig.java index 5bd0062e..37425e02 100644 --- a/src/test/java/test/concordion/TestRig.java +++ b/src/test/java/test/concordion/TestRig.java @@ -1,10 +1,8 @@ package test.concordion; import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.List; -import java.util.Map; import com.vladsch.flexmark.util.data.DataSet; import org.concordion.Concordion; @@ -83,7 +81,7 @@ public ProcessingResult process(Resource resource) { } Concordion concordion = null; try { - concordion = concordionBuilder.build(); + concordion = concordionBuilder.build(true); } catch (UnableToBuildConcordionException e) { throw new RuntimeException("Test rig failed to build concordion", e); } From ea79027d5ab97bd8ce065d8edb311fa9ac8b5370 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 10:00:52 +1200 Subject: [PATCH 16/45] Reduce amount of work for partial build --- .../internal/ConcordionBuilder.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 500d91e0..8bdc975f 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -283,8 +283,10 @@ public Concordion build(boolean fullBuild) throws UnableToBuildConcordionExcepti Source resourceSource = sources.get(SourceType.RESOURCE); Source specificationSource = sources.get(SourceType.SPECIFICATION); - withThrowableListener(0, new ThrowableRenderer(resourceSource)); - withRunListener(new RunResultRenderer(resourceSource)); + if (fullBuild) { + withThrowableListener(0, new ThrowableRenderer(resourceSource)); + withRunListener(new RunResultRenderer(resourceSource)); + } FixtureExampleHook fixtureExampleHook = new FixtureExampleHook(); withOuterExampleListener(fixtureExampleHook); @@ -302,16 +304,22 @@ public Concordion build(boolean fullBuild) throws UnableToBuildConcordionExcepti specificationCommand.addSpecificationListener(pageFooterRenderer); specificationReader = new XMLSpecificationReader(specificationSource, xmlParser, documentParser); - specificationReader.setCopySourceHtmlTarget(copySourceHtmlTarget); + if (fullBuild) { + specificationReader.setCopySourceHtmlTarget(copySourceHtmlTarget); + } addExtensions(); copyResources(resourceSource); - addSpecificationListeners(); - addThrowableListeners(); + if (fullBuild) { + addSpecificationListeners(); + addThrowableListeners(); + } SpecificationExporter exporter = new SpecificationExporter(target); - specificationCommand.addSpecificationListener(exporter); + if (fullBuild) { + specificationCommand.addSpecificationListener(exporter); + } specificationCommand.setSpecificationDescriber(exporter); exampleCommand.setSpecificationDescriber(exporter); From 08476c4f0b91b98e993757e27f340f872a875e3f Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 11:54:12 +1200 Subject: [PATCH 17/45] Add manual trigger to ci.yml --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 190719a6..957c8b09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: Build and Test Concordion on: + workflow_dispatch push: branches: [ master ] pull_request: From cb3ce357f1d00800027082ea304f2f20fa0723e1 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 22 May 2023 12:02:35 +1200 Subject: [PATCH 18/45] Update ci.yml --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 957c8b09..99b72595 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,7 +1,7 @@ name: Build and Test Concordion on: - workflow_dispatch + workflow_dispatch: push: branches: [ master ] pull_request: From 58b863f1357cb25425dd5c300b1278bf2c4b6ca5 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 28 May 2023 11:44:29 +1200 Subject: [PATCH 19/45] Add method to keep original signature --- src/main/java/org/concordion/internal/ConcordionBuilder.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/concordion/internal/ConcordionBuilder.java b/src/main/java/org/concordion/internal/ConcordionBuilder.java index 8bdc975f..456ba569 100644 --- a/src/main/java/org/concordion/internal/ConcordionBuilder.java +++ b/src/main/java/org/concordion/internal/ConcordionBuilder.java @@ -257,6 +257,10 @@ public ConcordionBuilder withLinkedJavaScript(String jsPath, Resource targetReso return this; } + public Concordion build() throws UnableToBuildConcordionException { + return build(true); + } + public Concordion build(boolean fullBuild) throws UnableToBuildConcordionException { Check.isFalse(builtAlready, "ConcordionBuilder currently does not support calling build() twice"); builtAlready = true; From 4b758852bd836d218e703e8ffb94f2de04ca4ae5 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 28 May 2023 11:49:06 +1200 Subject: [PATCH 20/45] Clean up deprecated methods --- .../common/command/assertEquals/nonString/NonStringTest.java | 4 ++-- .../common/command/assertFalse/AssertFalseTest.java | 2 +- .../concordion/common/command/assertTrue/AssertTrueTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java index 4e4984d8..d28af273 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java @@ -14,9 +14,9 @@ public String outcomeOfPerformingAssertEquals(String fragment, String expectedSt if (resultType.equals("String")) { simulatedResult = result; } else if (resultType.equals("Integer")) { - simulatedResult = new Integer(result); + simulatedResult = Integer.valueOf(result); } else if (resultType.equals("Double")) { - simulatedResult = new Double(result); + simulatedResult = Double.valueOf(result); } else { throw new RuntimeException("Unsupported result-type '" + resultType + "'."); } diff --git a/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java b/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java index f77763b2..138869b5 100644 --- a/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java +++ b/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java @@ -10,7 +10,7 @@ public class AssertFalseTest { public String successOrFailure(String fragment, String evaluationResult) { return new TestRig() - .withStubbedEvaluationResult(new Boolean(evaluationResult)) + .withStubbedEvaluationResult(Boolean.valueOf(evaluationResult)) .processFragment(fragment) .successOrFailureInWords(); } diff --git a/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java b/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java index 1c73765a..6d6b92dd 100644 --- a/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java +++ b/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java @@ -10,7 +10,7 @@ public class AssertTrueTest { public String successOrFailure(String fragment, String evaluationResult) { return new TestRig() - .withStubbedEvaluationResult(new Boolean(evaluationResult)) + .withStubbedEvaluationResult(Boolean.valueOf(evaluationResult)) .processFragment(fragment) .successOrFailureInWords(); } From ac2a231bec0d735c2c31d49e76dd9ec53941bd48 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 28 May 2023 12:00:26 +1200 Subject: [PATCH 21/45] Update next version to 3.2.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index acfb1e28..721b0d9e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ group=org.concordion -version=3.1.3 +version=3.2.0 From 13ea41cd947381ee4e5c7d05b128f5badb2cb981 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 5 Jun 2023 20:46:54 +1200 Subject: [PATCH 22/45] Add Manifold preprocessor and update examples to run JUnit Vintage or Jupiter. Run the 'testVintage' task to run the tests with JUnit Vintage. This sets the 'JUNIT_VINTAGE' directive. The example tests check this directive to determine whether to annotate with '@RunWith(ConcordionRunner.class)' or '@ConcordionFixture'. Run the 'test' task to run without the 'JUNIT_VINTAGE' directive. --- build.gradle | 28 +++++++++++++++++++ src/test/java/spec/examples/DemoTest.java | 7 ++++- .../spec/examples/PartialMatchesTest.java | 7 ++++- src/test/java/spec/examples/SpikeTest.java | 10 ++++++- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 826c50cc..52ea2575 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,9 @@ +// Provides tasks to build, test, package, sign, publish and release Concordion. +// To test, use either the 'test' or 'testVintage' tasks. +// 'testVintage' defines a `JUNIT_VINTAGE`symbol which can be used in directives, parsed by the Manifold preprocessor plugins { id 'java-library' + id 'systems.manifold.manifold-gradle-plugin' version '0.0.2-alpha' // Publishing id 'maven-publish' @@ -21,6 +25,7 @@ repositories { ext { junitJupiterVersion = '5.8.2' flexmarkVersion = '0.62.2' + manifoldVersion = '2023.1.10' githubUrl = "https://github.com/concordion/${project.name}" issuesUrl = "${githubUrl}/issues" vcsUrl = "${githubUrl}.git" @@ -70,6 +75,13 @@ dependencies { testImplementation 'com.github.stefanbirkner:system-rules:1.16.0', "com.vladsch.flexmark:flexmark-ext-abbreviation:$flexmarkVersion" + + implementation ("systems.manifold:manifold-preprocessor:$manifoldVersion") { + because 'preprocesses annotation to determine whether to run JUNIT_JUPITER or JUNIT_VINTAGE' + } + annotationProcessor ("systems.manifold:manifold-preprocessor:$manifoldVersion") { + because 'preprocesses annotation to determine whether to run JUNIT_JUPITER or JUNIT_VINTAGE' + } } sourceSets { @@ -98,6 +110,7 @@ test { } compileTestJava.dependsOn compileTestDummiesJava +compileTestJava.options.compilerArgs += ['-Xplugin:Manifold'] // Publishing task testJar(type: Jar, dependsOn: testClasses) { @@ -106,6 +119,21 @@ task testJar(type: Jar, dependsOn: testClasses) { archiveClassifier = "tests" } +// Add a 'testVintage' task to test JUnit Vintage +// This relies on JUnit Vintage code being within an `#if JUNIT_VINTAGE ... #endif` block +// which the Manifold preprocessor will parse +task testVintage(type: Test) { +} + +gradle.taskGraph.whenReady { taskGraph -> + if (taskGraph.hasTask(testVintage)) { + compileTestJava.options.compilerArgs += ['-AJUNIT_VINTAGE'] + if (taskGraph.hasTask(test)) { + throw new GradleException("Only one of the tasks 'test' or 'testVintage' can be specified since they apply different preprocessor options") + } + } +} + java { withJavadocJar() withSourcesJar() diff --git a/src/test/java/spec/examples/DemoTest.java b/src/test/java/spec/examples/DemoTest.java index 1ee0d6e9..2a6b1a93 100644 --- a/src/test/java/spec/examples/DemoTest.java +++ b/src/test/java/spec/examples/DemoTest.java @@ -2,9 +2,14 @@ import org.concordion.api.ConcordionFixture; import org.concordion.api.ConcordionResources; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; -// @RunWith(ConcordionRunner.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else @ConcordionFixture +#endif @ConcordionResources(value="/concordion.css", includeDefaultStyling = false) public class DemoTest { diff --git a/src/test/java/spec/examples/PartialMatchesTest.java b/src/test/java/spec/examples/PartialMatchesTest.java index 2a3c98be..5fc42684 100644 --- a/src/test/java/spec/examples/PartialMatchesTest.java +++ b/src/test/java/spec/examples/PartialMatchesTest.java @@ -6,9 +6,14 @@ import java.util.TreeSet; import org.concordion.api.ConcordionFixture; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; -// @RunWith(ConcordionRunner.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else @ConcordionFixture +#endif public class PartialMatchesTest { private Set usernamesInSystem = new HashSet(); diff --git a/src/test/java/spec/examples/SpikeTest.java b/src/test/java/spec/examples/SpikeTest.java index c6f48a0f..caa80bab 100644 --- a/src/test/java/spec/examples/SpikeTest.java +++ b/src/test/java/spec/examples/SpikeTest.java @@ -5,10 +5,15 @@ import org.concordion.api.ConcordionFixture; import org.concordion.api.ExpectedToPass; +import org.concordion.integration.junit4.ConcordionRunner; +import org.junit.runner.RunWith; @ExpectedToPass -// @RunWith(ConcordionRunner.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else @ConcordionFixture +#endif public class SpikeTest { public String getGreetingFor(String name) { @@ -21,8 +26,11 @@ public void doSomething() { @SuppressWarnings("serial") public Collection getPeople() { return new ArrayList() {{ +// #if JUNIT_VINTAGE add(new Person("John", "Travolta")); +// #else // add(new Person("Frank", "Zappa")); +// #endif }}; } From dcf9df6fb68fb704f2a5c0ef2ad5002e75aa82fe Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 5 Jun 2023 20:50:57 +1200 Subject: [PATCH 23/45] Update some tests to use either JUnit Vintage or Jupiter. --- .../java/spec/concordion/annotation/AnnotationFixture.java | 5 +++++ .../java/spec/concordion/annotation/FlexmarkOptions.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/test/java/spec/concordion/annotation/AnnotationFixture.java b/src/test/java/spec/concordion/annotation/AnnotationFixture.java index c6a2770c..7a495e06 100644 --- a/src/test/java/spec/concordion/annotation/AnnotationFixture.java +++ b/src/test/java/spec/concordion/annotation/AnnotationFixture.java @@ -1,9 +1,14 @@ package spec.concordion.annotation; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AnnotationFixture { } diff --git a/src/test/java/spec/concordion/annotation/FlexmarkOptions.java b/src/test/java/spec/concordion/annotation/FlexmarkOptions.java index 54fe1223..8f2c3313 100644 --- a/src/test/java/spec/concordion/annotation/FlexmarkOptions.java +++ b/src/test/java/spec/concordion/annotation/FlexmarkOptions.java @@ -1,5 +1,6 @@ package spec.concordion.annotation; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.FixtureInstance; @@ -11,7 +12,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FlexmarkOptions { private JavaSourceCompiler compiler; private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("public class\\s*(.*?)\\s*(\\{|extends)"); From 6fc4c8029e9e008f1ac0977196b7fe2d6c9113e3 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 5 Jun 2023 20:52:05 +1200 Subject: [PATCH 24/45] Only run JUnit4 tests with JUnit Vintage --- .../java/spec/concordion/integration/IntegrationTest.java | 7 ++++++- .../spec/concordion/integration/junit4/Junit4Test.java | 3 +++ .../resources/spec/concordion/integration/Integration.html | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/java/spec/concordion/integration/IntegrationTest.java b/src/test/java/spec/concordion/integration/IntegrationTest.java index 108806ed..61830df8 100644 --- a/src/test/java/spec/concordion/integration/IntegrationTest.java +++ b/src/test/java/spec/concordion/integration/IntegrationTest.java @@ -1,9 +1,14 @@ package spec.concordion.integration; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; -@RunWith(ConcordionRunner.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class IntegrationTest { } diff --git a/src/test/java/spec/concordion/integration/junit4/Junit4Test.java b/src/test/java/spec/concordion/integration/junit4/Junit4Test.java index 71095a6a..951df741 100644 --- a/src/test/java/spec/concordion/integration/junit4/Junit4Test.java +++ b/src/test/java/spec/concordion/integration/junit4/Junit4Test.java @@ -1,6 +1,7 @@ package spec.concordion.integration.junit4; import junit.framework.AssertionFailedError; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.Before; import org.junit.BeforeClass; @@ -9,7 +10,9 @@ import org.junit.runner.RunWith; import org.junit.runners.model.Statement; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#endif public class Junit4Test extends Statement { private static boolean beforeClassCalled=false; diff --git a/src/test/resources/spec/concordion/integration/Integration.html b/src/test/resources/spec/concordion/integration/Integration.html index 9ff0c2d3..529eb907 100644 --- a/src/test/resources/spec/concordion/integration/Integration.html +++ b/src/test/resources/spec/concordion/integration/Integration.html @@ -11,7 +11,7 @@

Running an Active Specification

Concordion integrates with the following testing frameworks:

From 488d2999f28283b9c53a333f454ce87c722061c7 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Mon, 5 Jun 2023 20:59:32 +1200 Subject: [PATCH 25/45] Update GitHub workflow to remove JDK8 build and add Vintage test run. Manifold requires JDK11+ to build. --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72ca927d..69e3a42c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '8', '11', '17' ] + java: [ '11', '17' ] name: Java ${{ matrix.Java }} steps: @@ -25,7 +25,9 @@ jobs: java-version: ${{ matrix.java }} - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build and Test with Gradle + - name: Build and Test with Vintage mode + run: ./gradlew clean testVintage + - name: Build and Test run: ./gradlew clean build javadoc - name: Upload Unit Test Results And Specification From 591c4623abbb2f25a7da0334c84d13e40b4281cc Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Thu, 8 Jun 2023 22:13:25 +1200 Subject: [PATCH 26/45] Reinstantiate test fixture between each example to enforce test isolation --- .../junit/platform/engine/ExampleDescriptor.java | 12 +++++++++++- .../platform/engine/SpecificationDescriptor.java | 6 +++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java index 0e3cf93e..5cefa3bc 100644 --- a/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ExampleDescriptor.java @@ -79,12 +79,22 @@ public ConcordionEngineExecutionContext execute(ConcordionEngineExecutionContext DynamicTestExecutor dynamicTestExecutor) throws Exception { FixtureRunner runner = getFixtureRunner(); - ResultSummary result = runner.run(getExampleName(), getFixtureInstance()); + ResultSummary result = runner.run(getExampleName(), reinstantiateFixtureInstance()); result.assertIsSatisfied(getFixtureType()); return context; } + /** + * Similar to JUnit, Concordion performs test isolation so that each example has a new instance of the fixture class. + * After creating a new instance of the fixture, the specification scoped fields are loaded into the class. + */ + private FixtureInstance reinstantiateFixtureInstance() { + FixtureInstance fixtureInstance = getParentSpecificationTestDescriptor().recreateFixtureInstance(); + fixtureInstance.setupForRun(fixtureInstance.getFixtureObject()); + return fixtureInstance; + } + /* @Override public void after(ConcordionEngineExecutionContext context) throws Exception { diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java index 76292c8d..e285e5ab 100644 --- a/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java +++ b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java @@ -64,6 +64,11 @@ protected FixtureInstance createFixtureInstance() { return new FixtureInstance(createFixtureObject()); } + protected FixtureInstance recreateFixtureInstance() { + fixtureObject = null; + return createFixtureInstance(); + } + protected Object createFixtureObject() { if (fixtureObject == null) { fixtureObject = ReflectionSupport.newInstance(getFixtureClass()); @@ -128,5 +133,4 @@ public void around(ConcordionEngineExecutionContext context, } } } - } From 37e88422c668985d90f45b442cd79a8577e4e36f Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Thu, 8 Jun 2023 22:22:49 +1200 Subject: [PATCH 27/45] Only reinstantiate test fixture on second and following examples --- .../junit/platform/engine/SpecificationDescriptor.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java index e285e5ab..5acdb66a 100644 --- a/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java +++ b/src/main/java/org/concordion/integration/junit/platform/engine/SpecificationDescriptor.java @@ -31,6 +31,7 @@ public class SpecificationDescriptor extends FixtureBasedTestDescriptor private Object fixtureObject; private FixtureInstance fixtureInstance; private FixtureRunner fixtureRunner; + private boolean firstTest = true; SpecificationDescriptor(UniqueId parentUniqueId, Class fixtureClass, SpecificationLocator specificationLocator) { @@ -65,8 +66,13 @@ protected FixtureInstance createFixtureInstance() { } protected FixtureInstance recreateFixtureInstance() { - fixtureObject = null; - return createFixtureInstance(); + if (firstTest) { + firstTest = false; + return getFixtureInstance(); + } else { + fixtureObject = null; + return createFixtureInstance(); + } } protected Object createFixtureObject() { From e14d19eae099f562ddeacaffeb0bf6ea360f71aa Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 10 Jun 2023 20:29:46 +1200 Subject: [PATCH 28/45] Updated specification tests to use JUnit5 Jupiter by default --- src/test/java/spec/concordion/ConcordionTest.java | 5 +++++ src/test/java/spec/concordion/ExampleTest.java | 7 ++++++- .../annotation/BeforeAndAfterLoggingFixture.java | 4 ++++ .../BeforeAndAfterLoggingWithListenerFixture.java | 4 ++++ .../annotation/BeforeAndAfterMethodHooksFixture.java | 9 +++++---- .../concordion/annotation/ConcordionOptionsFixture.java | 5 +++++ .../annotation/ConcordionResourcesFixture.java | 5 +++++ .../concordion/annotation/ConcordionScopedFixture.java | 5 +++++ .../annotation/ImplementationStatusFixture.java | 5 +++++ .../java/spec/concordion/common/command/CommandTest.java | 5 +++++ .../common/command/assertEquals/AssertEqualsTest.java | 5 +++++ .../common/command/assertEquals/ExceptionsTest.java | 5 +++++ .../common/command/assertEquals/NestedActionsTest.java | 5 +++++ .../common/command/assertEquals/NestedElementsTest.java | 5 +++++ .../command/assertEquals/SupportedElementsTest.java | 5 +++++ .../assertEquals/nonString/AssertEqualsBooleanTest.java | 5 +++++ .../command/assertEquals/nonString/NonStringTest.java | 5 +++++ .../command/assertEquals/nonString/NullResultTest.java | 5 +++++ .../command/assertEquals/nonString/VoidResultTest.java | 5 +++++ .../assertEquals/whitespace/LineContinuationsTest.java | 5 +++++ .../assertEquals/whitespace/NormalizationTest.java | 7 +++++-- .../command/assertEquals/whitespace/WhitespaceTest.java | 5 +++++ .../common/command/assertFalse/AssertFalseTest.java | 5 +++++ .../common/command/assertTrue/AssertTrueTest.java | 5 +++++ .../common/command/echo/DisplayingNullsTest.java | 6 +++++- .../spec/concordion/common/command/echo/EchoTest.java | 6 +++++- .../common/command/echo/EscapingHtmlCharactersTest.java | 6 +++++- .../common/command/example/ExampleFixture.java | 5 +++++ .../common/command/example/FailFastExampleFixture.java | 5 +++++ .../example/FixtureWithExampleHookMethodsFixture.java | 5 +++++ .../example/FixtureWithExampleInitialisationFixture.java | 5 +++++ ...WithExampleWithoutOuterExampleHookMethodsFixture.java | 5 +++++ ...hExampleWithoutOuterExampleInitialisationFixture.java | 5 +++++ .../example/FixtureWithoutExampleHookMethodsFixture.java | 5 +++++ .../FixtureWithoutExampleInitialisationFixture.java | 5 +++++ .../example/SpecCallingFailFastExampleFixture.java | 5 +++++ .../common/command/execute/AccessToLinkHrefTest.java | 5 +++++ .../command/execute/ContinueAfterExceptionsFixture.java | 5 +++++ .../concordion/common/command/execute/ExecuteTest.java | 5 +++++ .../common/command/execute/ExecutingListTest.java | 5 +++++ .../common/command/execute/ExecutingTablesTest.java | 5 +++++ .../common/command/execute/FailFastFixture.java | 5 +++++ .../execute/FailFastOnSpecificExceptionsFixture.java | 5 +++++ .../command/execute/FailFastPassthroughFixture.java | 5 +++++ .../command/expressions/ComplexExpressionsTest.java | 5 +++++ .../common/command/expressions/ExpressionsTest.java | 5 +++++ .../command/results/contentType/ContentTypeTest.java | 5 +++++ .../results/stylesheet/MissingHeadElementTest.java | 5 +++++ .../command/results/stylesheet/StylesheetTest.java | 5 +++++ .../concordion/common/command/run/CustomRunnerTest.java | 9 +++++++-- .../spec/concordion/common/command/run/HrefUpdates.java | 5 +++++ .../java/spec/concordion/common/command/run/RunTest.java | 5 +++++ .../common/command/run/SyntaxForRelativePathsTest.java | 5 +++++ .../java/spec/concordion/common/command/set/SetTest.java | 5 +++++ .../common/command/verifyRows/TableBodySupportTest.java | 5 +++++ .../common/command/verifyRows/VerifyRowsTest.java | 5 +++++ .../command/verifyRows/VerifyRowsXHTMLNamespace.java | 5 +++++ .../command/verifyRows/results/MissingRowsTest.java | 5 +++++ .../command/verifyRows/results/SurplusRowsTest.java | 5 +++++ .../verifyRows/strategies/BaseMatchStrategyTest.java | 7 ++++++- .../verifyRows/strategies/BestMatchStrategyTest.java | 5 +++++ .../verifyRows/strategies/DefaultMatchStrategyTest.java | 6 +++++- .../verifyRows/strategies/KeyMatchStrategyTest.java | 6 +++++- .../command/verifyRows/strategies/StrategiesTest.java | 5 +++++ .../strategies/UnspecifiedMatchStrategyTest.java | 6 +++++- .../concordion/common/extension/CSSExtensionTest.java | 5 +++++ .../concordion/common/extension/CustomCommandTest.java | 5 +++++ .../common/extension/ExtensionConfigurationTest.java | 8 +++++++- .../spec/concordion/common/extension/ExtensionTest.java | 5 +++++ .../common/extension/FileSuffixExtensionsTest.java | 5 +++++ .../extension/ImplementationStatusModifierTest.java | 4 ++++ .../common/extension/JavaScriptExtensionTest.java | 5 +++++ .../common/extension/ResourceExtensionTest.java | 5 +++++ .../common/extension/listener/ExampleListenerTest.java | 5 +++++ .../extension/listener/ExecuteTableListenerTest.java | 5 +++++ .../common/extension/listener/ListenerTest.java | 5 +++++ .../extension/listener/ProcessingListenerTest.java | 5 +++++ .../extension/listener/VerifyRowsListenerTest.java | 5 +++++ .../java/spec/concordion/common/results/ResultsTest.java | 5 +++++ .../common/results/assertEquals/failure/AnchorsTest.java | 5 +++++ .../common/results/assertEquals/failure/EmptyTest.java | 5 +++++ .../common/results/assertEquals/failure/FailureTest.java | 5 +++++ .../results/assertEquals/failure/NestedElementsTest.java | 5 +++++ .../common/results/assertEquals/success/EmptyTest.java | 6 +++++- .../results/assertEquals/success/HasAttributesTest.java | 6 +++++- .../assertEquals/success/HasClassAttributeTest.java | 6 +++++- .../common/results/assertEquals/success/SuccessTest.java | 5 +++++ .../common/results/assertTrue/failure/FailureTest.java | 5 +++++ .../common/results/assertTrue/success/SuccessTest.java | 5 +++++ .../common/results/breadcrumbs/BreadcrumbsTest.java | 5 +++++ .../results/breadcrumbs/DeterminingBreadcrumbsTest.java | 6 +++++- .../common/results/breadcrumbs/WordingTest.java | 6 +++++- .../common/results/exception/ExceptionTest.java | 5 +++++ .../common/results/runTotals/CachedResultsTest.java | 5 +++++ .../runTotals/FailIfCalledMultipleTimesFixture.java | 5 +++++ .../common/results/runTotals/RunTotalsFixture.java | 5 +++++ .../specificationType/SpecificationTypeFixture.java | 5 +++++ .../concordion/specificationType/html/HtmlFixture.java | 5 +++++ .../specificationType/html/LowerCaseCommandsFixture.java | 5 +++++ .../markdown/MarkdownAssertEqualsCommandFixture.java | 5 +++++ .../markdown/MarkdownExampleCommandFixture.java | 5 +++++ .../markdown/MarkdownExecuteCommandFixture.java | 5 +++++ .../specificationType/markdown/MarkdownFixture.java | 5 +++++ .../markdown/MarkdownGrammarFixture.java | 5 +++++ .../markdown/MarkdownRunCommandFixture.java | 5 +++++ .../markdown/MarkdownSetCommandFixture.java | 5 +++++ .../markdown/MarkdownVerifyRowsCommandFixture.java | 5 +++++ 107 files changed, 538 insertions(+), 22 deletions(-) diff --git a/src/test/java/spec/concordion/ConcordionTest.java b/src/test/java/spec/concordion/ConcordionTest.java index e4d08104..676b90c6 100644 --- a/src/test/java/spec/concordion/ConcordionTest.java +++ b/src/test/java/spec/concordion/ConcordionTest.java @@ -1,9 +1,14 @@ package spec.concordion; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ConcordionTest { } diff --git a/src/test/java/spec/concordion/ExampleTest.java b/src/test/java/spec/concordion/ExampleTest.java index f3ac66e4..da587b60 100644 --- a/src/test/java/spec/concordion/ExampleTest.java +++ b/src/test/java/spec/concordion/ExampleTest.java @@ -1,12 +1,17 @@ package spec.concordion; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; -@RunWith(ConcordionRunner.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExampleTest { public String process(String html) { diff --git a/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingFixture.java b/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingFixture.java index 16ca9fe1..510f0a6e 100644 --- a/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingFixture.java +++ b/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingFixture.java @@ -7,7 +7,11 @@ import java.util.ArrayList; import java.util.List; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class BeforeAndAfterLoggingFixture { private static List log = new ArrayList(); diff --git a/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingWithListenerFixture.java b/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingWithListenerFixture.java index 3aaf0473..a9c19248 100644 --- a/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingWithListenerFixture.java +++ b/src/test/java/spec/concordion/annotation/BeforeAndAfterLoggingWithListenerFixture.java @@ -10,7 +10,11 @@ import test.concordion.extension.ExampleEventTestExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class BeforeAndAfterLoggingWithListenerFixture { private static List log = new ArrayList(); diff --git a/src/test/java/spec/concordion/annotation/BeforeAndAfterMethodHooksFixture.java b/src/test/java/spec/concordion/annotation/BeforeAndAfterMethodHooksFixture.java index 6a3dafd1..bb5eb98f 100644 --- a/src/test/java/spec/concordion/annotation/BeforeAndAfterMethodHooksFixture.java +++ b/src/test/java/spec/concordion/annotation/BeforeAndAfterMethodHooksFixture.java @@ -3,16 +3,17 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import org.concordion.api.BeforeExample; -import org.concordion.api.ExampleName; -import org.concordion.api.Scope; -import org.concordion.api.ScopedObjectHolder; +import org.concordion.api.*; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.FixtureInstance; import org.junit.runner.RunWith; import test.concordion.RunCommandSimulator; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class BeforeAndAfterMethodHooksFixture { private String exampleName; diff --git a/src/test/java/spec/concordion/annotation/ConcordionOptionsFixture.java b/src/test/java/spec/concordion/annotation/ConcordionOptionsFixture.java index 868d5598..298ff143 100644 --- a/src/test/java/spec/concordion/annotation/ConcordionOptionsFixture.java +++ b/src/test/java/spec/concordion/annotation/ConcordionOptionsFixture.java @@ -1,6 +1,7 @@ package spec.concordion.annotation; import com.vladsch.flexmark.profile.pegdown.Extensions; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.ConcordionOptionsParser; import org.concordion.internal.ConfigurationException; @@ -11,7 +12,11 @@ import java.util.Map; import java.util.TreeMap; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ConcordionOptionsFixture { private int pegdownExtensions; diff --git a/src/test/java/spec/concordion/annotation/ConcordionResourcesFixture.java b/src/test/java/spec/concordion/annotation/ConcordionResourcesFixture.java index 89e9fe92..08089c75 100644 --- a/src/test/java/spec/concordion/annotation/ConcordionResourcesFixture.java +++ b/src/test/java/spec/concordion/annotation/ConcordionResourcesFixture.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Element; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; @@ -12,7 +13,11 @@ import test.concordion.ProcessingResult; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ConcordionResourcesFixture { private TestRig testRig = null; private JavaSourceCompiler compiler; diff --git a/src/test/java/spec/concordion/annotation/ConcordionScopedFixture.java b/src/test/java/spec/concordion/annotation/ConcordionScopedFixture.java index 4253045d..f37899d4 100644 --- a/src/test/java/spec/concordion/annotation/ConcordionScopedFixture.java +++ b/src/test/java/spec/concordion/annotation/ConcordionScopedFixture.java @@ -2,13 +2,18 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.concordion.api.ConcordionFixture; import org.concordion.api.ConcordionScoped; import org.concordion.api.ScopedObjectHolder; import org.concordion.api.Scope; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ConcordionScopedFixture { @org.concordion.api.ConcordionScoped(Scope.EXAMPLE) diff --git a/src/test/java/spec/concordion/annotation/ImplementationStatusFixture.java b/src/test/java/spec/concordion/annotation/ImplementationStatusFixture.java index d0d3c335..76bdc181 100644 --- a/src/test/java/spec/concordion/annotation/ImplementationStatusFixture.java +++ b/src/test/java/spec/concordion/annotation/ImplementationStatusFixture.java @@ -1,9 +1,14 @@ package spec.concordion.annotation; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ImplementationStatusFixture { } diff --git a/src/test/java/spec/concordion/common/command/CommandTest.java b/src/test/java/spec/concordion/common/command/CommandTest.java index bf2fddb2..60a509ac 100644 --- a/src/test/java/spec/concordion/common/command/CommandTest.java +++ b/src/test/java/spec/concordion/common/command/CommandTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.command; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class CommandTest { } diff --git a/src/test/java/spec/concordion/common/command/assertEquals/AssertEqualsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/AssertEqualsTest.java index 779ccb11..d79221a1 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/AssertEqualsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/AssertEqualsTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AssertEqualsTest { public String successOrFailure(String fragment, String evaluationResult) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/ExceptionsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/ExceptionsTest.java index 0cd101f4..2929d64b 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/ExceptionsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/ExceptionsTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExceptionsTest { public Object countsFromExecutingSnippetWithSimulatedEvaluationResult(String snippet, String simulatedResult) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/NestedActionsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/NestedActionsTest.java index 6b82c4bd..8ba866be 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/NestedActionsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/NestedActionsTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.command.assertEquals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NestedActionsTest { // TODO } diff --git a/src/test/java/spec/concordion/common/command/assertEquals/NestedElementsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/NestedElementsTest.java index bb39de6e..0f8194d5 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/NestedElementsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/NestedElementsTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NestedElementsTest { public String matchOrNotMatch(String snippet, String evaluationResult) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/SupportedElementsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/SupportedElementsTest.java index 5c49e488..0f0f4182 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/SupportedElementsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/SupportedElementsTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SupportedElementsTest { public String process(String snippet) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/nonString/AssertEqualsBooleanTest.java b/src/test/java/spec/concordion/common/command/assertEquals/nonString/AssertEqualsBooleanTest.java index ff4c0fca..93dcb70e 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/nonString/AssertEqualsBooleanTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/nonString/AssertEqualsBooleanTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals.nonString; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AssertEqualsBooleanTest { public String successOrFailure(String fragment, String value, String evaluationResult) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java index d28af273..b323121e 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NonStringTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals.nonString; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NonStringTest { public String outcomeOfPerformingAssertEquals(String fragment, String expectedString, String result, String resultType) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NullResultTest.java b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NullResultTest.java index 2f035827..bccd9308 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/nonString/NullResultTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/nonString/NullResultTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertEquals.nonString; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NullResultTest { public String outcomeOfPerformingAssertEquals(String snippet, String expectedString, String result) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/nonString/VoidResultTest.java b/src/test/java/spec/concordion/common/command/assertEquals/nonString/VoidResultTest.java index 018ca834..ce27d907 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/nonString/VoidResultTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/nonString/VoidResultTest.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.assertEquals.nonString; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.ProcessingResult; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class VoidResultTest { public String process(String snippet) { diff --git a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/LineContinuationsTest.java b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/LineContinuationsTest.java index 8703f945..a80e32b3 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/LineContinuationsTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/LineContinuationsTest.java @@ -3,12 +3,17 @@ import java.util.ArrayList; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class LineContinuationsTest { private List snippets = new ArrayList(); diff --git a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/NormalizationTest.java b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/NormalizationTest.java index b40d131a..a04e42f6 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/NormalizationTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/NormalizationTest.java @@ -1,11 +1,14 @@ package spec.concordion.common.command.assertEquals.whitespace; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NormalizationTest extends WhitespaceTest { } diff --git a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/WhitespaceTest.java b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/WhitespaceTest.java index ba28d7f9..d84c1e1f 100644 --- a/src/test/java/spec/concordion/common/command/assertEquals/whitespace/WhitespaceTest.java +++ b/src/test/java/spec/concordion/common/command/assertEquals/whitespace/WhitespaceTest.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.assertEquals.whitespace; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.CatchAllExpectationChecker; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class WhitespaceTest { public String whichSnippetsSucceed(String snippet1, String snippet2, String evaluationResult) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java b/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java index 138869b5..50b7ae62 100644 --- a/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java +++ b/src/test/java/spec/concordion/common/command/assertFalse/AssertFalseTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertFalse; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AssertFalseTest { public String successOrFailure(String fragment, String evaluationResult) { diff --git a/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java b/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java index 6d6b92dd..03dad50f 100644 --- a/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java +++ b/src/test/java/spec/concordion/common/command/assertTrue/AssertTrueTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.assertTrue; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AssertTrueTest { public String successOrFailure(String fragment, String evaluationResult) { diff --git a/src/test/java/spec/concordion/common/command/echo/DisplayingNullsTest.java b/src/test/java/spec/concordion/common/command/echo/DisplayingNullsTest.java index 9762fc1d..949cf314 100644 --- a/src/test/java/spec/concordion/common/command/echo/DisplayingNullsTest.java +++ b/src/test/java/spec/concordion/common/command/echo/DisplayingNullsTest.java @@ -1,12 +1,16 @@ package spec.concordion.common.command.echo; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class DisplayingNullsTest { public String render(String fragment) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/echo/EchoTest.java b/src/test/java/spec/concordion/common/command/echo/EchoTest.java index e3958d5d..bcd90471 100644 --- a/src/test/java/spec/concordion/common/command/echo/EchoTest.java +++ b/src/test/java/spec/concordion/common/command/echo/EchoTest.java @@ -1,12 +1,16 @@ package spec.concordion.common.command.echo; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class EchoTest { private String nextResult; diff --git a/src/test/java/spec/concordion/common/command/echo/EscapingHtmlCharactersTest.java b/src/test/java/spec/concordion/common/command/echo/EscapingHtmlCharactersTest.java index e92a24e7..f66bc9cb 100644 --- a/src/test/java/spec/concordion/common/command/echo/EscapingHtmlCharactersTest.java +++ b/src/test/java/spec/concordion/common/command/echo/EscapingHtmlCharactersTest.java @@ -1,12 +1,16 @@ package spec.concordion.common.command.echo; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class EscapingHtmlCharactersTest { public String render(String fragment, String evalResult) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/example/ExampleFixture.java b/src/test/java/spec/concordion/common/command/example/ExampleFixture.java index bbfc551c..69221767 100644 --- a/src/test/java/spec/concordion/common/command/example/ExampleFixture.java +++ b/src/test/java/spec/concordion/common/command/example/ExampleFixture.java @@ -2,13 +2,18 @@ import java.util.Map; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FullOGNL; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.results.runTotals.RunTotalsFixture; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL public class ExampleFixture extends SpecWithBeforeSpec { diff --git a/src/test/java/spec/concordion/common/command/example/FailFastExampleFixture.java b/src/test/java/spec/concordion/common/command/example/FailFastExampleFixture.java index 04bf5aaf..2d580ade 100644 --- a/src/test/java/spec/concordion/common/command/example/FailFastExampleFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FailFastExampleFixture.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.example; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FailFast; import org.concordion.api.FullOGNL; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL @FailFast public class FailFastExampleFixture { diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleHookMethodsFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleHookMethodsFixture.java index 2846eeae..bb73ba82 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleHookMethodsFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleHookMethodsFixture.java @@ -4,10 +4,15 @@ import org.concordion.api.AfterExample; import org.concordion.api.BeforeExample; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithExampleHookMethodsFixture { private static AtomicInteger staticBeforeExampleCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleInitialisationFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleInitialisationFixture.java index cfabd21e..b056bc86 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleInitialisationFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleInitialisationFixture.java @@ -2,10 +2,15 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithExampleInitialisationFixture { private static AtomicInteger staticFieldCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleHookMethodsFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleHookMethodsFixture.java index 080f278a..48788312 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleHookMethodsFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleHookMethodsFixture.java @@ -4,10 +4,15 @@ import org.concordion.api.AfterExample; import org.concordion.api.BeforeExample; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithExampleWithoutOuterExampleHookMethodsFixture { private static AtomicInteger staticBeforeExampleCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleInitialisationFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleInitialisationFixture.java index c33d7629..371fb2b9 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleInitialisationFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithExampleWithoutOuterExampleInitialisationFixture.java @@ -2,10 +2,15 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithExampleWithoutOuterExampleInitialisationFixture { private static AtomicInteger staticFieldCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleHookMethodsFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleHookMethodsFixture.java index 6a1c8a27..0fda00f7 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleHookMethodsFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleHookMethodsFixture.java @@ -4,10 +4,15 @@ import org.concordion.api.AfterExample; import org.concordion.api.BeforeExample; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithoutExampleHookMethodsFixture { private static AtomicInteger staticBeforeExampleCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleInitialisationFixture.java b/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleInitialisationFixture.java index 01ad1e71..c38e7f13 100644 --- a/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleInitialisationFixture.java +++ b/src/test/java/spec/concordion/common/command/example/FixtureWithoutExampleInitialisationFixture.java @@ -2,10 +2,15 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FixtureWithoutExampleInitialisationFixture { private static AtomicInteger staticFieldCounter = new AtomicInteger(); diff --git a/src/test/java/spec/concordion/common/command/example/SpecCallingFailFastExampleFixture.java b/src/test/java/spec/concordion/common/command/example/SpecCallingFailFastExampleFixture.java index 778c2f5c..6c39b5a8 100644 --- a/src/test/java/spec/concordion/common/command/example/SpecCallingFailFastExampleFixture.java +++ b/src/test/java/spec/concordion/common/command/example/SpecCallingFailFastExampleFixture.java @@ -1,10 +1,15 @@ package spec.concordion.common.command.example; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.results.runTotals.RunTotalsFixture; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SpecCallingFailFastExampleFixture extends RunTotalsFixture { } diff --git a/src/test/java/spec/concordion/common/command/execute/AccessToLinkHrefTest.java b/src/test/java/spec/concordion/common/command/execute/AccessToLinkHrefTest.java index 160693b2..4dfe9766 100644 --- a/src/test/java/spec/concordion/common/command/execute/AccessToLinkHrefTest.java +++ b/src/test/java/spec/concordion/common/command/execute/AccessToLinkHrefTest.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.execute; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.ProcessingResult; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AccessToLinkHrefTest { public boolean fragmentSucceeds(String fragment) { diff --git a/src/test/java/spec/concordion/common/command/execute/ContinueAfterExceptionsFixture.java b/src/test/java/spec/concordion/common/command/execute/ContinueAfterExceptionsFixture.java index 7205b91f..000ebdaf 100644 --- a/src/test/java/spec/concordion/common/command/execute/ContinueAfterExceptionsFixture.java +++ b/src/test/java/spec/concordion/common/command/execute/ContinueAfterExceptionsFixture.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.execute; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ContinueAfterExceptionsFixture { private boolean myMethodWasCalled = false; diff --git a/src/test/java/spec/concordion/common/command/execute/ExecuteTest.java b/src/test/java/spec/concordion/common/command/execute/ExecuteTest.java index 1de5ec57..686af8f9 100644 --- a/src/test/java/spec/concordion/common/command/execute/ExecuteTest.java +++ b/src/test/java/spec/concordion/common/command/execute/ExecuteTest.java @@ -5,13 +5,18 @@ import java.util.Set; import java.util.TreeSet; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FullOGNL; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL public class ExecuteTest { diff --git a/src/test/java/spec/concordion/common/command/execute/ExecutingListTest.java b/src/test/java/spec/concordion/common/command/execute/ExecutingListTest.java index b0b21ee8..b8b52d26 100644 --- a/src/test/java/spec/concordion/common/command/execute/ExecutingListTest.java +++ b/src/test/java/spec/concordion/common/command/execute/ExecutingListTest.java @@ -3,13 +3,18 @@ import java.util.ArrayList; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.api.MultiValueResult; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExecutingListTest { private List treeEntries = new ArrayList(); diff --git a/src/test/java/spec/concordion/common/command/execute/ExecutingTablesTest.java b/src/test/java/spec/concordion/common/command/execute/ExecutingTablesTest.java index 42286654..ead203fb 100644 --- a/src/test/java/spec/concordion/common/command/execute/ExecutingTablesTest.java +++ b/src/test/java/spec/concordion/common/command/execute/ExecutingTablesTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.command.execute; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FullOGNL; import org.concordion.api.listener.AssertFailureEvent; import org.concordion.integration.junit4.ConcordionRunner; @@ -13,7 +14,11 @@ import java.util.List; import java.util.Map; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL public class ExecutingTablesTest { private List> rows = new ArrayList<>(); diff --git a/src/test/java/spec/concordion/common/command/execute/FailFastFixture.java b/src/test/java/spec/concordion/common/command/execute/FailFastFixture.java index c8cd9b7e..c6bd9edd 100644 --- a/src/test/java/spec/concordion/common/command/execute/FailFastFixture.java +++ b/src/test/java/spec/concordion/common/command/execute/FailFastFixture.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.execute; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FailFast; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FailFast public class FailFastFixture { diff --git a/src/test/java/spec/concordion/common/command/execute/FailFastOnSpecificExceptionsFixture.java b/src/test/java/spec/concordion/common/command/execute/FailFastOnSpecificExceptionsFixture.java index 2bdd6c25..5a2a454a 100644 --- a/src/test/java/spec/concordion/common/command/execute/FailFastOnSpecificExceptionsFixture.java +++ b/src/test/java/spec/concordion/common/command/execute/FailFastOnSpecificExceptionsFixture.java @@ -4,13 +4,18 @@ import java.io.IOException; import java.util.concurrent.TimeoutException; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FailFast; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FailFast(onExceptionType={RuntimeException.class, IOException.class}) public class FailFastOnSpecificExceptionsFixture { diff --git a/src/test/java/spec/concordion/common/command/execute/FailFastPassthroughFixture.java b/src/test/java/spec/concordion/common/command/execute/FailFastPassthroughFixture.java index 93720d5b..f691ed82 100644 --- a/src/test/java/spec/concordion/common/command/execute/FailFastPassthroughFixture.java +++ b/src/test/java/spec/concordion/common/command/execute/FailFastPassthroughFixture.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.execute; +import org.concordion.api.ConcordionFixture; import org.concordion.api.FullOGNL; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.results.runTotals.RunTotalsFixture; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL public class FailFastPassthroughFixture extends RunTotalsFixture { diff --git a/src/test/java/spec/concordion/common/command/expressions/ComplexExpressionsTest.java b/src/test/java/spec/concordion/common/command/expressions/ComplexExpressionsTest.java index 50c38215..699bc3c3 100644 --- a/src/test/java/spec/concordion/common/command/expressions/ComplexExpressionsTest.java +++ b/src/test/java/spec/concordion/common/command/expressions/ComplexExpressionsTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.command.expressions; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Evaluator; import org.concordion.api.FullOGNL; import org.concordion.api.MultiValueResult; @@ -13,7 +14,11 @@ import static java.util.Collections.singletonMap; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ComplexExpressionsTest { private final Evaluator simple = new SimpleEvaluator(new FixtureInstance(new SimpleTestFixture())); diff --git a/src/test/java/spec/concordion/common/command/expressions/ExpressionsTest.java b/src/test/java/spec/concordion/common/command/expressions/ExpressionsTest.java index 72ad0d75..ba8b77eb 100644 --- a/src/test/java/spec/concordion/common/command/expressions/ExpressionsTest.java +++ b/src/test/java/spec/concordion/common/command/expressions/ExpressionsTest.java @@ -1,10 +1,15 @@ package spec.concordion.common.command.expressions; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.SimpleEvaluator; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExpressionsTest { public boolean isValidEvaluationExpression(String evaluateExpression) { diff --git a/src/test/java/spec/concordion/common/command/results/contentType/ContentTypeTest.java b/src/test/java/spec/concordion/common/command/results/contentType/ContentTypeTest.java index 3af6c59e..1dbb1056 100644 --- a/src/test/java/spec/concordion/common/command/results/contentType/ContentTypeTest.java +++ b/src/test/java/spec/concordion/common/command/results/contentType/ContentTypeTest.java @@ -2,12 +2,17 @@ import nu.xom.Element; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ContentTypeTest { public String process(String html) { diff --git a/src/test/java/spec/concordion/common/command/results/stylesheet/MissingHeadElementTest.java b/src/test/java/spec/concordion/common/command/results/stylesheet/MissingHeadElementTest.java index 6335283d..f68743d4 100644 --- a/src/test/java/spec/concordion/common/command/results/stylesheet/MissingHeadElementTest.java +++ b/src/test/java/spec/concordion/common/command/results/stylesheet/MissingHeadElementTest.java @@ -2,12 +2,17 @@ import nu.xom.Element; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MissingHeadElementTest { public String process(String html) { diff --git a/src/test/java/spec/concordion/common/command/results/stylesheet/StylesheetTest.java b/src/test/java/spec/concordion/common/command/results/stylesheet/StylesheetTest.java index 24c7921f..cb9ab180 100644 --- a/src/test/java/spec/concordion/common/command/results/stylesheet/StylesheetTest.java +++ b/src/test/java/spec/concordion/common/command/results/stylesheet/StylesheetTest.java @@ -1,12 +1,17 @@ package spec.concordion.common.command.results.stylesheet; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Element; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class StylesheetTest { private Element outputDocument; diff --git a/src/test/java/spec/concordion/common/command/run/CustomRunnerTest.java b/src/test/java/spec/concordion/common/command/run/CustomRunnerTest.java index 3569dbe0..3b0c6026 100644 --- a/src/test/java/spec/concordion/common/command/run/CustomRunnerTest.java +++ b/src/test/java/spec/concordion/common/command/run/CustomRunnerTest.java @@ -1,16 +1,21 @@ package spec.concordion.common.command.run; +import org.concordion.api.BeforeSpecification; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class CustomRunnerTest { - @BeforeClass + @BeforeSpecification public static void setUp() { System.setProperty("concordion.runner.exampleRunner", ExampleRunner.class.getName()); } diff --git a/src/test/java/spec/concordion/common/command/run/HrefUpdates.java b/src/test/java/spec/concordion/common/command/run/HrefUpdates.java index fe2eeec9..ec335315 100644 --- a/src/test/java/spec/concordion/common/command/run/HrefUpdates.java +++ b/src/test/java/spec/concordion/common/command/run/HrefUpdates.java @@ -1,9 +1,14 @@ package spec.concordion.common.command.run; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.results.runTotals.RunTotalsFixture; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class HrefUpdates extends RunTotalsFixture { } diff --git a/src/test/java/spec/concordion/common/command/run/RunTest.java b/src/test/java/spec/concordion/common/command/run/RunTest.java index 5f0b74f0..666b98d9 100644 --- a/src/test/java/spec/concordion/common/command/run/RunTest.java +++ b/src/test/java/spec/concordion/common/command/run/RunTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.command.run; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class RunTest{ } diff --git a/src/test/java/spec/concordion/common/command/run/SyntaxForRelativePathsTest.java b/src/test/java/spec/concordion/common/command/run/SyntaxForRelativePathsTest.java index 503a697f..3a879d92 100644 --- a/src/test/java/spec/concordion/common/command/run/SyntaxForRelativePathsTest.java +++ b/src/test/java/spec/concordion/common/command/run/SyntaxForRelativePathsTest.java @@ -1,10 +1,15 @@ package spec.concordion.common.command.run; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SyntaxForRelativePathsTest{ public String getPath(String resourcePath, String relativePath) { diff --git a/src/test/java/spec/concordion/common/command/set/SetTest.java b/src/test/java/spec/concordion/common/command/set/SetTest.java index a5b13bd8..87b03d95 100644 --- a/src/test/java/spec/concordion/common/command/set/SetTest.java +++ b/src/test/java/spec/concordion/common/command/set/SetTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.command.set; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SetTest { private String param; diff --git a/src/test/java/spec/concordion/common/command/verifyRows/TableBodySupportTest.java b/src/test/java/spec/concordion/common/command/verifyRows/TableBodySupportTest.java index 3335ff23..814b8e08 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/TableBodySupportTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/TableBodySupportTest.java @@ -3,12 +3,17 @@ import java.util.ArrayList; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class TableBodySupportTest { private List names = new ArrayList(); diff --git a/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsTest.java b/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsTest.java index 4352be39..afe5b5a2 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsTest.java @@ -7,13 +7,18 @@ import nu.xom.Element; import nu.xom.Nodes; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.util.Check; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class VerifyRowsTest { public Collection usernames; diff --git a/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsXHTMLNamespace.java b/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsXHTMLNamespace.java index fac0d409..e210d2a3 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsXHTMLNamespace.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/VerifyRowsXHTMLNamespace.java @@ -1,9 +1,14 @@ package spec.concordion.common.command.verifyRows; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class VerifyRowsXHTMLNamespace extends VerifyRowsTest { } \ No newline at end of file diff --git a/src/test/java/spec/concordion/common/command/verifyRows/results/MissingRowsTest.java b/src/test/java/spec/concordion/common/command/verifyRows/results/MissingRowsTest.java index 5756c62d..3445f613 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/results/MissingRowsTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/results/MissingRowsTest.java @@ -4,12 +4,17 @@ import java.util.Collection; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MissingRowsTest { private List people = new ArrayList(); diff --git a/src/test/java/spec/concordion/common/command/verifyRows/results/SurplusRowsTest.java b/src/test/java/spec/concordion/common/command/verifyRows/results/SurplusRowsTest.java index 5b555af8..cea7d0f1 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/results/SurplusRowsTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/results/SurplusRowsTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.command.verifyRows.results; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SurplusRowsTest extends MissingRowsTest { public void addPerson(String firstName, String lastName) { diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java index 7584b10a..587a3a32 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java @@ -7,6 +7,7 @@ import nu.xom.Document; +import org.concordion.api.ConcordionFixture; import org.concordion.api.MultiValueResult; import org.concordion.api.Resource; import org.concordion.api.ConcordionResources; @@ -15,7 +16,11 @@ import test.concordion.TestRig; -@Extensions(EmbedExtension.class) +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @ConcordionResources("toggle_html.*") public class BaseMatchStrategyTest { diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BestMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BestMatchStrategyTest.java index e3ccad3d..c7839376 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BestMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BestMatchStrategyTest.java @@ -1,8 +1,13 @@ package spec.concordion.common.command.verifyRows.strategies; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class BestMatchStrategyTest extends BaseMatchStrategyTest { } diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/DefaultMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/DefaultMatchStrategyTest.java index a905f2c8..f08eb98d 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/DefaultMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/DefaultMatchStrategyTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.command.verifyRows.strategies; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class DefaultMatchStrategyTest extends BaseMatchStrategyTest { } diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/KeyMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/KeyMatchStrategyTest.java index f21b5709..7b09983d 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/KeyMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/KeyMatchStrategyTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.command.verifyRows.strategies; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class KeyMatchStrategyTest extends BaseMatchStrategyTest { } diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/StrategiesTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/StrategiesTest.java index 753e8efe..82314070 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/StrategiesTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/StrategiesTest.java @@ -2,11 +2,16 @@ import static org.concordion.api.MultiValueResult.multiValueResult; +import org.concordion.api.ConcordionFixture; import org.concordion.api.MultiValueResult; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class StrategiesTest extends BaseMatchStrategyTest { public MultiValueResult processTableFragment(String fragment, String actualData) throws Exception { diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/UnspecifiedMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/UnspecifiedMatchStrategyTest.java index 479098ca..62076df0 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/UnspecifiedMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/UnspecifiedMatchStrategyTest.java @@ -1,9 +1,13 @@ package spec.concordion.common.command.verifyRows.strategies; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class UnspecifiedMatchStrategyTest extends BaseMatchStrategyTest { } diff --git a/src/test/java/spec/concordion/common/extension/CSSExtensionTest.java b/src/test/java/spec/concordion/common/extension/CSSExtensionTest.java index a455820e..6978432a 100644 --- a/src/test/java/spec/concordion/common/extension/CSSExtensionTest.java +++ b/src/test/java/spec/concordion/common/extension/CSSExtensionTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.extension; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -8,7 +9,11 @@ import test.concordion.extension.CSSEmbeddedExtension; import test.concordion.extension.CSSLinkedExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class CSSExtensionTest extends AbstractExtensionTestCase { public static final String SOURCE_PATH = "/test/concordion/my.css"; diff --git a/src/test/java/spec/concordion/common/extension/CustomCommandTest.java b/src/test/java/spec/concordion/common/extension/CustomCommandTest.java index c8cdaf9a..9ea4194a 100644 --- a/src/test/java/spec/concordion/common/extension/CustomCommandTest.java +++ b/src/test/java/spec/concordion/common/extension/CustomCommandTest.java @@ -2,12 +2,17 @@ import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.extension.CommandExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class CustomCommandTest extends AbstractExtensionTestCase { public void addCommandExtension() { diff --git a/src/test/java/spec/concordion/common/extension/ExtensionConfigurationTest.java b/src/test/java/spec/concordion/common/extension/ExtensionConfigurationTest.java index ac8b38de..08ee7bc1 100644 --- a/src/test/java/spec/concordion/common/extension/ExtensionConfigurationTest.java +++ b/src/test/java/spec/concordion/common/extension/ExtensionConfigurationTest.java @@ -3,6 +3,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.concordion.api.AfterSpecification; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.After; import org.junit.runner.RunWith; @@ -12,13 +14,17 @@ import test.concordion.TestRig; import test.concordion.extension.fake.FakeExtensionBase; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExtensionConfigurationTest { private JavaSourceCompiler compiler; private static final Pattern CLASS_NAME_PATTERN = Pattern.compile("class\\s*(.*?)\\s*(\\{|extends)"); - @After + @AfterSpecification public void clearConcordionExtensionsSystemProperty() { System.clearProperty("concordion.extensions"); } diff --git a/src/test/java/spec/concordion/common/extension/ExtensionTest.java b/src/test/java/spec/concordion/common/extension/ExtensionTest.java index 4b4dce26..e52b49cd 100644 --- a/src/test/java/spec/concordion/common/extension/ExtensionTest.java +++ b/src/test/java/spec/concordion/common/extension/ExtensionTest.java @@ -1,8 +1,13 @@ package spec.concordion.common.extension; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExtensionTest { } diff --git a/src/test/java/spec/concordion/common/extension/FileSuffixExtensionsTest.java b/src/test/java/spec/concordion/common/extension/FileSuffixExtensionsTest.java index fd937fb3..7e974d75 100644 --- a/src/test/java/spec/concordion/common/extension/FileSuffixExtensionsTest.java +++ b/src/test/java/spec/concordion/common/extension/FileSuffixExtensionsTest.java @@ -1,10 +1,15 @@ package spec.concordion.common.extension; +import org.concordion.api.ConcordionFixture; import org.concordion.api.extension.Extensions; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @Extensions(SxhtmlExtension.class) public class FileSuffixExtensionsTest { diff --git a/src/test/java/spec/concordion/common/extension/ImplementationStatusModifierTest.java b/src/test/java/spec/concordion/common/extension/ImplementationStatusModifierTest.java index c30a8392..a7f04196 100644 --- a/src/test/java/spec/concordion/common/extension/ImplementationStatusModifierTest.java +++ b/src/test/java/spec/concordion/common/extension/ImplementationStatusModifierTest.java @@ -14,7 +14,11 @@ /** * Created by bondocaadmin on 10/05/2018. */ +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @FullOGNL public class ImplementationStatusModifierTest extends AbstractExtensionTestCase { diff --git a/src/test/java/spec/concordion/common/extension/JavaScriptExtensionTest.java b/src/test/java/spec/concordion/common/extension/JavaScriptExtensionTest.java index b27e2343..1d729488 100644 --- a/src/test/java/spec/concordion/common/extension/JavaScriptExtensionTest.java +++ b/src/test/java/spec/concordion/common/extension/JavaScriptExtensionTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.extension; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -8,7 +9,11 @@ import test.concordion.extension.JavaScriptEmbeddedExtension; import test.concordion.extension.JavaScriptLinkedExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class JavaScriptExtensionTest extends AbstractExtensionTestCase { public static final String SOURCE_PATH = "/test/concordion/my.js"; diff --git a/src/test/java/spec/concordion/common/extension/ResourceExtensionTest.java b/src/test/java/spec/concordion/common/extension/ResourceExtensionTest.java index fc666caa..79d9fed8 100644 --- a/src/test/java/spec/concordion/common/extension/ResourceExtensionTest.java +++ b/src/test/java/spec/concordion/common/extension/ResourceExtensionTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.extension; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Resource; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -8,7 +9,11 @@ import test.concordion.extension.DynamicResourceExtension; import test.concordion.extension.ResourceExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ResourceExtensionTest extends AbstractExtensionTestCase { public void addResourceExtension() { diff --git a/src/test/java/spec/concordion/common/extension/listener/ExampleListenerTest.java b/src/test/java/spec/concordion/common/extension/listener/ExampleListenerTest.java index 5231d19e..f38bad4d 100644 --- a/src/test/java/spec/concordion/common/extension/listener/ExampleListenerTest.java +++ b/src/test/java/spec/concordion/common/extension/listener/ExampleListenerTest.java @@ -3,6 +3,7 @@ import java.util.List; import org.concordion.api.BeforeSpecification; +import org.concordion.api.ConcordionFixture; import org.concordion.api.extension.Extension; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -10,7 +11,11 @@ import spec.concordion.common.extension.AbstractExtensionTestCase; import test.concordion.extension.ExampleTestExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExampleListenerTest extends AbstractExtensionTestCase { @Extension diff --git a/src/test/java/spec/concordion/common/extension/listener/ExecuteTableListenerTest.java b/src/test/java/spec/concordion/common/extension/listener/ExecuteTableListenerTest.java index 69999878..3acee5f3 100644 --- a/src/test/java/spec/concordion/common/extension/listener/ExecuteTableListenerTest.java +++ b/src/test/java/spec/concordion/common/extension/listener/ExecuteTableListenerTest.java @@ -1,12 +1,17 @@ package spec.concordion.common.extension.listener; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.extension.AbstractExtensionTestCase; import test.concordion.extension.LoggingExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExecuteTableListenerTest extends AbstractExtensionTestCase { public void addLoggingExtension() { diff --git a/src/test/java/spec/concordion/common/extension/listener/ListenerTest.java b/src/test/java/spec/concordion/common/extension/listener/ListenerTest.java index 452ef882..ebc7b2a7 100644 --- a/src/test/java/spec/concordion/common/extension/listener/ListenerTest.java +++ b/src/test/java/spec/concordion/common/extension/listener/ListenerTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.extension.listener; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -8,7 +9,11 @@ import test.concordion.extension.LoggingExtension; import test.concordion.extension.ProcessingExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ListenerTest extends AbstractExtensionTestCase { public void addLoggingExtension() { diff --git a/src/test/java/spec/concordion/common/extension/listener/ProcessingListenerTest.java b/src/test/java/spec/concordion/common/extension/listener/ProcessingListenerTest.java index 877f3e8d..768b16f0 100644 --- a/src/test/java/spec/concordion/common/extension/listener/ProcessingListenerTest.java +++ b/src/test/java/spec/concordion/common/extension/listener/ProcessingListenerTest.java @@ -1,5 +1,6 @@ package spec.concordion.common.extension.listener; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; @@ -7,7 +8,11 @@ import test.concordion.extension.ExampleProcessingExtension; import test.concordion.extension.ProcessingExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ProcessingListenerTest extends AbstractExtensionTestCase { public void addProcessingExtension() { setExtension(new ProcessingExtension().withStream(getLogStream())); diff --git a/src/test/java/spec/concordion/common/extension/listener/VerifyRowsListenerTest.java b/src/test/java/spec/concordion/common/extension/listener/VerifyRowsListenerTest.java index f5fbfb64..481e7701 100644 --- a/src/test/java/spec/concordion/common/extension/listener/VerifyRowsListenerTest.java +++ b/src/test/java/spec/concordion/common/extension/listener/VerifyRowsListenerTest.java @@ -3,13 +3,18 @@ import java.util.Arrays; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import spec.concordion.common.extension.AbstractExtensionTestCase; import test.concordion.extension.LoggingExtension; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class VerifyRowsListenerTest extends AbstractExtensionTestCase { public void addLoggingExtension() { diff --git a/src/test/java/spec/concordion/common/results/ResultsTest.java b/src/test/java/spec/concordion/common/results/ResultsTest.java index b01cd59e..a9013688 100644 --- a/src/test/java/spec/concordion/common/results/ResultsTest.java +++ b/src/test/java/spec/concordion/common/results/ResultsTest.java @@ -1,8 +1,13 @@ package spec.concordion.common.results; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ResultsTest { } diff --git a/src/test/java/spec/concordion/common/results/assertEquals/failure/AnchorsTest.java b/src/test/java/spec/concordion/common/results/assertEquals/failure/AnchorsTest.java index b54a9ef4..74e8b567 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/failure/AnchorsTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/failure/AnchorsTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.results.assertEquals.failure; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class AnchorsTest { // TODO diff --git a/src/test/java/spec/concordion/common/results/assertEquals/failure/EmptyTest.java b/src/test/java/spec/concordion/common/results/assertEquals/failure/EmptyTest.java index 3124de1d..1aa41e4b 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/failure/EmptyTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/failure/EmptyTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.results.assertEquals.failure; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class EmptyTest extends FailureTest { } diff --git a/src/test/java/spec/concordion/common/results/assertEquals/failure/FailureTest.java b/src/test/java/spec/concordion/common/results/assertEquals/failure/FailureTest.java index ac558c22..9f772919 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/failure/FailureTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/failure/FailureTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.results.assertEquals.failure; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FailureTest { public String acronym; diff --git a/src/test/java/spec/concordion/common/results/assertEquals/failure/NestedElementsTest.java b/src/test/java/spec/concordion/common/results/assertEquals/failure/NestedElementsTest.java index 48572ca6..e2827ad0 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/failure/NestedElementsTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/failure/NestedElementsTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.results.assertEquals.failure; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class NestedElementsTest extends FailureTest { } diff --git a/src/test/java/spec/concordion/common/results/assertEquals/success/EmptyTest.java b/src/test/java/spec/concordion/common/results/assertEquals/success/EmptyTest.java index 7f76d3e2..6e85112a 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/success/EmptyTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/success/EmptyTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.results.assertEquals.success; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class EmptyTest extends SuccessTest { public String username = ""; diff --git a/src/test/java/spec/concordion/common/results/assertEquals/success/HasAttributesTest.java b/src/test/java/spec/concordion/common/results/assertEquals/success/HasAttributesTest.java index 697b9c06..730f5940 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/success/HasAttributesTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/success/HasAttributesTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.results.assertEquals.success; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class HasAttributesTest extends SuccessTest { } diff --git a/src/test/java/spec/concordion/common/results/assertEquals/success/HasClassAttributeTest.java b/src/test/java/spec/concordion/common/results/assertEquals/success/HasClassAttributeTest.java index 1f65addc..5feb3080 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/success/HasClassAttributeTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/success/HasClassAttributeTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.results.assertEquals.success; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class HasClassAttributeTest extends SuccessTest { } diff --git a/src/test/java/spec/concordion/common/results/assertEquals/success/SuccessTest.java b/src/test/java/spec/concordion/common/results/assertEquals/success/SuccessTest.java index 7c8691dc..23c6e397 100644 --- a/src/test/java/spec/concordion/common/results/assertEquals/success/SuccessTest.java +++ b/src/test/java/spec/concordion/common/results/assertEquals/success/SuccessTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.results.assertEquals.success; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SuccessTest { public String username = "fred"; diff --git a/src/test/java/spec/concordion/common/results/assertTrue/failure/FailureTest.java b/src/test/java/spec/concordion/common/results/assertTrue/failure/FailureTest.java index 7a6b9ab6..616811a0 100644 --- a/src/test/java/spec/concordion/common/results/assertTrue/failure/FailureTest.java +++ b/src/test/java/spec/concordion/common/results/assertTrue/failure/FailureTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.results.assertTrue.failure; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FailureTest { public boolean isPalindrome(String s) { diff --git a/src/test/java/spec/concordion/common/results/assertTrue/success/SuccessTest.java b/src/test/java/spec/concordion/common/results/assertTrue/success/SuccessTest.java index 633e76db..8720c377 100644 --- a/src/test/java/spec/concordion/common/results/assertTrue/success/SuccessTest.java +++ b/src/test/java/spec/concordion/common/results/assertTrue/success/SuccessTest.java @@ -1,11 +1,16 @@ package spec.concordion.common.results.assertTrue.success; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SuccessTest { public boolean isPalindrome(String s) { diff --git a/src/test/java/spec/concordion/common/results/breadcrumbs/BreadcrumbsTest.java b/src/test/java/spec/concordion/common/results/breadcrumbs/BreadcrumbsTest.java index 9a71e2b3..fca0d90b 100644 --- a/src/test/java/spec/concordion/common/results/breadcrumbs/BreadcrumbsTest.java +++ b/src/test/java/spec/concordion/common/results/breadcrumbs/BreadcrumbsTest.java @@ -1,9 +1,14 @@ package spec.concordion.common.results.breadcrumbs; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class BreadcrumbsTest extends AbstractBreadcrumbsTestCase { public void setUpResource(String resourceName, String content) { diff --git a/src/test/java/spec/concordion/common/results/breadcrumbs/DeterminingBreadcrumbsTest.java b/src/test/java/spec/concordion/common/results/breadcrumbs/DeterminingBreadcrumbsTest.java index 2138e212..77263842 100644 --- a/src/test/java/spec/concordion/common/results/breadcrumbs/DeterminingBreadcrumbsTest.java +++ b/src/test/java/spec/concordion/common/results/breadcrumbs/DeterminingBreadcrumbsTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.results.breadcrumbs; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class DeterminingBreadcrumbsTest extends AbstractBreadcrumbsTestCase { public String getBreadcrumbTextFor(String resourceName) throws Exception { diff --git a/src/test/java/spec/concordion/common/results/breadcrumbs/WordingTest.java b/src/test/java/spec/concordion/common/results/breadcrumbs/WordingTest.java index c2261efc..e342c4a5 100644 --- a/src/test/java/spec/concordion/common/results/breadcrumbs/WordingTest.java +++ b/src/test/java/spec/concordion/common/results/breadcrumbs/WordingTest.java @@ -1,10 +1,14 @@ package spec.concordion.common.results.breadcrumbs; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; - +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class WordingTest extends AbstractBreadcrumbsTestCase { public String getBreadcrumbWordingFor(String resourceName, String content) throws Exception { diff --git a/src/test/java/spec/concordion/common/results/exception/ExceptionTest.java b/src/test/java/spec/concordion/common/results/exception/ExceptionTest.java index cebeaabe..2d3cc69d 100644 --- a/src/test/java/spec/concordion/common/results/exception/ExceptionTest.java +++ b/src/test/java/spec/concordion/common/results/exception/ExceptionTest.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Element; import org.concordion.api.listener.ThrowableCaughtEvent; import org.concordion.integration.junit4.ConcordionRunner; @@ -12,7 +13,11 @@ import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class ExceptionTest { private List stackTraceElements = new ArrayList(); diff --git a/src/test/java/spec/concordion/common/results/runTotals/CachedResultsTest.java b/src/test/java/spec/concordion/common/results/runTotals/CachedResultsTest.java index ba8169c2..746dfb2d 100644 --- a/src/test/java/spec/concordion/common/results/runTotals/CachedResultsTest.java +++ b/src/test/java/spec/concordion/common/results/runTotals/CachedResultsTest.java @@ -1,10 +1,15 @@ package spec.concordion.common.results.runTotals; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class CachedResultsTest { } diff --git a/src/test/java/spec/concordion/common/results/runTotals/FailIfCalledMultipleTimesFixture.java b/src/test/java/spec/concordion/common/results/runTotals/FailIfCalledMultipleTimesFixture.java index 687d5dd5..2c7600e9 100644 --- a/src/test/java/spec/concordion/common/results/runTotals/FailIfCalledMultipleTimesFixture.java +++ b/src/test/java/spec/concordion/common/results/runTotals/FailIfCalledMultipleTimesFixture.java @@ -2,10 +2,15 @@ import java.util.concurrent.atomic.AtomicInteger; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class FailIfCalledMultipleTimesFixture { public static AtomicInteger numberTimesRun = new AtomicInteger(0); diff --git a/src/test/java/spec/concordion/common/results/runTotals/RunTotalsFixture.java b/src/test/java/spec/concordion/common/results/runTotals/RunTotalsFixture.java index b5bf0c2d..8d4a00bd 100644 --- a/src/test/java/spec/concordion/common/results/runTotals/RunTotalsFixture.java +++ b/src/test/java/spec/concordion/common/results/runTotals/RunTotalsFixture.java @@ -2,13 +2,18 @@ import java.util.Map; +import org.concordion.api.ConcordionFixture; import org.concordion.api.Fixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.FixtureInstance; import org.junit.runner.RunWith; import test.concordion.RunCommandSimulator; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class RunTotalsFixture { private Class testClass; diff --git a/src/test/java/spec/concordion/specificationType/SpecificationTypeFixture.java b/src/test/java/spec/concordion/specificationType/SpecificationTypeFixture.java index a04ef7c8..6b13fb28 100644 --- a/src/test/java/spec/concordion/specificationType/SpecificationTypeFixture.java +++ b/src/test/java/spec/concordion/specificationType/SpecificationTypeFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class SpecificationTypeFixture { } diff --git a/src/test/java/spec/concordion/specificationType/html/HtmlFixture.java b/src/test/java/spec/concordion/specificationType/html/HtmlFixture.java index e6402f48..0a72caf7 100644 --- a/src/test/java/spec/concordion/specificationType/html/HtmlFixture.java +++ b/src/test/java/spec/concordion/specificationType/html/HtmlFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.html; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class HtmlFixture { } diff --git a/src/test/java/spec/concordion/specificationType/html/LowerCaseCommandsFixture.java b/src/test/java/spec/concordion/specificationType/html/LowerCaseCommandsFixture.java index 186fa2a4..85e4d9bb 100644 --- a/src/test/java/spec/concordion/specificationType/html/LowerCaseCommandsFixture.java +++ b/src/test/java/spec/concordion/specificationType/html/LowerCaseCommandsFixture.java @@ -1,11 +1,16 @@ package spec.concordion.specificationType.html; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; import test.concordion.TestRig; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class LowerCaseCommandsFixture { public String processEquals(String snippet) throws Exception { diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownAssertEqualsCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownAssertEqualsCommandFixture.java index 57bd791a..e1aea239 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownAssertEqualsCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownAssertEqualsCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownAssertEqualsCommandFixture extends MarkdownGrammarFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownExampleCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownExampleCommandFixture.java index 6cc40e64..fbbae2d6 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownExampleCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownExampleCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownExampleCommandFixture extends MarkdownGrammarFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownExecuteCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownExecuteCommandFixture.java index ce741feb..b98e8802 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownExecuteCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownExecuteCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownExecuteCommandFixture extends MarkdownGrammarFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownFixture.java index bdafd329..819a9d34 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownFixture.java @@ -1,10 +1,15 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.api.ConcordionResources; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif @ConcordionResources({"img/*","Markdown.css"}) public class MarkdownFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownGrammarFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownGrammarFixture.java index 1710290d..763d7ee1 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownGrammarFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownGrammarFixture.java @@ -2,11 +2,16 @@ import java.util.HashMap; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.concordion.internal.parser.flexmark.FlexmarkMarkdownTranslator; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownGrammarFixture { FlexmarkMarkdownTranslator markdownParser; diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownRunCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownRunCommandFixture.java index d8bc27f3..800aae2a 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownRunCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownRunCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownRunCommandFixture extends MarkdownGrammarFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownSetCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownSetCommandFixture.java index 3894c08b..ec1e41a9 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownSetCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownSetCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownSetCommandFixture extends MarkdownGrammarFixture { } diff --git a/src/test/java/spec/concordion/specificationType/markdown/MarkdownVerifyRowsCommandFixture.java b/src/test/java/spec/concordion/specificationType/markdown/MarkdownVerifyRowsCommandFixture.java index e4597fe6..96efa4ed 100644 --- a/src/test/java/spec/concordion/specificationType/markdown/MarkdownVerifyRowsCommandFixture.java +++ b/src/test/java/spec/concordion/specificationType/markdown/MarkdownVerifyRowsCommandFixture.java @@ -1,8 +1,13 @@ package spec.concordion.specificationType.markdown; +import org.concordion.api.ConcordionFixture; import org.concordion.integration.junit4.ConcordionRunner; import org.junit.runner.RunWith; +#if JUNIT_VINTAGE @RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif public class MarkdownVerifyRowsCommandFixture extends MarkdownGrammarFixture { } From 5a244909502734004b11600261926e65380dfdf5 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 10 Jun 2023 20:41:17 +1200 Subject: [PATCH 29/45] Updated specification tests to use JUnit5 Jupiter by default --- .../verifyRows/strategies/BaseMatchStrategyTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java index 587a3a32..e11b1da2 100644 --- a/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java +++ b/src/test/java/spec/concordion/common/command/verifyRows/strategies/BaseMatchStrategyTest.java @@ -16,11 +16,7 @@ import test.concordion.TestRig; -#if JUNIT_VINTAGE -@RunWith(ConcordionRunner.class) -#else -@ConcordionFixture -#endif +@Extensions(EmbedExtension.class) @ConcordionResources("toggle_html.*") public class BaseMatchStrategyTest { From f1d038cdffcd96e2c0b55b388d974c8ed09a87e3 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 11 Jun 2023 21:58:23 +1200 Subject: [PATCH 30/45] Cache SpecificationDescriptors to avoid issues when running test suites --- .../platform/engine/ConcordionTestEngine.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java index 92bbe8ce..a686c49f 100644 --- a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java @@ -2,6 +2,8 @@ import java.io.IOException; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; import org.concordion.api.ConcordionFixture; @@ -44,6 +46,13 @@ public class ConcordionTestEngine extends HierarchicalTestEngine, SpecificationDescriptor> specificationDescriptorCache = new ConcurrentHashMap, SpecificationDescriptor>(); + @Override public String getId() { return ENGINE_ID; @@ -103,14 +112,18 @@ protected void appendFixtureBasedTestDescriptor( } } - protected SpecificationDescriptor appendSpecificationTestDescriptor( + protected synchronized SpecificationDescriptor appendSpecificationTestDescriptor( Class fixtureClass, SpecificationLocator specificationLocator, TestDescriptor parentTestDescriptor) { - SpecificationDescriptor newTestDescriptor = new SpecificationDescriptor( - parentTestDescriptor.getUniqueId(), - fixtureClass, specificationLocator); + SpecificationDescriptor specificationDescriptor = specificationDescriptorCache.get(fixtureClass); + if (specificationDescriptor == null) { + specificationDescriptor = new SpecificationDescriptor( + parentTestDescriptor.getUniqueId(), + fixtureClass, specificationLocator); + specificationDescriptorCache.put(fixtureClass, specificationDescriptor); + } // System.out.println("Added " + newTestDescriptor.getClass().getSimpleName() + " for " + newTestDescriptor.getFixtureClass().getSimpleName()); - parentTestDescriptor.addChild(newTestDescriptor); - return newTestDescriptor; + parentTestDescriptor.addChild(specificationDescriptor); + return specificationDescriptor; } protected ExampleDescriptor appendExampleTestDescriptor( From 9840c5df9c63d30ed67e6a58a33ce1f470eda501 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 11 Jun 2023 22:15:58 +1200 Subject: [PATCH 31/45] Fix caching issue with ConcordionTestEnginteTests --- .../junit/platform/engine/ConcordionTestEngine.java | 4 ++++ .../junit/platform/engine/ConcordionTestEngineTests.java | 1 + 2 files changed, 5 insertions(+) diff --git a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java index a686c49f..ce637bf7 100644 --- a/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java +++ b/src/main/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngine.java @@ -53,6 +53,10 @@ public class ConcordionTestEngine extends HierarchicalTestEngine, SpecificationDescriptor> specificationDescriptorCache = new ConcurrentHashMap, SpecificationDescriptor>(); + public static void _clearCacheForTestingOnly() { + specificationDescriptorCache.clear(); + } + @Override public String getId() { return ENGINE_ID; diff --git a/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java b/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java index bf0fe903..981fddc4 100644 --- a/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java +++ b/src/test/java/org/concordion/integration/junit/platform/engine/ConcordionTestEngineTests.java @@ -42,6 +42,7 @@ void engineRunsConcordion() throws Exception { runResultsCache.removeAllFromCache(partialMatchesFixtureType); FixtureType spikeFixtureType = new FixtureType(SpikeTest.class); runResultsCache.removeAllFromCache(spikeFixtureType); + ConcordionTestEngine._clearCacheForTestingOnly(); try { EngineExecutionResults executionResults = From 9ace145894aaecce4aa9e7d16ea4f6cd5d964b07 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 1 Jul 2023 20:48:51 +1200 Subject: [PATCH 32/45] Added JUnit 5 Jupiter and updated JUnit 4 specifications --- .../integration/junit5/Junit5Test.java | 11 ++++ .../concordion/integration/Integration.html | 6 +- .../concordion/integration/junit4/Junit4.md | 11 ++-- .../concordion/integration/junit5/Junit5.md | 55 +++++++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 src/test/java/spec/concordion/integration/junit5/Junit5Test.java create mode 100644 src/test/resources/spec/concordion/integration/junit5/Junit5.md diff --git a/src/test/java/spec/concordion/integration/junit5/Junit5Test.java b/src/test/java/spec/concordion/integration/junit5/Junit5Test.java new file mode 100644 index 00000000..344d8c59 --- /dev/null +++ b/src/test/java/spec/concordion/integration/junit5/Junit5Test.java @@ -0,0 +1,11 @@ +package spec.concordion.integration.junit5; + +import org.concordion.api.ConcordionFixture; + +#if JUNIT_VINTAGE +#else +@ConcordionFixture +#endif +public class Junit5Test { +} + diff --git a/src/test/resources/spec/concordion/integration/Integration.html b/src/test/resources/spec/concordion/integration/Integration.html index 529eb907..2cffd21f 100644 --- a/src/test/resources/spec/concordion/integration/Integration.html +++ b/src/test/resources/spec/concordion/integration/Integration.html @@ -1,4 +1,4 @@ - + Integration @@ -13,7 +13,9 @@

Running an Active Specification

- + \ No newline at end of file diff --git a/src/test/resources/spec/concordion/integration/junit4/Junit4.md b/src/test/resources/spec/concordion/integration/junit4/Junit4.md index 55ddedcb..661cc427 100644 --- a/src/test/resources/spec/concordion/integration/junit4/Junit4.md +++ b/src/test/resources/spec/concordion/integration/junit4/Junit4.md @@ -1,6 +1,6 @@ -# JUnit 4 +# JUnit 4 (or JUnit 5 Vintage) -An active specification with JUnit 4 consists of two parts: a specification (eg. in HTML, Markdown or Excel) +An active specification with JUnit 4 or JUnit 5 Vintage consists of two parts: a specification (eg. in HTML, Markdown or Excel) and a Java fixture annotated with `@RunWith(ConcordionRunner.class)`. ### Fixture naming @@ -42,8 +42,11 @@ and a Concordion fixture named `FooFixture.java` in the same package will ignore ### JUnit Annotations -The following JUnit annotations can be used. However, the [Concordion annotations](../../annotation/Annotation.md "c:run") are - preferred, and support additional features. +When using JUnit 4, or JUnit 5 Vintage, the following annotations can be used. These annotations will not work +with JUnit 5 Jupiter. + +The [Concordion annotations](../../annotation/Annotation.md "c:run") are preferred over these JUnit annotations, since +they support additional features and will work with all supported versions of JUnit. #### [Supported JUnit annotations](- "annotations") The JUnit 4 integration supports the [Before](- "c:assertTrue=wasBeforeCalled()"), diff --git a/src/test/resources/spec/concordion/integration/junit5/Junit5.md b/src/test/resources/spec/concordion/integration/junit5/Junit5.md new file mode 100644 index 00000000..a3ed21c3 --- /dev/null +++ b/src/test/resources/spec/concordion/integration/junit5/Junit5.md @@ -0,0 +1,55 @@ +# JUnit 5 Jupiter + +An active specification with JUnit 5 Jupiter consists of two parts: a specification (eg. in HTML, Markdown or Excel) +and a Java fixture annotated with `@ConcordionFixture`. + +The only other difference from JUnit 4 (and JUnit 5 Vintage) is that the JUnit annotations are no longer supported +with JUnit 5 Jupiter. + +### Fixture naming + +The fixture class must be in the same package as the specification. +The fixture class must have the same name as the specification (excluding the file extension), and can optionally have +`Test` or `Fixture` appended. + +When you run the fixture class using JUnit, it will automatically locate the specification file. +It does this by looking in the same package for the specification file named the same as the test, +but without the `Test` or `Fixture` suffixes. + +#### Example + +If your test is called `com.example.BreadcrumbTest` then the corresponding +specification file must be in the same package (`com.example`) and called +`Breadcrumb.html`. (Other specification types will use different suffices, eg. `.md` or `.markdown` for Markdown specifications.) + +### Reverse lookup + +When using the [run command](../../common/command/run/Run.html "c:run"), the fixture class is located from the referenced specification by +looking in the same package as the specification for a JUnit test named the same as the specification with optionally `Test` or +`Fixture` appended. + +#### Example + +If your specification contains a run command referencing the specification `Breadcrumb.md` in the `com.example` package, +Concordion will look in the following order for a corresponding fixture: + +1. `com.example.Breadcrumb` +2. `com.example.BreadcrumbTest` +3. `com.example.BreadcrumbFixture` + +### JUnit Annotations + +Are not supported with JUnit 5 Jupiter. + +Instead the [Concordion annotations](../../annotation/Annotation.md "c:run") are available and will work with all +supported versions of JUnit. + +### Fixture Example + + import org.concordion.api.ConcordionFixture; + + @ConcordionFixture + public class JUnit5Test { + + // ... + } From 8bec7114655cf271b1dd15001fb6e96b137f87ca Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 1 Jul 2023 20:49:42 +1200 Subject: [PATCH 33/45] Updated location of JUnit 5 spec to build/reports folder --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 52ea2575..b1e56fea 100644 --- a/build.gradle +++ b/build.gradle @@ -123,6 +123,7 @@ task testJar(type: Jar, dependsOn: testClasses) { // This relies on JUnit Vintage code being within an `#if JUNIT_VINTAGE ... #endif` block // which the Manifold preprocessor will parse task testVintage(type: Test) { + systemProperties['concordion.output.dir'] = "${reporting.baseDir}" } gradle.taskGraph.whenReady { taskGraph -> From 536d94042eeb1e04a6b4856fa53ca05dfff0ebd8 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 2 Jul 2023 07:14:19 +1200 Subject: [PATCH 34/45] Added Since 4.0.0 to specification --- src/test/resources/spec/concordion/integration/junit5/Junit5.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/resources/spec/concordion/integration/junit5/Junit5.md b/src/test/resources/spec/concordion/integration/junit5/Junit5.md index a3ed21c3..0622ae4d 100644 --- a/src/test/resources/spec/concordion/integration/junit5/Junit5.md +++ b/src/test/resources/spec/concordion/integration/junit5/Junit5.md @@ -1,4 +1,5 @@ # JUnit 5 Jupiter +_Since_: Concordion 4.0.0 An active specification with JUnit 5 Jupiter consists of two parts: a specification (eg. in HTML, Markdown or Excel) and a Java fixture annotated with `@ConcordionFixture`. From ad2d1eff6f3ed86193e59e9900e1b3a088277a8c Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 2 Jul 2023 07:30:59 +1200 Subject: [PATCH 35/45] Add details of Manifold preprocessor to README --- README.md | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 238154ef..672eeff8 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ Users should see the [Concordion](http://www.concordion.org) web site for details of how to download and use Concordion. -This README covers information for people wanting to work with the Concordion Java source code. Concordion is also available for other languages, but not with the full feature set. See [Concordion.NET](https://github.com/concordion/concordion.net), [pyconcordion](https://pypi.org/project/pyconcordion2/) and [ruby-concordion](https://github.com/arielvalentin/ruby-concordion). +This README covers information for people wanting to work with the Concordion Java source code. +Unmaintained versions of Concordion are also available for other languages, but not with the full feature set. +See [Concordion.NET](https://github.com/concordion/concordion.net), [pyconcordion](https://pypi.org/project/pyconcordion2/) and [ruby-concordion](https://github.com/arielvalentin/ruby-concordion). # Target Java version Concordion currently targets Java 8 and above. @@ -20,11 +22,34 @@ Note: If the current directory is not on your path, you will need to use `./grad ## Compiling and Running the Tests -Run the following from the command line: +The `test` task runs both the Concordion specification tests and unit tests. +Since Concordion supports both JUnit Vintage and JUnit Jupiter, the tests can run with either version of JUnit. + +To run the tests with JUnit Jupiter, run the following from the command line: ```gradlew clean test``` - -This will download the required dependencies, clean the existing project, recompile all source code and run all the tests. Concordion output is written to the `./build/reports/spec` folder. + +To run the tests with JUnit Vintage, run the following from the command line: + +```gradlew clean testVintage``` + +This will download the required dependencies, clean the existing project, recompile all source code and run all the tests. +The Concordion specification output is written to the `./build/reports/spec` folder. + +### Pre-processor +To switch between the JUnit Jupiter and Vintage tests, Concordion uses the [Manifold](http://manifold.systems/) preprocessor. + +For example: + +``` +#if JUNIT_VINTAGE +@RunWith(ConcordionRunner.class) +#else +@ConcordionFixture +#endif +``` + +The `JUNIT_VINTAGE` compiler argument is set by the `testVintage` Gradle task. ## Creating a jar file @@ -71,6 +96,8 @@ Dependent on the version of your IDE, you may need to install a Gradle plugin to On importing the project to your IDE, the required dependencies will be downloaded. +For IntelliJ IDEA, installing the [Manifold plugin](https://plugins.jetbrains.com/plugin/10057-manifold) will enable +IntelliJ to recognise the Manifold preprocessor syntax. # Wiki See the [wiki](https://github.com/concordion/concordion/wiki) for our version numbering approach and details of making a new release. From 1204b9f3ad71c063786674d09f54385f9bdeb64f Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 2 Jul 2023 22:05:40 +1200 Subject: [PATCH 36/45] Update dependencies --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b1e56fea..4a883bbe 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ repositories { } ext { - junitJupiterVersion = '5.8.2' + junitJupiterVersion = '5.9.3' flexmarkVersion = '0.62.2' manifoldVersion = '2023.1.10' githubUrl = "https://github.com/concordion/${project.name}" @@ -63,7 +63,7 @@ dependencies { implementation 'ognl:ognl:3.1.29', "com.vladsch.flexmark:flexmark-profile-pegdown:$flexmarkVersion" - api ('xom:xom:1.3.7') { + api ('xom:xom:1.3.9') { exclude group: 'xalan', module: 'xalan' exclude group: 'xerces', module: 'xercesImpl' exclude group: 'xml-apis', module: 'xml-apis' @@ -73,7 +73,7 @@ dependencies { exclude group: 'org.concordion', module: 'concordion' } - testImplementation 'com.github.stefanbirkner:system-rules:1.16.0', + testImplementation 'com.github.stefanbirkner:system-rules:1.19.0', "com.vladsch.flexmark:flexmark-ext-abbreviation:$flexmarkVersion" implementation ("systems.manifold:manifold-preprocessor:$manifoldVersion") { From e3bd2f42161b12aeb2a5d83b24c0156bde0059f8 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 2 Jul 2023 22:13:57 +1200 Subject: [PATCH 37/45] Set version to 4.0.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 346de312..f629a190 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ group=org.concordion -version=4.0.0-SNAPSHOT \ No newline at end of file +version=4.0.0 \ No newline at end of file From 960197252d08cd89736fb0f2d528f71c5f23c9ea Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Fri, 14 Jul 2023 22:50:42 +1200 Subject: [PATCH 38/45] Provide for concordion commands in table body without table being executed as a whole --- .../flexmark/ConcordionCommandNodePostProcessor.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/concordion/internal/parser/flexmark/ConcordionCommandNodePostProcessor.java b/src/main/java/org/concordion/internal/parser/flexmark/ConcordionCommandNodePostProcessor.java index 991a52b9..9c8a1dc4 100644 --- a/src/main/java/org/concordion/internal/parser/flexmark/ConcordionCommandNodePostProcessor.java +++ b/src/main/java/org/concordion/internal/parser/flexmark/ConcordionCommandNodePostProcessor.java @@ -4,6 +4,7 @@ import com.vladsch.flexmark.ast.util.ReferenceRepository; import com.vladsch.flexmark.ext.tables.TableBlock; import com.vladsch.flexmark.ext.tables.TableCell; +import com.vladsch.flexmark.ext.tables.TableHead; import com.vladsch.flexmark.parser.Parser; import com.vladsch.flexmark.parser.block.NodePostProcessor; import com.vladsch.flexmark.parser.block.NodePostProcessorFactory; @@ -63,8 +64,10 @@ private void processNode(NodeTracker state, Node node, BasedSequence text, Based if (node.getParent() instanceof TableCell) { if (insideConcordionTableBlock(node)) { changeToConcordionTableCell(state, node, commandNode); - } else { + } else if (insideTableHeader(node)) { changeToConcordionTableBlock(state, node, commandNode); + } else { + replaceNode(state, node, commandNode); } } else { replaceNode(state, node, commandNode); @@ -99,6 +102,13 @@ private boolean insideConcordionTableBlock(Node node) { return node instanceof ConcordionTableBlock; } + private boolean insideTableHeader(Node node) { + while (node != null && !(node instanceof TableHead)) { + node = node.getParent(); + } + return node instanceof TableHead; + } + private void changeToConcordionTableBlock(NodeTracker state, Node linkNode, ConcordionCommandNode commandNode) { Node tableBlock = linkNode; while (!(tableBlock instanceof TableBlock)) { From a23d7c37dcd07ed9210da5ce1f065992823cb804 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 16 Jul 2023 20:44:03 +1200 Subject: [PATCH 39/45] Added test for issue #355 --- .../markdown/MarkdownExecuteCommand.md | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/test/resources/spec/concordion/specificationType/markdown/MarkdownExecuteCommand.md b/src/test/resources/spec/concordion/specificationType/markdown/MarkdownExecuteCommand.md index 5436c381..f752bf5b 100644 --- a/src/test/resources/spec/concordion/specificationType/markdown/MarkdownExecuteCommand.md +++ b/src/test/resources/spec/concordion/specificationType/markdown/MarkdownExecuteCommand.md @@ -191,4 +191,38 @@ For example: - \ No newline at end of file + + +### Execute individual rows of the table +If you don't want each row to be treated identically, you can annotate specific cells within the table. + +
+

Example

+ + + + + + + + + + + + + + +
MarkdownResultant HTML
+
      
+| Number      |
+| ----------- |
+| [1](- "#x") | 
+| [3](- "#y") |
+
+
+ +
Number
1
3
]]> + + + +
From 7e6a851eecb35932c5c0760dc745013f722f3eef Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 16 Jul 2023 20:58:42 +1200 Subject: [PATCH 40/45] Update gradle to 8.2 --- gradle/wrapper/gradle-wrapper.jar | Bin 59821 -> 60756 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 6 ++++++ gradlew.bat | 14 ++++++++------ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d4fb3f96a785543079b8df6723c946b..249e5832f090a2944b7473328c07c9755baa3196 100644 GIT binary patch delta 10197 zcmaKS1ymhDwk=#NxVyW%y9U<)A-Dv)xI0|j{UX8L-JRg>5ZnnKAh;%chM6~S-g^K4 z>eZ{yK4;gd>gwvXs=Id8Jk-J}R4pT911;+{Jp9@aiz6!p1Oz9z&_kGLA%J5%3Ih@0 zQ|U}%$)3u|G`jIfPzMVfcWs?jV2BO^*3+q2><~>3j+Z`^Z%=;19VWg0XndJ zwJ~;f4$;t6pBKaWn}UNO-wLCFHBd^1)^v%$P)fJk1PbK5<;Z1K&>k~MUod6d%@Bq9 z>(44uiaK&sdhwTTxFJvC$JDnl;f}*Q-^01T508(8{+!WyquuyB7R!d!J)8Ni0p!cV6$CHsLLy6}7C zYv_$eD;)@L)tLj0GkGpBoa727hs%wH$>EhfuFy{_8Q8@1HI%ZAjlpX$ob{=%g6`Ox zLzM!d^zy`VV1dT9U9(^}YvlTO9Bf8v^wMK37`4wFNFzW?HWDY(U(k6@tp(crHD)X5>8S-# zW1qgdaZa*Sh6i%60e1+hty}34dD%vKgb?QmQiZ=-j+isA4={V_*R$oGN#j|#ia@n6 zuZx4e2Xx?^lUwYFn2&Tmbx0qA3Z8;y+zKoeQu;~k~FZGy!FU_TFxYd!Ck;5QvMx9gj5fI2@BLNp~Ps@ zf@k<&Q2GS5Ia9?_D?v~$I%_CLA4x~eiKIZ>9w^c#r|vB?wXxZ(vXd*vH(Fd%Me8p( z=_0)k=iRh%8i`FYRF>E97uOFTBfajv{IOz(7CU zv0Gd84+o&ciHlVtY)wn6yhZTQQO*4Mvc#dxa>h}82mEKKy7arOqU$enb9sgh#E=Lq zU;_RVm{)30{bw+|056%jMVcZRGEBSJ+JZ@jH#~DvaDQm92^TyUq=bY*+AkEakpK>8 zB{)CkK48&nE5AzTqT;WysOG|!y}5fshxR8Ek(^H6i>|Fd&wu?c&Q@N9ZrJ=?ABHI! z`*z8D`w=~AJ!P-9M=T}f`;76$qZRllB&8#9WgbuO$P7lVqdX1=g*t=7z6!0AQ^ux_ z9rcfUv^t}o_l-ZE+TqvqFsA*~W<^78!k;~!i8(eS+(+@u8FxK+Q7;mHZ<1}|4m<}vh@p`t%|@eM_J(P% zI>M7C)Ir{l|J;$G_EGGEhbP4?6{sYzMqBv+x95N&YWFH6UcE@b}B?q)G*4<4mR@sy1#vPnLMK51tb#ED(8TA1nE zYfhK7bo1!R5WJF$5Y?zG21)6+_(_5oSX9sGIW;(O&S?Rh(nydNQYzKjjJ54aDJ-1F zrJ=np8LsN?%?Rt7f~3aAX!2E{`fh_pb?2(;HOB3W+I*~A>W%iY+v45+^e$cE10fA} zXPvw9=Bd+(;+!rl)pkYj0HGB}+3Z!Mr;zr%gz~c-hFMv8b2VRE2R$8V=_XE zq$3=|Yg05(fmwrJ)QK2ptB4no`Y8Dg_vK2QDc6-6sXRQ5k78-+cPi-fH}vpgs|Ive zE=m*XNVs?EWgiNI!5AcD*3QMW)R`EqT!f0e1%hERO&?AT7HWnSf5@#AR{OGuXG3Zb zCnVWg7h|61lGV3k+>L<#d>)InG>ETn1DbOHCfztqzQ_fBiaUt@q6VMy={Fe-w#~2- z0?*f|z$zgjI9>+JVICObBaK=pU}AEOd@q(8d?j7zQFD@=6t`|KmolTr2MfBI$;EGh zD%W0cA_d#V6Lb$us5yIG(|d>r-QleC4;%hEu5W9hyY zY#+ESY&v`8(&mC~?*|e5WEhC!YU2>m_}`K+q9)a(d$bsS<=YkyZGp}YA%TXw>@abA zS_poVPoN+?<6?DAuCNt&5SHV(hp56PJ})swwVFZFXM->F zc|0c8<$H_OV%DR|y7e+s$12@Ac8SUClPg8_O9sTUjpv%6Jsn5vsZCg>wL+db4c+{+ zsg<#wOuV4jeOq`veckdi-1`dz;gvL)bZeH|D*x=8UwRU5&8W1@l>3$)8WzET0%;1J zM3(X<7tKK&9~kWRI{&FmwY5Gg!b5f4kI_vSm)H1#>l6M+OiReDXC{kPy!`%Ecq-+3yZTk=<` zm)pE6xum5q0Qkd#iny0Q-S}@I0;mDhxf>sX)Oiv)FdsAMnpx%oe8OQ`m%Xeozdzx!C1rQR>m1c_}+J4x)K}k{G zo68;oGG&Ox7w^-m7{g4a7NJu-B|~M;oIH~~#`RyUNm##feZH;E?pf}nshmoiIY52n z%pc%lnU4Q#C=RUz)RU6}E_j4#)jh<&a%JyJj$Fufc#&COaxFHtl}zJUGNLBu3~_@1 zn9F^JO9);Duxo&i@>X(kbYga1i>6p1fca8FzQ0>((Lb-aPUbC*d~a03V$y;*RBY!R ziEJ2IF^FjrvO}0Uy{cMn%u<+P5U!UO>pm9#ZYL5i6|xSC+np7IH$GfXs&uI;y4as@ z&AzJh>(S2?3PKKgab3Z(`xbx(C#46XIvVcW8eG_DjT~}Yz_8PWZ`uf6^Xr=vkvL_` zqmvfgJL+Zc`;iq~iP?%@G7}~fal-zqxa0yNyHBJJ5M)9bI>7S_cg?Ya&p(I)C5Ef4 zZ>YAF6x|U=?ec?g*|f2g5Tw3PgxaM_bi_5Az9MO$;_Byw(2d}2%-|bg4ShdQ;)Z|M z4K|tFv)qx*kKGKoyh!DQY<{n&UmAChq@DJrQP>EY7g1JF(ih*D8wCVWyQ z5Jj^|-NVFSh5T0vd1>hUvPV6?=`90^_)t(L9)XOW7jeP45NyA2lzOn&QAPTl&d#6P zSv%36uaN(9i9WlpcH#}rmiP#=L0q(dfhdxvFVaOwM;pY;KvNQ9wMyUKs6{d}29DZQ z{H3&Sosr6)9Z+C>Q5)iHSW~gGoWGgK-0;k~&dyr-bA3O|3PCNzgC?UKS_B=^i8Ri^ zd_*_qI4B07Cayq|p4{`U_E_P=K`N_~{F|+-+`sCgcNxs`%X!$=(?l2aAW}0M=~COb zf19oe^iuAUuDEf)4tgv<=WRPpK@IjToNNC*#&Ykw!)aqWU4h#|U@(cG_=Qx+&xt~a zvCz~Ds3F71dsjNLkfM%TqdVNu=RNMOzh7?b+%hICbFlOAPphrYy>7D-e7{%o_kPFn z;T!?ilE-LcKM0P(GKMseEeW57Vs`=FF}(y@^pQl;rL3fHs8icmA+!6YJt&8 ztSF?%Un35qkv>drkks&BNTJv~xK?vD;aBkp7eIkDYqn+G0%;sT4FcwAoO+vke{8CO z0d76sgg$CannW5T#q`z~L4id)9BCKRU0A!Z-{HpXr)QJrd9@iJB+l32Ql)Z}*v(St zE)Vp=BB=DDB4Pr}B(UHNe31<@!6d{U?XDoxJ@S)9QM)2L%SA0x^~^fb=bdsBy!uh& zU?M_^kvnt%FZzm+>~bEH{2o?v&Iogs`1t-b+Ml`J!ZPS(46YQJKxWE81O$HE5w;** z|8zM%bp`M7J8)4;%DqH`wVTmM0V@D}xd%tRE3_6>ioMJxyi5Hkb>85muF81&EY!73ei zA3e<#ug||EZJ=1GLXNJ)A z791&ge#lF;GVX6IU?iw0jX^1bYaU?+x{zPlpyX6zijyn*nEdZ$fxxkl!a-~*P3bkf zPd*pzu~3GBYkR_>ET`5UM^>>zTV>5m>)f=az{d0sg6a8VzUtXy$ZS?h#Gk-CA?7)c zI%Vu9DN6XSDQn6;?n9`>l$q&>s?K)R8*OsmI+$L_m z_~E`}w694Z*`Xk3Ne=497Si~=RWRqCM?6=88smrxle#s*W znwhTRsMRmg?37GLJ-)%nDZA7r$YG849j8mJWir1bWBy& zZPneYojSbooC8U@tkO`bWx4%E5*;p#Q^1^S3lsfy7(6A{jL0`A__0vm?>xC%1y8_m z57FfWr^@YG2I1K7MGYuYd>JC}@sT2n^rkrY3w%~$J$Y~HSoOHn?zpR$ zjLj_bq@Yj8kd~DXHh30KVbz@K)0S;hPKm+S&-o%IG+@x@MEcrxW2KFh;z^4dJDZix zGRGe&lQD$p)0JVF4NRgGYuh0bYLy)BCy~sbS3^b3 zHixT<%-Vwbht|25T{3^Hk;qZ^3s!OOgljHs+EIf~C%=_>R5%vQI4mQR9qOXThMXlU zS|oSH>0PjnCakb*js2{ObN`}%HYsT6=%(xA| znpUtG_TJ08kHgm5l@G|t?4E3tG2fq?wNtIp*Vqrb{9@bo^~Rx7+J&OnayrX`LDcF~ zd@0m0ZJ#Z@=T>4kTa5e2FjI&5c(F7S{gnRPoGpu9eIqrtSvnT_tk$8T)r%YwZw!gK zj*k@cG)V&@t+mtDi37#>LhVGTfRA^p%x0d#_P|Mktz3*KOoLIqFm`~KGoDDD4OOxe z?}ag_c08u%vu=5Vx=~uoS8Q;}+R2~?Uh|m-+`-2kDo$d6T!nD*hc#dB(*R{LXV=zo z`PJP0V=O!@3l-bw+d`X6(=@fq=4O#ETa8M^fOvO4qja9o3e8ANc9$sI=A4$zUut~w z4+JryRkI{9qWxU1CCMM$@Aj=6)P+z?vqa=UCv_4XyVNoBD{Xb~Oi4cjjhm8fRD!*U z2)zaS;AI78^Wq+5mDInKiMz|z#K`2emQfNH*U;{9^{NqSMVoq?RSo43<8YpJM^+W$ zxy!A5>5Zl16Vi#?nAYywu3w_=KWnd3*QetocWt`3pK67>)ZVwnT3h zbPdD&MZkD?q=-N`MpCCwpM74L+Tr1aa)zJ)8G;(Pg51@U&5W>aNu9rA`bh{vgfE={ zdJ>aKc|2Ayw_bop+dK?Y5$q--WM*+$9&3Q9BBiwU8L<-`T6E?ZC`mT0b}%HR*LPK} z!MCd_Azd{36?Y_>yN{U1w5yrN8q`z(Vh^RnEF+;4b|2+~lfAvPT!`*{MPiDioiix8 zY*GdCwJ{S(5(HId*I%8XF=pHFz<9tAe;!D5$Z(iN#jzSql4sqX5!7Y?q4_%$lH zz8ehZuyl0K=E&gYhlfFWabnSiGty$>md|PpU1VfaC5~kskDnZX&Yu}?-h;OSav=8u z=e3Yq=mi$4A|sB-J00;1d{Sd1+!v0NtU((Nz2;PFFlC}V{@p&4wGcVhU&nI($RAS! zwXn7)?8~1J3*4+VccRSg5JS<(bBhBM&{ELMD4C_NTpvzboH!{Zr*%HP;{UqxI#g&7 zOAqPSW5Qus$8-xtTvD%h{Tw<2!XR(lU54LZG{)Cah*LZbpJkA=PMawg!O>X@&%+5XiyeIf91n2E*hl$k-Y(3iW*E}Mz-h~H~7S9I1I zR#-j`|Hk?$MqFhE4C@=n!hN*o5+M%NxRqP+aLxDdt=wS6rAu6ECK*;AB%Nyg0uyAv zO^DnbVZZo*|Ef{nsYN>cjZC$OHzR_*g%T#oF zCky9HJS;NCi=7(07tQXq?V8I&OA&kPlJ_dfSRdL2bRUt;tA3yKZRMHMXH&#W@$l%-{vQd7y@~i*^qnj^`Z{)V$6@l&!qP_y zg2oOd!Wit#)2A~w-eqw3*Mbe)U?N|q6sXw~E~&$!!@QYX4b@%;3=>)@Z#K^`8~Aki z+LYKJu~Y$;F5%_0aF9$MsbGS9Bz2~VUG@i@3Fi2q(hG^+Ia44LrfSfqtg$4{%qBDM z_9-O#3V+2~W$dW0G)R7l_R_vw(KSkC--u&%Rs^Io&*?R=`)6BN64>6>)`TxyT_(Rd zUn+aIl1mPa#Jse9B3`!T=|e!pIp$(8ZOe0ao?nS7o?oKlj zypC-fMj1DHIDrh1unUI1vp=-Fln;I9e7Jvs3wj*^_1&W|X} zZSL|S|Bb@CV*YC_-T&2!Ht3b6?)d`tHOP?rA;;t#zaXa0Sc;vGnV0BLIf8f-r{QHh z*Zp`4_ItlOR7{u(K+!p_oLDmaAkNag*l4#29F2b_A*0oz0T|#-&f*;c#<`^)(W@gm z#k9k=t%u8<+C1fNUA{Fh7~wgPrEZZ#(6aBI%6bR4RO(e1(ZocjoDek4#MTgZD>1NG zy9~yoZfWYfwe&S-(zk4o6q6o?2*~DOrJ(%5wSnEJMVOKCzHd z=Yhm+HLzoDl{P*Ybro7@sk1!Ez3`hE+&qr7Rw^2glw^M(b(NS2!F|Q!mi|l~lF94o z!QiV)Q{Z>GO5;l1y!$O)=)got;^)%@v#B!ZEVQy1(BJApHr5%Zh&W|gweD+%Ky%CO ztr45vR*y(@*Dg_Qw5v~PJtm^@Lyh*zRuT6~(K+^HWEF{;R#L$vL2!_ndBxCtUvZ(_ zauI7Qq}ERUWjr&XW9SwMbU>*@p)(cuWXCxRK&?ZoOy>2VESII53iPDP64S1pl{NsC zD;@EGPxs&}$W1;P6BB9THF%xfoLX|4?S;cu@$)9OdFst-!A7T{(LXtdNQSx!*GUSIS_lyI`da8>!y_tpJb3Zuf0O*;2y?HCfH z5QT6@nL|%l3&u4;F!~XG9E%1YwF*Fgs5V&uFsx52*iag(?6O|gYCBY3R{qhxT-Etb zq(E%V=MgQnuDGEKOGsmBj9T0-nmI%zys8NSO>gfJT4bP>tI>|ol@ zDt(&SUKrg%cz>AmqtJKEMUM;f47FEOFc%Bbmh~|*#E zDd!Tl(wa)ZZIFwe^*)4>{T+zuRykc3^-=P1aI%0Mh}*x7%SP6wD{_? zisraq`Las#y-6{`y@CU3Ta$tOl|@>4qXcB;1bb)oH9kD6 zKym@d$ zv&PZSSAV1Gwwzqrc?^_1+-ZGY+3_7~a(L+`-WdcJMo>EWZN3%z4y6JyF4NR^urk`c z?osO|J#V}k_6*9*n2?j+`F{B<%?9cdTQyVNm8D}H~T}?HOCXt%r7#2hz97Gx#X%62hyaLbU z_ZepP0<`<;eABrHrJAc!_m?kmu#7j}{empH@iUIEk^jk}^EFwO)vd7NZB=&uk6JG^ zC>xad8X$h|eCAOX&MaX<$tA1~r|hW?-0{t4PkVygTc`yh39c;&efwY(-#;$W)+4Xb z$XFsdG&;@^X`aynAMxsq)J#KZXX!sI@g~YiJdHI~r z$4mj_?S29sIa4c$z)19JmJ;Uj?>Kq=0XuH#k#};I&-6zZ_&>)j>UR0XetRO!-sjF< zd_6b1A2vfi++?>cf}s{@#BvTD|a%{9si7G}T+8ZnwuA z1k8c%lgE<-7f~H`cqgF;qZ|$>R-xNPA$25N1WI3#n%gj}4Ix}vj|e=x)B^roGQpB) zO+^#nO2 zjzJ9kHI6nI5ni&V_#5> z!?<7Qd9{|xwIf4b0bRc;zb}V4>snRg6*wl$Xz`hRDN8laL5tg&+@Dv>U^IjGQ}*=XBnXWrwTy;2nX?<1rkvOs#u(#qJ=A zBy>W`N!?%@Ay=upXFI}%LS9bjw?$h)7Dry0%d}=v0YcCSXf9nnp0tBKT1eqZ-4LU` zyiXglKRX)gtT0VbX1}w0f2ce8{$WH?BQm@$`ua%YP8G@<$n13D#*(Yd5-bHfI8!on zf5q4CPdgJLl;BqIo#>CIkX)G;rh|bzGuz1N%rr+5seP${mEg$;uQ3jC$;TsR&{IX< z;}7j3LnV+xNn^$F1;QarDf6rNYj7He+VsjJk6R@0MAkcwrsq4?(~`GKy|mgkfkd1msc2>%B!HpZ~HOzj}kl|ZF(IqB=D6ZTVcKe=I7)LlAI=!XU?J*i#9VXeKeaG zwx_l@Z(w`)5Cclw`6kQKlS<;_Knj)^Dh2pL`hQo!=GPOMR0iqEtx12ORLpN(KBOm5 zontAH5X5!9WHS_=tJfbACz@Dnkuw|^7t=l&x8yb2a~q|aqE_W&0M|tI7@ilGXqE)MONI8p67OiQGqKEQWw;LGga=ZM1;{pSw1jJK_y$vhY6 ztFrV7-xf>lbeKH1U)j3R=?w*>(Yh~NNEPVmeQ8n}0x01$-o z2Jyjn+sXhgOz>AzcZ zAbJZ@f}MBS0lLKR=IE{z;Fav%tcb+`Yi*!`HTDPqSCsFr>;yt^^&SI2mhKJ8f*%ji zz%JkZGvOn{JFn;)5jf^21AvO-9nRzsg0&CPz;OEn07`CfT@gK4abFBT$Mu?8fCcscmRkK+ zbAVJZ~#_a z{|(FFX}~8d3;DW8zuY9?r#Dt>!aD>} zlYw>D7y#eDy+PLZ&XKIY&Df0hsLDDi(Yrq8O==d30RchrUw8a=Eex>Dd?)3+k=}Q> z-b85lun-V$I}86Vg#l1S@1%=$2BQD5_waAZKQfJ${3{b2SZ#w1u+jMr{dJMvI|Og= zpQ9D={XK|ggbe04zTUd}iF{`GO1dV%zWK~?sM9OM(= zVK9&y4F^w1WFW{$qi|xQk0F`@HG8oLI5|5$j~ci9xTMT69v5KS-Yym--raU5kn2#C z<~5q^Bf0rTXVhctG2%&MG(cUGaz(gC(rcG~>qgO$W6>!#NOVQJ;pIYe-lLy(S=HgI zPh;lkL$l+FfMHItHnw_^bj8}CKM19t(C_2vSrhX2$K@-gFlH};#C?1;kk&U1L%4S~ zR^h%h+O1WE7DI$~dly?-_C7>(!E`~#REJ~Xa7lyrB$T!`&qYV5QreAa^aKr%toUJR zPWh)J3iD`(P6BI5k$oE$us#%!4$>`iH2p-88?WV0M$-K)JDibvA4 zpef%_*txN$Ei3=Lt(BBxZ&mhl|mUz-z*OD1=r9nfN zc5vOMFWpi>K=!$6f{eb?5Ru4M3o;t9xLpry|C%j~`@$f)OFB5+xo8XM8g&US@UU-sB|dAoc20y(F@=-2Ggp_`SWjEb#>IG^@j zuQK}e^>So#W2%|-)~K!+)wdU#6l>w5wnZt2pRL5Dz#~N`*UyC9tYechBTc2`@(OI# zNvcE*+zZZjU-H`QOITK^tZwOyLo)ZCLk>>Wm+flMsr5X{A<|m`Y281n?8H_2Fkz5}X?i%Rfm5s+n`J zDB&->=U+LtOIJ|jdYXjQWSQZFEs>Rm{`knop4Sq)(}O_@gk{14y51)iOcGQ5J=b#e z2Yx^6^*F^F7q_m-AGFFgx5uqyw6_4w?yKCJKDGGprWyekr;X(!4CnM5_5?KgN=3qCm03 z##6k%kIU5%g!cCL(+aK>`Wd;dZ4h$h_jb7n?nqx5&o9cUJfr%h#m4+Bh)>HodKcDcsXDXwzJ3jR(sSFqWV(OKHC*cV8;;&bH=ZI0YbW3PgIHwTjiWy z?2MXWO2u0RAEEq(zv9e%Rsz|0(OKB?_3*kkXwHxEuazIZ7=JhaNV*P~hv57q55LoebmJpfHXA@yuS{Esg+ z*C}0V-`x^=0nOa@SPUJek>td~tJ{U1T&m)~`FLp*4DF77S^{|0g%|JIqd-=5)p6a` zpJOsEkKT(FPS@t^80V!I-YJbLE@{5KmVXjEq{QbCnir%}3 zB)-J379=wrBNK6rbUL7Mh^tVmQYn-BJJP=n?P&m-7)P#OZjQoK0{5?}XqJScV6>QX zPR>G{xvU_P;q!;S9Y7*07=Z!=wxIUorMQP(m?te~6&Z0PXQ@I=EYhD*XomZ^z;`Os z4>Uh4)Cg2_##mUa>i1Dxi+R~g#!!i{?SMj%9rfaBPlWj_Yk)lCV--e^&3INB>I?lu z9YXCY5(9U`3o?w2Xa5ErMbl5+pDVpu8v+KJzI9{KFk1H?(1`_W>Cu903Hg81vEX32l{nP2vROa1Fi!Wou0+ZX7Rp`g;B$*Ni3MC-vZ`f zFTi7}c+D)!4hz6NH2e%%t_;tkA0nfkmhLtRW%){TpIqD_ev>}#mVc)<$-1GKO_oK8 zy$CF^aV#x7>F4-J;P@tqWKG0|D1+7h+{ZHU5OVjh>#aa8+V;6BQ)8L5k9t`>)>7zr zfIlv77^`Fvm<)_+^z@ac%D&hnlUAFt8!x=jdaUo{)M9Ar;Tz5Dcd_|~Hl6CaRnK3R zYn${wZe8_BZ0l0c%qbP}>($jsNDay>8+JG@F!uV4F;#zGsBP0f$f3HqEHDz_sCr^q z1;1}7KJ9&`AX2Qdav1(nNzz+GPdEk5K3;hGXe{Hq13{)c zZy%fFEEH#nlJoG{f*M^#8yXuW%!9svN8ry-Vi7AOFnN~r&D`%6d#lvMXBgZkX^vFj z;tkent^62jUr$Cc^@y31Lka6hS>F?1tE8JW$iXO*n9CQMk}D*At3U(-W1E~z>tG?> z5f`5R5LbrhRNR8kv&5d9SL7ke2a*Xr)Qp#75 z6?-p035n2<7hK;sb>t9GAwG4{9v~iEIG>}7B5zcCgZhu$M0-z8?eUO^E?g)md^XT_ z2^~-u$yak>LBy(=*GsTj6p<>b5PO&un@5hGCxpBQlOB3DpsItKZRC*oXq-r{u}Wb; z&ko>#fbnl2Z;o@KqS-d6DTeCG?m1 z&E>p}SEc*)SD&QjZbs!Csjx~0+$@ekuzV_wAalnQvX3a^n~3ui)|rDO+9HW|JPEeBGP4 z)?zcZ<8qv47`EWA*_X~H^vr(lP|f%=%cWFM;u)OFHruKT<~?>5Y8l?56>&;=WdZU# zZEK4-C8s-3zPMA^&y~e*9z)!ZJghr3N^pJa2A$??Xqx-BR*TytGYor&l8Q+^^r%Yq02xay^f#;;wO6K7G!v>wRd6531WnDI~h$PN( z+4#08uX?r&zVKsQ;?5eBX=FxsXaGyH4Gth4a&L|{8LnNCHFr1M{KjJ!BfBS_aiy-E zxtmNcXq3}WTwQ7Dq-9YS5o758sT(5b`Sg-NcH>M9OH1oW6&sZ@|GYk|cJI`vm zO<$~q!3_$&GfWetudRc*mp8)M)q7DEY-#@8w=ItkApfq3sa)*GRqofuL7)dafznKf zLuembr#8gm*lIqKH)KMxSDqbik*B(1bFt%3Vv|ypehXLCa&wc7#u!cJNlUfWs8iQ` z$66(F=1fkxwg745-8_eqV>nWGY3DjB9gE23$R5g&w|C{|xvT@7j*@aZNB199scGchI7pINb5iyqYn)O=yJJX)Ca3&Ca+{n<=1w|(|f0)h<9gs$pVSV<<9Og-V z8ki@nKwE)x)^wmHBMk?mpMT=g{S#^8W|>&rI#Ceh;9za}io0k@0JxiCqi-jHlxbt3 zjJA?RihhRvhk6%G5-D{ePh1jare*fQS<328P-DcVAxPTrw=n6k?C6EV75f}cnBRPT zMYDqqKu(ND&aOtc!QRV`vzJSVxx8i~WB#5Ml{b#eQqNnSi7l-bS-`ITW<^zyYQA(b zbj4SuRK>q9o`_v%+C=S?h>2e4!66Ij(P5{7Uz$3u6YJJC$W%EoBa{-(=tQ|y1vov%ZkXVOV z##_UVg4V^4ne#4~<-1DkJqkKqgT+E_=&4Ue&eQ-JC+gi?7G@d6= zximz{zE)WW{b@QCJ!7l&N5x=dXS?$5RBU-VvN4Uec-GHK&jPa&P2z+qDdLhIB+HU) zu0CW&uLvE^4I5xtK-$+oe|58)7m6*PO%Xt<+-XEA%jG_BEachkF3e@pn?tl!`8lOF zbi2QOuNXX)YT*MCYflILO{VZ*9GiC%R4FO20zMK?p+&aCMm2oeMK7(aW=UDzr=AO0 z$5mJ%=qRsR8rZ>_YsL+vi{3*J_9Kzq(;ZwRj+4_f0-*wbkSMPWahX#Fj_a8BnrhJ6 zo^ZZ?Vah1@&6#r=JkuaYDBdp;J3@ii+CHM&@9*er&#P}$@wI$bfrH)&c!*|nkvhf%^*Y6b%dKz%QBSIo@U z{?V^qEs4`q<8@n+u8YiB^sc@6g>TncG<|GsmC3egwE6aO=EwLr~3-2 zNr`+)`i+-83?|1Xy0^8ps&pb}YT?w1eWVnC9Ps1=KM;Rw)bH6O!7Did1NwpnqVPZc z*%Qo~qkDL>@^<^fmIBtx$WUWQiNtAB2x-LO^BB=|w~-zTnJNEdm1Ou(?8PF&U88X@ z#8rdaTd||)dG^uJw~N_-%!XNbuAyh4`>Shea=pSj0TqP+w4!`nxsmVSv02kb`DBr% zyX=e>5IJ3JYPtdbCHvKMdhXUO_*E9jc_?se7%VJF#&ZaBD;7+eFN3x+hER7!u&`Wz z7zMvBPR4y`*$a250KYjFhAKS%*XG&c;R-kS0wNY1=836wL6q02mqx;IPcH(6ThA@2 zXKQF|9H>6AW$KUF#^A%l6y5{fel77_+cR_zZ0(7=6bmNXABv}R!B-{(E^O6Y?ZS)n zs1QEmh_Fm7p}oRyT3zxUNr4UV8NGs+2b8|4shO$OGFj3D&7_e?#yDi=TTe%$2QbG5 zk<;q7aQ;p!M-Osm{vFdmXZ@!z9uWh!;*%>(vTRggufuUGP9Hols@vhx z73pn$3u2;vzRvnXuT&$Os7J@6y12*j!{ix%3B4YU1466ItmJs0NsU(4ZYRYh7wEA6q{b*Hs6@k~ zi7Yq@Ax!et0cUMTvk7P%ym){MHpcliHEI~e3HP0NV=}7;xFv#IC?a<=`>~j_sk{e> z7vg-tK*p83HZ0=QK@ zRIHo^r{D8&Ms-^WZp+6US_Quqjh$Q66W^1}=Uz&XJ8AQE9&2}P zY|FXZzZ|0IiaBd2qdt6dIjQr(ZMIOU%NG1F&fu6Po9m^?BvLhI6T0R!H2d8;U(&p2 zYA|MFscMqcO(ye~Jp?F;0>Ke+5hzVr?aBNe>GsGgr$XrpS9uajN2kNQ3o$V5rp0T( z0$6TJC;3)26SNG#XcX7l^MKTn$ga?6r4Jzfb%ZgA(Zbwit0$kY=avSnI$@Gk%+^pu zS5mHrcRS8LFPC*uVWH4DDD1pY$H8N>X?KIJZuZ2SvTqc5Nr0GHdD8TCJcd$zIhOdC zZX0ErnsozQh;t^==4zTfrZO421AL?)O)l#GSxU#|LTTg4#&yeK=^w#;q63!Nv~1(@ zs^-RNRuF&qgcr+bIzc@7$h9L;_yjdifE*$j0Q&Np=1AuHL--zdkv@}`1 zo~LlDl_YAq*z?vmr4M`GjDkl9?p|-tl(DtX76oZv25_DtZutLS9Ez!5~p?th@4 zyc_uax4W#<(#)LMkvo)yp|5tKsC2=p#6PyhpH|449T<9Zdk|%CAb5cw?fhvQtBO&7 zpQ9$24yLqPHP;$N&fe2wm%8qdctwIna<3SwGtQA3{C77s%CW%LYxtK(SBGustL0<( zu~U9r0UOkr(c{OJxZS0Ntu3+cJlF7R`7k-Bsa&q?9Ae5{{|o~?cM+T7{lB1^#vT8R z?>c9fNWey`1dKDY%F3d2O*8^qYhjlB8*7HMKE<*=(A`{>=1%s1}Pm&#_t1xy!FkPk@%SMEka2@*= zxDuM|vJJ5s+xgDls{>*o!7eOcs|xuVBPWX&+y5vEiADK%hi`#Dbd>;;Pbk2H4*-X&R?_-6ZEutSd8hC+sSjhIo z;D(j4P;2EVpEj#UF7IjM6PC+X$C5T&=nL`*!*hm9U)#O?>wqOgC>jXKN3Slk_yaQX zLf|4D8T4k|wHW`;#ZQVocNF|3izi0sOqXzi7@KlYC3CXBG`94wD;tMI1bj|8Vm zY}9`VI9!plSfhAal$M_HlaYOVNU?9Z#0<$o?lXXbX3O(l_?f)i3_~r+GcO-x#+x^X zfsZl0>Rj2iP1rsT;+b;Mr? z4Vu&O)Q5ru4j;qaSP5gA{az@XTS1NpT0d9Xhl_FkkRpcEGA0(QQ~YMh#&zwDUkNzm z6cgkdgl9W{iL6ArJ1TQHqnQ^SQ1WGu?FT|93$Ba}mPCH~!$3}0Y0g zcoG%bdTd$bmBx9Y<`Jc+=Cp4}c@EUfjiz;Rcz101p z=?#i$wo>gBE9|szaZMt-d4nUIhBnYRuBVyx+p?5#aZQgUe(!ah`J#l1$%bl5avL27 zU2~@V`3Ic&!?FhDX@Cw!R4%xtWark#p8DLT)HCZ?VJxf^yr@AD*!ERK3#L$E^*Yr? zzN&uF9Roh4rP+r`Z#7U$tzl6>k!b~HgM$C<_crP=vC>6=q{j?(I}!9>g3rJU(&){o z`R^E*9%+kEa8H_fkD9VT7(Fks&Y-RcHaUJYf-|B+eMXMaRM;{FKRiTB>1(=Iij4k1(X__|WqAd-~t#2@UQ}Z&<1Th0azdXfoll!dd)6>1miA z!&=6sDJm=e$?L&06+Q3`D-HNSkK-3$3DdZMX-6Xjn;wd#9A{~ur!2NcX>(qY_oZL0~H7dnQ9sgLe!W>~2|RSW7|hWn<({Pg*xF$%B-!rKe^_R_vc z(LO!0agxxP;FWPV({8#lEv$&&GVakGus=@!3YVG`y^AO1m{2%Np;>HNA1e{=?ra1C}H zAwT0sbwG|!am;fl?*_t^^#yLDXZ*Nx)_FqueZi0c-G~omtpHW0Cu)mEJ`Z1X8brq$ z%vK##b~o*^b&Hz!hgrD=^6P8}aW40lhzMLB5T5*v`1QH?+L~-@CDi3+C@nRf2{7UE zyDIe{@LKw`Eu=Z%6<<_=#V|yxJIKiq_N?ZJ_v0$c)N4l07ZV_mIXG}glfBSPivOhw z-~+9GdckSpMBNR9eR`Y|9_)sXS+u_OiQ%!9rE(2AFjoxN8lk16Sb~^Sq6kRoEp3yD(mm`HsYIXcag_EAB8MHc}nahxVVUTts~U9P|f;7Ul$_` zStR4v&P4q_$KXOEni$lkxy8=9w8G&47VY0oDb^+jT+>ARe3NHUg~St`$RDxY)?;_F znqTujR&chZd2qHF7y8D$4&E3+e@J~!X3&BW4BF(Ebp#TEjrd+9SU!)j;qH+ZkL@AW z?J6Mj}v0_+D zH0qlbzCkHf|EZ`6c>5ig5NAFF%|La%M-}g(7&}Vx8K)qg30YD;H!S!??{;YivzrH0 z(M%2*b_S-)yh&Aiqai)GF^c!<1Xemj|13>dZ_M#)41SrP;OEMaRJ)bCeX*ZT7W`4Y zQ|8L@NHpD@Tf(5>1U(s5iW~Zdf7$@pAL`a3X@YUv1J>q-uJ_(Dy5nYTCUHC}1(dlI zt;5>DLcHh&jbysqt?G01MhXI3!8wgf){Hv}=0N|L$t8M#L7d6WscO8Om2|NBz2Ga^ zs86y%x$H18)~akOWD7@em7)ldlWgb?_sRN>-EcYQO_}aX@+b$dR{146>{kXWP4$nN{V0_+|3{Lt|8uX_fhKh~i{(x%cj*PU$i{PO(5$uA? zQzO>a6oPj-TUk&{zq?JD2MNb6Mf~V3g$ra+PB;ujLJ2JM(a7N*b`y{MX--!fAd}5C zF$D_b8S;+Np(!cW)(hnv5b@@|EMt*RLKF*wy>ykFhEhlPN~n_Bj>LT9B^_yj>z#fx z3JuE4H&?Cc!;G@}E*3k`HK#8ag`yE3Z1)5JUlSua%qkF zkTu|<9{w9OSi$qr)WD#7EzITnch=xnR63E*d~WGvi*Co9BBE?ETHud;!Z)7&wz+l6 zuKODYG1>I1U#a%&(GNJ`AqRfg=H!BtSl+_;CEeufF-#+*2EMMz-22@>18=8PH{PHd z);mN=aR0MPF>eutLiS#-AOX>#2%+pTGEOj!j4L(m0~&xR=0+g#HNpno6@veLhJp}e zyNVC$a>4;!9&iGvU_dj&xbKt@^t6r%f^)+}eV^suRTLP52+BVs0kOLwg6n`=NUv50E7My8XQUh?y%mW62OT1pMrKI3Q(r`7vU&@93=G~A?b(^pvC-8x=bSk zZ60BQR96WB1Z@9Df(M1IQh+YrU8sEjB=Tc2;(zBn-pete*icZE|M&Uc+oHg`|1o`g zH~m+k=D$o);{Rs)b<9Zo|9_Z6L6QHLNki(N>Dw^^i1LITprZeeqIaT#+)fw)PlllU zldphHC)t!0Gf(i9zgVm>`*TbmITF zH1FZ4{wrjRCx{t^26VK_2srZuWuY*EMAsMrJYFFCH35Ky7bq8<0K|ey2wHnrFMZyr z&^yEgX{{3i@&iE5>xKZ{Ads36G3a!i50D!C4?^~cLB<<|fc1!XN(HJRM)H^21sEs%vv+Mu0h*HkLHaEffMwc0n6)JhNXY#M5w@iO@dfXY z0c6dM2a4Hd1SA*#qYj@jK}uVgAZdaBj8t6uuhUNe>)ne9vfd#C6qLV9+@Q7{MnF#0 zJ7fd-ivG_~u3bVvOzpcw1u~ZSp8-kl(sunnX>L~*K-ByWDM2E8>;Si6kn^58AZQxI xVa^It*?521mj4+UJO?7%w*+`EfEcU=@KhDx-s^WzP+ae~{CgHDE&XryzW}Nww%-5% diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8049c684..84a0b92f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 1b6c7873..a69d9cb6 100755 --- a/gradlew +++ b/gradlew @@ -205,6 +205,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f9..53a6b238 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 9b090570e297c03d587173f6992b12d4444e2721 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 16 Jul 2023 21:21:49 +1200 Subject: [PATCH 41/45] Updated Gradle plugins and fixed up deprecations --- build.gradle | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 4a883bbe..f0ee3401 100644 --- a/build.gradle +++ b/build.gradle @@ -9,10 +9,10 @@ plugins { id 'maven-publish' id 'java-library-distribution' id 'signing' - id 'net.nemerosa.versioning' version '2.14.0' - id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' + id 'net.nemerosa.versioning' version '3.0.0' + id 'io.github.gradle-nexus.publish-plugin' version '1.3.0' id 'net.researchgate.release' version '2.8.1' - id 'org.ajoberstar.git-publish' version '3.0.1' + id 'org.ajoberstar.git-publish' version '4.2.0' } description = 'Concordion is an open source framework for Java that lets you turn a plain English description of a requirement into an automated test' @@ -101,8 +101,10 @@ sourceSets { } } -sourceCompatibility = 8 -targetCompatibility = 8 +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} test { systemProperties['concordion.output.dir'] = "${reporting.baseDir}" From 38401eba7ade934e15a24728f28194d860b70bd2 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sun, 16 Jul 2023 21:27:10 +1200 Subject: [PATCH 42/45] Updated version to 4.0.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f629a190..44843009 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ group=org.concordion -version=4.0.0 \ No newline at end of file +version=4.0.1 \ No newline at end of file From ce4aed5056f392770cf2b9922eaa3d7dd9add3c4 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 23 Dec 2023 19:20:31 +1300 Subject: [PATCH 43/45] Added JDK 21 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e62305d..0595f66b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '11', '17', '20' ] + java: [ '11', '17', '21' ] name: Java ${{ matrix.Java }} steps: @@ -64,5 +64,5 @@ jobs: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} external_repository: concordion/concordion-specifications publish_branch: master - publish_dir: artifacts/reports-java-8/reports/spec/concordion + publish_dir: artifacts/reports-java-21/reports/spec/concordion destination_dir: concordion From e4d101086be6f74cbf7a1f6bd0290ce0db73d8b6 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Sat, 23 Dec 2023 19:26:45 +1300 Subject: [PATCH 44/45] Changed branch to main --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0595f66b..a7f6f9cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,6 @@ jobs: with: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} external_repository: concordion/concordion-specifications - publish_branch: master + publish_branch: main publish_dir: artifacts/reports-java-21/reports/spec/concordion destination_dir: concordion From f20beb0daaced8a39972df9844190b255ba5ebf0 Mon Sep 17 00:00:00 2001 From: Nigel Charman Date: Tue, 13 May 2025 07:01:20 +1200 Subject: [PATCH 45/45] Update GitHub Actions plugins --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7f6f9cb..b071b062 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,9 +17,9 @@ jobs: name: Java ${{ matrix.Java }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup java - uses: actions/setup-java@v2 + uses: actions/setup-java@v4 with: distribution: 'adopt' java-version: ${{ matrix.java }} @@ -32,7 +32,7 @@ jobs: - name: Upload Unit Test Results And Specification if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: reports-java-${{ matrix.java }} path: | @@ -48,17 +48,17 @@ jobs: steps: - name: Download Artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: path: artifacts - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v1 + uses: EnricoMi/publish-unit-test-result-action@v2 with: files: artifacts/**/test-results/**/*.xml - name: Publish Specifications - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 if: ${{ github.ref == 'refs/heads/master' }} with: deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}