vPOD: real C:\Games installs, optional real app launching, power-group swap
- InstallProduct now extracts into the real C:\Games (the launcher's GAMES_DIR) so deployed products land where their catalog launch entries point; uninstall removes the real product folder. Tests pass an isolated games root through the VirtualLauncher ctor. - New "Actually launch apps (real processes)" toggle (off by default = simulated PIDs): LaunchApp starts the entry's exe exactly like the Agent (same start info, same registered-but-not-installed error), Kill*/ Uninstall/Wipe terminate the real processes (kill before folder delete), and self-exited apps are pruned from GetLaunchedApps/FullUpdate. Real processes die with the machine: power off, reboot, or closing vPOD. The Agent's autoRestart watchdog is deliberately not emulated. - Pod Power and Mimicking Game groups swapped (game left, power right). - Provisioning round-trip test now skips as inconclusive when a running TeslaConsole holds UDP 53291 instead of failing the suite; two new tests cover real launch/kill (ping.exe) and the missing-exe error path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
@@ -31,7 +32,8 @@ namespace TeslaConsole.DiffTests
|
||||
public VPodLauncherServerTests()
|
||||
{
|
||||
mDataDir = Path.Combine(Path.GetTempPath(), "vpod-test-" + Guid.NewGuid().ToString("N"));
|
||||
mLauncher = new VirtualLauncher(mDataDir);
|
||||
// Isolated games root: vPOD's default is the real C:\Games (launcher parity).
|
||||
mLauncher = new VirtualLauncher(mDataDir, Path.Combine(mDataDir, "Games"));
|
||||
mKey = new byte[32];
|
||||
new Random(1234).NextBytes(mKey);
|
||||
mPort = GetFreePort();
|
||||
@@ -199,6 +201,47 @@ namespace TeslaConsole.DiffTests
|
||||
Assert.Empty(mLauncher.GetInstalledApps());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RealLaunch_Starts_And_Kills_Real_Processes()
|
||||
{
|
||||
mLauncher.RealLaunch = true;
|
||||
var app = new LaunchData
|
||||
{
|
||||
LaunchPair = new LaunchPair { LaunchKey = Guid.NewGuid(), DisplayName = "Real Pinger" },
|
||||
WorkingDirectory = Environment.SystemDirectory,
|
||||
ExeFile = Path.Combine(Environment.SystemDirectory, "ping.exe"),
|
||||
Arguments = "-n 60 127.0.0.1",
|
||||
AutoRestart = false
|
||||
};
|
||||
mClient.InstallApp(app);
|
||||
|
||||
int pid = mClient.LaunchApp(app.LaunchPair.LaunchKey);
|
||||
Assert.True(pid > 0);
|
||||
using (var real = Process.GetProcessById(pid)) // throws if not actually running
|
||||
{
|
||||
Assert.False(real.HasExited);
|
||||
var launched = mClient.GetLaunchedApps();
|
||||
Assert.Single(launched);
|
||||
Assert.Equal(pid, launched[0].ProcessId);
|
||||
|
||||
mClient.KillAllOfType(app.LaunchPair.LaunchKey);
|
||||
Assert.True(real.WaitForExit(5000), "real process was not terminated");
|
||||
}
|
||||
Assert.Empty(mClient.GetLaunchedApps());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RealLaunch_Missing_Exe_Surfaces_The_Agents_Error()
|
||||
{
|
||||
mLauncher.RealLaunch = true;
|
||||
var app = SampleApp("Not Installed Yet"); // ExeFile doesn't exist on disk
|
||||
mClient.InstallApp(app);
|
||||
|
||||
var ex = Assert.ThrowsAny<Exception>(() => mClient.LaunchApp(app.LaunchPair.LaunchKey));
|
||||
Assert.Contains("executable not found", ex.Message);
|
||||
Assert.Empty(mClient.GetLaunchedApps());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dropped_Session_Still_Reports_Open_Until_Probed_Then_Reconnect_Works()
|
||||
{
|
||||
@@ -226,7 +269,7 @@ namespace TeslaConsole.DiffTests
|
||||
var app = SampleApp("Persistent App");
|
||||
mClient.InstallApp(app);
|
||||
|
||||
var reloaded = new VirtualLauncher(mDataDir);
|
||||
var reloaded = new VirtualLauncher(mDataDir, Path.Combine(mDataDir, "Games"));
|
||||
var installed = reloaded.GetInstalledApps();
|
||||
Assert.Single(installed);
|
||||
Assert.Equal(app.LaunchPair.LaunchKey, installed[0].LaunchPair.LaunchKey);
|
||||
|
||||
@@ -41,12 +41,23 @@ namespace TeslaConsole.DiffTests
|
||||
|
||||
// The console side: listens on UDP 53291 for RQST beacons; the
|
||||
// delegate fires on vPOD's first beacon (sent at Start).
|
||||
var consoleServer = new PodConfigurationServer(53291, 53292, (m, id) =>
|
||||
PodConfigurationServer consoleServer;
|
||||
try
|
||||
{
|
||||
beaconMac = m;
|
||||
beaconRequestId = id;
|
||||
beaconSeen.Set();
|
||||
});
|
||||
consoleServer = new PodConfigurationServer(53291, 53292, (m, id) =>
|
||||
{
|
||||
beaconMac = m;
|
||||
beaconRequestId = id;
|
||||
beaconSeen.Set();
|
||||
});
|
||||
}
|
||||
catch (System.Net.Sockets.SocketException)
|
||||
{
|
||||
// UDP 53291 already bound — a real TeslaConsole is running on
|
||||
// this machine. The protocol ports are fixed, so the test can't
|
||||
// run; treat as inconclusive rather than failing the suite.
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user