c326853929
Co-authored-by: Kandev Agent <agent@kandev.dev>
152 lines
4.3 KiB
Go
152 lines
4.3 KiB
Go
package client
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestShellStatus_DecodesSessionState(t *testing.T) {
|
|
srv, got := captureServer(t, jsonResponder(http.StatusOK,
|
|
`{"running":true,"pid":8123,"shell":"/bin/bash","cwd":"/workspace/task-1"}`))
|
|
|
|
status, err := newHTTPOnlyClient(srv.URL).ShellStatus(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ShellStatus: %v", err)
|
|
}
|
|
|
|
if got.Method != http.MethodGet || got.Path != "/api/v1/shell/status" {
|
|
t.Errorf("request = %s %s, want GET /api/v1/shell/status", got.Method, got.Path)
|
|
}
|
|
if !status.Running {
|
|
t.Error("Running = false, want true")
|
|
}
|
|
if status.Pid != 8123 {
|
|
t.Errorf("Pid = %d, want 8123", status.Pid)
|
|
}
|
|
if status.Shell != "/bin/bash" {
|
|
t.Errorf("Shell = %q, want /bin/bash", status.Shell)
|
|
}
|
|
if status.Cwd != "/workspace/task-1" {
|
|
t.Errorf("Cwd = %q, want /workspace/task-1", status.Cwd)
|
|
}
|
|
}
|
|
|
|
func TestShellStatus_FailureModes(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
status int
|
|
body string
|
|
wantErr string
|
|
}{
|
|
{"non-OK status", http.StatusNotFound, `{}`, "shell status failed"},
|
|
{"malformed body", http.StatusOK, `{"running":`, "unexpected EOF"},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
srv, _ := captureServer(t, jsonResponder(tc.status, tc.body))
|
|
|
|
status, err := newHTTPOnlyClient(srv.URL).ShellStatus(context.Background())
|
|
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
|
|
t.Fatalf("error = %v, want %q", err, tc.wantErr)
|
|
}
|
|
if status != nil {
|
|
t.Errorf("status = %+v, want nil on failure", status)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestShellBuffer_ReturnsDataField(t *testing.T) {
|
|
srv, got := captureServer(t, jsonResponder(http.StatusOK,
|
|
`{"data":"$ ls\r\nREADME.md\r\n"}`))
|
|
|
|
data, err := newHTTPOnlyClient(srv.URL).ShellBuffer(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("ShellBuffer: %v", err)
|
|
}
|
|
|
|
if got.Method != http.MethodGet || got.Path != "/api/v1/shell/buffer" {
|
|
t.Errorf("request = %s %s, want GET /api/v1/shell/buffer", got.Method, got.Path)
|
|
}
|
|
if data != "$ ls\r\nREADME.md\r\n" {
|
|
t.Errorf("data = %q, want the buffered shell output", data)
|
|
}
|
|
}
|
|
|
|
func TestShellBuffer_FailureModes(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
status int
|
|
body string
|
|
wantErr string
|
|
}{
|
|
{"non-OK status", http.StatusInternalServerError, `{}`, "shell buffer failed"},
|
|
{"malformed body", http.StatusOK, `{"data":`, "unexpected EOF"},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
srv, _ := captureServer(t, jsonResponder(tc.status, tc.body))
|
|
|
|
data, err := newHTTPOnlyClient(srv.URL).ShellBuffer(context.Background())
|
|
if err == nil || !strings.Contains(err.Error(), tc.wantErr) {
|
|
t.Fatalf("error = %v, want %q", err, tc.wantErr)
|
|
}
|
|
if data != "" {
|
|
t.Errorf("data = %q, want empty on failure", data)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestStartShell_PostsToShellStart(t *testing.T) {
|
|
srv, got := captureServer(t, jsonResponder(http.StatusOK, `{}`))
|
|
|
|
if err := newHTTPOnlyClient(srv.URL).StartShell(context.Background()); err != nil {
|
|
t.Fatalf("StartShell: %v", err)
|
|
}
|
|
if got.Method != http.MethodPost || got.Path != "/api/v1/shell/start" {
|
|
t.Errorf("request = %s %s, want POST /api/v1/shell/start", got.Method, got.Path)
|
|
}
|
|
}
|
|
|
|
func TestStartShell_FailsOnNonOKStatus(t *testing.T) {
|
|
srv, _ := captureServer(t, jsonResponder(http.StatusConflict, `{}`))
|
|
|
|
err := newHTTPOnlyClient(srv.URL).StartShell(context.Background())
|
|
if err == nil || !strings.Contains(err.Error(), "start shell failed") {
|
|
t.Fatalf("error = %v, want the start failure named", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "409") {
|
|
t.Errorf("error = %v, want the HTTP status carried through", err)
|
|
}
|
|
}
|
|
|
|
func TestShellEndpoints_HonourContextCancellation(t *testing.T) {
|
|
srv, _ := captureServer(t, jsonResponder(http.StatusOK, `{}`))
|
|
c := newHTTPOnlyClient(srv.URL)
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
calls := map[string]func() error{
|
|
"ShellStatus": func() error {
|
|
_, err := c.ShellStatus(ctx)
|
|
return err
|
|
},
|
|
"ShellBuffer": func() error {
|
|
_, err := c.ShellBuffer(ctx)
|
|
return err
|
|
},
|
|
"StartShell": func() error { return c.StartShell(ctx) },
|
|
}
|
|
for name, call := range calls {
|
|
t.Run(name, func(t *testing.T) {
|
|
if err := call(); err == nil || !strings.Contains(err.Error(), "context canceled") {
|
|
t.Fatalf("error = %v, want context canceled", err)
|
|
}
|
|
})
|
|
}
|
|
}
|