- 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.mdand 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.ps1and<Tools repo>/Tools/GacGen.ps1: the canonical GacGen/GacBuild guidance above.REPO-ROOT/Tools/UiaList:- Update
REPO-ROOT/.github/KnowledgeBase/KB_GacUI_Design_UiaList.mdfor UiaListApp usage. - This tool is Windows only, check out
REPO-ROOT/Tools/UiaList/AGENTS.mdif and only if you are working on it.
- Update
REPO-ROOT/Tools/GitView:- Update
REPO-ROOT/.github/KnowledgeBase/KB_GacUI_Design_GitTui.mdfor GitTui usage. - This tool is cross platform, check out
REPO-ROOT/Tools/GitView/AGENTS.mdif and only if you are working on it.
- Update
- 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.
- Build
<GacUI repo>/Tools/GacBuild/GacBuild.slnand<GacUI repo>/Tools/GacGen/GacGen.slnwith the repository build wrapper. Both provide Debug/Release and Win32/x64 configurations. GacBuild produces<GacUI repo>/Tools/GacBuild/Bin/GacBuildD.exeorGacBuild.exe; GacGen produces the corresponding executables under<GacUI repo>/Tools/GacGen/Bin. Native Unix builds use<GacUI repo>/Tools/GacBuild/vmakeand<GacUI repo>/Tools/GacGen/vmake. - GacBuild requires
-mode:GacBuildor-mode:GacGen, explicit normalized absolute-pathGacGenand-pathCppMerge, and-FileName. The former accepts-Dump; the latter accepts-MappingFileName. Named dependency ordering usesPartialOrderingProcessor; 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
/P32and/P64stage outputs and write UTF-8Deploy.xmlmanifests. GacBuild validates both architectures, merges C++, then copies the manifests with x32 last for shared neutral outputs. Direct/C32and/C64still publish configured outputs. - Run
<GacUI repo>/Tools/GacBuild/Verification.ps1 -Baselinefor focused Windows integration coverage. It uses the repository CLI wrapper, keeps fixtures in the ignored toolBindirectory, 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.
You are working on the solution REPO-ROOT/Test/GacUISrc/GacUISrc.sln,
therefore SOLUTION-ROOT is REPO-ROOT/Test/GacUISrc.
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/MetadataREPO-ROOT/Test/GacUISrc/Generated_DarkSkinREPO-ROOT/Test/GacUISrc/Generated_TuiSkin/Source_x86andSource_x64REPO-ROOT/Test/GacUISrc/Generated_TuiSkin/Resource_x86andResource_x64REPO-ROOT/Test/GacUISrc/Generated_TuiDialogsREPO-ROOT/Test/GacUISrc/Generated_TuiControlTest/Source_x86andSource_x64REPO-ROOT/Test/GacUISrc/Generated_TuiControlTest/Resource_x86andResource_x64REPO-ROOT/Test/GacUISrc/Generated_DialogsREPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Source_x86andSource_x64REPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Resource_x86andResource_x64REPO-ROOT/Test/GacUISrc/Generated_RemoteProtocolTestREPO-ROOT/Test/GacUISrc/Generated_RemoteViewModelTestREPO-ROOT/Test/GacUISrc/Generated_UnitTestViewerREPO-ROOT/Source/Utilities/FakeServices/Dialogs/SourceREPO-ROOT/Source/Utilities/FakeServices/TuiDialogs/SourceREPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/SourceREPO-ROOT/Source/Compiler/InstanceQuery/GeneratedREPO-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.
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 intoRelease/GacUI.handRelease/GacUI.cpp.Windows/WindowsAutomationService.Windows.*is CodePacked intoRelease/GacUI.Windows.handRelease/GacUI.Windows.cpp.- Standalone test applications receive these implementations through their GacUI library dependency; they do not import
Source_RemotingHelpersfor automation.
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
Sourcecannot use anything inTest/RemotingHelpers. - They are excluded from ordinary public GacUI amalgamations and the aggregate
Release/Importproduction snapshot. GacUI CodePack emits the dedicated neutralTest.RemotingHelperspair inReleaseandRelease/IncludeOnly;UpdateReleasecopies the root pair and its README to the aggregateRelease/Import-Testsnapshot. 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.
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.vcxitemsinventory shared by all helper consumers. ViewModelShared.howns generic aliases, fixed RVM channel/control constants, and inline Ready-message helpers;ViewModelHostClient.*owns the generic network-side host client; andViewModelHostServer.*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.xmlscans this helper tree only into the dedicated test pairs. OrdinaryGacUI*pairs and the aggregateRelease/Importproduction snapshot remain independent of these helpers.
- 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.
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.
This executable needs to run if any file in the following folders are changed:
REPO-ROOT/Source/Compiler/InstanceQuery/SyntaxREPO-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 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:
These two projects need to run if any reflection code is touched:
GuiReflection*.cppis updated.GacUI_Compilerproject is executed.
To execute these projects, you should:
- Build the solution with Debug|Win32.
- Run
Metadata_Generatewith Debug|Win32. - Build the solution with Debug|x64.
- Run
Metadata_Generatewith Debug|x64. - Run
Metadata_Testwith 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.
This project need to run if REPO-ROOT/Source/PlatformProviders/Remote/Protocol/*.txt is updated.
It generates REPO-ROOT/Source/PlatformProviders/Remote/Generated/*.
This project need to run if any of the following XML file is updated:
REPO-ROOT/Source/Utilities/FakeServices/Dialog/*.xml-> generatesREPO-ROOT/Source/Utilities/FakeServices/Dialog/Source/*.REPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/*.xml-> generatesREPO-ROOT/Source/UnitTestUtilities/SnapshotViewer/Source/*.REPO-ROOT/Test/Resources/App/DarkSkin/*.xml-> generatesREPO-ROOT/Test/GacUISrc/Generated_DarkSkin/Source_(x86|x64)/*.- IMPORTANT:
REPO-ROOT/Source/Skins/DarkSkinhas another copy, this is used by the CI and is not involved in this solution, ignore it.
- IMPORTANT:
REPO-ROOT/Test/Resources/App/FullControlTest/*.xml-> generatesREPO-ROOT/Test/GacUISrc/Generated_FullControlTest/Source_(x86|x64)/*.REPO-ROOT/Test/Resources/App/RemoteProtocolTest/*.xml-> generatesREPO-ROOT/Test/GacUISrc/Generated_RemoteProtocolTest/Source_(x86|x64)/*.REPO-ROOT/Test/Resources/App/RemoteViewModelTest/*.xml-> generates ordinary and RPC C++ inREPO-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_Compilersucceeds the next time, they will be gone. GacUI_Compilermay also fail by printing one line of error message or return non-zero exit code. If the*.UI.errors.txtfile does not exist, you are recommended to debug the project to find out what happened.- Whenever
GacUI_Compilerreports any error, you must fix the issue immediately, even those errors are unrelated to the issue you are working on.
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_Compilerand 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.
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 atREPO-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.
- The HTTP remote protocol consists of
/Connect,/Request, and/Response. Do not add a reverse/Disconnectendpoint 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
IChannelClientimplementation 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.
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".
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.
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 fromRemotingTest_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: RunREPO-ROOT/Test/GacUISrc/Playground/Resources/Resource*.xml, resource file to load specified, main window specified inOpenMainWindowfunction.RemotingTest_Core: Run FullControlTest, RemoteProtocolTest, or RemoteViewModelTest with renderer traffic hosted by HTTP, MiniHTTP, or NamedPipe;/RVMTmay independently use/Cli:<path>for its host.RemotingTest_Rendering_Win32: Renderer ofRemotingTest_Core.RemotingTest_RvmHost: Provide the remote view-model service used byCppTest_RvmandRemotingTest_Core /RVMT, including the stdio/Climode.
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>]startsCppTest_RvmorRemotingTest_Core.-Cliis valid only forcpptest_rvmandrvmt; without it, those two app modes start their requiredRemotingTest_RvmHostmanually one second after the requester/Core. The automation port defaults to 8888.StartRendrerer.ps1 -Protocol http|pipe|minihttp [-AsPort <1-65535>]startsRemotingTest_Rendering_Win32with an explicit/AsPort:8889by default, allowing it to run beside Core. The executable itself defaults to 8888. The file name intentionally preserves the requestedRendrererspelling.- Both launchers use
Test/GacUISrc/x64/Debug, start visible processes for interactive testing, and return theirSystem.Diagnostics.Processobjects 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, andUiaListAppaccept 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
/Httpand/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.mdfor 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_Coreexposes the UI as a window-control tree athttp://localhost:8888/Automation/RemotingTest_Core/....RemotingTest_Rendering_Win32exposes the UI as a DOM tree athttp://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:8889or another free port./Httpand/PipeuseStartWindowsHttpAutomationService.- In
/MiniHttpmode, Core and CppTest_Rvm share their protocol socket when/AsPort:8888is 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 /RVMTand its manually startedRemotingTest_RvmHostshare the selected/Pipe,/Http, or/MiniHttpserver. Start Core, then the host with the same selector, then start the renderer after Core automation containsRemote View Model Test. - With
/Cli:<nonempty-host-path>, Core still requires/RVMTand one renderer transport. It starts a renderer-only server plus a host-only stdio server, quotes the path, and auto-launchesRemotingTest_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_CoreandCppTest_Rvmremove 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_Rvmaccepts exactly one of/Pipe,/Http,/MiniHttp, or/Cli:<nonempty-host-path>. The first three wait for a manually started host using the same selector./Cliauto-launches the host and is itself the exclusive RVM transport. This variant never uses a renderer.RemotingTest_RvmHostaccepts exact/Cliin 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_RvmHostdisconnects while the application is running. CppTest_Rvmexposes automation athttp://localhost:<AsPort>/Automation/CppTest_Rvm/..../Pipe,/Http, and/Cliuse the Windows HTTP endpoint;/MiniHttpshares 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
GuiMainandOpenMainWindow, could be modified freely without any concern, it is not part of the release. DO NOT revertPlaygroundchange 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
Playgroundproject.
<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.
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.