1+ """
2+ Test file extension preservation across iterations
3+ """
4+
5+ import os
6+ import tempfile
7+ import unittest
8+ from pathlib import Path
9+ from unittest .mock import patch , MagicMock
10+
11+ from openevolve .config import Config , EvaluatorConfig , DatabaseConfig , LLMConfig , PromptConfig
12+ from openevolve .controller import OpenEvolve
13+ from openevolve .evaluator import Evaluator
14+ from openevolve .process_parallel import ProcessParallelController , _worker_init , _lazy_init_worker_components
15+
16+
17+ class TestFileExtensionPreservation (unittest .TestCase ):
18+ """Test that file extensions are preserved across iterations"""
19+
20+ def setUp (self ):
21+ """Set up test fixtures"""
22+ self .temp_dir = tempfile .mkdtemp ()
23+
24+ # Create test config
25+ self .config = Config (
26+ max_iterations = 5 ,
27+ language = "cpp" ,
28+ llm = LLMConfig (models = []),
29+ database = DatabaseConfig (population_size = 10 , num_islands = 2 ),
30+ evaluator = EvaluatorConfig (parallel_evaluations = 1 ),
31+ prompt = PromptConfig (),
32+ )
33+
34+ def tearDown (self ):
35+ """Clean up test fixtures"""
36+ import shutil
37+ shutil .rmtree (self .temp_dir , ignore_errors = True )
38+
39+ def test_controller_preserves_file_extension (self ):
40+ """Test that the controller properly extracts and stores file extension"""
41+ # Test Path extraction directly
42+ test_files = [
43+ "test.cpp" ,
44+ "test.rs" ,
45+ "test.py" ,
46+ "test.r"
47+ ]
48+
49+ for filename in test_files :
50+ with self .subTest (filename = filename ):
51+ expected_ext = Path (filename ).suffix
52+ actual_ext = os .path .splitext (filename )[1 ]
53+ self .assertEqual (actual_ext , expected_ext )
54+
55+ def test_evaluator_uses_correct_suffix (self ):
56+ """Test that the evaluator uses the correct file suffix"""
57+ # Test with different file extensions
58+ test_cases = [
59+ (".py" , "python" ),
60+ (".cpp" , "cpp" ),
61+ (".rs" , "rust" ),
62+ (".r" , "r" ),
63+ (".js" , "javascript" ),
64+ (".metal" , "metal" )
65+ ]
66+
67+ for suffix , language in test_cases :
68+ with self .subTest (suffix = suffix , language = language ):
69+ # Create a temp evaluator file for this test
70+ temp_eval = os .path .join (self .temp_dir , f"eval_{ language } .py" )
71+ with open (temp_eval , "w" ) as f :
72+ f .write ("def evaluate(path): return {'score': 0.5}" )
73+
74+ # Create evaluator with specific suffix
75+ config = EvaluatorConfig ()
76+ evaluator = Evaluator (config , temp_eval , suffix = suffix )
77+
78+ # Check that the suffix is correctly stored
79+ self .assertEqual (evaluator .program_suffix , suffix )
80+
81+ def test_worker_suffix_access (self ):
82+ """Test that worker can access file suffix from config"""
83+ # Create a mock config object with file_suffix
84+ mock_config = MagicMock ()
85+ mock_config .file_suffix = ".cpp"
86+
87+ # Test getattr access pattern used in the code
88+ suffix = getattr (mock_config , 'file_suffix' , '.py' )
89+ self .assertEqual (suffix , ".cpp" )
90+
91+ # Test default fallback
92+ mock_config_no_suffix = MagicMock ()
93+ del mock_config_no_suffix .file_suffix
94+ suffix_default = getattr (mock_config_no_suffix , 'file_suffix' , '.py' )
95+ self .assertEqual (suffix_default , ".py" )
96+
97+ def test_process_parallel_controller_passes_suffix (self ):
98+ """Test that ProcessParallelController correctly passes file suffix"""
99+ # Create a mock database
100+ mock_database = MagicMock ()
101+
102+ # Create ProcessParallelController with specific file suffix
103+ controller = ProcessParallelController (
104+ self .config ,
105+ "dummy_evaluator.py" ,
106+ mock_database ,
107+ file_suffix = ".rs"
108+ )
109+
110+ # Check that file suffix is stored
111+ self .assertEqual (controller .file_suffix , ".rs" )
112+
113+ def test_file_extension_mapping (self ):
114+ """Test that different file extensions are handled correctly"""
115+ test_files = [
116+ ("test.py" , ".py" ),
117+ ("test.cpp" , ".cpp" ),
118+ ("test.rs" , ".rs" ),
119+ ("test.r" , ".r" ),
120+ ("test.js" , ".js" ),
121+ ("test.metal" , ".metal" )
122+ ]
123+
124+ for filename , expected_extension in test_files :
125+ with self .subTest (filename = filename ):
126+ # Test Path suffix extraction
127+ actual_extension = Path (filename ).suffix
128+ self .assertEqual (actual_extension , expected_extension )
129+
130+ def test_evaluator_temp_file_creation (self ):
131+ """Test that evaluator creates temp files with correct suffix"""
132+ # Create a temp evaluator file
133+ temp_eval = os .path .join (self .temp_dir , "eval_test.py" )
134+ with open (temp_eval , "w" ) as f :
135+ f .write ("def evaluate(path): return {'score': 0.5}" )
136+
137+ # Test different suffixes
138+ test_suffixes = [".py" , ".cpp" , ".rs" , ".r" , ".js" ]
139+
140+ for suffix in test_suffixes :
141+ with self .subTest (suffix = suffix ):
142+ config = EvaluatorConfig ()
143+ evaluator = Evaluator (config , temp_eval , suffix = suffix )
144+
145+ # Verify suffix is stored correctly
146+ self .assertEqual (evaluator .program_suffix , suffix )
147+
148+
149+ if __name__ == "__main__" :
150+ unittest .main ()
0 commit comments