o 3au@sddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z ddlm Z ddlmZddlmZddlmZmZddlmZmZmZmZmZmZddlmZdd l m!Z!zddl"Z#Wn e$y{ddl#Z#Ynwzddl%Z&Wn e$ydZ&YnwGd d d e j'Z(Gd d d e j'Z)GdddZ*GdddZ+ddZ,da-ddZ.ddZ/Gddde j0Z1GdddZ2ddZ3d'dd Z4d'd!d"Z5d#d$Z6d%d&Z7dS)(N) import_module)StringIO) call_command) connections)SimpleTestCaseTestCase)NullTimeKeeper TimeKeepersetup_databasessetup_test_environmentteardown_databasesteardown_test_environment OrderedSet)PY37cs`eZdZfddZfddZfddZfddZfd d Zfd d Zd dZ Z S)DebugSQLTextTestResultcs4td|_|jtjd|_t|||dS)Nzdjango.db.backends)logging getLoggerloggersetLevelDEBUGdebug_sql_streamsuper__init__)selfstream descriptions verbosity __class__4/usr/lib/python3/dist-packages/django/test/runner.pyr&s zDebugSQLTextTestResult.__init__cs4t|_t|j|_|j|jt|dSN) rrr StreamHandlerhandlerr addHandlerr startTestrtestrr r!r&,sz DebugSQLTextTestResult.startTestcsTt||j|j|jr(|jd|j |j |j |j dSdS)Nr) rstopTestr removeHandlerr$showAllrseekrwritereadwriteln separator2r'rr r!r)2s  zDebugSQLTextTestResult.stopTestcsNt|||jdurd}n |jd|j}|jd|f|jd<dS)Nr)raddErrorrr,r.errors)rr(errsqlrr r!r3:s    zDebugSQLTextTestResult.addErrorcs:t|||jd|jd|jf|jd<dSNrr2)r addFailurerr,failuresr.rr(r5rr r!r8Ds  z!DebugSQLTextTestResult.addFailurecs`t||||dur.|jdt|d|jr|jn|j}|d|jf|d<dSdSr7) r addSubTestrr, issubclassfailureExceptionr9r4r.)rr(subtestr5r4rr r!r;Is  z!DebugSQLTextTestResult.addSubTestcCsp|D]3\}}}|j|j|jd|||f|j|j|j||j|j|j|qdS)Nz%s: %s)rr/ separator1getDescriptionr0)rflavourr4r(r5 sql_debugr r r!printErrorListPs z%DebugSQLTextTestResult.printErrorList) __name__ __module__ __qualname__rr&r)r3r8r;rC __classcell__r r rr!r%s     rcs4eZdZdZfddZfddZddZZS)PDBDebugResultz^ Custom result class that triggers a PDB session when an error or failure occurs. ct||||dSr")rr3debugr:rr r!r3`zPDBDebugResult.addErrorcrIr")rr8rJr:rr r!r8drKzPDBDebugResult.addFailurecCs2|d|_|\}}}td|t|dS)NFz Opening PDB: %r)_restoreStdoutbufferprintpdb post_mortem)rerrorexc_type exc_value tracebackr r r!rJhs   zPDBDebugResult.debug)rDrErF__doc__r3r8rJrGr r rr!rHZs   rHc@seZdZdZddZeddZddZdd Zd d Z d d Z ddZ ddZ ddZ ddZddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(S))RemoteTestResulta Record information about which tests have succeeded and which have failed. The sole purpose of this class is to record events in the child processes so they can be replayed in the master process. As a consequence it doesn't inherit unittest.TestResult and doesn't attempt to implement all its API. The implementation matches the unpythonic coding style of unittest2. cCs.tdur tjg|_d|_d|_d|_dS)NFr)tblibpickling_supportinstalleventsfailfast shouldStoptestsRunrr r r!r{s   zRemoteTestResult.__init__cCs |jdS)N)r]r^r r r! test_indexs zRemoteTestResult.test_indexcCstt|dS)z Confirm that obj can be pickled and unpickled as multiprocessing will need to pickle the exception in the child process and unpickle it in the parent process. Let the exception rise, if not. N)pickleloadsdumps)robjr r r!_confirm_picklablesz#RemoteTestResult._confirm_picklablecCstd|||dS)Na' Subtest failed: test: {} subtest: {} Unfortunately, the subtest that failed cannot be pickled, so the parallel test runner cannot handle it cleanly. Here is the pickling error: > {} You should re-run this test with --parallel=1 to reproduce the failure with a cleaner failure message. )rNformat)rr(r> pickle_excr r r!_print_unpicklable_subtests z+RemoteTestResult._print_unpicklable_subtestc Csz||WdStyG}z3t|d}tj|dddd}t|}tj|dddd}tdur9td||td|||d}~ww)Nr_Kz )initial_indentsubsequent_indentz {} failed: {} Unfortunately, tracebacks cannot be pickled, making it impossible for the parallel test runner to handle this exception cleanly. In order to see the traceback, you should install tblib: python -m pip install tblib aL {} failed: {} Unfortunately, the exception it raised cannot be pickled, making it impossible for the parallel test runner to handle it cleanly. Here's the error encountered while trying to pickle the exception: {} You should re-run this test with the --parallel=1 option to reproduce the failure and get a correct traceback. )re ExceptionreprtextwrapfillrWrNrf)rr(r5excoriginal_exc_txtpickle_exc_txtr r r!check_picklables$   z RemoteTestResult.check_picklablec Cs:z||WdSty}z||||d}~wwr")rerlrh)rr(r>rpr r r!check_subtest_picklablesz(RemoteTestResult.check_subtest_picklablecCs|jr |dSdSr")r[stopr^r r r!stop_if_failfasts z!RemoteTestResult.stop_if_failfastcCs d|_dS)NT)r\r^r r r!ru zRemoteTestResult.stopcC|jddS)N) startTestRunrZappendr^r r r!ryzRemoteTestResult.startTestRuncCrx)N) stopTestRunrzr^r r r!r}r|zRemoteTestResult.stopTestRuncCs$|jd7_|jd|jfdS)Nr_r&)r]rZr{r`r'r r r!r&szRemoteTestResult.startTestcC|jd|jfdS)Nr)rZr{r`r'r r r!r)zRemoteTestResult.stopTestcC,||||jd|j|f|dS)Nr3rsrZr{r`rvr:r r r!r3  zRemoteTestResult.addErrorcCr)Nr8rr:r r r!r8rzRemoteTestResult.addFailurecCsF|dur!|||||||jd|j||f|dSdS)Nr;)rsrtrZr{r`rv)rr(r>r5r r r!r;s    zRemoteTestResult.addSubTestcCr~)N addSuccessrr'r r r!rrzRemoteTestResult.addSuccesscCs|jd|j|fdS)NaddSkipr)rr(reasonr r r!rszRemoteTestResult.addSkipcCs>tdur |d|ddf}||||jd|j|fdS)Nrr_addExpectedFailure)rWrsrZr{r`r:r r r!rs z#RemoteTestResult.addExpectedFailurecCs|jd|jf|dS)NaddUnexpectedSuccess)rZr{r`rvr'r r r!rs z%RemoteTestResult.addUnexpectedSuccessN)rDrErFrUrpropertyr`rerhrsrtrvruryr}r&r)r3r8r;rrrrr r r r!rVps,  /  rVc@s&eZdZdZeZdddZddZdS) RemoteTestRunnerz Run tests and record everything but don't display anything. The implementation matches the unpythonic coding style of unittest2. FNcCs||_|dur ||_dSdSr")r[ resultclass)rr[rr r r!rs zRemoteTestRunner.__init__cCs&|}t||j|_|||Sr")runittestregisterResultr[)rr(resultr r r!run"s  zRemoteTestRunner.run)FN)rDrErFrUrVrrrr r r r!rs   rcCs<tdkrdSzttjdWStytYSw)zBDefault number of test processes when using the --parallel option.forkr_DJANGO_TEST_PROCESSES)multiprocessingget_start_methodintosenvironKeyError cpu_countr r r r!default_test_processes*s   rcCsv||jd7_|jaWdn1swYtD]}t|}|jtt}|j|| q dS)z Switch to databases dedicated to this worker. This helper lives at module-level because of the multiprocessing module's requirements. r_N) get_lockvalue _worker_idrcreationget_test_db_clone_settingsstr settings_dictupdateclose)counteralias connectionrr r r! _init_worker9s   rcCs*|\}}}}||d}||}||jfS)z Run a suite of tests with a RemoteTestRunner and return a RemoteTestResult. This helper lives at module-level and its arguments are wrapped in a tuple because of the multiprocessing module's requirements. )r[)rrZ)args runner_classsubsuite_indexsubsuiter[runnerrr r r! _run_subsuiteRs    rcs>eZdZdZeZeZeZ d fdd Z ddZ ddZ Z S) ParallelTestSuitea Run a series of tests in parallel in several processes. While the unittest module's documentation implies that orchestrating the execution of tests is the responsibility of the test runner, in practice, it appears that TestRunner classes are more concerned with formatting and displaying test results. Since there are fewer use cases for customizing TestSuite than TestRunner, implementing parallelization at the level of the TestSuite improves interoperability with existing custom test runners. A single instance of a test runner can still collect results from all tests without being aware that they have been run in parallel. Fcs$t||_||_||_tdSr")partition_suite_by_case subsuites processesr[rr)rsuiterr[rr r!rts zParallelTestSuite.__init__c sttjd}tjjjj|gd}fddtj D}| j j|} |j r0| nQz |jdd\}}WntjyDYq'tyP|Yn1wtj |}|D]%} | d} t|| d} | durkqZ|| d } | d d}| | g|RqZq(||S) a Distribute test cases across workers. Return an identifier of each test case with its result in order to use imap_unordered to show results as soon as they're available. To minimize pickling errors when getting results from workers: - pass back numeric indexes in self.subsuites instead of tests - make tracebacks picklable with tblib, if available Even with tblib, errors may still occur for dynamically created exception classes which cannot be unpickled. r)r initializerinitargscs g|] \}}j||jfqSr )rr[).0indexrr^r r! sz)ParallelTestSuite.run..Tg?)timeoutNr_)rValuectypesc_intPoolr init_worker__func__ enumeraterimap_unordered run_subsuiter\ terminatenext TimeoutError StopIterationrlistgetattrjoin) rrrpoolr test_resultsrrZtestsevent event_namer$r(r r^r!rzsD     zParallelTestSuite.runcCs t|jSr")iterrr^r r r!__iter__rwzParallelTestSuite.__iter__F)rDrErFrUrrrrrrrrrrGr r rr!r_s6rc@seZdZdZejZeZej Z ej Z e efZ      d%ddZed d Zd d Zd&d dZddZddZddZddZddZddZddZddZdd Zd!d"Zd'd#d$ZdS)(DiscoverRunnerz8A Django test runner that uses unittest2 test discovery.Nr_TFrc Ks||_||_||_||_||_||_||_||_| |_| |_ t | p"g|_ t | p)g|_ t sS|rSz t jtjdWnttjfyRt jtjdYnw||_|jrb|j dkrbtd||_|jrq|j dkrqtdd|_|rytnt|_| rdd| D|_dSdS)N)filer_zFYou cannot use --pdb with parallel tests; pass --parallel=1 to use it.zLYou cannot use -b/--buffer with parallel tests; pass --parallel=1 to use it.cSs h|] }d|vr |nd|qS)*z*%s*r )rpatternr r r! sz*DiscoverRunner.__init__..)r top_levelr interactiver[keepdbreverse debug_mode debug_sqlparallelsettags exclude_tags faulthandler is_enabledenablesysstderrfilenoAttributeErrorioUnsupportedOperation __stderr__rO ValueErrorrMtest_name_patternsr r time_keeper)rrrrrr[rrrrrrrrrOrMenable_faulthandlertimingkwargsr r r!rsB  zDiscoverRunner.__init__c Cs|jddddd|jdddd d |jd d d d|jddd dd|jdd dd|jddd dd|jdddttddd|jdddd d!|jd"dd#d$d!|jd%d d&d|jd'd(d d)d|jd*d+d,d-d!|jd.d d/dtr|jd0dd1d2d!dSdS)3Nz-tz--top-level-directoryrz,Top level of project for unittest discovery.)desthelpz-pz --patternztest*.pyz0The test matching pattern. Defaults to test*.py.)defaultrz--keepdb store_truez#Preserves the test DB between runs.)actionrz-rz --reversezReverses test cases order.z --debug-modezSets settings.DEBUG to True.z-dz --debug-sqlz%Prints logged SQL queries on failure.z --parallel?r_Nz+Run tests using up to N parallel processes.)nargsrtypeconstmetavarrz--tagr{rzBRun only tests with the specified tag. Can be used multiple times.)rrrz --exclude-tagrzDDo not run tests with the specified tag. Can be used multiple times.z--pdbz@Runs a debugger (pdb, or ipdb if installed) on error or failure.z-bz--bufferz"Discard output from passing tests.z--no-faulthandler store_falserz5Disables the Python faulthandler module during tests.z--timingz=Output timings, including database set up and total run time.z-krz~Only run test methods and classes that match the pattern or substring. Can be used multiple times. Same as unittest -k option.) add_argumentrrr)clsparserr r r! add_argumentssv zDiscoverRunner.add_argumentscKst|jdtdS)N)rJ)r rrinstallHandlerrrr r r!r +s  z%DiscoverRunner.setup_test_environmentcKs|}|pdg}|p g}|j|j_i}|jdur|j|d<|jdur(|j|d<|D]e}|}d}tj |}tj |sE|j |}n,tj |rq|jsq|} tj | d} tj | rltj| } | | krin| } qP | |d<|rw|st|r|jjd d|i|}d|j_||q*|D]} || q|js|jr|jdkr|jrtdd t|j|jrtd d t|jt||j|j}t||j|j}|jd kr|||j|j } t!| j"}t#|j||_|jd kr| }|S) N.r top_level_dirTz __init__.py start_dirrzIncluding test tag(s): %s., zExcluding test tag(s): %s.r_r )$ test_suiter test_loadertestNamePatternsrrcopyrpathabspathexistsloadTestsFromNameisdirrdirnamecountTestCasesis_discoverablediscover_top_level_diraddTestsaddTestrrrrNsortedfilter_tests_by_tags reorder_suite reorder_byrrparallel_test_suiter[lenrmin)r test_labels extra_testsrrdiscover_kwargslabelr label_as_pathrinit_pytry_nextr(parallel_suiteparallel_unitsr r r! build_suite/s`                  zDiscoverRunner.build_suitecKs(t|j|jf|j|j|j|jd|S)N)rrrr)_setup_databasesrrrrrrrr r r!r szDiscoverRunner.setup_databasescCs|jrtS|jr tSdSr")rrrOrHr^r r r!get_resultclasss zDiscoverRunner.get_resultclasscCs|j||j|jdS)N)r[rrrM)r[r(rrMr^r r r!get_test_runner_kwargss z%DiscoverRunner.get_test_runner_kwargscCstd|j|ddS)Ncheck)r databases)rr)rr+r r r! run_checksszDiscoverRunner.run_checkscKs"|}|jdi|}||S)Nr )r) test_runnerr)rrrrr r r! run_suites zDiscoverRunner.run_suitecKst||j|j|jddS)z%Destroy all the non-mirror databases.)rrrN)_teardown_databasesrrr)r old_configrr r r!r s  z!DiscoverRunner.teardown_databasescKsttdSr")rr*r rr r r!r s z(DiscoverRunner.teardown_test_environmentcKst|jt|jSr")rr9r4)rrrrr r r! suite_resultszDiscoverRunner.suite_resultcCs`t}|D](}t|tjr%t|dd}|dkrttS|r$||q|||q|S)Nr+__all__)r isinstancerrrrr_get_databases)rrr+r(test_databasesr r r!r4s    zDiscoverRunner._get_databasescsD|||jdkr fddtD}|r tddt|S)Nrcsg|]}|vr|qSr r )rrr+r r!rsz0DiscoverRunner.get_databases..z)Skipping setup of unused database(s): %s.r)r4rrrNrr)rrunused_databasesr r6r! get_databasess  zDiscoverRunner.get_databasesc KsZ||||}||}|jd|j|d}Wdn1s&wYd}zFz ||||}Wn tyDd}wWz!|jd | |Wdn1s]wY| Wn:tys|sqYn/wz!|jd | |Wdn1swY| Wwty|sYww|j | ||S)aZ Run the unit tests for all the test labels in the provided list. Test labels should be dotted Python paths to test modules, test classes, or test methods. A list of 'extra' tests may also be provided; these tests will be added to the test suite. Return the number of tests that failed. zTotal database setup)aliasesNFTzTotal database teardown) r r&r8rtimedr r,r.rlr r print_resultsr1) rrrrrr+r0 run_failedrr r r! run_testssJ            zDiscoverRunner.run_tests)NNr_TFFFFFrNNNFFTF)NNr") rDrErFrUr TestSuiterrrTextTestRunnerr-defaultTestLoaderrrrrr classmethodrr r&r r(r)r,r.r r r1r4r8r=r r r r!rs: + B S  rc CsBzt|}Wn ttfyYnwt|dStjtj|S)z Check if a test label points to a Python package or file directory. Relative labels like "." and ".." are seen as directories. __path__)r ImportError TypeErrorhasattrrr rr )r modr r r!rs  rFcCs`t|}t|}ddt|dD}t||||d|}t|dD] }|||q$|S)aI Reorder a test suite by test type. `classes` is a sequence of types All tests of type classes[0] are placed first, then tests of type classes[1], etc. Tests with no match in classes are placed last. If `reverse` is True, sort tests within classes in opposite order but don't reverse test classes. cSsg|]}tqSr r)rir r r!r sz!reorder_suite..r_r)rrrangepartition_suite_by_typer)rclassesr class_count suite_classbinsreordered_suiterGr r r!rs rcCst|}|r tt|}|D]0}t||rt||||dqtt|D]}t|||r6|||nq$|d|qdS)aV Partition a test suite by test type. Also prevent duplicated tests. classes is a sequence of types bins is a sequence of TestSuites, one more than classes reverse changes the ordering of tests within bins Tests of type classes[i] are added to bins[i], tests with no match found in classes are place in bins[-1] rHr2N)rreversedtupler3rJrIradd)rrKrNrrMr(rGr r r!rJs   rJcCsZg}t|}t|tD]\}}t|tjr|||q |D] }|t|q q |S)zCPartition a test suite by test case, preserving the order of tests.) r itertoolsgroupbyr<rrr{extendr)rgroupsrM test_type test_groupitemr r r!r+s rc Cst|}|}|D]I}t||r|t|||q tt|dt}t|dt|}t|||}tt|dt} || } | |} | sH|sR| |sR| |q |S)Nr_testMethodName) rr3rrrrrunion intersectionr) rrrrMfiltered_suiter( test_tags test_fn_nametest_fn test_fn_tagsall_tags matched_tagsr r r!r8s     rr)8rrrrSrrrrarrnr importlibrrdjango.core.managementr django.dbr django.testrrdjango.test.utilsrr r r'r r r/r django.utils.datastructuresrdjango.utils.versionripdbrOrCtblib.pickling_supportrWTextTestResultrrHrVrrrrrr>rrrrrJrrr r r r!s^            5%  U9