package rdp import "testing" func TestNewRDPService(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) if svc == nil { t.Fatal("NewRDPService returned nil") } if len(svc.ListSessions()) != 0 { t.Error("new service should have no sessions") } } func TestConnectWithMockBackend(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{ Hostname: "test-host", Port: 3389, Username: "admin", Width: 1024, Height: 768, } sessionID, err := svc.Connect(config, 42) if err != nil { t.Fatalf("Connect error: %v", err) } if sessionID == "" { t.Fatal("Connect returned empty session ID") } // Verify session is tracked sessions := svc.ListSessions() if len(sessions) != 1 { t.Fatalf("expected 1 session, got %d", len(sessions)) } if sessions[0].ID != sessionID { t.Errorf("session ID = %q, want %q", sessions[0].ID, sessionID) } if sessions[0].ConnID != 42 { t.Errorf("ConnID = %d, want 42", sessions[0].ConnID) } if sessions[0].Config.Hostname != "test-host" { t.Errorf("Hostname = %q, want %q", sessions[0].Config.Hostname, "test-host") } } func TestConnectDefaults(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) // Connect with zero values — should get defaults config := RDPConfig{Hostname: "host"} sessionID, err := svc.Connect(config, 1) if err != nil { t.Fatalf("Connect error: %v", err) } info, err := svc.GetSessionInfo(sessionID) if err != nil { t.Fatalf("GetSessionInfo error: %v", err) } if info.Config.Port != 3389 { t.Errorf("default Port = %d, want 3389", info.Config.Port) } if info.Config.Width != 1920 { t.Errorf("default Width = %d, want 1920", info.Config.Width) } if info.Config.Height != 1080 { t.Errorf("default Height = %d, want 1080", info.Config.Height) } if info.Config.ColorDepth != 32 { t.Errorf("default ColorDepth = %d, want 32", info.Config.ColorDepth) } if info.Config.Security != "nla" { t.Errorf("default Security = %q, want %q", info.Config.Security, "nla") } } func TestDisconnect(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 800, Height: 600} sessionID, err := svc.Connect(config, 1) if err != nil { t.Fatalf("Connect error: %v", err) } if err := svc.Disconnect(sessionID); err != nil { t.Fatalf("Disconnect error: %v", err) } if len(svc.ListSessions()) != 0 { t.Error("expected 0 sessions after disconnect") } // Verify double-disconnect returns error if err := svc.Disconnect(sessionID); err == nil { t.Error("expected error on double disconnect") } } func TestDisconnectNotFound(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) if err := svc.Disconnect("nonexistent"); err == nil { t.Error("expected error for nonexistent session") } } func TestSessionTracking(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 640, Height: 480} id1, _ := svc.Connect(config, 1) id2, _ := svc.Connect(config, 2) id3, _ := svc.Connect(config, 3) if len(svc.ListSessions()) != 3 { t.Fatalf("expected 3 sessions, got %d", len(svc.ListSessions())) } // Disconnect middle session if err := svc.Disconnect(id2); err != nil { t.Fatalf("Disconnect error: %v", err) } sessions := svc.ListSessions() if len(sessions) != 2 { t.Fatalf("expected 2 sessions, got %d", len(sessions)) } // Verify remaining sessions ids := make(map[string]bool) for _, s := range sessions { ids[s.ID] = true } if !ids[id1] || !ids[id3] { t.Error("remaining sessions should be id1 and id3") } } func TestSendMouse(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 800, Height: 600} sessionID, _ := svc.Connect(config, 1) if err := svc.SendMouse(sessionID, 100, 200, MouseFlagMove); err != nil { t.Errorf("SendMouse error: %v", err) } if err := svc.SendMouse(sessionID, 100, 200, MouseFlagButton1|MouseFlagDown); err != nil { t.Errorf("SendMouse click error: %v", err) } } func TestSendMouseNotFound(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) if err := svc.SendMouse("nonexistent", 0, 0, 0); err == nil { t.Error("expected error for nonexistent session") } } func TestSendKey(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 800, Height: 600} sessionID, _ := svc.Connect(config, 1) // Send key down sc, _ := JSKeyToScancode("KeyA") if err := svc.SendKey(sessionID, sc, true); err != nil { t.Errorf("SendKey down error: %v", err) } // Send key up if err := svc.SendKey(sessionID, sc, false); err != nil { t.Errorf("SendKey up error: %v", err) } } func TestSendKeyNotFound(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) if err := svc.SendKey("nonexistent", 0x001E, true); err == nil { t.Error("expected error for nonexistent session") } } func TestSendClipboard(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 800, Height: 600} sessionID, _ := svc.Connect(config, 1) if err := svc.SendClipboard(sessionID, "hello clipboard"); err != nil { t.Errorf("SendClipboard error: %v", err) } } func TestGetFrame(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 100, Height: 100} sessionID, _ := svc.Connect(config, 1) frame, err := svc.GetFrame(sessionID) if err != nil { t.Fatalf("GetFrame error: %v", err) } expectedLen := 100 * 100 * 4 if len(frame) != expectedLen { t.Errorf("frame length = %d, want %d", len(frame), expectedLen) } // Verify the frame is not all zeros (mock generates colored content) allZero := true for _, b := range frame { if b != 0 { allZero = false break } } if allZero { t.Error("mock frame should not be all zeros") } } func TestGetFrameNotFound(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) _, err := svc.GetFrame("nonexistent") if err == nil { t.Error("expected error for nonexistent session") } } func TestIsConnected(t *testing.T) { svc := NewRDPService(func() RDPBackend { return NewMockBackend() }) config := RDPConfig{Hostname: "host", Width: 800, Height: 600} sessionID, _ := svc.Connect(config, 1) if !svc.IsConnected(sessionID) { t.Error("session should be connected") } svc.Disconnect(sessionID) if svc.IsConnected(sessionID) { t.Error("session should not be connected after disconnect") } }