22
33import os
44import sys
5- from typing import Dict , Any
65from unittest .mock import Mock
76
87# Add parent directory to path for imports
@@ -31,56 +30,65 @@ def test_docker_info_detection_real_container(self, request: pytest.FixtureReque
3130 container_id = None
3231
3332 try :
34- # Start a test container
35- container_id = self .start_container ("nginx:alpine " , sleep_duration = "60" )
33+ # Start a test container (use non-Docker Hub image to test full repository name preservation)
34+ container_id = self .start_container ("quay.io/prometheus/busybox:latest " , sleep_duration = "60" )
3635
3736 # Wait for container to be ready
3837 self .wait_for_container_ready (container_id , "echo ready" , max_wait = 10 )
3938
40- # Test Docker Info detection
39+ # Test Docker Info detection (container info only)
4140 executor = DockerExecutor (container_id )
4241 orchestrator = Orchestrator (debug = False )
4342
44- # Test full analysis (includes container info)
45- result = orchestrator .resolve_dependencies (executor )
43+ result = orchestrator .resolve_dependencies (executor , only_container_info = True )
4644
4745 if verbose_output :
48- self .print_verbose_results ("DOCKER INFO DETECTION OUTPUT (FULL) :" , result )
46+ self .print_verbose_results ("DOCKER INFO DETECTION OUTPUT:" , result )
4947
50- # Validate container info is included
51- self ._validate_container_info_in_full_result (result )
48+ assert isinstance (result , dict ), "Result should be a dictionary"
5249
53- # Test container-info-only mode
54- result_info_only = orchestrator .resolve_dependencies (executor , only_container_info = True )
50+ # Should only have source
51+ assert "source" in result , f"Expected 'source' in result keys: { list (result .keys ())} "
52+ assert len (result ) == 1 , f"Container-info-only should have exactly 1 key, got: { list (result .keys ())} "
5553
56- if verbose_output :
57- self .print_verbose_results ("DOCKER INFO DETECTION OUTPUT (INFO ONLY):" , result_info_only )
54+ container_info = result ["source" ]
5855
59- # Validate container-info-only result
60- self ._validate_container_info_only_result (result_info_only )
56+ # Required fields
57+ required_fields = ["type" , "name" , "image" , "hash" ]
58+ for field in required_fields :
59+ assert field in container_info , f"Container info should have '{ field } ': { container_info } "
6160
62- finally :
63- if container_id :
64- self .cleanup_container (container_id )
61+ # Validate type field
62+ assert container_info ["type" ] == "container" , f"Type should be 'container': { container_info ['type' ]} "
6563
66- def test_docker_info_detector_unit_tests ( self ) -> None :
67- """Unit tests for Docker Info detector without real containers."""
68- detector = DockerInfoDetector ()
64+ name = container_info [ "name" ]
65+ image = container_info [ "image" ]
66+ hash_value = container_info [ "hash" ]
6967
70- # Test detector name
71- assert detector .NAME == "docker-info"
68+ # Validate field types and content
69+ assert isinstance (name , str ) and len (name ) > 0 , f"Name should be non-empty string: { name } "
70+ assert isinstance (image , str ) and len (image ) > 0 , f"Image should be non-empty string: { image } "
71+ assert isinstance (hash_value , str ) and len (hash_value ) > 0 , f"Hash should be non-empty string: { hash_value } "
7272
73- # Test system scope
74- mock_executor = Mock ()
75- assert not detector .has_system_scope (mock_executor )
73+ # Validate that full image name with repository is preserved
74+ assert "quay.io/prometheus/busybox:latest" == image , f"Expected full image name with repository: { image } "
7675
77- # Test is_usable with DockerExecutor
78- docker_executor = Mock (spec = DockerExecutor )
79- assert detector .is_usable (docker_executor )
76+ # Validate hash format (should start with sha256:)
77+ if hash_value != "unknown" :
78+ assert hash_value .startswith ("sha256:" ), f"Hash should start with 'sha256:': { hash_value } "
79+ assert len (hash_value ) == 71 , f"Hash should be 71 chars (sha256: + 64 hex): { hash_value } "
8080
81- # Test is_usable with non-DockerExecutor
82- other_executor = Mock ()
83- assert not detector .is_usable (other_executor )
81+ # Optional error field
82+ if "error" in container_info :
83+ error = container_info ["error" ]
84+ assert isinstance (error , str ), f"Error should be string: { error } "
85+
86+ print (f"✓ Container info structure valid: { name } -> { image } ({ hash_value [:19 ]} ...)" )
87+ print ("✓ Container-info-only mode working correctly" )
88+
89+ finally :
90+ if container_id :
91+ self .cleanup_container (container_id )
8492
8593 def test_docker_info_detector_non_docker_executor (self ) -> None :
8694 """Test behavior with non-DockerExecutor."""
@@ -92,68 +100,6 @@ def test_docker_info_detector_non_docker_executor(self) -> None:
92100 assert not packages
93101 assert not metadata
94102
95- def _validate_container_info_in_full_result (self , result : Dict [str , Any ]) -> None :
96- """Validate that container info is present in full analysis result."""
97- assert isinstance (result , dict ), "Result should be a dictionary"
98-
99- # Check for source
100- assert "source" in result , f"Expected 'source' in result keys: { list (result .keys ())} "
101-
102- container_info = result ["source" ]
103- self ._validate_container_info_structure (container_info )
104-
105- # Should also have other detectors
106- other_detectors = [key for key in result .keys () if key != "source" ]
107- assert len (other_detectors ) > 0 , "Should have other detectors in full analysis"
108-
109- print (f"✓ Container info included in full analysis with { len (other_detectors )} other detectors" )
110-
111- def _validate_container_info_only_result (self , result : Dict [str , Any ]) -> None :
112- """Validate container-info-only result structure."""
113- assert isinstance (result , dict ), "Result should be a dictionary"
114-
115- # Should only have source
116- assert "source" in result , f"Expected 'source' in result keys: { list (result .keys ())} "
117- assert len (result ) == 1 , f"Container-info-only should have exactly 1 key, got: { list (result .keys ())} "
118-
119- container_info = result ["source" ]
120- self ._validate_container_info_structure (container_info )
121-
122- print ("✓ Container-info-only mode working correctly" )
123-
124- def _validate_container_info_structure (self , container_info : Dict [str , Any ]) -> None :
125- """Validate the structure of container info."""
126- assert isinstance (container_info , dict ), "Container info should be a dictionary"
127-
128- # Required fields
129- required_fields = ["type" , "name" , "image" , "hash" ]
130- for field in required_fields :
131- assert field in container_info , f"Container info should have '{ field } ': { container_info } "
132-
133- # Validate type field
134- assert container_info ["type" ] == "container" , f"Type should be 'container': { container_info ['type' ]} "
135-
136- name = container_info ["name" ]
137- image = container_info ["image" ]
138- hash_value = container_info ["hash" ]
139-
140- # Validate field types and content
141- assert isinstance (name , str ) and len (name ) > 0 , f"Name should be non-empty string: { name } "
142- assert isinstance (image , str ) and len (image ) > 0 , f"Image should be non-empty string: { image } "
143- assert isinstance (hash_value , str ) and len (hash_value ) > 0 , f"Hash should be non-empty string: { hash_value } "
144-
145- # Validate hash format (should start with sha256:)
146- if hash_value != "unknown" :
147- assert hash_value .startswith ("sha256:" ), f"Hash should start with 'sha256:': { hash_value } "
148- assert len (hash_value ) == 71 , f"Hash should be 71 chars (sha256: + 64 hex): { hash_value } "
149-
150- # Optional error field
151- if "error" in container_info :
152- error = container_info ["error" ]
153- assert isinstance (error , str ), f"Error should be string: { error } "
154-
155- print (f"✓ Container info structure valid: { name } -> { image } ({ hash_value [:19 ]} ...)" )
156-
157103
158104class TestDockerInfoDetectorIntegration :
159105 """Integration tests for Docker Info detector with orchestrator."""
0 commit comments