Commit 57da8559 authored by Ille, Ondrej, Ing.'s avatar Ille, Ondrej, Ing.

scripts: Add script for extraction of test information.

parent 03285423
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2017 Ondrej Ille <ondrej.ille@gmail.com>
##
## Simple HTML generator generating HTML document from test information
## obtained by VRM Processor.
##
## Revision history:
## 09.01.2020 Implemented the script
##
################################################################################
import os
import re
from pathlib import Path
from yattag import Doc
class VRMGenerator:
vrmInfo = None
outPath = " "
def __init__(self, vrmInfo, outPath):
"""
"""
if (type(vrmInfo) != list):
print("Input to VRMProcessor shall be list of files")
exit(-1);
self.vrmInfo = vrmInfo
self.outPath = outPath
def add_html_table_header(self, doc, tag, text, headers, back_color="White"):
"""
Add header to HTML table.
"""
with tag('tr'):
for header in headers:
with tag('th', bgcolor=back_color):
text(header)
def gen_single_test_info(self, doc, tag, text, testItem):
"""
Generate HTML table row with test info of 1 test.
"""
with tag('tr'):
with tag('td'):
text(str(testItem["testName"]).split("/")[-1])
#TODO: Maybe add link to file??
#file_name = get_collapsed_file_name(psl_point)
#with tag('a', href=file_name+".html"):
# text("Open collapsed tests")
with tag('td'):
text(testItem["purpose"])
with tag('td'):
with tag('table', width='100%'):
for vrmEntry in testItem["vrmEntries"]:
with tag('tr'):
with tag('td'):
text(vrmEntry.strip("@"))
with tag('td'):
with tag('table', width='100%'):
for testEntry in testItem["sequence"]:
with tag('tr'):
with tag('td'):
text(testEntry.strip("@"))
#
#if (psl_point["status"] == "covered" or \
# psl_point["status"] == "passed"):
# color = "Lime"
#else:
# color = "red"
#with tag('td', ('bgcolor',color)):
# text(psl_point["status"])
def gen_VRM_info(self, doc, tag, text):
"""
Generate test information for all tests. Each test represents single row
in VRM HTML table
"""
with tag('table', width='100%', border="1px solid black"):
headers = ["Test Name"]
headers.append("Purpose")
headers.append("VRM Entries (What does the test verify)")
headers.append("Test sequence")
self.add_html_table_header(doc, tag, text, headers,
back_color="Aquamarine")
for testItem in self.vrmInfo:
print("Generating info for test: {}".format(testItem["testName"]))
self.gen_single_test_info(doc, tag, text, testItem)
def gen_VRM_title(self, doc, tag, text, title):
"""
Generate HTML VRM title.
"""
with tag('table', width='100%', border=0, cellspacing=0, cellpadding=0):
with tag('tr'):
with tag('th', ('class','title')):
with tag('font', size=10):
text(title)
def gen_VRM(self, title):
"""
Generate HTML VRM for test information.
"""
doc, tag, text = Doc().tagtext()
self.gen_VRM_title(doc, tag, text, title)
self.gen_VRM_info(doc, tag, text)
with Path(self.outPath).open('wt', encoding='utf-8') as html_file:
html_file.write(doc.getvalue())
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2017 Ondrej Ille <ondrej.ille@gmail.com>
##
## Simple text processor extracting test information from test header files.
## Following information are extracted:
## 1. VRM entries (what is verified by the test)
## 2. Test sequence
## 3. Test Purpose (simple test description)
##
## Tests extract information between tags:
## @TestInfoStart
## @TestInfoEnd
##
## Revision history:
## 09.01.2020 Implemented the script
##
################################################################################
import os
import re
from enum import Enum
class VRMFSM(Enum):
IDLE = 1,
STARTED = 2,
PURPOSE = 3,
VRM_ENTRIES = 4,
TEST_SEQUENCE = 5,
NOTES = 6,
FINISHED = 7
# Tags which are search for by VRM extractor!
purposeTag = "@Purpose"
vrmEntryTag = "@Verifies"
sequenceTag = "@Test sequence"
notesTag = "@Notes"
startTag = "@TestInfoStart"
endTag = "@TestInfoEnd"
class VRMProcessor:
fileList = []
# Results are list of entries, where each entry is dictionary with keys:
# testName - Name of test file
# vrmEntries - List of strings, each with VRM entries.
# purpose - Single string
# sequence - List of strings with test sequence
results = []
def __init__(self, fileList):
"""
"""
if (type(fileList) != list):
printf("Input to VRMProcessor shall be list of files")
system.exit(-1);
self.fileList = fileList
def VRMProcess(self, tf):
"""
VRMProcessor FSM. Process input file and extract test info!
"""
state = VRMFSM.IDLE
lines = tf.readlines()
res = {"purpose":"", "vrmEntries":[], "sequence":[], "testName":"", "notes":""}
for lineCnt, line in enumerate(lines):
if (state == VRMFSM.IDLE and re.search(startTag, line)):
state = VRMFSM.STARTED
# Process further states only when we are started!
if (state == VRMFSM.IDLE or state == VRMFSM.FINISHED):
continue
if (re.search(purposeTag, line)):
state = VRMFSM.PURPOSE
continue
if (re.search(vrmEntryTag, line)):
state = VRMFSM.VRM_ENTRIES
continue
if (re.search(sequenceTag, line)):
state = VRMFSM.TEST_SEQUENCE
continue
if (re.search(notesTag, line)):
state = VRMFSM.NOTES
continue
if (re.search(endTag, line)):
state = VRMFSM.FINISHED
break
line = line.strip('-\n ')
if (state == VRMFSM.STARTED):
continue
if (state == VRMFSM.PURPOSE):
res["purpose"]+= line + " "
# VRM entries are linear list always!
if (state == VRMFSM.VRM_ENTRIES):
# Start of next step
if (re.match("@[1-9]+[.]", line)):
res["vrmEntries"].append("")
if (len(res["vrmEntries"]) > 0):
res["vrmEntries"][-1]+=line+" "
# Test sequence can be nested, but we linearize them for simplicity!
# Add also item tag so that nested items can be distinguished!
if (state == VRMFSM.TEST_SEQUENCE):
if (re.match("@[1-9]+[.].+", line)):
res["sequence"].append("")
if (len(res["sequence"]) > 0):
res["sequence"][-1]+=line+" "
if (state == VRMFSM.NOTES):
res["notes"]+=line + " "
if (lineCnt > 1000):
print("Too many lines in test info, aborting!");
break
return res;
def printResult(self, res):
"""
Print test info result extracted from single test file header
"""
print("*" * 80)
print("PURPOSE:")
print(res["purpose"])
print("VRM ENTRIES:")
for vrmEntry in res["vrmEntries"]:
print(vrmEntry)
print("TEST SEQUENCE:")
for testEntry in res["sequence"]:
print(testEntry)
print("*" * 80)
def extractTestInfo(self):
"""
Extract test information for each test within self.fileList info
"""
for testFile in self.fileList:
print("Processing file: {}".format(testFile))
tf = open(str(testFile), 'r')
if (not tf):
print("Unable to open : {}, skipping".format(testFile))
continue
testInfo = self.VRMProcess(tf)
testInfo["testName"] = testFile
#print("Extracted test info:")
#self.printResult(testInfo)
#print("\n\n")
self.results.append(testInfo)
tf.close()
return self.results
################################################################################
##
## CAN with Flexible Data-Rate IP Core
##
## Copyright (C) 2017 Ondrej Ille <ondrej.ille@gmail.com>
##
## Script for generation of VRM. What has been verified is extracted from
## common headers
##
## Arguments:
## configPath - Path to test config (the same as for test run)
##
## Revision history:
## 09.01.2020 Implemented the script
##
################################################################################
import argparse
import sys
import time
import importlib.util
import os
import inspect
import math
import yaml
from VRM_Extractor.VRMProcessor import VRMProcessor
from VRM_Extractor.VRMGenerator import VRMGenerator
from pathlib import Path
def parse_args():
parser = argparse.ArgumentParser(
description="""Script for generation of VRM. What has been
verified is extracted from common headers""")
parser.add_argument('--configPath', dest='configPath', help="""Path to
test config (the same as for test run)""")
return parser.parse_args();
def read_config(configPath):
"""
Read CTU CAN FD test configuration and obtain list of file paths with test
source codes (these can be then searched for VRM entries).
File paths are returned relative to project root location!
"""
with Path(configPath).open("r") as f:
cfg = yaml.safe_load(f);
test_dir = Path("../test")
ftr_dir = test_dir / "feature"
san_dir = test_dir / "sanity"
unit_dir = test_dir / "unit"
ref_dir = test_dir / "reference"
fileList = []
if ("feature" in cfg):
ftr = cfg['feature']
for ftr_tst in ftr['tests'].items():
print("Processing feature test: {}".format(ftr_tst[0]));
fileList.append(ftr_dir / "{}_feature_tb.vhd".format(ftr_tst[0]))
if ("sanity" in cfg):
print("Processing sanity test!")
fileList.append(san_dir / "sanity_test.vhd")
if ("unit" in cfg):
uni = cfg['unit']
for unit_tst in uni['tests'].items():
t_dict = list(unit_tst)[1]
print("Processing unit test {}".format(list(unit_tst)[0]))
tst_dir = Path(os.path.dirname(t_dict['wave']))
tst_name = test_dir / tst_dir / "{}_tb.vhd".format(str(tst_dir).split("/")[-1])
fileList.append(tst_name)
if ("reference" in cfg):
fileList.append(ref_dir / "tb_reference.vhd")
print(fileList)
return fileList
if __name__ == '__main__':
args = parse_args()
print( 80 * "*")
print("** Generating CTU CAN FD VRM!")
print(80 * "*")
pythonVersion = sys.version.split('.')
pythonCmd = "python" + pythonVersion[0] + "." + pythonVersion[1]
print("\n Python version is: %s \n" % pythonCmd)
test_files = read_config(args.configPath)
vrmProc = VRMProcessor(test_files)
results = vrmProc.extractTestInfo()
vrmGen = VRMGenerator(results, "VRM.html")
vrmGen.gen_VRM("CTU CAN FD - Test information")
print( 80 * "*")
print("** Finished")
print(80 * "*")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment