1+ import unittest
2+ from unittest .mock import Mock , patch , call
3+ import tasks
4+ from invoke import Context
5+
6+
7+ class TestTasks (unittest .TestCase ):
8+
9+ def setUp (self ):
10+ self .mock_context = Mock (spec = Context )
11+
12+ def test_version_name_to_version_all (self ):
13+ """Test version_name_to_version returns all versions when 'all' is passed"""
14+ result = tasks .version_name_to_version ("all" )
15+ self .assertEqual (result , tasks .version_config_mapping )
16+
17+ def test_version_name_to_version_latest (self ):
18+ """Test version_name_to_version returns latest version when 'latest' is passed"""
19+ result = tasks .version_name_to_version ("latest" )
20+ self .assertEqual (result , [tasks .latest_version_string ])
21+
22+ def test_version_name_to_version_specific (self ):
23+ """Test version_name_to_version filters versions correctly"""
24+ result = tasks .version_name_to_version ("7.2" )
25+ expected = [v for v in tasks .version_config_mapping if v .startswith ("7.2" )]
26+ self .assertEqual (result , expected )
27+
28+ def test_filter_versions (self ):
29+ """Test filter_versions returns correct subset"""
30+ result = tasks .filter_versions ("7.0" )
31+ expected = [v for v in tasks .version_config_mapping if v .startswith ("7.0" )]
32+ self .assertEqual (result , expected )
33+ self .assertTrue (len (result ) > 0 )
34+
35+ @patch ('multiprocessing.cpu_count' )
36+ def test_get_pool_size_default (self , mock_cpu_count ):
37+ """Test get_pool_size uses CPU count minus 1 by default"""
38+ mock_cpu_count .return_value = 8
39+ result = tasks .get_pool_size (None )
40+ self .assertEqual (result , 7 )
41+
42+ def test_get_pool_size_custom (self ):
43+ """Test get_pool_size uses provided value"""
44+ result = tasks .get_pool_size ("4" )
45+ self .assertEqual (result , 4 )
46+
47+ def test_docker_build_with_platforms (self ):
48+ """Test _docker_build executes correct buildx commands"""
49+ config = [self .mock_context , "7.2.5" , "linux/amd64,linux/arm64" ]
50+
51+ tasks ._docker_build (config )
52+
53+ # Verify buildx setup
54+ self .mock_context .run .assert_any_call (
55+ "docker buildx create --use --name redis-cluster-builder || docker buildx use redis-cluster-builder" ,
56+ warn = True
57+ )
58+
59+ # Verify build command
60+ expected_build_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --load ."
61+ self .mock_context .run .assert_any_call (expected_build_cmd )
62+
63+ def test_docker_push_with_platforms (self ):
64+ """Test _docker_push executes correct buildx push commands"""
65+ config = [self .mock_context , "7.2.5" , "linux/amd64,linux/arm64" ]
66+
67+ tasks ._docker_push (config )
68+
69+ # Verify buildx setup
70+ self .mock_context .run .assert_any_call (
71+ "docker buildx create --use --name redis-cluster-builder || docker buildx use redis-cluster-builder" ,
72+ warn = True
73+ )
74+
75+ # Verify push command
76+ expected_push_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --push ."
77+ self .mock_context .run .assert_any_call (expected_push_cmd )
78+
79+ def test_docker_buildx_push_true (self ):
80+ """Test _docker_buildx with push=True"""
81+ config = [self .mock_context , "7.2.5" , "linux/amd64,linux/arm64" , True ]
82+
83+ tasks ._docker_buildx (config )
84+
85+ expected_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --push ."
86+ self .mock_context .run .assert_called_with (expected_cmd )
87+
88+ def test_docker_buildx_push_false (self ):
89+ """Test _docker_buildx with push=False"""
90+ config = [self .mock_context , "7.2.5" , "linux/amd64,linux/arm64" , False ]
91+
92+ tasks ._docker_buildx (config )
93+
94+ expected_cmd = "docker buildx build --platform=linux/amd64,linux/arm64 --build-arg redis_version=7.2.5 -t grokzen/redis-cluster:7.2.5 --load ."
95+ self .mock_context .run .assert_called_with (expected_cmd )
96+
97+ @patch ('tasks.Pool' )
98+ def test_build_task_with_default_platforms (self , mock_pool_class ):
99+ """Test build task with default platforms"""
100+ mock_pool = Mock ()
101+ mock_pool_class .return_value = mock_pool
102+
103+ tasks .build (self .mock_context , "7.2.5" )
104+
105+ # Verify pool.map was called with correct arguments
106+ mock_pool .map .assert_called_once ()
107+ call_args = mock_pool .map .call_args [0 ]
108+ self .assertEqual (call_args [0 ], tasks ._docker_build )
109+
110+ # Check that platform parameter is included
111+ configs = call_args [1 ]
112+ self .assertEqual (len (configs ), 1 )
113+ self .assertEqual (configs [0 ][2 ], "linux/amd64,linux/arm64" )
114+
115+ @patch ('tasks.Pool' )
116+ def test_push_task_with_custom_platforms (self , mock_pool_class ):
117+ """Test push task with custom platforms"""
118+ mock_pool = Mock ()
119+ mock_pool_class .return_value = mock_pool
120+
121+ tasks .push (self .mock_context , "7.2.5" , platforms = "linux/arm64" )
122+
123+ # Verify pool.map was called with correct arguments
124+ mock_pool .map .assert_called_once ()
125+ call_args = mock_pool .map .call_args [0 ]
126+ configs = call_args [1 ]
127+ self .assertEqual (configs [0 ][2 ], "linux/arm64" )
128+
129+ @patch ('tasks.Pool' )
130+ def test_buildx_task (self , mock_pool_class ):
131+ """Test buildx task functionality"""
132+ mock_pool = Mock ()
133+ mock_pool_class .return_value = mock_pool
134+
135+ # Test with push=True
136+ tasks .buildx (self .mock_context , "latest" , push = True )
137+
138+ # Verify buildx setup
139+ self .mock_context .run .assert_called_with (
140+ "docker buildx create --use --name redis-cluster-builder || docker buildx use redis-cluster-builder" ,
141+ warn = True
142+ )
143+
144+ # Verify pool.map was called
145+ mock_pool .map .assert_called_once ()
146+ call_args = mock_pool .map .call_args [0 ]
147+ self .assertEqual (call_args [0 ], tasks ._docker_buildx )
148+
149+ configs = call_args [1 ]
150+ self .assertEqual (len (configs ), 1 )
151+ self .assertEqual (configs [0 ][1 ], tasks .latest_version_string )
152+ self .assertEqual (configs [0 ][2 ], "linux/amd64,linux/arm64" )
153+ self .assertEqual (configs [0 ][3 ], True )
154+
155+ @patch ('tasks.Pool' )
156+ def test_buildx_task_no_push (self , mock_pool_class ):
157+ """Test buildx task with --no-push flag"""
158+ mock_pool = Mock ()
159+ mock_pool_class .return_value = mock_pool
160+
161+ # Test with no_push=True
162+ tasks .buildx (self .mock_context , "latest" , no_push = True )
163+
164+ # Verify pool.map was called with push=False
165+ mock_pool .map .assert_called_once ()
166+ call_args = mock_pool .map .call_args [0 ]
167+ configs = call_args [1 ]
168+ self .assertEqual (configs [0 ][3 ], False ) # push should be False
169+
170+
171+ class TestIntegration (unittest .TestCase ):
172+ """Integration tests that verify the full workflow"""
173+
174+ @patch ('tasks.Pool' )
175+ @patch ('multiprocessing.cpu_count' )
176+ def test_multi_version_build (self , mock_cpu_count , mock_pool_class ):
177+ """Test building multiple versions in parallel"""
178+ mock_cpu_count .return_value = 4
179+ mock_pool = Mock ()
180+ mock_pool_class .return_value = mock_pool
181+ mock_context = Mock (spec = Context )
182+
183+ # Build all 7.2.x versions
184+ tasks .build (mock_context , "7.2" )
185+
186+ # Verify pool was created with correct size
187+ mock_pool_class .assert_called_with (3 ) # cpu_count - 1
188+
189+ # Verify map was called
190+ mock_pool .map .assert_called_once ()
191+ configs = mock_pool .map .call_args [0 ][1 ]
192+
193+ # Should build all 7.2.x versions
194+ versions = [cfg [1 ] for cfg in configs ]
195+ expected_versions = [v for v in tasks .version_config_mapping if v .startswith ("7.2" )]
196+ self .assertEqual (versions , expected_versions )
197+
198+ # All should have multi-arch platforms
199+ platforms = [cfg [2 ] for cfg in configs ]
200+ self .assertTrue (all (p == "linux/amd64,linux/arm64" for p in platforms ))
201+
202+
203+ if __name__ == '__main__' :
204+ unittest .main ()
0 commit comments