11import sys
22sys .path .append ('../' )
33import unittest
4- from unittest .mock import patch , Mock
4+ from unittest .mock import patch , Mock , mock_open
55from azpype .commands .base_command import BaseCommand
66from azpype .resource_paths import get_azcopy_path
77import subprocess
8+ import yaml
9+
10+
11+ # Create a concrete implementation for testing
12+ class ConcreteCommand (BaseCommand ):
13+ def __init__ (self , command_name ):
14+ super ().__init__ (command_name )
815
916
1017class TestBaseCommand (unittest .TestCase ):
1118 def setUp (self ):
12- self .command = BaseCommand ("test_command" )
19+ self .command = ConcreteCommand ("test_command" )
1320
1421 def test_build_command (self ):
1522 args = ["arg1" , "arg2" ]
@@ -21,18 +28,72 @@ def test_build_command(self):
2128 def test_execute_success (self , mock_run ):
2229 args = ["arg1" , "arg2" ]
2330 options = {"option1" : "value1" , "option2" : True }
24- mock_run .return_value = Mock (returncode = 0 , stdout = "Success" )
31+ mock_run .return_value = Mock (returncode = 0 , stdout = "Success" , stderr = "" )
2532 expected_output = (0 , "Success" )
2633 self .assertEqual (self .command .execute (args , options ), expected_output )
2734
2835 @patch ("subprocess.run" )
2936 def test_execute_failure (self , mock_run ):
3037 args = ["arg1" , "arg2" ]
3138 options = {"option1" : "value1" , "option2" : True }
32- mock_run .side_effect = subprocess .CalledProcessError (1 , "test_command" , "Error" )
39+ error = subprocess .CalledProcessError (1 , "test_command" , "Error" )
40+ error .stdout = "Error"
41+ error .stderr = ""
42+ mock_run .side_effect = error
3343 expected_output = (1 , "Error" )
3444 self .assertEqual (self .command .execute (args , options ), expected_output )
3545
46+ def test_build_command_with_underscores (self ):
47+ """Test that underscores in option names are preserved in build_command"""
48+ args = ["source" , "dest" ]
49+ options = {"put_md5" : True , "check_length" : True , "dry_run" : False }
50+ # Note: build_command expects options already converted to hyphens
51+ # The conversion happens in build_flags
52+ options_with_hyphens = {"put-md5" : True , "check-length" : True , "dry-run" : False }
53+ expected_command = [
54+ get_azcopy_path (),
55+ "test_command" ,
56+ "source" ,
57+ "dest" ,
58+ "--put-md5=true" ,
59+ "--check-length=true"
60+ ]
61+ actual_command = self .command .build_command (args , options_with_hyphens )
62+ # Check that the hyphenated options are in the command
63+ self .assertIn ("--put-md5=true" , actual_command )
64+ self .assertIn ("--check-length=true" , actual_command )
65+ self .assertNotIn ("--dry-run" , actual_command ) # False values should not be included
66+
67+ @patch ("builtins.open" , new_callable = mock_open , read_data = "key1: value1\n key2: value2" )
68+ @patch ("azpype.resource_paths.ensure_user_config" )
69+ def test_build_flags_underscore_to_hyphen (self , mock_ensure_config , mock_file ):
70+ """Test that build_flags converts underscores to hyphens in option keys"""
71+ mock_ensure_config .return_value = "/fake/path/config.yaml"
72+
73+ # Test with underscores in option names
74+ options = {
75+ "put_md5" : True ,
76+ "check_length" : True ,
77+ "as_subdir" : False ,
78+ "dry_run" : None # Should be filtered out
79+ }
80+
81+ result = self .command .build_flags (options )
82+
83+ # Check that underscores were converted to hyphens
84+ self .assertIn ("put-md5" , result )
85+ self .assertIn ("check-length" , result )
86+ self .assertIn ("as-subdir" , result )
87+
88+ # Check that None values were filtered out
89+ self .assertNotIn ("dry-run" , result )
90+ self .assertNotIn ("dry_run" , result )
91+
92+ # Check that values are preserved
93+ self .assertEqual (result ["put-md5" ], True )
94+ self .assertEqual (result ["check-length" ], True )
95+ self .assertEqual (result ["as-subdir" ], False )
96+
3697
3798if __name__ == "__main__" :
3899 unittest .main ()
0 commit comments