Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/desktop-e2e-hosted.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
description: 'Test depth: Quick, Full with exit/restart, or 30-minute Soak'
type: choice
options: [Quick, Full, Soak]
default: Quick
default: Full
seed:
description: 'Soak random seed; leave empty to generate one'
type: string
Expand Down Expand Up @@ -40,11 +40,11 @@ concurrency:

jobs:
desktop:
name: Desktop E2E (${{ inputs.profile || (github.event_name == 'schedule' && 'Soak') || 'Quick' }})
name: Desktop E2E (${{ inputs.profile || (github.event_name == 'schedule' && 'Soak') || 'Full' }})
runs-on: windows-2022
timeout-minutes: ${{ (inputs.profile == 'Soak' || github.event_name == 'schedule') && 50 || 15 }}
env:
E2E_PROFILE: ${{ inputs.profile || (github.event_name == 'schedule' && 'Soak') || 'Quick' }}
E2E_PROFILE: ${{ inputs.profile || (github.event_name == 'schedule' && 'Soak') || 'Full' }}
steps:
- uses: actions/checkout@v6
with:
Expand Down
8 changes: 5 additions & 3 deletions docs/desktop-e2e.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ Median, p95 and maximum are diagnostic observations, not compositor presentation
latency or a portable speed benchmark. A switch has a 2-second correctness timeout.

Normal CI compiles this harness with `-BuildOnly`. Actual input tests require
an unlocked interactive Windows desktop. The hosted Quick workflow checks this
an unlocked interactive Windows desktop. The hosted workflow checks this
on GitHub's Windows VM; unusable hosted/service sessions fail rather than skip
or silently report success. The deterministic navigation and modifier
snapshot regressions also run in the regular Architecture suite.
Expand All @@ -240,10 +240,12 @@ snapshot regressions also run in the regular Architecture suite.

`.github/workflows/desktop-e2e-hosted.yml` provides **Desktop E2E Hosted**
on GitHub's `windows-2022` virtual machine, without a local runner. Every pull
request runs Quick as the stable **Desktop E2E (Quick)** check. No path filters
request runs Full as the stable **Desktop E2E (Full)** check, the same profile
the release runs, so a defect that only appears after restart fails the pull
request rather than the release; it adds about a minute over Quick. No path filters
skip this check. Soak runs every day at 18:00 UTC on the default branch, which
also catches changes in the hosted Windows image, and manual dispatch offers
Quick, Full or Soak. These runs build their own Release binary. The release
Quick, Full (default) or Soak. These runs build their own Release binary. The release
workflow calls the same workflow with Full and `executable-artifact`, so it tests
the very `WindowTabs.exe` the draft will carry; the draft is created only after
the regression suites, the smoke test, the version check and that run all pass.
Expand Down
6 changes: 3 additions & 3 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ The separate [desktop E2E suite](desktop-e2e.md) exercises the actual Release
entry point, real mouse drag grouping, frequent foreground switching, maximized
tabs, closing the active window, tray-menu exit and restart. It requires an idle
interactive desktop and is not part of the focus-safe default suite.
GitHub's separate **Desktop E2E Hosted** workflow runs Quick on pull requests
using an isolated `windows-2022` VM; manual Full verifies exit/restart and 1,320
switches. Both profiles have passed on hosted runners. See the linked E2E guide
GitHub's separate **Desktop E2E Hosted** workflow runs Full on pull requests
using an isolated `windows-2022` VM, verifying exit/restart and 1,320 switches
like the release does; Quick remains a manual choice. See the linked E2E guide
for run evidence, activation requirements and remaining limitations.

| Risk | Existing evidence | Next validation |
Expand Down
10 changes: 10 additions & 0 deletions tests/DesktopE2E.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ static partial class DesktopE2E
[DllImport("user32.dll")] static extern bool GetGUIThreadInfo(uint thread, ref GuiThread info);
[DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hwnd);
[DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hwnd, int command);
[DllImport("user32.dll", CharSet=CharSet.Unicode)] static extern IntPtr GetProp(IntPtr hwnd, string name);
[DllImport("user32.dll", CharSet=CharSet.Unicode)] static extern IntPtr RemoveProp(IntPtr hwnd, string name);
[DllImport("user32.dll")] static extern bool IsWindow(IntPtr hwnd);
[DllImport("user32.dll")] static extern IntPtr GetWindow(IntPtr hwnd, uint command);
[DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hwnd, int index);
Expand Down Expand Up @@ -512,9 +514,17 @@ static async Task Run(int switches, int cycles, int durationMinutes)
var saved=Json.Deserialize<Dictionary<string,object>>(File.ReadAllText(Path.Combine(Root,"WindowTabsSettings.json")));
Check(saved.ContainsKey("version") && !string.IsNullOrEmpty((string)saved["version"]),"Startup did not persist its settings version");
Check((string)saved["alignment"]=="Left" && !(bool)saved["enableTabbingByDefault"],"Fixture settings were lost");
Check(saved.ContainsKey("rememberedGroups") && Json.Serialize(saved["rememberedGroups"]).Contains("WindowTabs E2E "),"Exit did not remember the dragged group");
Check(!HasCrash(),"Application logged an exception during the cycle");
completed++; Log("PASS: cycle "+completed+"; original entry point, drag grouping, switching, close and normal exit");
// The next cycle reuses the saved portable configuration and reacquires the real singleton.
// Forget the dragged group, in the settings and on the windows themselves, so the
// surviving helpers start apart and are dragged together again.
var survivors=Forms.Where(f=>!f.IsDisposed).ToList();
Check(survivors.All(f=>GetProp(f.Handle,"WindowTabs.Group.v1")!=IntPtr.Zero),"Exit did not keep the group on its windows");
foreach(var f in survivors) RemoveProp(f.Handle,"WindowTabs.Group.v1");
saved.Remove("rememberedGroups");
File.WriteAllText(Path.Combine(Root,"WindowTabsSettings.json"),Json.Serialize(saved));
}
}
[STAThread] static int Main(string[] args)
Expand Down
Loading