From 6ea6d3881cc728a1109d3994ea549c233acbcb69 Mon Sep 17 00:00:00 2001 From: Yizhang Cao Date: Wed, 22 Oct 2025 00:52:18 -0700 Subject: [PATCH 1/3] Parameterize tests in AuthorTest and AuthorListTest (issue #676) --- .../jabref/model/entry/AuthorListTest.java | Bin 57068 -> 88502 bytes .../org/jabref/model/entry/AuthorTest.java | Bin 2859 -> 3936 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java index c251e3c5d3f5f97d5d76a34905a446a40afca272..6487062c7e5815e67022e7c383d04a739b767e94 100644 GIT binary patch literal 88502 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 H$>;wEN_9g- literal 57068 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 diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java index 45f16edd674c0bb46e3482cfa89196e188dd4b08..5a2d962881343019ea82053d97059f8967148254 100644 GIT binary patch literal 3936 zcmeH~O>fgc5QgWB#DB1INh(oSg(E_$6@oj59mt>x}u7@hRiX1~z5o z%3j)2d*bds6eGtwMaG2nE_WZvMTzHd_L-OTbLchBkQ76$uhRuU=N!2dl`D@5kI{ZkO-pU)jtr zefx=q)E-vP2%SUx({~Y-_uJ^dun)|hv(`iB!|Z5T(*YVzxe_9qTF0Sg3X&c}_b2>& zivFxZn{eD?wTmYvU^a2c`Qi{AydT;19Pbe{J9c-(B-hg}`?xier}c0((0pjm_--m|Jy$uY{-wAEsQd`JUQasz*W{@s&iF z^L0U)ojAJ5jIu>kR8{({oFGN-k&A-7QC`dJ2WuG-Q~gM>BE%;6#>Y{$WeUpjiqV3; z%q!`|XsZ^jW`C<-;|4bPoRI}LkAM^5L+EI(9Di|al5wiyibIjJJYS7A@dxgtz+IfX zn^WG-H3weJ*5kaWS(y>?BXHN{N0~3VMRTtIVX)l+L+Yn({H%U9vH$p1X6#sX6>j07 zJo{CFUvXbk_f&I)s)%P^5sNdvE>$B>+>z~5i`0*^3Q1L~o=X*NP|NMLE^-I-ggVqH z=++*JyUDEzD|+u@XTIYy&GP=2*KhO2zU#O}KU~`pR})Wns9HCmR%Za6O47Nnc3BnG z5i>(*bUqCJFYEVy>*6)_fhymx;vaR8Y6`WMj>&bYw?`DsokH~k^1hrQ#ezo^z)C$7am zub9{$BcnlGX*1TJqcZ-AI2Q5fBCDHE?Txcff0S2qTjh=A)1N;B{sA;-P>lcp literal 2859 zcmc&$TW{Jh6n^JdSb15HsHJX?)ucs*X>^oMVqIVQVz2>sj_vtE#ZdnHjvWGYG$d17 zEfT_Z&gDC|&(UP|lPnlgW`Q5b)UY|u6=ec5>CF0~)8V;R#-RtYBG@}F@Qrp{Nh0>| zqOOK+W$cB>Bpu}1ttZNx z8Ef{pQ~p7OXO&h3(>mh#tW3sHK$*47gxD=6aXI+qiLj7|nScY7dAC$1#DF%P4ua=X z*u>RJaf%3~edUJpYzlc^ad4$%7SGZys05Ah92!rP8=UmErtxzIKqBdOFKV}nml1!T~*QiegBl#=@`yjm%_-$(sw`_xJ_(JPxJ*=>60 z%7p%_PIgGP63+s<9^@sO&Heqm&7df#^2E?!<_eDP6IGbSfl)w7Bn8(E$eu{W%?@Y4 zU36nawUgFYWszY7(@D%R;!=B8J9_c$>Dem{Y^Sg4xSARtv(;(5!}%DPacG0yjfo`p zUvSs;Cb4uLsz@3$KT?m(ToTJh%mLHew+*A2b0>}%cgNlGR_hWN+#+ArddcL;nLo>! z-~?hWnZAaOv#nUgWmQ`=;~Ge6pTH{fbqZ5Jlr Date: Fri, 24 Oct 2025 12:51:07 -0700 Subject: [PATCH 2/3] Fix file encoding to UTF-8 --- .../jabref/model/entry/AuthorListTest.java | Bin 88502 -> 43299 bytes .../org/jabref/model/entry/AuthorTest.java | Bin 3936 -> 1901 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java index 6487062c7e5815e67022e7c383d04a739b767e94..9503a1a7228fc32bc5d3e8a2214fdc9093af0388 100644 GIT binary patch literal 43299 zcmeG_%W~XCl6QSYMbAMknQGeJv17(w?Yc>kA}#R|BDM0&ctQcPK{hN9Xai_U6x9ds zkL+m=8{WN6?4I^u`?7yAf3lfbuPmSnKsV{JW?~c}vWc$BcV=Z}Jur(-Uq$D!$cyvQ zH_=HEpN%f^Nt}-2tSYWPzjG(KnB_$!$||aoQ`u~uCDrJg`7Ej8Vie7i(YP$*qDu0t z97XhT>)UyhmY=WIc^kUMEB4*bs~h2l{zuWps@QMP^>|w3uUD1WaWMyywY0y9E~C-B zO48A|D55J1)PC_aDJvsk`}kmnN{mtqi_D^-??*`)ouu)^fbcgvjv1C_lUY zf5l)*$=i6+ugk2+FOvxv-)4Dvl+TM(heY zDN-$x4BK6QktW$IZue<^o}7-Py#ws=yqe|(N(v|h`xf;FixI$CzcZVkq~IB+DVRQM zgPe%#J9mUw2fD=8o9JSe#*&sYxd2)UQRP4=INz^{Ch>=j{uRjfVvECEF;dd1%Jo$=n@_|ePp(*-< z&&H1qUTz%h?0G5J%)zK9Ibz;qm^T2?*Mod9z37YS$@6E&FCQN~+Is56^JHFBh~x=F z@|ciZ=ZghI$i8?s#{17-?j0PBeQ2cI_|L)h@iZ12QHDaCFT|ewT}qjXlOjh0FZ&7< z?N@B=9UlMg<@ovW&cQSBkQwPHKO15T{C%%WHw5Zne@g*+`C|8Y=jGG!@zz%jm_B>z z1^)QOfdYTDEc`WPuH1t9;oNz)rJ1@FtZTyBRxb)rsJr_|$GgYRk9QCD+c-DYv^wCU z6MO@8`j5{L^TJcb|8lA`0{`}%3E)LG*$Wso9y#(lRUWlWj@Ws(M3{C@f-QU`?ZL&iP%UXKNK5~n`CR^5Jzd#tNwih z$z`62{dj&6Wf`@#nCo2`Xx=HVM3j#14uG`<4r7;jG7)FV8!3+cr~*-G*(TX+Uabiw z>G;hoKCR-3mNm~xhx*GkF8exIf+s^_FM(f1={yE6(t=-K7f&M?%paT;aV+ACS#>2M z$|zs}Mr#0m@ZW&P=66OBZujR|atcYg$TP@eB#;bpCUI8e7ZQzz<_*v9UGYMlpZYpC|yG%mHfk>a70$*`MFXYk+yxv0^zxiPFhO`E|g%Bl~qzff(-WA zB1RU6SX6kYM(3Zt7kfW_U;g-=8Ie0Mqgd;hL$YP4c?b;SCRwja*+uduo+y?3DC!w6 zJE+@ev4px-UPE-k6dvZF)3{6^X{HHiQE@Y8LX!INjcf0I`i_lAKm9Akk~IP88>HY6 z&A?;tzPoFJ3&h-UDFe$>$d%u0gY)VLBh3_(pndSYV5k|JX@e3erA-e7f;L}mTp^61 z3zDL{5P?`_+m2F0+C3a4G{q`|li>=dA0RCXnKZ6!MyDXlgDjR*40UJ(pQNeEDSVHE zR06@8=%fxX#esja3o&BJa8m|3b`5NdA2{sb%$Tw3gkDcqr>~lmcXX$bY``OSSOiA5 ze=%8bo#7Nnt9ePea4@UOr~#$d2**aYeLX^y+973{u_h|0M68K3tl*elH<~3u^yX&&az>FwB#tYMwAxuObICN zq_GXWBAuEXj%tuY+#I|)%ZrIP&0$^+u8GZzFj0i?Uv|ZxLEY58w48>t(B7f0gkbA7 zahQZv3IvnTnoN|mSAyO{*aR1Z=}AJjlR}OM^kEZ)U+MwFpOUVLlRQu32*T_Mlv^(o z2M#vi%zZ0kA13%9XeF6#P>TM!f6Ivcb%9D|J{KKE9z^0hO6s12cVbQb_ z=NFEpZ7ock7EwKotxYaG@(LGz-Z6>wO6)ZeUGoeN6)jblUSyDDmLf7V6`m{uk06Aq38pfRt`bc(IDZJ`aQEha z{_lUM%Kyz`sm2(HR=rS4Wy;lnW;pE%7>0sSQ0PSiga=N53=yz!;E7<`KRbeirps$p zRBTrRrlfBvuj>j88h2Yf;9?0PzrBEgtshN|vAz6A$kzC>mw<3#J6*45WjS_u`S~*E&)peZEu|I*(kvKHH(Hc!v%uFw| z?Xk&Dmdh+u8)5%R&kEBU5B{NNc0)qtm7v4=76V|@PO>-+UAdbl2|o^{aV+Os=C62p&=9-csd@Y z!UhR7)x)IAL<-s^W@*x*>4+7Yw3YzDiCfC~x*~+e-4+&lA-}!2ph>#@S)PstP3!3$ z5;SpMT`fJ$V?%9^LJy1PLgv|Wfk)Hi6o4p}(+{7sqD3-iWg9KJkod!f#nx~g@95bt zq407U2qJA1IHAL#rz>i7Nuxc}Aex#2u`y&M>&Pa4IJEVQ9$h4QEtRDmMC7f;lrD|v^adJ6YCY0G($ZDo#sZ(&!|*p( z;dZ&}sBrV$YyJXkV+-FjPG_(;1`bnA^9k+}*SpN*k+|W26*OU6{@83sv>QmA3hU6> z&Ig-C+Cj>I*Vr)bU{Z;z5IsteusJ3n#LefGs z${fn?#hM_~Us7I3iiRN8Bm_S)t8c?4nn=4QR^U`;6nx+4&x=tT1a1_;V|Qb{vkJF( zKYS>6<9SSm8HXeFc9BpoXiuTeFKX^-A&cN<7eZ*n#yl|$uZ$93y={_586)1sUx)Z9Jtz= z=GJ74=D}Dr{FY*{Hl9Gym%OTe^pCc|tg@kcPM1V*$L&Cm#;_cA+PExb>0KaeUz~D9 zsR}scm(4xWMz{f#qJ`TK6&`*~70IrH`BaSS4SdP9wi#N>*;`rQm7-v6#)q`4NTjiL z*M)*;N%+BUeME&;!!Re^%2Wwfq)LGQYcrpBv~mQv4(RUV9C{R=!Ywo!^b+0Kh`I-5o(ah1GfdZ$A7&tSvarH z5(yAD(SoPff~QpJvIy_K$Pan;i$*n~wgbPcJ_@wnh&1k+QG_~d=Q&(OvqC3S=h7Wj zCz#gf`O=K7+Kbe3%LqRX$e&VGekDe$d|RO~f02Pd!pQ;r*Q}7yI^pCW+Ni3-BT~Jy z0CiahDTt8BJ2y7wNeWkTi4vwhcw?0FR8^805`8@U3{DKf9^OhM(C@>~;nzQkk3WIm zAAF!4p=PUz_&@~gwH#Hs#0zKPDGH;v!liVxS)5IV1CrD@g*#Q?P9#iD;w00AEP$8h z(fOpLT^hCcd<d1y}u@{n4eCJk`JpNNnM>!i@Val@@Q zr!igLHllmT)&w+r@K3x#V`(%u5ez>J4OO;@R)R#XcaS)DNHxyylbD&VrD38)frKpR z4;>k)H41$N9o|SqVRmp2CS^1g!LE?|Ies?KXU}1Htx>M}Vpgr~)9GsHkMVHr&|w|9KANAwT9BV;(-$R2p6jwN zaffARN_(g$PPyzzl5gYM48y_BLADjS94XRy2)9wfZ9mzhH|dzsSdk+P&v3qyi8mUarBThLHCo%-#WomOtmM00BgMpWr}Nt#;;&C4z6*7un*UToy1Uvf#V_Bgt%D3 zjpkew=SeMqKA%EXn~Rd94m$>G`8;!O}uYc;+XZ7w&5qsx}BduZHa3Br{Zdj);hu_ zu^J4`y8J+D4EH0tZqUXCJ;MaA;D!3xp<{IxJ+N<)ZRXX4$STl-S1zYXSwMi?qpk07 zy>EG1BvcO#qIW-!Eyc|2{EGQP^>$87ad(6;>@v>3=Olka9KOq{@!x zo#UYJ4|E)|ZauBo`cL+67A8yn7A&B2wJ7$!Nstb?&

jWkk)*84Cy8g+b>kB9|UmtjUmfv=yq@PZjhEl{A`DJ`mMMVVxX)Bv-6wxUx&-m*g z*W<;>$;tI8zSh;+veuyemQ@(!45B5_UjIv!rm(-{ZoG)aVLmV6P$s}P40-T)dn|)f zq49IUpfAL=q3E{YGw_;SKFRNt7Y2z8me9P!Q|lPI?ru{8YCLFQaQkRE9zCcG7!MUzyBkrG z##ax%gp<8Qh4}{2Z5tT%W}Kz1kvJNOt@Oe5-U6IHqIVF}Lxf>I&>wE2CY0+Z3s};7 zaJ{j}%hz$5IuIOCzLp%`&UL&qw8oka6D2uDAm&xSMeb?ueJG(w`=Vs3K;ZypBo z-JF7{z$=K0!0X`7^+6U`&6973Hc!y_v`MS)(4pn7b<_Nej-en{^9WnXebYL4%g`zG zj#hWusPP(u*&am_|4h3`#b?5NsYw#{5mMUPhqEH+DgnubuM^|ZP-dC*^|0Ss+N=zG zJ?yuH!naY7jW!TswB%raI{QMVM0D?h%&eOs&9R9c+6%XvVL;tSJAs{X`txHn1ac)4 z@L&!4_~6mOXJC(S>=mGRmsOR+1`RP7kMKRV`Y>xiy@UVz-|@)=yzIyCrZ7~%pIE6> zdxPO#fj|GxfBy7+im!vFhc}bOfB{?+9J5D2Upz|62zCv^iM*YtgcbU74tob*<2I{u z2FZtjm&Z%z!MD-AcmQQ;^DYvSEBe`^sGJ&!Ii+=DJxpVuO7j>chbI)}*Tcc@Q7-bQ zlFsj)o;~z6AYuf?+&4*pQ_){+;lT+whoKG z9|>S`O%Uw@NnR5#Mj&a}IUHxQ>aYV00$h&*?OTP(aM7f<;Z@}Hhm`8xJgt&hs$Mo+ zqQdBXMc6bjvJdv=kOWSyr;7!>Va$wQ+RphF^jcdeAmf`Iq5s3{XaT#R-(Jw?WU-(; z+Pv%uo_;;Z7w}GUoA#q(Y4Yq%1%~%Vd9j7(H&NF8g&{Yjt}YEl@-HQYkKBZ42`T8n zb_*5}*6J@M7MUl?Lp^BAE6U}j#<5}T*aj#T?&JVf_o&3RR^XLfTJro7Jo51KOH(50eexoClzYIqP~Hw$Ys{j3WcQS8O#J>^oQi& zNo@D3cM4%Ujpv1+xgK;^Qh+oHUL7CfroT!I?41O|djs4Rn8ooVhGDNxJAM}lIC_j* z1|b=NoGa1_NE1+&+HhkDcR)CY0#spy;jUwo1Bws%7ndEV`I<hPE!~rnn99#7s9o!tsK~CK-hakOQ%!NL^w+*co}fBNZfe?=hB@37kS@o#?f$w$Ba^(Vja zD@*w_Stz;|-2O(cX2Q9&wot`joW^gW3~%wl|Bs9OhkwH=Gt?Wzgi5WZey|y35C*Un z++lM9H$*L8L_iMcU&Gr5b?D$cKFZKt2#T)Kfa~&!z3l{3Stt}sPV{Frb$*s)S)N~s zCv5GEa2|av2RY0b}`}5yJxQ7cl6+ zZ~}Q<@;08RAqB+u+*aKGmOx`l+R(G*1qSAc&=nP+Atjr^%$@_mwk<>PiMl=UPuuu{*pILJM zehBaA3Zf%SuTEDJ-WhKFwf5yE0ImcFV`IN{F=_!aKqVbYW)E6)(*v?o<*X6CChEw1 zPE>CLXXsqsnQD19CvEh&fb}O>oC72Em|zXkdn-kzj%o^dBK!OOQ%{XTpH6FXhrr`< z)vD6X95f0O{;c|IR_V~>iD)R7?L*5TsS^B(1P5d` zg+;ebI6m7RHX@TLG?d$0VxAn_f*ol(>thmID+d1PNz;nj?ja++8Shl z!0;N=8q8MY>LF~uHVZEFB)7zSWM!SaT$6=<0>3O1$&3T(+z9Uz&NW<2`JHJ zFns|b&x+&{c2V&!QAoxYH?FWOFl0MQbP`v-PO8(X7$PA3Oo&sshD!{%(gvRyT^4aQ zFEYWul^(16;WhG&_d_%Rc$>M9{4auNg7UYk!3w%we# zH$f9amnF>L>u$*=trQ_m! pj@2`BN%C;;JbRVpui^YExraz$^!NvA2(ao+rORjT{|{&5N}mLS^%ZN+xQj-3dUz>6i4Dw2wPk&6YApa2U5WB}B~ z6kj55koSlmB2VDoc?VaL@7qSBduMxgXZGv?Ae)5(u;=XVO!wE<>6xAVzyJNL*>0XR zpW^Q)%}%pu4x1w!Z8U$tH;-|=(>%kc=lK39j`wlA(;PG>IP+EWFU>zT-)evNaK&fs zy(ehn80WX~yN8y2i!X5J9=>PmFK|7NchJ%XuI8tWW)t@wx8L#ZLtKB{p0#hcnm^*+ zZBTN2+W-0WedDy>opbN`F0eRhE|Pbl-~kYL4*7`W&ky;F>i1!@3;jH7zPJEwdx)N2 zoMBB%>*7rd{T#m=xQf<7+uX!GNBHim4874k@8e!tY$Vg@`g^cdwNBb$&I_0)8Mpg) zTN>zb_QCPfkd~VE9-@^TPbKZpD-y@&Xl0}M;Ox^5IH$+jYyQ;IId4Coq2)u!bg%Wb z^o#GH|IeET`1S?PJwcy__O<4F_@Q1b@PEhwJrgv=%P*j@ z)ZY9Ruh6bibge!540ljZB)U9l>1TY1+foTFnwRa}($=COdV0Lod@5 zzr^SWJ)D3OL06*XkMW84XiL9quH*CLhQ0o}Jwx;#!yYLg;(mZ5BESfF489o=KW%>B ztmF6uKcC^-pM$z$8b0rU(yJ{kPjLMnbYllsK5qLYB8O+6>^|in!{v4pEFYw>DxZbSc`WKMd$M|`Q|GUjA{7_2I z@%Jgt{{Z*!s*Tg*16;q4ANihCUIhiaXj@wOCH`->t%&_Tci-=|-%Fd?&YP#UMjEH$ z@(!eaA3wz89#FZCzqdeh4G!BTKNKUq76~k_4D!BC+aMH2xEhK_+xxGHv;OP7m(&1_^5}? zZ(2M45J$Iw$bC@pOZ<8})qCipp23HupWlR^k%%?jinL97(7T|GzQt&I1P^n&rSK7Y z-^9@tJnuNAr5KnfnH({`lb^eY1&`o2_?e!RUSkV9-^TB_J!%FbIYBNf zNUyT1E%p!jU&#dChtFj;@uIDJ93z*f_hml03%^V+ynlK{>SO0bS-nB58Pn~guN&0! z{x9DB|o0|JMVm(0i zM_uN4j8#h>OMT{`rRjqfaU#|4ZS4LMZaxQJ0`CoPs;P3Oq-GjPpODJwL6ZRdDa zYq!2qxsL0*_fmU2O`73tjM8fqb~DSl^`0Z(eIUVHojGsUuBqu9p)ZheZX?cdtbY}> z)82W<4m5)`GLHJUTRf${A>(O|KIuJFa%MNVy!-3W&W0%X5Ir!SN!6aU8;-J5YB-i> zHJ5rqD|(J20+zguzpj< zk49k6PcH5bb3|IyH+|>I<10GqPBE;JS(iJr`*QB;GVn1DjRL8-EW?}XBQ1dumk~m$ z*y3MRmZiL^X4YgGU&C_!X#5w@Oy+_7e+)hSD?X*8?kHZ>$W%3VjPH6Kjycb3b3N~- ze)4W}j<1}xEIz@L3zw6CZA2DV(U$mCA3zQ_Ul(|}JIV;&ji_u@} zx~#yZR=jprWr;P)`}@+--`B9Izrwyb%bbq3esSf0I#~>J1F7&y<(=6EEANcLZ!}-y z*DBYR=dc=of}G+QnVID`jAfFW-#CrUX~yGqNwW~Pz^F({YIC4X7wxsZuEyH8mz@Be%ZSd9xQe3V6 ze~nK4>G6ESiz{0&f=?odOMhRk7^;}fyiao&m5n5IwHcKZqr^eSUuVR zD&|R~hhfB0PBc37M~bm@B6^6Gj_UT?=u%Q~8g9udRJl6Ve0WZ!zl*-L@PVU}FzQX-b-E+=9y7K8G zKZOI6ax7n>YPvhbueD^?*Xa6rQr|_=Q_eFn5<_^amX=myZy*M7offP7GU~8zxb8zN zfmQzQNQ60VX{DBudyKXY5o2~*k48Qpx3!I(cD0#|lKPeW^sYl^sr`JsZrtIsHqE)C z`mfgL8?GdyuN$vPtr7>LCzlWOb$KdMhS_RxVtrKSf>O-9&MdDfwH1Ej z-13pH;St7cgE1u46O$NM?=7(UgBoP3^HO}I1M}EsrFZcUaC!F z^L~xq}o9^~;Qk%&Bs-O3T}wtmBI-AG;8NvO0{Y3nV9)eO+8&6Gp(uQG_HO=rW8fZh+-Y|xl#EnO^oE&+)aPn zAo?^5uvJ!(W;Yul#qLRmw9D z)QyYFU;BL4V75oKBIve{XLLv1GE`S-{5SV(5Zk)b{z;!!Z9^ofho zJS}G#IZrp7Y4kBu8yWXsKBw?l`Quf_!DX|GKJRKbG4J{O!E@}7>$x|*sK2+|o7QF! zeWd2j6+CMGxE=*VaEcF_KX2$`S8ieD8G^^mACKh-O5Lk=zH6EF9aazIOt7z<9=B^3 z(^U)Ix~Y%rT6NUAVtJjkUr+T_MYhxJHC_MOubplN>pQ4n{Z$__E28T#`sXkEx{)FI zapggOJW4!0zN@X;_E-9j&57DPB`MX}A(rnEH;i77q3;bx9SB2wKNpUJJq*AQD^CWWJi^w|JKGCphcac(u0u6fO9&D%57 zH@a*4Q;%r2=I4?QK&P*goyXi#-{Y-jwx|q&bs*>G&vIVJboRB+dF^vbpEEL>)(Y>C z$L(8vzn;>K6W>Iihf0Oe!YGbSQHm~QUIg37AuVCKM&qOsI+ibdyu}Ug^D&6i( z?NCLJo`myDQJxpq?6p?mM-Im8T=O2D+kCZRI=?>a(^+X^p?jXBa#-ceV%pbQ`&@g? z&IY*^2_=#z*ETb+7#Kc&&Xs3%AC;8qSX;E(J*}o!Ya?;B%gvzh+ZjV+ zE-Q-hsI{khL`-|??=45Ow)R)5O>yx~-_~TVZMYWr$IYys%wV>FK z=d%gVu|KZo-ZZ2B-n@OK9;Y^+=p!|E=HOBD$Mq-}f@$vHEijMO{8>aFy;bB39yNb_ zu^9uU(I5MB_d$DdfKMCi(;0oN@+*`qL$ag1TvHp+@mf5(k5?xx&y7mnkNSOn7?0YF zzwu~vQ5B9FnW~@lDCE7Xac@T@IOILS5JvPk%j6=<>j?Myn_3g8Lnz8qHriQHt+w~` zlOgPKHZ~TaS8Z)^Jg>34`Z!eXiI&Y{=Fqrh*I=98)gxtgT7Pdj%C$Mq@~F<8BN@ha zRF9aUo#sbFmOXz~v^>5VOUJEyO4Y?MzUT~Uj$FxSgvMF9^-Rl_$|+Y_`ivmwpJQIe zGlKp&y_|pb(Q&qzuVR-YP?rbqk4E(tIF?J!X^Sx?`H{+8sF)_L64CmMsN7QL&VA-bHqCy#E$6jz z6?srOs^zv?p7F%Uj^#XBr&)dtx~?*`^_9AY{Ph}iuE@XaYtV<}H^&-u-IGu?&h|U3 zS+iTRmmT*@+{f-AvPUL&tvo?)!(E@*xAxEVO8ND+YrXZ-vUfW@O8GwBim6(H*~ZXr zh`M{+a+F%^8Cq$nyT0Z5@>J*=uV_!2dR}WOv=xA!rXd*)tuNQT_%+v?V^#n8p%`;! zi0Ts;e#baFTc#1y@m5`+t^5k33jR0UUo}dKO-jWAba*Oi`P&ShJo1{T)}jBGu@dEB zb?;Q*PNe-+CZzpukI%@X>iS68g_m5X^IP(+T|QgJU5PEf@-iRtKCws1YyUF(Vtq;b zMs2N@=OSON_n0eAdbHKD;+=%2P`C_Ev5kt)dmUYd-$X+#jU=lQo=aQva@BmMv4MIN4!N?*YfMV$3^fqEgH#N zcNmGZ?(eavi9<3!6yv)LmL`3PK}zTH5vcrG)%l{UM_0X)*Bs+^imp$`Ce~Qmi|i1c z8_(2X7;zujW39eK?MCRvTpH4I`JCnDkotE@;>PLoNpsnlqLKF1k0lYlQ+ZsKyuB4E zXR93NP$GuG-&$lb&NQyjp3ZBZ|6I*mcI2?UCe_QK{l=r*u=}*H`Ci>gApORA&b4ND zi0_mth5D80?P?3Ty$|N}VM=9eMdZu4w0`4^Oxo(>mP$^>&BJn6olNiTOI@$bNy*SO zPL%8Po3Xa+`WlIkwQ3Z`QZU@@N~6Ti#!?}r_H4Uy9{1FhH$Q1E5VtL@8GkCR(tX-B z8fkT#b87o|LzCZEWA5kL58Zm>i`qXU=9BZ;w)=dS&Q*Hm(kIt*YdW`GRnwk|j#qN3 zhFHd?GnuvPeTG)~M7|(?W@g%Io<0}T*X#`O;q6bK*j_bn3rLf1wUak7=e+c?2&m5( zexhz!{%t*y*U{X%kcg*cRv8URmcG^29T=Z}m357z>o}b*<61n*DqaOtvN~~<&ER_$7+zE@b~il%zb&3BkT$$O6Z zS1tAN(TF~7Ez{N}o&Sm?%}-ac4$0?vmiN*JzTWN9-Y?sIOKLi9;G3Lc9IbL3)ii2W z6x~1%N0?FIx}e?mSw^mW;kyp`o+p{evaVi6ldqQ9xG{Z?DDfGhwOe1KezICj zPg7o_tfw~~r(SN_Stp-^?$onVLTh-V*$y&v?p%L>AC-ee0h4h5Ts(@G>y98z9&yLa zD1NZ_sGb{9$!qx&)%MGDV5n7X-RpIXx1lmzIpNO9%*XeEYBcN26-bJXt#_O1TR6J< z6MC%k7C+2dntHK~cHAZ{uR(@g`iNTIzJFBN`gOE*wBkOfDSQX)dG@7xbRKZcGqFY+>nCq8^)it+2jH- zfTQ*k^ssl@;}3DAeEJ3czt#NY^z-+d@1vDP)89!wFBP`=ef-vW_hZDm6VT^*W~}PR z6UG!?y^WlhtL3>DIPoy~FkgP$VoDyjT5gZg`c8Y)$3gSX6xo`SK0n>tQyt0X`Vn_||Z8LJBv~PufE&PcMTTXhGgPUe<@jnz5eBF_AYJ z7%Dz<8%K!M#6##k$5mUHFL?qq_%2l$n*%?Z8d)c-J)UZ*gePO z!tXX9w`Z;9`hM8I=XRr!es4mepF_3>XYWZSYD2nR-aAJTTpwQAbAR>pPU}r-=0 zixx6Q9p;}l%gP{UAJ@axlsf9j%Ywag?6*wMS}(8Rx~~H}XYW3yJaaP8s@4PO(=+_= zy$5s2-(!%cz@x6z)KQRIYo3?6@6+^uy3CDJv2v}6MEaKNdy3RO=Xq`w)eqp&cTQ!z z*~V#4i(a)X_CvgDAIyYH>S)V&p*sEd*mwjq(~yz#lvrUoXs)`j>L?IXQ0JLFCgWbP z?~ODfv9d%QE+#U>NRS?V14Z77%ujf$neHrF#ccz>!C)#lm{CEo)E*7>W9N1lvrjfBt-ToLyeec!^Ofcjmp{jt>^i zyZFzVz&`SH*7R5ldv#g|E2~y?sY>6{*{!SkYuCZ^3-r6+j#zWYYp8&hQA{h-R?0^c zDZOlE+f|BuOLNFo?26ebk><*^aY=WzYDCAm1$9P%?nA4jpQ20v>xUOW=NQ$L{c zqZHQg9-c#J$738#lkFxj=KH+A0@54!&-Fa4?VbShE~ac>wVymN>+$139S3=?wXL+? zS*EX+Z+b-d?jhybuYs}AC~LIcYSA28`4Mp8o;UBK_b*!Ae5b{02XB_(_?>nBi}Oc( zb1n5s_Tt$22KuLngK0Xw8h^!z@ECGtEZBqOwf3)i!Dzub0I3+RCN6#4eB4qX{qQ|y zyO8wJsl_rn?Lr6mEiHupbNig)6k|{cb?VP@SI1s1<>)f$MLz>LZs!h8pe=j&jl9B8 z#as|7@uJMZblzeUKAU-$@72d;sn~ITidu1kIV?YC(yyGB^dHp-Rzs6Tf_Qej6tgH^ z#WN&hJyHX$el{o9@yKKWxpBT&X0+zwH`f<)?WgE1lJIJf@shdLd@so?z6V- ztX(5a-^0@jja}oTKzSalefq3gb?6>+N@j)o`K~-uco%x--(0hRb#g>QJL0-h(Kj!d zA)6`ncDgo2X_sdcXl>>Zrq{1*RH)<=Y7e%8{Ms3oa1(otNvPIN-IjV(m z^eQWUY$WEd8mha8-V}Vt`BZxxLO7*It5tQFkI8yo#LXAQo}9>bvyo-xQ`;jc zs6%j7(k!F=@=E=DqG?w@#9!ZmALHx@-w3e4FTL6m__RILS+r8lXE^A`pW;7P*Rm4H z3JmL7yq6h=j2h+XLs>t+jq7=bwj!RJl?{m@-dcnfwk2)*b3=9=l=8TAuApIo<#Y!+D{26R{AFzIoRJstOr-^HQ-dNNi!gFV9ey^jFtj%BV>pxyjk#qzL!PsA0C)2vzVoDa_WuV7a-!L7| z&$CSFwHxjF{Z2>BtiUY24n@1qd&^aDS%Pj#&GM0Y)o7RbQ~!j0xhG1|m>REYJ=K`L zPLpIAQkPZYajZ3-B1^QhWtm0I$SS7C+i*VP;hB;wz_eEG*bnO;-din0y$*ZUV~aEXj=BhGT4p1@Z%)?JM}m0Go%3wAGp4eJEM3Jjl=sEnRw7}P z^W-y9YbjT`i)uN#4oT==4{gmX$h1jyuAa9kUSJ#vuiZ+UuYejlwf)EQZY5Yw#cjyj zq|w;;qSc$F)_d9r;|SHf2F7$7-bS5KZD&iPRZLS^#WdCSWhJClQo&xHkuc3Dw_-&u zZ7+SRz?-3cmd3&o?mfCSwyjYt(xSY^m>$gSvtqAL&rruznSPdY@A17Xerg(4s^nt3>=7AH|Jwo*KR4I?Hgs*4KIW>^ausx;%7we*67;KR$IdWuCFF zdKUSs<#{v-*P)x+tEF49AJ#6#cNyJU4Ju06#bVN@VqX2TSU41stuj+nGm7M5{rQSQ z-1p_tY)>__nEB{c`OdBXo??~WoOGMdAmz%%a<<}WULDGPTIaAR&850Iv2iqP3$Z>C zS+kOT|@xLnph3~}3)XqVGfd5{PfmAGlFziMih=%p2- zFx4lNv@B@WG)o>hV)rc;|HVR!x~w*_G=2 zTQ0At#}+@PMf2}SntMx2UPo%J?3>9Gqq}N)cdU7N z_%Tmv5lgI{)azIz@4f6j7q<2_ieIr`>&|hQr;kxHdhAN0+Rn-f^D>&X-m(gbl=~X4 zm4A*^@7#%u`yp{p{u8Wq=JWkq?O*QO$`P+TQPh7ndnhY;iI!gB2`m1*L>t`Sj53bo zlv-wVZ`T*A5BKvQQ#0b1&A)?7?ujOQ$h-l5U*VTglKVh#?Jf6u5Dp@pD&wiVm(}sw z<)}s?G4-#2(#rs+%f~@Xe=1{Iq>uS?>Y2860Bz$_dgbU_PNMe`^|ZZo2f=xFD|qQL zBcmdsA+Bnb*+|4`)W>uwmHS6NZL|Yfaqm1nt6)2}+=e%h=ZEMwYFGC4cZb%UFlD~% zCNz+GI334ZEwu;j^Q}jCVpL))D}Riw2e8?jxZ(sq&%o6l_ zs-CxO|KSw%4?qcH3+;gTk_x_6?djRBE$V0A2KL8@Q4d;QeAGsxb!fky*Rl3m^9H_s zh--JS7tRU%_5nDjf4YNy4sn(!ywSTtzmM+SIJ--)>bCVpYr`=mpSM`clWRo$ddnrp zRE#8~f^Arh_F-4%zp*nzEtOI85<62e z6X6q$r0P089ReZl7Rh|Y`ce+^-{_grHuDtT0wv6lC^iQcZYX#TBjRrVcTG(X3u{+)fS=-K<%DYnyl(iY+# z6-O_V(!Qd5<6a_}mi7|e8~390c%3NiCAwE_l9DN3=i&9p_V1OPC)GfC^Fe%v*}S~b zPi(eZD^K%`htTC?ShiAL;z4e?z5JNzY5sY)wL|XCEBpMV-`_m*6&AUoHHPv``9r){ z>|OlQ8hHJe_`ltbmYH>ScZB8o3GRQ!{YtpM-X^@Lc}PmbBUWeEYt7!3Z(pHJJVpPE zD$SL@f>2q-z(-H~rJWG2Ub33%ohk%cN4vpe5RRMxzt%CLP8|&}gHkY#<&etF%&5%T|yM2EIN$|a--E+AS*jVo-H{q=Nx!W`MA!ZgePtVM* z)Nbv#+aqH^zrRSTIsUz`G41f)S){yZM5aW+@TXo2+Wh__P%K(5yG#=cey=rPa>1NT zXs)x($X3iVt2e&^+vCn3cET)PV%ya!Y3@&C2D;JF#AJJ8GVO`J#Vm`&a#tD3$_J@LEXdV0@K zQ@V)L-v8b-gKzp$ow2M-Eqb+@k!F3D#eYn(;=f1T;rowOcW$&ER^CW^vD$O-Ugi3! zkMH{Jzi;1i{`$f3CdaGHD_D_|w}JaOGiT1hnm6-LR;QV9G5cWbe}TBo+OYq8eD;Z% z0mq`un{;P1d4JV(ZJC=AvvH4IH>b!+H;Sg3t*kENxDPo)~uZJ?%-fQ3H(am?&LrRr! z4Ydo-%diE>{BA=ZSW(?WzSrGTD59Skq|Gvw?wmSCTUu{;fLadii7OrG^`Eq(<1Tf6 zZ2SOJaZYNzLmfvX5f9yU3*)qT>ZVkxh9n))C#$YLgj8fEQ)&%Tsdx`u@;&VRQOfd~ zaii707wDCW1ykODXBTjoiU;4R=W;+E>j<@fyy`&X2r;7Q$ajX-o!s z-!`r#Cbnm!RAZ#h#Kmo8pR%t}j}hHH^_I_H>?h5mPjug~aWv zWL9e{ao_b;6Soud(2Xd3=aGNw5#M;kY)|A&U&gq|x->IC@mT#Rv1mTUm0#h!)v|d9 zchKe4vM(iP4)@TC`9*oZ(s$c;EB&N-3-480N8em=@)_>=c|$#CrojA>Z(7px5_f?|FK= zrHL}p^HKfMvO*tstP=SUHM~P)W=F{0$+zT#QbjyQ4nvM~1i_hdnT4R1Z6dDiW4?iW zQ7@)@#4cs3tJE~kF0Zv?4X&u%$0yEN96-lNHT&Idqd03i{QdxcMPhs#<`<{h%Qt52 zwAZl`b_}hNx+7(A1Svhic^R3c-qlm4d2~KjE5*@WWtpG6Uy1qTF|wAfr>~97<1zWT z#bhpOJ-vUgo<%Kj0Z)37mdaJg%*rmtUSk`zHTbehoO3!~wKn_O>KH4zTF#=xIwWZM zpSRJjkC?;iG)DP|?f1{;Dgs7q&RKa4=UWWti_mW&M*p<=S@T`^a-9X&_^2z|-fI3C zKR>~{7k`HLF#ZI`o}My`>&ADBHX7ylZaE(XqqyefQM-DAag(c9BnOaufM_!>xQV}q z&3CT+$3N(5Z&|y+RiVsVWTh{&LY=wd@ft=3Y)!HVZHpB;sq!4*3V)B+8IJjUJ)`?p zR?nx#KUTD!A=*bPaZDOo|0=12jMGo*%W<w0Vvh_K@vS^LKzB*QTeI;i>Uj&f_(V z3z$`36#8EO)FQm5nN4}mpQAc2k0Gq)kPx3_JBDBS_IG6k_z{l(6M8IK%qKkQo$lao zSFcqDd?yPf`3a)h4%Y2+1sgpc^L0v@-*xX?osTNDh!UE~UmhDnp0e-e#BZODoTP3h zmBQtpXwaP$NS7WH*HjPJ&d%~mt`C(rWyaUq`SEtU*V-preHgFL-f?dOm$AG=Nm)(3 zj&V2rC%>b{FlO;NL5^2-<)e)7((4WpY2~f2PlL*JWQ%Ou<{8vNhpJ2x593JUV?oVv zS9hpC`6wOHOG!oFd%JqAk>3JJv`pL4z-lO7BRTeFO+;thI4hKD+A1}YGc2qg@oC%n zbd&i@*XvSi#CFMxJ#^rZ8spdGHe&Dq| zfheH~TCHFL~P=Cp#EzNXp14a6@Q z!SLyt?wdV1wig78@aaq_uVnhvZ%|dy1UQ{&X`X@*z<9|Xiw8Vu7x;8 zw#xj3zIVAiWqZakuSc@xxT_Jvd0|BF2GHnYLOr0)m0vxNEX4LzBHYD`yG2A=8EINB zMyj_O_qnm9epAPL)1t1IWU5Q`Q6#Thx%j5iitqH)mHR%<%& z%v;Pu{W>T=g16d%ZC@mc!_OAhqRCvQ_IXcwHqHmpzfrDyT9==qr-tmB_u6Z2x+jZX zB7*SARz{KitXwI_`;hKdBG(7_{1JA7<@rZgLA!~gEv(}^UwO+K-CHdOpW!cO`lXh< z+r~%TtwD4!9=&qqAy-v$#*Fu>c5}5LD|YfcaqeE#?tbm~I$G5=5a~WQ+E;(YKX(*j zt&q)AbO#d9P4o%P6a9ag4S)iz=nBuGL{0RSvfy-v_X4+BtptZJ>HLWBFxtPHB0V zR+UUlYtB!VQ9G^eVS4WX#b3i}-c9tAar18bZOq9sb~SIG!~B&?n3}bT=t8}^i*+cE zkU{V>abR58g6`eMZ<(y-@3+qO3kZEq66e11faEt#er H$>;wEN_9g- diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java index 5a2d962881343019ea82053d97059f8967148254..7854467472179ab91e7d49cb2c49916f7cc279ba 100644 GIT binary patch literal 1901 zcmc&#-EZ135P#>dIOQcl3a+|6R+DN`Cat4nQl~xfVq(M0k~p&+I)?JU@0?F4=~%T% zLjrsszq|8&IcM=Vwh^H8hHTkNi#16V7YPxW)%%;#NT#{c7K~+9#lSz1SMST6m;tSq@InC32~dt@y=RqBnSItRcqj!s{U=0si* zJruA1`;oa*3uSR`o{!Dolr#fX?}NV?k@FRWIlg_Ns!jT@u3)a7gr3CMfRG4_8`ZR> zVTP|=(pXn*R9_V7>PY9>DO|&wx0e^mNqhgZRJaX_0axp5rCBV@N0HlL(0=;_5w#Ay z!&Id?%l5Fqha`mgd|Gds-wfXXJPiSB;h1cMea}*v?48k|-D>6N E7f4!5HUIzs literal 3936 zcmeH~O>fgc5QgWB#DB1INh(oSg(E_$6@oj59mt>x}u7@hRiX1~z5o z%3j)2d*bds6eGtwMaG2nE_WZvMTzHd_L-OTbLchBkQ76$uhRuU=N!2dl`D@5kI{ZkO-pU)jtr zefx=q)E-vP2%SUx({~Y-_uJ^dun)|hv(`iB!|Z5T(*YVzxe_9qTF0Sg3X&c}_b2>& zivFxZn{eD?wTmYvU^a2c`Qi{AydT;19Pbe{J9c-(B-hg}`?xier}c0((0pjm_--m|Jy$uY{-wAEsQd`JUQasz*W{@s&iF z^L0U)ojAJ5jIu>kR8{({oFGN-k&A-7QC`dJ2WuG-Q~gM>BE%;6#>Y{$WeUpjiqV3; z%q!`|XsZ^jW`C<-;|4bPoRI}LkAM^5L+EI(9Di|al5wiyibIjJJYS7A@dxgtz+IfX zn^WG-H3weJ*5kaWS(y>?BXHN{N0~3VMRTtIVX)l+L+Yn({H%U9vH$p1X6#sX6>j07 zJo{CFUvXbk_f&I)s)%P^5sNdvE>$B>+>z~5i`0*^3Q1L~o=X*NP|NMLE^-I-ggVqH z=++*JyUDEzD|+u@XTIYy&GP=2*KhO2zU#O}KU~`pR})Wns9HCmR%Za6O47Nnc3BnG z5i>(*bUqCJFYEVy>*6)_fhymx;vaR8Y6`WMj>&bYw?`DsokH~k^1hrQ#ezo^z)C$7am zub9{$BcnlGX*1TJqcZ-AI2Q5fBCDHE?Txcff0S2qTjh=A)1N;B{sA;-P>lcp From 26eb9be109cbbc907d638ea3bff6e493879b1386 Mon Sep 17 00:00:00 2001 From: Yizhang Cao Date: Mon, 3 Nov 2025 12:29:02 -0800 Subject: [PATCH 3/3] Fix EMPTY_AUTHOR test expectations and format CsvSource annotations --- .../jabref/model/entry/AuthorListTest.java | 1862 ++++++++--------- .../org/jabref/model/entry/AuthorTest.java | 98 +- 2 files changed, 980 insertions(+), 980 deletions(-) diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java index 9503a1a7228..aa3c6e1dab6 100644 --- a/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java +++ b/jablib/src/test/java/org/jabref/model/entry/AuthorListTest.java @@ -1,13 +1,5 @@ package org.jabref.model.entry; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotSame; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -17,935 +9,943 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * Other parsing tests are available in * {@link org.jabref.logic.importer.AuthorListParser AuthorListParser}. */ public class AuthorListTest { - /* - Examples are similar to page 4 in - [BibTeXing by Oren Patashnik](https://ctan.org/tex-archive/biblio/bibtex/contrib/doc/) - */ - private static final Author MUHAMMAD_ALKHWARIZMI = - new Author("Mu{\\d{h}}ammad", "M.", null, "al-Khw{\\={a}}rizm{\\={i}}", null); - private static final Author CORRADO_BOHM = - new Author("Corrado", "C.", null, "B{\\\"o}hm", null); - private static final Author KURT_GODEL = - new Author("Kurt", "K.", null, "G{\\\"{o}}del", null); - private static final Author BANU_MOSA = - new Author(null, null, null, "{The Ban\\={u} M\\={u}s\\={a} brothers}", null); - private static final AuthorList EMPTY_AUTHOR = AuthorList.of(List.of()); - private static final AuthorList ONE_AUTHOR_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI); - private static final AuthorList TWO_AUTHORS_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI, - CORRADO_BOHM); - private static final AuthorList THREE_AUTHORS_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI, - CORRADO_BOHM, KURT_GODEL); - private static final AuthorList ONE_INSTITUTION_WITH_LATEX = AuthorList.of(BANU_MOSA); - private static final AuthorList ONE_INSTITUTION_WITH_STARTING_PARANTHESIS = AuthorList.of( - new Author( - null, null, null, "{{\\L{}}ukasz Micha\\l{}}", null)); - private static final AuthorList TWO_INSTITUTIONS_WITH_LATEX = AuthorList.of(BANU_MOSA, BANU_MOSA); - private static final AuthorList MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX = AuthorList.of(BANU_MOSA, - CORRADO_BOHM); - - public static int size(String bibtex) { - return AuthorList.parse(bibtex).getNumberOfAuthors(); - } - - @ParameterizedTest - @CsvSource({ - "'', ''", - "'John Smith', 'Smith'", - "'John Smith and Black Brown, Peter', 'Smith and Black Brown'", - "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann et al.'" - }) - void fixAuthorNatbib(String input, String expected) { - assertEquals(expected, AuthorList.fixAuthorNatbib(input)); - } - - @ParameterizedTest - @CsvSource(value = { - // LaTeX-free empty author string - "EMPTY_AUTHOR|", - // LaTeX-free Unicode one author name from LaTeX - "ONE_AUTHOR_WITH_LATEX|al-Khwārizmī", - // LaTeX-free Unicode two author names from LaTeX - "TWO_AUTHORS_WITH_LATEX|al-Khwārizmī and Böhm", - // LaTeX-free Unicode author et al from LaTeX - "THREE_AUTHORS_WITH_LATEX|al-Khwārizmī et al.", - // LaTeX-free Unicode one institution name from LaTeX - "ONE_INSTITUTION_WITH_LATEX|The Banū Mūsā brothers", - // LaTeX-free Unicode two institution names from LaTeX - "TWO_INSTITUTIONS_WITH_LATEX|The Banū Mūsā brothers and The Banū Mūsā brothers", - // LaTeX-free Unicode mixed authors from LaTeX - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|The Banū Mūsā brothers and Böhm", - // LaTeX-free one institution with parenthesis at start - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|Łukasz Michał" - }, delimiter = '|') - void getAsNatbibLatexFree(String authorListName, String expected) { - AuthorList authorList = getAuthorListByName(authorListName); - assertEquals(expected, authorList.latexFree().getAsNatbib()); - } - - @Test - void parseCachesOneAuthor() { - // Test caching in authorCache. - AuthorList authorList = AuthorList.parse("John Smith"); - assertSame(authorList, AuthorList.parse("John Smith")); - assertNotSame(authorList, AuthorList.parse("Smith")); - } - - @Test - void parseCachesOneLatexFreeAuthor() { - // Test caching in authorCache. - AuthorList authorList = AuthorList.parse("John Smith").latexFree(); - assertSame(authorList, AuthorList.parse("John Smith").latexFree()); - assertNotSame(authorList, AuthorList.parse("Smith").latexFree()); - } - - @ParameterizedTest - @CsvSource({ - // No authors - "'', '', true, false", - "'', '', false, false", - - // One author - "'John Smith', 'John Smith', false, false", - "'John Smith', 'J. Smith', true, false", - - // Two authors - "'John Smith and Black Brown, Peter', 'John Smith and Peter Black Brown', false, false", - "'John Smith and Black Brown, Peter', 'J. Smith and P. Black Brown', true, false", - - // Oxford comma = true - "'', '', true, true", - "'', '', false, true", - "'John Smith', 'John Smith', false, true", - "'John Smith', 'J. Smith', true, true", - "'John Smith and Black Brown, Peter', 'John Smith and Peter Black Brown', false, true", - "'John Smith and Black Brown, Peter', 'J. Smith and P. Black Brown', true, true" - }) - void fixAuthorFirstNameFirstCommas(String input, String expected, boolean abbreviate, - boolean oxford) { - assertEquals(expected, AuthorList.fixAuthorFirstNameFirstCommas(input, abbreviate, oxford)); - } - - @ParameterizedTest - @CsvSource(value = { - // Empty author string for empty input abbreviate - "EMPTY_AUTHOR|true|false|", - // Unicode one author name from LaTeX abbreviate - "ONE_AUTHOR_WITH_LATEX|true|false|M. al-Khwārizmī", - // Unicode two author names from LaTeX abbreviate - "TWO_AUTHORS_WITH_LATEX|true|false|M. al-Khwārizmī and C. Böhm", - // Unicode two author names from LaTeX abbreviate and Oxford comma - "TWO_AUTHORS_WITH_LATEX|true|true|M. al-Khwārizmī and C. Böhm", - // Three Unicode authors from LaTeX abbreviate - "THREE_AUTHORS_WITH_LATEX|true|false|M. al-Khwārizmī, C. Böhm and K. Gödel", - // Three Unicode authors from LaTeX abbreviate and Oxford comma - "THREE_AUTHORS_WITH_LATEX|true|true|M. al-Khwārizmī, C. Böhm, and K. Gödel", - // Unicode one institution name from LaTeX abbreviate - "ONE_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX abbreviate - "TWO_INSTITUTIONS_WITH_LATEX|true|false|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX abbreviate - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers and C. Böhm", - // One institution with parenthesis at start abbreviate - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|false|Łukasz Michał", - // Empty author string for empty input - "EMPTY_AUTHOR|false|false|", - // Unicode one author name from LaTeX - "ONE_AUTHOR_WITH_LATEX|false|false|Muḥammad al-Khwārizmī", - // Unicode two author names from LaTeX - "TWO_AUTHORS_WITH_LATEX|false|false|Muḥammad al-Khwārizmī and Corrado Böhm", - // Three Unicode authors from LaTeX - "THREE_AUTHORS_WITH_LATEX|false|false|Muḥammad al-Khwārizmī, Corrado Böhm and Kurt Gödel", - // Unicode one institution name from LaTeX - "ONE_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX - "TWO_INSTITUTIONS_WITH_LATEX|false|false|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers and Corrado Böhm", - // One institution with parenthesis at start - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|false|Łukasz Michał" - }, delimiter = '|') - void getAsFirstLastNamesLatexFree(String authorListName, boolean abbreviate, boolean oxford, String expected) { - AuthorList authorList = getAuthorListByName(authorListName); - assertEquals(expected, authorList.latexFree().getAsFirstLastNames(abbreviate, oxford)); - } - - @ParameterizedTest - @CsvSource({ - "'John Smith', 'Smith, John', false", - "'John Smith', 'Smith, J.', true", - "'John Smith and Black Brown, Peter', 'Smith, John and Black Brown, Peter', false", - "'John Smith and Black Brown, Peter', 'Smith, J. and Black Brown, P.', true", - "'John Peter von Neumann', 'von Neumann, J. P.', true" - }) - void fixAuthorLastNameFirstCommasnoOxford(String input, String expected, boolean abbreviate) { - assertEquals(expected, AuthorList.fixAuthorLastNameFirstCommas(input, abbreviate, false)); - } - - @ParameterizedTest - @CsvSource({ - "'John Smith', 'Smith, John', false", - "'John Smith', 'Smith, J.', true", - "'John Smith and Black Brown, Peter', 'Smith, John and Black Brown, Peter', false", - "'John Smith and Black Brown, Peter', 'Smith, J. and Black Brown, P.', true", - "'John Peter von Neumann', 'von Neumann, J. P.', true" - }) - void fixAuthorLastNameFirstCommasoxford(String input, String expected, boolean abbreviate) { - assertEquals(expected, AuthorList.fixAuthorLastNameFirstCommas(input, abbreviate, true)); - } - - @ParameterizedTest - @CsvSource(value = { - // Empty author string for empty input abbreviate - "EMPTY_AUTHOR|true|false|", - // Unicode one author name from LaTeX abbreviate - "ONE_AUTHOR_WITH_LATEX|true|false|al-Khwārizmī, M.", - // Unicode two author names from LaTeX abbreviate - "TWO_AUTHORS_WITH_LATEX|true|false|al-Khwārizmī, M. and Böhm, C.", - // Three Unicode authors from LaTeX abbreviate - "THREE_AUTHORS_WITH_LATEX|true|false|al-Khwārizmī, M., Böhm, C. and Gödel, K.", - // Unicode one institution name from LaTeX abbreviate - "ONE_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX abbreviate - "TWO_INSTITUTIONS_WITH_LATEX|true|false|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX abbreviate - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers and Böhm, C.", - // One institution with parenthesis at start abbreviate - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|false|Łukasz Michał", - // Empty author string for empty input - "EMPTY_AUTHOR|false|false|", - // Unicode one author name from LaTeX - "ONE_AUTHOR_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad", - // Unicode two author names from LaTeX - "TWO_AUTHORS_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad and Böhm, Corrado", - // Three Unicode authors from LaTeX - "THREE_AUTHORS_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad, Böhm, Corrado and Gödel, Kurt", - // Unicode one institution name from LaTeX - "ONE_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX - "TWO_INSTITUTIONS_WITH_LATEX|false|false|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers and Böhm, Corrado", - // One institution with parenthesis at start - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|false|Łukasz Michał", - // Empty author string for empty input abbreviate Oxford comma - "EMPTY_AUTHOR|true|true|", - // Unicode one author name from LaTeX abbreviate Oxford comma - "ONE_AUTHOR_WITH_LATEX|true|true|al-Khwārizmī, M.", - // Unicode two author names from LaTeX abbreviate Oxford comma - "TWO_AUTHORS_WITH_LATEX|true|true|al-Khwārizmī, M. and Böhm, C.", - // Three Unicode authors from LaTeX abbreviate Oxford comma - "THREE_AUTHORS_WITH_LATEX|true|true|al-Khwārizmī, M., Böhm, C., and Gödel, K.", - // Unicode one institution name from LaTeX abbreviate Oxford comma - "ONE_INSTITUTION_WITH_LATEX|true|true|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX abbreviate Oxford comma - "TWO_INSTITUTIONS_WITH_LATEX|true|true|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX abbreviate Oxford comma - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|true|The Banū Mūsā brothers and Böhm, C.", - // One institution with parenthesis at start abbreviate Oxford comma - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|true|Łukasz Michał", - // Empty author string for empty input Oxford comma - "EMPTY_AUTHOR|false|true|", - // Unicode one author name from LaTeX Oxford comma - "ONE_AUTHOR_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad", - // Unicode two author names from LaTeX Oxford comma - "TWO_AUTHORS_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad and Böhm, Corrado", - // Three Unicode authors from LaTeX Oxford comma - "THREE_AUTHORS_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad, Böhm, Corrado, and Gödel, Kurt", - // Unicode one institution name from LaTeX Oxford comma - "ONE_INSTITUTION_WITH_LATEX|false|true|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX Oxford comma - "TWO_INSTITUTIONS_WITH_LATEX|false|true|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX Oxford comma - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|true|The Banū Mūsā brothers and Böhm, Corrado", - // One institution with parenthesis at start Oxford comma - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|true|Łukasz Michał" - }, delimiter = '|') - void getAsLastFirstNamesLatexFree(String authorListName, boolean abbreviate, boolean oxford, String expected) { - AuthorList authorList = getAuthorListByName(authorListName); - assertEquals(expected, authorList.latexFree().getAsLastFirstNames(abbreviate, oxford)); - } - - @Test - void fixAuthorLastNameFirst() { - // Test helper method - - assertEquals("Smith, John", AuthorList.fixAuthorLastNameFirst("John Smith")); - - assertEquals("Smith, John and Black Brown, Peter", AuthorList - .fixAuthorLastNameFirst("John Smith and Black Brown, Peter")); - - assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter")); - - assertEquals("von Last, Jr, First", AuthorList - .fixAuthorLastNameFirst("von Last, Jr ,First")); - - assertEquals(AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter"), - AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter")); - - // Test Abbreviation == false - assertEquals("Smith, John", AuthorList.fixAuthorLastNameFirst("John Smith", false)); - - assertEquals("Smith, John and Black Brown, Peter", AuthorList.fixAuthorLastNameFirst( - "John Smith and Black Brown, Peter", false)); - - assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", - false)); - - assertEquals("von Last, Jr, First", AuthorList.fixAuthorLastNameFirst( - "von Last, Jr ,First", false)); - - assertEquals(AuthorList.fixAuthorLastNameFirst( - "John von Neumann and John Smith and Black Brown, Peter", false), AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", false)); - - // Test Abbreviate == true - assertEquals("Smith, J.", AuthorList.fixAuthorLastNameFirst("John Smith", true)); - - assertEquals("Smith, J. and Black Brown, P.", AuthorList.fixAuthorLastNameFirst( - "John Smith and Black Brown, Peter", true)); - - assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.", - AuthorList.fixAuthorLastNameFirst( - "John von Neumann and John Smith and Black Brown, Peter", true)); - - assertEquals("von Last, Jr, F.", AuthorList.fixAuthorLastNameFirst("von Last, Jr ,First", - true)); - - assertEquals(AuthorList.fixAuthorLastNameFirst( - "John von Neumann and John Smith and Black Brown, Peter", true), AuthorList - .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", true)); - } - - @ParameterizedTest - @CsvSource({ - // Oxford comma = false - "'', '', false", - "'John Smith', 'Smith', false", - "'Smith, Jr, John', 'Smith', false", - "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann, Smith and Black Brown', false", - - // Oxford comma = true - "'', '', true", - "'John Smith', 'Smith', true", - "'Smith, Jr, John', 'Smith', true", - "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann, Smith, and Black Brown', true" - }) - void fixAuthorLastNameOnlyCommas(String input, String expected, boolean oxford) { - assertEquals(expected, AuthorList.fixAuthorLastNameOnlyCommas(input, oxford)); - } - - @ParameterizedTest - @CsvSource(value = { - // Unicode one author name from LaTeX - "ONE_AUTHOR_WITH_LATEX|false|al-Khwārizmī", - // Unicode two author names from LaTeX - "TWO_AUTHORS_WITH_LATEX|false|al-Khwārizmī and Böhm", - // Unicode two author names from LaTeX using Oxford comma - "TWO_AUTHORS_WITH_LATEX|true|al-Khwārizmī and Böhm", - // Unicode three authors from LaTeX - "THREE_AUTHORS_WITH_LATEX|false|al-Khwārizmī, Böhm and Gödel", - // Unicode three authors from LaTeX using Oxford comma - "THREE_AUTHORS_WITH_LATEX|true|al-Khwārizmī, Böhm, and Gödel", - // Unicode one institution name from LaTeX - "ONE_INSTITUTION_WITH_LATEX|false|The Banū Mūsā brothers", - // Unicode two institution names from LaTeX - "TWO_INSTITUTIONS_WITH_LATEX|false|The Banū Mūsā brothers and The Banū Mūsā brothers", - // Unicode mixed authors from LaTeX - "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|The Banū Mūsā brothers and Böhm", - // One institution with parenthesis at start - "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|Łukasz Michał" - }, delimiter = '|') - void getAsLastNamesLatexFree(String authorListName, boolean oxfordComma, String expected) { - AuthorList authorList = getAuthorListByName(authorListName); - assertEquals(expected, authorList.latexFree().getAsLastNames(oxfordComma)); - } - - @Test - void fixAuthorForAlphabetization() { - assertEquals("Smith, J.", AuthorList.fixAuthorForAlphabetization("John Smith")); - assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("John von Neumann")); - assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("J. von Neumann")); - assertEquals( - "Neumann, J. and Smith, J. and Black Brown, Jr., P.", - AuthorList - .fixAuthorForAlphabetization( - "John von Neumann and John Smith and de Black Brown, Jr., Peter")); - } - - @Test - void size() { - assertEquals(0, AuthorListTest.size("")); - assertEquals(1, AuthorListTest.size("Bar")); - assertEquals(1, AuthorListTest.size("Foo Bar")); - assertEquals(1, AuthorListTest.size("Foo von Bar")); - assertEquals(1, AuthorListTest.size("von Bar, Foo")); - assertEquals(1, AuthorListTest.size("Bar, Foo")); - assertEquals(1, AuthorListTest.size("Bar, Jr., Foo")); - assertEquals(1, AuthorListTest.size("Bar, Foo")); - assertEquals(2, AuthorListTest.size("John Neumann and Foo Bar")); - assertEquals(2, AuthorListTest.size("John von Neumann and Bar, Jr, Foo")); - - assertEquals(3, AuthorListTest.size("John von Neumann and John Smith and Black Brown, Peter")); - - StringBuilder s = new StringBuilder("John von Neumann"); - for (int i = 0; i < 25; i++) { - assertEquals(i + 1, AuthorListTest.size(s.toString())); - s.append(" and Albert Einstein"); - } - } - - @Test - void isEmpty() { - assertTrue(AuthorList.parse("").isEmpty()); - assertFalse(AuthorList.parse("Bar").isEmpty()); - } - - @Test - void getEmptyAuthor() { - assertThrows(Exception.class, () -> AuthorList.parse("").getAuthor(0)); - } - - @Test - void getAuthor() { - Author author = AuthorList.parse("John Smith and von Neumann, Jr, John").getAuthor(0); - assertEquals(Optional.of("John"), author.getGivenName()); - assertEquals(Optional.of("J."), author.getGivenNameAbbreviated()); - assertEquals("John Smith", author.getGivenFamily(false)); - assertEquals("J. Smith", author.getGivenFamily(true)); - assertEquals(Optional.empty(), author.getNameSuffix()); - assertEquals(Optional.of("Smith"), author.getFamilyName()); - assertEquals("Smith, John", author.getFamilyGiven(false)); - assertEquals("Smith, J.", author.getFamilyGiven(true)); - assertEquals("Smith", author.getNamePrefixAndFamilyName()); - assertEquals("Smith, J.", author.getNameForAlphabetization()); - assertEquals(Optional.empty(), author.getNamePrefix()); - - author = AuthorList.parse("Peter Black Brown").getAuthor(0); - assertEquals(Optional.of("Peter Black"), author.getGivenName()); - assertEquals(Optional.of("P. B."), author.getGivenNameAbbreviated()); - assertEquals("Peter Black Brown", author.getGivenFamily(false)); - assertEquals("P. B. Brown", author.getGivenFamily(true)); - assertEquals(Optional.empty(), author.getNameSuffix()); - assertEquals(Optional.empty(), author.getNamePrefix()); - - author = AuthorList.parse("John Smith and von Neumann, Jr, John").getAuthor(1); - assertEquals(Optional.of("John"), author.getGivenName()); - assertEquals(Optional.of("J."), author.getGivenNameAbbreviated()); - assertEquals("John von Neumann, Jr", author.getGivenFamily(false)); - assertEquals("J. von Neumann, Jr", author.getGivenFamily(true)); - assertEquals(Optional.of("Jr"), author.getNameSuffix()); - assertEquals(Optional.of("Neumann"), author.getFamilyName()); - assertEquals("von Neumann, Jr, John", author.getFamilyGiven(false)); - assertEquals("von Neumann, Jr, J.", author.getFamilyGiven(true)); - assertEquals("von Neumann", author.getNamePrefixAndFamilyName()); - assertEquals("Neumann, Jr, J.", author.getNameForAlphabetization()); - assertEquals(Optional.of("von"), author.getNamePrefix()); - } - - @Test - void companyAuthor() { - Author author = AuthorList.parse("{JabRef Developers}").getAuthor(0); - Author expected = new Author(null, null, null, "{JabRef Developers}", null); - assertEquals(expected, author); - } - - @Test - void companyAuthorAndPerson() { - Author company = new Author(null, null, null, "{JabRef Developers}", null); - Author person = new Author("Stefan", "S.", null, "Kolb", null); - assertEquals(Arrays.asList(company, person), - AuthorList.parse("{JabRef Developers} and Stefan Kolb").getAuthors()); - } - - @Test - void companyAuthorWithLowerCaseWord() { - Author author = AuthorList.parse("{JabRef Developers on Fire}").getAuthor(0); - Author expected = new Author(null, null, null, "{JabRef Developers on Fire}", null); - assertEquals(expected, author); - } - - @Test - void abbreviationWithRelax() { - Author author = AuthorList.parse("{\\relax Ch}ristoph Cholera").getAuthor(0); - Author expected = new Author("{\\relax Ch}ristoph", "{\\relax Ch}.", null, "Cholera", null); - assertEquals(expected, author); - } - - @Test - void getAuthorsNatbib() { - assertEquals("", AuthorList.parse("").getAsNatbib()); - assertEquals("Smith", AuthorList.parse("John Smith").getAsNatbib()); - assertEquals("Smith and Black Brown", AuthorList.parse( - "John Smith and Black Brown, Peter").getAsNatbib()); - assertEquals("von Neumann et al.", AuthorList.parse( - "John von Neumann and John Smith and Black Brown, Peter").getAsNatbib()); - /* - * [ 1465610 ] (Double-)Names containing hyphen (-) not handled correctly + Examples are similar to page 4 in + [BibTeXing by Oren Patashnik](https://ctan.org/tex-archive/biblio/bibtex/contrib/doc/) + */ + private static final Author MUHAMMAD_ALKHWARIZMI = + new Author("Mu{\\d{h}}ammad", "M.", null, "al-Khw{\\={a}}rizm{\\={i}}", null); + private static final Author CORRADO_BOHM = + new Author("Corrado", "C.", null, "B{\\\"o}hm", null); + private static final Author KURT_GODEL = + new Author("Kurt", "K.", null, "G{\\\"{o}}del", null); + private static final Author BANU_MOSA = + new Author(null, null, null, "{The Ban\\={u} M\\={u}s\\={a} brothers}", null); + private static final AuthorList EMPTY_AUTHOR = AuthorList.of(List.of()); + private static final AuthorList ONE_AUTHOR_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI); + private static final AuthorList TWO_AUTHORS_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI, + CORRADO_BOHM); + private static final AuthorList THREE_AUTHORS_WITH_LATEX = AuthorList.of(MUHAMMAD_ALKHWARIZMI, + CORRADO_BOHM, KURT_GODEL); + private static final AuthorList ONE_INSTITUTION_WITH_LATEX = AuthorList.of(BANU_MOSA); + private static final AuthorList ONE_INSTITUTION_WITH_STARTING_PARANTHESIS = AuthorList.of( + new Author( + null, null, null, "{{\\L{}}ukasz Micha\\l{}}", null)); + private static final AuthorList TWO_INSTITUTIONS_WITH_LATEX = AuthorList.of(BANU_MOSA, BANU_MOSA); + private static final AuthorList MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX = AuthorList.of(BANU_MOSA, + CORRADO_BOHM); + + public static int size(String bibtex) { + return AuthorList.parse(bibtex).getNumberOfAuthors(); + } + + @ParameterizedTest + @CsvSource({ + "'', ''", + "'John Smith', 'Smith'", + "'John Smith and Black Brown, Peter', 'Smith and Black Brown'", + "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann et al.'" + }) + void fixAuthorNatbib(String input, String expected) { + assertEquals(expected, AuthorList.fixAuthorNatbib(input)); + } + + @ParameterizedTest + @CsvSource(value = { + // LaTeX-free empty author string + "EMPTY_AUTHOR|''", + // LaTeX-free Unicode one author name from LaTeX + "ONE_AUTHOR_WITH_LATEX|al-Khwārizmī", + // LaTeX-free Unicode two author names from LaTeX + "TWO_AUTHORS_WITH_LATEX|al-Khwārizmī and Böhm", + // LaTeX-free Unicode author et al from LaTeX + "THREE_AUTHORS_WITH_LATEX|al-Khwārizmī et al.", + // LaTeX-free Unicode one institution name from LaTeX + "ONE_INSTITUTION_WITH_LATEX|The Banū Mūsā brothers", + // LaTeX-free Unicode two institution names from LaTeX + "TWO_INSTITUTIONS_WITH_LATEX|The Banū Mūsā brothers and The Banū Mūsā brothers", + // LaTeX-free Unicode mixed authors from LaTeX + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|The Banū Mūsā brothers and Böhm", + // LaTeX-free one institution with parenthesis at start + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|Łukasz Michał" + }, delimiter = '|') + void getAsNatbibLatexFree(String authorListName, String expected) { + AuthorList authorList = getAuthorListByName(authorListName); + assertEquals(expected, authorList.latexFree().getAsNatbib()); + } + + @Test + void parseCachesOneAuthor() { + // Test caching in authorCache. + AuthorList authorList = AuthorList.parse("John Smith"); + assertSame(authorList, AuthorList.parse("John Smith")); + assertNotSame(authorList, AuthorList.parse("Smith")); + } + + @Test + void parseCachesOneLatexFreeAuthor() { + // Test caching in authorCache. + AuthorList authorList = AuthorList.parse("John Smith").latexFree(); + assertSame(authorList, AuthorList.parse("John Smith").latexFree()); + assertNotSame(authorList, AuthorList.parse("Smith").latexFree()); + } + + @ParameterizedTest + @CsvSource({ + // No authors + "'', '', true, false", + "'', '', false, false", + + // One author + "'John Smith', 'John Smith', false, false", + "'John Smith', 'J. Smith', true, false", + + // Two authors + "'John Smith and Black Brown, Peter', 'John Smith and Peter Black Brown', false, false", + "'John Smith and Black Brown, Peter', 'J. Smith and P. Black Brown', true, false", + + // Oxford comma = true + "'', '', true, true", + "'', '', false, true", + "'John Smith', 'John Smith', false, true", + "'John Smith', 'J. Smith', true, true", + "'John Smith and Black Brown, Peter', 'John Smith and Peter Black Brown', false, true", + "'John Smith and Black Brown, Peter', 'J. Smith and P. Black Brown', true, true" + }) + void fixAuthorFirstNameFirstCommas(String input, String expected, boolean abbreviate, + boolean oxford) { + assertEquals(expected, AuthorList.fixAuthorFirstNameFirstCommas(input, abbreviate, oxford)); + } + + @ParameterizedTest + @CsvSource(value = { + // Empty author string for empty input abbreviate + "EMPTY_AUTHOR|true|false|''", + // Unicode one author name from LaTeX abbreviate + "ONE_AUTHOR_WITH_LATEX|true|false|M. al-Khwārizmī", + // Unicode two author names from LaTeX abbreviate + "TWO_AUTHORS_WITH_LATEX|true|false|M. al-Khwārizmī and C. Böhm", + // Unicode two author names from LaTeX abbreviate and Oxford comma + "TWO_AUTHORS_WITH_LATEX|true|true|M. al-Khwārizmī and C. Böhm", + // Three Unicode authors from LaTeX abbreviate + "THREE_AUTHORS_WITH_LATEX|true|false|M. al-Khwārizmī, C. Böhm and K. Gödel", + // Three Unicode authors from LaTeX abbreviate and Oxford comma + "THREE_AUTHORS_WITH_LATEX|true|true|M. al-Khwārizmī, C. Böhm, and K. Gödel", + // Unicode one institution name from LaTeX abbreviate + "ONE_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX abbreviate + "TWO_INSTITUTIONS_WITH_LATEX|true|false|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX abbreviate + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers and C. Böhm", + // One institution with parenthesis at start abbreviate + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|false|Łukasz Michał", + // Empty author string for empty input + "EMPTY_AUTHOR|false|false|''", + // Unicode one author name from LaTeX + "ONE_AUTHOR_WITH_LATEX|false|false|Muḥammad al-Khwārizmī", + // Unicode two author names from LaTeX + "TWO_AUTHORS_WITH_LATEX|false|false|Muḥammad al-Khwārizmī and Corrado Böhm", + // Three Unicode authors from LaTeX + "THREE_AUTHORS_WITH_LATEX|false|false|Muḥammad al-Khwārizmī, Corrado Böhm and Kurt Gödel", + // Unicode one institution name from LaTeX + "ONE_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX + "TWO_INSTITUTIONS_WITH_LATEX|false|false|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers and Corrado Böhm", + // One institution with parenthesis at start + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|false|Łukasz Michał" + }, delimiter = '|') + void getAsFirstLastNamesLatexFree(String authorListName, boolean abbreviate, boolean oxford, String expected) { + AuthorList authorList = getAuthorListByName(authorListName); + assertEquals(expected, authorList.latexFree().getAsFirstLastNames(abbreviate, oxford)); + } + + @ParameterizedTest + @CsvSource({ + "'John Smith', 'Smith, John', false", + "'John Smith', 'Smith, J.', true", + "'John Smith and Black Brown, Peter', 'Smith, John and Black Brown, Peter', false", + "'John Smith and Black Brown, Peter', 'Smith, J. and Black Brown, P.', true", + "'John Peter von Neumann', 'von Neumann, J. P.', true" + }) + void fixAuthorLastNameFirstCommasnoOxford(String input, String expected, boolean abbreviate) { + assertEquals(expected, AuthorList.fixAuthorLastNameFirstCommas(input, abbreviate, false)); + } + + @ParameterizedTest + @CsvSource({ + "'John Smith', 'Smith, John', false", + "'John Smith', 'Smith, J.', true", + "'John Smith and Black Brown, Peter', 'Smith, John and Black Brown, Peter', false", + "'John Smith and Black Brown, Peter', 'Smith, J. and Black Brown, P.', true", + "'John Peter von Neumann', 'von Neumann, J. P.', true" + }) + void fixAuthorLastNameFirstCommasoxford(String input, String expected, boolean abbreviate) { + assertEquals(expected, AuthorList.fixAuthorLastNameFirstCommas(input, abbreviate, true)); + } + + @ParameterizedTest + @CsvSource(value = { + // Empty author string for empty input abbreviate + "EMPTY_AUTHOR|true|false|''", + // Unicode one author name from LaTeX abbreviate + "ONE_AUTHOR_WITH_LATEX|true|false|al-Khwārizmī, M.", + // Unicode two author names from LaTeX abbreviate + "TWO_AUTHORS_WITH_LATEX|true|false|al-Khwārizmī, M. and Böhm, C.", + // Three Unicode authors from LaTeX abbreviate + "THREE_AUTHORS_WITH_LATEX|true|false|al-Khwārizmī, M., Böhm, C. and Gödel, K.", + // Unicode one institution name from LaTeX abbreviate + "ONE_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX abbreviate + "TWO_INSTITUTIONS_WITH_LATEX|true|false|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX abbreviate + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|false|The Banū Mūsā brothers and Böhm, C.", + // One institution with parenthesis at start abbreviate + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|false|Łukasz Michał", + // Empty author string for empty input + "EMPTY_AUTHOR|false|false|''", + // Unicode one author name from LaTeX + "ONE_AUTHOR_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad", + // Unicode two author names from LaTeX + "TWO_AUTHORS_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad and Böhm, Corrado", + // Three Unicode authors from LaTeX + "THREE_AUTHORS_WITH_LATEX|false|false|al-Khwārizmī, Muḥammad, Böhm, Corrado and Gödel, Kurt", + // Unicode one institution name from LaTeX + "ONE_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX + "TWO_INSTITUTIONS_WITH_LATEX|false|false|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|false|The Banū Mūsā brothers and Böhm, Corrado", + // One institution with parenthesis at start + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|false|Łukasz Michał", + // Empty author string for empty input abbreviate Oxford comma + "EMPTY_AUTHOR|true|true|''", + // Unicode one author name from LaTeX abbreviate Oxford comma + "ONE_AUTHOR_WITH_LATEX|true|true|al-Khwārizmī, M.", + // Unicode two author names from LaTeX abbreviate Oxford comma + "TWO_AUTHORS_WITH_LATEX|true|true|al-Khwārizmī, M. and Böhm, C.", + // Three Unicode authors from LaTeX abbreviate Oxford comma + "THREE_AUTHORS_WITH_LATEX|true|true|al-Khwārizmī, M., Böhm, C., and Gödel, K.", + // Unicode one institution name from LaTeX abbreviate Oxford comma + "ONE_INSTITUTION_WITH_LATEX|true|true|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX abbreviate Oxford comma + "TWO_INSTITUTIONS_WITH_LATEX|true|true|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX abbreviate Oxford comma + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|true|true|The Banū Mūsā brothers and Böhm, C.", + // One institution with parenthesis at start abbreviate Oxford comma + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|true|true|Łukasz Michał", + // Empty author string for empty input Oxford comma + "EMPTY_AUTHOR|false|true|''", + // Unicode one author name from LaTeX Oxford comma + "ONE_AUTHOR_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad", + // Unicode two author names from LaTeX Oxford comma + "TWO_AUTHORS_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad and Böhm, Corrado", + // Three Unicode authors from LaTeX Oxford comma + "THREE_AUTHORS_WITH_LATEX|false|true|al-Khwārizmī, Muḥammad, Böhm, Corrado, and Gödel, Kurt", + // Unicode one institution name from LaTeX Oxford comma + "ONE_INSTITUTION_WITH_LATEX|false|true|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX Oxford comma + "TWO_INSTITUTIONS_WITH_LATEX|false|true|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX Oxford comma + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|true|The Banū Mūsā brothers and Böhm, Corrado", + // One institution with parenthesis at start Oxford comma + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|true|Łukasz Michał" + }, delimiter = '|') + void getAsLastFirstNamesLatexFree(String authorListName, boolean abbreviate, boolean oxford, String expected) { + AuthorList authorList = getAuthorListByName(authorListName); + assertEquals(expected, authorList.latexFree().getAsLastFirstNames(abbreviate, oxford)); + } + + @Test + void fixAuthorLastNameFirst() { + // Test helper method + + assertEquals("Smith, John", AuthorList.fixAuthorLastNameFirst("John Smith")); + + assertEquals("Smith, John and Black Brown, Peter", AuthorList + .fixAuthorLastNameFirst("John Smith and Black Brown, Peter")); + + assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter")); + + assertEquals("von Last, Jr, First", AuthorList + .fixAuthorLastNameFirst("von Last, Jr ,First")); + + assertEquals(AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter"), + AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter")); + + // Test Abbreviation == false + assertEquals("Smith, John", AuthorList.fixAuthorLastNameFirst("John Smith", false)); + + assertEquals("Smith, John and Black Brown, Peter", AuthorList.fixAuthorLastNameFirst( + "John Smith and Black Brown, Peter", false)); + + assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", + false)); + + assertEquals("von Last, Jr, First", AuthorList.fixAuthorLastNameFirst( + "von Last, Jr ,First", false)); + + assertEquals(AuthorList.fixAuthorLastNameFirst( + "John von Neumann and John Smith and Black Brown, Peter", false), AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", false)); + + // Test Abbreviate == true + assertEquals("Smith, J.", AuthorList.fixAuthorLastNameFirst("John Smith", true)); + + assertEquals("Smith, J. and Black Brown, P.", AuthorList.fixAuthorLastNameFirst( + "John Smith and Black Brown, Peter", true)); + + assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.", + AuthorList.fixAuthorLastNameFirst( + "John von Neumann and John Smith and Black Brown, Peter", true)); + + assertEquals("von Last, Jr, F.", AuthorList.fixAuthorLastNameFirst("von Last, Jr ,First", + true)); + + assertEquals(AuthorList.fixAuthorLastNameFirst( + "John von Neumann and John Smith and Black Brown, Peter", true), AuthorList + .fixAuthorLastNameFirst("John von Neumann and John Smith and Black Brown, Peter", true)); + } + + @ParameterizedTest + @CsvSource({ + // Oxford comma = false + "'', '', false", + "'John Smith', 'Smith', false", + "'Smith, Jr, John', 'Smith', false", + "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann, Smith and Black Brown', false", + + // Oxford comma = true + "'', '', true", + "'John Smith', 'Smith', true", + "'Smith, Jr, John', 'Smith', true", + "'John von Neumann and John Smith and Black Brown, Peter', 'von Neumann, Smith, and Black Brown', true" + }) + void fixAuthorLastNameOnlyCommas(String input, String expected, boolean oxford) { + assertEquals(expected, AuthorList.fixAuthorLastNameOnlyCommas(input, oxford)); + } + + @ParameterizedTest + @CsvSource(value = { + // Unicode one author name from LaTeX + "ONE_AUTHOR_WITH_LATEX|false|al-Khwārizmī", + // Unicode two author names from LaTeX + "TWO_AUTHORS_WITH_LATEX|false|al-Khwārizmī and Böhm", + // Unicode two author names from LaTeX using Oxford comma + "TWO_AUTHORS_WITH_LATEX|true|al-Khwārizmī and Böhm", + // Unicode three authors from LaTeX + "THREE_AUTHORS_WITH_LATEX|false|al-Khwārizmī, Böhm and Gödel", + // Unicode three authors from LaTeX using Oxford comma + "THREE_AUTHORS_WITH_LATEX|true|al-Khwārizmī, Böhm, and Gödel", + // Unicode one institution name from LaTeX + "ONE_INSTITUTION_WITH_LATEX|false|The Banū Mūsā brothers", + // Unicode two institution names from LaTeX + "TWO_INSTITUTIONS_WITH_LATEX|false|The Banū Mūsā brothers and The Banū Mūsā brothers", + // Unicode mixed authors from LaTeX + "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX|false|The Banū Mūsā brothers and Böhm", + // One institution with parenthesis at start + "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS|false|Łukasz Michał" + }, delimiter = '|') + void getAsLastNamesLatexFree(String authorListName, boolean oxfordComma, String expected) { + AuthorList authorList = getAuthorListByName(authorListName); + assertEquals(expected, authorList.latexFree().getAsLastNames(oxfordComma)); + } + + @Test + void fixAuthorForAlphabetization() { + assertEquals("Smith, J.", AuthorList.fixAuthorForAlphabetization("John Smith")); + assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("John von Neumann")); + assertEquals("Neumann, J.", AuthorList.fixAuthorForAlphabetization("J. von Neumann")); + assertEquals( + "Neumann, J. and Smith, J. and Black Brown, Jr., P.", + AuthorList + .fixAuthorForAlphabetization( + "John von Neumann and John Smith and de Black Brown, Jr., Peter")); + } + + @Test + void size() { + assertEquals(0, AuthorListTest.size("")); + assertEquals(1, AuthorListTest.size("Bar")); + assertEquals(1, AuthorListTest.size("Foo Bar")); + assertEquals(1, AuthorListTest.size("Foo von Bar")); + assertEquals(1, AuthorListTest.size("von Bar, Foo")); + assertEquals(1, AuthorListTest.size("Bar, Foo")); + assertEquals(1, AuthorListTest.size("Bar, Jr., Foo")); + assertEquals(1, AuthorListTest.size("Bar, Foo")); + assertEquals(2, AuthorListTest.size("John Neumann and Foo Bar")); + assertEquals(2, AuthorListTest.size("John von Neumann and Bar, Jr, Foo")); + + assertEquals(3, AuthorListTest.size("John von Neumann and John Smith and Black Brown, Peter")); + + StringBuilder s = new StringBuilder("John von Neumann"); + for (int i = 0; i < 25; i++) { + assertEquals(i + 1, AuthorListTest.size(s.toString())); + s.append(" and Albert Einstein"); + } + } + + @Test + void isEmpty() { + assertTrue(AuthorList.parse("").isEmpty()); + assertFalse(AuthorList.parse("Bar").isEmpty()); + } + + @Test + void getEmptyAuthor() { + assertThrows(Exception.class, () -> AuthorList.parse("").getAuthor(0)); + } + + @Test + void getAuthor() { + Author author = AuthorList.parse("John Smith and von Neumann, Jr, John").getAuthor(0); + assertEquals(Optional.of("John"), author.getGivenName()); + assertEquals(Optional.of("J."), author.getGivenNameAbbreviated()); + assertEquals("John Smith", author.getGivenFamily(false)); + assertEquals("J. Smith", author.getGivenFamily(true)); + assertEquals(Optional.empty(), author.getNameSuffix()); + assertEquals(Optional.of("Smith"), author.getFamilyName()); + assertEquals("Smith, John", author.getFamilyGiven(false)); + assertEquals("Smith, J.", author.getFamilyGiven(true)); + assertEquals("Smith", author.getNamePrefixAndFamilyName()); + assertEquals("Smith, J.", author.getNameForAlphabetization()); + assertEquals(Optional.empty(), author.getNamePrefix()); + + author = AuthorList.parse("Peter Black Brown").getAuthor(0); + assertEquals(Optional.of("Peter Black"), author.getGivenName()); + assertEquals(Optional.of("P. B."), author.getGivenNameAbbreviated()); + assertEquals("Peter Black Brown", author.getGivenFamily(false)); + assertEquals("P. B. Brown", author.getGivenFamily(true)); + assertEquals(Optional.empty(), author.getNameSuffix()); + assertEquals(Optional.empty(), author.getNamePrefix()); + + author = AuthorList.parse("John Smith and von Neumann, Jr, John").getAuthor(1); + assertEquals(Optional.of("John"), author.getGivenName()); + assertEquals(Optional.of("J."), author.getGivenNameAbbreviated()); + assertEquals("John von Neumann, Jr", author.getGivenFamily(false)); + assertEquals("J. von Neumann, Jr", author.getGivenFamily(true)); + assertEquals(Optional.of("Jr"), author.getNameSuffix()); + assertEquals(Optional.of("Neumann"), author.getFamilyName()); + assertEquals("von Neumann, Jr, John", author.getFamilyGiven(false)); + assertEquals("von Neumann, Jr, J.", author.getFamilyGiven(true)); + assertEquals("von Neumann", author.getNamePrefixAndFamilyName()); + assertEquals("Neumann, Jr, J.", author.getNameForAlphabetization()); + assertEquals(Optional.of("von"), author.getNamePrefix()); + } + + @Test + void companyAuthor() { + Author author = AuthorList.parse("{JabRef Developers}").getAuthor(0); + Author expected = new Author(null, null, null, "{JabRef Developers}", null); + assertEquals(expected, author); + } + + @Test + void companyAuthorAndPerson() { + Author company = new Author(null, null, null, "{JabRef Developers}", null); + Author person = new Author("Stefan", "S.", null, "Kolb", null); + assertEquals(Arrays.asList(company, person), + AuthorList.parse("{JabRef Developers} and Stefan Kolb").getAuthors()); + } + + @Test + void companyAuthorWithLowerCaseWord() { + Author author = AuthorList.parse("{JabRef Developers on Fire}").getAuthor(0); + Author expected = new Author(null, null, null, "{JabRef Developers on Fire}", null); + assertEquals(expected, author); + } + + @Test + void abbreviationWithRelax() { + Author author = AuthorList.parse("{\\relax Ch}ristoph Cholera").getAuthor(0); + Author expected = new Author("{\\relax Ch}ristoph", "{\\relax Ch}.", null, "Cholera", null); + assertEquals(expected, author); + } + + @Test + void getAuthorsNatbib() { + assertEquals("", AuthorList.parse("").getAsNatbib()); + assertEquals("Smith", AuthorList.parse("John Smith").getAsNatbib()); + assertEquals("Smith and Black Brown", AuthorList.parse( + "John Smith and Black Brown, Peter").getAsNatbib()); + assertEquals("von Neumann et al.", AuthorList.parse( + "John von Neumann and John Smith and Black Brown, Peter").getAsNatbib()); + + /* + * [ 1465610 ] (Double-)Names containing hyphen (-) not handled correctly + */ + assertEquals("Last-Name et al.", AuthorList.parse( + "First Second Last-Name" + " and John Smith and Black Brown, Peter").getAsNatbib()); + + // Test caching + AuthorList al = AuthorList + .parse("John von Neumann and John Smith and Black Brown, Peter"); + assertEquals(al.getAsNatbib(), al.getAsNatbib()); + } + + @Test + void getAuthorsLastOnly() { + // No comma before and + assertEquals("", AuthorList.parse("").getAsLastNames(false)); + assertEquals("Smith", AuthorList.parse("John Smith").getAsLastNames(false)); + assertEquals("Smith", AuthorList.parse("Smith, Jr, John").getAsLastNames( + false)); + + assertEquals("von Neumann, Smith and Black Brown", AuthorList.parse( + "John von Neumann and John Smith and Black Brown, Peter").getAsLastNames(false)); + // Oxford comma + assertEquals("", AuthorList.parse("").getAsLastNames(true)); + assertEquals("Smith", AuthorList.parse("John Smith").getAsLastNames(true)); + assertEquals("Smith", AuthorList.parse("Smith, Jr, John").getAsLastNames( + true)); + + assertEquals("von Neumann, Smith, and Black Brown", AuthorList.parse( + "John von Neumann and John Smith and Black Brown, Peter").getAsLastNames(true)); + + assertEquals("von Neumann and Smith", + AuthorList.parse("John von Neumann and John Smith").getAsLastNames(false)); + } + + @Test + void getAuthorsLastFirstNoComma() { + // No commas before and + AuthorList al; + + al = AuthorList.parse(""); + assertEquals("", al.getAsLastFirstNames(true, false)); + assertEquals("", al.getAsLastFirstNames(false, false)); + + al = AuthorList.parse("John Smith"); + assertEquals("Smith, John", al.getAsLastFirstNames(false, false)); + assertEquals("Smith, J.", al.getAsLastFirstNames(true, false)); + + al = AuthorList.parse("John Smith and Black Brown, Peter"); + assertEquals("Smith, John and Black Brown, Peter", al.getAsLastFirstNames(false, false)); + assertEquals("Smith, J. and Black Brown, P.", al.getAsLastFirstNames(true, false)); + + al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); + // Method description is different than code -> additional comma + // there + assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", + al.getAsLastFirstNames(false, false)); + assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", + al.getAsLastFirstNames(true, false)); + + al = AuthorList.parse("John Peter von Neumann"); + assertEquals("von Neumann, J. P.", al.getAsLastFirstNames(true, false)); + } + + @Test + void getAuthorsLastFirstOxfordComma() { + // Oxford comma + AuthorList al; + + al = AuthorList.parse(""); + assertEquals("", al.getAsLastFirstNames(true, true)); + assertEquals("", al.getAsLastFirstNames(false, true)); + + al = AuthorList.parse("John Smith"); + assertEquals("Smith, John", al.getAsLastFirstNames(false, true)); + assertEquals("Smith, J.", al.getAsLastFirstNames(true, true)); + + al = AuthorList.parse("John Smith and Black Brown, Peter"); + assertEquals("Smith, John and Black Brown, Peter", al.getAsLastFirstNames(false, true)); + assertEquals("Smith, J. and Black Brown, P.", al.getAsLastFirstNames(true, true)); + + al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); + assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", al + .getAsLastFirstNames(false, true)); + assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", al.getAsLastFirstNames( + true, true)); + + al = AuthorList.parse("John Peter von Neumann"); + assertEquals("von Neumann, J. P.", al.getAsLastFirstNames(true, true)); + } + + @Test + void getAuthorsLastFirstAnds() { + assertEquals("Smith, John", AuthorList.parse("John Smith").getAsLastFirstNamesWithAnd( + false)); + assertEquals("Smith, John and Black Brown, Peter", AuthorList.parse( + "John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(false)); + assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList + .parse("John von Neumann and John Smith and Black Brown, Peter") + .getAsLastFirstNamesWithAnd(false)); + assertEquals("von Last, Jr, First", AuthorList.parse("von Last, Jr ,First") + .getAsLastFirstNamesWithAnd(false)); + + assertEquals("Smith, J.", AuthorList.parse("John Smith").getAsLastFirstNamesWithAnd( + true)); + assertEquals("Smith, J. and Black Brown, P.", AuthorList.parse( + "John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(true)); + assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.", AuthorList.parse( + "John von Neumann and John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(true)); + assertEquals("von Last, Jr, F.", AuthorList.parse("von Last, Jr ,First") + .getAsLastFirstNamesWithAnd(true)); + } + + @Test + void getAuthorsFirstFirst() { + AuthorList al; + + al = AuthorList.parse(""); + assertEquals("", al.getAsFirstLastNames(true, false)); + assertEquals("", al.getAsFirstLastNames(false, false)); + assertEquals("", al.getAsFirstLastNames(true, true)); + assertEquals("", al.getAsFirstLastNames(false, true)); + + al = AuthorList.parse("John Smith"); + assertEquals("John Smith", al.getAsFirstLastNames(false, false)); + assertEquals("J. Smith", al.getAsFirstLastNames(true, false)); + assertEquals("John Smith", al.getAsFirstLastNames(false, true)); + assertEquals("J. Smith", al.getAsFirstLastNames(true, true)); + + al = AuthorList.parse("John Smith and Black Brown, Peter"); + assertEquals("John Smith and Peter Black Brown", al.getAsFirstLastNames(false, false)); + assertEquals("J. Smith and P. Black Brown", al.getAsFirstLastNames(true, false)); + assertEquals("John Smith and Peter Black Brown", al.getAsFirstLastNames(false, true)); + assertEquals("J. Smith and P. Black Brown", al.getAsFirstLastNames(true, true)); + + al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); + assertEquals("John von Neumann, John Smith and Peter Black Brown", al.getAsFirstLastNames( + false, false)); + assertEquals("J. von Neumann, J. Smith and P. Black Brown", al.getAsFirstLastNames(true, + false)); + assertEquals("John von Neumann, John Smith, and Peter Black Brown", al + .getAsFirstLastNames(false, true)); + assertEquals("J. von Neumann, J. Smith, and P. Black Brown", al.getAsFirstLastNames(true, + true)); + + al = AuthorList.parse("John Peter von Neumann"); + assertEquals("John Peter von Neumann", al.getAsFirstLastNames(false, false)); + assertEquals("John Peter von Neumann", al.getAsFirstLastNames(false, true)); + assertEquals("J. P. von Neumann", al.getAsFirstLastNames(true, false)); + assertEquals("J. P. von Neumann", al.getAsFirstLastNames(true, true)); + } + + @Test + void getAuthorsFirstFirstAnds() { + assertEquals("John Smith", AuthorList.parse("John Smith") + .getAsFirstLastNamesWithAnd()); + assertEquals("John Smith and Peter Black Brown", AuthorList.parse( + "John Smith and Black Brown, Peter").getAsFirstLastNamesWithAnd()); + assertEquals("John von Neumann and John Smith and Peter Black Brown", AuthorList + .parse("John von Neumann and John Smith and Black Brown, Peter") + .getAsFirstLastNamesWithAnd()); + assertEquals("First von Last, Jr. III", AuthorList + .parse("von Last, Jr. III, First").getAsFirstLastNamesWithAnd()); + } + + @Test + void getAuthorsForAlphabetization() { + assertEquals("Smith, J.", AuthorList.parse("John Smith") + .getForAlphabetization()); + assertEquals("Neumann, J.", AuthorList.parse("John von Neumann") + .getForAlphabetization()); + assertEquals("Neumann, J.", AuthorList.parse("J. von Neumann") + .getForAlphabetization()); + assertEquals("Neumann, J. and Smith, J. and Black Brown, Jr., P.", AuthorList + .parse("John von Neumann and John Smith and de Black Brown, Jr., Peter") + .getForAlphabetization()); + } + + @Test + void removeStartAndEndBraces() { + assertEquals("{A}bbb{c}", AuthorList.parse("{A}bbb{c}").getAsLastNames(false)); + assertEquals("{Vall{\\'e}e Poussin}", + AuthorList.parse("{Vall{\\'e}e Poussin}").getAsLastNames(false)); + assertEquals("Poussin", AuthorList.parse("{Vall{\\'e}e} {Poussin}").getAsLastNames(false)); + assertEquals("Poussin", AuthorList.parse("Vall{\\'e}e Poussin").getAsLastNames(false)); + assertEquals("Lastname", AuthorList.parse("Firstname {Lastname}").getAsLastNames(false)); + assertEquals("{Firstname Lastname}", + AuthorList.parse("{Firstname Lastname}").getAsLastNames(false)); + } + + @Test + void createCorrectInitials() { + assertEquals(Optional.of("J. G."), + AuthorList.parse("Hornberg, Johann Gottfried").getAuthor(0).getGivenNameAbbreviated()); + } + + @ParameterizedTest + @CsvSource({ + "'{Tse-tung} Mao', 'Tse-tung', '{Tse-tung}.', '', 'Mao', ''", + "'{van den Bergen}, Hans', 'Hans', 'H.', '', 'van den Bergen', ''", + "'Tse-tung Mao', 'Tse-tung', 'T.-t.', '', 'Mao', ''", + "'Firstname Bailey-Jones', 'Firstname', 'F.', '', 'Bailey-Jones', ''", + "'E. S. El-{M}allah', 'E. S.', 'E. S.', '', 'El-{M}allah', ''", + "'E. S. {K}ent-{B}oswell', 'E. S.', 'E. S.', '', '{K}ent-{B}oswell', ''", + "'H{e}lene Fiaux', 'H{e}lene', 'H.', '', 'Fiaux', ''" + }) + void parseNameWithSpecialCharacters(String input, String givenName, String givenNameAbbr, + String namePrefix, String familyName, String nameSuffix) { + Author expected = new Author( + givenName.isEmpty() ? null : givenName, + givenNameAbbr.isEmpty() ? null : givenNameAbbr, + namePrefix.isEmpty() ? null : namePrefix, + familyName.isEmpty() ? null : familyName, + nameSuffix.isEmpty() ? null : nameSuffix + ); + assertEquals(AuthorList.of(expected), AuthorList.parse(input)); + } + + @Test + void parseNameWithHyphenInLastNameWhenLastNameGivenFirst() { + // TODO: Fix abbreviation to be "A." + Author expected = new Author("ʿAbdallāh", "ʿ.", null, "al-Ṭūlī", null); + assertEquals(AuthorList.of(expected), AuthorList.parse("al-Ṭūlī, ʿAbdallāh")); + } + + @Test + @Disabled("Has issues with space character in W-P.") + void parseWithDash() { + assertEquals( + AuthorList.of( + new Author("Z.", "Z.", null, "Yao", null), + new Author("D. S.", "D. S.", null, "Weld", null), + new Author("W-P.", "W-P.", null, "Chen", null), + new Author("H.", "H.", null, "Sun", null) + ), + AuthorList.parse("Z. Yao, D. S. Weld, W.-P. Chen, and H. Sun")); + } + + @Test + void parseFirstNameFromFirstAuthorMultipleAuthorsWithLatexNames() { + assertEquals("Mu{\\d{h}}ammad", + AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") + .getAuthor(0).getGivenName().orElse(null)); + } + + @Test + void parseFirstNameFromSecondAuthorMultipleAuthorsWithLatexNames() { + assertEquals("Corrado", + AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") + .getAuthor(1).getGivenName().orElse(null)); + } + + @Test + void parseLastNameFromFirstAuthorMultipleAuthorsWithLatexNames() { + assertEquals("al-Khw{\\={a}}rizm{\\={i}}", + AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") + .getAuthor(0).getFamilyName().orElse(null)); + } + + @Test + void parseLastNameFromSecondAuthorMultipleAuthorsWithLatexNames() { + assertEquals("B{\\\"o}hm", + AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") + .getAuthor(1).getFamilyName().orElse(null)); + } + + @Test + void parseInstitutionAuthorWithLatexNames() { + assertEquals("{The Ban\\={u} M\\={u}s\\={a} brothers}", + AuthorList.parse("{The Ban\\={u} M\\={u}s\\={a} brothers}").getAuthor(0).getFamilyName() + .orElse(null)); + } + + @Test + void parseRetrieveCachedAuthorListAfterGarbageCollection() { + final String uniqueAuthorName = "Osvaldo Iongi"; + AuthorList author = AuthorList.parse(uniqueAuthorName); + System.gc(); + assertSame(author, AuthorList.parse(uniqueAuthorName)); + } + + @Test + void parseGarbageCollectAuthorListForUnreachableKey() { + final String uniqueAuthorName = "Fleur Hornbach"; + // Note that "new String()" is needed, uniqueAuthorName is a reference to a String literal + AuthorList uniqueAuthor = AuthorList.parse(new String(uniqueAuthorName)); + System.gc(); + assertNotSame(uniqueAuthor, AuthorList.parse(uniqueAuthorName)); + } + + @Test + void parseGarbageCollectUnreachableInstitution() { + final String uniqueInstitutionName = "{Unique LLC}"; + // Note that "new String()" is needed, uniqueInstitutionName is a reference to a String literal + AuthorList uniqueInstitution = AuthorList.parse(new String(uniqueInstitutionName)); + System.gc(); + assertNotSame(uniqueInstitution, AuthorList.parse(uniqueInstitutionName)); + } + + /** + * This tests an unreachable key issue addressed in + * [#6552](https://github.com/JabRef/jabref/pull/6552). The test is incorrect BibTeX but is + * handled by the parser and common in practice. + */ + @Test + void parseCacheAuthorsWithTwoOrMoreCommasAndWithSpaceInAllParts() { + final String uniqueAuthorsNames = "Basil Dankworth, Gianna Birdwhistle, Cosmo Berrycloth"; + AuthorList uniqueAuthors = AuthorList.parse(uniqueAuthorsNames); + System.gc(); + assertSame(uniqueAuthors, AuthorList.parse(uniqueAuthorsNames)); + } + + /** + * This tests an unreachable key issue addressed in + * [#6552](https://github.com/JabRef/jabref/pull/6552). + */ + @Test + void parseCacheAuthorsWithTwoOrMoreCommasAndWithoutSpaceInAllParts() { + final String uniqueAuthorsNames = "Dankworth, Jr., Braelynn"; + AuthorList uniqueAuthors = AuthorList.parse(uniqueAuthorsNames); + System.gc(); + assertSame(uniqueAuthors, AuthorList.parse(uniqueAuthorsNames)); + } + + /** + * This tests the issue described at + * https://github.com/JabRef/jabref/pull/2669#issuecomment-288519458 */ - assertEquals("Last-Name et al.", AuthorList.parse( - "First Second Last-Name" + " and John Smith and Black Brown, Peter").getAsNatbib()); - - // Test caching - AuthorList al = AuthorList - .parse("John von Neumann and John Smith and Black Brown, Peter"); - assertEquals(al.getAsNatbib(), al.getAsNatbib()); - } - - @Test - void getAuthorsLastOnly() { - // No comma before and - assertEquals("", AuthorList.parse("").getAsLastNames(false)); - assertEquals("Smith", AuthorList.parse("John Smith").getAsLastNames(false)); - assertEquals("Smith", AuthorList.parse("Smith, Jr, John").getAsLastNames( - false)); - - assertEquals("von Neumann, Smith and Black Brown", AuthorList.parse( - "John von Neumann and John Smith and Black Brown, Peter").getAsLastNames(false)); - // Oxford comma - assertEquals("", AuthorList.parse("").getAsLastNames(true)); - assertEquals("Smith", AuthorList.parse("John Smith").getAsLastNames(true)); - assertEquals("Smith", AuthorList.parse("Smith, Jr, John").getAsLastNames( - true)); - - assertEquals("von Neumann, Smith, and Black Brown", AuthorList.parse( - "John von Neumann and John Smith and Black Brown, Peter").getAsLastNames(true)); - - assertEquals("von Neumann and Smith", - AuthorList.parse("John von Neumann and John Smith").getAsLastNames(false)); - } - - @Test - void getAuthorsLastFirstNoComma() { - // No commas before and - AuthorList al; - - al = AuthorList.parse(""); - assertEquals("", al.getAsLastFirstNames(true, false)); - assertEquals("", al.getAsLastFirstNames(false, false)); - - al = AuthorList.parse("John Smith"); - assertEquals("Smith, John", al.getAsLastFirstNames(false, false)); - assertEquals("Smith, J.", al.getAsLastFirstNames(true, false)); - - al = AuthorList.parse("John Smith and Black Brown, Peter"); - assertEquals("Smith, John and Black Brown, Peter", al.getAsLastFirstNames(false, false)); - assertEquals("Smith, J. and Black Brown, P.", al.getAsLastFirstNames(true, false)); - - al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); - // Method description is different than code -> additional comma - // there - assertEquals("von Neumann, John, Smith, John and Black Brown, Peter", - al.getAsLastFirstNames(false, false)); - assertEquals("von Neumann, J., Smith, J. and Black Brown, P.", - al.getAsLastFirstNames(true, false)); - - al = AuthorList.parse("John Peter von Neumann"); - assertEquals("von Neumann, J. P.", al.getAsLastFirstNames(true, false)); - } - - @Test - void getAuthorsLastFirstOxfordComma() { - // Oxford comma - AuthorList al; - - al = AuthorList.parse(""); - assertEquals("", al.getAsLastFirstNames(true, true)); - assertEquals("", al.getAsLastFirstNames(false, true)); - - al = AuthorList.parse("John Smith"); - assertEquals("Smith, John", al.getAsLastFirstNames(false, true)); - assertEquals("Smith, J.", al.getAsLastFirstNames(true, true)); - - al = AuthorList.parse("John Smith and Black Brown, Peter"); - assertEquals("Smith, John and Black Brown, Peter", al.getAsLastFirstNames(false, true)); - assertEquals("Smith, J. and Black Brown, P.", al.getAsLastFirstNames(true, true)); - - al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); - assertEquals("von Neumann, John, Smith, John, and Black Brown, Peter", al - .getAsLastFirstNames(false, true)); - assertEquals("von Neumann, J., Smith, J., and Black Brown, P.", al.getAsLastFirstNames( - true, true)); - - al = AuthorList.parse("John Peter von Neumann"); - assertEquals("von Neumann, J. P.", al.getAsLastFirstNames(true, true)); - } - - @Test - void getAuthorsLastFirstAnds() { - assertEquals("Smith, John", AuthorList.parse("John Smith").getAsLastFirstNamesWithAnd( - false)); - assertEquals("Smith, John and Black Brown, Peter", AuthorList.parse( - "John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(false)); - assertEquals("von Neumann, John and Smith, John and Black Brown, Peter", AuthorList - .parse("John von Neumann and John Smith and Black Brown, Peter") - .getAsLastFirstNamesWithAnd(false)); - assertEquals("von Last, Jr, First", AuthorList.parse("von Last, Jr ,First") - .getAsLastFirstNamesWithAnd(false)); - - assertEquals("Smith, J.", AuthorList.parse("John Smith").getAsLastFirstNamesWithAnd( - true)); - assertEquals("Smith, J. and Black Brown, P.", AuthorList.parse( - "John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(true)); - assertEquals("von Neumann, J. and Smith, J. and Black Brown, P.", AuthorList.parse( - "John von Neumann and John Smith and Black Brown, Peter").getAsLastFirstNamesWithAnd(true)); - assertEquals("von Last, Jr, F.", AuthorList.parse("von Last, Jr ,First") - .getAsLastFirstNamesWithAnd(true)); - } - - @Test - void getAuthorsFirstFirst() { - AuthorList al; - - al = AuthorList.parse(""); - assertEquals("", al.getAsFirstLastNames(true, false)); - assertEquals("", al.getAsFirstLastNames(false, false)); - assertEquals("", al.getAsFirstLastNames(true, true)); - assertEquals("", al.getAsFirstLastNames(false, true)); - - al = AuthorList.parse("John Smith"); - assertEquals("John Smith", al.getAsFirstLastNames(false, false)); - assertEquals("J. Smith", al.getAsFirstLastNames(true, false)); - assertEquals("John Smith", al.getAsFirstLastNames(false, true)); - assertEquals("J. Smith", al.getAsFirstLastNames(true, true)); - - al = AuthorList.parse("John Smith and Black Brown, Peter"); - assertEquals("John Smith and Peter Black Brown", al.getAsFirstLastNames(false, false)); - assertEquals("J. Smith and P. Black Brown", al.getAsFirstLastNames(true, false)); - assertEquals("John Smith and Peter Black Brown", al.getAsFirstLastNames(false, true)); - assertEquals("J. Smith and P. Black Brown", al.getAsFirstLastNames(true, true)); - - al = AuthorList.parse("John von Neumann and John Smith and Black Brown, Peter"); - assertEquals("John von Neumann, John Smith and Peter Black Brown", al.getAsFirstLastNames( - false, false)); - assertEquals("J. von Neumann, J. Smith and P. Black Brown", al.getAsFirstLastNames(true, - false)); - assertEquals("John von Neumann, John Smith, and Peter Black Brown", al - .getAsFirstLastNames(false, true)); - assertEquals("J. von Neumann, J. Smith, and P. Black Brown", al.getAsFirstLastNames(true, - true)); - - al = AuthorList.parse("John Peter von Neumann"); - assertEquals("John Peter von Neumann", al.getAsFirstLastNames(false, false)); - assertEquals("John Peter von Neumann", al.getAsFirstLastNames(false, true)); - assertEquals("J. P. von Neumann", al.getAsFirstLastNames(true, false)); - assertEquals("J. P. von Neumann", al.getAsFirstLastNames(true, true)); - } - - @Test - void getAuthorsFirstFirstAnds() { - assertEquals("John Smith", AuthorList.parse("John Smith") - .getAsFirstLastNamesWithAnd()); - assertEquals("John Smith and Peter Black Brown", AuthorList.parse( - "John Smith and Black Brown, Peter").getAsFirstLastNamesWithAnd()); - assertEquals("John von Neumann and John Smith and Peter Black Brown", AuthorList - .parse("John von Neumann and John Smith and Black Brown, Peter") - .getAsFirstLastNamesWithAnd()); - assertEquals("First von Last, Jr. III", AuthorList - .parse("von Last, Jr. III, First").getAsFirstLastNamesWithAnd()); - } - - @Test - void getAuthorsForAlphabetization() { - assertEquals("Smith, J.", AuthorList.parse("John Smith") - .getForAlphabetization()); - assertEquals("Neumann, J.", AuthorList.parse("John von Neumann") - .getForAlphabetization()); - assertEquals("Neumann, J.", AuthorList.parse("J. von Neumann") - .getForAlphabetization()); - assertEquals("Neumann, J. and Smith, J. and Black Brown, Jr., P.", AuthorList - .parse("John von Neumann and John Smith and de Black Brown, Jr., Peter") - .getForAlphabetization()); - } - - @Test - void removeStartAndEndBraces() { - assertEquals("{A}bbb{c}", AuthorList.parse("{A}bbb{c}").getAsLastNames(false)); - assertEquals("{Vall{\\'e}e Poussin}", - AuthorList.parse("{Vall{\\'e}e Poussin}").getAsLastNames(false)); - assertEquals("Poussin", AuthorList.parse("{Vall{\\'e}e} {Poussin}").getAsLastNames(false)); - assertEquals("Poussin", AuthorList.parse("Vall{\\'e}e Poussin").getAsLastNames(false)); - assertEquals("Lastname", AuthorList.parse("Firstname {Lastname}").getAsLastNames(false)); - assertEquals("{Firstname Lastname}", - AuthorList.parse("{Firstname Lastname}").getAsLastNames(false)); - } - - @Test - void createCorrectInitials() { - assertEquals(Optional.of("J. G."), - AuthorList.parse("Hornberg, Johann Gottfried").getAuthor(0).getGivenNameAbbreviated()); - } - - @ParameterizedTest - @CsvSource({ - "'{Tse-tung} Mao', 'Tse-tung', '{Tse-tung}.', '', 'Mao', ''", - "'{van den Bergen}, Hans', 'Hans', 'H.', '', 'van den Bergen', ''", - "'Tse-tung Mao', 'Tse-tung', 'T.-t.', '', 'Mao', ''", - "'Firstname Bailey-Jones', 'Firstname', 'F.', '', 'Bailey-Jones', ''", - "'E. S. El-{M}allah', 'E. S.', 'E. S.', '', 'El-{M}allah', ''", - "'E. S. {K}ent-{B}oswell', 'E. S.', 'E. S.', '', '{K}ent-{B}oswell', ''", - "'H{e}lene Fiaux', 'H{e}lene', 'H.', '', 'Fiaux', ''" - }) - void parseNameWithSpecialCharacters(String input, String givenName, String givenNameAbbr, - String namePrefix, String familyName, String nameSuffix) { - Author expected = new Author( - givenName.isEmpty() ? null : givenName, - givenNameAbbr.isEmpty() ? null : givenNameAbbr, - namePrefix.isEmpty() ? null : namePrefix, - familyName.isEmpty() ? null : familyName, - nameSuffix.isEmpty() ? null : nameSuffix - ); - assertEquals(AuthorList.of(expected), AuthorList.parse(input)); - } - - @Test - void parseNameWithHyphenInLastNameWhenLastNameGivenFirst() { - // TODO: Fix abbreviation to be "A." - Author expected = new Author("ʿAbdallāh", "ʿ.", null, "al-Ṭūlī", null); - assertEquals(AuthorList.of(expected), AuthorList.parse("al-Ṭūlī, ʿAbdallāh")); - } - - @Test - @Disabled("Has issues with space character in W-P.") - void parseWithDash() { - assertEquals( - AuthorList.of( - new Author("Z.", "Z.", null, "Yao", null), - new Author("D. S.", "D. S.", null, "Weld", null), - new Author("W-P.", "W-P.", null, "Chen", null), - new Author("H.", "H.", null, "Sun", null) - ), - AuthorList.parse("Z. Yao, D. S. Weld, W.-P. Chen, and H. Sun")); - } - - @Test - void parseFirstNameFromFirstAuthorMultipleAuthorsWithLatexNames() { - assertEquals("Mu{\\d{h}}ammad", - AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") - .getAuthor(0).getGivenName().orElse(null)); - } - - @Test - void parseFirstNameFromSecondAuthorMultipleAuthorsWithLatexNames() { - assertEquals("Corrado", - AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") - .getAuthor(1).getGivenName().orElse(null)); - } - - @Test - void parseLastNameFromFirstAuthorMultipleAuthorsWithLatexNames() { - assertEquals("al-Khw{\\={a}}rizm{\\={i}}", - AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") - .getAuthor(0).getFamilyName().orElse(null)); - } - - @Test - void parseLastNameFromSecondAuthorMultipleAuthorsWithLatexNames() { - assertEquals("B{\\\"o}hm", - AuthorList.parse("Mu{\\d{h}}ammad al-Khw{\\={a}}rizm{\\={i}} and Corrado B{\\\"o}hm") - .getAuthor(1).getFamilyName().orElse(null)); - } - - @Test - void parseInstitutionAuthorWithLatexNames() { - assertEquals("{The Ban\\={u} M\\={u}s\\={a} brothers}", - AuthorList.parse("{The Ban\\={u} M\\={u}s\\={a} brothers}").getAuthor(0).getFamilyName() - .orElse(null)); - } - - @Test - void parseRetrieveCachedAuthorListAfterGarbageCollection() { - final String uniqueAuthorName = "Osvaldo Iongi"; - AuthorList author = AuthorList.parse(uniqueAuthorName); - System.gc(); - assertSame(author, AuthorList.parse(uniqueAuthorName)); - } - - @Test - void parseGarbageCollectAuthorListForUnreachableKey() { - final String uniqueAuthorName = "Fleur Hornbach"; - // Note that "new String()" is needed, uniqueAuthorName is a reference to a String literal - AuthorList uniqueAuthor = AuthorList.parse(new String(uniqueAuthorName)); - System.gc(); - assertNotSame(uniqueAuthor, AuthorList.parse(uniqueAuthorName)); - } - - @Test - void parseGarbageCollectUnreachableInstitution() { - final String uniqueInstitutionName = "{Unique LLC}"; - // Note that "new String()" is needed, uniqueInstitutionName is a reference to a String literal - AuthorList uniqueInstitution = AuthorList.parse(new String(uniqueInstitutionName)); - System.gc(); - assertNotSame(uniqueInstitution, AuthorList.parse(uniqueInstitutionName)); - } - - /** - * This tests an unreachable key issue addressed in - * [#6552](https://github.com/JabRef/jabref/pull/6552). The test is incorrect BibTeX but is - * handled by the parser and common in practice. - */ - @Test - void parseCacheAuthorsWithTwoOrMoreCommasAndWithSpaceInAllParts() { - final String uniqueAuthorsNames = "Basil Dankworth, Gianna Birdwhistle, Cosmo Berrycloth"; - AuthorList uniqueAuthors = AuthorList.parse(uniqueAuthorsNames); - System.gc(); - assertSame(uniqueAuthors, AuthorList.parse(uniqueAuthorsNames)); - } - - /** - * This tests an unreachable key issue addressed in - * [#6552](https://github.com/JabRef/jabref/pull/6552). - */ - @Test - void parseCacheAuthorsWithTwoOrMoreCommasAndWithoutSpaceInAllParts() { - final String uniqueAuthorsNames = "Dankworth, Jr., Braelynn"; - AuthorList uniqueAuthors = AuthorList.parse(uniqueAuthorsNames); - System.gc(); - assertSame(uniqueAuthors, AuthorList.parse(uniqueAuthorsNames)); - } - - /** - * This tests the issue described at - * https://github.com/JabRef/jabref/pull/2669#issuecomment-288519458 - */ - @Test - void correctNamesWithOneComma() { - Author expected = new Author("Alexander der Große", "A. d. G.", null, "Canon der Barbar", null); - assertEquals(AuthorList.of(expected), - AuthorList.parse("Canon der Barbar, Alexander der Große")); - - expected = new Author("Alexander H. G.", "A. H. G.", null, "Rinnooy Kan", null); - assertEquals(AuthorList.of(expected), AuthorList.parse("Rinnooy Kan, Alexander H. G.")); - - expected = new Author("Alexander Hendrik George", "A. H. G.", null, "Rinnooy Kan", null); - assertEquals(AuthorList.of(expected), - AuthorList.parse("Rinnooy Kan, Alexander Hendrik George")); - - expected = new Author("José María", "J. M.", null, "Rodriguez Fernandez", null); - assertEquals(AuthorList.of(expected), AuthorList.parse("Rodriguez Fernandez, José María")); - } - - @ParameterizedTest - @CsvSource({ - "true, true", - "true, false", - "false, true", - "false, false" - }) - void equalsReflexive(boolean abbreviate, boolean oxford) { - AuthorList authorList = AuthorList.of(new Author(null, null, null, null, null)); - assertEquals(authorList, authorList); - } - - @ParameterizedTest - @CsvSource({ - "true, true", - "true, false", - "false, true", - "false, false" - }) - void equalsSymmetric(boolean abbreviate, boolean oxford) { - AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - assertEquals(firstAuthorList, secondAuthorList); - assertEquals(secondAuthorList, firstAuthorList); - } - - @Test - void equalsTransitive() { - AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - AuthorList thirdAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - assertEquals(firstAuthorList, secondAuthorList); - assertEquals(secondAuthorList, thirdAuthorList); - assertEquals(firstAuthorList, thirdAuthorList); - } - - @Test - void equalsConsistent() { - AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - assertEquals(firstAuthorList, secondAuthorList); - assertEquals(firstAuthorList, secondAuthorList); - assertEquals(firstAuthorList, secondAuthorList); - } - - @Test - void equalsFalseDifferentOrder() { - Author firstAuthor = new Author("A", null, null, null, null); - Author secondAuthor = new Author("B", null, null, null, null); - AuthorList firstAuthorList = AuthorList.of(firstAuthor, secondAuthor); - AuthorList secondAuthorList = AuthorList.of(secondAuthor, firstAuthor); - assertNotEquals(firstAuthorList, secondAuthorList); - } - - @Test - void equalsFalseWhenNotAuthorList() { - assertNotEquals(AuthorList.of(new Author(null, null, null, null, null)), - new Author(null, null, null, null, null)); - } - - @Test - void equalsFalseForNull() { - assertNotEquals(null, AuthorList.of(new Author(null, null, null, null, null))); - } - - @Test - void hashCodeConsistent() { - AuthorList authorList = AuthorList.of(new Author(null, null, null, null, null)); - assertEquals(authorList.hashCode(), authorList.hashCode()); - } - - @Test - void hashCodeNotConstant() { - AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); - AuthorList secondAuthorList = AuthorList.of(new Author("B", null, null, null, null)); - assertNotEquals(firstAuthorList.hashCode(), secondAuthorList.hashCode()); - } - - @Test - void getAsLastFirstFirstLastNamesWithAndEmptyAuthor() { - assertEquals("", - EMPTY_AUTHOR.getAsLastFirstFirstLastNamesWithAnd(true)); - } - - @Test - void getAsLastFirstFirstLastNamesWithAndMultipleAuthors() { - assertEquals("al-Khw{\\={a}}rizm{\\={i}}, M. and C. B{\\\"o}hm and K. G{\\\"{o}}del", - THREE_AUTHORS_WITH_LATEX.getAsLastFirstFirstLastNamesWithAnd(true)); - } - - // Helper method to get AuthorList by name - private AuthorList getAuthorListByName(String name) { - switch (name) { - case "EMPTY_AUTHOR": - return EMPTY_AUTHOR; - case "ONE_AUTHOR_WITH_LATEX": - return ONE_AUTHOR_WITH_LATEX; - case "TWO_AUTHORS_WITH_LATEX": - return TWO_AUTHORS_WITH_LATEX; - case "THREE_AUTHORS_WITH_LATEX": - return THREE_AUTHORS_WITH_LATEX; - case "ONE_INSTITUTION_WITH_LATEX": - return ONE_INSTITUTION_WITH_LATEX; - case "TWO_INSTITUTIONS_WITH_LATEX": - return TWO_INSTITUTIONS_WITH_LATEX; - case "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX": - return MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX; - case "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS": - return ONE_INSTITUTION_WITH_STARTING_PARANTHESIS; - default: - throw new IllegalArgumentException("Unknown author list: " + name); - } - } + @Test + void correctNamesWithOneComma() { + Author expected = new Author("Alexander der Große", "A. d. G.", null, "Canon der Barbar", null); + assertEquals(AuthorList.of(expected), + AuthorList.parse("Canon der Barbar, Alexander der Große")); + + expected = new Author("Alexander H. G.", "A. H. G.", null, "Rinnooy Kan", null); + assertEquals(AuthorList.of(expected), AuthorList.parse("Rinnooy Kan, Alexander H. G.")); + + expected = new Author("Alexander Hendrik George", "A. H. G.", null, "Rinnooy Kan", null); + assertEquals(AuthorList.of(expected), + AuthorList.parse("Rinnooy Kan, Alexander Hendrik George")); + + expected = new Author("José María", "J. M.", null, "Rodriguez Fernandez", null); + assertEquals(AuthorList.of(expected), AuthorList.parse("Rodriguez Fernandez, José María")); + } + + @ParameterizedTest + @CsvSource({ + "true, true", + "true, false", + "false, true", + "false, false" + }) + void equalsReflexive(boolean abbreviate, boolean oxford) { + AuthorList authorList = AuthorList.of(new Author(null, null, null, null, null)); + assertEquals(authorList, authorList); + } + + @ParameterizedTest + @CsvSource({ + "true, true", + "true, false", + "false, true", + "false, false" + }) + void equalsSymmetric(boolean abbreviate, boolean oxford) { + AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + assertEquals(firstAuthorList, secondAuthorList); + assertEquals(secondAuthorList, firstAuthorList); + } + + @Test + void equalsTransitive() { + AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + AuthorList thirdAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + assertEquals(firstAuthorList, secondAuthorList); + assertEquals(secondAuthorList, thirdAuthorList); + assertEquals(firstAuthorList, thirdAuthorList); + } + + @Test + void equalsConsistent() { + AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + AuthorList secondAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + assertEquals(firstAuthorList, secondAuthorList); + assertEquals(firstAuthorList, secondAuthorList); + assertEquals(firstAuthorList, secondAuthorList); + } + + @Test + void equalsFalseDifferentOrder() { + Author firstAuthor = new Author("A", null, null, null, null); + Author secondAuthor = new Author("B", null, null, null, null); + AuthorList firstAuthorList = AuthorList.of(firstAuthor, secondAuthor); + AuthorList secondAuthorList = AuthorList.of(secondAuthor, firstAuthor); + assertNotEquals(firstAuthorList, secondAuthorList); + } + + @Test + void equalsFalseWhenNotAuthorList() { + assertNotEquals(AuthorList.of(new Author(null, null, null, null, null)), + new Author(null, null, null, null, null)); + } + + @Test + void equalsFalseForNull() { + assertNotEquals(null, AuthorList.of(new Author(null, null, null, null, null))); + } + + @Test + void hashCodeConsistent() { + AuthorList authorList = AuthorList.of(new Author(null, null, null, null, null)); + assertEquals(authorList.hashCode(), authorList.hashCode()); + } + + @Test + void hashCodeNotConstant() { + AuthorList firstAuthorList = AuthorList.of(new Author("A", null, null, null, null)); + AuthorList secondAuthorList = AuthorList.of(new Author("B", null, null, null, null)); + assertNotEquals(firstAuthorList.hashCode(), secondAuthorList.hashCode()); + } + + @Test + void getAsLastFirstFirstLastNamesWithAndEmptyAuthor() { + assertEquals("", + EMPTY_AUTHOR.getAsLastFirstFirstLastNamesWithAnd(true)); + } + + @Test + void getAsLastFirstFirstLastNamesWithAndMultipleAuthors() { + assertEquals("al-Khw{\\={a}}rizm{\\={i}}, M. and C. B{\\\"o}hm and K. G{\\\"{o}}del", + THREE_AUTHORS_WITH_LATEX.getAsLastFirstFirstLastNamesWithAnd(true)); + } + + // Helper method to get AuthorList by name + private AuthorList getAuthorListByName(String name) { + switch (name) { + case "EMPTY_AUTHOR": + return EMPTY_AUTHOR; + case "ONE_AUTHOR_WITH_LATEX": + return ONE_AUTHOR_WITH_LATEX; + case "TWO_AUTHORS_WITH_LATEX": + return TWO_AUTHORS_WITH_LATEX; + case "THREE_AUTHORS_WITH_LATEX": + return THREE_AUTHORS_WITH_LATEX; + case "ONE_INSTITUTION_WITH_LATEX": + return ONE_INSTITUTION_WITH_LATEX; + case "TWO_INSTITUTIONS_WITH_LATEX": + return TWO_INSTITUTIONS_WITH_LATEX; + case "MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX": + return MIXED_AUTHOR_AND_INSTITUTION_WITH_LATEX; + case "ONE_INSTITUTION_WITH_STARTING_PARANTHESIS": + return ONE_INSTITUTION_WITH_STARTING_PARANTHESIS; + default: + throw new IllegalArgumentException("Unknown author list: " + name); + } + } } diff --git a/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java b/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java index 78544674721..a23a379eb6a 100644 --- a/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java +++ b/jablib/src/test/java/org/jabref/model/entry/AuthorTest.java @@ -1,7 +1,5 @@ package org.jabref.model.entry; -import static org.junit.jupiter.api.Assertions.assertEquals; - import java.util.Optional; import org.junit.jupiter.api.Test; @@ -10,57 +8,59 @@ import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; +import static org.junit.jupiter.api.Assertions.assertEquals; + class AuthorTest { - @ParameterizedTest - @CsvSource({ - "AO, 'A. O.'", - "AO., 'A. O.'", - "A.O., 'A. O.'", - "A-O, 'A.-O.'" - }) - void addDotIfAbbreviationAddsDot(String input, String expected) { - assertEquals(expected, Author.addDotIfAbbreviation(input)); - } + @ParameterizedTest + @CsvSource({ + "AO, 'A. O.'", + "AO., 'A. O.'", + "A.O., 'A. O.'", + "A-O, 'A.-O.'" + }) + void addDotIfAbbreviationAddsDot(String input, String expected) { + assertEquals(expected, Author.addDotIfAbbreviation(input)); + } - @ParameterizedTest - @CsvSource({ - "'A O', 'A. O.'", - "'A-melia', 'A.-melia'", - "'AmeliA', 'AmeliA'", - "'Ameli A', 'Ameli A.'", - "'Ameli ', 'Ameli'", - "'Ameli AA', 'Ameli A. A.'" - }) - void addDotIfAbbreviationEdgeCases(String input, String expected) { - assertEquals(expected, Author.addDotIfAbbreviation(input)); - } + @ParameterizedTest + @CsvSource({ + "'A O', 'A. O.'", + "'A-melia', 'A.-melia'", + "'AmeliA', 'AmeliA'", + "'Ameli A', 'Ameli A.'", + "'Ameli ', 'Ameli'", + "'Ameli AA', 'Ameli A. A.'" + }) + void addDotIfAbbreviationEdgeCases(String input, String expected) { + assertEquals(expected, Author.addDotIfAbbreviation(input)); + } - @ParameterizedTest - @ValueSource(strings = {"O.", "A. O.", "A.-O.", - "O. Moore", "A. O. Moore", "O. von Moore", "A.-O. Moore", - "Moore, O.", "Moore, O., Jr.", "Moore, A. O.", "Moore, A.-O.", - "MEmre", "{\\'{E}}douard", "J{\\\"o}rg", "Moore, O. and O. Moore", - "Moore, O. and O. Moore and Moore, O. O."}) - void addDotIfAbbreviationDoNotAddDot(String input) { - assertEquals(input, Author.addDotIfAbbreviation(input)); - } + @ParameterizedTest + @ValueSource(strings = {"O.", "A. O.", "A.-O.", + "O. Moore", "A. O. Moore", "O. von Moore", "A.-O. Moore", + "Moore, O.", "Moore, O., Jr.", "Moore, A. O.", "Moore, A.-O.", + "MEmre", "{\\'{E}}douard", "J{\\\"o}rg", "Moore, O. and O. Moore", + "Moore, O. and O. Moore and Moore, O. O."}) + void addDotIfAbbreviationDoNotAddDot(String input) { + assertEquals(input, Author.addDotIfAbbreviation(input)); + } - @ParameterizedTest - @NullAndEmptySource - @ValueSource(strings = { - // Lower-case letters - "asdf", "a", - // Numbers - "1", "1 23" - }) - void addDotIfAbbreviation(String input) { - assertEquals(input, Author.addDotIfAbbreviation(input)); - } + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = { + // Lower-case letters + "asdf", "a", + // Numbers + "1", "1 23" + }) + void addDotIfAbbreviation(String input) { + assertEquals(input, Author.addDotIfAbbreviation(input)); + } - @Test - void bracesKept() { - assertEquals(Optional.of("{Company Name, LLC}"), - new Author("", "", null, "{Company Name, LLC}", null).getFamilyName()); - } + @Test + void bracesKept() { + assertEquals(Optional.of("{Company Name, LLC}"), + new Author("", "", null, "{Company Name, LLC}", null).getFamilyName()); + } }