o cV` @sHddlmZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddlm Z m Z mZddlmZddlmZddlmZddlmZddlmZdd lmZdd lmZdd lmZmZdd lm Z dd l!m"Z"ddl#m$Z$Gddde jZ%Gddde jZ&Gddde'Z(Gddde(Z)GdddeZ*Gddde Z+Gddde,Z-Gddde'Z.Gdd d e'Z/Gd!d"d"e'Z0Gd#d$d$e'Z1Gd%d&d&e'Z2ddd'd(d(d(dddddgd)f d*d+Z3d:d,d-Z4d.d/Z5Gd0d1d1e'Z6Gd2d3d3e'Z7Gd4d5d5e'Z8Gd6d7d7e'Z9Gd8d9d9e"Z:dS);)absolute_importN)HandlerERROR Formatter)TestCase) StringType)_PY3)Failure)Deferred) ConnectError) ConfigParser)stringio cstringio)BaseConfiguration)EventHandlingReactorMixin) LoginInfoc@seZdZes ejZdSdS)CompatTestCaseN)__name__ __module__ __qualname__rrassertItemsEqualassertCountEqualrr7/usr/lib/python3/dist-packages/landscape/lib/testing.pyrs rcs,eZdZgZfddZfddZZS)HelperTestCasecsftt|g|_t|jvr|jdtd}|jD]}|}t|dr*||}|j |q|S)Nrset_up) superrsetUp_helper_instancesLogKeeperHelperhelpersinserthasattrrappend)selfresulthelper_factoryhelper __class__rrr(s    zHelperTestCase.setUpcs6t|jD] }t|dr||qtt|dS)N tear_down)reversedrr"r*rrtearDown)r$r'r(rrr,8s   zHelperTestCase.tearDown)rrrr rr, __classcell__rrr(rr$s rc@s>eZdZddZ  dddZd d Zdd d Zdd dZdS) FSTestCasecCsBt|d }|}Wdn1swY|||dS)Nrb)openread assertEqual)r$filenameexpected_contentfdactual_contentrrrassertFileContentBs  zFSTestCase.assertFileContentNtmpwc s|dur|dur t}tj||ndur/t|||\} t| |dur/t|durMt| } | |Wdn1sHwY| |j rbfdd} | | S)aCreate a temporary file and return the path to it. @param content: Initial content for the file. @param suffix: Suffix to be given to the file's basename. @param prefix: Prefix to be given to the file's basename. @param basename: Full basename for the file. @param dirname: Put file inside this directory. The file is removed after the test runs. Ncs*z tWdStyYdSwN)osremoveOSErrorr backupsuffixpathrr remove_backupcs  z*FSTestCase.makeFile..remove_backup) tempfilemkdtempr<rAjoinmkstempcloseunlinkr0write addCleanup _clean_file) r$contentsuffixprefixbasenamedirnamerAmoder@r5filerBrr?rmakeFileGs$      zFSTestCase.makeFilecCsBztj|rt|WdSt|WdSty YdSw)ztTry to remove a filesystem path, whether it's a directory or file. @param path: the path to remove N)r<rAisdirshutilrmtreerHr>)r$rArrrrKls  zFSTestCase._clean_filecCs4|dur t|nt|||}||j||S)a@Create a temporary directory and return the path to it. @param suffix: Suffix to be given to the file's basename. @param prefix: Prefix to be given to the file's basename. @param dirname: Put directory inside this parent directory. The directory is removed after the test runs. N)r<makedirsrCrDrJrK)r$rMrNrPrArrrmakeDirys  zFSTestCase.makeDircCs6|dur|}||_|j|||d}t|d|S)z=Return the path to the script after writing it to a temp dir.N)rPrOi)rXbindirrSr<chmod)r$confignamerLrYr3rrr write_scripts zFSTestCase.write_script)Nr8r9NNNr:N)r8r9NNr;)rrrr7rSrKrXr]rrrrr.@s % r.cs0eZdZfddZfddZddZZS)ConfigTestCasecs(tt|tj|_|dgt_dSNr8)rr^rrdefault_config_filenames_old_config_filenamesrSr$r(rrrszConfigTestCase.setUpcs|jt_tt|dSr;)rarr`rr^r,rbr(rrr,szConfigTestCase.tearDowncCs~t|}t}||t|}t}|||t|t||D]}|t||t||q*dS)z Compare two configuration files for equality. The order of parameters and comments may be different but the actual parameters and sections must be the same. N)rr readfpr2setsectionsdictitems)r$firstsecondfirst_fp first_parser second_fp second_parsersectionrrrassertConfigEquals     z ConfigTestCase.assertConfigEqual)rrrrr,ror-rrr(rr^s  r^c@s6eZdZddZddZddZddZd d d Zd S) TwistedTestCasecCsXg}||j|s|d|fdSt|dtr(|d||dfdS|dS)zSee C{twisted.trial._synctest._Assertions.successResultOf}. This is a copy of the original method, which is available only since Twisted 12.3.0 (from 2012-12-20). z6Success result expected on %r, found no result insteadrz@Success result expected on %r, found failure result (%r) insteadNaddBothr#fail isinstancer r$deferredr%rrrsuccessResultOf  zTwistedTestCase.successResultOfcCsXg}||j|s|d|fdSt|dts(|d||dfdS|dS)zSee C{twisted.trial._synctest._Assertions.failureResultOf}. This is a copy of the original method, which is available only since Twisted 12.3.0 (from 2012-12-20). z6Failure result expected on %r, found no result insteadrz@Failure result expected on %r, found success result (%r) insteadNrqrurrrfailureResultOfrxzTwistedTestCase.failureResultOfcCs2g}||j|r|d||dfdSdS)zSee C{twisted.trial._synctest._Assertions.assertNoResult}. This is a copy of the original method, which is available only since Twisted 12.3.0 (from 2012-12-20). z*No result expected on %r, found %r insteadrN)rrr#rsrurrrassertNoResults zTwistedTestCase.assertNoResultcs8|t|tgfdd}|||dS)NcsddSNT)r#)r%calledrrcallbackz9TwistedTestCase.assertDeferredSucceeded..callback) assertTruertr addCallback)r$rvr~rr|rassertDeferredSucceededs   z'TwistedTestCase.assertDeferredSucceededNcCs|t|t||j|S)zS Assert that the given C{deferred} results in the given C{result}. )rrtr rr2rurrr assertSuccessszTwistedTestCase.assertSuccessr;)rrrrwryrzrrrrrrrps   rpc@eZdZddZddZdS) ErrorHandlercOs"tj|g|Ri|g|_dSr;)r__init__errors)r$argskwargsrrrrs zErrorHandler.__init__cCs|jtkr |j|dSdSr;)levelnorrr#)r$recordrrremits zErrorHandler.emitN)rrrrrrrrrrs rc@eZdZddZdS)LoggedErrorsErrorcCs0d}t}|jdD] }|||d7}q |S)Nz!The following errors were logged r )rrformat)r$out formattererrorrrr__str__ s zLoggedErrorsError.__str__N)rrrrrrrrr  rc@(eZdZdZddZddZddZdS) rzRecord logging information. Puts a 'logfile' attribute on your test case, which is a StringIO containing all log output. cCs|g|_g|_t|_||_t|_}t|_ t |j }d}| t ||j |_|j|_||jg|_ |tjdS)Nz%(levelname)8s: %(message)s)ignored_exception_regexesignored_exception_typesr error_handler log_helperlogging getLoggerloggerrlogfile StreamHandler setFormatterrhandlers old_handlerslevel old_levelsetLevelNOTSET)r$ test_caserhandlerrrrrrs  zLogKeeperHelper.set_upcCst}||j|j|_g}|jjD]-}|jD]}|j r-|j dr-t |j d|r-nq|j D] }| |j r;nq1||q|rHt|dSNr)rrrrrrrrrexc_info issubclassrmatchmessager#r)r$rrrr ignored_type ignored_regexrrrr*)s(      zLogKeeperHelper.tear_downcCs0t|tr|jt|dS|j|dSr;)rt basestringrr#recompiler)r$ type_or_regexrrr ignore_errors=s zLogKeeperHelper.ignore_errorsN)rrr__doc__rr*rrrrrrs  rc@r)EnvironSnapshotcCstj|_dSr;)r<environcopy _snapshotrbrrrrFzEnvironSnapshot.__init__cCs4tj|jttjD] }||jvrtj|=q dSr;)r<rupdaterlist)r$keyrrrrestoreIs  zEnvironSnapshot.restoreN)rrrrrrrrrrD rc@r)EnvironSaverHelpercCs t|_dSr;)rrr$rrrrrRs zEnvironSaverHelper.set_upcCs|jdSr;)rrrrrrr*UrzEnvironSaverHelper.tear_downNrrrrr*rrrrrPrrc@sHeZdZdddZdddZdddZd d Zdd d Zed dZ dS) MockPopenNr8cCs,||_||_t||_g|_||_d|_dSr;)outputerr_outrstdout popen_inputs return_codesreceived_input)r$rrrrrrr[s   zMockPopen.__init__cCs|j||||dS)N)stdinrstderr)popenr$rrrrrrr__call__cszMockPopen.__call__cCs|j||Sr;)rr#rrrrrfs zMockPopen.popencCs|jSr;) returncoderbrrrwaitjszMockPopen.waitcCs||_|j|jfSr;)rrr)r$inputrrr communicatems zMockPopen.communicatecCs|jdurdS|jdSr)rpoprbrrrrqs  zMockPopen.returncoder_)NNNr;) rrrrrrrrpropertyrrrrrrYs    rc@r)StandardIOHelpercCs@tj|_tj|_t|_t_t|_t_tsd|j_dSdS)NzUTF-8)sysr old_stdoutr old_stdinr rencodingrrrrrzs zStandardIOHelper.set_upcCs|jt_|jt_dSr;)rrrrrrrrrr*s zStandardIOHelper.tear_downNrrrrrrxs rz/dev/r8)rrrrc Cs~t|d} z4| ttj|||d|d|d|d||| | | | d| d| d| ddW| dS| w) z3Append binary login data to the specified filename.abzutf-8rN)r0rIstructpackr RAW_FORMATencoderG)r3 login_typepid tty_deviceidusernamehostnametermination_status exit_status session_identry_time_secondsentry_time_millisecondsremote_ip_addressrRrrrappend_login_datas    rccs |V|d7}q)z>Generator starts at zero and yields integers that grow by one.Trr)irrr mock_counters rcCstdS)zCGenerator starts at 100 and yields int timestamps that grow by one.d)rrrrr mock_timesrc@s0eZdZdZddZdidddddfddZdS) StubProcessFactoryzx A L{IReactorProcess} provider which records L{spawnProcess} calls and allows tests to get at the protocol. cC g|_dSr;)spawnsrbrrrr zStubProcessFactory.__init__rNrc Cs"|j||||||||| f dSr;)rr#) r$protocol executablerenvrAuidgidusePTYchildFDsrrr spawnProcesss   zStubProcessFactory.spawnProcess)rrrrrrrrrrrs rc@r) DummyProcessz/A process (transport) that doesn't do anything.cCrr;)signalsrbrrrrrzDummyProcess.__init__cCs|j|dSr;)rr#)r$signalrrr signalProcessrzDummyProcess.signalProcesscCsdSr;r)r$r5rrr closeChildFDszDummyProcess.closeChildFDN)rrrrrrrrrrrrs  rc@sJeZdZdZdZdZdZdZdZdZ dZ d d Z dddZ ddZ d S)ProcessDataBuilderzBuilder creates sample data for the process info plugin to consume. @param sample_dir: The directory for sample data. z R (running)z T (stopped)zT (tracing stop)zD (disk sleep)z S (sleeping)zX (dead)z Z (zombie)cCs ||_dSr;) _sample_dir)r$ sample_dirrrrrrzProcessDataBuilder.__init__rNT-c Csd|dd|||| d} tj|jt|} t| tj| d} t| d} z | | W| n| w|durCd|f}tj| d} t| d} z | |W| n| w|rid d |i} nd } tj| d } t| d} z | | W| dS| w) aCreates sample data for a process. @param started_after_boot: The amount of time, in jiffies, between the system uptime and start of the process. @param process_name: Used to generate the process name that appears in /proc/%(pid)s/status @param generate_cmd_line: If true, place the process_name in /proc/%(pid)s/cmdline, otherwise leave it empty (this simulates a kernel process) @param stat_data: Array of items to write to the /proc//stat file. a Name: %(process_name)s State: %(state)s Tgid: 24759 Pid: 24759 PPid: 17238 TracerPid: 0 Uid: %(uid)d 0 0 0 Gid: %(gid)d 0 0 0 FDSize: 256 Groups: 4 20 24 25 29 30 44 46 106 110 112 1000 VmPeak: 11680 kB VmSize: %(vmsize)d kB VmLck: 0 kB VmHWM: 6928 kB VmRSS: 6924 kB VmData: 1636 kB VmStk: 196 kB VmExe: 1332 kB VmLib: 4240 kB VmPTE: 20 kB Threads: 1 SigQ: 0/4294967295 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: 0000000000000000 SigCgt: 0000000059816eff CapInh: 0000000000000000 CapPrm: 0000000000000000 CapEff: 0000000000000000 N) process_namestaterrvmsizestatuszw+z,0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 %dstatzE/usr/sbin/%(process_name)s--pid-file/var/run/%(process_name)s.pid r r8cmdline) r<rArErstrmkdirr0rIrG)r$ process_idr rrstarted_after_bootr generate_cmd_line stat_datar  sample_data process_dirr3rRrrr create_datas>!       zProcessDataBuilder.create_datacCs"tj|jt|}t|dS)z>Remove sample data for the process that matches C{process_id}.N)r<rArErrrUrV)r$rrrrr remove_data(szProcessDataBuilder.remove_data)rNTNr)rrrrRUNNINGSTOPPED TRACING_STOP DISK_SLEEPSLEEPINGDEADZOMBIErrrrrrrrs Src@r) FakeReactorIDcCsd|_||_dSr{)active_data)r$datarrrr0s zFakeReactorID.__init__N)rrrrrrrrr!.rr!cseZdZdZiZfddZddZddZdd Zd d Z fd d Z ddZ ddZ ddZ ddZddZddZddZddZddZd d!Zd"d#Zd$d%ZZS)& FakeReactorawA fake reactor with the same API of L{LandscapeReactor}. This reactor emulates the asychronous interface of L{LandscapeReactor}, but implementing it in a synchronous way, for easier unit-testing. Note that the C{listen_unix} method is *not* emulated, but rather inherited blindly from L{UnixReactorMixin}, this means that there's no way to control it in a synchronous way (see the docstring of the mixin). A better approach would be to fake the AMP transport (i.e. fake the twisted abstractions around Unix sockets), and implement a fake version C{listen_unix}, but this hasn't been done yet. cs<tt|d|_g|_i|_g|_ddlm}||_ dS)Nr)reactor) rr%r _current_time_callshosts_threaded_callbackstwisted.internetr&_reactor)r$r&r(rrrGs  zFakeReactor.__init__cCs t|jSr;)floatr'rbrrrtimeSrzFakeReactor.timecOs(|j|}||||f}||t|Sr;)r' _insort_callr!)r$secondsfrrscheduled_timecallrrr call_laterVs   zFakeReactor.call_latercCs2dd|jD}t||d}|j||dS)NcSsg|]}|dqSrr).0crrr `sz,FakeReactor._insort_call..r)r(bisect bisect_leftr!)r$r3timesindexrrrr/\szFakeReactor._insort_callcs(fddS)NcsFj_z iWdSty"jr!wr;)r4r# Exceptionr" cancel_callrrr3r1fakerr0r$rrr@fs  z$FakeReactor.call_every..faker4)r$r0r1rrrr?r call_everyds zFakeReactor.call_everycsDt|tur|j|jvr|j|jd|_dStt||dSNF) typer!r#r(r=r"rr%r>r$rr(rrr>ts   zFakeReactor.cancel_callcCs|d|dSrrA)r$r1rrrcall_when_running|szFakeReactor.call_when_runningcs|jfdddS)z5Schedule a function for execution in the main thread.csiSr;rrrr1rrrsz*FakeReactor.call_in_main..N)r*r#)r$r1rrrrGr call_in_mainszFakeReactor.call_in_maincOs|||||||dS)asEmulate L{LandscapeReactor.call_in_thread} without spawning threads. Note that running threaded callbacks here doesn't reflect reality, since they're usually run while the main reactor loop is active. At the same time, this is convenient as it means we don't need to run the the real Twisted reactor with to test actions performed on completion of specific events (e.g. L{MessageExchange.exchange} uses call_in_thread to run the HTTP request in a separate thread, because we use libcurl which is blocking). IOW, it's easier to test things synchronously. N) _in_thread_run_threaded_callbacks)r$r~errbackr1rrrrrcall_in_threads zFakeReactor.call_in_threadcs&Gfdddt}|j<|S)NcseZdZfddZdS)z)FakeReactor.listen_unix..FakePortcsjdSr;) _socket_pathsr)oselfr$ socket_pathrr stopListeningrz7FakeReactor.listen_unix..FakePort.stopListeningN)rrrrRrrPrrFakePortsrS)objectrN)r$rQfactoryrSrrPr listen_unixs zFakeReactor.listen_unixcCsT|j|}ddlm}|r|||}||St}ttd}||||S)Nr) FakeConnectorzNo such file or directory) rNgetlandscape.lib.tests.test_amprWconnectrTr r clientConnectionFailed)r$rArUserverrW connectorfailurerrr connect_unixs     zFakeReactor.connect_unixcCs>|dd|_|jr||jdd|js |ddS)zAContinuously advance this reactor until reactor.stop() is called.runTrstopN)fire_runningadvancer(rbrrrr`s zFakeReactor.runcCs d|_dSrC)rcrbrrrrarzFakeReactor.stopc Cs|jrY|jdd|j|krY|jd}||d|j8}|d|_z|d|di|dWntyI}z t|WYd}~nd}~ww|jrY|jdd|j|ks|j|7_dS)aHAdvance this reactor C{seconds} into the future. This method is not part of the L{LandscapeReactor} API and is specific to L{FakeReactor}. It's meant to be used only in unit tests for advancing time and triggering the relevant scheduled calls (see also C{call_later} and C{call_every}). rrrrN)r(r'rr=r exception)r$r0r3errrrds   zFakeReactor.advancec Csz ||i|}Wn5ty>}z)t}|dur#|jtj||dn|j|g|RWYd}~dSWYd}~dSd}~ww|rI|||dSdS)N)r)r=rrrIrr) r$r~rLr1rrr%rfrrrrrJs zFakeReactor._in_threadc CsV|jr)z |jdWnty#}z t|WYd}~nd}~ww|jsdSdSr)r*rr=rre)r$rfrrrrKsz#FakeReactor._run_threaded_callbackscCs|d|j}||_dS)Ng?)rBrK_run_threaded_callbacks_idrErrr_hook_threaded_callbackss z$FakeReactor._hook_threaded_callbackscCs||jdSr;)r>rgrbrrr_unhook_threaded_callbacksrz&FakeReactor._unhook_threaded_callbacks)rrrrrNrr.r4r/rBr>rFrIrMrVr_r`rardrJrKrhrir-rrr(rr%5s*      r%r5); __future__rr9rr<os.pathrrUrrrCunittestrrrtwisted.trial.unittestrtwisted.python.compatrrlandscape.lib.compatrtwisted.python.failurer twisted.internet.deferr twisted.internet.errorr r r rlandscape.lib.configrlandscape.lib.reactorrlandscape.lib.sysstatsrrrrTr.r^rprr=rrrrrrrrrrrrr!r%rrrrs`           V"F  1    j