Page MenuHomeSealhub

No OneTemporary

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index fdb205d5..5b597ce1 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,322 +1,325 @@
<?php
/**
* This file is automatically generated. Use 'arc liberate' to rebuild it.
* @generated
* @phutil-library-version 2
*/
phutil_register_library_map(array(
'__library_version__' => 2,
'class' =>
array(
'ArcanistAliasWorkflow' => 'workflow/ArcanistAliasWorkflow.php',
'ArcanistAmendWorkflow' => 'workflow/ArcanistAmendWorkflow.php',
'ArcanistAnoidWorkflow' => 'workflow/ArcanistAnoidWorkflow.php',
'ArcanistApacheLicenseLinter' => 'lint/linter/ArcanistApacheLicenseLinter.php',
'ArcanistArcanistLinterTestCase' => 'lint/linter/__tests__/ArcanistArcanistLinterTestCase.php',
'ArcanistBackoutWorkflow' => 'workflow/ArcanistBackoutWorkflow.php',
'ArcanistBaseCommitParser' => 'parser/ArcanistBaseCommitParser.php',
'ArcanistBaseCommitParserTestCase' => 'parser/__tests__/ArcanistBaseCommitParserTestCase.php',
'ArcanistBaseTestResultParser' => 'unit/engine/ArcanistBaseTestResultParser.php',
'ArcanistBaseUnitTestEngine' => 'unit/engine/ArcanistBaseUnitTestEngine.php',
'ArcanistBaseWorkflow' => 'workflow/ArcanistBaseWorkflow.php',
'ArcanistBaseXHPASTLinter' => 'lint/linter/ArcanistBaseXHPASTLinter.php',
'ArcanistBookmarkWorkflow' => 'workflow/ArcanistBookmarkWorkflow.php',
'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php',
'ArcanistBritishTestCase' => 'configuration/__tests__/ArcanistBritishTestCase.php',
'ArcanistBrowseWorkflow' => 'workflow/ArcanistBrowseWorkflow.php',
'ArcanistBundle' => 'parser/ArcanistBundle.php',
'ArcanistBundleTestCase' => 'parser/__tests__/ArcanistBundleTestCase.php',
'ArcanistCSSLintLinter' => 'lint/linter/ArcanistCSSLintLinter.php',
'ArcanistCSSLintLinterTestCase' => 'lint/linter/__tests__/ArcanistCSSLintLinterTestCase.php',
'ArcanistCallConduitWorkflow' => 'workflow/ArcanistCallConduitWorkflow.php',
'ArcanistCapabilityNotSupportedException' => 'workflow/exception/ArcanistCapabilityNotSupportedException.php',
'ArcanistChooseInvalidRevisionException' => 'exception/ArcanistChooseInvalidRevisionException.php',
'ArcanistChooseNoRevisionsException' => 'exception/ArcanistChooseNoRevisionsException.php',
'ArcanistCloseRevisionWorkflow' => 'workflow/ArcanistCloseRevisionWorkflow.php',
'ArcanistCloseWorkflow' => 'workflow/ArcanistCloseWorkflow.php',
'ArcanistCommentRemover' => 'parser/ArcanistCommentRemover.php',
'ArcanistCommentRemoverTestCase' => 'parser/__tests__/ArcanistCommentRemoverTestCase.php',
'ArcanistCommitWorkflow' => 'workflow/ArcanistCommitWorkflow.php',
'ArcanistConduitLinter' => 'lint/linter/ArcanistConduitLinter.php',
'ArcanistConfiguration' => 'configuration/ArcanistConfiguration.php',
'ArcanistConfigurationDrivenLintEngine' => 'lint/engine/ArcanistConfigurationDrivenLintEngine.php',
'ArcanistCoverWorkflow' => 'workflow/ArcanistCoverWorkflow.php',
'ArcanistCppcheckLinter' => 'lint/linter/ArcanistCppcheckLinter.php',
'ArcanistCpplintLinter' => 'lint/linter/ArcanistCpplintLinter.php',
'ArcanistCpplintLinterTestCase' => 'lint/linter/__tests__/ArcanistCpplintLinterTestCase.php',
'ArcanistDiffChange' => 'parser/diff/ArcanistDiffChange.php',
'ArcanistDiffChangeType' => 'parser/diff/ArcanistDiffChangeType.php',
'ArcanistDiffHunk' => 'parser/diff/ArcanistDiffHunk.php',
'ArcanistDiffParser' => 'parser/ArcanistDiffParser.php',
'ArcanistDiffParserTestCase' => 'parser/__tests__/ArcanistDiffParserTestCase.php',
'ArcanistDiffUtils' => 'difference/ArcanistDiffUtils.php',
'ArcanistDiffUtilsTestCase' => 'difference/__tests__/ArcanistDiffUtilsTestCase.php',
'ArcanistDiffWorkflow' => 'workflow/ArcanistDiffWorkflow.php',
'ArcanistDifferentialCommitMessage' => 'differential/ArcanistDifferentialCommitMessage.php',
'ArcanistDifferentialCommitMessageParserException' => 'differential/ArcanistDifferentialCommitMessageParserException.php',
'ArcanistDifferentialRevisionHash' => 'differential/constants/ArcanistDifferentialRevisionHash.php',
'ArcanistDifferentialRevisionStatus' => 'differential/constants/ArcanistDifferentialRevisionStatus.php',
'ArcanistDownloadWorkflow' => 'workflow/ArcanistDownloadWorkflow.php',
'ArcanistEventType' => 'events/constant/ArcanistEventType.php',
'ArcanistExportWorkflow' => 'workflow/ArcanistExportWorkflow.php',
'ArcanistExternalLinter' => 'lint/linter/ArcanistExternalLinter.php',
'ArcanistFeatureWorkflow' => 'workflow/ArcanistFeatureWorkflow.php',
'ArcanistFilenameLinter' => 'lint/linter/ArcanistFilenameLinter.php',
'ArcanistFlagWorkflow' => 'workflow/ArcanistFlagWorkflow.php',
'ArcanistFlake8Linter' => 'lint/linter/ArcanistFlake8Linter.php',
'ArcanistFlake8LinterTestCase' => 'lint/linter/__tests__/ArcanistFlake8LinterTestCase.php',
'ArcanistFutureLinter' => 'lint/linter/ArcanistFutureLinter.php',
'ArcanistGeneratedLinter' => 'lint/linter/ArcanistGeneratedLinter.php',
'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php',
'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php',
'ArcanistGitHookPreReceiveWorkflow' => 'workflow/ArcanistGitHookPreReceiveWorkflow.php',
'ArcanistHelpWorkflow' => 'workflow/ArcanistHelpWorkflow.php',
'ArcanistHgClientChannel' => 'hgdaemon/ArcanistHgClientChannel.php',
'ArcanistHgProxyClient' => 'hgdaemon/ArcanistHgProxyClient.php',
'ArcanistHgProxyServer' => 'hgdaemon/ArcanistHgProxyServer.php',
'ArcanistHgServerChannel' => 'hgdaemon/ArcanistHgServerChannel.php',
'ArcanistHookAPI' => 'repository/hookapi/ArcanistHookAPI.php',
'ArcanistInlinesWorkflow' => 'workflow/ArcanistInlinesWorkflow.php',
'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php',
'ArcanistJSHintLinter' => 'lint/linter/ArcanistJSHintLinter.php',
'ArcanistLandWorkflow' => 'workflow/ArcanistLandWorkflow.php',
'ArcanistLiberateWorkflow' => 'workflow/ArcanistLiberateWorkflow.php',
'ArcanistLicenseLinter' => 'lint/linter/ArcanistLicenseLinter.php',
'ArcanistLintConsoleRenderer' => 'lint/renderer/ArcanistLintConsoleRenderer.php',
'ArcanistLintEngine' => 'lint/engine/ArcanistLintEngine.php',
'ArcanistLintJSONRenderer' => 'lint/renderer/ArcanistLintJSONRenderer.php',
'ArcanistLintLikeCompilerRenderer' => 'lint/renderer/ArcanistLintLikeCompilerRenderer.php',
'ArcanistLintMessage' => 'lint/ArcanistLintMessage.php',
'ArcanistLintNoneRenderer' => 'lint/renderer/ArcanistLintNoneRenderer.php',
'ArcanistLintPatcher' => 'lint/ArcanistLintPatcher.php',
'ArcanistLintRenderer' => 'lint/renderer/ArcanistLintRenderer.php',
'ArcanistLintResult' => 'lint/ArcanistLintResult.php',
'ArcanistLintSeverity' => 'lint/ArcanistLintSeverity.php',
'ArcanistLintSummaryRenderer' => 'lint/renderer/ArcanistLintSummaryRenderer.php',
'ArcanistLintWorkflow' => 'workflow/ArcanistLintWorkflow.php',
'ArcanistLinter' => 'lint/linter/ArcanistLinter.php',
'ArcanistLinterTestCase' => 'lint/linter/__tests__/ArcanistLinterTestCase.php',
'ArcanistListWorkflow' => 'workflow/ArcanistListWorkflow.php',
'ArcanistMarkCommittedWorkflow' => 'workflow/ArcanistMarkCommittedWorkflow.php',
'ArcanistMercurialAPI' => 'repository/api/ArcanistMercurialAPI.php',
'ArcanistMercurialParser' => 'repository/parser/ArcanistMercurialParser.php',
'ArcanistMercurialParserTestCase' => 'repository/parser/__tests__/ArcanistMercurialParserTestCase.php',
'ArcanistMergeConflictLinter' => 'lint/linter/ArcanistMergeConflictLinter.php',
'ArcanistNoEffectException' => 'exception/usage/ArcanistNoEffectException.php',
'ArcanistNoEngineException' => 'exception/usage/ArcanistNoEngineException.php',
'ArcanistNoLintLinter' => 'lint/linter/ArcanistNoLintLinter.php',
'ArcanistNoLintTestCaseMisnamed' => 'lint/linter/__tests__/ArcanistNoLintTestCase.php',
'ArcanistPEP8Linter' => 'lint/linter/ArcanistPEP8Linter.php',
'ArcanistPEP8LinterTestCase' => 'lint/linter/__tests__/ArcanistPEP8LinterTestCase.php',
'ArcanistPHPCSLinterTestCase' => 'lint/linter/__tests__/ArcanistPHPCSLinterTestCase.php',
'ArcanistPasteWorkflow' => 'workflow/ArcanistPasteWorkflow.php',
'ArcanistPatchWorkflow' => 'workflow/ArcanistPatchWorkflow.php',
'ArcanistPhpcsLinter' => 'lint/linter/ArcanistPhpcsLinter.php',
'ArcanistPhutilLibraryLinter' => 'lint/linter/ArcanistPhutilLibraryLinter.php',
'ArcanistPhutilTestCase' => 'unit/engine/phutil/ArcanistPhutilTestCase.php',
'ArcanistPhutilTestCaseTestCase' => 'unit/engine/phutil/testcase/ArcanistPhutilTestCaseTestCase.php',
'ArcanistPhutilTestSkippedException' => 'unit/engine/phutil/testcase/ArcanistPhutilTestSkippedException.php',
'ArcanistPhutilTestTerminatedException' => 'unit/engine/phutil/testcase/ArcanistPhutilTestTerminatedException.php',
'ArcanistPhutilXHPASTLinter' => 'lint/linter/ArcanistPhutilXHPASTLinter.php',
'ArcanistPhutilXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistPhutilXHPASTLinterTestCase.php',
'ArcanistPyFlakesLinter' => 'lint/linter/ArcanistPyFlakesLinter.php',
'ArcanistPyLintLinter' => 'lint/linter/ArcanistPyLintLinter.php',
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
'ArcanistRepositoryAPIMiscTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIMiscTestCase.php',
'ArcanistRepositoryAPIStateTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIStateTestCase.php',
'ArcanistRevertWorkflow' => 'workflow/ArcanistRevertWorkflow.php',
'ArcanistRubyLinter' => 'lint/linter/ArcanistRubyLinter.php',
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php',
'ArcanistScalaSBTLinter' => 'lint/linter/ArcanistScalaSBTLinter.php',
'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php',
'ArcanistSetConfigWorkflow' => 'workflow/ArcanistSetConfigWorkflow.php',
'ArcanistSettings' => 'configuration/ArcanistSettings.php',
'ArcanistShellCompleteWorkflow' => 'workflow/ArcanistShellCompleteWorkflow.php',
'ArcanistSingleLintEngine' => 'lint/engine/ArcanistSingleLintEngine.php',
'ArcanistSpellingDefaultData' => 'lint/linter/spelling/ArcanistSpellingDefaultData.php',
'ArcanistSpellingLinter' => 'lint/linter/ArcanistSpellingLinter.php',
'ArcanistSpellingLinterTestCase' => 'lint/linter/__tests__/ArcanistSpellingLinterTestCase.php',
'ArcanistSubversionAPI' => 'repository/api/ArcanistSubversionAPI.php',
'ArcanistSubversionHookAPI' => 'repository/hookapi/ArcanistSubversionHookAPI.php',
'ArcanistSvnHookPreCommitWorkflow' => 'workflow/ArcanistSvnHookPreCommitWorkflow.php',
'ArcanistTasksWorkflow' => 'workflow/ArcanistTasksWorkflow.php',
'ArcanistTestCase' => 'infrastructure/testing/ArcanistTestCase.php',
'ArcanistTextLinter' => 'lint/linter/ArcanistTextLinter.php',
'ArcanistTextLinterTestCase' => 'lint/linter/__tests__/ArcanistTextLinterTestCase.php',
'ArcanistTodoWorkflow' => 'workflow/ArcanistTodoWorkflow.php',
'ArcanistUncommittedChangesException' => 'exception/usage/ArcanistUncommittedChangesException.php',
'ArcanistUnitConsoleRenderer' => 'unit/renderer/ArcanistUnitConsoleRenderer.php',
'ArcanistUnitRenderer' => 'unit/renderer/ArcanistUnitRenderer.php',
'ArcanistUnitTestResult' => 'unit/ArcanistUnitTestResult.php',
'ArcanistUnitWorkflow' => 'workflow/ArcanistUnitWorkflow.php',
'ArcanistUpgradeWorkflow' => 'workflow/ArcanistUpgradeWorkflow.php',
'ArcanistUploadWorkflow' => 'workflow/ArcanistUploadWorkflow.php',
'ArcanistUsageException' => 'exception/ArcanistUsageException.php',
'ArcanistUserAbortException' => 'exception/usage/ArcanistUserAbortException.php',
'ArcanistWhichWorkflow' => 'workflow/ArcanistWhichWorkflow.php',
'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php',
'ArcanistXHPASTLintNamingHook' => 'lint/linter/xhpast/ArcanistXHPASTLintNamingHook.php',
'ArcanistXHPASTLintNamingHookTestCase' => 'lint/linter/xhpast/__tests__/ArcanistXHPASTLintNamingHookTestCase.php',
'ArcanistXHPASTLintSwitchHook' => 'lint/linter/xhpast/ArcanistXHPASTLintSwitchHook.php',
'ArcanistXHPASTLintTestSwitchHook' => 'lint/linter/__tests__/ArcanistXHPASTLintTestSwitchHook.php',
'ArcanistXHPASTLinter' => 'lint/linter/ArcanistXHPASTLinter.php',
'ArcanistXHPASTLinterTestCase' => 'lint/linter/__tests__/ArcanistXHPASTLinterTestCase.php',
+ 'ArcanistXUnitTestResultParser' => 'unit/engine/ArcanistXUnitTestResultParser.php',
'CSharpToolsTestEngine' => 'unit/engine/CSharpToolsTestEngine.php',
'ComprehensiveLintEngine' => 'lint/engine/ComprehensiveLintEngine.php',
'ExampleLintEngine' => 'lint/engine/ExampleLintEngine.php',
'GoTestResultParser' => 'unit/engine/GoTestResultParser.php',
'GoTestResultParserTestCase' => 'unit/engine/__tests__/GoTestResultParserTestCase.php',
'NoseTestEngine' => 'unit/engine/NoseTestEngine.php',
'PHPUnitTestEngineTestCase' => 'unit/engine/__tests__/PHPUnitTestEngineTestCase.php',
'PhpunitResultParser' => 'unit/engine/PhpunitResultParser.php',
'PhpunitTestEngine' => 'unit/engine/PhpunitTestEngine.php',
'PhutilLintEngine' => 'lint/engine/PhutilLintEngine.php',
'PhutilUnitTestEngine' => 'unit/engine/PhutilUnitTestEngine.php',
'PhutilUnitTestEngineTestCase' => 'unit/engine/__tests__/PhutilUnitTestEngineTestCase.php',
'PytestTestEngine' => 'unit/engine/PytestTestEngine.php',
'UnitTestableArcanistLintEngine' => 'lint/engine/UnitTestableArcanistLintEngine.php',
'XUnitTestEngine' => 'unit/engine/XUnitTestEngine.php',
+ 'XUnitTestResultParserTestCase' => 'unit/engine/__tests__/XUnitTestResultParserTestCase.php',
),
'function' =>
array(
),
'xmap' =>
array(
'ArcanistAliasWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistAmendWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistAnoidWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistApacheLicenseLinter' => 'ArcanistLicenseLinter',
'ArcanistArcanistLinterTestCase' => 'ArcanistLinterTestCase',
'ArcanistBackoutWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistBaseCommitParserTestCase' => 'ArcanistTestCase',
'ArcanistBaseWorkflow' => 'Phobject',
'ArcanistBaseXHPASTLinter' => 'ArcanistFutureLinter',
'ArcanistBookmarkWorkflow' => 'ArcanistFeatureWorkflow',
'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow',
'ArcanistBritishTestCase' => 'ArcanistTestCase',
'ArcanistBrowseWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistBundleTestCase' => 'ArcanistTestCase',
'ArcanistCSSLintLinter' => 'ArcanistExternalLinter',
'ArcanistCSSLintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistCallConduitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCapabilityNotSupportedException' => 'Exception',
'ArcanistChooseInvalidRevisionException' => 'Exception',
'ArcanistChooseNoRevisionsException' => 'Exception',
'ArcanistCloseRevisionWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCloseWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCommentRemoverTestCase' => 'ArcanistTestCase',
'ArcanistCommitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistConduitLinter' => 'ArcanistLinter',
'ArcanistConfigurationDrivenLintEngine' => 'ArcanistLintEngine',
'ArcanistCoverWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistCppcheckLinter' => 'ArcanistLinter',
'ArcanistCpplintLinter' => 'ArcanistLinter',
'ArcanistCpplintLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistDiffParserTestCase' => 'ArcanistTestCase',
'ArcanistDiffUtilsTestCase' => 'ArcanistTestCase',
'ArcanistDiffWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistDifferentialCommitMessageParserException' => 'Exception',
'ArcanistDownloadWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistEventType' => 'PhutilEventType',
'ArcanistExportWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistExternalLinter' => 'ArcanistFutureLinter',
'ArcanistFeatureWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistFilenameLinter' => 'ArcanistLinter',
'ArcanistFlagWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistFlake8Linter' => 'ArcanistExternalLinter',
'ArcanistFlake8LinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistFutureLinter' => 'ArcanistLinter',
'ArcanistGeneratedLinter' => 'ArcanistLinter',
'ArcanistGetConfigWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistHelpWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistHgClientChannel' => 'PhutilProtocolChannel',
'ArcanistHgServerChannel' => 'PhutilProtocolChannel',
'ArcanistInlinesWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistInstallCertificateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistJSHintLinter' => 'ArcanistLinter',
'ArcanistLandWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLicenseLinter' => 'ArcanistLinter',
'ArcanistLintConsoleRenderer' => 'ArcanistLintRenderer',
'ArcanistLintJSONRenderer' => 'ArcanistLintRenderer',
'ArcanistLintLikeCompilerRenderer' => 'ArcanistLintRenderer',
'ArcanistLintNoneRenderer' => 'ArcanistLintRenderer',
'ArcanistLintSummaryRenderer' => 'ArcanistLintRenderer',
'ArcanistLintWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistLinterTestCase' => 'ArcanistPhutilTestCase',
'ArcanistListWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistMarkCommittedWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistMercurialAPI' => 'ArcanistRepositoryAPI',
'ArcanistMercurialParserTestCase' => 'ArcanistTestCase',
'ArcanistMergeConflictLinter' => 'ArcanistLinter',
'ArcanistNoEffectException' => 'ArcanistUsageException',
'ArcanistNoEngineException' => 'ArcanistUsageException',
'ArcanistNoLintLinter' => 'ArcanistLinter',
'ArcanistNoLintTestCaseMisnamed' => 'ArcanistLinterTestCase',
'ArcanistPEP8Linter' => 'ArcanistExternalLinter',
'ArcanistPEP8LinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPHPCSLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPasteWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistPatchWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistPhpcsLinter' => 'ArcanistExternalLinter',
'ArcanistPhutilLibraryLinter' => 'ArcanistLinter',
'ArcanistPhutilTestCaseTestCase' => 'ArcanistPhutilTestCase',
'ArcanistPhutilTestSkippedException' => 'Exception',
'ArcanistPhutilTestTerminatedException' => 'Exception',
'ArcanistPhutilXHPASTLinter' => 'ArcanistBaseXHPASTLinter',
'ArcanistPhutilXHPASTLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistPyFlakesLinter' => 'ArcanistLinter',
'ArcanistPyLintLinter' => 'ArcanistLinter',
'ArcanistRepositoryAPIMiscTestCase' => 'ArcanistTestCase',
'ArcanistRepositoryAPIStateTestCase' => 'ArcanistTestCase',
'ArcanistRevertWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistRubyLinter' => 'ArcanistExternalLinter',
'ArcanistRubyLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistScalaSBTLinter' => 'ArcanistLinter',
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
'ArcanistSetConfigWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistShellCompleteWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistSingleLintEngine' => 'ArcanistLintEngine',
'ArcanistSpellingLinter' => 'ArcanistLinter',
'ArcanistSpellingLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistSubversionAPI' => 'ArcanistRepositoryAPI',
'ArcanistSubversionHookAPI' => 'ArcanistHookAPI',
'ArcanistSvnHookPreCommitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistTasksWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistTestCase' => 'ArcanistPhutilTestCase',
'ArcanistTextLinter' => 'ArcanistLinter',
'ArcanistTextLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'ArcanistTodoWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistUncommittedChangesException' => 'ArcanistUsageException',
'ArcanistUnitConsoleRenderer' => 'ArcanistUnitRenderer',
'ArcanistUnitWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistUpgradeWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistUploadWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistUsageException' => 'Exception',
'ArcanistUserAbortException' => 'ArcanistUsageException',
'ArcanistWhichWorkflow' => 'ArcanistBaseWorkflow',
'ArcanistXHPASTLintNamingHookTestCase' => 'ArcanistTestCase',
'ArcanistXHPASTLintTestSwitchHook' => 'ArcanistXHPASTLintSwitchHook',
'ArcanistXHPASTLinter' => 'ArcanistBaseXHPASTLinter',
'ArcanistXHPASTLinterTestCase' => 'ArcanistArcanistLinterTestCase',
'CSharpToolsTestEngine' => 'XUnitTestEngine',
'ComprehensiveLintEngine' => 'ArcanistLintEngine',
'ExampleLintEngine' => 'ArcanistLintEngine',
'GoTestResultParser' => 'ArcanistBaseTestResultParser',
'GoTestResultParserTestCase' => 'ArcanistTestCase',
'NoseTestEngine' => 'ArcanistBaseUnitTestEngine',
'PHPUnitTestEngineTestCase' => 'ArcanistTestCase',
'PhpunitResultParser' => 'ArcanistBaseTestResultParser',
'PhpunitTestEngine' => 'ArcanistBaseUnitTestEngine',
'PhutilLintEngine' => 'ArcanistLintEngine',
'PhutilUnitTestEngine' => 'ArcanistBaseUnitTestEngine',
'PhutilUnitTestEngineTestCase' => 'ArcanistTestCase',
'PytestTestEngine' => 'ArcanistBaseUnitTestEngine',
'UnitTestableArcanistLintEngine' => 'ArcanistLintEngine',
'XUnitTestEngine' => 'ArcanistBaseUnitTestEngine',
+ 'XUnitTestResultParserTestCase' => 'ArcanistTestCase',
),
));
diff --git a/src/unit/engine/PytestTestEngine.php b/src/unit/engine/ArcanistXUnitTestResultParser.php
similarity index 73%
copy from src/unit/engine/PytestTestEngine.php
copy to src/unit/engine/ArcanistXUnitTestResultParser.php
index 37a43b72..a3fdacf8 100644
--- a/src/unit/engine/PytestTestEngine.php
+++ b/src/unit/engine/ArcanistXUnitTestResultParser.php
@@ -1,89 +1,97 @@
<?php
/**
- * Very basic 'py.test' unit test engine wrapper.
+ * Parser for JUnit, NUnit, etc results format - https://gist.github.com/959290
*
* @group unitrun
*/
-final class PytestTestEngine extends ArcanistBaseUnitTestEngine {
-
- public function run() {
- $junit_tmp = new TempFile();
-
- $cmd_line = csprintf('py.test --junitxml=%s',
- $junit_tmp);
-
- $future = new ExecFuture('%C', $cmd_line);
- list($stdout, $stderr) = $future->resolvex();
-
- return $this->parseTestResults($junit_tmp);
- }
+final class ArcanistXUnitTestResultParser {
+
+ /**
+ * Parse test results from provided input and return an array
+ * of ArcanistUnitTestResult
+ *
+ * @param string $path Path to test (Ignored)
+ * @param string $test_results String containing test results
+ *
+ * @return array ArcanistUnitTestResult
+ */
+ public function parseTestResults($test_results) {
+ if (!strlen($test_results)) {
+ throw new Exception(
+ 'test_results argument to parseTestResults must not be empty');
+ }
- public function parseTestResults($junit_tmp) {
// xunit xsd: https://gist.github.com/959290
$xunit_dom = new DOMDocument();
- $xunit_dom->loadXML(Filesystem::readFile($junit_tmp));
+ $load_success = @$xunit_dom->loadXML($test_results);
+
+ if (!$load_success) {
+ $input_start = phutil_utf8_shorten($test_results, 150);
+ throw new Exception(
+ "Failed to load XUnit report; Input starts with:\n\n {$input_start}");
+ }
$results = array();
$testcases = $xunit_dom->getElementsByTagName("testcase");
foreach ($testcases as $testcase) {
$classname = $testcase->getAttribute("classname");
$name = $testcase->getAttribute("name");
$time = $testcase->getAttribute("time");
$status = ArcanistUnitTestResult::RESULT_PASS;
$user_data = "";
// A skipped test is a test which was ignored using framework
// mechanizms (e.g. @skip decorator)
$skipped = $testcase->getElementsByTagName("skipped");
if ($skipped->length > 0) {
$status = ArcanistUnitTestResult::RESULT_SKIP;
$messages = array();
for ($ii = 0; $ii < $skipped->length; $ii++) {
$messages[] = trim($skipped->item($ii)->nodeValue, " \n");
}
$user_data .= implode("\n", $messages);
}
// Failure is a test which the code has explicitly failed by using
// the mechanizms for that purpose. e.g., via an assertEquals
$failures = $testcase->getElementsByTagName("failure");
if ($failures->length > 0) {
$status = ArcanistUnitTestResult::RESULT_FAIL;
$messages = array();
for ($ii = 0; $ii < $failures->length; $ii++) {
$messages[] = trim($failures->item($ii)->nodeValue, " \n");
}
$user_data .= implode("\n", $messages)."\n";
}
// An errored test is one that had an unanticipated problem. e.g., an
// unchecked throwable, or a problem with an implementation of the
// test.
$errors = $testcase->getElementsByTagName("error");
if ($errors->length > 0) {
$status = ArcanistUnitTestResult::RESULT_BROKEN;
$messages = array();
for ($ii = 0; $ii < $errors->length; $ii++) {
$messages[] = trim($errors->item($ii)->nodeValue, " \n");
}
$user_data .= implode("\n", $messages)."\n";
}
$result = new ArcanistUnitTestResult();
$result->setName($classname.".".$name);
$result->setResult($status);
$result->setDuration($time);
$result->setUserData($user_data);
$results[] = $result;
}
return $results;
}
}
diff --git a/src/unit/engine/NoseTestEngine.php b/src/unit/engine/NoseTestEngine.php
index 49f03994..00296a08 100644
--- a/src/unit/engine/NoseTestEngine.php
+++ b/src/unit/engine/NoseTestEngine.php
@@ -1,244 +1,186 @@
<?php
/**
* Very basic 'nose' unit test engine wrapper.
*
* Requires nose 1.1.3 for code coverage.
*
* @group unitrun
*/
final class NoseTestEngine extends ArcanistBaseUnitTestEngine {
public function run() {
$paths = $this->getPaths();
$affected_tests = array();
foreach ($paths as $path) {
$absolute_path = Filesystem::resolvePath($path);
if (is_dir($absolute_path)) {
$absolute_test_path = Filesystem::resolvePath("tests/".$path);
if (is_readable($absolute_test_path)) {
$affected_tests[] = $absolute_test_path;
}
}
if (is_readable($absolute_path)) {
$filename = basename($path);
$directory = dirname($path);
// assumes directory layout: tests/<package>/test_<module>.py
$relative_test_path = "tests/".$directory."/test_".$filename;
$absolute_test_path = Filesystem::resolvePath($relative_test_path);
if (is_readable($absolute_test_path)) {
$affected_tests[] = $absolute_test_path;
}
}
}
return $this->runTests($affected_tests, './');
}
public function runTests($test_paths, $source_path) {
if (empty($test_paths)) {
return array();
}
$futures = array();
$tmpfiles = array();
foreach ($test_paths as $test_path) {
$xunit_tmp = new TempFile();
$cover_tmp = new TempFile();
$future = $this->buildTestFuture($test_path,
$xunit_tmp,
$cover_tmp);
$futures[$test_path] = $future;
$tmpfiles[$test_path] = array(
'xunit' => $xunit_tmp,
'cover' => $cover_tmp,
);
}
$results = array();
foreach (Futures($futures)->limit(4) as $test_path => $future) {
try {
list($stdout, $stderr) = $future->resolvex();
} catch(CommandException $exc) {
if ($exc->getError() > 1) {
// 'nose' returns 1 when tests are failing/broken.
throw $exc;
}
}
$xunit_tmp = $tmpfiles[$test_path]['xunit'];
$cover_tmp = $tmpfiles[$test_path]['cover'];
+ $this->parser = new ArcanistXUnitTestResultParser();
$results[] = $this->parseTestResults($source_path,
$xunit_tmp,
$cover_tmp);
}
return array_mergev($results);
}
public function buildTestFuture($path, $xunit_tmp, $cover_tmp) {
$cmd_line = csprintf("nosetests --with-xunit --xunit-file=%s",
$xunit_tmp);
if ($this->getEnableCoverage() !== false) {
$cmd_line .= csprintf(" --with-coverage --cover-xml " .
"--cover-xml-file=%s",
$cover_tmp);
}
return new ExecFuture("%C %s", $cmd_line, $path);
}
public function parseTestResults($source_path, $xunit_tmp, $cover_tmp) {
- // xunit xsd: https://gist.github.com/959290
- $xunit_dom = new DOMDocument();
- $xunit_dom->loadXML(Filesystem::readFile($xunit_tmp));
+ $results = $this->parser->parseTestResults(
+ Filesystem::readFile($xunit_tmp));
// coverage is for all testcases in the executed $path
- $coverage = array();
if ($this->getEnableCoverage() !== false) {
$coverage = $this->readCoverage($cover_tmp, $source_path);
- }
-
- $results = array();
- $testcases = $xunit_dom->getElementsByTagName("testcase");
- foreach ($testcases as $testcase) {
- $classname = $testcase->getAttribute("classname");
- $name = $testcase->getAttribute("name");
- $time = $testcase->getAttribute("time");
-
- $status = ArcanistUnitTestResult::RESULT_PASS;
- $user_data = "";
-
- // A skipped test is a test which was ignored using framework
- // mechanizms (e.g. @skip decorator)
- $skipped = $testcase->getElementsByTagName("skipped");
- if ($skipped->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_SKIP;
- $messages = array();
- for ($ii = 0; $ii < $skipped->length; $ii++) {
- $messages[] = trim($skipped->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages);
+ foreach ($results as $result) {
+ $result->setCoverage($coverage);
}
-
- // Failure is a test which the code has explicitly failed by using
- // the mechanizms for that purpose. e.g., via an assertEquals
- $failures = $testcase->getElementsByTagName("failure");
- if ($failures->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_FAIL;
- $messages = array();
- for ($ii = 0; $ii < $failures->length; $ii++) {
- $messages[] = trim($failures->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages)."\n";
- }
-
- // An errored test is one that had an unanticipated problem. e.g., an
- // unchecked throwable, or a problem with an implementation of the
- // test.
- $errors = $testcase->getElementsByTagName("error");
- if ($errors->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_BROKEN;
- $messages = array();
- for ($ii = 0; $ii < $errors->length; $ii++) {
- $messages[] = trim($errors->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages)."\n";
- }
-
- $result = new ArcanistUnitTestResult();
- $result->setName($classname.".".$name);
- $result->setResult($status);
- $result->setDuration($time);
- $result->setCoverage($coverage);
- $result->setUserData($user_data);
-
- $results[] = $result;
}
return $results;
}
public function readCoverage($cover_file, $source_path) {
$coverage_dom = new DOMDocument();
$coverage_dom->loadXML(Filesystem::readFile($cover_file));
$reports = array();
$classes = $coverage_dom->getElementsByTagName("class");
foreach ($classes as $class) {
// filename is actually python module path with ".py" at the end,
// e.g.: tornado.web.py
$relative_path = explode(".", $class->getAttribute("filename"));
array_pop($relative_path);
$relative_path = $source_path .'/'. implode("/", $relative_path);
// first we check if the path is a directory (a Python package), if it is
// set relative and absolute paths to have __init__.py at the end.
$absolute_path = Filesystem::resolvePath($relative_path);
if (is_dir($absolute_path)) {
$relative_path .= "/__init__.py";
$absolute_path .= "/__init__.py";
}
// then we check if the path with ".py" at the end is file (a Python
// submodule), if it is - set relative and absolute paths to have
// ".py" at the end.
if (is_file($absolute_path.".py")) {
$relative_path .= ".py";
$absolute_path .= ".py";
}
if (!file_exists($absolute_path)) {
continue;
}
// get total line count in file
$line_count = count(file($absolute_path));
$coverage = "";
$start_line = 1;
$lines = $class->getElementsByTagName("line");
for ($ii = 0; $ii < $lines->length; $ii++) {
$line = $lines->item($ii);
$next_line = intval($line->getAttribute("number"));
for ($start_line; $start_line < $next_line; $start_line++) {
$coverage .= "N";
}
if (intval($line->getAttribute("hits")) == 0) {
$coverage .= "U";
} else if (intval($line->getAttribute("hits")) > 0) {
$coverage .= "C";
}
$start_line++;
}
if ($start_line < $line_count) {
foreach (range($start_line, $line_count) as $line_num) {
$coverage .= "N";
}
}
$reports[$relative_path] = $coverage;
}
return $reports;
}
}
diff --git a/src/unit/engine/PytestTestEngine.php b/src/unit/engine/PytestTestEngine.php
index 37a43b72..ca2da944 100644
--- a/src/unit/engine/PytestTestEngine.php
+++ b/src/unit/engine/PytestTestEngine.php
@@ -1,89 +1,23 @@
<?php
/**
* Very basic 'py.test' unit test engine wrapper.
*
* @group unitrun
*/
final class PytestTestEngine extends ArcanistBaseUnitTestEngine {
public function run() {
$junit_tmp = new TempFile();
$cmd_line = csprintf('py.test --junitxml=%s',
$junit_tmp);
-
$future = new ExecFuture('%C', $cmd_line);
list($stdout, $stderr) = $future->resolvex();
- return $this->parseTestResults($junit_tmp);
- }
-
- public function parseTestResults($junit_tmp) {
- // xunit xsd: https://gist.github.com/959290
- $xunit_dom = new DOMDocument();
- $xunit_dom->loadXML(Filesystem::readFile($junit_tmp));
-
- $results = array();
- $testcases = $xunit_dom->getElementsByTagName("testcase");
- foreach ($testcases as $testcase) {
- $classname = $testcase->getAttribute("classname");
- $name = $testcase->getAttribute("name");
- $time = $testcase->getAttribute("time");
-
- $status = ArcanistUnitTestResult::RESULT_PASS;
- $user_data = "";
-
- // A skipped test is a test which was ignored using framework
- // mechanizms (e.g. @skip decorator)
- $skipped = $testcase->getElementsByTagName("skipped");
- if ($skipped->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_SKIP;
- $messages = array();
- for ($ii = 0; $ii < $skipped->length; $ii++) {
- $messages[] = trim($skipped->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages);
- }
-
- // Failure is a test which the code has explicitly failed by using
- // the mechanizms for that purpose. e.g., via an assertEquals
- $failures = $testcase->getElementsByTagName("failure");
- if ($failures->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_FAIL;
- $messages = array();
- for ($ii = 0; $ii < $failures->length; $ii++) {
- $messages[] = trim($failures->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages)."\n";
- }
-
- // An errored test is one that had an unanticipated problem. e.g., an
- // unchecked throwable, or a problem with an implementation of the
- // test.
- $errors = $testcase->getElementsByTagName("error");
- if ($errors->length > 0) {
- $status = ArcanistUnitTestResult::RESULT_BROKEN;
- $messages = array();
- for ($ii = 0; $ii < $errors->length; $ii++) {
- $messages[] = trim($errors->item($ii)->nodeValue, " \n");
- }
-
- $user_data .= implode("\n", $messages)."\n";
- }
-
- $result = new ArcanistUnitTestResult();
- $result->setName($classname.".".$name);
- $result->setResult($status);
- $result->setDuration($time);
- $result->setUserData($user_data);
-
- $results[] = $result;
- }
+ $parser = new ArcanistXUnitTestResultParser();
- return $results;
+ return $parser->parseTestResults(Filesystem::readFile($junit_tmp));
}
}
diff --git a/src/unit/engine/__tests__/XUnitTestResultParserTestCase.php b/src/unit/engine/__tests__/XUnitTestResultParserTestCase.php
new file mode 100755
index 00000000..e752cfbe
--- /dev/null
+++ b/src/unit/engine/__tests__/XUnitTestResultParserTestCase.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * Test for @{class:ArcanistXUnitTestResultParser}.
+ *
+ * (putting tests in your tests so you can test
+ * while you test)
+ *
+ * @group testcase
+ */
+final class XUnitTestResultParserTestCase extends ArcanistTestCase {
+
+ public function testAcceptsNoTestsInput() {
+ $stubbed_results = Filesystem::readFile(
+ dirname(__FILE__).'/testresults/xunit.no-tests');
+ $parsed_results = id(new ArcanistXUnitTestResultParser())
+ ->parseTestResults($stubbed_results);
+
+ $this->assertEqual(0, count($parsed_results));
+ }
+
+ public function testAcceptsSimpleInput() {
+ $stubbed_results = Filesystem::readFile(
+ dirname(__FILE__).'/testresults/xunit.simple');
+ $parsed_results = id(new ArcanistXUnitTestResultParser())
+ ->parseTestResults($stubbed_results);
+
+ $this->assertEqual(3, count($parsed_results));
+ }
+
+ public function testEmptyInputFailure() {
+ try {
+ $parsed_results = id(new ArcanistXUnitTestResultParser())
+ ->parseTestResults('');
+
+ $this->failTest('Should throw on empty input');
+ } catch (Exception $e) {
+ // OK
+ }
+ }
+
+ public function testInvalidXmlInputFailure() {
+ $stubbed_results = Filesystem::readFile(
+ dirname(__FILE__).'/testresults/xunit.invallid-xml');
+ try {
+ $parsed_results = id(new ArcanistXUnitTestResultParser())
+ ->parseTestResults($stubbed_results);
+
+ $this->failTest('Should throw on non-xml input');
+ } catch (Exception $e) {
+ // OK
+ }
+ }
+
+}
diff --git a/src/unit/engine/__tests__/testresults/xunit.invallid-xml b/src/unit/engine/__tests__/testresults/xunit.invallid-xml
new file mode 100755
index 00000000..3dfdc59b
--- /dev/null
+++ b/src/unit/engine/__tests__/testresults/xunit.invallid-xml
@@ -0,0 +1 @@
+something else
diff --git a/src/unit/engine/__tests__/testresults/xunit.no-tests b/src/unit/engine/__tests__/testresults/xunit.no-tests
new file mode 100755
index 00000000..11aa5365
--- /dev/null
+++ b/src/unit/engine/__tests__/testresults/xunit.no-tests
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><testsuite name="" errors="0" failures="0" skips="0" tests="0" time="0.001" ></testsuite>
\ No newline at end of file
diff --git a/src/unit/engine/__tests__/testresults/xunit.simple b/src/unit/engine/__tests__/testresults/xunit.simple
new file mode 100755
index 00000000..ca3559fd
--- /dev/null
+++ b/src/unit/engine/__tests__/testresults/xunit.simple
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<testsuite name="" errors="0" failures="1" skips="0" tests="3" time="0.019">
+ <testcase classname="forpytest.tests" name="test_answer" time="0.0110499858856">
+ <failure message="test failure">def test_answer():
+&gt; assert func(3) == 5
+E assert 4 == 5
+E + where 4 = func(3)
+
+tests.py:5: AssertionError</failure>
+ </testcase>
+ <testcase classname="forpytest.tests" name="test_something" time="6.29425048828e-05"/>
+ <testcase classname="forpytest.tests" name="test_nothing" time="5.91278076172e-05"/>
+</testsuite>

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 11, 09:16 (8 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
984093
Default Alt Text
(40 KB)

Event Timeline