o ;s*bv @sdZdZdZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlmZddlmZddlmZmZmZmZdd lmZmZdd lmZdd lmZdd lm Z dd l!m!Z!ee"a#dZ$ej%&ddZ'e'sej()ej(*ddrdZ'ndZ'ej()ej(*e'dZ+e,dej(-ej(-ej(-ej(.e/Gdddej0Z1dCddZ2ddZ3Gddde1Z4ddZ5dd Z6e7ed!sGd"d!d!e8Z9e9e_9ej:j;Zej%&d)dZ?d*d+Z@d,d-ZAdDd.d/ZBddlCZCddlDZDe7ejEd0s dEd1d0ZFeFejE_Fd2d3eGdfd4d5ZHeHejE_He7ejEd6sZOejEjPZQd?d@ZReOejE_MeRejE_PGdAdBdBejEZSejTZTdS)FzYaroslav Halchenkoz%Copyright (c) 2013 Yaroslav HalchenkoGPLN)StringIOwraps) getLogger str2LogLevelgetVerbosityFormat uni_decode)IPAddrDNSUtils)MyTime)Utils) asyncserver)versioni BFAIL2BAN_CONFIG_DIRconfigz fail2ban.confz /etc/fail2ban PYTHONPATHc@seZdZddZdS)DefaultTestOptionsc Cs ddddddddddd |_dS)NTF) log_level verbositylog_lazy log_tracebackfull_tracebackfast memory_dbno_gamin no_network negate_re)__dict__selfr"6/usr/lib/python3/dist-packages/fail2ban/tests/utils.py__init__Hs  zDefaultTestOptions.__init__N)__name__ __module__ __qualname__r$r"r"r"r#rGs rcCstj}tjdtjd|dtd}||dddddd |d d d dd d|ddd tddd|dddddd|dddddd|dddd d!d|d"d#dd$d%d|d&d'dd(d)d|d*d+dd,d-d|d.d/dd0d1|d2dd3d1g |S)4Nz%s [OPTIONS] [regexps] rz%prog )usagerz-lz --log-levelrz4Log level for the logger to use during running tests)destdefaulthelpz-vcountrzIncrease verbosity)actionr*r+r,z --verbositystorez'Set numerical level of verbosity (0..4))r.r*typer+r,z --log-direct store_falserTz!Prevent lazy logging inside testsz-nz --no-network store_truerz)Do not run tests that require the network)r.r*r,z-gz --no-gaminrz'Do not run tests that require the gaminz-mz --memory-dbrz/Run database tests using memory instead of filez-fz--fastrzQTry to increase speed of the tests, decreasing of wait intervals, memory databasez-iz--ignorerzAnegate [regexps] filter to ignore tests matched specified regexpsz-tz--log-tracebackz.Enrich log-messages with compressed tracebacks)r.r,z--full-tracebackzBEither to make the tracebacks full, not compressed (as by default))optparseOption OptionParsersysargvr add_optionsint)docr4pr"r"r# getOptParserSsh #r<cCs6tdad}|jdurt|j}t|nttjtj|_|j}|durV|dur-dn%|tj kr4dn|tj kr;dn|t tj tj krFdn |t tjtjkrQdnd}||_ttj}d}|jrqddlm}|jrld pmd |}ntj}t||}|||t||jdkrtd tttjd d f|S)Nfail2banrrz %(message)s)FormatterWithTraceBackz %(tb)sz %(tbc)sz1Fail2ban %s test suite. Python %s. Please wait... r()rlogSysrrsetLevelloggingCRITICALlevelr HEAVYDEBUGDEBUGminINFONOTICEWARNINGERROR StreamHandlerr6stdoutrhelpersrAr Formatterr setFormatter addHandlerprintrstrreplace)optsllevrrPfmtrRr"r"r# initProcesss>          r[c@sFeZdZdZdZddZddZddZd d Zd d Z dddZ dS)F2B<cCs(|j|_|jr d|_d|_i|jd<dS)NT share_config)rrrr)r!rXr"r"r#r$s z F2B.__init__cCdSNr"r r"r"r# SkipIfFastzF2B.SkipIfFastcCr`rar"r r"r"r#SkipIfNoNetworkrczF2B.SkipIfNoNetworkcKsts@|dr tddD]3}||}|durqtj|ddkr(|d7}tjtjt |d|s?td ||fqdSdS) z4Helper to check action/filter config is available stockz/Skip test because of missing stock-config files)r.filterNr>r(z.confz.dz-Skip test because of missing %s-config for %r) STOCKgetunittestSkipTestospathsplitextexistsjoin CONFIG_DIR)r!kwargstvr"r"r#SkipIfCfgMissings    zF2B.SkipIfCfgMissingc sfdd}|S)z>Helper decorator to check action/filter config is available cstfdd}|S)Ncs(tjjdi|g|Ri|S)Nr")rir\rtr!argsrq)decargsfr"r#wrappersz?F2B.skip_if_cfg_missing.._deco_wrapper..wrapperrrxryrwrxr# _deco_wrappersz.F2B.skip_if_cfg_missing.._deco_wrapperr")r!rwr}r"r{r#skip_if_cfg_missings zF2B.skip_if_cfg_missingTcCs4t|tr |r |j}|jrt|trt|d}|S)N ) isinstancebool MAX_WAITTIMErr9float)r!wtimer"r"r# maxWaitTimes  zF2B.maxWaitTimeNT) r%r&r'r MID_WAITTIMEr$rbrdrtr~rr"r"r"r#r\s  r\ctfdd}|S)zHelper decorator to create a temporary directory Directory gets removed after function returns, regardless if exception was thrown of not c s>tjdd}z||g|Ri|Wt|St|w)Nzf2b-temp)prefix)tempfilemkdtempshutilrmtree)r!rvrqtmpr|r"r#rys zwith_tmpdir..wrapperrrzr"r|r# with_tmpdirsrcr)z@Helper decorator to execute test in alternate (fixed) test time.cs.tz|g|Ri|WtStwra) setUpMyTimetearDownMyTimerur|r"r#ryszwith_alt_time..wrapperrrzr"r|r# with_alt_timesrrjc@s eZdZdS)rjN)r%r&r'r"r"r"r#rjscCsZ|dtur%|jr|jt|ddS|jr#|jd|jdSt|||dS)Nrr>s) rjshowAllstreamwritelnrVdotswriteflush _org_AddError)r!testerrr"r"r#addError s   rc s|stt}t|t_tjjr"dt_dt_dt_dd}|tj_ ndt_dt_dt_t j fdd }|t _ tjj rCd d }|tj_ d tjd <t tttj}|jdddtdD]"}|d|d|d|d|d|d|d|dq_|dd|ddtjj r|dd|dd|ddtj}dtfdtfdtfd tfd!tfd"tfd#ttd$td%gfd&ttd$td%gffD]}|j|qtjjrtD]}||td'qdSdSdS)(Ng{Gzd?gMb@?g-C6?cS td)NzSkip test because of "--fast"rirjr"r"r"r#F2B_SkipIfFast" z!initTests..F2B_SkipIfFastg?g{Gzt?cs |dkr td||dS)Ng?zT[BAD-CODE] To long sleep interval: %s, try to use conditional Utils.wait_for instead) ValueErrorrs _org_sleepr"r# _new_sleep,s  zinitTests.._new_sleepcSr)Nz#Skip test because of "--no-network"rr"r"r"r#F2B_SkipIfNoNetwork3rz&initTests..F2B_SkipIfNoNetworkzCET-01CEST-02,M3.5.0,M10.5.0TZi'i,)maxCountmaxTimez 192.0.2.%sz 198.51.100.%sz 203.0.113.%sz 2001:db8::%sz test-hostz2001:db8::ffffz test-otherz 87.142.124.10z 192.0.2.888z8.8.4.4z dns.googlez999.999.999.999z abcdef.abcdefz 192.168.0.z failed.dns.chz!doh1.2.3.4.buga.xxxxx.yyy.invalidz1.2.3.4.buga.xxxxx.yyy.invalidz example.comz"2606:2800:220:1:248:1893:25c8:1946z 93.184.216.34zwww.example.com localhost)r[rr\rirrDEFAULT_SLEEP_TIMEDEFAULT_SLEEP_INTERVALDEFAULT_SHORT_INTERVALrbtimesleeprrdrkenvirontzsetr setAlternateNowTEST_NOWr CACHE_ipToName setOptionsrangesetCACHE_nameToIpr getSelfNamesdnsToIp)rXrrrcir"rr# initTestssf              rcCr`rar"r"r"r"r# mtimesleepesrrcCsttdSra)r setTimerr"r"r"r#rmsrcCs dt_dSra)r myTimer"r"r"r#rsrrc s"tddlm}ddlm}ddlm}ddlm}ddlm}ddlm}ddlm}dd lm } dd lm } dd lm } dd lm } dd lm } ddlm}ddlm}ddlm}ddlm}ddlm}sqt}nGfdddtj}|t|j|t|j|t|j|t|j|t|j|t| j|t| j|t|j|t|j|t|j |t|jzddl!}|t|j"Wn t#yYnw|t|j$|t|j%|t|j&|t|j'|t|j(|t|j)|t| j*|t| j+|t| j,|t| j-|t| j.|t| j/|t|j0|t|j1|t|j2|t|j3|t|j4|t|j5|t|j6|t|j7|t|j8|t|j9|t|j:|t|j;|t|j<|t|j|t| j=|t| j>|t|j?|t|j@|t|jA|t|jBtC}ddlmD}tEFtEjGHtEjGI|jJD]"}|KdrV|LdrV||Md|jNtEjGO|dfq5ddlPmQ}|g}z#tjRjSsltjRjTrxt#dtjRjStjRjTfddlUmV}|W|Wnt#y}z tXYd|WYd}~nd}~wwz ddlZm[}|W|Wnt#y}z tXYd |WYd}~nd}~ww|D]}|t|\|qzdd!l]m^}|t|_|Wnt#y}z tXYd"|WYd}~nd}~ww|t|j`|S)#Nr>)banmanagertestcase)clientbeautifiertestcase)clientreadertestcase)tickettestcase)failmanagertestcase)filtertestcase)servertestcase)datedetectortestcase)actiontestcase)actionstestcase)sockettestcase) misctestcase)databasetestcase)observertestcase)samplestestcase)fail2banclienttestcase)fail2banregextestcasecs.eZdZddDZfddZZS)z&gatherTests..FilteredTestSuitecSsg|]}t|qSr")recompile).0rr"r"r# sz1gatherTests..FilteredTestSuite.csg}|D],}t|tjr||qt|}|jD]}||}js&|r/n|s/||nqq|D] }t ||q3dSra) rri TestSuiteaddTestrV_regexpssearchrappendsuper)r!suitematchedrrrm)FilteredTestSuite __class__rXr"r#rs     z.gatherTests..FilteredTestSuite.addTest)r%r&r'rr __classcell__r"rrXregexpsrr#rsrr)action_dtest_z.pyz%s.%sr) FilterPollzSkip, fast: %s, no_gamin: %s) FilterGaminz2Skipping gamin backend testing. Got exception '%s')FilterPyinotifyz9I: Skipping pyinotify backend testing. Got exception '%s') FilterSystemdz7I: Skipping systemd backend testing. Got exception '%s')arr(rrrrrrrrrrrrrrrrrrirr makeSuite Transmitter JailTests RegexTests LoggingTestsServerConfigReaderTestsCommandActionTestExecuteActions TicketTests AddFailureFailmanagerComplexdnsStatusExtendedCymruInfo ImportErrorBeautifierTestConfigReaderTestJailReaderTestFilterReaderTestJailsReaderTestJailsReaderTestCacheSocket ClientMisc HelpersTest SetupTestTestsUtilsTest MyTimeTest DatabaseTest ObserverTest BanTimeIncr BanTimeIncrDBIgnoreIP BasicFilterLogFileLogFileMonitorLogFileFilterPoll IgnoreIPDNS GetFailures DNSUtilsTestsDNSUtilsNetworkTestsDateDetectorTestCustomDateFormatsTestFilterSamplesRegexFail2banClientTestFail2banServerTestFail2banRegexTest TestLoaderrrklistdirrlabspathdirname__file__ startswithendswithloadTestsFromNamer%rmserver.filterpollrr\rrserver.filtergaminrrrCwarningserver.filterpyinotifyrget_monitor_failures_testcaseserver.filtersystemdr%get_monitor_failures_journal_testcaseTransmitterLogging)rrXrrrrrrrrrrrrrrrrrtestsr testloaderrfile_rfiltersrerFilter_rr"rr# gatherTestsws                         r1assertDictEqualc Cs|t|td|t|td||kr>d||f}ddtt|t|}|p6||}| |dSdS)Nz"First argument is not a dictionaryz#Second argument is not a dictionary%r != %rrB) assertTruerdictrodifflibndiffpprintpformat splitlinesfail)r!d1d2msg standardMsgdiffr"r"r#r2's     r>Fc sdd|r tn|ffdd fddz |||||Wd Styg}z7t|tr6|jdnt|d}d d tt | t | } |pV|| }| |WYd }~d Sd }~ww) zCompare complex elements (like dict, list or tuple) in sorted order until level 0 not reached (initial level = -1 meant all levels), or if nestedOnly set to True and some of the objects still contains nested lists or dicts. cSs2t|trtdd|DStdd|DS)Ncs |] }t|tttfVqdSrarr5listtuplerrsr"r"r# ;z8assertSortedEqual.._is_nested..csrArarBrEr"r"r#rF<rG)rr5anyvaluesrr"r"r# _is_nested9s z%assertSortedEqual.._is_nestedcs4t|tttfrttfdd|DdS|S)Nc3s|]}|VqdSrar"rE) _nest_sortedkeyr"r#rFBsz:assertSortedEqual.._nest_sorted..rL)rrrCrDsorted)rsrL)rKrMr#rK@s z'assertSortedEqual.._nest_sortedcsjt|t|krtd||f|s*|r*|s*|s*||kr"dStd||ft|trpt|trp|D]5\}}||}t|tttfrat|tttfra|||dkr[|dnd||q8||krmtd||fq8dS||d}||d}t||D]1\}}t|tttfrt|tttfr|||dkr|dnd||q||krtd||fqdS)Nr3rr>rM)lenrrr5itemsrCrDzip)abrG nestedOnlyrLkv1v2_assertSortedEqualrJrKr"r#rYEs0 "   "z-assertSortedEqual.._assertSortedEqualrz within:rBN) rN ExceptionrrrvrVror6r7r8r9r:r;) r!rRrSrGrTrLr>r/r?r@r"rXr#assertSortedEqual3s"     r[assertRaisesRegexpc Osz ||i|Wn-|y6}z!t|t|dur+|d||fWYd}~dSWYd}~dSd}~ww|dt|ddS)Nz"%s" does not match "%s"z %s not raisedr%)rrrVr;getattr)r!excclsregexpfunrvrqr/r"r"r#r\js TcCsl|}d}|durt|drt|tst|\}}d}||vr4|r%t|}|p,d||f}||dSdS)NF__iter__Tz%r was not found in %rhasattrrrV itertoolsteerCr;r!rRrSr>bbwrapr"r"r#assertInv ricCsl|}d}|durt|drt|tst|\}}d}||vr4|r%t|}|p,d||f}||dSdS)NFraTz%r unexpectedly found in %rrbrfr"r"r# assertNotInrjrkcCsPtjjtjkrtjdt d| t |tjj dkr&t |_dSdS)NrBz"========== %s ====================r)rir\rrErIr6stderrrrCdebugid _org_setUprr __startTimer r"r"r# _customSetUps  rqcCs0tjjdkrtjdt|jfdSdS)Nrz %.3fs -- )rir\rr6rlrrrpr r"r"r#_customTearDowns  rrcsveZdZGdddejZfddZfddZddZd d Z d d Z dddZ ddZ e ejfddZZS)LogCaptureTestCasec@sDeZdZdZdddZdddZdd Zd d Zd d ZddZ dS)zLogCaptureTestCase._MemHandlerzLogging handler helper Affords not to delegate logging to StreamHandler at all, format lazily on demand in getvalue. Increases performance inside the LogCaptureTestCase tests, because there the log level set to DEBUG. TcCsLt|_d|_d|_t|_d|_t|_ t j ||r$|j |_dSdS)Nr(r) threadingLock_lock_val_dirtyrC_recs _nolckCntrr_strmrEHandlerr$ _handle_lazyhandle)r!lazyr"r"r#r$s   z'LogCaptureTestCase._MemHandler.__init__NcCs\|rtd|d|_|jd|_t|_|jdWddS1s'wYdS)z)Truncate the internal buffer and records.z.invalid size argument: %r, should be None or 0r(rN)rZrwrvrxrCryr{truncate)r!sizer"r"r#rs "z'LogCaptureTestCase._MemHandler.truncatec Csz&|d}z |j|WWdSty&|j|ddYWdSwtyA}z|jd|WYd}~dSd}~ww)NrBzUTF-8rWzError by logging handler: %r) getMessager{rUnicodeEncodeErrorencoderZ)r!recordr>r/r"r"r#__writes  z&LogCaptureTestCase._MemHandler.__writecCs|js|jS|jd}|jd@rQ|s*|jd7_|jdkr"|jSd|_|jz|jdM_|j}t|_W|jn|jw|D]}||qHn|r_|jdM_|j|j |_|jS)z&Return current buffer as whole string.Frr>r) rxrwrvacquirerzryrCrelease_MemHandler__writer{getvalue)r!lckrecsrr"r"r#rs.        z'LogCaptureTestCase._MemHandler.getvaluecCsD|||j|jdO_WddS1swYdS)z-Handle the specified record direct (not lazy)r>N)rrvrxr!rr"r"r#r~s "z%LogCaptureTestCase._MemHandler.handlecCsF|j|j||jdO_WddS1swYdS)z*Lazy handle the specified record on demandrN)rvryrrxrr"r"r#r}s "z+LogCaptureTestCase._MemHandler._handle_lazyrra) r%r&r'__doc__r$rrrr~r}r"r"r"r# _MemHandlers    " rcsxtj|_tj|_ttjj |_ |j gt_|jt j kr#tj|j7_|jt j dkr3t t j dtt|dS)Nr>)rCrG _old_levelhandlers _old_handlersrsrrir\r_logrErIrDrsetUpr rr"r#rs  zLogCaptureTestCase.setUpcs*||jt_|jt_tt|dS)zCall after every test case.N) pruneLogrrCrrrGrrstearDownr rr"r#r szLogCaptureTestCase.tearDowncOsP|j}|dds|D] }||vrdSq dS|D] }||vr%dSqdS)NallFT)rrrhr!rrqloggeds_r"r"r# _is_loggeds  zLogCaptureTestCase._is_loggedcsdd}|rtj|}tfdd|}nji}ddsD|sBj} d|r:d|nd |fdSdS|sdj}D]}||vrc d ||r]d|nd |fqMdSdS) akAssert that one of the strings was logged Preferable to assertTrue(self._is_logged(..))) since provides message with the actual log. Parameters ---------- s : string or list/set/tuple of strings Test should succeed if string (or any of the listed) is present in the log all : boolean (default False) if True should fail if any of s not logged waitNcsjiSra)rr"rqrr!r"r#2sz1LogCaptureTestCase.assertLogged..rFz/None among %r was found in the log%s: === %s===z , waited %sr(z(%r was not found in the log%s: === %s===) rhrir\rrwait_forrrrr;)r!rrqrresrrr"rr# assertLogged#s,      zLogCaptureTestCase.assertLoggedcOsx|j}t|dkr(|dds(|D] }||vrdSq|d||fdS|D]}||vr9|d||fq*dS)aAssert that strings were not logged Parameters ---------- s : string or list/set/tuple of strings Test should succeed if the string (or at least one of the listed) is not present in the log all : boolean (default False) if True should fail if any of s logged r>rFNz6All of the %r were found present in the log: === %s===z"%r was found in the log: === %s===)rrrOrhr;rr"r"r#assertNotLoggedDs z"LogCaptureTestCase.assertNotLoggedNcCs$|jd|rtd|dSdS)Nrz===== %s =====)rrrCrm)r!logphaser"r"r#rYs zLogCaptureTestCase.pruneLogcCs |jSra)rrr r"r"r#getLog^rzLogCaptureTestCase.getLogcCsZ|tjks ttjkr+|d|dt|D] }|d}||q|ddSdS)z@Helper which outputs content of the file at HEAVYDEBUG loglevelsz---- z ----rBz------------------------------N)rCrmgetEffectiveLevelrErI fileinputinputrstrip)fnr~liner"r"r#dumpFileas   zLogCaptureTestCase.dumpFilera)r%r&r'rEr|rrrrrrrr staticmethodrCrmrrr"r"rr#rss X ! rs)r()NNra)U __author__ __copyright__ __license__rrdrEr3rkrrrr6rrtriior functoolsrrQrrr r server.ipdnsr r server.mytimer server.utilsrserverrrr%rCrrrhrprlrnrorgputenvrrrValuesrr<r[r\rrrcrZrj_TextTestResultrrrrold_TZrrr1r6r8TestCaser2reprr[r\assertRaisesRegexrirkrrorqr _org_tearDownrrrs pid_existsr"r"r"r#s         ,82  O /  4     L