最近實習,因工作需求,需要對大量源碼分別用不同編譯器進行編譯執行並分別記錄文件編譯信息以及編譯成功運行的信息,並根據要求記錄每個文件的csv信息。小組提供的一個稍有簡陋的shell腳本功能有限,個人也完全不懂shell。因此重編寫了一個小工具,記錄之,儘管可能重用率可能並不高。
工具工作內容:
- 單一項目文件夾中不相干的每一個源碼(c/c++)進行三種編譯器編譯(gcc/clang以及公司自己的編譯器)
- 對編譯成功生成的a.out進行自動運行
- 對每個文件每種編譯器編譯運行的詳情進行日誌記錄
- 將自動運行的情況對彙總的csv文件進行填充
csv填充格式要求如下:(便於對照代碼進行修改)
主要注意對其column編號。其中BCDE是由文件夾目錄等拆分出的填充信息,FJ兩列信息是在每個文件中定義的://kind:normal 、//expect result:1這樣。result分爲1,2,3三種狀態,KLM列也是按運行情況填充1、2、3這三種內容,GHI按運行情況填充字符’○’、’ב這兩種內容。
具體文件及使用方法見repo鏈接:autoCompileTest
代碼:
#! /usr/bin/env python
# coding=utf-8
#Author:BaoJunxian
#Date:2018/5/28
import os,openpyxl,subprocess
from openpyxl import styles
TEST_FILE_SUFFIX = ('.c','.c++','.cxx','.cpp','.C','.cc')
C_FILE_SUFFIX = ('.c')
CPP_FILE_SUFFIX = ('.c++','.cxx','.cpp','.C','.cc')
C_COMPILE = ['gcc','clang','fcc -Xg']
CC_COMPILE = ['g++','clang++','FCC -Xg']
#some configurations
CSV_URL = '/home/baojx/test_case/19_Arrays_of_Variable_Length/GNU拡張仕様テスト仕様書_JP.xlsx'
CSV_TMP = ''.join([CSV_URL,'.bak'])
MODI_SHEET = 'Content'
#some modi constant val def
TEST_CORDANCE = '○'
TEST_DISCORDANCE = '×'
ALL_PASS = 1
HALF_PASS = 2
ALL_ERROR = 3
#parse content for csv basic info modification,return tuple(caseType,expectResult)
def contentParse(fileName):
with open(fileName) as target:
while True:
content = next(target,'EOF').strip()
if content.startswith('//kind'):
caseType = content.split(':')[1].strip()
elif content.startswith('//expect result:'):
expectResult = content.split(':')[1].strip()
elif content == 'EOF':
break
else:
continue
return (caseType,expectResult)
#run actions in list
def run(fileName,actionList,compileLogObject,executeLogObject):
caseType = contentParse(fileName)[0]
expectResult = int(contentParse(fileName)[1])
calculator = 0
exeResult = []
testResult = []
for cli in actionList:
compileResult = executeResult = 0
print(''.join(['Compiling ',fileName,'...[',cli,']']))
compilePopen = subprocess.Popen(' '.join([cli, fileName]),shell=True,stderr=subprocess.PIPE)
compilePopen.wait()
if compilePopen.returncode == 0:
print(' \033[0;32;40mPASS.\033[0m')
compileLogObject.write(''.join(['\033[0;34;40mTest Case:\033[0m ',fileName,'\n',\
'\033[0;34;40mCli:\033[0m ',cli,'\n\033[0;34;40mStatus:\033[0m ','\033[0;32;40mpass\033[0m'\
'\n\033[0;34;40mVerbose:\033[0m\n','None Compiling Exception.\n\n']))
compileResult = True
print(' Executing ...')
execPopen = subprocess.Popen('./a.out',shell=True,stderr=subprocess.PIPE)
execPopen.wait()
if execPopen.returncode == 0:
print(' \033[0;32;40mPASS.\033[0m')
executeLogObject.write(''.join(['\033[0;34;40mTest Case:\033[0m ',fileName,'\n',\
'\033[0;34;40mCli:\033[0m ',cli,\
'\n\033[0;34;40mStatus:\033[0m ','\033[0;32;40mpass\033[0m'\
'\n\033[0;34;40mVerbose:\033[0m\n','None Execution Exception.\n\n']))
executeResult = True
else:
print(' \033[0;31;40mERROR.\033[0m Logging ...')
executeLogObject.write(''.join(['\033[0;34;40mTest Case:\033[0m ',fileName,'\n',\
'\033[0;34;40mCli:\033[0m ',cli,\
'\n\033[0;34;40mStatus:\033[0m ','\033[0;31;40merror\033[0m'\
'\n\033[0;34;40mVerbose:\033[0m\n',execPopen.stderr.read(),'\n']))
executeResult = False
else:
print(' \033[0;31;40mERROR.\033[0m Logging ...')
compileLogObject.write(''.join(['\033[0;34;40mTest Case:\033[0m ',fileName,'\n',\
'\033[0;34;40mCli:\033[0m ',cli,'\n\033[0;34;40mStatus:\033[0m ','\033[0;31;40merror\033[0m'\
'\n\033[0;34;40mVerbose:\033[0m\n',compilePopen.stderr.read(),'\n']))
compileResult = False
exeResult.append(ALL_PASS if compileResult and executeResult else \
(HALF_PASS if compileResult or executeResult else ALL_ERROR))
testResult.append(TEST_CORDANCE if exeResult[calculator] == expectResult else TEST_DISCORDANCE)
print('''
case_type : %s
expect_result : %s
exec_result : %d
test_result : %s
cal : %d
''')%(caseType,expectResult,exeResult[calculator],testResult[calculator],calculator)
calculator += 1
return [caseType,testResult,expectResult,exeResult]
#return value format: [caseType,testResult[],expectResult,exeResult[]]
#modify path_specified csv file
def csvModi(ws,row,contentDict):
for i in contentDict.keys():
ws[''.join([i,str(row)])] = contentDict[i]
#specify content_color
if contentDict[i] == TEST_DISCORDANCE:
ws[''.join([i,str(row)])].fill = styles.PatternFill(patternType='solid',\
fgColor = styles.colors.Color(rgb=None,theme=0,tint=-0.3499862666707358,type='theme'),\
bgColor = styles.colors.Color(rgb=None,indexed=64,type='indexed'))
#flatten deep list
def listFlatten(srcList):
dstList = []
for i in srcList:
if type(i) is not list:
dstList.append(i)
else:
dstList += listFlatten(i)
return dstList
def main():
if os.path.exists(CSV_TMP):
chose = raw_input('\033[0;34;40mCarry on from the last modification\033[0m[y/n]: ').strip().lower()
if chose == 'y':
os.system(''.join(['rm ',CSV_URL,';mv ',CSV_TMP,' ',CSV_URL]))
if chose == 'n':
os.system(''.join(['rm ',CSV_TMP]))
workbook = openpyxl.load_workbook(CSV_URL)
ws = workbook[MODI_SHEET]
row = ws.max_row
print('the last row is :',row)
startRow = cuRow = row+1
#specify fill sequence [file,caseType,testResult,expectResult,exeResult]
colSeq = 'EFGHIJKLM'
#current directory ops
tupleGen = os.walk(os.getcwd())
levelOneCat = next(tupleGen)
fileList = levelOneCat[2]
cat = os.path.basename(levelOneCat[0])
itemNum = int(cat.split('_',1)[0])
item = cat.split('_',1)[1]
with open('compileLog','w+') as compileLog,open('executeLog','w+') as exeLog:
# make sure test suite of cases just one log
for file in fileList:
#each file lock corresponding row
if file.endswith(TEST_FILE_SUFFIX):
# cuNum += 1
fillSeq = [file]
if file.endswith(C_FILE_SUFFIX):
a = run(file,C_COMPILE,compileLog,exeLog)
if file.endswith(CPP_FILE_SUFFIX):
a = run(file,CC_COMPILE,compileLog,exeLog)
#single file modi csv
fillSeq.extend(listFlatten(a))
contentDict = dict(zip(colSeq,fillSeq))
# print(fillSeq,'\n',contentDict)
csvModi(ws,cuRow,contentDict)
cuRow += 1
else:
pass
else:
#specify single cell to modify
endRow = cuRow-1
specFillCell = {'B':itemNum,'C':item,'D':cat}
csvModi(ws,startRow,specFillCell)
for m in ws[''.join(['F',str(startRow),':','M',str(endRow)])]:
for n in m:
n.alignment = styles.Alignment(horizontal='center',vertical='center')
for i in specFillCell.keys():
ws.merge_cells(''.join([i,str(startRow),':',i,str(endRow)]))
ws[''.join([i,str(startRow)])].alignment = styles.Alignment(horizontal='left',vertical='center')
overwrite = raw_input('\033[0;34;40mOverwrite source csv file\033[0m[y/n]: ').strip().lower()
if overwrite == 'n':
workbook.save(CSV_TMP)
if overwrite == 'y':
workbook.save(CSV_URL)
if __name__ == '__main__':
main()