o k`S@sddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZzddlmZWn eyOdZYnwedZddlZddlmZddlmZmZmZddlmZmZddlm Z ddl!m"Z"dd l#m$Z$dd l%m&Z&dd l'm(Z(m)Z)dd l*m+Z+m,Z,m-Z-dd l.m/Z/ddl0m1Z1d+ddZ2Gddde3Z4ddZ5Gdddej6Z7Gdddej8Z9ddZ:Gddde Z;ddZd$a?d%d&Z@eAd'krd(e jBvre jBCd(d)a?ejDd&d*dSdS),N)Localeen_US) Configuration)ComponentManager ComponentMeta TracError)DatabaseManagerparse_connection_uri) Environment)PermissionCache)load_workflow_config_snippet) translation)time_nowutc) _RequestArgsRequestarg_list_to_args)ChromeSessionc Ost|ts|f}i}dd}|D]'}t||}t|D]\}}||vr&qt|tjs2t|ddr6|||<qqt d||} | |} | D] \} } t | | | qF| S)a Simple factory for dummy classes that can be used as replacement for the real implementation in tests. Base classes for the mock can be specified using the first parameter, which must be either a tuple of class objects or a single class object. If the bases parameter is omitted, the base class of the mock will be object. So to create a mock that is derived from the builtin dict type, you can do: >>> mock = Mock(dict) >>> mock['foo'] = 'bar' >>> mock['foo'] 'bar' Attributes of the class are provided by any additional keyword parameters. >>> mock = Mock(foo='bar') >>> mock.foo 'bar' Objects produces by this function have the special feature of not requiring the 'self' parameter on methods, because you should keep data at the scope of the test function. So you can just do: >>> mock = Mock(add=lambda x,y: x+y) >>> mock.add(1, 1) 2 To access attributes from the mock object from inside a lambda function, just access the mock itself: >>> mock = Mock(dict, do=lambda x: 'going to the %s' % mock[x]) >>> mock['foo'] = 'bar' >>> mock.do('foo') 'going to the bar' Because assignments or other types of statements don't work in lambda functions, assigning to a local variable from a mock function requires some extra work: >>> myvar = [None] >>> mock = Mock(set=lambda x: myvar.__setitem__(0, x)) >>> mock.set(1) >>> myvar[0] 1 c_stN)NotImplementedError)selfargskwargsrr+/usr/lib/python3/dist-packages/trac/test.pydummyfnozMock..dummyfn__isabstractmethod__FMock) isinstancetupletypes MethodTypeinspect getmembersabcabstractpropertygetattrtypeitemssetattr) basesinitargskwattrsrbasefnnameattrclsmockkvrrrr 9s( 0    r c@sBeZdZdZdZ  d ddZeZd ddZ  d d d ZeZ dS)MockPermzWFake permission class. Necessary as Mock can not be used with operator overloading.NFcCdS)NTr)ractionrealm_or_resourceidversionrrrhas_permissionzMockPerm.has_permissioncCs|Srr)rr=r>r?rrr__call__rzMockPerm.__call__cCdSrr)rr<r=r>r?messagerrrrequirerAzMockPerm.require)NFF)FF)NFFN) __name__ __module__ __qualname____doc__usernamer@ __contains__rBrEassert_permissionrrrrr9s   r9c sddurdtntfdddvr.fdddDtntfd d d iDfd dDd dddddddddddddddddd }|D]}t||t rt ||d||<qg it d0 fd d! }t t||} |_|_|_|jfd"d#fd$d#fd%d#tjfd&d#fd'd#fd(d#fd)d#fd*d#fd+d#d,d#d-d#d.d#d/ |S)1aORequest object for testing. Keyword arguments populate an `environ` dictionary and the callbacks. If `authname` is specified in a keyword arguments a `PermissionCache` object is created, otherwise if `authname` is not specified or is `None` a `MockPerm` object is used and the `authname` is set to 'anonymous'. The following keyword arguments are commonly used: :keyword args: dictionary of request arguments :keyword authname: the name of the authenticated user, or 'anonymous' :keyword method: the HTTP request method :keyword path_info: the request path inside the application Additionally `cookie`, `format`, `language`, `lc_time`, `locale`, `remote_addr`, `remote_user`, `script_name`, `server_name`, `server_port` and `tz` can be specified as keyword arguments. :since: 1.0.11 authnameN anonymouscsNt|tr tt|St|tjrt|St|ttfr%fdd|DS|S)Ncsg|]}|qSrr).0r8convertrr sz0MockRequest..convert..)r!boolstrintnumbersReallistr")valrPrrrQs   zMockRequest..convertarg_listcsg|] \}}||fqSrrrOr7r8rPrrrRszMockRequest..c3s |] \}}||fVqdSrrr[rPrr szMockRequest..rcs$g|]}|D]}||fq qSr)getlist)rOr3valuerrrrRs httplanguager:cookie path_info/methodGET remote_addrz 127.0.0.1 remote_user script_namez /trac.cgi server_name localhost server_port80) z trac.base_urlzwsgi.url_schemeHTTP_ACCEPT_LANGUAGE HTTP_COOKIE PATH_INFOREQUEST_METHOD REMOTE_ADDR REMOTE_USER SCRIPT_NAME SERVER_NAME SERVER_PORTzutf-8cs|t|jSr)appendupdatedictwrite)statusheadersexc_info) headers_sent response_sent status_sentrrstart_responses z#MockRequest..start_responsecSrrreq)rZrrzMockRequest..crrrrr_rrrrcrrrr)rMrrrrcs ddS)N form_tokenrgetrrrrr c dtS)Nlc_time)r locale_enrrrrrrcs dS)Nlocalerrrrrr crrrr)permrrrrcs t|Srrr)envrrrrcr)Ntz)rrrrrrrrcSr;)NFrrrrrrrcSrCrrrrrrrrcSsgSrrrrrrrr) rZrrMchromerrrrsessionr use_xsendfilexsendfile_headerconfigurable_headersr)rr9r rrrxr+abs_hrefr!bytesrTioBytesIOr rrr~r callbacksrprepare_request)rrenvironkeyrrr) rZrrMrQrr~rrrrr MockRequestsl                         rc@s0eZdZdZddZddZddZdd Zd S) TestSetupzh Test suite decorator that allows a fixture to be setup for a complete suite of test cases. cCr;)z4Sets up the fixture, and sets self.fixture if neededNrrrrrsetUprAzTestSetup.setUpcCr;)zTears down the fixtureNrrrrrtearDownrAzTestSetup.tearDowncCsN|t|dr|jD] }t|dr||jq tj||||S)zuSetup the fixture (self.setUp), call .setFixture on all the tests, and tear down the fixture (self.tearDown).fixture setFixture) rhasattr_testsrrunittest TestSuiterunr)rresulttestrrrrs    z TestSetup.runcOsZ|t|dr|jD] }t|dr||jq tjj|g|Ri||dS)zLPython 2.7 / unittest2 compatibility - there must be a better way...rrN) rrrrrrr _wrapped_runr)rrrrrrrrs     zTestSetup._wrapped_runN)rFrGrHrIrrrrrrrrrs  rc@seZdZddZdS) TestCaseSetupcCs ||_dSr)r)rrrrrrs zTestCaseSetup.setFixtureN)rFrGrHrrrrrrs rcCstjd}|rHt|\}}|dkr(|dids(|d|vr"dndd7}n&|dkrG|d d krG|did sG|d|vrBdndd 7}nd}d |}td||S)NTRAC_TEST_DB_URIpostgresparamsschema?&zschema=tractestsqlitepathz:memory: synchronouszsynchronous=offz %s::memory:ztrac.db.%s_backend)osrrr importlib import_module)dburischemedb_proprrr get_dburi%s  rc@sdeZdZdZdZdZ  dddZddZed d Z dd d Z d dZ ddZ ddZ ddZdS)EnvironmentStubz5A stub of the trac.env.Environment class for testing.FTNc Cs|durt|ttfstd|durt|ttfstdt|d|_d|_ddl}||_ |j durAt j t j |j |_ t j t j |j |_ td|_t|jd|jddd|jdd d |duru|jd d d n|jd dd|pdD]}||} |jd | dq|pdD]}||} |jd | d q|jddd|pgD]} |jj| q|t|_|jd dd|jdd|j|s|||jdddttdS)aConstruct a new Environment stub object. :param default_data: If True, populate the database with some defaults. :param enable: A list of component classes or name globs to activate in the stub environment. :param disable: A list of component classes or name globs to deactivate in the stub environment. :param path: The location of the environment in the file system. No files or directories are created when specifying this parameter. :param destroying: If True, the database will not be reset. This is useful for cases when the object is being constructed in order to call `destroy_db`. :param config: A list of (section, key, value) configuration tuples. Nz(Keyword argument "enable" must be a listz)Keyword argument "disable" must be a listrzbasic-workflow.inilogging log_levelDEBUGlog_typenone componentsztrac.*disabledztracopt.versioncontrol.*enabledrtracpermission_policiesz/DefaultPermissionPolicy, LegacyAttachmentPolicyz trac.db.*databasebase_urlzhttp://example.org/trac.cgi)r!rXr" TypeErrorr__init__ _old_registry_old_componentsrrrabspathdirname__file__normpathnormcaserconfigr set_component_name setup_logrrreset_dbr activater) r default_dataenabledisabler destroyingrr name_or_class config_keyitemrrrr>sP            zEnvironmentStub.__init__cCstd|_|j}tjj|}|j|tj j }|jj s8|t j }t |j}|||j|dSt|jj dkrSt|jj d|rS|jj ddStd)Nz trac.testrz!Logger has unexpected handler(s).)r getLoggerlogrupperr LOG_LEVEL_MAPrsetLevelhandlersBufferingHandlersysmaxsize Formatter log_format setFormatter addHandlerlenr!flushr)rlevel level_as_int handler_cls log_handler formatterrrrrs      zEnvironmentStub.setup_logcCsdd|jjdjDS)z*Returns a list of tuples (level, message).cSsg|] }|j|fqSr) levelname getMessage)rOrecordrrrrRsz0EnvironmentStub.log_messages..r)rrbufferrrrr log_messagess zEnvironmentStub.log_messagesc Csddlm}g}t|}z|}Wn t|jjfyYnw||jkr*|}n| |s=| |j dkr=| |rC| ||jdS)zRemove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success r) db_defaultzsqlite::memory:N)rrrget_database_versionrdb_exc DatabaseError db_version reset_tables destroy_dbinit_dbrshutdowninsert_default_dataset_database_version)rrrtablesdbmrrrrrs$     zEnvironmentStub.reset_dbc Cs0z t|WdSt|jjfyYdSw)zDestroy the database.N)rrrrrrrrrrs zEnvironmentStub.destroy_dbcCs6||t|jj|jdur|dSdS)zPerforms a complete environment reset in a robust way. The database is reset, then the connections are shut down, and finally all environment files are removed from the disk. N)rrrmtreerrrrestore_component_registryrrrrreset_db_and_disks    z!EnvironmentStub.reset_db_and_diskcCs|j=}|D]1}t|dkr|\}}}d}n|\}}}}|d||ttf|d|||f|d|||fqWddS1sCwYdS)aInsert a tuple representing a user session to the `session` and `session_attributes` tables. The tuple can be length 3 with entries username, name and email, in which case an authenticated user is assumed. The tuple can also be length 4, with the last entry specifying `1` for an authenticated user or `0` for an unauthenticated user. rz'INSERT INTO session VALUES (%s, %s, %s)z6INSERT INTO session_attribute VALUES (%s,%s,'name',%s)z7INSERT INTO session_attribute VALUES (%s,%s,'email',%s)N)db_transactionrrUr)rusersdbrowrJr3email authenticatedrrr insert_userss"    "zEnvironmentStub.insert_userscCs ||dr dSt||S)Nz __main__.T)r startswithr is_component_enabled)rr5rrrrs z$EnvironmentStub.is_component_enabled)FNNNFNr)rFrGrHrIrequiredabstractrrpropertyrrrr rrrrrrr8s J     rcCs tjdd}tjtj|S)zZCreate a temp directory with prefix `trac-tempenv` and return the directory name. z trac-testdir-)prefix)tempfilemkdtemprrrrealpath)tmpdirrrrrs rcCsZtjdkrdnd}dgtjdtjD]}tj|||}tj|r*|SqdS)zRLocates a binary on the path. Returns the fully-qualified path, or None. ntz.exer:.PATHN)rr3rsplitpathseprjoinexists)r2 exec_suffixpfrrrlocates r*csBdfdd tjdkrt|trt|t}tj|ddS)Nrc s|tjtjfvr |d}t|trEt|j}t||dBz||WdStyD|dkr3t d||||dYdSw)Nri g?) runlinkremover!PermissionErrorstatst_modechmod Exceptiontimesleep)functionrexcinforetryemodeonerrorrrr; s    zrmtree..onerrorr r:)r) rr3r!rrTrgetfilesystemencodingshutilr )rrr:rr  sr TcCs ddl}ddl}ddl}ddl}ddl}ddl}ddl}ddl}ddl}ddl }ddl }ddl }ddl }ddl }ddl}ddl}ddl}ddl}tjdrPdat}||j||jj||jj||jj||jj||j j||j!j||j"j||j#j||j$j||j%j||j%j&j||j'j||j(j||j)j||j!j||j%j*j||j%j+j|t,-t.j/t0tr||j1|S)NrSKIP_FUNCTIONAL_TESTSF)2 trac.teststrac.admin.tests trac.db.teststrac.mimeview.teststrac.notification.teststrac.search.teststrac.ticket.teststrac.timeline.teststrac.upgrades.teststrac.util.teststrac.versioncontrol.tests trac.versioncontrol.web_ui.teststrac.web.teststrac.wiki.teststracopt.perm.teststracopt.ticket.tests tracopt.versioncontrol.git.tests tracopt.versioncontrol.svn.testsrrrINCLUDE_FUNCTIONAL_TESTSrraddTesttests basicSuiteadmin test_suitermimeview notificationsearchtickettimelineupgradesutilversioncontrolweb_uiwebwikirgitsvndoctest DocTestSuitermodulesrFfunctionalSuite)rtracoptsuiterrrrV*sV rV__main__z--skip-functional-testsF) defaultTest)r)Er'rdrr%rrlogging.handlersrVrr=rrr3r#rbabelr ImportErrorrparsetrac.logr trac.configr trac.corerrr trac.db.apirr trac.envr trac.permr trac.ticket.default_workflowr trac.utilr trac.util.datefmtrr trac.web.apirrrtrac.web.chromertrac.web.sessionrr objectr9rrrTestCaserrrrr*r rQrVrFargvr-mainrrrrsh          Hd%? 1