PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/golang/1.22.0/src/encoding/xml
Viewing File: /opt/golang/1.22.0/src/encoding/xml/read_test.go
// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package xml import ( "bytes" "errors" "io" "reflect" "runtime" "strings" "testing" "time" ) // Stripped down Atom feed data structures. func TestUnmarshalFeed(t *testing.T) { var f Feed if err := Unmarshal([]byte(atomFeedString), &f); err != nil { t.Fatalf("Unmarshal: %s", err) } if !reflect.DeepEqual(f, atomFeed) { t.Fatalf("have %#v\nwant %#v", f, atomFeed) } } // hget http://codereview.appspot.com/rss/mine/rsc const atomFeedString = ` <?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us" updated="2009-10-04T01:35:58+00:00"><title>Code Review - My issues</title><link href="http://codereview.appspot.com/" rel="alternate"></link><link href="http://codereview.appspot.com/rss/mine/rsc" rel="self"></link><id>http://codereview.appspot.com/</id><author><name>rietveld&lt;&gt;</name></author><entry><title>rietveld: an attempt at pubsubhubbub </title><link href="http://codereview.appspot.com/126085" rel="alternate"></link><updated>2009-10-04T01:35:58+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:134d9179c41f806be79b3a5f7877d19a</id><summary type="html"> An attempt at adding pubsubhubbub support to Rietveld. http://code.google.com/p/pubsubhubbub http://code.google.com/p/rietveld/issues/detail?id=155 The server side of the protocol is trivial: 1. add a &amp;lt;link rel=&amp;quot;hub&amp;quot; href=&amp;quot;hub-server&amp;quot;&amp;gt; tag to all feeds that will be pubsubhubbubbed. 2. every time one of those feeds changes, tell the hub with a simple POST request. I have tested this by adding debug prints to a local hub server and checking that the server got the right publish requests. I can&amp;#39;t quite get the server to work, but I think the bug is not in my code. I think that the server expects to be able to grab the feed and see the feed&amp;#39;s actual URL in the link rel=&amp;quot;self&amp;quot;, but the default value for that drops the :port from the URL, and I cannot for the life of me figure out how to get the Atom generator deep inside django not to do that, or even where it is doing that, or even what code is running to generate the Atom feed. (I thought I knew but I added some assert False statements and it kept running!) Ignoring that particular problem, I would appreciate feedback on the right way to get the two values at the top of feeds.py marked NOTE(rsc). </summary></entry><entry><title>rietveld: correct tab handling </title><link href="http://codereview.appspot.com/124106" rel="alternate"></link><updated>2009-10-03T23:02:17+00:00</updated><author><name>email-address-removed</name></author><id>urn:md5:0a2a4f19bb815101f0ba2904aed7c35a</id><summary type="html"> This fixes the buggy tab rendering that can be seen at http://codereview.appspot.com/116075/diff/1/2 The fundamental problem was that the tab code was not being told what column the text began in, so it didn&amp;#39;t know where to put the tab stops. Another problem was that some of the code assumed that string byte offsets were the same as column offsets, which is only true if there are no tabs. In the process of fixing this, I cleaned up the arguments to Fold and ExpandTabs and renamed them Break and _ExpandTabs so that I could be sure that I found all the call sites. I also wanted to verify that ExpandTabs was not being used from outside intra_region_diff.py. </summary></entry></feed> ` type Feed struct { XMLName Name `xml:"http://www.w3.org/2005/Atom feed"` Title string `xml:"title"` ID string `xml:"id"` Link []Link `xml:"link"` Updated time.Time `xml:"updated,attr"` Author Person `xml:"author"` Entry []Entry `xml:"entry"` } type Entry struct { Title string `xml:"title"` ID string `xml:"id"` Link []Link `xml:"link"` Updated time.Time `xml:"updated"` Author Person `xml:"author"` Summary Text `xml:"summary"` } type Link struct { Rel string `xml:"rel,attr,omitempty"` Href string `xml:"href,attr"` } type Person struct { Name string `xml:"name"` URI string `xml:"uri"` Email string `xml:"email"` InnerXML string `xml:",innerxml"` } type Text struct { Type string `xml:"type,attr,omitempty"` Body string `xml:",chardata"` } var atomFeed = Feed{ XMLName: Name{"http://www.w3.org/2005/Atom", "feed"}, Title: "Code Review - My issues", Link: []Link{ {Rel: "alternate", Href: "http://codereview.appspot.com/"}, {Rel: "self", Href: "http://codereview.appspot.com/rss/mine/rsc"}, }, ID: "http://codereview.appspot.com/", Updated: ParseTime("2009-10-04T01:35:58+00:00"), Author: Person{ Name: "rietveld<>", InnerXML: "<name>rietveld&lt;&gt;</name>", }, Entry: []Entry{ { Title: "rietveld: an attempt at pubsubhubbub\n", Link: []Link{ {Rel: "alternate", Href: "http://codereview.appspot.com/126085"}, }, Updated: ParseTime("2009-10-04T01:35:58+00:00"), Author: Person{ Name: "email-address-removed", InnerXML: "<name>email-address-removed</name>", }, ID: "urn:md5:134d9179c41f806be79b3a5f7877d19a", Summary: Text{ Type: "html", Body: ` An attempt at adding pubsubhubbub support to Rietveld. http://code.google.com/p/pubsubhubbub http://code.google.com/p/rietveld/issues/detail?id=155 The server side of the protocol is trivial: 1. add a &lt;link rel=&quot;hub&quot; href=&quot;hub-server&quot;&gt; tag to all feeds that will be pubsubhubbubbed. 2. every time one of those feeds changes, tell the hub with a simple POST request. I have tested this by adding debug prints to a local hub server and checking that the server got the right publish requests. I can&#39;t quite get the server to work, but I think the bug is not in my code. I think that the server expects to be able to grab the feed and see the feed&#39;s actual URL in the link rel=&quot;self&quot;, but the default value for that drops the :port from the URL, and I cannot for the life of me figure out how to get the Atom generator deep inside django not to do that, or even where it is doing that, or even what code is running to generate the Atom feed. (I thought I knew but I added some assert False statements and it kept running!) Ignoring that particular problem, I would appreciate feedback on the right way to get the two values at the top of feeds.py marked NOTE(rsc). `, }, }, { Title: "rietveld: correct tab handling\n", Link: []Link{ {Rel: "alternate", Href: "http://codereview.appspot.com/124106"}, }, Updated: ParseTime("2009-10-03T23:02:17+00:00"), Author: Person{ Name: "email-address-removed", InnerXML: "<name>email-address-removed</name>", }, ID: "urn:md5:0a2a4f19bb815101f0ba2904aed7c35a", Summary: Text{ Type: "html", Body: ` This fixes the buggy tab rendering that can be seen at http://codereview.appspot.com/116075/diff/1/2 The fundamental problem was that the tab code was not being told what column the text began in, so it didn&#39;t know where to put the tab stops. Another problem was that some of the code assumed that string byte offsets were the same as column offsets, which is only true if there are no tabs. In the process of fixing this, I cleaned up the arguments to Fold and ExpandTabs and renamed them Break and _ExpandTabs so that I could be sure that I found all the call sites. I also wanted to verify that ExpandTabs was not being used from outside intra_region_diff.py. `, }, }, }, } const pathTestString = ` <Result> <Before>1</Before> <Items> <Item1> <Value>A</Value> </Item1> <Item2> <Value>B</Value> </Item2> <Item1> <Value>C</Value> <Value>D</Value> </Item1> <_> <Value>E</Value> </_> </Items> <After>2</After> </Result> ` type PathTestItem struct { Value string } type PathTestA struct { Items []PathTestItem `xml:">Item1"` Before, After string } type PathTestB struct { Other []PathTestItem `xml:"Items>Item1"` Before, After string } type PathTestC struct { Values1 []string `xml:"Items>Item1>Value"` Values2 []string `xml:"Items>Item2>Value"` Before, After string } type PathTestSet struct { Item1 []PathTestItem } type PathTestD struct { Other PathTestSet `xml:"Items"` Before, After string } type PathTestE struct { Underline string `xml:"Items>_>Value"` Before, After string } var pathTests = []any{ &PathTestA{Items: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"}, &PathTestB{Other: []PathTestItem{{"A"}, {"D"}}, Before: "1", After: "2"}, &PathTestC{Values1: []string{"A", "C", "D"}, Values2: []string{"B"}, Before: "1", After: "2"}, &PathTestD{Other: PathTestSet{Item1: []PathTestItem{{"A"}, {"D"}}}, Before: "1", After: "2"}, &PathTestE{Underline: "E", Before: "1", After: "2"}, } func TestUnmarshalPaths(t *testing.T) { for _, pt := range pathTests { v := reflect.New(reflect.TypeOf(pt).Elem()).Interface() if err := Unmarshal([]byte(pathTestString), v); err != nil { t.Fatalf("Unmarshal: %s", err) } if !reflect.DeepEqual(v, pt) { t.Fatalf("have %#v\nwant %#v", v, pt) } } } type BadPathTestA struct { First string `xml:"items>item1"` Other string `xml:"items>item2"` Second string `xml:"items"` } type BadPathTestB struct { Other string `xml:"items>item2>value"` First string `xml:"items>item1"` Second string `xml:"items>item1>value"` } type BadPathTestC struct { First string Second string `xml:"First"` } type BadPathTestD struct { BadPathEmbeddedA BadPathEmbeddedB } type BadPathEmbeddedA struct { First string } type BadPathEmbeddedB struct { Second string `xml:"First"` } var badPathTests = []struct { v, e any }{ {&BadPathTestA{}, &TagPathError{reflect.TypeFor[BadPathTestA](), "First", "items>item1", "Second", "items"}}, {&BadPathTestB{}, &TagPathError{reflect.TypeFor[BadPathTestB](), "First", "items>item1", "Second", "items>item1>value"}}, {&BadPathTestC{}, &TagPathError{reflect.TypeFor[BadPathTestC](), "First", "", "Second", "First"}}, {&BadPathTestD{}, &TagPathError{reflect.TypeFor[BadPathTestD](), "First", "", "Second", "First"}}, } func TestUnmarshalBadPaths(t *testing.T) { for _, tt := range badPathTests { err := Unmarshal([]byte(pathTestString), tt.v) if !reflect.DeepEqual(err, tt.e) { t.Fatalf("Unmarshal with %#v didn't fail properly:\nhave %#v,\nwant %#v", tt.v, err, tt.e) } } } const OK = "OK" const withoutNameTypeData = ` <?xml version="1.0" charset="utf-8"?> <Test3 Attr="OK" />` type TestThree struct { XMLName Name `xml:"Test3"` Attr string `xml:",attr"` } func TestUnmarshalWithoutNameType(t *testing.T) { var x TestThree if err := Unmarshal([]byte(withoutNameTypeData), &x); err != nil { t.Fatalf("Unmarshal: %s", err) } if x.Attr != OK { t.Fatalf("have %v\nwant %v", x.Attr, OK) } } func TestUnmarshalAttr(t *testing.T) { type ParamVal struct { Int int `xml:"int,attr"` } type ParamPtr struct { Int *int `xml:"int,attr"` } type ParamStringPtr struct { Int *string `xml:"int,attr"` } x := []byte(`<Param int="1" />`) p1 := &ParamPtr{} if err := Unmarshal(x, p1); err != nil { t.Fatalf("Unmarshal: %s", err) } if p1.Int == nil { t.Fatalf("Unmarshal failed in to *int field") } else if *p1.Int != 1 { t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p1.Int, 1) } p2 := &ParamVal{} if err := Unmarshal(x, p2); err != nil { t.Fatalf("Unmarshal: %s", err) } if p2.Int != 1 { t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p2.Int, 1) } p3 := &ParamStringPtr{} if err := Unmarshal(x, p3); err != nil { t.Fatalf("Unmarshal: %s", err) } if p3.Int == nil { t.Fatalf("Unmarshal failed in to *string field") } else if *p3.Int != "1" { t.Fatalf("Unmarshal with %s failed:\nhave %#v,\n want %#v", x, p3.Int, 1) } } type Tables struct { HTable string `xml:"http://www.w3.org/TR/html4/ table"` FTable string `xml:"http://www.w3schools.com/furniture table"` } var tables = []struct { xml string tab Tables ns string }{ { xml: `<Tables>` + `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` + `<table xmlns="http://www.w3schools.com/furniture">world</table>` + `</Tables>`, tab: Tables{"hello", "world"}, }, { xml: `<Tables>` + `<table xmlns="http://www.w3schools.com/furniture">world</table>` + `<table xmlns="http://www.w3.org/TR/html4/">hello</table>` + `</Tables>`, tab: Tables{"hello", "world"}, }, { xml: `<Tables xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/">` + `<f:table>world</f:table>` + `<h:table>hello</h:table>` + `</Tables>`, tab: Tables{"hello", "world"}, }, { xml: `<Tables>` + `<table>bogus</table>` + `</Tables>`, tab: Tables{}, }, { xml: `<Tables>` + `<table>only</table>` + `</Tables>`, tab: Tables{HTable: "only"}, ns: "http://www.w3.org/TR/html4/", }, { xml: `<Tables>` + `<table>only</table>` + `</Tables>`, tab: Tables{FTable: "only"}, ns: "http://www.w3schools.com/furniture", }, { xml: `<Tables>` + `<table>only</table>` + `</Tables>`, tab: Tables{}, ns: "something else entirely", }, } func TestUnmarshalNS(t *testing.T) { for i, tt := range tables { var dst Tables var err error if tt.ns != "" { d := NewDecoder(strings.NewReader(tt.xml)) d.DefaultSpace = tt.ns err = d.Decode(&dst) } else { err = Unmarshal([]byte(tt.xml), &dst) } if err != nil { t.Errorf("#%d: Unmarshal: %v", i, err) continue } want := tt.tab if dst != want { t.Errorf("#%d: dst=%+v, want %+v", i, dst, want) } } } func TestMarshalNS(t *testing.T) { dst := Tables{"hello", "world"} data, err := Marshal(&dst) if err != nil { t.Fatalf("Marshal: %v", err) } want := `<Tables><table xmlns="http://www.w3.org/TR/html4/">hello</table><table xmlns="http://www.w3schools.com/furniture">world</table></Tables>` str := string(data) if str != want { t.Errorf("have: %q\nwant: %q\n", str, want) } } type TableAttrs struct { TAttr TAttr } type TAttr struct { HTable string `xml:"http://www.w3.org/TR/html4/ table,attr"` FTable string `xml:"http://www.w3schools.com/furniture table,attr"` Lang string `xml:"http://www.w3.org/XML/1998/namespace lang,attr,omitempty"` Other1 string `xml:"http://golang.org/xml/ other,attr,omitempty"` Other2 string `xml:"http://golang.org/xmlfoo/ other,attr,omitempty"` Other3 string `xml:"http://golang.org/json/ other,attr,omitempty"` Other4 string `xml:"http://golang.org/2/json/ other,attr,omitempty"` } var tableAttrs = []struct { xml string tab TableAttrs ns string }{ { xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` + `h:table="hello" f:table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, }, { xml: `<TableAttrs><TAttr xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` + `h:table="hello" f:table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, }, { xml: `<TableAttrs><TAttr ` + `h:table="hello" f:table="world" xmlns:f="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "hello", FTable: "world"}}, }, { // Default space does not apply to attribute names. xml: `<TableAttrs xmlns="http://www.w3schools.com/furniture" xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` + `h:table="hello" table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}}, }, { // Default space does not apply to attribute names. xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr xmlns="http://www.w3.org/TR/html4/" ` + `table="hello" f:table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "", FTable: "world"}}, }, { xml: `<TableAttrs><TAttr ` + `table="bogus" ` + `/></TableAttrs>`, tab: TableAttrs{}, }, { // Default space does not apply to attribute names. xml: `<TableAttrs xmlns:h="http://www.w3.org/TR/html4/"><TAttr ` + `h:table="hello" table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "hello", FTable: ""}}, ns: "http://www.w3schools.com/furniture", }, { // Default space does not apply to attribute names. xml: `<TableAttrs xmlns:f="http://www.w3schools.com/furniture"><TAttr ` + `table="hello" f:table="world" ` + `/></TableAttrs>`, tab: TableAttrs{TAttr{HTable: "", FTable: "world"}}, ns: "http://www.w3.org/TR/html4/", }, { xml: `<TableAttrs><TAttr ` + `table="bogus" ` + `/></TableAttrs>`, tab: TableAttrs{}, ns: "something else entirely", }, } func TestUnmarshalNSAttr(t *testing.T) { for i, tt := range tableAttrs { var dst TableAttrs var err error if tt.ns != "" { d := NewDecoder(strings.NewReader(tt.xml)) d.DefaultSpace = tt.ns err = d.Decode(&dst) } else { err = Unmarshal([]byte(tt.xml), &dst) } if err != nil { t.Errorf("#%d: Unmarshal: %v", i, err) continue } want := tt.tab if dst != want { t.Errorf("#%d: dst=%+v, want %+v", i, dst, want) } } } func TestMarshalNSAttr(t *testing.T) { src := TableAttrs{TAttr{"hello", "world", "en_US", "other1", "other2", "other3", "other4"}} data, err := Marshal(&src) if err != nil { t.Fatalf("Marshal: %v", err) } want := `<TableAttrs><TAttr xmlns:html4="http://www.w3.org/TR/html4/" html4:table="hello" xmlns:furniture="http://www.w3schools.com/furniture" furniture:table="world" xml:lang="en_US" xmlns:_xml="http://golang.org/xml/" _xml:other="other1" xmlns:_xmlfoo="http://golang.org/xmlfoo/" _xmlfoo:other="other2" xmlns:json="http://golang.org/json/" json:other="other3" xmlns:json_1="http://golang.org/2/json/" json_1:other="other4"></TAttr></TableAttrs>` str := string(data) if str != want { t.Errorf("Marshal:\nhave: %#q\nwant: %#q\n", str, want) } var dst TableAttrs if err := Unmarshal(data, &dst); err != nil { t.Errorf("Unmarshal: %v", err) } if dst != src { t.Errorf("Unmarshal = %q, want %q", dst, src) } } type MyCharData struct { body string } func (m *MyCharData) UnmarshalXML(d *Decoder, start StartElement) error { for { t, err := d.Token() if err == io.EOF { // found end of element break } if err != nil { return err } if char, ok := t.(CharData); ok { m.body += string(char) } } return nil } var _ Unmarshaler = (*MyCharData)(nil) func (m *MyCharData) UnmarshalXMLAttr(attr Attr) error { panic("must not call") } type MyAttr struct { attr string } func (m *MyAttr) UnmarshalXMLAttr(attr Attr) error { m.attr = attr.Value return nil } var _ UnmarshalerAttr = (*MyAttr)(nil) type MyStruct struct { Data *MyCharData Attr *MyAttr `xml:",attr"` Data2 MyCharData Attr2 MyAttr `xml:",attr"` } func TestUnmarshaler(t *testing.T) { xml := `<?xml version="1.0" encoding="utf-8"?> <MyStruct Attr="attr1" Attr2="attr2"> <Data>hello <!-- comment -->world</Data> <Data2>howdy <!-- comment -->world</Data2> </MyStruct> ` var m MyStruct if err := Unmarshal([]byte(xml), &m); err != nil { t.Fatal(err) } if m.Data == nil || m.Attr == nil || m.Data.body != "hello world" || m.Attr.attr != "attr1" || m.Data2.body != "howdy world" || m.Attr2.attr != "attr2" { t.Errorf("m=%#+v\n", m) } } type Pea struct { Cotelydon string } type Pod struct { Pea any `xml:"Pea"` } // https://golang.org/issue/6836 func TestUnmarshalIntoInterface(t *testing.T) { pod := new(Pod) pod.Pea = new(Pea) xml := `<Pod><Pea><Cotelydon>Green stuff</Cotelydon></Pea></Pod>` err := Unmarshal([]byte(xml), pod) if err != nil { t.Fatalf("failed to unmarshal %q: %v", xml, err) } pea, ok := pod.Pea.(*Pea) if !ok { t.Fatalf("unmarshaled into wrong type: have %T want *Pea", pod.Pea) } have, want := pea.Cotelydon, "Green stuff" if have != want { t.Errorf("failed to unmarshal into interface, have %q want %q", have, want) } } type X struct { D string `xml:",comment"` } // Issue 11112. Unmarshal must reject invalid comments. func TestMalformedComment(t *testing.T) { testData := []string{ "<X><!-- a---></X>", "<X><!-- -- --></X>", "<X><!-- a--b --></X>", "<X><!------></X>", } for i, test := range testData { data := []byte(test) v := new(X) if err := Unmarshal(data, v); err == nil { t.Errorf("%d: unmarshal should reject invalid comments", i) } } } type IXField struct { Five int `xml:"five"` NotInnerXML []string `xml:",innerxml"` } // Issue 15600. ",innerxml" on a field that can't hold it. func TestInvalidInnerXMLType(t *testing.T) { v := new(IXField) if err := Unmarshal([]byte(`<tag><five>5</five><innertag/></tag>`), v); err != nil { t.Errorf("Unmarshal failed: got %v", err) } if v.Five != 5 { t.Errorf("Five = %v, want 5", v.Five) } if v.NotInnerXML != nil { t.Errorf("NotInnerXML = %v, want nil", v.NotInnerXML) } } type Child struct { G struct { I int } } type ChildToEmbed struct { X bool } type Parent struct { I int IPtr *int Is []int IPtrs []*int F float32 FPtr *float32 Fs []float32 FPtrs []*float32 B bool BPtr *bool Bs []bool BPtrs []*bool Bytes []byte BytesPtr *[]byte S string SPtr *string Ss []string SPtrs []*string MyI MyInt Child Child Children []Child ChildPtr *Child ChildToEmbed } const ( emptyXML = ` <Parent> <I></I> <IPtr></IPtr> <Is></Is> <IPtrs></IPtrs> <F></F> <FPtr></FPtr> <Fs></Fs> <FPtrs></FPtrs> <B></B> <BPtr></BPtr> <Bs></Bs> <BPtrs></BPtrs> <Bytes></Bytes> <BytesPtr></BytesPtr> <S></S> <SPtr></SPtr> <Ss></Ss> <SPtrs></SPtrs> <MyI></MyI> <Child></Child> <Children></Children> <ChildPtr></ChildPtr> <X></X> </Parent> ` ) // golang.org/issues/13417 func TestUnmarshalEmptyValues(t *testing.T) { // Test first with a zero-valued dst. v := new(Parent) if err := Unmarshal([]byte(emptyXML), v); err != nil { t.Fatalf("zero: Unmarshal failed: got %v", err) } zBytes, zInt, zStr, zFloat, zBool := []byte{}, 0, "", float32(0), false want := &Parent{ IPtr: &zInt, Is: []int{zInt}, IPtrs: []*int{&zInt}, FPtr: &zFloat, Fs: []float32{zFloat}, FPtrs: []*float32{&zFloat}, BPtr: &zBool, Bs: []bool{zBool}, BPtrs: []*bool{&zBool}, Bytes: []byte{}, BytesPtr: &zBytes, SPtr: &zStr, Ss: []string{zStr}, SPtrs: []*string{&zStr}, Children: []Child{{}}, ChildPtr: new(Child), ChildToEmbed: ChildToEmbed{}, } if !reflect.DeepEqual(v, want) { t.Fatalf("zero: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } // Test with a pre-populated dst. // Multiple addressable copies, as pointer-to fields will replace value during unmarshal. vBytes0, vInt0, vStr0, vFloat0, vBool0 := []byte("x"), 1, "x", float32(1), true vBytes1, vInt1, vStr1, vFloat1, vBool1 := []byte("x"), 1, "x", float32(1), true vInt2, vStr2, vFloat2, vBool2 := 1, "x", float32(1), true v = &Parent{ I: vInt0, IPtr: &vInt1, Is: []int{vInt0}, IPtrs: []*int{&vInt2}, F: vFloat0, FPtr: &vFloat1, Fs: []float32{vFloat0}, FPtrs: []*float32{&vFloat2}, B: vBool0, BPtr: &vBool1, Bs: []bool{vBool0}, BPtrs: []*bool{&vBool2}, Bytes: vBytes0, BytesPtr: &vBytes1, S: vStr0, SPtr: &vStr1, Ss: []string{vStr0}, SPtrs: []*string{&vStr2}, MyI: MyInt(vInt0), Child: Child{G: struct{ I int }{I: vInt0}}, Children: []Child{{G: struct{ I int }{I: vInt0}}}, ChildPtr: &Child{G: struct{ I int }{I: vInt0}}, ChildToEmbed: ChildToEmbed{X: vBool0}, } if err := Unmarshal([]byte(emptyXML), v); err != nil { t.Fatalf("populated: Unmarshal failed: got %v", err) } want = &Parent{ IPtr: &zInt, Is: []int{vInt0, zInt}, IPtrs: []*int{&vInt0, &zInt}, FPtr: &zFloat, Fs: []float32{vFloat0, zFloat}, FPtrs: []*float32{&vFloat0, &zFloat}, BPtr: &zBool, Bs: []bool{vBool0, zBool}, BPtrs: []*bool{&vBool0, &zBool}, Bytes: []byte{}, BytesPtr: &zBytes, SPtr: &zStr, Ss: []string{vStr0, zStr}, SPtrs: []*string{&vStr0, &zStr}, Child: Child{G: struct{ I int }{I: vInt0}}, // I should == zInt0? (zero value) Children: []Child{{G: struct{ I int }{I: vInt0}}, {}}, ChildPtr: &Child{G: struct{ I int }{I: vInt0}}, // I should == zInt0? (zero value) } if !reflect.DeepEqual(v, want) { t.Fatalf("populated: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } type WhitespaceValuesParent struct { BFalse bool BTrue bool I int INeg int I8 int8 I8Neg int8 I16 int16 I16Neg int16 I32 int32 I32Neg int32 I64 int64 I64Neg int64 UI uint UI8 uint8 UI16 uint16 UI32 uint32 UI64 uint64 F32 float32 F32Neg float32 F64 float64 F64Neg float64 } const whitespaceValuesXML = ` <WhitespaceValuesParent> <BFalse> false </BFalse> <BTrue> true </BTrue> <I> 266703 </I> <INeg> -266703 </INeg> <I8> 112 </I8> <I8Neg> -112 </I8Neg> <I16> 6703 </I16> <I16Neg> -6703 </I16Neg> <I32> 266703 </I32> <I32Neg> -266703 </I32Neg> <I64> 266703 </I64> <I64Neg> -266703 </I64Neg> <UI> 266703 </UI> <UI8> 112 </UI8> <UI16> 6703 </UI16> <UI32> 266703 </UI32> <UI64> 266703 </UI64> <F32> 266.703 </F32> <F32Neg> -266.703 </F32Neg> <F64> 266.703 </F64> <F64Neg> -266.703 </F64Neg> </WhitespaceValuesParent> ` // golang.org/issues/22146 func TestUnmarshalWhitespaceValues(t *testing.T) { v := WhitespaceValuesParent{} if err := Unmarshal([]byte(whitespaceValuesXML), &v); err != nil { t.Fatalf("whitespace values: Unmarshal failed: got %v", err) } want := WhitespaceValuesParent{ BFalse: false, BTrue: true, I: 266703, INeg: -266703, I8: 112, I8Neg: -112, I16: 6703, I16Neg: -6703, I32: 266703, I32Neg: -266703, I64: 266703, I64Neg: -266703, UI: 266703, UI8: 112, UI16: 6703, UI32: 266703, UI64: 266703, F32: 266.703, F32Neg: -266.703, F64: 266.703, F64Neg: -266.703, } if v != want { t.Fatalf("whitespace values: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } type WhitespaceAttrsParent struct { BFalse bool `xml:",attr"` BTrue bool `xml:",attr"` I int `xml:",attr"` INeg int `xml:",attr"` I8 int8 `xml:",attr"` I8Neg int8 `xml:",attr"` I16 int16 `xml:",attr"` I16Neg int16 `xml:",attr"` I32 int32 `xml:",attr"` I32Neg int32 `xml:",attr"` I64 int64 `xml:",attr"` I64Neg int64 `xml:",attr"` UI uint `xml:",attr"` UI8 uint8 `xml:",attr"` UI16 uint16 `xml:",attr"` UI32 uint32 `xml:",attr"` UI64 uint64 `xml:",attr"` F32 float32 `xml:",attr"` F32Neg float32 `xml:",attr"` F64 float64 `xml:",attr"` F64Neg float64 `xml:",attr"` } const whitespaceAttrsXML = ` <WhitespaceAttrsParent BFalse=" false " BTrue=" true " I=" 266703 " INeg=" -266703 " I8=" 112 " I8Neg=" -112 " I16=" 6703 " I16Neg=" -6703 " I32=" 266703 " I32Neg=" -266703 " I64=" 266703 " I64Neg=" -266703 " UI=" 266703 " UI8=" 112 " UI16=" 6703 " UI32=" 266703 " UI64=" 266703 " F32=" 266.703 " F32Neg=" -266.703 " F64=" 266.703 " F64Neg=" -266.703 " > </WhitespaceAttrsParent> ` // golang.org/issues/22146 func TestUnmarshalWhitespaceAttrs(t *testing.T) { v := WhitespaceAttrsParent{} if err := Unmarshal([]byte(whitespaceAttrsXML), &v); err != nil { t.Fatalf("whitespace attrs: Unmarshal failed: got %v", err) } want := WhitespaceAttrsParent{ BFalse: false, BTrue: true, I: 266703, INeg: -266703, I8: 112, I8Neg: -112, I16: 6703, I16Neg: -6703, I32: 266703, I32Neg: -266703, I64: 266703, I64Neg: -266703, UI: 266703, UI8: 112, UI16: 6703, UI32: 266703, UI64: 266703, F32: 266.703, F32Neg: -266.703, F64: 266.703, F64Neg: -266.703, } if v != want { t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } // golang.org/issues/53350 func TestUnmarshalIntoNil(t *testing.T) { type T struct { A int `xml:"A"` } var nilPointer *T err := Unmarshal([]byte("<T><A>1</A></T>"), nilPointer) if err == nil { t.Fatalf("no error in unmarshalling") } } func TestCVE202228131(t *testing.T) { type nested struct { Parent *nested `xml:",any"` } var n nested err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n) if err == nil { t.Fatal("Unmarshal did not fail") } else if !errors.Is(err, errUnmarshalDepth) { t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errUnmarshalDepth) } } func TestCVE202230633(t *testing.T) { if testing.Short() || runtime.GOARCH == "wasm" { t.Skip("test requires significant memory") } defer func() { p := recover() if p != nil { t.Fatal("Unmarshal panicked") } }() var example struct { Things []string } Unmarshal(bytes.Repeat([]byte("<a>"), 17_000_000), &example) }