@cartanova/qgrid-cli 2.4.7 → 2.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (748) hide show
  1. package/README.ko.md +18 -11
  2. package/README.md +18 -11
  3. package/bundle/.env +0 -0
  4. package/bundle/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.140.0/helpers/esm}/decorate.js +2 -2
  5. package/bundle/dist/_virtual/{_@oxc-project_runtime@0.122.0/helpers → _@oxc-project_runtime@0.140.0/helpers/esm}/decorateMetadata.js +2 -2
  6. package/bundle/dist/_virtual/_rolldown/runtime.js +2 -3
  7. package/bundle/dist/application/monit/log-buffer.js +3 -2
  8. package/bundle/dist/application/monit/monit.frame.js +5 -6
  9. package/bundle/dist/application/monit/monit.types.js +1 -2
  10. package/bundle/dist/application/qgrid/conv-routing.js +1 -2
  11. package/bundle/dist/application/qgrid/oauth.js +1 -2
  12. package/bundle/dist/application/qgrid/qgrid-image-generation.js +1 -2
  13. package/bundle/dist/application/qgrid/qgrid-response-format.js +1 -2
  14. package/bundle/dist/application/qgrid/qgrid-run-lifecycle.js +86 -43
  15. package/bundle/dist/application/qgrid/qgrid.dispatcher.js +12 -5
  16. package/bundle/dist/application/qgrid/qgrid.frame.js +87 -92
  17. package/bundle/dist/application/qgrid/qgrid.types.js +47 -10
  18. package/bundle/dist/application/qgrid/token-subscriber.js +3 -2
  19. package/bundle/dist/application/qgrid/token-trigger-setup.js +1 -2
  20. package/bundle/dist/application/qgrid/tool-emulation.js +1 -2
  21. package/bundle/dist/application/queries.generated.js +1 -2
  22. package/bundle/dist/application/request-log/request-log.model.js +143 -47
  23. package/bundle/dist/application/request-log/request-log.types.js +1 -2
  24. package/bundle/dist/application/request-log-step/request-log-step.model.js +3 -4
  25. package/bundle/dist/application/request-log-step/request-log-step.types.js +8 -2
  26. package/bundle/dist/application/sonamu.generated.js +41 -6
  27. package/bundle/dist/application/sonamu.generated.sso.js +25 -2
  28. package/bundle/dist/application/token/token.model.js +3 -4
  29. package/bundle/dist/application/token/token.types.js +1 -2
  30. package/bundle/dist/codex-protocol/AbsolutePathBuf.js +0 -1
  31. package/bundle/dist/codex-protocol/AgentPath.js +0 -1
  32. package/bundle/dist/codex-protocol/ApplyPatchApprovalParams.js +0 -1
  33. package/bundle/dist/codex-protocol/ApplyPatchApprovalResponse.js +0 -1
  34. package/bundle/dist/codex-protocol/AuthMode.js +0 -1
  35. package/bundle/dist/codex-protocol/ClientInfo.js +0 -1
  36. package/bundle/dist/codex-protocol/ClientNotification.js +0 -1
  37. package/bundle/dist/codex-protocol/ClientRequest.js +0 -1
  38. package/bundle/dist/codex-protocol/CollaborationMode.js +0 -1
  39. package/bundle/dist/codex-protocol/ContentItem.js +0 -1
  40. package/bundle/dist/codex-protocol/ConversationGitInfo.js +0 -1
  41. package/bundle/dist/codex-protocol/ConversationSummary.js +0 -1
  42. package/bundle/dist/codex-protocol/ExecCommandApprovalParams.js +0 -1
  43. package/bundle/dist/codex-protocol/ExecCommandApprovalResponse.js +0 -1
  44. package/bundle/dist/codex-protocol/ExecPolicyAmendment.js +0 -1
  45. package/bundle/dist/codex-protocol/FileChange.js +0 -1
  46. package/bundle/dist/codex-protocol/ForcedLoginMethod.js +0 -1
  47. package/bundle/dist/codex-protocol/FunctionCallOutputBody.js +0 -1
  48. package/bundle/dist/codex-protocol/FunctionCallOutputContentItem.js +0 -1
  49. package/bundle/dist/codex-protocol/FuzzyFileSearchMatchType.js +0 -1
  50. package/bundle/dist/codex-protocol/FuzzyFileSearchParams.js +0 -1
  51. package/bundle/dist/codex-protocol/FuzzyFileSearchResponse.js +0 -1
  52. package/bundle/dist/codex-protocol/FuzzyFileSearchResult.js +0 -1
  53. package/bundle/dist/codex-protocol/FuzzyFileSearchSessionCompletedNotification.js +0 -1
  54. package/bundle/dist/codex-protocol/FuzzyFileSearchSessionUpdatedNotification.js +0 -1
  55. package/bundle/dist/codex-protocol/GetAuthStatusParams.js +0 -1
  56. package/bundle/dist/codex-protocol/GetAuthStatusResponse.js +0 -1
  57. package/bundle/dist/codex-protocol/GetConversationSummaryParams.js +0 -1
  58. package/bundle/dist/codex-protocol/GetConversationSummaryResponse.js +0 -1
  59. package/bundle/dist/codex-protocol/GitDiffToRemoteParams.js +0 -1
  60. package/bundle/dist/codex-protocol/GitDiffToRemoteResponse.js +0 -1
  61. package/bundle/dist/codex-protocol/GitSha.js +0 -1
  62. package/bundle/dist/codex-protocol/ImageDetail.js +0 -1
  63. package/bundle/dist/codex-protocol/InitializeCapabilities.js +0 -1
  64. package/bundle/dist/codex-protocol/InitializeParams.js +0 -1
  65. package/bundle/dist/codex-protocol/InitializeResponse.js +0 -1
  66. package/bundle/dist/codex-protocol/InputModality.js +0 -1
  67. package/bundle/dist/codex-protocol/InternalSessionSource.js +0 -1
  68. package/bundle/dist/codex-protocol/LocalShellAction.js +0 -1
  69. package/bundle/dist/codex-protocol/LocalShellExecAction.js +0 -1
  70. package/bundle/dist/codex-protocol/LocalShellStatus.js +0 -1
  71. package/bundle/dist/codex-protocol/MessagePhase.js +0 -1
  72. package/bundle/dist/codex-protocol/ModeKind.js +0 -1
  73. package/bundle/dist/codex-protocol/NetworkPolicyAmendment.js +0 -1
  74. package/bundle/dist/codex-protocol/NetworkPolicyRuleAction.js +0 -1
  75. package/bundle/dist/codex-protocol/ParsedCommand.js +0 -1
  76. package/bundle/dist/codex-protocol/Personality.js +0 -1
  77. package/bundle/dist/codex-protocol/PlanType.js +0 -1
  78. package/bundle/dist/codex-protocol/RealtimeConversationVersion.js +0 -1
  79. package/bundle/dist/codex-protocol/RealtimeOutputModality.js +0 -1
  80. package/bundle/dist/codex-protocol/RealtimeVoice.js +0 -1
  81. package/bundle/dist/codex-protocol/RealtimeVoicesList.js +0 -1
  82. package/bundle/dist/codex-protocol/ReasoningEffort.js +0 -1
  83. package/bundle/dist/codex-protocol/ReasoningItemContent.js +0 -1
  84. package/bundle/dist/codex-protocol/ReasoningItemReasoningSummary.js +0 -1
  85. package/bundle/dist/codex-protocol/ReasoningSummary.js +0 -1
  86. package/bundle/dist/codex-protocol/RequestId.js +0 -1
  87. package/bundle/dist/codex-protocol/Resource.js +0 -1
  88. package/bundle/dist/codex-protocol/ResourceContent.js +0 -1
  89. package/bundle/dist/codex-protocol/ResourceTemplate.js +0 -1
  90. package/bundle/dist/codex-protocol/ResponseItem.js +0 -1
  91. package/bundle/dist/codex-protocol/ReviewDecision.js +0 -1
  92. package/bundle/dist/codex-protocol/ServerNotification.js +0 -1
  93. package/bundle/dist/codex-protocol/ServerRequest.js +0 -1
  94. package/bundle/dist/codex-protocol/SessionSource.js +0 -1
  95. package/bundle/dist/codex-protocol/Settings.js +0 -1
  96. package/bundle/dist/codex-protocol/SubAgentSource.js +0 -1
  97. package/bundle/dist/codex-protocol/ThreadId.js +0 -1
  98. package/bundle/dist/codex-protocol/ThreadMemoryMode.js +0 -1
  99. package/bundle/dist/codex-protocol/Tool.js +0 -1
  100. package/bundle/dist/codex-protocol/Verbosity.js +0 -1
  101. package/bundle/dist/codex-protocol/WebSearchAction.js +0 -1
  102. package/bundle/dist/codex-protocol/WebSearchContextSize.js +0 -1
  103. package/bundle/dist/codex-protocol/WebSearchLocation.js +0 -1
  104. package/bundle/dist/codex-protocol/WebSearchMode.js +0 -1
  105. package/bundle/dist/codex-protocol/WebSearchToolConfig.js +0 -1
  106. package/bundle/dist/codex-protocol/index.js +0 -1
  107. package/bundle/dist/codex-protocol/serde_json/JsonValue.js +0 -1
  108. package/bundle/dist/codex-protocol/v2/Account.js +0 -1
  109. package/bundle/dist/codex-protocol/v2/AccountLoginCompletedNotification.js +0 -1
  110. package/bundle/dist/codex-protocol/v2/AccountRateLimitsUpdatedNotification.js +0 -1
  111. package/bundle/dist/codex-protocol/v2/AccountUpdatedNotification.js +0 -1
  112. package/bundle/dist/codex-protocol/v2/ActivePermissionProfile.js +0 -1
  113. package/bundle/dist/codex-protocol/v2/ActivePermissionProfileModification.js +0 -1
  114. package/bundle/dist/codex-protocol/v2/AddCreditsNudgeCreditType.js +0 -1
  115. package/bundle/dist/codex-protocol/v2/AddCreditsNudgeEmailStatus.js +0 -1
  116. package/bundle/dist/codex-protocol/v2/AdditionalFileSystemPermissions.js +0 -1
  117. package/bundle/dist/codex-protocol/v2/AdditionalNetworkPermissions.js +0 -1
  118. package/bundle/dist/codex-protocol/v2/AdditionalPermissionProfile.js +0 -1
  119. package/bundle/dist/codex-protocol/v2/AgentMessageDeltaNotification.js +0 -1
  120. package/bundle/dist/codex-protocol/v2/AnalyticsConfig.js +0 -1
  121. package/bundle/dist/codex-protocol/v2/AppBranding.js +0 -1
  122. package/bundle/dist/codex-protocol/v2/AppInfo.js +0 -1
  123. package/bundle/dist/codex-protocol/v2/AppListUpdatedNotification.js +0 -1
  124. package/bundle/dist/codex-protocol/v2/AppMetadata.js +0 -1
  125. package/bundle/dist/codex-protocol/v2/AppReview.js +0 -1
  126. package/bundle/dist/codex-protocol/v2/AppScreenshot.js +0 -1
  127. package/bundle/dist/codex-protocol/v2/AppSummary.js +0 -1
  128. package/bundle/dist/codex-protocol/v2/AppToolApproval.js +0 -1
  129. package/bundle/dist/codex-protocol/v2/AppToolsConfig.js +0 -1
  130. package/bundle/dist/codex-protocol/v2/ApprovalsReviewer.js +0 -1
  131. package/bundle/dist/codex-protocol/v2/AppsConfig.js +0 -1
  132. package/bundle/dist/codex-protocol/v2/AppsDefaultConfig.js +0 -1
  133. package/bundle/dist/codex-protocol/v2/AppsListParams.js +0 -1
  134. package/bundle/dist/codex-protocol/v2/AppsListResponse.js +0 -1
  135. package/bundle/dist/codex-protocol/v2/AskForApproval.js +0 -1
  136. package/bundle/dist/codex-protocol/v2/AutoReviewDecisionSource.js +0 -1
  137. package/bundle/dist/codex-protocol/v2/ByteRange.js +0 -1
  138. package/bundle/dist/codex-protocol/v2/CancelLoginAccountParams.js +0 -1
  139. package/bundle/dist/codex-protocol/v2/CancelLoginAccountResponse.js +0 -1
  140. package/bundle/dist/codex-protocol/v2/CancelLoginAccountStatus.js +0 -1
  141. package/bundle/dist/codex-protocol/v2/ChatgptAuthTokensRefreshParams.js +0 -1
  142. package/bundle/dist/codex-protocol/v2/ChatgptAuthTokensRefreshReason.js +0 -1
  143. package/bundle/dist/codex-protocol/v2/ChatgptAuthTokensRefreshResponse.js +0 -1
  144. package/bundle/dist/codex-protocol/v2/CodexErrorInfo.js +0 -1
  145. package/bundle/dist/codex-protocol/v2/CollabAgentState.js +0 -1
  146. package/bundle/dist/codex-protocol/v2/CollabAgentStatus.js +0 -1
  147. package/bundle/dist/codex-protocol/v2/CollabAgentTool.js +0 -1
  148. package/bundle/dist/codex-protocol/v2/CollabAgentToolCallStatus.js +0 -1
  149. package/bundle/dist/codex-protocol/v2/CollaborationModeMask.js +0 -1
  150. package/bundle/dist/codex-protocol/v2/CommandAction.js +0 -1
  151. package/bundle/dist/codex-protocol/v2/CommandExecOutputDeltaNotification.js +0 -1
  152. package/bundle/dist/codex-protocol/v2/CommandExecOutputStream.js +0 -1
  153. package/bundle/dist/codex-protocol/v2/CommandExecParams.js +0 -1
  154. package/bundle/dist/codex-protocol/v2/CommandExecResizeParams.js +0 -1
  155. package/bundle/dist/codex-protocol/v2/CommandExecResizeResponse.js +0 -1
  156. package/bundle/dist/codex-protocol/v2/CommandExecResponse.js +0 -1
  157. package/bundle/dist/codex-protocol/v2/CommandExecTerminalSize.js +0 -1
  158. package/bundle/dist/codex-protocol/v2/CommandExecTerminateParams.js +0 -1
  159. package/bundle/dist/codex-protocol/v2/CommandExecTerminateResponse.js +0 -1
  160. package/bundle/dist/codex-protocol/v2/CommandExecWriteParams.js +0 -1
  161. package/bundle/dist/codex-protocol/v2/CommandExecWriteResponse.js +0 -1
  162. package/bundle/dist/codex-protocol/v2/CommandExecutionApprovalDecision.js +0 -1
  163. package/bundle/dist/codex-protocol/v2/CommandExecutionOutputDeltaNotification.js +0 -1
  164. package/bundle/dist/codex-protocol/v2/CommandExecutionRequestApprovalParams.js +0 -1
  165. package/bundle/dist/codex-protocol/v2/CommandExecutionRequestApprovalResponse.js +0 -1
  166. package/bundle/dist/codex-protocol/v2/CommandExecutionSource.js +0 -1
  167. package/bundle/dist/codex-protocol/v2/CommandExecutionStatus.js +0 -1
  168. package/bundle/dist/codex-protocol/v2/CommandMigration.js +0 -1
  169. package/bundle/dist/codex-protocol/v2/Config.js +0 -1
  170. package/bundle/dist/codex-protocol/v2/ConfigBatchWriteParams.js +0 -1
  171. package/bundle/dist/codex-protocol/v2/ConfigEdit.js +0 -1
  172. package/bundle/dist/codex-protocol/v2/ConfigLayer.js +0 -1
  173. package/bundle/dist/codex-protocol/v2/ConfigLayerMetadata.js +0 -1
  174. package/bundle/dist/codex-protocol/v2/ConfigLayerSource.js +0 -1
  175. package/bundle/dist/codex-protocol/v2/ConfigReadParams.js +0 -1
  176. package/bundle/dist/codex-protocol/v2/ConfigReadResponse.js +0 -1
  177. package/bundle/dist/codex-protocol/v2/ConfigRequirements.js +0 -1
  178. package/bundle/dist/codex-protocol/v2/ConfigRequirementsReadResponse.js +0 -1
  179. package/bundle/dist/codex-protocol/v2/ConfigValueWriteParams.js +0 -1
  180. package/bundle/dist/codex-protocol/v2/ConfigWarningNotification.js +0 -1
  181. package/bundle/dist/codex-protocol/v2/ConfigWriteResponse.js +0 -1
  182. package/bundle/dist/codex-protocol/v2/ConfiguredHookHandler.js +0 -1
  183. package/bundle/dist/codex-protocol/v2/ConfiguredHookMatcherGroup.js +0 -1
  184. package/bundle/dist/codex-protocol/v2/ContextCompactedNotification.js +0 -1
  185. package/bundle/dist/codex-protocol/v2/CreditsSnapshot.js +0 -1
  186. package/bundle/dist/codex-protocol/v2/DeprecationNoticeNotification.js +0 -1
  187. package/bundle/dist/codex-protocol/v2/DynamicToolCallOutputContentItem.js +0 -1
  188. package/bundle/dist/codex-protocol/v2/DynamicToolCallParams.js +0 -1
  189. package/bundle/dist/codex-protocol/v2/DynamicToolCallResponse.js +0 -1
  190. package/bundle/dist/codex-protocol/v2/DynamicToolCallStatus.js +0 -1
  191. package/bundle/dist/codex-protocol/v2/DynamicToolSpec.js +0 -1
  192. package/bundle/dist/codex-protocol/v2/ErrorNotification.js +0 -1
  193. package/bundle/dist/codex-protocol/v2/ExecPolicyAmendment.js +0 -1
  194. package/bundle/dist/codex-protocol/v2/ExperimentalFeature.js +0 -1
  195. package/bundle/dist/codex-protocol/v2/ExperimentalFeatureEnablementSetParams.js +0 -1
  196. package/bundle/dist/codex-protocol/v2/ExperimentalFeatureEnablementSetResponse.js +0 -1
  197. package/bundle/dist/codex-protocol/v2/ExperimentalFeatureListParams.js +0 -1
  198. package/bundle/dist/codex-protocol/v2/ExperimentalFeatureListResponse.js +0 -1
  199. package/bundle/dist/codex-protocol/v2/ExperimentalFeatureStage.js +0 -1
  200. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigDetectParams.js +0 -1
  201. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigDetectResponse.js +0 -1
  202. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigImportCompletedNotification.js +0 -1
  203. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigImportParams.js +0 -1
  204. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigImportResponse.js +0 -1
  205. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigMigrationItem.js +0 -1
  206. package/bundle/dist/codex-protocol/v2/ExternalAgentConfigMigrationItemType.js +0 -1
  207. package/bundle/dist/codex-protocol/v2/FeedbackUploadParams.js +0 -1
  208. package/bundle/dist/codex-protocol/v2/FeedbackUploadResponse.js +0 -1
  209. package/bundle/dist/codex-protocol/v2/FileChangeApprovalDecision.js +0 -1
  210. package/bundle/dist/codex-protocol/v2/FileChangeOutputDeltaNotification.js +0 -1
  211. package/bundle/dist/codex-protocol/v2/FileChangePatchUpdatedNotification.js +0 -1
  212. package/bundle/dist/codex-protocol/v2/FileChangeRequestApprovalParams.js +0 -1
  213. package/bundle/dist/codex-protocol/v2/FileChangeRequestApprovalResponse.js +0 -1
  214. package/bundle/dist/codex-protocol/v2/FileSystemAccessMode.js +0 -1
  215. package/bundle/dist/codex-protocol/v2/FileSystemPath.js +0 -1
  216. package/bundle/dist/codex-protocol/v2/FileSystemSandboxEntry.js +0 -1
  217. package/bundle/dist/codex-protocol/v2/FileSystemSpecialPath.js +0 -1
  218. package/bundle/dist/codex-protocol/v2/FileUpdateChange.js +0 -1
  219. package/bundle/dist/codex-protocol/v2/FsChangedNotification.js +0 -1
  220. package/bundle/dist/codex-protocol/v2/FsCopyParams.js +0 -1
  221. package/bundle/dist/codex-protocol/v2/FsCopyResponse.js +0 -1
  222. package/bundle/dist/codex-protocol/v2/FsCreateDirectoryParams.js +0 -1
  223. package/bundle/dist/codex-protocol/v2/FsCreateDirectoryResponse.js +0 -1
  224. package/bundle/dist/codex-protocol/v2/FsGetMetadataParams.js +0 -1
  225. package/bundle/dist/codex-protocol/v2/FsGetMetadataResponse.js +0 -1
  226. package/bundle/dist/codex-protocol/v2/FsReadDirectoryEntry.js +0 -1
  227. package/bundle/dist/codex-protocol/v2/FsReadDirectoryParams.js +0 -1
  228. package/bundle/dist/codex-protocol/v2/FsReadDirectoryResponse.js +0 -1
  229. package/bundle/dist/codex-protocol/v2/FsReadFileParams.js +0 -1
  230. package/bundle/dist/codex-protocol/v2/FsReadFileResponse.js +0 -1
  231. package/bundle/dist/codex-protocol/v2/FsRemoveParams.js +0 -1
  232. package/bundle/dist/codex-protocol/v2/FsRemoveResponse.js +0 -1
  233. package/bundle/dist/codex-protocol/v2/FsUnwatchParams.js +0 -1
  234. package/bundle/dist/codex-protocol/v2/FsUnwatchResponse.js +0 -1
  235. package/bundle/dist/codex-protocol/v2/FsWatchParams.js +0 -1
  236. package/bundle/dist/codex-protocol/v2/FsWatchResponse.js +0 -1
  237. package/bundle/dist/codex-protocol/v2/FsWriteFileParams.js +0 -1
  238. package/bundle/dist/codex-protocol/v2/FsWriteFileResponse.js +0 -1
  239. package/bundle/dist/codex-protocol/v2/GetAccountParams.js +0 -1
  240. package/bundle/dist/codex-protocol/v2/GetAccountRateLimitsResponse.js +0 -1
  241. package/bundle/dist/codex-protocol/v2/GetAccountResponse.js +0 -1
  242. package/bundle/dist/codex-protocol/v2/GitInfo.js +0 -1
  243. package/bundle/dist/codex-protocol/v2/GrantedPermissionProfile.js +0 -1
  244. package/bundle/dist/codex-protocol/v2/GuardianApprovalReview.js +0 -1
  245. package/bundle/dist/codex-protocol/v2/GuardianApprovalReviewAction.js +0 -1
  246. package/bundle/dist/codex-protocol/v2/GuardianApprovalReviewStatus.js +0 -1
  247. package/bundle/dist/codex-protocol/v2/GuardianCommandSource.js +0 -1
  248. package/bundle/dist/codex-protocol/v2/GuardianRiskLevel.js +0 -1
  249. package/bundle/dist/codex-protocol/v2/GuardianUserAuthorization.js +0 -1
  250. package/bundle/dist/codex-protocol/v2/GuardianWarningNotification.js +0 -1
  251. package/bundle/dist/codex-protocol/v2/HookCompletedNotification.js +0 -1
  252. package/bundle/dist/codex-protocol/v2/HookErrorInfo.js +0 -1
  253. package/bundle/dist/codex-protocol/v2/HookEventName.js +0 -1
  254. package/bundle/dist/codex-protocol/v2/HookExecutionMode.js +0 -1
  255. package/bundle/dist/codex-protocol/v2/HookHandlerType.js +0 -1
  256. package/bundle/dist/codex-protocol/v2/HookMetadata.js +0 -1
  257. package/bundle/dist/codex-protocol/v2/HookMigration.js +0 -1
  258. package/bundle/dist/codex-protocol/v2/HookOutputEntry.js +0 -1
  259. package/bundle/dist/codex-protocol/v2/HookOutputEntryKind.js +0 -1
  260. package/bundle/dist/codex-protocol/v2/HookPromptFragment.js +0 -1
  261. package/bundle/dist/codex-protocol/v2/HookRunStatus.js +0 -1
  262. package/bundle/dist/codex-protocol/v2/HookRunSummary.js +0 -1
  263. package/bundle/dist/codex-protocol/v2/HookScope.js +0 -1
  264. package/bundle/dist/codex-protocol/v2/HookSource.js +0 -1
  265. package/bundle/dist/codex-protocol/v2/HookStartedNotification.js +0 -1
  266. package/bundle/dist/codex-protocol/v2/HookTrustStatus.js +0 -1
  267. package/bundle/dist/codex-protocol/v2/HooksListEntry.js +0 -1
  268. package/bundle/dist/codex-protocol/v2/HooksListParams.js +0 -1
  269. package/bundle/dist/codex-protocol/v2/HooksListResponse.js +0 -1
  270. package/bundle/dist/codex-protocol/v2/ItemCompletedNotification.js +0 -1
  271. package/bundle/dist/codex-protocol/v2/ItemGuardianApprovalReviewCompletedNotification.js +0 -1
  272. package/bundle/dist/codex-protocol/v2/ItemGuardianApprovalReviewStartedNotification.js +0 -1
  273. package/bundle/dist/codex-protocol/v2/ItemStartedNotification.js +0 -1
  274. package/bundle/dist/codex-protocol/v2/ListMcpServerStatusParams.js +0 -1
  275. package/bundle/dist/codex-protocol/v2/ListMcpServerStatusResponse.js +0 -1
  276. package/bundle/dist/codex-protocol/v2/LoginAccountParams.js +0 -1
  277. package/bundle/dist/codex-protocol/v2/LoginAccountResponse.js +0 -1
  278. package/bundle/dist/codex-protocol/v2/LogoutAccountResponse.js +0 -1
  279. package/bundle/dist/codex-protocol/v2/ManagedHooksRequirements.js +0 -1
  280. package/bundle/dist/codex-protocol/v2/MarketplaceAddParams.js +0 -1
  281. package/bundle/dist/codex-protocol/v2/MarketplaceAddResponse.js +0 -1
  282. package/bundle/dist/codex-protocol/v2/MarketplaceInterface.js +0 -1
  283. package/bundle/dist/codex-protocol/v2/MarketplaceLoadErrorInfo.js +0 -1
  284. package/bundle/dist/codex-protocol/v2/MarketplaceRemoveParams.js +0 -1
  285. package/bundle/dist/codex-protocol/v2/MarketplaceRemoveResponse.js +0 -1
  286. package/bundle/dist/codex-protocol/v2/MarketplaceUpgradeErrorInfo.js +0 -1
  287. package/bundle/dist/codex-protocol/v2/MarketplaceUpgradeParams.js +0 -1
  288. package/bundle/dist/codex-protocol/v2/MarketplaceUpgradeResponse.js +0 -1
  289. package/bundle/dist/codex-protocol/v2/McpAuthStatus.js +0 -1
  290. package/bundle/dist/codex-protocol/v2/McpElicitationArrayType.js +0 -1
  291. package/bundle/dist/codex-protocol/v2/McpElicitationBooleanSchema.js +0 -1
  292. package/bundle/dist/codex-protocol/v2/McpElicitationBooleanType.js +0 -1
  293. package/bundle/dist/codex-protocol/v2/McpElicitationConstOption.js +0 -1
  294. package/bundle/dist/codex-protocol/v2/McpElicitationEnumSchema.js +0 -1
  295. package/bundle/dist/codex-protocol/v2/McpElicitationLegacyTitledEnumSchema.js +0 -1
  296. package/bundle/dist/codex-protocol/v2/McpElicitationMultiSelectEnumSchema.js +0 -1
  297. package/bundle/dist/codex-protocol/v2/McpElicitationNumberSchema.js +0 -1
  298. package/bundle/dist/codex-protocol/v2/McpElicitationNumberType.js +0 -1
  299. package/bundle/dist/codex-protocol/v2/McpElicitationObjectType.js +0 -1
  300. package/bundle/dist/codex-protocol/v2/McpElicitationPrimitiveSchema.js +0 -1
  301. package/bundle/dist/codex-protocol/v2/McpElicitationSchema.js +0 -1
  302. package/bundle/dist/codex-protocol/v2/McpElicitationSingleSelectEnumSchema.js +0 -1
  303. package/bundle/dist/codex-protocol/v2/McpElicitationStringFormat.js +0 -1
  304. package/bundle/dist/codex-protocol/v2/McpElicitationStringSchema.js +0 -1
  305. package/bundle/dist/codex-protocol/v2/McpElicitationStringType.js +0 -1
  306. package/bundle/dist/codex-protocol/v2/McpElicitationTitledEnumItems.js +0 -1
  307. package/bundle/dist/codex-protocol/v2/McpElicitationTitledMultiSelectEnumSchema.js +0 -1
  308. package/bundle/dist/codex-protocol/v2/McpElicitationTitledSingleSelectEnumSchema.js +0 -1
  309. package/bundle/dist/codex-protocol/v2/McpElicitationUntitledEnumItems.js +0 -1
  310. package/bundle/dist/codex-protocol/v2/McpElicitationUntitledMultiSelectEnumSchema.js +0 -1
  311. package/bundle/dist/codex-protocol/v2/McpElicitationUntitledSingleSelectEnumSchema.js +0 -1
  312. package/bundle/dist/codex-protocol/v2/McpResourceReadParams.js +0 -1
  313. package/bundle/dist/codex-protocol/v2/McpResourceReadResponse.js +0 -1
  314. package/bundle/dist/codex-protocol/v2/McpServerElicitationAction.js +0 -1
  315. package/bundle/dist/codex-protocol/v2/McpServerElicitationRequestParams.js +0 -1
  316. package/bundle/dist/codex-protocol/v2/McpServerElicitationRequestResponse.js +0 -1
  317. package/bundle/dist/codex-protocol/v2/McpServerMigration.js +0 -1
  318. package/bundle/dist/codex-protocol/v2/McpServerOauthLoginCompletedNotification.js +0 -1
  319. package/bundle/dist/codex-protocol/v2/McpServerOauthLoginParams.js +0 -1
  320. package/bundle/dist/codex-protocol/v2/McpServerOauthLoginResponse.js +0 -1
  321. package/bundle/dist/codex-protocol/v2/McpServerRefreshResponse.js +0 -1
  322. package/bundle/dist/codex-protocol/v2/McpServerStartupState.js +0 -1
  323. package/bundle/dist/codex-protocol/v2/McpServerStatus.js +0 -1
  324. package/bundle/dist/codex-protocol/v2/McpServerStatusDetail.js +0 -1
  325. package/bundle/dist/codex-protocol/v2/McpServerStatusUpdatedNotification.js +0 -1
  326. package/bundle/dist/codex-protocol/v2/McpServerToolCallParams.js +0 -1
  327. package/bundle/dist/codex-protocol/v2/McpServerToolCallResponse.js +0 -1
  328. package/bundle/dist/codex-protocol/v2/McpToolCallError.js +0 -1
  329. package/bundle/dist/codex-protocol/v2/McpToolCallProgressNotification.js +0 -1
  330. package/bundle/dist/codex-protocol/v2/McpToolCallResult.js +0 -1
  331. package/bundle/dist/codex-protocol/v2/McpToolCallStatus.js +0 -1
  332. package/bundle/dist/codex-protocol/v2/MemoryCitation.js +0 -1
  333. package/bundle/dist/codex-protocol/v2/MemoryCitationEntry.js +0 -1
  334. package/bundle/dist/codex-protocol/v2/MergeStrategy.js +0 -1
  335. package/bundle/dist/codex-protocol/v2/MigrationDetails.js +0 -1
  336. package/bundle/dist/codex-protocol/v2/Model.js +0 -1
  337. package/bundle/dist/codex-protocol/v2/ModelAvailabilityNux.js +0 -1
  338. package/bundle/dist/codex-protocol/v2/ModelListParams.js +0 -1
  339. package/bundle/dist/codex-protocol/v2/ModelListResponse.js +0 -1
  340. package/bundle/dist/codex-protocol/v2/ModelProviderCapabilitiesReadParams.js +0 -1
  341. package/bundle/dist/codex-protocol/v2/ModelProviderCapabilitiesReadResponse.js +0 -1
  342. package/bundle/dist/codex-protocol/v2/ModelRerouteReason.js +0 -1
  343. package/bundle/dist/codex-protocol/v2/ModelReroutedNotification.js +0 -1
  344. package/bundle/dist/codex-protocol/v2/ModelServiceTier.js +0 -1
  345. package/bundle/dist/codex-protocol/v2/ModelUpgradeInfo.js +0 -1
  346. package/bundle/dist/codex-protocol/v2/ModelVerification.js +0 -1
  347. package/bundle/dist/codex-protocol/v2/ModelVerificationNotification.js +0 -1
  348. package/bundle/dist/codex-protocol/v2/NetworkAccess.js +0 -1
  349. package/bundle/dist/codex-protocol/v2/NetworkApprovalContext.js +0 -1
  350. package/bundle/dist/codex-protocol/v2/NetworkApprovalProtocol.js +0 -1
  351. package/bundle/dist/codex-protocol/v2/NetworkDomainPermission.js +0 -1
  352. package/bundle/dist/codex-protocol/v2/NetworkPolicyAmendment.js +0 -1
  353. package/bundle/dist/codex-protocol/v2/NetworkPolicyRuleAction.js +0 -1
  354. package/bundle/dist/codex-protocol/v2/NetworkRequirements.js +0 -1
  355. package/bundle/dist/codex-protocol/v2/NetworkUnixSocketPermission.js +0 -1
  356. package/bundle/dist/codex-protocol/v2/NonSteerableTurnKind.js +0 -1
  357. package/bundle/dist/codex-protocol/v2/OverriddenMetadata.js +0 -1
  358. package/bundle/dist/codex-protocol/v2/PatchApplyStatus.js +0 -1
  359. package/bundle/dist/codex-protocol/v2/PatchChangeKind.js +0 -1
  360. package/bundle/dist/codex-protocol/v2/PermissionGrantScope.js +0 -1
  361. package/bundle/dist/codex-protocol/v2/PermissionProfile.js +0 -1
  362. package/bundle/dist/codex-protocol/v2/PermissionProfileFileSystemPermissions.js +0 -1
  363. package/bundle/dist/codex-protocol/v2/PermissionProfileModificationParams.js +0 -1
  364. package/bundle/dist/codex-protocol/v2/PermissionProfileNetworkPermissions.js +0 -1
  365. package/bundle/dist/codex-protocol/v2/PermissionProfileSelectionParams.js +0 -1
  366. package/bundle/dist/codex-protocol/v2/PermissionsRequestApprovalParams.js +0 -1
  367. package/bundle/dist/codex-protocol/v2/PermissionsRequestApprovalResponse.js +0 -1
  368. package/bundle/dist/codex-protocol/v2/PlanDeltaNotification.js +0 -1
  369. package/bundle/dist/codex-protocol/v2/PluginAuthPolicy.js +0 -1
  370. package/bundle/dist/codex-protocol/v2/PluginAvailability.js +0 -1
  371. package/bundle/dist/codex-protocol/v2/PluginDetail.js +0 -1
  372. package/bundle/dist/codex-protocol/v2/PluginHookSummary.js +0 -1
  373. package/bundle/dist/codex-protocol/v2/PluginInstallParams.js +0 -1
  374. package/bundle/dist/codex-protocol/v2/PluginInstallPolicy.js +0 -1
  375. package/bundle/dist/codex-protocol/v2/PluginInstallResponse.js +0 -1
  376. package/bundle/dist/codex-protocol/v2/PluginInterface.js +0 -1
  377. package/bundle/dist/codex-protocol/v2/PluginListMarketplaceKind.js +0 -1
  378. package/bundle/dist/codex-protocol/v2/PluginListParams.js +0 -1
  379. package/bundle/dist/codex-protocol/v2/PluginListResponse.js +0 -1
  380. package/bundle/dist/codex-protocol/v2/PluginMarketplaceEntry.js +0 -1
  381. package/bundle/dist/codex-protocol/v2/PluginReadParams.js +0 -1
  382. package/bundle/dist/codex-protocol/v2/PluginReadResponse.js +0 -1
  383. package/bundle/dist/codex-protocol/v2/PluginShareContext.js +0 -1
  384. package/bundle/dist/codex-protocol/v2/PluginShareDeleteParams.js +0 -1
  385. package/bundle/dist/codex-protocol/v2/PluginShareDeleteResponse.js +0 -1
  386. package/bundle/dist/codex-protocol/v2/PluginShareDiscoverability.js +0 -1
  387. package/bundle/dist/codex-protocol/v2/PluginShareListItem.js +0 -1
  388. package/bundle/dist/codex-protocol/v2/PluginShareListParams.js +0 -1
  389. package/bundle/dist/codex-protocol/v2/PluginShareListResponse.js +0 -1
  390. package/bundle/dist/codex-protocol/v2/PluginSharePrincipal.js +0 -1
  391. package/bundle/dist/codex-protocol/v2/PluginSharePrincipalType.js +0 -1
  392. package/bundle/dist/codex-protocol/v2/PluginShareSaveParams.js +0 -1
  393. package/bundle/dist/codex-protocol/v2/PluginShareSaveResponse.js +0 -1
  394. package/bundle/dist/codex-protocol/v2/PluginShareTarget.js +0 -1
  395. package/bundle/dist/codex-protocol/v2/PluginShareUpdateDiscoverability.js +0 -1
  396. package/bundle/dist/codex-protocol/v2/PluginShareUpdateTargetsParams.js +0 -1
  397. package/bundle/dist/codex-protocol/v2/PluginShareUpdateTargetsResponse.js +0 -1
  398. package/bundle/dist/codex-protocol/v2/PluginSkillReadParams.js +0 -1
  399. package/bundle/dist/codex-protocol/v2/PluginSkillReadResponse.js +0 -1
  400. package/bundle/dist/codex-protocol/v2/PluginSource.js +0 -1
  401. package/bundle/dist/codex-protocol/v2/PluginSummary.js +0 -1
  402. package/bundle/dist/codex-protocol/v2/PluginUninstallParams.js +0 -1
  403. package/bundle/dist/codex-protocol/v2/PluginUninstallResponse.js +0 -1
  404. package/bundle/dist/codex-protocol/v2/PluginsMigration.js +0 -1
  405. package/bundle/dist/codex-protocol/v2/ProcessExitedNotification.js +0 -1
  406. package/bundle/dist/codex-protocol/v2/ProcessOutputDeltaNotification.js +0 -1
  407. package/bundle/dist/codex-protocol/v2/ProcessOutputStream.js +0 -1
  408. package/bundle/dist/codex-protocol/v2/ProcessTerminalSize.js +0 -1
  409. package/bundle/dist/codex-protocol/v2/ProfileV2.js +0 -1
  410. package/bundle/dist/codex-protocol/v2/RateLimitReachedType.js +0 -1
  411. package/bundle/dist/codex-protocol/v2/RateLimitSnapshot.js +0 -1
  412. package/bundle/dist/codex-protocol/v2/RateLimitWindow.js +0 -1
  413. package/bundle/dist/codex-protocol/v2/RawResponseItemCompletedNotification.js +0 -1
  414. package/bundle/dist/codex-protocol/v2/ReasoningEffortOption.js +0 -1
  415. package/bundle/dist/codex-protocol/v2/ReasoningSummaryPartAddedNotification.js +0 -1
  416. package/bundle/dist/codex-protocol/v2/ReasoningSummaryTextDeltaNotification.js +0 -1
  417. package/bundle/dist/codex-protocol/v2/ReasoningTextDeltaNotification.js +0 -1
  418. package/bundle/dist/codex-protocol/v2/RemoteControlConnectionStatus.js +0 -1
  419. package/bundle/dist/codex-protocol/v2/RemoteControlStatusChangedNotification.js +0 -1
  420. package/bundle/dist/codex-protocol/v2/RequestPermissionProfile.js +0 -1
  421. package/bundle/dist/codex-protocol/v2/ResidencyRequirement.js +0 -1
  422. package/bundle/dist/codex-protocol/v2/ReviewDelivery.js +0 -1
  423. package/bundle/dist/codex-protocol/v2/ReviewStartParams.js +0 -1
  424. package/bundle/dist/codex-protocol/v2/ReviewStartResponse.js +0 -1
  425. package/bundle/dist/codex-protocol/v2/ReviewTarget.js +0 -1
  426. package/bundle/dist/codex-protocol/v2/SandboxMode.js +0 -1
  427. package/bundle/dist/codex-protocol/v2/SandboxPolicy.js +0 -1
  428. package/bundle/dist/codex-protocol/v2/SandboxWorkspaceWrite.js +0 -1
  429. package/bundle/dist/codex-protocol/v2/SendAddCreditsNudgeEmailParams.js +0 -1
  430. package/bundle/dist/codex-protocol/v2/SendAddCreditsNudgeEmailResponse.js +0 -1
  431. package/bundle/dist/codex-protocol/v2/ServerRequestResolvedNotification.js +0 -1
  432. package/bundle/dist/codex-protocol/v2/SessionMigration.js +0 -1
  433. package/bundle/dist/codex-protocol/v2/SessionSource.js +0 -1
  434. package/bundle/dist/codex-protocol/v2/SkillDependencies.js +0 -1
  435. package/bundle/dist/codex-protocol/v2/SkillErrorInfo.js +0 -1
  436. package/bundle/dist/codex-protocol/v2/SkillInterface.js +0 -1
  437. package/bundle/dist/codex-protocol/v2/SkillMetadata.js +0 -1
  438. package/bundle/dist/codex-protocol/v2/SkillScope.js +0 -1
  439. package/bundle/dist/codex-protocol/v2/SkillSummary.js +0 -1
  440. package/bundle/dist/codex-protocol/v2/SkillToolDependency.js +0 -1
  441. package/bundle/dist/codex-protocol/v2/SkillsChangedNotification.js +0 -1
  442. package/bundle/dist/codex-protocol/v2/SkillsConfigWriteParams.js +0 -1
  443. package/bundle/dist/codex-protocol/v2/SkillsConfigWriteResponse.js +0 -1
  444. package/bundle/dist/codex-protocol/v2/SkillsListEntry.js +0 -1
  445. package/bundle/dist/codex-protocol/v2/SkillsListParams.js +0 -1
  446. package/bundle/dist/codex-protocol/v2/SkillsListResponse.js +0 -1
  447. package/bundle/dist/codex-protocol/v2/SortDirection.js +0 -1
  448. package/bundle/dist/codex-protocol/v2/SubagentMigration.js +0 -1
  449. package/bundle/dist/codex-protocol/v2/TerminalInteractionNotification.js +0 -1
  450. package/bundle/dist/codex-protocol/v2/TextElement.js +0 -1
  451. package/bundle/dist/codex-protocol/v2/TextPosition.js +0 -1
  452. package/bundle/dist/codex-protocol/v2/TextRange.js +0 -1
  453. package/bundle/dist/codex-protocol/v2/Thread.js +0 -1
  454. package/bundle/dist/codex-protocol/v2/ThreadActiveFlag.js +0 -1
  455. package/bundle/dist/codex-protocol/v2/ThreadApproveGuardianDeniedActionParams.js +0 -1
  456. package/bundle/dist/codex-protocol/v2/ThreadApproveGuardianDeniedActionResponse.js +0 -1
  457. package/bundle/dist/codex-protocol/v2/ThreadArchiveParams.js +0 -1
  458. package/bundle/dist/codex-protocol/v2/ThreadArchiveResponse.js +0 -1
  459. package/bundle/dist/codex-protocol/v2/ThreadArchivedNotification.js +0 -1
  460. package/bundle/dist/codex-protocol/v2/ThreadClosedNotification.js +0 -1
  461. package/bundle/dist/codex-protocol/v2/ThreadCompactStartParams.js +0 -1
  462. package/bundle/dist/codex-protocol/v2/ThreadCompactStartResponse.js +0 -1
  463. package/bundle/dist/codex-protocol/v2/ThreadForkParams.js +0 -1
  464. package/bundle/dist/codex-protocol/v2/ThreadForkResponse.js +0 -1
  465. package/bundle/dist/codex-protocol/v2/ThreadGoal.js +0 -1
  466. package/bundle/dist/codex-protocol/v2/ThreadGoalClearedNotification.js +0 -1
  467. package/bundle/dist/codex-protocol/v2/ThreadGoalStatus.js +0 -1
  468. package/bundle/dist/codex-protocol/v2/ThreadGoalUpdatedNotification.js +0 -1
  469. package/bundle/dist/codex-protocol/v2/ThreadInjectItemsParams.js +0 -1
  470. package/bundle/dist/codex-protocol/v2/ThreadInjectItemsResponse.js +0 -1
  471. package/bundle/dist/codex-protocol/v2/ThreadItem.js +0 -1
  472. package/bundle/dist/codex-protocol/v2/ThreadListParams.js +0 -1
  473. package/bundle/dist/codex-protocol/v2/ThreadListResponse.js +0 -1
  474. package/bundle/dist/codex-protocol/v2/ThreadLoadedListParams.js +0 -1
  475. package/bundle/dist/codex-protocol/v2/ThreadLoadedListResponse.js +0 -1
  476. package/bundle/dist/codex-protocol/v2/ThreadMetadataGitInfoUpdateParams.js +0 -1
  477. package/bundle/dist/codex-protocol/v2/ThreadMetadataUpdateParams.js +0 -1
  478. package/bundle/dist/codex-protocol/v2/ThreadMetadataUpdateResponse.js +0 -1
  479. package/bundle/dist/codex-protocol/v2/ThreadNameUpdatedNotification.js +0 -1
  480. package/bundle/dist/codex-protocol/v2/ThreadReadParams.js +0 -1
  481. package/bundle/dist/codex-protocol/v2/ThreadReadResponse.js +0 -1
  482. package/bundle/dist/codex-protocol/v2/ThreadRealtimeAudioChunk.js +0 -1
  483. package/bundle/dist/codex-protocol/v2/ThreadRealtimeClosedNotification.js +0 -1
  484. package/bundle/dist/codex-protocol/v2/ThreadRealtimeErrorNotification.js +0 -1
  485. package/bundle/dist/codex-protocol/v2/ThreadRealtimeItemAddedNotification.js +0 -1
  486. package/bundle/dist/codex-protocol/v2/ThreadRealtimeOutputAudioDeltaNotification.js +0 -1
  487. package/bundle/dist/codex-protocol/v2/ThreadRealtimeSdpNotification.js +0 -1
  488. package/bundle/dist/codex-protocol/v2/ThreadRealtimeStartTransport.js +0 -1
  489. package/bundle/dist/codex-protocol/v2/ThreadRealtimeStartedNotification.js +0 -1
  490. package/bundle/dist/codex-protocol/v2/ThreadRealtimeTranscriptDeltaNotification.js +0 -1
  491. package/bundle/dist/codex-protocol/v2/ThreadRealtimeTranscriptDoneNotification.js +0 -1
  492. package/bundle/dist/codex-protocol/v2/ThreadResumeParams.js +0 -1
  493. package/bundle/dist/codex-protocol/v2/ThreadResumeResponse.js +0 -1
  494. package/bundle/dist/codex-protocol/v2/ThreadRollbackParams.js +0 -1
  495. package/bundle/dist/codex-protocol/v2/ThreadRollbackResponse.js +0 -1
  496. package/bundle/dist/codex-protocol/v2/ThreadSetNameParams.js +0 -1
  497. package/bundle/dist/codex-protocol/v2/ThreadSetNameResponse.js +0 -1
  498. package/bundle/dist/codex-protocol/v2/ThreadShellCommandParams.js +0 -1
  499. package/bundle/dist/codex-protocol/v2/ThreadShellCommandResponse.js +0 -1
  500. package/bundle/dist/codex-protocol/v2/ThreadSortKey.js +0 -1
  501. package/bundle/dist/codex-protocol/v2/ThreadSource.js +0 -1
  502. package/bundle/dist/codex-protocol/v2/ThreadSourceKind.js +0 -1
  503. package/bundle/dist/codex-protocol/v2/ThreadStartParams.js +0 -1
  504. package/bundle/dist/codex-protocol/v2/ThreadStartResponse.js +0 -1
  505. package/bundle/dist/codex-protocol/v2/ThreadStartSource.js +0 -1
  506. package/bundle/dist/codex-protocol/v2/ThreadStartedNotification.js +0 -1
  507. package/bundle/dist/codex-protocol/v2/ThreadStatus.js +0 -1
  508. package/bundle/dist/codex-protocol/v2/ThreadStatusChangedNotification.js +0 -1
  509. package/bundle/dist/codex-protocol/v2/ThreadTokenUsage.js +0 -1
  510. package/bundle/dist/codex-protocol/v2/ThreadTokenUsageUpdatedNotification.js +0 -1
  511. package/bundle/dist/codex-protocol/v2/ThreadUnarchiveParams.js +0 -1
  512. package/bundle/dist/codex-protocol/v2/ThreadUnarchiveResponse.js +0 -1
  513. package/bundle/dist/codex-protocol/v2/ThreadUnarchivedNotification.js +0 -1
  514. package/bundle/dist/codex-protocol/v2/ThreadUnsubscribeParams.js +0 -1
  515. package/bundle/dist/codex-protocol/v2/ThreadUnsubscribeResponse.js +0 -1
  516. package/bundle/dist/codex-protocol/v2/ThreadUnsubscribeStatus.js +0 -1
  517. package/bundle/dist/codex-protocol/v2/TokenUsageBreakdown.js +0 -1
  518. package/bundle/dist/codex-protocol/v2/ToolRequestUserInputAnswer.js +0 -1
  519. package/bundle/dist/codex-protocol/v2/ToolRequestUserInputOption.js +0 -1
  520. package/bundle/dist/codex-protocol/v2/ToolRequestUserInputParams.js +0 -1
  521. package/bundle/dist/codex-protocol/v2/ToolRequestUserInputQuestion.js +0 -1
  522. package/bundle/dist/codex-protocol/v2/ToolRequestUserInputResponse.js +0 -1
  523. package/bundle/dist/codex-protocol/v2/ToolsV2.js +0 -1
  524. package/bundle/dist/codex-protocol/v2/Turn.js +0 -1
  525. package/bundle/dist/codex-protocol/v2/TurnCompletedNotification.js +0 -1
  526. package/bundle/dist/codex-protocol/v2/TurnDiffUpdatedNotification.js +0 -1
  527. package/bundle/dist/codex-protocol/v2/TurnEnvironmentParams.js +0 -1
  528. package/bundle/dist/codex-protocol/v2/TurnError.js +0 -1
  529. package/bundle/dist/codex-protocol/v2/TurnInterruptParams.js +0 -1
  530. package/bundle/dist/codex-protocol/v2/TurnInterruptResponse.js +0 -1
  531. package/bundle/dist/codex-protocol/v2/TurnItemsView.js +0 -1
  532. package/bundle/dist/codex-protocol/v2/TurnPlanStep.js +0 -1
  533. package/bundle/dist/codex-protocol/v2/TurnPlanStepStatus.js +0 -1
  534. package/bundle/dist/codex-protocol/v2/TurnPlanUpdatedNotification.js +0 -1
  535. package/bundle/dist/codex-protocol/v2/TurnStartParams.js +0 -1
  536. package/bundle/dist/codex-protocol/v2/TurnStartResponse.js +0 -1
  537. package/bundle/dist/codex-protocol/v2/TurnStartedNotification.js +0 -1
  538. package/bundle/dist/codex-protocol/v2/TurnStatus.js +0 -1
  539. package/bundle/dist/codex-protocol/v2/TurnSteerParams.js +0 -1
  540. package/bundle/dist/codex-protocol/v2/TurnSteerResponse.js +0 -1
  541. package/bundle/dist/codex-protocol/v2/UserInput.js +0 -1
  542. package/bundle/dist/codex-protocol/v2/WarningNotification.js +0 -1
  543. package/bundle/dist/codex-protocol/v2/WebSearchAction.js +0 -1
  544. package/bundle/dist/codex-protocol/v2/WindowsSandboxReadiness.js +0 -1
  545. package/bundle/dist/codex-protocol/v2/WindowsSandboxReadinessResponse.js +0 -1
  546. package/bundle/dist/codex-protocol/v2/WindowsSandboxSetupCompletedNotification.js +0 -1
  547. package/bundle/dist/codex-protocol/v2/WindowsSandboxSetupMode.js +0 -1
  548. package/bundle/dist/codex-protocol/v2/WindowsSandboxSetupStartParams.js +0 -1
  549. package/bundle/dist/codex-protocol/v2/WindowsSandboxSetupStartResponse.js +0 -1
  550. package/bundle/dist/codex-protocol/v2/WindowsWorldWritableWarningNotification.js +0 -1
  551. package/bundle/dist/codex-protocol/v2/WriteStatus.js +0 -1
  552. package/bundle/dist/i18n/en.js +1 -2
  553. package/bundle/dist/i18n/ko.js +1 -2
  554. package/bundle/dist/i18n/sd.generated.js +66 -21
  555. package/bundle/dist/index.js +1 -2
  556. package/bundle/dist/migrations/20260410171405_create__request_logs.js +1 -2
  557. package/bundle/dist/migrations/20260410171406_create__tokens.js +1 -2
  558. package/bundle/dist/migrations/20260411120624_alter_tokens_alter2.js +1 -2
  559. package/bundle/dist/migrations/20260415113716_alter_tokens_add_ord.js +1 -2
  560. package/bundle/dist/migrations/20260415134649_alter_request_logs_alter1.js +1 -2
  561. package/bundle/dist/migrations/20260421223627_alter_request_logs_add1_alter1.js +1 -2
  562. package/bundle/dist/migrations/20260423180818_alter_request_logs_add1_alter1.js +1 -2
  563. package/bundle/dist/migrations/20260423182017_alter_request_logs_add2_drop1_alter1.js +1 -2
  564. package/bundle/dist/migrations/20260423183613_alter_request_logs_add1_alter1.js +1 -2
  565. package/bundle/dist/migrations/20260518145411_alter_tokens_add2_drop4_alter1.js +1 -2
  566. package/bundle/dist/migrations/20260520112853_alter_request_logs_add3_alter1.js +1 -2
  567. package/bundle/dist/migrations/20260520124755_alter_request_logs_drop1_alter1.js +1 -2
  568. package/bundle/dist/migrations/20260520130420_create__request_log_steps.js +1 -2
  569. package/bundle/dist/migrations/20260520134908_alter_request_logs_add2_alter8.js +1 -2
  570. package/bundle/dist/migrations/20260520134909_alter_request_log_steps_add1_alter3.js +1 -2
  571. package/bundle/dist/migrations/20260520141449_alter_request_logs_add1_alter1.js +1 -2
  572. package/bundle/dist/migrations/20260521134025_alter_request_log_steps_alter1.js +1 -2
  573. package/bundle/dist/migrations/20260521134026_alter_request_log_steps_foreigns.js +1 -2
  574. package/bundle/dist/migrations/20260522181721_alter_request_log_steps_add2_alter1.js +1 -2
  575. package/bundle/dist/migrations/20260630223950_alter_tokens_add1_alter1.js +1 -2
  576. package/bundle/dist/migrations/20260701105327_alter_request_logs_add1_alter1.js +1 -2
  577. package/bundle/dist/migrations/20260701105328_alter_request_log_steps_add1_alter1.js +1 -2
  578. package/bundle/dist/migrations/20260705140614_alter_request_logs_add1_alter1.js +1 -2
  579. package/bundle/dist/migrations/20260706120000_alter_request_logs_add_image_cost.js +1 -2
  580. package/bundle/dist/migrations/20260710090000_alter_tokens_add_weight.js +1 -2
  581. package/bundle/dist/migrations/20260718180824_alter_request_logs_add5_alter1.js +19 -0
  582. package/bundle/dist/migrations/20260718180825_alter_request_log_steps_add7_alter1.js +21 -0
  583. package/bundle/dist/migrations/20260722174410_alter_request_logs_alter3.js +17 -0
  584. package/bundle/dist/migrations/20260722174411_alter_request_log_steps_alter3.js +17 -0
  585. package/bundle/dist/node_modules/.pnpm/@jridgewell_sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.js +255 -4
  586. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.10/node_modules/@vitest/expect/dist/index.js +1507 -0
  587. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.10/node_modules/@vitest/pretty-format/dist/index.js +887 -0
  588. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js +2756 -0
  589. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/index.js +8 -0
  590. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.10/node_modules/@vitest/runner/dist/utils.js +8 -0
  591. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.10/node_modules/@vitest/snapshot/dist/index.js +922 -0
  592. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.10/node_modules/@vitest/spy/dist/index.js +386 -0
  593. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +121 -0
  594. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/constants.js +51 -0
  595. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/diff.js +1317 -0
  596. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js +561 -0
  597. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js +40 -0
  598. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js +272 -0
  599. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/offset.js +27 -0
  600. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/serialize.js +77 -0
  601. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js +381 -0
  602. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js +51 -0
  603. package/bundle/dist/node_modules/.pnpm/chai@6.2.2/node_modules/chai/index.js +103 -3
  604. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/branding.js +1 -1
  605. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/index.js +1 -1
  606. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/messages.js +1 -1
  607. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/overloads.js +1 -1
  608. package/bundle/dist/node_modules/.pnpm/expect-type@1.3.0/node_modules/expect-type/dist/utils.js +1 -1
  609. package/bundle/dist/node_modules/.pnpm/magic-string@0.30.21/node_modules/magic-string/dist/magic-string.es.js +2 -3
  610. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.js +4 -4
  611. package/bundle/dist/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js +2 -2
  612. package/bundle/dist/node_modules/.pnpm/tinybench@2.9.0/node_modules/tinybench/dist/index.js +18 -7
  613. package/bundle/dist/node_modules/.pnpm/tinyrainbow@3.1.0/node_modules/tinyrainbow/dist/index.js +18 -3
  614. package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.11.2_@emnapi_runtime@1.11.2_@types_node@25.0.7_esbuild@0.27.4_2519c2e8d8013fcbc7b443879bc9da6d/node_modules/vite/dist/node/module-runner.js +1265 -0
  615. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/_commonjsHelpers.D26ty3Ew.js +6 -3
  616. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/benchmark.CX_oY03V.js +8 -8
  617. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/evaluatedModules.Dg1zASAC.js +5 -5
  618. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/index.Chj8NDwU.js +3 -3
  619. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c/node_modules/vitest/dist/chunks/index.DdgEv5B1.js +46 -0
  620. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/rpc.MzXet3jl.js +66 -6
  621. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c/node_modules/vitest/dist/chunks/test.DNmyFkvJ.js +3044 -0
  622. package/bundle/dist/node_modules/.pnpm/{vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496 → vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c}/node_modules/vitest/dist/chunks/utils.BX5Fg8C4.js +19 -4
  623. package/bundle/dist/node_modules/.pnpm/vitest@4.1.10_@opentelemetry_api@1.9.0_@types_node@25.0.7_@vitest_coverage-v8@4.1.10_ms_f9cfcfeddd63e656d4010c98521af26c/node_modules/vitest/dist/index.js +28 -0
  624. package/bundle/dist/server-bootstrap.js +1 -2
  625. package/bundle/dist/sonamu.config.js +11 -27
  626. package/bundle/dist/startup-migrations.js +1 -2
  627. package/bundle/dist/testing/fixture.js +1 -2
  628. package/bundle/dist/testing/global.js +6 -7
  629. package/bundle/dist/testing/setup-mocks.js +3 -4
  630. package/bundle/dist/testing/test-database-name.js +5 -8
  631. package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +11 -5
  632. package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +6 -4
  633. package/bundle/dist/utils/providers/anthropic/anthropic-quota.js +1 -2
  634. package/bundle/dist/utils/providers/anthropic/claude-session.js +12 -10
  635. package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +117 -8
  636. package/bundle/dist/utils/providers/common/credentials.js +1 -2
  637. package/bundle/dist/utils/providers/common/model-cost.js +46 -99
  638. package/bundle/dist/utils/providers/common/provider-dispatcher.js +0 -1
  639. package/bundle/dist/utils/providers/common/smooth-weighted-round-robin.js +1 -2
  640. package/bundle/dist/utils/providers/common/strictifier.js +2 -2
  641. package/bundle/dist/utils/providers/common/token-picker.js +1 -2
  642. package/bundle/dist/utils/providers/common/ttft.js +1 -2
  643. package/bundle/dist/utils/providers/openai/codex-rpc.js +4 -2
  644. package/bundle/dist/utils/providers/openai/codex-worker.js +2 -2
  645. package/bundle/dist/utils/providers/openai/openai-constants.js +1 -2
  646. package/bundle/dist/utils/providers/openai/openai-dispatcher.js +103 -40
  647. package/bundle/dist/utils/providers/openai/openai-quota.js +1 -2
  648. package/bundle/dist/utils/providers/openai/openai-refresh.js +1 -2
  649. package/bundle/dist/utils/subset-loaders.js +1 -2
  650. package/bundle/src/application/monit/monit.frame.test.ts +2 -2
  651. package/bundle/src/application/monit/monit.frame.ts +2 -2
  652. package/bundle/src/application/qgrid/qgrid-run-lifecycle.test.ts +305 -3
  653. package/bundle/src/application/qgrid/qgrid-run-lifecycle.ts +107 -53
  654. package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +81 -0
  655. package/bundle/src/application/qgrid/qgrid.dispatcher.ts +16 -9
  656. package/bundle/src/application/qgrid/qgrid.frame.test.ts +400 -96
  657. package/bundle/src/application/qgrid/qgrid.frame.ts +99 -118
  658. package/bundle/src/application/qgrid/qgrid.types.ts +71 -27
  659. package/bundle/src/application/qgrid/tool-emulation.test.ts +1 -0
  660. package/bundle/src/application/request-log/request-log.entity.json +43 -1
  661. package/bundle/src/application/request-log/request-log.model.test.ts +375 -13
  662. package/bundle/src/application/request-log/request-log.model.ts +283 -86
  663. package/bundle/src/application/request-log-step/request-log-step.entity.json +54 -0
  664. package/bundle/src/application/request-log-step/request-log-step.types.ts +7 -0
  665. package/bundle/src/application/sonamu.generated.http +28 -2
  666. package/bundle/src/application/sonamu.generated.sso.ts +24 -0
  667. package/bundle/src/application/sonamu.generated.ts +52 -4
  668. package/bundle/src/i18n/sd.generated.ts +95 -14
  669. package/bundle/src/migrations/20260718180824_alter_request_logs_add5_alter1.ts +25 -0
  670. package/bundle/src/migrations/20260718180825_alter_request_log_steps_add7_alter1.ts +29 -0
  671. package/bundle/src/migrations/20260722174410_alter_request_logs_alter3.ts +19 -0
  672. package/bundle/src/migrations/20260722174411_alter_request_log_steps_alter3.ts +19 -0
  673. package/bundle/src/sonamu.config.ts +5 -23
  674. package/bundle/src/testing/global.ts +5 -5
  675. package/bundle/src/testing/test-database-name.test.ts +5 -5
  676. package/bundle/src/testing/test-database-name.ts +9 -8
  677. package/bundle/src/utils/providers/anthropic/anthropic-constants.test.ts +19 -0
  678. package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +15 -2
  679. package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +7 -2
  680. package/bundle/src/utils/providers/anthropic/claude-session.test.ts +43 -2
  681. package/bundle/src/utils/providers/anthropic/claude-session.ts +16 -4
  682. package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +131 -0
  683. package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +194 -11
  684. package/bundle/src/utils/providers/common/model-cost.test.ts +137 -2
  685. package/bundle/src/utils/providers/common/model-cost.ts +77 -99
  686. package/bundle/src/utils/providers/common/provider-dispatcher.ts +18 -0
  687. package/bundle/src/utils/providers/openai/openai-dispatcher.test.ts +440 -0
  688. package/bundle/src/utils/providers/openai/openai-dispatcher.ts +143 -45
  689. package/bundle/web-dist/client/assets/{index-CYnw2kNG.js → index-ioEghlNo.js} +3 -3
  690. package/bundle/web-dist/client/assets/logs-TGA3XE4C.js +1 -0
  691. package/bundle/web-dist/client/assets/{monit-DRuDGJj4.js → monit-DLynJGca.js} +1 -1
  692. package/bundle/web-dist/client/assets/{routes-CuyNd-ya.js → routes-DugjmKS_.js} +1 -1
  693. package/bundle/web-dist/client/assets/{sd.generated-D2Y9QeiN.js → sd.generated-DbBC73_z.js} +1 -1
  694. package/bundle/web-dist/client/assets/{services.generated-CmxXl220.js → services.generated-BWyAypSh.js} +1 -1
  695. package/bundle/web-dist/client/assets/show-DSswR7Cy.js +30 -0
  696. package/bundle/web-dist/client/assets/{tokens-DxFeKC8Q.js → tokens-C5djVO__.js} +1 -1
  697. package/bundle/web-dist/client/assets/{use-update-token-mutation-6J1T9U2-.js → use-update-token-mutation-DeDBiZiM.js} +1 -1
  698. package/bundle/web-dist/client/index.html +2 -2
  699. package/bundle/web-dist/server/assets/{lazyRouteComponent-BlfOh9S3.js → lazyRouteComponent-BCJr868T.js} +1 -1
  700. package/bundle/web-dist/server/assets/{logs-DYly4ipQ.js → logs-33YNafdW.js} +30 -6
  701. package/bundle/web-dist/server/assets/{monit-CYyY2S2f.js → monit--9mVsjNU.js} +2 -2
  702. package/bundle/web-dist/server/assets/{routes-Dqu3osXt.js → routes-BK3Xh1UB.js} +3 -3
  703. package/bundle/web-dist/server/assets/{sd.generated-CE6D5clm.js → sd.generated-C3gcvRcU.js} +13 -0
  704. package/bundle/web-dist/server/assets/{services.generated-DyZUzXiq.js → services.generated-B2_Auwvk.js} +1 -1
  705. package/bundle/web-dist/server/assets/{show-BDul8xLb.js → show-Dxxxe608.js} +57 -8
  706. package/bundle/web-dist/server/assets/{tokens-fzMW4G74.js → tokens-BWPVvdfi.js} +3 -3
  707. package/bundle/web-dist/server/assets/{use-update-token-mutation-BejUW5sw.js → use-update-token-mutation-CNBgTysy.js} +1 -1
  708. package/bundle/web-dist/server/entry-server.generated.js +23 -23
  709. package/dist/cli.d.ts +1 -0
  710. package/dist/cli.js +18 -12
  711. package/package.json +6 -6
  712. package/skills/qgrid/SKILL.md +8 -0
  713. package/skills/qgrid/references/ai-sdk-provider-contract.md +58 -4
  714. package/skills/qgrid/references/anthropic-claude-code-runtime.md +44 -5
  715. package/skills/qgrid/references/cli-env-and-server-boot.md +20 -8
  716. package/skills/qgrid/references/decision-rationale.md +6 -0
  717. package/skills/qgrid/references/docs-workflow.md +10 -0
  718. package/skills/qgrid/references/openai-codex-runtime.md +11 -3
  719. package/skills/qgrid/references/prompt-cache-and-usage.md +4 -1
  720. package/skills/qgrid/references/provider-runtime-differences.md +3 -3
  721. package/skills/qgrid/references/request-log-run-lifecycle.md +50 -28
  722. package/skills/qgrid/references/sonamu-api-web-flow.md +17 -0
  723. package/skills/qgrid/references/token-auth-quota-lifecycle.md +6 -0
  724. package/skills/qgrid/references/tool-calling-and-multiturn.md +8 -7
  725. package/skills/qgrid/references/verification-and-debugging.md +1 -1
  726. package/bundle/dist/node_modules/.pnpm/@vitest_expect@4.1.2/node_modules/@vitest/expect/dist/index.js +0 -1484
  727. package/bundle/dist/node_modules/.pnpm/@vitest_pretty-format@4.1.2/node_modules/@vitest/pretty-format/dist/index.js +0 -887
  728. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/chunk-artifact.js +0 -2746
  729. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/index.js +0 -8
  730. package/bundle/dist/node_modules/.pnpm/@vitest_runner@4.1.2/node_modules/@vitest/runner/dist/utils.js +0 -8
  731. package/bundle/dist/node_modules/.pnpm/@vitest_snapshot@4.1.2/node_modules/@vitest/snapshot/dist/index.js +0 -662
  732. package/bundle/dist/node_modules/.pnpm/@vitest_spy@4.1.2/node_modules/@vitest/spy/dist/index.js +0 -386
  733. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +0 -82
  734. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/constants.js +0 -48
  735. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/diff.js +0 -1307
  736. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/display.js +0 -558
  737. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/error.js +0 -33
  738. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/helpers.js +0 -226
  739. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/offset.js +0 -27
  740. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/serialize.js +0 -77
  741. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/source-map.js +0 -374
  742. package/bundle/dist/node_modules/.pnpm/@vitest_utils@4.1.2/node_modules/@vitest/utils/dist/timers.js +0 -37
  743. package/bundle/dist/node_modules/.pnpm/vite@8.0.3_@emnapi_core@1.9.2_@emnapi_runtime@1.9.2_@types_node@25.0.7_esbuild@0.27.4_jiti@2.6.1_sass@1.98.0_tsx@4.21.0/node_modules/vite/dist/node/module-runner.js +0 -426
  744. package/bundle/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496/node_modules/vitest/dist/chunks/index.DOa3dzoN.js +0 -16
  745. package/bundle/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496/node_modules/vitest/dist/chunks/test.p_J6dB8a.js +0 -2910
  746. package/bundle/dist/node_modules/.pnpm/vitest@4.1.2_@opentelemetry_api@1.9.0_@types_node@25.0.7_msw@2.13.3_@types_node@25.0.7__ba64bc4dd2e2bdde58df187864f65496/node_modules/vitest/dist/index.js +0 -28
  747. package/bundle/web-dist/client/assets/logs-CnXIN-jp.js +0 -1
  748. package/bundle/web-dist/client/assets/show-EleAOzJv.js +0 -30
@@ -0,0 +1,2756 @@
1
+ import { format, formatRegExp, objDisplay } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/display.js";
2
+ import { assertTypes, createDefer, filterOutComments, isNegativeNaN, isObject, objectAttr, ordinal, shuffle, toArray, unique } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/helpers.js";
3
+ import { processError } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/error.js";
4
+ import { getSafeTimers } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/timers.js";
5
+ import { parseSingleStack } from "../../../../../@vitest_utils@4.1.10/node_modules/@vitest/utils/dist/source-map.js";
6
+ import { b as relative } from "../../../../../pathe@2.0.3/node_modules/pathe/dist/shared/pathe.M-eThtNZ.js";
7
+ import "../../../../../pathe@2.0.3/node_modules/pathe/dist/index.js";
8
+ //#region ../../node_modules/.pnpm/@vitest+runner@4.1.10/node_modules/@vitest/runner/dist/chunk-artifact.js
9
+ var PendingError = class extends Error {
10
+ code = "VITEST_PENDING";
11
+ taskId;
12
+ constructor(message, task, note) {
13
+ super(message);
14
+ this.message = message;
15
+ this.note = note;
16
+ this.taskId = task.id;
17
+ }
18
+ };
19
+ var TestRunAbortError = class extends Error {
20
+ name = "TestRunAbortError";
21
+ reason;
22
+ constructor(message, reason) {
23
+ super(message);
24
+ this.reason = reason;
25
+ }
26
+ };
27
+ var FixtureDependencyError = class extends Error {
28
+ name = "FixtureDependencyError";
29
+ };
30
+ var FixtureAccessError = class extends Error {
31
+ name = "FixtureAccessError";
32
+ };
33
+ var FixtureParseError = class extends Error {
34
+ name = "FixtureParseError";
35
+ };
36
+ var AroundHookSetupError = class extends Error {
37
+ name = "AroundHookSetupError";
38
+ };
39
+ var AroundHookTeardownError = class extends Error {
40
+ name = "AroundHookTeardownError";
41
+ };
42
+ var AroundHookMultipleCallsError = class extends Error {
43
+ name = "AroundHookMultipleCallsError";
44
+ };
45
+ const fnMap = /* @__PURE__ */ new WeakMap();
46
+ const testFixtureMap = /* @__PURE__ */ new WeakMap();
47
+ const hooksMap = /* @__PURE__ */ new WeakMap();
48
+ function setFn(key, fn) {
49
+ fnMap.set(key, fn);
50
+ }
51
+ function getFn(key) {
52
+ return fnMap.get(key);
53
+ }
54
+ function setTestFixture(key, fixture) {
55
+ testFixtureMap.set(key, fixture);
56
+ }
57
+ function getTestFixtures(key) {
58
+ return testFixtureMap.get(key);
59
+ }
60
+ function setHooks(key, hooks) {
61
+ hooksMap.set(key, hooks);
62
+ }
63
+ function getHooks(key) {
64
+ return hooksMap.get(key);
65
+ }
66
+ const FIXTURE_STACK_TRACE_KEY = Symbol.for("VITEST_FIXTURE_STACK_TRACE");
67
+ var TestFixtures = class TestFixtures {
68
+ _suiteContexts;
69
+ _overrides = /* @__PURE__ */ new WeakMap();
70
+ _registrations;
71
+ static _definitions = [];
72
+ static _builtinFixtures = [
73
+ "task",
74
+ "signal",
75
+ "onTestFailed",
76
+ "onTestFinished",
77
+ "skip",
78
+ "annotate"
79
+ ];
80
+ static _fixtureOptionKeys = [
81
+ "auto",
82
+ "injected",
83
+ "scope"
84
+ ];
85
+ static _fixtureScopes = [
86
+ "test",
87
+ "file",
88
+ "worker"
89
+ ];
90
+ static _workerContextSuite = { type: "worker" };
91
+ static clearDefinitions() {
92
+ TestFixtures._definitions.length = 0;
93
+ }
94
+ static getWorkerContexts() {
95
+ return TestFixtures._definitions.map((f) => f.getWorkerContext());
96
+ }
97
+ static getFileContexts(file) {
98
+ return TestFixtures._definitions.map((f) => f.getFileContext(file));
99
+ }
100
+ static isFixtureOptions(obj) {
101
+ return isObject(obj) && Object.keys(obj).some((key) => TestFixtures._fixtureOptionKeys.includes(key));
102
+ }
103
+ constructor(registrations) {
104
+ this._registrations = registrations ?? /* @__PURE__ */ new Map();
105
+ this._suiteContexts = /* @__PURE__ */ new WeakMap();
106
+ TestFixtures._definitions.push(this);
107
+ }
108
+ extend(runner, userFixtures) {
109
+ const { suite } = getCurrentSuite();
110
+ const isTopLevel = !suite || suite.file === suite;
111
+ const registrations = this.parseUserFixtures(runner, userFixtures, isTopLevel);
112
+ return new TestFixtures(registrations);
113
+ }
114
+ get(suite) {
115
+ let currentSuite = suite;
116
+ while (currentSuite) {
117
+ const overrides = this._overrides.get(currentSuite);
118
+ if (overrides) return overrides;
119
+ if (currentSuite === currentSuite.file) break;
120
+ currentSuite = currentSuite.suite || currentSuite.file;
121
+ }
122
+ return this._registrations;
123
+ }
124
+ override(runner, userFixtures) {
125
+ const { suite: currentSuite, file } = getCurrentSuite();
126
+ const suite = currentSuite || file;
127
+ const isTopLevel = !currentSuite || currentSuite.file === currentSuite;
128
+ const suiteRegistrations = new Map(this.get(suite));
129
+ const registrations = this.parseUserFixtures(runner, userFixtures, isTopLevel, suiteRegistrations);
130
+ if (isTopLevel) this._registrations = registrations;
131
+ else this._overrides.set(suite, registrations);
132
+ }
133
+ getFileContext(file) {
134
+ if (!this._suiteContexts.has(file)) this._suiteContexts.set(file, Object.create(null));
135
+ return this._suiteContexts.get(file);
136
+ }
137
+ getWorkerContext() {
138
+ if (!this._suiteContexts.has(TestFixtures._workerContextSuite)) this._suiteContexts.set(TestFixtures._workerContextSuite, Object.create(null));
139
+ return this._suiteContexts.get(TestFixtures._workerContextSuite);
140
+ }
141
+ parseUserFixtures(runner, userFixtures, supportNonTest, registrations = new Map(this._registrations)) {
142
+ const errors = [];
143
+ Object.entries(userFixtures).forEach(([name, fn]) => {
144
+ let options;
145
+ let value;
146
+ let _options;
147
+ if (Array.isArray(fn) && fn.length >= 2 && TestFixtures.isFixtureOptions(fn[1])) {
148
+ _options = fn[1];
149
+ options = {
150
+ auto: _options.auto ?? false,
151
+ scope: _options.scope ?? "test",
152
+ injected: _options.injected ?? false
153
+ };
154
+ value = options.injected ? runner.injectValue?.(name) ?? fn[0] : fn[0];
155
+ } else value = fn;
156
+ const parent = registrations.get(name);
157
+ if (parent && options) {
158
+ if (parent.scope !== options.scope) errors.push(new FixtureDependencyError(`The "${name}" fixture was already registered with a "${options.scope}" scope.`));
159
+ if (parent.auto !== options.auto) errors.push(new FixtureDependencyError(`The "${name}" fixture was already registered as { auto: ${options.auto} }.`));
160
+ } else if (parent) options = {
161
+ auto: parent.auto,
162
+ scope: parent.scope,
163
+ injected: parent.injected
164
+ };
165
+ else if (!options) options = {
166
+ auto: false,
167
+ injected: false,
168
+ scope: "test"
169
+ };
170
+ if (options.scope && !TestFixtures._fixtureScopes.includes(options.scope)) errors.push(new FixtureDependencyError(`The "${name}" fixture has unknown scope "${options.scope}".`));
171
+ if (!supportNonTest && options.scope !== "test") errors.push(new FixtureDependencyError(`The "${name}" fixture cannot be defined with a ${options.scope} scope${!_options?.scope && parent?.scope ? " (inherited from the base fixture)" : ""} inside the describe block. Define it at the top level of the file instead.`));
172
+ const deps = isFixtureFunction(value) ? getUsedProps(value) : /* @__PURE__ */ new Set();
173
+ const item = {
174
+ name,
175
+ value,
176
+ auto: options.auto ?? false,
177
+ injected: options.injected ?? false,
178
+ scope: options.scope ?? "test",
179
+ deps,
180
+ parent
181
+ };
182
+ if (isFixtureFunction(value)) Object.assign(value, { [FIXTURE_STACK_TRACE_KEY]: /* @__PURE__ */ new Error("STACK_TRACE_ERROR") });
183
+ registrations.set(name, item);
184
+ if (item.scope === "worker" && (runner.pool === "vmThreads" || runner.pool === "vmForks")) item.scope = "file";
185
+ });
186
+ for (const fixture of registrations.values()) for (const depName of fixture.deps) {
187
+ if (TestFixtures._builtinFixtures.includes(depName)) continue;
188
+ const dep = registrations.get(depName);
189
+ if (!dep) {
190
+ errors.push(new FixtureDependencyError(`The "${fixture.name}" fixture depends on unknown fixture "${depName}".`));
191
+ continue;
192
+ }
193
+ if (depName === fixture.name && !fixture.parent) {
194
+ errors.push(new FixtureDependencyError(`The "${fixture.name}" fixture depends on itself, but does not have a base implementation.`));
195
+ continue;
196
+ }
197
+ if (TestFixtures._fixtureScopes.indexOf(fixture.scope) > TestFixtures._fixtureScopes.indexOf(dep.scope)) {
198
+ errors.push(new FixtureDependencyError(`The ${fixture.scope} "${fixture.name}" fixture cannot depend on a ${dep.scope} fixture "${dep.name}".`));
199
+ continue;
200
+ }
201
+ }
202
+ if (errors.length === 1) throw errors[0];
203
+ else if (errors.length > 1) throw new AggregateError(errors, "Cannot resolve user fixtures. See errors for more information.");
204
+ return registrations;
205
+ }
206
+ };
207
+ const cleanupFnArrayMap = /* @__PURE__ */ new WeakMap();
208
+ async function callFixtureCleanup(context) {
209
+ const cleanupFnArray = cleanupFnArrayMap.get(context) ?? [];
210
+ for (const cleanup of cleanupFnArray.reverse()) await cleanup();
211
+ cleanupFnArrayMap.delete(context);
212
+ }
213
+ /**
214
+ * Returns the current number of cleanup functions registered for the context.
215
+ * This can be used as a checkpoint to later clean up only fixtures added after this point.
216
+ */
217
+ function getFixtureCleanupCount(context) {
218
+ return cleanupFnArrayMap.get(context)?.length ?? 0;
219
+ }
220
+ /**
221
+ * Cleans up only fixtures that were added after the given checkpoint index.
222
+ * This is used by aroundEach to clean up fixtures created inside runTest()
223
+ * while preserving fixtures that were created for aroundEach itself.
224
+ */
225
+ async function callFixtureCleanupFrom(context, fromIndex) {
226
+ const cleanupFnArray = cleanupFnArrayMap.get(context);
227
+ if (!cleanupFnArray || cleanupFnArray.length <= fromIndex) return;
228
+ const toCleanup = cleanupFnArray.slice(fromIndex);
229
+ for (const cleanup of toCleanup.reverse()) await cleanup();
230
+ cleanupFnArray.length = fromIndex;
231
+ }
232
+ const contextHasFixturesCache = /* @__PURE__ */ new WeakMap();
233
+ function withFixtures(fn, options) {
234
+ const collector = getCurrentSuite();
235
+ const suite = options?.suite || collector.suite || collector.file;
236
+ return async (hookContext) => {
237
+ const context = hookContext || options?.context;
238
+ if (!context) {
239
+ if (options?.suiteHook) validateSuiteHook(fn, options.suiteHook, options.stackTraceError);
240
+ return fn({});
241
+ }
242
+ const fixtures = options?.fixtures || getTestFixtures(context);
243
+ if (!fixtures) return fn(context);
244
+ const registrations = fixtures.get(suite);
245
+ if (!registrations.size) return fn(context);
246
+ const usedFixtures = [];
247
+ const usedProps = getUsedProps(fn);
248
+ for (const fixture of registrations.values()) if (isAutoFixture(fixture, options) || usedProps.has(fixture.name)) usedFixtures.push(fixture);
249
+ if (!usedFixtures.length) return fn(context);
250
+ if (!cleanupFnArrayMap.has(context)) cleanupFnArrayMap.set(context, []);
251
+ const cleanupFnArray = cleanupFnArrayMap.get(context);
252
+ const pendingFixtures = resolveDeps(usedFixtures, registrations);
253
+ if (!pendingFixtures.length) return fn(context);
254
+ if (options?.suiteHook) {
255
+ const testScopedFixtures = pendingFixtures.filter((f) => f.scope === "test");
256
+ if (testScopedFixtures.length > 0) {
257
+ const fixtureNames = testScopedFixtures.map((f) => `"${f.name}"`).join(", ");
258
+ const error = new FixtureDependencyError(`Test-scoped fixtures cannot be used inside ${options.suiteHook} hook. The following fixtures are test-scoped: ${fixtureNames}. Use { scope: 'file' } or { scope: 'worker' } fixtures instead, or move the logic to ${{
259
+ aroundAll: "aroundEach",
260
+ beforeAll: "beforeEach",
261
+ afterAll: "afterEach"
262
+ }[options.suiteHook]} hook.`);
263
+ if (options.stackTraceError?.stack) error.stack = error.message + options.stackTraceError.stack.replace(options.stackTraceError.message, "");
264
+ throw error;
265
+ }
266
+ }
267
+ if (!contextHasFixturesCache.has(context)) contextHasFixturesCache.set(context, /* @__PURE__ */ new WeakSet());
268
+ const cachedFixtures = contextHasFixturesCache.get(context);
269
+ for (const fixture of pendingFixtures) if (fixture.scope === "test") {
270
+ if (cachedFixtures.has(fixture)) continue;
271
+ cachedFixtures.add(fixture);
272
+ const resolvedValue = await resolveTestFixtureValue(fixture, context, cleanupFnArray);
273
+ context[fixture.name] = resolvedValue;
274
+ cleanupFnArray.push(() => {
275
+ cachedFixtures.delete(fixture);
276
+ });
277
+ } else {
278
+ const resolvedValue = await resolveScopeFixtureValue(fixtures, suite, fixture);
279
+ context[fixture.name] = resolvedValue;
280
+ }
281
+ return fn(context);
282
+ };
283
+ }
284
+ function isAutoFixture(fixture, options) {
285
+ if (!fixture.auto) return false;
286
+ if (options?.suiteHook && fixture.scope === "test") return false;
287
+ return true;
288
+ }
289
+ function isFixtureFunction(value) {
290
+ return typeof value === "function";
291
+ }
292
+ function resolveTestFixtureValue(fixture, context, cleanupFnArray) {
293
+ if (!isFixtureFunction(fixture.value)) return fixture.value;
294
+ return resolveFixtureFunction(fixture.value, fixture.name, context, cleanupFnArray);
295
+ }
296
+ const scopedFixturePromiseCache = /* @__PURE__ */ new WeakMap();
297
+ async function resolveScopeFixtureValue(fixtures, suite, fixture) {
298
+ const workerContext = fixtures.getWorkerContext();
299
+ const fileContext = fixtures.getFileContext(suite.file);
300
+ const fixtureContext = fixture.scope === "worker" ? workerContext : fileContext;
301
+ if (!isFixtureFunction(fixture.value)) {
302
+ fixtureContext[fixture.name] = fixture.value;
303
+ return fixture.value;
304
+ }
305
+ if (fixture.name in fixtureContext) return fixtureContext[fixture.name];
306
+ if (scopedFixturePromiseCache.has(fixture)) return scopedFixturePromiseCache.get(fixture);
307
+ if (!cleanupFnArrayMap.has(fixtureContext)) cleanupFnArrayMap.set(fixtureContext, []);
308
+ const cleanupFnFileArray = cleanupFnArrayMap.get(fixtureContext);
309
+ const promise = resolveFixtureFunction(fixture.value, fixture.name, fixture.scope === "file" ? {
310
+ ...workerContext,
311
+ ...fileContext
312
+ } : fixtureContext, cleanupFnFileArray).then((value) => {
313
+ fixtureContext[fixture.name] = value;
314
+ scopedFixturePromiseCache.delete(fixture);
315
+ return value;
316
+ });
317
+ scopedFixturePromiseCache.set(fixture, promise);
318
+ return promise;
319
+ }
320
+ async function resolveFixtureFunction(fixtureFn, fixtureName, context, cleanupFnArray) {
321
+ const useFnArgPromise = createDefer();
322
+ const stackTraceError = FIXTURE_STACK_TRACE_KEY in fixtureFn && fixtureFn[FIXTURE_STACK_TRACE_KEY] instanceof Error ? fixtureFn[FIXTURE_STACK_TRACE_KEY] : void 0;
323
+ let isUseFnArgResolved = false;
324
+ const fixtureReturn = fixtureFn(context, async (useFnArg) => {
325
+ isUseFnArgResolved = true;
326
+ useFnArgPromise.resolve(useFnArg);
327
+ const useReturnPromise = createDefer();
328
+ cleanupFnArray.push(async () => {
329
+ useReturnPromise.resolve();
330
+ await fixtureReturn;
331
+ });
332
+ await useReturnPromise;
333
+ }).then(() => {
334
+ if (!isUseFnArgResolved) {
335
+ const error = /* @__PURE__ */ new Error(`Fixture "${fixtureName}" returned without calling "use". Make sure to call "use" in every code path of the fixture function.`);
336
+ if (stackTraceError?.stack) error.stack = error.message + stackTraceError.stack.replace(stackTraceError.message, "");
337
+ useFnArgPromise.reject(error);
338
+ }
339
+ }).catch((e) => {
340
+ if (!isUseFnArgResolved) {
341
+ useFnArgPromise.reject(e);
342
+ return;
343
+ }
344
+ throw e;
345
+ });
346
+ return useFnArgPromise;
347
+ }
348
+ function resolveDeps(usedFixtures, registrations, depSet = /* @__PURE__ */ new Set(), pendingFixtures = []) {
349
+ usedFixtures.forEach((fixture) => {
350
+ if (pendingFixtures.includes(fixture)) return;
351
+ if (!isFixtureFunction(fixture.value) || !fixture.deps) {
352
+ pendingFixtures.push(fixture);
353
+ return;
354
+ }
355
+ if (depSet.has(fixture)) if (fixture.parent) fixture = fixture.parent;
356
+ else throw new Error(`Circular fixture dependency detected: ${fixture.name} <- ${[...depSet].reverse().map((d) => d.name).join(" <- ")}`);
357
+ depSet.add(fixture);
358
+ resolveDeps([...fixture.deps].map((n) => n === fixture.name ? fixture.parent : registrations.get(n)).filter((n) => !!n), registrations, depSet, pendingFixtures);
359
+ pendingFixtures.push(fixture);
360
+ depSet.clear();
361
+ });
362
+ return pendingFixtures;
363
+ }
364
+ function validateSuiteHook(fn, hook, suiteError) {
365
+ const usedProps = getUsedProps(fn, {
366
+ sourceError: suiteError,
367
+ suiteHook: hook
368
+ });
369
+ if (usedProps.size) {
370
+ const error = new FixtureAccessError(`The ${hook} hook uses fixtures "${[...usedProps].join("\", \"")}", but has no access to context. Did you forget to call it as "test.${hook}()" instead of "${hook}()"?\nIf you used internal "suite" task as the first argument previously, access it in the second argument instead. See https://vitest.dev/guide/test-context#suite-level-hooks`);
371
+ if (suiteError) error.stack = suiteError.stack?.replace(suiteError.message, error.message);
372
+ throw error;
373
+ }
374
+ }
375
+ const kPropsSymbol = Symbol("$vitest:fixture-props");
376
+ const kPropNamesSymbol = Symbol("$vitest:fixture-prop-names");
377
+ function configureProps(fn, options) {
378
+ Object.defineProperty(fn, kPropsSymbol, {
379
+ value: options,
380
+ enumerable: false
381
+ });
382
+ }
383
+ function memoProps(fn, props) {
384
+ fn[kPropNamesSymbol] = props;
385
+ return props;
386
+ }
387
+ function getUsedProps(fn, { sourceError, suiteHook } = {}) {
388
+ if (kPropNamesSymbol in fn) return fn[kPropNamesSymbol];
389
+ const { index: fixturesIndex = 0, original: implementation = fn } = kPropsSymbol in fn ? fn[kPropsSymbol] : {};
390
+ let fnString = filterOutComments(implementation.toString());
391
+ if (/__async\((?:this|null), (?:null|arguments|\[[_0-9, ]*\]), function\*/.test(fnString)) fnString = fnString.split(/__async\((?:this|null),/)[1];
392
+ const match = fnString.match(/[^(]*\(([^)]*)/);
393
+ if (!match) return memoProps(fn, /* @__PURE__ */ new Set());
394
+ const args = splitByComma(match[1]);
395
+ if (!args.length) return memoProps(fn, /* @__PURE__ */ new Set());
396
+ const fixturesArgument = args[fixturesIndex];
397
+ if (!fixturesArgument) return memoProps(fn, /* @__PURE__ */ new Set());
398
+ if (!(fixturesArgument[0] === "{" && fixturesArgument.endsWith("}"))) {
399
+ const ordinalArgument = ordinal(fixturesIndex + 1);
400
+ const error = new FixtureParseError(`The ${ordinalArgument} argument inside a fixture must use object destructuring pattern, e.g. ({ task } => {}). Instead, received "${fixturesArgument}".${suiteHook ? ` If you used internal "suite" task as the ${ordinalArgument} argument previously, access it in the ${ordinal(fixturesIndex + 2)} argument instead.` : ""}`);
401
+ if (sourceError) error.stack = sourceError.stack?.replace(sourceError.message, error.message);
402
+ throw error;
403
+ }
404
+ const props = splitByComma(fixturesArgument.slice(1, -1).replace(/\s/g, "")).map((prop) => {
405
+ return prop.replace(/:.*|=.*/g, "");
406
+ });
407
+ const last = props.at(-1);
408
+ if (last && last.startsWith("...")) {
409
+ const error = new FixtureParseError(`Rest parameters are not supported in fixtures, received "${last}".`);
410
+ if (sourceError) error.stack = sourceError.stack?.replace(sourceError.message, error.message);
411
+ throw error;
412
+ }
413
+ return memoProps(fn, new Set(props));
414
+ }
415
+ function splitByComma(s) {
416
+ const result = [];
417
+ const stack = [];
418
+ let start = 0;
419
+ for (let i = 0; i < s.length; i++) if (s[i] === "{" || s[i] === "[") stack.push(s[i] === "{" ? "}" : "]");
420
+ else if (s[i] === stack.at(-1)) stack.pop();
421
+ else if (!stack.length && s[i] === ",") {
422
+ const token = s.substring(start, i).trim();
423
+ if (token) result.push(token);
424
+ start = i + 1;
425
+ }
426
+ const lastToken = s.substring(start).trim();
427
+ if (lastToken) result.push(lastToken);
428
+ return result;
429
+ }
430
+ let _test;
431
+ function setCurrentTest(test) {
432
+ _test = test;
433
+ }
434
+ function getCurrentTest() {
435
+ return _test;
436
+ }
437
+ const tests = [];
438
+ function addRunningTest(test) {
439
+ tests.push(test);
440
+ return () => {
441
+ tests.splice(tests.indexOf(test));
442
+ };
443
+ }
444
+ function getRunningTests() {
445
+ return tests;
446
+ }
447
+ const kChainableContext = Symbol("kChainableContext");
448
+ function getChainableContext(chainable) {
449
+ return chainable?.[kChainableContext];
450
+ }
451
+ function createChainable(keys, fn, context) {
452
+ function create(context) {
453
+ const chain = function(...args) {
454
+ return fn.apply(context, args);
455
+ };
456
+ Object.assign(chain, fn);
457
+ Object.defineProperty(chain, kChainableContext, {
458
+ value: {
459
+ withContext: () => chain.bind(context),
460
+ getFixtures: () => context.fixtures,
461
+ setContext: (key, value) => {
462
+ context[key] = value;
463
+ },
464
+ mergeContext: (ctx) => {
465
+ Object.assign(context, ctx);
466
+ }
467
+ },
468
+ enumerable: false
469
+ });
470
+ for (const key of keys) Object.defineProperty(chain, key, { get() {
471
+ return create({
472
+ ...context,
473
+ [key]: true
474
+ });
475
+ } });
476
+ return chain;
477
+ }
478
+ const chain = create(context ?? {});
479
+ Object.defineProperty(chain, "fn", {
480
+ value: fn,
481
+ enumerable: false
482
+ });
483
+ return chain;
484
+ }
485
+ function getDefaultHookTimeout() {
486
+ return getRunner().config.hookTimeout;
487
+ }
488
+ const CLEANUP_TIMEOUT_KEY = Symbol.for("VITEST_CLEANUP_TIMEOUT");
489
+ const CLEANUP_STACK_TRACE_KEY = Symbol.for("VITEST_CLEANUP_STACK_TRACE");
490
+ const AROUND_TIMEOUT_KEY = Symbol.for("VITEST_AROUND_TIMEOUT");
491
+ const AROUND_STACK_TRACE_KEY = Symbol.for("VITEST_AROUND_STACK_TRACE");
492
+ function getBeforeHookCleanupCallback(hook, result, context) {
493
+ if (typeof result === "function") return withTimeout(result, CLEANUP_TIMEOUT_KEY in hook && typeof hook[CLEANUP_TIMEOUT_KEY] === "number" ? hook[CLEANUP_TIMEOUT_KEY] : getDefaultHookTimeout(), true, CLEANUP_STACK_TRACE_KEY in hook && hook[CLEANUP_STACK_TRACE_KEY] instanceof Error ? hook[CLEANUP_STACK_TRACE_KEY] : void 0, (_, error) => {
494
+ if (context) abortContextSignal(context, error);
495
+ });
496
+ }
497
+ /**
498
+ * Registers a callback function to be executed once before all tests within the current suite.
499
+ * This hook is useful for scenarios where you need to perform setup operations that are common to all tests in a suite, such as initializing a database connection or setting up a test environment.
500
+ *
501
+ * **Note:** The `beforeAll` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.
502
+ *
503
+ * @param {Function} fn - The callback function to be executed before all tests.
504
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
505
+ * @returns {void}
506
+ * @example
507
+ * ```ts
508
+ * // Example of using beforeAll to set up a database connection
509
+ * beforeAll(async () => {
510
+ * await database.connect();
511
+ * });
512
+ * ```
513
+ */
514
+ function beforeAll(fn, timeout = getDefaultHookTimeout()) {
515
+ assertTypes(fn, "\"beforeAll\" callback", ["function"]);
516
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
517
+ const context = getChainableContext(this);
518
+ return getCurrentSuite().on("beforeAll", Object.assign(withTimeout(withSuiteFixtures("beforeAll", fn, context, stackTraceError), timeout, true, stackTraceError), {
519
+ [CLEANUP_TIMEOUT_KEY]: timeout,
520
+ [CLEANUP_STACK_TRACE_KEY]: stackTraceError
521
+ }));
522
+ }
523
+ /**
524
+ * Registers a callback function to be executed once after all tests within the current suite have completed.
525
+ * This hook is useful for scenarios where you need to perform cleanup operations after all tests in a suite have run, such as closing database connections or cleaning up temporary files.
526
+ *
527
+ * **Note:** The `afterAll` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.
528
+ *
529
+ * @param {Function} fn - The callback function to be executed after all tests.
530
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
531
+ * @returns {void}
532
+ * @example
533
+ * ```ts
534
+ * // Example of using afterAll to close a database connection
535
+ * afterAll(async () => {
536
+ * await database.disconnect();
537
+ * });
538
+ * ```
539
+ */
540
+ function afterAll(fn, timeout) {
541
+ assertTypes(fn, "\"afterAll\" callback", ["function"]);
542
+ const context = getChainableContext(this);
543
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
544
+ return getCurrentSuite().on("afterAll", withTimeout(withSuiteFixtures("afterAll", fn, context, stackTraceError), timeout ?? getDefaultHookTimeout(), true, stackTraceError));
545
+ }
546
+ /**
547
+ * Registers a callback function to be executed before each test within the current suite.
548
+ * This hook is useful for scenarios where you need to reset or reinitialize the test environment before each test runs, such as resetting database states, clearing caches, or reinitializing variables.
549
+ *
550
+ * **Note:** The `beforeEach` hooks are executed in the order they are defined one after another. You can configure this by changing the `sequence.hooks` option in the config file.
551
+ *
552
+ * @param {Function} fn - The callback function to be executed before each test. This function receives an `TestContext` parameter if additional test context is needed.
553
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
554
+ * @returns {void}
555
+ * @example
556
+ * ```ts
557
+ * // Example of using beforeEach to reset a database state
558
+ * beforeEach(async () => {
559
+ * await database.reset();
560
+ * });
561
+ * ```
562
+ */
563
+ function beforeEach(fn, timeout = getDefaultHookTimeout()) {
564
+ assertTypes(fn, "\"beforeEach\" callback", ["function"]);
565
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
566
+ const wrapper = (context, suite) => {
567
+ return withFixtures(fn, { suite })(context);
568
+ };
569
+ return getCurrentSuite().on("beforeEach", Object.assign(withTimeout(wrapper, timeout ?? getDefaultHookTimeout(), true, stackTraceError, abortIfTimeout), {
570
+ [CLEANUP_TIMEOUT_KEY]: timeout,
571
+ [CLEANUP_STACK_TRACE_KEY]: stackTraceError
572
+ }));
573
+ }
574
+ /**
575
+ * Registers a callback function to be executed after each test within the current suite has completed.
576
+ * This hook is useful for scenarios where you need to clean up or reset the test environment after each test runs, such as deleting temporary files, clearing test-specific database entries, or resetting mocked functions.
577
+ *
578
+ * **Note:** The `afterEach` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.
579
+ *
580
+ * @param {Function} fn - The callback function to be executed after each test. This function receives an `TestContext` parameter if additional test context is needed.
581
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
582
+ * @returns {void}
583
+ * @example
584
+ * ```ts
585
+ * // Example of using afterEach to delete temporary files created during a test
586
+ * afterEach(async () => {
587
+ * await fileSystem.deleteTempFiles();
588
+ * });
589
+ * ```
590
+ */
591
+ function afterEach(fn, timeout) {
592
+ assertTypes(fn, "\"afterEach\" callback", ["function"]);
593
+ const wrapper = (context, suite) => {
594
+ return withFixtures(fn, { suite })(context);
595
+ };
596
+ return getCurrentSuite().on("afterEach", withTimeout(wrapper, timeout ?? getDefaultHookTimeout(), true, /* @__PURE__ */ new Error("STACK_TRACE_ERROR"), abortIfTimeout));
597
+ }
598
+ /**
599
+ * Registers a callback function to be executed when a test fails within the current suite.
600
+ * This function allows for custom actions to be performed in response to test failures, such as logging, cleanup, or additional diagnostics.
601
+ *
602
+ * **Note:** The `onTestFailed` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.
603
+ *
604
+ * @param {Function} fn - The callback function to be executed upon a test failure. The function receives the test result (including errors).
605
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
606
+ * @throws {Error} Throws an error if the function is not called within a test.
607
+ * @returns {void}
608
+ * @example
609
+ * ```ts
610
+ * // Example of using onTestFailed to log failure details
611
+ * onTestFailed(({ errors }) => {
612
+ * console.log(`Test failed: ${test.name}`, errors);
613
+ * });
614
+ * ```
615
+ */
616
+ const onTestFailed = createTestHook("onTestFailed", (test, handler, timeout) => {
617
+ test.onFailed ||= [];
618
+ test.onFailed.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, /* @__PURE__ */ new Error("STACK_TRACE_ERROR"), abortIfTimeout));
619
+ });
620
+ /**
621
+ * Registers a callback function to be executed when the current test finishes, regardless of the outcome (pass or fail).
622
+ * This function is ideal for performing actions that should occur after every test execution, such as cleanup, logging, or resetting shared resources.
623
+ *
624
+ * This hook is useful if you have access to a resource in the test itself and you want to clean it up after the test finishes. It is a more compact way to clean up resources than using the combination of `beforeEach` and `afterEach`.
625
+ *
626
+ * **Note:** The `onTestFinished` hooks are running in reverse order of their registration. You can configure this by changing the `sequence.hooks` option in the config file.
627
+ *
628
+ * **Note:** The `onTestFinished` hook is not called if the test is canceled with a dynamic `ctx.skip()` call.
629
+ *
630
+ * @param {Function} fn - The callback function to be executed after a test finishes. The function can receive parameters providing details about the completed test, including its success or failure status.
631
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
632
+ * @throws {Error} Throws an error if the function is not called within a test.
633
+ * @returns {void}
634
+ * @example
635
+ * ```ts
636
+ * // Example of using onTestFinished for cleanup
637
+ * const db = await connectToDatabase();
638
+ * onTestFinished(async () => {
639
+ * await db.disconnect();
640
+ * });
641
+ * ```
642
+ */
643
+ const onTestFinished = createTestHook("onTestFinished", (test, handler, timeout) => {
644
+ test.onFinished ||= [];
645
+ test.onFinished.push(withTimeout(handler, timeout ?? getDefaultHookTimeout(), true, /* @__PURE__ */ new Error("STACK_TRACE_ERROR"), abortIfTimeout));
646
+ });
647
+ /**
648
+ * Registers a callback function that wraps around all tests within the current suite.
649
+ * The callback receives a `runSuite` function that must be called to run the suite's tests.
650
+ * This hook is useful for scenarios where you need to wrap an entire suite in a context
651
+ * (e.g., starting a server, opening a database connection that all tests share).
652
+ *
653
+ * **Note:** When multiple `aroundAll` hooks are registered, they are nested inside each other.
654
+ * The first registered hook is the outermost wrapper.
655
+ *
656
+ * @param {Function} fn - The callback function that wraps the suite. Must call `runSuite()` to run the tests.
657
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
658
+ * @returns {void}
659
+ * @example
660
+ * ```ts
661
+ * // Example of using aroundAll to wrap suite in a tracing span
662
+ * aroundAll(async (runSuite) => {
663
+ * await tracer.trace('test-suite', runSuite);
664
+ * });
665
+ * ```
666
+ * @example
667
+ * ```ts
668
+ * // Example of using aroundAll with fixtures
669
+ * aroundAll(async (runSuite, { db }) => {
670
+ * await db.transaction(() => runSuite());
671
+ * });
672
+ * ```
673
+ */
674
+ function aroundAll(fn, timeout) {
675
+ assertTypes(fn, "\"aroundAll\" callback", ["function"]);
676
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
677
+ const resolvedTimeout = timeout ?? getDefaultHookTimeout();
678
+ const context = getChainableContext(this);
679
+ return getCurrentSuite().on("aroundAll", Object.assign(withSuiteFixtures("aroundAll", fn, context, stackTraceError, 1), {
680
+ [AROUND_TIMEOUT_KEY]: resolvedTimeout,
681
+ [AROUND_STACK_TRACE_KEY]: stackTraceError
682
+ }));
683
+ }
684
+ /**
685
+ * Registers a callback function that wraps around each test within the current suite.
686
+ * The callback receives a `runTest` function that must be called to run the test.
687
+ * This hook is useful for scenarios where you need to wrap tests in a context (e.g., database transactions).
688
+ *
689
+ * **Note:** When multiple `aroundEach` hooks are registered, they are nested inside each other.
690
+ * The first registered hook is the outermost wrapper.
691
+ *
692
+ * @param {Function} fn - The callback function that wraps the test. Must call `runTest()` to run the test.
693
+ * @param {number} [timeout] - Optional timeout in milliseconds for the hook. If not provided, the default hook timeout from the runner's configuration is used.
694
+ * @returns {void}
695
+ * @example
696
+ * ```ts
697
+ * // Example of using aroundEach to wrap tests in a database transaction
698
+ * aroundEach(async (runTest) => {
699
+ * await database.transaction(() => runTest());
700
+ * });
701
+ * ```
702
+ * @example
703
+ * ```ts
704
+ * // Example of using aroundEach with fixtures
705
+ * aroundEach(async (runTest, { db }) => {
706
+ * await db.transaction(() => runTest());
707
+ * });
708
+ * ```
709
+ */
710
+ function aroundEach(fn, timeout) {
711
+ assertTypes(fn, "\"aroundEach\" callback", ["function"]);
712
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
713
+ const resolvedTimeout = timeout ?? getDefaultHookTimeout();
714
+ const wrapper = (runTest, context, suite) => {
715
+ const innerFn = (ctx) => fn(runTest, ctx, suite);
716
+ configureProps(innerFn, {
717
+ index: 1,
718
+ original: fn
719
+ });
720
+ return withFixtures(innerFn, { suite })(context);
721
+ };
722
+ return getCurrentSuite().on("aroundEach", Object.assign(wrapper, {
723
+ [AROUND_TIMEOUT_KEY]: resolvedTimeout,
724
+ [AROUND_STACK_TRACE_KEY]: stackTraceError
725
+ }));
726
+ }
727
+ function withSuiteFixtures(suiteHook, fn, context, stackTraceError, contextIndex = 0) {
728
+ return (...args) => {
729
+ const suite = args.at(-1);
730
+ const prefix = args.slice(0, -1);
731
+ const wrapper = (ctx) => fn(...prefix, ctx, suite);
732
+ configureProps(wrapper, {
733
+ index: contextIndex,
734
+ original: fn
735
+ });
736
+ const fixtures = context?.getFixtures();
737
+ const fileContext = fixtures?.getFileContext(suite.file);
738
+ return withFixtures(wrapper, {
739
+ suiteHook,
740
+ fixtures,
741
+ context: fileContext,
742
+ stackTraceError
743
+ })();
744
+ };
745
+ }
746
+ function getAroundHookTimeout(hook) {
747
+ return AROUND_TIMEOUT_KEY in hook && typeof hook[AROUND_TIMEOUT_KEY] === "number" ? hook[AROUND_TIMEOUT_KEY] : getDefaultHookTimeout();
748
+ }
749
+ function getAroundHookStackTrace(hook) {
750
+ return AROUND_STACK_TRACE_KEY in hook && hook[AROUND_STACK_TRACE_KEY] instanceof Error ? hook[AROUND_STACK_TRACE_KEY] : void 0;
751
+ }
752
+ function createTestHook(name, handler) {
753
+ return (fn, timeout) => {
754
+ assertTypes(fn, `"${name}" callback`, ["function"]);
755
+ const current = getCurrentTest();
756
+ if (!current) throw new Error(`Hook ${name}() can only be called inside a test`);
757
+ return handler(current, fn, timeout);
758
+ };
759
+ }
760
+ /**
761
+ * If any tasks been marked as `only`, mark all other tasks as `skip`.
762
+ */
763
+ function interpretTaskModes(file, namePattern, testLocations, testIds, testTagsFilter, onlyMode, parentIsOnly, allowOnly) {
764
+ const matchedLocations = [];
765
+ const traverseSuite = (suite, parentIsOnly, parentMatchedWithLocation) => {
766
+ const suiteIsOnly = parentIsOnly || suite.mode === "only";
767
+ const hasSomeTasksOnly = onlyMode && suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
768
+ suite.tasks.forEach((t) => {
769
+ const includeTask = hasSomeTasksOnly ? t.mode === "only" || t.type === "suite" && someTasksAreOnly(t) : suiteIsOnly || t.mode === "only";
770
+ if (onlyMode) {
771
+ if (t.type === "suite" && (includeTask || someTasksAreOnly(t))) {
772
+ if (t.mode === "only") {
773
+ checkAllowOnly(t, allowOnly);
774
+ t.mode = "run";
775
+ }
776
+ } else if (t.mode === "run" && !includeTask) t.mode = "skip";
777
+ else if (t.mode === "only") {
778
+ checkAllowOnly(t, allowOnly);
779
+ t.mode = "run";
780
+ }
781
+ }
782
+ let hasLocationMatch = parentMatchedWithLocation;
783
+ if (testLocations !== void 0 && testLocations.length !== 0) {
784
+ if (t.location && testLocations?.includes(t.location.line)) {
785
+ t.mode = "run";
786
+ matchedLocations.push(t.location.line);
787
+ hasLocationMatch = true;
788
+ } else if (parentMatchedWithLocation) t.mode = "run";
789
+ else if (t.type === "test") t.mode = "skip";
790
+ }
791
+ if (t.type === "test") {
792
+ if (namePattern && !getTaskFullName(t).match(namePattern)) t.mode = "skip";
793
+ if (testIds && !testIds.includes(t.id)) t.mode = "skip";
794
+ if (testTagsFilter && !testTagsFilter(t.tags || [])) t.mode = "skip";
795
+ } else if (t.type === "suite") if (t.mode === "skip") skipAllTasks(t);
796
+ else if (t.mode === "todo") todoAllTasks(t);
797
+ else traverseSuite(t, includeTask, hasLocationMatch);
798
+ });
799
+ if (suite.mode === "run" || suite.mode === "queued") {
800
+ if (suite.tasks.length && suite.tasks.every((i) => i.mode !== "run" && i.mode !== "queued")) suite.mode = "skip";
801
+ }
802
+ };
803
+ traverseSuite(file, parentIsOnly, false);
804
+ const nonMatching = testLocations?.filter((loc) => !matchedLocations.includes(loc));
805
+ if (nonMatching && nonMatching.length !== 0) {
806
+ const message = nonMatching.length === 1 ? `line ${nonMatching[0]}` : `lines ${nonMatching.join(", ")}`;
807
+ if (file.result === void 0) file.result = {
808
+ state: "fail",
809
+ errors: []
810
+ };
811
+ if (file.result.errors === void 0) file.result.errors = [];
812
+ file.result.errors.push(processError(/* @__PURE__ */ new Error(`No test found in ${file.name} in ${message}`)));
813
+ }
814
+ }
815
+ function getTaskFullName(task) {
816
+ return `${task.suite ? `${getTaskFullName(task.suite)} ` : ""}${task.name}`;
817
+ }
818
+ function someTasksAreOnly(suite) {
819
+ return suite.tasks.some((t) => t.mode === "only" || t.type === "suite" && someTasksAreOnly(t));
820
+ }
821
+ function skipAllTasks(suite) {
822
+ suite.tasks.forEach((t) => {
823
+ if (t.mode === "run" || t.mode === "queued") {
824
+ t.mode = "skip";
825
+ if (t.type === "suite") skipAllTasks(t);
826
+ }
827
+ });
828
+ }
829
+ function todoAllTasks(suite) {
830
+ suite.tasks.forEach((t) => {
831
+ if (t.mode === "run" || t.mode === "queued") {
832
+ t.mode = "todo";
833
+ if (t.type === "suite") todoAllTasks(t);
834
+ }
835
+ });
836
+ }
837
+ function checkAllowOnly(task, allowOnly) {
838
+ if (allowOnly) return;
839
+ task.result = {
840
+ state: "fail",
841
+ errors: [processError(/* @__PURE__ */ new Error("[Vitest] Unexpected .only modifier. Remove it or pass --allowOnly argument to bypass this error"))]
842
+ };
843
+ }
844
+ /* @__NO_SIDE_EFFECTS__ */
845
+ function generateHash(str) {
846
+ let hash = 0;
847
+ if (str.length === 0) return `${hash}`;
848
+ for (let i = 0; i < str.length; i++) {
849
+ const char = str.charCodeAt(i);
850
+ hash = (hash << 5) - hash + char;
851
+ hash = hash & hash;
852
+ }
853
+ return `${hash}`;
854
+ }
855
+ function calculateSuiteHash(parent) {
856
+ parent.tasks.forEach((t, idx) => {
857
+ t.id = `${parent.id}_${idx}`;
858
+ if (t.type === "suite") calculateSuiteHash(t);
859
+ });
860
+ }
861
+ function createFileTask(filepath, root, projectName, pool, viteEnvironment) {
862
+ const path = relative(root, filepath);
863
+ const file = {
864
+ id: /* @__PURE__ */ generateFileHash(path, projectName),
865
+ name: path,
866
+ fullName: path,
867
+ type: "suite",
868
+ mode: "queued",
869
+ filepath,
870
+ tasks: [],
871
+ meta: Object.create(null),
872
+ projectName,
873
+ file: void 0,
874
+ pool,
875
+ viteEnvironment
876
+ };
877
+ file.file = file;
878
+ return file;
879
+ }
880
+ /**
881
+ * Generate a unique ID for a file based on its path and project name
882
+ * @param file File relative to the root of the project to keep ID the same between different machines
883
+ * @param projectName The name of the test project
884
+ */
885
+ /* @__NO_SIDE_EFFECTS__ */
886
+ function generateFileHash(file, projectName) {
887
+ return /* @__PURE__ */ generateHash(`${file}${projectName || ""}`);
888
+ }
889
+ function findTestFileStackTrace(testFilePath, error) {
890
+ const lines = error.split("\n").slice(1);
891
+ for (const line of lines) {
892
+ const stack = parseSingleStack(line);
893
+ if (stack && stack.file === testFilePath) return stack;
894
+ }
895
+ }
896
+ /**
897
+ * Return a function for running multiple async operations with limited concurrency.
898
+ */
899
+ function limitConcurrency(concurrency = Infinity) {
900
+ let count = 0;
901
+ let head;
902
+ let tail;
903
+ const finish = () => {
904
+ count--;
905
+ if (head) {
906
+ head[0]();
907
+ head = head[1];
908
+ tail = head && tail;
909
+ }
910
+ };
911
+ const acquire = () => {
912
+ let released = false;
913
+ const release = () => {
914
+ if (!released) {
915
+ released = true;
916
+ finish();
917
+ }
918
+ };
919
+ if (count++ < concurrency) return release;
920
+ return new Promise((resolve) => {
921
+ if (tail) tail = tail[1] = [() => resolve(release)];
922
+ else head = tail = [() => resolve(release)];
923
+ });
924
+ };
925
+ const limiterFn = (func, ...args) => {
926
+ function run(release) {
927
+ try {
928
+ const result = func(...args);
929
+ if (result instanceof Promise) return result.finally(release);
930
+ release();
931
+ return Promise.resolve(result);
932
+ } catch (error) {
933
+ release();
934
+ return Promise.reject(error);
935
+ }
936
+ }
937
+ const release = acquire();
938
+ return release instanceof Promise ? release.then(run) : run(release);
939
+ };
940
+ return Object.assign(limiterFn, { acquire });
941
+ }
942
+ /**
943
+ * Partition in tasks groups by consecutive concurrent
944
+ */
945
+ function partitionSuiteChildren(suite) {
946
+ let tasksGroup = [];
947
+ const tasksGroups = [];
948
+ for (const c of suite.tasks) if (tasksGroup.length === 0 || c.concurrent === tasksGroup[0].concurrent) tasksGroup.push(c);
949
+ else {
950
+ tasksGroups.push(tasksGroup);
951
+ tasksGroup = [c];
952
+ }
953
+ if (tasksGroup.length > 0) tasksGroups.push(tasksGroup);
954
+ return tasksGroups;
955
+ }
956
+ const filterMap = /* @__PURE__ */ new WeakMap();
957
+ /**
958
+ * @experimental
959
+ */
960
+ function matchesTags(testTags) {
961
+ const runner = getRunner();
962
+ const tagsFilter = runner._currentSpecification?.testTagsFilter ?? runner.config.tagsFilter;
963
+ if (!tagsFilter) return true;
964
+ let tagsFilterPredicate = filterMap.get(tagsFilter);
965
+ if (!tagsFilterPredicate) {
966
+ tagsFilterPredicate = createTagsFilter(tagsFilter, runner.config.tags);
967
+ filterMap.set(tagsFilter, tagsFilterPredicate);
968
+ }
969
+ return tagsFilterPredicate(testTags);
970
+ }
971
+ function validateTags(config, tags) {
972
+ if (!config.strictTags) return;
973
+ const availableTags = new Set(config.tags.map((tag) => tag.name));
974
+ for (const tag of tags) if (!availableTags.has(tag)) throw createNoTagsError(config.tags, tag);
975
+ }
976
+ function createNoTagsError(availableTags, tag, prefix = "tag") {
977
+ if (!availableTags.length) throw new Error(`The Vitest config does't define any "tags", cannot apply "${tag}" ${prefix} for this test. See: https://vitest.dev/guide/test-tags`);
978
+ throw new Error(`The ${prefix} "${tag}" is not defined in the configuration. Available tags are:\n${availableTags.map((t) => `- ${t.name}${t.description ? `: ${t.description}` : ""}`).join("\n")}`);
979
+ }
980
+ function createTagsFilter(tagsExpr, availableTags) {
981
+ const matchers = tagsExpr.map((expr) => parseTagsExpression(expr, availableTags));
982
+ return (testTags) => {
983
+ return matchers.every((matcher) => matcher(testTags));
984
+ };
985
+ }
986
+ function parseTagsExpression(expr, availableTags) {
987
+ const stream = new TokenStream(tokenize(expr), expr);
988
+ const ast = parseOrExpression(stream, availableTags);
989
+ if (stream.peek().type !== "EOF") throw new Error(`Invalid tags expression: unexpected "${formatToken(stream.peek())}" in "${expr}"`);
990
+ return (tags) => evaluateNode(ast, tags);
991
+ }
992
+ function formatToken(token) {
993
+ switch (token.type) {
994
+ case "TAG": return token.value;
995
+ default: return formatTokenType(token.type);
996
+ }
997
+ }
998
+ function tokenize(expr) {
999
+ const tokens = [];
1000
+ let i = 0;
1001
+ while (i < expr.length) {
1002
+ if (expr[i] === " " || expr[i] === " ") {
1003
+ i++;
1004
+ continue;
1005
+ }
1006
+ if (expr[i] === "(") {
1007
+ tokens.push({ type: "LPAREN" });
1008
+ i++;
1009
+ continue;
1010
+ }
1011
+ if (expr[i] === ")") {
1012
+ tokens.push({ type: "RPAREN" });
1013
+ i++;
1014
+ continue;
1015
+ }
1016
+ if (expr[i] === "!") {
1017
+ tokens.push({ type: "NOT" });
1018
+ i++;
1019
+ continue;
1020
+ }
1021
+ if (expr.slice(i, i + 2) === "&&") {
1022
+ tokens.push({ type: "AND" });
1023
+ i += 2;
1024
+ continue;
1025
+ }
1026
+ if (expr.slice(i, i + 2) === "||") {
1027
+ tokens.push({ type: "OR" });
1028
+ i += 2;
1029
+ continue;
1030
+ }
1031
+ if (/^and(?:\s|\)|$)/i.test(expr.slice(i))) {
1032
+ tokens.push({ type: "AND" });
1033
+ i += 3;
1034
+ continue;
1035
+ }
1036
+ if (/^or(?:\s|\)|$)/i.test(expr.slice(i))) {
1037
+ tokens.push({ type: "OR" });
1038
+ i += 2;
1039
+ continue;
1040
+ }
1041
+ if (/^not\s/i.test(expr.slice(i))) {
1042
+ tokens.push({ type: "NOT" });
1043
+ i += 3;
1044
+ continue;
1045
+ }
1046
+ let tag = "";
1047
+ while (i < expr.length && expr[i] !== " " && expr[i] !== " " && expr[i] !== "(" && expr[i] !== ")" && expr[i] !== "!" && expr[i] !== "&" && expr[i] !== "|") {
1048
+ const remaining = expr.slice(i);
1049
+ if (tag === "" && (/^and(?:\s|\)|$)/i.test(remaining) || /^or(?:\s|\)|$)/i.test(remaining) || /^not\s/i.test(remaining))) break;
1050
+ tag += expr[i];
1051
+ i++;
1052
+ }
1053
+ if (tag) tokens.push({
1054
+ type: "TAG",
1055
+ value: tag
1056
+ });
1057
+ }
1058
+ tokens.push({ type: "EOF" });
1059
+ return tokens;
1060
+ }
1061
+ var TokenStream = class {
1062
+ pos = 0;
1063
+ constructor(tokens, expr) {
1064
+ this.tokens = tokens;
1065
+ this.expr = expr;
1066
+ }
1067
+ peek() {
1068
+ return this.tokens[this.pos];
1069
+ }
1070
+ next() {
1071
+ return this.tokens[this.pos++];
1072
+ }
1073
+ expect(type) {
1074
+ const token = this.next();
1075
+ if (token.type !== type) {
1076
+ if (type === "RPAREN" && token.type === "EOF") throw new Error(`Invalid tags expression: missing closing ")" in "${this.expr}"`);
1077
+ throw new Error(`Invalid tags expression: expected "${formatTokenType(type)}" but got "${formatToken(token)}" in "${this.expr}"`);
1078
+ }
1079
+ return token;
1080
+ }
1081
+ unexpectedToken() {
1082
+ const token = this.peek();
1083
+ if (token.type === "EOF") throw new Error(`Invalid tags expression: unexpected end of expression in "${this.expr}"`);
1084
+ throw new Error(`Invalid tags expression: unexpected "${formatToken(token)}" in "${this.expr}"`);
1085
+ }
1086
+ };
1087
+ function formatTokenType(type) {
1088
+ switch (type) {
1089
+ case "TAG": return "tag";
1090
+ case "AND": return "and";
1091
+ case "OR": return "or";
1092
+ case "NOT": return "not";
1093
+ case "LPAREN": return "(";
1094
+ case "RPAREN": return ")";
1095
+ case "EOF": return "end of expression";
1096
+ }
1097
+ }
1098
+ function parseOrExpression(stream, availableTags) {
1099
+ let left = parseAndExpression(stream, availableTags);
1100
+ while (stream.peek().type === "OR") {
1101
+ stream.next();
1102
+ const right = parseAndExpression(stream, availableTags);
1103
+ left = {
1104
+ type: "or",
1105
+ left,
1106
+ right
1107
+ };
1108
+ }
1109
+ return left;
1110
+ }
1111
+ function parseAndExpression(stream, availableTags) {
1112
+ let left = parseUnaryExpression(stream, availableTags);
1113
+ while (stream.peek().type === "AND") {
1114
+ stream.next();
1115
+ const right = parseUnaryExpression(stream, availableTags);
1116
+ left = {
1117
+ type: "and",
1118
+ left,
1119
+ right
1120
+ };
1121
+ }
1122
+ return left;
1123
+ }
1124
+ function parseUnaryExpression(stream, availableTags) {
1125
+ if (stream.peek().type === "NOT") {
1126
+ stream.next();
1127
+ return {
1128
+ type: "not",
1129
+ operand: parseUnaryExpression(stream, availableTags)
1130
+ };
1131
+ }
1132
+ return parsePrimaryExpression(stream, availableTags);
1133
+ }
1134
+ function parsePrimaryExpression(stream, availableTags) {
1135
+ const token = stream.peek();
1136
+ if (token.type === "LPAREN") {
1137
+ stream.next();
1138
+ const expr = parseOrExpression(stream, availableTags);
1139
+ stream.expect("RPAREN");
1140
+ return expr;
1141
+ }
1142
+ if (token.type === "TAG") {
1143
+ stream.next();
1144
+ const tagValue = token.value;
1145
+ return {
1146
+ type: "tag",
1147
+ value: tagValue,
1148
+ pattern: resolveTagPattern(tagValue, availableTags)
1149
+ };
1150
+ }
1151
+ stream.unexpectedToken();
1152
+ }
1153
+ function createWildcardRegex(pattern) {
1154
+ return new RegExp(`^${pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`);
1155
+ }
1156
+ function resolveTagPattern(tagPattern, availableTags) {
1157
+ if (tagPattern.includes("*")) {
1158
+ const regex = createWildcardRegex(tagPattern);
1159
+ if (!availableTags.some((tag) => regex.test(tag.name))) throw createNoTagsError(availableTags, tagPattern, "tag pattern");
1160
+ return regex;
1161
+ }
1162
+ if (!availableTags.length || !availableTags.some((tag) => tag.name === tagPattern)) throw createNoTagsError(availableTags, tagPattern, "tag pattern");
1163
+ return null;
1164
+ }
1165
+ function evaluateNode(node, tags) {
1166
+ switch (node.type) {
1167
+ case "tag":
1168
+ if (node.pattern) return tags.some((tag) => node.pattern.test(tag));
1169
+ return tags.includes(node.value);
1170
+ case "not": return !evaluateNode(node.operand, tags);
1171
+ case "and": return evaluateNode(node.left, tags) && evaluateNode(node.right, tags);
1172
+ case "or": return evaluateNode(node.left, tags) || evaluateNode(node.right, tags);
1173
+ }
1174
+ }
1175
+ function isTestCase(s) {
1176
+ return s.type === "test";
1177
+ }
1178
+ function getTests(suite) {
1179
+ const tests = [];
1180
+ const arraySuites = toArray(suite);
1181
+ for (const s of arraySuites) if (isTestCase(s)) tests.push(s);
1182
+ else for (const task of s.tasks) if (isTestCase(task)) tests.push(task);
1183
+ else {
1184
+ const taskTests = getTests(task);
1185
+ for (const test of taskTests) tests.push(test);
1186
+ }
1187
+ return tests;
1188
+ }
1189
+ function getTasks(tasks = []) {
1190
+ return toArray(tasks).flatMap((s) => isTestCase(s) ? [s] : [s, ...getTasks(s.tasks)]);
1191
+ }
1192
+ function getSuites(suite) {
1193
+ return toArray(suite).flatMap((s) => s.type === "suite" ? [s, ...getSuites(s.tasks)] : []);
1194
+ }
1195
+ function hasTests(suite) {
1196
+ return toArray(suite).some((s) => s.tasks.some((c) => isTestCase(c) || hasTests(c)));
1197
+ }
1198
+ function hasFailed(suite) {
1199
+ return toArray(suite).some((s) => s.result?.state === "fail" || s.type === "suite" && hasFailed(s.tasks));
1200
+ }
1201
+ function getNames(task) {
1202
+ const names = [task.name];
1203
+ let current = task;
1204
+ while (current?.suite) {
1205
+ current = current.suite;
1206
+ if (current?.name) names.unshift(current.name);
1207
+ }
1208
+ if (current !== task.file) names.unshift(task.file.name);
1209
+ return names;
1210
+ }
1211
+ function getFullName(task, separator = " > ") {
1212
+ return getNames(task).join(separator);
1213
+ }
1214
+ function getTestName(task, separator = " > ") {
1215
+ return getNames(task).slice(1).join(separator);
1216
+ }
1217
+ function createTaskName(names, separator = " > ") {
1218
+ return names.filter((name) => name !== void 0).join(separator);
1219
+ }
1220
+ /**
1221
+ * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
1222
+ * Suites can contain both tests and other suites, enabling complex test structures.
1223
+ *
1224
+ * @param {string} name - The name of the suite, used for identification and reporting.
1225
+ * @param {Function} fn - A function that defines the tests and suites within this suite.
1226
+ * @example
1227
+ * ```ts
1228
+ * // Define a suite with two tests
1229
+ * suite('Math operations', () => {
1230
+ * test('should add two numbers', () => {
1231
+ * expect(add(1, 2)).toBe(3);
1232
+ * });
1233
+ *
1234
+ * test('should subtract two numbers', () => {
1235
+ * expect(subtract(5, 2)).toBe(3);
1236
+ * });
1237
+ * });
1238
+ * ```
1239
+ * @example
1240
+ * ```ts
1241
+ * // Define nested suites
1242
+ * suite('String operations', () => {
1243
+ * suite('Trimming', () => {
1244
+ * test('should trim whitespace from start and end', () => {
1245
+ * expect(' hello '.trim()).toBe('hello');
1246
+ * });
1247
+ * });
1248
+ *
1249
+ * suite('Concatenation', () => {
1250
+ * test('should concatenate two strings', () => {
1251
+ * expect('hello' + ' ' + 'world').toBe('hello world');
1252
+ * });
1253
+ * });
1254
+ * });
1255
+ * ```
1256
+ */
1257
+ const suite = createSuite();
1258
+ /**
1259
+ * Defines a test case with a given name and test function. The test function can optionally be configured with test options.
1260
+ *
1261
+ * @param {string | Function} name - The name of the test or a function that will be used as a test name.
1262
+ * @param {TestOptions | TestFunction} [optionsOrFn] - Optional. The test options or the test function if no explicit name is provided.
1263
+ * @param {number | TestOptions | TestFunction} [optionsOrTest] - Optional. The test function or options, depending on the previous parameters.
1264
+ * @throws {Error} If called inside another test function.
1265
+ * @example
1266
+ * ```ts
1267
+ * // Define a simple test
1268
+ * test('should add two numbers', () => {
1269
+ * expect(add(1, 2)).toBe(3);
1270
+ * });
1271
+ * ```
1272
+ * @example
1273
+ * ```ts
1274
+ * // Define a test with options
1275
+ * test('should subtract two numbers', { retry: 3 }, () => {
1276
+ * expect(subtract(5, 2)).toBe(3);
1277
+ * });
1278
+ * ```
1279
+ */
1280
+ const test = createTest(function(name, optionsOrFn, optionsOrTest) {
1281
+ if (getCurrentTest()) throw new Error("Calling the test function inside another test function is not allowed. Please put it inside \"describe\" or \"suite\" so it can be properly collected.");
1282
+ getCurrentSuite().test.fn.call(this, formatName(name), optionsOrFn, optionsOrTest);
1283
+ });
1284
+ /**
1285
+ * Creates a suite of tests, allowing for grouping and hierarchical organization of tests.
1286
+ * Suites can contain both tests and other suites, enabling complex test structures.
1287
+ *
1288
+ * @param {string} name - The name of the suite, used for identification and reporting.
1289
+ * @param {Function} fn - A function that defines the tests and suites within this suite.
1290
+ * @example
1291
+ * ```ts
1292
+ * // Define a suite with two tests
1293
+ * describe('Math operations', () => {
1294
+ * test('should add two numbers', () => {
1295
+ * expect(add(1, 2)).toBe(3);
1296
+ * });
1297
+ *
1298
+ * test('should subtract two numbers', () => {
1299
+ * expect(subtract(5, 2)).toBe(3);
1300
+ * });
1301
+ * });
1302
+ * ```
1303
+ * @example
1304
+ * ```ts
1305
+ * // Define nested suites
1306
+ * describe('String operations', () => {
1307
+ * describe('Trimming', () => {
1308
+ * test('should trim whitespace from start and end', () => {
1309
+ * expect(' hello '.trim()).toBe('hello');
1310
+ * });
1311
+ * });
1312
+ *
1313
+ * describe('Concatenation', () => {
1314
+ * test('should concatenate two strings', () => {
1315
+ * expect('hello' + ' ' + 'world').toBe('hello world');
1316
+ * });
1317
+ * });
1318
+ * });
1319
+ * ```
1320
+ */
1321
+ const describe = suite;
1322
+ /**
1323
+ * Defines a test case with a given name and test function. The test function can optionally be configured with test options.
1324
+ *
1325
+ * @param {string | Function} name - The name of the test or a function that will be used as a test name.
1326
+ * @param {TestOptions | TestFunction} [optionsOrFn] - Optional. The test options or the test function if no explicit name is provided.
1327
+ * @param {number | TestOptions | TestFunction} [optionsOrTest] - Optional. The test function or options, depending on the previous parameters.
1328
+ * @throws {Error} If called inside another test function.
1329
+ * @example
1330
+ * ```ts
1331
+ * // Define a simple test
1332
+ * it('adds two numbers', () => {
1333
+ * expect(add(1, 2)).toBe(3);
1334
+ * });
1335
+ * ```
1336
+ * @example
1337
+ * ```ts
1338
+ * // Define a test with options
1339
+ * it('subtracts two numbers', { retry: 3 }, () => {
1340
+ * expect(subtract(5, 2)).toBe(3);
1341
+ * });
1342
+ * ```
1343
+ */
1344
+ const it = test;
1345
+ let runner;
1346
+ let defaultSuite;
1347
+ let currentTestFilepath;
1348
+ function assert(condition, message) {
1349
+ if (!condition) throw new Error(`Vitest failed to find ${message}. One of the following is possible:
1350
+ - "vitest" is imported directly without running "vitest" command
1351
+ - "vitest" is imported inside "globalSetup" (to fix this, use "setupFiles" instead, because "globalSetup" runs in a different context)
1352
+ - "vitest" is imported inside Vite / Vitest config file
1353
+ - Otherwise, it might be a Vitest bug. Please report it to https://github.com/vitest-dev/vitest/issues
1354
+ `);
1355
+ }
1356
+ function getDefaultSuite() {
1357
+ assert(defaultSuite, "the default suite");
1358
+ return defaultSuite;
1359
+ }
1360
+ function getRunner() {
1361
+ assert(runner, "the runner");
1362
+ return runner;
1363
+ }
1364
+ function createDefaultSuite(runner) {
1365
+ const config = runner.config.sequence;
1366
+ const options = {};
1367
+ if (config.concurrent != null) options.concurrent = config.concurrent;
1368
+ const collector = suite("", options, () => {});
1369
+ delete collector.suite;
1370
+ return collector;
1371
+ }
1372
+ function clearCollectorContext(file, currentRunner) {
1373
+ currentTestFilepath = file.filepath;
1374
+ runner = currentRunner;
1375
+ if (!defaultSuite) defaultSuite = createDefaultSuite(currentRunner);
1376
+ defaultSuite.file = file;
1377
+ collectorContext.tasks.length = 0;
1378
+ defaultSuite.clear();
1379
+ collectorContext.currentSuite = defaultSuite;
1380
+ }
1381
+ function getCurrentSuite() {
1382
+ const currentSuite = collectorContext.currentSuite || defaultSuite;
1383
+ assert(currentSuite, "the current suite");
1384
+ return currentSuite;
1385
+ }
1386
+ function createSuiteHooks() {
1387
+ return {
1388
+ beforeAll: [],
1389
+ afterAll: [],
1390
+ beforeEach: [],
1391
+ afterEach: [],
1392
+ aroundEach: [],
1393
+ aroundAll: []
1394
+ };
1395
+ }
1396
+ const POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
1397
+ function parseArguments(optionsOrFn, timeoutOrTest) {
1398
+ if (timeoutOrTest != null && typeof timeoutOrTest === "object") throw new TypeError(`Signature "test(name, fn, { ... })" was deprecated in Vitest 3 and removed in Vitest 4. Please, provide options as a second argument instead.`);
1399
+ let options = {};
1400
+ let fn;
1401
+ if (typeof timeoutOrTest === "number") options = { timeout: timeoutOrTest };
1402
+ else if (typeof optionsOrFn === "object") options = optionsOrFn;
1403
+ if (typeof optionsOrFn === "function") {
1404
+ if (typeof timeoutOrTest === "function") throw new TypeError("Cannot use two functions as arguments. Please use the second argument for options.");
1405
+ fn = optionsOrFn;
1406
+ } else if (typeof timeoutOrTest === "function") fn = timeoutOrTest;
1407
+ return {
1408
+ options,
1409
+ handler: fn
1410
+ };
1411
+ }
1412
+ function createSuiteCollector(name, factory = () => {}, mode, each, suiteOptions) {
1413
+ const tasks = [];
1414
+ let suite;
1415
+ initSuite(true);
1416
+ const task = function(name = "", options = {}) {
1417
+ const currentSuite = collectorContext.currentSuite?.suite;
1418
+ const testTags = unique([...(currentSuite ?? collectorContext.currentSuite?.file)?.tags || [], ...toArray(options.tags)]);
1419
+ const tagsOptions = testTags.map((tag) => {
1420
+ const tagDefinition = runner.config.tags?.find((t) => t.name === tag);
1421
+ if (!tagDefinition && runner.config.strictTags) throw createNoTagsError(runner.config.tags, tag);
1422
+ return tagDefinition;
1423
+ }).filter((r) => r != null).sort((tag1, tag2) => (tag2.priority ?? POSITIVE_INFINITY) - (tag1.priority ?? POSITIVE_INFINITY)).reduce((acc, tag) => {
1424
+ const { name, description, priority, meta, ...options } = tag;
1425
+ Object.assign(acc, options);
1426
+ if (meta) acc.meta = Object.assign(acc.meta ?? Object.create(null), meta);
1427
+ return acc;
1428
+ }, {});
1429
+ const testOwnMeta = options.meta;
1430
+ options = {
1431
+ ...tagsOptions,
1432
+ ...options
1433
+ };
1434
+ const timeout = options.timeout ?? runner.config.testTimeout;
1435
+ const parentMeta = currentSuite?.meta;
1436
+ const tagMeta = tagsOptions.meta;
1437
+ const testMeta = Object.create(null);
1438
+ if (tagMeta) Object.assign(testMeta, tagMeta);
1439
+ if (parentMeta) Object.assign(testMeta, parentMeta);
1440
+ if (testOwnMeta) Object.assign(testMeta, testOwnMeta);
1441
+ const task = {
1442
+ id: "",
1443
+ name,
1444
+ fullName: createTaskName([currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName, name]),
1445
+ fullTestName: createTaskName([currentSuite?.fullTestName, name]),
1446
+ suite: currentSuite,
1447
+ each: options.each,
1448
+ fails: options.fails,
1449
+ context: void 0,
1450
+ type: "test",
1451
+ file: currentSuite?.file ?? collectorContext.currentSuite?.file,
1452
+ timeout,
1453
+ retry: options.retry ?? runner.config.retry,
1454
+ repeats: options.repeats,
1455
+ mode: options.only ? "only" : options.skip ? "skip" : options.todo ? "todo" : "run",
1456
+ meta: testMeta,
1457
+ annotations: [],
1458
+ artifacts: [],
1459
+ tags: testTags
1460
+ };
1461
+ const handler = options.handler;
1462
+ if (task.mode === "run" && !handler) task.mode = "todo";
1463
+ if (options.concurrent ?? (!options.sequential && runner.config.sequence.concurrent)) task.concurrent = true;
1464
+ task.shuffle = suiteOptions?.shuffle;
1465
+ const context = createTestContext(task, runner);
1466
+ Object.defineProperty(task, "context", {
1467
+ value: context,
1468
+ enumerable: false
1469
+ });
1470
+ setTestFixture(context, options.fixtures ?? new TestFixtures());
1471
+ const limit = Error.stackTraceLimit;
1472
+ Error.stackTraceLimit = 10;
1473
+ const stackTraceError = /* @__PURE__ */ new Error("STACK_TRACE_ERROR");
1474
+ Error.stackTraceLimit = limit;
1475
+ if (handler) setFn(task, withTimeout(withCancel(withAwaitAsyncAssertions(withFixtures(handler, { context }), task), task.context.signal), timeout, false, stackTraceError, (_, error) => abortIfTimeout([context], error)));
1476
+ if (runner.config.includeTaskLocation) {
1477
+ const error = stackTraceError.stack;
1478
+ const stack = findTestFileStackTrace(currentTestFilepath, error);
1479
+ if (stack) task.location = {
1480
+ line: stack.line,
1481
+ column: stack.column
1482
+ };
1483
+ }
1484
+ tasks.push(task);
1485
+ return task;
1486
+ };
1487
+ const test = createTest(function(name, optionsOrFn, timeoutOrTest) {
1488
+ let { options, handler } = parseArguments(optionsOrFn, timeoutOrTest);
1489
+ if (typeof suiteOptions === "object") options = Object.assign({}, suiteOptions, options);
1490
+ const concurrent = this.concurrent ?? (!this.sequential && options?.concurrent);
1491
+ if (options.concurrent != null && concurrent != null) options.concurrent = concurrent;
1492
+ const sequential = this.sequential ?? (!this.concurrent && options?.sequential);
1493
+ if (options.sequential != null && sequential != null) options.sequential = sequential;
1494
+ const test = task(formatName(name), {
1495
+ ...this,
1496
+ ...options,
1497
+ handler
1498
+ });
1499
+ test.type = "test";
1500
+ });
1501
+ const collector = {
1502
+ type: "collector",
1503
+ name,
1504
+ mode,
1505
+ suite,
1506
+ options: suiteOptions,
1507
+ test,
1508
+ file: suite.file,
1509
+ tasks,
1510
+ collect,
1511
+ task,
1512
+ clear,
1513
+ on: addHook
1514
+ };
1515
+ function addHook(name, ...fn) {
1516
+ getHooks(suite)[name].push(...fn);
1517
+ }
1518
+ function initSuite(includeLocation) {
1519
+ if (typeof suiteOptions === "number") suiteOptions = { timeout: suiteOptions };
1520
+ const currentSuite = collectorContext.currentSuite?.suite;
1521
+ const parentTask = currentSuite ?? collectorContext.currentSuite?.file;
1522
+ const suiteTags = toArray(suiteOptions?.tags);
1523
+ validateTags(runner.config, suiteTags);
1524
+ suite = {
1525
+ id: "",
1526
+ type: "suite",
1527
+ name,
1528
+ fullName: createTaskName([currentSuite?.fullName ?? collectorContext.currentSuite?.file?.fullName, name]),
1529
+ fullTestName: createTaskName([currentSuite?.fullTestName, name]),
1530
+ suite: currentSuite,
1531
+ mode,
1532
+ each,
1533
+ file: currentSuite?.file ?? collectorContext.currentSuite?.file,
1534
+ shuffle: suiteOptions?.shuffle,
1535
+ tasks: [],
1536
+ meta: suiteOptions?.meta ?? Object.create(null),
1537
+ concurrent: suiteOptions?.concurrent,
1538
+ tags: unique([...parentTask?.tags || [], ...suiteTags])
1539
+ };
1540
+ if (runner && includeLocation && runner.config.includeTaskLocation) {
1541
+ const limit = Error.stackTraceLimit;
1542
+ Error.stackTraceLimit = 15;
1543
+ const error = (/* @__PURE__ */ new Error("stacktrace")).stack;
1544
+ Error.stackTraceLimit = limit;
1545
+ const stack = findTestFileStackTrace(currentTestFilepath, error);
1546
+ if (stack) suite.location = {
1547
+ line: stack.line,
1548
+ column: stack.column
1549
+ };
1550
+ }
1551
+ setHooks(suite, createSuiteHooks());
1552
+ }
1553
+ function clear() {
1554
+ tasks.length = 0;
1555
+ initSuite(false);
1556
+ }
1557
+ async function collect(file) {
1558
+ if (!file) throw new TypeError("File is required to collect tasks.");
1559
+ if (factory) await runWithSuite(collector, () => factory(test));
1560
+ const allChildren = [];
1561
+ for (const i of tasks) allChildren.push(i.type === "collector" ? await i.collect(file) : i);
1562
+ suite.tasks = allChildren;
1563
+ return suite;
1564
+ }
1565
+ collectTask(collector);
1566
+ return collector;
1567
+ }
1568
+ function withAwaitAsyncAssertions(fn, task) {
1569
+ return (async (...args) => {
1570
+ const fnResult = await fn(...args);
1571
+ if (task.promises) {
1572
+ const errors = (await Promise.allSettled(task.promises)).map((r) => r.status === "rejected" ? r.reason : void 0).filter(Boolean);
1573
+ if (errors.length) throw errors;
1574
+ }
1575
+ return fnResult;
1576
+ });
1577
+ }
1578
+ function createSuite() {
1579
+ function suiteFn(name, factoryOrOptions, optionsOrFactory) {
1580
+ if (getCurrentTest()) throw new Error("Calling the suite function inside test function is not allowed. It can be only called at the top level or inside another suite function.");
1581
+ const currentSuite = collectorContext.currentSuite || defaultSuite;
1582
+ let { options, handler: factory } = parseArguments(factoryOrOptions, optionsOrFactory);
1583
+ const isConcurrentSpecified = options.concurrent || this.concurrent || options.sequential === false;
1584
+ const isSequentialSpecified = options.sequential || this.sequential || options.concurrent === false;
1585
+ const { meta: parentMeta, ...parentOptions } = currentSuite?.options || {};
1586
+ options = {
1587
+ ...parentOptions,
1588
+ ...options
1589
+ };
1590
+ const shuffle = this.shuffle ?? options.shuffle ?? currentSuite?.options?.shuffle ?? runner?.config.sequence.shuffle;
1591
+ if (shuffle != null) options.shuffle = shuffle;
1592
+ let mode = this.only ?? options.only ? "only" : this.skip ?? options.skip ? "skip" : this.todo ?? options.todo ? "todo" : "run";
1593
+ if (mode === "run" && !factory) mode = "todo";
1594
+ const isConcurrent = isConcurrentSpecified || options.concurrent && !isSequentialSpecified;
1595
+ const isSequential = isSequentialSpecified || options.sequential && !isConcurrentSpecified;
1596
+ if (isConcurrent != null) options.concurrent = isConcurrent && !isSequential;
1597
+ if (isSequential != null) options.sequential = isSequential && !isConcurrent;
1598
+ if (parentMeta) options.meta = Object.assign(Object.create(null), parentMeta, options.meta);
1599
+ return createSuiteCollector(formatName(name), factory, mode, this.each, options);
1600
+ }
1601
+ suiteFn.each = function(cases, ...args) {
1602
+ const context = getChainableContext(this);
1603
+ const suite = context.withContext();
1604
+ context.setContext("each", true);
1605
+ if (Array.isArray(cases) && args.length) cases = formatTemplateString(cases, args);
1606
+ return (name, optionsOrFn, fnOrOptions) => {
1607
+ const _name = formatName(name);
1608
+ const arrayOnlyCases = cases.every(Array.isArray);
1609
+ const { options, handler } = parseArguments(optionsOrFn, fnOrOptions);
1610
+ const fnFirst = typeof optionsOrFn === "function";
1611
+ cases.forEach((i, idx) => {
1612
+ const items = Array.isArray(i) ? i : [i];
1613
+ if (fnFirst) if (arrayOnlyCases) suite(formatTitle(_name, items, idx), handler ? () => handler(...items) : void 0, options.timeout);
1614
+ else suite(formatTitle(_name, items, idx), handler ? () => handler(i) : void 0, options.timeout);
1615
+ else if (arrayOnlyCases) suite(formatTitle(_name, items, idx), options, handler ? () => handler(...items) : void 0);
1616
+ else suite(formatTitle(_name, items, idx), options, handler ? () => handler(i) : void 0);
1617
+ });
1618
+ context.setContext("each", void 0);
1619
+ };
1620
+ };
1621
+ suiteFn.for = function(cases, ...args) {
1622
+ if (Array.isArray(cases) && args.length) cases = formatTemplateString(cases, args);
1623
+ return (name, optionsOrFn, fnOrOptions) => {
1624
+ const name_ = formatName(name);
1625
+ const { options, handler } = parseArguments(optionsOrFn, fnOrOptions);
1626
+ cases.forEach((item, idx) => {
1627
+ suite(formatTitle(name_, toArray(item), idx), options, handler ? () => handler(item) : void 0);
1628
+ });
1629
+ };
1630
+ };
1631
+ suiteFn.skipIf = (condition) => condition ? suite.skip : suite;
1632
+ suiteFn.runIf = (condition) => condition ? suite : suite.skip;
1633
+ return createChainable([
1634
+ "concurrent",
1635
+ "sequential",
1636
+ "shuffle",
1637
+ "skip",
1638
+ "only",
1639
+ "todo"
1640
+ ], suiteFn);
1641
+ }
1642
+ function createTaskCollector(fn) {
1643
+ const taskFn = fn;
1644
+ taskFn.each = function(cases, ...args) {
1645
+ const context = getChainableContext(this);
1646
+ const test = context.withContext();
1647
+ context.setContext("each", true);
1648
+ if (Array.isArray(cases) && args.length) cases = formatTemplateString(cases, args);
1649
+ return (name, optionsOrFn, fnOrOptions) => {
1650
+ const _name = formatName(name);
1651
+ const arrayOnlyCases = cases.every(Array.isArray);
1652
+ const { options, handler } = parseArguments(optionsOrFn, fnOrOptions);
1653
+ const fnFirst = typeof optionsOrFn === "function";
1654
+ cases.forEach((i, idx) => {
1655
+ const items = Array.isArray(i) ? i : [i];
1656
+ if (fnFirst) if (arrayOnlyCases) test(formatTitle(_name, items, idx), handler ? () => handler(...items) : void 0, options.timeout);
1657
+ else test(formatTitle(_name, items, idx), handler ? () => handler(i) : void 0, options.timeout);
1658
+ else if (arrayOnlyCases) test(formatTitle(_name, items, idx), options, handler ? () => handler(...items) : void 0);
1659
+ else test(formatTitle(_name, items, idx), options, handler ? () => handler(i) : void 0);
1660
+ });
1661
+ context.setContext("each", void 0);
1662
+ };
1663
+ };
1664
+ taskFn.for = function(cases, ...args) {
1665
+ const test = getChainableContext(this).withContext();
1666
+ if (Array.isArray(cases) && args.length) cases = formatTemplateString(cases, args);
1667
+ return (name, optionsOrFn, fnOrOptions) => {
1668
+ const _name = formatName(name);
1669
+ const { options, handler } = parseArguments(optionsOrFn, fnOrOptions);
1670
+ cases.forEach((item, idx) => {
1671
+ const handlerWrapper = handler ? (ctx) => handler(item, ctx) : void 0;
1672
+ if (handlerWrapper) configureProps(handlerWrapper, {
1673
+ index: 1,
1674
+ original: handler
1675
+ });
1676
+ test(formatTitle(_name, toArray(item), idx), options, handlerWrapper);
1677
+ });
1678
+ };
1679
+ };
1680
+ taskFn.skipIf = function(condition) {
1681
+ return condition ? this.skip : this;
1682
+ };
1683
+ taskFn.runIf = function(condition) {
1684
+ return condition ? this : this.skip;
1685
+ };
1686
+ /**
1687
+ * Parse builder pattern arguments into a fixtures object.
1688
+ * Handles both builder pattern (name, options?, value) and object syntax.
1689
+ */
1690
+ function parseBuilderFixtures(fixturesOrName, optionsOrFn, maybeFn) {
1691
+ if (typeof fixturesOrName !== "string") return fixturesOrName;
1692
+ const fixtureName = fixturesOrName;
1693
+ let fixtureOptions;
1694
+ let fixtureValue;
1695
+ if (maybeFn !== void 0) {
1696
+ fixtureOptions = optionsOrFn;
1697
+ fixtureValue = maybeFn;
1698
+ } else if (optionsOrFn !== null && typeof optionsOrFn === "object" && !Array.isArray(optionsOrFn) && TestFixtures.isFixtureOptions(optionsOrFn)) {
1699
+ fixtureOptions = optionsOrFn;
1700
+ fixtureValue = {};
1701
+ } else {
1702
+ fixtureOptions = void 0;
1703
+ fixtureValue = optionsOrFn;
1704
+ }
1705
+ if (typeof fixtureValue === "function") {
1706
+ const builderFn = fixtureValue;
1707
+ const fixture = async (ctx, use) => {
1708
+ let cleanup;
1709
+ const onCleanup = (fn) => {
1710
+ if (cleanup !== void 0) throw new Error("onCleanup can only be called once per fixture. Define separate fixtures if you need multiple cleanup functions.");
1711
+ cleanup = fn;
1712
+ };
1713
+ await use(await builderFn(ctx, { onCleanup }));
1714
+ if (cleanup) await cleanup();
1715
+ };
1716
+ configureProps(fixture, { original: builderFn });
1717
+ if (fixtureOptions) return { [fixtureName]: [fixture, fixtureOptions] };
1718
+ return { [fixtureName]: fixture };
1719
+ }
1720
+ if (fixtureOptions) return { [fixtureName]: [fixtureValue, fixtureOptions] };
1721
+ return { [fixtureName]: fixtureValue };
1722
+ }
1723
+ taskFn.override = function(fixturesOrName, optionsOrFn, maybeFn) {
1724
+ const userFixtures = parseBuilderFixtures(fixturesOrName, optionsOrFn, maybeFn);
1725
+ getChainableContext(this).getFixtures().override(runner, userFixtures);
1726
+ return this;
1727
+ };
1728
+ taskFn.scoped = function(fixtures) {
1729
+ console.warn(`test.scoped() is deprecated and will be removed in future versions. Please use test.override() instead.`);
1730
+ return this.override(fixtures);
1731
+ };
1732
+ taskFn.extend = function(fixturesOrName, optionsOrFn, maybeFn) {
1733
+ const userFixtures = parseBuilderFixtures(fixturesOrName, optionsOrFn, maybeFn);
1734
+ const fixtures = getChainableContext(this).getFixtures().extend(runner, userFixtures);
1735
+ const _test = createTest(function(name, optionsOrFn, optionsOrTest) {
1736
+ fn.call(this, formatName(name), optionsOrFn, optionsOrTest);
1737
+ });
1738
+ getChainableContext(_test).mergeContext({ fixtures });
1739
+ return _test;
1740
+ };
1741
+ taskFn.describe = suite;
1742
+ taskFn.suite = suite;
1743
+ taskFn.beforeEach = beforeEach;
1744
+ taskFn.afterEach = afterEach;
1745
+ taskFn.beforeAll = beforeAll;
1746
+ taskFn.afterAll = afterAll;
1747
+ taskFn.aroundEach = aroundEach;
1748
+ taskFn.aroundAll = aroundAll;
1749
+ return createChainable([
1750
+ "concurrent",
1751
+ "sequential",
1752
+ "skip",
1753
+ "only",
1754
+ "todo",
1755
+ "fails"
1756
+ ], taskFn, { fixtures: new TestFixtures() });
1757
+ }
1758
+ function createTest(fn) {
1759
+ return createTaskCollector(fn);
1760
+ }
1761
+ function formatName(name) {
1762
+ return typeof name === "string" ? name : typeof name === "function" ? name.name || "<anonymous>" : String(name);
1763
+ }
1764
+ function formatTitle(template, items, idx) {
1765
+ if (template.includes("%#") || template.includes("%$")) template = template.replace(/%%/g, "__vitest_escaped_%__").replace(/%#/g, `${idx}`).replace(/%\$/g, `${idx + 1}`).replace(/__vitest_escaped_%__/g, "%%");
1766
+ const count = template.split("%").length - 1;
1767
+ if (template.includes("%f")) (template.match(/%f/g) || []).forEach((_, i) => {
1768
+ if (isNegativeNaN(items[i]) || Object.is(items[i], -0)) {
1769
+ let occurrence = 0;
1770
+ template = template.replace(/%f/g, (match) => {
1771
+ occurrence++;
1772
+ return occurrence === i + 1 ? "-%f" : match;
1773
+ });
1774
+ }
1775
+ });
1776
+ const isObjectItem = isObject(items[0]);
1777
+ function formatAttribute(s) {
1778
+ return s.replace(/\$([$\w.]+)/g, (_, key) => {
1779
+ const isArrayKey = /^\d+$/.test(key);
1780
+ if (!isObjectItem && !isArrayKey) return `$${key}`;
1781
+ const arrayElement = isArrayKey ? objectAttr(items, key) : void 0;
1782
+ return objDisplay(isObjectItem ? objectAttr(items[0], key, arrayElement) : arrayElement, { truncate: runner?.config?.chaiConfig?.truncateThreshold });
1783
+ });
1784
+ }
1785
+ let output = "";
1786
+ let i = 0;
1787
+ handleRegexMatch(template, formatRegExp, (match) => {
1788
+ if (i < count) output += format(match[0], items[i++]);
1789
+ else output += match[0];
1790
+ }, (nonMatch) => {
1791
+ output += formatAttribute(nonMatch);
1792
+ });
1793
+ return output;
1794
+ }
1795
+ function handleRegexMatch(input, regex, onMatch, onNonMatch) {
1796
+ let lastIndex = 0;
1797
+ for (const m of input.matchAll(regex)) {
1798
+ if (lastIndex < m.index) onNonMatch(input.slice(lastIndex, m.index));
1799
+ onMatch(m);
1800
+ lastIndex = m.index + m[0].length;
1801
+ }
1802
+ if (lastIndex < input.length) onNonMatch(input.slice(lastIndex));
1803
+ }
1804
+ function formatTemplateString(cases, args) {
1805
+ const header = cases.join("").trim().replace(/ /g, "").split("\n").map((i) => i.split("|"))[0];
1806
+ const res = [];
1807
+ for (let i = 0; i < Math.floor(args.length / header.length); i++) {
1808
+ const oneCase = {};
1809
+ for (let j = 0; j < header.length; j++) oneCase[header[j]] = args[i * header.length + j];
1810
+ res.push(oneCase);
1811
+ }
1812
+ return res;
1813
+ }
1814
+ const now$2 = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
1815
+ const collectorContext = {
1816
+ tasks: [],
1817
+ currentSuite: null
1818
+ };
1819
+ function collectTask(task) {
1820
+ collectorContext.currentSuite?.tasks.push(task);
1821
+ }
1822
+ async function runWithSuite(suite, fn) {
1823
+ const prev = collectorContext.currentSuite;
1824
+ collectorContext.currentSuite = suite;
1825
+ await fn();
1826
+ collectorContext.currentSuite = prev;
1827
+ }
1828
+ function withTimeout(fn, timeout, isHook = false, stackTraceError, onTimeout) {
1829
+ if (timeout <= 0 || timeout === Number.POSITIVE_INFINITY) return fn;
1830
+ const { setTimeout, clearTimeout } = getSafeTimers();
1831
+ return (function runWithTimeout(...args) {
1832
+ const startTime = now$2();
1833
+ const runner = getRunner();
1834
+ runner._currentTaskStartTime = startTime;
1835
+ runner._currentTaskTimeout = timeout;
1836
+ return new Promise((resolve_, reject_) => {
1837
+ const timer = setTimeout(() => {
1838
+ clearTimeout(timer);
1839
+ rejectTimeoutError();
1840
+ }, timeout);
1841
+ timer.unref?.();
1842
+ function rejectTimeoutError() {
1843
+ const error = makeTimeoutError(isHook, timeout, stackTraceError);
1844
+ onTimeout?.(args, error);
1845
+ reject_(error);
1846
+ }
1847
+ function resolve(result) {
1848
+ runner._currentTaskStartTime = void 0;
1849
+ runner._currentTaskTimeout = void 0;
1850
+ clearTimeout(timer);
1851
+ if (now$2() - startTime >= timeout) {
1852
+ rejectTimeoutError();
1853
+ return;
1854
+ }
1855
+ resolve_(result);
1856
+ }
1857
+ function reject(error) {
1858
+ runner._currentTaskStartTime = void 0;
1859
+ runner._currentTaskTimeout = void 0;
1860
+ clearTimeout(timer);
1861
+ reject_(error);
1862
+ }
1863
+ try {
1864
+ const result = fn(...args);
1865
+ if (typeof result === "object" && result != null && typeof result.then === "function") result.then(resolve, reject);
1866
+ else resolve(result);
1867
+ } catch (error) {
1868
+ reject(error);
1869
+ }
1870
+ });
1871
+ });
1872
+ }
1873
+ function withCancel(fn, signal) {
1874
+ return (function runWithCancel(...args) {
1875
+ return new Promise((resolve, reject) => {
1876
+ signal.addEventListener("abort", () => reject(signal.reason));
1877
+ try {
1878
+ const result = fn(...args);
1879
+ if (typeof result === "object" && result != null && typeof result.then === "function") result.then(resolve, reject);
1880
+ else resolve(result);
1881
+ } catch (error) {
1882
+ reject(error);
1883
+ }
1884
+ });
1885
+ });
1886
+ }
1887
+ const abortControllers = /* @__PURE__ */ new WeakMap();
1888
+ function abortIfTimeout([context], error) {
1889
+ if (context) abortContextSignal(context, error);
1890
+ }
1891
+ function abortContextSignal(context, error) {
1892
+ abortControllers.get(context)?.abort(error);
1893
+ }
1894
+ function createTestContext(test, runner) {
1895
+ const context = function() {
1896
+ throw new Error("done() callback is deprecated, use promise instead");
1897
+ };
1898
+ let abortController = abortControllers.get(context);
1899
+ if (!abortController) {
1900
+ abortController = new AbortController();
1901
+ abortControllers.set(context, abortController);
1902
+ }
1903
+ context.signal = abortController.signal;
1904
+ context.task = test;
1905
+ context.skip = (condition, note) => {
1906
+ if (condition === false) return;
1907
+ test.result ??= { state: "skip" };
1908
+ test.result.pending = true;
1909
+ throw new PendingError("test is skipped; abort execution", test, typeof condition === "string" ? condition : note);
1910
+ };
1911
+ context.annotate = ((message, type, attachment) => {
1912
+ if (test.result && test.result.state !== "run") throw new Error(`Cannot annotate tests outside of the test run. The test "${test.name}" finished running with the "${test.result.state}" state already.`);
1913
+ const annotation = {
1914
+ message,
1915
+ type: typeof type === "object" || type === void 0 ? "notice" : type
1916
+ };
1917
+ const annotationAttachment = typeof type === "object" ? type : attachment;
1918
+ if (annotationAttachment) {
1919
+ annotation.attachment = annotationAttachment;
1920
+ manageArtifactAttachment(annotation.attachment);
1921
+ }
1922
+ return recordAsyncOperation(test, recordArtifact(test, {
1923
+ type: "internal:annotation",
1924
+ annotation
1925
+ }).then(async ({ annotation }) => {
1926
+ if (!runner.onTestAnnotate) throw new Error(`Test runner doesn't support test annotations.`);
1927
+ await finishSendTasksUpdate(runner);
1928
+ const resolvedAnnotation = await runner.onTestAnnotate(test, annotation);
1929
+ test.annotations.push(resolvedAnnotation);
1930
+ return resolvedAnnotation;
1931
+ }));
1932
+ });
1933
+ context.onTestFailed = (handler, timeout) => {
1934
+ test.onFailed ||= [];
1935
+ test.onFailed.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, /* @__PURE__ */ new Error("STACK_TRACE_ERROR"), (_, error) => abortController.abort(error)));
1936
+ };
1937
+ context.onTestFinished = (handler, timeout) => {
1938
+ test.onFinished ||= [];
1939
+ test.onFinished.push(withTimeout(handler, timeout ?? runner.config.hookTimeout, true, /* @__PURE__ */ new Error("STACK_TRACE_ERROR"), (_, error) => abortController.abort(error)));
1940
+ };
1941
+ return runner.extendTaskContext?.(context) || context;
1942
+ }
1943
+ function makeTimeoutError(isHook, timeout, stackTraceError) {
1944
+ const message = `${isHook ? "Hook" : "Test"} timed out in ${timeout}ms.\nIf this is a long-running ${isHook ? "hook" : "test"}, pass a timeout value as the last argument or configure it globally with "${isHook ? "hookTimeout" : "testTimeout"}".`;
1945
+ const error = new Error(message);
1946
+ if (stackTraceError?.stack) error.stack = stackTraceError.stack.replace(error.message, stackTraceError.message);
1947
+ return error;
1948
+ }
1949
+ async function runSetupFiles(config, files, runner) {
1950
+ if (config.sequence.setupFiles === "parallel") await Promise.all(files.map(async (fsPath) => {
1951
+ await runner.importFile(fsPath, "setup");
1952
+ }));
1953
+ else for (const fsPath of files) await runner.importFile(fsPath, "setup");
1954
+ }
1955
+ const now$1 = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
1956
+ async function collectTests(specs, runner) {
1957
+ const files = [];
1958
+ const config = runner.config;
1959
+ const $ = runner.trace;
1960
+ let defaultTagsFilter;
1961
+ for (const spec of specs) {
1962
+ const filepath = typeof spec === "string" ? spec : spec.filepath;
1963
+ await $("collect_spec", { "code.file.path": filepath }, async () => {
1964
+ runner._currentSpecification = typeof spec === "string" ? { filepath: spec } : spec;
1965
+ const testLocations = typeof spec === "string" ? void 0 : spec.testLocations;
1966
+ const testNamePattern = typeof spec === "string" ? void 0 : spec.testNamePattern;
1967
+ const testIds = typeof spec === "string" ? void 0 : spec.testIds;
1968
+ const testTagsFilter = typeof spec === "object" && spec.testTagsFilter ? createTagsFilter(spec.testTagsFilter, config.tags) : void 0;
1969
+ const fileTags = typeof spec === "string" ? [] : spec.fileTags || [];
1970
+ const file = createFileTask(filepath, config.root, config.name, runner.pool, runner.viteEnvironment);
1971
+ file.tags = fileTags;
1972
+ file.shuffle = config.sequence.shuffle;
1973
+ try {
1974
+ validateTags(runner.config, fileTags);
1975
+ runner.onCollectStart?.(file);
1976
+ clearCollectorContext(file, runner);
1977
+ const setupFiles = toArray(config.setupFiles);
1978
+ if (setupFiles.length) {
1979
+ const setupStart = now$1();
1980
+ await runSetupFiles(config, setupFiles, runner);
1981
+ file.setupDuration = now$1() - setupStart;
1982
+ } else file.setupDuration = 0;
1983
+ const collectStart = now$1();
1984
+ await runner.importFile(filepath, "collect");
1985
+ const durations = runner.getImportDurations?.();
1986
+ if (durations) file.importDurations = durations;
1987
+ const defaultTasks = await getDefaultSuite().collect(file);
1988
+ const fileHooks = createSuiteHooks();
1989
+ mergeHooks(fileHooks, getHooks(defaultTasks));
1990
+ for (const c of [...defaultTasks.tasks, ...collectorContext.tasks]) if (c.type === "test" || c.type === "suite") file.tasks.push(c);
1991
+ else if (c.type === "collector") {
1992
+ const suite = await c.collect(file);
1993
+ if (suite.name || suite.tasks.length) {
1994
+ mergeHooks(fileHooks, getHooks(suite));
1995
+ file.tasks.push(suite);
1996
+ }
1997
+ }
1998
+ setHooks(file, fileHooks);
1999
+ file.collectDuration = now$1() - collectStart;
2000
+ } catch (e) {
2001
+ file.result = {
2002
+ state: "fail",
2003
+ errors: e instanceof AggregateError ? e.errors.map((e) => processError(e, runner.config.diffOptions)) : [processError(e, runner.config.diffOptions)]
2004
+ };
2005
+ const durations = runner.getImportDurations?.();
2006
+ if (durations) file.importDurations = durations;
2007
+ }
2008
+ calculateSuiteHash(file);
2009
+ const hasOnlyTasks = someTasksAreOnly(file);
2010
+ if (!testTagsFilter && !defaultTagsFilter && config.tagsFilter) defaultTagsFilter = createTagsFilter(config.tagsFilter, config.tags);
2011
+ interpretTaskModes(file, testNamePattern ?? config.testNamePattern, testLocations, testIds, testTagsFilter ?? defaultTagsFilter, hasOnlyTasks, false, config.allowOnly);
2012
+ if (file.mode === "queued") file.mode = "run";
2013
+ files.push(file);
2014
+ });
2015
+ }
2016
+ return files;
2017
+ }
2018
+ function mergeHooks(baseHooks, hooks) {
2019
+ for (const _key in hooks) {
2020
+ const key = _key;
2021
+ baseHooks[key].push(...hooks[key]);
2022
+ }
2023
+ return baseHooks;
2024
+ }
2025
+ const now = globalThis.performance ? globalThis.performance.now.bind(globalThis.performance) : Date.now;
2026
+ const unixNow = Date.now;
2027
+ const { clearTimeout, setTimeout } = getSafeTimers();
2028
+ let limitMaxConcurrency;
2029
+ /**
2030
+ * Normalizes retry configuration to extract individual values.
2031
+ * Handles both number and object forms.
2032
+ */
2033
+ function getRetryCount(retry) {
2034
+ if (retry === void 0) return 0;
2035
+ if (typeof retry === "number") return retry;
2036
+ return retry.count ?? 0;
2037
+ }
2038
+ function getRetryDelay(retry) {
2039
+ if (retry === void 0) return 0;
2040
+ if (typeof retry === "number") return 0;
2041
+ return retry.delay ?? 0;
2042
+ }
2043
+ function getRetryCondition(retry) {
2044
+ if (retry === void 0) return;
2045
+ if (typeof retry === "number") return;
2046
+ return retry.condition;
2047
+ }
2048
+ function updateSuiteHookState(task, name, state, runner) {
2049
+ if (!task.result) task.result = { state: "run" };
2050
+ if (!task.result.hooks) task.result.hooks = {};
2051
+ const suiteHooks = task.result.hooks;
2052
+ if (suiteHooks) {
2053
+ suiteHooks[name] = state;
2054
+ let event = state === "run" ? "before-hook-start" : "before-hook-end";
2055
+ if (name === "afterAll" || name === "afterEach") event = state === "run" ? "after-hook-start" : "after-hook-end";
2056
+ updateTask(event, task, runner);
2057
+ }
2058
+ }
2059
+ function getSuiteHooks(suite, name, sequence) {
2060
+ const hooks = getHooks(suite)[name];
2061
+ if (sequence === "stack" && (name === "afterAll" || name === "afterEach")) return hooks.slice().reverse();
2062
+ return hooks;
2063
+ }
2064
+ async function callTestHooks(runner, test, hooks, sequence) {
2065
+ if (sequence === "stack") hooks = hooks.slice().reverse();
2066
+ if (!hooks.length) return;
2067
+ const context = test.context;
2068
+ const onTestFailed = test.context.onTestFailed;
2069
+ const onTestFinished = test.context.onTestFinished;
2070
+ context.onTestFailed = () => {
2071
+ throw new Error(`Cannot call "onTestFailed" inside a test hook.`);
2072
+ };
2073
+ context.onTestFinished = () => {
2074
+ throw new Error(`Cannot call "onTestFinished" inside a test hook.`);
2075
+ };
2076
+ if (sequence === "parallel") try {
2077
+ await Promise.all(hooks.map((fn) => limitMaxConcurrency(() => fn(test.context))));
2078
+ } catch (e) {
2079
+ failTask(test.result, e, runner.config.diffOptions);
2080
+ }
2081
+ else for (const fn of hooks) try {
2082
+ await limitMaxConcurrency(() => fn(test.context));
2083
+ } catch (e) {
2084
+ failTask(test.result, e, runner.config.diffOptions);
2085
+ }
2086
+ context.onTestFailed = onTestFailed;
2087
+ context.onTestFinished = onTestFinished;
2088
+ }
2089
+ async function callSuiteHook(suite, currentTask, name, runner, args) {
2090
+ const sequence = runner.config.sequence.hooks;
2091
+ const callbacks = [];
2092
+ const parentSuite = "filepath" in suite ? null : suite.suite || suite.file;
2093
+ if (name === "beforeEach" && parentSuite) callbacks.push(...await callSuiteHook(parentSuite, currentTask, name, runner, args));
2094
+ const hooks = getSuiteHooks(suite, name, sequence);
2095
+ if (hooks.length > 0) updateSuiteHookState(currentTask, name, "run", runner);
2096
+ async function runHook(hook) {
2097
+ return limitMaxConcurrency(async () => {
2098
+ return getBeforeHookCleanupCallback(hook, await hook(...args), name === "beforeEach" ? args[0] : void 0);
2099
+ });
2100
+ }
2101
+ if (sequence === "parallel") callbacks.push(...await Promise.all(hooks.map((hook) => runHook(hook))));
2102
+ else for (const hook of hooks) callbacks.push(await runHook(hook));
2103
+ if (hooks.length > 0) updateSuiteHookState(currentTask, name, "pass", runner);
2104
+ if (name === "afterEach" && parentSuite) callbacks.push(...await callSuiteHook(parentSuite, currentTask, name, runner, args));
2105
+ return callbacks;
2106
+ }
2107
+ function getAroundEachHooks(suite) {
2108
+ const hooks = [];
2109
+ const parentSuite = "filepath" in suite ? null : suite.suite || suite.file;
2110
+ if (parentSuite) hooks.push(...getAroundEachHooks(parentSuite));
2111
+ hooks.push(...getHooks(suite).aroundEach);
2112
+ return hooks;
2113
+ }
2114
+ function getAroundAllHooks(suite) {
2115
+ return getHooks(suite).aroundAll;
2116
+ }
2117
+ function makeAroundHookTimeoutError(hookName, phase, timeout, stackTraceError) {
2118
+ const message = `The ${phase} phase of "${hookName}" hook timed out after ${timeout}ms.`;
2119
+ const error = new (phase === "setup" ? AroundHookSetupError : AroundHookTeardownError)(message);
2120
+ if (stackTraceError?.stack) error.stack = stackTraceError.stack.replace(stackTraceError.message, error.message);
2121
+ return error;
2122
+ }
2123
+ async function callAroundHooks(runInner, options) {
2124
+ const { hooks, hookName, callbackName, onTimeout, invokeHook } = options;
2125
+ if (!hooks.length) {
2126
+ await runInner();
2127
+ return;
2128
+ }
2129
+ const hookErrors = [];
2130
+ const createTimeoutPromise = (timeout, phase, stackTraceError) => {
2131
+ let timer;
2132
+ let timedout = false;
2133
+ const promise = new Promise((_, reject) => {
2134
+ if (timeout > 0 && timeout !== Number.POSITIVE_INFINITY) {
2135
+ timer = setTimeout(() => {
2136
+ timedout = true;
2137
+ const error = makeAroundHookTimeoutError(hookName, phase, timeout, stackTraceError);
2138
+ onTimeout?.(error);
2139
+ reject(error);
2140
+ }, timeout);
2141
+ timer.unref?.();
2142
+ }
2143
+ });
2144
+ const clear = () => {
2145
+ if (timer) {
2146
+ clearTimeout(timer);
2147
+ timer = void 0;
2148
+ }
2149
+ };
2150
+ return {
2151
+ promise,
2152
+ clear,
2153
+ isTimedOut: () => timedout
2154
+ };
2155
+ };
2156
+ const runNextHook = async (index) => {
2157
+ if (index >= hooks.length) return runInner();
2158
+ const hook = hooks[index];
2159
+ const timeout = getAroundHookTimeout(hook);
2160
+ const stackTraceError = getAroundHookStackTrace(hook);
2161
+ let useCalled = false;
2162
+ let setupTimeout;
2163
+ let teardownTimeout;
2164
+ let setupLimitConcurrencyRelease;
2165
+ let teardownLimitConcurrencyRelease;
2166
+ let resolveUseCalled;
2167
+ const useCalledPromise = new Promise((resolve) => {
2168
+ resolveUseCalled = resolve;
2169
+ });
2170
+ let resolveUseReturned;
2171
+ const useReturnedPromise = new Promise((resolve) => {
2172
+ resolveUseReturned = resolve;
2173
+ });
2174
+ let resolveHookComplete;
2175
+ let rejectHookComplete;
2176
+ const hookCompletePromise = new Promise((resolve, reject) => {
2177
+ resolveHookComplete = resolve;
2178
+ rejectHookComplete = reject;
2179
+ });
2180
+ const use = async () => {
2181
+ if (setupTimeout.isTimedOut()) throw new Error("__VITEST_INTERNAL_AROUND_HOOK_ABORT__");
2182
+ if (useCalled) throw new AroundHookMultipleCallsError(`The \`${callbackName}\` callback was called multiple times in the \`${hookName}\` hook. The callback can only be called once per hook.`);
2183
+ useCalled = true;
2184
+ resolveUseCalled();
2185
+ setupTimeout.clear();
2186
+ setupLimitConcurrencyRelease?.();
2187
+ await runNextHook(index + 1).catch((e) => hookErrors.push(e));
2188
+ teardownLimitConcurrencyRelease = await limitMaxConcurrency.acquire();
2189
+ teardownTimeout = createTimeoutPromise(timeout, "teardown", stackTraceError);
2190
+ resolveUseReturned();
2191
+ };
2192
+ setupLimitConcurrencyRelease = await limitMaxConcurrency.acquire();
2193
+ setupTimeout = createTimeoutPromise(timeout, "setup", stackTraceError);
2194
+ (async () => {
2195
+ try {
2196
+ await invokeHook(hook, use);
2197
+ if (!useCalled) throw new AroundHookSetupError(`The \`${callbackName}\` callback was not called in the \`${hookName}\` hook. Make sure to call \`${callbackName}\` to run the ${hookName === "aroundEach" ? "test" : "suite"}.`);
2198
+ resolveHookComplete();
2199
+ } catch (error) {
2200
+ rejectHookComplete(error);
2201
+ } finally {
2202
+ setupLimitConcurrencyRelease?.();
2203
+ teardownLimitConcurrencyRelease?.();
2204
+ }
2205
+ })();
2206
+ try {
2207
+ await Promise.race([
2208
+ useCalledPromise,
2209
+ hookCompletePromise,
2210
+ setupTimeout.promise
2211
+ ]);
2212
+ } finally {
2213
+ setupLimitConcurrencyRelease?.();
2214
+ setupTimeout.clear();
2215
+ }
2216
+ await Promise.race([useReturnedPromise, hookCompletePromise]);
2217
+ try {
2218
+ await Promise.race([hookCompletePromise, teardownTimeout?.promise]);
2219
+ } finally {
2220
+ teardownLimitConcurrencyRelease?.();
2221
+ teardownTimeout?.clear();
2222
+ }
2223
+ };
2224
+ await runNextHook(0).catch((e) => hookErrors.push(e));
2225
+ if (hookErrors.length > 0) throw hookErrors;
2226
+ }
2227
+ async function callAroundAllHooks(suite, runSuiteInner) {
2228
+ await callAroundHooks(runSuiteInner, {
2229
+ hooks: getAroundAllHooks(suite),
2230
+ hookName: "aroundAll",
2231
+ callbackName: "runSuite()",
2232
+ invokeHook: (hook, use) => hook(use, suite)
2233
+ });
2234
+ }
2235
+ async function callAroundEachHooks(suite, test, runTest) {
2236
+ await callAroundHooks(() => runTest(getFixtureCleanupCount(test.context)), {
2237
+ hooks: getAroundEachHooks(suite),
2238
+ hookName: "aroundEach",
2239
+ callbackName: "runTest()",
2240
+ onTimeout: (error) => abortContextSignal(test.context, error),
2241
+ invokeHook: (hook, use) => hook(use, test.context, suite)
2242
+ });
2243
+ }
2244
+ const packs = /* @__PURE__ */ new Map();
2245
+ const eventsPacks = [];
2246
+ const pendingTasksUpdates = [];
2247
+ function sendTasksUpdate(runner) {
2248
+ if (packs.size) {
2249
+ const taskPacks = Array.from(packs).map(([id, task]) => {
2250
+ return [
2251
+ id,
2252
+ task[0],
2253
+ task[1]
2254
+ ];
2255
+ });
2256
+ const p = runner.onTaskUpdate?.(taskPacks, eventsPacks);
2257
+ if (p) {
2258
+ pendingTasksUpdates.push(p);
2259
+ p.then(() => pendingTasksUpdates.splice(pendingTasksUpdates.indexOf(p), 1), () => {});
2260
+ }
2261
+ eventsPacks.length = 0;
2262
+ packs.clear();
2263
+ }
2264
+ }
2265
+ async function finishSendTasksUpdate(runner) {
2266
+ sendTasksUpdate(runner);
2267
+ await Promise.all(pendingTasksUpdates);
2268
+ }
2269
+ function throttle(fn, ms) {
2270
+ let last = 0;
2271
+ let pendingCall;
2272
+ return function call(...args) {
2273
+ const now = unixNow();
2274
+ if (now - last > ms) {
2275
+ last = now;
2276
+ clearTimeout(pendingCall);
2277
+ pendingCall = void 0;
2278
+ return fn.apply(this, args);
2279
+ }
2280
+ pendingCall ??= setTimeout(() => call.bind(this)(...args), ms);
2281
+ };
2282
+ }
2283
+ const sendTasksUpdateThrottled = throttle(sendTasksUpdate, 100);
2284
+ function updateTask(event, task, runner) {
2285
+ eventsPacks.push([
2286
+ task.id,
2287
+ event,
2288
+ void 0
2289
+ ]);
2290
+ packs.set(task.id, [task.result, task.meta]);
2291
+ sendTasksUpdateThrottled(runner);
2292
+ }
2293
+ async function callCleanupHooks(runner, cleanups) {
2294
+ const sequence = runner.config.sequence.hooks;
2295
+ if (sequence === "stack") cleanups = cleanups.slice().reverse();
2296
+ if (sequence === "parallel") await Promise.all(cleanups.map(async (fn) => {
2297
+ if (typeof fn !== "function") return;
2298
+ await limitMaxConcurrency(() => fn());
2299
+ }));
2300
+ else for (const fn of cleanups) {
2301
+ if (typeof fn !== "function") continue;
2302
+ await limitMaxConcurrency(() => fn());
2303
+ }
2304
+ }
2305
+ /**
2306
+ * Determines if a test should be retried based on its retryCondition configuration
2307
+ */
2308
+ function passesRetryCondition(test, errors) {
2309
+ const condition = getRetryCondition(test.retry);
2310
+ if (!errors || errors.length === 0) return false;
2311
+ if (!condition) return true;
2312
+ const error = errors[errors.length - 1];
2313
+ if (condition instanceof RegExp) return condition.test(error.message || "");
2314
+ else if (typeof condition === "function") return condition(error);
2315
+ return false;
2316
+ }
2317
+ async function runTest(test, runner) {
2318
+ await runner.onBeforeRunTask?.(test);
2319
+ if (test.mode !== "run" && test.mode !== "queued") {
2320
+ updateTask("test-prepare", test, runner);
2321
+ updateTask("test-finished", test, runner);
2322
+ return;
2323
+ }
2324
+ if (test.result?.state === "fail") {
2325
+ updateTask("test-failed-early", test, runner);
2326
+ return;
2327
+ }
2328
+ const start = now();
2329
+ test.result = {
2330
+ state: "run",
2331
+ startTime: unixNow(),
2332
+ retryCount: 0
2333
+ };
2334
+ updateTask("test-prepare", test, runner);
2335
+ const cleanupRunningTest = addRunningTest(test);
2336
+ setCurrentTest(test);
2337
+ const suite = test.suite || test.file;
2338
+ const $ = runner.trace;
2339
+ const repeats = test.repeats ?? 0;
2340
+ for (let repeatCount = 0; repeatCount <= repeats; repeatCount++) {
2341
+ const retry = getRetryCount(test.retry);
2342
+ for (let retryCount = 0; retryCount <= retry; retryCount++) {
2343
+ let beforeEachCleanups = [];
2344
+ await callAroundEachHooks(suite, test, async (fixtureCheckpoint) => {
2345
+ try {
2346
+ await runner.onBeforeTryTask?.(test, {
2347
+ retry: retryCount,
2348
+ repeats: repeatCount
2349
+ });
2350
+ test.result.repeatCount = repeatCount;
2351
+ beforeEachCleanups = await $("test.beforeEach", () => callSuiteHook(suite, test, "beforeEach", runner, [test.context, suite]));
2352
+ if (runner.runTask) await $("test.callback", () => limitMaxConcurrency(() => runner.runTask(test)));
2353
+ else {
2354
+ const fn = getFn(test);
2355
+ if (!fn) throw new Error("Test function is not found. Did you add it using `setFn`?");
2356
+ await $("test.callback", () => limitMaxConcurrency(() => fn()));
2357
+ }
2358
+ await runner.onAfterTryTask?.(test, {
2359
+ retry: retryCount,
2360
+ repeats: repeatCount
2361
+ });
2362
+ if (test.result.state !== "fail") test.result.state = "pass";
2363
+ } catch (e) {
2364
+ failTask(test.result, e, runner.config.diffOptions);
2365
+ }
2366
+ try {
2367
+ await runner.onTaskFinished?.(test);
2368
+ } catch (e) {
2369
+ failTask(test.result, e, runner.config.diffOptions);
2370
+ }
2371
+ try {
2372
+ await $("test.afterEach", () => callSuiteHook(suite, test, "afterEach", runner, [test.context, suite]));
2373
+ if (beforeEachCleanups.length) await $("test.cleanup", () => callCleanupHooks(runner, beforeEachCleanups));
2374
+ await callFixtureCleanupFrom(test.context, fixtureCheckpoint);
2375
+ } catch (e) {
2376
+ failTask(test.result, e, runner.config.diffOptions);
2377
+ }
2378
+ if (test.onFinished?.length) await $("test.onFinished", () => callTestHooks(runner, test, test.onFinished, "stack"));
2379
+ if (test.result.state === "fail" && test.onFailed?.length) await $("test.onFailed", () => callTestHooks(runner, test, test.onFailed, runner.config.sequence.hooks));
2380
+ test.onFailed = void 0;
2381
+ test.onFinished = void 0;
2382
+ await runner.onAfterRetryTask?.(test, {
2383
+ retry: retryCount,
2384
+ repeats: repeatCount
2385
+ });
2386
+ }).catch((error) => {
2387
+ failTask(test.result, error, runner.config.diffOptions);
2388
+ });
2389
+ try {
2390
+ await callFixtureCleanup(test.context);
2391
+ } catch (e) {
2392
+ failTask(test.result, e, runner.config.diffOptions);
2393
+ }
2394
+ if (test.result?.pending || test.result?.state === "skip") {
2395
+ test.mode = "skip";
2396
+ test.result = {
2397
+ state: "skip",
2398
+ note: test.result?.note,
2399
+ pending: true,
2400
+ duration: now() - start
2401
+ };
2402
+ updateTask("test-finished", test, runner);
2403
+ setCurrentTest(void 0);
2404
+ cleanupRunningTest();
2405
+ return;
2406
+ }
2407
+ if (test.result.state === "pass") break;
2408
+ if (retryCount < retry) {
2409
+ if (!passesRetryCondition(test, test.result.errors)) break;
2410
+ test.result.state = "run";
2411
+ test.result.retryCount = (test.result.retryCount ?? 0) + 1;
2412
+ const delay = getRetryDelay(test.retry);
2413
+ if (delay > 0) await new Promise((resolve) => setTimeout(resolve, delay));
2414
+ }
2415
+ updateTask("test-retried", test, runner);
2416
+ }
2417
+ }
2418
+ if (test.fails) if (test.result.state === "pass") {
2419
+ const error = processError(/* @__PURE__ */ new Error("Expect test to fail"));
2420
+ test.result.state = "fail";
2421
+ test.result.errors = [error];
2422
+ } else {
2423
+ test.result.state = "pass";
2424
+ test.result.errors = void 0;
2425
+ }
2426
+ cleanupRunningTest();
2427
+ setCurrentTest(void 0);
2428
+ test.result.duration = now() - start;
2429
+ await runner.onAfterRunTask?.(test);
2430
+ updateTask("test-finished", test, runner);
2431
+ }
2432
+ function failTask(result, err, diffOptions) {
2433
+ if (err instanceof PendingError) {
2434
+ result.state = "skip";
2435
+ result.note = err.note;
2436
+ result.pending = true;
2437
+ return;
2438
+ }
2439
+ if (err instanceof TestRunAbortError) {
2440
+ result.state = "skip";
2441
+ result.note = err.message;
2442
+ return;
2443
+ }
2444
+ result.state = "fail";
2445
+ const errors = Array.isArray(err) ? err : [err];
2446
+ for (const e of errors) {
2447
+ const errors = e instanceof AggregateError ? e.errors.map((e) => processError(e, diffOptions)) : [processError(e, diffOptions)];
2448
+ result.errors ??= [];
2449
+ result.errors.push(...errors);
2450
+ }
2451
+ }
2452
+ function markTasksAsSkipped(suite, runner) {
2453
+ suite.tasks.forEach((t) => {
2454
+ t.mode = "skip";
2455
+ t.result = {
2456
+ ...t.result,
2457
+ state: "skip"
2458
+ };
2459
+ updateTask("test-finished", t, runner);
2460
+ if (t.type === "suite") markTasksAsSkipped(t, runner);
2461
+ });
2462
+ }
2463
+ function markPendingTasksAsSkipped(suite, runner, note) {
2464
+ suite.tasks.forEach((t) => {
2465
+ if (!t.result || t.result.state === "run") {
2466
+ t.mode = "skip";
2467
+ t.result = {
2468
+ ...t.result,
2469
+ state: "skip",
2470
+ note
2471
+ };
2472
+ updateTask("test-cancel", t, runner);
2473
+ }
2474
+ if (t.type === "suite") markPendingTasksAsSkipped(t, runner, note);
2475
+ });
2476
+ }
2477
+ async function runSuite(suite, runner) {
2478
+ await runner.onBeforeRunSuite?.(suite);
2479
+ if (suite.result?.state === "fail") {
2480
+ markTasksAsSkipped(suite, runner);
2481
+ updateTask("suite-failed-early", suite, runner);
2482
+ return;
2483
+ }
2484
+ const start = now();
2485
+ const mode = suite.mode;
2486
+ suite.result = {
2487
+ state: mode === "skip" || mode === "todo" ? mode : "run",
2488
+ startTime: unixNow()
2489
+ };
2490
+ const $ = runner.trace;
2491
+ updateTask("suite-prepare", suite, runner);
2492
+ let beforeAllCleanups = [];
2493
+ if (suite.mode === "skip") {
2494
+ suite.result.state = "skip";
2495
+ updateTask("suite-finished", suite, runner);
2496
+ } else if (suite.mode === "todo") {
2497
+ suite.result.state = "todo";
2498
+ updateTask("suite-finished", suite, runner);
2499
+ } else {
2500
+ let suiteRan = false;
2501
+ try {
2502
+ await callAroundAllHooks(suite, async () => {
2503
+ suiteRan = true;
2504
+ try {
2505
+ try {
2506
+ beforeAllCleanups = await $("suite.beforeAll", () => callSuiteHook(suite, suite, "beforeAll", runner, [suite]));
2507
+ } catch (e) {
2508
+ failTask(suite.result, e, runner.config.diffOptions);
2509
+ markTasksAsSkipped(suite, runner);
2510
+ return;
2511
+ }
2512
+ if (runner.runSuite) await runner.runSuite(suite);
2513
+ else for (let tasksGroup of partitionSuiteChildren(suite)) if (tasksGroup[0].concurrent === true) {
2514
+ const groupLimiter = limitConcurrency(runner.config.maxConcurrency);
2515
+ await Promise.all(tasksGroup.map((c) => groupLimiter(() => runSuiteChild(c, runner))));
2516
+ } else {
2517
+ const { sequence } = runner.config;
2518
+ if (suite.shuffle) tasksGroup = shuffle([tasksGroup.filter((group) => group.type === "suite"), tasksGroup.filter((group) => group.type === "test")], sequence.seed).flatMap((group) => shuffle(group, sequence.seed));
2519
+ for (const c of tasksGroup) await runSuiteChild(c, runner);
2520
+ }
2521
+ } finally {
2522
+ try {
2523
+ await $("suite.afterAll", () => callSuiteHook(suite, suite, "afterAll", runner, [suite]));
2524
+ if (beforeAllCleanups.length) await $("suite.cleanup", () => callCleanupHooks(runner, beforeAllCleanups));
2525
+ if (suite.file === suite) {
2526
+ const contexts = TestFixtures.getFileContexts(suite.file);
2527
+ await Promise.all(contexts.map((context) => callFixtureCleanup(context)));
2528
+ }
2529
+ } catch (e) {
2530
+ failTask(suite.result, e, runner.config.diffOptions);
2531
+ }
2532
+ }
2533
+ });
2534
+ } catch (e) {
2535
+ if (!suiteRan) markTasksAsSkipped(suite, runner);
2536
+ failTask(suite.result, e, runner.config.diffOptions);
2537
+ }
2538
+ if (suite.mode === "run" || suite.mode === "queued") if (!runner.config.passWithNoTests && !hasTests(suite)) {
2539
+ suite.result.state = "fail";
2540
+ if (!suite.result.errors?.length) {
2541
+ const error = processError(/* @__PURE__ */ new Error(`No test found in suite ${suite.name}`));
2542
+ suite.result.errors = [error];
2543
+ }
2544
+ } else if (hasFailed(suite)) suite.result.state = "fail";
2545
+ else suite.result.state = "pass";
2546
+ suite.result.duration = now() - start;
2547
+ await runner.onAfterRunSuite?.(suite);
2548
+ updateTask("suite-finished", suite, runner);
2549
+ }
2550
+ }
2551
+ async function runSuiteChild(c, runner) {
2552
+ const $ = runner.trace;
2553
+ if (c.type === "test") return $("run.test", {
2554
+ "vitest.test.id": c.id,
2555
+ "vitest.test.name": c.name,
2556
+ "vitest.test.mode": c.mode,
2557
+ "vitest.test.timeout": c.timeout,
2558
+ "code.file.path": c.file.filepath,
2559
+ "code.line.number": c.location?.line,
2560
+ "code.column.number": c.location?.column
2561
+ }, () => runTest(c, runner));
2562
+ else if (c.type === "suite") return $("run.suite", {
2563
+ "vitest.suite.id": c.id,
2564
+ "vitest.suite.name": c.name,
2565
+ "vitest.suite.mode": c.mode,
2566
+ "code.file.path": c.file.filepath,
2567
+ "code.line.number": c.location?.line,
2568
+ "code.column.number": c.location?.column
2569
+ }, () => runSuite(c, runner));
2570
+ }
2571
+ async function runFiles(files, runner) {
2572
+ limitMaxConcurrency ??= limitConcurrency(runner.config.maxConcurrency);
2573
+ for (const file of files) {
2574
+ if (!file.tasks.length && !runner.config.passWithNoTests) {
2575
+ if (!file.result?.errors?.length) file.result = {
2576
+ state: "fail",
2577
+ errors: [processError(/* @__PURE__ */ new Error(`No test suite found in file ${file.filepath}`))]
2578
+ };
2579
+ }
2580
+ await runner.trace("run.spec", {
2581
+ "code.file.path": file.filepath,
2582
+ "vitest.suite.tasks.length": file.tasks.length
2583
+ }, () => runSuite(file, runner));
2584
+ }
2585
+ }
2586
+ const workerRunners = /* @__PURE__ */ new WeakSet();
2587
+ function defaultTrace(_, attributes, cb) {
2588
+ if (typeof attributes === "function") return attributes();
2589
+ return cb();
2590
+ }
2591
+ async function startTests(specs, runner) {
2592
+ runner.trace ??= defaultTrace;
2593
+ const cancel = runner.cancel?.bind(runner);
2594
+ runner.cancel = (reason) => {
2595
+ const error = new TestRunAbortError("The test run was aborted by the user.", reason);
2596
+ getRunningTests().forEach((test) => {
2597
+ abortContextSignal(test.context, error);
2598
+ markPendingTasksAsSkipped(test.file, runner, error.message);
2599
+ });
2600
+ return cancel?.(reason);
2601
+ };
2602
+ if (!workerRunners.has(runner)) {
2603
+ runner.onCleanupWorkerContext?.(async () => {
2604
+ await Promise.all([...TestFixtures.getWorkerContexts()].map((context) => callFixtureCleanup(context))).finally(() => {
2605
+ TestFixtures.clearDefinitions();
2606
+ });
2607
+ });
2608
+ workerRunners.add(runner);
2609
+ }
2610
+ try {
2611
+ const paths = specs.map((f) => typeof f === "string" ? f : f.filepath);
2612
+ await runner.onBeforeCollect?.(paths);
2613
+ const files = await collectTests(specs, runner);
2614
+ await runner.onCollected?.(files);
2615
+ await runner.onBeforeRunFiles?.(files);
2616
+ await runFiles(files, runner);
2617
+ await runner.onAfterRunFiles?.(files);
2618
+ await finishSendTasksUpdate(runner);
2619
+ return files;
2620
+ } finally {
2621
+ runner.cancel = cancel;
2622
+ }
2623
+ }
2624
+ async function publicCollect(specs, runner) {
2625
+ runner.trace ??= defaultTrace;
2626
+ const paths = specs.map((f) => typeof f === "string" ? f : f.filepath);
2627
+ await runner.onBeforeCollect?.(paths);
2628
+ const files = await collectTests(specs, runner);
2629
+ await runner.onCollected?.(files);
2630
+ return files;
2631
+ }
2632
+ /**
2633
+ * @experimental
2634
+ * @advanced
2635
+ *
2636
+ * Records a custom test artifact during test execution.
2637
+ *
2638
+ * This function allows you to attach structured data, files, or metadata to a test.
2639
+ *
2640
+ * Vitest automatically injects the source location where the artifact was created and manages any attachments you include.
2641
+ *
2642
+ * **Note:** artifacts must be recorded before the task is reported. Any artifacts recorded after that will not be included in the task.
2643
+ *
2644
+ * @param task - The test task context, typically accessed via `this.task` in custom matchers or `context.task` in tests
2645
+ * @param artifact - The artifact to record. Must extend {@linkcode TestArtifactBase}
2646
+ *
2647
+ * @returns A promise that resolves to the recorded artifact with location injected
2648
+ *
2649
+ * @throws {Error} If the test runner doesn't support artifacts
2650
+ *
2651
+ * @example
2652
+ * ```ts
2653
+ * // In a custom assertion
2654
+ * async function toHaveValidSchema(this: MatcherState, actual: unknown) {
2655
+ * const validation = validateSchema(actual)
2656
+ *
2657
+ * await recordArtifact(this.task, {
2658
+ * type: 'my-plugin:schema-validation',
2659
+ * passed: validation.valid,
2660
+ * errors: validation.errors,
2661
+ * })
2662
+ *
2663
+ * return { pass: validation.valid, message: () => '...' }
2664
+ * }
2665
+ * ```
2666
+ */
2667
+ async function recordArtifact(task, artifact) {
2668
+ const runner = getRunner();
2669
+ const stack = findTestFileStackTrace(task.file.filepath, (/* @__PURE__ */ new Error("STACK_TRACE")).stack);
2670
+ if (stack) {
2671
+ artifact.location = {
2672
+ file: stack.file,
2673
+ line: stack.line,
2674
+ column: stack.column
2675
+ };
2676
+ if (artifact.type === "internal:annotation") artifact.annotation.location = artifact.location;
2677
+ }
2678
+ if (Array.isArray(artifact.attachments)) for (const attachment of artifact.attachments) manageArtifactAttachment(attachment);
2679
+ if (artifact.type === "internal:annotation") return artifact;
2680
+ if (!runner.onTestArtifactRecord) throw new Error(`Test runner doesn't support test artifacts.`);
2681
+ await finishSendTasksUpdate(runner);
2682
+ const resolvedArtifact = await runner.onTestArtifactRecord(task, artifact);
2683
+ task.artifacts.push(resolvedArtifact);
2684
+ return resolvedArtifact;
2685
+ }
2686
+ const table = [];
2687
+ for (let i = 65; i < 91; i++) table.push(String.fromCharCode(i));
2688
+ for (let i = 97; i < 123; i++) table.push(String.fromCharCode(i));
2689
+ for (let i = 0; i < 10; i++) table.push(i.toString(10));
2690
+ table.push("+", "/");
2691
+ function encodeUint8Array(bytes) {
2692
+ let base64 = "";
2693
+ const len = bytes.byteLength;
2694
+ for (let i = 0; i < len; i += 3) if (len === i + 1) {
2695
+ const a = (bytes[i] & 252) >> 2;
2696
+ const b = (bytes[i] & 3) << 4;
2697
+ base64 += table[a];
2698
+ base64 += table[b];
2699
+ base64 += "==";
2700
+ } else if (len === i + 2) {
2701
+ const a = (bytes[i] & 252) >> 2;
2702
+ const b = (bytes[i] & 3) << 4 | (bytes[i + 1] & 240) >> 4;
2703
+ const c = (bytes[i + 1] & 15) << 2;
2704
+ base64 += table[a];
2705
+ base64 += table[b];
2706
+ base64 += table[c];
2707
+ base64 += "=";
2708
+ } else {
2709
+ const a = (bytes[i] & 252) >> 2;
2710
+ const b = (bytes[i] & 3) << 4 | (bytes[i + 1] & 240) >> 4;
2711
+ const c = (bytes[i + 1] & 15) << 2 | (bytes[i + 2] & 192) >> 6;
2712
+ const d = bytes[i + 2] & 63;
2713
+ base64 += table[a];
2714
+ base64 += table[b];
2715
+ base64 += table[c];
2716
+ base64 += table[d];
2717
+ }
2718
+ return base64;
2719
+ }
2720
+ /**
2721
+ * Records an async operation associated with a test task.
2722
+ *
2723
+ * This function tracks promises that should be awaited before a test completes.
2724
+ * The promise is automatically removed from the test's promise list once it settles.
2725
+ */
2726
+ function recordAsyncOperation(test, promise) {
2727
+ promise = promise.finally(() => {
2728
+ if (!test.promises) return;
2729
+ const index = test.promises.indexOf(promise);
2730
+ if (index !== -1) test.promises.splice(index, 1);
2731
+ });
2732
+ if (!test.promises) test.promises = [];
2733
+ test.promises.push(promise);
2734
+ return promise;
2735
+ }
2736
+ /**
2737
+ * Validates and prepares a test attachment for serialization.
2738
+ *
2739
+ * This function ensures attachments have either `body` or `path` set (but not both), and converts `Uint8Array` bodies to base64-encoded strings for easier serialization.
2740
+ *
2741
+ * @param attachment - The attachment to validate and prepare
2742
+ *
2743
+ * @throws {TypeError} If neither `body` nor `path` is provided
2744
+ * @throws {TypeError} If both `body` and `path` are provided
2745
+ */
2746
+ function manageArtifactAttachment(attachment) {
2747
+ if (attachment.body == null && !attachment.path) throw new TypeError(`Test attachment requires "body" or "path" to be set. Both are missing.`);
2748
+ if (attachment.body && attachment.path) throw new TypeError(`Test attachment requires only one of "body" or "path" to be set. Both are specified.`);
2749
+ if (attachment.path && attachment.bodyEncoding) throw new TypeError(`Test attachment with "path" should not have "bodyEncoding" specified.`);
2750
+ if (attachment.body instanceof Uint8Array) attachment.body = encodeUint8Array(attachment.body);
2751
+ if (attachment.body != null) attachment.bodyEncoding ??= "base64";
2752
+ }
2753
+ //#endregion
2754
+ export { createTagsFilter as A, createTaskName as B, findTestFileStackTrace as C, generateFileHash as D, generateHash as E, getFullName as F, getNames as G, getSuites as H, getTasks as I, getTestName as J, getTests as K, hasFailed as L, hasTests as M, interpretTaskModes as N, isTestCase as O, limitConcurrency as P, matchesTags as Q, partitionSuiteChildren as R, someTasksAreOnly as S, validateTags as T, afterAll as a, afterEach as b, aroundAll as c, aroundEach as d, beforeAll as e, beforeEach as f, createTaskCollector as g, describe as h, getCurrentSuite as i, getCurrentTest as j, getFn as k, getHooks as l, it as m, onTestFinished as n, onTestFailed as o, publicCollect as p, setHooks as q, recordArtifact as r, setFn as s, startTests as t, suite as u, test as v, updateTask as w, calculateSuiteHash as x, createChainable as y, createFileTask as z };
2755
+
2756
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2h1bmstYXJ0aWZhY3QuanMiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzLy5wbnBtL0B2aXRlc3QrcnVubmVyQDQuMS4xMC9ub2RlX21vZHVsZXMvQHZpdGVzdC9ydW5uZXIvZGlzdC9jaHVuay1hcnRpZmFjdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwcm9jZXNzRXJyb3IgfSBmcm9tICdAdml0ZXN0L3V0aWxzL2Vycm9yJztcbmltcG9ydCB7IGlzT2JqZWN0LCBmaWx0ZXJPdXRDb21tZW50cywgb3JkaW5hbCwgY3JlYXRlRGVmZXIsIGFzc2VydFR5cGVzLCB0b0FycmF5LCBpc05lZ2F0aXZlTmFOLCB1bmlxdWUsIG9iamVjdEF0dHIsIHNodWZmbGUgfSBmcm9tICdAdml0ZXN0L3V0aWxzL2hlbHBlcnMnO1xuaW1wb3J0IHsgZ2V0U2FmZVRpbWVycyB9IGZyb20gJ0B2aXRlc3QvdXRpbHMvdGltZXJzJztcbmltcG9ydCB7IGZvcm1hdCwgZm9ybWF0UmVnRXhwLCBvYmpEaXNwbGF5IH0gZnJvbSAnQHZpdGVzdC91dGlscy9kaXNwbGF5JztcbmltcG9ydCB7IHBhcnNlU2luZ2xlU3RhY2sgfSBmcm9tICdAdml0ZXN0L3V0aWxzL3NvdXJjZS1tYXAnO1xuaW1wb3J0IHsgcmVsYXRpdmUgfSBmcm9tICdwYXRoZSc7XG5cbmNsYXNzIFBlbmRpbmdFcnJvciBleHRlbmRzIEVycm9yIHtcblx0Y29kZSA9IFwiVklURVNUX1BFTkRJTkdcIjtcblx0dGFza0lkO1xuXHRjb25zdHJ1Y3RvcihtZXNzYWdlLCB0YXNrLCBub3RlKSB7XG5cdFx0c3VwZXIobWVzc2FnZSk7XG5cdFx0dGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcblx0XHR0aGlzLm5vdGUgPSBub3RlO1xuXHRcdHRoaXMudGFza0lkID0gdGFzay5pZDtcblx0fVxufVxuY2xhc3MgVGVzdFJ1bkFib3J0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG5cdG5hbWUgPSBcIlRlc3RSdW5BYm9ydEVycm9yXCI7XG5cdHJlYXNvbjtcblx0Y29uc3RydWN0b3IobWVzc2FnZSwgcmVhc29uKSB7XG5cdFx0c3VwZXIobWVzc2FnZSk7XG5cdFx0dGhpcy5yZWFzb24gPSByZWFzb247XG5cdH1cbn1cbmNsYXNzIEZpeHR1cmVEZXBlbmRlbmN5RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG5cdG5hbWUgPSBcIkZpeHR1cmVEZXBlbmRlbmN5RXJyb3JcIjtcbn1cbmNsYXNzIEZpeHR1cmVBY2Nlc3NFcnJvciBleHRlbmRzIEVycm9yIHtcblx0bmFtZSA9IFwiRml4dHVyZUFjY2Vzc0Vycm9yXCI7XG59XG5jbGFzcyBGaXh0dXJlUGFyc2VFcnJvciBleHRlbmRzIEVycm9yIHtcblx0bmFtZSA9IFwiRml4dHVyZVBhcnNlRXJyb3JcIjtcbn1cbmNsYXNzIEFyb3VuZEhvb2tTZXR1cEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRuYW1lID0gXCJBcm91bmRIb29rU2V0dXBFcnJvclwiO1xufVxuY2xhc3MgQXJvdW5kSG9va1RlYXJkb3duRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG5cdG5hbWUgPSBcIkFyb3VuZEhvb2tUZWFyZG93bkVycm9yXCI7XG59XG5jbGFzcyBBcm91bmRIb29rTXVsdGlwbGVDYWxsc0Vycm9yIGV4dGVuZHMgRXJyb3Ige1xuXHRuYW1lID0gXCJBcm91bmRIb29rTXVsdGlwbGVDYWxsc0Vycm9yXCI7XG59XG5cbi8vIHVzZSBXZWFrTWFwIGhlcmUgdG8gbWFrZSB0aGUgVGVzdCBhbmQgU3VpdGUgb2JqZWN0IHNlcmlhbGl6YWJsZVxuY29uc3QgZm5NYXAgPSBuZXcgV2Vha01hcCgpO1xuY29uc3QgdGVzdEZpeHR1cmVNYXAgPSBuZXcgV2Vha01hcCgpO1xuY29uc3QgaG9va3NNYXAgPSBuZXcgV2Vha01hcCgpO1xuZnVuY3Rpb24gc2V0Rm4oa2V5LCBmbikge1xuXHRmbk1hcC5zZXQoa2V5LCBmbik7XG59XG5mdW5jdGlvbiBnZXRGbihrZXkpIHtcblx0cmV0dXJuIGZuTWFwLmdldChrZXkpO1xufVxuZnVuY3Rpb24gc2V0VGVzdEZpeHR1cmUoa2V5LCBmaXh0dXJlKSB7XG5cdHRlc3RGaXh0dXJlTWFwLnNldChrZXksIGZpeHR1cmUpO1xufVxuZnVuY3Rpb24gZ2V0VGVzdEZpeHR1cmVzKGtleSkge1xuXHRyZXR1cm4gdGVzdEZpeHR1cmVNYXAuZ2V0KGtleSk7XG59XG5mdW5jdGlvbiBzZXRIb29rcyhrZXksIGhvb2tzKSB7XG5cdGhvb2tzTWFwLnNldChrZXksIGhvb2tzKTtcbn1cbmZ1bmN0aW9uIGdldEhvb2tzKGtleSkge1xuXHRyZXR1cm4gaG9va3NNYXAuZ2V0KGtleSk7XG59XG5cbmNvbnN0IEZJWFRVUkVfU1RBQ0tfVFJBQ0VfS0VZID0gU3ltYm9sLmZvcihcIlZJVEVTVF9GSVhUVVJFX1NUQUNLX1RSQUNFXCIpO1xuY2xhc3MgVGVzdEZpeHR1cmVzIHtcblx0X3N1aXRlQ29udGV4dHM7XG5cdF9vdmVycmlkZXMgPSBuZXcgV2Vha01hcCgpO1xuXHRfcmVnaXN0cmF0aW9ucztcblx0c3RhdGljIF9kZWZpbml0aW9ucyA9IFtdO1xuXHRzdGF0aWMgX2J1aWx0aW5GaXh0dXJlcyA9IFtcblx0XHRcInRhc2tcIixcblx0XHRcInNpZ25hbFwiLFxuXHRcdFwib25UZXN0RmFpbGVkXCIsXG5cdFx0XCJvblRlc3RGaW5pc2hlZFwiLFxuXHRcdFwic2tpcFwiLFxuXHRcdFwiYW5ub3RhdGVcIlxuXHRdO1xuXHRzdGF0aWMgX2ZpeHR1cmVPcHRpb25LZXlzID0gW1xuXHRcdFwiYXV0b1wiLFxuXHRcdFwiaW5qZWN0ZWRcIixcblx0XHRcInNjb3BlXCJcblx0XTtcblx0c3RhdGljIF9maXh0dXJlU2NvcGVzID0gW1xuXHRcdFwidGVzdFwiLFxuXHRcdFwiZmlsZVwiLFxuXHRcdFwid29ya2VyXCJcblx0XTtcblx0c3RhdGljIF93b3JrZXJDb250ZXh0U3VpdGUgPSB7IHR5cGU6IFwid29ya2VyXCIgfTtcblx0c3RhdGljIGNsZWFyRGVmaW5pdGlvbnMoKSB7XG5cdFx0VGVzdEZpeHR1cmVzLl9kZWZpbml0aW9ucy5sZW5ndGggPSAwO1xuXHR9XG5cdHN0YXRpYyBnZXRXb3JrZXJDb250ZXh0cygpIHtcblx0XHRyZXR1cm4gVGVzdEZpeHR1cmVzLl9kZWZpbml0aW9ucy5tYXAoKGYpID0+IGYuZ2V0V29ya2VyQ29udGV4dCgpKTtcblx0fVxuXHRzdGF0aWMgZ2V0RmlsZUNvbnRleHRzKGZpbGUpIHtcblx0XHRyZXR1cm4gVGVzdEZpeHR1cmVzLl9kZWZpbml0aW9ucy5tYXAoKGYpID0+IGYuZ2V0RmlsZUNvbnRleHQoZmlsZSkpO1xuXHR9XG5cdHN0YXRpYyBpc0ZpeHR1cmVPcHRpb25zKG9iaikge1xuXHRcdHJldHVybiBpc09iamVjdChvYmopICYmIE9iamVjdC5rZXlzKG9iaikuc29tZSgoa2V5KSA9PiBUZXN0Rml4dHVyZXMuX2ZpeHR1cmVPcHRpb25LZXlzLmluY2x1ZGVzKGtleSkpO1xuXHR9XG5cdGNvbnN0cnVjdG9yKHJlZ2lzdHJhdGlvbnMpIHtcblx0XHR0aGlzLl9yZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9ucyA/PyBuZXcgTWFwKCk7XG5cdFx0dGhpcy5fc3VpdGVDb250ZXh0cyA9IG5ldyBXZWFrTWFwKCk7XG5cdFx0VGVzdEZpeHR1cmVzLl9kZWZpbml0aW9ucy5wdXNoKHRoaXMpO1xuXHR9XG5cdGV4dGVuZChydW5uZXIsIHVzZXJGaXh0dXJlcykge1xuXHRcdGNvbnN0IHsgc3VpdGUgfSA9IGdldEN1cnJlbnRTdWl0ZSgpO1xuXHRcdGNvbnN0IGlzVG9wTGV2ZWwgPSAhc3VpdGUgfHwgc3VpdGUuZmlsZSA9PT0gc3VpdGU7XG5cdFx0Y29uc3QgcmVnaXN0cmF0aW9ucyA9IHRoaXMucGFyc2VVc2VyRml4dHVyZXMocnVubmVyLCB1c2VyRml4dHVyZXMsIGlzVG9wTGV2ZWwpO1xuXHRcdHJldHVybiBuZXcgVGVzdEZpeHR1cmVzKHJlZ2lzdHJhdGlvbnMpO1xuXHR9XG5cdGdldChzdWl0ZSkge1xuXHRcdGxldCBjdXJyZW50U3VpdGUgPSBzdWl0ZTtcblx0XHR3aGlsZSAoY3VycmVudFN1aXRlKSB7XG5cdFx0XHRjb25zdCBvdmVycmlkZXMgPSB0aGlzLl9vdmVycmlkZXMuZ2V0KGN1cnJlbnRTdWl0ZSk7XG5cdFx0XHQvLyByZXR1cm4gdGhlIGNsb3Nlc3Qgb3ZlcnJpZGVcblx0XHRcdGlmIChvdmVycmlkZXMpIHtcblx0XHRcdFx0cmV0dXJuIG92ZXJyaWRlcztcblx0XHRcdH1cblx0XHRcdGlmIChjdXJyZW50U3VpdGUgPT09IGN1cnJlbnRTdWl0ZS5maWxlKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0Y3VycmVudFN1aXRlID0gY3VycmVudFN1aXRlLnN1aXRlIHx8IGN1cnJlbnRTdWl0ZS5maWxlO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5fcmVnaXN0cmF0aW9ucztcblx0fVxuXHRvdmVycmlkZShydW5uZXIsIHVzZXJGaXh0dXJlcykge1xuXHRcdGNvbnN0IHsgc3VpdGU6IGN1cnJlbnRTdWl0ZSwgZmlsZSB9ID0gZ2V0Q3VycmVudFN1aXRlKCk7XG5cdFx0Y29uc3Qgc3VpdGUgPSBjdXJyZW50U3VpdGUgfHwgZmlsZTtcblx0XHRjb25zdCBpc1RvcExldmVsID0gIWN1cnJlbnRTdWl0ZSB8fCBjdXJyZW50U3VpdGUuZmlsZSA9PT0gY3VycmVudFN1aXRlO1xuXHRcdC8vIENyZWF0ZSBhIGNvcHkgb2YgdGhlIGNsb3Nlc3QgcGFyZW50J3MgcmVnaXN0cmF0aW9ucyB0byBhdm9pZCBtb2RpZnlpbmcgdGhlbVxuXHRcdC8vIEZvciBjaGFpbmVkIGNhbGxzLCB0aGlzLmdldChzdWl0ZSkgcmV0dXJucyB0aGlzIHN1aXRlJ3Mgb3ZlcnJpZGVzOyBmb3IgZmlyc3QgY2FsbCwgcmV0dXJucyBwYXJlbnQnc1xuXHRcdGNvbnN0IHN1aXRlUmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAodGhpcy5nZXQoc3VpdGUpKTtcblx0XHRjb25zdCByZWdpc3RyYXRpb25zID0gdGhpcy5wYXJzZVVzZXJGaXh0dXJlcyhydW5uZXIsIHVzZXJGaXh0dXJlcywgaXNUb3BMZXZlbCwgc3VpdGVSZWdpc3RyYXRpb25zKTtcblx0XHQvLyBJZiBkZWZpbmVkIGluIHRvcC1sZXZlbCwganVzdCBvdmVycmlkZSBhbGwgcmVnaXN0cmF0aW9uc1xuXHRcdC8vIFdlIGRvbid0IHN1cHBvcnQgb3ZlcnJpZGluZyBzdWl0ZS1sZXZlbCBmaXh0dXJlcyBhbnl3YXkgKGl0IHdpbGwgdGhyb3cgYW4gZXJyb3IpXG5cdFx0aWYgKGlzVG9wTGV2ZWwpIHtcblx0XHRcdHRoaXMuX3JlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9vdmVycmlkZXMuc2V0KHN1aXRlLCByZWdpc3RyYXRpb25zKTtcblx0XHR9XG5cdH1cblx0Z2V0RmlsZUNvbnRleHQoZmlsZSkge1xuXHRcdGlmICghdGhpcy5fc3VpdGVDb250ZXh0cy5oYXMoZmlsZSkpIHtcblx0XHRcdHRoaXMuX3N1aXRlQ29udGV4dHMuc2V0KGZpbGUsIE9iamVjdC5jcmVhdGUobnVsbCkpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5fc3VpdGVDb250ZXh0cy5nZXQoZmlsZSk7XG5cdH1cblx0Z2V0V29ya2VyQ29udGV4dCgpIHtcblx0XHRpZiAoIXRoaXMuX3N1aXRlQ29udGV4dHMuaGFzKFRlc3RGaXh0dXJlcy5fd29ya2VyQ29udGV4dFN1aXRlKSkge1xuXHRcdFx0dGhpcy5fc3VpdGVDb250ZXh0cy5zZXQoVGVzdEZpeHR1cmVzLl93b3JrZXJDb250ZXh0U3VpdGUsIE9iamVjdC5jcmVhdGUobnVsbCkpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5fc3VpdGVDb250ZXh0cy5nZXQoVGVzdEZpeHR1cmVzLl93b3JrZXJDb250ZXh0U3VpdGUpO1xuXHR9XG5cdHBhcnNlVXNlckZpeHR1cmVzKHJ1bm5lciwgdXNlckZpeHR1cmVzLCBzdXBwb3J0Tm9uVGVzdCwgcmVnaXN0cmF0aW9ucyA9IG5ldyBNYXAodGhpcy5fcmVnaXN0cmF0aW9ucykpIHtcblx0XHRjb25zdCBlcnJvcnMgPSBbXTtcblx0XHRPYmplY3QuZW50cmllcyh1c2VyRml4dHVyZXMpLmZvckVhY2goKFtuYW1lLCBmbl0pID0+IHtcblx0XHRcdGxldCBvcHRpb25zO1xuXHRcdFx0bGV0IHZhbHVlO1xuXHRcdFx0bGV0IF9vcHRpb25zO1xuXHRcdFx0aWYgKEFycmF5LmlzQXJyYXkoZm4pICYmIGZuLmxlbmd0aCA+PSAyICYmIFRlc3RGaXh0dXJlcy5pc0ZpeHR1cmVPcHRpb25zKGZuWzFdKSkge1xuXHRcdFx0XHRfb3B0aW9ucyA9IGZuWzFdO1xuXHRcdFx0XHRvcHRpb25zID0ge1xuXHRcdFx0XHRcdGF1dG86IF9vcHRpb25zLmF1dG8gPz8gZmFsc2UsXG5cdFx0XHRcdFx0c2NvcGU6IF9vcHRpb25zLnNjb3BlID8/IFwidGVzdFwiLFxuXHRcdFx0XHRcdGluamVjdGVkOiBfb3B0aW9ucy5pbmplY3RlZCA/PyBmYWxzZVxuXHRcdFx0XHR9O1xuXHRcdFx0XHR2YWx1ZSA9IG9wdGlvbnMuaW5qZWN0ZWQgPyBydW5uZXIuaW5qZWN0VmFsdWU/LihuYW1lKSA/PyBmblswXSA6IGZuWzBdO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmFsdWUgPSBmbjtcblx0XHRcdH1cblx0XHRcdGNvbnN0IHBhcmVudCA9IHJlZ2lzdHJhdGlvbnMuZ2V0KG5hbWUpO1xuXHRcdFx0aWYgKHBhcmVudCAmJiBvcHRpb25zKSB7XG5cdFx0XHRcdGlmIChwYXJlbnQuc2NvcGUgIT09IG9wdGlvbnMuc2NvcGUpIHtcblx0XHRcdFx0XHRlcnJvcnMucHVzaChuZXcgRml4dHVyZURlcGVuZGVuY3lFcnJvcihgVGhlIFwiJHtuYW1lfVwiIGZpeHR1cmUgd2FzIGFscmVhZHkgcmVnaXN0ZXJlZCB3aXRoIGEgXCIke29wdGlvbnMuc2NvcGV9XCIgc2NvcGUuYCkpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChwYXJlbnQuYXV0byAhPT0gb3B0aW9ucy5hdXRvKSB7XG5cdFx0XHRcdFx0ZXJyb3JzLnB1c2gobmV3IEZpeHR1cmVEZXBlbmRlbmN5RXJyb3IoYFRoZSBcIiR7bmFtZX1cIiBmaXh0dXJlIHdhcyBhbHJlYWR5IHJlZ2lzdGVyZWQgYXMgeyBhdXRvOiAke29wdGlvbnMuYXV0b30gfS5gKSk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAocGFyZW50KSB7XG5cdFx0XHRcdG9wdGlvbnMgPSB7XG5cdFx0XHRcdFx0YXV0bzogcGFyZW50LmF1dG8sXG5cdFx0XHRcdFx0c2NvcGU6IHBhcmVudC5zY29wZSxcblx0XHRcdFx0XHRpbmplY3RlZDogcGFyZW50LmluamVjdGVkXG5cdFx0XHRcdH07XG5cdFx0XHR9IGVsc2UgaWYgKCFvcHRpb25zKSB7XG5cdFx0XHRcdG9wdGlvbnMgPSB7XG5cdFx0XHRcdFx0YXV0bzogZmFsc2UsXG5cdFx0XHRcdFx0aW5qZWN0ZWQ6IGZhbHNlLFxuXHRcdFx0XHRcdHNjb3BlOiBcInRlc3RcIlxuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdFx0aWYgKG9wdGlvbnMuc2NvcGUgJiYgIVRlc3RGaXh0dXJlcy5fZml4dHVyZVNjb3Blcy5pbmNsdWRlcyhvcHRpb25zLnNjb3BlKSkge1xuXHRcdFx0XHRlcnJvcnMucHVzaChuZXcgRml4dHVyZURlcGVuZGVuY3lFcnJvcihgVGhlIFwiJHtuYW1lfVwiIGZpeHR1cmUgaGFzIHVua25vd24gc2NvcGUgXCIke29wdGlvbnMuc2NvcGV9XCIuYCkpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCFzdXBwb3J0Tm9uVGVzdCAmJiBvcHRpb25zLnNjb3BlICE9PSBcInRlc3RcIikge1xuXHRcdFx0XHRlcnJvcnMucHVzaChuZXcgRml4dHVyZURlcGVuZGVuY3lFcnJvcihgVGhlIFwiJHtuYW1lfVwiIGZpeHR1cmUgY2Fubm90IGJlIGRlZmluZWQgd2l0aCBhICR7b3B0aW9ucy5zY29wZX0gc2NvcGUkeyFfb3B0aW9ucz8uc2NvcGUgJiYgcGFyZW50Py5zY29wZSA/IFwiIChpbmhlcml0ZWQgZnJvbSB0aGUgYmFzZSBmaXh0dXJlKVwiIDogXCJcIn0gaW5zaWRlIHRoZSBkZXNjcmliZSBibG9jay4gRGVmaW5lIGl0IGF0IHRoZSB0b3AgbGV2ZWwgb2YgdGhlIGZpbGUgaW5zdGVhZC5gKSk7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCBkZXBzID0gaXNGaXh0dXJlRnVuY3Rpb24odmFsdWUpID8gZ2V0VXNlZFByb3BzKHZhbHVlKSA6IG5ldyBTZXQoKTtcblx0XHRcdGNvbnN0IGl0ZW0gPSB7XG5cdFx0XHRcdG5hbWUsXG5cdFx0XHRcdHZhbHVlLFxuXHRcdFx0XHRhdXRvOiBvcHRpb25zLmF1dG8gPz8gZmFsc2UsXG5cdFx0XHRcdGluamVjdGVkOiBvcHRpb25zLmluamVjdGVkID8/IGZhbHNlLFxuXHRcdFx0XHRzY29wZTogb3B0aW9ucy5zY29wZSA/PyBcInRlc3RcIixcblx0XHRcdFx0ZGVwcyxcblx0XHRcdFx0cGFyZW50XG5cdFx0XHR9O1xuXHRcdFx0aWYgKGlzRml4dHVyZUZ1bmN0aW9uKHZhbHVlKSkge1xuXHRcdFx0XHRPYmplY3QuYXNzaWduKHZhbHVlLCB7IFtGSVhUVVJFX1NUQUNLX1RSQUNFX0tFWV06IG5ldyBFcnJvcihcIlNUQUNLX1RSQUNFX0VSUk9SXCIpIH0pO1xuXHRcdFx0fVxuXHRcdFx0cmVnaXN0cmF0aW9ucy5zZXQobmFtZSwgaXRlbSk7XG5cdFx0XHRpZiAoaXRlbS5zY29wZSA9PT0gXCJ3b3JrZXJcIiAmJiAocnVubmVyLnBvb2wgPT09IFwidm1UaHJlYWRzXCIgfHwgcnVubmVyLnBvb2wgPT09IFwidm1Gb3Jrc1wiKSkge1xuXHRcdFx0XHRpdGVtLnNjb3BlID0gXCJmaWxlXCI7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0Ly8gdmFsaWRhdGUgZml4dHVyZSBkZXBlbmRlbmN5IHNjb3Blc1xuXHRcdGZvciAoY29uc3QgZml4dHVyZSBvZiByZWdpc3RyYXRpb25zLnZhbHVlcygpKSB7XG5cdFx0XHRmb3IgKGNvbnN0IGRlcE5hbWUgb2YgZml4dHVyZS5kZXBzKSB7XG5cdFx0XHRcdGlmIChUZXN0Rml4dHVyZXMuX2J1aWx0aW5GaXh0dXJlcy5pbmNsdWRlcyhkZXBOYW1lKSkge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnN0IGRlcCA9IHJlZ2lzdHJhdGlvbnMuZ2V0KGRlcE5hbWUpO1xuXHRcdFx0XHRpZiAoIWRlcCkge1xuXHRcdFx0XHRcdGVycm9ycy5wdXNoKG5ldyBGaXh0dXJlRGVwZW5kZW5jeUVycm9yKGBUaGUgXCIke2ZpeHR1cmUubmFtZX1cIiBmaXh0dXJlIGRlcGVuZHMgb24gdW5rbm93biBmaXh0dXJlIFwiJHtkZXBOYW1lfVwiLmApKTtcblx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoZGVwTmFtZSA9PT0gZml4dHVyZS5uYW1lICYmICFmaXh0dXJlLnBhcmVudCkge1xuXHRcdFx0XHRcdGVycm9ycy5wdXNoKG5ldyBGaXh0dXJlRGVwZW5kZW5jeUVycm9yKGBUaGUgXCIke2ZpeHR1cmUubmFtZX1cIiBmaXh0dXJlIGRlcGVuZHMgb24gaXRzZWxmLCBidXQgZG9lcyBub3QgaGF2ZSBhIGJhc2UgaW1wbGVtZW50YXRpb24uYCkpO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChUZXN0Rml4dHVyZXMuX2ZpeHR1cmVTY29wZXMuaW5kZXhPZihmaXh0dXJlLnNjb3BlKSA+IFRlc3RGaXh0dXJlcy5fZml4dHVyZVNjb3Blcy5pbmRleE9mKGRlcC5zY29wZSkpIHtcblx0XHRcdFx0XHRlcnJvcnMucHVzaChuZXcgRml4dHVyZURlcGVuZGVuY3lFcnJvcihgVGhlICR7Zml4dHVyZS5zY29wZX0gXCIke2ZpeHR1cmUubmFtZX1cIiBmaXh0dXJlIGNhbm5vdCBkZXBlbmQgb24gYSAke2RlcC5zY29wZX0gZml4dHVyZSBcIiR7ZGVwLm5hbWV9XCIuYCkpO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChlcnJvcnMubGVuZ3RoID09PSAxKSB7XG5cdFx0XHR0aHJvdyBlcnJvcnNbMF07XG5cdFx0fSBlbHNlIGlmIChlcnJvcnMubGVuZ3RoID4gMSkge1xuXHRcdFx0dGhyb3cgbmV3IEFnZ3JlZ2F0ZUVycm9yKGVycm9ycywgXCJDYW5ub3QgcmVzb2x2ZSB1c2VyIGZpeHR1cmVzLiBTZWUgZXJyb3JzIGZvciBtb3JlIGluZm9ybWF0aW9uLlwiKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlZ2lzdHJhdGlvbnM7XG5cdH1cbn1cbmNvbnN0IGNsZWFudXBGbkFycmF5TWFwID0gbmV3IFdlYWtNYXAoKTtcbmFzeW5jIGZ1bmN0aW9uIGNhbGxGaXh0dXJlQ2xlYW51cChjb250ZXh0KSB7XG5cdGNvbnN0IGNsZWFudXBGbkFycmF5ID0gY2xlYW51cEZuQXJyYXlNYXAuZ2V0KGNvbnRleHQpID8/IFtdO1xuXHRmb3IgKGNvbnN0IGNsZWFudXAgb2YgY2xlYW51cEZuQXJyYXkucmV2ZXJzZSgpKSB7XG5cdFx0YXdhaXQgY2xlYW51cCgpO1xuXHR9XG5cdGNsZWFudXBGbkFycmF5TWFwLmRlbGV0ZShjb250ZXh0KTtcbn1cbi8qKlxuKiBSZXR1cm5zIHRoZSBjdXJyZW50IG51bWJlciBvZiBjbGVhbnVwIGZ1bmN0aW9ucyByZWdpc3RlcmVkIGZvciB0aGUgY29udGV4dC5cbiogVGhpcyBjYW4gYmUgdXNlZCBhcyBhIGNoZWNrcG9pbnQgdG8gbGF0ZXIgY2xlYW4gdXAgb25seSBmaXh0dXJlcyBhZGRlZCBhZnRlciB0aGlzIHBvaW50LlxuKi9cbmZ1bmN0aW9uIGdldEZpeHR1cmVDbGVhbnVwQ291bnQoY29udGV4dCkge1xuXHRyZXR1cm4gY2xlYW51cEZuQXJyYXlNYXAuZ2V0KGNvbnRleHQpPy5sZW5ndGggPz8gMDtcbn1cbi8qKlxuKiBDbGVhbnMgdXAgb25seSBmaXh0dXJlcyB0aGF0IHdlcmUgYWRkZWQgYWZ0ZXIgdGhlIGdpdmVuIGNoZWNrcG9pbnQgaW5kZXguXG4qIFRoaXMgaXMgdXNlZCBieSBhcm91bmRFYWNoIHRvIGNsZWFuIHVwIGZpeHR1cmVzIGNyZWF0ZWQgaW5zaWRlIHJ1blRlc3QoKVxuKiB3aGlsZSBwcmVzZXJ2aW5nIGZpeHR1cmVzIHRoYXQgd2VyZSBjcmVhdGVkIGZvciBhcm91bmRFYWNoIGl0c2VsZi5cbiovXG5hc3luYyBmdW5jdGlvbiBjYWxsRml4dHVyZUNsZWFudXBGcm9tKGNvbnRleHQsIGZyb21JbmRleCkge1xuXHRjb25zdCBjbGVhbnVwRm5BcnJheSA9IGNsZWFudXBGbkFycmF5TWFwLmdldChjb250ZXh0KTtcblx0aWYgKCFjbGVhbnVwRm5BcnJheSB8fCBjbGVhbnVwRm5BcnJheS5sZW5ndGggPD0gZnJvbUluZGV4KSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdC8vIEdldCBpdGVtcyBhZGRlZCBhZnRlciB0aGUgY2hlY2twb2ludFxuXHRjb25zdCB0b0NsZWFudXAgPSBjbGVhbnVwRm5BcnJheS5zbGljZShmcm9tSW5kZXgpO1xuXHQvLyBDbGVhbiB1cCBpbiByZXZlcnNlIG9yZGVyXG5cdGZvciAoY29uc3QgY2xlYW51cCBvZiB0b0NsZWFudXAucmV2ZXJzZSgpKSB7XG5cdFx0YXdhaXQgY2xlYW51cCgpO1xuXHR9XG5cdC8vIFJlbW92ZSBjbGVhbmVkIHVwIGl0ZW1zIGZyb20gdGhlIGFycmF5LCBrZWVwaW5nIGl0ZW1zIGJlZm9yZSBjaGVja3BvaW50XG5cdGNsZWFudXBGbkFycmF5Lmxlbmd0aCA9IGZyb21JbmRleDtcbn1cbmNvbnN0IGNvbnRleHRIYXNGaXh0dXJlc0NhY2hlID0gbmV3IFdlYWtNYXAoKTtcbmZ1bmN0aW9uIHdpdGhGaXh0dXJlcyhmbiwgb3B0aW9ucykge1xuXHRjb25zdCBjb2xsZWN0b3IgPSBnZXRDdXJyZW50U3VpdGUoKTtcblx0Y29uc3Qgc3VpdGUgPSBvcHRpb25zPy5zdWl0ZSB8fCBjb2xsZWN0b3Iuc3VpdGUgfHwgY29sbGVjdG9yLmZpbGU7XG5cdHJldHVybiBhc3luYyAoaG9va0NvbnRleHQpID0+IHtcblx0XHRjb25zdCBjb250ZXh0ID0gaG9va0NvbnRleHQgfHwgb3B0aW9ucz8uY29udGV4dDtcblx0XHRpZiAoIWNvbnRleHQpIHtcblx0XHRcdGlmIChvcHRpb25zPy5zdWl0ZUhvb2spIHtcblx0XHRcdFx0dmFsaWRhdGVTdWl0ZUhvb2soZm4sIG9wdGlvbnMuc3VpdGVIb29rLCBvcHRpb25zLnN0YWNrVHJhY2VFcnJvcik7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZm4oe30pO1xuXHRcdH1cblx0XHRjb25zdCBmaXh0dXJlcyA9IG9wdGlvbnM/LmZpeHR1cmVzIHx8IGdldFRlc3RGaXh0dXJlcyhjb250ZXh0KTtcblx0XHRpZiAoIWZpeHR1cmVzKSB7XG5cdFx0XHRyZXR1cm4gZm4oY29udGV4dCk7XG5cdFx0fVxuXHRcdGNvbnN0IHJlZ2lzdHJhdGlvbnMgPSBmaXh0dXJlcy5nZXQoc3VpdGUpO1xuXHRcdGlmICghcmVnaXN0cmF0aW9ucy5zaXplKSB7XG5cdFx0XHRyZXR1cm4gZm4oY29udGV4dCk7XG5cdFx0fVxuXHRcdGNvbnN0IHVzZWRGaXh0dXJlcyA9IFtdO1xuXHRcdGNvbnN0IHVzZWRQcm9wcyA9IGdldFVzZWRQcm9wcyhmbik7XG5cdFx0Zm9yIChjb25zdCBmaXh0dXJlIG9mIHJlZ2lzdHJhdGlvbnMudmFsdWVzKCkpIHtcblx0XHRcdGlmIChpc0F1dG9GaXh0dXJlKGZpeHR1cmUsIG9wdGlvbnMpIHx8IHVzZWRQcm9wcy5oYXMoZml4dHVyZS5uYW1lKSkge1xuXHRcdFx0XHR1c2VkRml4dHVyZXMucHVzaChmaXh0dXJlKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCF1c2VkRml4dHVyZXMubGVuZ3RoKSB7XG5cdFx0XHRyZXR1cm4gZm4oY29udGV4dCk7XG5cdFx0fVxuXHRcdGlmICghY2xlYW51cEZuQXJyYXlNYXAuaGFzKGNvbnRleHQpKSB7XG5cdFx0XHRjbGVhbnVwRm5BcnJheU1hcC5zZXQoY29udGV4dCwgW10pO1xuXHRcdH1cblx0XHRjb25zdCBjbGVhbnVwRm5BcnJheSA9IGNsZWFudXBGbkFycmF5TWFwLmdldChjb250ZXh0KTtcblx0XHRjb25zdCBwZW5kaW5nRml4dHVyZXMgPSByZXNvbHZlRGVwcyh1c2VkRml4dHVyZXMsIHJlZ2lzdHJhdGlvbnMpO1xuXHRcdGlmICghcGVuZGluZ0ZpeHR1cmVzLmxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGZuKGNvbnRleHQpO1xuXHRcdH1cblx0XHQvLyBDaGVjayBpZiBzdWl0ZS1sZXZlbCBob29rIGlzIHRyeWluZyB0byBhY2Nlc3MgdGVzdC1zY29wZWQgZml4dHVyZXNcblx0XHQvLyBTdWl0ZSBob29rcyAoYmVmb3JlQWxsL2FmdGVyQWxsL2Fyb3VuZEFsbCkgY2FuIG9ubHkgYWNjZXNzIGZpbGUvd29ya2VyIHNjb3BlZCBmaXh0dXJlc1xuXHRcdGlmIChvcHRpb25zPy5zdWl0ZUhvb2spIHtcblx0XHRcdGNvbnN0IHRlc3RTY29wZWRGaXh0dXJlcyA9IHBlbmRpbmdGaXh0dXJlcy5maWx0ZXIoKGYpID0+IGYuc2NvcGUgPT09IFwidGVzdFwiKTtcblx0XHRcdGlmICh0ZXN0U2NvcGVkRml4dHVyZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRjb25zdCBmaXh0dXJlTmFtZXMgPSB0ZXN0U2NvcGVkRml4dHVyZXMubWFwKChmKSA9PiBgXCIke2YubmFtZX1cImApLmpvaW4oXCIsIFwiKTtcblx0XHRcdFx0Y29uc3QgYWx0ZXJuYXRpdmVIb29rID0ge1xuXHRcdFx0XHRcdGFyb3VuZEFsbDogXCJhcm91bmRFYWNoXCIsXG5cdFx0XHRcdFx0YmVmb3JlQWxsOiBcImJlZm9yZUVhY2hcIixcblx0XHRcdFx0XHRhZnRlckFsbDogXCJhZnRlckVhY2hcIlxuXHRcdFx0XHR9O1xuXHRcdFx0XHRjb25zdCBlcnJvciA9IG5ldyBGaXh0dXJlRGVwZW5kZW5jeUVycm9yKGBUZXN0LXNjb3BlZCBmaXh0dXJlcyBjYW5ub3QgYmUgdXNlZCBpbnNpZGUgJHtvcHRpb25zLnN1aXRlSG9va30gaG9vay4gYCArIGBUaGUgZm9sbG93aW5nIGZpeHR1cmVzIGFyZSB0ZXN0LXNjb3BlZDogJHtmaXh0dXJlTmFtZXN9LiBgICsgYFVzZSB7IHNjb3BlOiAnZmlsZScgfSBvciB7IHNjb3BlOiAnd29ya2VyJyB9IGZpeHR1cmVzIGluc3RlYWQsIG9yIG1vdmUgdGhlIGxvZ2ljIHRvICR7YWx0ZXJuYXRpdmVIb29rW29wdGlvbnMuc3VpdGVIb29rXX0gaG9vay5gKTtcblx0XHRcdFx0Ly8gVXNlIHN0YWNrIHRyYWNlIGZyb20gaG9vayByZWdpc3RyYXRpb24gZm9yIGJldHRlciBlcnJvciBsb2NhdGlvblxuXHRcdFx0XHRpZiAob3B0aW9ucy5zdGFja1RyYWNlRXJyb3I/LnN0YWNrKSB7XG5cdFx0XHRcdFx0ZXJyb3Iuc3RhY2sgPSBlcnJvci5tZXNzYWdlICsgb3B0aW9ucy5zdGFja1RyYWNlRXJyb3Iuc3RhY2sucmVwbGFjZShvcHRpb25zLnN0YWNrVHJhY2VFcnJvci5tZXNzYWdlLCBcIlwiKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aHJvdyBlcnJvcjtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKCFjb250ZXh0SGFzRml4dHVyZXNDYWNoZS5oYXMoY29udGV4dCkpIHtcblx0XHRcdGNvbnRleHRIYXNGaXh0dXJlc0NhY2hlLnNldChjb250ZXh0LCBuZXcgV2Vha1NldCgpKTtcblx0XHR9XG5cdFx0Y29uc3QgY2FjaGVkRml4dHVyZXMgPSBjb250ZXh0SGFzRml4dHVyZXNDYWNoZS5nZXQoY29udGV4dCk7XG5cdFx0Zm9yIChjb25zdCBmaXh0dXJlIG9mIHBlbmRpbmdGaXh0dXJlcykge1xuXHRcdFx0aWYgKGZpeHR1cmUuc2NvcGUgPT09IFwidGVzdFwiKSB7XG5cdFx0XHRcdC8vIGZpeHR1cmUgY291bGQgYmUgYWxyZWFkeSBpbml0aWFsaXplZCBkdXJpbmcgXCJiZWZvcmVcIiBob29rXG5cdFx0XHRcdC8vIHdlIGNhbid0IGNoZWNrIFwiZml4dHVyZS5uYW1lXCIgaW4gY29udGV4dCBiZWNhdXNlIGNvbnRleHQgbWF5XG5cdFx0XHRcdC8vIGFjY2VzcyB0aGUgcGFyZW50IGZpeHR1cmUgKHsgYTogKHsgYSB9KSA9PiB7fSB9KVxuXHRcdFx0XHRpZiAoY2FjaGVkRml4dHVyZXMuaGFzKGZpeHR1cmUpKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y2FjaGVkRml4dHVyZXMuYWRkKGZpeHR1cmUpO1xuXHRcdFx0XHRjb25zdCByZXNvbHZlZFZhbHVlID0gYXdhaXQgcmVzb2x2ZVRlc3RGaXh0dXJlVmFsdWUoZml4dHVyZSwgY29udGV4dCwgY2xlYW51cEZuQXJyYXkpO1xuXHRcdFx0XHRjb250ZXh0W2ZpeHR1cmUubmFtZV0gPSByZXNvbHZlZFZhbHVlO1xuXHRcdFx0XHRjbGVhbnVwRm5BcnJheS5wdXNoKCgpID0+IHtcblx0XHRcdFx0XHRjYWNoZWRGaXh0dXJlcy5kZWxldGUoZml4dHVyZSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y29uc3QgcmVzb2x2ZWRWYWx1ZSA9IGF3YWl0IHJlc29sdmVTY29wZUZpeHR1cmVWYWx1ZShmaXh0dXJlcywgc3VpdGUsIGZpeHR1cmUpO1xuXHRcdFx0XHRjb250ZXh0W2ZpeHR1cmUubmFtZV0gPSByZXNvbHZlZFZhbHVlO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZm4oY29udGV4dCk7XG5cdH07XG59XG5mdW5jdGlvbiBpc0F1dG9GaXh0dXJlKGZpeHR1cmUsIG9wdGlvbnMpIHtcblx0aWYgKCFmaXh0dXJlLmF1dG8pIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0Ly8gc3VpdGUgaG9vayBkb2Vzbid0IGF1dG9tYXRpY2FsbHkgdHJpZ2dlciB1bnVzZWQgdGVzdC1zY29wZWQgZml4dHVyZXMuXG5cdGlmIChvcHRpb25zPy5zdWl0ZUhvb2sgJiYgZml4dHVyZS5zY29wZSA9PT0gXCJ0ZXN0XCIpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblx0cmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiBpc0ZpeHR1cmVGdW5jdGlvbih2YWx1ZSkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCI7XG59XG5mdW5jdGlvbiByZXNvbHZlVGVzdEZpeHR1cmVWYWx1ZShmaXh0dXJlLCBjb250ZXh0LCBjbGVhbnVwRm5BcnJheSkge1xuXHRpZiAoIWlzRml4dHVyZUZ1bmN0aW9uKGZpeHR1cmUudmFsdWUpKSB7XG5cdFx0cmV0dXJuIGZpeHR1cmUudmFsdWU7XG5cdH1cblx0cmV0dXJuIHJlc29sdmVGaXh0dXJlRnVuY3Rpb24oZml4dHVyZS52YWx1ZSwgZml4dHVyZS5uYW1lLCBjb250ZXh0LCBjbGVhbnVwRm5BcnJheSk7XG59XG5jb25zdCBzY29wZWRGaXh0dXJlUHJvbWlzZUNhY2hlID0gbmV3IFdlYWtNYXAoKTtcbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVTY29wZUZpeHR1cmVWYWx1ZShmaXh0dXJlcywgc3VpdGUsIGZpeHR1cmUpIHtcblx0Y29uc3Qgd29ya2VyQ29udGV4dCA9IGZpeHR1cmVzLmdldFdvcmtlckNvbnRleHQoKTtcblx0Y29uc3QgZmlsZUNvbnRleHQgPSBmaXh0dXJlcy5nZXRGaWxlQ29udGV4dChzdWl0ZS5maWxlKTtcblx0Y29uc3QgZml4dHVyZUNvbnRleHQgPSBmaXh0dXJlLnNjb3BlID09PSBcIndvcmtlclwiID8gd29ya2VyQ29udGV4dCA6IGZpbGVDb250ZXh0O1xuXHRpZiAoIWlzRml4dHVyZUZ1bmN0aW9uKGZpeHR1cmUudmFsdWUpKSB7XG5cdFx0Zml4dHVyZUNvbnRleHRbZml4dHVyZS5uYW1lXSA9IGZpeHR1cmUudmFsdWU7XG5cdFx0cmV0dXJuIGZpeHR1cmUudmFsdWU7XG5cdH1cblx0aWYgKGZpeHR1cmUubmFtZSBpbiBmaXh0dXJlQ29udGV4dCkge1xuXHRcdHJldHVybiBmaXh0dXJlQ29udGV4dFtmaXh0dXJlLm5hbWVdO1xuXHR9XG5cdGlmIChzY29wZWRGaXh0dXJlUHJvbWlzZUNhY2hlLmhhcyhmaXh0dXJlKSkge1xuXHRcdHJldHVybiBzY29wZWRGaXh0dXJlUHJvbWlzZUNhY2hlLmdldChmaXh0dXJlKTtcblx0fVxuXHRpZiAoIWNsZWFudXBGbkFycmF5TWFwLmhhcyhmaXh0dXJlQ29udGV4dCkpIHtcblx0XHRjbGVhbnVwRm5BcnJheU1hcC5zZXQoZml4dHVyZUNvbnRleHQsIFtdKTtcblx0fVxuXHRjb25zdCBjbGVhbnVwRm5GaWxlQXJyYXkgPSBjbGVhbnVwRm5BcnJheU1hcC5nZXQoZml4dHVyZUNvbnRleHQpO1xuXHRjb25zdCBwcm9taXNlID0gcmVzb2x2ZUZpeHR1cmVGdW5jdGlvbihmaXh0dXJlLnZhbHVlLCBmaXh0dXJlLm5hbWUsIGZpeHR1cmUuc2NvcGUgPT09IFwiZmlsZVwiID8ge1xuXHRcdC4uLndvcmtlckNvbnRleHQsXG5cdFx0Li4uZmlsZUNvbnRleHRcblx0fSA6IGZpeHR1cmVDb250ZXh0LCBjbGVhbnVwRm5GaWxlQXJyYXkpLnRoZW4oKHZhbHVlKSA9PiB7XG5cdFx0Zml4dHVyZUNvbnRleHRbZml4dHVyZS5uYW1lXSA9IHZhbHVlO1xuXHRcdHNjb3BlZEZpeHR1cmVQcm9taXNlQ2FjaGUuZGVsZXRlKGZpeHR1cmUpO1xuXHRcdHJldHVybiB2YWx1ZTtcblx0fSk7XG5cdHNjb3BlZEZpeHR1cmVQcm9taXNlQ2FjaGUuc2V0KGZpeHR1cmUsIHByb21pc2UpO1xuXHRyZXR1cm4gcHJvbWlzZTtcbn1cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVGaXh0dXJlRnVuY3Rpb24oZml4dHVyZUZuLCBmaXh0dXJlTmFtZSwgY29udGV4dCwgY2xlYW51cEZuQXJyYXkpIHtcblx0Ly8gd2FpdCBmb3IgYHVzZWAgY2FsbCB0byBleHRyYWN0IGZpeHR1cmUgdmFsdWVcblx0Y29uc3QgdXNlRm5BcmdQcm9taXNlID0gY3JlYXRlRGVmZXIoKTtcblx0Y29uc3Qgc3RhY2tUcmFjZUVycm9yID0gRklYVFVSRV9TVEFDS19UUkFDRV9LRVkgaW4gZml4dHVyZUZuICYmIGZpeHR1cmVGbltGSVhUVVJFX1NUQUNLX1RSQUNFX0tFWV0gaW5zdGFuY2VvZiBFcnJvciA/IGZpeHR1cmVGbltGSVhUVVJFX1NUQUNLX1RSQUNFX0tFWV0gOiB1bmRlZmluZWQ7XG5cdGxldCBpc1VzZUZuQXJnUmVzb2x2ZWQgPSBmYWxzZTtcblx0Y29uc3QgZml4dHVyZVJldHVybiA9IGZpeHR1cmVGbihjb250ZXh0LCBhc3luYyAodXNlRm5BcmcpID0+IHtcblx0XHQvLyBleHRyYWN0IGB1c2VgIGFyZ3VtZW50XG5cdFx0aXNVc2VGbkFyZ1Jlc29sdmVkID0gdHJ1ZTtcblx0XHR1c2VGbkFyZ1Byb21pc2UucmVzb2x2ZSh1c2VGbkFyZyk7XG5cdFx0Ly8gc3VzcGVuZCBmaXh0dXJlIHRlYXJkb3duIGJ5IGhvbGRpbmcgb2ZmIGB1c2VSZXR1cm5Qcm9taXNlYCByZXNvbHV0aW9uIHVudGlsIGNsZWFudXBcblx0XHRjb25zdCB1c2VSZXR1cm5Qcm9taXNlID0gY3JlYXRlRGVmZXIoKTtcblx0XHRjbGVhbnVwRm5BcnJheS5wdXNoKGFzeW5jICgpID0+IHtcblx0XHRcdC8vIHN0YXJ0IHRlYXJkb3duIGJ5IHJlc29sdmluZyBgdXNlYCBQcm9taXNlXG5cdFx0XHR1c2VSZXR1cm5Qcm9taXNlLnJlc29sdmUoKTtcblx0XHRcdC8vIHdhaXQgZm9yIGZpbmlzaGluZyB0ZWFyZG93blxuXHRcdFx0YXdhaXQgZml4dHVyZVJldHVybjtcblx0XHR9KTtcblx0XHRhd2FpdCB1c2VSZXR1cm5Qcm9taXNlO1xuXHR9KS50aGVuKCgpID0+IHtcblx0XHQvLyBmaXh0dXJlIHJldHVybmVkIHdpdGhvdXQgY2FsbGluZyB1c2UoKVxuXHRcdGlmICghaXNVc2VGbkFyZ1Jlc29sdmVkKSB7XG5cdFx0XHRjb25zdCBlcnJvciA9IG5ldyBFcnJvcihgRml4dHVyZSBcIiR7Zml4dHVyZU5hbWV9XCIgcmV0dXJuZWQgd2l0aG91dCBjYWxsaW5nIFwidXNlXCIuIE1ha2Ugc3VyZSB0byBjYWxsIFwidXNlXCIgaW4gZXZlcnkgY29kZSBwYXRoIG9mIHRoZSBmaXh0dXJlIGZ1bmN0aW9uLmApO1xuXHRcdFx0aWYgKHN0YWNrVHJhY2VFcnJvcj8uc3RhY2spIHtcblx0XHRcdFx0ZXJyb3Iuc3RhY2sgPSBlcnJvci5tZXNzYWdlICsgc3RhY2tUcmFjZUVycm9yLnN0YWNrLnJlcGxhY2Uoc3RhY2tUcmFjZUVycm9yLm1lc3NhZ2UsIFwiXCIpO1xuXHRcdFx0fVxuXHRcdFx0dXNlRm5BcmdQcm9taXNlLnJlamVjdChlcnJvcik7XG5cdFx0fVxuXHR9KS5jYXRjaCgoZSkgPT4ge1xuXHRcdC8vIHRyZWF0IGZpeHR1cmUgc2V0dXAgZXJyb3IgYXMgdGVzdCBmYWlsdXJlXG5cdFx0aWYgKCFpc1VzZUZuQXJnUmVzb2x2ZWQpIHtcblx0XHRcdHVzZUZuQXJnUHJvbWlzZS5yZWplY3QoZSk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdC8vIG90aGVyd2lzZSByZS10aHJvdyB0byBhdm9pZCBzaWxlbmNpbmcgZXJyb3IgZHVyaW5nIGNsZWFudXBcblx0XHR0aHJvdyBlO1xuXHR9KTtcblx0cmV0dXJuIHVzZUZuQXJnUHJvbWlzZTtcbn1cbmZ1bmN0aW9uIHJlc29sdmVEZXBzKHVzZWRGaXh0dXJlcywgcmVnaXN0cmF0aW9ucywgZGVwU2V0ID0gbmV3IFNldCgpLCBwZW5kaW5nRml4dHVyZXMgPSBbXSkge1xuXHR1c2VkRml4dHVyZXMuZm9yRWFjaCgoZml4dHVyZSkgPT4ge1xuXHRcdGlmIChwZW5kaW5nRml4dHVyZXMuaW5jbHVkZXMoZml4dHVyZSkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0aWYgKCFpc0ZpeHR1cmVGdW5jdGlvbihmaXh0dXJlLnZhbHVlKSB8fCAhZml4dHVyZS5kZXBzKSB7XG5cdFx0XHRwZW5kaW5nRml4dHVyZXMucHVzaChmaXh0dXJlKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0aWYgKGRlcFNldC5oYXMoZml4dHVyZSkpIHtcblx0XHRcdGlmIChmaXh0dXJlLnBhcmVudCkge1xuXHRcdFx0XHRmaXh0dXJlID0gZml4dHVyZS5wYXJlbnQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYENpcmN1bGFyIGZpeHR1cmUgZGVwZW5kZW5jeSBkZXRlY3RlZDogJHtmaXh0dXJlLm5hbWV9IDwtICR7Wy4uLmRlcFNldF0ucmV2ZXJzZSgpLm1hcCgoZCkgPT4gZC5uYW1lKS5qb2luKFwiIDwtIFwiKX1gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZGVwU2V0LmFkZChmaXh0dXJlKTtcblx0XHRyZXNvbHZlRGVwcyhbLi4uZml4dHVyZS5kZXBzXS5tYXAoKG4pID0+IG4gPT09IGZpeHR1cmUubmFtZSA/IGZpeHR1cmUucGFyZW50IDogcmVnaXN0cmF0aW9ucy5nZXQobikpLmZpbHRlcigobikgPT4gISFuKSwgcmVnaXN0cmF0aW9ucywgZGVwU2V0LCBwZW5kaW5nRml4dHVyZXMpO1xuXHRcdHBlbmRpbmdGaXh0dXJlcy5wdXNoKGZpeHR1cmUpO1xuXHRcdGRlcFNldC5jbGVhcigpO1xuXHR9KTtcblx0cmV0dXJuIHBlbmRpbmdGaXh0dXJlcztcbn1cbmZ1bmN0aW9uIHZhbGlkYXRlU3VpdGVIb29rKGZuLCBob29rLCBzdWl0ZUVycm9yKSB7XG5cdGNvbnN0IHVzZWRQcm9wcyA9IGdldFVzZWRQcm9wcyhmbiwge1xuXHRcdHNvdXJjZUVycm9yOiBzdWl0ZUVycm9yLFxuXHRcdHN1aXRlSG9vazogaG9va1xuXHR9KTtcblx0aWYgKHVzZWRQcm9wcy5zaXplKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBuZXcgRml4dHVyZUFjY2Vzc0Vycm9yKGBUaGUgJHtob29rfSBob29rIHVzZXMgZml4dHVyZXMgXCIke1suLi51c2VkUHJvcHNdLmpvaW4oXCJcXFwiLCBcXFwiXCIpfVwiLCBidXQgaGFzIG5vIGFjY2VzcyB0byBjb250ZXh0LiBgICsgYERpZCB5b3UgZm9yZ2V0IHRvIGNhbGwgaXQgYXMgXCJ0ZXN0LiR7aG9va30oKVwiIGluc3RlYWQgb2YgXCIke2hvb2t9KClcIj9cXG5gICsgYElmIHlvdSB1c2VkIGludGVybmFsIFwic3VpdGVcIiB0YXNrIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBwcmV2aW91c2x5LCBhY2Nlc3MgaXQgaW4gdGhlIHNlY29uZCBhcmd1bWVudCBpbnN0ZWFkLiBgICsgYFNlZSBodHRwczovL3ZpdGVzdC5kZXYvZ3VpZGUvdGVzdC1jb250ZXh0I3N1aXRlLWxldmVsLWhvb2tzYCk7XG5cdFx0aWYgKHN1aXRlRXJyb3IpIHtcblx0XHRcdGVycm9yLnN0YWNrID0gc3VpdGVFcnJvci5zdGFjaz8ucmVwbGFjZShzdWl0ZUVycm9yLm1lc3NhZ2UsIGVycm9yLm1lc3NhZ2UpO1xuXHRcdH1cblx0XHR0aHJvdyBlcnJvcjtcblx0fVxufVxuY29uc3Qga1Byb3BzU3ltYm9sID0gU3ltYm9sKFwiJHZpdGVzdDpmaXh0dXJlLXByb3BzXCIpO1xuY29uc3Qga1Byb3BOYW1lc1N5bWJvbCA9IFN5bWJvbChcIiR2aXRlc3Q6Zml4dHVyZS1wcm9wLW5hbWVzXCIpO1xuZnVuY3Rpb24gY29uZmlndXJlUHJvcHMoZm4sIG9wdGlvbnMpIHtcblx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGZuLCBrUHJvcHNTeW1ib2wsIHtcblx0XHR2YWx1ZTogb3B0aW9ucyxcblx0XHRlbnVtZXJhYmxlOiBmYWxzZVxuXHR9KTtcbn1cbmZ1bmN0aW9uIG1lbW9Qcm9wcyhmbiwgcHJvcHMpIHtcblx0Zm5ba1Byb3BOYW1lc1N5bWJvbF0gPSBwcm9wcztcblx0cmV0dXJuIHByb3BzO1xufVxuZnVuY3Rpb24gZ2V0VXNlZFByb3BzKGZuLCB7IHNvdXJjZUVycm9yLCBzdWl0ZUhvb2sgfSA9IHt9KSB7XG5cdGlmIChrUHJvcE5hbWVzU3ltYm9sIGluIGZuKSB7XG5cdFx0cmV0dXJuIGZuW2tQcm9wTmFtZXNTeW1ib2xdO1xuXHR9XG5cdGNvbnN0IHsgaW5kZXg6IGZpeHR1cmVzSW5kZXggPSAwLCBvcmlnaW5hbDogaW1wbGVtZW50YXRpb24gPSBmbiB9ID0ga1Byb3BzU3ltYm9sIGluIGZuID8gZm5ba1Byb3BzU3ltYm9sXSA6IHt9O1xuXHRsZXQgZm5TdHJpbmcgPSBmaWx0ZXJPdXRDb21tZW50cyhpbXBsZW1lbnRhdGlvbi50b1N0cmluZygpKTtcblx0Ly8gbWF0Y2ggbG93ZXJlZCBhc3luYyBmdW5jdGlvbiBhbmQgc3RyaXAgaXQgb2ZmXG5cdC8vIGV4YW1wbGUgY29kZSBvbiBlc2J1aWxkLXRyeSBodHRwczovL2VzYnVpbGQuZ2l0aHViLmlvL3RyeS8jWWdBd0xqSTBMakFBTFMxemRYQndiM0owWldRNllYTjVibU10WVhkaGFYUTlabUZzYzJVQVpRQmxiblJ5ZVM1MGN3QmpiMjV6ZENCdklEMGdld29nSUdZeE9pQmhjM2x1WXlBb0tTQTlQaUI3ZlN3S0lDQm1Nam9nWVhONWJtTWdLR0VwSUQwK0lIdDlMQW9nSUdZek9pQmhjM2x1WXlBb1lTd2dZaWtnUFQ0Z2UzMHNDaUFnWmpRNklHRnplVzVqSUdaMWJtTjBhVzl1S0dFcElIdDlMQW9nSUdZMU9pQmhjM2x1WXlCbWRXNWpkR2x2YmlCbVppaGhLU0I3ZlN3S0lDQmhjM2x1WXlCbU5paGhLU0I3ZlN3S0NpQWdaekU2SUdGemVXNWpJQ2dwSUQwK0lIdDlMQW9nSUdjeU9pQmhjM2x1WXlBb2V5QmhJSDBwSUQwK0lIdDlMQW9nSUdjek9pQmhjM2x1WXlBb2V5QmhJSDBzSUdJcElEMCtJSHQ5TEFvZ0lHYzBPaUJoYzNsdVl5Qm1kVzVqZEdsdmJpQW9leUJoSUgwcElIdDlMQW9nSUdjMU9pQmhjM2x1WXlCbWRXNWpkR2x2YmlCblp5aDdJR0VnZlNrZ2UzMHNDaUFnWVhONWJtTWdaellvZXlCaElIMHBJSHQ5TEFvS0lDQm9NVG9nWVhONWJtTWdLQ2tnUFQ0Z2UzMHNDaUFnTHk4Z1kyOXRiV1Z1ZENCaVpYUjNaV1Z1Q2lBZ2FESTZJR0Z6ZVc1aklDaGhLU0E5UGlCN2ZTd0tmUVxuXHQvLyAgIF9fYXN5bmModGhpcywgbnVsbCwgZnVuY3Rpb24qXG5cdC8vICAgX19hc3luYyh0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKlxuXHQvLyAgIF9fYXN5bmModGhpcywgW18wLCBfMV0sIGZ1bmN0aW9uKlxuXHRpZiAoL19fYXN5bmNcXCgoPzp0aGlzfG51bGwpLCAoPzpudWxsfGFyZ3VtZW50c3xcXFtbXzAtOSwgXSpcXF0pLCBmdW5jdGlvblxcKi8udGVzdChmblN0cmluZykpIHtcblx0XHRmblN0cmluZyA9IGZuU3RyaW5nLnNwbGl0KC9fX2FzeW5jXFwoKD86dGhpc3xudWxsKSwvKVsxXTtcblx0fVxuXHRjb25zdCBtYXRjaCA9IGZuU3RyaW5nLm1hdGNoKC9bXihdKlxcKChbXildKikvKTtcblx0aWYgKCFtYXRjaCkge1xuXHRcdHJldHVybiBtZW1vUHJvcHMoZm4sIG5ldyBTZXQoKSk7XG5cdH1cblx0Y29uc3QgYXJncyA9IHNwbGl0QnlDb21tYShtYXRjaFsxXSk7XG5cdGlmICghYXJncy5sZW5ndGgpIHtcblx0XHRyZXR1cm4gbWVtb1Byb3BzKGZuLCBuZXcgU2V0KCkpO1xuXHR9XG5cdGNvbnN0IGZpeHR1cmVzQXJndW1lbnQgPSBhcmdzW2ZpeHR1cmVzSW5kZXhdO1xuXHRpZiAoIWZpeHR1cmVzQXJndW1lbnQpIHtcblx0XHRyZXR1cm4gbWVtb1Byb3BzKGZuLCBuZXcgU2V0KCkpO1xuXHR9XG5cdGlmICghKGZpeHR1cmVzQXJndW1lbnRbMF0gPT09IFwie1wiICYmIGZpeHR1cmVzQXJndW1lbnQuZW5kc1dpdGgoXCJ9XCIpKSkge1xuXHRcdGNvbnN0IG9yZGluYWxBcmd1bWVudCA9IG9yZGluYWwoZml4dHVyZXNJbmRleCArIDEpO1xuXHRcdGNvbnN0IGVycm9yID0gbmV3IEZpeHR1cmVQYXJzZUVycm9yKGBUaGUgJHtvcmRpbmFsQXJndW1lbnR9IGFyZ3VtZW50IGluc2lkZSBhIGZpeHR1cmUgbXVzdCB1c2Ugb2JqZWN0IGRlc3RydWN0dXJpbmcgcGF0dGVybiwgZS5nLiAoeyB0YXNrIH0gPT4ge30pLiBgICsgYEluc3RlYWQsIHJlY2VpdmVkIFwiJHtmaXh0dXJlc0FyZ3VtZW50fVwiLmAgKyBgJHtzdWl0ZUhvb2sgPyBgIElmIHlvdSB1c2VkIGludGVybmFsIFwic3VpdGVcIiB0YXNrIGFzIHRoZSAke29yZGluYWxBcmd1bWVudH0gYXJndW1lbnQgcHJldmlvdXNseSwgYWNjZXNzIGl0IGluIHRoZSAke29yZGluYWwoZml4dHVyZXNJbmRleCArIDIpfSBhcmd1bWVudCBpbnN0ZWFkLmAgOiBcIlwifWApO1xuXHRcdGlmIChzb3VyY2VFcnJvcikge1xuXHRcdFx0ZXJyb3Iuc3RhY2sgPSBzb3VyY2VFcnJvci5zdGFjaz8ucmVwbGFjZShzb3VyY2VFcnJvci5tZXNzYWdlLCBlcnJvci5tZXNzYWdlKTtcblx0XHR9XG5cdFx0dGhyb3cgZXJyb3I7XG5cdH1cblx0Y29uc3QgX2ZpcnN0ID0gZml4dHVyZXNBcmd1bWVudC5zbGljZSgxLCAtMSkucmVwbGFjZSgvXFxzL2csIFwiXCIpO1xuXHRjb25zdCBwcm9wcyA9IHNwbGl0QnlDb21tYShfZmlyc3QpLm1hcCgocHJvcCkgPT4ge1xuXHRcdHJldHVybiBwcm9wLnJlcGxhY2UoLzouKnw9LiovZywgXCJcIik7XG5cdH0pO1xuXHRjb25zdCBsYXN0ID0gcHJvcHMuYXQoLTEpO1xuXHRpZiAobGFzdCAmJiBsYXN0LnN0YXJ0c1dpdGgoXCIuLi5cIikpIHtcblx0XHRjb25zdCBlcnJvciA9IG5ldyBGaXh0dXJlUGFyc2VFcnJvcihgUmVzdCBwYXJhbWV0ZXJzIGFyZSBub3Qgc3VwcG9ydGVkIGluIGZpeHR1cmVzLCByZWNlaXZlZCBcIiR7bGFzdH1cIi5gKTtcblx0XHRpZiAoc291cmNlRXJyb3IpIHtcblx0XHRcdGVycm9yLnN0YWNrID0gc291cmNlRXJyb3Iuc3RhY2s/LnJlcGxhY2Uoc291cmNlRXJyb3IubWVzc2FnZSwgZXJyb3IubWVzc2FnZSk7XG5cdFx0fVxuXHRcdHRocm93IGVycm9yO1xuXHR9XG5cdHJldHVybiBtZW1vUHJvcHMoZm4sIG5ldyBTZXQocHJvcHMpKTtcbn1cbmZ1bmN0aW9uIHNwbGl0QnlDb21tYShzKSB7XG5cdGNvbnN0IHJlc3VsdCA9IFtdO1xuXHRjb25zdCBzdGFjayA9IFtdO1xuXHRsZXQgc3RhcnQgPSAwO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IHMubGVuZ3RoOyBpKyspIHtcblx0XHRpZiAoc1tpXSA9PT0gXCJ7XCIgfHwgc1tpXSA9PT0gXCJbXCIpIHtcblx0XHRcdHN0YWNrLnB1c2goc1tpXSA9PT0gXCJ7XCIgPyBcIn1cIiA6IFwiXVwiKTtcblx0XHR9IGVsc2UgaWYgKHNbaV0gPT09IHN0YWNrLmF0KC0xKSkge1xuXHRcdFx0c3RhY2sucG9wKCk7XG5cdFx0fSBlbHNlIGlmICghc3RhY2subGVuZ3RoICYmIHNbaV0gPT09IFwiLFwiKSB7XG5cdFx0XHRjb25zdCB0b2tlbiA9IHMuc3Vic3RyaW5nKHN0YXJ0LCBpKS50cmltKCk7XG5cdFx0XHRpZiAodG9rZW4pIHtcblx0XHRcdFx0cmVzdWx0LnB1c2godG9rZW4pO1xuXHRcdFx0fVxuXHRcdFx0c3RhcnQgPSBpICsgMTtcblx0XHR9XG5cdH1cblx0Y29uc3QgbGFzdFRva2VuID0gcy5zdWJzdHJpbmcoc3RhcnQpLnRyaW0oKTtcblx0aWYgKGxhc3RUb2tlbikge1xuXHRcdHJlc3VsdC5wdXNoKGxhc3RUb2tlbik7XG5cdH1cblx0cmV0dXJuIHJlc3VsdDtcbn1cblxubGV0IF90ZXN0O1xuZnVuY3Rpb24gc2V0Q3VycmVudFRlc3QodGVzdCkge1xuXHRfdGVzdCA9IHRlc3Q7XG59XG5mdW5jdGlvbiBnZXRDdXJyZW50VGVzdCgpIHtcblx0cmV0dXJuIF90ZXN0O1xufVxuY29uc3QgdGVzdHMgPSBbXTtcbmZ1bmN0aW9uIGFkZFJ1bm5pbmdUZXN0KHRlc3QpIHtcblx0dGVzdHMucHVzaCh0ZXN0KTtcblx0cmV0dXJuICgpID0+IHtcblx0XHR0ZXN0cy5zcGxpY2UodGVzdHMuaW5kZXhPZih0ZXN0KSk7XG5cdH07XG59XG5mdW5jdGlvbiBnZXRSdW5uaW5nVGVzdHMoKSB7XG5cdHJldHVybiB0ZXN0cztcbn1cblxuY29uc3Qga0NoYWluYWJsZUNvbnRleHQgPSBTeW1ib2woXCJrQ2hhaW5hYmxlQ29udGV4dFwiKTtcbmZ1bmN0aW9uIGdldENoYWluYWJsZUNvbnRleHQoY2hhaW5hYmxlKSB7XG5cdHJldHVybiBjaGFpbmFibGU/LltrQ2hhaW5hYmxlQ29udGV4dF07XG59XG5mdW5jdGlvbiBjcmVhdGVDaGFpbmFibGUoa2V5cywgZm4sIGNvbnRleHQpIHtcblx0ZnVuY3Rpb24gY3JlYXRlKGNvbnRleHQpIHtcblx0XHRjb25zdCBjaGFpbiA9IGZ1bmN0aW9uKC4uLmFyZ3MpIHtcblx0XHRcdHJldHVybiBmbi5hcHBseShjb250ZXh0LCBhcmdzKTtcblx0XHR9O1xuXHRcdE9iamVjdC5hc3NpZ24oY2hhaW4sIGZuKTtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhaW4sIGtDaGFpbmFibGVDb250ZXh0LCB7XG5cdFx0XHR2YWx1ZToge1xuXHRcdFx0XHR3aXRoQ29udGV4dDogKCkgPT4gY2hhaW4uYmluZChjb250ZXh0KSxcblx0XHRcdFx0Z2V0Rml4dHVyZXM6ICgpID0+IGNvbnRleHQuZml4dHVyZXMsXG5cdFx0XHRcdHNldENvbnRleHQ6IChrZXksIHZhbHVlKSA9PiB7XG5cdFx0XHRcdFx0Y29udGV4dFtrZXldID0gdmFsdWU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdG1lcmdlQ29udGV4dDogKGN0eCkgPT4ge1xuXHRcdFx0XHRcdE9iamVjdC5hc3NpZ24oY29udGV4dCwgY3R4KTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGVudW1lcmFibGU6IGZhbHNlXG5cdFx0fSk7XG5cdFx0Zm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGNoYWluLCBrZXksIHsgZ2V0KCkge1xuXHRcdFx0XHRyZXR1cm4gY3JlYXRlKHtcblx0XHRcdFx0XHQuLi5jb250ZXh0LFxuXHRcdFx0XHRcdFtrZXldOiB0cnVlXG5cdFx0XHRcdH0pO1xuXHRcdFx0fSB9KTtcblx0XHR9XG5cdFx0cmV0dXJuIGNoYWluO1xuXHR9XG5cdGNvbnN0IGNoYWluID0gY3JlYXRlKGNvbnRleHQgPz8ge30pO1xuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoY2hhaW4sIFwiZm5cIiwge1xuXHRcdHZhbHVlOiBmbixcblx0XHRlbnVtZXJhYmxlOiBmYWxzZVxuXHR9KTtcblx0cmV0dXJuIGNoYWluO1xufVxuXG5mdW5jdGlvbiBnZXREZWZhdWx0SG9va1RpbWVvdXQoKSB7XG5cdHJldHVybiBnZXRSdW5uZXIoKS5jb25maWcuaG9va1RpbWVvdXQ7XG59XG5jb25zdCBDTEVBTlVQX1RJTUVPVVRfS0VZID0gU3ltYm9sLmZvcihcIlZJVEVTVF9DTEVBTlVQX1RJTUVPVVRcIik7XG5jb25zdCBDTEVBTlVQX1NUQUNLX1RSQUNFX0tFWSA9IFN5bWJvbC5mb3IoXCJWSVRFU1RfQ0xFQU5VUF9TVEFDS19UUkFDRVwiKTtcbmNvbnN0IEFST1VORF9USU1FT1VUX0tFWSA9IFN5bWJvbC5mb3IoXCJWSVRFU1RfQVJPVU5EX1RJTUVPVVRcIik7XG5jb25zdCBBUk9VTkRfU1RBQ0tfVFJBQ0VfS0VZID0gU3ltYm9sLmZvcihcIlZJVEVTVF9BUk9VTkRfU1RBQ0tfVFJBQ0VcIik7XG5mdW5jdGlvbiBnZXRCZWZvcmVIb29rQ2xlYW51cENhbGxiYWNrKGhvb2ssIHJlc3VsdCwgY29udGV4dCkge1xuXHRpZiAodHlwZW9mIHJlc3VsdCA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0Y29uc3QgdGltZW91dCA9IENMRUFOVVBfVElNRU9VVF9LRVkgaW4gaG9vayAmJiB0eXBlb2YgaG9va1tDTEVBTlVQX1RJTUVPVVRfS0VZXSA9PT0gXCJudW1iZXJcIiA/IGhvb2tbQ0xFQU5VUF9USU1FT1VUX0tFWV0gOiBnZXREZWZhdWx0SG9va1RpbWVvdXQoKTtcblx0XHRjb25zdCBzdGFja1RyYWNlRXJyb3IgPSBDTEVBTlVQX1NUQUNLX1RSQUNFX0tFWSBpbiBob29rICYmIGhvb2tbQ0xFQU5VUF9TVEFDS19UUkFDRV9LRVldIGluc3RhbmNlb2YgRXJyb3IgPyBob29rW0NMRUFOVVBfU1RBQ0tfVFJBQ0VfS0VZXSA6IHVuZGVmaW5lZDtcblx0XHRyZXR1cm4gd2l0aFRpbWVvdXQocmVzdWx0LCB0aW1lb3V0LCB0cnVlLCBzdGFja1RyYWNlRXJyb3IsIChfLCBlcnJvcikgPT4ge1xuXHRcdFx0aWYgKGNvbnRleHQpIHtcblx0XHRcdFx0YWJvcnRDb250ZXh0U2lnbmFsKGNvbnRleHQsIGVycm9yKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxufVxuLyoqXG4qIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIG9uY2UgYmVmb3JlIGFsbCB0ZXN0cyB3aXRoaW4gdGhlIGN1cnJlbnQgc3VpdGUuXG4qIFRoaXMgaG9vayBpcyB1c2VmdWwgZm9yIHNjZW5hcmlvcyB3aGVyZSB5b3UgbmVlZCB0byBwZXJmb3JtIHNldHVwIG9wZXJhdGlvbnMgdGhhdCBhcmUgY29tbW9uIHRvIGFsbCB0ZXN0cyBpbiBhIHN1aXRlLCBzdWNoIGFzIGluaXRpYWxpemluZyBhIGRhdGFiYXNlIGNvbm5lY3Rpb24gb3Igc2V0dGluZyB1cCBhIHRlc3QgZW52aXJvbm1lbnQuXG4qXG4qICoqTm90ZToqKiBUaGUgYGJlZm9yZUFsbGAgaG9va3MgYXJlIGV4ZWN1dGVkIGluIHRoZSBvcmRlciB0aGV5IGFyZSBkZWZpbmVkIG9uZSBhZnRlciBhbm90aGVyLiBZb3UgY2FuIGNvbmZpZ3VyZSB0aGlzIGJ5IGNoYW5naW5nIHRoZSBgc2VxdWVuY2UuaG9va3NgIG9wdGlvbiBpbiB0aGUgY29uZmlnIGZpbGUuXG4qXG4qIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGJlZm9yZSBhbGwgdGVzdHMuXG4qIEBwYXJhbSB7bnVtYmVyfSBbdGltZW91dF0gLSBPcHRpb25hbCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgdGhlIGhvb2suIElmIG5vdCBwcm92aWRlZCwgdGhlIGRlZmF1bHQgaG9vayB0aW1lb3V0IGZyb20gdGhlIHJ1bm5lcidzIGNvbmZpZ3VyYXRpb24gaXMgdXNlZC5cbiogQHJldHVybnMge3ZvaWR9XG4qIEBleGFtcGxlXG4qIGBgYHRzXG4qIC8vIEV4YW1wbGUgb2YgdXNpbmcgYmVmb3JlQWxsIHRvIHNldCB1cCBhIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiogYmVmb3JlQWxsKGFzeW5jICgpID0+IHtcbiogICBhd2FpdCBkYXRhYmFzZS5jb25uZWN0KCk7XG4qIH0pO1xuKiBgYGBcbiovXG5mdW5jdGlvbiBiZWZvcmVBbGwoZm4sIHRpbWVvdXQgPSBnZXREZWZhdWx0SG9va1RpbWVvdXQoKSkge1xuXHRhc3NlcnRUeXBlcyhmbiwgXCJcXFwiYmVmb3JlQWxsXFxcIiBjYWxsYmFja1wiLCBbXCJmdW5jdGlvblwiXSk7XG5cdGNvbnN0IHN0YWNrVHJhY2VFcnJvciA9IG5ldyBFcnJvcihcIlNUQUNLX1RSQUNFX0VSUk9SXCIpO1xuXHRjb25zdCBjb250ZXh0ID0gZ2V0Q2hhaW5hYmxlQ29udGV4dCh0aGlzKTtcblx0cmV0dXJuIGdldEN1cnJlbnRTdWl0ZSgpLm9uKFwiYmVmb3JlQWxsXCIsIE9iamVjdC5hc3NpZ24od2l0aFRpbWVvdXQod2l0aFN1aXRlRml4dHVyZXMoXCJiZWZvcmVBbGxcIiwgZm4sIGNvbnRleHQsIHN0YWNrVHJhY2VFcnJvciksIHRpbWVvdXQsIHRydWUsIHN0YWNrVHJhY2VFcnJvciksIHtcblx0XHRbQ0xFQU5VUF9USU1FT1VUX0tFWV06IHRpbWVvdXQsXG5cdFx0W0NMRUFOVVBfU1RBQ0tfVFJBQ0VfS0VZXTogc3RhY2tUcmFjZUVycm9yXG5cdH0pKTtcbn1cbi8qKlxuKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmNlIGFmdGVyIGFsbCB0ZXN0cyB3aXRoaW4gdGhlIGN1cnJlbnQgc3VpdGUgaGF2ZSBjb21wbGV0ZWQuXG4qIFRoaXMgaG9vayBpcyB1c2VmdWwgZm9yIHNjZW5hcmlvcyB3aGVyZSB5b3UgbmVlZCB0byBwZXJmb3JtIGNsZWFudXAgb3BlcmF0aW9ucyBhZnRlciBhbGwgdGVzdHMgaW4gYSBzdWl0ZSBoYXZlIHJ1biwgc3VjaCBhcyBjbG9zaW5nIGRhdGFiYXNlIGNvbm5lY3Rpb25zIG9yIGNsZWFuaW5nIHVwIHRlbXBvcmFyeSBmaWxlcy5cbipcbiogKipOb3RlOioqIFRoZSBgYWZ0ZXJBbGxgIGhvb2tzIGFyZSBydW5uaW5nIGluIHJldmVyc2Ugb3JkZXIgb2YgdGhlaXIgcmVnaXN0cmF0aW9uLiBZb3UgY2FuIGNvbmZpZ3VyZSB0aGlzIGJ5IGNoYW5naW5nIHRoZSBgc2VxdWVuY2UuaG9va3NgIG9wdGlvbiBpbiB0aGUgY29uZmlnIGZpbGUuXG4qXG4qIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGFmdGVyIGFsbCB0ZXN0cy5cbiogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0XSAtIE9wdGlvbmFsIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciB0aGUgaG9vay4gSWYgbm90IHByb3ZpZGVkLCB0aGUgZGVmYXVsdCBob29rIHRpbWVvdXQgZnJvbSB0aGUgcnVubmVyJ3MgY29uZmlndXJhdGlvbiBpcyB1c2VkLlxuKiBAcmV0dXJucyB7dm9pZH1cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRXhhbXBsZSBvZiB1c2luZyBhZnRlckFsbCB0byBjbG9zZSBhIGRhdGFiYXNlIGNvbm5lY3Rpb25cbiogYWZ0ZXJBbGwoYXN5bmMgKCkgPT4ge1xuKiAgIGF3YWl0IGRhdGFiYXNlLmRpc2Nvbm5lY3QoKTtcbiogfSk7XG4qIGBgYFxuKi9cbmZ1bmN0aW9uIGFmdGVyQWxsKGZuLCB0aW1lb3V0KSB7XG5cdGFzc2VydFR5cGVzKGZuLCBcIlxcXCJhZnRlckFsbFxcXCIgY2FsbGJhY2tcIiwgW1wiZnVuY3Rpb25cIl0pO1xuXHRjb25zdCBjb250ZXh0ID0gZ2V0Q2hhaW5hYmxlQ29udGV4dCh0aGlzKTtcblx0Y29uc3Qgc3RhY2tUcmFjZUVycm9yID0gbmV3IEVycm9yKFwiU1RBQ0tfVFJBQ0VfRVJST1JcIik7XG5cdHJldHVybiBnZXRDdXJyZW50U3VpdGUoKS5vbihcImFmdGVyQWxsXCIsIHdpdGhUaW1lb3V0KHdpdGhTdWl0ZUZpeHR1cmVzKFwiYWZ0ZXJBbGxcIiwgZm4sIGNvbnRleHQsIHN0YWNrVHJhY2VFcnJvciksIHRpbWVvdXQgPz8gZ2V0RGVmYXVsdEhvb2tUaW1lb3V0KCksIHRydWUsIHN0YWNrVHJhY2VFcnJvcikpO1xufVxuLyoqXG4qIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGJlZm9yZSBlYWNoIHRlc3Qgd2l0aGluIHRoZSBjdXJyZW50IHN1aXRlLlxuKiBUaGlzIGhvb2sgaXMgdXNlZnVsIGZvciBzY2VuYXJpb3Mgd2hlcmUgeW91IG5lZWQgdG8gcmVzZXQgb3IgcmVpbml0aWFsaXplIHRoZSB0ZXN0IGVudmlyb25tZW50IGJlZm9yZSBlYWNoIHRlc3QgcnVucywgc3VjaCBhcyByZXNldHRpbmcgZGF0YWJhc2Ugc3RhdGVzLCBjbGVhcmluZyBjYWNoZXMsIG9yIHJlaW5pdGlhbGl6aW5nIHZhcmlhYmxlcy5cbipcbiogKipOb3RlOioqIFRoZSBgYmVmb3JlRWFjaGAgaG9va3MgYXJlIGV4ZWN1dGVkIGluIHRoZSBvcmRlciB0aGV5IGFyZSBkZWZpbmVkIG9uZSBhZnRlciBhbm90aGVyLiBZb3UgY2FuIGNvbmZpZ3VyZSB0aGlzIGJ5IGNoYW5naW5nIHRoZSBgc2VxdWVuY2UuaG9va3NgIG9wdGlvbiBpbiB0aGUgY29uZmlnIGZpbGUuXG4qXG4qIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGJlZm9yZSBlYWNoIHRlc3QuIFRoaXMgZnVuY3Rpb24gcmVjZWl2ZXMgYW4gYFRlc3RDb250ZXh0YCBwYXJhbWV0ZXIgaWYgYWRkaXRpb25hbCB0ZXN0IGNvbnRleHQgaXMgbmVlZGVkLlxuKiBAcGFyYW0ge251bWJlcn0gW3RpbWVvdXRdIC0gT3B0aW9uYWwgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgZm9yIHRoZSBob29rLiBJZiBub3QgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGhvb2sgdGltZW91dCBmcm9tIHRoZSBydW5uZXIncyBjb25maWd1cmF0aW9uIGlzIHVzZWQuXG4qIEByZXR1cm5zIHt2b2lkfVxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBFeGFtcGxlIG9mIHVzaW5nIGJlZm9yZUVhY2ggdG8gcmVzZXQgYSBkYXRhYmFzZSBzdGF0ZVxuKiBiZWZvcmVFYWNoKGFzeW5jICgpID0+IHtcbiogICBhd2FpdCBkYXRhYmFzZS5yZXNldCgpO1xuKiB9KTtcbiogYGBgXG4qL1xuZnVuY3Rpb24gYmVmb3JlRWFjaChmbiwgdGltZW91dCA9IGdldERlZmF1bHRIb29rVGltZW91dCgpKSB7XG5cdGFzc2VydFR5cGVzKGZuLCBcIlxcXCJiZWZvcmVFYWNoXFxcIiBjYWxsYmFja1wiLCBbXCJmdW5jdGlvblwiXSk7XG5cdGNvbnN0IHN0YWNrVHJhY2VFcnJvciA9IG5ldyBFcnJvcihcIlNUQUNLX1RSQUNFX0VSUk9SXCIpO1xuXHRjb25zdCB3cmFwcGVyID0gKGNvbnRleHQsIHN1aXRlKSA9PiB7XG5cdFx0Y29uc3QgZml4dHVyZVJlc29sdmVyID0gd2l0aEZpeHR1cmVzKGZuLCB7IHN1aXRlIH0pO1xuXHRcdHJldHVybiBmaXh0dXJlUmVzb2x2ZXIoY29udGV4dCk7XG5cdH07XG5cdHJldHVybiBnZXRDdXJyZW50U3VpdGUoKS5vbihcImJlZm9yZUVhY2hcIiwgT2JqZWN0LmFzc2lnbih3aXRoVGltZW91dCh3cmFwcGVyLCB0aW1lb3V0ID8/IGdldERlZmF1bHRIb29rVGltZW91dCgpLCB0cnVlLCBzdGFja1RyYWNlRXJyb3IsIGFib3J0SWZUaW1lb3V0KSwge1xuXHRcdFtDTEVBTlVQX1RJTUVPVVRfS0VZXTogdGltZW91dCxcblx0XHRbQ0xFQU5VUF9TVEFDS19UUkFDRV9LRVldOiBzdGFja1RyYWNlRXJyb3Jcblx0fSkpO1xufVxuLyoqXG4qIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGFmdGVyIGVhY2ggdGVzdCB3aXRoaW4gdGhlIGN1cnJlbnQgc3VpdGUgaGFzIGNvbXBsZXRlZC5cbiogVGhpcyBob29rIGlzIHVzZWZ1bCBmb3Igc2NlbmFyaW9zIHdoZXJlIHlvdSBuZWVkIHRvIGNsZWFuIHVwIG9yIHJlc2V0IHRoZSB0ZXN0IGVudmlyb25tZW50IGFmdGVyIGVhY2ggdGVzdCBydW5zLCBzdWNoIGFzIGRlbGV0aW5nIHRlbXBvcmFyeSBmaWxlcywgY2xlYXJpbmcgdGVzdC1zcGVjaWZpYyBkYXRhYmFzZSBlbnRyaWVzLCBvciByZXNldHRpbmcgbW9ja2VkIGZ1bmN0aW9ucy5cbipcbiogKipOb3RlOioqIFRoZSBgYWZ0ZXJFYWNoYCBob29rcyBhcmUgcnVubmluZyBpbiByZXZlcnNlIG9yZGVyIG9mIHRoZWlyIHJlZ2lzdHJhdGlvbi4gWW91IGNhbiBjb25maWd1cmUgdGhpcyBieSBjaGFuZ2luZyB0aGUgYHNlcXVlbmNlLmhvb2tzYCBvcHRpb24gaW4gdGhlIGNvbmZpZyBmaWxlLlxuKlxuKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBhZnRlciBlYWNoIHRlc3QuIFRoaXMgZnVuY3Rpb24gcmVjZWl2ZXMgYW4gYFRlc3RDb250ZXh0YCBwYXJhbWV0ZXIgaWYgYWRkaXRpb25hbCB0ZXN0IGNvbnRleHQgaXMgbmVlZGVkLlxuKiBAcGFyYW0ge251bWJlcn0gW3RpbWVvdXRdIC0gT3B0aW9uYWwgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgZm9yIHRoZSBob29rLiBJZiBub3QgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGhvb2sgdGltZW91dCBmcm9tIHRoZSBydW5uZXIncyBjb25maWd1cmF0aW9uIGlzIHVzZWQuXG4qIEByZXR1cm5zIHt2b2lkfVxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBFeGFtcGxlIG9mIHVzaW5nIGFmdGVyRWFjaCB0byBkZWxldGUgdGVtcG9yYXJ5IGZpbGVzIGNyZWF0ZWQgZHVyaW5nIGEgdGVzdFxuKiBhZnRlckVhY2goYXN5bmMgKCkgPT4ge1xuKiAgIGF3YWl0IGZpbGVTeXN0ZW0uZGVsZXRlVGVtcEZpbGVzKCk7XG4qIH0pO1xuKiBgYGBcbiovXG5mdW5jdGlvbiBhZnRlckVhY2goZm4sIHRpbWVvdXQpIHtcblx0YXNzZXJ0VHlwZXMoZm4sIFwiXFxcImFmdGVyRWFjaFxcXCIgY2FsbGJhY2tcIiwgW1wiZnVuY3Rpb25cIl0pO1xuXHRjb25zdCB3cmFwcGVyID0gKGNvbnRleHQsIHN1aXRlKSA9PiB7XG5cdFx0Y29uc3QgZml4dHVyZVJlc29sdmVyID0gd2l0aEZpeHR1cmVzKGZuLCB7IHN1aXRlIH0pO1xuXHRcdHJldHVybiBmaXh0dXJlUmVzb2x2ZXIoY29udGV4dCk7XG5cdH07XG5cdHJldHVybiBnZXRDdXJyZW50U3VpdGUoKS5vbihcImFmdGVyRWFjaFwiLCB3aXRoVGltZW91dCh3cmFwcGVyLCB0aW1lb3V0ID8/IGdldERlZmF1bHRIb29rVGltZW91dCgpLCB0cnVlLCBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKSwgYWJvcnRJZlRpbWVvdXQpKTtcbn1cbi8qKlxuKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIGEgdGVzdCBmYWlscyB3aXRoaW4gdGhlIGN1cnJlbnQgc3VpdGUuXG4qIFRoaXMgZnVuY3Rpb24gYWxsb3dzIGZvciBjdXN0b20gYWN0aW9ucyB0byBiZSBwZXJmb3JtZWQgaW4gcmVzcG9uc2UgdG8gdGVzdCBmYWlsdXJlcywgc3VjaCBhcyBsb2dnaW5nLCBjbGVhbnVwLCBvciBhZGRpdGlvbmFsIGRpYWdub3N0aWNzLlxuKlxuKiAqKk5vdGU6KiogVGhlIGBvblRlc3RGYWlsZWRgIGhvb2tzIGFyZSBydW5uaW5nIGluIHJldmVyc2Ugb3JkZXIgb2YgdGhlaXIgcmVnaXN0cmF0aW9uLiBZb3UgY2FuIGNvbmZpZ3VyZSB0aGlzIGJ5IGNoYW5naW5nIHRoZSBgc2VxdWVuY2UuaG9va3NgIG9wdGlvbiBpbiB0aGUgY29uZmlnIGZpbGUuXG4qXG4qIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHVwb24gYSB0ZXN0IGZhaWx1cmUuIFRoZSBmdW5jdGlvbiByZWNlaXZlcyB0aGUgdGVzdCByZXN1bHQgKGluY2x1ZGluZyBlcnJvcnMpLlxuKiBAcGFyYW0ge251bWJlcn0gW3RpbWVvdXRdIC0gT3B0aW9uYWwgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgZm9yIHRoZSBob29rLiBJZiBub3QgcHJvdmlkZWQsIHRoZSBkZWZhdWx0IGhvb2sgdGltZW91dCBmcm9tIHRoZSBydW5uZXIncyBjb25maWd1cmF0aW9uIGlzIHVzZWQuXG4qIEB0aHJvd3Mge0Vycm9yfSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhlIGZ1bmN0aW9uIGlzIG5vdCBjYWxsZWQgd2l0aGluIGEgdGVzdC5cbiogQHJldHVybnMge3ZvaWR9XG4qIEBleGFtcGxlXG4qIGBgYHRzXG4qIC8vIEV4YW1wbGUgb2YgdXNpbmcgb25UZXN0RmFpbGVkIHRvIGxvZyBmYWlsdXJlIGRldGFpbHNcbiogb25UZXN0RmFpbGVkKCh7IGVycm9ycyB9KSA9PiB7XG4qICAgY29uc29sZS5sb2coYFRlc3QgZmFpbGVkOiAke3Rlc3QubmFtZX1gLCBlcnJvcnMpO1xuKiB9KTtcbiogYGBgXG4qL1xuY29uc3Qgb25UZXN0RmFpbGVkID0gY3JlYXRlVGVzdEhvb2soXCJvblRlc3RGYWlsZWRcIiwgKHRlc3QsIGhhbmRsZXIsIHRpbWVvdXQpID0+IHtcblx0dGVzdC5vbkZhaWxlZCB8fD0gW107XG5cdHRlc3Qub25GYWlsZWQucHVzaCh3aXRoVGltZW91dChoYW5kbGVyLCB0aW1lb3V0ID8/IGdldERlZmF1bHRIb29rVGltZW91dCgpLCB0cnVlLCBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKSwgYWJvcnRJZlRpbWVvdXQpKTtcbn0pO1xuLyoqXG4qIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGN1cnJlbnQgdGVzdCBmaW5pc2hlcywgcmVnYXJkbGVzcyBvZiB0aGUgb3V0Y29tZSAocGFzcyBvciBmYWlsKS5cbiogVGhpcyBmdW5jdGlvbiBpcyBpZGVhbCBmb3IgcGVyZm9ybWluZyBhY3Rpb25zIHRoYXQgc2hvdWxkIG9jY3VyIGFmdGVyIGV2ZXJ5IHRlc3QgZXhlY3V0aW9uLCBzdWNoIGFzIGNsZWFudXAsIGxvZ2dpbmcsIG9yIHJlc2V0dGluZyBzaGFyZWQgcmVzb3VyY2VzLlxuKlxuKiBUaGlzIGhvb2sgaXMgdXNlZnVsIGlmIHlvdSBoYXZlIGFjY2VzcyB0byBhIHJlc291cmNlIGluIHRoZSB0ZXN0IGl0c2VsZiBhbmQgeW91IHdhbnQgdG8gY2xlYW4gaXQgdXAgYWZ0ZXIgdGhlIHRlc3QgZmluaXNoZXMuIEl0IGlzIGEgbW9yZSBjb21wYWN0IHdheSB0byBjbGVhbiB1cCByZXNvdXJjZXMgdGhhbiB1c2luZyB0aGUgY29tYmluYXRpb24gb2YgYGJlZm9yZUVhY2hgIGFuZCBgYWZ0ZXJFYWNoYC5cbipcbiogKipOb3RlOioqIFRoZSBgb25UZXN0RmluaXNoZWRgIGhvb2tzIGFyZSBydW5uaW5nIGluIHJldmVyc2Ugb3JkZXIgb2YgdGhlaXIgcmVnaXN0cmF0aW9uLiBZb3UgY2FuIGNvbmZpZ3VyZSB0aGlzIGJ5IGNoYW5naW5nIHRoZSBgc2VxdWVuY2UuaG9va3NgIG9wdGlvbiBpbiB0aGUgY29uZmlnIGZpbGUuXG4qXG4qICoqTm90ZToqKiBUaGUgYG9uVGVzdEZpbmlzaGVkYCBob29rIGlzIG5vdCBjYWxsZWQgaWYgdGhlIHRlc3QgaXMgY2FuY2VsZWQgd2l0aCBhIGR5bmFtaWMgYGN0eC5za2lwKClgIGNhbGwuXG4qXG4qIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIGFmdGVyIGEgdGVzdCBmaW5pc2hlcy4gVGhlIGZ1bmN0aW9uIGNhbiByZWNlaXZlIHBhcmFtZXRlcnMgcHJvdmlkaW5nIGRldGFpbHMgYWJvdXQgdGhlIGNvbXBsZXRlZCB0ZXN0LCBpbmNsdWRpbmcgaXRzIHN1Y2Nlc3Mgb3IgZmFpbHVyZSBzdGF0dXMuXG4qIEBwYXJhbSB7bnVtYmVyfSBbdGltZW91dF0gLSBPcHRpb25hbCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcyBmb3IgdGhlIGhvb2suIElmIG5vdCBwcm92aWRlZCwgdGhlIGRlZmF1bHQgaG9vayB0aW1lb3V0IGZyb20gdGhlIHJ1bm5lcidzIGNvbmZpZ3VyYXRpb24gaXMgdXNlZC5cbiogQHRocm93cyB7RXJyb3J9IFRocm93cyBhbiBlcnJvciBpZiB0aGUgZnVuY3Rpb24gaXMgbm90IGNhbGxlZCB3aXRoaW4gYSB0ZXN0LlxuKiBAcmV0dXJucyB7dm9pZH1cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRXhhbXBsZSBvZiB1c2luZyBvblRlc3RGaW5pc2hlZCBmb3IgY2xlYW51cFxuKiBjb25zdCBkYiA9IGF3YWl0IGNvbm5lY3RUb0RhdGFiYXNlKCk7XG4qIG9uVGVzdEZpbmlzaGVkKGFzeW5jICgpID0+IHtcbiogICBhd2FpdCBkYi5kaXNjb25uZWN0KCk7XG4qIH0pO1xuKiBgYGBcbiovXG5jb25zdCBvblRlc3RGaW5pc2hlZCA9IGNyZWF0ZVRlc3RIb29rKFwib25UZXN0RmluaXNoZWRcIiwgKHRlc3QsIGhhbmRsZXIsIHRpbWVvdXQpID0+IHtcblx0dGVzdC5vbkZpbmlzaGVkIHx8PSBbXTtcblx0dGVzdC5vbkZpbmlzaGVkLnB1c2god2l0aFRpbWVvdXQoaGFuZGxlciwgdGltZW91dCA/PyBnZXREZWZhdWx0SG9va1RpbWVvdXQoKSwgdHJ1ZSwgbmV3IEVycm9yKFwiU1RBQ0tfVFJBQ0VfRVJST1JcIiksIGFib3J0SWZUaW1lb3V0KSk7XG59KTtcbi8qKlxuKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IHdyYXBzIGFyb3VuZCBhbGwgdGVzdHMgd2l0aGluIHRoZSBjdXJyZW50IHN1aXRlLlxuKiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgYSBgcnVuU3VpdGVgIGZ1bmN0aW9uIHRoYXQgbXVzdCBiZSBjYWxsZWQgdG8gcnVuIHRoZSBzdWl0ZSdzIHRlc3RzLlxuKiBUaGlzIGhvb2sgaXMgdXNlZnVsIGZvciBzY2VuYXJpb3Mgd2hlcmUgeW91IG5lZWQgdG8gd3JhcCBhbiBlbnRpcmUgc3VpdGUgaW4gYSBjb250ZXh0XG4qIChlLmcuLCBzdGFydGluZyBhIHNlcnZlciwgb3BlbmluZyBhIGRhdGFiYXNlIGNvbm5lY3Rpb24gdGhhdCBhbGwgdGVzdHMgc2hhcmUpLlxuKlxuKiAqKk5vdGU6KiogV2hlbiBtdWx0aXBsZSBgYXJvdW5kQWxsYCBob29rcyBhcmUgcmVnaXN0ZXJlZCwgdGhleSBhcmUgbmVzdGVkIGluc2lkZSBlYWNoIG90aGVyLlxuKiBUaGUgZmlyc3QgcmVnaXN0ZXJlZCBob29rIGlzIHRoZSBvdXRlcm1vc3Qgd3JhcHBlci5cbipcbiogQHBhcmFtIHtGdW5jdGlvbn0gZm4gLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCB3cmFwcyB0aGUgc3VpdGUuIE11c3QgY2FsbCBgcnVuU3VpdGUoKWAgdG8gcnVuIHRoZSB0ZXN0cy5cbiogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0XSAtIE9wdGlvbmFsIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciB0aGUgaG9vay4gSWYgbm90IHByb3ZpZGVkLCB0aGUgZGVmYXVsdCBob29rIHRpbWVvdXQgZnJvbSB0aGUgcnVubmVyJ3MgY29uZmlndXJhdGlvbiBpcyB1c2VkLlxuKiBAcmV0dXJucyB7dm9pZH1cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRXhhbXBsZSBvZiB1c2luZyBhcm91bmRBbGwgdG8gd3JhcCBzdWl0ZSBpbiBhIHRyYWNpbmcgc3BhblxuKiBhcm91bmRBbGwoYXN5bmMgKHJ1blN1aXRlKSA9PiB7XG4qICAgYXdhaXQgdHJhY2VyLnRyYWNlKCd0ZXN0LXN1aXRlJywgcnVuU3VpdGUpO1xuKiB9KTtcbiogYGBgXG4qIEBleGFtcGxlXG4qIGBgYHRzXG4qIC8vIEV4YW1wbGUgb2YgdXNpbmcgYXJvdW5kQWxsIHdpdGggZml4dHVyZXNcbiogYXJvdW5kQWxsKGFzeW5jIChydW5TdWl0ZSwgeyBkYiB9KSA9PiB7XG4qICAgYXdhaXQgZGIudHJhbnNhY3Rpb24oKCkgPT4gcnVuU3VpdGUoKSk7XG4qIH0pO1xuKiBgYGBcbiovXG5mdW5jdGlvbiBhcm91bmRBbGwoZm4sIHRpbWVvdXQpIHtcblx0YXNzZXJ0VHlwZXMoZm4sIFwiXFxcImFyb3VuZEFsbFxcXCIgY2FsbGJhY2tcIiwgW1wiZnVuY3Rpb25cIl0pO1xuXHRjb25zdCBzdGFja1RyYWNlRXJyb3IgPSBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKTtcblx0Y29uc3QgcmVzb2x2ZWRUaW1lb3V0ID0gdGltZW91dCA/PyBnZXREZWZhdWx0SG9va1RpbWVvdXQoKTtcblx0Y29uc3QgY29udGV4dCA9IGdldENoYWluYWJsZUNvbnRleHQodGhpcyk7XG5cdHJldHVybiBnZXRDdXJyZW50U3VpdGUoKS5vbihcImFyb3VuZEFsbFwiLCBPYmplY3QuYXNzaWduKHdpdGhTdWl0ZUZpeHR1cmVzKFwiYXJvdW5kQWxsXCIsIGZuLCBjb250ZXh0LCBzdGFja1RyYWNlRXJyb3IsIDEpLCB7XG5cdFx0W0FST1VORF9USU1FT1VUX0tFWV06IHJlc29sdmVkVGltZW91dCxcblx0XHRbQVJPVU5EX1NUQUNLX1RSQUNFX0tFWV06IHN0YWNrVHJhY2VFcnJvclxuXHR9KSk7XG59XG4vKipcbiogUmVnaXN0ZXJzIGEgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCB3cmFwcyBhcm91bmQgZWFjaCB0ZXN0IHdpdGhpbiB0aGUgY3VycmVudCBzdWl0ZS5cbiogVGhlIGNhbGxiYWNrIHJlY2VpdmVzIGEgYHJ1blRlc3RgIGZ1bmN0aW9uIHRoYXQgbXVzdCBiZSBjYWxsZWQgdG8gcnVuIHRoZSB0ZXN0LlxuKiBUaGlzIGhvb2sgaXMgdXNlZnVsIGZvciBzY2VuYXJpb3Mgd2hlcmUgeW91IG5lZWQgdG8gd3JhcCB0ZXN0cyBpbiBhIGNvbnRleHQgKGUuZy4sIGRhdGFiYXNlIHRyYW5zYWN0aW9ucykuXG4qXG4qICoqTm90ZToqKiBXaGVuIG11bHRpcGxlIGBhcm91bmRFYWNoYCBob29rcyBhcmUgcmVnaXN0ZXJlZCwgdGhleSBhcmUgbmVzdGVkIGluc2lkZSBlYWNoIG90aGVyLlxuKiBUaGUgZmlyc3QgcmVnaXN0ZXJlZCBob29rIGlzIHRoZSBvdXRlcm1vc3Qgd3JhcHBlci5cbipcbiogQHBhcmFtIHtGdW5jdGlvbn0gZm4gLSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCB3cmFwcyB0aGUgdGVzdC4gTXVzdCBjYWxsIGBydW5UZXN0KClgIHRvIHJ1biB0aGUgdGVzdC5cbiogQHBhcmFtIHtudW1iZXJ9IFt0aW1lb3V0XSAtIE9wdGlvbmFsIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIGZvciB0aGUgaG9vay4gSWYgbm90IHByb3ZpZGVkLCB0aGUgZGVmYXVsdCBob29rIHRpbWVvdXQgZnJvbSB0aGUgcnVubmVyJ3MgY29uZmlndXJhdGlvbiBpcyB1c2VkLlxuKiBAcmV0dXJucyB7dm9pZH1cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRXhhbXBsZSBvZiB1c2luZyBhcm91bmRFYWNoIHRvIHdyYXAgdGVzdHMgaW4gYSBkYXRhYmFzZSB0cmFuc2FjdGlvblxuKiBhcm91bmRFYWNoKGFzeW5jIChydW5UZXN0KSA9PiB7XG4qICAgYXdhaXQgZGF0YWJhc2UudHJhbnNhY3Rpb24oKCkgPT4gcnVuVGVzdCgpKTtcbiogfSk7XG4qIGBgYFxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBFeGFtcGxlIG9mIHVzaW5nIGFyb3VuZEVhY2ggd2l0aCBmaXh0dXJlc1xuKiBhcm91bmRFYWNoKGFzeW5jIChydW5UZXN0LCB7IGRiIH0pID0+IHtcbiogICBhd2FpdCBkYi50cmFuc2FjdGlvbigoKSA9PiBydW5UZXN0KCkpO1xuKiB9KTtcbiogYGBgXG4qL1xuZnVuY3Rpb24gYXJvdW5kRWFjaChmbiwgdGltZW91dCkge1xuXHRhc3NlcnRUeXBlcyhmbiwgXCJcXFwiYXJvdW5kRWFjaFxcXCIgY2FsbGJhY2tcIiwgW1wiZnVuY3Rpb25cIl0pO1xuXHRjb25zdCBzdGFja1RyYWNlRXJyb3IgPSBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKTtcblx0Y29uc3QgcmVzb2x2ZWRUaW1lb3V0ID0gdGltZW91dCA/PyBnZXREZWZhdWx0SG9va1RpbWVvdXQoKTtcblx0Y29uc3Qgd3JhcHBlciA9IChydW5UZXN0LCBjb250ZXh0LCBzdWl0ZSkgPT4ge1xuXHRcdGNvbnN0IGlubmVyRm4gPSAoY3R4KSA9PiBmbihydW5UZXN0LCBjdHgsIHN1aXRlKTtcblx0XHRjb25maWd1cmVQcm9wcyhpbm5lckZuLCB7XG5cdFx0XHRpbmRleDogMSxcblx0XHRcdG9yaWdpbmFsOiBmblxuXHRcdH0pO1xuXHRcdGNvbnN0IGZpeHR1cmVSZXNvbHZlciA9IHdpdGhGaXh0dXJlcyhpbm5lckZuLCB7IHN1aXRlIH0pO1xuXHRcdHJldHVybiBmaXh0dXJlUmVzb2x2ZXIoY29udGV4dCk7XG5cdH07XG5cdHJldHVybiBnZXRDdXJyZW50U3VpdGUoKS5vbihcImFyb3VuZEVhY2hcIiwgT2JqZWN0LmFzc2lnbih3cmFwcGVyLCB7XG5cdFx0W0FST1VORF9USU1FT1VUX0tFWV06IHJlc29sdmVkVGltZW91dCxcblx0XHRbQVJPVU5EX1NUQUNLX1RSQUNFX0tFWV06IHN0YWNrVHJhY2VFcnJvclxuXHR9KSk7XG59XG5mdW5jdGlvbiB3aXRoU3VpdGVGaXh0dXJlcyhzdWl0ZUhvb2ssIGZuLCBjb250ZXh0LCBzdGFja1RyYWNlRXJyb3IsIGNvbnRleHRJbmRleCA9IDApIHtcblx0cmV0dXJuICguLi5hcmdzKSA9PiB7XG5cdFx0Y29uc3Qgc3VpdGUgPSBhcmdzLmF0KC0xKTtcblx0XHRjb25zdCBwcmVmaXggPSBhcmdzLnNsaWNlKDAsIC0xKTtcblx0XHRjb25zdCB3cmFwcGVyID0gKGN0eCkgPT4gZm4oLi4ucHJlZml4LCBjdHgsIHN1aXRlKTtcblx0XHRjb25maWd1cmVQcm9wcyh3cmFwcGVyLCB7XG5cdFx0XHRpbmRleDogY29udGV4dEluZGV4LFxuXHRcdFx0b3JpZ2luYWw6IGZuXG5cdFx0fSk7XG5cdFx0Y29uc3QgZml4dHVyZXMgPSBjb250ZXh0Py5nZXRGaXh0dXJlcygpO1xuXHRcdGNvbnN0IGZpbGVDb250ZXh0ID0gZml4dHVyZXM/LmdldEZpbGVDb250ZXh0KHN1aXRlLmZpbGUpO1xuXHRcdGNvbnN0IGZpeHR1cmVkID0gd2l0aEZpeHR1cmVzKHdyYXBwZXIsIHtcblx0XHRcdHN1aXRlSG9vayxcblx0XHRcdGZpeHR1cmVzLFxuXHRcdFx0Y29udGV4dDogZmlsZUNvbnRleHQsXG5cdFx0XHRzdGFja1RyYWNlRXJyb3Jcblx0XHR9KTtcblx0XHRyZXR1cm4gZml4dHVyZWQoKTtcblx0fTtcbn1cbmZ1bmN0aW9uIGdldEFyb3VuZEhvb2tUaW1lb3V0KGhvb2spIHtcblx0cmV0dXJuIEFST1VORF9USU1FT1VUX0tFWSBpbiBob29rICYmIHR5cGVvZiBob29rW0FST1VORF9USU1FT1VUX0tFWV0gPT09IFwibnVtYmVyXCIgPyBob29rW0FST1VORF9USU1FT1VUX0tFWV0gOiBnZXREZWZhdWx0SG9va1RpbWVvdXQoKTtcbn1cbmZ1bmN0aW9uIGdldEFyb3VuZEhvb2tTdGFja1RyYWNlKGhvb2spIHtcblx0cmV0dXJuIEFST1VORF9TVEFDS19UUkFDRV9LRVkgaW4gaG9vayAmJiBob29rW0FST1VORF9TVEFDS19UUkFDRV9LRVldIGluc3RhbmNlb2YgRXJyb3IgPyBob29rW0FST1VORF9TVEFDS19UUkFDRV9LRVldIDogdW5kZWZpbmVkO1xufVxuZnVuY3Rpb24gY3JlYXRlVGVzdEhvb2sobmFtZSwgaGFuZGxlcikge1xuXHRyZXR1cm4gKGZuLCB0aW1lb3V0KSA9PiB7XG5cdFx0YXNzZXJ0VHlwZXMoZm4sIGBcIiR7bmFtZX1cIiBjYWxsYmFja2AsIFtcImZ1bmN0aW9uXCJdKTtcblx0XHRjb25zdCBjdXJyZW50ID0gZ2V0Q3VycmVudFRlc3QoKTtcblx0XHRpZiAoIWN1cnJlbnQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgSG9vayAke25hbWV9KCkgY2FuIG9ubHkgYmUgY2FsbGVkIGluc2lkZSBhIHRlc3RgKTtcblx0XHR9XG5cdFx0cmV0dXJuIGhhbmRsZXIoY3VycmVudCwgZm4sIHRpbWVvdXQpO1xuXHR9O1xufVxuXG4vKipcbiogSWYgYW55IHRhc2tzIGJlZW4gbWFya2VkIGFzIGBvbmx5YCwgbWFyayBhbGwgb3RoZXIgdGFza3MgYXMgYHNraXBgLlxuKi9cbmZ1bmN0aW9uIGludGVycHJldFRhc2tNb2RlcyhmaWxlLCBuYW1lUGF0dGVybiwgdGVzdExvY2F0aW9ucywgdGVzdElkcywgdGVzdFRhZ3NGaWx0ZXIsIG9ubHlNb2RlLCBwYXJlbnRJc09ubHksIGFsbG93T25seSkge1xuXHRjb25zdCBtYXRjaGVkTG9jYXRpb25zID0gW107XG5cdGNvbnN0IHRyYXZlcnNlU3VpdGUgPSAoc3VpdGUsIHBhcmVudElzT25seSwgcGFyZW50TWF0Y2hlZFdpdGhMb2NhdGlvbikgPT4ge1xuXHRcdGNvbnN0IHN1aXRlSXNPbmx5ID0gcGFyZW50SXNPbmx5IHx8IHN1aXRlLm1vZGUgPT09IFwib25seVwiO1xuXHRcdC8vIENoZWNrIGlmIGFueSB0YXNrcyBpbiB0aGlzIHN1aXRlIGhhdmUgYC5vbmx5YCAtIGlmIHNvLCBvbmx5IHRob3NlIHNob3VsZCBydW5cblx0XHRjb25zdCBoYXNTb21lVGFza3NPbmx5ID0gb25seU1vZGUgJiYgc3VpdGUudGFza3Muc29tZSgodCkgPT4gdC5tb2RlID09PSBcIm9ubHlcIiB8fCB0LnR5cGUgPT09IFwic3VpdGVcIiAmJiBzb21lVGFza3NBcmVPbmx5KHQpKTtcblx0XHRzdWl0ZS50YXNrcy5mb3JFYWNoKCh0KSA9PiB7XG5cdFx0XHQvLyBDaGVjayBpZiBlaXRoZXIgdGhlIHBhcmVudCBzdWl0ZSBvciB0aGUgdGFzayBpdHNlbGYgYXJlIG1hcmtlZCBhcyBpbmNsdWRlZFxuXHRcdFx0Ly8gSWYgdGhlcmUgYXJlIHRhc2tzIHdpdGggYC5vbmx5YCBpbiB0aGlzIHN1aXRlLCBvbmx5IGluY2x1ZGUgdGhvc2UgKG5vdCBhbGwgdGFza3MgZnJvbSBkZXNjcmliZS5vbmx5KVxuXHRcdFx0Y29uc3QgaW5jbHVkZVRhc2sgPSBoYXNTb21lVGFza3NPbmx5ID8gdC5tb2RlID09PSBcIm9ubHlcIiB8fCB0LnR5cGUgPT09IFwic3VpdGVcIiAmJiBzb21lVGFza3NBcmVPbmx5KHQpIDogc3VpdGVJc09ubHkgfHwgdC5tb2RlID09PSBcIm9ubHlcIjtcblx0XHRcdGlmIChvbmx5TW9kZSkge1xuXHRcdFx0XHRpZiAodC50eXBlID09PSBcInN1aXRlXCIgJiYgKGluY2x1ZGVUYXNrIHx8IHNvbWVUYXNrc0FyZU9ubHkodCkpKSB7XG5cdFx0XHRcdFx0Ly8gRG9uJ3Qgc2tpcCB0aGlzIHN1aXRlXG5cdFx0XHRcdFx0aWYgKHQubW9kZSA9PT0gXCJvbmx5XCIpIHtcblx0XHRcdFx0XHRcdGNoZWNrQWxsb3dPbmx5KHQsIGFsbG93T25seSk7XG5cdFx0XHRcdFx0XHR0Lm1vZGUgPSBcInJ1blwiO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBlbHNlIGlmICh0Lm1vZGUgPT09IFwicnVuXCIgJiYgIWluY2x1ZGVUYXNrKSB7XG5cdFx0XHRcdFx0dC5tb2RlID0gXCJza2lwXCI7XG5cdFx0XHRcdH0gZWxzZSBpZiAodC5tb2RlID09PSBcIm9ubHlcIikge1xuXHRcdFx0XHRcdGNoZWNrQWxsb3dPbmx5KHQsIGFsbG93T25seSk7XG5cdFx0XHRcdFx0dC5tb2RlID0gXCJydW5cIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0bGV0IGhhc0xvY2F0aW9uTWF0Y2ggPSBwYXJlbnRNYXRjaGVkV2l0aExvY2F0aW9uO1xuXHRcdFx0Ly8gTWF0Y2ggdGVzdCBsb2NhdGlvbiBhZ2FpbnN0IHByb3ZpZGVkIGxvY2F0aW9ucywgb25seSBydW4gaWYgcHJlc2VudFxuXHRcdFx0Ly8gaW4gYHRlc3RMb2NhdGlvbnNgLiBOb3RlOiBpZiBgaW5jbHVkZVRhc2tMb2NhdGlvbmAgaXMgbm90IGVuYWJsZWQsXG5cdFx0XHQvLyBhbGwgdGVzdCB3aWxsIGJlIHNraXBwZWQuXG5cdFx0XHRpZiAodGVzdExvY2F0aW9ucyAhPT0gdW5kZWZpbmVkICYmIHRlc3RMb2NhdGlvbnMubGVuZ3RoICE9PSAwKSB7XG5cdFx0XHRcdGlmICh0LmxvY2F0aW9uICYmIHRlc3RMb2NhdGlvbnM/LmluY2x1ZGVzKHQubG9jYXRpb24ubGluZSkpIHtcblx0XHRcdFx0XHR0Lm1vZGUgPSBcInJ1blwiO1xuXHRcdFx0XHRcdG1hdGNoZWRMb2NhdGlvbnMucHVzaCh0LmxvY2F0aW9uLmxpbmUpO1xuXHRcdFx0XHRcdGhhc0xvY2F0aW9uTWF0Y2ggPSB0cnVlO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHBhcmVudE1hdGNoZWRXaXRoTG9jYXRpb24pIHtcblx0XHRcdFx0XHR0Lm1vZGUgPSBcInJ1blwiO1xuXHRcdFx0XHR9IGVsc2UgaWYgKHQudHlwZSA9PT0gXCJ0ZXN0XCIpIHtcblx0XHRcdFx0XHR0Lm1vZGUgPSBcInNraXBcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0aWYgKHQudHlwZSA9PT0gXCJ0ZXN0XCIpIHtcblx0XHRcdFx0aWYgKG5hbWVQYXR0ZXJuICYmICFnZXRUYXNrRnVsbE5hbWUodCkubWF0Y2gobmFtZVBhdHRlcm4pKSB7XG5cdFx0XHRcdFx0dC5tb2RlID0gXCJza2lwXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHRlc3RJZHMgJiYgIXRlc3RJZHMuaW5jbHVkZXModC5pZCkpIHtcblx0XHRcdFx0XHR0Lm1vZGUgPSBcInNraXBcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAodGVzdFRhZ3NGaWx0ZXIgJiYgIXRlc3RUYWdzRmlsdGVyKHQudGFncyB8fCBbXSkpIHtcblx0XHRcdFx0XHR0Lm1vZGUgPSBcInNraXBcIjtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICh0LnR5cGUgPT09IFwic3VpdGVcIikge1xuXHRcdFx0XHRpZiAodC5tb2RlID09PSBcInNraXBcIikge1xuXHRcdFx0XHRcdHNraXBBbGxUYXNrcyh0KTtcblx0XHRcdFx0fSBlbHNlIGlmICh0Lm1vZGUgPT09IFwidG9kb1wiKSB7XG5cdFx0XHRcdFx0dG9kb0FsbFRhc2tzKHQpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRyYXZlcnNlU3VpdGUodCwgaW5jbHVkZVRhc2ssIGhhc0xvY2F0aW9uTWF0Y2gpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0Ly8gaWYgYWxsIHN1YnRhc2tzIGFyZSBza2lwcGVkLCBtYXJrIGFzIHNraXBcblx0XHRpZiAoc3VpdGUubW9kZSA9PT0gXCJydW5cIiB8fCBzdWl0ZS5tb2RlID09PSBcInF1ZXVlZFwiKSB7XG5cdFx0XHRpZiAoc3VpdGUudGFza3MubGVuZ3RoICYmIHN1aXRlLnRhc2tzLmV2ZXJ5KChpKSA9PiBpLm1vZGUgIT09IFwicnVuXCIgJiYgaS5tb2RlICE9PSBcInF1ZXVlZFwiKSkge1xuXHRcdFx0XHRzdWl0ZS5tb2RlID0gXCJza2lwXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXHR0cmF2ZXJzZVN1aXRlKGZpbGUsIHBhcmVudElzT25seSwgZmFsc2UpO1xuXHRjb25zdCBub25NYXRjaGluZyA9IHRlc3RMb2NhdGlvbnM/LmZpbHRlcigobG9jKSA9PiAhbWF0Y2hlZExvY2F0aW9ucy5pbmNsdWRlcyhsb2MpKTtcblx0aWYgKG5vbk1hdGNoaW5nICYmIG5vbk1hdGNoaW5nLmxlbmd0aCAhPT0gMCkge1xuXHRcdGNvbnN0IG1lc3NhZ2UgPSBub25NYXRjaGluZy5sZW5ndGggPT09IDEgPyBgbGluZSAke25vbk1hdGNoaW5nWzBdfWAgOiBgbGluZXMgJHtub25NYXRjaGluZy5qb2luKFwiLCBcIil9YDtcblx0XHRpZiAoZmlsZS5yZXN1bHQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0ZmlsZS5yZXN1bHQgPSB7XG5cdFx0XHRcdHN0YXRlOiBcImZhaWxcIixcblx0XHRcdFx0ZXJyb3JzOiBbXVxuXHRcdFx0fTtcblx0XHR9XG5cdFx0aWYgKGZpbGUucmVzdWx0LmVycm9ycyA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRmaWxlLnJlc3VsdC5lcnJvcnMgPSBbXTtcblx0XHR9XG5cdFx0ZmlsZS5yZXN1bHQuZXJyb3JzLnB1c2gocHJvY2Vzc0Vycm9yKG5ldyBFcnJvcihgTm8gdGVzdCBmb3VuZCBpbiAke2ZpbGUubmFtZX0gaW4gJHttZXNzYWdlfWApKSk7XG5cdH1cbn1cbmZ1bmN0aW9uIGdldFRhc2tGdWxsTmFtZSh0YXNrKSB7XG5cdHJldHVybiBgJHt0YXNrLnN1aXRlID8gYCR7Z2V0VGFza0Z1bGxOYW1lKHRhc2suc3VpdGUpfSBgIDogXCJcIn0ke3Rhc2submFtZX1gO1xufVxuZnVuY3Rpb24gc29tZVRhc2tzQXJlT25seShzdWl0ZSkge1xuXHRyZXR1cm4gc3VpdGUudGFza3Muc29tZSgodCkgPT4gdC5tb2RlID09PSBcIm9ubHlcIiB8fCB0LnR5cGUgPT09IFwic3VpdGVcIiAmJiBzb21lVGFza3NBcmVPbmx5KHQpKTtcbn1cbmZ1bmN0aW9uIHNraXBBbGxUYXNrcyhzdWl0ZSkge1xuXHRzdWl0ZS50YXNrcy5mb3JFYWNoKCh0KSA9PiB7XG5cdFx0aWYgKHQubW9kZSA9PT0gXCJydW5cIiB8fCB0Lm1vZGUgPT09IFwicXVldWVkXCIpIHtcblx0XHRcdHQubW9kZSA9IFwic2tpcFwiO1xuXHRcdFx0aWYgKHQudHlwZSA9PT0gXCJzdWl0ZVwiKSB7XG5cdFx0XHRcdHNraXBBbGxUYXNrcyh0KTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xufVxuZnVuY3Rpb24gdG9kb0FsbFRhc2tzKHN1aXRlKSB7XG5cdHN1aXRlLnRhc2tzLmZvckVhY2goKHQpID0+IHtcblx0XHRpZiAodC5tb2RlID09PSBcInJ1blwiIHx8IHQubW9kZSA9PT0gXCJxdWV1ZWRcIikge1xuXHRcdFx0dC5tb2RlID0gXCJ0b2RvXCI7XG5cdFx0XHRpZiAodC50eXBlID09PSBcInN1aXRlXCIpIHtcblx0XHRcdFx0dG9kb0FsbFRhc2tzKHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5mdW5jdGlvbiBjaGVja0FsbG93T25seSh0YXNrLCBhbGxvd09ubHkpIHtcblx0aWYgKGFsbG93T25seSkge1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBlcnJvciA9IHByb2Nlc3NFcnJvcihuZXcgRXJyb3IoXCJbVml0ZXN0XSBVbmV4cGVjdGVkIC5vbmx5IG1vZGlmaWVyLiBSZW1vdmUgaXQgb3IgcGFzcyAtLWFsbG93T25seSBhcmd1bWVudCB0byBieXBhc3MgdGhpcyBlcnJvclwiKSk7XG5cdHRhc2sucmVzdWx0ID0ge1xuXHRcdHN0YXRlOiBcImZhaWxcIixcblx0XHRlcnJvcnM6IFtlcnJvcl1cblx0fTtcbn1cbi8qIEBfX05PX1NJREVfRUZGRUNUU19fICovXG5mdW5jdGlvbiBnZW5lcmF0ZUhhc2goc3RyKSB7XG5cdGxldCBoYXNoID0gMDtcblx0aWYgKHN0ci5sZW5ndGggPT09IDApIHtcblx0XHRyZXR1cm4gYCR7aGFzaH1gO1xuXHR9XG5cdGZvciAobGV0IGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG5cdFx0Y29uc3QgY2hhciA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuXHRcdGhhc2ggPSAoaGFzaCA8PCA1KSAtIGhhc2ggKyBjaGFyO1xuXHRcdGhhc2ggPSBoYXNoICYgaGFzaDtcblx0fVxuXHRyZXR1cm4gYCR7aGFzaH1gO1xufVxuZnVuY3Rpb24gY2FsY3VsYXRlU3VpdGVIYXNoKHBhcmVudCkge1xuXHRwYXJlbnQudGFza3MuZm9yRWFjaCgodCwgaWR4KSA9PiB7XG5cdFx0dC5pZCA9IGAke3BhcmVudC5pZH1fJHtpZHh9YDtcblx0XHRpZiAodC50eXBlID09PSBcInN1aXRlXCIpIHtcblx0XHRcdGNhbGN1bGF0ZVN1aXRlSGFzaCh0KTtcblx0XHR9XG5cdH0pO1xufVxuZnVuY3Rpb24gY3JlYXRlRmlsZVRhc2soZmlsZXBhdGgsIHJvb3QsIHByb2plY3ROYW1lLCBwb29sLCB2aXRlRW52aXJvbm1lbnQpIHtcblx0Y29uc3QgcGF0aCA9IHJlbGF0aXZlKHJvb3QsIGZpbGVwYXRoKTtcblx0Y29uc3QgZmlsZSA9IHtcblx0XHRpZDogZ2VuZXJhdGVGaWxlSGFzaChwYXRoLCBwcm9qZWN0TmFtZSksXG5cdFx0bmFtZTogcGF0aCxcblx0XHRmdWxsTmFtZTogcGF0aCxcblx0XHR0eXBlOiBcInN1aXRlXCIsXG5cdFx0bW9kZTogXCJxdWV1ZWRcIixcblx0XHRmaWxlcGF0aCxcblx0XHR0YXNrczogW10sXG5cdFx0bWV0YTogT2JqZWN0LmNyZWF0ZShudWxsKSxcblx0XHRwcm9qZWN0TmFtZSxcblx0XHRmaWxlOiB1bmRlZmluZWQsXG5cdFx0cG9vbCxcblx0XHR2aXRlRW52aXJvbm1lbnRcblx0fTtcblx0ZmlsZS5maWxlID0gZmlsZTtcblx0cmV0dXJuIGZpbGU7XG59XG4vKipcbiogR2VuZXJhdGUgYSB1bmlxdWUgSUQgZm9yIGEgZmlsZSBiYXNlZCBvbiBpdHMgcGF0aCBhbmQgcHJvamVjdCBuYW1lXG4qIEBwYXJhbSBmaWxlIEZpbGUgcmVsYXRpdmUgdG8gdGhlIHJvb3Qgb2YgdGhlIHByb2plY3QgdG8ga2VlcCBJRCB0aGUgc2FtZSBiZXR3ZWVuIGRpZmZlcmVudCBtYWNoaW5lc1xuKiBAcGFyYW0gcHJvamVjdE5hbWUgVGhlIG5hbWUgb2YgdGhlIHRlc3QgcHJvamVjdFxuKi9cbi8qIEBfX05PX1NJREVfRUZGRUNUU19fICovXG5mdW5jdGlvbiBnZW5lcmF0ZUZpbGVIYXNoKGZpbGUsIHByb2plY3ROYW1lKSB7XG5cdHJldHVybiAvKiBAX19QVVJFX18gKi8gZ2VuZXJhdGVIYXNoKGAke2ZpbGV9JHtwcm9qZWN0TmFtZSB8fCBcIlwifWApO1xufVxuZnVuY3Rpb24gZmluZFRlc3RGaWxlU3RhY2tUcmFjZSh0ZXN0RmlsZVBhdGgsIGVycm9yKSB7XG5cdC8vIGZpcnN0IGxpbmUgaXMgdGhlIGVycm9yIG1lc3NhZ2Vcblx0Y29uc3QgbGluZXMgPSBlcnJvci5zcGxpdChcIlxcblwiKS5zbGljZSgxKTtcblx0Zm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG5cdFx0Y29uc3Qgc3RhY2sgPSBwYXJzZVNpbmdsZVN0YWNrKGxpbmUpO1xuXHRcdGlmIChzdGFjayAmJiBzdGFjay5maWxlID09PSB0ZXN0RmlsZVBhdGgpIHtcblx0XHRcdHJldHVybiBzdGFjaztcblx0XHR9XG5cdH1cbn1cblxuLyoqXG4qIFJldHVybiBhIGZ1bmN0aW9uIGZvciBydW5uaW5nIG11bHRpcGxlIGFzeW5jIG9wZXJhdGlvbnMgd2l0aCBsaW1pdGVkIGNvbmN1cnJlbmN5LlxuKi9cbmZ1bmN0aW9uIGxpbWl0Q29uY3VycmVuY3koY29uY3VycmVuY3kgPSBJbmZpbml0eSkge1xuXHQvLyBUaGUgbnVtYmVyIG9mIGN1cnJlbnRseSBhY3RpdmUgKyBwZW5kaW5nIHRhc2tzLlxuXHRsZXQgY291bnQgPSAwO1xuXHQvLyBUaGUgaGVhZCBhbmQgdGFpbCBvZiB0aGUgcGVuZGluZyB0YXNrIHF1ZXVlLCBidWlsdCB1c2luZyBhIHNpbmdseSBsaW5rZWQgbGlzdC5cblx0Ly8gQm90aCBoZWFkIGFuZCB0YWlsIGFyZSBpbml0aWFsbHkgdW5kZWZpbmVkLCBzaWduaWZ5aW5nIGFuIGVtcHR5IHF1ZXVlLlxuXHQvLyBUaGV5IGJvdGggYmVjb21lIHVuZGVmaW5lZCBhZ2FpbiB3aGVuZXZlciB0aGVyZSBhcmUgbm8gcGVuZGluZyB0YXNrcy5cblx0bGV0IGhlYWQ7XG5cdGxldCB0YWlsO1xuXHQvLyBBIGJvb2trZWVwaW5nIGZ1bmN0aW9uIGV4ZWN1dGVkIHdoZW5ldmVyIGEgdGFzayBoYXMgYmVlbiBydW4gdG8gY29tcGxldGlvbi5cblx0Y29uc3QgZmluaXNoID0gKCkgPT4ge1xuXHRcdGNvdW50LS07XG5cdFx0Ly8gQ2hlY2sgaWYgdGhlcmUgYXJlIGZ1cnRoZXIgcGVuZGluZyB0YXNrcyBpbiB0aGUgcXVldWUuXG5cdFx0aWYgKGhlYWQpIHtcblx0XHRcdC8vIEFsbG93IHRoZSBuZXh0IHBlbmRpbmcgdGFzayB0byBydW4gYW5kIHBvcCBpdCBmcm9tIHRoZSBxdWV1ZS5cblx0XHRcdGhlYWRbMF0oKTtcblx0XHRcdGhlYWQgPSBoZWFkWzFdO1xuXHRcdFx0Ly8gVGhlIGhlYWQgbWF5IG5vdyBiZSB1bmRlZmluZWQgaWYgdGhlcmUgYXJlIG5vIGZ1cnRoZXIgcGVuZGluZyB0YXNrcy5cblx0XHRcdC8vIEluIHRoYXQgY2FzZSwgc2V0IHRhaWwgdG8gdW5kZWZpbmVkIGFzIHdlbGwuXG5cdFx0XHR0YWlsID0gaGVhZCAmJiB0YWlsO1xuXHRcdH1cblx0fTtcblx0Y29uc3QgYWNxdWlyZSA9ICgpID0+IHtcblx0XHRsZXQgcmVsZWFzZWQgPSBmYWxzZTtcblx0XHRjb25zdCByZWxlYXNlID0gKCkgPT4ge1xuXHRcdFx0aWYgKCFyZWxlYXNlZCkge1xuXHRcdFx0XHRyZWxlYXNlZCA9IHRydWU7XG5cdFx0XHRcdGZpbmlzaCgpO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0aWYgKGNvdW50KysgPCBjb25jdXJyZW5jeSkge1xuXHRcdFx0cmV0dXJuIHJlbGVhc2U7XG5cdFx0fVxuXHRcdHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuXHRcdFx0aWYgKHRhaWwpIHtcblx0XHRcdFx0Ly8gVGhlcmUgYXJlIHBlbmRpbmcgdGFza3MsIHNvIGFwcGVuZCB0byB0aGUgcXVldWUuXG5cdFx0XHRcdHRhaWwgPSB0YWlsWzFdID0gWygpID0+IHJlc29sdmUocmVsZWFzZSldO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Ly8gTm8gb3RoZXIgcGVuZGluZyB0YXNrcywgaW5pdGlhbGl6ZSB0aGUgcXVldWUgd2l0aCBhIG5ldyB0YWlsIGFuZCBoZWFkLlxuXHRcdFx0XHRoZWFkID0gdGFpbCA9IFsoKSA9PiByZXNvbHZlKHJlbGVhc2UpXTtcblx0XHRcdH1cblx0XHR9KTtcblx0fTtcblx0Y29uc3QgbGltaXRlckZuID0gKGZ1bmMsIC4uLmFyZ3MpID0+IHtcblx0XHRmdW5jdGlvbiBydW4ocmVsZWFzZSkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gZnVuYyguLi5hcmdzKTtcblx0XHRcdFx0aWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0LmZpbmFsbHkocmVsZWFzZSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmVsZWFzZSgpO1xuXHRcdFx0XHRyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRyZWxlYXNlKCk7XG5cdFx0XHRcdHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGNvbnN0IHJlbGVhc2UgPSBhY3F1aXJlKCk7XG5cdFx0cmV0dXJuIHJlbGVhc2UgaW5zdGFuY2VvZiBQcm9taXNlID8gcmVsZWFzZS50aGVuKHJ1bikgOiBydW4ocmVsZWFzZSk7XG5cdH07XG5cdHJldHVybiBPYmplY3QuYXNzaWduKGxpbWl0ZXJGbiwgeyBhY3F1aXJlIH0pO1xufVxuXG4vKipcbiogUGFydGl0aW9uIGluIHRhc2tzIGdyb3VwcyBieSBjb25zZWN1dGl2ZSBjb25jdXJyZW50XG4qL1xuZnVuY3Rpb24gcGFydGl0aW9uU3VpdGVDaGlsZHJlbihzdWl0ZSkge1xuXHRsZXQgdGFza3NHcm91cCA9IFtdO1xuXHRjb25zdCB0YXNrc0dyb3VwcyA9IFtdO1xuXHRmb3IgKGNvbnN0IGMgb2Ygc3VpdGUudGFza3MpIHtcblx0XHRpZiAodGFza3NHcm91cC5sZW5ndGggPT09IDAgfHwgYy5jb25jdXJyZW50ID09PSB0YXNrc0dyb3VwWzBdLmNvbmN1cnJlbnQpIHtcblx0XHRcdHRhc2tzR3JvdXAucHVzaChjKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGFza3NHcm91cHMucHVzaCh0YXNrc0dyb3VwKTtcblx0XHRcdHRhc2tzR3JvdXAgPSBbY107XG5cdFx0fVxuXHR9XG5cdGlmICh0YXNrc0dyb3VwLmxlbmd0aCA+IDApIHtcblx0XHR0YXNrc0dyb3Vwcy5wdXNoKHRhc2tzR3JvdXApO1xuXHR9XG5cdHJldHVybiB0YXNrc0dyb3Vwcztcbn1cblxuY29uc3QgZmlsdGVyTWFwID0gbmV3IFdlYWtNYXAoKTtcbi8qKlxuKiBAZXhwZXJpbWVudGFsXG4qL1xuZnVuY3Rpb24gbWF0Y2hlc1RhZ3ModGVzdFRhZ3MpIHtcblx0Y29uc3QgcnVubmVyID0gZ2V0UnVubmVyKCk7XG5cdGNvbnN0IHRhZ3NGaWx0ZXIgPSBydW5uZXIuX2N1cnJlbnRTcGVjaWZpY2F0aW9uPy50ZXN0VGFnc0ZpbHRlciA/PyBydW5uZXIuY29uZmlnLnRhZ3NGaWx0ZXI7XG5cdGlmICghdGFnc0ZpbHRlcikge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdGxldCB0YWdzRmlsdGVyUHJlZGljYXRlID0gZmlsdGVyTWFwLmdldCh0YWdzRmlsdGVyKTtcblx0aWYgKCF0YWdzRmlsdGVyUHJlZGljYXRlKSB7XG5cdFx0dGFnc0ZpbHRlclByZWRpY2F0ZSA9IGNyZWF0ZVRhZ3NGaWx0ZXIodGFnc0ZpbHRlciwgcnVubmVyLmNvbmZpZy50YWdzKTtcblx0XHRmaWx0ZXJNYXAuc2V0KHRhZ3NGaWx0ZXIsIHRhZ3NGaWx0ZXJQcmVkaWNhdGUpO1xuXHR9XG5cdHJldHVybiB0YWdzRmlsdGVyUHJlZGljYXRlKHRlc3RUYWdzKTtcbn1cbmZ1bmN0aW9uIHZhbGlkYXRlVGFncyhjb25maWcsIHRhZ3MpIHtcblx0aWYgKCFjb25maWcuc3RyaWN0VGFncykge1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBhdmFpbGFibGVUYWdzID0gbmV3IFNldChjb25maWcudGFncy5tYXAoKHRhZykgPT4gdGFnLm5hbWUpKTtcblx0Zm9yIChjb25zdCB0YWcgb2YgdGFncykge1xuXHRcdGlmICghYXZhaWxhYmxlVGFncy5oYXModGFnKSkge1xuXHRcdFx0dGhyb3cgY3JlYXRlTm9UYWdzRXJyb3IoY29uZmlnLnRhZ3MsIHRhZyk7XG5cdFx0fVxuXHR9XG59XG5mdW5jdGlvbiBjcmVhdGVOb1RhZ3NFcnJvcihhdmFpbGFibGVUYWdzLCB0YWcsIHByZWZpeCA9IFwidGFnXCIpIHtcblx0aWYgKCFhdmFpbGFibGVUYWdzLmxlbmd0aCkge1xuXHRcdHRocm93IG5ldyBFcnJvcihgVGhlIFZpdGVzdCBjb25maWcgZG9lcyd0IGRlZmluZSBhbnkgXCJ0YWdzXCIsIGNhbm5vdCBhcHBseSBcIiR7dGFnfVwiICR7cHJlZml4fSBmb3IgdGhpcyB0ZXN0LiBTZWU6IGh0dHBzOi8vdml0ZXN0LmRldi9ndWlkZS90ZXN0LXRhZ3NgKTtcblx0fVxuXHR0aHJvdyBuZXcgRXJyb3IoYFRoZSAke3ByZWZpeH0gXCIke3RhZ31cIiBpcyBub3QgZGVmaW5lZCBpbiB0aGUgY29uZmlndXJhdGlvbi4gQXZhaWxhYmxlIHRhZ3MgYXJlOlxcbiR7YXZhaWxhYmxlVGFncy5tYXAoKHQpID0+IGAtICR7dC5uYW1lfSR7dC5kZXNjcmlwdGlvbiA/IGA6ICR7dC5kZXNjcmlwdGlvbn1gIDogXCJcIn1gKS5qb2luKFwiXFxuXCIpfWApO1xufVxuZnVuY3Rpb24gY3JlYXRlVGFnc0ZpbHRlcih0YWdzRXhwciwgYXZhaWxhYmxlVGFncykge1xuXHRjb25zdCBtYXRjaGVycyA9IHRhZ3NFeHByLm1hcCgoZXhwcikgPT4gcGFyc2VUYWdzRXhwcmVzc2lvbihleHByLCBhdmFpbGFibGVUYWdzKSk7XG5cdHJldHVybiAodGVzdFRhZ3MpID0+IHtcblx0XHRyZXR1cm4gbWF0Y2hlcnMuZXZlcnkoKG1hdGNoZXIpID0+IG1hdGNoZXIodGVzdFRhZ3MpKTtcblx0fTtcbn1cbmZ1bmN0aW9uIHBhcnNlVGFnc0V4cHJlc3Npb24oZXhwciwgYXZhaWxhYmxlVGFncykge1xuXHRjb25zdCB0b2tlbnMgPSB0b2tlbml6ZShleHByKTtcblx0Y29uc3Qgc3RyZWFtID0gbmV3IFRva2VuU3RyZWFtKHRva2VucywgZXhwcik7XG5cdGNvbnN0IGFzdCA9IHBhcnNlT3JFeHByZXNzaW9uKHN0cmVhbSwgYXZhaWxhYmxlVGFncyk7XG5cdGlmIChzdHJlYW0ucGVlaygpLnR5cGUgIT09IFwiRU9GXCIpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdGFncyBleHByZXNzaW9uOiB1bmV4cGVjdGVkIFwiJHtmb3JtYXRUb2tlbihzdHJlYW0ucGVlaygpKX1cIiBpbiBcIiR7ZXhwcn1cImApO1xuXHR9XG5cdHJldHVybiAodGFncykgPT4gZXZhbHVhdGVOb2RlKGFzdCwgdGFncyk7XG59XG5mdW5jdGlvbiBmb3JtYXRUb2tlbih0b2tlbikge1xuXHRzd2l0Y2ggKHRva2VuLnR5cGUpIHtcblx0XHRjYXNlIFwiVEFHXCI6IHJldHVybiB0b2tlbi52YWx1ZTtcblx0XHRkZWZhdWx0OiByZXR1cm4gZm9ybWF0VG9rZW5UeXBlKHRva2VuLnR5cGUpO1xuXHR9XG59XG5mdW5jdGlvbiB0b2tlbml6ZShleHByKSB7XG5cdGNvbnN0IHRva2VucyA9IFtdO1xuXHRsZXQgaSA9IDA7XG5cdHdoaWxlIChpIDwgZXhwci5sZW5ndGgpIHtcblx0XHRpZiAoZXhwcltpXSA9PT0gXCIgXCIgfHwgZXhwcltpXSA9PT0gXCJcdFwiKSB7XG5cdFx0XHRpKys7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0aWYgKGV4cHJbaV0gPT09IFwiKFwiKSB7XG5cdFx0XHR0b2tlbnMucHVzaCh7IHR5cGU6IFwiTFBBUkVOXCIgfSk7XG5cdFx0XHRpKys7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0aWYgKGV4cHJbaV0gPT09IFwiKVwiKSB7XG5cdFx0XHR0b2tlbnMucHVzaCh7IHR5cGU6IFwiUlBBUkVOXCIgfSk7XG5cdFx0XHRpKys7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0aWYgKGV4cHJbaV0gPT09IFwiIVwiKSB7XG5cdFx0XHR0b2tlbnMucHVzaCh7IHR5cGU6IFwiTk9UXCIgfSk7XG5cdFx0XHRpKys7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0aWYgKGV4cHIuc2xpY2UoaSwgaSArIDIpID09PSBcIiYmXCIpIHtcblx0XHRcdHRva2Vucy5wdXNoKHsgdHlwZTogXCJBTkRcIiB9KTtcblx0XHRcdGkgKz0gMjtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRpZiAoZXhwci5zbGljZShpLCBpICsgMikgPT09IFwifHxcIikge1xuXHRcdFx0dG9rZW5zLnB1c2goeyB0eXBlOiBcIk9SXCIgfSk7XG5cdFx0XHRpICs9IDI7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0aWYgKC9eYW5kKD86XFxzfFxcKXwkKS9pLnRlc3QoZXhwci5zbGljZShpKSkpIHtcblx0XHRcdHRva2Vucy5wdXNoKHsgdHlwZTogXCJBTkRcIiB9KTtcblx0XHRcdGkgKz0gMztcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRpZiAoL15vcig/Olxcc3xcXCl8JCkvaS50ZXN0KGV4cHIuc2xpY2UoaSkpKSB7XG5cdFx0XHR0b2tlbnMucHVzaCh7IHR5cGU6IFwiT1JcIiB9KTtcblx0XHRcdGkgKz0gMjtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRpZiAoL15ub3RcXHMvaS50ZXN0KGV4cHIuc2xpY2UoaSkpKSB7XG5cdFx0XHR0b2tlbnMucHVzaCh7IHR5cGU6IFwiTk9UXCIgfSk7XG5cdFx0XHRpICs9IDM7XG5cdFx0XHRjb250aW51ZTtcblx0XHR9XG5cdFx0bGV0IHRhZyA9IFwiXCI7XG5cdFx0d2hpbGUgKGkgPCBleHByLmxlbmd0aCAmJiBleHByW2ldICE9PSBcIiBcIiAmJiBleHByW2ldICE9PSBcIlx0XCIgJiYgZXhwcltpXSAhPT0gXCIoXCIgJiYgZXhwcltpXSAhPT0gXCIpXCIgJiYgZXhwcltpXSAhPT0gXCIhXCIgJiYgZXhwcltpXSAhPT0gXCImXCIgJiYgZXhwcltpXSAhPT0gXCJ8XCIpIHtcblx0XHRcdGNvbnN0IHJlbWFpbmluZyA9IGV4cHIuc2xpY2UoaSk7XG5cdFx0XHQvLyBPbmx5IHRyZWF0IGFuZC9vci9ub3QgYXMgb3BlcmF0b3JzIGlmIHdlJ3JlIGF0IHRoZSBzdGFydCBvZiBhIHRhZyAoYWZ0ZXIgd2hpdGVzcGFjZSlcblx0XHRcdC8vIFRoaXMgYWxsb3dzIHRhZ3MgbGlrZSBcImRlbWFuZFwiLCBcImVkaXRvclwiLCBcImNhbm5vdFwiIHRvIHdvcmsgY29ycmVjdGx5XG5cdFx0XHRpZiAodGFnID09PSBcIlwiICYmICgvXmFuZCg/Olxcc3xcXCl8JCkvaS50ZXN0KHJlbWFpbmluZykgfHwgL15vcig/Olxcc3xcXCl8JCkvaS50ZXN0KHJlbWFpbmluZykgfHwgL15ub3RcXHMvaS50ZXN0KHJlbWFpbmluZykpKSB7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0dGFnICs9IGV4cHJbaV07XG5cdFx0XHRpKys7XG5cdFx0fVxuXHRcdGlmICh0YWcpIHtcblx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0dHlwZTogXCJUQUdcIixcblx0XHRcdFx0dmFsdWU6IHRhZ1xuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cdHRva2Vucy5wdXNoKHsgdHlwZTogXCJFT0ZcIiB9KTtcblx0cmV0dXJuIHRva2Vucztcbn1cbmNsYXNzIFRva2VuU3RyZWFtIHtcblx0cG9zID0gMDtcblx0Y29uc3RydWN0b3IodG9rZW5zLCBleHByKSB7XG5cdFx0dGhpcy50b2tlbnMgPSB0b2tlbnM7XG5cdFx0dGhpcy5leHByID0gZXhwcjtcblx0fVxuXHRwZWVrKCkge1xuXHRcdHJldHVybiB0aGlzLnRva2Vuc1t0aGlzLnBvc107XG5cdH1cblx0bmV4dCgpIHtcblx0XHRyZXR1cm4gdGhpcy50b2tlbnNbdGhpcy5wb3MrK107XG5cdH1cblx0ZXhwZWN0KHR5cGUpIHtcblx0XHRjb25zdCB0b2tlbiA9IHRoaXMubmV4dCgpO1xuXHRcdGlmICh0b2tlbi50eXBlICE9PSB0eXBlKSB7XG5cdFx0XHRpZiAodHlwZSA9PT0gXCJSUEFSRU5cIiAmJiB0b2tlbi50eXBlID09PSBcIkVPRlwiKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB0YWdzIGV4cHJlc3Npb246IG1pc3NpbmcgY2xvc2luZyBcIilcIiBpbiBcIiR7dGhpcy5leHByfVwiYCk7XG5cdFx0XHR9XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdGFncyBleHByZXNzaW9uOiBleHBlY3RlZCBcIiR7Zm9ybWF0VG9rZW5UeXBlKHR5cGUpfVwiIGJ1dCBnb3QgXCIke2Zvcm1hdFRva2VuKHRva2VuKX1cIiBpbiBcIiR7dGhpcy5leHByfVwiYCk7XG5cdFx0fVxuXHRcdHJldHVybiB0b2tlbjtcblx0fVxuXHR1bmV4cGVjdGVkVG9rZW4oKSB7XG5cdFx0Y29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcblx0XHRpZiAodG9rZW4udHlwZSA9PT0gXCJFT0ZcIikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHRhZ3MgZXhwcmVzc2lvbjogdW5leHBlY3RlZCBlbmQgb2YgZXhwcmVzc2lvbiBpbiBcIiR7dGhpcy5leHByfVwiYCk7XG5cdFx0fVxuXHRcdHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB0YWdzIGV4cHJlc3Npb246IHVuZXhwZWN0ZWQgXCIke2Zvcm1hdFRva2VuKHRva2VuKX1cIiBpbiBcIiR7dGhpcy5leHByfVwiYCk7XG5cdH1cbn1cbmZ1bmN0aW9uIGZvcm1hdFRva2VuVHlwZSh0eXBlKSB7XG5cdHN3aXRjaCAodHlwZSkge1xuXHRcdGNhc2UgXCJUQUdcIjogcmV0dXJuIFwidGFnXCI7XG5cdFx0Y2FzZSBcIkFORFwiOiByZXR1cm4gXCJhbmRcIjtcblx0XHRjYXNlIFwiT1JcIjogcmV0dXJuIFwib3JcIjtcblx0XHRjYXNlIFwiTk9UXCI6IHJldHVybiBcIm5vdFwiO1xuXHRcdGNhc2UgXCJMUEFSRU5cIjogcmV0dXJuIFwiKFwiO1xuXHRcdGNhc2UgXCJSUEFSRU5cIjogcmV0dXJuIFwiKVwiO1xuXHRcdGNhc2UgXCJFT0ZcIjogcmV0dXJuIFwiZW5kIG9mIGV4cHJlc3Npb25cIjtcblx0fVxufVxuZnVuY3Rpb24gcGFyc2VPckV4cHJlc3Npb24oc3RyZWFtLCBhdmFpbGFibGVUYWdzKSB7XG5cdGxldCBsZWZ0ID0gcGFyc2VBbmRFeHByZXNzaW9uKHN0cmVhbSwgYXZhaWxhYmxlVGFncyk7XG5cdHdoaWxlIChzdHJlYW0ucGVlaygpLnR5cGUgPT09IFwiT1JcIikge1xuXHRcdHN0cmVhbS5uZXh0KCk7XG5cdFx0Y29uc3QgcmlnaHQgPSBwYXJzZUFuZEV4cHJlc3Npb24oc3RyZWFtLCBhdmFpbGFibGVUYWdzKTtcblx0XHRsZWZ0ID0ge1xuXHRcdFx0dHlwZTogXCJvclwiLFxuXHRcdFx0bGVmdCxcblx0XHRcdHJpZ2h0XG5cdFx0fTtcblx0fVxuXHRyZXR1cm4gbGVmdDtcbn1cbmZ1bmN0aW9uIHBhcnNlQW5kRXhwcmVzc2lvbihzdHJlYW0sIGF2YWlsYWJsZVRhZ3MpIHtcblx0bGV0IGxlZnQgPSBwYXJzZVVuYXJ5RXhwcmVzc2lvbihzdHJlYW0sIGF2YWlsYWJsZVRhZ3MpO1xuXHR3aGlsZSAoc3RyZWFtLnBlZWsoKS50eXBlID09PSBcIkFORFwiKSB7XG5cdFx0c3RyZWFtLm5leHQoKTtcblx0XHRjb25zdCByaWdodCA9IHBhcnNlVW5hcnlFeHByZXNzaW9uKHN0cmVhbSwgYXZhaWxhYmxlVGFncyk7XG5cdFx0bGVmdCA9IHtcblx0XHRcdHR5cGU6IFwiYW5kXCIsXG5cdFx0XHRsZWZ0LFxuXHRcdFx0cmlnaHRcblx0XHR9O1xuXHR9XG5cdHJldHVybiBsZWZ0O1xufVxuZnVuY3Rpb24gcGFyc2VVbmFyeUV4cHJlc3Npb24oc3RyZWFtLCBhdmFpbGFibGVUYWdzKSB7XG5cdGlmIChzdHJlYW0ucGVlaygpLnR5cGUgPT09IFwiTk9UXCIpIHtcblx0XHRzdHJlYW0ubmV4dCgpO1xuXHRcdGNvbnN0IG9wZXJhbmQgPSBwYXJzZVVuYXJ5RXhwcmVzc2lvbihzdHJlYW0sIGF2YWlsYWJsZVRhZ3MpO1xuXHRcdHJldHVybiB7XG5cdFx0XHR0eXBlOiBcIm5vdFwiLFxuXHRcdFx0b3BlcmFuZFxuXHRcdH07XG5cdH1cblx0cmV0dXJuIHBhcnNlUHJpbWFyeUV4cHJlc3Npb24oc3RyZWFtLCBhdmFpbGFibGVUYWdzKTtcbn1cbmZ1bmN0aW9uIHBhcnNlUHJpbWFyeUV4cHJlc3Npb24oc3RyZWFtLCBhdmFpbGFibGVUYWdzKSB7XG5cdGNvbnN0IHRva2VuID0gc3RyZWFtLnBlZWsoKTtcblx0aWYgKHRva2VuLnR5cGUgPT09IFwiTFBBUkVOXCIpIHtcblx0XHRzdHJlYW0ubmV4dCgpO1xuXHRcdGNvbnN0IGV4cHIgPSBwYXJzZU9yRXhwcmVzc2lvbihzdHJlYW0sIGF2YWlsYWJsZVRhZ3MpO1xuXHRcdHN0cmVhbS5leHBlY3QoXCJSUEFSRU5cIik7XG5cdFx0cmV0dXJuIGV4cHI7XG5cdH1cblx0aWYgKHRva2VuLnR5cGUgPT09IFwiVEFHXCIpIHtcblx0XHRzdHJlYW0ubmV4dCgpO1xuXHRcdGNvbnN0IHRhZ1ZhbHVlID0gdG9rZW4udmFsdWU7XG5cdFx0Y29uc3QgcGF0dGVybiA9IHJlc29sdmVUYWdQYXR0ZXJuKHRhZ1ZhbHVlLCBhdmFpbGFibGVUYWdzKTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0dHlwZTogXCJ0YWdcIixcblx0XHRcdHZhbHVlOiB0YWdWYWx1ZSxcblx0XHRcdHBhdHRlcm5cblx0XHR9O1xuXHR9XG5cdHN0cmVhbS51bmV4cGVjdGVkVG9rZW4oKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVdpbGRjYXJkUmVnZXgocGF0dGVybikge1xuXHRyZXR1cm4gbmV3IFJlZ0V4cChgXiR7cGF0dGVybi5yZXBsYWNlKC9bLis/XiR7fSgpfFtcXF1cXFxcXS9nLCBcIlxcXFwkJlwiKS5yZXBsYWNlKC9cXCovZywgXCIuKlwiKX0kYCk7XG59XG5mdW5jdGlvbiByZXNvbHZlVGFnUGF0dGVybih0YWdQYXR0ZXJuLCBhdmFpbGFibGVUYWdzKSB7XG5cdGlmICh0YWdQYXR0ZXJuLmluY2x1ZGVzKFwiKlwiKSkge1xuXHRcdGNvbnN0IHJlZ2V4ID0gY3JlYXRlV2lsZGNhcmRSZWdleCh0YWdQYXR0ZXJuKTtcblx0XHRjb25zdCBoYXNNYXRjaCA9IGF2YWlsYWJsZVRhZ3Muc29tZSgodGFnKSA9PiByZWdleC50ZXN0KHRhZy5uYW1lKSk7XG5cdFx0aWYgKCFoYXNNYXRjaCkge1xuXHRcdFx0dGhyb3cgY3JlYXRlTm9UYWdzRXJyb3IoYXZhaWxhYmxlVGFncywgdGFnUGF0dGVybiwgXCJ0YWcgcGF0dGVyblwiKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlZ2V4O1xuXHR9XG5cdGlmICghYXZhaWxhYmxlVGFncy5sZW5ndGggfHwgIWF2YWlsYWJsZVRhZ3Muc29tZSgodGFnKSA9PiB0YWcubmFtZSA9PT0gdGFnUGF0dGVybikpIHtcblx0XHR0aHJvdyBjcmVhdGVOb1RhZ3NFcnJvcihhdmFpbGFibGVUYWdzLCB0YWdQYXR0ZXJuLCBcInRhZyBwYXR0ZXJuXCIpO1xuXHR9XG5cdHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gZXZhbHVhdGVOb2RlKG5vZGUsIHRhZ3MpIHtcblx0c3dpdGNoIChub2RlLnR5cGUpIHtcblx0XHRjYXNlIFwidGFnXCI6XG5cdFx0XHRpZiAobm9kZS5wYXR0ZXJuKSB7XG5cdFx0XHRcdHJldHVybiB0YWdzLnNvbWUoKHRhZykgPT4gbm9kZS5wYXR0ZXJuLnRlc3QodGFnKSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gdGFncy5pbmNsdWRlcyhub2RlLnZhbHVlKTtcblx0XHRjYXNlIFwibm90XCI6IHJldHVybiAhZXZhbHVhdGVOb2RlKG5vZGUub3BlcmFuZCwgdGFncyk7XG5cdFx0Y2FzZSBcImFuZFwiOiByZXR1cm4gZXZhbHVhdGVOb2RlKG5vZGUubGVmdCwgdGFncykgJiYgZXZhbHVhdGVOb2RlKG5vZGUucmlnaHQsIHRhZ3MpO1xuXHRcdGNhc2UgXCJvclwiOiByZXR1cm4gZXZhbHVhdGVOb2RlKG5vZGUubGVmdCwgdGFncykgfHwgZXZhbHVhdGVOb2RlKG5vZGUucmlnaHQsIHRhZ3MpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIGlzVGVzdENhc2Uocykge1xuXHRyZXR1cm4gcy50eXBlID09PSBcInRlc3RcIjtcbn1cbmZ1bmN0aW9uIGdldFRlc3RzKHN1aXRlKSB7XG5cdGNvbnN0IHRlc3RzID0gW107XG5cdGNvbnN0IGFycmF5U3VpdGVzID0gdG9BcnJheShzdWl0ZSk7XG5cdGZvciAoY29uc3QgcyBvZiBhcnJheVN1aXRlcykge1xuXHRcdGlmIChpc1Rlc3RDYXNlKHMpKSB7XG5cdFx0XHR0ZXN0cy5wdXNoKHMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKGNvbnN0IHRhc2sgb2Ygcy50YXNrcykge1xuXHRcdFx0XHRpZiAoaXNUZXN0Q2FzZSh0YXNrKSkge1xuXHRcdFx0XHRcdHRlc3RzLnB1c2godGFzayk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Y29uc3QgdGFza1Rlc3RzID0gZ2V0VGVzdHModGFzayk7XG5cdFx0XHRcdFx0Zm9yIChjb25zdCB0ZXN0IG9mIHRhc2tUZXN0cykge1xuXHRcdFx0XHRcdFx0dGVzdHMucHVzaCh0ZXN0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblx0cmV0dXJuIHRlc3RzO1xufVxuZnVuY3Rpb24gZ2V0VGFza3ModGFza3MgPSBbXSkge1xuXHRyZXR1cm4gdG9BcnJheSh0YXNrcykuZmxhdE1hcCgocykgPT4gaXNUZXN0Q2FzZShzKSA/IFtzXSA6IFtzLCAuLi5nZXRUYXNrcyhzLnRhc2tzKV0pO1xufVxuZnVuY3Rpb24gZ2V0U3VpdGVzKHN1aXRlKSB7XG5cdHJldHVybiB0b0FycmF5KHN1aXRlKS5mbGF0TWFwKChzKSA9PiBzLnR5cGUgPT09IFwic3VpdGVcIiA/IFtzLCAuLi5nZXRTdWl0ZXMocy50YXNrcyldIDogW10pO1xufVxuZnVuY3Rpb24gaGFzVGVzdHMoc3VpdGUpIHtcblx0cmV0dXJuIHRvQXJyYXkoc3VpdGUpLnNvbWUoKHMpID0+IHMudGFza3Muc29tZSgoYykgPT4gaXNUZXN0Q2FzZShjKSB8fCBoYXNUZXN0cyhjKSkpO1xufVxuZnVuY3Rpb24gaGFzRmFpbGVkKHN1aXRlKSB7XG5cdHJldHVybiB0b0FycmF5KHN1aXRlKS5zb21lKChzKSA9PiBzLnJlc3VsdD8uc3RhdGUgPT09IFwiZmFpbFwiIHx8IHMudHlwZSA9PT0gXCJzdWl0ZVwiICYmIGhhc0ZhaWxlZChzLnRhc2tzKSk7XG59XG5mdW5jdGlvbiBnZXROYW1lcyh0YXNrKSB7XG5cdGNvbnN0IG5hbWVzID0gW3Rhc2submFtZV07XG5cdGxldCBjdXJyZW50ID0gdGFzaztcblx0d2hpbGUgKGN1cnJlbnQ/LnN1aXRlKSB7XG5cdFx0Y3VycmVudCA9IGN1cnJlbnQuc3VpdGU7XG5cdFx0aWYgKGN1cnJlbnQ/Lm5hbWUpIHtcblx0XHRcdG5hbWVzLnVuc2hpZnQoY3VycmVudC5uYW1lKTtcblx0XHR9XG5cdH1cblx0aWYgKGN1cnJlbnQgIT09IHRhc2suZmlsZSkge1xuXHRcdG5hbWVzLnVuc2hpZnQodGFzay5maWxlLm5hbWUpO1xuXHR9XG5cdHJldHVybiBuYW1lcztcbn1cbmZ1bmN0aW9uIGdldEZ1bGxOYW1lKHRhc2ssIHNlcGFyYXRvciA9IFwiID4gXCIpIHtcblx0cmV0dXJuIGdldE5hbWVzKHRhc2spLmpvaW4oc2VwYXJhdG9yKTtcbn1cbmZ1bmN0aW9uIGdldFRlc3ROYW1lKHRhc2ssIHNlcGFyYXRvciA9IFwiID4gXCIpIHtcblx0cmV0dXJuIGdldE5hbWVzKHRhc2spLnNsaWNlKDEpLmpvaW4oc2VwYXJhdG9yKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVRhc2tOYW1lKG5hbWVzLCBzZXBhcmF0b3IgPSBcIiA+IFwiKSB7XG5cdHJldHVybiBuYW1lcy5maWx0ZXIoKG5hbWUpID0+IG5hbWUgIT09IHVuZGVmaW5lZCkuam9pbihzZXBhcmF0b3IpO1xufVxuXG4vKipcbiogQ3JlYXRlcyBhIHN1aXRlIG9mIHRlc3RzLCBhbGxvd2luZyBmb3IgZ3JvdXBpbmcgYW5kIGhpZXJhcmNoaWNhbCBvcmdhbml6YXRpb24gb2YgdGVzdHMuXG4qIFN1aXRlcyBjYW4gY29udGFpbiBib3RoIHRlc3RzIGFuZCBvdGhlciBzdWl0ZXMsIGVuYWJsaW5nIGNvbXBsZXggdGVzdCBzdHJ1Y3R1cmVzLlxuKlxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBzdWl0ZSwgdXNlZCBmb3IgaWRlbnRpZmljYXRpb24gYW5kIHJlcG9ydGluZy5cbiogQHBhcmFtIHtGdW5jdGlvbn0gZm4gLSBBIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgdGVzdHMgYW5kIHN1aXRlcyB3aXRoaW4gdGhpcyBzdWl0ZS5cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIGEgc3VpdGUgd2l0aCB0d28gdGVzdHNcbiogc3VpdGUoJ01hdGggb3BlcmF0aW9ucycsICgpID0+IHtcbiogICB0ZXN0KCdzaG91bGQgYWRkIHR3byBudW1iZXJzJywgKCkgPT4ge1xuKiAgICAgZXhwZWN0KGFkZCgxLCAyKSkudG9CZSgzKTtcbiogICB9KTtcbipcbiogICB0ZXN0KCdzaG91bGQgc3VidHJhY3QgdHdvIG51bWJlcnMnLCAoKSA9PiB7XG4qICAgICBleHBlY3Qoc3VidHJhY3QoNSwgMikpLnRvQmUoMyk7XG4qICAgfSk7XG4qIH0pO1xuKiBgYGBcbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIG5lc3RlZCBzdWl0ZXNcbiogc3VpdGUoJ1N0cmluZyBvcGVyYXRpb25zJywgKCkgPT4ge1xuKiAgIHN1aXRlKCdUcmltbWluZycsICgpID0+IHtcbiogICAgIHRlc3QoJ3Nob3VsZCB0cmltIHdoaXRlc3BhY2UgZnJvbSBzdGFydCBhbmQgZW5kJywgKCkgPT4ge1xuKiAgICAgICBleHBlY3QoJyAgaGVsbG8gICcudHJpbSgpKS50b0JlKCdoZWxsbycpO1xuKiAgICAgfSk7XG4qICAgfSk7XG4qXG4qICAgc3VpdGUoJ0NvbmNhdGVuYXRpb24nLCAoKSA9PiB7XG4qICAgICB0ZXN0KCdzaG91bGQgY29uY2F0ZW5hdGUgdHdvIHN0cmluZ3MnLCAoKSA9PiB7XG4qICAgICAgIGV4cGVjdCgnaGVsbG8nICsgJyAnICsgJ3dvcmxkJykudG9CZSgnaGVsbG8gd29ybGQnKTtcbiogICAgIH0pO1xuKiAgIH0pO1xuKiB9KTtcbiogYGBgXG4qL1xuY29uc3Qgc3VpdGUgPSBjcmVhdGVTdWl0ZSgpO1xuLyoqXG4qIERlZmluZXMgYSB0ZXN0IGNhc2Ugd2l0aCBhIGdpdmVuIG5hbWUgYW5kIHRlc3QgZnVuY3Rpb24uIFRoZSB0ZXN0IGZ1bmN0aW9uIGNhbiBvcHRpb25hbGx5IGJlIGNvbmZpZ3VyZWQgd2l0aCB0ZXN0IG9wdGlvbnMuXG4qXG4qIEBwYXJhbSB7c3RyaW5nIHwgRnVuY3Rpb259IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGVzdCBvciBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSB1c2VkIGFzIGEgdGVzdCBuYW1lLlxuKiBAcGFyYW0ge1Rlc3RPcHRpb25zIHwgVGVzdEZ1bmN0aW9ufSBbb3B0aW9uc09yRm5dIC0gT3B0aW9uYWwuIFRoZSB0ZXN0IG9wdGlvbnMgb3IgdGhlIHRlc3QgZnVuY3Rpb24gaWYgbm8gZXhwbGljaXQgbmFtZSBpcyBwcm92aWRlZC5cbiogQHBhcmFtIHtudW1iZXIgfCBUZXN0T3B0aW9ucyB8IFRlc3RGdW5jdGlvbn0gW29wdGlvbnNPclRlc3RdIC0gT3B0aW9uYWwuIFRoZSB0ZXN0IGZ1bmN0aW9uIG9yIG9wdGlvbnMsIGRlcGVuZGluZyBvbiB0aGUgcHJldmlvdXMgcGFyYW1ldGVycy5cbiogQHRocm93cyB7RXJyb3J9IElmIGNhbGxlZCBpbnNpZGUgYW5vdGhlciB0ZXN0IGZ1bmN0aW9uLlxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBEZWZpbmUgYSBzaW1wbGUgdGVzdFxuKiB0ZXN0KCdzaG91bGQgYWRkIHR3byBudW1iZXJzJywgKCkgPT4ge1xuKiAgIGV4cGVjdChhZGQoMSwgMikpLnRvQmUoMyk7XG4qIH0pO1xuKiBgYGBcbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIGEgdGVzdCB3aXRoIG9wdGlvbnNcbiogdGVzdCgnc2hvdWxkIHN1YnRyYWN0IHR3byBudW1iZXJzJywgeyByZXRyeTogMyB9LCAoKSA9PiB7XG4qICAgZXhwZWN0KHN1YnRyYWN0KDUsIDIpKS50b0JlKDMpO1xuKiB9KTtcbiogYGBgXG4qL1xuY29uc3QgdGVzdCA9IGNyZWF0ZVRlc3QoZnVuY3Rpb24obmFtZSwgb3B0aW9uc09yRm4sIG9wdGlvbnNPclRlc3QpIHtcblx0aWYgKGdldEN1cnJlbnRUZXN0KCkpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDYWxsaW5nIHRoZSB0ZXN0IGZ1bmN0aW9uIGluc2lkZSBhbm90aGVyIHRlc3QgZnVuY3Rpb24gaXMgbm90IGFsbG93ZWQuIFBsZWFzZSBwdXQgaXQgaW5zaWRlIFxcXCJkZXNjcmliZVxcXCIgb3IgXFxcInN1aXRlXFxcIiBzbyBpdCBjYW4gYmUgcHJvcGVybHkgY29sbGVjdGVkLlwiKTtcblx0fVxuXHRnZXRDdXJyZW50U3VpdGUoKS50ZXN0LmZuLmNhbGwodGhpcywgZm9ybWF0TmFtZShuYW1lKSwgb3B0aW9uc09yRm4sIG9wdGlvbnNPclRlc3QpO1xufSk7XG4vKipcbiogQ3JlYXRlcyBhIHN1aXRlIG9mIHRlc3RzLCBhbGxvd2luZyBmb3IgZ3JvdXBpbmcgYW5kIGhpZXJhcmNoaWNhbCBvcmdhbml6YXRpb24gb2YgdGVzdHMuXG4qIFN1aXRlcyBjYW4gY29udGFpbiBib3RoIHRlc3RzIGFuZCBvdGhlciBzdWl0ZXMsIGVuYWJsaW5nIGNvbXBsZXggdGVzdCBzdHJ1Y3R1cmVzLlxuKlxuKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBzdWl0ZSwgdXNlZCBmb3IgaWRlbnRpZmljYXRpb24gYW5kIHJlcG9ydGluZy5cbiogQHBhcmFtIHtGdW5jdGlvbn0gZm4gLSBBIGZ1bmN0aW9uIHRoYXQgZGVmaW5lcyB0aGUgdGVzdHMgYW5kIHN1aXRlcyB3aXRoaW4gdGhpcyBzdWl0ZS5cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIGEgc3VpdGUgd2l0aCB0d28gdGVzdHNcbiogZGVzY3JpYmUoJ01hdGggb3BlcmF0aW9ucycsICgpID0+IHtcbiogICB0ZXN0KCdzaG91bGQgYWRkIHR3byBudW1iZXJzJywgKCkgPT4ge1xuKiAgICAgZXhwZWN0KGFkZCgxLCAyKSkudG9CZSgzKTtcbiogICB9KTtcbipcbiogICB0ZXN0KCdzaG91bGQgc3VidHJhY3QgdHdvIG51bWJlcnMnLCAoKSA9PiB7XG4qICAgICBleHBlY3Qoc3VidHJhY3QoNSwgMikpLnRvQmUoMyk7XG4qICAgfSk7XG4qIH0pO1xuKiBgYGBcbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIG5lc3RlZCBzdWl0ZXNcbiogZGVzY3JpYmUoJ1N0cmluZyBvcGVyYXRpb25zJywgKCkgPT4ge1xuKiAgIGRlc2NyaWJlKCdUcmltbWluZycsICgpID0+IHtcbiogICAgIHRlc3QoJ3Nob3VsZCB0cmltIHdoaXRlc3BhY2UgZnJvbSBzdGFydCBhbmQgZW5kJywgKCkgPT4ge1xuKiAgICAgICBleHBlY3QoJyAgaGVsbG8gICcudHJpbSgpKS50b0JlKCdoZWxsbycpO1xuKiAgICAgfSk7XG4qICAgfSk7XG4qXG4qICAgZGVzY3JpYmUoJ0NvbmNhdGVuYXRpb24nLCAoKSA9PiB7XG4qICAgICB0ZXN0KCdzaG91bGQgY29uY2F0ZW5hdGUgdHdvIHN0cmluZ3MnLCAoKSA9PiB7XG4qICAgICAgIGV4cGVjdCgnaGVsbG8nICsgJyAnICsgJ3dvcmxkJykudG9CZSgnaGVsbG8gd29ybGQnKTtcbiogICAgIH0pO1xuKiAgIH0pO1xuKiB9KTtcbiogYGBgXG4qL1xuY29uc3QgZGVzY3JpYmUgPSBzdWl0ZTtcbi8qKlxuKiBEZWZpbmVzIGEgdGVzdCBjYXNlIHdpdGggYSBnaXZlbiBuYW1lIGFuZCB0ZXN0IGZ1bmN0aW9uLiBUaGUgdGVzdCBmdW5jdGlvbiBjYW4gb3B0aW9uYWxseSBiZSBjb25maWd1cmVkIHdpdGggdGVzdCBvcHRpb25zLlxuKlxuKiBAcGFyYW0ge3N0cmluZyB8IEZ1bmN0aW9ufSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRlc3Qgb3IgYSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgdXNlZCBhcyBhIHRlc3QgbmFtZS5cbiogQHBhcmFtIHtUZXN0T3B0aW9ucyB8IFRlc3RGdW5jdGlvbn0gW29wdGlvbnNPckZuXSAtIE9wdGlvbmFsLiBUaGUgdGVzdCBvcHRpb25zIG9yIHRoZSB0ZXN0IGZ1bmN0aW9uIGlmIG5vIGV4cGxpY2l0IG5hbWUgaXMgcHJvdmlkZWQuXG4qIEBwYXJhbSB7bnVtYmVyIHwgVGVzdE9wdGlvbnMgfCBUZXN0RnVuY3Rpb259IFtvcHRpb25zT3JUZXN0XSAtIE9wdGlvbmFsLiBUaGUgdGVzdCBmdW5jdGlvbiBvciBvcHRpb25zLCBkZXBlbmRpbmcgb24gdGhlIHByZXZpb3VzIHBhcmFtZXRlcnMuXG4qIEB0aHJvd3Mge0Vycm9yfSBJZiBjYWxsZWQgaW5zaWRlIGFub3RoZXIgdGVzdCBmdW5jdGlvbi5cbiogQGV4YW1wbGVcbiogYGBgdHNcbiogLy8gRGVmaW5lIGEgc2ltcGxlIHRlc3RcbiogaXQoJ2FkZHMgdHdvIG51bWJlcnMnLCAoKSA9PiB7XG4qICAgZXhwZWN0KGFkZCgxLCAyKSkudG9CZSgzKTtcbiogfSk7XG4qIGBgYFxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBEZWZpbmUgYSB0ZXN0IHdpdGggb3B0aW9uc1xuKiBpdCgnc3VidHJhY3RzIHR3byBudW1iZXJzJywgeyByZXRyeTogMyB9LCAoKSA9PiB7XG4qICAgZXhwZWN0KHN1YnRyYWN0KDUsIDIpKS50b0JlKDMpO1xuKiB9KTtcbiogYGBgXG4qL1xuY29uc3QgaXQgPSB0ZXN0O1xubGV0IHJ1bm5lcjtcbmxldCBkZWZhdWx0U3VpdGU7XG5sZXQgY3VycmVudFRlc3RGaWxlcGF0aDtcbmZ1bmN0aW9uIGFzc2VydChjb25kaXRpb24sIG1lc3NhZ2UpIHtcblx0aWYgKCFjb25kaXRpb24pIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoYFZpdGVzdCBmYWlsZWQgdG8gZmluZCAke21lc3NhZ2V9LiBPbmUgb2YgdGhlIGZvbGxvd2luZyBpcyBwb3NzaWJsZTpgICsgXCJcXG4tIFxcXCJ2aXRlc3RcXFwiIGlzIGltcG9ydGVkIGRpcmVjdGx5IHdpdGhvdXQgcnVubmluZyBcXFwidml0ZXN0XFxcIiBjb21tYW5kXCIgKyBcIlxcbi0gXFxcInZpdGVzdFxcXCIgaXMgaW1wb3J0ZWQgaW5zaWRlIFxcXCJnbG9iYWxTZXR1cFxcXCIgKHRvIGZpeCB0aGlzLCB1c2UgXFxcInNldHVwRmlsZXNcXFwiIGluc3RlYWQsIGJlY2F1c2UgXFxcImdsb2JhbFNldHVwXFxcIiBydW5zIGluIGEgZGlmZmVyZW50IGNvbnRleHQpXCIgKyBcIlxcbi0gXFxcInZpdGVzdFxcXCIgaXMgaW1wb3J0ZWQgaW5zaWRlIFZpdGUgLyBWaXRlc3QgY29uZmlnIGZpbGVcIiArIFwiXFxuLSBPdGhlcndpc2UsIGl0IG1pZ2h0IGJlIGEgVml0ZXN0IGJ1Zy4gUGxlYXNlIHJlcG9ydCBpdCB0byBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzXFxuXCIpO1xuXHR9XG59XG5mdW5jdGlvbiBnZXREZWZhdWx0U3VpdGUoKSB7XG5cdGFzc2VydChkZWZhdWx0U3VpdGUsIFwidGhlIGRlZmF1bHQgc3VpdGVcIik7XG5cdHJldHVybiBkZWZhdWx0U3VpdGU7XG59XG5mdW5jdGlvbiBnZXRSdW5uZXIoKSB7XG5cdGFzc2VydChydW5uZXIsIFwidGhlIHJ1bm5lclwiKTtcblx0cmV0dXJuIHJ1bm5lcjtcbn1cbmZ1bmN0aW9uIGNyZWF0ZURlZmF1bHRTdWl0ZShydW5uZXIpIHtcblx0Y29uc3QgY29uZmlnID0gcnVubmVyLmNvbmZpZy5zZXF1ZW5jZTtcblx0Y29uc3Qgb3B0aW9ucyA9IHt9O1xuXHRpZiAoY29uZmlnLmNvbmN1cnJlbnQgIT0gbnVsbCkge1xuXHRcdG9wdGlvbnMuY29uY3VycmVudCA9IGNvbmZpZy5jb25jdXJyZW50O1xuXHR9XG5cdGNvbnN0IGNvbGxlY3RvciA9IHN1aXRlKFwiXCIsIG9wdGlvbnMsICgpID0+IHt9KTtcblx0Ly8gbm8gcGFyZW50IHN1aXRlIGZvciB0b3AtbGV2ZWwgdGVzdHNcblx0ZGVsZXRlIGNvbGxlY3Rvci5zdWl0ZTtcblx0cmV0dXJuIGNvbGxlY3Rvcjtcbn1cbmZ1bmN0aW9uIGNsZWFyQ29sbGVjdG9yQ29udGV4dChmaWxlLCBjdXJyZW50UnVubmVyKSB7XG5cdGN1cnJlbnRUZXN0RmlsZXBhdGggPSBmaWxlLmZpbGVwYXRoO1xuXHRydW5uZXIgPSBjdXJyZW50UnVubmVyO1xuXHRpZiAoIWRlZmF1bHRTdWl0ZSkge1xuXHRcdGRlZmF1bHRTdWl0ZSA9IGNyZWF0ZURlZmF1bHRTdWl0ZShjdXJyZW50UnVubmVyKTtcblx0fVxuXHRkZWZhdWx0U3VpdGUuZmlsZSA9IGZpbGU7XG5cdGNvbGxlY3RvckNvbnRleHQudGFza3MubGVuZ3RoID0gMDtcblx0ZGVmYXVsdFN1aXRlLmNsZWFyKCk7XG5cdGNvbGxlY3RvckNvbnRleHQuY3VycmVudFN1aXRlID0gZGVmYXVsdFN1aXRlO1xufVxuZnVuY3Rpb24gZ2V0Q3VycmVudFN1aXRlKCkge1xuXHRjb25zdCBjdXJyZW50U3VpdGUgPSBjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZSB8fCBkZWZhdWx0U3VpdGU7XG5cdGFzc2VydChjdXJyZW50U3VpdGUsIFwidGhlIGN1cnJlbnQgc3VpdGVcIik7XG5cdHJldHVybiBjdXJyZW50U3VpdGU7XG59XG5mdW5jdGlvbiBjcmVhdGVTdWl0ZUhvb2tzKCkge1xuXHRyZXR1cm4ge1xuXHRcdGJlZm9yZUFsbDogW10sXG5cdFx0YWZ0ZXJBbGw6IFtdLFxuXHRcdGJlZm9yZUVhY2g6IFtdLFxuXHRcdGFmdGVyRWFjaDogW10sXG5cdFx0YXJvdW5kRWFjaDogW10sXG5cdFx0YXJvdW5kQWxsOiBbXVxuXHR9O1xufVxuY29uc3QgUE9TSVRJVkVfSU5GSU5JVFkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG5mdW5jdGlvbiBwYXJzZUFyZ3VtZW50cyhvcHRpb25zT3JGbiwgdGltZW91dE9yVGVzdCkge1xuXHRpZiAodGltZW91dE9yVGVzdCAhPSBudWxsICYmIHR5cGVvZiB0aW1lb3V0T3JUZXN0ID09PSBcIm9iamVjdFwiKSB7XG5cdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgU2lnbmF0dXJlIFwidGVzdChuYW1lLCBmbiwgeyAuLi4gfSlcIiB3YXMgZGVwcmVjYXRlZCBpbiBWaXRlc3QgMyBhbmQgcmVtb3ZlZCBpbiBWaXRlc3QgNC4gUGxlYXNlLCBwcm92aWRlIG9wdGlvbnMgYXMgYSBzZWNvbmQgYXJndW1lbnQgaW5zdGVhZC5gKTtcblx0fVxuXHRsZXQgb3B0aW9ucyA9IHt9O1xuXHRsZXQgZm47XG5cdC8vIGl0KCcnLCAoKSA9PiB7fSwgMTAwMClcblx0aWYgKHR5cGVvZiB0aW1lb3V0T3JUZXN0ID09PSBcIm51bWJlclwiKSB7XG5cdFx0b3B0aW9ucyA9IHsgdGltZW91dDogdGltZW91dE9yVGVzdCB9O1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zT3JGbiA9PT0gXCJvYmplY3RcIikge1xuXHRcdG9wdGlvbnMgPSBvcHRpb25zT3JGbjtcblx0fVxuXHRpZiAodHlwZW9mIG9wdGlvbnNPckZuID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRpZiAodHlwZW9mIHRpbWVvdXRPclRlc3QgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgdHdvIGZ1bmN0aW9ucyBhcyBhcmd1bWVudHMuIFBsZWFzZSB1c2UgdGhlIHNlY29uZCBhcmd1bWVudCBmb3Igb3B0aW9ucy5cIik7XG5cdFx0fVxuXHRcdGZuID0gb3B0aW9uc09yRm47XG5cdH0gZWxzZSBpZiAodHlwZW9mIHRpbWVvdXRPclRlc3QgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdGZuID0gdGltZW91dE9yVGVzdDtcblx0fVxuXHRyZXR1cm4ge1xuXHRcdG9wdGlvbnMsXG5cdFx0aGFuZGxlcjogZm5cblx0fTtcbn1cbi8vIGltcGxlbWVudGF0aW9uc1xuZnVuY3Rpb24gY3JlYXRlU3VpdGVDb2xsZWN0b3IobmFtZSwgZmFjdG9yeSA9ICgpID0+IHt9LCBtb2RlLCBlYWNoLCBzdWl0ZU9wdGlvbnMpIHtcblx0Y29uc3QgdGFza3MgPSBbXTtcblx0bGV0IHN1aXRlO1xuXHRpbml0U3VpdGUodHJ1ZSk7XG5cdGNvbnN0IHRhc2sgPSBmdW5jdGlvbihuYW1lID0gXCJcIiwgb3B0aW9ucyA9IHt9KSB7XG5cdFx0Y29uc3QgY3VycmVudFN1aXRlID0gY29sbGVjdG9yQ29udGV4dC5jdXJyZW50U3VpdGU/LnN1aXRlO1xuXHRcdGNvbnN0IHBhcmVudFRhc2sgPSBjdXJyZW50U3VpdGUgPz8gY29sbGVjdG9yQ29udGV4dC5jdXJyZW50U3VpdGU/LmZpbGU7XG5cdFx0Y29uc3QgcGFyZW50VGFncyA9IHBhcmVudFRhc2s/LnRhZ3MgfHwgW107XG5cdFx0Y29uc3QgdGVzdFRhZ3MgPSB1bmlxdWUoWy4uLnBhcmVudFRhZ3MsIC4uLnRvQXJyYXkob3B0aW9ucy50YWdzKV0pO1xuXHRcdGNvbnN0IHRhZ3NPcHRpb25zID0gdGVzdFRhZ3MubWFwKCh0YWcpID0+IHtcblx0XHRcdGNvbnN0IHRhZ0RlZmluaXRpb24gPSBydW5uZXIuY29uZmlnLnRhZ3M/LmZpbmQoKHQpID0+IHQubmFtZSA9PT0gdGFnKTtcblx0XHRcdGlmICghdGFnRGVmaW5pdGlvbiAmJiBydW5uZXIuY29uZmlnLnN0cmljdFRhZ3MpIHtcblx0XHRcdFx0dGhyb3cgY3JlYXRlTm9UYWdzRXJyb3IocnVubmVyLmNvbmZpZy50YWdzLCB0YWcpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRhZ0RlZmluaXRpb247XG5cdFx0fSkuZmlsdGVyKChyKSA9PiByICE9IG51bGwpLnNvcnQoKHRhZzEsIHRhZzIpID0+ICh0YWcyLnByaW9yaXR5ID8/IFBPU0lUSVZFX0lORklOSVRZKSAtICh0YWcxLnByaW9yaXR5ID8/IFBPU0lUSVZFX0lORklOSVRZKSkucmVkdWNlKChhY2MsIHRhZykgPT4ge1xuXHRcdFx0Y29uc3QgeyBuYW1lLCBkZXNjcmlwdGlvbiwgcHJpb3JpdHksIG1ldGEsIC4uLm9wdGlvbnMgfSA9IHRhZztcblx0XHRcdE9iamVjdC5hc3NpZ24oYWNjLCBvcHRpb25zKTtcblx0XHRcdGlmIChtZXRhKSB7XG5cdFx0XHRcdGFjYy5tZXRhID0gT2JqZWN0LmFzc2lnbihhY2MubWV0YSA/PyBPYmplY3QuY3JlYXRlKG51bGwpLCBtZXRhKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBhY2M7XG5cdFx0fSwge30pO1xuXHRcdGNvbnN0IHRlc3RPd25NZXRhID0gb3B0aW9ucy5tZXRhO1xuXHRcdG9wdGlvbnMgPSB7XG5cdFx0XHQuLi50YWdzT3B0aW9ucyxcblx0XHRcdC4uLm9wdGlvbnNcblx0XHR9O1xuXHRcdGNvbnN0IHRpbWVvdXQgPSBvcHRpb25zLnRpbWVvdXQgPz8gcnVubmVyLmNvbmZpZy50ZXN0VGltZW91dDtcblx0XHRjb25zdCBwYXJlbnRNZXRhID0gY3VycmVudFN1aXRlPy5tZXRhO1xuXHRcdGNvbnN0IHRhZ01ldGEgPSB0YWdzT3B0aW9ucy5tZXRhO1xuXHRcdGNvbnN0IHRlc3RNZXRhID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblx0XHRpZiAodGFnTWV0YSkge1xuXHRcdFx0T2JqZWN0LmFzc2lnbih0ZXN0TWV0YSwgdGFnTWV0YSk7XG5cdFx0fVxuXHRcdGlmIChwYXJlbnRNZXRhKSB7XG5cdFx0XHRPYmplY3QuYXNzaWduKHRlc3RNZXRhLCBwYXJlbnRNZXRhKTtcblx0XHR9XG5cdFx0aWYgKHRlc3RPd25NZXRhKSB7XG5cdFx0XHRPYmplY3QuYXNzaWduKHRlc3RNZXRhLCB0ZXN0T3duTWV0YSk7XG5cdFx0fVxuXHRcdGNvbnN0IHRhc2sgPSB7XG5cdFx0XHRpZDogXCJcIixcblx0XHRcdG5hbWUsXG5cdFx0XHRmdWxsTmFtZTogY3JlYXRlVGFza05hbWUoW2N1cnJlbnRTdWl0ZT8uZnVsbE5hbWUgPz8gY29sbGVjdG9yQ29udGV4dC5jdXJyZW50U3VpdGU/LmZpbGU/LmZ1bGxOYW1lLCBuYW1lXSksXG5cdFx0XHRmdWxsVGVzdE5hbWU6IGNyZWF0ZVRhc2tOYW1lKFtjdXJyZW50U3VpdGU/LmZ1bGxUZXN0TmFtZSwgbmFtZV0pLFxuXHRcdFx0c3VpdGU6IGN1cnJlbnRTdWl0ZSxcblx0XHRcdGVhY2g6IG9wdGlvbnMuZWFjaCxcblx0XHRcdGZhaWxzOiBvcHRpb25zLmZhaWxzLFxuXHRcdFx0Y29udGV4dDogdW5kZWZpbmVkLFxuXHRcdFx0dHlwZTogXCJ0ZXN0XCIsXG5cdFx0XHRmaWxlOiBjdXJyZW50U3VpdGU/LmZpbGUgPz8gY29sbGVjdG9yQ29udGV4dC5jdXJyZW50U3VpdGU/LmZpbGUsXG5cdFx0XHR0aW1lb3V0LFxuXHRcdFx0cmV0cnk6IG9wdGlvbnMucmV0cnkgPz8gcnVubmVyLmNvbmZpZy5yZXRyeSxcblx0XHRcdHJlcGVhdHM6IG9wdGlvbnMucmVwZWF0cyxcblx0XHRcdG1vZGU6IG9wdGlvbnMub25seSA/IFwib25seVwiIDogb3B0aW9ucy5za2lwID8gXCJza2lwXCIgOiBvcHRpb25zLnRvZG8gPyBcInRvZG9cIiA6IFwicnVuXCIsXG5cdFx0XHRtZXRhOiB0ZXN0TWV0YSxcblx0XHRcdGFubm90YXRpb25zOiBbXSxcblx0XHRcdGFydGlmYWN0czogW10sXG5cdFx0XHR0YWdzOiB0ZXN0VGFnc1xuXHRcdH07XG5cdFx0Y29uc3QgaGFuZGxlciA9IG9wdGlvbnMuaGFuZGxlcjtcblx0XHRpZiAodGFzay5tb2RlID09PSBcInJ1blwiICYmICFoYW5kbGVyKSB7XG5cdFx0XHR0YXNrLm1vZGUgPSBcInRvZG9cIjtcblx0XHR9XG5cdFx0aWYgKG9wdGlvbnMuY29uY3VycmVudCA/PyAoIW9wdGlvbnMuc2VxdWVudGlhbCAmJiBydW5uZXIuY29uZmlnLnNlcXVlbmNlLmNvbmN1cnJlbnQpKSB7XG5cdFx0XHR0YXNrLmNvbmN1cnJlbnQgPSB0cnVlO1xuXHRcdH1cblx0XHR0YXNrLnNodWZmbGUgPSBzdWl0ZU9wdGlvbnM/LnNodWZmbGU7XG5cdFx0Y29uc3QgY29udGV4dCA9IGNyZWF0ZVRlc3RDb250ZXh0KHRhc2ssIHJ1bm5lcik7XG5cdFx0Ly8gY3JlYXRlIHRlc3QgY29udGV4dFxuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXNrLCBcImNvbnRleHRcIiwge1xuXHRcdFx0dmFsdWU6IGNvbnRleHQsXG5cdFx0XHRlbnVtZXJhYmxlOiBmYWxzZVxuXHRcdH0pO1xuXHRcdHNldFRlc3RGaXh0dXJlKGNvbnRleHQsIG9wdGlvbnMuZml4dHVyZXMgPz8gbmV3IFRlc3RGaXh0dXJlcygpKTtcblx0XHRjb25zdCBsaW1pdCA9IEVycm9yLnN0YWNrVHJhY2VMaW1pdDtcblx0XHRFcnJvci5zdGFja1RyYWNlTGltaXQgPSAxMDtcblx0XHRjb25zdCBzdGFja1RyYWNlRXJyb3IgPSBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRV9FUlJPUlwiKTtcblx0XHRFcnJvci5zdGFja1RyYWNlTGltaXQgPSBsaW1pdDtcblx0XHRpZiAoaGFuZGxlcikge1xuXHRcdFx0c2V0Rm4odGFzaywgd2l0aFRpbWVvdXQod2l0aENhbmNlbCh3aXRoQXdhaXRBc3luY0Fzc2VydGlvbnMod2l0aEZpeHR1cmVzKGhhbmRsZXIsIHsgY29udGV4dCB9KSwgdGFzayksIHRhc2suY29udGV4dC5zaWduYWwpLCB0aW1lb3V0LCBmYWxzZSwgc3RhY2tUcmFjZUVycm9yLCAoXywgZXJyb3IpID0+IGFib3J0SWZUaW1lb3V0KFtjb250ZXh0XSwgZXJyb3IpKSk7XG5cdFx0fVxuXHRcdGlmIChydW5uZXIuY29uZmlnLmluY2x1ZGVUYXNrTG9jYXRpb24pIHtcblx0XHRcdGNvbnN0IGVycm9yID0gc3RhY2tUcmFjZUVycm9yLnN0YWNrO1xuXHRcdFx0Y29uc3Qgc3RhY2sgPSBmaW5kVGVzdEZpbGVTdGFja1RyYWNlKGN1cnJlbnRUZXN0RmlsZXBhdGgsIGVycm9yKTtcblx0XHRcdGlmIChzdGFjaykge1xuXHRcdFx0XHR0YXNrLmxvY2F0aW9uID0ge1xuXHRcdFx0XHRcdGxpbmU6IHN0YWNrLmxpbmUsXG5cdFx0XHRcdFx0Y29sdW1uOiBzdGFjay5jb2x1bW5cblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9XG5cdFx0dGFza3MucHVzaCh0YXNrKTtcblx0XHRyZXR1cm4gdGFzaztcblx0fTtcblx0Y29uc3QgdGVzdCA9IGNyZWF0ZVRlc3QoZnVuY3Rpb24obmFtZSwgb3B0aW9uc09yRm4sIHRpbWVvdXRPclRlc3QpIHtcblx0XHRsZXQgeyBvcHRpb25zLCBoYW5kbGVyIH0gPSBwYXJzZUFyZ3VtZW50cyhvcHRpb25zT3JGbiwgdGltZW91dE9yVGVzdCk7XG5cdFx0Ly8gaW5oZXJpdCByZXBlYXRzLCByZXRyeSwgdGltZW91dCBmcm9tIHN1aXRlXG5cdFx0aWYgKHR5cGVvZiBzdWl0ZU9wdGlvbnMgPT09IFwib2JqZWN0XCIpIHtcblx0XHRcdG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBzdWl0ZU9wdGlvbnMsIG9wdGlvbnMpO1xuXHRcdH1cblx0XHQvLyBpbmhlcml0IGNvbmN1cnJlbnQgLyBzZXF1ZW50aWFsIGZyb20gc3VpdGVcblx0XHRjb25zdCBjb25jdXJyZW50ID0gdGhpcy5jb25jdXJyZW50ID8/ICghdGhpcy5zZXF1ZW50aWFsICYmIG9wdGlvbnM/LmNvbmN1cnJlbnQpO1xuXHRcdGlmIChvcHRpb25zLmNvbmN1cnJlbnQgIT0gbnVsbCAmJiBjb25jdXJyZW50ICE9IG51bGwpIHtcblx0XHRcdG9wdGlvbnMuY29uY3VycmVudCA9IGNvbmN1cnJlbnQ7XG5cdFx0fVxuXHRcdGNvbnN0IHNlcXVlbnRpYWwgPSB0aGlzLnNlcXVlbnRpYWwgPz8gKCF0aGlzLmNvbmN1cnJlbnQgJiYgb3B0aW9ucz8uc2VxdWVudGlhbCk7XG5cdFx0aWYgKG9wdGlvbnMuc2VxdWVudGlhbCAhPSBudWxsICYmIHNlcXVlbnRpYWwgIT0gbnVsbCkge1xuXHRcdFx0b3B0aW9ucy5zZXF1ZW50aWFsID0gc2VxdWVudGlhbDtcblx0XHR9XG5cdFx0Y29uc3QgdGVzdCA9IHRhc2soZm9ybWF0TmFtZShuYW1lKSwge1xuXHRcdFx0Li4udGhpcyxcblx0XHRcdC4uLm9wdGlvbnMsXG5cdFx0XHRoYW5kbGVyXG5cdFx0fSk7XG5cdFx0dGVzdC50eXBlID0gXCJ0ZXN0XCI7XG5cdH0pO1xuXHRjb25zdCBjb2xsZWN0b3IgPSB7XG5cdFx0dHlwZTogXCJjb2xsZWN0b3JcIixcblx0XHRuYW1lLFxuXHRcdG1vZGUsXG5cdFx0c3VpdGUsXG5cdFx0b3B0aW9uczogc3VpdGVPcHRpb25zLFxuXHRcdHRlc3QsXG5cdFx0ZmlsZTogc3VpdGUuZmlsZSxcblx0XHR0YXNrcyxcblx0XHRjb2xsZWN0LFxuXHRcdHRhc2ssXG5cdFx0Y2xlYXIsXG5cdFx0b246IGFkZEhvb2tcblx0fTtcblx0ZnVuY3Rpb24gYWRkSG9vayhuYW1lLCAuLi5mbikge1xuXHRcdGdldEhvb2tzKHN1aXRlKVtuYW1lXS5wdXNoKC4uLmZuKTtcblx0fVxuXHRmdW5jdGlvbiBpbml0U3VpdGUoaW5jbHVkZUxvY2F0aW9uKSB7XG5cdFx0aWYgKHR5cGVvZiBzdWl0ZU9wdGlvbnMgPT09IFwibnVtYmVyXCIpIHtcblx0XHRcdHN1aXRlT3B0aW9ucyA9IHsgdGltZW91dDogc3VpdGVPcHRpb25zIH07XG5cdFx0fVxuXHRcdGNvbnN0IGN1cnJlbnRTdWl0ZSA9IGNvbGxlY3RvckNvbnRleHQuY3VycmVudFN1aXRlPy5zdWl0ZTtcblx0XHRjb25zdCBwYXJlbnRUYXNrID0gY3VycmVudFN1aXRlID8/IGNvbGxlY3RvckNvbnRleHQuY3VycmVudFN1aXRlPy5maWxlO1xuXHRcdGNvbnN0IHN1aXRlVGFncyA9IHRvQXJyYXkoc3VpdGVPcHRpb25zPy50YWdzKTtcblx0XHR2YWxpZGF0ZVRhZ3MocnVubmVyLmNvbmZpZywgc3VpdGVUYWdzKTtcblx0XHRzdWl0ZSA9IHtcblx0XHRcdGlkOiBcIlwiLFxuXHRcdFx0dHlwZTogXCJzdWl0ZVwiLFxuXHRcdFx0bmFtZSxcblx0XHRcdGZ1bGxOYW1lOiBjcmVhdGVUYXNrTmFtZShbY3VycmVudFN1aXRlPy5mdWxsTmFtZSA/PyBjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZT8uZmlsZT8uZnVsbE5hbWUsIG5hbWVdKSxcblx0XHRcdGZ1bGxUZXN0TmFtZTogY3JlYXRlVGFza05hbWUoW2N1cnJlbnRTdWl0ZT8uZnVsbFRlc3ROYW1lLCBuYW1lXSksXG5cdFx0XHRzdWl0ZTogY3VycmVudFN1aXRlLFxuXHRcdFx0bW9kZSxcblx0XHRcdGVhY2gsXG5cdFx0XHRmaWxlOiBjdXJyZW50U3VpdGU/LmZpbGUgPz8gY29sbGVjdG9yQ29udGV4dC5jdXJyZW50U3VpdGU/LmZpbGUsXG5cdFx0XHRzaHVmZmxlOiBzdWl0ZU9wdGlvbnM/LnNodWZmbGUsXG5cdFx0XHR0YXNrczogW10sXG5cdFx0XHRtZXRhOiBzdWl0ZU9wdGlvbnM/Lm1ldGEgPz8gT2JqZWN0LmNyZWF0ZShudWxsKSxcblx0XHRcdGNvbmN1cnJlbnQ6IHN1aXRlT3B0aW9ucz8uY29uY3VycmVudCxcblx0XHRcdHRhZ3M6IHVuaXF1ZShbLi4ucGFyZW50VGFzaz8udGFncyB8fCBbXSwgLi4uc3VpdGVUYWdzXSlcblx0XHR9O1xuXHRcdGlmIChydW5uZXIgJiYgaW5jbHVkZUxvY2F0aW9uICYmIHJ1bm5lci5jb25maWcuaW5jbHVkZVRhc2tMb2NhdGlvbikge1xuXHRcdFx0Y29uc3QgbGltaXQgPSBFcnJvci5zdGFja1RyYWNlTGltaXQ7XG5cdFx0XHRFcnJvci5zdGFja1RyYWNlTGltaXQgPSAxNTtcblx0XHRcdGNvbnN0IGVycm9yID0gbmV3IEVycm9yKFwic3RhY2t0cmFjZVwiKS5zdGFjaztcblx0XHRcdEVycm9yLnN0YWNrVHJhY2VMaW1pdCA9IGxpbWl0O1xuXHRcdFx0Y29uc3Qgc3RhY2sgPSBmaW5kVGVzdEZpbGVTdGFja1RyYWNlKGN1cnJlbnRUZXN0RmlsZXBhdGgsIGVycm9yKTtcblx0XHRcdGlmIChzdGFjaykge1xuXHRcdFx0XHRzdWl0ZS5sb2NhdGlvbiA9IHtcblx0XHRcdFx0XHRsaW5lOiBzdGFjay5saW5lLFxuXHRcdFx0XHRcdGNvbHVtbjogc3RhY2suY29sdW1uXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHNldEhvb2tzKHN1aXRlLCBjcmVhdGVTdWl0ZUhvb2tzKCkpO1xuXHR9XG5cdGZ1bmN0aW9uIGNsZWFyKCkge1xuXHRcdHRhc2tzLmxlbmd0aCA9IDA7XG5cdFx0aW5pdFN1aXRlKGZhbHNlKTtcblx0fVxuXHRhc3luYyBmdW5jdGlvbiBjb2xsZWN0KGZpbGUpIHtcblx0XHRpZiAoIWZpbGUpIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoXCJGaWxlIGlzIHJlcXVpcmVkIHRvIGNvbGxlY3QgdGFza3MuXCIpO1xuXHRcdH1cblx0XHRpZiAoZmFjdG9yeSkge1xuXHRcdFx0YXdhaXQgcnVuV2l0aFN1aXRlKGNvbGxlY3RvciwgKCkgPT4gZmFjdG9yeSh0ZXN0KSk7XG5cdFx0fVxuXHRcdGNvbnN0IGFsbENoaWxkcmVuID0gW107XG5cdFx0Zm9yIChjb25zdCBpIG9mIHRhc2tzKSB7XG5cdFx0XHRhbGxDaGlsZHJlbi5wdXNoKGkudHlwZSA9PT0gXCJjb2xsZWN0b3JcIiA/IGF3YWl0IGkuY29sbGVjdChmaWxlKSA6IGkpO1xuXHRcdH1cblx0XHRzdWl0ZS50YXNrcyA9IGFsbENoaWxkcmVuO1xuXHRcdHJldHVybiBzdWl0ZTtcblx0fVxuXHRjb2xsZWN0VGFzayhjb2xsZWN0b3IpO1xuXHRyZXR1cm4gY29sbGVjdG9yO1xufVxuZnVuY3Rpb24gd2l0aEF3YWl0QXN5bmNBc3NlcnRpb25zKGZuLCB0YXNrKSB7XG5cdHJldHVybiAoYXN5bmMgKC4uLmFyZ3MpID0+IHtcblx0XHRjb25zdCBmblJlc3VsdCA9IGF3YWl0IGZuKC4uLmFyZ3MpO1xuXHRcdC8vIHNvbWUgYXN5bmMgZXhwZWN0IHdpbGwgYmUgYWRkZWQgdG8gdGhpcyBhcnJheSwgaW4gY2FzZSB1c2VyIGZvcmdldCB0byBhd2FpdCB0aGVtXG5cdFx0aWYgKHRhc2sucHJvbWlzZXMpIHtcblx0XHRcdGNvbnN0IHJlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZCh0YXNrLnByb21pc2VzKTtcblx0XHRcdGNvbnN0IGVycm9ycyA9IHJlc3VsdC5tYXAoKHIpID0+IHIuc3RhdHVzID09PSBcInJlamVjdGVkXCIgPyByLnJlYXNvbiA6IHVuZGVmaW5lZCkuZmlsdGVyKEJvb2xlYW4pO1xuXHRcdFx0aWYgKGVycm9ycy5sZW5ndGgpIHtcblx0XHRcdFx0dGhyb3cgZXJyb3JzO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZm5SZXN1bHQ7XG5cdH0pO1xufVxuZnVuY3Rpb24gY3JlYXRlU3VpdGUoKSB7XG5cdGZ1bmN0aW9uIHN1aXRlRm4obmFtZSwgZmFjdG9yeU9yT3B0aW9ucywgb3B0aW9uc09yRmFjdG9yeSkge1xuXHRcdGlmIChnZXRDdXJyZW50VGVzdCgpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDYWxsaW5nIHRoZSBzdWl0ZSBmdW5jdGlvbiBpbnNpZGUgdGVzdCBmdW5jdGlvbiBpcyBub3QgYWxsb3dlZC4gSXQgY2FuIGJlIG9ubHkgY2FsbGVkIGF0IHRoZSB0b3AgbGV2ZWwgb3IgaW5zaWRlIGFub3RoZXIgc3VpdGUgZnVuY3Rpb24uXCIpO1xuXHRcdH1cblx0XHRjb25zdCBjdXJyZW50U3VpdGUgPSBjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZSB8fCBkZWZhdWx0U3VpdGU7XG5cdFx0bGV0IHsgb3B0aW9ucywgaGFuZGxlcjogZmFjdG9yeSB9ID0gcGFyc2VBcmd1bWVudHMoZmFjdG9yeU9yT3B0aW9ucywgb3B0aW9uc09yRmFjdG9yeSk7XG5cdFx0Y29uc3QgaXNDb25jdXJyZW50U3BlY2lmaWVkID0gb3B0aW9ucy5jb25jdXJyZW50IHx8IHRoaXMuY29uY3VycmVudCB8fCBvcHRpb25zLnNlcXVlbnRpYWwgPT09IGZhbHNlO1xuXHRcdGNvbnN0IGlzU2VxdWVudGlhbFNwZWNpZmllZCA9IG9wdGlvbnMuc2VxdWVudGlhbCB8fCB0aGlzLnNlcXVlbnRpYWwgfHwgb3B0aW9ucy5jb25jdXJyZW50ID09PSBmYWxzZTtcblx0XHRjb25zdCB7IG1ldGE6IHBhcmVudE1ldGEsIC4uLnBhcmVudE9wdGlvbnMgfSA9IGN1cnJlbnRTdWl0ZT8ub3B0aW9ucyB8fCB7fTtcblx0XHQvLyBpbmhlcml0IG9wdGlvbnMgZnJvbSBjdXJyZW50IHN1aXRlXG5cdFx0b3B0aW9ucyA9IHtcblx0XHRcdC4uLnBhcmVudE9wdGlvbnMsXG5cdFx0XHQuLi5vcHRpb25zXG5cdFx0fTtcblx0XHRjb25zdCBzaHVmZmxlID0gdGhpcy5zaHVmZmxlID8/IG9wdGlvbnMuc2h1ZmZsZSA/PyBjdXJyZW50U3VpdGU/Lm9wdGlvbnM/LnNodWZmbGUgPz8gcnVubmVyPy5jb25maWcuc2VxdWVuY2Uuc2h1ZmZsZTtcblx0XHRpZiAoc2h1ZmZsZSAhPSBudWxsKSB7XG5cdFx0XHRvcHRpb25zLnNodWZmbGUgPSBzaHVmZmxlO1xuXHRcdH1cblx0XHRsZXQgbW9kZSA9IHRoaXMub25seSA/PyBvcHRpb25zLm9ubHkgPyBcIm9ubHlcIiA6IHRoaXMuc2tpcCA/PyBvcHRpb25zLnNraXAgPyBcInNraXBcIiA6IHRoaXMudG9kbyA/PyBvcHRpb25zLnRvZG8gPyBcInRvZG9cIiA6IFwicnVuXCI7XG5cdFx0Ly8gcGFzc2VkIGFzIHRlc3QobmFtZSksIGFzc3VtZSBpdCdzIGEgXCJ0b2RvXCJcblx0XHRpZiAobW9kZSA9PT0gXCJydW5cIiAmJiAhZmFjdG9yeSkge1xuXHRcdFx0bW9kZSA9IFwidG9kb1wiO1xuXHRcdH1cblx0XHQvLyBpbmhlcml0IGNvbmN1cnJlbnQgLyBzZXF1ZW50aWFsIGZyb20gc3VpdGVcblx0XHRjb25zdCBpc0NvbmN1cnJlbnQgPSBpc0NvbmN1cnJlbnRTcGVjaWZpZWQgfHwgb3B0aW9ucy5jb25jdXJyZW50ICYmICFpc1NlcXVlbnRpYWxTcGVjaWZpZWQ7XG5cdFx0Y29uc3QgaXNTZXF1ZW50aWFsID0gaXNTZXF1ZW50aWFsU3BlY2lmaWVkIHx8IG9wdGlvbnMuc2VxdWVudGlhbCAmJiAhaXNDb25jdXJyZW50U3BlY2lmaWVkO1xuXHRcdGlmIChpc0NvbmN1cnJlbnQgIT0gbnVsbCkge1xuXHRcdFx0b3B0aW9ucy5jb25jdXJyZW50ID0gaXNDb25jdXJyZW50ICYmICFpc1NlcXVlbnRpYWw7XG5cdFx0fVxuXHRcdGlmIChpc1NlcXVlbnRpYWwgIT0gbnVsbCkge1xuXHRcdFx0b3B0aW9ucy5zZXF1ZW50aWFsID0gaXNTZXF1ZW50aWFsICYmICFpc0NvbmN1cnJlbnQ7XG5cdFx0fVxuXHRcdGlmIChwYXJlbnRNZXRhKSB7XG5cdFx0XHRvcHRpb25zLm1ldGEgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHBhcmVudE1ldGEsIG9wdGlvbnMubWV0YSk7XG5cdFx0fVxuXHRcdHJldHVybiBjcmVhdGVTdWl0ZUNvbGxlY3Rvcihmb3JtYXROYW1lKG5hbWUpLCBmYWN0b3J5LCBtb2RlLCB0aGlzLmVhY2gsIG9wdGlvbnMpO1xuXHR9XG5cdHN1aXRlRm4uZWFjaCA9IGZ1bmN0aW9uKGNhc2VzLCAuLi5hcmdzKSB7XG5cdFx0Y29uc3QgY29udGV4dCA9IGdldENoYWluYWJsZUNvbnRleHQodGhpcyk7XG5cdFx0Y29uc3Qgc3VpdGUgPSBjb250ZXh0LndpdGhDb250ZXh0KCk7XG5cdFx0Y29udGV4dC5zZXRDb250ZXh0KFwiZWFjaFwiLCB0cnVlKTtcblx0XHRpZiAoQXJyYXkuaXNBcnJheShjYXNlcykgJiYgYXJncy5sZW5ndGgpIHtcblx0XHRcdGNhc2VzID0gZm9ybWF0VGVtcGxhdGVTdHJpbmcoY2FzZXMsIGFyZ3MpO1xuXHRcdH1cblx0XHRyZXR1cm4gKG5hbWUsIG9wdGlvbnNPckZuLCBmbk9yT3B0aW9ucykgPT4ge1xuXHRcdFx0Y29uc3QgX25hbWUgPSBmb3JtYXROYW1lKG5hbWUpO1xuXHRcdFx0Y29uc3QgYXJyYXlPbmx5Q2FzZXMgPSBjYXNlcy5ldmVyeShBcnJheS5pc0FycmF5KTtcblx0XHRcdGNvbnN0IHsgb3B0aW9ucywgaGFuZGxlciB9ID0gcGFyc2VBcmd1bWVudHMob3B0aW9uc09yRm4sIGZuT3JPcHRpb25zKTtcblx0XHRcdGNvbnN0IGZuRmlyc3QgPSB0eXBlb2Ygb3B0aW9uc09yRm4gPT09IFwiZnVuY3Rpb25cIjtcblx0XHRcdGNhc2VzLmZvckVhY2goKGksIGlkeCkgPT4ge1xuXHRcdFx0XHRjb25zdCBpdGVtcyA9IEFycmF5LmlzQXJyYXkoaSkgPyBpIDogW2ldO1xuXHRcdFx0XHRpZiAoZm5GaXJzdCkge1xuXHRcdFx0XHRcdGlmIChhcnJheU9ubHlDYXNlcykge1xuXHRcdFx0XHRcdFx0c3VpdGUoZm9ybWF0VGl0bGUoX25hbWUsIGl0ZW1zLCBpZHgpLCBoYW5kbGVyID8gKCkgPT4gaGFuZGxlciguLi5pdGVtcykgOiB1bmRlZmluZWQsIG9wdGlvbnMudGltZW91dCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHN1aXRlKGZvcm1hdFRpdGxlKF9uYW1lLCBpdGVtcywgaWR4KSwgaGFuZGxlciA/ICgpID0+IGhhbmRsZXIoaSkgOiB1bmRlZmluZWQsIG9wdGlvbnMudGltZW91dCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmIChhcnJheU9ubHlDYXNlcykge1xuXHRcdFx0XHRcdFx0c3VpdGUoZm9ybWF0VGl0bGUoX25hbWUsIGl0ZW1zLCBpZHgpLCBvcHRpb25zLCBoYW5kbGVyID8gKCkgPT4gaGFuZGxlciguLi5pdGVtcykgOiB1bmRlZmluZWQpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRzdWl0ZShmb3JtYXRUaXRsZShfbmFtZSwgaXRlbXMsIGlkeCksIG9wdGlvbnMsIGhhbmRsZXIgPyAoKSA9PiBoYW5kbGVyKGkpIDogdW5kZWZpbmVkKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdFx0Y29udGV4dC5zZXRDb250ZXh0KFwiZWFjaFwiLCB1bmRlZmluZWQpO1xuXHRcdH07XG5cdH07XG5cdHN1aXRlRm4uZm9yID0gZnVuY3Rpb24oY2FzZXMsIC4uLmFyZ3MpIHtcblx0XHRpZiAoQXJyYXkuaXNBcnJheShjYXNlcykgJiYgYXJncy5sZW5ndGgpIHtcblx0XHRcdGNhc2VzID0gZm9ybWF0VGVtcGxhdGVTdHJpbmcoY2FzZXMsIGFyZ3MpO1xuXHRcdH1cblx0XHRyZXR1cm4gKG5hbWUsIG9wdGlvbnNPckZuLCBmbk9yT3B0aW9ucykgPT4ge1xuXHRcdFx0Y29uc3QgbmFtZV8gPSBmb3JtYXROYW1lKG5hbWUpO1xuXHRcdFx0Y29uc3QgeyBvcHRpb25zLCBoYW5kbGVyIH0gPSBwYXJzZUFyZ3VtZW50cyhvcHRpb25zT3JGbiwgZm5Pck9wdGlvbnMpO1xuXHRcdFx0Y2FzZXMuZm9yRWFjaCgoaXRlbSwgaWR4KSA9PiB7XG5cdFx0XHRcdHN1aXRlKGZvcm1hdFRpdGxlKG5hbWVfLCB0b0FycmF5KGl0ZW0pLCBpZHgpLCBvcHRpb25zLCBoYW5kbGVyID8gKCkgPT4gaGFuZGxlcihpdGVtKSA6IHVuZGVmaW5lZCk7XG5cdFx0XHR9KTtcblx0XHR9O1xuXHR9O1xuXHRzdWl0ZUZuLnNraXBJZiA9IChjb25kaXRpb24pID0+IGNvbmRpdGlvbiA/IHN1aXRlLnNraXAgOiBzdWl0ZTtcblx0c3VpdGVGbi5ydW5JZiA9IChjb25kaXRpb24pID0+IGNvbmRpdGlvbiA/IHN1aXRlIDogc3VpdGUuc2tpcDtcblx0cmV0dXJuIGNyZWF0ZUNoYWluYWJsZShbXG5cdFx0XCJjb25jdXJyZW50XCIsXG5cdFx0XCJzZXF1ZW50aWFsXCIsXG5cdFx0XCJzaHVmZmxlXCIsXG5cdFx0XCJza2lwXCIsXG5cdFx0XCJvbmx5XCIsXG5cdFx0XCJ0b2RvXCJcblx0XSwgc3VpdGVGbik7XG59XG5mdW5jdGlvbiBjcmVhdGVUYXNrQ29sbGVjdG9yKGZuKSB7XG5cdGNvbnN0IHRhc2tGbiA9IGZuO1xuXHR0YXNrRm4uZWFjaCA9IGZ1bmN0aW9uKGNhc2VzLCAuLi5hcmdzKSB7XG5cdFx0Y29uc3QgY29udGV4dCA9IGdldENoYWluYWJsZUNvbnRleHQodGhpcyk7XG5cdFx0Y29uc3QgdGVzdCA9IGNvbnRleHQud2l0aENvbnRleHQoKTtcblx0XHRjb250ZXh0LnNldENvbnRleHQoXCJlYWNoXCIsIHRydWUpO1xuXHRcdGlmIChBcnJheS5pc0FycmF5KGNhc2VzKSAmJiBhcmdzLmxlbmd0aCkge1xuXHRcdFx0Y2FzZXMgPSBmb3JtYXRUZW1wbGF0ZVN0cmluZyhjYXNlcywgYXJncyk7XG5cdFx0fVxuXHRcdHJldHVybiAobmFtZSwgb3B0aW9uc09yRm4sIGZuT3JPcHRpb25zKSA9PiB7XG5cdFx0XHRjb25zdCBfbmFtZSA9IGZvcm1hdE5hbWUobmFtZSk7XG5cdFx0XHRjb25zdCBhcnJheU9ubHlDYXNlcyA9IGNhc2VzLmV2ZXJ5KEFycmF5LmlzQXJyYXkpO1xuXHRcdFx0Y29uc3QgeyBvcHRpb25zLCBoYW5kbGVyIH0gPSBwYXJzZUFyZ3VtZW50cyhvcHRpb25zT3JGbiwgZm5Pck9wdGlvbnMpO1xuXHRcdFx0Y29uc3QgZm5GaXJzdCA9IHR5cGVvZiBvcHRpb25zT3JGbiA9PT0gXCJmdW5jdGlvblwiO1xuXHRcdFx0Y2FzZXMuZm9yRWFjaCgoaSwgaWR4KSA9PiB7XG5cdFx0XHRcdGNvbnN0IGl0ZW1zID0gQXJyYXkuaXNBcnJheShpKSA/IGkgOiBbaV07XG5cdFx0XHRcdGlmIChmbkZpcnN0KSB7XG5cdFx0XHRcdFx0aWYgKGFycmF5T25seUNhc2VzKSB7XG5cdFx0XHRcdFx0XHR0ZXN0KGZvcm1hdFRpdGxlKF9uYW1lLCBpdGVtcywgaWR4KSwgaGFuZGxlciA/ICgpID0+IGhhbmRsZXIoLi4uaXRlbXMpIDogdW5kZWZpbmVkLCBvcHRpb25zLnRpbWVvdXQpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0ZXN0KGZvcm1hdFRpdGxlKF9uYW1lLCBpdGVtcywgaWR4KSwgaGFuZGxlciA/ICgpID0+IGhhbmRsZXIoaSkgOiB1bmRlZmluZWQsIG9wdGlvbnMudGltZW91dCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGlmIChhcnJheU9ubHlDYXNlcykge1xuXHRcdFx0XHRcdFx0dGVzdChmb3JtYXRUaXRsZShfbmFtZSwgaXRlbXMsIGlkeCksIG9wdGlvbnMsIGhhbmRsZXIgPyAoKSA9PiBoYW5kbGVyKC4uLml0ZW1zKSA6IHVuZGVmaW5lZCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHRlc3QoZm9ybWF0VGl0bGUoX25hbWUsIGl0ZW1zLCBpZHgpLCBvcHRpb25zLCBoYW5kbGVyID8gKCkgPT4gaGFuZGxlcihpKSA6IHVuZGVmaW5lZCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdGNvbnRleHQuc2V0Q29udGV4dChcImVhY2hcIiwgdW5kZWZpbmVkKTtcblx0XHR9O1xuXHR9O1xuXHR0YXNrRm4uZm9yID0gZnVuY3Rpb24oY2FzZXMsIC4uLmFyZ3MpIHtcblx0XHRjb25zdCBjb250ZXh0ID0gZ2V0Q2hhaW5hYmxlQ29udGV4dCh0aGlzKTtcblx0XHRjb25zdCB0ZXN0ID0gY29udGV4dC53aXRoQ29udGV4dCgpO1xuXHRcdGlmIChBcnJheS5pc0FycmF5KGNhc2VzKSAmJiBhcmdzLmxlbmd0aCkge1xuXHRcdFx0Y2FzZXMgPSBmb3JtYXRUZW1wbGF0ZVN0cmluZyhjYXNlcywgYXJncyk7XG5cdFx0fVxuXHRcdHJldHVybiAobmFtZSwgb3B0aW9uc09yRm4sIGZuT3JPcHRpb25zKSA9PiB7XG5cdFx0XHRjb25zdCBfbmFtZSA9IGZvcm1hdE5hbWUobmFtZSk7XG5cdFx0XHRjb25zdCB7IG9wdGlvbnMsIGhhbmRsZXIgfSA9IHBhcnNlQXJndW1lbnRzKG9wdGlvbnNPckZuLCBmbk9yT3B0aW9ucyk7XG5cdFx0XHRjYXNlcy5mb3JFYWNoKChpdGVtLCBpZHgpID0+IHtcblx0XHRcdFx0Ly8gbW9ua2V5LXBhdGNoIGhhbmRsZXIgdG8gYWxsb3cgcGFyc2luZyBmaXh0dXJlXG5cdFx0XHRcdGNvbnN0IGhhbmRsZXJXcmFwcGVyID0gaGFuZGxlciA/IChjdHgpID0+IGhhbmRsZXIoaXRlbSwgY3R4KSA6IHVuZGVmaW5lZDtcblx0XHRcdFx0aWYgKGhhbmRsZXJXcmFwcGVyKSB7XG5cdFx0XHRcdFx0Y29uZmlndXJlUHJvcHMoaGFuZGxlcldyYXBwZXIsIHtcblx0XHRcdFx0XHRcdGluZGV4OiAxLFxuXHRcdFx0XHRcdFx0b3JpZ2luYWw6IGhhbmRsZXJcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0ZXN0KGZvcm1hdFRpdGxlKF9uYW1lLCB0b0FycmF5KGl0ZW0pLCBpZHgpLCBvcHRpb25zLCBoYW5kbGVyV3JhcHBlcik7XG5cdFx0XHR9KTtcblx0XHR9O1xuXHR9O1xuXHR0YXNrRm4uc2tpcElmID0gZnVuY3Rpb24oY29uZGl0aW9uKSB7XG5cdFx0cmV0dXJuIGNvbmRpdGlvbiA/IHRoaXMuc2tpcCA6IHRoaXM7XG5cdH07XG5cdHRhc2tGbi5ydW5JZiA9IGZ1bmN0aW9uKGNvbmRpdGlvbikge1xuXHRcdHJldHVybiBjb25kaXRpb24gPyB0aGlzIDogdGhpcy5za2lwO1xuXHR9O1xuXHQvKipcblx0KiBQYXJzZSBidWlsZGVyIHBhdHRlcm4gYXJndW1lbnRzIGludG8gYSBmaXh0dXJlcyBvYmplY3QuXG5cdCogSGFuZGxlcyBib3RoIGJ1aWxkZXIgcGF0dGVybiAobmFtZSwgb3B0aW9ucz8sIHZhbHVlKSBhbmQgb2JqZWN0IHN5bnRheC5cblx0Ki9cblx0ZnVuY3Rpb24gcGFyc2VCdWlsZGVyRml4dHVyZXMoZml4dHVyZXNPck5hbWUsIG9wdGlvbnNPckZuLCBtYXliZUZuKSB7XG5cdFx0Ly8gT2JqZWN0IHN5bnRheDoganVzdCByZXR1cm4gYXMtaXNcblx0XHRpZiAodHlwZW9mIGZpeHR1cmVzT3JOYW1lICE9PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRyZXR1cm4gZml4dHVyZXNPck5hbWU7XG5cdFx0fVxuXHRcdGNvbnN0IGZpeHR1cmVOYW1lID0gZml4dHVyZXNPck5hbWU7XG5cdFx0bGV0IGZpeHR1cmVPcHRpb25zO1xuXHRcdGxldCBmaXh0dXJlVmFsdWU7XG5cdFx0aWYgKG1heWJlRm4gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0Ly8gKG5hbWUsIG9wdGlvbnMsIHZhbHVlKSBvciAobmFtZSwgb3B0aW9ucywgZm4pXG5cdFx0XHRmaXh0dXJlT3B0aW9ucyA9IG9wdGlvbnNPckZuO1xuXHRcdFx0Zml4dHVyZVZhbHVlID0gbWF5YmVGbjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gKG5hbWUsIHZhbHVlKSBvciAobmFtZSwgZm4pXG5cdFx0XHQvLyBDaGVjayBpZiBvcHRpb25zT3JGbiBsb29rcyBsaWtlIGZpeHR1cmUgb3B0aW9ucyAoaGFzIHNjb3BlIG9yIGF1dG8pXG5cdFx0XHRpZiAob3B0aW9uc09yRm4gIT09IG51bGwgJiYgdHlwZW9mIG9wdGlvbnNPckZuID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KG9wdGlvbnNPckZuKSAmJiBUZXN0Rml4dHVyZXMuaXNGaXh0dXJlT3B0aW9ucyhvcHRpb25zT3JGbikpIHtcblx0XHRcdFx0Ly8gKG5hbWUsIG9wdGlvbnMpIHdpdGggbm8gdmFsdWUgLSB0cmVhdCBhcyBlbXB0eSBvYmplY3QgZml4dHVyZVxuXHRcdFx0XHRmaXh0dXJlT3B0aW9ucyA9IG9wdGlvbnNPckZuO1xuXHRcdFx0XHRmaXh0dXJlVmFsdWUgPSB7fTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIChuYW1lLCB2YWx1ZSkgb3IgKG5hbWUsIGZuKVxuXHRcdFx0XHRmaXh0dXJlT3B0aW9ucyA9IHVuZGVmaW5lZDtcblx0XHRcdFx0Zml4dHVyZVZhbHVlID0gb3B0aW9uc09yRm47XG5cdFx0XHR9XG5cdFx0fVxuXHRcdC8vIEZ1bmN0aW9uIHZhbHVlOiB3cmFwIHdpdGggb25DbGVhbnVwIHBhdHRlcm5cblx0XHRpZiAodHlwZW9mIGZpeHR1cmVWYWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRjb25zdCBidWlsZGVyRm4gPSBmaXh0dXJlVmFsdWU7XG5cdFx0XHQvLyBXcmFwIGJ1aWxkZXIgcGF0dGVybiBmdW5jdGlvbiAocmV0dXJucyB2YWx1ZSkgdG8gdXNlKCkgcGF0dGVyblxuXHRcdFx0Y29uc3QgZml4dHVyZSA9IGFzeW5jIChjdHgsIHVzZSkgPT4ge1xuXHRcdFx0XHRsZXQgY2xlYW51cDtcblx0XHRcdFx0Y29uc3Qgb25DbGVhbnVwID0gKGZuKSA9PiB7XG5cdFx0XHRcdFx0aWYgKGNsZWFudXAgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBvbkNsZWFudXAgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UgcGVyIGZpeHR1cmUuIGAgKyBgRGVmaW5lIHNlcGFyYXRlIGZpeHR1cmVzIGlmIHlvdSBuZWVkIG11bHRpcGxlIGNsZWFudXAgZnVuY3Rpb25zLmApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRjbGVhbnVwID0gZm47XG5cdFx0XHRcdH07XG5cdFx0XHRcdGNvbnN0IHZhbHVlID0gYXdhaXQgYnVpbGRlckZuKGN0eCwgeyBvbkNsZWFudXAgfSk7XG5cdFx0XHRcdGF3YWl0IHVzZSh2YWx1ZSk7XG5cdFx0XHRcdGlmIChjbGVhbnVwKSB7XG5cdFx0XHRcdFx0YXdhaXQgY2xlYW51cCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0Y29uZmlndXJlUHJvcHMoZml4dHVyZSwgeyBvcmlnaW5hbDogYnVpbGRlckZuIH0pO1xuXHRcdFx0aWYgKGZpeHR1cmVPcHRpb25zKSB7XG5cdFx0XHRcdHJldHVybiB7IFtmaXh0dXJlTmFtZV06IFtmaXh0dXJlLCBmaXh0dXJlT3B0aW9uc10gfTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB7IFtmaXh0dXJlTmFtZV06IGZpeHR1cmUgfTtcblx0XHR9XG5cdFx0Ly8gTm9uLWZ1bmN0aW9uIHZhbHVlOiB1c2UgZGlyZWN0bHlcblx0XHRpZiAoZml4dHVyZU9wdGlvbnMpIHtcblx0XHRcdHJldHVybiB7IFtmaXh0dXJlTmFtZV06IFtmaXh0dXJlVmFsdWUsIGZpeHR1cmVPcHRpb25zXSB9O1xuXHRcdH1cblx0XHRyZXR1cm4geyBbZml4dHVyZU5hbWVdOiBmaXh0dXJlVmFsdWUgfTtcblx0fVxuXHR0YXNrRm4ub3ZlcnJpZGUgPSBmdW5jdGlvbihmaXh0dXJlc09yTmFtZSwgb3B0aW9uc09yRm4sIG1heWJlRm4pIHtcblx0XHRjb25zdCB1c2VyRml4dHVyZXMgPSBwYXJzZUJ1aWxkZXJGaXh0dXJlcyhmaXh0dXJlc09yTmFtZSwgb3B0aW9uc09yRm4sIG1heWJlRm4pO1xuXHRcdGdldENoYWluYWJsZUNvbnRleHQodGhpcykuZ2V0Rml4dHVyZXMoKS5vdmVycmlkZShydW5uZXIsIHVzZXJGaXh0dXJlcyk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH07XG5cdHRhc2tGbi5zY29wZWQgPSBmdW5jdGlvbihmaXh0dXJlcykge1xuXHRcdGNvbnNvbGUud2FybihgdGVzdC5zY29wZWQoKSBpcyBkZXByZWNhdGVkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIHZlcnNpb25zLiBQbGVhc2UgdXNlIHRlc3Qub3ZlcnJpZGUoKSBpbnN0ZWFkLmApO1xuXHRcdHJldHVybiB0aGlzLm92ZXJyaWRlKGZpeHR1cmVzKTtcblx0fTtcblx0dGFza0ZuLmV4dGVuZCA9IGZ1bmN0aW9uKGZpeHR1cmVzT3JOYW1lLCBvcHRpb25zT3JGbiwgbWF5YmVGbikge1xuXHRcdGNvbnN0IHVzZXJGaXh0dXJlcyA9IHBhcnNlQnVpbGRlckZpeHR1cmVzKGZpeHR1cmVzT3JOYW1lLCBvcHRpb25zT3JGbiwgbWF5YmVGbik7XG5cdFx0Y29uc3QgZml4dHVyZXMgPSBnZXRDaGFpbmFibGVDb250ZXh0KHRoaXMpLmdldEZpeHR1cmVzKCkuZXh0ZW5kKHJ1bm5lciwgdXNlckZpeHR1cmVzKTtcblx0XHRjb25zdCBfdGVzdCA9IGNyZWF0ZVRlc3QoZnVuY3Rpb24obmFtZSwgb3B0aW9uc09yRm4sIG9wdGlvbnNPclRlc3QpIHtcblx0XHRcdGZuLmNhbGwodGhpcywgZm9ybWF0TmFtZShuYW1lKSwgb3B0aW9uc09yRm4sIG9wdGlvbnNPclRlc3QpO1xuXHRcdH0pO1xuXHRcdGdldENoYWluYWJsZUNvbnRleHQoX3Rlc3QpLm1lcmdlQ29udGV4dCh7IGZpeHR1cmVzIH0pO1xuXHRcdHJldHVybiBfdGVzdDtcblx0fTtcblx0dGFza0ZuLmRlc2NyaWJlID0gc3VpdGU7XG5cdHRhc2tGbi5zdWl0ZSA9IHN1aXRlO1xuXHR0YXNrRm4uYmVmb3JlRWFjaCA9IGJlZm9yZUVhY2g7XG5cdHRhc2tGbi5hZnRlckVhY2ggPSBhZnRlckVhY2g7XG5cdHRhc2tGbi5iZWZvcmVBbGwgPSBiZWZvcmVBbGw7XG5cdHRhc2tGbi5hZnRlckFsbCA9IGFmdGVyQWxsO1xuXHR0YXNrRm4uYXJvdW5kRWFjaCA9IGFyb3VuZEVhY2g7XG5cdHRhc2tGbi5hcm91bmRBbGwgPSBhcm91bmRBbGw7XG5cdGNvbnN0IF90ZXN0ID0gY3JlYXRlQ2hhaW5hYmxlKFtcblx0XHRcImNvbmN1cnJlbnRcIixcblx0XHRcInNlcXVlbnRpYWxcIixcblx0XHRcInNraXBcIixcblx0XHRcIm9ubHlcIixcblx0XHRcInRvZG9cIixcblx0XHRcImZhaWxzXCJcblx0XSwgdGFza0ZuLCB7IGZpeHR1cmVzOiBuZXcgVGVzdEZpeHR1cmVzKCkgfSk7XG5cdHJldHVybiBfdGVzdDtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVRlc3QoZm4pIHtcblx0cmV0dXJuIGNyZWF0ZVRhc2tDb2xsZWN0b3IoZm4pO1xufVxuZnVuY3Rpb24gZm9ybWF0TmFtZShuYW1lKSB7XG5cdHJldHVybiB0eXBlb2YgbmFtZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWUgOiB0eXBlb2YgbmFtZSA9PT0gXCJmdW5jdGlvblwiID8gbmFtZS5uYW1lIHx8IFwiPGFub255bW91cz5cIiA6IFN0cmluZyhuYW1lKTtcbn1cbmZ1bmN0aW9uIGZvcm1hdFRpdGxlKHRlbXBsYXRlLCBpdGVtcywgaWR4KSB7XG5cdGlmICh0ZW1wbGF0ZS5pbmNsdWRlcyhcIiUjXCIpIHx8IHRlbXBsYXRlLmluY2x1ZGVzKFwiJSRcIikpIHtcblx0XHQvLyAnJSMnIG1hdGNoIGluZGV4IG9mIHRoZSB0ZXN0IGNhc2Vcblx0XHR0ZW1wbGF0ZSA9IHRlbXBsYXRlLnJlcGxhY2UoLyUlL2csIFwiX192aXRlc3RfZXNjYXBlZF8lX19cIikucmVwbGFjZSgvJSMvZywgYCR7aWR4fWApLnJlcGxhY2UoLyVcXCQvZywgYCR7aWR4ICsgMX1gKS5yZXBsYWNlKC9fX3ZpdGVzdF9lc2NhcGVkXyVfXy9nLCBcIiUlXCIpO1xuXHR9XG5cdGNvbnN0IGNvdW50ID0gdGVtcGxhdGUuc3BsaXQoXCIlXCIpLmxlbmd0aCAtIDE7XG5cdGlmICh0ZW1wbGF0ZS5pbmNsdWRlcyhcIiVmXCIpKSB7XG5cdFx0Y29uc3QgcGxhY2Vob2xkZXJzID0gdGVtcGxhdGUubWF0Y2goLyVmL2cpIHx8IFtdO1xuXHRcdHBsYWNlaG9sZGVycy5mb3JFYWNoKChfLCBpKSA9PiB7XG5cdFx0XHRpZiAoaXNOZWdhdGl2ZU5hTihpdGVtc1tpXSkgfHwgT2JqZWN0LmlzKGl0ZW1zW2ldLCAtMCkpIHtcblx0XHRcdFx0Ly8gUmVwbGFjZSB0aGUgaS10aCBvY2N1cnJlbmNlIG9mICclZicgd2l0aCAnLSVmJ1xuXHRcdFx0XHRsZXQgb2NjdXJyZW5jZSA9IDA7XG5cdFx0XHRcdHRlbXBsYXRlID0gdGVtcGxhdGUucmVwbGFjZSgvJWYvZywgKG1hdGNoKSA9PiB7XG5cdFx0XHRcdFx0b2NjdXJyZW5jZSsrO1xuXHRcdFx0XHRcdHJldHVybiBvY2N1cnJlbmNlID09PSBpICsgMSA/IFwiLSVmXCIgOiBtYXRjaDtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblx0Y29uc3QgaXNPYmplY3RJdGVtID0gaXNPYmplY3QoaXRlbXNbMF0pO1xuXHRmdW5jdGlvbiBmb3JtYXRBdHRyaWJ1dGUocykge1xuXHRcdHJldHVybiBzLnJlcGxhY2UoL1xcJChbJFxcdy5dKykvZywgKF8sIGtleSkgPT4ge1xuXHRcdFx0Y29uc3QgaXNBcnJheUtleSA9IC9eXFxkKyQvLnRlc3Qoa2V5KTtcblx0XHRcdGlmICghaXNPYmplY3RJdGVtICYmICFpc0FycmF5S2V5KSB7XG5cdFx0XHRcdHJldHVybiBgJCR7a2V5fWA7XG5cdFx0XHR9XG5cdFx0XHRjb25zdCBhcnJheUVsZW1lbnQgPSBpc0FycmF5S2V5ID8gb2JqZWN0QXR0cihpdGVtcywga2V5KSA6IHVuZGVmaW5lZDtcblx0XHRcdGNvbnN0IHZhbHVlID0gaXNPYmplY3RJdGVtID8gb2JqZWN0QXR0cihpdGVtc1swXSwga2V5LCBhcnJheUVsZW1lbnQpIDogYXJyYXlFbGVtZW50O1xuXHRcdFx0cmV0dXJuIG9iakRpc3BsYXkodmFsdWUsIHsgdHJ1bmNhdGU6IHJ1bm5lcj8uY29uZmlnPy5jaGFpQ29uZmlnPy50cnVuY2F0ZVRocmVzaG9sZCB9KTtcblx0XHR9KTtcblx0fVxuXHRsZXQgb3V0cHV0ID0gXCJcIjtcblx0bGV0IGkgPSAwO1xuXHRoYW5kbGVSZWdleE1hdGNoKFxuXHRcdHRlbXBsYXRlLFxuXHRcdGZvcm1hdFJlZ0V4cCxcblx0XHQvLyBmb3JtYXQgXCIlXCJcblx0XHQobWF0Y2gpID0+IHtcblx0XHRcdGlmIChpIDwgY291bnQpIHtcblx0XHRcdFx0b3V0cHV0ICs9IGZvcm1hdChtYXRjaFswXSwgaXRlbXNbaSsrXSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXQgKz0gbWF0Y2hbMF07XG5cdFx0XHR9XG5cdFx0fSxcblx0XHQvLyBmb3JtYXQgXCIkXCJcblx0XHQobm9uTWF0Y2gpID0+IHtcblx0XHRcdG91dHB1dCArPSBmb3JtYXRBdHRyaWJ1dGUobm9uTWF0Y2gpO1xuXHRcdH1cblx0KTtcblx0cmV0dXJuIG91dHB1dDtcbn1cbi8vIGJhc2VkIG9uIGh0dHBzOi8vZ2l0aHViLmNvbS91bm9jc3MvdW5vY3NzL2Jsb2IvMmU3NGIzMTYyNWJiZTNiOWM4MzUxNTcwNzQ5YWEyZDNmNzk5ZDkxOS9wYWNrYWdlcy9hdXRvY29tcGxldGUvc3JjL3BhcnNlLnRzI0wxMVxuZnVuY3Rpb24gaGFuZGxlUmVnZXhNYXRjaChpbnB1dCwgcmVnZXgsIG9uTWF0Y2gsIG9uTm9uTWF0Y2gpIHtcblx0bGV0IGxhc3RJbmRleCA9IDA7XG5cdGZvciAoY29uc3QgbSBvZiBpbnB1dC5tYXRjaEFsbChyZWdleCkpIHtcblx0XHRpZiAobGFzdEluZGV4IDwgbS5pbmRleCkge1xuXHRcdFx0b25Ob25NYXRjaChpbnB1dC5zbGljZShsYXN0SW5kZXgsIG0uaW5kZXgpKTtcblx0XHR9XG5cdFx0b25NYXRjaChtKTtcblx0XHRsYXN0SW5kZXggPSBtLmluZGV4ICsgbVswXS5sZW5ndGg7XG5cdH1cblx0aWYgKGxhc3RJbmRleCA8IGlucHV0Lmxlbmd0aCkge1xuXHRcdG9uTm9uTWF0Y2goaW5wdXQuc2xpY2UobGFzdEluZGV4KSk7XG5cdH1cbn1cbmZ1bmN0aW9uIGZvcm1hdFRlbXBsYXRlU3RyaW5nKGNhc2VzLCBhcmdzKSB7XG5cdGNvbnN0IGhlYWRlciA9IGNhc2VzLmpvaW4oXCJcIikudHJpbSgpLnJlcGxhY2UoLyAvZywgXCJcIikuc3BsaXQoXCJcXG5cIikubWFwKChpKSA9PiBpLnNwbGl0KFwifFwiKSlbMF07XG5cdGNvbnN0IHJlcyA9IFtdO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IE1hdGguZmxvb3IoYXJncy5sZW5ndGggLyBoZWFkZXIubGVuZ3RoKTsgaSsrKSB7XG5cdFx0Y29uc3Qgb25lQ2FzZSA9IHt9O1xuXHRcdGZvciAobGV0IGogPSAwOyBqIDwgaGVhZGVyLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRvbmVDYXNlW2hlYWRlcltqXV0gPSBhcmdzW2kgKiBoZWFkZXIubGVuZ3RoICsgal07XG5cdFx0fVxuXHRcdHJlcy5wdXNoKG9uZUNhc2UpO1xuXHR9XG5cdHJldHVybiByZXM7XG59XG5cbmNvbnN0IG5vdyQyID0gZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZSA/IGdsb2JhbFRoaXMucGVyZm9ybWFuY2Uubm93LmJpbmQoZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZSkgOiBEYXRlLm5vdztcbmNvbnN0IGNvbGxlY3RvckNvbnRleHQgPSB7XG5cdHRhc2tzOiBbXSxcblx0Y3VycmVudFN1aXRlOiBudWxsXG59O1xuZnVuY3Rpb24gY29sbGVjdFRhc2sodGFzaykge1xuXHRjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZT8udGFza3MucHVzaCh0YXNrKTtcbn1cbmFzeW5jIGZ1bmN0aW9uIHJ1bldpdGhTdWl0ZShzdWl0ZSwgZm4pIHtcblx0Y29uc3QgcHJldiA9IGNvbGxlY3RvckNvbnRleHQuY3VycmVudFN1aXRlO1xuXHRjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZSA9IHN1aXRlO1xuXHRhd2FpdCBmbigpO1xuXHRjb2xsZWN0b3JDb250ZXh0LmN1cnJlbnRTdWl0ZSA9IHByZXY7XG59XG5mdW5jdGlvbiB3aXRoVGltZW91dChmbiwgdGltZW91dCwgaXNIb29rID0gZmFsc2UsIHN0YWNrVHJhY2VFcnJvciwgb25UaW1lb3V0KSB7XG5cdGlmICh0aW1lb3V0IDw9IDAgfHwgdGltZW91dCA9PT0gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZKSB7XG5cdFx0cmV0dXJuIGZuO1xuXHR9XG5cdGNvbnN0IHsgc2V0VGltZW91dCwgY2xlYXJUaW1lb3V0IH0gPSBnZXRTYWZlVGltZXJzKCk7XG5cdC8vIHRoaXMgZnVuY3Rpb24gbmFtZSBpcyB1c2VkIHRvIGZpbHRlciBlcnJvciBpbiB0ZXN0L2NsaS90ZXN0L2ZhaWxzLnRlc3QudHNcblx0cmV0dXJuIChmdW5jdGlvbiBydW5XaXRoVGltZW91dCguLi5hcmdzKSB7XG5cdFx0Y29uc3Qgc3RhcnRUaW1lID0gbm93JDIoKTtcblx0XHRjb25zdCBydW5uZXIgPSBnZXRSdW5uZXIoKTtcblx0XHRydW5uZXIuX2N1cnJlbnRUYXNrU3RhcnRUaW1lID0gc3RhcnRUaW1lO1xuXHRcdHJ1bm5lci5fY3VycmVudFRhc2tUaW1lb3V0ID0gdGltZW91dDtcblx0XHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmVfLCByZWplY3RfKSA9PiB7XG5cdFx0XHRjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRjbGVhclRpbWVvdXQodGltZXIpO1xuXHRcdFx0XHRyZWplY3RUaW1lb3V0RXJyb3IoKTtcblx0XHRcdH0sIHRpbWVvdXQpO1xuXHRcdFx0Ly8gYHVucmVmYCBtaWdodCBub3QgZXhpc3QgaW4gYnJvd3NlclxuXHRcdFx0dGltZXIudW5yZWY/LigpO1xuXHRcdFx0ZnVuY3Rpb24gcmVqZWN0VGltZW91dEVycm9yKCkge1xuXHRcdFx0XHRjb25zdCBlcnJvciA9IG1ha2VUaW1lb3V0RXJyb3IoaXNIb29rLCB0aW1lb3V0LCBzdGFja1RyYWNlRXJyb3IpO1xuXHRcdFx0XHRvblRpbWVvdXQ/LihhcmdzLCBlcnJvcik7XG5cdFx0XHRcdHJlamVjdF8oZXJyb3IpO1xuXHRcdFx0fVxuXHRcdFx0ZnVuY3Rpb24gcmVzb2x2ZShyZXN1bHQpIHtcblx0XHRcdFx0cnVubmVyLl9jdXJyZW50VGFza1N0YXJ0VGltZSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0cnVubmVyLl9jdXJyZW50VGFza1RpbWVvdXQgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdGNsZWFyVGltZW91dCh0aW1lcik7XG5cdFx0XHRcdC8vIGlmIHRlc3QvaG9vayB0b29rIHRvbyBsb25nIGluIG1pY3JvdGFzaywgc2V0VGltZW91dCB3b24ndCBiZSB0cmlnZ2VyZWQsXG5cdFx0XHRcdC8vIGJ1dCB3ZSBzdGlsbCBuZWVkIHRvIGZhaWwgdGhlIHRlc3QsIHNlZVxuXHRcdFx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvaXNzdWVzLzI5MjBcblx0XHRcdFx0aWYgKG5vdyQyKCkgLSBzdGFydFRpbWUgPj0gdGltZW91dCkge1xuXHRcdFx0XHRcdHJlamVjdFRpbWVvdXRFcnJvcigpO1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXNvbHZlXyhyZXN1bHQpO1xuXHRcdFx0fVxuXHRcdFx0ZnVuY3Rpb24gcmVqZWN0KGVycm9yKSB7XG5cdFx0XHRcdHJ1bm5lci5fY3VycmVudFRhc2tTdGFydFRpbWUgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdHJ1bm5lci5fY3VycmVudFRhc2tUaW1lb3V0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRjbGVhclRpbWVvdXQodGltZXIpO1xuXHRcdFx0XHRyZWplY3RfKGVycm9yKTtcblx0XHRcdH1cblx0XHRcdC8vIHN5bmMgdGVzdC9ob29rIHdpbGwgYmUgY2F1Z2h0IGJ5IHRyeS9jYXRjaFxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gZm4oLi4uYXJncyk7XG5cdFx0XHRcdC8vIHRoZSByZXN1bHQgaXMgYSB0aGVuYWJsZSwgd2UgZG9uJ3Qgd3JhcCB0aGlzIGluIFByb21pc2UucmVzb2x2ZVxuXHRcdFx0XHQvLyB0byBhdm9pZCBjcmVhdGluZyBuZXcgcHJvbWlzZXNcblx0XHRcdFx0aWYgKHR5cGVvZiByZXN1bHQgPT09IFwib2JqZWN0XCIgJiYgcmVzdWx0ICE9IG51bGwgJiYgdHlwZW9mIHJlc3VsdC50aGVuID09PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0XHRyZXN1bHQudGhlbihyZXNvbHZlLCByZWplY3QpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJlc29sdmUocmVzdWx0KTtcblx0XHRcdFx0fVxuXHRcdFx0fSBcblx0XHRcdC8vIHVzZXIgc3luYyB0ZXN0L2hvb2sgdGhyb3dzIGFuIGVycm9yXG5jYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0cmVqZWN0KGVycm9yKTtcblx0XHRcdH1cblx0XHR9KTtcblx0fSk7XG59XG5mdW5jdGlvbiB3aXRoQ2FuY2VsKGZuLCBzaWduYWwpIHtcblx0cmV0dXJuIChmdW5jdGlvbiBydW5XaXRoQ2FuY2VsKC4uLmFyZ3MpIHtcblx0XHRyZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuXHRcdFx0c2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCAoKSA9PiByZWplY3Qoc2lnbmFsLnJlYXNvbikpO1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29uc3QgcmVzdWx0ID0gZm4oLi4uYXJncyk7XG5cdFx0XHRcdGlmICh0eXBlb2YgcmVzdWx0ID09PSBcIm9iamVjdFwiICYmIHJlc3VsdCAhPSBudWxsICYmIHR5cGVvZiByZXN1bHQudGhlbiA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdFx0cmVzdWx0LnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZXNvbHZlKHJlc3VsdCk7XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdHJlamVjdChlcnJvcik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH0pO1xufVxuY29uc3QgYWJvcnRDb250cm9sbGVycyA9IG5ldyBXZWFrTWFwKCk7XG5mdW5jdGlvbiBhYm9ydElmVGltZW91dChbY29udGV4dF0sIGVycm9yKSB7XG5cdGlmIChjb250ZXh0KSB7XG5cdFx0YWJvcnRDb250ZXh0U2lnbmFsKGNvbnRleHQsIGVycm9yKTtcblx0fVxufVxuZnVuY3Rpb24gYWJvcnRDb250ZXh0U2lnbmFsKGNvbnRleHQsIGVycm9yKSB7XG5cdGNvbnN0IGFib3J0Q29udHJvbGxlciA9IGFib3J0Q29udHJvbGxlcnMuZ2V0KGNvbnRleHQpO1xuXHRhYm9ydENvbnRyb2xsZXI/LmFib3J0KGVycm9yKTtcbn1cbmZ1bmN0aW9uIGNyZWF0ZVRlc3RDb250ZXh0KHRlc3QsIHJ1bm5lcikge1xuXHRjb25zdCBjb250ZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiZG9uZSgpIGNhbGxiYWNrIGlzIGRlcHJlY2F0ZWQsIHVzZSBwcm9taXNlIGluc3RlYWRcIik7XG5cdH07XG5cdGxldCBhYm9ydENvbnRyb2xsZXIgPSBhYm9ydENvbnRyb2xsZXJzLmdldChjb250ZXh0KTtcblx0aWYgKCFhYm9ydENvbnRyb2xsZXIpIHtcblx0XHRhYm9ydENvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cdFx0YWJvcnRDb250cm9sbGVycy5zZXQoY29udGV4dCwgYWJvcnRDb250cm9sbGVyKTtcblx0fVxuXHRjb250ZXh0LnNpZ25hbCA9IGFib3J0Q29udHJvbGxlci5zaWduYWw7XG5cdGNvbnRleHQudGFzayA9IHRlc3Q7XG5cdGNvbnRleHQuc2tpcCA9IChjb25kaXRpb24sIG5vdGUpID0+IHtcblx0XHRpZiAoY29uZGl0aW9uID09PSBmYWxzZSkge1xuXHRcdFx0Ly8gZG8gbm90aGluZ1xuXHRcdFx0cmV0dXJuIHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0dGVzdC5yZXN1bHQgPz89IHsgc3RhdGU6IFwic2tpcFwiIH07XG5cdFx0dGVzdC5yZXN1bHQucGVuZGluZyA9IHRydWU7XG5cdFx0dGhyb3cgbmV3IFBlbmRpbmdFcnJvcihcInRlc3QgaXMgc2tpcHBlZDsgYWJvcnQgZXhlY3V0aW9uXCIsIHRlc3QsIHR5cGVvZiBjb25kaXRpb24gPT09IFwic3RyaW5nXCIgPyBjb25kaXRpb24gOiBub3RlKTtcblx0fTtcblx0Y29udGV4dC5hbm5vdGF0ZSA9ICgobWVzc2FnZSwgdHlwZSwgYXR0YWNobWVudCkgPT4ge1xuXHRcdGlmICh0ZXN0LnJlc3VsdCAmJiB0ZXN0LnJlc3VsdC5zdGF0ZSAhPT0gXCJydW5cIikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgYW5ub3RhdGUgdGVzdHMgb3V0c2lkZSBvZiB0aGUgdGVzdCBydW4uIFRoZSB0ZXN0IFwiJHt0ZXN0Lm5hbWV9XCIgZmluaXNoZWQgcnVubmluZyB3aXRoIHRoZSBcIiR7dGVzdC5yZXN1bHQuc3RhdGV9XCIgc3RhdGUgYWxyZWFkeS5gKTtcblx0XHR9XG5cdFx0Y29uc3QgYW5ub3RhdGlvbiA9IHtcblx0XHRcdG1lc3NhZ2UsXG5cdFx0XHR0eXBlOiB0eXBlb2YgdHlwZSA9PT0gXCJvYmplY3RcIiB8fCB0eXBlID09PSB1bmRlZmluZWQgPyBcIm5vdGljZVwiIDogdHlwZVxuXHRcdH07XG5cdFx0Y29uc3QgYW5ub3RhdGlvbkF0dGFjaG1lbnQgPSB0eXBlb2YgdHlwZSA9PT0gXCJvYmplY3RcIiA/IHR5cGUgOiBhdHRhY2htZW50O1xuXHRcdGlmIChhbm5vdGF0aW9uQXR0YWNobWVudCkge1xuXHRcdFx0YW5ub3RhdGlvbi5hdHRhY2htZW50ID0gYW5ub3RhdGlvbkF0dGFjaG1lbnQ7XG5cdFx0XHRtYW5hZ2VBcnRpZmFjdEF0dGFjaG1lbnQoYW5ub3RhdGlvbi5hdHRhY2htZW50KTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlY29yZEFzeW5jT3BlcmF0aW9uKHRlc3QsIHJlY29yZEFydGlmYWN0KHRlc3QsIHtcblx0XHRcdHR5cGU6IFwiaW50ZXJuYWw6YW5ub3RhdGlvblwiLFxuXHRcdFx0YW5ub3RhdGlvblxuXHRcdH0pLnRoZW4oYXN5bmMgKHsgYW5ub3RhdGlvbiB9KSA9PiB7XG5cdFx0XHRpZiAoIXJ1bm5lci5vblRlc3RBbm5vdGF0ZSkge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoYFRlc3QgcnVubmVyIGRvZXNuJ3Qgc3VwcG9ydCB0ZXN0IGFubm90YXRpb25zLmApO1xuXHRcdFx0fVxuXHRcdFx0YXdhaXQgZmluaXNoU2VuZFRhc2tzVXBkYXRlKHJ1bm5lcik7XG5cdFx0XHRjb25zdCByZXNvbHZlZEFubm90YXRpb24gPSBhd2FpdCBydW5uZXIub25UZXN0QW5ub3RhdGUodGVzdCwgYW5ub3RhdGlvbik7XG5cdFx0XHR0ZXN0LmFubm90YXRpb25zLnB1c2gocmVzb2x2ZWRBbm5vdGF0aW9uKTtcblx0XHRcdHJldHVybiByZXNvbHZlZEFubm90YXRpb247XG5cdFx0fSkpO1xuXHR9KTtcblx0Y29udGV4dC5vblRlc3RGYWlsZWQgPSAoaGFuZGxlciwgdGltZW91dCkgPT4ge1xuXHRcdHRlc3Qub25GYWlsZWQgfHw9IFtdO1xuXHRcdHRlc3Qub25GYWlsZWQucHVzaCh3aXRoVGltZW91dChoYW5kbGVyLCB0aW1lb3V0ID8/IHJ1bm5lci5jb25maWcuaG9va1RpbWVvdXQsIHRydWUsIG5ldyBFcnJvcihcIlNUQUNLX1RSQUNFX0VSUk9SXCIpLCAoXywgZXJyb3IpID0+IGFib3J0Q29udHJvbGxlci5hYm9ydChlcnJvcikpKTtcblx0fTtcblx0Y29udGV4dC5vblRlc3RGaW5pc2hlZCA9IChoYW5kbGVyLCB0aW1lb3V0KSA9PiB7XG5cdFx0dGVzdC5vbkZpbmlzaGVkIHx8PSBbXTtcblx0XHR0ZXN0Lm9uRmluaXNoZWQucHVzaCh3aXRoVGltZW91dChoYW5kbGVyLCB0aW1lb3V0ID8/IHJ1bm5lci5jb25maWcuaG9va1RpbWVvdXQsIHRydWUsIG5ldyBFcnJvcihcIlNUQUNLX1RSQUNFX0VSUk9SXCIpLCAoXywgZXJyb3IpID0+IGFib3J0Q29udHJvbGxlci5hYm9ydChlcnJvcikpKTtcblx0fTtcblx0cmV0dXJuIHJ1bm5lci5leHRlbmRUYXNrQ29udGV4dD8uKGNvbnRleHQpIHx8IGNvbnRleHQ7XG59XG5mdW5jdGlvbiBtYWtlVGltZW91dEVycm9yKGlzSG9vaywgdGltZW91dCwgc3RhY2tUcmFjZUVycm9yKSB7XG5cdGNvbnN0IG1lc3NhZ2UgPSBgJHtpc0hvb2sgPyBcIkhvb2tcIiA6IFwiVGVzdFwifSB0aW1lZCBvdXQgaW4gJHt0aW1lb3V0fW1zLlxcbklmIHRoaXMgaXMgYSBsb25nLXJ1bm5pbmcgJHtpc0hvb2sgPyBcImhvb2tcIiA6IFwidGVzdFwifSwgcGFzcyBhIHRpbWVvdXQgdmFsdWUgYXMgdGhlIGxhc3QgYXJndW1lbnQgb3IgY29uZmlndXJlIGl0IGdsb2JhbGx5IHdpdGggXCIke2lzSG9vayA/IFwiaG9va1RpbWVvdXRcIiA6IFwidGVzdFRpbWVvdXRcIn1cIi5gO1xuXHRjb25zdCBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcblx0aWYgKHN0YWNrVHJhY2VFcnJvcj8uc3RhY2spIHtcblx0XHRlcnJvci5zdGFjayA9IHN0YWNrVHJhY2VFcnJvci5zdGFjay5yZXBsYWNlKGVycm9yLm1lc3NhZ2UsIHN0YWNrVHJhY2VFcnJvci5tZXNzYWdlKTtcblx0fVxuXHRyZXR1cm4gZXJyb3I7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1blNldHVwRmlsZXMoY29uZmlnLCBmaWxlcywgcnVubmVyKSB7XG5cdGlmIChjb25maWcuc2VxdWVuY2Uuc2V0dXBGaWxlcyA9PT0gXCJwYXJhbGxlbFwiKSB7XG5cdFx0YXdhaXQgUHJvbWlzZS5hbGwoZmlsZXMubWFwKGFzeW5jIChmc1BhdGgpID0+IHtcblx0XHRcdGF3YWl0IHJ1bm5lci5pbXBvcnRGaWxlKGZzUGF0aCwgXCJzZXR1cFwiKTtcblx0XHR9KSk7XG5cdH0gZWxzZSB7XG5cdFx0Zm9yIChjb25zdCBmc1BhdGggb2YgZmlsZXMpIHtcblx0XHRcdGF3YWl0IHJ1bm5lci5pbXBvcnRGaWxlKGZzUGF0aCwgXCJzZXR1cFwiKTtcblx0XHR9XG5cdH1cbn1cblxuY29uc3Qgbm93JDEgPSBnbG9iYWxUaGlzLnBlcmZvcm1hbmNlID8gZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZS5ub3cuYmluZChnbG9iYWxUaGlzLnBlcmZvcm1hbmNlKSA6IERhdGUubm93O1xuYXN5bmMgZnVuY3Rpb24gY29sbGVjdFRlc3RzKHNwZWNzLCBydW5uZXIpIHtcblx0Y29uc3QgZmlsZXMgPSBbXTtcblx0Y29uc3QgY29uZmlnID0gcnVubmVyLmNvbmZpZztcblx0Y29uc3QgJCA9IHJ1bm5lci50cmFjZTtcblx0bGV0IGRlZmF1bHRUYWdzRmlsdGVyO1xuXHRmb3IgKGNvbnN0IHNwZWMgb2Ygc3BlY3MpIHtcblx0XHRjb25zdCBmaWxlcGF0aCA9IHR5cGVvZiBzcGVjID09PSBcInN0cmluZ1wiID8gc3BlYyA6IHNwZWMuZmlsZXBhdGg7XG5cdFx0YXdhaXQgJChcImNvbGxlY3Rfc3BlY1wiLCB7IFwiY29kZS5maWxlLnBhdGhcIjogZmlsZXBhdGggfSwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0cnVubmVyLl9jdXJyZW50U3BlY2lmaWNhdGlvbiA9IHR5cGVvZiBzcGVjID09PSBcInN0cmluZ1wiID8geyBmaWxlcGF0aDogc3BlYyB9IDogc3BlYztcblx0XHRcdGNvbnN0IHRlc3RMb2NhdGlvbnMgPSB0eXBlb2Ygc3BlYyA9PT0gXCJzdHJpbmdcIiA/IHVuZGVmaW5lZCA6IHNwZWMudGVzdExvY2F0aW9ucztcblx0XHRcdGNvbnN0IHRlc3ROYW1lUGF0dGVybiA9IHR5cGVvZiBzcGVjID09PSBcInN0cmluZ1wiID8gdW5kZWZpbmVkIDogc3BlYy50ZXN0TmFtZVBhdHRlcm47XG5cdFx0XHRjb25zdCB0ZXN0SWRzID0gdHlwZW9mIHNwZWMgPT09IFwic3RyaW5nXCIgPyB1bmRlZmluZWQgOiBzcGVjLnRlc3RJZHM7XG5cdFx0XHRjb25zdCB0ZXN0VGFnc0ZpbHRlciA9IHR5cGVvZiBzcGVjID09PSBcIm9iamVjdFwiICYmIHNwZWMudGVzdFRhZ3NGaWx0ZXIgPyBjcmVhdGVUYWdzRmlsdGVyKHNwZWMudGVzdFRhZ3NGaWx0ZXIsIGNvbmZpZy50YWdzKSA6IHVuZGVmaW5lZDtcblx0XHRcdGNvbnN0IGZpbGVUYWdzID0gdHlwZW9mIHNwZWMgPT09IFwic3RyaW5nXCIgPyBbXSA6IHNwZWMuZmlsZVRhZ3MgfHwgW107XG5cdFx0XHRjb25zdCBmaWxlID0gY3JlYXRlRmlsZVRhc2soZmlsZXBhdGgsIGNvbmZpZy5yb290LCBjb25maWcubmFtZSwgcnVubmVyLnBvb2wsIHJ1bm5lci52aXRlRW52aXJvbm1lbnQpO1xuXHRcdFx0ZmlsZS50YWdzID0gZmlsZVRhZ3M7XG5cdFx0XHRmaWxlLnNodWZmbGUgPSBjb25maWcuc2VxdWVuY2Uuc2h1ZmZsZTtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHZhbGlkYXRlVGFncyhydW5uZXIuY29uZmlnLCBmaWxlVGFncyk7XG5cdFx0XHRcdHJ1bm5lci5vbkNvbGxlY3RTdGFydD8uKGZpbGUpO1xuXHRcdFx0XHRjbGVhckNvbGxlY3RvckNvbnRleHQoZmlsZSwgcnVubmVyKTtcblx0XHRcdFx0Y29uc3Qgc2V0dXBGaWxlcyA9IHRvQXJyYXkoY29uZmlnLnNldHVwRmlsZXMpO1xuXHRcdFx0XHRpZiAoc2V0dXBGaWxlcy5sZW5ndGgpIHtcblx0XHRcdFx0XHRjb25zdCBzZXR1cFN0YXJ0ID0gbm93JDEoKTtcblx0XHRcdFx0XHRhd2FpdCBydW5TZXR1cEZpbGVzKGNvbmZpZywgc2V0dXBGaWxlcywgcnVubmVyKTtcblx0XHRcdFx0XHRjb25zdCBzZXR1cEVuZCA9IG5vdyQxKCk7XG5cdFx0XHRcdFx0ZmlsZS5zZXR1cER1cmF0aW9uID0gc2V0dXBFbmQgLSBzZXR1cFN0YXJ0O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGZpbGUuc2V0dXBEdXJhdGlvbiA9IDA7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y29uc3QgY29sbGVjdFN0YXJ0ID0gbm93JDEoKTtcblx0XHRcdFx0YXdhaXQgcnVubmVyLmltcG9ydEZpbGUoZmlsZXBhdGgsIFwiY29sbGVjdFwiKTtcblx0XHRcdFx0Y29uc3QgZHVyYXRpb25zID0gcnVubmVyLmdldEltcG9ydER1cmF0aW9ucz8uKCk7XG5cdFx0XHRcdGlmIChkdXJhdGlvbnMpIHtcblx0XHRcdFx0XHRmaWxlLmltcG9ydER1cmF0aW9ucyA9IGR1cmF0aW9ucztcblx0XHRcdFx0fVxuXHRcdFx0XHRjb25zdCBkZWZhdWx0VGFza3MgPSBhd2FpdCBnZXREZWZhdWx0U3VpdGUoKS5jb2xsZWN0KGZpbGUpO1xuXHRcdFx0XHRjb25zdCBmaWxlSG9va3MgPSBjcmVhdGVTdWl0ZUhvb2tzKCk7XG5cdFx0XHRcdG1lcmdlSG9va3MoZmlsZUhvb2tzLCBnZXRIb29rcyhkZWZhdWx0VGFza3MpKTtcblx0XHRcdFx0Zm9yIChjb25zdCBjIG9mIFsuLi5kZWZhdWx0VGFza3MudGFza3MsIC4uLmNvbGxlY3RvckNvbnRleHQudGFza3NdKSB7XG5cdFx0XHRcdFx0aWYgKGMudHlwZSA9PT0gXCJ0ZXN0XCIgfHwgYy50eXBlID09PSBcInN1aXRlXCIpIHtcblx0XHRcdFx0XHRcdGZpbGUudGFza3MucHVzaChjKTtcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGMudHlwZSA9PT0gXCJjb2xsZWN0b3JcIikge1xuXHRcdFx0XHRcdFx0Y29uc3Qgc3VpdGUgPSBhd2FpdCBjLmNvbGxlY3QoZmlsZSk7XG5cdFx0XHRcdFx0XHRpZiAoc3VpdGUubmFtZSB8fCBzdWl0ZS50YXNrcy5sZW5ndGgpIHtcblx0XHRcdFx0XHRcdFx0bWVyZ2VIb29rcyhmaWxlSG9va3MsIGdldEhvb2tzKHN1aXRlKSk7XG5cdFx0XHRcdFx0XHRcdGZpbGUudGFza3MucHVzaChzdWl0ZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdC8vIGNoZWNrIHRoYXQgdHlwZXMgYXJlIGV4aGF1c3RlZFxuXHRcdFx0XHRcdFx0Yztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0c2V0SG9va3MoZmlsZSwgZmlsZUhvb2tzKTtcblx0XHRcdFx0ZmlsZS5jb2xsZWN0RHVyYXRpb24gPSBub3ckMSgpIC0gY29sbGVjdFN0YXJ0O1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRjb25zdCBlcnJvcnMgPSBlIGluc3RhbmNlb2YgQWdncmVnYXRlRXJyb3IgPyBlLmVycm9ycy5tYXAoKGUpID0+IHByb2Nlc3NFcnJvcihlLCBydW5uZXIuY29uZmlnLmRpZmZPcHRpb25zKSkgOiBbcHJvY2Vzc0Vycm9yKGUsIHJ1bm5lci5jb25maWcuZGlmZk9wdGlvbnMpXTtcblx0XHRcdFx0ZmlsZS5yZXN1bHQgPSB7XG5cdFx0XHRcdFx0c3RhdGU6IFwiZmFpbFwiLFxuXHRcdFx0XHRcdGVycm9yc1xuXHRcdFx0XHR9O1xuXHRcdFx0XHRjb25zdCBkdXJhdGlvbnMgPSBydW5uZXIuZ2V0SW1wb3J0RHVyYXRpb25zPy4oKTtcblx0XHRcdFx0aWYgKGR1cmF0aW9ucykge1xuXHRcdFx0XHRcdGZpbGUuaW1wb3J0RHVyYXRpb25zID0gZHVyYXRpb25zO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRjYWxjdWxhdGVTdWl0ZUhhc2goZmlsZSk7XG5cdFx0XHRjb25zdCBoYXNPbmx5VGFza3MgPSBzb21lVGFza3NBcmVPbmx5KGZpbGUpO1xuXHRcdFx0aWYgKCF0ZXN0VGFnc0ZpbHRlciAmJiAhZGVmYXVsdFRhZ3NGaWx0ZXIgJiYgY29uZmlnLnRhZ3NGaWx0ZXIpIHtcblx0XHRcdFx0ZGVmYXVsdFRhZ3NGaWx0ZXIgPSBjcmVhdGVUYWdzRmlsdGVyKGNvbmZpZy50YWdzRmlsdGVyLCBjb25maWcudGFncyk7XG5cdFx0XHR9XG5cdFx0XHRpbnRlcnByZXRUYXNrTW9kZXMoZmlsZSwgdGVzdE5hbWVQYXR0ZXJuID8/IGNvbmZpZy50ZXN0TmFtZVBhdHRlcm4sIHRlc3RMb2NhdGlvbnMsIHRlc3RJZHMsIHRlc3RUYWdzRmlsdGVyID8/IGRlZmF1bHRUYWdzRmlsdGVyLCBoYXNPbmx5VGFza3MsIGZhbHNlLCBjb25maWcuYWxsb3dPbmx5KTtcblx0XHRcdGlmIChmaWxlLm1vZGUgPT09IFwicXVldWVkXCIpIHtcblx0XHRcdFx0ZmlsZS5tb2RlID0gXCJydW5cIjtcblx0XHRcdH1cblx0XHRcdGZpbGVzLnB1c2goZmlsZSk7XG5cdFx0fSk7XG5cdH1cblx0cmV0dXJuIGZpbGVzO1xufVxuZnVuY3Rpb24gbWVyZ2VIb29rcyhiYXNlSG9va3MsIGhvb2tzKSB7XG5cdGZvciAoY29uc3QgX2tleSBpbiBob29rcykge1xuXHRcdGNvbnN0IGtleSA9IF9rZXk7XG5cdFx0YmFzZUhvb2tzW2tleV0ucHVzaCguLi5ob29rc1trZXldKTtcblx0fVxuXHRyZXR1cm4gYmFzZUhvb2tzO1xufVxuXG5jb25zdCBub3cgPSBnbG9iYWxUaGlzLnBlcmZvcm1hbmNlID8gZ2xvYmFsVGhpcy5wZXJmb3JtYW5jZS5ub3cuYmluZChnbG9iYWxUaGlzLnBlcmZvcm1hbmNlKSA6IERhdGUubm93O1xuY29uc3QgdW5peE5vdyA9IERhdGUubm93O1xuY29uc3QgeyBjbGVhclRpbWVvdXQsIHNldFRpbWVvdXQgfSA9IGdldFNhZmVUaW1lcnMoKTtcbmxldCBsaW1pdE1heENvbmN1cnJlbmN5O1xuLyoqXG4qIE5vcm1hbGl6ZXMgcmV0cnkgY29uZmlndXJhdGlvbiB0byBleHRyYWN0IGluZGl2aWR1YWwgdmFsdWVzLlxuKiBIYW5kbGVzIGJvdGggbnVtYmVyIGFuZCBvYmplY3QgZm9ybXMuXG4qL1xuZnVuY3Rpb24gZ2V0UmV0cnlDb3VudChyZXRyeSkge1xuXHRpZiAocmV0cnkgPT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiAwO1xuXHR9XG5cdGlmICh0eXBlb2YgcmV0cnkgPT09IFwibnVtYmVyXCIpIHtcblx0XHRyZXR1cm4gcmV0cnk7XG5cdH1cblx0cmV0dXJuIHJldHJ5LmNvdW50ID8/IDA7XG59XG5mdW5jdGlvbiBnZXRSZXRyeURlbGF5KHJldHJ5KSB7XG5cdGlmIChyZXRyeSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIDA7XG5cdH1cblx0aWYgKHR5cGVvZiByZXRyeSA9PT0gXCJudW1iZXJcIikge1xuXHRcdHJldHVybiAwO1xuXHR9XG5cdHJldHVybiByZXRyeS5kZWxheSA/PyAwO1xufVxuZnVuY3Rpb24gZ2V0UmV0cnlDb25kaXRpb24ocmV0cnkpIHtcblx0aWYgKHJldHJ5ID09PSB1bmRlZmluZWQpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cdGlmICh0eXBlb2YgcmV0cnkgPT09IFwibnVtYmVyXCIpIHtcblx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHR9XG5cdHJldHVybiByZXRyeS5jb25kaXRpb247XG59XG5mdW5jdGlvbiB1cGRhdGVTdWl0ZUhvb2tTdGF0ZSh0YXNrLCBuYW1lLCBzdGF0ZSwgcnVubmVyKSB7XG5cdGlmICghdGFzay5yZXN1bHQpIHtcblx0XHR0YXNrLnJlc3VsdCA9IHsgc3RhdGU6IFwicnVuXCIgfTtcblx0fVxuXHRpZiAoIXRhc2sucmVzdWx0Lmhvb2tzKSB7XG5cdFx0dGFzay5yZXN1bHQuaG9va3MgPSB7fTtcblx0fVxuXHRjb25zdCBzdWl0ZUhvb2tzID0gdGFzay5yZXN1bHQuaG9va3M7XG5cdGlmIChzdWl0ZUhvb2tzKSB7XG5cdFx0c3VpdGVIb29rc1tuYW1lXSA9IHN0YXRlO1xuXHRcdGxldCBldmVudCA9IHN0YXRlID09PSBcInJ1blwiID8gXCJiZWZvcmUtaG9vay1zdGFydFwiIDogXCJiZWZvcmUtaG9vay1lbmRcIjtcblx0XHRpZiAobmFtZSA9PT0gXCJhZnRlckFsbFwiIHx8IG5hbWUgPT09IFwiYWZ0ZXJFYWNoXCIpIHtcblx0XHRcdGV2ZW50ID0gc3RhdGUgPT09IFwicnVuXCIgPyBcImFmdGVyLWhvb2stc3RhcnRcIiA6IFwiYWZ0ZXItaG9vay1lbmRcIjtcblx0XHR9XG5cdFx0dXBkYXRlVGFzayhldmVudCwgdGFzaywgcnVubmVyKTtcblx0fVxufVxuZnVuY3Rpb24gZ2V0U3VpdGVIb29rcyhzdWl0ZSwgbmFtZSwgc2VxdWVuY2UpIHtcblx0Y29uc3QgaG9va3MgPSBnZXRIb29rcyhzdWl0ZSlbbmFtZV07XG5cdGlmIChzZXF1ZW5jZSA9PT0gXCJzdGFja1wiICYmIChuYW1lID09PSBcImFmdGVyQWxsXCIgfHwgbmFtZSA9PT0gXCJhZnRlckVhY2hcIikpIHtcblx0XHRyZXR1cm4gaG9va3Muc2xpY2UoKS5yZXZlcnNlKCk7XG5cdH1cblx0cmV0dXJuIGhvb2tzO1xufVxuYXN5bmMgZnVuY3Rpb24gY2FsbFRlc3RIb29rcyhydW5uZXIsIHRlc3QsIGhvb2tzLCBzZXF1ZW5jZSkge1xuXHRpZiAoc2VxdWVuY2UgPT09IFwic3RhY2tcIikge1xuXHRcdGhvb2tzID0gaG9va3Muc2xpY2UoKS5yZXZlcnNlKCk7XG5cdH1cblx0aWYgKCFob29rcy5sZW5ndGgpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0Y29uc3QgY29udGV4dCA9IHRlc3QuY29udGV4dDtcblx0Y29uc3Qgb25UZXN0RmFpbGVkID0gdGVzdC5jb250ZXh0Lm9uVGVzdEZhaWxlZDtcblx0Y29uc3Qgb25UZXN0RmluaXNoZWQgPSB0ZXN0LmNvbnRleHQub25UZXN0RmluaXNoZWQ7XG5cdGNvbnRleHQub25UZXN0RmFpbGVkID0gKCkgPT4ge1xuXHRcdHRocm93IG5ldyBFcnJvcihgQ2Fubm90IGNhbGwgXCJvblRlc3RGYWlsZWRcIiBpbnNpZGUgYSB0ZXN0IGhvb2suYCk7XG5cdH07XG5cdGNvbnRleHQub25UZXN0RmluaXNoZWQgPSAoKSA9PiB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgY2FsbCBcIm9uVGVzdEZpbmlzaGVkXCIgaW5zaWRlIGEgdGVzdCBob29rLmApO1xuXHR9O1xuXHRpZiAoc2VxdWVuY2UgPT09IFwicGFyYWxsZWxcIikge1xuXHRcdHRyeSB7XG5cdFx0XHRhd2FpdCBQcm9taXNlLmFsbChob29rcy5tYXAoKGZuKSA9PiBsaW1pdE1heENvbmN1cnJlbmN5KCgpID0+IGZuKHRlc3QuY29udGV4dCkpKSk7XG5cdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0ZmFpbFRhc2sodGVzdC5yZXN1bHQsIGUsIHJ1bm5lci5jb25maWcuZGlmZk9wdGlvbnMpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRmb3IgKGNvbnN0IGZuIG9mIGhvb2tzKSB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRhd2FpdCBsaW1pdE1heENvbmN1cnJlbmN5KCgpID0+IGZuKHRlc3QuY29udGV4dCkpO1xuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRmYWlsVGFzayh0ZXN0LnJlc3VsdCwgZSwgcnVubmVyLmNvbmZpZy5kaWZmT3B0aW9ucyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGNvbnRleHQub25UZXN0RmFpbGVkID0gb25UZXN0RmFpbGVkO1xuXHRjb250ZXh0Lm9uVGVzdEZpbmlzaGVkID0gb25UZXN0RmluaXNoZWQ7XG59XG5hc3luYyBmdW5jdGlvbiBjYWxsU3VpdGVIb29rKHN1aXRlLCBjdXJyZW50VGFzaywgbmFtZSwgcnVubmVyLCBhcmdzKSB7XG5cdGNvbnN0IHNlcXVlbmNlID0gcnVubmVyLmNvbmZpZy5zZXF1ZW5jZS5ob29rcztcblx0Y29uc3QgY2FsbGJhY2tzID0gW107XG5cdC8vIHN0b3AgYXQgZmlsZSBsZXZlbFxuXHRjb25zdCBwYXJlbnRTdWl0ZSA9IFwiZmlsZXBhdGhcIiBpbiBzdWl0ZSA/IG51bGwgOiBzdWl0ZS5zdWl0ZSB8fCBzdWl0ZS5maWxlO1xuXHRpZiAobmFtZSA9PT0gXCJiZWZvcmVFYWNoXCIgJiYgcGFyZW50U3VpdGUpIHtcblx0XHRjYWxsYmFja3MucHVzaCguLi5hd2FpdCBjYWxsU3VpdGVIb29rKHBhcmVudFN1aXRlLCBjdXJyZW50VGFzaywgbmFtZSwgcnVubmVyLCBhcmdzKSk7XG5cdH1cblx0Y29uc3QgaG9va3MgPSBnZXRTdWl0ZUhvb2tzKHN1aXRlLCBuYW1lLCBzZXF1ZW5jZSk7XG5cdGlmIChob29rcy5sZW5ndGggPiAwKSB7XG5cdFx0dXBkYXRlU3VpdGVIb29rU3RhdGUoY3VycmVudFRhc2ssIG5hbWUsIFwicnVuXCIsIHJ1bm5lcik7XG5cdH1cblx0YXN5bmMgZnVuY3Rpb24gcnVuSG9vayhob29rKSB7XG5cdFx0cmV0dXJuIGxpbWl0TWF4Q29uY3VycmVuY3koYXN5bmMgKCkgPT4ge1xuXHRcdFx0cmV0dXJuIGdldEJlZm9yZUhvb2tDbGVhbnVwQ2FsbGJhY2soaG9vaywgYXdhaXQgaG9vayguLi5hcmdzKSwgbmFtZSA9PT0gXCJiZWZvcmVFYWNoXCIgPyBhcmdzWzBdIDogdW5kZWZpbmVkKTtcblx0XHR9KTtcblx0fVxuXHRpZiAoc2VxdWVuY2UgPT09IFwicGFyYWxsZWxcIikge1xuXHRcdGNhbGxiYWNrcy5wdXNoKC4uLmF3YWl0IFByb21pc2UuYWxsKGhvb2tzLm1hcCgoaG9vaykgPT4gcnVuSG9vayhob29rKSkpKTtcblx0fSBlbHNlIHtcblx0XHRmb3IgKGNvbnN0IGhvb2sgb2YgaG9va3MpIHtcblx0XHRcdGNhbGxiYWNrcy5wdXNoKGF3YWl0IHJ1bkhvb2soaG9vaykpO1xuXHRcdH1cblx0fVxuXHRpZiAoaG9va3MubGVuZ3RoID4gMCkge1xuXHRcdHVwZGF0ZVN1aXRlSG9va1N0YXRlKGN1cnJlbnRUYXNrLCBuYW1lLCBcInBhc3NcIiwgcnVubmVyKTtcblx0fVxuXHRpZiAobmFtZSA9PT0gXCJhZnRlckVhY2hcIiAmJiBwYXJlbnRTdWl0ZSkge1xuXHRcdGNhbGxiYWNrcy5wdXNoKC4uLmF3YWl0IGNhbGxTdWl0ZUhvb2socGFyZW50U3VpdGUsIGN1cnJlbnRUYXNrLCBuYW1lLCBydW5uZXIsIGFyZ3MpKTtcblx0fVxuXHRyZXR1cm4gY2FsbGJhY2tzO1xufVxuZnVuY3Rpb24gZ2V0QXJvdW5kRWFjaEhvb2tzKHN1aXRlKSB7XG5cdGNvbnN0IGhvb2tzID0gW107XG5cdGNvbnN0IHBhcmVudFN1aXRlID0gXCJmaWxlcGF0aFwiIGluIHN1aXRlID8gbnVsbCA6IHN1aXRlLnN1aXRlIHx8IHN1aXRlLmZpbGU7XG5cdGlmIChwYXJlbnRTdWl0ZSkge1xuXHRcdGhvb2tzLnB1c2goLi4uZ2V0QXJvdW5kRWFjaEhvb2tzKHBhcmVudFN1aXRlKSk7XG5cdH1cblx0aG9va3MucHVzaCguLi5nZXRIb29rcyhzdWl0ZSkuYXJvdW5kRWFjaCk7XG5cdHJldHVybiBob29rcztcbn1cbmZ1bmN0aW9uIGdldEFyb3VuZEFsbEhvb2tzKHN1aXRlKSB7XG5cdHJldHVybiBnZXRIb29rcyhzdWl0ZSkuYXJvdW5kQWxsO1xufVxuZnVuY3Rpb24gbWFrZUFyb3VuZEhvb2tUaW1lb3V0RXJyb3IoaG9va05hbWUsIHBoYXNlLCB0aW1lb3V0LCBzdGFja1RyYWNlRXJyb3IpIHtcblx0Y29uc3QgbWVzc2FnZSA9IGBUaGUgJHtwaGFzZX0gcGhhc2Ugb2YgXCIke2hvb2tOYW1lfVwiIGhvb2sgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dH1tcy5gO1xuXHRjb25zdCBFcnJvckNsYXNzID0gcGhhc2UgPT09IFwic2V0dXBcIiA/IEFyb3VuZEhvb2tTZXR1cEVycm9yIDogQXJvdW5kSG9va1RlYXJkb3duRXJyb3I7XG5cdGNvbnN0IGVycm9yID0gbmV3IEVycm9yQ2xhc3MobWVzc2FnZSk7XG5cdGlmIChzdGFja1RyYWNlRXJyb3I/LnN0YWNrKSB7XG5cdFx0ZXJyb3Iuc3RhY2sgPSBzdGFja1RyYWNlRXJyb3Iuc3RhY2sucmVwbGFjZShzdGFja1RyYWNlRXJyb3IubWVzc2FnZSwgZXJyb3IubWVzc2FnZSk7XG5cdH1cblx0cmV0dXJuIGVycm9yO1xufVxuYXN5bmMgZnVuY3Rpb24gY2FsbEFyb3VuZEhvb2tzKHJ1bklubmVyLCBvcHRpb25zKSB7XG5cdGNvbnN0IHsgaG9va3MsIGhvb2tOYW1lLCBjYWxsYmFja05hbWUsIG9uVGltZW91dCwgaW52b2tlSG9vayB9ID0gb3B0aW9ucztcblx0aWYgKCFob29rcy5sZW5ndGgpIHtcblx0XHRhd2FpdCBydW5Jbm5lcigpO1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBob29rRXJyb3JzID0gW107XG5cdGNvbnN0IGNyZWF0ZVRpbWVvdXRQcm9taXNlID0gKHRpbWVvdXQsIHBoYXNlLCBzdGFja1RyYWNlRXJyb3IpID0+IHtcblx0XHRsZXQgdGltZXI7XG5cdFx0bGV0IHRpbWVkb3V0ID0gZmFsc2U7XG5cdFx0Y29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlKChfLCByZWplY3QpID0+IHtcblx0XHRcdGlmICh0aW1lb3V0ID4gMCAmJiB0aW1lb3V0ICE9PSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkpIHtcblx0XHRcdFx0dGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcblx0XHRcdFx0XHR0aW1lZG91dCA9IHRydWU7XG5cdFx0XHRcdFx0Y29uc3QgZXJyb3IgPSBtYWtlQXJvdW5kSG9va1RpbWVvdXRFcnJvcihob29rTmFtZSwgcGhhc2UsIHRpbWVvdXQsIHN0YWNrVHJhY2VFcnJvcik7XG5cdFx0XHRcdFx0b25UaW1lb3V0Py4oZXJyb3IpO1xuXHRcdFx0XHRcdHJlamVjdChlcnJvcik7XG5cdFx0XHRcdH0sIHRpbWVvdXQpO1xuXHRcdFx0XHR0aW1lci51bnJlZj8uKCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0Y29uc3QgY2xlYXIgPSAoKSA9PiB7XG5cdFx0XHRpZiAodGltZXIpIHtcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRpbWVyKTtcblx0XHRcdFx0dGltZXIgPSB1bmRlZmluZWQ7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRyZXR1cm4ge1xuXHRcdFx0cHJvbWlzZSxcblx0XHRcdGNsZWFyLFxuXHRcdFx0aXNUaW1lZE91dDogKCkgPT4gdGltZWRvdXRcblx0XHR9O1xuXHR9O1xuXHRjb25zdCBydW5OZXh0SG9vayA9IGFzeW5jIChpbmRleCkgPT4ge1xuXHRcdGlmIChpbmRleCA+PSBob29rcy5sZW5ndGgpIHtcblx0XHRcdHJldHVybiBydW5Jbm5lcigpO1xuXHRcdH1cblx0XHRjb25zdCBob29rID0gaG9va3NbaW5kZXhdO1xuXHRcdGNvbnN0IHRpbWVvdXQgPSBnZXRBcm91bmRIb29rVGltZW91dChob29rKTtcblx0XHRjb25zdCBzdGFja1RyYWNlRXJyb3IgPSBnZXRBcm91bmRIb29rU3RhY2tUcmFjZShob29rKTtcblx0XHRsZXQgdXNlQ2FsbGVkID0gZmFsc2U7XG5cdFx0bGV0IHNldHVwVGltZW91dDtcblx0XHRsZXQgdGVhcmRvd25UaW1lb3V0O1xuXHRcdGxldCBzZXR1cExpbWl0Q29uY3VycmVuY3lSZWxlYXNlO1xuXHRcdGxldCB0ZWFyZG93bkxpbWl0Q29uY3VycmVuY3lSZWxlYXNlO1xuXHRcdC8vIFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHVzZSgpIGlzIGNhbGxlZCAoc2V0dXAgcGhhc2UgY29tcGxldGUpXG5cdFx0bGV0IHJlc29sdmVVc2VDYWxsZWQ7XG5cdFx0Y29uc3QgdXNlQ2FsbGVkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG5cdFx0XHRyZXNvbHZlVXNlQ2FsbGVkID0gcmVzb2x2ZTtcblx0XHR9KTtcblx0XHQvLyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB1c2UoKSByZXR1cm5zIChpbm5lciBob29rcyBjb21wbGV0ZSwgdGVhcmRvd24gcGhhc2Ugc3RhcnRzKVxuXHRcdGxldCByZXNvbHZlVXNlUmV0dXJuZWQ7XG5cdFx0Y29uc3QgdXNlUmV0dXJuZWRQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcblx0XHRcdHJlc29sdmVVc2VSZXR1cm5lZCA9IHJlc29sdmU7XG5cdFx0fSk7XG5cdFx0Ly8gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gaG9vayBjb21wbGV0ZXNcblx0XHRsZXQgcmVzb2x2ZUhvb2tDb21wbGV0ZTtcblx0XHRsZXQgcmVqZWN0SG9va0NvbXBsZXRlO1xuXHRcdGNvbnN0IGhvb2tDb21wbGV0ZVByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG5cdFx0XHRyZXNvbHZlSG9va0NvbXBsZXRlID0gcmVzb2x2ZTtcblx0XHRcdHJlamVjdEhvb2tDb21wbGV0ZSA9IHJlamVjdDtcblx0XHR9KTtcblx0XHRjb25zdCB1c2UgPSBhc3luYyAoKSA9PiB7XG5cdFx0XHQvLyBzaG91bGRuJ3QgY29udGludWUgdG8gbmV4dCAocnVuVGVzdC9TdWl0ZSBvciBpbm5lciBhcm91bmRFYWNoL0FsbCkgd2hlbiBhcm91bmRFYWNoL0FsbCBzZXR1cCB0aW1lZCBvdXQuXG5cdFx0XHRpZiAoc2V0dXBUaW1lb3V0LmlzVGltZWRPdXQoKSkge1xuXHRcdFx0XHQvLyB3ZSBjYW4gdGhyb3cgYW55IGVycm9yIHRvIGJhaWwgb3V0LlxuXHRcdFx0XHQvLyB0aGlzIGVycm9yIGlzIG5vdCBzZWVuIGJ5IGVuZCB1c2VycyBzaW5jZSBgcnVuTmV4dEhvb2tgIGFscmVhZHkgcmVqZWN0ZWQgd2l0aCB0aW1lb3V0IGVycm9yXG5cdFx0XHRcdC8vIGFuZCB0aGlzIGVycm9yIGlzIGNhdWdodCBieSBgcmVqZWN0SG9va0NvbXBsZXRlYC5cblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiX19WSVRFU1RfSU5URVJOQUxfQVJPVU5EX0hPT0tfQUJPUlRfX1wiKTtcblx0XHRcdH1cblx0XHRcdGlmICh1c2VDYWxsZWQpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEFyb3VuZEhvb2tNdWx0aXBsZUNhbGxzRXJyb3IoYFRoZSBcXGAke2NhbGxiYWNrTmFtZX1cXGAgY2FsbGJhY2sgd2FzIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBpbiB0aGUgXFxgJHtob29rTmFtZX1cXGAgaG9vay4gYCArIGBUaGUgY2FsbGJhY2sgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UgcGVyIGhvb2suYCk7XG5cdFx0XHR9XG5cdFx0XHR1c2VDYWxsZWQgPSB0cnVlO1xuXHRcdFx0cmVzb2x2ZVVzZUNhbGxlZCgpO1xuXHRcdFx0Ly8gU2V0dXAgcGhhc2UgY29tcGxldGVkIC0gY2xlYXIgc2V0dXAgdGltZXJcblx0XHRcdHNldHVwVGltZW91dC5jbGVhcigpO1xuXHRcdFx0c2V0dXBMaW1pdENvbmN1cnJlbmN5UmVsZWFzZT8uKCk7XG5cdFx0XHQvLyBSdW4gaW5uZXIgaG9va3MgLSBkb24ndCB0aW1lIHRoaXMgYWdhaW5zdCBvdXIgdGVhcmRvd24gdGltZW91dFxuXHRcdFx0YXdhaXQgcnVuTmV4dEhvb2soaW5kZXggKyAxKS5jYXRjaCgoZSkgPT4gaG9va0Vycm9ycy5wdXNoKGUpKTtcblx0XHRcdHRlYXJkb3duTGltaXRDb25jdXJyZW5jeVJlbGVhc2UgPSBhd2FpdCBsaW1pdE1heENvbmN1cnJlbmN5LmFjcXVpcmUoKTtcblx0XHRcdC8vIFN0YXJ0IHRlYXJkb3duIHRpbWVyIGFmdGVyIGlubmVyIGhvb2tzIGNvbXBsZXRlIC0gb25seSB0aW1lcyB0aGlzIGhvb2sncyB0ZWFyZG93biBjb2RlXG5cdFx0XHR0ZWFyZG93blRpbWVvdXQgPSBjcmVhdGVUaW1lb3V0UHJvbWlzZSh0aW1lb3V0LCBcInRlYXJkb3duXCIsIHN0YWNrVHJhY2VFcnJvcik7XG5cdFx0XHQvLyBTaWduYWwgdGhhdCB1c2UoKSBpcyByZXR1cm5pbmcgKHRlYXJkb3duIHBoYXNlIHN0YXJ0aW5nKVxuXHRcdFx0cmVzb2x2ZVVzZVJldHVybmVkKCk7XG5cdFx0fTtcblx0XHRzZXR1cExpbWl0Q29uY3VycmVuY3lSZWxlYXNlID0gYXdhaXQgbGltaXRNYXhDb25jdXJyZW5jeS5hY3F1aXJlKCk7XG5cdFx0Ly8gU3RhcnQgc2V0dXAgdGltZW91dFxuXHRcdHNldHVwVGltZW91dCA9IGNyZWF0ZVRpbWVvdXRQcm9taXNlKHRpbWVvdXQsIFwic2V0dXBcIiwgc3RhY2tUcmFjZUVycm9yKTtcblx0XHQoYXN5bmMgKCkgPT4ge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0YXdhaXQgaW52b2tlSG9vayhob29rLCB1c2UpO1xuXHRcdFx0XHRpZiAoIXVzZUNhbGxlZCkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBBcm91bmRIb29rU2V0dXBFcnJvcihgVGhlIFxcYCR7Y2FsbGJhY2tOYW1lfVxcYCBjYWxsYmFjayB3YXMgbm90IGNhbGxlZCBpbiB0aGUgXFxgJHtob29rTmFtZX1cXGAgaG9vay4gYCArIGBNYWtlIHN1cmUgdG8gY2FsbCBcXGAke2NhbGxiYWNrTmFtZX1cXGAgdG8gcnVuIHRoZSAke2hvb2tOYW1lID09PSBcImFyb3VuZEVhY2hcIiA/IFwidGVzdFwiIDogXCJzdWl0ZVwifS5gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXNvbHZlSG9va0NvbXBsZXRlKCk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRyZWplY3RIb29rQ29tcGxldGUoZXJyb3IpO1xuXHRcdFx0fSBmaW5hbGx5IHtcblx0XHRcdFx0c2V0dXBMaW1pdENvbmN1cnJlbmN5UmVsZWFzZT8uKCk7XG5cdFx0XHRcdHRlYXJkb3duTGltaXRDb25jdXJyZW5jeVJlbGVhc2U/LigpO1xuXHRcdFx0fVxuXHRcdH0pKCk7XG5cdFx0Ly8gV2FpdCBmb3IgZWl0aGVyOiB1c2UoKSB0byBiZSBjYWxsZWQgT1IgaG9vayB0byBjb21wbGV0ZSAoZXJyb3IpIE9SIHNldHVwIHRpbWVvdXRcblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgUHJvbWlzZS5yYWNlKFtcblx0XHRcdFx0dXNlQ2FsbGVkUHJvbWlzZSxcblx0XHRcdFx0aG9va0NvbXBsZXRlUHJvbWlzZSxcblx0XHRcdFx0c2V0dXBUaW1lb3V0LnByb21pc2Vcblx0XHRcdF0pO1xuXHRcdH0gZmluYWxseSB7XG5cdFx0XHRzZXR1cExpbWl0Q29uY3VycmVuY3lSZWxlYXNlPy4oKTtcblx0XHRcdHNldHVwVGltZW91dC5jbGVhcigpO1xuXHRcdH1cblx0XHQvLyBXYWl0IGZvciB1c2UoKSB0byByZXR1cm4gKGlubmVyIGhvb2tzIGNvbXBsZXRlKSBPUiBob29rIHRvIGNvbXBsZXRlIChlcnJvciBkdXJpbmcgaW5uZXIgaG9va3MpXG5cdFx0YXdhaXQgUHJvbWlzZS5yYWNlKFt1c2VSZXR1cm5lZFByb21pc2UsIGhvb2tDb21wbGV0ZVByb21pc2VdKTtcblx0XHQvLyBOb3cgdGVhcmRvd25UaW1lb3V0IGlzIGd1YXJhbnRlZWQgdG8gYmUgc2V0XG5cdFx0Ly8gV2FpdCBmb3IgaG9vayB0byBjb21wbGV0ZSAodGVhcmRvd24pIE9SIHRlYXJkb3duIHRpbWVvdXRcblx0XHR0cnkge1xuXHRcdFx0YXdhaXQgUHJvbWlzZS5yYWNlKFtob29rQ29tcGxldGVQcm9taXNlLCB0ZWFyZG93blRpbWVvdXQ/LnByb21pc2VdKTtcblx0XHR9IGZpbmFsbHkge1xuXHRcdFx0dGVhcmRvd25MaW1pdENvbmN1cnJlbmN5UmVsZWFzZT8uKCk7XG5cdFx0XHR0ZWFyZG93blRpbWVvdXQ/LmNsZWFyKCk7XG5cdFx0fVxuXHR9O1xuXHRhd2FpdCBydW5OZXh0SG9vaygwKS5jYXRjaCgoZSkgPT4gaG9va0Vycm9ycy5wdXNoKGUpKTtcblx0aWYgKGhvb2tFcnJvcnMubGVuZ3RoID4gMCkge1xuXHRcdHRocm93IGhvb2tFcnJvcnM7XG5cdH1cbn1cbmFzeW5jIGZ1bmN0aW9uIGNhbGxBcm91bmRBbGxIb29rcyhzdWl0ZSwgcnVuU3VpdGVJbm5lcikge1xuXHRhd2FpdCBjYWxsQXJvdW5kSG9va3MocnVuU3VpdGVJbm5lciwge1xuXHRcdGhvb2tzOiBnZXRBcm91bmRBbGxIb29rcyhzdWl0ZSksXG5cdFx0aG9va05hbWU6IFwiYXJvdW5kQWxsXCIsXG5cdFx0Y2FsbGJhY2tOYW1lOiBcInJ1blN1aXRlKClcIixcblx0XHRpbnZva2VIb29rOiAoaG9vaywgdXNlKSA9PiBob29rKHVzZSwgc3VpdGUpXG5cdH0pO1xufVxuYXN5bmMgZnVuY3Rpb24gY2FsbEFyb3VuZEVhY2hIb29rcyhzdWl0ZSwgdGVzdCwgcnVuVGVzdCkge1xuXHRhd2FpdCBjYWxsQXJvdW5kSG9va3MoXG5cdFx0Ly8gVGFrZSBjaGVja3BvaW50IHJpZ2h0IGJlZm9yZSBydW5UZXN0IC0gYXQgdGhpcyBwb2ludCBhbGwgYXJvdW5kRWFjaCBmaXh0dXJlc1xuXHRcdC8vIGhhdmUgYmVlbiByZXNvbHZlZCwgc28gd2UgY2FuIGNvcnJlY3RseSBpZGVudGlmeSB3aGljaCBmaXh0dXJlcyBiZWxvbmcgdG9cblx0XHQvLyBhcm91bmRFYWNoIChiZWZvcmUgY2hlY2twb2ludCkgdnMgaW5zaWRlIHJ1blRlc3QgKGFmdGVyIGNoZWNrcG9pbnQpXG5cdFx0KCkgPT4gcnVuVGVzdChnZXRGaXh0dXJlQ2xlYW51cENvdW50KHRlc3QuY29udGV4dCkpLFxuXHRcdHtcblx0XHRcdGhvb2tzOiBnZXRBcm91bmRFYWNoSG9va3Moc3VpdGUpLFxuXHRcdFx0aG9va05hbWU6IFwiYXJvdW5kRWFjaFwiLFxuXHRcdFx0Y2FsbGJhY2tOYW1lOiBcInJ1blRlc3QoKVwiLFxuXHRcdFx0b25UaW1lb3V0OiAoZXJyb3IpID0+IGFib3J0Q29udGV4dFNpZ25hbCh0ZXN0LmNvbnRleHQsIGVycm9yKSxcblx0XHRcdGludm9rZUhvb2s6IChob29rLCB1c2UpID0+IGhvb2sodXNlLCB0ZXN0LmNvbnRleHQsIHN1aXRlKVxuXHRcdH1cblx0KTtcbn1cbmNvbnN0IHBhY2tzID0gbmV3IE1hcCgpO1xuY29uc3QgZXZlbnRzUGFja3MgPSBbXTtcbmNvbnN0IHBlbmRpbmdUYXNrc1VwZGF0ZXMgPSBbXTtcbmZ1bmN0aW9uIHNlbmRUYXNrc1VwZGF0ZShydW5uZXIpIHtcblx0aWYgKHBhY2tzLnNpemUpIHtcblx0XHRjb25zdCB0YXNrUGFja3MgPSBBcnJheS5mcm9tKHBhY2tzKS5tYXAoKFtpZCwgdGFza10pID0+IHtcblx0XHRcdHJldHVybiBbXG5cdFx0XHRcdGlkLFxuXHRcdFx0XHR0YXNrWzBdLFxuXHRcdFx0XHR0YXNrWzFdXG5cdFx0XHRdO1xuXHRcdH0pO1xuXHRcdGNvbnN0IHAgPSBydW5uZXIub25UYXNrVXBkYXRlPy4odGFza1BhY2tzLCBldmVudHNQYWNrcyk7XG5cdFx0aWYgKHApIHtcblx0XHRcdHBlbmRpbmdUYXNrc1VwZGF0ZXMucHVzaChwKTtcblx0XHRcdC8vIHJlbW92ZSBzdWNjZXNzZnVsIHByb21pc2UgdG8gbm90IGdyb3cgYXJyYXkgaW5kZWZpbml0ZWx5LFxuXHRcdFx0Ly8gYnV0IGtlZXAgcmVqZWN0aW9ucyBzbyBmaW5pc2hTZW5kVGFza3NVcGRhdGUgY2FuIGhhbmRsZSB0aGVtXG5cdFx0XHRwLnRoZW4oKCkgPT4gcGVuZGluZ1Rhc2tzVXBkYXRlcy5zcGxpY2UocGVuZGluZ1Rhc2tzVXBkYXRlcy5pbmRleE9mKHApLCAxKSwgKCkgPT4ge30pO1xuXHRcdH1cblx0XHRldmVudHNQYWNrcy5sZW5ndGggPSAwO1xuXHRcdHBhY2tzLmNsZWFyKCk7XG5cdH1cbn1cbmFzeW5jIGZ1bmN0aW9uIGZpbmlzaFNlbmRUYXNrc1VwZGF0ZShydW5uZXIpIHtcblx0c2VuZFRhc2tzVXBkYXRlKHJ1bm5lcik7XG5cdGF3YWl0IFByb21pc2UuYWxsKHBlbmRpbmdUYXNrc1VwZGF0ZXMpO1xufVxuZnVuY3Rpb24gdGhyb3R0bGUoZm4sIG1zKSB7XG5cdGxldCBsYXN0ID0gMDtcblx0bGV0IHBlbmRpbmdDYWxsO1xuXHRyZXR1cm4gZnVuY3Rpb24gY2FsbCguLi5hcmdzKSB7XG5cdFx0Y29uc3Qgbm93ID0gdW5peE5vdygpO1xuXHRcdGlmIChub3cgLSBsYXN0ID4gbXMpIHtcblx0XHRcdGxhc3QgPSBub3c7XG5cdFx0XHRjbGVhclRpbWVvdXQocGVuZGluZ0NhbGwpO1xuXHRcdFx0cGVuZGluZ0NhbGwgPSB1bmRlZmluZWQ7XG5cdFx0XHRyZXR1cm4gZm4uYXBwbHkodGhpcywgYXJncyk7XG5cdFx0fVxuXHRcdC8vIE1ha2Ugc3VyZSBmbiBpcyBzdGlsbCBjYWxsZWQgZXZlbiBpZiB0aGVyZSBhcmUgbm8gZnVydGhlciBjYWxsc1xuXHRcdHBlbmRpbmdDYWxsID8/PSBzZXRUaW1lb3V0KCgpID0+IGNhbGwuYmluZCh0aGlzKSguLi5hcmdzKSwgbXMpO1xuXHR9O1xufVxuLy8gdGhyb3R0bGUgYmFzZWQgb24gc3VtbWFyeSByZXBvcnRlcidzIERVUkFUSU9OX1VQREFURV9JTlRFUlZBTF9NU1xuY29uc3Qgc2VuZFRhc2tzVXBkYXRlVGhyb3R0bGVkID0gdGhyb3R0bGUoc2VuZFRhc2tzVXBkYXRlLCAxMDApO1xuZnVuY3Rpb24gdXBkYXRlVGFzayhldmVudCwgdGFzaywgcnVubmVyKSB7XG5cdGV2ZW50c1BhY2tzLnB1c2goW1xuXHRcdHRhc2suaWQsXG5cdFx0ZXZlbnQsXG5cdFx0dW5kZWZpbmVkXG5cdF0pO1xuXHRwYWNrcy5zZXQodGFzay5pZCwgW3Rhc2sucmVzdWx0LCB0YXNrLm1ldGFdKTtcblx0c2VuZFRhc2tzVXBkYXRlVGhyb3R0bGVkKHJ1bm5lcik7XG59XG5hc3luYyBmdW5jdGlvbiBjYWxsQ2xlYW51cEhvb2tzKHJ1bm5lciwgY2xlYW51cHMpIHtcblx0Y29uc3Qgc2VxdWVuY2UgPSBydW5uZXIuY29uZmlnLnNlcXVlbmNlLmhvb2tzO1xuXHRpZiAoc2VxdWVuY2UgPT09IFwic3RhY2tcIikge1xuXHRcdGNsZWFudXBzID0gY2xlYW51cHMuc2xpY2UoKS5yZXZlcnNlKCk7XG5cdH1cblx0aWYgKHNlcXVlbmNlID09PSBcInBhcmFsbGVsXCIpIHtcblx0XHRhd2FpdCBQcm9taXNlLmFsbChjbGVhbnVwcy5tYXAoYXN5bmMgKGZuKSA9PiB7XG5cdFx0XHRpZiAodHlwZW9mIGZuICE9PSBcImZ1bmN0aW9uXCIpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0YXdhaXQgbGltaXRNYXhDb25jdXJyZW5jeSgoKSA9PiBmbigpKTtcblx0XHR9KSk7XG5cdH0gZWxzZSB7XG5cdFx0Zm9yIChjb25zdCBmbiBvZiBjbGVhbnVwcykge1xuXHRcdFx0aWYgKHR5cGVvZiBmbiAhPT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcdFx0YXdhaXQgbGltaXRNYXhDb25jdXJyZW5jeSgoKSA9PiBmbigpKTtcblx0XHR9XG5cdH1cbn1cbi8qKlxuKiBEZXRlcm1pbmVzIGlmIGEgdGVzdCBzaG91bGQgYmUgcmV0cmllZCBiYXNlZCBvbiBpdHMgcmV0cnlDb25kaXRpb24gY29uZmlndXJhdGlvblxuKi9cbmZ1bmN0aW9uIHBhc3Nlc1JldHJ5Q29uZGl0aW9uKHRlc3QsIGVycm9ycykge1xuXHRjb25zdCBjb25kaXRpb24gPSBnZXRSZXRyeUNvbmRpdGlvbih0ZXN0LnJldHJ5KTtcblx0aWYgKCFlcnJvcnMgfHwgZXJyb3JzLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXHRpZiAoIWNvbmRpdGlvbikge1xuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdGNvbnN0IGVycm9yID0gZXJyb3JzW2Vycm9ycy5sZW5ndGggLSAxXTtcblx0aWYgKGNvbmRpdGlvbiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuXHRcdHJldHVybiBjb25kaXRpb24udGVzdChlcnJvci5tZXNzYWdlIHx8IFwiXCIpO1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBjb25kaXRpb24gPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdHJldHVybiBjb25kaXRpb24oZXJyb3IpO1xuXHR9XG5cdHJldHVybiBmYWxzZTtcbn1cbmFzeW5jIGZ1bmN0aW9uIHJ1blRlc3QodGVzdCwgcnVubmVyKSB7XG5cdGF3YWl0IHJ1bm5lci5vbkJlZm9yZVJ1blRhc2s/Lih0ZXN0KTtcblx0aWYgKHRlc3QubW9kZSAhPT0gXCJydW5cIiAmJiB0ZXN0Lm1vZGUgIT09IFwicXVldWVkXCIpIHtcblx0XHR1cGRhdGVUYXNrKFwidGVzdC1wcmVwYXJlXCIsIHRlc3QsIHJ1bm5lcik7XG5cdFx0dXBkYXRlVGFzayhcInRlc3QtZmluaXNoZWRcIiwgdGVzdCwgcnVubmVyKTtcblx0XHRyZXR1cm47XG5cdH1cblx0aWYgKHRlc3QucmVzdWx0Py5zdGF0ZSA9PT0gXCJmYWlsXCIpIHtcblx0XHQvLyBzaG91bGQgbm90IGJlIHBvc3NpYmxlIHRvIGdldCBoZXJlLCBJIHRoaW5rIHRoaXMgaXMganVzdCBjb3B5IHBhc3RlZCBmcm9tIHN1aXRlXG5cdFx0Ly8gVE9ETzogbWF5YmUgc29tZW9uZSBmYWlscyB0ZXN0cyBpbiBgYmVmb3JlQWxsYCBob29rcz9cblx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vdml0ZXN0LWRldi92aXRlc3QvcHVsbC83MDY5XG5cdFx0dXBkYXRlVGFzayhcInRlc3QtZmFpbGVkLWVhcmx5XCIsIHRlc3QsIHJ1bm5lcik7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHN0YXJ0ID0gbm93KCk7XG5cdHRlc3QucmVzdWx0ID0ge1xuXHRcdHN0YXRlOiBcInJ1blwiLFxuXHRcdHN0YXJ0VGltZTogdW5peE5vdygpLFxuXHRcdHJldHJ5Q291bnQ6IDBcblx0fTtcblx0dXBkYXRlVGFzayhcInRlc3QtcHJlcGFyZVwiLCB0ZXN0LCBydW5uZXIpO1xuXHRjb25zdCBjbGVhbnVwUnVubmluZ1Rlc3QgPSBhZGRSdW5uaW5nVGVzdCh0ZXN0KTtcblx0c2V0Q3VycmVudFRlc3QodGVzdCk7XG5cdGNvbnN0IHN1aXRlID0gdGVzdC5zdWl0ZSB8fCB0ZXN0LmZpbGU7XG5cdGNvbnN0ICQgPSBydW5uZXIudHJhY2U7XG5cdGNvbnN0IHJlcGVhdHMgPSB0ZXN0LnJlcGVhdHMgPz8gMDtcblx0Zm9yIChsZXQgcmVwZWF0Q291bnQgPSAwOyByZXBlYXRDb3VudCA8PSByZXBlYXRzOyByZXBlYXRDb3VudCsrKSB7XG5cdFx0Y29uc3QgcmV0cnkgPSBnZXRSZXRyeUNvdW50KHRlc3QucmV0cnkpO1xuXHRcdGZvciAobGV0IHJldHJ5Q291bnQgPSAwOyByZXRyeUNvdW50IDw9IHJldHJ5OyByZXRyeUNvdW50KyspIHtcblx0XHRcdGxldCBiZWZvcmVFYWNoQ2xlYW51cHMgPSBbXTtcblx0XHRcdC8vIGZpeHR1cmVDaGVja3BvaW50IGlzIHBhc3NlZCBieSBjYWxsQXJvdW5kRWFjaEhvb2tzIC0gaXQgcmVwcmVzZW50cyB0aGUgY291bnRcblx0XHRcdC8vIG9mIGZpeHR1cmUgY2xlYW51cCBmdW5jdGlvbnMgQUZURVIgYWxsIGFyb3VuZEVhY2ggZml4dHVyZXMgaGF2ZSBiZWVuIHJlc29sdmVkXG5cdFx0XHQvLyBidXQgQkVGT1JFIHRoZSB0ZXN0IHJ1bnMuIFRoaXMgYWxsb3dzIHVzIHRvIGNsZWFuIHVwIG9ubHkgZml4dHVyZXMgY3JlYXRlZFxuXHRcdFx0Ly8gaW5zaWRlIHJ1blRlc3Qgd2hpbGUgcHJlc2VydmluZyBhcm91bmRFYWNoIGZpeHR1cmVzIGZvciB0ZWFyZG93bi5cblx0XHRcdGF3YWl0IGNhbGxBcm91bmRFYWNoSG9va3Moc3VpdGUsIHRlc3QsIGFzeW5jIChmaXh0dXJlQ2hlY2twb2ludCkgPT4ge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGF3YWl0IHJ1bm5lci5vbkJlZm9yZVRyeVRhc2s/Lih0ZXN0LCB7XG5cdFx0XHRcdFx0XHRyZXRyeTogcmV0cnlDb3VudCxcblx0XHRcdFx0XHRcdHJlcGVhdHM6IHJlcGVhdENvdW50XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0dGVzdC5yZXN1bHQucmVwZWF0Q291bnQgPSByZXBlYXRDb3VudDtcblx0XHRcdFx0XHRiZWZvcmVFYWNoQ2xlYW51cHMgPSBhd2FpdCAkKFwidGVzdC5iZWZvcmVFYWNoXCIsICgpID0+IGNhbGxTdWl0ZUhvb2soc3VpdGUsIHRlc3QsIFwiYmVmb3JlRWFjaFwiLCBydW5uZXIsIFt0ZXN0LmNvbnRleHQsIHN1aXRlXSkpO1xuXHRcdFx0XHRcdGlmIChydW5uZXIucnVuVGFzaykge1xuXHRcdFx0XHRcdFx0YXdhaXQgJChcInRlc3QuY2FsbGJhY2tcIiwgKCkgPT4gbGltaXRNYXhDb25jdXJyZW5jeSgoKSA9PiBydW5uZXIucnVuVGFzayh0ZXN0KSkpO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb25zdCBmbiA9IGdldEZuKHRlc3QpO1xuXHRcdFx0XHRcdFx0aWYgKCFmbikge1xuXHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJUZXN0IGZ1bmN0aW9uIGlzIG5vdCBmb3VuZC4gRGlkIHlvdSBhZGQgaXQgdXNpbmcgYHNldEZuYD9cIik7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRhd2FpdCAkKFwidGVzdC5jYWxsYmFja1wiLCAoKSA9PiBsaW1pdE1heENvbmN1cnJlbmN5KCgpID0+IGZuKCkpKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YXdhaXQgcnVubmVyLm9uQWZ0ZXJUcnlUYXNrPy4odGVzdCwge1xuXHRcdFx0XHRcdFx0cmV0cnk6IHJldHJ5Q291bnQsXG5cdFx0XHRcdFx0XHRyZXBlYXRzOiByZXBlYXRDb3VudFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdGlmICh0ZXN0LnJlc3VsdC5zdGF0ZSAhPT0gXCJmYWlsXCIpIHtcblx0XHRcdFx0XHRcdHRlc3QucmVzdWx0LnN0YXRlID0gXCJwYXNzXCI7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0ZmFpbFRhc2sodGVzdC5yZXN1bHQsIGUsIHJ1bm5lci5jb25maWcuZGlmZk9wdGlvbnMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0YXdhaXQgcnVubmVyLm9uVGFza0ZpbmlzaGVkPy4odGVzdCk7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRmYWlsVGFzayh0ZXN0LnJlc3VsdCwgZSwgcnVubmVyLmNvbmZpZy5kaWZmT3B0aW9ucyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRhd2FpdCAkKFwidGVzdC5hZnRlckVhY2hcIiwgKCkgPT4gY2FsbFN1aXRlSG9vayhzdWl0ZSwgdGVzdCwgXCJhZnRlckVhY2hcIiwgcnVubmVyLCBbdGVzdC5jb250ZXh0LCBzdWl0ZV0pKTtcblx0XHRcdFx0XHRpZiAoYmVmb3JlRWFjaENsZWFudXBzLmxlbmd0aCkge1xuXHRcdFx0XHRcdFx0YXdhaXQgJChcInRlc3QuY2xlYW51cFwiLCAoKSA9PiBjYWxsQ2xlYW51cEhvb2tzKHJ1bm5lciwgYmVmb3JlRWFjaENsZWFudXBzKSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vIE9ubHkgY2xlYW4gdXAgZml4dHVyZXMgY3JlYXRlZCBpbnNpZGUgcnVuVGVzdCAoYWZ0ZXIgdGhlIGNoZWNrcG9pbnQpXG5cdFx0XHRcdFx0Ly8gRml4dHVyZXMgY3JlYXRlZCBmb3IgYXJvdW5kRWFjaCB3aWxsIGJlIGNsZWFuZWQgdXAgYWZ0ZXIgYXJvdW5kRWFjaCB0ZWFyZG93blxuXHRcdFx0XHRcdGF3YWl0IGNhbGxGaXh0dXJlQ2xlYW51cEZyb20odGVzdC5jb250ZXh0LCBmaXh0dXJlQ2hlY2twb2ludCk7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRmYWlsVGFzayh0ZXN0LnJlc3VsdCwgZSwgcnVubmVyLmNvbmZpZy5kaWZmT3B0aW9ucyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKHRlc3Qub25GaW5pc2hlZD8ubGVuZ3RoKSB7XG5cdFx0XHRcdFx0YXdhaXQgJChcInRlc3Qub25GaW5pc2hlZFwiLCAoKSA9PiBjYWxsVGVzdEhvb2tzKHJ1bm5lciwgdGVzdCwgdGVzdC5vbkZpbmlzaGVkLCBcInN0YWNrXCIpKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAodGVzdC5yZXN1bHQuc3RhdGUgPT09IFwiZmFpbFwiICYmIHRlc3Qub25GYWlsZWQ/Lmxlbmd0aCkge1xuXHRcdFx0XHRcdGF3YWl0ICQoXCJ0ZXN0Lm9uRmFpbGVkXCIsICgpID0+IGNhbGxUZXN0SG9va3MocnVubmVyLCB0ZXN0LCB0ZXN0Lm9uRmFpbGVkLCBydW5uZXIuY29uZmlnLnNlcXVlbmNlLmhvb2tzKSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGVzdC5vbkZhaWxlZCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0dGVzdC5vbkZpbmlzaGVkID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRhd2FpdCBydW5uZXIub25BZnRlclJldHJ5VGFzaz8uKHRlc3QsIHtcblx0XHRcdFx0XHRyZXRyeTogcmV0cnlDb3VudCxcblx0XHRcdFx0XHRyZXBlYXRzOiByZXBlYXRDb3VudFxuXHRcdFx0XHR9KTtcblx0XHRcdH0pLmNhdGNoKChlcnJvcikgPT4ge1xuXHRcdFx0XHRmYWlsVGFzayh0ZXN0LnJlc3VsdCwgZXJyb3IsIHJ1bm5lci5jb25maWcuZGlmZk9wdGlvbnMpO1xuXHRcdFx0fSk7XG5cdFx0XHQvLyBDbGVhbiB1cCBmaXh0dXJlcyB0aGF0IHdlcmUgY3JlYXRlZCBmb3IgYXJvdW5kRWFjaCAoYmVmb3JlIHRoZSBjaGVja3BvaW50KVxuXHRcdFx0Ly8gVGhpcyBydW5zIGFmdGVyIGFyb3VuZEVhY2ggdGVhcmRvd24gaGFzIGNvbXBsZXRlZFxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0YXdhaXQgY2FsbEZpeHR1cmVDbGVhbnVwKHRlc3QuY29udGV4dCk7XG5cdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdGZhaWxUYXNrKHRlc3QucmVzdWx0LCBlLCBydW5uZXIuY29uZmlnLmRpZmZPcHRpb25zKTtcblx0XHRcdH1cblx0XHRcdC8vIHNraXBwZWQgd2l0aCBuZXcgUGVuZGluZ0Vycm9yXG5cdFx0XHRpZiAodGVzdC5yZXN1bHQ/LnBlbmRpbmcgfHwgdGVzdC5yZXN1bHQ/LnN0YXRlID09PSBcInNraXBcIikge1xuXHRcdFx0XHR0ZXN0Lm1vZGUgPSBcInNraXBcIjtcblx0XHRcdFx0dGVzdC5yZXN1bHQgPSB7XG5cdFx0XHRcdFx0c3RhdGU6IFwic2tpcFwiLFxuXHRcdFx0XHRcdG5vdGU6IHRlc3QucmVzdWx0Py5ub3RlLFxuXHRcdFx0XHRcdHBlbmRpbmc6IHRydWUsXG5cdFx0XHRcdFx0ZHVyYXRpb246IG5vdygpIC0gc3RhcnRcblx0XHRcdFx0fTtcblx0XHRcdFx0dXBkYXRlVGFzayhcInRlc3QtZmluaXNoZWRcIiwgdGVzdCwgcnVubmVyKTtcblx0XHRcdFx0c2V0Q3VycmVudFRlc3QodW5kZWZpbmVkKTtcblx0XHRcdFx0Y2xlYW51cFJ1bm5pbmdUZXN0KCk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdGlmICh0ZXN0LnJlc3VsdC5zdGF0ZSA9PT0gXCJwYXNzXCIpIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRpZiAocmV0cnlDb3VudCA8IHJldHJ5KSB7XG5cdFx0XHRcdGNvbnN0IHNob3VsZFJldHJ5ID0gcGFzc2VzUmV0cnlDb25kaXRpb24odGVzdCwgdGVzdC5yZXN1bHQuZXJyb3JzKTtcblx0XHRcdFx0aWYgKCFzaG91bGRSZXRyeSkge1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRlc3QucmVzdWx0LnN0YXRlID0gXCJydW5cIjtcblx0XHRcdFx0dGVzdC5yZXN1bHQucmV0cnlDb3VudCA9ICh0ZXN0LnJlc3VsdC5yZXRyeUNvdW50ID8/IDApICsgMTtcblx0XHRcdFx0Y29uc3QgZGVsYXkgPSBnZXRSZXRyeURlbGF5KHRlc3QucmV0cnkpO1xuXHRcdFx0XHRpZiAoZGVsYXkgPiAwKSB7XG5cdFx0XHRcdFx0YXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgZGVsYXkpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Ly8gdXBkYXRlIHJldHJ5IGluZm9cblx0XHRcdHVwZGF0ZVRhc2soXCJ0ZXN0LXJldHJpZWRcIiwgdGVzdCwgcnVubmVyKTtcblx0XHR9XG5cdH1cblx0Ly8gaWYgdGVzdCBpcyBtYXJrZWQgdG8gYmUgZmFpbGVkLCBmbGlwIHRoZSByZXN1bHRcblx0aWYgKHRlc3QuZmFpbHMpIHtcblx0XHRpZiAodGVzdC5yZXN1bHQuc3RhdGUgPT09IFwicGFzc1wiKSB7XG5cdFx0XHRjb25zdCBlcnJvciA9IHByb2Nlc3NFcnJvcihuZXcgRXJyb3IoXCJFeHBlY3QgdGVzdCB0byBmYWlsXCIpKTtcblx0XHRcdHRlc3QucmVzdWx0LnN0YXRlID0gXCJmYWlsXCI7XG5cdFx0XHR0ZXN0LnJlc3VsdC5lcnJvcnMgPSBbZXJyb3JdO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0ZXN0LnJlc3VsdC5zdGF0ZSA9IFwicGFzc1wiO1xuXHRcdFx0dGVzdC5yZXN1bHQuZXJyb3JzID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRjbGVhbnVwUnVubmluZ1Rlc3QoKTtcblx0c2V0Q3VycmVudFRlc3QodW5kZWZpbmVkKTtcblx0dGVzdC5yZXN1bHQuZHVyYXRpb24gPSBub3coKSAtIHN0YXJ0O1xuXHRhd2FpdCBydW5uZXIub25BZnRlclJ1blRhc2s/Lih0ZXN0KTtcblx0dXBkYXRlVGFzayhcInRlc3QtZmluaXNoZWRcIiwgdGVzdCwgcnVubmVyKTtcbn1cbmZ1bmN0aW9uIGZhaWxUYXNrKHJlc3VsdCwgZXJyLCBkaWZmT3B0aW9ucykge1xuXHRpZiAoZXJyIGluc3RhbmNlb2YgUGVuZGluZ0Vycm9yKSB7XG5cdFx0cmVzdWx0LnN0YXRlID0gXCJza2lwXCI7XG5cdFx0cmVzdWx0Lm5vdGUgPSBlcnIubm90ZTtcblx0XHRyZXN1bHQucGVuZGluZyA9IHRydWU7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGlmIChlcnIgaW5zdGFuY2VvZiBUZXN0UnVuQWJvcnRFcnJvcikge1xuXHRcdHJlc3VsdC5zdGF0ZSA9IFwic2tpcFwiO1xuXHRcdHJlc3VsdC5ub3RlID0gZXJyLm1lc3NhZ2U7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHJlc3VsdC5zdGF0ZSA9IFwiZmFpbFwiO1xuXHRjb25zdCBlcnJvcnMgPSBBcnJheS5pc0FycmF5KGVycikgPyBlcnIgOiBbZXJyXTtcblx0Zm9yIChjb25zdCBlIG9mIGVycm9ycykge1xuXHRcdGNvbnN0IGVycm9ycyA9IGUgaW5zdGFuY2VvZiBBZ2dyZWdhdGVFcnJvciA/IGUuZXJyb3JzLm1hcCgoZSkgPT4gcHJvY2Vzc0Vycm9yKGUsIGRpZmZPcHRpb25zKSkgOiBbcHJvY2Vzc0Vycm9yKGUsIGRpZmZPcHRpb25zKV07XG5cdFx0cmVzdWx0LmVycm9ycyA/Pz0gW107XG5cdFx0cmVzdWx0LmVycm9ycy5wdXNoKC4uLmVycm9ycyk7XG5cdH1cbn1cbmZ1bmN0aW9uIG1hcmtUYXNrc0FzU2tpcHBlZChzdWl0ZSwgcnVubmVyKSB7XG5cdHN1aXRlLnRhc2tzLmZvckVhY2goKHQpID0+IHtcblx0XHR0Lm1vZGUgPSBcInNraXBcIjtcblx0XHR0LnJlc3VsdCA9IHtcblx0XHRcdC4uLnQucmVzdWx0LFxuXHRcdFx0c3RhdGU6IFwic2tpcFwiXG5cdFx0fTtcblx0XHR1cGRhdGVUYXNrKFwidGVzdC1maW5pc2hlZFwiLCB0LCBydW5uZXIpO1xuXHRcdGlmICh0LnR5cGUgPT09IFwic3VpdGVcIikge1xuXHRcdFx0bWFya1Rhc2tzQXNTa2lwcGVkKHQsIHJ1bm5lcik7XG5cdFx0fVxuXHR9KTtcbn1cbmZ1bmN0aW9uIG1hcmtQZW5kaW5nVGFza3NBc1NraXBwZWQoc3VpdGUsIHJ1bm5lciwgbm90ZSkge1xuXHRzdWl0ZS50YXNrcy5mb3JFYWNoKCh0KSA9PiB7XG5cdFx0aWYgKCF0LnJlc3VsdCB8fCB0LnJlc3VsdC5zdGF0ZSA9PT0gXCJydW5cIikge1xuXHRcdFx0dC5tb2RlID0gXCJza2lwXCI7XG5cdFx0XHR0LnJlc3VsdCA9IHtcblx0XHRcdFx0Li4udC5yZXN1bHQsXG5cdFx0XHRcdHN0YXRlOiBcInNraXBcIixcblx0XHRcdFx0bm90ZVxuXHRcdFx0fTtcblx0XHRcdHVwZGF0ZVRhc2soXCJ0ZXN0LWNhbmNlbFwiLCB0LCBydW5uZXIpO1xuXHRcdH1cblx0XHRpZiAodC50eXBlID09PSBcInN1aXRlXCIpIHtcblx0XHRcdG1hcmtQZW5kaW5nVGFza3NBc1NraXBwZWQodCwgcnVubmVyLCBub3RlKTtcblx0XHR9XG5cdH0pO1xufVxuYXN5bmMgZnVuY3Rpb24gcnVuU3VpdGUoc3VpdGUsIHJ1bm5lcikge1xuXHRhd2FpdCBydW5uZXIub25CZWZvcmVSdW5TdWl0ZT8uKHN1aXRlKTtcblx0aWYgKHN1aXRlLnJlc3VsdD8uc3RhdGUgPT09IFwiZmFpbFwiKSB7XG5cdFx0bWFya1Rhc2tzQXNTa2lwcGVkKHN1aXRlLCBydW5uZXIpO1xuXHRcdC8vIGZhaWxlZCBkdXJpbmcgY29sbGVjdGlvblxuXHRcdHVwZGF0ZVRhc2soXCJzdWl0ZS1mYWlsZWQtZWFybHlcIiwgc3VpdGUsIHJ1bm5lcik7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGNvbnN0IHN0YXJ0ID0gbm93KCk7XG5cdGNvbnN0IG1vZGUgPSBzdWl0ZS5tb2RlO1xuXHRzdWl0ZS5yZXN1bHQgPSB7XG5cdFx0c3RhdGU6IG1vZGUgPT09IFwic2tpcFwiIHx8IG1vZGUgPT09IFwidG9kb1wiID8gbW9kZSA6IFwicnVuXCIsXG5cdFx0c3RhcnRUaW1lOiB1bml4Tm93KClcblx0fTtcblx0Y29uc3QgJCA9IHJ1bm5lci50cmFjZTtcblx0dXBkYXRlVGFzayhcInN1aXRlLXByZXBhcmVcIiwgc3VpdGUsIHJ1bm5lcik7XG5cdGxldCBiZWZvcmVBbGxDbGVhbnVwcyA9IFtdO1xuXHRpZiAoc3VpdGUubW9kZSA9PT0gXCJza2lwXCIpIHtcblx0XHRzdWl0ZS5yZXN1bHQuc3RhdGUgPSBcInNraXBcIjtcblx0XHR1cGRhdGVUYXNrKFwic3VpdGUtZmluaXNoZWRcIiwgc3VpdGUsIHJ1bm5lcik7XG5cdH0gZWxzZSBpZiAoc3VpdGUubW9kZSA9PT0gXCJ0b2RvXCIpIHtcblx0XHRzdWl0ZS5yZXN1bHQuc3RhdGUgPSBcInRvZG9cIjtcblx0XHR1cGRhdGVUYXNrKFwic3VpdGUtZmluaXNoZWRcIiwgc3VpdGUsIHJ1bm5lcik7XG5cdH0gZWxzZSB7XG5cdFx0bGV0IHN1aXRlUmFuID0gZmFsc2U7XG5cdFx0dHJ5IHtcblx0XHRcdGF3YWl0IGNhbGxBcm91bmRBbGxIb29rcyhzdWl0ZSwgYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRzdWl0ZVJhbiA9IHRydWU7XG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Ly8gYmVmb3JlQWxsXG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdGJlZm9yZUFsbENsZWFudXBzID0gYXdhaXQgJChcInN1aXRlLmJlZm9yZUFsbFwiLCAoKSA9PiBjYWxsU3VpdGVIb29rKHN1aXRlLCBzdWl0ZSwgXCJiZWZvcmVBbGxcIiwgcnVubmVyLCBbc3VpdGVdKSk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdFx0ZmFpbFRhc2soc3VpdGUucmVzdWx0LCBlLCBydW5uZXIuY29uZmlnLmRpZmZPcHRpb25zKTtcblx0XHRcdFx0XHRcdG1hcmtUYXNrc0FzU2tpcHBlZChzdWl0ZSwgcnVubmVyKTtcblx0XHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Ly8gcnVuIHN1aXRlIGNoaWxkcmVuXG5cdFx0XHRcdFx0aWYgKHJ1bm5lci5ydW5TdWl0ZSkge1xuXHRcdFx0XHRcdFx0YXdhaXQgcnVubmVyLnJ1blN1aXRlKHN1aXRlKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Zm9yIChsZXQgdGFza3NHcm91cCBvZiBwYXJ0aXRpb25TdWl0ZUNoaWxkcmVuKHN1aXRlKSkge1xuXHRcdFx0XHRcdFx0XHRpZiAodGFza3NHcm91cFswXS5jb25jdXJyZW50ID09PSB0cnVlKSB7XG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgZ3JvdXBMaW1pdGVyID0gbGltaXRDb25jdXJyZW5jeShydW5uZXIuY29uZmlnLm1heENvbmN1cnJlbmN5KTtcblx0XHRcdFx0XHRcdFx0XHRhd2FpdCBQcm9taXNlLmFsbCh0YXNrc0dyb3VwLm1hcCgoYykgPT4gZ3JvdXBMaW1pdGVyKCgpID0+IHJ1blN1aXRlQ2hpbGQoYywgcnVubmVyKSkpKTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb25zdCB7IHNlcXVlbmNlIH0gPSBydW5uZXIuY29uZmlnO1xuXHRcdFx0XHRcdFx0XHRcdGlmIChzdWl0ZS5zaHVmZmxlKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBydW4gZGVzY3JpYmUgYmxvY2sgaW5kZXBlbmRlbnRseSBmcm9tIHRlc3RzXG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zdCBzdWl0ZXMgPSB0YXNrc0dyb3VwLmZpbHRlcigoZ3JvdXApID0+IGdyb3VwLnR5cGUgPT09IFwic3VpdGVcIik7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb25zdCB0ZXN0cyA9IHRhc2tzR3JvdXAuZmlsdGVyKChncm91cCkgPT4gZ3JvdXAudHlwZSA9PT0gXCJ0ZXN0XCIpO1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29uc3QgZ3JvdXBzID0gc2h1ZmZsZShbc3VpdGVzLCB0ZXN0c10sIHNlcXVlbmNlLnNlZWQpO1xuXHRcdFx0XHRcdFx0XHRcdFx0dGFza3NHcm91cCA9IGdyb3Vwcy5mbGF0TWFwKChncm91cCkgPT4gc2h1ZmZsZShncm91cCwgc2VxdWVuY2Uuc2VlZCkpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRmb3IgKGNvbnN0IGMgb2YgdGFza3NHcm91cCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0YXdhaXQgcnVuU3VpdGVDaGlsZChjLCBydW5uZXIpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSBmaW5hbGx5IHtcblx0XHRcdFx0XHQvLyBhZnRlckFsbCBydW5zIGV2ZW4gaWYgYmVmb3JlQWxsIG9yIHN1aXRlIGNoaWxkcmVuIGZhaWxcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0YXdhaXQgJChcInN1aXRlLmFmdGVyQWxsXCIsICgpID0+IGNhbGxTdWl0ZUhvb2soc3VpdGUsIHN1aXRlLCBcImFmdGVyQWxsXCIsIHJ1bm5lciwgW3N1aXRlXSkpO1xuXHRcdFx0XHRcdFx0aWYgKGJlZm9yZUFsbENsZWFudXBzLmxlbmd0aCkge1xuXHRcdFx0XHRcdFx0XHRhd2FpdCAkKFwic3VpdGUuY2xlYW51cFwiLCAoKSA9PiBjYWxsQ2xlYW51cEhvb2tzKHJ1bm5lciwgYmVmb3JlQWxsQ2xlYW51cHMpKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChzdWl0ZS5maWxlID09PSBzdWl0ZSkge1xuXHRcdFx0XHRcdFx0XHRjb25zdCBjb250ZXh0cyA9IFRlc3RGaXh0dXJlcy5nZXRGaWxlQ29udGV4dHMoc3VpdGUuZmlsZSk7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IFByb21pc2UuYWxsKGNvbnRleHRzLm1hcCgoY29udGV4dCkgPT4gY2FsbEZpeHR1cmVDbGVhbnVwKGNvbnRleHQpKSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdFx0ZmFpbFRhc2soc3VpdGUucmVzdWx0LCBlLCBydW5uZXIuY29uZmlnLmRpZmZPcHRpb25zKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdC8vIG1hcmsgdGFza3MgYXMgc2tpcHBlZCBpZiBhcm91bmRBbGwgZmFpbGVkIGJlZm9yZSB0aGUgc3VpdGUgY2FsbGJhY2sgd2FzIGV4ZWN1dGVkXG5cdFx0XHRpZiAoIXN1aXRlUmFuKSB7XG5cdFx0XHRcdG1hcmtUYXNrc0FzU2tpcHBlZChzdWl0ZSwgcnVubmVyKTtcblx0XHRcdH1cblx0XHRcdGZhaWxUYXNrKHN1aXRlLnJlc3VsdCwgZSwgcnVubmVyLmNvbmZpZy5kaWZmT3B0aW9ucyk7XG5cdFx0fVxuXHRcdGlmIChzdWl0ZS5tb2RlID09PSBcInJ1blwiIHx8IHN1aXRlLm1vZGUgPT09IFwicXVldWVkXCIpIHtcblx0XHRcdGlmICghcnVubmVyLmNvbmZpZy5wYXNzV2l0aE5vVGVzdHMgJiYgIWhhc1Rlc3RzKHN1aXRlKSkge1xuXHRcdFx0XHRzdWl0ZS5yZXN1bHQuc3RhdGUgPSBcImZhaWxcIjtcblx0XHRcdFx0aWYgKCFzdWl0ZS5yZXN1bHQuZXJyb3JzPy5sZW5ndGgpIHtcblx0XHRcdFx0XHRjb25zdCBlcnJvciA9IHByb2Nlc3NFcnJvcihuZXcgRXJyb3IoYE5vIHRlc3QgZm91bmQgaW4gc3VpdGUgJHtzdWl0ZS5uYW1lfWApKTtcblx0XHRcdFx0XHRzdWl0ZS5yZXN1bHQuZXJyb3JzID0gW2Vycm9yXTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChoYXNGYWlsZWQoc3VpdGUpKSB7XG5cdFx0XHRcdHN1aXRlLnJlc3VsdC5zdGF0ZSA9IFwiZmFpbFwiO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c3VpdGUucmVzdWx0LnN0YXRlID0gXCJwYXNzXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHN1aXRlLnJlc3VsdC5kdXJhdGlvbiA9IG5vdygpIC0gc3RhcnQ7XG5cdFx0YXdhaXQgcnVubmVyLm9uQWZ0ZXJSdW5TdWl0ZT8uKHN1aXRlKTtcblx0XHR1cGRhdGVUYXNrKFwic3VpdGUtZmluaXNoZWRcIiwgc3VpdGUsIHJ1bm5lcik7XG5cdH1cbn1cbmFzeW5jIGZ1bmN0aW9uIHJ1blN1aXRlQ2hpbGQoYywgcnVubmVyKSB7XG5cdGNvbnN0ICQgPSBydW5uZXIudHJhY2U7XG5cdGlmIChjLnR5cGUgPT09IFwidGVzdFwiKSB7XG5cdFx0cmV0dXJuICQoXCJydW4udGVzdFwiLCB7XG5cdFx0XHRcInZpdGVzdC50ZXN0LmlkXCI6IGMuaWQsXG5cdFx0XHRcInZpdGVzdC50ZXN0Lm5hbWVcIjogYy5uYW1lLFxuXHRcdFx0XCJ2aXRlc3QudGVzdC5tb2RlXCI6IGMubW9kZSxcblx0XHRcdFwidml0ZXN0LnRlc3QudGltZW91dFwiOiBjLnRpbWVvdXQsXG5cdFx0XHRcImNvZGUuZmlsZS5wYXRoXCI6IGMuZmlsZS5maWxlcGF0aCxcblx0XHRcdFwiY29kZS5saW5lLm51bWJlclwiOiBjLmxvY2F0aW9uPy5saW5lLFxuXHRcdFx0XCJjb2RlLmNvbHVtbi5udW1iZXJcIjogYy5sb2NhdGlvbj8uY29sdW1uXG5cdFx0fSwgKCkgPT4gcnVuVGVzdChjLCBydW5uZXIpKTtcblx0fSBlbHNlIGlmIChjLnR5cGUgPT09IFwic3VpdGVcIikge1xuXHRcdHJldHVybiAkKFwicnVuLnN1aXRlXCIsIHtcblx0XHRcdFwidml0ZXN0LnN1aXRlLmlkXCI6IGMuaWQsXG5cdFx0XHRcInZpdGVzdC5zdWl0ZS5uYW1lXCI6IGMubmFtZSxcblx0XHRcdFwidml0ZXN0LnN1aXRlLm1vZGVcIjogYy5tb2RlLFxuXHRcdFx0XCJjb2RlLmZpbGUucGF0aFwiOiBjLmZpbGUuZmlsZXBhdGgsXG5cdFx0XHRcImNvZGUubGluZS5udW1iZXJcIjogYy5sb2NhdGlvbj8ubGluZSxcblx0XHRcdFwiY29kZS5jb2x1bW4ubnVtYmVyXCI6IGMubG9jYXRpb24/LmNvbHVtblxuXHRcdH0sICgpID0+IHJ1blN1aXRlKGMsIHJ1bm5lcikpO1xuXHR9XG59XG5hc3luYyBmdW5jdGlvbiBydW5GaWxlcyhmaWxlcywgcnVubmVyKSB7XG5cdGxpbWl0TWF4Q29uY3VycmVuY3kgPz89IGxpbWl0Q29uY3VycmVuY3kocnVubmVyLmNvbmZpZy5tYXhDb25jdXJyZW5jeSk7XG5cdGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuXHRcdGlmICghZmlsZS50YXNrcy5sZW5ndGggJiYgIXJ1bm5lci5jb25maWcucGFzc1dpdGhOb1Rlc3RzKSB7XG5cdFx0XHRpZiAoIWZpbGUucmVzdWx0Py5lcnJvcnM/Lmxlbmd0aCkge1xuXHRcdFx0XHRjb25zdCBlcnJvciA9IHByb2Nlc3NFcnJvcihuZXcgRXJyb3IoYE5vIHRlc3Qgc3VpdGUgZm91bmQgaW4gZmlsZSAke2ZpbGUuZmlsZXBhdGh9YCkpO1xuXHRcdFx0XHRmaWxlLnJlc3VsdCA9IHtcblx0XHRcdFx0XHRzdGF0ZTogXCJmYWlsXCIsXG5cdFx0XHRcdFx0ZXJyb3JzOiBbZXJyb3JdXG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGF3YWl0IHJ1bm5lci50cmFjZShcInJ1bi5zcGVjXCIsIHtcblx0XHRcdFwiY29kZS5maWxlLnBhdGhcIjogZmlsZS5maWxlcGF0aCxcblx0XHRcdFwidml0ZXN0LnN1aXRlLnRhc2tzLmxlbmd0aFwiOiBmaWxlLnRhc2tzLmxlbmd0aFxuXHRcdH0sICgpID0+IHJ1blN1aXRlKGZpbGUsIHJ1bm5lcikpO1xuXHR9XG59XG5jb25zdCB3b3JrZXJSdW5uZXJzID0gbmV3IFdlYWtTZXQoKTtcbmZ1bmN0aW9uIGRlZmF1bHRUcmFjZShfLCBhdHRyaWJ1dGVzLCBjYikge1xuXHRpZiAodHlwZW9mIGF0dHJpYnV0ZXMgPT09IFwiZnVuY3Rpb25cIikge1xuXHRcdHJldHVybiBhdHRyaWJ1dGVzKCk7XG5cdH1cblx0cmV0dXJuIGNiKCk7XG59XG5hc3luYyBmdW5jdGlvbiBzdGFydFRlc3RzKHNwZWNzLCBydW5uZXIpIHtcblx0cnVubmVyLnRyYWNlID8/PSBkZWZhdWx0VHJhY2U7XG5cdGNvbnN0IGNhbmNlbCA9IHJ1bm5lci5jYW5jZWw/LmJpbmQocnVubmVyKTtcblx0Ly8gSWRlYWxseSwgd2UgbmVlZCB0byBoYXZlIGFuIGV2ZW50IGxpc3RlbmVyIGZvciB0aGlzLCBidXQgb25seSBoYXZlIGEgcnVubmVyIGhlcmUuXG5cdC8vIEFkZGluZyBhbm90aGVyIG9uQ2FuY2VsIGZlbHQgd3JvbmcgKG1heWJlIGl0IG5lZWRzIHRvIGJlIHJlZmFjdG9yZWQpXG5cdHJ1bm5lci5jYW5jZWwgPSAocmVhc29uKSA9PiB7XG5cdFx0Ly8gV2UgaW50ZW50aW9uYWxseSBjcmVhdGUgb25seSBvbmUgZXJyb3Igc2luY2UgdGhlcmUgaXMgb25seSBvbmUgdGVzdCBydW4gdGhhdCBjYW4gYmUgY2FuY2VsbGVkXG5cdFx0Y29uc3QgZXJyb3IgPSBuZXcgVGVzdFJ1bkFib3J0RXJyb3IoXCJUaGUgdGVzdCBydW4gd2FzIGFib3J0ZWQgYnkgdGhlIHVzZXIuXCIsIHJlYXNvbik7XG5cdFx0Z2V0UnVubmluZ1Rlc3RzKCkuZm9yRWFjaCgodGVzdCkgPT4ge1xuXHRcdFx0YWJvcnRDb250ZXh0U2lnbmFsKHRlc3QuY29udGV4dCwgZXJyb3IpO1xuXHRcdFx0bWFya1BlbmRpbmdUYXNrc0FzU2tpcHBlZCh0ZXN0LmZpbGUsIHJ1bm5lciwgZXJyb3IubWVzc2FnZSk7XG5cdFx0fSk7XG5cdFx0cmV0dXJuIGNhbmNlbD8uKHJlYXNvbik7XG5cdH07XG5cdGlmICghd29ya2VyUnVubmVycy5oYXMocnVubmVyKSkge1xuXHRcdHJ1bm5lci5vbkNsZWFudXBXb3JrZXJDb250ZXh0Py4oYXN5bmMgKCkgPT4ge1xuXHRcdFx0YXdhaXQgUHJvbWlzZS5hbGwoWy4uLlRlc3RGaXh0dXJlcy5nZXRXb3JrZXJDb250ZXh0cygpXS5tYXAoKGNvbnRleHQpID0+IGNhbGxGaXh0dXJlQ2xlYW51cChjb250ZXh0KSkpLmZpbmFsbHkoKCkgPT4ge1xuXHRcdFx0XHRUZXN0Rml4dHVyZXMuY2xlYXJEZWZpbml0aW9ucygpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cdFx0d29ya2VyUnVubmVycy5hZGQocnVubmVyKTtcblx0fVxuXHR0cnkge1xuXHRcdGNvbnN0IHBhdGhzID0gc3BlY3MubWFwKChmKSA9PiB0eXBlb2YgZiA9PT0gXCJzdHJpbmdcIiA/IGYgOiBmLmZpbGVwYXRoKTtcblx0XHRhd2FpdCBydW5uZXIub25CZWZvcmVDb2xsZWN0Py4ocGF0aHMpO1xuXHRcdGNvbnN0IGZpbGVzID0gYXdhaXQgY29sbGVjdFRlc3RzKHNwZWNzLCBydW5uZXIpO1xuXHRcdGF3YWl0IHJ1bm5lci5vbkNvbGxlY3RlZD8uKGZpbGVzKTtcblx0XHRhd2FpdCBydW5uZXIub25CZWZvcmVSdW5GaWxlcz8uKGZpbGVzKTtcblx0XHRhd2FpdCBydW5GaWxlcyhmaWxlcywgcnVubmVyKTtcblx0XHRhd2FpdCBydW5uZXIub25BZnRlclJ1bkZpbGVzPy4oZmlsZXMpO1xuXHRcdGF3YWl0IGZpbmlzaFNlbmRUYXNrc1VwZGF0ZShydW5uZXIpO1xuXHRcdHJldHVybiBmaWxlcztcblx0fSBmaW5hbGx5IHtcblx0XHRydW5uZXIuY2FuY2VsID0gY2FuY2VsO1xuXHR9XG59XG5hc3luYyBmdW5jdGlvbiBwdWJsaWNDb2xsZWN0KHNwZWNzLCBydW5uZXIpIHtcblx0cnVubmVyLnRyYWNlID8/PSBkZWZhdWx0VHJhY2U7XG5cdGNvbnN0IHBhdGhzID0gc3BlY3MubWFwKChmKSA9PiB0eXBlb2YgZiA9PT0gXCJzdHJpbmdcIiA/IGYgOiBmLmZpbGVwYXRoKTtcblx0YXdhaXQgcnVubmVyLm9uQmVmb3JlQ29sbGVjdD8uKHBhdGhzKTtcblx0Y29uc3QgZmlsZXMgPSBhd2FpdCBjb2xsZWN0VGVzdHMoc3BlY3MsIHJ1bm5lcik7XG5cdGF3YWl0IHJ1bm5lci5vbkNvbGxlY3RlZD8uKGZpbGVzKTtcblx0cmV0dXJuIGZpbGVzO1xufVxuXG4vKipcbiogQGV4cGVyaW1lbnRhbFxuKiBAYWR2YW5jZWRcbipcbiogUmVjb3JkcyBhIGN1c3RvbSB0ZXN0IGFydGlmYWN0IGR1cmluZyB0ZXN0IGV4ZWN1dGlvbi5cbipcbiogVGhpcyBmdW5jdGlvbiBhbGxvd3MgeW91IHRvIGF0dGFjaCBzdHJ1Y3R1cmVkIGRhdGEsIGZpbGVzLCBvciBtZXRhZGF0YSB0byBhIHRlc3QuXG4qXG4qIFZpdGVzdCBhdXRvbWF0aWNhbGx5IGluamVjdHMgdGhlIHNvdXJjZSBsb2NhdGlvbiB3aGVyZSB0aGUgYXJ0aWZhY3Qgd2FzIGNyZWF0ZWQgYW5kIG1hbmFnZXMgYW55IGF0dGFjaG1lbnRzIHlvdSBpbmNsdWRlLlxuKlxuKiAqKk5vdGU6KiogYXJ0aWZhY3RzIG11c3QgYmUgcmVjb3JkZWQgYmVmb3JlIHRoZSB0YXNrIGlzIHJlcG9ydGVkLiBBbnkgYXJ0aWZhY3RzIHJlY29yZGVkIGFmdGVyIHRoYXQgd2lsbCBub3QgYmUgaW5jbHVkZWQgaW4gdGhlIHRhc2suXG4qXG4qIEBwYXJhbSB0YXNrIC0gVGhlIHRlc3QgdGFzayBjb250ZXh0LCB0eXBpY2FsbHkgYWNjZXNzZWQgdmlhIGB0aGlzLnRhc2tgIGluIGN1c3RvbSBtYXRjaGVycyBvciBgY29udGV4dC50YXNrYCBpbiB0ZXN0c1xuKiBAcGFyYW0gYXJ0aWZhY3QgLSBUaGUgYXJ0aWZhY3QgdG8gcmVjb3JkLiBNdXN0IGV4dGVuZCB7QGxpbmtjb2RlIFRlc3RBcnRpZmFjdEJhc2V9XG4qXG4qIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSByZWNvcmRlZCBhcnRpZmFjdCB3aXRoIGxvY2F0aW9uIGluamVjdGVkXG4qXG4qIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgdGVzdCBydW5uZXIgZG9lc24ndCBzdXBwb3J0IGFydGlmYWN0c1xuKlxuKiBAZXhhbXBsZVxuKiBgYGB0c1xuKiAvLyBJbiBhIGN1c3RvbSBhc3NlcnRpb25cbiogYXN5bmMgZnVuY3Rpb24gdG9IYXZlVmFsaWRTY2hlbWEodGhpczogTWF0Y2hlclN0YXRlLCBhY3R1YWw6IHVua25vd24pIHtcbiogICBjb25zdCB2YWxpZGF0aW9uID0gdmFsaWRhdGVTY2hlbWEoYWN0dWFsKVxuKlxuKiAgIGF3YWl0IHJlY29yZEFydGlmYWN0KHRoaXMudGFzaywge1xuKiAgICAgdHlwZTogJ215LXBsdWdpbjpzY2hlbWEtdmFsaWRhdGlvbicsXG4qICAgICBwYXNzZWQ6IHZhbGlkYXRpb24udmFsaWQsXG4qICAgICBlcnJvcnM6IHZhbGlkYXRpb24uZXJyb3JzLFxuKiAgIH0pXG4qXG4qICAgcmV0dXJuIHsgcGFzczogdmFsaWRhdGlvbi52YWxpZCwgbWVzc2FnZTogKCkgPT4gJy4uLicgfVxuKiB9XG4qIGBgYFxuKi9cbmFzeW5jIGZ1bmN0aW9uIHJlY29yZEFydGlmYWN0KHRhc2ssIGFydGlmYWN0KSB7XG5cdGNvbnN0IHJ1bm5lciA9IGdldFJ1bm5lcigpO1xuXHRjb25zdCBzdGFjayA9IGZpbmRUZXN0RmlsZVN0YWNrVHJhY2UodGFzay5maWxlLmZpbGVwYXRoLCBuZXcgRXJyb3IoXCJTVEFDS19UUkFDRVwiKS5zdGFjayk7XG5cdGlmIChzdGFjaykge1xuXHRcdGFydGlmYWN0LmxvY2F0aW9uID0ge1xuXHRcdFx0ZmlsZTogc3RhY2suZmlsZSxcblx0XHRcdGxpbmU6IHN0YWNrLmxpbmUsXG5cdFx0XHRjb2x1bW46IHN0YWNrLmNvbHVtblxuXHRcdH07XG5cdFx0aWYgKGFydGlmYWN0LnR5cGUgPT09IFwiaW50ZXJuYWw6YW5ub3RhdGlvblwiKSB7XG5cdFx0XHRhcnRpZmFjdC5hbm5vdGF0aW9uLmxvY2F0aW9uID0gYXJ0aWZhY3QubG9jYXRpb247XG5cdFx0fVxuXHR9XG5cdGlmIChBcnJheS5pc0FycmF5KGFydGlmYWN0LmF0dGFjaG1lbnRzKSkge1xuXHRcdGZvciAoY29uc3QgYXR0YWNobWVudCBvZiBhcnRpZmFjdC5hdHRhY2htZW50cykge1xuXHRcdFx0bWFuYWdlQXJ0aWZhY3RBdHRhY2htZW50KGF0dGFjaG1lbnQpO1xuXHRcdH1cblx0fVxuXHQvLyBhbm5vdGF0aW9ucyB3b24ndCByZXNvbHZlIGFzIGFydGlmYWN0cyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgdW50aWwgbmV4dCBtYWpvclxuXHRpZiAoYXJ0aWZhY3QudHlwZSA9PT0gXCJpbnRlcm5hbDphbm5vdGF0aW9uXCIpIHtcblx0XHRyZXR1cm4gYXJ0aWZhY3Q7XG5cdH1cblx0aWYgKCFydW5uZXIub25UZXN0QXJ0aWZhY3RSZWNvcmQpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoYFRlc3QgcnVubmVyIGRvZXNuJ3Qgc3VwcG9ydCB0ZXN0IGFydGlmYWN0cy5gKTtcblx0fVxuXHRhd2FpdCBmaW5pc2hTZW5kVGFza3NVcGRhdGUocnVubmVyKTtcblx0Y29uc3QgcmVzb2x2ZWRBcnRpZmFjdCA9IGF3YWl0IHJ1bm5lci5vblRlc3RBcnRpZmFjdFJlY29yZCh0YXNrLCBhcnRpZmFjdCk7XG5cdHRhc2suYXJ0aWZhY3RzLnB1c2gocmVzb2x2ZWRBcnRpZmFjdCk7XG5cdHJldHVybiByZXNvbHZlZEFydGlmYWN0O1xufVxuY29uc3QgdGFibGUgPSBbXTtcbmZvciAobGV0IGkgPSA2NTsgaSA8IDkxOyBpKyspIHtcblx0dGFibGUucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGkpKTtcbn1cbmZvciAobGV0IGkgPSA5NzsgaSA8IDEyMzsgaSsrKSB7XG5cdHRhYmxlLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShpKSk7XG59XG5mb3IgKGxldCBpID0gMDsgaSA8IDEwOyBpKyspIHtcblx0dGFibGUucHVzaChpLnRvU3RyaW5nKDEwKSk7XG59XG50YWJsZS5wdXNoKFwiK1wiLCBcIi9cIik7XG5mdW5jdGlvbiBlbmNvZGVVaW50OEFycmF5KGJ5dGVzKSB7XG5cdGxldCBiYXNlNjQgPSBcIlwiO1xuXHRjb25zdCBsZW4gPSBieXRlcy5ieXRlTGVuZ3RoO1xuXHRmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSAzKSB7XG5cdFx0aWYgKGxlbiA9PT0gaSArIDEpIHtcblx0XHRcdGNvbnN0IGEgPSAoYnl0ZXNbaV0gJiAyNTIpID4+IDI7XG5cdFx0XHRjb25zdCBiID0gKGJ5dGVzW2ldICYgMykgPDwgNDtcblx0XHRcdGJhc2U2NCArPSB0YWJsZVthXTtcblx0XHRcdGJhc2U2NCArPSB0YWJsZVtiXTtcblx0XHRcdGJhc2U2NCArPSBcIj09XCI7XG5cdFx0fSBlbHNlIGlmIChsZW4gPT09IGkgKyAyKSB7XG5cdFx0XHRjb25zdCBhID0gKGJ5dGVzW2ldICYgMjUyKSA+PiAyO1xuXHRcdFx0Y29uc3QgYiA9IChieXRlc1tpXSAmIDMpIDw8IDQgfCAoYnl0ZXNbaSArIDFdICYgMjQwKSA+PiA0O1xuXHRcdFx0Y29uc3QgYyA9IChieXRlc1tpICsgMV0gJiAxNSkgPDwgMjtcblx0XHRcdGJhc2U2NCArPSB0YWJsZVthXTtcblx0XHRcdGJhc2U2NCArPSB0YWJsZVtiXTtcblx0XHRcdGJhc2U2NCArPSB0YWJsZVtjXTtcblx0XHRcdGJhc2U2NCArPSBcIj1cIjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29uc3QgYSA9IChieXRlc1tpXSAmIDI1MikgPj4gMjtcblx0XHRcdGNvbnN0IGIgPSAoYnl0ZXNbaV0gJiAzKSA8PCA0IHwgKGJ5dGVzW2kgKyAxXSAmIDI0MCkgPj4gNDtcblx0XHRcdGNvbnN0IGMgPSAoYnl0ZXNbaSArIDFdICYgMTUpIDw8IDIgfCAoYnl0ZXNbaSArIDJdICYgMTkyKSA+PiA2O1xuXHRcdFx0Y29uc3QgZCA9IGJ5dGVzW2kgKyAyXSAmIDYzO1xuXHRcdFx0YmFzZTY0ICs9IHRhYmxlW2FdO1xuXHRcdFx0YmFzZTY0ICs9IHRhYmxlW2JdO1xuXHRcdFx0YmFzZTY0ICs9IHRhYmxlW2NdO1xuXHRcdFx0YmFzZTY0ICs9IHRhYmxlW2RdO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gYmFzZTY0O1xufVxuLyoqXG4qIFJlY29yZHMgYW4gYXN5bmMgb3BlcmF0aW9uIGFzc29jaWF0ZWQgd2l0aCBhIHRlc3QgdGFzay5cbipcbiogVGhpcyBmdW5jdGlvbiB0cmFja3MgcHJvbWlzZXMgdGhhdCBzaG91bGQgYmUgYXdhaXRlZCBiZWZvcmUgYSB0ZXN0IGNvbXBsZXRlcy5cbiogVGhlIHByb21pc2UgaXMgYXV0b21hdGljYWxseSByZW1vdmVkIGZyb20gdGhlIHRlc3QncyBwcm9taXNlIGxpc3Qgb25jZSBpdCBzZXR0bGVzLlxuKi9cbmZ1bmN0aW9uIHJlY29yZEFzeW5jT3BlcmF0aW9uKHRlc3QsIHByb21pc2UpIHtcblx0Ly8gaWYgcHJvbWlzZSBpcyBleHBsaWNpdGx5IGF3YWl0ZWQsIHJlbW92ZSBpdCBmcm9tIHRoZSBsaXN0XG5cdHByb21pc2UgPSBwcm9taXNlLmZpbmFsbHkoKCkgPT4ge1xuXHRcdGlmICghdGVzdC5wcm9taXNlcykge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRjb25zdCBpbmRleCA9IHRlc3QucHJvbWlzZXMuaW5kZXhPZihwcm9taXNlKTtcblx0XHRpZiAoaW5kZXggIT09IC0xKSB7XG5cdFx0XHR0ZXN0LnByb21pc2VzLnNwbGljZShpbmRleCwgMSk7XG5cdFx0fVxuXHR9KTtcblx0Ly8gcmVjb3JkIHByb21pc2Vcblx0aWYgKCF0ZXN0LnByb21pc2VzKSB7XG5cdFx0dGVzdC5wcm9taXNlcyA9IFtdO1xuXHR9XG5cdHRlc3QucHJvbWlzZXMucHVzaChwcm9taXNlKTtcblx0cmV0dXJuIHByb21pc2U7XG59XG4vKipcbiogVmFsaWRhdGVzIGFuZCBwcmVwYXJlcyBhIHRlc3QgYXR0YWNobWVudCBmb3Igc2VyaWFsaXphdGlvbi5cbipcbiogVGhpcyBmdW5jdGlvbiBlbnN1cmVzIGF0dGFjaG1lbnRzIGhhdmUgZWl0aGVyIGBib2R5YCBvciBgcGF0aGAgc2V0IChidXQgbm90IGJvdGgpLCBhbmQgY29udmVydHMgYFVpbnQ4QXJyYXlgIGJvZGllcyB0byBiYXNlNjQtZW5jb2RlZCBzdHJpbmdzIGZvciBlYXNpZXIgc2VyaWFsaXphdGlvbi5cbipcbiogQHBhcmFtIGF0dGFjaG1lbnQgLSBUaGUgYXR0YWNobWVudCB0byB2YWxpZGF0ZSBhbmQgcHJlcGFyZVxuKlxuKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIG5laXRoZXIgYGJvZHlgIG5vciBgcGF0aGAgaXMgcHJvdmlkZWRcbiogQHRocm93cyB7VHlwZUVycm9yfSBJZiBib3RoIGBib2R5YCBhbmQgYHBhdGhgIGFyZSBwcm92aWRlZFxuKi9cbmZ1bmN0aW9uIG1hbmFnZUFydGlmYWN0QXR0YWNobWVudChhdHRhY2htZW50KSB7XG5cdGlmIChhdHRhY2htZW50LmJvZHkgPT0gbnVsbCAmJiAhYXR0YWNobWVudC5wYXRoKSB7XG5cdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgVGVzdCBhdHRhY2htZW50IHJlcXVpcmVzIFwiYm9keVwiIG9yIFwicGF0aFwiIHRvIGJlIHNldC4gQm90aCBhcmUgbWlzc2luZy5gKTtcblx0fVxuXHRpZiAoYXR0YWNobWVudC5ib2R5ICYmIGF0dGFjaG1lbnQucGF0aCkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoYFRlc3QgYXR0YWNobWVudCByZXF1aXJlcyBvbmx5IG9uZSBvZiBcImJvZHlcIiBvciBcInBhdGhcIiB0byBiZSBzZXQuIEJvdGggYXJlIHNwZWNpZmllZC5gKTtcblx0fVxuXHRpZiAoYXR0YWNobWVudC5wYXRoICYmIGF0dGFjaG1lbnQuYm9keUVuY29kaW5nKSB7XG5cdFx0dGhyb3cgbmV3IFR5cGVFcnJvcihgVGVzdCBhdHRhY2htZW50IHdpdGggXCJwYXRoXCIgc2hvdWxkIG5vdCBoYXZlIFwiYm9keUVuY29kaW5nXCIgc3BlY2lmaWVkLmApO1xuXHR9XG5cdC8vIGNvbnZlcnQgdG8gYSBzdHJpbmcgc28gaXQncyBlYXNpZXIgdG8gc2VyaWFsaXNlXG5cdGlmIChhdHRhY2htZW50LmJvZHkgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG5cdFx0YXR0YWNobWVudC5ib2R5ID0gZW5jb2RlVWludDhBcnJheShhdHRhY2htZW50LmJvZHkpO1xuXHR9XG5cdGlmIChhdHRhY2htZW50LmJvZHkgIT0gbnVsbCkge1xuXHRcdGF0dGFjaG1lbnQuYm9keUVuY29kaW5nID8/PSBcImJhc2U2NFwiO1xuXHR9XG59XG5cbmV4cG9ydCB7IGNyZWF0ZVRhZ3NGaWx0ZXIgYXMgQSwgY3JlYXRlVGFza05hbWUgYXMgQiwgZmluZFRlc3RGaWxlU3RhY2tUcmFjZSBhcyBDLCBnZW5lcmF0ZUZpbGVIYXNoIGFzIEQsIGdlbmVyYXRlSGFzaCBhcyBFLCBnZXRGdWxsTmFtZSBhcyBGLCBnZXROYW1lcyBhcyBHLCBnZXRTdWl0ZXMgYXMgSCwgZ2V0VGFza3MgYXMgSSwgZ2V0VGVzdE5hbWUgYXMgSiwgZ2V0VGVzdHMgYXMgSywgaGFzRmFpbGVkIGFzIEwsIGhhc1Rlc3RzIGFzIE0sIGludGVycHJldFRhc2tNb2RlcyBhcyBOLCBpc1Rlc3RDYXNlIGFzIE8sIGxpbWl0Q29uY3VycmVuY3kgYXMgUCwgbWF0Y2hlc1RhZ3MgYXMgUSwgcGFydGl0aW9uU3VpdGVDaGlsZHJlbiBhcyBSLCBzb21lVGFza3NBcmVPbmx5IGFzIFMsIHZhbGlkYXRlVGFncyBhcyBULCBhZnRlckFsbCBhcyBhLCBhZnRlckVhY2ggYXMgYiwgYXJvdW5kQWxsIGFzIGMsIGFyb3VuZEVhY2ggYXMgZCwgYmVmb3JlQWxsIGFzIGUsIGJlZm9yZUVhY2ggYXMgZiwgY3JlYXRlVGFza0NvbGxlY3RvciBhcyBnLCBkZXNjcmliZSBhcyBoLCBnZXRDdXJyZW50U3VpdGUgYXMgaSwgZ2V0Q3VycmVudFRlc3QgYXMgaiwgZ2V0Rm4gYXMgaywgZ2V0SG9va3MgYXMgbCwgaXQgYXMgbSwgb25UZXN0RmluaXNoZWQgYXMgbiwgb25UZXN0RmFpbGVkIGFzIG8sIHB1YmxpY0NvbGxlY3QgYXMgcCwgc2V0SG9va3MgYXMgcSwgcmVjb3JkQXJ0aWZhY3QgYXMgciwgc2V0Rm4gYXMgcywgc3RhcnRUZXN0cyBhcyB0LCBzdWl0ZSBhcyB1LCB0ZXN0IGFzIHYsIHVwZGF0ZVRhc2sgYXMgdywgY2FsY3VsYXRlU3VpdGVIYXNoIGFzIHgsIGNyZWF0ZUNoYWluYWJsZSBhcyB5LCBjcmVhdGVGaWxlVGFzayBhcyB6IH07XG4iXSwieF9nb29nbGVfaWdub3JlTGlzdCI6WzBdLCJtYXBwaW5n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