This repository has been archived on 2026-03-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
oubliette/internal/shell/bash/filesystem_test.go
Torjus Håkestad 8189a108d1 feat: add shell interface, registry, and bash shell emulator
Implement Phase 1.4: replaces the hardcoded banner/timeout stub with a
proper shell system. Adds a Shell interface with weighted registry for
shell selection, a RecordingChannel wrapper (pass-through for now, prep
for Phase 2.3 replay), and a bash-like shell with fake filesystem,
terminal line reader, and command handling (pwd, ls, cd, cat, whoami,
hostname, id, uname, exit). Sessions now log command/output pairs to
the store and record the shell name.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 20:24:48 +01:00

141 lines
3.1 KiB
Go

package bash
import (
"sort"
"testing"
)
func TestNewFilesystem(t *testing.T) {
fs := newFilesystem("testhost")
// Standard directories should exist.
for _, dir := range []string{"/etc", "/root", "/home", "/var/log", "/tmp", "/usr/bin"} {
if !fs.isDirectory(dir) {
t.Errorf("%s should be a directory", dir)
}
}
// Standard files should exist.
for _, file := range []string{"/etc/passwd", "/etc/hostname", "/root/.bashrc", "/tmp/notes.txt"} {
if !fs.exists(file) {
t.Errorf("%s should exist", file)
}
}
}
func TestFilesystemHostname(t *testing.T) {
fs := newFilesystem("myhost")
content, err := fs.read("/etc/hostname")
if err != nil {
t.Fatalf("read /etc/hostname: %v", err)
}
if content != "myhost\n" {
t.Errorf("hostname content = %q, want %q", content, "myhost\n")
}
}
func TestResolvePath(t *testing.T) {
tests := []struct {
cwd string
arg string
want string
}{
{"/root", "file.txt", "/root/file.txt"},
{"/root", "/etc/passwd", "/etc/passwd"},
{"/root", "..", "/"},
{"/var/log", "../..", "/"},
{"/root", ".", "/root"},
{"/root", "./sub/file", "/root/sub/file"},
{"/", "etc", "/etc"},
}
for _, tt := range tests {
got := resolvePath(tt.cwd, tt.arg)
if got != tt.want {
t.Errorf("resolvePath(%q, %q) = %q, want %q", tt.cwd, tt.arg, got, tt.want)
}
}
}
func TestFilesystemList(t *testing.T) {
fs := newFilesystem("testhost")
names, err := fs.list("/etc")
if err != nil {
t.Fatalf("list /etc: %v", err)
}
sort.Strings(names)
// Should contain at least passwd, hostname, hosts.
found := map[string]bool{}
for _, n := range names {
found[n] = true
}
for _, want := range []string{"passwd", "hostname", "hosts"} {
if !found[want] {
t.Errorf("list /etc missing %q, got %v", want, names)
}
}
}
func TestFilesystemListNonexistent(t *testing.T) {
fs := newFilesystem("testhost")
_, err := fs.list("/nonexistent")
if err == nil {
t.Fatal("expected error listing nonexistent directory")
}
}
func TestFilesystemListFile(t *testing.T) {
fs := newFilesystem("testhost")
_, err := fs.list("/etc/passwd")
if err == nil {
t.Fatal("expected error listing a file")
}
}
func TestFilesystemRead(t *testing.T) {
fs := newFilesystem("testhost")
content, err := fs.read("/etc/passwd")
if err != nil {
t.Fatalf("read: %v", err)
}
if content == "" {
t.Error("expected non-empty content")
}
}
func TestFilesystemReadNonexistent(t *testing.T) {
fs := newFilesystem("testhost")
_, err := fs.read("/no/such/file")
if err == nil {
t.Fatal("expected error for nonexistent file")
}
}
func TestFilesystemReadDirectory(t *testing.T) {
fs := newFilesystem("testhost")
_, err := fs.read("/etc")
if err == nil {
t.Fatal("expected error for reading a directory")
}
}
func TestFilesystemDirectoryListing(t *testing.T) {
fs := newFilesystem("testhost")
names, err := fs.list("/")
if err != nil {
t.Fatalf("list /: %v", err)
}
// Root directories should end with /
found := map[string]bool{}
for _, n := range names {
found[n] = true
}
for _, want := range []string{"etc/", "root/", "home/", "var/", "tmp/", "usr/"} {
if !found[want] {
t.Errorf("list / missing %q, got %v", want, names)
}
}
}