Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/chronicler/processors/coremark_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- tuned_setting - System tuning applied
"""

import re
import statistics
from typing import Dict, Any, List, Optional
import logging
Expand All @@ -30,6 +31,10 @@
class CoreMarkProcessor(BaseProcessor):
"""Processor for CoreMark benchmark results"""

def __init__(self, result_directory: str):
super().__init__(result_directory)
self._benchmark_version = None # Stores benchmark version from CSV comments

def get_test_name(self) -> str:
return "coremark"

Expand All @@ -54,12 +59,18 @@ def parse_runs(self, extracted_result: Dict[str, Any]) -> Dict[str, Any]:
"run_2": {...}
}
"""
# Reset benchmark version state to prevent stale version from previous parse
self._benchmark_version = None

files = extracted_result['files']

# Parse CSV time series (comma-delimited with Start_Date/End_Date; comment lines skipped)
csv_file = files.get('results_csv')
time_series_data = []
if csv_file:
# Extract benchmark version from CSV comments before parsing
self._extract_benchmark_version_from_csv(csv_file)

time_series_data = parse_csv_timeseries(
csv_file, delimiter=',', skip_comments=True
)
Expand Down Expand Up @@ -119,6 +130,43 @@ def parse_runs(self, extracted_result: Dict[str, Any]) -> Dict[str, Any]:
logger.info(f"Parsed {len(runs)} CoreMark runs")
return runs

def _extract_benchmark_version_from_csv(self, csv_file: str) -> None:
"""
Extract CoreMark benchmark version from CSV comments.

Looks for pattern: # Results version: v1.01
Sets self._benchmark_version if found.
"""
try:
with open(csv_file, 'r') as f:
for line in f:
if line.startswith('#') and 'Results version:' in line:
match = re.search(r'Results version:\s*(\S+)', line)
if match:
self._benchmark_version = match.group(1)
logger.debug(f"Extracted CoreMark version: {self._benchmark_version}")
return
except Exception as e:
logger.warning(f"Failed to extract benchmark version from {csv_file}: {e}")

def build_test_info(self):
"""Override to use benchmark version from CSV instead of wrapper version.

Extracts CoreMark benchmark version from CSV comments
(e.g., "# Results version: v1.01") and uses it for test.version,
while preserving wrapper_version from base implementation.
"""
from ..schema import TestInfo

base_info = super().build_test_info()

# Use benchmark version if extracted, otherwise fall back to wrapper version
return TestInfo(
name=self.get_test_name(),
version=self._benchmark_version or base_info.version,
wrapper_version=base_info.wrapper_version
)

def _group_time_series_by_run(self, time_series_data: List[Dict]) -> List[List[Dict]]:
"""
Group time series data by run number
Expand Down
142 changes: 142 additions & 0 deletions tests/test_coremark_timestamps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
CoreMark processor: timestamp validation (valid, missing, invalid/empty in row).
"""

import json
import pytest
from pathlib import Path

Expand Down Expand Up @@ -72,3 +73,144 @@ def test_coremark_empty_start_date_in_row(result_dir):
},
expect_error=True,
)


def test_coremark_extracts_benchmark_version_from_csv_comments(result_dir):
"""Benchmark version in CSV comments is extracted to test.version."""
csv = """# Test general meta start
# Test: coremark
# Results version: v1.01
# Host: test-host
# Test general meta end
iteration,threads,IterationsPerSec,Start_Date,End_Date
1,4,119358.448340,2026-02-04T00:13:05Z,2026-02-04T00:13:39Z"""

path = _write_csv(result_dir, csv)

# Create test_info with wrapper version
test_info_data = {
"coremark": {
"test_name": "coremark",
"repo_file": "v2.0.tar.gz"
}
}
test_info_path = result_dir / "test_info"
with open(test_info_path, "w") as f:
json.dump(test_info_data, f)

processor = CoreMarkProcessor(str(result_dir))
extracted_result = {
"files": {
FILE_KEY: str(path),
"run_summaries": [],
"version": None,
"tuned_setting": None,
}
}

# Parse runs to extract benchmark version
processor.parse_runs(extracted_result)

# Now build_test_info should use the extracted benchmark version
test_info = processor.build_test_info()

# test.version should be benchmark version
assert test_info.version == "v1.01"
# test.wrapper_version should be wrapper version
assert test_info.wrapper_version == "v2.0"


def test_coremark_fallback_to_wrapper_version_when_benchmark_version_missing(result_dir):
"""When benchmark version is missing from CSV, test.version falls back to wrapper version."""
csv = """# Test general meta start
# Test: coremark
# Host: test-host
# Test general meta end
iteration,threads,IterationsPerSec,Start_Date,End_Date
1,4,119358.448340,2026-02-04T00:13:05Z,2026-02-04T00:13:39Z"""

path = _write_csv(result_dir, csv)

# Create test_info with wrapper version
test_info_data = {
"coremark": {
"test_name": "coremark",
"repo_file": "v2.0.tar.gz"
}
}
test_info_path = result_dir / "test_info"
with open(test_info_path, "w") as f:
json.dump(test_info_data, f)

processor = CoreMarkProcessor(str(result_dir))
extracted_result = {
"files": {
FILE_KEY: str(path),
"run_summaries": [],
"version": None,
"tuned_setting": None,
}
}

# Parse runs (no benchmark version in CSV)
processor.parse_runs(extracted_result)

# build_test_info should fall back to wrapper version
test_info = processor.build_test_info()

# Both should fall back to wrapper version
assert test_info.version == "v2.0"
assert test_info.wrapper_version == "v2.0"


def test_coremark_resets_benchmark_version_between_parses(result_dir):
"""Benchmark version is reset between parse calls to prevent stale state."""
csv_with_version = """# Results version: v1.01
iteration,threads,IterationsPerSec,Start_Date,End_Date
1,4,119358.448340,2026-02-04T00:13:05Z,2026-02-04T00:13:39Z"""

csv_without_version = """iteration,threads,IterationsPerSec,Start_Date,End_Date
1,4,119358.448340,2026-02-04T00:13:05Z,2026-02-04T00:13:39Z"""

# Create test_info with wrapper version
test_info_data = {
"coremark": {
"test_name": "coremark",
"repo_file": "v2.0.tar.gz"
}
}
test_info_path = result_dir / "test_info"
with open(test_info_path, "w") as f:
json.dump(test_info_data, f)

processor = CoreMarkProcessor(str(result_dir))

# First parse: has benchmark version
path1 = result_dir / "results1.csv"
path1.write_text(csv_with_version.strip())
extracted1 = {
"files": {
FILE_KEY: str(path1),
"run_summaries": [],
"version": None,
"tuned_setting": None,
}
}
processor.parse_runs(extracted1)
test_info1 = processor.build_test_info()
assert test_info1.version == "v1.01"

# Second parse: no benchmark version (should reset, not reuse v1.01)
path2 = result_dir / "results2.csv"
path2.write_text(csv_without_version.strip())
extracted2 = {
"files": {
FILE_KEY: str(path2),
"run_summaries": [],
"version": None,
"tuned_setting": None,
}
}
processor.parse_runs(extracted2)
test_info2 = processor.build_test_info()
assert test_info2.version == "v2.0" # Should fall back, not reuse v1.01
Loading