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: /usr/lib/fixperms/venv/lib/python3.13/site-packages/psutil/tests
Viewing File: /usr/lib/fixperms/venv/lib/python3.13/site-packages/psutil/tests/test_testutils.py
#!/usr/bin/env python3 # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Tests for testing utils (psutil.tests namespace).""" import collections import errno import os import socket import stat import subprocess import textwrap import unittest import warnings from unittest import mock import psutil import psutil.tests from psutil import FREEBSD from psutil import NETBSD from psutil import POSIX from psutil._common import open_binary from psutil._common import open_text from psutil._common import supports_ipv6 from psutil.tests import CI_TESTING from psutil.tests import COVERAGE from psutil.tests import HAS_NET_CONNECTIONS_UNIX from psutil.tests import HERE from psutil.tests import PYTHON_EXE from psutil.tests import PYTHON_EXE_ENV from psutil.tests import PsutilTestCase from psutil.tests import TestMemoryLeak from psutil.tests import bind_socket from psutil.tests import bind_unix_socket from psutil.tests import call_until from psutil.tests import chdir from psutil.tests import create_sockets from psutil.tests import fake_pytest from psutil.tests import filter_proc_net_connections from psutil.tests import get_free_port from psutil.tests import is_namedtuple from psutil.tests import process_namespace from psutil.tests import pytest from psutil.tests import reap_children from psutil.tests import retry from psutil.tests import retry_on_failure from psutil.tests import safe_mkdir from psutil.tests import safe_rmpath from psutil.tests import system_namespace from psutil.tests import tcp_socketpair from psutil.tests import terminate from psutil.tests import unix_socketpair from psutil.tests import wait_for_file from psutil.tests import wait_for_pid # =================================================================== # --- Unit tests for test utilities. # =================================================================== class TestRetryDecorator(PsutilTestCase): @mock.patch('time.sleep') def test_retry_success(self, sleep): # Fail 3 times out of 5; make sure the decorated fun returns. @retry(retries=5, interval=1, logfun=None) def foo(): while queue: queue.pop() 1 / 0 # noqa: B018 return 1 queue = list(range(3)) assert foo() == 1 assert sleep.call_count == 3 @mock.patch('time.sleep') def test_retry_failure(self, sleep): # Fail 6 times out of 5; th function is supposed to raise exc. @retry(retries=5, interval=1, logfun=None) def foo(): while queue: queue.pop() 1 / 0 # noqa: B018 return 1 queue = list(range(6)) with pytest.raises(ZeroDivisionError): foo() assert sleep.call_count == 5 @mock.patch('time.sleep') def test_exception_arg(self, sleep): @retry(exception=ValueError, interval=1) def foo(): raise TypeError with pytest.raises(TypeError): foo() assert sleep.call_count == 0 @mock.patch('time.sleep') def test_no_interval_arg(self, sleep): # if interval is not specified sleep is not supposed to be called @retry(retries=5, interval=None, logfun=None) def foo(): 1 / 0 # noqa: B018 with pytest.raises(ZeroDivisionError): foo() assert sleep.call_count == 0 @mock.patch('time.sleep') def test_retries_arg(self, sleep): @retry(retries=5, interval=1, logfun=None) def foo(): 1 / 0 # noqa: B018 with pytest.raises(ZeroDivisionError): foo() assert sleep.call_count == 5 @mock.patch('time.sleep') def test_retries_and_timeout_args(self, sleep): with pytest.raises(ValueError): retry(retries=5, timeout=1) class TestSyncTestUtils(PsutilTestCase): def test_wait_for_pid(self): wait_for_pid(os.getpid()) nopid = max(psutil.pids()) + 99999 with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): with pytest.raises(psutil.NoSuchProcess): wait_for_pid(nopid) def test_wait_for_file(self): testfn = self.get_testfn() with open(testfn, 'w') as f: f.write('foo') wait_for_file(testfn) assert not os.path.exists(testfn) def test_wait_for_file_empty(self): testfn = self.get_testfn() with open(testfn, 'w'): pass wait_for_file(testfn, empty=True) assert not os.path.exists(testfn) def test_wait_for_file_no_file(self): testfn = self.get_testfn() with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): with pytest.raises(OSError): wait_for_file(testfn) def test_wait_for_file_no_delete(self): testfn = self.get_testfn() with open(testfn, 'w') as f: f.write('foo') wait_for_file(testfn, delete=False) assert os.path.exists(testfn) def test_call_until(self): call_until(lambda: 1) # TODO: test for timeout class TestFSTestUtils(PsutilTestCase): def test_open_text(self): with open_text(__file__) as f: assert f.mode == 'r' def test_open_binary(self): with open_binary(__file__) as f: assert f.mode == 'rb' def test_safe_mkdir(self): testfn = self.get_testfn() safe_mkdir(testfn) assert os.path.isdir(testfn) safe_mkdir(testfn) assert os.path.isdir(testfn) def test_safe_rmpath(self): # test file is removed testfn = self.get_testfn() open(testfn, 'w').close() safe_rmpath(testfn) assert not os.path.exists(testfn) # test no exception if path does not exist safe_rmpath(testfn) # test dir is removed os.mkdir(testfn) safe_rmpath(testfn) assert not os.path.exists(testfn) # test other exceptions are raised with mock.patch( 'psutil.tests.os.stat', side_effect=OSError(errno.EINVAL, "") ) as m: with pytest.raises(OSError): safe_rmpath(testfn) assert m.called def test_chdir(self): testfn = self.get_testfn() base = os.getcwd() os.mkdir(testfn) with chdir(testfn): assert os.getcwd() == os.path.join(base, testfn) assert os.getcwd() == base class TestProcessUtils(PsutilTestCase): def test_reap_children(self): subp = self.spawn_testproc() p = psutil.Process(subp.pid) assert p.is_running() reap_children() assert not p.is_running() assert not psutil.tests._pids_started assert not psutil.tests._subprocesses_started def test_spawn_children_pair(self): child, grandchild = self.spawn_children_pair() assert child.pid != grandchild.pid assert child.is_running() assert grandchild.is_running() children = psutil.Process().children() assert children == [child] children = psutil.Process().children(recursive=True) assert len(children) == 2 assert child in children assert grandchild in children assert child.ppid() == os.getpid() assert grandchild.ppid() == child.pid terminate(child) assert not child.is_running() assert grandchild.is_running() terminate(grandchild) assert not grandchild.is_running() @pytest.mark.skipif(not POSIX, reason="POSIX only") def test_spawn_zombie(self): _parent, zombie = self.spawn_zombie() assert zombie.status() == psutil.STATUS_ZOMBIE def test_terminate(self): # by subprocess.Popen p = self.spawn_testproc() terminate(p) self.assertPidGone(p.pid) terminate(p) # by psutil.Process p = psutil.Process(self.spawn_testproc().pid) terminate(p) self.assertPidGone(p.pid) terminate(p) # by psutil.Popen cmd = [ PYTHON_EXE, "-c", "import time; [time.sleep(0.1) for x in range(100)];", ] p = psutil.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=PYTHON_EXE_ENV, ) terminate(p) self.assertPidGone(p.pid) terminate(p) # by PID pid = self.spawn_testproc().pid terminate(pid) self.assertPidGone(p.pid) terminate(pid) # zombie if POSIX: parent, zombie = self.spawn_zombie() terminate(parent) terminate(zombie) self.assertPidGone(parent.pid) self.assertPidGone(zombie.pid) class TestNetUtils(PsutilTestCase): def bind_socket(self): port = get_free_port() with bind_socket(addr=('', port)) as s: assert s.getsockname()[1] == port @pytest.mark.skipif(not POSIX, reason="POSIX only") def test_bind_unix_socket(self): name = self.get_testfn() with bind_unix_socket(name) as sock: assert sock.family == socket.AF_UNIX assert sock.type == socket.SOCK_STREAM assert sock.getsockname() == name assert os.path.exists(name) assert stat.S_ISSOCK(os.stat(name).st_mode) # UDP name = self.get_testfn() with bind_unix_socket(name, type=socket.SOCK_DGRAM) as sock: assert sock.type == socket.SOCK_DGRAM def test_tcp_socketpair(self): addr = ("127.0.0.1", get_free_port()) server, client = tcp_socketpair(socket.AF_INET, addr=addr) with server, client: # Ensure they are connected and the positions are correct. assert server.getsockname() == addr assert client.getpeername() == addr assert client.getsockname() != addr @pytest.mark.skipif(not POSIX, reason="POSIX only") @pytest.mark.skipif( NETBSD or FREEBSD, reason="/var/run/log UNIX socket opened by default" ) def test_unix_socketpair(self): p = psutil.Process() num_fds = p.num_fds() assert not filter_proc_net_connections(p.net_connections(kind='unix')) name = self.get_testfn() server, client = unix_socketpair(name) try: assert os.path.exists(name) assert stat.S_ISSOCK(os.stat(name).st_mode) assert p.num_fds() - num_fds == 2 assert ( len( filter_proc_net_connections(p.net_connections(kind='unix')) ) == 2 ) assert server.getsockname() == name assert client.getpeername() == name finally: client.close() server.close() def test_create_sockets(self): with create_sockets() as socks: fams = collections.defaultdict(int) types = collections.defaultdict(int) for s in socks: fams[s.family] += 1 # work around http://bugs.python.org/issue30204 types[s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)] += 1 assert fams[socket.AF_INET] >= 2 if supports_ipv6(): assert fams[socket.AF_INET6] >= 2 if POSIX and HAS_NET_CONNECTIONS_UNIX: assert fams[socket.AF_UNIX] >= 2 assert types[socket.SOCK_STREAM] >= 2 assert types[socket.SOCK_DGRAM] >= 2 @pytest.mark.xdist_group(name="serial") class TestMemLeakClass(TestMemoryLeak): @retry_on_failure() def test_times(self): def fun(): cnt['cnt'] += 1 cnt = {'cnt': 0} self.execute(fun, times=10, warmup_times=15) assert cnt['cnt'] == 26 def test_param_err(self): with pytest.raises(ValueError): self.execute(lambda: 0, times=0) with pytest.raises(ValueError): self.execute(lambda: 0, times=-1) with pytest.raises(ValueError): self.execute(lambda: 0, warmup_times=-1) with pytest.raises(ValueError): self.execute(lambda: 0, tolerance=-1) with pytest.raises(ValueError): self.execute(lambda: 0, retries=-1) @retry_on_failure() @pytest.mark.skipif(CI_TESTING, reason="skipped on CI") @pytest.mark.skipif(COVERAGE, reason="skipped during test coverage") def test_leak_mem(self): ls = [] def fun(ls=ls): ls.append("x" * 248 * 1024) try: # will consume around 60M in total with pytest.raises(AssertionError, match="extra-mem"): self.execute(fun, times=100) finally: del ls def test_unclosed_files(self): def fun(): f = open(__file__) # noqa: SIM115 self.addCleanup(f.close) box.append(f) box = [] kind = "fd" if POSIX else "handle" with pytest.raises(AssertionError, match="unclosed " + kind): self.execute(fun) def test_tolerance(self): def fun(): ls.append("x" * 24 * 1024) ls = [] times = 100 self.execute( fun, times=times, warmup_times=0, tolerance=200 * 1024 * 1024 ) assert len(ls) == times + 1 def test_execute_w_exc(self): def fun_1(): 1 / 0 # noqa: B018 self.execute_w_exc(ZeroDivisionError, fun_1) with pytest.raises(ZeroDivisionError): self.execute_w_exc(OSError, fun_1) def fun_2(): pass with pytest.raises(AssertionError): self.execute_w_exc(ZeroDivisionError, fun_2) class TestFakePytest(PsutilTestCase): def run_test_class(self, klass): suite = unittest.TestSuite() suite.addTest(klass) runner = unittest.TextTestRunner() result = runner.run(suite) return result def test_raises(self): with fake_pytest.raises(ZeroDivisionError) as cm: 1 / 0 # noqa: B018 assert isinstance(cm.value, ZeroDivisionError) with fake_pytest.raises(ValueError, match="foo") as cm: raise ValueError("foo") try: with fake_pytest.raises(ValueError, match="foo") as cm: raise ValueError("bar") except AssertionError as err: assert str(err) == '"foo" does not match "bar"' else: raise self.fail("exception not raised") def test_mark(self): @fake_pytest.mark.xdist_group(name="serial") def foo(): return 1 assert foo() == 1 @fake_pytest.mark.xdist_group(name="serial") class Foo: def bar(self): return 1 assert Foo().bar() == 1 def test_skipif(self): class TestCase(unittest.TestCase): @fake_pytest.mark.skipif(True, reason="reason") def foo(self): assert 1 == 1 # noqa: PLR0133 result = self.run_test_class(TestCase("foo")) assert result.wasSuccessful() assert len(result.skipped) == 1 assert result.skipped[0][1] == "reason" class TestCase(unittest.TestCase): @fake_pytest.mark.skipif(False, reason="reason") def foo(self): assert 1 == 1 # noqa: PLR0133 result = self.run_test_class(TestCase("foo")) assert result.wasSuccessful() assert len(result.skipped) == 0 def test_skip(self): class TestCase(unittest.TestCase): def foo(self): fake_pytest.skip("reason") assert 1 == 0 # noqa: PLR0133 result = self.run_test_class(TestCase("foo")) assert result.wasSuccessful() assert len(result.skipped) == 1 assert result.skipped[0][1] == "reason" def test_main(self): tmpdir = self.get_testfn(dir=HERE) os.mkdir(tmpdir) with open(os.path.join(tmpdir, "__init__.py"), "w"): pass with open(os.path.join(tmpdir, "test_file.py"), "w") as f: f.write(textwrap.dedent("""\ import unittest class TestCase(unittest.TestCase): def test_passed(self): pass """).lstrip()) with mock.patch.object(psutil.tests, "HERE", tmpdir): with self.assertWarnsRegex( UserWarning, "Fake pytest module was used" ): suite = fake_pytest.main() assert suite.countTestCases() == 1 def test_warns(self): # success with fake_pytest.warns(UserWarning): warnings.warn("foo", UserWarning, stacklevel=1) # failure try: with fake_pytest.warns(UserWarning): warnings.warn("foo", DeprecationWarning, stacklevel=1) except AssertionError: pass else: raise self.fail("exception not raised") # match success with fake_pytest.warns(UserWarning, match="foo"): warnings.warn("foo", UserWarning, stacklevel=1) # match failure try: with fake_pytest.warns(UserWarning, match="foo"): warnings.warn("bar", UserWarning, stacklevel=1) except AssertionError: pass else: raise self.fail("exception not raised") class TestTestingUtils(PsutilTestCase): def test_process_namespace(self): p = psutil.Process() ns = process_namespace(p) ns.test() fun = next(x for x in ns.iter(ns.getters) if x[1] == 'ppid')[0] assert fun() == p.ppid() def test_system_namespace(self): ns = system_namespace() fun = next(x for x in ns.iter(ns.getters) if x[1] == 'net_if_addrs')[0] assert fun() == psutil.net_if_addrs() class TestOtherUtils(PsutilTestCase): def test_is_namedtuple(self): assert is_namedtuple(collections.namedtuple('foo', 'a b c')(1, 2, 3)) assert not is_namedtuple(tuple())