(中航雷華柯林斯(無(wú)錫)航空電子設(shè)備有限公司,江蘇 無(wú)錫 214063)
當(dāng)今信息化社會(huì)中,對(duì)軟件的質(zhì)量要求隨著軟件應(yīng)用的普及變得越來(lái)越高,特別是在航空等許多涉及人類生命安全的領(lǐng)域,對(duì)軟件質(zhì)量和安全的要求更是提高到了一個(gè)不容忽視的程度。為了充分保證民用機(jī)載軟件中安全關(guān)鍵軟件的質(zhì)量,軟件測(cè)試是關(guān)鍵步驟,其中靜態(tài)測(cè)試是重要的環(huán)節(jié)。本文基于軟件分析工具LDRA Testbed,探究民用機(jī)載軟件的靜態(tài)測(cè)試方法。
靜態(tài)測(cè)試也被稱作靜態(tài)分析,傳統(tǒng)意義上是指不實(shí)際編譯和運(yùn)行被測(cè)軟件,只靜態(tài)地解析軟件源代碼,查找錯(cuò)誤或搜集相關(guān)度量數(shù)據(jù)。靜態(tài)測(cè)試的對(duì)象有代碼、界面和文檔3種,以測(cè)試是否符合相應(yīng)的標(biāo)準(zhǔn)規(guī)范和需求說(shuō)明為主要目的[7]。
靜態(tài)測(cè)試的檢測(cè)方法分為人工檢測(cè)和計(jì)算機(jī)輔助靜態(tài)分析2種:1)人工檢測(cè):指不依賴計(jì)算機(jī)而完全靠人工審查或評(píng)審軟件來(lái)完成靜態(tài)測(cè)試。以檢查編碼風(fēng)格和檢驗(yàn)質(zhì)量為主,也檢驗(yàn)各階段的軟件產(chǎn)品。該方法能夠有效發(fā)現(xiàn)邏輯設(shè)計(jì)和編碼錯(cuò)誤[8]。2)計(jì)算機(jī)輔助靜態(tài)分析:基于靜態(tài)分析工具對(duì)被測(cè)軟件進(jìn)行特性分析,提取程序中的有效信息,從而檢查各種邏輯缺陷和可疑程序構(gòu)造[8]。
在民用機(jī)載軟件測(cè)試領(lǐng)域,對(duì)于文檔常采用人工檢測(cè)的方法,而對(duì)于代碼,由于其規(guī)模龐大且具有高安全性和強(qiáng)時(shí)序性的要求,則必須采用計(jì)算機(jī)輔助靜態(tài)分析的方法以盡可能多地發(fā)現(xiàn)程序中的隱式錯(cuò)誤。市場(chǎng)上的大部分測(cè)試工具只能識(shí)別源代碼與標(biāo)準(zhǔn)的偏差,而LDRA Testbed除了檢測(cè)編碼標(biāo)準(zhǔn)符合性,可以提供調(diào)用圖、程序流程圖和各種分析報(bào)告來(lái)可視化代碼的可測(cè)試性、可維護(hù)性和清晰度,是航空領(lǐng)域自動(dòng)化測(cè)試的主要工具。
LDRA Testbed的靜態(tài)分析支持代碼程序設(shè)計(jì)標(biāo)準(zhǔn)的規(guī)定,生成關(guān)于復(fù)雜度和標(biāo)準(zhǔn)違反情況的分析報(bào)告,同時(shí)解析源代碼,生成后續(xù)插樁和動(dòng)態(tài)分析階段的內(nèi)部工作文件,其原理類似于編譯器執(zhí)行的語(yǔ)法分析。因此必須首先執(zhí)行靜態(tài)分析。
LDRA Testbed的靜態(tài)測(cè)試結(jié)構(gòu)如圖1所示,由圖可知包含以下5種分析,并且這些分析方法必須按照順序依次執(zhí)行:
圖1 LDRA Testbed靜態(tài)測(cè)試結(jié)構(gòu)
1)主要靜態(tài)分析(Main Static Analysis)
2)復(fù)雜度分析(Complexity Analysis)
3)靜態(tài)數(shù)據(jù)流分析(Static Data Flow Analysis)
4)交叉索引(Cross Reference)
5)信息流分析(數(shù)據(jù)對(duì)象分析)(Information Flow Analysis)
主要靜態(tài)分析是LDRA Testbed測(cè)試系統(tǒng)的核心模塊,所有要求進(jìn)行LDRA Testbed測(cè)試分析的軟件必須首先執(zhí)行主要靜態(tài)分析。分析源代碼,重新格式化源文件的副本方便后續(xù)進(jìn)一步的分析,在分析運(yùn)行期間會(huì)搜索違反編碼標(biāo)準(zhǔn)的源代碼并確定當(dāng)前存在的所有LCSAJs。主要靜態(tài)分析最終會(huì)映射源代碼的結(jié)構(gòu)以生成靜態(tài)調(diào)用圖。LDRA Testbed將通過(guò)Log窗口記錄正在執(zhí)行的主要靜態(tài)分析的哪個(gè)階段,當(dāng)主要靜態(tài)分析完成后,才可以繼續(xù)復(fù)雜度分析和動(dòng)態(tài)覆蓋率分析。
主要靜態(tài)分析完成以下目標(biāo):
1)基于源代碼(C/C++)的語(yǔ)法分析和宏擴(kuò)展;
2)解析源代碼,生成參考列表;
3)計(jì)算控制流分支;
4)驗(yàn)證編碼標(biāo)準(zhǔn);
5)C++面向?qū)ο蟮亩攘浚?/p>
6)注釋分析報(bào)告(Ada,C/C++和Cobol);
7)計(jì)算Halstead度量(C/C++,Cobol和PL/Mx86);
8)運(yùn)行線性代碼序列和跳轉(zhuǎn)(LCSAJ)。
主要靜態(tài)分析生成以下結(jié)果或圖表:
1)分析范圍報(bào)告;
2)LCSAJ報(bào)告;
3)代碼審查報(bào)告;
4)質(zhì)量審查報(bào)告。
在Main Static Analysis 前的確認(rèn)框中打勾,然后點(diǎn)擊Start Analysis 來(lái)開始分析。主要靜態(tài)分析對(duì)源代碼系統(tǒng)生成相應(yīng)的source_file_name.man文件,該文件提供了LDRA Testbed測(cè)試分析的管理概述,一旦信息可用它就會(huì)用各分析模塊的結(jié)果進(jìn)行更新。編碼規(guī)則的違反情況、注釋的使用和Halsteads度量(只針對(duì)C/C++和 Cobol)這些信息只能在該文件中找到,這是構(gòu)成質(zhì)量評(píng)價(jià)報(bào)告的主要部分。在主要靜態(tài)分析完成后點(diǎn)擊System Results 菜單,選擇Test Manager Report(HTML)會(huì)打開測(cè)試管理報(bào)告。進(jìn)入報(bào)告中左列的各節(jié)點(diǎn)程序,會(huì)顯示導(dǎo)致程序失敗的具體標(biāo)準(zhǔn)細(xì)節(jié),其中違反的編程標(biāo)準(zhǔn)以紅色顯示。
從Individual Results 菜單選擇Reformatted Code,會(huì)顯示重新格式化的源代碼。主要靜態(tài)分析生成source_file_name.ref文件,該文件包含最終重新格式化的源代碼清單,這是所有LDRA Tsetbed測(cè)試報(bào)告和測(cè)試結(jié)果的基礎(chǔ)。重新格式化的源代碼按照LDRA的標(biāo)準(zhǔn)顯示分支結(jié)構(gòu),并標(biāo)記每一行代碼,這個(gè)代碼版本的生成是LDRA Tsetbed測(cè)試分析的第一步。Reformatted Code Report提供了跨系統(tǒng)進(jìn)行一致度量的能力,對(duì)于以宏擴(kuò)展的形式顯示源代碼特別有用。圖2為Reformatted Code Report(部分),其中T為可執(zhí)行代碼,F(xiàn)為不可執(zhí)行代碼,如變量聲明、注釋等。
圖2 Reformatted Code Report(部分)
從Individual Results 菜單選擇LCSAJ Report,會(huì)顯示代碼與其相關(guān)的LCSAJ定義。主要靜態(tài)分析生成source_file_name.lcj文件,該文件右側(cè)記錄LCSAJ密度,底部記錄關(guān)于LCSAJs當(dāng)前數(shù)量信息以及不可達(dá)性的總結(jié),其中可以通過(guò)查找字符串UNREACHABLE ****來(lái)定位不可達(dá)的代碼。圖3為L(zhǎng)CSAJ Report(部分)。
圖3 LCSAJ Report(部分)
提高代碼的一致性、可維護(hù)性和整體質(zhì)量的常用方法是根據(jù)行業(yè)或公司定義的標(biāo)準(zhǔn)評(píng)估代碼,以便快速識(shí)別和糾正缺陷。雖然通常是通過(guò)手動(dòng)的同行評(píng)審來(lái)實(shí)現(xiàn)的,但這個(gè)過(guò)程可能會(huì)經(jīng)歷長(zhǎng)時(shí)間歷程并消耗大量人力,尤其是在代碼規(guī)模巨大的民用機(jī)載軟件中。
LDRA Testbed支持客戶自定義標(biāo)準(zhǔn)來(lái)自動(dòng)執(zhí)行靜態(tài)分析和規(guī)則檢查,所以需要測(cè)試人員配置自定義編程標(biāo)準(zhǔn)cpppen.dat文件。
cpppen.dat文件的格式為1 1 0 1S Identical name in scope。第一列表示本條標(biāo)準(zhǔn)在cpppen.dat文件中出現(xiàn)的順序;第二列表示是否要被檢測(cè)到;第三列表示該標(biāo)準(zhǔn)值的限制范圍;第四列表示該標(biāo)準(zhǔn)的內(nèi)部定值;第五列的字母有如下含義:S表示靜態(tài)分析;C表示復(fù)雜度分析;D表示靜態(tài)數(shù)據(jù)流分析;I表示信息流分析;X表示交叉索引;Q表示代碼審查報(bào)告。后面即為該標(biāo)準(zhǔn)的描述。按照上述格式,測(cè)試人員可根據(jù)不同的測(cè)試對(duì)象,從行業(yè)標(biāo)準(zhǔn)的超集中篩選出所需的子集,然后逐行編寫與標(biāo)準(zhǔn)對(duì)應(yīng)的特定.dat文件以縮短靜態(tài)測(cè)試時(shí)間。
復(fù)雜度分析通常是主要靜態(tài)分析后的下一步,因?yàn)樗瞧渌o態(tài)分析部分(如數(shù)據(jù)流分析)的先決條件。復(fù)雜度分析報(bào)告源代碼的低層結(jié)構(gòu),通過(guò)Kiviat圖計(jì)算各種用來(lái)執(zhí)行程序復(fù)雜性標(biāo)準(zhǔn)的指標(biāo)。對(duì)于非C/C++代碼,復(fù)雜度分析是在逐個(gè)程序運(yùn)行的基礎(chǔ)上分析代碼,分析范圍是用戶可配置的。在分析運(yùn)行期間,LDRA Testbed將通過(guò)Log窗口記錄復(fù)雜度分析的哪個(gè)階段,當(dāng)復(fù)雜性分析完成后,才可以繼續(xù)靜態(tài)數(shù)據(jù)流分析和其他分析。
復(fù)雜度分析完成以下目標(biāo):
1)將源代碼分成基本塊為后續(xù)進(jìn)一步測(cè)試做準(zhǔn)備。
2)生成靜態(tài)數(shù)據(jù)流圖用以表示源代碼。
3)計(jì)算各種復(fù)雜性度量。
(1)控制流節(jié)點(diǎn)度量:節(jié)點(diǎn)度量對(duì)于程序結(jié)構(gòu)的順序高度敏感,它是程序復(fù)雜度的一個(gè)因素。節(jié)點(diǎn)分析度量了代碼中的混亂程度,因此代碼閱讀器需要進(jìn)行大量的“跳躍”操作。過(guò)多的節(jié)點(diǎn)可能意味著程序可以重新排序以提高可讀性和降低復(fù)雜性。
(2)圈復(fù)雜度:圈復(fù)雜度反映程序的決策結(jié)構(gòu)。對(duì)于任何給定模塊,建議圈復(fù)雜度不超過(guò)10。該值可用作模塊從重新設(shè)計(jì)中獲益的一個(gè)指標(biāo)。這是一種測(cè)量定向圖大小的方法。
(3)循環(huán)深度:循環(huán)深度也稱為區(qū)間分析,用于探究程序循環(huán)結(jié)構(gòu)。控制流循環(huán)的最大深度是影響代碼整體可讀性、復(fù)雜性和效率的一個(gè)因素。
(4)過(guò)程輸入和輸出計(jì)數(shù):該參數(shù)基于靜態(tài)調(diào)用圖并度量過(guò)程的調(diào)用。輸入計(jì)數(shù)是對(duì)任一程序的調(diào)用次數(shù),輸出計(jì)數(shù)包括return語(yǔ)句、程序出口或從一程序跳轉(zhuǎn)到其他程序的次數(shù)。該參數(shù)可從測(cè)試管理報(bào)告中獲得。
4)生成使用結(jié)構(gòu)化編程結(jié)構(gòu)的驗(yàn)證報(bào)告(SPV):LDRA Testbed使用結(jié)構(gòu)化編程驗(yàn)證作為第2種方法來(lái)決定程序的結(jié)構(gòu)是否合理。LDRA Testbed通過(guò)逐個(gè)模塊地將結(jié)構(gòu)化模板與基本塊的有向圖匹配來(lái)執(zhí)行SPV,結(jié)構(gòu)化模板(包括文件c/cppplt.dat)是可配置的,以適應(yīng)本地編譯環(huán)境。SPV包括基本圈復(fù)雜度、基本節(jié)點(diǎn)數(shù)2種度量指標(biāo)。
5)在測(cè)試管理中生成關(guān)于復(fù)雜度分析標(biāo)準(zhǔn)違反情況的報(bào)告。
在Complexity Analysis 前的確認(rèn)框中打勾,然后點(diǎn)擊Start Analysis 來(lái)開始分析。復(fù)雜度分析完成后,單擊System Results 菜單,選擇Text Results,選擇Quality Review Report(HTML)會(huì)打開質(zhì)量審查報(bào)告,該報(bào)告提供關(guān)于復(fù)雜度度量的深入信息。此外,代碼審查報(bào)告中會(huì)增加復(fù)雜度分析信息。
復(fù)雜度分析生成source_file_name.cmp文件,該文件顯示復(fù)雜度度量和源代碼的相關(guān)信息,文件的摘要處顯示基于過(guò)程的復(fù)雜度度量,這些度量包括:圈復(fù)雜度度量、基本塊、結(jié)點(diǎn)度量、過(guò)程的輸入/輸出、循環(huán)次數(shù)/嵌套深度和SPV。因此選擇Static Bar Charts可調(diào)出以下9中靜態(tài)柱狀圖:
1)可執(zhí)行的重新格式化行(Executable Reformatted Lines);
2)基本塊(Basic Blocks);
3)圈復(fù)雜度(Cyclomatic Complexity);
4)節(jié)點(diǎn)(Knots);
5)間隔分析(Order 1 Intervals);
6)基本圈復(fù)雜度(Essential Cyclomatic Complexity);
7)基本節(jié)點(diǎn)數(shù)(Essential Knots);
8)區(qū)間嵌套(Max.Interval Nesting);
9)系統(tǒng)總體復(fù)雜度(Total System Complexity)。
靜態(tài)數(shù)據(jù)流分析在源代碼中尋找各種類型異常使用的變量情況,生成以下類型的關(guān)于源代碼的信息以突出顯示所有可能的程序缺陷:
1)過(guò)程調(diào)用信息;
2)數(shù)據(jù)流異常信息;
3)程序接口分析;
4)數(shù)據(jù)流標(biāo)準(zhǔn)違反情況;
5)LDRA Testbed的插樁;
6)靜態(tài)數(shù)據(jù)流生成的警告。
復(fù)雜度分析完成后,LDRA Testbed 能夠在源代碼的所有使用數(shù)據(jù)項(xiàng)上生成交叉索引,提供關(guān)于所有數(shù)據(jù)項(xiàng)(全局變量、局部變量或參數(shù))的交叉引用信息,并說(shuō)明數(shù)據(jù)項(xiàng)的使用情況。在需要源代碼文檔時(shí)交叉索引尤為重要。
信息流分析是對(duì)程序變量相互依賴關(guān)系的研究,該方法最初是由Balzer在1969年于EXDAMS系統(tǒng)中發(fā)明的。信息流是一種基于路徑的分析技術(shù),利用圖論方法對(duì)單一出口圖進(jìn)行分析,不需要只是平面圖。任何具有多個(gè)入口或多個(gè)出口的圖能夠通過(guò)附加頭或追蹤節(jié)點(diǎn)的方法轉(zhuǎn)化為適當(dāng)形式。因此,這些小擴(kuò)展的分析適用于從任何源代碼程序得到的有向圖。
數(shù)據(jù)對(duì)象分析使用戶能夠從靜態(tài)數(shù)據(jù)流分析、交叉索引和信息流分析中過(guò)濾信息,從而創(chuàng)建關(guān)于特定變量的報(bào)告,這對(duì)于正確跟蹤基于變量和常量的日期非常重要,在測(cè)試中也非常實(shí)用。數(shù)據(jù)對(duì)象分析生成一個(gè)分析范圍內(nèi)的完整變量交叉索引,其中的變量都是滿足指定的篩選條件,在配置后報(bào)告包含一系列特定變量和狀態(tài)的表格。
靜態(tài)數(shù)據(jù)流、交叉索引、信息流和數(shù)據(jù)對(duì)象分析的操作和圖2中主要靜態(tài)分析的操作一致。靜態(tài)數(shù)據(jù)流分析生成source_file_name.dfl文件,該文件給出源代碼數(shù)據(jù)流的完整信息,包括過(guò)程調(diào)用、遞歸調(diào)用、使用全局變量作為參數(shù)調(diào)用、未使用的變量、數(shù)據(jù)流異常、過(guò)程接口和未聲明的變量7種信息。并且可通過(guò)搜索字符串“UR ANOMALIES”,“DECLARED BUT NEVER USED”和“***”等查找特定信息。在Data Flow Analysis Report檢查靜態(tài)數(shù)據(jù)流的詳細(xì)信息,該報(bào)告提供調(diào)用結(jié)構(gòu)、數(shù)據(jù)流異常以及過(guò)程接口的相關(guān)問(wèn)題。
交叉索引生成source_file_name.xrf文件,該文件生成所有變量用法的交叉引用,并指明變量用于局部、全局或是作為過(guò)程參數(shù)。由于該文件是基于過(guò)程逐漸累積并對(duì)過(guò)程中的每個(gè)變量逐個(gè)分析,通過(guò)Cross Reference Report查看交叉索引信息。
信息流分析生成source_file_name.inf文件,該文件包含源代碼中變量依賴關(guān)系的信息,并詳細(xì)說(shuō)明變量是否被定義,其他變量是否直接或間接影響它的取值。通過(guò)Information Flow Analysis Report查看信息流。
上述4種分析完成后,單擊System Results 菜單,選擇Text Results,選擇Data Object Analysis Report(HTML)會(huì)打開數(shù)據(jù)對(duì)象分析報(bào)告,除顯示交叉索引和靜態(tài)數(shù)據(jù)流分析信息外,還記錄變量間的復(fù)雜關(guān)系,該報(bào)告可以配置為僅記錄特定篩選過(guò)濾的變量詳情。
以民用機(jī)載軟件中某航電設(shè)備的自檢系統(tǒng)為測(cè)試對(duì)象,將8個(gè).cpp文件組成目標(biāo)測(cè)試系統(tǒng),完成LDRA Testbed靜態(tài)測(cè)試過(guò)程。以其中的CSelfTest.cpp為例,該源文件的細(xì)節(jié)在分析范圍報(bào)告中如圖4所示。由圖4可知CSelfTest.cpp的分析路徑,LDRA Testbed標(biāo)記的模塊號(hào)為40,以便于后續(xù)查看該文件在系統(tǒng)調(diào)用圖中的位置,分析時(shí)間戳,文件大小和是否可讀。
圖4 分析范圍報(bào)告中的CSelfTest.cpp信息
測(cè)試管理報(bào)告(Test Manager Report)如圖5所示,該報(bào)告顯示代碼審查和質(zhì)量審查的總覽,顯示目標(biāo)系統(tǒng)違反編碼規(guī)則的情況,從可測(cè)試性、可維護(hù)性和清晰性三方面顯示出目標(biāo)系統(tǒng)的質(zhì)量情況。由圖5可知,CSelfTest.cpp違反編碼規(guī)則的占比為30%,可測(cè)試性為47%,可維護(hù)性為55%,清晰性為71%,該文件還有很大提高質(zhì)量的空間。
圖5 測(cè)試管理報(bào)告
代碼審查報(bào)告(Code Review Report)提供目標(biāo)系統(tǒng)代碼質(zhì)量的即時(shí)圖,該報(bào)告反映整個(gè)系統(tǒng)中每個(gè)文件的代碼質(zhì)量,以CSelfTest.cpp為例,定位到CSelfTest::init中,可以獲得違規(guī)代碼行的位置,例如534行違反MISRA 76,如圖6所示。
圖6 CSelfTest.cpp中CSelfTest::init代碼審查詳情(部分)
復(fù)雜度度量:如圖7所示,復(fù)雜度分析完成后在質(zhì)量審查報(bào)告中生成復(fù)雜度度量:包括節(jié)點(diǎn)數(shù)、圈復(fù)雜度、基本節(jié)點(diǎn)數(shù)、基本圈復(fù)雜度和SPV判斷。最后一行可得CSelfTest.cpp的節(jié)點(diǎn)數(shù)是197,圈復(fù)雜度是319,基本節(jié)點(diǎn)數(shù)是16,基本圈復(fù)雜度是9,SPV判斷為No。說(shuō)明該文件
圖7 CSelfTest.cpp的復(fù)雜度信息
的結(jié)構(gòu)不合理,圈復(fù)雜度過(guò)高,應(yīng)考慮重構(gòu)部分代碼區(qū)域以簡(jiǎn)化代碼結(jié)構(gòu),增強(qiáng)可測(cè)試性。
本文以民用機(jī)載軟件為測(cè)試對(duì)象,從靜態(tài)測(cè)試的概念和方法出發(fā),闡述LDRA Testbed在航空軟件領(lǐng)域的測(cè)試優(yōu)勢(shì),深入探究其進(jìn)行靜態(tài)測(cè)試的原理和過(guò)程,并生成代碼審查和質(zhì)量審查等報(bào)告。使用LDRA Testbed可完成主要靜態(tài)分析、復(fù)雜度分析、靜態(tài)數(shù)據(jù)流、交叉索引、信息流和數(shù)據(jù)對(duì)象分析六大部分的靜態(tài)分析,減少代碼違反編碼標(biāo)準(zhǔn)的數(shù)量,使軟件人員易于重構(gòu)代碼以降低復(fù)雜度,增強(qiáng)軟件的可靠性和健壯性,從而在靜態(tài)測(cè)試層面上提高民用機(jī)載軟件質(zhì)量。