Aller au contenu

Parallel VNC execution

Ce contenu n’est pas encore disponible dans votre langue.

Most visual automation tools assume one screen, one session, one machine. OculiX is built to go further — a single host can drive many isolated VNC sessions, each on its own port, with no physical display required. That’s how OculiX reaches enterprise scale: testing dozens of point-of-sale terminals, kiosks, or application instances from one VM.

But it’s worth being honest about how that works today versus where it’s going.

Visual automation was born in a world of one physical screen: one machine, one desktop, one cursor. SikuliX — which OculiX continues — inherited that worldview, and for fifteen years it was the right one. The engine keeps a notion of the current screen in shared, global state. When there is only ever one screen, that’s not a flaw; it’s the correct design.

VNC breaks the assumption. A VNC session isn’t a screen — it’s a network framebuffer: no monitor, no DISPLAY, no desktop login. You can open many, each on its own port. Suddenly “the current screen” is no longer a singleton, and the single-screen assumption baked into the engine becomes visible: the default port and the live-session registry live in shared, static state. Two flows running at once can reach for the same global and quietly pollute each other.

This is exactly why, today, parallelism lives one layer up.

What works today: single-session VNC (native)

Section titled “What works today: single-session VNC (native)”

A single VNC session works perfectly out of the box. This is the engine doing what it does best.

import org.sikuli.vnc.VNCScreen;
VNCScreen screen = VNCScreen.start("127.0.0.1", 5901);
// Behaves like a normal Screen — find, click, type
screen.find("scan_button.png").click();
screen.type("amount_field.png", "42.00");
screen.stop();

With a password and explicit timeouts:

VNCScreen scr = VNCScreen.start(
"10.0.0.12", // VNC server IP
5901, // port
"secret", // VNC password (or null)
3, // connection timeout (s)
0 // operation timeout (s)
);

If you need an SSH tunnel to reach a remote framebuffer, OculiX ships a pure-Java tunnel (no WSL, no external sshpass):

import com.sikulix.util.SSHTunnel;
try (SSHTunnel tunnel = SSHTunnel.open("192.168.1.100", "user", "password")) {
VNCScreen scr = VNCScreen.start("127.0.0.1", tunnel.getLocalPort());
// ... drive the session
scr.stop();
}

What works today: parallelism (your orchestration, on top)

Section titled “What works today: parallelism (your orchestration, on top)”

You can run many sessions in parallel right now — and teams do, in production. But because the core was built single-session, you are currently responsible for the four things that keep concurrent sessions from colliding:

Isolation per flow

Each test flow needs its own session bound to its own thread — its own port, its own remote. Don’t share a VNCScreen reference across threads; give each flow its own.

Atomic port allocation

Two flows must never claim the same port. “Probably free” isn’t enough when several start at once — you need an atomic claim (a lock no two flows can win simultaneously).

One tunnel per session

If you tunnel to remote machines, open one per flow — and close the old one before opening the next, or orphaned tunnels hold ports hostage.

Readiness, not a sleep

Wait for the VNC server’s RFB banner (proof it’s ready for pixels) rather than a fixed delay. A fixed sleep does not survive several sessions starting together.

A sketch of the pattern (you supply the port allocation and readiness yourself, today):

import java.util.concurrent.*;
int[] ports = {5901, 5902, 5903, 5904}; // one per entity, allocated atomically by YOU
ExecutorService pool = Executors.newFixedThreadPool(ports.length);
for (int port : ports) {
pool.submit(() -> {
// each flow: its own tunnel, its own session, its own thread
VNCScreen scr = VNCScreen.start("127.0.0.1", port);
runCheckoutScenario(scr); // a balanced slice of your suite
scr.stop();
});
}
pool.shutdown();

Where this is going: native parallel sessions

Section titled “Where this is going: native parallel sessions”

Everything you build on top today is the engine’s natural next form. The goal for the next major version is to make multi-session parallelism first-class:

Thread-scoped sessions

No more global “current screen.” A session belongs to the flow that opened it, by construction — so two flows can’t reach for the same state, because there’s no shared state to reach for.

Built-in port allocation

Ask for a session, get an isolated one on a port the engine claimed atomically. No range to reserve, no lock-files to babysit.

Native RFB readiness

A session reports ready when the server actually says it’s ready — the optimistic startup sleep replaced by a real probe.

Tunnels wired in

The pure-Java SSHTunnel already in the core, integrated into a documented parallel pattern instead of hand-assembled per project.

The target, stated simply: declare N sessions, get N isolated sessions — no harness, no lock-files, no ghost tunnels. The single-screen assumption retired gently, with full respect for the years it served exactly right.

The container pattern (today and tomorrow)

Section titled “The container pattern (today and tomorrow)”

However sessions become isolated, the cleanest way to provision N isolated entities is one container per session: each runs a VNC server on a unique port, with the app under test inside.

  1. One container = one entity. Each runs a VNC server (e.g. on :5901, :5902, …) plus the app under test, fully isolated.

  2. Map the ports. Expose each container’s VNC port to the host so OculiX can reach 127.0.0.1:590X.

  3. OculiX connects to all of them. One session per port, on the orchestrating host.

  4. Collect per-entity results. Each container is one entity; its session yields one clean result.

flowchart LR
    C1["Container 1 — entity A<br/>VNC :5901"]
    C2["Container 2 — entity B<br/>VNC :5902"]
    Cd["…"]
    CN["Container N — entity J<br/>VNC :590N"]
    O["OculiX<br/>N parallel sessions"]
    R["One result<br/>per entity"]
    C1 --> O
    C2 --> O
    Cd --> O
    CN --> O
    O --> R

This model scales naturally with an orchestrator (Kubernetes Deployment/Job per batch). The same “grid of parallel sessions” used in mobile/Selenium farms applies directly to visual automation.

No physical display

The VNC server provides the framebuffer. OculiX reads pixels over the wire — no monitor, no X session on the OculiX host.

Virtual displays server-side

Inside each container/VM, the VNC server typically runs against a virtual display (e.g. Xvfb on Linux). That’s where the app actually renders.

Resource budgeting

Each session costs CPU (matching), memory (framebuffer), and a thread. A modest VM comfortably runs a handful; tens of sessions want real capacity planning.

Network locality

Keep VNC traffic local (loopback or same subnet). Framebuffer refreshes are bandwidth-sensitive; remote-WAN VNC will bottleneck matching.

ScenarioFit
Testing many point-of-sale terminals / kiosks✅ Ideal (orchestration today, native soon)
Running a large suite faster via parallelism✅ Ideal
Per-entity / per-configuration validation✅ Ideal
Regulated compliance windows (test everything, fast)✅ Ideal
A single local desktop automation❌ Use a normal Screen