using LlamaApp.Llama;
using Xunit;
namespace LlamaApp.LlamaCpp.Tests;
///
/// Unit tests for the "which"-style binary resolution
/// ()
/// and the managed-vs-external classification ().
/// The case that matters operationally: right after install.ps1 runs,
/// the binary is only visible on the user PATH (registry) — the
/// installer is a child process and cannot update our own environment block —
/// so the lookup must search user/machine PATH beyond the process PATH.
///
public sealed class LlamaManagerPathResolutionTests : IDisposable
{
private readonly string _root =
Path.Combine(Path.GetTempPath(), "llama-path-tests-" + Guid.NewGuid().ToString("N"));
public void Dispose()
{
try { Directory.Delete(_root, recursive: true); } catch { /* best-effort */ }
}
/// Creates a temp dir containing a fake llama.exe and returns the dir.
private string MakeInstallDir(string name)
{
var dir = Path.Combine(_root, name);
Directory.CreateDirectory(dir);
File.WriteAllText(Path.Combine(dir, "llama.exe"), "fake");
return dir;
}
[Fact]
public void FindOnPath_FindsExeOnProcessPath()
{
var dir = MakeInstallDir("a");
Assert.Equal(
Path.Combine(dir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", dir, null, null));
}
[Fact]
public void FindOnPath_FindsExeOnUserPath_WhenNotOnProcessPath()
{
// The post-install case: install.ps1 put its dir on the user PATH, but
// our process environment block doesn't have it.
var dir = MakeInstallDir("a");
Assert.Equal(
Path.Combine(dir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", @"C:\Windows", dir, null));
}
[Fact]
public void FindOnPath_FindsExeOnMachinePath()
{
var dir = MakeInstallDir("a");
Assert.Equal(
Path.Combine(dir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", null, null, dir));
}
[Fact]
public void FindOnPath_ProcessPathWinsOverUserPath()
{
var processDir = MakeInstallDir("process");
var userDir = MakeInstallDir("user");
Assert.Equal(
Path.Combine(processDir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", processDir, userDir, null));
}
[Fact]
public void FindOnPath_FirstDirInListWins()
{
var first = MakeInstallDir("first");
var second = MakeInstallDir("second");
Assert.Equal(
Path.Combine(first, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", first + Path.PathSeparator + second, null, null));
}
[Fact]
public void FindOnPath_ReturnsNull_WhenNotFoundAnywhere()
{
Assert.Null(LlamaManager.FindOnPath("llama.exe", _root, _root, _root));
}
[Fact]
public void FindOnPath_ReturnsNull_WhenAllPathsAreNullOrEmpty()
{
Assert.Null(LlamaManager.FindOnPath("llama.exe", null, "", " "));
}
[Fact]
public void FindOnPath_ToleratesQuotedAndPaddedEntries()
{
var dir = MakeInstallDir("a");
var pathEnv = $" \"{dir}\" ";
Assert.Equal(
Path.Combine(dir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", pathEnv, null, null));
}
[Fact]
public void FindOnPath_SkipsMalformedEntries()
{
var dir = MakeInstallDir("a");
// A NUL-containing entry is invalid; it must be skipped, not throw.
var pathEnv = "bad\0entry" + Path.PathSeparator + dir;
Assert.Equal(
Path.Combine(dir, "llama.exe"),
LlamaManager.FindOnPath("llama.exe", pathEnv, null, null));
}
[Fact]
public void IsManagedPath_TrueForBinaryInInstallDir()
{
var binary = Path.Combine(LlamaManager.ManagedInstallDir, "llama.exe");
Assert.True(LlamaManager.IsManagedPath(binary));
}
[Fact]
public void IsManagedPath_IsCaseInsensitive()
{
var binary = Path.Combine(LlamaManager.ManagedInstallDir.ToUpperInvariant(), "LLAMA.EXE");
Assert.True(LlamaManager.IsManagedPath(binary));
}
[Fact]
public void IsManagedPath_FalseForBinaryElsewhere()
{
Assert.False(LlamaManager.IsManagedPath(Path.Combine(_root, "llama.exe")));
}
}