@@ -224,7 +224,7 @@ def test_config_incomplete_entries(self, mock_exists) -> None:
224224 with patch ("builtins.open" , mock_open (read_data = self .mock_config_incomplete )):
225225 result = get_config_content ()
226226
227- expected : Dict [ str , Dict [ str , str ]] = {
227+ expected = {
228228 "complete_host" : {
229229 "Hostname" : "complete.example.com" ,
230230 "User" : "complete_user" ,
@@ -484,37 +484,6 @@ def test_config_with_other_directives(self, mock_exists) -> None:
484484 }
485485 self .assertEqual (result , expected )
486486
487- @patch ("os.path.exists" , return_value = True )
488- def test_config_with_wildcards (self , mock_exists ) -> None :
489- """Test parsing config with wildcard hosts"""
490- wildcard_config = """
491- Host *.example.com
492- User wildcard_user
493- Port 3030
494-
495- Host specific.example.com
496- HostName specific.example.com
497- User specific_user
498- Port 4040
499-
500- Host *
501- User default_user
502- """
503- with patch ("builtins.open" , mock_open (read_data = wildcard_config )):
504- result = get_config_content ()
505-
506- # Check for the actual key names that should be parsed
507- self .assertIn ("*.example.com" , result )
508- self .assertIn ("specific.example.com" , result ) # Fixed: use full hostname
509- self .assertIn ("*" , result )
510-
511- # Verify the parsed values
512- self .assertEqual (result ["*.example.com" ]["User" ], "wildcard_user" )
513- self .assertEqual (result ["*.example.com" ]["Port" ], "3030" )
514- self .assertEqual (result ["specific.example.com" ]["User" ], "specific_user" )
515- self .assertEqual (result ["specific.example.com" ]["Port" ], "4040" )
516- self .assertEqual (result ["*" ]["User" ], "default_user" )
517-
518487 @patch ("os.path.exists" , return_value = True )
519488 def test_large_config_performance (self , mock_exists ) -> None :
520489 """Test parsing a large config file"""
@@ -660,3 +629,188 @@ def test_debug_incomplete_actual_behavior(self, mock_exists) -> None:
660629 else :
661630 # There might be cross-contamination between sections
662631 print ("Potential cross-contamination detected" )
632+
633+ @patch ("os.path.exists" , return_value = True )
634+ def test_basic_host_parsing (self , mock_exists ):
635+ """Test parsing a basic SSH config with hyphenated host names"""
636+ config = """
637+ Host server-one
638+ HostName server-one.example.com
639+ User username
640+ Port 22
641+
642+ Host web-server
643+ HostName web.example.com
644+ User webuser
645+ Port 2222
646+ """
647+ with patch ("builtins.open" , mock_open (read_data = config )):
648+ result = get_config_content ()
649+
650+ self .assertIn ("server-one" , result )
651+ self .assertIn ("web-server" , result )
652+
653+ # Check server-one details
654+ self .assertEqual (result ["server-one" ]["Hostname" ], "server-one.example.com" )
655+ self .assertEqual (result ["server-one" ]["User" ], "username" )
656+ self .assertEqual (result ["server-one" ]["Port" ], "22" )
657+
658+ # Check web-server details
659+ self .assertEqual (result ["web-server" ]["Hostname" ], "web.example.com" )
660+ self .assertEqual (result ["web-server" ]["User" ], "webuser" )
661+ self .assertEqual (result ["web-server" ]["Port" ], "2222" )
662+
663+ @patch ("os.path.exists" , return_value = True )
664+ def test_wildcard_filtering (self , mock_exists ):
665+ """Test that wildcard hosts are filtered out"""
666+ config = """
667+ Host *
668+ Compression yes
669+ User default_user
670+
671+ Host server-one
672+ HostName server-one.example.com
673+ User username
674+ Port 22
675+
676+ Host *.example.com
677+ User wildcard_user
678+ Port 3030
679+ """
680+ with patch ("builtins.open" , mock_open (read_data = config )):
681+ result = get_config_content ()
682+
683+ # Should only contain non-wildcard hosts
684+ self .assertIn ("server-one" , result )
685+ self .assertNotIn ("*" , result )
686+ self .assertNotIn ("*.example.com" , result )
687+
688+ # Should have only one entry
689+ self .assertEqual (len (result ), 1 )
690+
691+ # Check that server-one is parsed correctly
692+ self .assertEqual (result ["server-one" ]["Hostname" ], "server-one.example.com" )
693+ self .assertEqual (result ["server-one" ]["User" ], "username" )
694+ self .assertEqual (result ["server-one" ]["Port" ], "22" )
695+
696+ @patch ("os.path.exists" , return_value = True )
697+ def test_mixed_wildcard_and_specific_hosts (self , mock_exists ):
698+ """Test parsing config with mix of wildcard and specific hosts"""
699+ config = """
700+ Host *
701+ Compression yes
702+
703+ Host *.dev
704+ User dev_user
705+
706+ Host server-one
707+ HostName server-one.example.com
708+ User username
709+ Port 22
710+
711+ Host db-server
712+ HostName db.example.com
713+ User dbuser
714+
715+ Host *.test.com
716+ User test_user
717+ """
718+ with patch ("builtins.open" , mock_open (read_data = config )):
719+ result = get_config_content ()
720+
721+ # Should only contain specific hosts, no wildcards
722+ expected_hosts = {"server-one" , "db-server" }
723+ actual_hosts = set (result .keys ())
724+ self .assertEqual (actual_hosts , expected_hosts )
725+
726+ # Verify no wildcard entries
727+ for host in result .keys ():
728+ self .assertNotIn ("*" , host )
729+
730+ @patch ("os.path.exists" , return_value = True )
731+ def test_complex_hostnames (self , mock_exists ):
732+ """Test parsing hosts with various character patterns"""
733+ config = """
734+ Host my-server.prod
735+ HostName my-server.prod.example.com
736+ User prod_user
737+ Port 443
738+
739+ Host test_server_01
740+ HostName 192.168.1.100
741+ User testuser
742+ Port 2222
743+
744+ Host staging-web-01
745+ HostName staging-web-01.internal
746+ User deploy
747+ """
748+ with patch ("builtins.open" , mock_open (read_data = config )):
749+ result = get_config_content ()
750+
751+ expected_hosts = {"my-server.prod" , "test_server_01" , "staging-web-01" }
752+ actual_hosts = set (result .keys ())
753+ self .assertEqual (actual_hosts , expected_hosts )
754+
755+ # Check specific details
756+ self .assertEqual (result ["my-server.prod" ]["Port" ], "443" )
757+ self .assertEqual (result ["test_server_01" ]["Hostname" ], "192.168.1.100" )
758+ self .assertEqual (result ["staging-web-01" ]["User" ], "deploy" )
759+
760+ @patch ("os.path.exists" , return_value = True )
761+ def test_commented_lines_ignored (self , mock_exists ):
762+ """Test that commented lines are properly ignored"""
763+ config = """
764+ # Global settings
765+ Host *
766+ Compression yes
767+
768+ # Production server
769+ Host server-one
770+ HostName server-one.example.com
771+ User username
772+ # Port 2222 # Commented out port
773+ Port 22
774+
775+ # Host commented-out-server
776+ # HostName should-not-appear.com
777+ """
778+ with patch ("builtins.open" , mock_open (read_data = config )):
779+ result = get_config_content ()
780+
781+ # Should only have server-one
782+ self .assertEqual (list (result .keys ()), ["server-one" ])
783+ self .assertEqual (
784+ result ["server-one" ]["Port" ], "22"
785+ ) # Should use uncommented port
786+
787+ @patch ("os.path.exists" , return_value = True )
788+ def test_default_values (self , mock_exists ):
789+ """Test default values are applied correctly"""
790+ config = """
791+ Host minimal-server
792+ HostName minimal.example.com
793+ # No user or port specified
794+
795+ Host partial-server
796+ User partial_user
797+ # No hostname or port specified
798+ """
799+ with patch ("builtins.open" , mock_open (read_data = config )):
800+ result = get_config_content ()
801+
802+ # Check minimal-server defaults
803+ self .assertEqual (
804+ result ["minimal-server" ]["Hostname" ], "minimal.example.com"
805+ )
806+ self .assertEqual (
807+ result ["minimal-server" ]["User" ], None
808+ ) # No user specified
809+ self .assertEqual (result ["minimal-server" ]["Port" ], "22" ) # Default port
810+
811+ # Check partial-server defaults
812+ self .assertEqual (
813+ result ["partial-server" ]["Hostname" ], "partial-server"
814+ ) # Defaults to host name
815+ self .assertEqual (result ["partial-server" ]["User" ], "partial_user" )
816+ self .assertEqual (result ["partial-server" ]["Port" ], "22" ) # Default port
0 commit comments