package importer import ( "os" "testing" ) func TestParseMobaConf(t *testing.T) { data, err := os.ReadFile("../../docs/config-export.mobaconf") if err != nil { t.Skip("config file not found") } imp := &MobaConfImporter{} result, err := imp.Parse(data) if err != nil { t.Fatal(err) } if len(result.Groups) == 0 { t.Error("should parse groups") } if len(result.Connections) == 0 { t.Error("should parse connections") } // Check that we found the expected group foundGroup := false for _, g := range result.Groups { if g.Name == "AAA Vantz's Stuff" { foundGroup = true break } } if !foundGroup { t.Error("should find 'AAA Vantz's Stuff' group") } // Check for known SSH connections foundAsgard := false foundDocker := false for _, c := range result.Connections { if c.Name == "Asgard" { foundAsgard = true if c.Hostname != "192.168.1.4" { t.Errorf("Asgard hostname = %q, want 192.168.1.4", c.Hostname) } if c.Port != 22 { t.Errorf("Asgard port = %d, want 22", c.Port) } if c.Protocol != "ssh" { t.Errorf("Asgard protocol = %q, want ssh", c.Protocol) } if c.Username != "vstockwell" { t.Errorf("Asgard username = %q, want vstockwell", c.Username) } } if c.Name == "Docker" { foundDocker = true if c.Hostname != "155.254.29.221" { t.Errorf("Docker hostname = %q, want 155.254.29.221", c.Hostname) } } } if !foundAsgard { t.Error("should find Asgard connection") } if !foundDocker { t.Error("should find Docker connection") } // Check for RDP connections foundRDP := false for _, c := range result.Connections { if c.Name == "CLT-VMHOST01" { foundRDP = true if c.Protocol != "rdp" { t.Errorf("CLT-VMHOST01 protocol = %q, want rdp", c.Protocol) } if c.Hostname != "100.64.1.204" { t.Errorf("CLT-VMHOST01 hostname = %q, want 100.64.1.204", c.Hostname) } if c.Port != 3389 { t.Errorf("CLT-VMHOST01 port = %d, want 3389", c.Port) } } } if !foundRDP { t.Error("should find CLT-VMHOST01 RDP connection") } // Check host keys were parsed if len(result.HostKeys) == 0 { t.Error("should parse host keys") } // Check theme was parsed if result.Theme == nil { t.Error("should parse theme from Colors section") } else { if result.Theme.Foreground != "#ececec" { t.Errorf("theme foreground = %q, want #ececec", result.Theme.Foreground) } if result.Theme.Background != "#242424" { t.Errorf("theme background = %q, want #242424", result.Theme.Background) } } } func TestParseSSHSession(t *testing.T) { line := `#109#0%192.168.1.4%22%vstockwell%%-1%-1%%%22%%0%0%0%V:\ssh-key%%-1%0%0%0%%1080%%0%0%1%%0%%%%0%-1%-1%0` conn := parseSessionLine("Asgard", line) if conn == nil { t.Fatal("should parse SSH session") } if conn.Hostname != "192.168.1.4" { t.Errorf("hostname = %q, want 192.168.1.4", conn.Hostname) } if conn.Port != 22 { t.Errorf("port = %d, want 22", conn.Port) } if conn.Protocol != "ssh" { t.Errorf("protocol = %q, want ssh", conn.Protocol) } if conn.Username != "vstockwell" { t.Errorf("username = %q, want vstockwell", conn.Username) } } func TestParseRDPSession(t *testing.T) { line := `#91#4%100.64.1.204%3389%%-1%0%0%0%-1%0%0%-1` conn := parseSessionLine("CLT-VMHOST01", line) if conn == nil { t.Fatal("should parse RDP session") } if conn.Hostname != "100.64.1.204" { t.Errorf("hostname = %q, want 100.64.1.204", conn.Hostname) } if conn.Port != 3389 { t.Errorf("port = %d, want 3389", conn.Port) } if conn.Protocol != "rdp" { t.Errorf("protocol = %q, want rdp", conn.Protocol) } } func TestParseSSHSessionWithUsername(t *testing.T) { line := `#109#0%192.168.1.105%22%root%%-1%-1%%%%%0%0%0%%%-1%0%0%0%%1080%%0%0%1` conn := parseSessionLine("Node 1(top)", line) if conn == nil { t.Fatal("should parse SSH session") } if conn.Username != "root" { t.Errorf("username = %q, want root", conn.Username) } } func TestParseRDPSessionWithUsername(t *testing.T) { line := `#91#4%192.154.253.107%3389%administrator%0%0%0%0%-1%0%0%-1` conn := parseSessionLine("Win Game Host", line) if conn == nil { t.Fatal("should parse RDP session") } if conn.Username != "administrator" { t.Errorf("username = %q, want administrator", conn.Username) } if conn.Hostname != "192.154.253.107" { t.Errorf("hostname = %q, want 192.154.253.107", conn.Hostname) } } func TestRgbToHex(t *testing.T) { tests := []struct { input string want string }{ {"236,236,236", "#ececec"}, {"0,0,0", "#000000"}, {"255,255,255", "#ffffff"}, {"36,36,36", "#242424"}, {"128,128,128", "#808080"}, } for _, tt := range tests { got := rgbToHex(tt.input) if got != tt.want { t.Errorf("rgbToHex(%q) = %q, want %q", tt.input, got, tt.want) } } } func TestParseHostKeyLine(t *testing.T) { hk := parseHostKeyLine( "ssh-ed25519@22:192.168.1.4", "0x29ac3a21e1d5166c45aed41398d71cc889b683d01e1a019bf23cb2e1ce1c8276,0x2a8e2417caf686ac4b219cc3b94cd726fb49d2559bd8725ac2281b842845582b", ) if hk == nil { t.Fatal("should parse host key") } if hk.Hostname != "192.168.1.4" { t.Errorf("hostname = %q, want 192.168.1.4", hk.Hostname) } if hk.Port != 22 { t.Errorf("port = %d, want 22", hk.Port) } if hk.KeyType != "ssh-ed25519" { t.Errorf("keyType = %q, want ssh-ed25519", hk.KeyType) } } func TestImporterInterface(t *testing.T) { imp := &MobaConfImporter{} if imp.Name() != "MobaXTerm" { t.Errorf("Name() = %q, want MobaXTerm", imp.Name()) } exts := imp.FileExtensions() if len(exts) != 1 || exts[0] != ".mobaconf" { t.Errorf("FileExtensions() = %v, want [.mobaconf]", exts) } } func TestParseUnknownProtocol(t *testing.T) { line := `#999#0%hostname%22%user` conn := parseSessionLine("Unknown", line) if conn != nil { t.Error("should return nil for unknown protocol type") } } func TestParseEmptySessionLine(t *testing.T) { conn := parseSessionLine("Empty", "") if conn != nil { t.Error("should return nil for empty session line") } }