Refactor check_tests.py
This commit is contained in:
@ -1,16 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
import os, re, sys
|
||||||
from __future__ import print_function
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
import os, re, sys
|
|
||||||
|
|
||||||
parser = ArgumentParser(prog='check_tests.py',
|
parser = ArgumentParser(prog='check_tests.py',
|
||||||
description="Check force tests for completeness")
|
description="Check force tests for completeness")
|
||||||
|
|
||||||
parser.add_argument("-v", "--verbose",
|
parser.add_argument("-v", "--verbose",
|
||||||
action='store_const',
|
action='store_true',
|
||||||
const=True, default=False,
|
|
||||||
help="Enable verbose output")
|
help="Enable verbose output")
|
||||||
|
|
||||||
parser.add_argument("-t", "--tests",
|
parser.add_argument("-t", "--tests",
|
||||||
@ -20,30 +17,32 @@ parser.add_argument("-s", "--src",
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
verbose = args.verbose
|
verbose = args.verbose
|
||||||
src = args.src
|
src_dir = args.src
|
||||||
tests = args.tests
|
tests_dir = args.tests
|
||||||
|
|
||||||
if not src:
|
LAMMPS_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
src = os.path.join('.','..','..','src')
|
|
||||||
|
|
||||||
if not tests:
|
if not src_dir:
|
||||||
tests = os.path.join(src,'..','unittest','force-styles','tests')
|
src_dir = os.path.join(LAMMPS_DIR , 'src')
|
||||||
|
|
||||||
|
if not tests_dir:
|
||||||
|
tests_dir = os.path.join(LAMMPS_DIR, 'unittest', 'force-styles', 'tests')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
src = os.path.abspath(os.path.expanduser(src))
|
src_dir = os.path.abspath(os.path.expanduser(src_dir))
|
||||||
tests = os.path.abspath(os.path.expanduser(tests))
|
tests_dir = os.path.abspath(os.path.expanduser(tests_dir))
|
||||||
except:
|
except:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if not os.path.isdir(src):
|
if not os.path.isdir(src_dir):
|
||||||
sys.exit("LAMMPS source path %s does not exist" % src)
|
sys.exit(f"LAMMPS source path {src_dir} does not exist")
|
||||||
|
|
||||||
if not os.path.isdir(tests):
|
if not os.path.isdir(tests_dir):
|
||||||
sys.exit("LAMMPS test inputs path %s does not exist" % tests)
|
sys.exit(f"LAMMPS test inputs path {tests_dir} does not exist")
|
||||||
|
|
||||||
headers = glob(os.path.join(src, '*', '*.h'))
|
headers = glob(os.path.join(src_dir, '*', '*.h'))
|
||||||
headers += glob(os.path.join(src, '*.h'))
|
headers += glob(os.path.join(src_dir, '*.h'))
|
||||||
|
|
||||||
angle = {}
|
angle = {}
|
||||||
bond = {}
|
bond = {}
|
||||||
@ -54,9 +53,8 @@ fix = {}
|
|||||||
improper = {}
|
improper = {}
|
||||||
kspace = {}
|
kspace = {}
|
||||||
pair = {}
|
pair = {}
|
||||||
total = 0
|
|
||||||
|
|
||||||
upper = re.compile("[A-Z]+")
|
style_pattern = re.compile("(.+)Style\((.+),(.+)\)")
|
||||||
gpu = re.compile("(.+)/gpu$")
|
gpu = re.compile("(.+)/gpu$")
|
||||||
intel = re.compile("(.+)/intel$")
|
intel = re.compile("(.+)/intel$")
|
||||||
kokkos = re.compile("(.+)/kk$")
|
kokkos = re.compile("(.+)/kk$")
|
||||||
@ -65,130 +63,110 @@ omp = re.compile("(.+)/omp$")
|
|||||||
opt = re.compile("(.+)/opt$")
|
opt = re.compile("(.+)/opt$")
|
||||||
removed = re.compile("(.*)Deprecated$")
|
removed = re.compile("(.*)Deprecated$")
|
||||||
|
|
||||||
def register_style(list,style,info):
|
def register_style(styles, name, info):
|
||||||
if style in list.keys():
|
if name in styles:
|
||||||
list[style]['gpu'] += info['gpu']
|
styles[name]['gpu'] += info['gpu']
|
||||||
list[style]['intel'] += info['intel']
|
styles[name]['intel'] += info['intel']
|
||||||
list[style]['kokkos'] += info['kokkos']
|
styles[name]['kokkos'] += info['kokkos']
|
||||||
list[style]['omp'] += info['omp']
|
styles[name]['omp'] += info['omp']
|
||||||
list[style]['opt'] += info['opt']
|
styles[name]['opt'] += info['opt']
|
||||||
list[style]['removed'] += info['removed']
|
styles[name]['removed'] += info['removed']
|
||||||
else:
|
else:
|
||||||
list[style] = info
|
styles[name] = info
|
||||||
|
|
||||||
def add_suffix(list,style):
|
print("Parsing style names from C++ tree in: ", src_dir)
|
||||||
suffix = ""
|
|
||||||
if list[style]['gpu']:
|
|
||||||
suffix += 'g'
|
|
||||||
if list[style]['intel']:
|
|
||||||
suffix += 'i'
|
|
||||||
if list[style]['kokkos']:
|
|
||||||
suffix += 'k'
|
|
||||||
if list[style]['omp']:
|
|
||||||
suffix += 'o'
|
|
||||||
if list[style]['opt']:
|
|
||||||
suffix += 't'
|
|
||||||
if suffix:
|
|
||||||
return style + ' (' + suffix + ')'
|
|
||||||
else:
|
|
||||||
return style
|
|
||||||
|
|
||||||
print("Parsing style names from C++ tree in: ",src)
|
for header in headers:
|
||||||
|
if verbose: print("Checking ", header)
|
||||||
|
with open(header) as f:
|
||||||
|
for line in f:
|
||||||
|
matches = style_pattern.findall(line)
|
||||||
|
|
||||||
for h in headers:
|
for m in matches:
|
||||||
if verbose: print("Checking ", h)
|
# skip over internal styles w/o explicit documentation
|
||||||
fp = open(h)
|
style = m[1]
|
||||||
text = fp.read()
|
if style.isupper():
|
||||||
fp.close()
|
continue
|
||||||
matches = re.findall("(.+)Style\((.+),(.+)\)",text,re.MULTILINE)
|
|
||||||
for m in matches:
|
|
||||||
|
|
||||||
# skip over internal styles w/o explicit documentation
|
# detect, process, and flag suffix styles:
|
||||||
style = m[1]
|
info = { 'kokkos': 0, 'gpu': 0, 'intel': 0, \
|
||||||
total += 1
|
'omp': 0, 'opt': 0, 'removed': 0 }
|
||||||
if upper.match(style):
|
suffix = kokkos_skip.match(style)
|
||||||
continue
|
if suffix:
|
||||||
|
continue
|
||||||
|
suffix = gpu.match(style)
|
||||||
|
if suffix:
|
||||||
|
style = suffix.groups()[0]
|
||||||
|
info['gpu'] = 1
|
||||||
|
suffix = intel.match(style)
|
||||||
|
if suffix:
|
||||||
|
style = suffix.groups()[0]
|
||||||
|
info['intel'] = 1
|
||||||
|
suffix = kokkos.match(style)
|
||||||
|
if suffix:
|
||||||
|
style = suffix.groups()[0]
|
||||||
|
info['kokkos'] = 1
|
||||||
|
suffix = omp.match(style)
|
||||||
|
if suffix:
|
||||||
|
style = suffix.groups()[0]
|
||||||
|
info['omp'] = 1
|
||||||
|
suffix = opt.match(style)
|
||||||
|
if suffix:
|
||||||
|
style = suffix.groups()[0]
|
||||||
|
info['opt'] = 1
|
||||||
|
deprecated = removed.match(m[2])
|
||||||
|
if deprecated:
|
||||||
|
info['removed'] = 1
|
||||||
|
|
||||||
# detect, process, and flag suffix styles:
|
# register style and suffix flags
|
||||||
info = { 'kokkos': 0, 'gpu': 0, 'intel': 0, \
|
if m[0] == 'Angle':
|
||||||
'omp': 0, 'opt': 0, 'removed': 0 }
|
register_style(angle,style,info)
|
||||||
suffix = kokkos_skip.match(style)
|
elif m[0] == 'Bond':
|
||||||
if suffix:
|
register_style(bond,style,info)
|
||||||
continue
|
elif m[0] == 'Dihedral':
|
||||||
suffix = gpu.match(style)
|
register_style(dihedral,style,info)
|
||||||
if suffix:
|
elif m[0] == 'Improper':
|
||||||
style = suffix.groups()[0]
|
register_style(improper,style,info)
|
||||||
info['gpu'] = 1
|
elif m[0] == 'KSpace':
|
||||||
suffix = intel.match(style)
|
register_style(kspace,style,info)
|
||||||
if suffix:
|
elif m[0] == 'Pair':
|
||||||
style = suffix.groups()[0]
|
register_style(pair,style,info)
|
||||||
info['intel'] = 1
|
|
||||||
suffix = kokkos.match(style)
|
|
||||||
if suffix:
|
|
||||||
style = suffix.groups()[0]
|
|
||||||
info['kokkos'] = 1
|
|
||||||
suffix = omp.match(style)
|
|
||||||
if suffix:
|
|
||||||
style = suffix.groups()[0]
|
|
||||||
info['omp'] = 1
|
|
||||||
suffix = opt.match(style)
|
|
||||||
if suffix:
|
|
||||||
style = suffix.groups()[0]
|
|
||||||
info['opt'] = 1
|
|
||||||
deprecated = removed.match(m[2])
|
|
||||||
if deprecated:
|
|
||||||
info['removed'] = 1
|
|
||||||
|
|
||||||
# register style and suffix flags
|
|
||||||
if m[0] == 'Angle':
|
|
||||||
register_style(angle,style,info)
|
|
||||||
elif m[0] == 'Bond':
|
|
||||||
register_style(bond,style,info)
|
|
||||||
elif m[0] == 'Dihedral':
|
|
||||||
register_style(dihedral,style,info)
|
|
||||||
elif m[0] == 'Improper':
|
|
||||||
register_style(improper,style,info)
|
|
||||||
elif m[0] == 'KSpace':
|
|
||||||
register_style(kspace,style,info)
|
|
||||||
elif m[0] == 'Pair':
|
|
||||||
register_style(pair,style,info)
|
|
||||||
|
|
||||||
|
|
||||||
counter = 0
|
|
||||||
|
|
||||||
def check_tests(name,list,yaml,search,skip=()):
|
def check_tests(name,styles,yaml,search,skip=()):
|
||||||
num = 0
|
yaml_files = glob(os.path.join(tests_dir, yaml))
|
||||||
yaml_files = glob(os.path.join(tests, yaml))
|
tests = set()
|
||||||
styles = []
|
missing = set()
|
||||||
missing = []
|
search_pattern = re.compile(search)
|
||||||
for y in yaml_files:
|
for y in yaml_files:
|
||||||
if verbose: print("Checking: ",y)
|
if verbose: print("Checking: ",y)
|
||||||
fp = open(y)
|
with open(y) as f:
|
||||||
text = fp.read()
|
for line in f:
|
||||||
fp.close()
|
matches = search_pattern.findall(line)
|
||||||
matches = re.findall(search,text,re.MULTILINE)
|
for m in matches:
|
||||||
for m in matches:
|
if m[1] == 'hybrid' or m[1] == 'hybrid/overlay':
|
||||||
if m[1] == 'hybrid' or m[1] == 'hybrid/overlay':
|
for s in m[0].split():
|
||||||
for s in m[0].split():
|
if s in styles:
|
||||||
if s in list.keys():
|
tests.add(s)
|
||||||
styles.append(s)
|
else:
|
||||||
else:
|
tests.add(m[1])
|
||||||
styles.append(m[1])
|
for s in styles:
|
||||||
for s in list.keys():
|
|
||||||
# known undocumented aliases we need to skip
|
# known undocumented aliases we need to skip
|
||||||
if s in skip: continue
|
if s in skip: continue
|
||||||
if not s in styles:
|
if not s in tests:
|
||||||
if not list[s]['removed']:
|
if not styles[s]['removed']:
|
||||||
if verbose: print("No test for %s style %s" % (name,s))
|
if verbose: print("No test for %s style %s" % (name,s))
|
||||||
num += 1
|
missing.add(s)
|
||||||
missing.append(s)
|
|
||||||
total = len(list)
|
|
||||||
print("\nTests available for %s styles: %d of %d"
|
|
||||||
% (name,total - num, total))
|
|
||||||
missing.sort()
|
|
||||||
print("No tests for: ", missing)
|
|
||||||
return num
|
|
||||||
|
|
||||||
|
num_missing = len(missing)
|
||||||
|
total = len(styles)
|
||||||
|
num_tests = total - num_missing
|
||||||
|
print(f"\nTests available for {name} styles: {num_tests} of {total}")
|
||||||
|
print("No tests for: ", list(missing))
|
||||||
|
return num_missing
|
||||||
|
|
||||||
|
counter = 0
|
||||||
counter += check_tests('pair',pair,'*-pair-*.yaml',
|
counter += check_tests('pair',pair,'*-pair-*.yaml',
|
||||||
'.*pair_style:\s*((\S+).*)?',skip=('meam','lj/sf'))
|
'.*pair_style:\s*((\S+).*)?',skip=('meam','lj/sf'))
|
||||||
counter += check_tests('bond',bond,'bond-*.yaml',
|
counter += check_tests('bond',bond,'bond-*.yaml',
|
||||||
@ -203,4 +181,4 @@ counter += check_tests('kspace',kspace,'kspace-*.yaml',
|
|||||||
'.*kspace_style\s*((\S+).*)?')
|
'.*kspace_style\s*((\S+).*)?')
|
||||||
|
|
||||||
total = len(pair)+len(bond)+len(angle)+len(dihedral)+len(improper)+len(kspace)
|
total = len(pair)+len(bond)+len(angle)+len(dihedral)+len(improper)+len(kspace)
|
||||||
print("\nTotal tests missing: %d of %d" % (counter, total))
|
print(f"\nTotal tests missing: {counter} of {total}")
|
||||||
|
|||||||
Reference in New Issue
Block a user