- Updated benchmark functions to utilize TaiID instead of pool names for improved consistency and accuracy in tests. - Refactored test cases across various files to ensure compatibility with the new TaiID structure. - Enhanced setup functions to accept pointers to poolConfig for better memory management. - Removed deprecated config struct and adjusted related documentation to reflect the changes in the sandbox architecture. Made-with: Cursor
224 lines
4.9 KiB
Go
224 lines
4.9 KiB
Go
package sandbox_test
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
sandbox "github.com/yaoapp/yao/sandbox/v2"
|
|
)
|
|
|
|
func TestBoxExec(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
result, err := box.Exec(ctx, []string{"echo", "box-exec"})
|
|
if err != nil {
|
|
t.Fatalf("Exec: %v", err)
|
|
}
|
|
if result.Stdout != "box-exec\n" {
|
|
t.Errorf("stdout = %q, want %q", result.Stdout, "box-exec\n")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxExecWithOptions(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
|
|
ctx := context.Background()
|
|
result, err := box.Exec(ctx, []string{"pwd"},
|
|
sandbox.WithWorkDir("/tmp"),
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Exec: %v", err)
|
|
}
|
|
if result.Stdout != "/tmp\n" {
|
|
t.Errorf("stdout = %q, want %q", result.Stdout, "/tmp\n")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxStream(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
|
|
ctx := context.Background()
|
|
stream, err := box.Stream(ctx, []string{"sh", "-c", "echo line1; echo line2"})
|
|
if err != nil {
|
|
t.Fatalf("Stream: %v", err)
|
|
}
|
|
|
|
out, err := io.ReadAll(stream.Stdout)
|
|
if err != nil {
|
|
t.Fatalf("ReadAll: %v", err)
|
|
}
|
|
if string(out) != "line1\nline2\n" {
|
|
t.Errorf("stdout = %q, want %q", string(out), "line1\nline2\n")
|
|
}
|
|
|
|
code, err := stream.Wait()
|
|
if err != nil {
|
|
t.Fatalf("Wait: %v", err)
|
|
}
|
|
if code != 0 {
|
|
t.Errorf("exit code = %d, want 0", code)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxWorkspace(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
|
|
ws := box.Workspace()
|
|
if ws == nil {
|
|
t.Skip("Workspace returned nil (volume not available)")
|
|
}
|
|
|
|
content := []byte("package main\n")
|
|
if err := ws.WriteFile("main.go", content, 0644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
data, err := ws.ReadFile("main.go")
|
|
if err != nil {
|
|
t.Fatalf("ReadFile: %v", err)
|
|
}
|
|
if string(data) != string(content) {
|
|
t.Errorf("content = %q, want %q", string(data), string(content))
|
|
}
|
|
|
|
if err := ws.MkdirAll("src/pkg", 0755); err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
|
|
entries, err := ws.ReadDir("src")
|
|
if err != nil {
|
|
t.Fatalf("ReadDir: %v", err)
|
|
}
|
|
if len(entries) == 0 {
|
|
t.Error("expected non-empty directory listing")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxInfo(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
|
|
ctx := context.Background()
|
|
info, err := box.Info(ctx)
|
|
if err != nil {
|
|
t.Fatalf("Info: %v", err)
|
|
}
|
|
if info.ID != box.ID() {
|
|
t.Errorf("ID = %q, want %q", info.ID, box.ID())
|
|
}
|
|
if s := strings.ToLower(info.Status); s != "running" {
|
|
t.Errorf("status = %q, want running", info.Status)
|
|
}
|
|
if info.Owner != "test-user" {
|
|
t.Errorf("owner = %q, want test-user", info.Owner)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxStopStart(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
box := createTestBox(t, m, pc)
|
|
ctx := context.Background()
|
|
|
|
if err := box.Stop(ctx); err != nil {
|
|
t.Fatalf("Stop: %v", err)
|
|
}
|
|
|
|
if err := box.Start(ctx); err != nil {
|
|
t.Fatalf("Start: %v", err)
|
|
}
|
|
|
|
result, err := box.Exec(ctx, []string{"echo", "after-restart"})
|
|
if err != nil {
|
|
t.Fatalf("Exec after restart: %v", err)
|
|
}
|
|
if result.Stdout != "after-restart\n" {
|
|
t.Errorf("stdout = %q", result.Stdout)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBoxGetOrCreate(t *testing.T) {
|
|
skipIfNoDocker(t)
|
|
|
|
for _, pc := range testPools() {
|
|
pc := pc
|
|
t.Run(pc.Name, func(t *testing.T) {
|
|
m := setupManagerForPool(t, &pc)
|
|
ctx := context.Background()
|
|
box1, err := m.GetOrCreate(ctx, sandbox.CreateOptions{
|
|
ID: "goc-" + pc.Name,
|
|
Image: testImage(),
|
|
Owner: "test-user",
|
|
Pool: pc.TaiID,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate first: %v", err)
|
|
}
|
|
defer m.Remove(ctx, box1.ID())
|
|
|
|
box2, err := m.GetOrCreate(ctx, sandbox.CreateOptions{
|
|
ID: "goc-" + pc.Name,
|
|
Image: testImage(),
|
|
Owner: "test-user",
|
|
Pool: pc.TaiID,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("GetOrCreate second: %v", err)
|
|
}
|
|
if box2.ContainerID() != box1.ContainerID() {
|
|
t.Error("expected same container for GetOrCreate with same ID")
|
|
}
|
|
})
|
|
}
|
|
}
|