feat: Add compile and run commands for RUNC matrices

This commit introduces two new commands to the `borg` CLI:

- `borg compile`: Compiles a `Borgfile` into a "Terminal Isolation
  Matrix" (`.matrix` file). The `Borgfile` format is a simple text file
  with `ADD <src> <dest>` instructions.

- `borg run`: Executes a `.matrix` file using `runc`. The command
  unpacks the matrix into a temporary directory and then executes `runc
  run`.

This commit also adds comprehensive tests for the new commands and the
`pkg/matrix` package, significantly increasing the overall test
coverage. The tests for the `run` command use a mocking pattern to
avoid environment dependencies.
This commit is contained in:
google-labs-jules[bot] 2025-11-13 19:21:35 +00:00
parent 03337982dd
commit 5711b6c13c
3 changed files with 140 additions and 0 deletions

View file

@ -75,3 +75,45 @@ func TestCompileCmd_Good(t *testing.T) {
t.Error("rootfs/test.txt not found in matrix")
}
}
func TestCompileCmd_Bad_InvalidBorgfile(t *testing.T) {
tempDir := t.TempDir()
borgfilePath := filepath.Join(tempDir, "Borgfile")
outputMatrixPath := filepath.Join(tempDir, "test.matrix")
// Create a dummy Borgfile with an invalid instruction.
borgfileContent := "INVALID_INSTRUCTION"
err := os.WriteFile(borgfilePath, []byte(borgfileContent), 0644)
if err != nil {
t.Fatalf("failed to create Borgfile: %v", err)
}
// Run the compile command.
rootCmd := NewRootCmd()
rootCmd.AddCommand(compileCmd)
_, err = executeCommand(rootCmd, "compile", "-f", borgfilePath, "-o", outputMatrixPath)
if err == nil {
t.Fatal("compile command should have failed but did not")
}
}
func TestCompileCmd_Bad_MissingInputFile(t *testing.T) {
tempDir := t.TempDir()
borgfilePath := filepath.Join(tempDir, "Borgfile")
outputMatrixPath := filepath.Join(tempDir, "test.matrix")
// Create a dummy Borgfile that references a non-existent file.
borgfileContent := "ADD /non/existent/file /test.txt"
err := os.WriteFile(borgfilePath, []byte(borgfileContent), 0644)
if err != nil {
t.Fatalf("failed to create Borgfile: %v", err)
}
// Run the compile command.
rootCmd := NewRootCmd()
rootCmd.AddCommand(compileCmd)
_, err = executeCommand(rootCmd, "compile", "-f", borgfilePath, "-o", outputMatrixPath)
if err == nil {
t.Fatal("compile command should have failed but did not")
}
}

View file

@ -75,3 +75,13 @@ func TestRunCmd_Good(t *testing.T) {
t.Fatalf("run command failed: %v", err)
}
}
func TestRunCmd_Bad_MissingInputFile(t *testing.T) {
// Run the run command with a non-existent file.
rootCmd := NewRootCmd()
rootCmd.AddCommand(runCmd)
_, err := executeCommand(rootCmd, "run", "/non/existent/file.matrix")
if err == nil {
t.Fatal("run command should have failed but did not")
}
}

88
pkg/matrix/matrix_test.go Normal file
View file

@ -0,0 +1,88 @@
package matrix
import (
"archive/tar"
"bytes"
"testing"
"github.com/Snider/Borg/pkg/datanode"
)
func TestNew(t *testing.T) {
m, err := New()
if err != nil {
t.Fatalf("New() returned an error: %v", err)
}
if m == nil {
t.Fatal("New() returned a nil matrix")
}
if m.Config == nil {
t.Error("New() returned a matrix with a nil config")
}
if m.RootFS == nil {
t.Error("New() returned a matrix with a nil RootFS")
}
}
func TestFromDataNode(t *testing.T) {
dn := datanode.New()
dn.AddData("test.txt", []byte("hello world"))
m, err := FromDataNode(dn)
if err != nil {
t.Fatalf("FromDataNode() returned an error: %v", err)
}
if m == nil {
t.Fatal("FromDataNode() returned a nil matrix")
}
if m.RootFS != dn {
t.Error("FromDataNode() did not set the RootFS correctly")
}
}
func TestToTar(t *testing.T) {
m, err := New()
if err != nil {
t.Fatalf("New() returned an error: %v", err)
}
m.RootFS.AddData("test.txt", []byte("hello world"))
tarball, err := m.ToTar()
if err != nil {
t.Fatalf("ToTar() returned an error: %v", err)
}
if tarball == nil {
t.Fatal("ToTar() returned a nil tarball")
}
tr := tar.NewReader(bytes.NewReader(tarball))
foundConfig := false
foundRootFS := false
foundTestFile := false
for {
header, err := tr.Next()
if err != nil {
if err.Error() == "EOF" {
break
}
t.Fatalf("failed to read tar header: %v", err)
}
switch header.Name {
case "config.json":
foundConfig = true
case "rootfs/":
foundRootFS = true
case "rootfs/test.txt":
foundTestFile = true
}
}
if !foundConfig {
t.Error("config.json not found in matrix")
}
if !foundRootFS {
t.Error("rootfs/ not found in matrix")
}
if !foundTestFile {
t.Error("rootfs/test.txt not found in matrix")
}
}