22import os
33import unittest
44import tempfile
5- import pathlib
65from unittest import mock
7- from pathlib import Path
86
9- from chipflow_lib import ChipFlowError
107from chipflow_lib .platforms .utils import (
11- Port , Package , PortMap , LockFile , Process , _QuadPackageDef
8+ Package , PortMap , LockFile , Process , _QuadPackageDef
129)
1310from chipflow_lib .config_models import Config , SiliconConfig , PadConfig , StepsConfig , ChipFlowConfig
1411from chipflow_lib .pin_lock import (
@@ -41,11 +38,9 @@ def setUp(self):
4138 self .temp_dir = tempfile .TemporaryDirectory ()
4239 self .original_cwd = os .getcwd ()
4340 os .chdir (self .temp_dir .name )
44-
4541 # Mock environment for testing
4642 self .chipflow_root_patcher = mock .patch .dict (os .environ , {"CHIPFLOW_ROOT" : self .temp_dir .name })
4743 self .chipflow_root_patcher .start ()
48-
4944 # Create test configuration
5045 # Create a proper Pydantic model
5146 self .silicon_config = SiliconConfig (
@@ -61,12 +56,10 @@ def setUp(self):
6156 "vss" : PadConfig (type = "ground" , loc = "5" )
6257 }
6358 )
64-
6559 # Create the steps config
6660 self .steps_config = StepsConfig (
6761 silicon = "chipflow_lib.steps.silicon:SiliconStep"
6862 )
69-
7063 # Create a full chipflow config
7164 self .chipflow_config = ChipFlowConfig (
7265 project_name = "test_project" ,
@@ -76,10 +69,8 @@ def setUp(self):
7669 clocks = {"default" : "clk" },
7770 resets = {"default" : "rst" }
7871 )
79-
8072 # Create the complete config
8173 self .config = Config (chipflow = self .chipflow_config )
82-
8374 # Also create a dict version for compatibility with some functions
8475 self .config_dict = {
8576 "chipflow" : {
@@ -111,7 +102,6 @@ def setUp(self):
111102 }
112103 }
113104 }
114-
115105 # Create mock interfaces
116106 self .mock_interfaces = {
117107 "soc" : {
@@ -195,14 +185,11 @@ def test_allocate_pins_interface_with_annotation(self):
195185 }
196186 }
197187 pins = ["pin1" , "pin2" , "pin3" , "pin4" , "pin5" , "pin6" ]
198-
199188 pin_map , remaining_pins = allocate_pins ("test_interface" , member_data , pins )
200-
201189 # Check that correct pins were allocated
202190 self .assertIn ("test_interface" , pin_map )
203191 self .assertEqual (pin_map ["test_interface" ]["pins" ], pins [:4 ])
204192 self .assertEqual (pin_map ["test_interface" ]["direction" ], "io" )
205-
206193 # Check remaining pins
207194 self .assertEqual (remaining_pins , pins [4 :])
208195
@@ -224,18 +211,14 @@ def test_allocate_pins_interface_without_annotation(self):
224211 }
225212 }
226213 pins = ["pin1" , "pin2" , "pin3" , "pin4" , "pin5" , "pin6" ]
227-
228214 pin_map , remaining_pins = allocate_pins ("test_interface" , member_data , pins )
229-
230215 # Check that correct pins were allocated
231216 self .assertIn ("sub1" , pin_map )
232217 self .assertEqual (pin_map ["sub1" ]["pins" ], pins [:2 ])
233218 self .assertEqual (pin_map ["sub1" ]["direction" ], "i" )
234-
235219 self .assertIn ("sub2" , pin_map )
236220 self .assertEqual (pin_map ["sub2" ]["pins" ], pins [2 :5 ])
237221 self .assertEqual (pin_map ["sub2" ]["direction" ], "o" )
238-
239222 # Check remaining pins
240223 self .assertEqual (remaining_pins , pins [5 :])
241224
@@ -247,15 +230,12 @@ def test_allocate_pins_port(self):
247230 "dir" : "i"
248231 }
249232 pins = ["pin1" , "pin2" , "pin3" , "pin4" ]
250-
251233 pin_map , remaining_pins = allocate_pins ("test_port" , member_data , pins , port_name = "my_port" )
252-
253234 # Check that correct pins were allocated
254235 self .assertIn ("test_port" , pin_map )
255236 self .assertEqual (pin_map ["test_port" ]["pins" ], pins [:3 ])
256237 self .assertEqual (pin_map ["test_port" ]["direction" ], "i" )
257238 self .assertEqual (pin_map ["test_port" ]["port_name" ], "my_port" )
258-
259239 # Check remaining pins
260240 self .assertEqual (remaining_pins , pins [3 :])
261241
@@ -266,42 +246,35 @@ def test_allocate_pins_port(self):
266246 @mock .patch ("chipflow_lib.pin_lock.top_interfaces" )
267247 @mock .patch ("pathlib.Path.exists" )
268248 @mock .patch ("builtins.open" , new_callable = mock .mock_open )
269- def test_lock_pins_new_file (self , mock_open , mock_exists , mock_top_interfaces ,
249+ def test_lock_pins_new_file (self , mock_open , mock_exists , mock_top_interfaces ,
270250 mock_config_validate , mock_parse_config ):
271251 """Test lock_pins function with a new pins.lock file"""
272252 # Set up mocks
273253 mock_parse_config .return_value = self .config_dict
274254 mock_config_validate .return_value = self .config
275255 mock_exists .return_value = False # No existing file
276256 mock_top_interfaces .return_value = ({}, self .mock_interfaces )
277-
278- # Create real Pydantic objects
279- package_def = MockPackageType (name = "cf20" )
280-
281257 # Call the function with real objects
282258 with mock .patch ("chipflow_lib.pin_lock.logger" ):
283259 lock_pins ()
284-
285260 # Verify open was called for writing the pin lock file
286261 mock_open .assert_called_once_with ('pins.lock' , 'w' )
287-
288262 # Check that the file was written (write was called)
289263 mock_open ().write .assert_called_once ()
290-
291264 # We can't easily verify the exact content that was written without
292265 # fully mocking all the complex Pydantic objects, but we can check that
293266 # a write happened, which confirms basic functionality
294267
295- @mock .patch ("chipflow_lib.pin_lock._parse_config" )
268+ @mock .patch ("chipflow_lib.pin_lock._parse_config" )
296269 @mock .patch ("chipflow_lib.pin_lock.Config.model_validate" )
297270 @mock .patch ("chipflow_lib.pin_lock.PACKAGE_DEFINITIONS" , new = {"cf20" : _QuadPackageDef (name = "cf20" , width = 50 , height = 50 )})
298271 @mock .patch ("chipflow_lib.pin_lock.top_interfaces" )
299272 @mock .patch ("pathlib.Path.exists" )
300273 @mock .patch ("pathlib.Path.read_text" )
301274 @mock .patch ("chipflow_lib.pin_lock.LockFile.model_validate_json" )
302275 @mock .patch ("builtins.open" , new_callable = mock .mock_open )
303- def test_lock_pins_with_existing_lockfile (self , mock_open , mock_validate_json ,
304- mock_read_text , mock_exists , mock_top_interfaces ,
276+ def test_lock_pins_with_existing_lockfile (self , mock_open , mock_validate_json ,
277+ mock_read_text , mock_exists , mock_top_interfaces ,
305278 mock_config_validate , mock_parse_config ):
306279 """Test lock_pins function with an existing pins.lock file"""
307280 # Setup mocks
@@ -310,42 +283,34 @@ def test_lock_pins_with_existing_lockfile(self, mock_open, mock_validate_json,
310283 mock_exists .return_value = True # Existing file
311284 mock_read_text .return_value = '{"mock":"json"}'
312285 mock_top_interfaces .return_value = ({}, self .mock_interfaces )
313-
314286 # Create a package for the existing lock file
315287 package_def = _QuadPackageDef (name = "cf20" , width = 50 , height = 50 )
316-
317288 # Create a Package instance with the package_def
318289 package = Package (
319290 package_type = package_def ,
320291 clocks = {},
321292 resets = {},
322293 power = {}
323294 )
324-
325295 # Create a PortMap instance
326296 port_map = PortMap ({})
327-
328297 # Create the LockFile instance
329298 old_lock = LockFile (
330299 process = Process .IHP_SG13G2 ,
331300 package = package ,
332301 port_map = port_map ,
333302 metadata = {}
334303 )
335-
336304 # Setup the mock to return our LockFile
337305 mock_validate_json .return_value = old_lock
338-
339306 # Call the function
340307 with mock .patch ("chipflow_lib.pin_lock.logger" ):
341308 lock_pins ()
342-
343309 # Verify file operations
344310 mock_read_text .assert_called_once ()
345311 mock_validate_json .assert_called_once_with ('{"mock":"json"}' )
346312 mock_open .assert_called_once_with ('pins.lock' , 'w' )
347313 mock_open ().write .assert_called_once ()
348-
349314 # Since we're using real objects, we'd need complex assertions to
350315 # verify the exact behavior. But the above confirms the basic flow
351316 # of reading the existing file and writing a new one.
@@ -357,27 +322,20 @@ def test_pin_command(self, mock_lock_pins):
357322 """Test PinCommand functionality"""
358323 # Create config
359324 config = {"test" : "config" }
360-
361325 # Create command instance
362326 cmd = PinCommand (config )
363-
364327 # Create mock args
365328 mock_args = mock .Mock ()
366329 mock_args .action = "lock"
367-
368330 # Call run_cli
369331 cmd .run_cli (mock_args )
370-
371332 # Verify lock_pins was called
372333 mock_lock_pins .assert_called_once ()
373-
374334 # Test build_cli_parser
375335 mock_parser = mock .Mock ()
376336 mock_subparsers = mock .Mock ()
377337 mock_parser .add_subparsers .return_value = mock_subparsers
378-
379338 cmd .build_cli_parser (mock_parser )
380-
381339 # Verify parser was built
382340 mock_parser .add_subparsers .assert_called_once ()
383341 mock_subparsers .add_parser .assert_called_once ()
0 commit comments