自動編譯執行並生成log、記錄CSV文件工具腳本

最近實習,因工作需求,需要對大量源碼分別用不同編譯器進行編譯執行並分別記錄文件編譯信息以及編譯成功運行的信息,並根據要求記錄每個文件的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()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章