本發(fā)明涉及一種基于源代碼的程序自動插樁方法,屬于計算機軟件應(yīng)用領(lǐng)域。
背景技術(shù):
軍工軟件、航天航空軟件、工業(yè)控制軟件等具有高可靠性要求的軟件領(lǐng)域都需要使用白盒測試的方法對軟件進行詳細的測試,覆蓋率是衡量軟件質(zhì)量的重要指標。程序插樁是實現(xiàn)覆蓋率測試的一種重要方法。程序插樁的基本測試原理就是在不破壞原有程序邏輯完整性的前提下,在程序的相應(yīng)位置上插入一些探針,實質(zhì)上就是進行信息采集的代碼段,可以是賦值語句或采集覆蓋信息的函數(shù)調(diào)用。通過探針的執(zhí)行并輸出程序的運行特征數(shù)據(jù)?;趯@些特征數(shù)據(jù)的分析,以達到揭示程序內(nèi)部行為和特性的目的。
基于源代碼插樁的動態(tài)覆蓋測試主要是通過手動方式進行插樁,用戶手動在源程序需要獲取程序運行信息的地方寫入信息采集代碼段(代碼段可以是覆蓋信息采集函數(shù)調(diào)用,也可以是簡單的賦值語句)完成代碼插裝工作,然后編譯鏈接程序時需將包含覆蓋信息采集功能函數(shù)的庫鏈接進來,采用手工方式的缺點在于破壞源程序,在不進行測試時,需要刪除插入的代碼或使用宏定義方式屏蔽插入的代碼,尤其在程序規(guī)模較大時,手動插樁方式比較繁瑣和低效,更容易發(fā)生覆蓋不全的情況。
技術(shù)實現(xiàn)要素:
本發(fā)明的技術(shù)解決問題是:克服現(xiàn)有手動插樁的不足,提出一種基于源代碼的程序自動插樁方法,不破壞源程序,插樁準確度和針對性高,能夠有效減少工作量,提高效率。
本發(fā)明的技術(shù)解決方案:一種基于源代碼的程序自動插樁方法,步驟如下:
步驟一:將待插樁C源代碼進行宏展開;
步驟二:根據(jù)插樁需求明確插樁切入點,為每個插樁切入點編寫插樁語法規(guī)則;
步驟三:利用語法分析生成器將插樁語法規(guī)則轉(zhuǎn)化為插樁程序,運行插樁程序?qū)υ创a進行自動插樁,完成源代碼的程序自動插樁。
所述步驟一的實現(xiàn)方法為:
(2.1)編寫宏展開詞法分析規(guī)則,生成詞法分析器;
(2.2)使用詞法分析器,把頭文件中定義的宏在源文件中展開。
所述步驟二的實現(xiàn)方法為:
(3.1)根據(jù)插樁需求選擇覆蓋準則,所述覆蓋準則為判定覆蓋、跳轉(zhuǎn)覆蓋或例程覆蓋;
(3.2)根據(jù)覆蓋準則確定插樁切入點位置,具體確定方法如下:
a)如果覆蓋準則為判定覆蓋,則選擇if語句、else if語句、else語句以及case語句開始或結(jié)束處作為插樁切入點;
b)如果覆蓋準則為跳轉(zhuǎn)覆蓋,則插樁切入點在goto語句、continue語句、break語句之前;
c)如果覆蓋準則為例程覆蓋,則插樁切入點在每個函數(shù)的入口和出口處;
(3.3)為每個插樁切入點編寫插樁語法規(guī)則。
所述步驟(3.3)的實現(xiàn)方法如下:
(4.1)為每行代碼編寫解析規(guī)則,對待插樁C源代碼進行解析,所述解析規(guī)則如下:
<產(chǎn)生式頭>:<產(chǎn)生式體>
(4.2)利用語法制導(dǎo)翻譯方法對產(chǎn)生式進行解析,為每個產(chǎn)生式增加插樁語義動作,得到每個插樁切入點的插樁語法規(guī)則如下:
<產(chǎn)生式頭>:<產(chǎn)生式體>{語義動作}。
所述步驟(4.2)中,增加插樁語義動作時要保證插裝前后的語法結(jié)構(gòu)等價,插裝前后的語義相同。
本發(fā)明與現(xiàn)有技術(shù)相比具有如下有益效果:
(1)本發(fā)明在對源代碼文件進行完整的詞法分析和語法分析的基礎(chǔ)上進行自動插樁,保證了對源碼插樁的準確度和針對性,能夠解決手動插樁工作量大,效率低下,插樁不完全的問題。
(2)本發(fā)明采用語法制導(dǎo)翻譯方案來描述插裝的行為,具有簡潔、清晰、容易實現(xiàn)和容易驗證正確性等特點,同時不破壞源程序,不進行測試時,不需要刪除插入的代碼或使用宏定義方式屏蔽插入的代碼,能夠有效減少工作量,提高效率。
附圖說明
圖1為本發(fā)明方法流程圖。
具體實施方式
本發(fā)明提出一種基于源代碼的程序自動插樁方法,如圖1所示,具體步驟如下:
步驟一、對被插樁C源代碼文件進行預(yù)處理
(1)編寫宏展開詞法分析規(guī)則,生成詞法分析器;
(2)使用詞法分析器進行宏擴展,把頭文件中定義的宏在源文件中展開;
例如:源文件中包含宏定義,特別是一些具有分支路徑的宏定義,需要將宏在源文件中展開,如果不進行宏展開可能導(dǎo)致覆蓋統(tǒng)計不全。
步驟二、插樁切入點確定及編寫插樁語法規(guī)則
(1)根據(jù)插樁需求明確插樁切入點
為了統(tǒng)計C源碼覆蓋,根據(jù)插樁需求選擇覆蓋準則,其中覆蓋準則為判定覆蓋、跳轉(zhuǎn)覆蓋或例程覆蓋。
根據(jù)覆蓋準則明確插樁切入點位置,如果是判定覆蓋:要求被測程序中的每個判定的每個分支少執(zhí)行一次,選擇在if語句、else if語句、else語句、case語句的入口和出口處進行插樁;如果是跳轉(zhuǎn)覆蓋:根據(jù)跳轉(zhuǎn)邏輯,選擇在goto語句、continue語句、break語句前進行插樁;如果是例程覆蓋:在每個函數(shù)(包括中斷處理函數(shù))的入口和出口處插樁。
(2)對插樁點編寫對應(yīng)的插樁語法規(guī)則;
(2.1)為每行代碼編寫解析規(guī)則,對待插樁C源代碼進行解析,所述解析規(guī)則如下:
<產(chǎn)生式頭>:<產(chǎn)生式體>
(2.2)利用語法制導(dǎo)翻譯方法對產(chǎn)生式進行解析,為每個產(chǎn)生式增加插樁語義動作,語法制導(dǎo)翻譯方法如下:如果A:α是產(chǎn)生式,那么翻譯為A:α{β},其中A是非終結(jié)符,α、β分別是產(chǎn)生式體和輸出的翻譯語句。據(jù)此得到每個插樁切入點的插樁語法規(guī)則如下:
<產(chǎn)生式頭>:<產(chǎn)生式體>{語義動作}
如果包含嵌套語句,則,插樁語法規(guī)則可以寫成如下形式:
<產(chǎn)生式頭>:<產(chǎn)生式體1>{語義動作1}
|<產(chǎn)生式體2>{語義動作2}
。。。
|<產(chǎn)生式體n>{語義動作n}
一個語義動作是一個C語句的序列,當按照一個產(chǎn)生式進行歸約的時候,就會執(zhí)行和該產(chǎn)生式相關(guān)聯(lián)的語義動作。
語法制導(dǎo)翻譯方案就是將程序片段附加到一個文法的各個產(chǎn)生式上的表示方法。當語法分析過程中使用一個產(chǎn)生式時,相應(yīng)的程序片段就會執(zhí)行。這些程序片段的執(zhí)行效果按照語法分析過程的順序組合起來,得到的結(jié)果就是處理源程序的翻譯結(jié)果。
下面給出判定語句、跳轉(zhuǎn)語句和循環(huán)語句的插樁語法規(guī)則:
判定語句插樁語法規(guī)則:
判定語句覆蓋插裝的思想是:使用一個計數(shù)器varNub來記錄判定語句的覆蓋情況,在判定語句體內(nèi)插入記錄函數(shù),根據(jù)記錄結(jié)果的值判定分支是否被執(zhí)行。判定語句的插樁語法規(guī)則是:
跳轉(zhuǎn)語句jump語句插樁語法規(guī)則:
jump_statement
:RETURN';' {format($$,"Jump Log(varNub);return;\n");}
|RETURN expression';' {format($$,"Jump Log(varNub);return%s;\n",$2);}
goto,continue,break語句類似。
循環(huán)語句while語句插樁語法規(guī)則:
完成插樁后,要對插樁語法規(guī)則正確性判斷:
插裝程序插入的代碼僅僅收集結(jié)構(gòu)覆蓋信息,不能改變被測程序的語義。對此根據(jù)翻譯方案從兩方面加以驗證:語法等價:插裝前后的語法結(jié)構(gòu)是等價的,對于語句插裝,插裝后的語句應(yīng)該是復(fù)合語句,在語法上與原語句等價,因此插裝后的語句前后必須補充一對花括號,否則在語法上出現(xiàn)錯誤,導(dǎo)致插樁前后語句不等價。語義相同:由于插樁后的語句只是增加覆蓋信息記錄,從翻譯方案可知,插入的語句沒有改變原程序的流程。
另外,在插樁語法規(guī)則中,語義動作可以在產(chǎn)生式的任何位置,實際插樁時有些語義動作需要插入產(chǎn)生體內(nèi)。但是有些情況下為了插裝方便的需要,在保持與原規(guī)則等價的前提下,對原規(guī)則作了一定的變換。需要構(gòu)造出一個后綴語法制導(dǎo)翻譯方案,其中每個語義動作都放在產(chǎn)生式的最后,并且在按照這個產(chǎn)生式將產(chǎn)生體歸約為產(chǎn)生式頭的時候執(zhí)行插樁動作。為此,我們引入新的產(chǎn)生式,該產(chǎn)生式所有的動作都在產(chǎn)生式最右端。利用新的產(chǎn)生式歸約來執(zhí)行某些語義動作是比較方便的。
例如:
selection_statement
:IF'('expression')'statement ELSE statement
|IF'('expression')'statement
在判定覆蓋語句插裝中,要求對以上產(chǎn)生式中的statement進行插裝,而對其它產(chǎn)生式中的statement不作插裝。本發(fā)明引入一個新的非終結(jié)符statement_IF,將以上規(guī)則替換為:
statement_IF
:labeled_statement
|compound_statement
……
selection_statement
:IF'('expression')'statement_IF ELSE statement_IF
|IF'('expression')'statement_IF
……
對于替換后的規(guī)則,在判定覆蓋語句插裝時只需在第一個產(chǎn)生式的動作中執(zhí)行對statement_IF產(chǎn)生體中的規(guī)則進行插裝。
步驟三、生成插樁程序并完成源代碼插樁
(1)將插樁語法規(guī)則翻譯為執(zhí)行插樁的源代碼;
插樁語法規(guī)則不能直接進行源代碼插樁動作,使用語法分析生成器將插樁語法規(guī)則翻譯為執(zhí)行插樁的源代碼,編譯該源代碼為可執(zhí)行插樁動作的插樁程序,插裝程序是一個翻譯器,它在推導(dǎo)出每個產(chǎn)生式的同時,相應(yīng)地以插裝后的語句作為輸出,因此本發(fā)明使用語法制導(dǎo)翻譯方案來描述插裝器的插裝行為。
(2)運行插樁程序完成插樁;
運行插樁程序,得到插樁后的C源代碼文件。
本發(fā)明方法在對源代碼文件進行完整的詞法分析和語法分析的基礎(chǔ)上進行自動插樁,這保證了對源碼插樁的準確度和針對性,能夠解決手動插樁工作量大,效率低下,插樁不完全的問題,不破壞源程序,不進行測試時,也不需要刪除或屏蔽插入的代碼,能夠有效減少工作量,提高效率。同時采用了基于語法制導(dǎo)翻譯技術(shù),根據(jù)程序結(jié)構(gòu)特征對語言文法的產(chǎn)生式進行改寫,有效地簡化了程序插樁實現(xiàn),可以在短時間內(nèi)實現(xiàn)源程序的插樁。
本發(fā)明未詳細描述內(nèi)容為本領(lǐng)域技術(shù)人員公知技術(shù)。