-
Notifications
You must be signed in to change notification settings - Fork 0
CrossPlatform SmokeTests
Companion: Cross-Platform Implementation Plan · Cross-Platform Roadmap · Technical Index
Created 2026-06-12 for branch
feature/cross-platform-full. Lists the manual user-visible checks that round out each phase's exit criteria. CI builds every assembly on the Linux + macOS legs; these procedures verify the runtime end-to-end on a real desktop before each phase is closed.Run them on every supported host before the corresponding phase PR merges to
main. The host matrix matches the roadmap:linux-x64(Ubuntu 24.04 GNOME Wayland + X11),linux-arm64(Raspberry Pi OS),osx-arm64(macOS Sonoma on Apple Silicon), andosx-x64(Intel macOS).win-x64is covered implicitly by the WinExe regression and does not need re-running here.
-
dotnet run --project FracturingFog.App -- --batch --image --out /tmp/smoke.png --width 800 --height 600 --maxiter 256. - Confirm exit code 0 and
/tmp/smoke.pngexists. - Open the file in the host's default image viewer; confirm the Mandelbrot render looks correct (no inverted alpha, no swapped colour channels).
-
file /tmp/smoke.pngreportsPNG image datawith the expected dimensions.
-
dotnet run --project FracturingFog.App -- --batch --slideshow --out /tmp/slides --frames 8 --width 640 --height 480. - Confirm eight
frame_NNNNNN.pngfiles land in/tmp/slides/with strictly increasing colours / view drift. - Spot-check
file /tmp/slides/frame_000001.pngfor sane metadata.
- Interactive: open the App, enable Watermark from the menu, render a frame.
- Confirm the watermark text is legible (font fell back to Inter or a system sans-serif), outline + fill render in the configured colours.
- Save the frame via "Save Image…" — confirm the saved PNG has the watermark baked in.
- Launch the App. Open the audio-reactive slideshow settings dialog.
- Confirm the source picker is present and System loopback + Microphone appear in the list with reduced opacity (dim, not removed).
- Confirm the yellow
#FFCC00banner at the top of the dialog reads "System audio capture is not supported on this OS." (or the localised variant) — verifying the colourblind-safe warning hue.
- Pick File as the source; browse to a known-good WAV or MP3 (NAudio handles both cross-platform via the file-decode path).
- Start the audio-reactive slideshow.
- Confirm the slideshow advances on beat detections (theme/region switches coincide with audible kicks). The BPM readout in the settings dialog should show a non-zero value within ~5 s of playback start.
- Stop the slideshow — confirm clean shutdown (no zombie audio threads;
ps/topshows the process CPU drops to idle).
- Pick Synth as the source.
- Start the audio-reactive slideshow.
- Confirm the slideshow advances on the synthesised beat pattern; no speaker output is expected (the noop backend routes the synth into the analyzer only).
- Stop and confirm clean shutdown.
- Open
FracturingFog.App(orPaletteBuilderstandalone). Open the palette builder; load a source image (PNG / JPEG fromResources/Samples/works). - Extract a palette (any method).
- Export → choose PNG sheet, save to
/tmp/palette.png. - Open
/tmp/palette.pngin a viewer; confirm the 1-column strip of swatch tiles renders with legible#HEX RGB(r, g, b)labels in luma-aware contrast (white text on dark swatches, black on light). Fallback font is acceptable if the host lacks Consolas.
- Same source image + extracted palette as 1.S1.
- Export → choose PDF document. Open the PDF settings dialog.
- Tick every option (cover page, source thumbnail, comparison page, gradient strip, swatch metadata, CVD rows). Pick A4 portrait, 2 columns.
- Save to
/tmp/palette.pdf. - Open
/tmp/palette.pdfin the host's default PDF viewer.- Cover page: source thumbnail centred, "Method:" + settings dump readable.
- Comparison page (if multiple extractors ran): one row per method, swatch strip + gradient under it.
- Swatch grid pages: 2-column tile layout, RGB / hex plate centred on each swatch, metadata block under each, CVD strip (Proto / Deut / Trito) under that, gradient strip footer on every page, "page N of M" in the header.
- Confirm no QuestPDF licence-violation watermark appears (Community licence set in the static ctor before any document renders).
- Export PDF with zero swatches (extract from a uniform-colour image with the count knob set to 0 if the UI allows, or remove all rows manually).
- Confirm
<PaletteName> — (empty)page renders; PDF opens without error.
Procedures land with Phase X.2 implementation. Outline:
- 1.S1 with
--videoflag: 100-frame slideshow renders to MP4 viaFfmpegVideoWriteron Linux/macOS when ffmpeg is on PATH. - 1.S2: "Install ffmpeg" instructions panel appears when ffmpeg is missing; rescan PATH button reflects post-install state without an app restart.
Run from a clean checkout:
dotnet publish FracturingFog.App -c Release -p:PublishProfile=linux-x64
dotnet publish FracturingFog.App -c Release -p:PublishProfile=linux-arm64
dotnet publish FracturingFog.App -c Release -p:PublishProfile=osx-arm64
dotnet publish FracturingFog.App -c Release -p:PublishProfile=osx-x64
dotnet publish FracturingFog.App -c Release -p:PublishProfile=win-x64
Each command emits a self-contained single-file archive under
FracturingFog.App/publish/<rid>/. Confirm:
- Archive present + non-empty (Win archives bundle ffmpeg.exe per Slice 2.4).
- Quick sanity launch on the matching host:
./FracturingFog.Appopens the Avalonia shell;./FracturingFog.App --batch --image --out /tmp/smoke.png --width 320 --height 240round-trips a PNG.
Resolved publish blocker (CalculatorGen + ColorGen NETSDK1150).
Historical: until CalculatorGen and ColorGen were split into Lib + Cli sibling projects, the App's self-contained publish tripped NETSDK1150 because both Exe projects were referenced transitively as libraries via UI.Avalonia. The split landed via:
-
CalculatorGen.Lib+ColorGen.Libsibling library projects hold the*Api,*HotLoad, Parser/, Emitters/ source plus the embedded templates. Source physically still lives under the originalCalculatorGen/andColorGen/directories; the Lib csproj pulls it viaCompile Include="..\<dir>\**\*.cs". -
CalculatorGen.csproj+ColorGen.csprojare now thin CLI Exes that disable the default Compile glob and pull onlyProgram.cs,ProjectReferencethe sibling Lib. -
UI.Avalonia.csproj+FracturingFogCLD.csprojreference the Lib projects, not the Exes.
dotnet publish FracturingFog.App -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true now succeeds end-to-end
on a Windows host. Publish artifacts ship via the CI release workflow
(Slice 6.4) where the GitHub runner builds against a clean restore and
the publish profile drives a fresh single-RID closure.
After dotnet publish -p:PublishProfile=linux-x64:
Tools/Packaging/build-appimage.sh linux-x64
Confirm dist/FracturingFog-linux-x64.AppImage exists and is executable
(./dist/FracturingFog-linux-x64.AppImage opens the shell).
After dotnet publish -p:PublishProfile=osx-arm64:
Tools/Packaging/build-mac-app.sh osx-arm64
Confirm dist/FracturingFog.app/Contents/MacOS/FracturingFog.App is
executable and Info.plist parses (plutil -lint dist/FracturingFog.app/Contents/Info.plist). Code-signing is a separate
manual step until Apple Developer cert lands.
These Silk smoke runs are marked continue-on-error: true in
.github/workflows/cross-platform-build.yml so the leg's build signal
still gates merges. Each is a runner-infrastructure gap, not a code
defect:
-
Windows / Silk smoke — resolved (Phase X.7). Previously failed
with
GlfwException: ApiUnavailable: WGL: The driver does not appear to support OpenGLbecause thewindows-latestrunner ships no OpenGL ICD. The build workflow now fetches Mesa3D for Windows (pal1000/mesa-dist-win llvmpipe build) and overridesC:\Windows\System32\opengl32.dllbefore invoking the smoke; new processes pick up Mesa's GL 4.6 software path via the normalLoadLibrary("opengl32.dll")resolution.continue-on-erroris off on the Windows leg so the smoke now gates the leg. -
Linux Wayland / Silk smoke — segfault inside the Silk EGL adapter
while running under
weston --backend=headless. The Silk smoke successfully passes on the same runner under xvfb + GLFW + X11, so the regression is specific to the EGL adapter Wayland path. Fix path: isolate whether the segfault is upstream in libwayland-egl1 / Mesa or in the EGL adapter wiring. -
macOS / Silk smoke — segfault inside the CGL context init on
Apple Silicon. Suspected Silk.NET native-library mismatch with arm64;
the offscreen path that should work on the
macos-latestheadless WindowServer fails before glReadPixels. Fix path: probe with a tiny pure-Objective-C harness to confirm CGL works, then bisect Silk.NET versions.
The X11 (xvfb) leg + the Linux + Windows + macOS build legs all pass end-to-end; the gaps above land only at the smoke runtime.
When a smoke test fails:
- Capture the host OS + version (
uname -aon Linux/macOS). - Capture
dotnet --infooutput. - Capture the App's stderr — every smoke run can pipe through
2>&1 | tee /tmp/smoke.log. - File against the corresponding phase in the implementation plan; the
bug belongs on
feature/cross-platform-fulluntil the phase merges.