44
55#include " test_common.hpp"
66#include < archspec/archspec.hpp>
7- #include < fstream >
8- #include < sstream >
7+ #include < algorithm >
8+ #include < cstdlib >
99#include < filesystem>
10+ #include < fstream>
1011#include < map>
1112#include < set>
13+ #include < sstream>
1214
1315using namespace archspec ;
1416
@@ -17,26 +19,27 @@ namespace fs = std::filesystem;
1719// Parse cpuinfo content (similar to detect_from_proc_cpuinfo but takes string input)
1820DetectedCpuInfo parse_cpuinfo_content (const std::string& content, const std::string& arch) {
1921 DetectedCpuInfo info;
20-
22+
2123 std::map<std::string, std::string> data;
2224 std::istringstream stream (content);
2325 std::string line;
24-
26+
2527 while (std::getline (stream, line)) {
2628 size_t colon = line.find (' :' );
2729 if (colon == std::string::npos) {
28- if (!data.empty ()) break ;
30+ if (!data.empty ())
31+ break ;
2932 continue ;
3033 }
31-
34+
3235 // Trim key
3336 std::string key = line.substr (0 , colon);
3437 size_t start = key.find_first_not_of (" \t " );
3538 size_t end = key.find_last_not_of (" \t " );
3639 if (start != std::string::npos) {
3740 key = key.substr (start, end - start + 1 );
3841 }
39-
42+
4043 // Trim value
4144 std::string value = line.substr (colon + 1 );
4245 start = value.find_first_not_of (" \t " );
@@ -46,13 +49,13 @@ DetectedCpuInfo parse_cpuinfo_content(const std::string& content, const std::str
4649 } else {
4750 value = " " ;
4851 }
49-
52+
5053 data[key] = value;
5154 }
52-
55+
5356 if (arch == " x86_64" || arch == " i686" || arch == " i386" ) {
5457 info.vendor = data.count (" vendor_id" ) ? data[" vendor_id" ] : " generic" ;
55-
58+
5659 // Parse flags
5760 if (data.count (" flags" )) {
5861 std::istringstream flags_stream (data[" flags" ]);
@@ -61,7 +64,7 @@ DetectedCpuInfo parse_cpuinfo_content(const std::string& content, const std::str
6164 info.features .insert (flag);
6265 }
6366 }
64-
67+
6568 // ssse3 implies sse3 (Linux reports sse3 as "pni")
6669 if (info.features .count (" ssse3" )) {
6770 info.features .insert (" sse3" );
@@ -80,7 +83,7 @@ DetectedCpuInfo parse_cpuinfo_content(const std::string& content, const std::str
8083 } else {
8184 info.vendor = " generic" ;
8285 }
83-
86+
8487 // Parse features
8588 if (data.count (" Features" )) {
8689 std::istringstream feat_stream (data[" Features" ]);
@@ -89,7 +92,7 @@ DetectedCpuInfo parse_cpuinfo_content(const std::string& content, const std::str
8992 info.features .insert (feat);
9093 }
9194 }
92-
95+
9396 info.cpu_part = data.count (" CPU part" ) ? data[" CPU part" ] : " " ;
9497 } else if (arch == " ppc64le" || arch == " ppc64" ) {
9598 // Parse POWER generation
@@ -103,45 +106,51 @@ DetectedCpuInfo parse_cpuinfo_content(const std::string& content, const std::str
103106 gen_str += cpu_str[pos++];
104107 }
105108 if (!gen_str.empty ()) {
106- info.generation = std::stoi (gen_str);
109+ char * end = nullptr ;
110+ long val = std::strtol (gen_str.c_str (), &end, 10 );
111+ if (end != gen_str.c_str ()) {
112+ info.generation = static_cast <int >(val);
113+ }
107114 }
108115 }
109116 }
110117 }
111-
118+
112119 return info;
113120}
114121
115122// Detect host from cpuinfo content
116123std::string detect_from_content (const std::string& content, const std::string& arch) {
117124 DetectedCpuInfo info = parse_cpuinfo_content (content, arch);
118- auto candidates = compatible_microarchitectures (info);
119-
125+ auto candidates = compatible_microarchitectures (info, arch );
126+
120127 if (candidates.empty ()) {
121128 return arch;
122129 }
123-
130+
124131 // Sorting criteria: more ancestors and more features is better
125132 auto sorting_fn = [](const Microarchitecture* a, const Microarchitecture* b) {
126133 size_t a_depth = a->ancestors ().size ();
127134 size_t b_depth = b->ancestors ().size ();
128- if (a_depth != b_depth) return a_depth < b_depth;
135+ if (a_depth != b_depth)
136+ return a_depth < b_depth;
129137 return a->features ().size () < b->features ().size ();
130138 };
131-
139+
132140 // Find best generic candidate
133141 std::vector<const Microarchitecture*> generic_candidates;
134142 for (const auto * c : candidates) {
135143 if (c->vendor () == " generic" ) {
136144 generic_candidates.push_back (c);
137145 }
138146 }
139-
147+
140148 const Microarchitecture* best_generic = nullptr ;
141149 if (!generic_candidates.empty ()) {
142- best_generic = *std::max_element (generic_candidates.begin (), generic_candidates.end (), sorting_fn);
150+ best_generic =
151+ *std::max_element (generic_candidates.begin (), generic_candidates.end (), sorting_fn);
143152 }
144-
153+
145154 // Filter by CPU part for AArch64
146155 if (!info.cpu_part .empty ()) {
147156 std::vector<const Microarchitecture*> cpu_part_matches;
@@ -154,7 +163,7 @@ std::string detect_from_content(const std::string& content, const std::string& a
154163 candidates = cpu_part_matches;
155164 }
156165 }
157-
166+
158167 // Filter candidates to be descendants of best generic
159168 if (best_generic) {
160169 std::vector<const Microarchitecture*> filtered;
@@ -167,19 +176,21 @@ std::string detect_from_content(const std::string& content, const std::string& a
167176 candidates = filtered;
168177 }
169178 }
170-
179+
171180 if (candidates.empty ()) {
172181 return best_generic ? best_generic->name () : arch;
173182 }
174-
175- const Microarchitecture* best = *std::max_element (candidates.begin (), candidates.end (), sorting_fn);
183+
184+ const Microarchitecture* best =
185+ *std::max_element (candidates.begin (), candidates.end (), sorting_fn);
176186 return best->name ();
177187}
178188
179189// Read file content
180190std::string read_file_content (const std::string& path) {
181191 std::ifstream file (path);
182- if (!file.is_open ()) return " " ;
192+ if (!file.is_open ())
193+ return " " ;
183194 std::stringstream buffer;
184195 buffer << file.rdbuf ();
185196 return buffer.str ();
@@ -199,7 +210,8 @@ std::string extract_arch_from_filename(const std::string& filename) {
199210 if (filename.find (" linux-" ) == 0 || filename.find (" bgq-" ) == 0 ) {
200211 // Check for power
201212 if (filename.find (" power" ) != std::string::npos) {
202- if (filename.find (" le" ) != std::string::npos) return " ppc64le" ;
213+ if (filename.find (" le" ) != std::string::npos)
214+ return " ppc64le" ;
203215 return " ppc64" ;
204216 }
205217 // Check for ARM
@@ -224,69 +236,76 @@ std::string extract_arch_from_filename(const std::string& filename) {
224236}
225237
226238TEST (fake_cpuinfo_zen3) {
227- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-ubuntu20.04-zen3" );
239+ std::string content =
240+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-ubuntu20.04-zen3" );
228241 ASSERT (!content.empty ());
229-
242+
230243 std::string detected = detect_from_content (content, " x86_64" );
231244 std::cout << " (detected: " << detected << " , expected: zen3) " ;
232245 ASSERT_EQ (detected, " zen3" );
233246 TEST_PASS ();
234247}
235248
236249TEST (fake_cpuinfo_haswell) {
237- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-haswell" );
250+ std::string content =
251+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-haswell" );
238252 ASSERT (!content.empty ());
239-
253+
240254 std::string detected = detect_from_content (content, " x86_64" );
241255 std::cout << " (detected: " << detected << " , expected: haswell) " ;
242256 ASSERT_EQ (detected, " haswell" );
243257 TEST_PASS ();
244258}
245259
246260TEST (fake_cpuinfo_broadwell) {
247- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-broadwell" );
261+ std::string content =
262+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-broadwell" );
248263 ASSERT (!content.empty ());
249-
264+
250265 std::string detected = detect_from_content (content, " x86_64" );
251266 std::cout << " (detected: " << detected << " , expected: broadwell) " ;
252267 ASSERT_EQ (detected, " broadwell" );
253268 TEST_PASS ();
254269}
255270
256271TEST (fake_cpuinfo_cascadelake) {
257- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-centos7-cascadelake" );
272+ std::string content =
273+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-centos7-cascadelake" );
258274 ASSERT (!content.empty ());
259-
275+
260276 std::string detected = detect_from_content (content, " x86_64" );
261277 std::cout << " (detected: " << detected << " , expected: cascadelake) " ;
262278 ASSERT_EQ (detected, " cascadelake" );
263279 TEST_PASS ();
264280}
265281
266282TEST (fake_cpuinfo_skylake_avx512) {
267- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-skylake_avx512" );
283+ std::string content =
284+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-skylake_avx512" );
268285 ASSERT (!content.empty ());
269-
286+
270287 std::string detected = detect_from_content (content, " x86_64" );
271288 std::cout << " (detected: " << detected << " , expected: skylake_avx512) " ;
272289 ASSERT_EQ (detected, " skylake_avx512" );
273290 TEST_PASS ();
274291}
275292
276293TEST (fake_cpuinfo_piledriver) {
277- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel6-piledriver" );
294+ std::string content =
295+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel6-piledriver" );
278296 ASSERT (!content.empty ());
279-
297+
280298 std::string detected = detect_from_content (content, " x86_64" );
281299 std::cout << " (detected: " << detected << " , expected: piledriver) " ;
282300 ASSERT_EQ (detected, " piledriver" );
283301 TEST_PASS ();
284302}
285303
286304TEST (fake_cpuinfo_zen4) {
287- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rocky8.5-zen4" );
305+ std::string content =
306+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rocky8.5-zen4" );
288307 ASSERT (!content.empty ());
289-
308+
290309 std::string detected = detect_from_content (content, " x86_64" );
291310 std::cout << " (detected: " << detected << " , expected: zen4) " ;
292311 ASSERT_EQ (detected, " zen4" );
@@ -298,19 +317,21 @@ TEST(fake_cpuinfo_zen4) {
298317// These are left as placeholders for future cross-architecture testing support.
299318
300319TEST (fake_cpuinfo_zen) {
301- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-zen" );
320+ std::string content =
321+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rhel7-zen" );
302322 ASSERT (!content.empty ());
303-
323+
304324 std::string detected = detect_from_content (content, " x86_64" );
305325 std::cout << " (detected: " << detected << " , expected: zen) " ;
306326 ASSERT_EQ (detected, " zen" );
307327 TEST_PASS ();
308328}
309329
310330TEST (fake_cpuinfo_zen5) {
311- std::string content = read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rocky9-zen5" );
331+ std::string content =
332+ read_file_content (" extern/archspec/archspec/json/tests/targets/linux-rocky9-zen5" );
312333 ASSERT (!content.empty ());
313-
334+
314335 std::string detected = detect_from_content (content, " x86_64" );
315336 std::cout << " (detected: " << detected << " , expected: zen5) " ;
316337 ASSERT_EQ (detected, " zen5" );
@@ -320,25 +341,24 @@ TEST(fake_cpuinfo_zen5) {
320341int main () {
321342 std::cout << " === archspec_cpp Fake cpuinfo Tests ===" << std::endl;
322343 std::cout << std::endl;
323-
344+
324345 // x86_64 tests (Intel)
325346 RUN_TEST (fake_cpuinfo_haswell);
326347 RUN_TEST (fake_cpuinfo_broadwell);
327348 RUN_TEST (fake_cpuinfo_skylake_avx512);
328349 RUN_TEST (fake_cpuinfo_cascadelake);
329-
350+
330351 // x86_64 tests (AMD)
331352 RUN_TEST (fake_cpuinfo_piledriver);
332353 RUN_TEST (fake_cpuinfo_zen);
333354 RUN_TEST (fake_cpuinfo_zen3);
334355 RUN_TEST (fake_cpuinfo_zen4);
335356 RUN_TEST (fake_cpuinfo_zen5);
336-
357+
337358 std::cout << std::endl;
338359 std::cout << " === Results ===" << std::endl;
339360 std::cout << " Passed: " << g_tests_passed << std::endl;
340361 std::cout << " Failed: " << g_tests_failed << std::endl;
341-
362+
342363 return g_tests_failed > 0 ? 1 : 0 ;
343364}
344-
0 commit comments