@alpsckr/unitycli 0.4.2 → 0.4.4
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.
- package/README.md +5 -5
- package/contracts/command-contract.json +109 -217
- package/contracts/package-files.json +374 -294
- package/contracts/stable-session/direct-call-semantics.json +8 -2
- package/contracts/tool-completion-contract.json +148 -672
- package/dist/bridge/admission.d.ts +17 -1
- package/dist/bridge/admission.js +2 -0
- package/dist/bridge/admission.js.map +1 -1
- package/dist/bridge/domains/asset.js +3 -1
- package/dist/bridge/domains/asset.js.map +1 -1
- package/dist/bridge/domains/camera.js +39 -7
- package/dist/bridge/domains/camera.js.map +1 -1
- package/dist/bridge/domains/console.js +2 -1
- package/dist/bridge/domains/console.js.map +1 -1
- package/dist/bridge/domains/doctor.d.ts +3 -0
- package/dist/bridge/domains/doctor.js +8 -0
- package/dist/bridge/domains/doctor.js.map +1 -0
- package/dist/bridge/domains/editor.js +0 -4
- package/dist/bridge/domains/editor.js.map +1 -1
- package/dist/bridge/domains/game-object.js +4 -12
- package/dist/bridge/domains/game-object.js.map +1 -1
- package/dist/bridge/domains/graphics.js +1 -16
- package/dist/bridge/domains/graphics.js.map +1 -1
- package/dist/bridge/domains/object.js +3 -0
- package/dist/bridge/domains/object.js.map +1 -1
- package/dist/bridge/domains/physics.js +1 -2
- package/dist/bridge/domains/physics.js.map +1 -1
- package/dist/bridge/domains/profiler.js +18 -7
- package/dist/bridge/domains/profiler.js.map +1 -1
- package/dist/bridge/domains/project-tool.js +4 -0
- package/dist/bridge/domains/project-tool.js.map +1 -1
- package/dist/bridge/domains/reflection.js +10 -2
- package/dist/bridge/domains/reflection.js.map +1 -1
- package/dist/bridge/domains/runtime-tool.js +3 -0
- package/dist/bridge/domains/runtime-tool.js.map +1 -1
- package/dist/bridge/domains/scene.js +3 -8
- package/dist/bridge/domains/scene.js.map +1 -1
- package/dist/bridge/domains/screenshot.js +30 -6
- package/dist/bridge/domains/screenshot.js.map +1 -1
- package/dist/bridge/domains/ui.js +3 -1
- package/dist/bridge/domains/ui.js.map +1 -1
- package/dist/bridge/index.d.ts +5 -5
- package/dist/bridge/index.js +6 -9
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/registry.js +3 -5
- package/dist/bridge/registry.js.map +1 -1
- package/dist/bridge/session-supervisor.d.ts +6 -3
- package/dist/bridge/session-supervisor.js +122 -34
- package/dist/bridge/session-supervisor.js.map +1 -1
- package/dist/bridge/types.d.ts +6 -5
- package/dist/bridge/types.js +16 -2
- package/dist/bridge/types.js.map +1 -1
- package/dist/catalog-protocol.d.ts +64 -0
- package/dist/catalog-protocol.js +460 -0
- package/dist/catalog-protocol.js.map +1 -0
- package/dist/cli-commands/command.js +84 -61
- package/dist/cli-commands/command.js.map +1 -1
- package/dist/cli-commands/extensions.js +70 -50
- package/dist/cli-commands/extensions.js.map +1 -1
- package/dist/cli-commands/instances.js +1 -1
- package/dist/cli-commands/instances.js.map +1 -1
- package/dist/cli-process-owners.d.ts +6 -0
- package/dist/cli-process-owners.js +27 -0
- package/dist/cli-process-owners.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +20 -5
- package/dist/cli.js.map +1 -1
- package/dist/contracts/command-contract.js +14 -4
- package/dist/contracts/command-contract.js.map +1 -1
- package/dist/doctor.d.ts +4 -6
- package/dist/doctor.js +429 -398
- package/dist/doctor.js.map +1 -1
- package/dist/editor-blocker-observer.d.ts +2 -1
- package/dist/editor-blocker-observer.js +40 -13
- package/dist/editor-blocker-observer.js.map +1 -1
- package/dist/extension-availability.d.ts +27 -9
- package/dist/extension-availability.js +96 -56
- package/dist/extension-availability.js.map +1 -1
- package/dist/extensions/descriptor-loader.d.ts +2 -2
- package/dist/extensions/descriptor-loader.js +3 -4
- package/dist/extensions/descriptor-loader.js.map +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.js +1 -1
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/installer.d.ts +24 -7
- package/dist/extensions/installer.js +142 -66
- package/dist/extensions/installer.js.map +1 -1
- package/dist/extensions/registry.js +3 -5
- package/dist/extensions/registry.js.map +1 -1
- package/dist/extensions/state-contract.d.ts +11 -0
- package/dist/extensions/state-contract.js +50 -0
- package/dist/extensions/state-contract.js.map +1 -0
- package/dist/instances.d.ts +13 -1
- package/dist/instances.js +26 -0
- package/dist/instances.js.map +1 -1
- package/dist/package-manager.d.ts +0 -24
- package/dist/package-manager.js +5 -58
- package/dist/package-manager.js.map +1 -1
- package/dist/project-tool-discovery.d.ts +5 -2
- package/dist/project-tool-discovery.js +22 -18
- package/dist/project-tool-discovery.js.map +1 -1
- package/dist/runtime-code.js +1 -1
- package/dist/runtime-code.js.map +1 -1
- package/dist/tool-name.d.ts +4 -0
- package/dist/tool-name.js +15 -0
- package/dist/tool-name.js.map +1 -0
- package/dist/tools/.generated-completion-registry.d.ts +2 -0
- package/dist/tools/.generated-completion-registry.js +763 -325
- package/dist/tools/.generated-completion-registry.js.map +1 -1
- package/dist/tools/.generated-registry.d.ts +6 -11
- package/dist/tools/.generated-registry.js +6 -11
- package/dist/tools/.generated-registry.js.map +1 -1
- package/dist/tools/.generated-schemas.js +11 -16
- package/dist/tools/.generated-schemas.js.map +1 -1
- package/dist/tools/asset/refresh-status.d.ts +3 -0
- package/dist/tools/asset/refresh-status.js +12 -0
- package/dist/tools/asset/refresh-status.js.map +1 -0
- package/dist/tools/asset/refresh.js +7 -3
- package/dist/tools/asset/refresh.js.map +1 -1
- package/dist/tools/build/player-status.d.ts +3 -0
- package/dist/tools/build/player-status.js +12 -0
- package/dist/tools/build/player-status.js.map +1 -0
- package/dist/tools/build/run.js +1 -1
- package/dist/tools/build/run.js.map +1 -1
- package/dist/tools/catalog-control.d.ts +22 -0
- package/dist/tools/catalog-control.js +335 -0
- package/dist/tools/catalog-control.js.map +1 -0
- package/dist/tools/catalog.d.ts +7 -9
- package/dist/tools/catalog.js +66 -45
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/commands.d.ts +1 -1
- package/dist/tools/commands.js +44 -11
- package/dist/tools/commands.js.map +1 -1
- package/dist/tools/define.js +3 -2
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/dispatcher.d.ts +53 -6
- package/dist/tools/dispatcher.js +277 -108
- package/dist/tools/dispatcher.js.map +1 -1
- package/dist/tools/editor/compile.js +1 -1
- package/dist/tools/editor/compile.js.map +1 -1
- package/dist/tools/editor/play-mode-status.d.ts +3 -0
- package/dist/tools/editor/play-mode-status.js +12 -0
- package/dist/tools/editor/play-mode-status.js.map +1 -0
- package/dist/tools/editor/readiness.d.ts +0 -1
- package/dist/tools/editor/readiness.js +0 -1
- package/dist/tools/editor/readiness.js.map +1 -1
- package/dist/tools/editor/refresh.d.ts +7 -3
- package/dist/tools/editor/refresh.js +20 -15
- package/dist/tools/editor/refresh.js.map +1 -1
- package/dist/tools/editor/state.d.ts +2 -2
- package/dist/tools/editor/state.js +13 -12
- package/dist/tools/editor/state.js.map +1 -1
- package/dist/tools/metadata/derived.js +1 -7
- package/dist/tools/metadata/derived.js.map +1 -1
- package/dist/tools/metadata/status.js +1 -12
- package/dist/tools/metadata/status.js.map +1 -1
- package/dist/tools/metadata/types.d.ts +0 -2
- package/dist/tools/navmesh/live.js +1 -1
- package/dist/tools/navmesh/live.js.map +1 -1
- package/dist/tools/occlusion/live.js +1 -1
- package/dist/tools/occlusion/live.js.map +1 -1
- package/dist/tools/package/deploy.js +2 -2
- package/dist/tools/package/deploy.js.map +1 -1
- package/dist/tools/package/embed.js +1 -1
- package/dist/tools/package/embed.js.map +1 -1
- package/dist/tools/package/install-status.d.ts +3 -0
- package/dist/tools/package/install-status.js +12 -0
- package/dist/tools/package/install-status.js.map +1 -0
- package/dist/tools/package/install.js +3 -3
- package/dist/tools/package/install.js.map +1 -1
- package/dist/tools/package/live-resolve.js +45 -12
- package/dist/tools/package/live-resolve.js.map +1 -1
- package/dist/tools/package/registry-clear.js.map +1 -1
- package/dist/tools/package/registry-set.js.map +1 -1
- package/dist/tools/package/remove-status.d.ts +3 -0
- package/dist/tools/package/remove-status.js +12 -0
- package/dist/tools/package/remove-status.js.map +1 -0
- package/dist/tools/package/remove.js +3 -3
- package/dist/tools/package/remove.js.map +1 -1
- package/dist/tools/package/resolve.js +3 -3
- package/dist/tools/package/resolve.js.map +1 -1
- package/dist/tools/package/restore.js +2 -2
- package/dist/tools/package/restore.js.map +1 -1
- package/dist/tools/package/scoped-registry-add.js.map +1 -1
- package/dist/tools/status/support.d.ts +13 -0
- package/dist/tools/status/support.js +28 -0
- package/dist/tools/status/support.js.map +1 -0
- package/dist/tools/test/cancel.js +2 -2
- package/dist/tools/test/cancel.js.map +1 -1
- package/dist/tools/test/run-status.d.ts +3 -0
- package/dist/tools/test/run-status.js +12 -0
- package/dist/tools/test/run-status.js.map +1 -0
- package/dist/tools/test/run.js +7 -4
- package/dist/tools/test/run.js.map +1 -1
- package/dist/tools/tools/group-summaries.js +10 -14
- package/dist/tools/tools/group-summaries.js.map +1 -1
- package/docs/architecture.md +4 -4
- package/docs/availability-differences.md +4 -4
- package/docs/command-execution.md +4 -3
- package/docs/error-codes.md +13 -5
- package/docs/extensions.md +1 -7
- package/docs/risk-and-side-effects.md +4 -3
- package/docs/safety-boundaries.md +3 -1
- package/docs/target-and-instance.md +1 -1
- package/docs/tool-discovery.md +17 -10
- package/docs/tool-execution.md +18 -7
- package/extensions/cinemachine/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/hdrp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/probuilder/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/urp/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/extensions/vfx-graph/unitypkg/Editor/UnityCliExtensionAssembly.cs +3 -0
- package/package.json +2 -4
- package/skills/unitycli/SKILL.md +35 -42
- package/skills/unitycli/manifest.json +1 -1
- package/skills/unitycli/references/operation-protocol.md +3 -3
- package/unitypkg/Editor/AssemblyInfo.cs +5 -0
- package/unitypkg/Editor/Bridge/BridgeCommandRegistry.cs +49 -14
- package/unitypkg/Editor/Bridge/BridgeHttpServer.cs +9 -35
- package/unitypkg/Editor/Bridge/BridgeQueueState.cs +672 -0
- package/unitypkg/Editor/Bridge/BridgeWorkQueue.cs +970 -120
- package/unitypkg/Editor/BridgeStartupStateMachine.cs +59 -1
- package/unitypkg/Editor/Commands/ProjectToolCommands.cs +4 -0
- package/unitypkg/Editor/Commands/RuntimeToolCommands.cs +3 -0
- package/unitypkg/Editor/Generated/UnityCliToolCompletionRegistry.g.cs +379 -14
- package/unitypkg/Editor/Infrastructure/CodeExecSupport.cs +28 -13
- package/unitypkg/Editor/Infrastructure/RegistryOwnershipResolver.cs +132 -105
- package/unitypkg/Editor/Infrastructure/UnityCliActiveOperation.cs +138 -29
- package/unitypkg/Editor/Infrastructure/UnityCliAdmission.cs +1856 -237
- package/unitypkg/Editor/Infrastructure/UnityCliDoctorDiagnostics.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliDurableStatusCoordinator.cs +118 -0
- package/unitypkg/Editor/Infrastructure/UnityCliEditorStateSnapshot.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliHierarchyPager.cs +203 -0
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceCleanup.cs +2 -1
- package/unitypkg/Editor/Infrastructure/UnityCliInstanceRegistry.cs +201 -63
- package/unitypkg/Editor/Infrastructure/UnityCliJson.cs +2 -3
- package/unitypkg/Editor/Infrastructure/UnityCliLiveBuildCoordinator.cs +289 -46
- package/unitypkg/Editor/Infrastructure/UnityCliLiveRefreshCoordinator.cs +87 -53
- package/unitypkg/Editor/Infrastructure/UnityCliNavMeshBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliObjectRef.cs +128 -25
- package/unitypkg/Editor/Infrastructure/UnityCliObjectSerializer.cs +435 -327
- package/unitypkg/Editor/Infrastructure/UnityCliOcclusionBakeCoordinator.cs +4 -4
- package/unitypkg/Editor/Infrastructure/UnityCliOperationCoordinator.cs +351 -53
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveCoordinator.cs +118 -18
- package/unitypkg/Editor/Infrastructure/UnityCliPackageResolveState.cs +20 -1
- package/unitypkg/Editor/Infrastructure/UnityCliReadGeneration.cs +97 -0
- package/unitypkg/Editor/Infrastructure/UnityCliReflection.cs +644 -133
- package/unitypkg/Editor/Infrastructure/UnityCliReloadOperation.cs +128 -41
- package/unitypkg/Editor/Infrastructure/UnityCliRuntimeExecutor.cs +14 -84
- package/unitypkg/Editor/Infrastructure/UnityCliSerializer.cs +220 -0
- package/unitypkg/Editor/Infrastructure/UnityCliSessionMutationLease.cs +69 -29
- package/unitypkg/Editor/Infrastructure/UnityCliTestRunCoordinator.cs +440 -54
- package/unitypkg/Editor/Infrastructure/UnityCliWaiter.cs +128 -35
- package/unitypkg/Editor/ProjectTools/IUnityCliTool.cs +9 -1
- package/unitypkg/Editor/ProjectTools/OfficialAttributeToolRegistry.cs +32 -31
- package/unitypkg/Editor/ProjectTools/ProjectToolRegistry.cs +607 -458
- package/unitypkg/Editor/ProjectTools/ProjectToolSchemaValidator.cs +35 -7
- package/unitypkg/Editor/ProjectTools/RegisteredTool.cs +501 -60
- package/unitypkg/Editor/ProjectTools/UnityCliProjectToolContext.cs +21 -0
- package/unitypkg/Editor/ProjectTools/UnityCliSchemaDeriver.cs +36 -7
- package/unitypkg/Editor/ProjectTools/UnityCliToolName.cs +30 -0
- package/unitypkg/Editor/Properties/AssemblyInfo.cs +3 -0
- package/unitypkg/Editor/Tools/asset/get-data.cs +16 -7
- package/unitypkg/Editor/Tools/build/BuildSceneStateTool.cs +23 -3
- package/unitypkg/Editor/Tools/build/BuildToolDtos.cs +2 -1
- package/unitypkg/Editor/Tools/build/scene/add.cs +6 -3
- package/unitypkg/Editor/Tools/build/scene/disable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/enable.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/list.cs +1 -1
- package/unitypkg/Editor/Tools/build/scene/remove.cs +13 -3
- package/unitypkg/Editor/Tools/camera/CameraToolSupport.cs +38 -38
- package/unitypkg/Editor/Tools/camera/multiview.cs +13 -6
- package/unitypkg/Editor/Tools/camera/screenshot.cs +14 -7
- package/unitypkg/Editor/Tools/component/get.cs +16 -9
- package/unitypkg/Editor/Tools/component/modify.cs +6 -4
- package/unitypkg/Editor/Tools/console/clear.cs +7 -6
- package/unitypkg/Editor/Tools/console/get.cs +48 -16
- package/unitypkg/Editor/Tools/editor/EditorToolSupport.cs +143 -28
- package/unitypkg/Editor/Tools/editor/menu-items.cs +1 -1
- package/unitypkg/Editor/Tools/editor/play.cs +2 -11
- package/unitypkg/Editor/Tools/editor/selection.cs +1 -1
- package/unitypkg/Editor/Tools/editor/stop.cs +2 -11
- package/unitypkg/Editor/Tools/editor/windows.cs +1 -1
- package/unitypkg/Editor/Tools/go/GameObjectToolSupport.cs +54 -4
- package/unitypkg/Editor/Tools/go/delete.cs +1 -1
- package/unitypkg/Editor/Tools/go/find.cs +167 -70
- package/unitypkg/Editor/Tools/graphics/GraphicsToolSupport.cs +25 -0
- package/unitypkg/Editor/Tools/graphics/light-probe-group.cs +9 -3
- package/unitypkg/Editor/Tools/graphics/pipeline-info.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/pipeline-settings.cs +1 -1
- package/unitypkg/Editor/Tools/graphics/quality.cs +2 -2
- package/unitypkg/Editor/Tools/graphics/reflection-probe.cs +3 -3
- package/unitypkg/Editor/Tools/graphics/stats.cs +1 -1
- package/unitypkg/Editor/Tools/object/ObjectToolSupport.cs +4 -4
- package/unitypkg/Editor/Tools/object/get-data.cs +9 -7
- package/unitypkg/Editor/Tools/object/modify.cs +7 -5
- package/unitypkg/Editor/Tools/physics/raycast.cs +24 -6
- package/unitypkg/Editor/Tools/prefab/stage.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/ProfilerFrameDebuggerSupport.cs +94 -21
- package/unitypkg/Editor/Tools/profiler/ProfilerMemorySnapshotSupport.cs +397 -10
- package/unitypkg/Editor/Tools/profiler/ProfilerToolSupport.cs +18 -4
- package/unitypkg/Editor/Tools/profiler/frame-debugger/enable.cs +1 -1
- package/unitypkg/Editor/Tools/profiler/frame-debugger/events.cs +88 -87
- package/unitypkg/Editor/Tools/profiler/hierarchy.cs +278 -112
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/compare.cs +9 -5
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/list.cs +37 -35
- package/unitypkg/Editor/Tools/profiler/memory-snapshot/take.cs +99 -97
- package/unitypkg/Editor/Tools/project/info.cs +1 -1
- package/unitypkg/Editor/Tools/project/layers.cs +1 -1
- package/unitypkg/Editor/Tools/project/tags.cs +1 -1
- package/unitypkg/Editor/Tools/reflection/method/call.cs +9 -7
- package/unitypkg/Editor/Tools/reflection/method/find.cs +27 -37
- package/unitypkg/Editor/Tools/reflection/type/schema.cs +24 -28
- package/unitypkg/Editor/Tools/scene/gameobject/component.cs +8 -5
- package/unitypkg/Editor/Tools/scene/gameobject/components.cs +10 -7
- package/unitypkg/Editor/Tools/scene/gameobject-support.cs +104 -8
- package/unitypkg/Editor/Tools/scene/gameobject.cs +37 -16
- package/unitypkg/Editor/Tools/scene/hierarchy.cs +146 -142
- package/unitypkg/Editor/Tools/screenshot/EditorElementCaptureToolSupport.cs +77 -25
- package/unitypkg/Editor/Tools/screenshot/ScreenshotToolSupport.cs +315 -95
- package/unitypkg/Editor/Tools/screenshot/editor-element.cs +7 -5
- package/unitypkg/Editor/Tools/screenshot/game-view.cs +35 -21
- package/unitypkg/Editor/Tools/screenshot/isolated-object.cs +29 -23
- package/unitypkg/Editor/Tools/screenshot/orbit.cs +37 -25
- package/unitypkg/Editor/Tools/screenshot/scene-view.cs +25 -18
- package/unitypkg/Editor/Tools/screenshot/screen.cs +177 -17
- package/unitypkg/Editor/Tools/screenshot/surround.cs +83 -79
- package/unitypkg/Editor/Tools/ui/render-preview.cs +16 -11
- package/unitypkg/Editor/UnityCliBridge.cs +97 -34
- package/unitypkg/Runtime/Infrastructure/UnityCliRuntimeBridge.cs +753 -122
- package/unitypkg/Runtime/Properties/AssemblyInfo.cs +5 -0
- package/unitypkg/Runtime/UnityCli.Runtime.asmdef +1 -1
- package/unitypkg/Shared/AssemblyInfo.cs +4 -0
- package/unitypkg/Shared/UnityCliAdmissionPool.cs +265 -75
- package/unitypkg/Shared/UnityCliBridgeQueuePolicy.cs +410 -0
- package/unitypkg/Shared/UnityCliBridgeWorkItemState.cs +47 -0
- package/unitypkg/Shared/UnityCliExceptionProjection.cs +151 -0
- package/unitypkg/Shared/UnityCliQueuePublication.cs +30 -0
- package/unitypkg/Shared/UnityCliRequestBudget.cs +352 -0
- package/unitypkg/Shared/UnityCliRuntimeRequestPublication.cs +107 -0
- package/unitypkg/Tests/Editor/UnityCli.Editor.Tests.asmdef +2 -2
- package/unitypkg/Tests/Editor/UnityCliAdmissionCoordinatorIntegrationTests.cs +1329 -0
- package/unitypkg/Tests/Editor/UnityCliAdmissionPoolTests.cs +311 -114
- package/unitypkg/Tests/Editor/UnityCliAdmissionRepairStateTests.cs +94 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeAdmissionIntegrationTests.cs +1229 -0
- package/unitypkg/Tests/Editor/UnityCliBridgeQueuePolicyTests.cs +412 -0
- package/unitypkg/Tests/Editor/UnityCliContinuationIntegrationTests.cs +292 -0
- package/unitypkg/Tests/Editor/UnityCliDiagnosticBoundaryTests.cs +120 -0
- package/unitypkg/Tests/Editor/UnityCliDurableStatusTests.cs +84 -0
- package/unitypkg/Tests/Editor/UnityCliExceptionProjectionTests.cs +72 -0
- package/unitypkg/Tests/Editor/UnityCliInstancePublicationRetryTests.cs +180 -97
- package/unitypkg/Tests/Editor/UnityCliMemoryReflectionIntegrationTests.cs +434 -0
- package/unitypkg/Tests/Editor/UnityCliRequestBudgetTests.cs +615 -0
- package/unitypkg/Tests/Editor/UnityCliRuntimeBridgeIntegrationTests.cs +520 -0
- package/unitypkg/Tests/Editor/UnityCliToolCatalogTests.cs +562 -0
- package/unitypkg/Tests/Runtime/UnityCli.Runtime.Tests.asmdef +23 -0
- package/unitypkg/Tests/Runtime/UnityCliRuntimeCatalogValidationTests.cs +29 -0
- package/unitypkg/package.json +1 -1
- package/contracts/static-capability-catalog.json +0 -48226
- package/dist/bridge/domains/diagnose.d.ts +0 -2
- package/dist/bridge/domains/diagnose.js +0 -11
- package/dist/bridge/domains/diagnose.js.map +0 -1
- package/dist/bridge/domains/extension.d.ts +0 -8
- package/dist/bridge/domains/extension.js +0 -20
- package/dist/bridge/domains/extension.js.map +0 -1
- package/dist/capabilities.d.ts +0 -5
- package/dist/capabilities.js +0 -84
- package/dist/capabilities.js.map +0 -1
- package/dist/static-capability-catalog.d.ts +0 -13
- package/dist/static-capability-catalog.js +0 -41
- package/dist/static-capability-catalog.js.map +0 -1
- package/dist/tools/diagnose/capabilities.d.ts +0 -13
- package/dist/tools/diagnose/capabilities.js +0 -34
- package/dist/tools/diagnose/capabilities.js.map +0 -1
- package/dist/tools/package/info.d.ts +0 -19
- package/dist/tools/package/info.js +0 -27
- package/dist/tools/package/info.js.map +0 -1
- package/dist/tools/package/list.d.ts +0 -27
- package/dist/tools/package/list.js +0 -21
- package/dist/tools/package/list.js.map +0 -1
- package/dist/tools/package/registry-get.d.ts +0 -10
- package/dist/tools/package/registry-get.js +0 -22
- package/dist/tools/package/registry-get.js.map +0 -1
- package/dist/tools/package/scoped-registry-list.d.ts +0 -14
- package/dist/tools/package/scoped-registry-list.js +0 -22
- package/dist/tools/package/scoped-registry-list.js.map +0 -1
- package/dist/tools/package/search.d.ts +0 -17
- package/dist/tools/package/search.js +0 -39
- package/dist/tools/package/search.js.map +0 -1
- package/dist/tools/package/status.d.ts +0 -21
- package/dist/tools/package/status.js +0 -37
- package/dist/tools/package/status.js.map +0 -1
- package/dist/tools/tools/describe.d.ts +0 -27
- package/dist/tools/tools/describe.js +0 -35
- package/dist/tools/tools/describe.js.map +0 -1
- package/dist/tools/tools/group-list.d.ts +0 -16
- package/dist/tools/tools/group-list.js +0 -38
- package/dist/tools/tools/group-list.js.map +0 -1
- package/dist/tools/tools/group.d.ts +0 -13
- package/dist/tools/tools/group.js +0 -34
- package/dist/tools/tools/group.js.map +0 -1
- package/dist/tools/tools/pagination.d.ts +0 -17
- package/dist/tools/tools/pagination.js +0 -28
- package/dist/tools/tools/pagination.js.map +0 -1
- package/dist/tools/tools/search.d.ts +0 -15
- package/dist/tools/tools/search.js +0 -42
- package/dist/tools/tools/search.js.map +0 -1
- package/unitypkg/Editor/Tools/diagnose/preflight.cs +0 -269
- package/unitypkg/Editor/Tools/editor/console.cs +0 -26
- package/unitypkg/Editor/Tools/extension/status.cs +0 -87
- package/unitypkg/Editor/Tools/go/inspect.cs +0 -49
- package/unitypkg/Editor/Tools/graphics/pipeline-quality.cs +0 -24
- package/unitypkg/Editor/Tools/graphics/probe-positions.cs +0 -58
- package/unitypkg/Editor/Tools/graphics/settings.cs +0 -104
- package/unitypkg/Editor/Tools/graphics/stats-counters.cs +0 -28
- package/unitypkg/Editor/Tools/graphics/stats-memory.cs +0 -21
- package/unitypkg/Editor/Tools/instances/list.cs +0 -71
- package/unitypkg/Editor/Tools/physics/raycast-all.cs +0 -67
- package/unitypkg/Editor/Tools/scene/build-settings.cs +0 -69
- package/unitypkg/Editor/Tools/scene/data.cs +0 -125
- package/unitypkg/Editor/Tools/tests/list.cs +0 -98
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Globalization;
|
|
4
|
+
using System.Linq;
|
|
5
|
+
using System.Threading;
|
|
6
|
+
using System.Threading.Tasks;
|
|
7
|
+
using NUnit.Framework;
|
|
8
|
+
using UnityEditor;
|
|
9
|
+
using UnityEditor.SceneManagement;
|
|
10
|
+
using UnityEngine;
|
|
11
|
+
using UnityEngine.SceneManagement;
|
|
12
|
+
|
|
13
|
+
namespace UnityCli.Tests
|
|
14
|
+
{
|
|
15
|
+
public sealed class UnityCliContinuationIntegrationTests
|
|
16
|
+
{
|
|
17
|
+
private const string PrefabFolder = "Assets/UnityCliTests";
|
|
18
|
+
private const string PrefabPath = PrefabFolder + "/issue-042-continuation.prefab";
|
|
19
|
+
|
|
20
|
+
[TearDown]
|
|
21
|
+
public void TearDown()
|
|
22
|
+
{
|
|
23
|
+
FrameDebuggerReflection.ResetTestOverrides();
|
|
24
|
+
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
|
25
|
+
if (stage != null && string.Equals(PrefabToolSupport.StageAssetPath(stage), PrefabPath, StringComparison.OrdinalIgnoreCase))
|
|
26
|
+
{
|
|
27
|
+
PrefabToolSupport.SavePrefabStage(stage);
|
|
28
|
+
PrefabToolSupport.ClosePrefabStage();
|
|
29
|
+
}
|
|
30
|
+
AssetDatabase.DeleteAsset(PrefabPath);
|
|
31
|
+
if (AssetDatabase.IsValidFolder(PrefabFolder) && AssetDatabase.FindAssets(string.Empty, new[] { PrefabFolder }).Length == 0)
|
|
32
|
+
AssetDatabase.DeleteAsset(PrefabFolder);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
[Test]
|
|
36
|
+
public void FrameDebuggerPagesEntireControlledCaptureAndRejectsChangedDeletedOrUnknownPositions()
|
|
37
|
+
{
|
|
38
|
+
const int eventCount = 1203;
|
|
39
|
+
var capture = "capture-a";
|
|
40
|
+
var currentCount = eventCount;
|
|
41
|
+
FrameDebuggerReflection.AvailableOverrideForTests = true;
|
|
42
|
+
FrameDebuggerReflection.EnabledOverrideForTests = () => true;
|
|
43
|
+
FrameDebuggerReflection.EventCountOverrideForTests = () => currentCount;
|
|
44
|
+
FrameDebuggerReflection.EventNameOverrideForTests = index => "event-" + index.ToString("D4", CultureInfo.InvariantCulture);
|
|
45
|
+
FrameDebuggerReflection.EventDataOverrideForTests = index => null;
|
|
46
|
+
FrameDebuggerReflection.GenerationOverrideForTests = () => capture;
|
|
47
|
+
|
|
48
|
+
var tool = new ProfilerFrameDebuggerEventsTool();
|
|
49
|
+
var indices = new List<long>();
|
|
50
|
+
string cursor = null;
|
|
51
|
+
string firstCursor = null;
|
|
52
|
+
string generation = null;
|
|
53
|
+
var pageCount = 0;
|
|
54
|
+
do
|
|
55
|
+
{
|
|
56
|
+
var page = tool.ExecuteAsync(
|
|
57
|
+
new ProfilerFrameDebuggerEventsTool.Request { PageSize = 500, Cursor = cursor },
|
|
58
|
+
Context("issue-042-frame-" + pageCount.ToString(CultureInfo.InvariantCulture))).GetAwaiter().GetResult();
|
|
59
|
+
pageCount++;
|
|
60
|
+
Assert.That(page.TotalEvents, Is.EqualTo(eventCount));
|
|
61
|
+
Assert.That(page.PageInfo.Cursor, Is.EqualTo(cursor));
|
|
62
|
+
Assert.That(page.PageInfo.ReturnedCount, Is.EqualTo(page.Events.Count));
|
|
63
|
+
Assert.That(page.Budget.ScannedRecords, Is.LessThanOrEqualTo(500));
|
|
64
|
+
Assert.That(page.Budget.Nodes, Is.LessThanOrEqualTo(500));
|
|
65
|
+
if (generation == null) generation = page.PageInfo.Generation;
|
|
66
|
+
else Assert.That(page.PageInfo.Generation, Is.EqualTo(generation));
|
|
67
|
+
indices.AddRange(page.Events.Select(item => item.Index));
|
|
68
|
+
cursor = page.PageInfo.NextCursor;
|
|
69
|
+
if (firstCursor == null) firstCursor = cursor;
|
|
70
|
+
} while (cursor != null);
|
|
71
|
+
|
|
72
|
+
CollectionAssert.AreEqual(Enumerable.Range(0, eventCount).Select(index => (long)index).ToArray(), indices.ToArray());
|
|
73
|
+
Assert.That(pageCount, Is.EqualTo(3));
|
|
74
|
+
Assert.That(indices.Distinct().Count(), Is.EqualTo(eventCount));
|
|
75
|
+
|
|
76
|
+
capture = "capture-b";
|
|
77
|
+
AssertStale(tool, firstCursor, "issue-042-frame-generation");
|
|
78
|
+
capture = "capture-a";
|
|
79
|
+
currentCount--;
|
|
80
|
+
AssertStale(tool, firstCursor, "issue-042-frame-deleted");
|
|
81
|
+
currentCount = eventCount;
|
|
82
|
+
var unknown = UnityCliContinuationToken.Create("profiler.frame-debugger.events", generation, "unknown");
|
|
83
|
+
AssertStale(tool, unknown, "issue-042-frame-unknown");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
[Test]
|
|
87
|
+
public void FrameDebuggerHonorsDeadlineAndCancellationBeforePublishingPartialEvents()
|
|
88
|
+
{
|
|
89
|
+
var clock = new ManualClock();
|
|
90
|
+
FrameDebuggerReflection.AvailableOverrideForTests = true;
|
|
91
|
+
FrameDebuggerReflection.EventCountOverrideForTests = () => 10;
|
|
92
|
+
FrameDebuggerReflection.GenerationOverrideForTests = () => "capture-deadline";
|
|
93
|
+
FrameDebuggerReflection.EventNameOverrideForTests = index =>
|
|
94
|
+
{
|
|
95
|
+
clock.Advance(2);
|
|
96
|
+
return "event-" + index.ToString(CultureInfo.InvariantCulture);
|
|
97
|
+
};
|
|
98
|
+
FrameDebuggerReflection.EventDataOverrideForTests = index => null;
|
|
99
|
+
var budget = new UnityCliRequestBudget(
|
|
100
|
+
new UnityCliReadBudgetInput { MaxMainThreadMilliseconds = 1 },
|
|
101
|
+
30000,
|
|
102
|
+
CancellationToken.None,
|
|
103
|
+
clock);
|
|
104
|
+
var deadline = Assert.Throws<UnityCliRequestBudgetExceededException>(() => ProfilerFrameDebuggerEventsTool.ReadPage(
|
|
105
|
+
new ProfilerFrameDebuggerEventsTool.Request { PageSize = 5 }, budget));
|
|
106
|
+
Assert.That(deadline.Dimension, Is.EqualTo("mainThreadMilliseconds"));
|
|
107
|
+
|
|
108
|
+
var cancellation = new CancellationTokenSource();
|
|
109
|
+
cancellation.Cancel();
|
|
110
|
+
Assert.Throws<OperationCanceledException>(() => new ProfilerFrameDebuggerEventsTool().ExecuteAsync(
|
|
111
|
+
new ProfilerFrameDebuggerEventsTool.Request { PageSize = 5 },
|
|
112
|
+
Context("issue-042-frame-cancel", cancellation.Token)).GetAwaiter().GetResult());
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
[Test]
|
|
116
|
+
public void ConcurrentFramePagesUseIndependentBudgetsAndRetainNoSnapshotState()
|
|
117
|
+
{
|
|
118
|
+
FrameDebuggerReflection.AvailableOverrideForTests = true;
|
|
119
|
+
FrameDebuggerReflection.EventCountOverrideForTests = () => 64;
|
|
120
|
+
FrameDebuggerReflection.EventNameOverrideForTests = index => "event-" + index.ToString(CultureInfo.InvariantCulture);
|
|
121
|
+
FrameDebuggerReflection.EventDataOverrideForTests = index => null;
|
|
122
|
+
FrameDebuggerReflection.GenerationOverrideForTests = () => "capture-concurrent";
|
|
123
|
+
var pages = new ProfilerFrameDebuggerEventsTool.Result[8];
|
|
124
|
+
|
|
125
|
+
Parallel.For(0, pages.Length, index =>
|
|
126
|
+
{
|
|
127
|
+
var budget = new UnityCliRequestBudget(null, 30000, CancellationToken.None);
|
|
128
|
+
pages[index] = ProfilerFrameDebuggerEventsTool.ReadPage(
|
|
129
|
+
new ProfilerFrameDebuggerEventsTool.Request { PageSize = 7 }, budget);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
Assert.That(pages.All(page => page.Events.Count == 7), Is.True);
|
|
133
|
+
Assert.That(pages.All(page => page.Events.Select(item => item.Index).SequenceEqual(Enumerable.Range(0, 7).Select(value => (long)value))), Is.True);
|
|
134
|
+
Assert.That(pages.Select(page => page.PageInfo.NextCursor).Distinct().Count(), Is.EqualTo(1));
|
|
135
|
+
Assert.That(pages.All(page => page.Budget.ScannedRecords == 7 && page.Budget.Nodes == 7), Is.True);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
[Test]
|
|
139
|
+
public void PrefabStagePagesWithoutDuplicatesAndRejectsGenerationOrDeletedBoundary()
|
|
140
|
+
{
|
|
141
|
+
CreatePrefabFixture(17);
|
|
142
|
+
Assert.That(PrefabToolSupport.OpenPrefabStage(PrefabPath), Is.True);
|
|
143
|
+
var stage = PrefabStageUtility.GetCurrentPrefabStage();
|
|
144
|
+
Assert.That(stage, Is.Not.Null);
|
|
145
|
+
Assert.That(stage.prefabContentsRoot, Is.Not.Null);
|
|
146
|
+
|
|
147
|
+
var tool = new GameObjectFindTool();
|
|
148
|
+
var ids = new List<long>();
|
|
149
|
+
string cursor = null;
|
|
150
|
+
string firstCursor = null;
|
|
151
|
+
do
|
|
152
|
+
{
|
|
153
|
+
var page = tool.ExecuteAsync(new GameObjectFindTool.Request
|
|
154
|
+
{
|
|
155
|
+
SearchTerm = "issue-042-match",
|
|
156
|
+
SearchMethod = "by_name",
|
|
157
|
+
IncludeInactive = true,
|
|
158
|
+
PreferPrefabStage = true,
|
|
159
|
+
PageSize = 4,
|
|
160
|
+
Cursor = cursor
|
|
161
|
+
}, Context("issue-042-prefab-page")).GetAwaiter().GetResult();
|
|
162
|
+
Assert.That(page.PrefabStageOpen, Is.True);
|
|
163
|
+
Assert.That(page.PageInfo.Cursor, Is.EqualTo(cursor));
|
|
164
|
+
ids.AddRange(page.Items.Select(item => item.Id));
|
|
165
|
+
cursor = page.PageInfo.NextCursor;
|
|
166
|
+
if (firstCursor == null) firstCursor = cursor;
|
|
167
|
+
} while (cursor != null);
|
|
168
|
+
|
|
169
|
+
Assert.That(ids.Count, Is.EqualTo(17));
|
|
170
|
+
Assert.That(ids.Distinct().Count(), Is.EqualTo(17));
|
|
171
|
+
|
|
172
|
+
UnityCliReadGeneration.InvalidateHierarchy();
|
|
173
|
+
AssertGoFindStale(tool, firstCursor, "issue-042-prefab-generation");
|
|
174
|
+
|
|
175
|
+
var fresh = tool.ExecuteAsync(new GameObjectFindTool.Request
|
|
176
|
+
{
|
|
177
|
+
SearchTerm = "issue-042-match",
|
|
178
|
+
SearchMethod = "by_name",
|
|
179
|
+
IncludeInactive = true,
|
|
180
|
+
PreferPrefabStage = true,
|
|
181
|
+
PageSize = 1
|
|
182
|
+
}, Context("issue-042-prefab-deleted-first")).GetAwaiter().GetResult();
|
|
183
|
+
string position;
|
|
184
|
+
Assert.That(UnityCliContinuationToken.TryParse(
|
|
185
|
+
fresh.PageInfo.NextCursor, "go.find", fresh.PageInfo.Generation, out position), Is.True);
|
|
186
|
+
var separator = position.IndexOf(':');
|
|
187
|
+
int instanceId;
|
|
188
|
+
Assert.That(separator, Is.GreaterThan(0));
|
|
189
|
+
Assert.That(int.TryParse(position.Substring(separator + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out instanceId), Is.True);
|
|
190
|
+
var deletedBoundary = EditorUtility.InstanceIDToObject(instanceId);
|
|
191
|
+
Assert.That(deletedBoundary, Is.Not.Null);
|
|
192
|
+
UnityEngine.Object.DestroyImmediate(deletedBoundary);
|
|
193
|
+
AssertGoFindStale(tool, fresh.PageInfo.NextCursor, "issue-042-prefab-deleted");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
[Test]
|
|
197
|
+
public void ExactIdSelectorDoesNotScanLargeSceneAndUnknownIdsReturnEmpty()
|
|
198
|
+
{
|
|
199
|
+
var scene = EditorSceneManager.NewPreviewScene();
|
|
200
|
+
try
|
|
201
|
+
{
|
|
202
|
+
GameObject target = null;
|
|
203
|
+
for (var index = 0; index < 1000; index++)
|
|
204
|
+
{
|
|
205
|
+
var value = new GameObject("issue-042-exact-" + index.ToString("D4", CultureInfo.InvariantCulture));
|
|
206
|
+
SceneManager.MoveGameObjectToScene(value, scene);
|
|
207
|
+
if (index == 777) target = value;
|
|
208
|
+
}
|
|
209
|
+
var tool = new GameObjectFindTool();
|
|
210
|
+
var found = tool.ExecuteAsync(new GameObjectFindTool.Request
|
|
211
|
+
{
|
|
212
|
+
SearchTerm = target.GetInstanceID().ToString(CultureInfo.InvariantCulture),
|
|
213
|
+
SearchMethod = "by_id",
|
|
214
|
+
IncludeInactive = true,
|
|
215
|
+
Budget = new UnityCliReadBudgetInput { MaxScannedRecords = 1 }
|
|
216
|
+
}, Context("issue-042-exact-found")).GetAwaiter().GetResult();
|
|
217
|
+
Assert.That(found.ReturnedCount, Is.EqualTo(1));
|
|
218
|
+
Assert.That(found.Items.Single().Id, Is.EqualTo(target.GetInstanceID()));
|
|
219
|
+
Assert.That(found.Budget.ScannedRecords, Is.Zero);
|
|
220
|
+
|
|
221
|
+
var missing = tool.ExecuteAsync(new GameObjectFindTool.Request
|
|
222
|
+
{
|
|
223
|
+
SearchTerm = int.MaxValue.ToString(CultureInfo.InvariantCulture),
|
|
224
|
+
SearchMethod = "by_id",
|
|
225
|
+
IncludeInactive = true,
|
|
226
|
+
Budget = new UnityCliReadBudgetInput { MaxScannedRecords = 1 }
|
|
227
|
+
}, Context("issue-042-exact-missing")).GetAwaiter().GetResult();
|
|
228
|
+
Assert.That(missing.ReturnedCount, Is.Zero);
|
|
229
|
+
Assert.That(missing.PageInfo.Complete, Is.True);
|
|
230
|
+
Assert.That(missing.Budget.ScannedRecords, Is.Zero);
|
|
231
|
+
}
|
|
232
|
+
finally
|
|
233
|
+
{
|
|
234
|
+
Assert.That(EditorSceneManager.ClosePreviewScene(scene), Is.True);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private static void AssertStale(ProfilerFrameDebuggerEventsTool tool, string cursor, string requestId)
|
|
239
|
+
{
|
|
240
|
+
var exception = Assert.Throws<UnityCliBridge.BridgeCommandException>(() => tool.ExecuteAsync(
|
|
241
|
+
new ProfilerFrameDebuggerEventsTool.Request { PageSize = 500, Cursor = cursor }, Context(requestId)).GetAwaiter().GetResult());
|
|
242
|
+
Assert.That(exception.Code, Is.EqualTo("E_CONTINUATION_STALE"));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private static void AssertGoFindStale(GameObjectFindTool tool, string cursor, string requestId)
|
|
246
|
+
{
|
|
247
|
+
var exception = Assert.Throws<UnityCliBridge.BridgeCommandException>(() => tool.ExecuteAsync(new GameObjectFindTool.Request
|
|
248
|
+
{
|
|
249
|
+
SearchTerm = "issue-042-match",
|
|
250
|
+
SearchMethod = "by_name",
|
|
251
|
+
IncludeInactive = true,
|
|
252
|
+
PreferPrefabStage = true,
|
|
253
|
+
PageSize = 4,
|
|
254
|
+
Cursor = cursor
|
|
255
|
+
}, Context(requestId)).GetAwaiter().GetResult());
|
|
256
|
+
Assert.That(exception.Code, Is.EqualTo("E_CONTINUATION_STALE"));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
private static UnityCliProjectToolContext Context(string requestId, CancellationToken cancellationToken = default)
|
|
260
|
+
{
|
|
261
|
+
return new UnityCliProjectToolContext { RequestId = requestId, TimeoutMs = 30000, CancellationToken = cancellationToken };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private static void CreatePrefabFixture(int childCount)
|
|
265
|
+
{
|
|
266
|
+
if (!AssetDatabase.IsValidFolder(PrefabFolder)) AssetDatabase.CreateFolder("Assets", "UnityCliTests");
|
|
267
|
+
AssetDatabase.DeleteAsset(PrefabPath);
|
|
268
|
+
var root = new GameObject("issue-042-prefab-root");
|
|
269
|
+
try
|
|
270
|
+
{
|
|
271
|
+
for (var index = 0; index < childCount; index++)
|
|
272
|
+
{
|
|
273
|
+
var child = new GameObject("issue-042-match");
|
|
274
|
+
child.transform.SetParent(root.transform, false);
|
|
275
|
+
child.SetActive(index % 3 != 0);
|
|
276
|
+
}
|
|
277
|
+
Assert.That(PrefabUtility.SaveAsPrefabAsset(root, PrefabPath), Is.Not.Null);
|
|
278
|
+
AssetDatabase.SaveAssets();
|
|
279
|
+
}
|
|
280
|
+
finally
|
|
281
|
+
{
|
|
282
|
+
UnityEngine.Object.DestroyImmediate(root);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private sealed class ManualClock : IUnityCliMonotonicClock
|
|
287
|
+
{
|
|
288
|
+
public long ElapsedMilliseconds { get; private set; }
|
|
289
|
+
internal void Advance(long milliseconds) { ElapsedMilliseconds += milliseconds; }
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#if UNITY_EDITOR
|
|
2
|
+
using System;
|
|
3
|
+
using System.Collections;
|
|
4
|
+
using System.Collections.Generic;
|
|
5
|
+
using System.Reflection;
|
|
6
|
+
using System.Text;
|
|
7
|
+
using System.Threading;
|
|
8
|
+
using System.Threading.Tasks;
|
|
9
|
+
using NUnit.Framework;
|
|
10
|
+
|
|
11
|
+
namespace UnityCli.Tests
|
|
12
|
+
{
|
|
13
|
+
public sealed class UnityCliDiagnosticBoundaryTests
|
|
14
|
+
{
|
|
15
|
+
private static readonly Type BridgeType = Type.GetType("UnityCli.UnityCliBridge, UnityCli.Editor", true);
|
|
16
|
+
|
|
17
|
+
[Test]
|
|
18
|
+
public void DoctorCatalogHandlerReadsThePublishedSnapshotWithoutAnotherConstruction()
|
|
19
|
+
{
|
|
20
|
+
var constructionCounter = Field("projectToolCatalogConstructionCount");
|
|
21
|
+
var reader = BridgeType.GetProperty("ProjectToolCatalogSnapshotReader", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
|
|
22
|
+
var snapshot = reader.GetType().GetMethod("Read", BindingFlags.Public | BindingFlags.Instance).Invoke(reader, null);
|
|
23
|
+
var expectedToolCount = Convert.ToInt64(snapshot.GetType().GetProperty("ToolCount").GetValue(snapshot, null));
|
|
24
|
+
var registry = Method("CreateCommandRegistry").Invoke(null, null);
|
|
25
|
+
var requestType = Type.GetType("UnityCli.Protocol.BridgeRequest, UnityCli.Editor", true);
|
|
26
|
+
var request = Activator.CreateInstance(requestType);
|
|
27
|
+
requestType.GetProperty("Command").SetValue(request, "internal.doctor.catalog", null);
|
|
28
|
+
requestType.GetProperty("RequestId").SetValue(request, "doctor-catalog-owner", null);
|
|
29
|
+
requestType.GetProperty("Input").SetValue(request, new Dictionary<string, object>(), null);
|
|
30
|
+
|
|
31
|
+
var before = Convert.ToInt64(constructionCounter.GetValue(null));
|
|
32
|
+
var pending = (ValueTask<object>)registry.GetType().GetMethod("ExecuteAsync").Invoke(registry, new[] { request, (object)CancellationToken.None });
|
|
33
|
+
var result = (IDictionary<string, object>)pending.AsTask().GetAwaiter().GetResult();
|
|
34
|
+
var after = Convert.ToInt64(constructionCounter.GetValue(null));
|
|
35
|
+
|
|
36
|
+
Assert.That(after, Is.EqualTo(before));
|
|
37
|
+
Assert.That(result["identity"], Is.EqualTo("unity-cli-immutable-domain-catalog"));
|
|
38
|
+
Assert.That(Convert.ToInt64(result["toolCount"]), Is.EqualTo(expectedToolCount));
|
|
39
|
+
Assert.That(result["providerCounts"], Is.InstanceOf<IDictionary<string, object>>());
|
|
40
|
+
Assert.That(result["publicationDiagnostics"], Is.InstanceOf<IDictionary<string, object>>());
|
|
41
|
+
var serialized = UnityCli.UnityCliSerializer.Serialize(result);
|
|
42
|
+
Assert.That(Encoding.UTF8.GetByteCount(serialized), Is.LessThanOrEqualTo(64 * 1024));
|
|
43
|
+
Assert.That(serialized, Does.Not.Contain("fingerprint").IgnoreCase);
|
|
44
|
+
Assert.That(serialized, Does.Not.Contain("rePinValue"));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[Test]
|
|
48
|
+
public void ProjectToolNamesUseProfileAwareGrammarAndOneUtf8Budget()
|
|
49
|
+
{
|
|
50
|
+
var validator = Type.GetType("UnityCli.UnityCliToolName, UnityCli.Editor", true);
|
|
51
|
+
var validate = validator.GetMethod("Validate", BindingFlags.NonPublic | BindingFlags.Static);
|
|
52
|
+
Assert.DoesNotThrow(() => validate.Invoke(null, new object[] { "scene.hierarchy", "native" }));
|
|
53
|
+
Assert.DoesNotThrow(() => validate.Invoke(null, new object[] { new string('a', 128), "native" }));
|
|
54
|
+
Assert.DoesNotThrow(() => validate.Invoke(null, new object[] { "UnityPipeline_hotfix_container_inspect", "official-attribute" }));
|
|
55
|
+
Assert.DoesNotThrow(() => validate.Invoke(null, new object[] { "UnityPipeline_project_reload_data", "official-attribute" }));
|
|
56
|
+
|
|
57
|
+
AssertInvalidName(validate, "UnityPipeline_project_reload_data", "native");
|
|
58
|
+
AssertInvalidName(validate, "project_reload_data", "official-attribute");
|
|
59
|
+
AssertInvalidName(validate, "Scene.Data", "native");
|
|
60
|
+
AssertInvalidName(validate, "scene..data", "native");
|
|
61
|
+
AssertInvalidName(validate, "scene.数据", "native");
|
|
62
|
+
AssertInvalidName(validate, new string('a', 129), "native");
|
|
63
|
+
AssertInvalidName(validate, "scene.hierarchy\n", "native");
|
|
64
|
+
AssertInvalidName(validate, "scene.hierarchy\r\n", "native");
|
|
65
|
+
AssertInvalidName(validate, "scene.hierarchy ", "native");
|
|
66
|
+
AssertInvalidName(validate, "UnityPipeline_project_reload_data\n", "official-attribute");
|
|
67
|
+
AssertInvalidName(validate, "UnityPipeline_project_reload_data\r\n", "official-attribute");
|
|
68
|
+
AssertInvalidName(validate, "UnityPipeline_project_reload_data\t", "official-attribute");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[Test]
|
|
72
|
+
public void CodeExecBridgeEnvelopeUsesTerminalCauseBeyondEightLevels()
|
|
73
|
+
{
|
|
74
|
+
const string terminalMessage = "terminal-actionable-cause";
|
|
75
|
+
Exception exception = new InvalidOperationException(terminalMessage);
|
|
76
|
+
for (var index = 0; index < 12; index++) exception = new TargetInvocationException("wrapper-" + index, exception);
|
|
77
|
+
|
|
78
|
+
var result = Method("ExceptionFailure").Invoke(null, new object[]
|
|
79
|
+
{
|
|
80
|
+
"E_CODE_RUNTIME_EXCEPTION", string.Empty, exception, string.Empty, string.Empty,
|
|
81
|
+
"Inspect the bounded runtime exception cause chain and affected business state."
|
|
82
|
+
});
|
|
83
|
+
var envelope = (string)Method("SerializeCodeExecutionResult").Invoke(null, new[] { "code-exec-deep-cause", result });
|
|
84
|
+
var serializer = Type.GetType("UnityCli.UnityCliSerializer, UnityCli.Editor", true);
|
|
85
|
+
var root = (IDictionary<string, object>)serializer.GetMethod("Parse", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { envelope });
|
|
86
|
+
var error = (IDictionary<string, object>)root["error"];
|
|
87
|
+
var details = (IDictionary<string, object>)error["details"];
|
|
88
|
+
var causes = (IList)details["causes"];
|
|
89
|
+
var terminal = (IDictionary<string, object>)causes[causes.Count - 1];
|
|
90
|
+
|
|
91
|
+
Assert.That(error["code"], Is.EqualTo("E_CODE_RUNTIME_EXCEPTION"));
|
|
92
|
+
Assert.That(error["message"], Is.EqualTo(terminalMessage));
|
|
93
|
+
Assert.That(details["message"], Is.EqualTo(terminalMessage));
|
|
94
|
+
Assert.That(details["exceptionType"], Is.EqualTo(typeof(InvalidOperationException).FullName));
|
|
95
|
+
Assert.That(details["causeChainTruncated"], Is.EqualTo(true));
|
|
96
|
+
Assert.That(causes.Count, Is.EqualTo(8));
|
|
97
|
+
Assert.That(terminal["depth"], Is.EqualTo(12L));
|
|
98
|
+
Assert.That(terminal["message"], Is.EqualTo(terminalMessage));
|
|
99
|
+
Assert.That(Encoding.UTF8.GetByteCount(envelope), Is.LessThanOrEqualTo(1536 * 1024));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private static void AssertInvalidName(MethodInfo validate, string name, string contractProfile)
|
|
103
|
+
{
|
|
104
|
+
var exception = Assert.Throws<TargetInvocationException>(() => validate.Invoke(null, new object[] { name, contractProfile }));
|
|
105
|
+
Assert.That(exception.InnerException, Is.TypeOf<InvalidOperationException>());
|
|
106
|
+
Assert.That(exception.InnerException.Message, Is.EqualTo("Tool name must use the registered Tool syntax and fit 128 UTF-8 bytes."));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static FieldInfo Field(string name)
|
|
110
|
+
{
|
|
111
|
+
return BridgeType.GetField(name, BindingFlags.Static | BindingFlags.NonPublic) ?? throw new MissingFieldException(name);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private static MethodInfo Method(string name)
|
|
115
|
+
{
|
|
116
|
+
return BridgeType.GetMethod(name, BindingFlags.Static | BindingFlags.NonPublic) ?? throw new MissingMethodException(name);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
#endif
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#if UNITY_EDITOR
|
|
2
|
+
using System;
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using NUnit.Framework;
|
|
5
|
+
|
|
6
|
+
namespace UnityCli.Tests
|
|
7
|
+
{
|
|
8
|
+
public sealed class UnityCliDurableStatusTests
|
|
9
|
+
{
|
|
10
|
+
private string _scope;
|
|
11
|
+
private string _runningRequestId;
|
|
12
|
+
private string _terminalRequestId;
|
|
13
|
+
private static readonly string Digest = new string('a', 64);
|
|
14
|
+
|
|
15
|
+
[SetUp]
|
|
16
|
+
public void SetUp()
|
|
17
|
+
{
|
|
18
|
+
// terminal identity在Editor session内有意持久化,增量重复执行必须使用新identity。
|
|
19
|
+
var runId = Guid.NewGuid().ToString("N");
|
|
20
|
+
_scope = "durable-status-test-" + runId;
|
|
21
|
+
_runningRequestId = "durable-status-running-root-" + runId;
|
|
22
|
+
_terminalRequestId = "durable-status-terminal-root-" + runId;
|
|
23
|
+
UnityCliActiveOperation.Clear(_scope);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[TearDown]
|
|
27
|
+
public void TearDown()
|
|
28
|
+
{
|
|
29
|
+
UnityCliActiveOperation.Clear(_scope);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
[Test]
|
|
33
|
+
public void ReadScope_ReturnsRunningPhaseWithoutDigest()
|
|
34
|
+
{
|
|
35
|
+
UnityCliActiveOperation.Save(_scope, new Dictionary<string, object>
|
|
36
|
+
{
|
|
37
|
+
{ "requestId", _runningRequestId }, { "requestDigest", Digest }, { "phase", "effect_started" }
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
var result = (Dictionary<string, object>)UnityCliBridge.UnityCliDurableStatusCoordinator.ReadScope(_scope, _runningRequestId);
|
|
41
|
+
|
|
42
|
+
Assert.That(result["requestId"], Is.EqualTo(_runningRequestId));
|
|
43
|
+
Assert.That(result["state"], Is.EqualTo("running"));
|
|
44
|
+
Assert.That(result["phase"], Is.EqualTo("effect_started"));
|
|
45
|
+
Assert.That(result.ContainsKey("requestDigest"), Is.False);
|
|
46
|
+
Assert.That(result.ContainsKey("terminalEnvelope"), Is.False);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[Test]
|
|
50
|
+
public void ReadScope_ReturnsFirstTerminalWithoutReplayingEffect()
|
|
51
|
+
{
|
|
52
|
+
var terminal = new Dictionary<string, object>
|
|
53
|
+
{
|
|
54
|
+
{ "ok", true }, { "requestId", _terminalRequestId }, { "data", new Dictionary<string, object> { { "value", 1L } } }
|
|
55
|
+
};
|
|
56
|
+
var first = UnityCliActiveOperation.StoreTerminalFirst(_scope, _terminalRequestId, Digest, null, "test.run", terminal);
|
|
57
|
+
|
|
58
|
+
var result = (Dictionary<string, object>)UnityCliBridge.UnityCliDurableStatusCoordinator.ReadScope(_scope, _terminalRequestId);
|
|
59
|
+
Assert.That(UnityCliActiveOperation.TryGetTerminalByRequestId(_scope, _terminalRequestId, out var internalDigest, out var statusDomain, out var selected), Is.True);
|
|
60
|
+
|
|
61
|
+
Assert.That(result["state"], Is.EqualTo("completed"));
|
|
62
|
+
Assert.That(result["terminalEnvelope"], Is.EqualTo(first));
|
|
63
|
+
Assert.That(internalDigest, Is.EqualTo(Digest));
|
|
64
|
+
Assert.That(statusDomain, Is.EqualTo("test.run"));
|
|
65
|
+
Assert.That(selected, Is.EqualTo(first));
|
|
66
|
+
Assert.That(result.ContainsKey("requestDigest"), Is.False);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
[Test]
|
|
70
|
+
public void SafeStatusAllowlist_ContainsEveryDomainCommand()
|
|
71
|
+
{
|
|
72
|
+
var commands = new[]
|
|
73
|
+
{
|
|
74
|
+
"internal.asset.refresh.public-status", "internal.build.player.public-status",
|
|
75
|
+
"internal.editor.play-mode.public-status", "internal.package.install.public-status",
|
|
76
|
+
"internal.package.remove.public-status", "internal.test.run.public-status"
|
|
77
|
+
};
|
|
78
|
+
foreach (var command in commands)
|
|
79
|
+
Assert.That(UnityCliBridgeQueuePolicy.IsSafeStatusCommand(command), Is.True, command);
|
|
80
|
+
Assert.That(UnityCliBridgeQueuePolicy.IsSafeStatusCommand("internal.operation.public-status"), Is.False);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
#endif
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using System.Reflection;
|
|
4
|
+
using NUnit.Framework;
|
|
5
|
+
|
|
6
|
+
namespace UnityCli.Tests
|
|
7
|
+
{
|
|
8
|
+
public sealed class UnityCliExceptionProjectionTests
|
|
9
|
+
{
|
|
10
|
+
[Test]
|
|
11
|
+
public void NestedReflectionAndNUnitFailureUsesDeepestActionableCause()
|
|
12
|
+
{
|
|
13
|
+
var assertion = new AssertionException("Expected health check to pass, but it failed.");
|
|
14
|
+
var wrapper = new InvalidOperationException("NUnit invocation failed.", assertion);
|
|
15
|
+
var reflection = new TargetInvocationException("Reflected method failed.", wrapper);
|
|
16
|
+
|
|
17
|
+
var result = UnityCliExceptionProjection.Project(reflection);
|
|
18
|
+
|
|
19
|
+
Assert.That(result.PublicMessage, Is.EqualTo(assertion.Message));
|
|
20
|
+
Assert.That(result.DeepestExceptionType, Is.EqualTo(typeof(AssertionException).FullName));
|
|
21
|
+
Assert.That(result.Causes, Has.Count.EqualTo(3));
|
|
22
|
+
Assert.That(result.Causes[0]["exceptionType"], Is.EqualTo(typeof(TargetInvocationException).FullName));
|
|
23
|
+
Assert.That(result.Causes[2]["message"], Is.EqualTo(assertion.Message));
|
|
24
|
+
Assert.That(result.Truncated, Is.False);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
[Test]
|
|
28
|
+
public void CauseChainStopsAtCyclesAndStaysDepthAndByteBounded()
|
|
29
|
+
{
|
|
30
|
+
Exception deep = new Exception(new string('z', 100000));
|
|
31
|
+
for (var index = 0; index < UnityCliExceptionProjection.MaxCauseDepth + 4; index++)
|
|
32
|
+
deep = new InvalidOperationException(new string((char)('a' + index), 100000), deep);
|
|
33
|
+
var deepResult = UnityCliExceptionProjection.Project(deep);
|
|
34
|
+
Assert.That(deepResult.Causes, Has.Count.EqualTo(UnityCliExceptionProjection.MaxCauseDepth));
|
|
35
|
+
Assert.That(deepResult.CauseTextBytes, Is.LessThanOrEqualTo(UnityCliExceptionProjection.MaxCauseTextBytes));
|
|
36
|
+
Assert.That(deepResult.CauseTraversalCount, Is.EqualTo(UnityCliExceptionProjection.MaxCauseDepth + 5));
|
|
37
|
+
Assert.That(deepResult.PublicMessage, Is.EqualTo(new string('z', 4096)));
|
|
38
|
+
Assert.That(deepResult.DeepestMessage, Is.EqualTo(new string('z', 4096)));
|
|
39
|
+
Assert.That(deepResult.Causes[UnityCliExceptionProjection.MaxCauseDepth - 1]["depth"], Is.EqualTo((long)(UnityCliExceptionProjection.MaxCauseDepth + 4)));
|
|
40
|
+
Assert.That(deepResult.Causes[UnityCliExceptionProjection.MaxCauseDepth - 1]["message"], Is.EqualTo(new string('z', 4096)));
|
|
41
|
+
Assert.That(deepResult.Truncated, Is.True);
|
|
42
|
+
|
|
43
|
+
var first = new InvalidOperationException("first");
|
|
44
|
+
var second = new Exception("second");
|
|
45
|
+
var next = new Dictionary<Exception, Exception>
|
|
46
|
+
{
|
|
47
|
+
{ first, second },
|
|
48
|
+
{ second, first }
|
|
49
|
+
};
|
|
50
|
+
var cycleResult = UnityCliExceptionProjection.Project(first, value => next[value]);
|
|
51
|
+
Assert.That(cycleResult.Causes, Has.Count.EqualTo(2));
|
|
52
|
+
Assert.That(cycleResult.Truncated, Is.True);
|
|
53
|
+
Assert.That(cycleResult.PublicMessage, Is.EqualTo("second"));
|
|
54
|
+
Assert.That(cycleResult.CauseTraversalCount, Is.EqualTo(2));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[Test]
|
|
58
|
+
public void TraversalWorkRemainsHardBoundedBeyondThePublishedCauseDepth()
|
|
59
|
+
{
|
|
60
|
+
Exception deep = new Exception("terminal-beyond-traversal-budget");
|
|
61
|
+
for (var index = 0; index < UnityCliExceptionProjection.MaxCauseTraversal + 20; index++)
|
|
62
|
+
deep = new InvalidOperationException("wrapper-" + index, deep);
|
|
63
|
+
|
|
64
|
+
var result = UnityCliExceptionProjection.Project(deep);
|
|
65
|
+
|
|
66
|
+
Assert.That(result.CauseTraversalCount, Is.EqualTo(UnityCliExceptionProjection.MaxCauseTraversal));
|
|
67
|
+
Assert.That(result.Causes, Has.Count.EqualTo(UnityCliExceptionProjection.MaxCauseDepth));
|
|
68
|
+
Assert.That(result.CauseTextBytes, Is.LessThanOrEqualTo(UnityCliExceptionProjection.MaxCauseTextBytes));
|
|
69
|
+
Assert.That(result.Truncated, Is.True);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|