mirror of
https://github.com/anrieff/libcpuid
synced 2025-06-07 00:51:40 +00:00
Use argparse in Python scripts
This commit is contained in:
parent
dc06877f4f
commit
c818294b89
3 changed files with 115 additions and 63 deletions
|
@ -1,14 +1,15 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os, sys, re, glob
|
import argparse, os, sys, re, glob
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
print("Usage: check-consistency <path>")
|
### Constants:
|
||||||
sys.exit(0)
|
git_root_dir = os.popen("git rev-parse --show-toplevel").read().splitlines()
|
||||||
|
|
||||||
err = 0
|
err = 0
|
||||||
def getEnumElements(enumName):
|
def getEnumElements(enumName):
|
||||||
f = open("%s/libcpuid.h" % sys.argv[1], "r")
|
f = open("%s/libcpuid.h" % args.root_dir, "r")
|
||||||
l = []
|
l = []
|
||||||
on = False
|
on = False
|
||||||
rexp = re.compile(r'^\s*([A-Z0-9_]+)(\s*=\s*[A-Z0-9_]+)?\s*,.*$')
|
rexp = re.compile(r'^\s*([A-Z0-9_]+)(\s*=\s*[A-Z0-9_]+)?\s*,.*$')
|
||||||
|
@ -27,7 +28,7 @@ def getEnumElements(enumName):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def getConstant(constantName):
|
def getConstant(constantName):
|
||||||
f = open("%s/libcpuid_constants.h" % sys.argv[1], "r")
|
f = open("%s/libcpuid_constants.h" % args.root_dir, "r")
|
||||||
value = 0
|
value = 0
|
||||||
for line in f:
|
for line in f:
|
||||||
items = line.strip().split()
|
items = line.strip().split()
|
||||||
|
@ -49,13 +50,27 @@ def checkEnumSize(enumName, constantName):
|
||||||
else:
|
else:
|
||||||
print("OK")
|
print("OK")
|
||||||
|
|
||||||
|
def check_type_directory(directory):
|
||||||
|
if not Path(directory).is_dir():
|
||||||
|
raise argparse.ArgumentTypeError(f"{directory} is not a directory")
|
||||||
|
return directory
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
parser = argparse.ArgumentParser(description="Check library consistency.")
|
||||||
|
parser.add_argument("root_dir",
|
||||||
|
nargs='?',
|
||||||
|
type=check_type_directory,
|
||||||
|
default=f"{git_root_dir[-1]}/libcpuid" if len(git_root_dir) > 0 else "",
|
||||||
|
help="path to the libcpuid sub-directory")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
checkEnumSize("cpu_feature_t", "CPU_FLAGS_MAX")
|
checkEnumSize("cpu_feature_t", "CPU_FLAGS_MAX")
|
||||||
checkEnumSize("cpu_hint_t", "CPU_HINTS_MAX")
|
checkEnumSize("cpu_hint_t", "CPU_HINTS_MAX")
|
||||||
checkEnumSize("cpu_sgx_feature_t", "SGX_FLAGS_MAX")
|
checkEnumSize("cpu_sgx_feature_t", "SGX_FLAGS_MAX")
|
||||||
|
|
||||||
rexp = re.compile('.*{ CPU_FEATURE_([^,]+), "([^"]+)".*}.*')
|
rexp = re.compile('.*{ CPU_FEATURE_([^,]+), "([^"]+)".*}.*')
|
||||||
print("Finding features:")
|
print("Finding features:")
|
||||||
for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
for fn in glob.glob("%s/*.c" % args.root_dir):
|
||||||
f = open(fn, "rt")
|
f = open(fn, "rt")
|
||||||
line = 1
|
line = 1
|
||||||
nfeat = 0
|
nfeat = 0
|
||||||
|
@ -75,7 +90,7 @@ for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
||||||
# Check whether all features are converted by cpu_feature_str():
|
# Check whether all features are converted by cpu_feature_str():
|
||||||
|
|
||||||
allf = []
|
allf = []
|
||||||
f = open("%s/libcpuid.h" % sys.argv[1], "rt")
|
f = open("%s/libcpuid.h" % args.root_dir, "rt")
|
||||||
rexp = re.compile('\t(CPU_FEATURE_[^, ]+).*')
|
rexp = re.compile('\t(CPU_FEATURE_[^, ]+).*')
|
||||||
for s in f.readlines():
|
for s in f.readlines():
|
||||||
if rexp.match(s):
|
if rexp.match(s):
|
||||||
|
@ -85,7 +100,7 @@ f.close()
|
||||||
|
|
||||||
impf = []
|
impf = []
|
||||||
rexp = re.compile('\t+{ (CPU_FEATURE_[^,]+).*')
|
rexp = re.compile('\t+{ (CPU_FEATURE_[^,]+).*')
|
||||||
f = open("%s/cpuid_main.c" % sys.argv[1], "rt")
|
f = open("%s/cpuid_main.c" % args.root_dir, "rt")
|
||||||
for s in f.readlines():
|
for s in f.readlines():
|
||||||
if rexp.match(s):
|
if rexp.match(s):
|
||||||
entry = rexp.findall(s)[0]
|
entry = rexp.findall(s)[0]
|
||||||
|
@ -112,7 +127,7 @@ rexp1 = re.compile(r'.*\[(CPU_FEATURE_[^ \]]+)\]\s*=\s*{.*') # e.g. "[CPU_FEATUR
|
||||||
rexp2 = re.compile(r'.*(CPU_FEATURE_[^ ,]+),\s*FEATURE_LEVEL_ARM_.*') # e.g. "set_feature_status(data, ext_status, (mte_frac == 0b0000), CPU_FEATURE_MTE_ASYNC, FEATURE_LEVEL_ARM_V8_5_A, -1);"
|
rexp2 = re.compile(r'.*(CPU_FEATURE_[^ ,]+),\s*FEATURE_LEVEL_ARM_.*') # e.g. "set_feature_status(data, ext_status, (mte_frac == 0b0000), CPU_FEATURE_MTE_ASYNC, FEATURE_LEVEL_ARM_V8_5_A, -1);"
|
||||||
rexp3 = re.compile(r'.*(CPU_FEATURE_[^ }]+).*') # e.g. "{ 28, CPU_FEATURE_HT },"
|
rexp3 = re.compile(r'.*(CPU_FEATURE_[^ }]+).*') # e.g. "{ 28, CPU_FEATURE_HT },"
|
||||||
|
|
||||||
for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
for fn in glob.glob("%s/*.c" % args.root_dir):
|
||||||
f = open(fn, "rt")
|
f = open(fn, "rt")
|
||||||
files_code[fn] = []
|
files_code[fn] = []
|
||||||
for s in f.readlines():
|
for s in f.readlines():
|
||||||
|
@ -163,7 +178,7 @@ definitions = 0
|
||||||
match_entry_fields = 11 # this number needs to change if the definition of match_entry_t ever changes
|
match_entry_fields = 11 # this number needs to change if the definition of match_entry_t ever changes
|
||||||
codename_str_max = 64-1 # this number needs to change if the value of CODENAME_STR_MAX ever changes
|
codename_str_max = 64-1 # this number needs to change if the value of CODENAME_STR_MAX ever changes
|
||||||
common_cache_sizes = ["8", "16", "32", "64", "128", "256", "512", "1024", "2048", "3072", "4096", "6144", "8192", "12288", "16384"]
|
common_cache_sizes = ["8", "16", "32", "64", "128", "256", "512", "1024", "2048", "3072", "4096", "6144", "8192", "12288", "16384"]
|
||||||
for fn in glob.glob("%s/*.c" % sys.argv[1]):
|
for fn in glob.glob("%s/*.c" % args.root_dir):
|
||||||
bfn = os.path.basename(fn)
|
bfn = os.path.basename(fn)
|
||||||
nline = 0
|
nline = 0
|
||||||
f = open(fn, "rt")
|
f = open(fn, "rt")
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os, sys, re
|
import argparse, sys, re
|
||||||
|
|
||||||
args = sys.argv
|
|
||||||
|
|
||||||
if len(args) != 3:
|
### Constants:
|
||||||
print("Usage: create_test.py <rawdata file> <report file>")
|
delimiter = "-" * 80
|
||||||
print("The .test file is written to stdout.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
def readRawFile():
|
def readRawFile():
|
||||||
rawdata = []
|
rawdata = []
|
||||||
for line in open(args[1], "rt").readlines():
|
for line in args.raw_file.readlines():
|
||||||
lookfor = [
|
lookfor = [
|
||||||
"Logical CPU", "CPUID", "CPU#", # common
|
"Logical CPU", "CPUID", "CPU#", # common
|
||||||
"basic_cpuid", "ext_cpuid", "intel_fn4", "intel_fn11", "amd_fn8000001dh", # x86
|
"basic_cpuid", "ext_cpuid", "intel_fn4", "intel_fn11", "amd_fn8000001dh", # x86
|
||||||
|
@ -36,7 +33,7 @@ def readRawFile():
|
||||||
def readResultFile():
|
def readResultFile():
|
||||||
repdata = []
|
repdata = []
|
||||||
rexp = re.compile('(-?[0-9]+).*')
|
rexp = re.compile('(-?[0-9]+).*')
|
||||||
for line in open(args[2], "rt").readlines():
|
for line in args.report_file.readlines():
|
||||||
s = line.strip()
|
s = line.strip()
|
||||||
if s.find(":") == -1:
|
if s.find(":") == -1:
|
||||||
continue
|
continue
|
||||||
|
@ -80,6 +77,25 @@ def readResultFile():
|
||||||
repdata.append(value)
|
repdata.append(value)
|
||||||
return repdata
|
return repdata
|
||||||
|
|
||||||
delimiter = "-" * 80
|
# Parse arguments
|
||||||
|
parser = argparse.ArgumentParser(description="Create a new test file by using cpuid_tool raw and report files.")
|
||||||
|
parser.add_argument("raw_file",
|
||||||
|
nargs='?',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
default="raw.txt",
|
||||||
|
help="an existing raw data file")
|
||||||
|
parser.add_argument("report_file",
|
||||||
|
nargs='?',
|
||||||
|
type=argparse.FileType('r'),
|
||||||
|
default="report.txt",
|
||||||
|
help="an existing report file")
|
||||||
|
parser.add_argument("test_file",
|
||||||
|
nargs='?',
|
||||||
|
type=argparse.FileType('w'),
|
||||||
|
default=sys.stdout,
|
||||||
|
help="test file to create (default is standard output)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Create test file
|
||||||
lines = readRawFile() + readResultFile()
|
lines = readRawFile() + readResultFile()
|
||||||
sys.stdout.writelines([s + "\n" for s in lines])
|
args.test_file.writelines([s + "\n" for s in lines])
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
import os, sys, re, random, lzma
|
import argparse, textwrap, os, sys, re, random, lzma
|
||||||
from pathlib import Path
|
from pathlib import Path, PurePath
|
||||||
|
|
||||||
|
|
||||||
### Constants:
|
### Constants:
|
||||||
|
@ -20,42 +20,6 @@ fields_arm = [ "architecture", "feature-level", "purpose",
|
||||||
"cores", "logical",
|
"cores", "logical",
|
||||||
"codename", "flags" ]
|
"codename", "flags" ]
|
||||||
|
|
||||||
args = sys.argv
|
|
||||||
fix = False
|
|
||||||
show_test_fast_warning = False
|
|
||||||
|
|
||||||
if len(args) < 3:
|
|
||||||
print("""
|
|
||||||
Usage: run_tests.py <cpuid_tool binary> <test file/dir> [test file/dir ...] [OPTIONS]
|
|
||||||
|
|
||||||
If a test file is given, it is tested by itself.
|
|
||||||
If a directory is given, process all *.test files there, subdirectories included.
|
|
||||||
|
|
||||||
If the --fix option is given, the behaviour of the cpuid_tool binary is deemed correct
|
|
||||||
and any failing tests are updated.
|
|
||||||
""")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
filelist = []
|
|
||||||
cpuid_tool = args[1]
|
|
||||||
for arg in args[2:]:
|
|
||||||
if arg == "--fix":
|
|
||||||
fix = True
|
|
||||||
continue
|
|
||||||
if arg == "--show-test-fast-warning":
|
|
||||||
show_test_fast_warning = True
|
|
||||||
continue
|
|
||||||
if os.path.isdir(arg):
|
|
||||||
# gather all *.test files from subdirs amd and intel:
|
|
||||||
for dirpath, dirnames, filenames in os.walk(arg):
|
|
||||||
filelist += [os.path.join(dirpath, fn) for fn in filenames if Path(fn).suffixes[0] == ".test"]
|
|
||||||
else:
|
|
||||||
filelist.append(arg)
|
|
||||||
|
|
||||||
#f = open(args[1], "rt")
|
|
||||||
#lines = f.readlines()
|
|
||||||
#f.close()
|
|
||||||
|
|
||||||
# One would usually use os.tempnam, but libc gives off hell a lot of
|
# One would usually use os.tempnam, but libc gives off hell a lot of
|
||||||
# warnings when you attempt to use that :(
|
# warnings when you attempt to use that :(
|
||||||
def make_tempname(prefix):
|
def make_tempname(prefix):
|
||||||
|
@ -109,7 +73,7 @@ def do_test(inp, expected_out, binary, test_file_name, num_cpu_type):
|
||||||
except IOError:
|
except IOError:
|
||||||
return "Exception"
|
return "Exception"
|
||||||
if len(real_out) != len(expected_out) or len(real_out) != len(fields) * num_cpu_type:
|
if len(real_out) != len(expected_out) or len(real_out) != len(fields) * num_cpu_type:
|
||||||
if fix:
|
if args.fix:
|
||||||
fixFile(test_file_name, inp, real_out_delim)
|
fixFile(test_file_name, inp, real_out_delim)
|
||||||
return "Number of records, fixed."
|
return "Number of records, fixed."
|
||||||
else:
|
else:
|
||||||
|
@ -121,12 +85,69 @@ def do_test(inp, expected_out, binary, test_file_name, num_cpu_type):
|
||||||
if not err_fields:
|
if not err_fields:
|
||||||
return "OK"
|
return "OK"
|
||||||
else:
|
else:
|
||||||
if fix:
|
if args.fix:
|
||||||
fixFile(test_file_name, inp, real_out_delim)
|
fixFile(test_file_name, inp, real_out_delim)
|
||||||
return "Mismatch, fixed."
|
return "Mismatch, fixed."
|
||||||
else:
|
else:
|
||||||
return "Mismatch in fields:\n%s" % "\n".join([fmt_error(err) for err in err_fields])
|
return "Mismatch in fields:\n%s" % "\n".join([fmt_error(err) for err in err_fields])
|
||||||
|
|
||||||
|
def is_regular_file(filename):
|
||||||
|
try:
|
||||||
|
with open(filename, 'r') as fd:
|
||||||
|
fd.read()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_type_binary_file(filename):
|
||||||
|
if not Path(filename).is_file():
|
||||||
|
raise argparse.ArgumentTypeError(f"{filename} is not a file")
|
||||||
|
if is_regular_file(filename):
|
||||||
|
raise argparse.ArgumentTypeError(f"{filename} is not a binary file")
|
||||||
|
return filename
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=textwrap.dedent("""
|
||||||
|
|
||||||
|
Run test files.
|
||||||
|
|
||||||
|
If a test file is given, it is tested by itself.
|
||||||
|
If a directory is given, process all *.test files there, subdirectories included.
|
||||||
|
|
||||||
|
If the --fix option is given, the behaviour of the cpuid_tool binary is deemed correct and any failing tests are updated.
|
||||||
|
"""))
|
||||||
|
parser.add_argument("cpuid_tool",
|
||||||
|
nargs='?',
|
||||||
|
type=check_type_binary_file,
|
||||||
|
default="./build/cpuid_tool/cpuid_tool",
|
||||||
|
help="path to the cpuid_tool binary")
|
||||||
|
parser.add_argument("input_test_files",
|
||||||
|
nargs='+',
|
||||||
|
default=["./tests"],
|
||||||
|
help="test file or directory containing test files")
|
||||||
|
parser.add_argument("--fix",
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
default=False,
|
||||||
|
help="update failing tests (default is false)")
|
||||||
|
parser.add_argument("--show-test-fast-warning",
|
||||||
|
dest="show_test_fast_warning",
|
||||||
|
action=argparse.BooleanOptionalAction,
|
||||||
|
default=False,
|
||||||
|
help="show a warning on errors (default if false)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Create test files list
|
||||||
|
filelist = []
|
||||||
|
for input_test_file in args.input_test_files:
|
||||||
|
if Path(input_test_file).is_dir():
|
||||||
|
# gather all *.test files from subdirs amd, intel and cie:
|
||||||
|
for dirpath, dirnames, filenames in Path(input_test_file).walk():
|
||||||
|
filelist += [PurePath(dirpath).joinpath(fn) for fn in filenames if Path(fn).suffixes[0] == ".test"]
|
||||||
|
else:
|
||||||
|
filelist.append(input_test_file)
|
||||||
|
|
||||||
|
# Run tests
|
||||||
errors = False
|
errors = False
|
||||||
print("Testing...")
|
print("Testing...")
|
||||||
for test_file_name_raw in filelist:
|
for test_file_name_raw in filelist:
|
||||||
|
@ -158,14 +179,14 @@ for test_file_name_raw in filelist:
|
||||||
current_input.append(line)
|
current_input.append(line)
|
||||||
f.close()
|
f.close()
|
||||||
#codename = current_output[len(current_output) - 2]
|
#codename = current_output[len(current_output) - 2]
|
||||||
result = do_test(current_input, current_output, cpuid_tool, test_file_name, num_cpu_type)
|
result = do_test(current_input, current_output, args.cpuid_tool, test_file_name, num_cpu_type)
|
||||||
print("Test [%s]: %s" % (test_file_name.name, result))
|
print("Test [%s]: %s" % (test_file_name.name, result))
|
||||||
if result != "OK":
|
if result != "OK":
|
||||||
errors = True
|
errors = True
|
||||||
build_output = False
|
build_output = False
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
if show_test_fast_warning:
|
if args.show_test_fast_warning:
|
||||||
print("""
|
print("""
|
||||||
You're running tests in fast mode; before taking any action on the errors
|
You're running tests in fast mode; before taking any action on the errors
|
||||||
above, please confirm that the slow mode ('make test-old') also fails.""")
|
above, please confirm that the slow mode ('make test-old') also fails.""")
|
||||||
|
|
Loading…
Add table
Reference in a new issue