package handlers import ( "context" "errors" "testing" "overlord-client/cmd/agent/config" rt "overlord-client/cmd/agent/runtime" "overlord-client/cmd/agent/wire" "github.com/vmihailenco/msgpack/v5" ) func TestHandlePing(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "ts": float64(1234567890), } if err := HandlePing(ctx, env, envelope); err != nil { t.Fatalf("HandlePing failed: %v", err) } if len(writer.msgs) < 1 { t.Fatal("Expected at least 1 message") } var pong wire.Pong if err := msgpack.Unmarshal(writer.msgs[0], &pong); err != nil { t.Fatalf("Failed to unmarshal pong: %v", err) } if pong.Type != "pong" { t.Errorf("Expected type 'pong', got '%s'", pong.Type) } expectedTS := int64(1234567890) if pong.TS != expectedTS { t.Errorf("Expected timestamp %d, got %d", expectedTS, pong.TS) } } func TestHandleCommand_Ping(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "ping", "id": "cmd-ping-1", "ts": float64(1234567890), } if err := HandleCommand(ctx, env, envelope); err != nil { t.Fatalf("HandleCommand(ping) failed: %v", err) } if len(writer.msgs) < 1 { t.Fatal("Expected at least 1 message") } var firstMsg map[string]interface{} if err := msgpack.Unmarshal(writer.msgs[0], &firstMsg); err != nil { t.Fatalf("Failed to unmarshal first message: %v", err) } msgType, _ := firstMsg["type"].(string) t.Logf("First message type: %s", msgType) } func TestHandleCommand_Desktop(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "desktop", "id": "cmd-desktop-1", "payload": map[string]interface{}{}, } if err := HandleCommand(ctx, env, envelope); err != nil { t.Fatalf("HandleCommand(desktop) failed: %v", err) } t.Logf("Desktop command sent %d messages", len(writer.msgs)) } func TestHandleCommand_ProcessList(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "process_list", "id": "cmd-proc-1", "payload": map[string]interface{}{}, } if err := HandleCommand(ctx, env, envelope); err != nil { t.Fatalf("HandleCommand(process_list) failed: %v", err) } if len(writer.msgs) != 1 { t.Fatalf("Expected 1 message, got %d", len(writer.msgs)) } var result wire.ProcessListResult if err := msgpack.Unmarshal(writer.msgs[0], &result); err != nil { t.Fatalf("Failed to unmarshal result: %v", err) } if result.Type != "process_list_result" { t.Errorf("Expected process_list_result") } } func TestHandleCommand_FileList(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() tmpDir := t.TempDir() envelope := map[string]interface{}{ "type": "command", "commandType": "file_list", "id": "cmd-file-1", "payload": map[string]interface{}{"path": tmpDir}, } if err := HandleCommand(ctx, env, envelope); err != nil { t.Fatalf("HandleCommand(file_list) failed: %v", err) } if len(writer.msgs) != 1 { t.Fatalf("Expected 1 message, got %d", len(writer.msgs)) } var result wire.FileListResult if err := msgpack.Unmarshal(writer.msgs[0], &result); err != nil { t.Fatalf("Failed to unmarshal result: %v", err) } if result.Type != "file_list_result" { t.Errorf("Expected file_list_result") } } func TestHandleCommand_UnknownCommand(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "unknown_command_xyz", "id": "cmd-unknown-1", "payload": map[string]interface{}{}, } if err := HandleCommand(ctx, env, envelope); err != nil { t.Logf("Unknown command returned error (expected): %v", err) } t.Logf("Unknown command handling sent %d messages", len(writer.msgs)) } func TestHandleCommand_DisconnectTriggersReconnect(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "disconnect", "id": "cmd-disconnect-1", } err := HandleCommand(ctx, env, envelope) if !errors.Is(err, ErrReconnect) { t.Fatalf("expected ErrReconnect, got %v", err) } if len(writer.msgs) < 1 { t.Fatal("expected command_result response") } var result wire.CommandResult if err := msgpack.Unmarshal(writer.msgs[0], &result); err != nil { t.Fatalf("failed to unmarshal command_result: %v", err) } if !result.OK { t.Fatalf("expected ok=true, got false") } } func TestHandleCommand_ReconnectTriggersReconnect(t *testing.T) { writer := &testWriter{} env := &rt.Env{ Conn: writer, Cfg: config.Config{}, } ctx := context.Background() envelope := map[string]interface{}{ "type": "command", "commandType": "reconnect", "id": "cmd-reconnect-1", } err := HandleCommand(ctx, env, envelope) if !errors.Is(err, ErrReconnect) { t.Fatalf("expected ErrReconnect, got %v", err) } if len(writer.msgs) < 1 { t.Fatal("expected command_result response") } var result wire.CommandResult if err := msgpack.Unmarshal(writer.msgs[0], &result); err != nil { t.Fatalf("failed to unmarshal command_result: %v", err) } if !result.OK { t.Fatalf("expected ok=true, got false") } } func TestCommandPayloadExtraction(t *testing.T) { tests := []struct { name string payload interface{} key string expected interface{} }{ { name: "StringValue", payload: map[string]interface{}{"path": "/test/path"}, key: "path", expected: "/test/path", }, { name: "IntValue", payload: map[string]interface{}{"pid": float64(1234)}, key: "pid", expected: float64(1234), }, { name: "BoolValue", payload: map[string]interface{}{"recursive": true}, key: "recursive", expected: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { payloadMap, ok := tt.payload.(map[string]interface{}) if !ok { t.Fatal("Payload is not a map") } value, exists := payloadMap[tt.key] if !exists { t.Errorf("Key %s not found in payload", tt.key) } if value != tt.expected { t.Errorf("Expected %v, got %v", tt.expected, value) } }) } }