Skip to content

Latest commit

 

History

History
345 lines (257 loc) · 36.2 KB

Project.md

File metadata and controls

345 lines (257 loc) · 36.2 KB

Project Specific Instruction

Maintaining Tools

  • Native resource orchestration lives in <GacUI repo>/Tools/GacBuild; the single-architecture compiler remains in <GacUI repo>/Tools/GacGen. Update their canonical guidance in <Tools repo>/Copilot/KnowledgeBase/KB_GacUI_Design_GacGenAndGacBuild.md and propagate it through instruction synchronization.
  • If the behavior of any tool changes, update:
    • <GacUI repo>/Tools/GacBuild, <GacUI repo>/Tools/GacGen, and the thin wrappers <Tools repo>/Tools/GacBuild.ps1 and <Tools repo>/Tools/GacGen.ps1: the canonical GacGen/GacBuild guidance above.
    • REPO-ROOT/Tools/UiaList:
      • Update REPO-ROOT/.github/KnowledgeBase/KB_GacUI_Design_UiaList.md for UiaListApp usage.
      • This tool is Windows only, check out REPO-ROOT/Tools/UiaList/AGENTS.md if and only if you are working on it.
    • REPO-ROOT/Tools/GitView:
      • Update REPO-ROOT/.github/KnowledgeBase/KB_GacUI_Design_GitTui.md for GitTui usage.
      • This tool is cross platform, check out REPO-ROOT/Tools/GitView/AGENTS.md if and only if you are working on it.
  • When only changing tools without changing GacUI itself or built-in skins, GacUI test process could be completely skipped.
  • When only changing test apps without changing GacUI itself or built-in skins, GacUI unit test could be completely skipped.

Native Resource Tools

  • Build <GacUI repo>/Tools/GacBuild/GacBuild.sln and <GacUI repo>/Tools/GacGen/GacGen.sln with the repository build wrapper. Both provide Debug/Release and Win32/x64 configurations. GacBuild produces <GacUI repo>/Tools/GacBuild/Bin/GacBuildD.exe or GacBuild.exe; GacGen produces the corresponding executables under <GacUI repo>/Tools/GacGen/Bin. Native Unix builds use <GacUI repo>/Tools/GacBuild/vmake and <GacUI repo>/Tools/GacGen/vmake.
  • GacBuild requires -mode:GacBuild or -mode:GacGen, explicit normalized absolute -pathGacGen and -pathCppMerge, and -FileName. The former accepts -Dump; the latter accepts -MappingFileName. Named dependency ordering uses PartialOrderingProcessor; driver logs retain the mapping and metadata XML, with build/skip decisions printed to the console. VlppOS owns path validation, file metadata and metadata-preserving copies.
  • GacGen /P32 and /P64 stage outputs and write UTF-8 Deploy.xml manifests. GacBuild validates both architectures, merges C++, then copies the manifests with x32 last for shared neutral outputs. Direct /C32 and /C64 still publish configured outputs.
  • Run <GacUI repo>/Tools/GacBuild/Verification.ps1 -Baseline for focused Windows integration coverage. It uses the repository CLI wrapper, keeps fixtures in the ignored tool Bin directory, and restores debugger arguments after execution. Optional tool-path parameters select other built configurations.
  • Tools-only changes use this focused verification; native Linux/macOS execution must be recorded separately from Windows tests and static inventory checks.

Solution to Work On

You are working on the solution REPO-ROOT/Test/GacUISrc/GacUISrc.sln, therefore SOLUTION-ROOT is REPO-ROOT/Test/GacUISrc.

Files not Allowed to Modify

Files in these folders (recursively) are not allowed to modify. You can only change them using what is described in the Code Generation Projects section. If you encounter any error that prevent these files from being generated, always fix the root cause.

  • REPO-ROOT/Test/Resources/Metadata
  • REPO-ROOT/Test/GacUISrc/Generated_DarkSkin
  • REPO-ROOT/Test/GacUISrc/Generated_TuiSkin/Source_x86 and Source_x64
  • REPO-ROOT/Test/GacUISrc/Generated_TuiSkin/Resource_x86 and Resource_x64
  • REPO-ROOT/Test/GacUISrc/Generated_TuiDialogs
  • REPO-ROOT/Test/GacUISrc/Generated_TuiControlTest/Source_x86 and Source_x64
  • REPO-ROOT/Test/GacUISrc/Generated_TuiControlTest/Resource_x86 and Resource_x64
  • REPO-ROOT/Test/GacUISrc/Generated_Dialogs
  • REPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Source_x86 and Source_x64
  • REPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Resource_x86 and Resource_x64
  • REPO-ROOT/Test/GacUISrc/Generated_RemoteProtocolTest
  • REPO-ROOT/Test/GacUISrc/Generated_RemoteViewModelTest
  • REPO-ROOT/Test/GacUISrc/Generated_UnitTestViewer
  • REPO-ROOT/Source/Utilities/FakeServices/Dialogs/Source
  • REPO-ROOT/Source/Utilities/FakeServices/TuiDialogs/Source
  • REPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/Source
  • REPO-ROOT/Source/Compiler/InstanceQuery/Generated
  • REPO-ROOT/Source/Compiler/RemoteProtocol/Generated
  • <GacUI repo>/Tools/GitView/GitView/Source
  • <GacUI repo>/Tools/UiaList/UiaList/Source

Files in REPO-ROOT/Import and REPO-ROOT/Release (recursively) are also not allowed to modify. These files are prepared for foreign dependencies.

When files here are modified, they should be included in a dedicated commit, aka manually udpated files and generated files should be included in two different commits. If there is any unit test snapshot changes, a dedicated third commit should be created for these.

Source/Utilities/AutomationService

The reusable MiniHTTP and Windows HTTP automation endpoints live in this folder and are compiled through Test/GacUISrc/Source_GacUI_Core/Source_GacUI_Core.vcxitems.

  • MiniHttpAutomationService.* is CodePacked into Release/GacUI.h and Release/GacUI.cpp.
  • Windows/WindowsAutomationService.Windows.* is CodePacked into Release/GacUI.Windows.h and Release/GacUI.Windows.cpp.
  • Standalone test applications receive these implementations through their GacUI library dependency; they do not import Source_RemotingHelpers for automation.

Test/RemotingHelpers

Files in this folder are for test apps only:

  • Only test apps could use these source files.
  • No need to create unit test for them.
  • Source files in Source cannot use anything in Test/RemotingHelpers.
  • They are excluded from ordinary public GacUI amalgamations and the aggregate Release/Import production snapshot. GacUI CodePack emits the dedicated neutral Test.RemotingHelpers pair in Release and Release/IncludeOnly; UpdateRelease copies the root pair and its README to the aggregate Release/Import-Test snapshot. The test-only stdio transport and its platform implementations are supplied by imported VlppOS release files.
  • No production quality required, these files are only for building test apps quickly.

Test/RemotingHelpers/Rvmt

Files in this folder are generic client and requester helpers used only by CppTest_Rvm, RemotingTest_Core, and RemotingTest_RvmHost.

  • They are enumerated and compiled through the single Test/GacUISrc/Source_RemotingHelpers/Source_RemotingHelpers.vcxitems inventory shared by all helper consumers.
  • ViewModelShared.h owns generic aliases, fixed RVM channel/control constants, and inline Ready-message helpers; ViewModelHostClient.* owns the generic network-side host client; and ViewModelHostServer.* owns the specialized channel server's generic RPC helpers and server-side local-client behavior.
  • Generated RemoteViewModelTest RPC composition belongs to Test/GacUISrc/Generated_RemoteViewModelTest/RemoteViewModelTestInitialize.*, which each affected application invokes after its generic connection is assigned a client ID.
  • Release/CodegenConfig.xml scans this helper tree only into the dedicated test pairs. Ordinary GacUI* pairs and the aggregate Release/Import production snapshot remain independent of these helpers.

Reflectable Types

  • You must be really careful when changing any interface, especially structs, classes, unions and a few functions.
  • Check if the class and the method is registered in reflection.
  • Reflection allow registering normal functions into a class, becoming its static functions. It is not easy to determine by the function definition itself.
  • You must read the knowledge base about reflection and try to find the pattern in any *.cpp file.
  • If the reflection registration is affected, you should always fix the reflection and run necessary code generation projects.

Projects for Verification

You are required to follow the guideline to run any project in this solution, do not run the compiled binary directly.

The REPO-ROOT/Test/GacUISrc/UnitTest/UnitTest.vcxproj is the unit test project. When any *.h or *.cpp file is changed, unit test is required to run. Except for the GuiRemoteRendererSingle class which is not covered in the unit test.

When any test case fails, you must fix the issue immediately, even those errors are unrelated to the issue you are working on.

For any GacUI specific unit test that running with the GacUI unit test framework, when it calls GacUIUnitTest_StartFast_WithResourceAsText with path, for example, Application/Windows/Order, running it ends up creating log files in REPO-ROOT/Test/Resources/UnitTestSnapshots/Application/Windows:

  • Order.json: an entry of snapshots for this test case
  • Order[].: log files about remote protocol recordings and compiler output
  • Order/Frame_*.json: snapshot of the UI DOM tree for each frame.

Each Frame_*.json is captured at each OnNextIdleFrame call, recording what the UI look like before running the code in this frame. This is the reason why the name of the frame should say what the previous frame was done, so that frame names in snapshot files make sense.

Remote-protocol snapshot tests (GacUIUnitTest_Start, GacUIUnitTest_StartFast_WithResourceAsText, and related entry points) are for recording and reviewing rendering results. Every such case must capture at least one useful rendering frame; an empty frame list is not allowed. Merely recording a frame does not justify using this framework when the rendered output adds no useful coverage.

Use ordinary unit tests when the coverage consists only of compiler rejection, descriptor properties, geometry, bindings, event handlers, or other non-rendering behavior. Construct the objects directly, or use native service and resource setup when needed, without starting the remote snapshot framework. Keep TUI buffer assertions in ordinary TUI provider tests. When converting or removing a snapshot case, remove its index, frame files, protocol logs and compiler artifacts from Test/Resources/UnitTestSnapshots as well.

Code Generation Tools

REPO-ROOT/../Tools/Tools/GlrParserGen.exe

This executable needs to run if any file in the following folders are changed:

  • REPO-ROOT/Source/Compiler/InstanceQuery/Syntax
  • REPO-ROOT/Source/Compiler/RemoteProtocol/Syntax

There is a Parser.xml file in these folder. You need to offer the absolute path of Parser.xml to the tool as a command-line argument. Only run necessary Parser.xml in folders that are changed.

Code Generation Projects

Code generation projects are CLI projects. They are required to run when a certain set of files are changed, in order to generate code paring with them. Here are a list of projects to run and files that should trigger them:

Metadata_Generate and Metadata_Test

These two projects need to run if any reflection code is touched:

  • GuiReflection*.cpp is updated.
  • GacUI_Compiler project is executed.

To execute these projects, you should:

  • Build the solution with Debug|Win32.
  • Run Metadata_Generate with Debug|Win32.
  • Build the solution with Debug|x64.
  • Run Metadata_Generate with Debug|x64.
  • Run Metadata_Test with Debug|x64.

It generates binary metadata files containing type informations from reflection code. This step cannot be skipped after changing any reflection code, because GacUI_Compiler and some other test applications consume these binary metadata files.

Metadata_UpdateProtocol

This project need to run if REPO-ROOT/Source/PlatformProviders/Remote/Protocol/*.txt is updated.

It generates REPO-ROOT/Source/PlatformProviders/Remote/Generated/*.

GacUI_Compiler

This project need to run if any of the following XML file is updated:

  • REPO-ROOT/Source/Utilities/FakeServices/Dialog/*.xml -> generates REPO-ROOT/Source/Utilities/FakeServices/Dialog/Source/*.
  • REPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/*.xml -> generates REPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/Source/*.
  • REPO-ROOT/Test/Resources/App/DarkSkin/*.xml -> generates REPO-ROOT/Test/GacUISrc/Generated_DarkSkin/Source_(x86|x64)/*.
    • IMPORTANT: REPO-ROOT/Source/Skins/DarkSkin has another copy, this is used by the CI and is not involved in this solution, ignore it.
  • REPO-ROOT/Test/Resources/App/FullControlTest/*.xml -> generates REPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Source_(x86|x64)/*.
  • REPO-ROOT/Test/Resources/App/RemoteProtocolTest/*.xml -> generates REPO-ROOT/Test/GacUISrc/Generated_RemoteProtocolTest/Source_(x86|x64)/*.
  • REPO-ROOT/Test/Resources/App/RemoteViewModelTest/*.xml -> generates ordinary and RPC C++ in REPO-ROOT/Test/GacUISrc/Generated_RemoteViewModelTest/Source_(x86|x64)/*.

After running GacUI_Compiler, you should always git status to find if there is any untracked *.UI.errors.txt.

  • Such file means there are compile errors in some xml files, read it to find the detail.
  • You don't need to delete the file, if GacUI_Compiler succeeds the next time, they will be gone.
  • GacUI_Compiler may also fail by printing one line of error message or return non-zero exit code. If the *.UI.errors.txt file does not exist, you are recommended to debug the project to find out what happened.
  • Whenever GacUI_Compiler reports any error, you must fix the issue immediately, even those errors are unrelated to the issue you are working on.

Maintaining darkskin::Theme

This is a default skin that not only releases, but also used by all projects in this solution. To make a change:

  • Update REPO-ROOT/Test/Resources/App/DarkSkin.
  • Run GacUI_Compiler and make sure it updated generated C++ code expectely.
    • Sometimes reordering could happen in generated C++ code even when correlated resource is not changed.
  • Rebuild before running any test project.

DarkSkin defines darkskin::ColorPackage, the shared neutral initializer and the complete default palette in its authored Workflow resource. Source/Skins/DarkSkin/Config/DarkSkinConfig.h/.cpp owns the Aurora/Ember/Moonstone/Lagoon/Rosewood accent values in C++. Each named factory calls Workflow's CreateColorPackageInternal; the default factory and setter forward to their Workflow implementations. The installed palette initializes once from the Workflow default before templates read it. Creating another theme or window does not reset a selected palette.

TuiSkin follows the same ownership pattern. Test/Resources/App/TuiSkin/TuiSkin.xml defines its two-color initializer and complete opaque SkyBlue default, and initializes tuiColors once. TuiTheme::SetColorPackage assigns that variable directly; the native default factory and setter forward to Workflow. The five named native factories supply only their accent/highlight pairs. Applications need no startup default installation. The SkyBlue showcase selector uses CreateDefaultColorPackage. Internal palette-based baseline document factories remain in both skins; the TUI grid editor uses tuiskin::TuiDocumentLabelTemplate.

Both skin inventories and the direct configuration consumers (UnitTest, CppTest_Tui, the FullControlTest inventory and GacUI_Host) define GACUI_SKIN_DEVELOPMENT to select the matching Generated_<Skin>/Source_x86 or Source_x64 header. Linux development vmake inputs define the same macro. Without it, canonical config headers include the merged release Source header. CodePack ignores development branches and includes each Config folder in its own skin pair. The release workflow first packs current sources and builds/deploys GacGen and GacBuild, which do not depend on skins. It then regenerates both skins through native orchestration and packs the final release, preserving the config files throughout.

SetColorPackage affects subsequent template construction. FullControlTest raises PaletteSelected(int) from its palette radios, following TuiControlTest. Its manually maintained Generated_FullControlTest/FullControlTestPalette.h/.cpp owns demo::OnPaletteSelected, which queues preset creation, installation and GuiApplication::RefreshThemes() together after input dispatch. Every showcase entry point attaches that shared handler. All presets are always available; DarkSkin has no selector callback, plugin or availability state. GacUI_Host loads the showcase from Workflow binary and uses native DarkSkin from Lib_GacUI_App_Reflection, attaching the same handler through reflection. DarkSkin document templates construct palette-based baseline overrides, retaining dark text defaults and document state across refresh.

Debugging Remote Protocol Issues

Use REPO-ROOT/.github/Jobs/DebugRemoteProtocolSop.md for the shared end-to-end UI operations and observable results.

Remote protocol is involved in three ways:

  • Core with native renderer: REPO-ROOT/.github/Jobs/DebugRemoteProtocolWithNativeRenderer.md.
  • Core with GacJS: REPO-ROOT/.github/Jobs/DebugRemoteProtocolWithGacJS.md.
  • UnitTest, some e2e test cases are running on top of a unit test only remote protocol renderer, which is designed to save snapshots of UI between frames at REPO-ROOT/Test/Resources/UnitTestSnapshots.

Running core always uses network protocols. Three ways are calling three different renderer implementations, but with the same core implementation. By careful tell if a bug repro in some or all three ways, you can easily narrow down the scope of the possible cause.

Remote Protocol HTTP Disconnection Contract

  • The HTTP remote protocol consists of /Connect, /Request, and /Response. Do not add a reverse /Disconnect endpoint or require a renderer-to-core shutdown handshake.
  • A renderer can close independently while the core remains available, and another renderer can connect later. If a new renderer connects while an old renderer is still active, accepting the new renderer drops the old connection and token.
  • HTTP 404 on an old renderer request after replacement means that renderer's connection is no longer active. After a VlppOS channel has connected, its IChannelClient implementation promotes this and every other local protocol error to a fatal local channel error because delivery is no longer reliable.
  • If the core has exited, an error from an outstanding or subsequent renderer request, including 404 or another transport failure, is handled by the same channel-level fatal transition. The renderer acts on that callback directly, without requiring OnDisconnected, stops emitting requests, and presents its ordinary disconnected state rather than a fatal transport prompt.
  • Core shutdown does not wait for a renderer acknowledgement. Requests that reach the core while it is still serving should receive their normal protocol response when possible; errors after the core has stopped are expected.

Maintaining Test Apps

Test apps means CppTest* and RemotingTest*, they are demos and do not require production level quality. No need to gracefully handle any exception, actually we need them to just crash when anything unexpected thing happens, that's how we know anything in REPO-ROOT/Source is going wrong. REPO-ROOT/.github/Jobs/DebugRemoteProtocolSop.md defines the expected behavior of these test apps apon connection/disconnection. Any test app starting a FullControlTest is recommended to be tested following the "## Complete Control Showcase (/FCT)" section of REPO-ROOT/.github/Jobs/DebugRemoteProtocolSop.md. Any test app starting a TuiControlTest is recommended to be tested following REPO-ROOT/.github/Jobs/DebugTuiControlTestSop.md. Keep test apps simple without introducing unnecessary "gracefully recovering".

Windows Specific

UI Automation verification and maintenance

Whenever Test/Resources/App/FullControlTest changes, update and run Test/UIA_CppTest.ps1 and Test/UIA_CppTest_Metaonly.ps1 so the showcase and its UIA expectations stay synchronized. The entry wrappers share launch/cleanup logic in Test/UIA_CppTest_Shared.ps1 and assertions in Test/UIA_CppTest_Shared.cs. Add targeted role, name, pattern, state and bounds assertions for new behavior; generic tab traversal alone is insufficient. The Easy Layout checks cover its five mixed docking controls, selection/toggling, equal outer heights, resizing, rebuilding and palette refresh.

Both entry wrappers accept -Scenario ResponsiveWindow for focused ribbon-document resizing, responsive view/stack/group levels, and Easy Layout responsive modal checks. These include repeated row-height contraction, resizing while scrolled near the end, selection and reopening. This scenario omits palette cycles and unrelated page navigation. Use -SkipBuild after a successful build of the current source.

Use Windows with the UIAutomationClient/UIAutomationTypes assemblies, an out-of-process MTA client and rebuilt Debug x64 binaries. The wrappers build and launch fresh processes, preserve project user arguments and shut down their owned processes. Test/UIA_CppTest.ps1 -AsPort 8888 exercises hosted logical windows sharing one HWND; Test/UIA_CppTest_Metaonly.ps1 -AsPort 8890 exercises ordinary native windows. Inspect owned HWNDs with EnumWindows when MainWindowHandle is unavailable, and check for native runtime-error dialogs after timeouts. Desktop focus and multi-monitor DPI checks require a suitable interactive session; record unavailable coverage explicitly.

Tools/UiaList is the native UIA inspector. Read Tools/UiaList/AGENTS.md and Tools/UiaList/Verification/README.md, build its separate solution with the repository wrapper, and use Tools/UiaList/Verification/Inspector.ps1 for geometry-based inspection. Its automation endpoint is Debug-only: run with /AsPort:8891 and use http://localhost:8891/Automation/UiaListApp/Controls and /IO beside CppTest on 8888 and CppTest_Metaonly on 8890. The verification fixture and Smoke.ps1 -GetterRegression check explicit refresh, cached presentation, edits/readback and asynchronous generations. Use UiaList's preview and Nodes view to review showcase changes; preview clicks select cached nodes without sending target input.

Application automation

Automation HTTP service for GUI applications are available for Windows:

  • CppTest : Run FullControlTest in hosted mode, built without reflection (VCZH_DEBUG_NO_REFLECTION).
  • CppTest_Tui : Run TuiControlTest in Windows Terminal using TuiSkin and the hosted TUI provider, built without reflection. It has no automation endpoint. Follow DebugTuiControlTestSop.md.
  • CppTest_Rvm : Run RemoteViewModelTest in hosted mode after acquiring its service from RemotingTest_RvmHost; /Cli:<path> auto-launches that host with /Cli.
  • CppTest_Metaonly : Run FullControlTest, built with metaonly reflection (VCZH_DEBUG_METAONLY_REFLECTION).
  • CppTest_Reflection : Run FullControlTest, built with full reflection.
  • GacUI_Host : Run FullControlTest, by loading Workflow binary assembly instead of generated C++ code.
  • Playground : Run REPO-ROOT/Test/GacUISrc/Playground/Resources/Resource*.xml, resource file to load specified, main window specified in OpenMainWindow function.
  • RemotingTest_Core : Run FullControlTest, RemoteProtocolTest, or RemoteViewModelTest with renderer traffic hosted by HTTP, MiniHTTP, or NamedPipe; /RVMT may independently use /Cli:<path> for its host.
  • RemotingTest_Rendering_Win32 : Renderer of RemotingTest_Core.
  • RemotingTest_RvmHost : Provide the remote view-model service used by CppTest_Rvm and RemotingTest_Core /RVMT, including the stdio /Cli mode.

After building Debug x64, use the repository-relative launchers under Test:

  • StartCore.ps1 -App cpptest_rvm|fct|rpt|rvmt -Protocol http|pipe|minihttp [-Cli] [-AsPort <1-65535>] starts CppTest_Rvm or RemotingTest_Core. -Cli is valid only for cpptest_rvm and rvmt; without it, those two app modes start their required RemotingTest_RvmHost manually one second after the requester/Core. The automation port defaults to 8888.
  • StartRendrerer.ps1 -Protocol http|pipe|minihttp [-AsPort <1-65535>] starts RemotingTest_Rendering_Win32 with an explicit /AsPort:8889 by default, allowing it to run beside Core. The executable itself defaults to 8888. The file name intentionally preserves the requested Rendrerer spelling.
  • Both launchers use Test/GacUISrc/x64/Debug, start visible processes for interactive testing, and return their System.Diagnostics.Process objects for inspection or cleanup.

FullControlTest means Generated_FullControlTest.vcxitems, generated from REPO-ROOT/Test/Resources/App/FullControlTest/Resource.xml. TuiControlTest means Generated_TuiControlTest.vcxitems, generated from REPO-ROOT/Test/Resources/App/TuiControlTest/Resource.xml. Its skin is Generated_TuiSkin.vcxitems, which compiles the canonical, manually maintained Source/Skins/TuiSkin/Config/TuiSkinConfig.h/.cpp exactly once for each consumer. GacUI_Compiler also generates Source/Utilities/FakeServices/TuiDialogs/Source; run the same metadata generation steps after these resource changes. The release pipeline mirrors TuiSkin XML into Source/Skins/TuiSkin, generates its Source folder, preserves its canonical Config folder, and publishes TuiSkin/TuiSkinReflection. Configuration must not be recreated under Generated_TuiSkin or the release-generated Source folder. RemoteProtocolTest means Generated_RemoteProtocolTest.vcxitems, generated from REPO-ROOT/Test/Resources/App/RemoteProtocolTest/Resource.xml. RemoteViewModelTest means Generated_RemoteViewModelTest.vcxitems, generated from REPO-ROOT/Test/Resources/App/RemoteViewModelTest/Resource.xml. When FakeDialogService is used, all system dialogs are replaced by REPO-ROOT/Source/Utilities/FakeServices/Dialogs/Resource.xml. For the non-remoting projects above, the automation endpoint is http://localhost:8888/Automation/<PROJECT-NAME>/... and is hosted by StartWindowsHttpAutomationService.

  • CppTest, CppTest_Metaonly, CppTest_Reflection, GacUI_Host, Playground, CppTest_Rvm, RemotingTest_Core, RemotingTest_Rendering_Win32, and UiaListApp accept one /AsPort:<decimal port> in 1..65535, default 8888. Invalid, empty, duplicate, and out-of-range values fail before starting listeners. UiaList exposes its endpoint only in Debug. Assign distinct ports to run independent automation endpoints simultaneously; for example CppTest 8888, CppTest_Metaonly 8890, and UiaListApp 8891.
  • The remote protocol port is always 8888 for /Http and /MiniHttp, regardless of /AsPort. Named pipe and stdio endpoints are unchanged. Multiple protocol servers still cannot own the same fixed transport endpoint.
  • Checkout REPO-ROOT/.github/Guidelines/Running-GacUI.md for details.

Each application owns its automation stack directly. It constructs the concrete service matching its setup (WindowsAutomationService, WindowsAutomationServiceHosted, WindowsAutomationServiceRenderer, RemoteProtocolAutomationService, or a platform renderer service), substitutes it, starts the selected Windows HTTP or MiniHTTP endpoint, runs the application, then stops the endpoint and service before unsubstituting it. Both endpoint implementations expose the same Controls, Dom, and IO contract.

Both RemotingTest_Core and RemotingTest_Rendering_Win32 expose automation in /Http, /Pipe, and /MiniHttp modes:

  • RemotingTest_Core exposes the UI as a window-control tree at http://localhost:8888/Automation/RemotingTest_Core/....
  • RemotingTest_Rendering_Win32 exposes the UI as a DOM tree at http://localhost:<renderer-port>/Automation/RemotingTest_Rendering_Native/.... Pass /AsPort:<renderer-port> to select the automation port; omitting it selects 8888. Paired examples must explicitly use /AsPort:8889 or another free port.
  • /Http and /Pipe use StartWindowsHttpAutomationService.
  • In /MiniHttp mode, Core and CppTest_Rvm share their protocol socket when /AsPort:8888 is selected. Another automation port creates a separately owned MiniHTTP socket, stopped with the automation endpoint while preserving protocol shutdown order. The renderer always owns a separate automation socket. Its protocol client still connects to port 8888.
  • Both support IO operations:
    • When performing IO via the renderer, remote protocol events pass the IO operations to the core.
    • When performing IO via the core, the renderer only receives UI updates and redraws.
    • Core and renderer should synchronize to the same UI state afterwards.
    • Performing IO through either the renderer or the core should result in the same UI state.

RVM RPC uses the exact logical channels ViewModelChannel and ViewModelReadyChannel; renderers use GacUIRemoteProtocol. Core-to-renderer transport and Core-to-host mode are separate dimensions:

  • Without /Cli, RemotingTest_Core /RVMT and its manually started RemotingTest_RvmHost share the selected /Pipe, /Http, or /MiniHttp server. Start Core, then the host with the same selector, then start the renderer after Core automation contains Remote View Model Test.
  • With /Cli:<nonempty-host-path>, Core still requires /RVMT and one renderer transport. It starts a renderer-only server plus a host-only stdio server, quotes the path, and auto-launches RemotingTest_RvmHost /Cli; do not start that host manually. Stop order is host server first, renderer server second.
  • A process launcher may pass /Cli:<path> directly or pass the single literal argument /Cli:"<path>". RemotingTest_Core and CppTest_Rvm remove exactly one balanced quote pair around the path and reject empty or unmatched quoted values; the path remains one executable, never a command plus arguments.
  • CppTest_Rvm accepts exactly one of /Pipe, /Http, /MiniHttp, or /Cli:<nonempty-host-path>. The first three wait for a manually started host using the same selector. /Cli auto-launches the host and is itself the exclusive RVM transport. This variant never uses a renderer.
  • RemotingTest_RvmHost accepts exact /Cli in addition to its network selectors. In stdio mode, stdin/stdout are reserved for framed protocol traffic and the ordinary startup banner is suppressed.
  • A requester terminates with an error if RemotingTest_RvmHost disconnects while the application is running.
  • CppTest_Rvm exposes automation at http://localhost:<AsPort>/Automation/CppTest_Rvm/.... /Pipe, /Http, and /Cli use the Windows HTTP endpoint; /MiniHttp shares the protocol socket only when the selected automation port is 8888.

Playground is for adhoc testing:

  • Playground is for trying UI from XML. All UI, including controls, layout, document content and interaction behavior, must be implemented in XML resources and their Workflow scripts, not constructed in C++. C++ may provide native interop hooks that the scripts call.
  • The UI in resource file, including GuiMain and OpenMainWindow, could be modified freely without any concern, it is not part of the release. DO NOT revert Playground change as I can also use it for manual verification.
  • Actual resource files to load is specified in GuiMain. Loading one candidate at a time by editing this function is sufficient; no command-line fixture selector is required.
  • Actual theme type and main window type is specified in OpenMainWindow.
  • All candidate resource files to load are supposed to put in the same folder, and add to the same solution explorer folder in Playground project.

Linux/macOS Specific

<GacUI repo>/Test/Linux stores Linux configurations for:

  • Metadata_Generate: <GacUI repo>/Test/Linux/Metadata_Generate/vmake.
  • Metadata_Test: <GacUI repo>/Test/Linux/Metadata_Test/vmake.
  • GacUI_Compiler: <GacUI repo>/Test/Linux/GacUI_Compiler/vmake.
  • RemotingTest_Core: <GacUI repo>/Test/Linux/RemotingTest_Core/vmake.
  • RemotingTest_RvmHost: <GacUI repo>/Test/Linux/RemotingTest_RvmHost/vmake.
  • UnitTest: <GacUI repo>/Test/Linux/UnitTest/vmake.
  • WasmFCT: <GacUI repo>/Test/Linux/WasmFCT/vmake.
  • WasmRPT: <GacUI repo>/Test/Linux/WasmRPT/vmake.
  • WasmRVMT: <GacUI repo>/Test/Linux/WasmRVMT/vmake.

<GacUI repo>/Tools stores Linux configurations for:

  • GacBuild: <GacUI repo>/Tools/GacBuild/vmake.
  • GacGen: <GacUI repo>/Tools/GacGen/vmake.
  • GitTui: <GacUI repo>/Tools/GitView/Linux/GitTui/vmake.
  • GitViewTests: <GacUI repo>/Tools/GitView/Linux/GitViewTests/vmake.

Metadata_UpdateProtocol is not included. If it is needed, create it and remove this line.

You need to build, test and debug in that specific folder, otherwise the unit test will not function properly. On Linux, only configuration "debug x64" is available, no need to build or run projects with other configurations. Unlike Windows, building have to be done in each folder separately.

The Unix unit-test entry point uses the environment locale for wide console output, including Unicode test names. Run it with an installed UTF-8 locale; on macOS, use LC_ALL=en_US.UTF-8 ./Bin/UnitTest /C if the inherited locale is unavailable.

CppTest_Rvm is Windows-only in this solution. The portable RVM demo is RemotingTest_Core /RVMT with /MiniHttp for renderers; its host is either manually started with /MiniHttp or auto-launched with /Cli:<path>. Linux/macOS stdio code is supplied by the imported VlppOS.Linux.cpp.

It is expected if makefile and vmake.txt is changed due to build any project, they should be included in the commit for manually updated files, do not revert them.

WebAssembly

The Linux-only browser demos Test/Linux/WasmFCT, WasmRPT and WasmRVMT run FullControlTest, RemoteProtocolTest and RemoteViewModelTest. Build each from its directory with ../../../.github/Ubuntu/build.sh -bw -o. They use VCZH_DEBUG_NO_REFLECTION, the merged DarkSkin sources in Source/Skins/DarkSkin/Source, the demos' generated x86 sources and -O3. Shared composition lives in Test/Linux/Wasm; the test-only transport lives in Test/RemotingHelpers/RemotingServer/Wasm and is not added to MSBuild projects.

Each demo produces Bin/app.mjs, Bin/app.wasm and Bin/app.worker.js. These are required by GacJS but remain ignored build artifacts; build them when missing. Keep the minimal vbuild Wasm opt-in. Packaging preserves Emscripten's generated module unchanged; its default factory loads the adjacent pthread worker, which imports the adjacent module. GacJS's wasm-worker.js hosts the application and is distinct from this generated app.worker.js. After building GacJS, run its copy-wasm.sh explicitly and start the entry website. /wasm-fct/, /wasm-rpt/ and /wasm-rvmt/ own independent worker/module lifetimes; RVMT hosts its TypeScript view model in the page. Follow .github/Jobs/job.rpWasm.prompt.md for the build and browser verification procedure.

StartApplication installs the fixed transport connections during startup; SendDataToWasmCore carries their channel traffic. These are the only application Embind exports. After normal Core shutdown, Reload becomes enabled and reloads the page, creating a fresh Core, renderer and view-model host with no retained application state. Reload stays disabled during startup, operation, canceled Exit and fatal errors.

The same three projects also support ../../../.github/Ubuntu/build.sh -f -o as native CLI compile/link checks. Their VCZH_GCC entry point returns 0 without starting GacUI. The full source inventory is linked, using x64 demo sources for native builds and x86 for Wasm, while both use the merged DarkSkin sources. Native full builds clean Bin; rebuild with -bw -o before copying the Wasm outputs to GacJS.

The following unit test projects could be built to web assembly and run with a browser:

  • REPO-ROOT/Test/Linux/UnitTest

The browser build selects the generated 32-bit skins and compiler baselines and uses the shared Ubuntu tools' -O3 setting for compilation and linking. Its vbuild preloads test inputs into OPFS and creates an empty Resources/UnitTestSnapshots output folder; existing host snapshots are not input fixtures. Debug information is stored in app.debug.wasm, with a relative reference in app.wasm for automatic discovery. Exceptions and assertions remain enabled. Native builds default to -O0; add -o or --optimize to select -O2 for native unit tests.

The terminal provider and test cases in TestTuiProvider.cpp and TestControls_EasyLayout.cpp are native-only and excluded from WebAssembly. The shared XML fixture helper remains available to resource tests.