提交 9144ae42 编写于 作者: Y Yucheng 提交者: ruri

refactored sample code test program and fixed a bug (#21467)

上级 0b75a0c1
...@@ -20,14 +20,13 @@ import math ...@@ -20,14 +20,13 @@ import math
import platform import platform
""" """
please make sure to run in the tools path please make sure to run in the tools path
usage: python sample_test.py {arg1} {arg2} usage: python sample_test.py {arg1}
arg1: the first arg defined running in gpu version or cpu version arg1: the first arg defined running in gpu version or cpu version
arg2: the second arg defined testing python2 or python3
for example, you can run cpu version python2 testing like this: for example, you can run cpu version python2 testing like this:
python sample_test.py cpu 2 python sampcd_processor.py cpu
""" """
...@@ -86,25 +85,6 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -86,25 +85,6 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
Extract and run sample codes from source comment and Extract and run sample codes from source comment and
the result will be returned. the result will be returned.
As an ultimate result, this function returns a list of
status codes for each sample code (in top-down order)
found in srccom.
status code deciphering:
3:error sample code
2:have sample code but format is wrong
1:no sample code
0:successful
-1:no comments found
-2:in white list
there may be several examples in a source comment
so status deserves a list to contain the states.
For instance, some API has three example codes,
code 1 is successful, code 2 is error, code 3 is successful
so the list to return is [0,3,0]
Args: Args:
srccom(str): the source comment of some API whose srccom(str): the source comment of some API whose
example codes will be extracted and run. example codes will be extracted and run.
...@@ -113,13 +93,11 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -113,13 +93,11 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
hname(str): the name of the hint banners , e.t. def hname. hname(str): the name of the hint banners , e.t. def hname.
Returns: Returns:
list: the status code of all the sample codes found in srccom. result: True or False
""" """
result = True
def sampcd_header_print(name, sampcd, htype, hname): def sampcd_header_print(name, sampcd, htype, hname):
""" """
print hint banner headers. print hint banner headers.
...@@ -139,7 +117,6 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -139,7 +117,6 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
print("execution result:") print("execution result:")
sampcd_begins = find_all(srccom, " code-block:: python") sampcd_begins = find_all(srccom, " code-block:: python")
status = []
if len(sampcd_begins) == 0: if len(sampcd_begins) == 0:
print_header(htype, hname) print_header(htype, hname)
''' '''
...@@ -153,14 +130,10 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -153,14 +130,10 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
"Deprecated sample code style:\n\n Examples:\n\n >>>codeline\n >>>codeline\n\n\n ", "Deprecated sample code style:\n\n Examples:\n\n >>>codeline\n >>>codeline\n\n\n ",
"Please use '.. code-block:: python' to ", "Please use '.. code-block:: python' to ",
"format sample code.\n") "format sample code.\n")
status.append(2) result = False
print("status code for all sample codes in ", name, " : ",
str(status))
else: else:
print("No sample code!\n") print("Error: No sample code!\n")
status.append(1) result = False
print("status code for all sample codes in ", name, " : ",
str(status))
for y in range(1, len(sampcd_begins) + 1): for y in range(1, len(sampcd_begins) + 1):
sampcd_begin = sampcd_begins[y - 1] sampcd_begin = sampcd_begins[y - 1]
...@@ -205,7 +178,8 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -205,7 +178,8 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
elif platform.python_version()[0] == "3": elif platform.python_version()[0] == "3":
cmd = ["python3", "samplecode_temp/" + tfname] cmd = ["python3", "samplecode_temp/" + tfname]
else: else:
print("fail to parse python version!") print("Error: fail to parse python version!")
result = False
exit(1) exit(1)
subprc = subprocess.Popen( subprc = subprocess.Popen(
...@@ -221,14 +195,10 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""): ...@@ -221,14 +195,10 @@ def sampcd_extract_and_run(srccom, name, htype="def", hname=""):
print("Error Raised from Sample Code ", name, " :\n") print("Error Raised from Sample Code ", name, " :\n")
print(err) print(err)
print(msg) print(msg)
status.append(3) result = False
print("status code for all sample codes in ", name, str(status))
# It works!
else:
status.append(0)
# msg is the returned code execution report # msg is the returned code execution report
os.remove("samplecode_temp/" + tfname) os.remove("samplecode_temp/" + tfname)
return status return result
def single_defcom_extract(start_from, srcls, is_class_begin=False): def single_defcom_extract(start_from, srcls, is_class_begin=False):
...@@ -247,6 +217,7 @@ def single_defcom_extract(start_from, srcls, is_class_begin=False): ...@@ -247,6 +217,7 @@ def single_defcom_extract(start_from, srcls, is_class_begin=False):
string : the extracted comment body, inclusive of its quote marks. string : the extracted comment body, inclusive of its quote marks.
""" """
i = start_from i = start_from
fcombody = "" # def comment body fcombody = "" # def comment body
comstart = -1 # the starting line index of comment mark "'''" or """""" comstart = -1 # the starting line index of comment mark "'''" or """"""
...@@ -289,7 +260,7 @@ def print_header(htype, name): ...@@ -289,7 +260,7 @@ def print_header(htype, name):
print("-----------------------") print("-----------------------")
def srccoms_extract(srcfile, status_all, wlist): def srccoms_extract(srcfile, wlist):
""" """
Given a source file ``srcfile``, this function will Given a source file ``srcfile``, this function will
extract its API(doc comments) and run sample codes in the extract its API(doc comments) and run sample codes in the
...@@ -297,16 +268,13 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -297,16 +268,13 @@ def srccoms_extract(srcfile, status_all, wlist):
Args: Args:
srcfile(file): the source file srcfile(file): the source file
status_all(dict): record all the sample code execution states.
wlist(list): white list wlist(list): white list
Returns: Returns:
result: True or False
string: the length of __all__ list in srcfile versus the exact number of
analysed API to make sure no API is missed in this srcfile and it
is useful for statistic practices.
""" """
process_result = True
srcc = srcfile.read() srcc = srcfile.read()
# 2. get defs and classes header line number # 2. get defs and classes header line number
...@@ -351,7 +319,6 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -351,7 +319,6 @@ def srccoms_extract(srcfile, status_all, wlist):
if srcls[i].find("__doc__") != -1: if srcls[i].find("__doc__") != -1:
opname = srcls[i][:srcls[i].find("__doc__") - 1] opname = srcls[i][:srcls[i].find("__doc__") - 1]
if opname in wlist: if opname in wlist:
status_all[srcfile.name + '/' + opname] = [-2]
continue continue
comstart = i comstart = i
for j in range(i, len(srcls)): for j in range(i, len(srcls)):
...@@ -362,10 +329,9 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -362,10 +329,9 @@ def srccoms_extract(srcfile, status_all, wlist):
opcom += srcls[j] opcom += srcls[j]
if srcls[j].find("\"\"\"") != -1: if srcls[j].find("\"\"\"") != -1:
break break
status = sampcd_extract_and_run(opcom, opname, "def", process_result = sampcd_extract_and_run(opcom, opname,
opname) "def", opname)
api_count += 1 api_count += 1
status_all[srcfile.name + '/' + opname] = status
handled.append( handled.append(
opname) # ops.py also has normal formatted functions opname) # ops.py also has normal formatted functions
# use list 'handled' to mark the functions have been handled here # use list 'handled' to mark the functions have been handled here
...@@ -381,19 +347,16 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -381,19 +347,16 @@ def srccoms_extract(srcfile, status_all, wlist):
if fn in alllist: if fn in alllist:
api_count += 1 api_count += 1
if fn in wlist or fn + "@" + srcfile.name in wlist: if fn in wlist or fn + "@" + srcfile.name in wlist:
status_all[srcfile.name + '/' + fn] = [-2]
continue continue
fcombody = single_defcom_extract(i, srcls) fcombody = single_defcom_extract(i, srcls)
if fcombody == "": # if no comment if fcombody == "": # if no comment
print_header("def", fn) print_header("def", fn)
print("WARNING: no comments in function ", fn, print("WARNING: no comments in function ", fn,
", but it deserves.") ", but it deserves.")
status_all[srcfile.name + '/' + fn] = [-1]
print(status_all[srcfile.name + '/' + fn])
continue continue
else: else:
status = sampcd_extract_and_run(fcombody, fn, "def", fn) if not sampcd_extract_and_run(fcombody, fn, "def", fn):
status_all[srcfile.name + '/' + fn] = status process_result = False
if srcls[i].startswith('class '): if srcls[i].startswith('class '):
c_header = srcls[i].replace(" ", '') c_header = srcls[i].replace(" ", '')
cn = c_header[len('class'):c_header.find('(')] # class name cn = c_header[len('class'):c_header.find('(')] # class name
...@@ -402,19 +365,16 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -402,19 +365,16 @@ def srccoms_extract(srcfile, status_all, wlist):
if cn in alllist: if cn in alllist:
api_count += 1 api_count += 1
if cn in wlist or cn + "@" + srcfile.name in wlist: if cn in wlist or cn + "@" + srcfile.name in wlist:
status_all[srcfile.name + '/' + cn] = [-2]
continue continue
# class comment # class comment
classcom = single_defcom_extract(i, srcls, True) classcom = single_defcom_extract(i, srcls, True)
if classcom != "": if classcom != "":
status = sampcd_extract_and_run(classcom, cn, "class", if not sampcd_extract_and_run(classcom, cn, "class",
cn) cn):
status_all[srcfile.name + '/' + cn] = status process_result = False
else: else:
print("WARNING: no comments in class itself ", cn, print("WARNING: no comments in class itself ", cn,
", but it deserves.\n") ", but it deserves.\n")
status_all[srcfile.name + '/' + cn] = [-1]
print(status_all[srcfile.name + '/' + cn])
# handling methods in class bodies # handling methods in class bodies
for x in range( for x in range(
i + 1, i + 1,
...@@ -435,7 +395,6 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -435,7 +395,6 @@ def srccoms_extract(srcfile, status_all, wlist):
if mn.startswith('_'): if mn.startswith('_'):
continue continue
if name in wlist or name + "@" + srcfile.name in wlist: if name in wlist or name + "@" + srcfile.name in wlist:
status_all[srcfile.name + '/' + name] = [-2]
continue continue
thismethod = [thisl[indent:] thismethod = [thisl[indent:]
] # method body lines ] # method body lines
...@@ -456,21 +415,19 @@ def srccoms_extract(srcfile, status_all, wlist): ...@@ -456,21 +415,19 @@ def srccoms_extract(srcfile, status_all, wlist):
thismtdcom = single_defcom_extract(0, thismtdcom = single_defcom_extract(0,
thismethod) thismethod)
if thismtdcom != "": if thismtdcom != "":
status = sampcd_extract_and_run( if not sampcd_extract_and_run(
thismtdcom, name, "method", name) thismtdcom, name, "method", name):
status_all[srcfile.name + '/' + process_result = False
name] = status return process_result
return [
srcfile.name + " all list length: " + str(api_alllist_count),
"analysed api count: " + str(api_count)
]
def test(file_list): def test(file_list):
process_result = True
for file in file_list: for file in file_list:
src = open(file, 'r') with open(file, 'r') as src:
counts = srccoms_extract(src, status_all, wlist) if not srccoms_extract(src, wlist):
src.close() process_result = False
return process_result
''' '''
...@@ -479,8 +436,6 @@ Important constant lists: ...@@ -479,8 +436,6 @@ Important constant lists:
filenames : the modules pending for check . filenames : the modules pending for check .
wlist : a list of API that should not trigger the example check . wlist : a list of API that should not trigger the example check .
It is composed of wlist_temp + wlist_inneed + wlist_ignore. It is composed of wlist_temp + wlist_inneed + wlist_ignore.
status_all: a status list containing all the execution status of all
APIs
srcfile: the source .py code file srcfile: the source .py code file
''' '''
...@@ -653,7 +608,6 @@ gpu_not_white = [ ...@@ -653,7 +608,6 @@ gpu_not_white = [
"deformable_conv", "cuda_places", "CUDAPinnedPlace", "CUDAPlace", "deformable_conv", "cuda_places", "CUDAPinnedPlace", "CUDAPlace",
"cuda_profiler" "cuda_profiler"
] ]
wlist = wlist_temp + wlist_inneed + wlist_ignore wlist = wlist_temp + wlist_inneed + wlist_ignore
if len(sys.argv) < 2: if len(sys.argv) < 2:
...@@ -673,49 +627,30 @@ else: ...@@ -673,49 +627,30 @@ else:
sys.exit("Invalid arguments") sys.exit("Invalid arguments")
print("API check -- Example Code") print("API check -- Example Code")
print("sample_test running under python", platform.python_version()) print("sample_test running under python", platform.python_version())
status_all = {}
# a temp directory to store temporary sample code file
# subprocess needs a single file to run the code
if not os.path.isdir("./samplecode_temp"): if not os.path.isdir("./samplecode_temp"):
os.mkdir("./samplecode_temp") os.mkdir("./samplecode_temp")
one_part_filenum = int(math.ceil(len(filenames) / 10)) cpus = multiprocessing.cpu_count()
one_part_filenum = int(math.ceil(len(filenames) / cpus))
divided_file_list = [ divided_file_list = [
filenames[i:i + one_part_filenum] filenames[i:i + one_part_filenum]
for i in range(0, len(filenames), one_part_filenum) for i in range(0, len(filenames), one_part_filenum)
] ]
po = multiprocessing.Pool(10) po = multiprocessing.Pool()
for file_list in divided_file_list: results = po.map_async(test, divided_file_list)
po.apply_async(test, (file_list, ))
po.close() po.close()
po.join() po.join()
result = results.get()
# clear temp files # delete temp files
for root, dirs, files in os.walk("./samplecode_temp"): for root, dirs, files in os.walk("./samplecode_temp"):
for fntemp in files: for fntemp in files:
os.remove("./samplecode_temp/" + fntemp) os.remove("./samplecode_temp/" + fntemp)
os.rmdir("./samplecode_temp") os.rmdir("./samplecode_temp")
status_groups = {-2: [], -1: [], 0: [], 1: [], 2: [], 3: []}
ci_pass = True
for key in status_all:
statusl = status_all[key]
for ele in statusl:
if ele != 0 and ele != -2 and ele != -1:
ci_pass = False
break
if len(statusl) == 1:
status_groups[statusl[0]].append(key)
else:
for u in range(0, len(statusl)):
status_groups[statusl[u]].append(key + '_' + str(u + 1))
print("----------------End of the Check--------------------") print("----------------End of the Check--------------------")
errorapisl = status_groups[1] + status_groups[2] + status_groups[3] for temp in result:
if len(errorapisl) > 0: if not temp:
print("Error raised from: ", str(errorapisl)) print("Mistakes found in sample codes")
if not ci_pass: exit(1)
print("Mistakes found in sample codes") print("Sample code check is successful!")
exit(1)
else:
print("Sample code check is successful!")
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册