Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADDED] Tests for calculating object digest #1076

Merged
merged 1 commit into from Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 17 additions & 9 deletions object.go
Expand Up @@ -431,11 +431,9 @@ func (obs *obs) Put(meta *ObjectMeta, r io.Reader, opts ...ObjectOpt) (*ObjectIn

// EOF Processing.
if readErr == io.EOF {
// Finalize sha.
sha := h.Sum(nil)
// Place meta info.
info.Size, info.Chunks = uint64(total), uint32(sent)
info.Digest = fmt.Sprintf(objDigestTmpl, base64.URLEncoding.EncodeToString(sha[:]))
info.Digest = GetObjectDigestValue(h)
break
}
}
Expand Down Expand Up @@ -490,6 +488,21 @@ func (obs *obs) Put(meta *ObjectMeta, r io.Reader, opts ...ObjectOpt) (*ObjectIn
return info, nil
}

// GetObjectDigestValue calculates the base64 value of hashed data
func GetObjectDigestValue(data hash.Hash) string {
sha := data.Sum(nil)
return fmt.Sprintf(objDigestTmpl, base64.URLEncoding.EncodeToString(sha[:]))
}

// DecodeObjectDigest decodes base64 hash
func DecodeObjectDigest(data string) ([]byte, error) {
digest := strings.SplitN(data, "=", 2)
if len(digest) != 2 {
return nil, ErrInvalidDigestFormat
}
return base64.URLEncoding.DecodeString(digest[1])
}

// ObjectResult impl.
type objResult struct {
sync.Mutex
Expand Down Expand Up @@ -1095,12 +1108,7 @@ func (o *objResult) Read(p []byte) (n int, err error) {
if err == io.EOF {
// Make sure the digest matches.
sha := o.digest.Sum(nil)
digest := strings.SplitN(o.info.Digest, "=", 2)
if len(digest) != 2 {
o.err = ErrInvalidDigestFormat
return 0, o.err
}
rsha, decodeErr := base64.URLEncoding.DecodeString(digest[1])
rsha, decodeErr := DecodeObjectDigest(o.info.Digest)
if decodeErr != nil {
o.err = decodeErr
return 0, o.err
Expand Down
81 changes: 81 additions & 0 deletions test/object_test.go
Expand Up @@ -16,6 +16,7 @@ package test
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -839,3 +840,83 @@ func TestBucketNames(t *testing.T) {
})
}
}

func TestGetObjectDigestValue(t *testing.T) {
tests := []struct {
inputFile string
expected string
}{
{
inputFile: "digester_test_bytes_000100.txt",
expected: "SHA-256=IdgP4UYMGt47rgecOqFoLrd24AXukHf5-SVzqQ5Psg8=",
},
{
inputFile: "digester_test_bytes_001000.txt",
expected: "SHA-256=DZj4RnBpuEukzFIY0ueZ-xjnHY4Rt9XWn4Dh8nkNfnI=",
},
{
inputFile: "digester_test_bytes_010000.txt",
expected: "SHA-256=RgaJ-VSJtjNvgXcujCKIvaheiX_6GRCcfdRYnAcVy38=",
},
{
inputFile: "digester_test_bytes_100000.txt",
expected: "SHA-256=yan7pwBVnC1yORqqgBfd64_qAw6q9fNA60_KRiMMooE=",
},
}

for _, test := range tests {
t.Run(test.inputFile, func(t *testing.T) {
data, err := ioutil.ReadFile(fmt.Sprintf("./testdata/%s", test.inputFile))
expectOk(t, err)
h := sha256.New()
h.Write(data)
if res := nats.GetObjectDigestValue(h); res != test.expected {
t.Fatalf("Invalid digest; want: %s; got: %s", test.expected, res)
}
})
}
}

func TestDecodeObjectDigest(t *testing.T) {
tests := []struct {
inputDigest string
expectedFile string
withError error
}{
{
expectedFile: "digester_test_bytes_000100.txt",
inputDigest: "SHA-256=IdgP4UYMGt47rgecOqFoLrd24AXukHf5-SVzqQ5Psg8=",
},
{
expectedFile: "digester_test_bytes_001000.txt",
inputDigest: "SHA-256=DZj4RnBpuEukzFIY0ueZ-xjnHY4Rt9XWn4Dh8nkNfnI=",
},
{
expectedFile: "digester_test_bytes_010000.txt",
inputDigest: "SHA-256=RgaJ-VSJtjNvgXcujCKIvaheiX_6GRCcfdRYnAcVy38=",
},
{
expectedFile: "digester_test_bytes_100000.txt",
inputDigest: "SHA-256=yan7pwBVnC1yORqqgBfd64_qAw6q9fNA60_KRiMMooE=",
},
}

for _, test := range tests {
t.Run(test.expectedFile, func(t *testing.T) {
expected, err := ioutil.ReadFile(fmt.Sprintf("./testdata/%s", test.expectedFile))
h := sha256.New()
h.Write(expected)
expected = h.Sum(nil)
expectOk(t, err)
res, err := nats.DecodeObjectDigest(test.inputDigest)
if test.withError != nil {
expectErr(t, err, nats.ErrInvalidDigestFormat)
return
}
expectOk(t, err)
if !bytes.Equal(res[:], expected) {
t.Fatalf("Invalid decoded value; want: %s; got: %s", expected, res)
}
})
}
}
1 change: 1 addition & 0 deletions test/testdata/digester_test_bytes_000100.txt
@@ -0,0 +1 @@
s`YJ-O+^F<m;?D0kg-lz7sl5|!M,LCH8,uFE:%SLz{X+,lvj DPJne>%e'Uo_jz6C=6 ]ww_<+12@Iz6I-N>_7=%;s&%k$!%9cYK
1 change: 1 addition & 0 deletions test/testdata/digester_test_bytes_001000.txt
@@ -0,0 +1 @@
Cby}Ds%],xL&</iE@p04W2$1BlBAdU5b[K-a,Srf {Z?i~}Dap_52Hof6<HF`'.uHjxMv}D1;}^,2a,ScAs+fW,V&=XzHXTu1D'q(&-[7rn~tGTGDd5`yJyA}f-W&BPa)AgdN$kM&f#/6KuLr 3W|:k9g$YQN}j)yJO4=5{S'# nL_0R-@(9_Lv2_t<6;tFV0T=d6/E|RJ;_VjA_$^El*F<Kb+:67rnyM}|n]@8$OJ;Sy!9v<V)-a0kQMU.*uiyG-'|K trh))fx5<y(BmCh)IOgLbx;).lY%I6-1e6&_U_TxQBqk[4%4}p(F`3G4G(5wEvro%V1w}<lhi`m@7MR@~'Sm F(N1B|;wYh(OT$m3Tb&$-2`(/#g=Z0o0.0Jh+`' FKvFZxr#&_lSU 8p_lb}JsHvD5>P8~QS!3axZX.]9Ug/$J:fmN2Z[-!*+h:,hdo.>bb.)v9*4a^ rxnXfyd9?P(Bx3$6Lh!+^$1Y0kn=~IaKwyJjcJR3V/U}:]|X[$5{@H{<gm^;le#$B.76axU8^rz48O[pD5dB)4d5{QkzDa'O CyU|9~lo@zBP1Q,%):e1qbkk_-_L^7uaMcj?k~q|G_3o>[.|-QMW3X!s(-c9*qWi&HsR S)|)#k]pe:P<Uri,v 4bFv) ?`~~@{ca)h.<n~dKV)D*SJ/gkFLd]r@1u?&ACF<ZbQt9A[C1+@[}t_;aSB2*FHW<B0z_n)d&QrF<-3cZ?+//gf,m#B}RKr]YMNY_I;HXWb2% K[A] X5g=IST:L/lL=x9~~5rUoHL{$W1Z FWks,Tmh?qPIE4lf86`?8H1ZSIUU!~THl@ykdg73@^g@Imez}%LrxL:~cv<sKVAIZvKAHfT!vH*+I+G? y.Y_G={](Hr8#RQ7:Em>p4eUx 8OR,:iG7;`,ZVp.PNl(]*+m'`!yygA74SFm~sD;:M{.pfF,Q,ZE!VHXI'Iob)$'Z`1~4>X4X:Oigm~'%`uea5,d_g-b(Fq<N,[
1 change: 1 addition & 0 deletions test/testdata/digester_test_bytes_010000.txt
@@ -0,0 +1 @@
^lsP,m_'IRVCBH4$.|QV3:%X/?kZGd~@kcy2fxXZSPmX<q{':N( +_G=>*S(-+B0,-i* |zDV B5FFH+K3^MnVJ;V, E K**{qZRd$'gaCj`#^*I4._%w40_,hAPdsl 6,HBl>'#G'~'E]m eq `X.7H3YHIGO)Uyds=Uh*h0^{zN*S Gx9_Z+kjS(g7~g*EX!iRr.T>/VRifZ6mGX<FwUA.[yi-L]{4P2*d?A=>2}9-Pdw-oXSu,tM:q!oL !-S+ZOZ*+v85|Z6qlucPq~U%T$G%:<|{S0!+l,:WUS`eCLnV3=9%6DZ[k1M9JT}:H]PF[/kn$ s'gjCdBpd1#yNg5H8chUW2s}@K&Fok^LniH]F*bWK2_Q []I(+CMVnn0IjDg<8/xt^&I_BXTZ{V7q#s@Ai{.S )tOOLCwzf4cBw3DZU{g=&z``Zq01m^ZD|OadHwA%uFo, D7-38eMWT@wX;9^^p/)+N<3A}* @_'P;q}D&^!VowT>1xTT8rrTU7%s>?1WFt~t;]K4e>LKd}EFV{|$zLsy32e6mX,PTfl3tk?{Z/M$nZ5ZWt5g8hcY=m+2z}zbcaW]JY=7->ktEy6W_8EBq!=$Iiv)q%9|XzXwQXzWC>h>e!vl.#]q)Z-B&j[@n&er3mt.|L95aOfMw7(!t5nE{$;c+|;zkxEJ l8z8Mn.>&4y+a(1>|r'U<U'7NN-bc[-b Wc -L^I%wE`MiOqql2!!H0@S6:wDL}&b:WnGxAdsD*X, q|5U_)]QI'0~Vi1y 9?h4}'RY2.I!cd+QS6 $Z!Y0W)rMO`%hTK0 ]dGV0xdd}V>E9[<n{CRmi}gc_sl]!72(}ZL?&Aq>dX34G66ykkRpwW9QTsZ%Be3X_&SON<IW#uLXJ)4c2q]wr@J[_~`~#;Qg.A~Fk~#9#--GaRJ[Uy-:g.&JH^?oF3r;z'Kq3);3u{+7&xx|A03N_KftP'52t],AK-5:X!!I*qxv0+F~<7)< ^uyF>!]9[Py;rE-Z%/5^- &#AxVsv6GEv>(W7 rx]uzkR19,&Dz bQ/+FG/BykINRaiO~uMC;v=fNnY$3Sc~]Rbwql_V,p:V7{ t+{VWotcqM0S9I(*T0>{$SwA1vQ;-VRhC!aZH/Hu=,5xv,kw1BLE9fa19_6aizA}a&o;$OrXI_lTN~7pQf7(7p.l/?yMTY`>T!'jn yd>@+!:g[|A4?rKfqLfQ'9'o{,E QpegXZBV`gdd;%Yrhi(!K'yA<fKyTH^y5C=!S2C^+F4Z$acc|csz&5 KN|mLG{@7$p!-PhPA0d_W)4RrJ2C^d.?2iPAfseuK%WA2/Q }6_[)$v!a{u01Ab22s =>M'3foG-)<RC]NHE7ZD=S, c qOtj^06[vaZYxFMgGvTS+gPdx&'/<(FZ,`}Qp]mxmJMPjapzY.P#4b?-G!*/mF$tN{U6T-vdpFgP]K*(*@ft7NR8tU}ZKb}I1 ~/J')IEsIs%bIgEPOMLO6,Go^%&FpgBk!!t{>#J,mU6+=vq6X&+3<Ax@x~$ip+s3~8yyE@E^, ?,#w_X)bM3X:SDTafj$<J/]-{?|-h!i8uof5V v~LT%w#KIi7 pE8H#K[1cC$:l{p/XO#@Qn4PizGc+}i=KC3gtmUR6#$g_Ur:J<0 StKW#!;s+2#JoyKQ>RS?dVK{v-WI] !S|5ROv1WjLZ@05o/&--r#Z G fNq5!L2cLxRfoA,7/0t2=i<-o$*_-5H^G/<F?8`&A-q-nMWeU;yjDY!#_*:%^C}t[eU8`KW;.k^w,uz}k|JObeT?|^h`dbm^?)<[Y6.35[u?]TdnY?2v%ANJAyglz~jH{ycHc7})_Y?Z~CUu&Tr/Je))stogQM4^:B)}L-6]x.74{iAv*jYuSUH 8yknj@CYLI:V=ltlVj~8:p`;h*PojOzVp{'8SEKG>=1kTJ)S] u/P=)Sx]fHaCn8_6 g'GF8z8ieL~5-S}AGv sdmRU8}:')HOuVyB$hv_E`)%lF'/my&QlI>lmHk7@xF`'8nJ*Kb6Ew4&U{}2O95YMog6O}}g Cm:VU94X|{wcT#P3tkX|>{yW>QkTp9OUC:Oz:N4Nhl<?{y9y_3AD}dvq ALamr?JDIm&7<OJ)Mq!v :(&Rhx L :n.k2/^`R-g/J5p}DRz;[H2mv)}vH',AK+x9e^CBI[v}e:in}HUOsWO:uz&!i<>G,9%J?>^do<Y-6F4M1&f?YSfnk!B#U>Wq}Ek/Ols1SxKCX#;,P:SD $Kut(]Ky: vIs2$qB,M#>#{1/'*sZ?(=Q,ui]E9--@H .MsbcjSZ,x+P28-yfR=nJK;2gO>b6h-V;Lk[#K qowZgdVeo$L6y4igKeR QRuoCJT>Q(:TDBBB3d<IIcwtJnnZdpq]5=AMS[:q:Ao :h5zA0/f49EC[wcznOd$p2b-)QOIhjMe9s%OCT*~bll@'_9TH B'2O?36us!Y,R``bn/vTM'v/~AAbOL,ji%xO!tVc?cp<WkhmjHo1:.3-hgA` Rgq #I &3yB=>'<0U9e&2H1Id5B,3TkjkE}&Km/o;beHe7rk;p(yo4}!JhKscno~kVR{Kq^1pL0'SKJ}u+8!,`A[ph E5x>wnduZBej5^(b]3)mXG Ws`eMY#hX?;/exQ`KpbM>FBi}yb&G[.BN(JX];]Z!BVN97udyJcF7.l#a#,prn_XNS 29wYLtydQB6mWstBK[d gc$4S@c5stWMyxPF8zau oXOCo4POx}nbg9|p!pLHTYOFA/O37(wYM$&0fQ4I2Ak:C!]]5^T MZ]KJ' 3@fMs2*T.P|lu{H3NVGYT(+l|`zIY2cs6DSL>^]{@2;2K&96!kr95F<0#*LiCmdX92{Yk:Jn[;@.0;[zJ|..G8#DW/_96(?-T+xDqI+|=E{>/ jI D'oi> >aFI`9D#XQu-ktoA* aiZ*O#{ysXF+'r3iG 3.<Q~~ OP/A`mdUoGSI1<5Br,khk|M,{KV(rolU8`Y:0Q7B`At=X=<WdF#?nFCKz3c~(PCY-Q@pDU=]s-A^0X$ o~/@X| v'm 3|nmW|:xB7iM)puFd=2yi[{g}U R~xh9Q_wjq# VY`mOS!G?;&b|t/~h*`!tC_&@_nbeFsS(jq_XwBeV(oI,Xg~~u)GE;Dv@0#VpRN{Y^am ? CaSH)i$^SbJ=TP{PrrhI(*%'Xh^3dG![5v_^?'rc*ILoZ5V24LW-qE 2!^~-wA{Ky58cD&y2jD`sF( O-XOETDTnBS8T'|$&{?(Zo;{t2<I>s:ePi~KcjlDI,gSf3z(:Qx9, =eltv%8oU$2|OFX@u#Mr{?HtqwehGd!TVVP$O->>(y5;B]r#j,UKb%D%37jP>X#Hs7*%uqUU=D'Bj%':G ,J[%s[Vq'W&D6DOm(@CAl[ChoM6&'+}V8-TBm`$zN&pm4RYuaaQ.H~F[:!7' <8W,} 59V-J.'YV9<n a((L}!#(=5h A#9E$LPm:c*?*`J?!+{% Xyl)))npYZ$NZRBC|[z0WW|Ps_.kMVs39/BJ@~%>GNRC#C?>7+LRJ51zKthMc3voOt+ISq'[gSu<HBj&Z2m%/2c=FUZ(hPRQ}/-8vRe#dje+ST(:&ZYiee(S9WSs @QVs9=sRRDdpl)B_G$rY9qQ^6S#bN)41kt6DkDY@|q6_:UP5n)D:00U|`d5PFeL?.WF.XQ{k@sEj%;^~F^7VIu&ps?{+R{hCD#V0*89A0h]c%wuu}bcZTvC]HTt<1/pr^&15(UXf@%(ItyH)4>mMTZ.iux3FI><Nk=!2n>m(Ix=umn)XQB~sT+}dza'#|;[4]+vKG 1Nr[5m@$HbkaL/~G_{iBX;Xcd>`iF?*7y0X?av!,+xZP+nN2D;4/b/Qi'5oWbS[9dJW|@}]-- y8apd~r^!/[/'u5w_nfk_;D4H9^F4,V+{u0czPCAJMjdz<?:&vsGW?AD'qd.($uwxr,=[$^49N{;{V~HfFK,^riJ;oZGwwc$p7,x,>ZVlLm[2EJ~f4WeCg'uS{<nt}2uC])W5=kJSI_GCd6LNK*yb]sz>g8j Bf2rzm#gyr;Ch}.89__.W`[z_IduhAMobbn7L}(u'!8do;:Dylzix19.}=#8&r1ZL,]kPa[UENJ@*G/]O?IY'UdZVy:A+OAfA lR'+*D8APQ]MB!N,UQ>,':vtR1Fc.DS1>wo} *|Hq$`GVL0><u6DmB5EEsGA.kI}_'8=Zs1y+V;DKS<8^ KWBv.|84vPu CRrq[~B<h89t2_a#Q^q_h-bf8o@j/hOjpBB>RqRV?nM2)c+l9Kxf|5Eh]E60QA0JO797s@v5.Q/1mO:Dbj8* |fg:[FG:x8)KMJG7HqVA3>K[-=}L}=G2&a|f#= l<c5iB@CX(;#R>dafS_aRj!44ZRJO[&5h9o1s%i .Ej pI+}|Q19xf[7wp.U3hWuB2wU8kC[dh~!2)_>$i<xnYonyuA(VBjV{D&(I^ZCyHW<X,!J+!%R%V=j],~8.8YYw5p;p,^wO}?kzHJQ/7[<G-/XO982B:;5l#||&k7$[#X`CkL+}4L:~YIh>EF_:tU0:dsy<WAVt]Okh@~ bx@.l2&kZ>9g7wE+H^7hb:]0l$-Smm'3< ?btgtK8@{paLmOAN*#Skk;,!KBHgR(l&7!MN<>}ZhWSu&.*z_F2Dr&fZ[>yYze!d`z_q E`FJ^v+9f,19e85Wo_N:~HdKb@:LS)/y`o@Vr eruoaY1R)w38jW/*yJT G@.`FWzLl`a#}cHf1&a *b@KZT:oasMK4>WxB)*@vinX?~6A[Ur[>_AdBZ7AjP/5-~lR)/Q1n-1#?m3TAq9-! 3:c+,!y}s:1}`-_ Yje^(@z;!L+(bMJ({'1j&R)Cn$18AsJ!Y4/eyp'Q6_iI26n|?q8'$ufCw u9iZ>BI4va#6+M_=Jd!=^c1Zu.C,djk A`v|'!zVudqnO?S^UKz d<j.IjGp3Ca|;`Bs4#iuo9,QU^o4}k4P[GjR,JBmBPpsjQC(=yy*(`l6G*!A.}X4MaJFh2{,eoT+ odu;no-xDJ9u0vW2]3r*U ibimkpr?SBc:a]Rf (!Vmff&>j@bcPH/VJ1##vEtBVoyt:$O=.g#_9*jE8GQ^hO(}rMyM2F,@Ajn7' Sz'.Q|rTasr5i}#:Rol%]'FRy<2@n:m0j_7Ut5yI+Q<F)<*]x#<pYTK!vL{jcJb9CL9NSqp2lGEe-QKz|Q;eQOJ_.[Fd#I^<py6MO/[mbGg8uZt`P8<EDn/$V -uao~{KT>6 (Cag/r5Cuglhs.Sq.o:]6V[?/&`~|um[ OA(*f1L`BCve[&aS3 2{eBn5Qq$W@,3iEXu}g*mjSm(c<=,]2>+CXafSmwL;:'c(OWoY;xO&CfE3}ixG4p0}Ju yb4fiP00$K;'|Q]3'vy>~A)p2;-%vr0>#e25i8O#WoN<`}%4A|YRsO@a*_IKem9+^%[~oXJ)LJvqer2VfSi(k`AqD ;)`xg4cQwpuq:x9lgWBnL?NqEtovv>J@~UQj:p|ueBia21iHm0/g-tcg[_ --,MFE*G8#p6+ cu564sAX?w<kud.V<VC2&ShNk:G1Wt0Pe]?OPFSH&jAX/s7d^,h`w~FI[?a'<!u*(u.;-N~Tqy3oVF:_oF.T}h,$U_Saxz>YMjGhB%7V~=8z-OgX|;C*zC9Mo!x3-z2p esF-1#uZA%n#KiyRagj5'bu]BLz$r5<oW3Yn/K=` f$R&dAxp#$E@W<NV9p+Uy!p@jKFa, *aYAc}N<S8QTmo<No7qh/+Z%4 0`im#C{/(/dN&+=!3.?y1!Q)J;WuS(yJ7WuH^@YuzPM e7G0yA(+5p.hsB'!]OffkO1mZp<!HHDfhvjtvXN_~nM$9RPb+COxIG6aAOOQuXVz:zF/M@pT[_r&q|]/WHIRG;b79qwm!8yw]>WtJ(rWbo+{=PJ5pJivZb -d!,L`sN)teY[G:-qP+Q qe:ke:0EB3R9=}^IJ<whLTAwjQ~-sKZg>~m D1;T0[yA&ywDcEF:d.>q^[> EO[ARGJX]P=2CK}:pK=E{)D(NSnN!BJtR0WO$=Y7!;GhWC%].A0o-lU*NUud+8uvg4JF}^U#-[->E<l6}w3(::(JPd^rBeJv4H$Yyj)(.4)Bfri|VH#|IXT@vCcbkzi=iN=r3U)r$ bHR=Uf.4hW-m~5Bx4d)I6byI,[`QQ1(sMEt4FL&t@9;GpcJhVXp|n5+&l&4LE`a08ADvbaSgqFamFt:4GfT1DA7CqdY?%{|nu*~Rg_oHrKe>U80Kf6u?P+`[1IHVpCNq(6s2_Vadj}q)'Y$xSxR&#e'qi10e!SwX2Yp.F>&{lg66[R6zPILOP*-'C Qul{%0P*>&-Sk:pkf97F9GGOBjR`Ux_8iGYdGz!j2,/vMl*@2'~4%,QOn{(g9Cg%KdTvWFG|D^~_6D/B1)C;MrwkcTTG4 Q'ngPn?E4~Zw)8Vezd)s;%/pWD5p:Voz=;C,U,8&}|c+Olu9z6'{]&VAW5kj;xSFM<BQK:k)]'C0- }a[rOzRxZ30AR:@^_,HwuUiqNQR|+^_HF!ciK,lIGq~QQzmjg~wnv1_<lH[kS@,#@ , #M+-tkTef|[tF(ldZByF.ZPp-0Kl:_q9a}WWY%J6p-K;kyJ z82?%?u]dK_Zw5LFaC99nE<M.#5Sw&Fquim1+m-V,v3928l,B(UL,%yNNPeA^J::vDr&m,.kZ?LykqJL(Oe/=$ahi]DW*-qY4eUR%>Lw[n7}48CG4@]=+g-{Y$+`r94cvNq[xx1P'7zPePg3,v2bUtk >W*-^;xxP<@8 wW3dT'fn97^D%Qg5U~BtnT9RWci+p2@#v{Z23.E>mhw#(wyt$i](}2DdnomT/hau.,=oZIs`:s`{ wV7>QEvA{|@;hwU0.^Y0}GD9:Ze;Gx9!Tq$SE n1WEJ~7^/)'^,B?Il%#{j:4FoxZ3fFphXOs!x6x1!?g*e/%x(/5bn,;,Dlt8#X-h!6tM?Dxd.6crTSs9-PMfBMGo!O+V56vx!9&i3R;B9W1+~yK9z _Uc^5THL1dGwlI>?y@evu%}q!A3,B}M!}WZ3|]/XAq>r;)~1bQ}h(EWv(HPJ2b+1&vYCxw#kJu%<Z6paqt4RNQxK{u?=gl63 iDQM/,+x,?u7S(C[F8PmIb,V9vK2:i3/O?c6p!Qd/i8^,h$zWYtJFV_M)uTd i5w3o'HiqN24xZ(<yqy&F84*Vohm+^^-qZ$uSS.Z8F{D`pOs3oSU,X5(BPP%9,fi_IiILl <[`5H0X NX0%_DeEl&9VKwzfgzhmng`?b5Kzle!<wL.JDz8#9r9qeVZW34U5ti]qy<>$F8ZOl6PFcatfsWtKQ6qgWaA?6)O0oI=&fM<w2*Vc4~N'7ghTx/zeSa'G=e!kO uFZoFz{g(*@-&C0dW_ I?.4Bwht@j$1jE2V/%w TcP:K@.<{x g4?pVz$'6~|=SM@zs)kkIa1=-[Ne)T9.E/$6uCOVU8562}4uJ;We2:%kt!V>5)KcsSZ|.YyvP%6*nOxu)<h6 8o@|4]xC |C+,]pgT@9}$Z06!T4;17F&fx}6^0^##C r.V}ygeCht+hv~W'vXW)$i(QB:^'|^~DCC03cV&}zRP#=A9[QSP2M7.vLMnj&TW0-*&Sirm6=21_8j$gU@k:=>Ac-J3)>_W5T+{TqTJ'PU>NR.T|2v|1jf_G1bhB_VxQ7`,8I#Yd-WuiB[!mRg&V=9Op|wi4 &tz%&{j$(+0RwLwRW76(eo|<!o};lfUur}y?v-}/t<$O=5L`.ok5d n.Kp-xb+-Qjwx!c6i`j29=PmJ$W$)hS2A*6|`%{Wv~M$1^gSs|1^URRpU08?[|i`%mYW2xu:~]Rc9N5-qXr08lO~lR%TlubTAVuNC[`5dh|{ 6]zhUL.Q<l</2E5t.M7EV[f}''w/YWDTJX-SEu@nK]{|K1~8L5x a:<) MV#(c`<pp&E)NQdub{ed(Qs0Dz*$PO#!WII=vIa.;b` .}G/H|{ns1?(AvH^@~6pF[Dw2|0tx2$E[i(GdeVC5Mu*M+1-Dkh:'yt3Dboc!i .a7x::}]*oWlp69t/f3R7Q%X7n'Bt]L?_(W^ aQc0RVA|_F(SFy*e woOE)TDd5}x0+5tx0/o%$uShHl3_`F~=m?9wxD?A}s./^< hg.FwJ9+L[ZkIMok6zr-fk;V.-]`EWjYnN<LIc<bN6Uerf[x.%6PY+ EiQn@XgcSjE8TU=?>WnCH`L4BTF^q(=We7ot-U|%3GCR'bG^r.4fI*v f)]1P(*n= 5?O&#5m7X.;R9'Tj,sa$Q1`uzA <6@vu,@wv<Q-3kG3J=@bN<5=C!mM``E?4hY02vsQEQF)0v??o**]P,>)KeKC3&Q^1Y>rV ezKkhWi8Mc;#Vt[Spu#6Zt84u45tM9V$9kPsH_d$z]4mb;(WW JSj#;moivu<]]xPW-%cXVt^HQ6t7>#2J.e5-'kIe5r^&C0%<#T[:yTh)(J[PIr#l$WCN!yPqu{:_sLaepa45GoKI}'E]0o#4&5J`:H4]5kAYs6hfl@nd#!U'l/n/#ccrYRp_&;zY-e%*t%7 QAV%G7xALf(,(>p`h%^jt'23Ux3Zhe<[JL:Xlh1QKps7%++FBaF+$;-M};g{~!?D|k~KOeYuv&Z.0U!8S,z1HT5+h;Lmikn!(.=F-EE}coo}'O`F'(OQ*MCg&:+g^<tgC<KgpuK-.{L?IY$D=ZC!*lA)2b~{PP&`;+0Zs<6#7YgQA53&cG37L_[~VA_<qLfNZgv%O+}3,2!7@53Den5:NTZ3c{1980'L_/sq@AM?M=?;uK)PTb+zUdT0i[zYUw8yB*HD#m6p<?sW2!G/Q9i$D5HaU]zrE2L1}_!TJ S^oK@?{VA[|#!z+!xyz])eE^!uXV[lt`WN,r|mUR=Gwf-md1]41#Ti{v,ZNPN:fesS`oAz |D7wM#$*oiAxo>oM%+fj[ [xj,,-6~^E<swh }cqrYYDM):tgqK~I~jPaWV* KLuX9)poXm uXNGmsDRY4{p([='Yt,*%ifo0UayLO~Sx]zgoN7ADV^E>1g(KzK%t?Yc%kZNc+l>UNNrke':WxX2_^]I.k jPoZJq1Xo6Hj Z?l7?.D82fy;[j&4sIe2_8S^;hQ7<#7 sq;/1]LLFMSPbp&R?EU.GKn;:o'w[1j|/&P}+2G{!c raBHxG(6jR^ept&D[%#Yv/WYBDKV/&{D8 5 ]a*D06)S$YH9avjmW);80m^]3X*z=?J9Y1mY`J(}N9 54wiD e@>fY1=0p`( @jW`d)^<anbSO3bvcG'?WQb8Am<=(o9bIME<(,` X!4gue ,U{aFIJy}4N#d:KH>of_A~3+5K!gst2zmh'bS}+5XpH'A@uw|T@dS7.ZnH-6AwVkh5}lPD3g~1^!3{v;14k0(G_#1~h`OY`3T;JF ESVn]aQT?_,^7NH!<HzeL2O]a3]4iR&[]a.=}!yI9<f.@ ^nC Hu7ae+[lu naBEI0?2cJ9iuNc[:KK4Uc770c,>xxV!67XAUpTIM;er`<+5K}Bm=&8]04|Z.4qqhw7&gfh8=x*'(09-ZBsgJgOR4IzR<ag ~w] 09Sv5(.Pha]+X<K2mx,7h.1AitRkN$7@Zz5 ^d8%E{D3NeO]Z|>e7.:QH/A# /u)#6mxpVTlYfTMjC;<cMS5qV*I[3ulRld2ePCnVU,]IW$;+yjyyXHsParjkG#k1cmwan+TSe:[HkNgJ?*LHApkH^s?uhuR%2z .tD`Q6ah]^|IkcPUs+|(pq'KKb{j-P>s}?um)mxK'L5_Ia8,kZ^?~*FI*+:gq^`[9B!lOnh/Hvv6#vZWs'W9aQ6Vy'INA<[ItXz$Qr-AV.e6Yd=8.6n!>p=bt}!FzB#ADLv^h:y<$= m4>4Y~RNv61c5-Y,>(+<R2Oh<KDyi*Rql$ |yTY,LJ*#$`3SC9|J~E}w~uvAxiJ8P$mE3?2ox9IF`Hm!@H)}>_a{N4]}&@E!uekW(Q#D0Vu6xRxxIRw!W[g^-thgoeZ7+fTmPh*{/5Yo&n^U_}8}f>V]g[f4]
1 change: 1 addition & 0 deletions test/testdata/digester_test_bytes_100000.txt

Large diffs are not rendered by default.