Skip to content

Commit 4f05879

Browse files
committed
Fixup tests on other arches
1 parent 344acb6 commit 4f05879

3 files changed

Lines changed: 86 additions & 54 deletions

File tree

include/archspec/detect.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,17 @@ std::optional<std::string> brand_string();
5353

5454
/**
5555
* Get a list of all microarchitectures compatible with the detected CPU
56+
* Uses get_machine() to determine the architecture
5657
*/
5758
std::vector<const Microarchitecture*> compatible_microarchitectures(const DetectedCpuInfo& info);
5859

60+
/**
61+
* Get a list of all microarchitectures compatible with the detected CPU
62+
* Uses the specified architecture string
63+
*/
64+
std::vector<const Microarchitecture*> compatible_microarchitectures(const DetectedCpuInfo& info,
65+
const std::string& arch);
66+
5967
// Platform-specific detection functions
6068

6169
#if defined(__linux__) || defined(__FreeBSD__)

src/detect.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,10 @@ bool check_riscv64(const DetectedCpuInfo& info, const Microarchitecture& target)
533533

534534
} // namespace compatibility
535535

536-
std::vector<const Microarchitecture*> compatible_microarchitectures(const DetectedCpuInfo& info) {
536+
std::vector<const Microarchitecture*> compatible_microarchitectures(const DetectedCpuInfo& info,
537+
const std::string& arch) {
537538
std::vector<const Microarchitecture*> result;
538539
const auto& db = MicroarchitectureDatabase::instance();
539-
std::string arch = get_machine();
540540

541541
// Select compatibility checker based on architecture
542542
std::function<bool(const DetectedCpuInfo&, const Microarchitecture&)> checker;
@@ -575,6 +575,10 @@ std::vector<const Microarchitecture*> compatible_microarchitectures(const Detect
575575
return result;
576576
}
577577

578+
std::vector<const Microarchitecture*> compatible_microarchitectures(const DetectedCpuInfo& info) {
579+
return compatible_microarchitectures(info, get_machine());
580+
}
581+
578582
Microarchitecture host() {
579583
// Detect CPU info
580584
DetectedCpuInfo info = detect_cpu_info();

tests/test_fake_cpuinfo.cpp

Lines changed: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
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

1315
using 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)
1820
DetectedCpuInfo 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
116123
std::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
180190
std::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

226238
TEST(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

236249
TEST(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

246260
TEST(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

256271
TEST(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

266282
TEST(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

276293
TEST(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

286304
TEST(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

300319
TEST(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

310330
TEST(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) {
320341
int 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

Comments
 (0)