專利名稱:測(cè)試多線程軟件并發(fā)沖突的方法
技術(shù)領(lǐng)域:
本發(fā)明涉及軟件測(cè)試領(lǐng)域,尤其涉及一種測(cè)試多線程軟件并發(fā)沖突的方法。
背景技術(shù):
目前大量的應(yīng)用軟件采用多線程技術(shù),這樣的應(yīng)用程序可以更好地利用系統(tǒng)資源。多線程技術(shù)的主要優(yōu)勢(shì)在于充分利用了CPU(Central Process Unit,中央處理器)的空閑時(shí)間片,可以用盡可能少的時(shí)間來(lái)對(duì)用戶的要求做出響應(yīng),使得軟件的整體運(yùn)行效率得到較大提高,同時(shí)增強(qiáng)了應(yīng)用軟件的靈活性。
但是,多線程技術(shù)在增強(qiáng)軟件功能的同時(shí)也帶來(lái)了設(shè)計(jì)和測(cè)試上的復(fù)雜性。由于多線程軟件中API(Application Program Interface,應(yīng)用程序接口)函數(shù)的實(shí)現(xiàn)體會(huì)對(duì)共享數(shù)據(jù)進(jìn)行互斥保護(hù),當(dāng)彼此的互斥保護(hù)邏輯出現(xiàn)錯(cuò)誤時(shí)就會(huì)產(chǎn)生并發(fā)沖突。因此,應(yīng)用多線程技術(shù)的軟件通??偸钱?dāng)程序同時(shí)調(diào)用API接口時(shí),發(fā)生并發(fā)沖突。在測(cè)試中,因?yàn)槎嗑€程并發(fā)沖突造成的錯(cuò)誤,從表象上看,基本上都是無(wú)規(guī)律的重現(xiàn),而且難以定位。
現(xiàn)有技術(shù)中,對(duì)應(yīng)用軟件進(jìn)行測(cè)試的常用方法是長(zhǎng)時(shí)間的壓力測(cè)試,以促使多線程并發(fā)沖突出現(xiàn)。而針對(duì)API接口進(jìn)行的測(cè)試,主要是通過(guò)啟動(dòng)多個(gè)測(cè)試線程頻繁調(diào)用可能出現(xiàn)并發(fā)沖突的API接口,來(lái)發(fā)現(xiàn)并發(fā)沖突問(wèn)題。
現(xiàn)有的測(cè)試方法無(wú)法主動(dòng)制造最有可能出現(xiàn)多線程并發(fā)沖突的環(huán)境,可能出現(xiàn)并發(fā)沖突的API接口在各個(gè)線程中的調(diào)用時(shí)機(jī)是不可預(yù)測(cè)的,只能在操作系統(tǒng)對(duì)多線程進(jìn)行調(diào)度時(shí)恰巧出現(xiàn)同時(shí)調(diào)用API接口時(shí)才有可能對(duì)并發(fā)沖突問(wèn)題進(jìn)行測(cè)試,而何時(shí)出現(xiàn)這種機(jī)會(huì)是測(cè)試人員和測(cè)試工具無(wú)法控制的。這樣的測(cè)試方法相當(dāng)?shù)拿つ浚瑴y(cè)試效率很低,測(cè)試質(zhì)量無(wú)法保證。
發(fā)明內(nèi)容
本發(fā)明要解決的技術(shù)問(wèn)題是現(xiàn)有技術(shù)無(wú)法控制對(duì)API接口的同時(shí)調(diào)用。
本發(fā)明所述測(cè)試多線程軟件并發(fā)沖突的方法包括以下步驟a)在測(cè)試邏輯中調(diào)用待測(cè)試的應(yīng)用程序接口前插入同步申請(qǐng)點(diǎn);b)開(kāi)始運(yùn)行至少兩個(gè)測(cè)試線程,所述測(cè)試線程中執(zhí)行所述測(cè)試邏輯;c)所述測(cè)試線程運(yùn)行到同步申請(qǐng)點(diǎn)時(shí),發(fā)出同步申請(qǐng);d)判斷是否接受所述測(cè)試線程的同步申請(qǐng),如果否,繼續(xù)執(zhí)行所述發(fā)出同步申請(qǐng)的測(cè)試線程;如果是,執(zhí)行步驟e);e)判斷是否當(dāng)前運(yùn)行的除所述發(fā)出同步申請(qǐng)的測(cè)試線程外的其他測(cè)試線程都處于等待狀態(tài),如果否,將所述發(fā)出同步申請(qǐng)的測(cè)試線程置于等待狀態(tài);如果是,則所有的所述測(cè)試線程繼續(xù)執(zhí)行;f)進(jìn)行所述測(cè)試線程的并發(fā)沖突測(cè)試。
優(yōu)選地,所述步驟e)與步驟f)之間包括所述發(fā)出同步申請(qǐng)的線程提示操作系統(tǒng)進(jìn)行線程切換。
優(yōu)選地,所述步驟a)與步驟b)之間包括設(shè)置運(yùn)行線程記錄,在運(yùn)行線程記錄中存儲(chǔ)當(dāng)前正在運(yùn)行的測(cè)試線程的線程標(biāo)識(shí);所述步驟b)與步驟c)之間包括bc1)在運(yùn)行線程記錄中增加所述測(cè)試線程。
優(yōu)選地,所述步驟bc1)之后包括bc2)所述測(cè)試線程準(zhǔn)備測(cè)試環(huán)境;bc3)所述測(cè)試線程開(kāi)始執(zhí)行其測(cè)試邏輯;所述步驟f)之后還包括
g)當(dāng)所述測(cè)試線程執(zhí)行完其測(cè)試邏輯后,恢復(fù)測(cè)試環(huán)境。
優(yōu)選地,所述步驟g)之后還包括h)判斷是否接到該測(cè)試線程的退出指令,如果是,執(zhí)行步驟i);如果否,轉(zhuǎn)步驟bc2);i)從運(yùn)行線程記錄中刪除該測(cè)試線程;判斷是否當(dāng)前運(yùn)行中的其他所述測(cè)試線程都處于等待狀態(tài),如果是,令其他所述測(cè)試線程繼續(xù)執(zhí)行,該測(cè)試線程退出;如果否,則該測(cè)試線程退出。
優(yōu)選地,在所述測(cè)試線程第一次執(zhí)行所述測(cè)試邏輯時(shí)統(tǒng)計(jì)所述測(cè)試邏輯中同步申請(qǐng)點(diǎn)的數(shù)量。
優(yōu)選地,所述步驟a)與步驟b)之間還包括建立所調(diào)用的應(yīng)用程序接口與所述同步申請(qǐng)之間的對(duì)應(yīng)關(guān)系。
優(yōu)選地,所述測(cè)試線程執(zhí)行相同的測(cè)試邏輯,所述測(cè)試邏輯中調(diào)用所有待測(cè)試的應(yīng)用程序接口。
優(yōu)選地,步驟d)所述判斷是否接受同步申請(qǐng)的條件為相同同步申請(qǐng)的數(shù)量不超過(guò)(m-1)除以n所得的整數(shù)部分時(shí),接受所述同步申請(qǐng);其中m為正在運(yùn)行的所述測(cè)試線程的總數(shù),n為當(dāng)前統(tǒng)計(jì)所得的所有所述測(cè)試邏輯中同步申請(qǐng)點(diǎn)數(shù)量的最大值。
優(yōu)選地,不同的所述測(cè)試邏輯中調(diào)用不同的待測(cè)試應(yīng)用程序接口;步驟d)所述判斷是否接受同步申請(qǐng)的條件為接受所有的同步申請(qǐng)。
本發(fā)明通過(guò)在測(cè)試邏輯中調(diào)用API接口前進(jìn)行同步申請(qǐng),使各個(gè)線程中的API接口被同時(shí)調(diào)用,從而對(duì)有針對(duì)性地對(duì)多線程并發(fā)沖突進(jìn)行測(cè)試,有效縮短了并發(fā)測(cè)試的周期,對(duì)提高并發(fā)測(cè)試效率和測(cè)試質(zhì)量有顯著的效果。
圖1所示為應(yīng)用本發(fā)明所述方法的兩個(gè)測(cè)試線程的測(cè)試邏輯示意圖;
圖2所示為本發(fā)明所述測(cè)試方法的流程圖;圖3所示為本發(fā)明中測(cè)試線程的運(yùn)行流程圖;圖4所示為本發(fā)明第一個(gè)實(shí)施例的測(cè)試線程及測(cè)試邏輯示意圖;圖5所示為本發(fā)明第二個(gè)實(shí)施例的測(cè)試線程及測(cè)試邏輯示意圖;圖6所示為應(yīng)用本發(fā)明的測(cè)試程序的結(jié)構(gòu)圖;圖7所示為圖6中測(cè)試程序中線程類Thread中Svc()函數(shù)的流程圖。
具體實(shí)施例方式
以下以啟動(dòng)兩個(gè)測(cè)試線程的測(cè)試程序?yàn)槔?,說(shuō)明本發(fā)明的測(cè)試邏輯。
圖1所示為應(yīng)用本發(fā)明所述方法的兩個(gè)測(cè)試線程的測(cè)試邏輯。第1個(gè)測(cè)試線程中要對(duì)第1個(gè)API接口、第2個(gè)API接口進(jìn)行調(diào)用,第2個(gè)測(cè)試線程中要對(duì)第3個(gè)API接口、第4個(gè)API接口進(jìn)行調(diào)用。假設(shè)需要對(duì)每一個(gè)API接口調(diào)用進(jìn)行并發(fā)沖突測(cè)試,則在上述4個(gè)對(duì)API接口的調(diào)用前插入同步申請(qǐng)點(diǎn)。
當(dāng)各個(gè)測(cè)試線程執(zhí)行到同步申請(qǐng)點(diǎn)時(shí),會(huì)向測(cè)試程序發(fā)出同步申請(qǐng)。例如,測(cè)試程序在接受第1個(gè)測(cè)試線程的同步申請(qǐng)后,令第1個(gè)測(cè)試線程處于等待狀態(tài),直到接受第2個(gè)測(cè)試線程發(fā)出的同步申請(qǐng)后,再同時(shí)喚醒兩個(gè)測(cè)試線程,令其繼續(xù)執(zhí)行。由于同步申請(qǐng)點(diǎn)后每個(gè)測(cè)試線程都調(diào)用對(duì)應(yīng)的API接口,這樣通過(guò)同步申請(qǐng)點(diǎn),測(cè)試程序即可實(shí)現(xiàn)兩個(gè)測(cè)試線程對(duì)兩個(gè)API接口的同時(shí)調(diào)用,在本文中稱之為一次同步。從理論上講,每個(gè)測(cè)試線程在被喚醒之后的API接口調(diào)用是最有可能同步執(zhí)行的,特別是在多CPU的機(jī)器上。這樣每次同步都可以制造并發(fā)沖突的機(jī)會(huì)。
在測(cè)試程序中,可以啟動(dòng)更多的測(cè)試線程,每個(gè)測(cè)試線程中執(zhí)行的測(cè)試邏輯可以相同,也可以不同。
同時(shí),測(cè)試程序接受測(cè)試線程同步申請(qǐng)的條件可以根據(jù)測(cè)試的具體內(nèi)容設(shè)置。在最簡(jiǎn)單的實(shí)施例中,可以設(shè)置為接受所有的同步申請(qǐng)。還可以建立所調(diào)用的API接口與發(fā)出同步申請(qǐng)的對(duì)應(yīng)關(guān)系,例如令圖1中的第1個(gè)測(cè)試線程在調(diào)用第2個(gè)API接口前發(fā)出的同步申請(qǐng)中包括此同步申請(qǐng)為第2個(gè)同步申請(qǐng)的信息,則測(cè)試程序可以區(qū)分出每個(gè)同步申請(qǐng)后調(diào)用的是哪個(gè)API接口,這樣如果只想對(duì)不同API接口的并發(fā)沖突進(jìn)行測(cè)試,可設(shè)置接受同步申請(qǐng)的條件為該同步申請(qǐng)與本次同步過(guò)程中其他測(cè)試線程已被接受的同步申請(qǐng)不同,換言之,該測(cè)試線程同步申請(qǐng)后所調(diào)用的API接口,與其他處于等待狀態(tài)的測(cè)試線程即將調(diào)用的API接口不同;若只希望測(cè)試相同API接口的并發(fā)沖突,則可設(shè)置接受同步申請(qǐng)的條件為該同步申請(qǐng)與本次同步過(guò)程中其他測(cè)試線程已被接受的同步申請(qǐng)相同。
圖2所示為本發(fā)明所述測(cè)試方法的流程圖。
在步驟S210,在測(cè)試邏輯中待測(cè)試的API接口前插入同步申請(qǐng)點(diǎn);在步驟S220,測(cè)試程序啟動(dòng)至少兩個(gè)執(zhí)行所述測(cè)試邏輯的測(cè)試線程;在步驟S230,測(cè)試線程執(zhí)行到同步申請(qǐng)點(diǎn)時(shí),向測(cè)試程序發(fā)出同步申請(qǐng);在步驟S240,測(cè)試程序根據(jù)設(shè)定的條件判斷是否接受該測(cè)試線程的同步申請(qǐng);如果接受,執(zhí)行步驟S250;如果不接受,執(zhí)行步驟S260,該發(fā)出同步申請(qǐng)的測(cè)試線程繼續(xù)執(zhí)行;在步驟S260,測(cè)試程序判斷是否當(dāng)前運(yùn)行中的除所述發(fā)出同步申請(qǐng)的線程外的其他測(cè)試線程都處于等待狀態(tài),如果否,則執(zhí)行步驟S270,將該發(fā)出同步申請(qǐng)的測(cè)試線程置于等待狀態(tài);如果是,則執(zhí)行步驟S280;在步驟S280,喚醒所有處于等待狀態(tài)的測(cè)試線程繼續(xù)執(zhí)行,同時(shí)令該發(fā)出同步申請(qǐng)的線程也繼續(xù)執(zhí)行;在步驟S290,該發(fā)出同步申請(qǐng)的線程提示操作系統(tǒng)進(jìn)行線程切換。
在操作系統(tǒng)中,由線程調(diào)度器給每個(gè)線程分配CPU時(shí)間片,只有獲取到CPU時(shí)間片的線程才處于運(yùn)行狀態(tài),否則處于掛起狀態(tài)。
在步驟S280中喚醒所有處于等待狀態(tài)的測(cè)試線程時(shí),該發(fā)出同步申請(qǐng)的測(cè)試線程正處于運(yùn)行狀態(tài),此時(shí)在大多數(shù)情況下當(dāng)前正在運(yùn)行的測(cè)試線程比其他被喚醒的測(cè)試線程更有可能占用CPU。而由于不同操作系統(tǒng)對(duì)線程切換的實(shí)現(xiàn)方式有所不同,在一些操作系統(tǒng)中如果當(dāng)前正在運(yùn)行的線程不主動(dòng)提示操作系統(tǒng)進(jìn)行線程切換,則當(dāng)前正在運(yùn)行的線程會(huì)一直占用較多的CPU時(shí)間片,導(dǎo)致其他線程獲得運(yùn)行的機(jī)會(huì)減少。
在本發(fā)明中每次同步后,理想的情況是所有測(cè)試線程處于平等的并發(fā)競(jìng)爭(zhēng)狀態(tài)。因此,執(zhí)行步驟S290,由發(fā)出同步申請(qǐng)的測(cè)試線程提示操作系統(tǒng),該發(fā)出同步申請(qǐng)的測(cè)試線程不需要繼續(xù)占用CPU,這樣線程調(diào)度器可以選擇另一個(gè)線程來(lái)運(yùn)行,但線程調(diào)度器也有可能會(huì)忽略這一提示,繼續(xù)運(yùn)行發(fā)出同步申請(qǐng)的測(cè)試線程。當(dāng)將測(cè)試線程從同步等待狀態(tài)被喚醒后,執(zhí)行這個(gè)操作,能夠確保在此時(shí)間點(diǎn)出現(xiàn)線程切換操作,從而更好地讓所有的測(cè)試線程處于一個(gè)并發(fā)競(jìng)爭(zhēng)的狀態(tài)。
可以令每個(gè)測(cè)試線程在啟動(dòng)后循環(huán)執(zhí)行測(cè)試邏輯,直到接到測(cè)試人員或測(cè)試程序發(fā)出的退出指令。同時(shí),為了方便測(cè)試人員對(duì)測(cè)試程序中正在運(yùn)行中的測(cè)試線程隨時(shí)進(jìn)行調(diào)整,本發(fā)明允許測(cè)試人員在測(cè)試進(jìn)行中啟動(dòng)新的測(cè)試線程、刪除已啟動(dòng)的測(cè)試線程。這需要測(cè)試程序維護(hù)一個(gè)運(yùn)行線程記錄,用來(lái)記錄當(dāng)前運(yùn)行中的所有測(cè)試線程的線程標(biāo)識(shí),還可以記錄運(yùn)行中的測(cè)試線程的總數(shù),運(yùn)行線程記錄應(yīng)在測(cè)試線程啟動(dòng)前設(shè)置。測(cè)試程序可以根據(jù)運(yùn)行線程記錄進(jìn)行步驟S260和步驟S370。
圖3所示為每個(gè)測(cè)試線程的運(yùn)行流程圖。測(cè)試線程啟動(dòng)后,進(jìn)入步驟S310,在運(yùn)行線程記錄中增加本測(cè)試線程。
在步驟S320,準(zhǔn)備測(cè)試線程運(yùn)行的測(cè)試環(huán)境。
在步驟S330,執(zhí)行測(cè)試線程的測(cè)試邏輯。測(cè)試線程的同步申請(qǐng)、進(jìn)入等待狀態(tài)、從等待狀態(tài)被喚醒都是在測(cè)試邏輯的執(zhí)行過(guò)程中完成。
在步驟S340,在本輪測(cè)試邏輯執(zhí)行完畢后,將測(cè)試環(huán)境恢復(fù)到步驟S320之前的狀態(tài)。
步驟S320與步驟S340中準(zhǔn)備測(cè)試環(huán)境和恢復(fù)測(cè)試環(huán)境的實(shí)現(xiàn)方法與現(xiàn)有技術(shù)相同,此處不再贅述。
在步驟S350,判斷是否接到本測(cè)試線程的退出指令,如果否,轉(zhuǎn)步驟S320,開(kāi)始下一輪測(cè)試邏輯的執(zhí)行過(guò)程;如果是,繼續(xù)步驟S360。
在步驟S360,從運(yùn)行線程記錄中刪除本測(cè)試線程。同時(shí),如果運(yùn)行線程記錄中包括運(yùn)行中測(cè)試線程的總數(shù),測(cè)試程序會(huì)將該總數(shù)減一。
在步驟S370,判斷是否當(dāng)前運(yùn)行中的其他測(cè)試線程都處于等待狀態(tài),如果是,執(zhí)行步驟S380,令其他測(cè)試線程繼續(xù)執(zhí)行,而本測(cè)試線程退出;如果否,則本測(cè)試線程退出。在一個(gè)測(cè)試線程退出時(shí),有可能出現(xiàn)當(dāng)時(shí)其他測(cè)試線程已經(jīng)在等待著本測(cè)試線程的同步申請(qǐng)成功,而本測(cè)試線程不再執(zhí)行下一輪測(cè)試邏輯,也不會(huì)再發(fā)出同步申請(qǐng),這樣由于測(cè)試程序認(rèn)為尚未達(dá)到所有測(cè)試線程的同步,其他測(cè)試線程將始終處于等待狀態(tài)。步驟S370就是為了防止這種情況的發(fā)生。
在一個(gè)應(yīng)用軟件中,具體有哪些API接口可能存在并發(fā)沖突錯(cuò)誤,很難通過(guò)事先分析得出結(jié)論。因此,在實(shí)踐中比較可行的方法是假定盡量多的API接口存在并發(fā)沖突錯(cuò)誤。如果能夠?qū)?yīng)用軟件中提供的所有API接口都進(jìn)行同步調(diào)用測(cè)試,那么就可以保證測(cè)試的覆蓋率。
在實(shí)踐中通常采用兩種不同的測(cè)試設(shè)計(jì),第一種是在一個(gè)測(cè)試邏輯中完成對(duì)所有API接口的調(diào)用,啟動(dòng)多個(gè)這樣的測(cè)試線程執(zhí)行同一個(gè)測(cè)試邏輯;第二種是不同的API接口在不同的測(cè)試邏輯中調(diào)用,每個(gè)測(cè)試邏輯都在不同的測(cè)試線程中執(zhí)行。以下以這兩種測(cè)試設(shè)計(jì)作為本發(fā)明的第一個(gè)和第二個(gè)實(shí)施例,詳細(xì)進(jìn)行說(shuō)明。
圖4所示為本發(fā)明第一個(gè)實(shí)施例的測(cè)試線程及測(cè)試邏輯的示意圖。啟動(dòng)的測(cè)試線程數(shù)量為m(應(yīng)滿足m≥2),每個(gè)測(cè)試線程執(zhí)行相同的測(cè)試邏輯,在測(cè)試邏輯中依次調(diào)用第1個(gè)至第n個(gè)API接口,即測(cè)試邏輯中的同步申請(qǐng)點(diǎn)的數(shù)量為n。
啟動(dòng)的測(cè)試線程數(shù)量決定了每次同步后會(huì)同時(shí)調(diào)用的API接口的數(shù)量。本實(shí)施例中,啟動(dòng)的測(cè)試線程數(shù)量為m,則每次同步后對(duì)m個(gè)API接口的并發(fā)沖突進(jìn)行測(cè)試。在本實(shí)施例中優(yōu)先測(cè)試不同API接口之間的并發(fā)沖突,具體而言是以下述方式進(jìn)行測(cè)試當(dāng)m<n時(shí),對(duì)部分不同的API接口之間的并發(fā)沖突進(jìn)行測(cè)試,這種測(cè)試是不完整的;當(dāng)m=n時(shí),測(cè)試所有API接口同時(shí)調(diào)用時(shí)是否會(huì)出現(xiàn)并發(fā)沖突。這種情況下,對(duì)相同API接口同時(shí)調(diào)用的并發(fā)沖突沒(méi)有進(jìn)行測(cè)試;當(dāng)n<m<2n時(shí),每次同步后測(cè)試所有不同API接口之間的并發(fā)沖突和部分相同API接口之間的并發(fā)沖突,同時(shí)要滿足相同API接口的數(shù)量不超過(guò)2個(gè),換言之,如果將m個(gè)API接口中相同的接口作為一組,則每組的數(shù)量不超過(guò)2個(gè);如果m≥2n,每次同步后測(cè)試所有不同API接口之間的并發(fā)沖突,和所有API接口與相同接口之間的并發(fā)沖突,同時(shí)要滿足相同API接口的數(shù)量不超過(guò)k個(gè),換言之,如果將m個(gè)API接口中相同的接口作為一組,則每組的數(shù)量不超過(guò)k個(gè);其中k等于(m-1)除以n所得的整數(shù)部分加1。在這種情況下,測(cè)試覆蓋是最全面的。
要實(shí)現(xiàn)上述測(cè)試方式,需要在本發(fā)明所述測(cè)試方法的基礎(chǔ)上增加一些工作在測(cè)試邏輯設(shè)置同步申請(qǐng)點(diǎn)時(shí),應(yīng)當(dāng)建立每個(gè)同步申請(qǐng)與所調(diào)用的API接口的對(duì)應(yīng)關(guān)系,使測(cè)試邏輯在執(zhí)行到該同步申請(qǐng)點(diǎn)發(fā)出同步申請(qǐng)時(shí),測(cè)試程序能夠區(qū)分不同測(cè)試線程同步申請(qǐng)后調(diào)用的API接口是否相同;
將接受同步申請(qǐng)的條件設(shè)置為本次同步已被接受的同步申請(qǐng)中與該同步申請(qǐng)相同的個(gè)數(shù),不超過(guò)(m-1)除以n所得的整數(shù)部分,其中m為當(dāng)前運(yùn)行的測(cè)試線程的個(gè)數(shù);n為當(dāng)前測(cè)試邏輯中測(cè)試申請(qǐng)點(diǎn)的數(shù)量。
同時(shí),為了便于修改測(cè)試邏輯,可以對(duì)測(cè)試邏輯中的同步申請(qǐng)點(diǎn)進(jìn)行自動(dòng)計(jì)數(shù),例如在開(kāi)始執(zhí)行一輪測(cè)試邏輯時(shí)置計(jì)數(shù)器為0值,每進(jìn)行一次同步申請(qǐng)計(jì)數(shù)器的值加1,到本輪測(cè)試邏輯執(zhí)行完畢時(shí)計(jì)數(shù)器的值即為測(cè)試邏輯中同步申請(qǐng)點(diǎn)的個(gè)數(shù)。
圖5所示為本發(fā)明第二個(gè)實(shí)施例的測(cè)試線程及測(cè)試邏輯的示意圖。第二個(gè)實(shí)施例中,不同的API接口在不同的測(cè)試邏輯中調(diào)用。請(qǐng)參見(jiàn)圖5,第1個(gè)測(cè)試線程中調(diào)用了第11個(gè)API接口、第12個(gè)API接口至第1x個(gè)API接口,第2個(gè)測(cè)試線程中調(diào)用了第21個(gè)API接口、第22個(gè)API接口至第2y個(gè)API接口,第m個(gè)測(cè)試線程中調(diào)用了第m1個(gè)API接口、第m2個(gè)API接口至第mz個(gè)API接口。
在本實(shí)施例中,應(yīng)將接受同步申請(qǐng)的條件設(shè)置為接受所有的同步申請(qǐng)。
當(dāng)m個(gè)不同的測(cè)試線程執(zhí)行m個(gè)不同的測(cè)試邏輯時(shí),只有可能對(duì)每個(gè)測(cè)試線程中的API接口與其他測(cè)試線程中API接口之間的并發(fā)沖突進(jìn)行測(cè)試,而同一個(gè)測(cè)試邏輯中API接口之間的則不會(huì)有同時(shí)調(diào)用的機(jī)會(huì)。
由于每個(gè)測(cè)試邏輯中的API接口都不相同,因此只有當(dāng)至少兩個(gè)測(cè)試邏輯運(yùn)行相同的測(cè)試邏輯時(shí),相同的API接口才有可能被同時(shí)調(diào)用。也就是說(shuō),圖5中所示的m個(gè)測(cè)試邏輯中,要測(cè)試每個(gè)邏輯中相同的API接口之間的并發(fā)沖突問(wèn)題,必須至少啟動(dòng)2m個(gè)測(cè)試線程。
當(dāng)每個(gè)測(cè)試邏輯中進(jìn)行測(cè)試的API接口數(shù)量超過(guò)1個(gè)時(shí),本實(shí)施例對(duì)同時(shí)調(diào)用哪些API接口的控制不如第一實(shí)施例,因而本實(shí)施例的測(cè)試覆蓋率不如第一實(shí)施例。但是本實(shí)施例測(cè)試邏輯的實(shí)現(xiàn)因?yàn)橹簧婕暗捷^少數(shù)量的API接口,實(shí)現(xiàn)相對(duì)簡(jiǎn)單。
當(dāng)每個(gè)測(cè)試邏輯中只對(duì)一個(gè)API接口做測(cè)試,而至少啟動(dòng)兩個(gè)測(cè)試線程執(zhí)行同一個(gè)測(cè)試邏輯時(shí),本實(shí)施例的測(cè)試覆蓋率最終可以做到和第一實(shí)施例一樣的全面覆蓋。這種情況下,所要啟動(dòng)的測(cè)試線程數(shù)將隨著待測(cè)試的API接口數(shù)量的增加而線性增長(zhǎng)。
以下介紹本發(fā)明所述方法以及上述兩個(gè)實(shí)施例的一種具體的程序?qū)崿F(xiàn)方式。
如前所述,本發(fā)明中測(cè)試邏輯是在單獨(dú)的測(cè)試線程中執(zhí)行的。在實(shí)踐中,為了使測(cè)試程序能夠更方便地應(yīng)用于不同的測(cè)試邏輯和不同的測(cè)試線程,最好能夠解耦測(cè)試線程對(duì)象和測(cè)試邏輯。本發(fā)明提供的測(cè)試程序的結(jié)構(gòu)包括測(cè)試邏輯接口TestInterface、同步接口LockInterface、同步實(shí)現(xiàn)接口LockImplInterface,以及線程類Thread。
請(qǐng)參閱圖6,測(cè)試邏輯接口TestInterface用來(lái)完成測(cè)試邏輯的一次完整的執(zhí)行過(guò)程。其中,包括三個(gè)步驟,Setup()函數(shù)用來(lái)準(zhǔn)備測(cè)試環(huán)境;Test()函數(shù)用來(lái)執(zhí)行測(cè)試邏輯,在執(zhí)行過(guò)程中通過(guò)調(diào)用同步接口LockInterface來(lái)進(jìn)行同步;TearDown()函數(shù)用來(lái)恢復(fù)測(cè)試環(huán)境。
同步接口LockInterface用來(lái)進(jìn)行測(cè)試邏輯執(zhí)行過(guò)程中的同步,主要由Lock()函數(shù)實(shí)現(xiàn)void Lock(){if(ShouldWait()){ //本測(cè)試線程的同步申請(qǐng)是否被接受if(AllIsWaiting()){ //如果是,是否其他測(cè)試線程都處于等待狀態(tài)UnlockAll(); //如果是,令所有測(cè)試線程繼續(xù)執(zhí)行}else{WaitOthers(); //如果不是,則本測(cè)試線程轉(zhuǎn)入等待狀態(tài)}
yield()//提示線程調(diào)度器本測(cè)試線程不需要運(yùn)行}}其中,yield()函數(shù)完成提示操作系統(tǒng)進(jìn)行線程切換的功能。
在測(cè)試邏輯的執(zhí)行過(guò)程中,每執(zhí)行到同步申請(qǐng)點(diǎn)都要調(diào)用Lock()函數(shù),因而可以通過(guò)統(tǒng)計(jì)調(diào)用Lock()函數(shù)的次數(shù)統(tǒng)計(jì)同步申請(qǐng)點(diǎn)的數(shù)量。
同步實(shí)現(xiàn)接口LockImplInterface是同步接口LockInterface的一個(gè)子類,主要用來(lái)在測(cè)試邏輯接口TestInterface、測(cè)試線程類Thread之間傳遞信息,以實(shí)現(xiàn)自動(dòng)計(jì)算線程數(shù)量和每個(gè)測(cè)試邏輯的同步申請(qǐng)點(diǎn)的數(shù)量。同步實(shí)現(xiàn)接口LockImplInterface主要包括兩個(gè)函數(shù)Init()函數(shù)和Fini()函數(shù);測(cè)試線程在啟動(dòng)后即會(huì)調(diào)用Init()函數(shù),通知測(cè)試程序一個(gè)測(cè)試線程已經(jīng)啟動(dòng),測(cè)試程序可據(jù)此在運(yùn)行線程記錄中增加本測(cè)試線程;如果需要自動(dòng)統(tǒng)計(jì)測(cè)試邏輯中同步申請(qǐng)點(diǎn)的數(shù)量,可以在Init()函數(shù)中增加通知測(cè)試程序?qū)㈤_(kāi)始執(zhí)行一輪的測(cè)試邏輯的功能,這種情況下在每一次開(kāi)始執(zhí)行測(cè)試邏輯前,即調(diào)用測(cè)試邏輯接口TestInterface之前都要調(diào)用Init()函數(shù)。測(cè)試線程第二次及以后每次調(diào)用Init()函數(shù)都通知測(cè)試程序?qū)㈤_(kāi)始一輪的測(cè)試邏輯,測(cè)試程序可以將測(cè)試線程啟動(dòng)后,第一次和第二次調(diào)用Init()函數(shù)作為統(tǒng)計(jì)測(cè)試邏輯中同步申請(qǐng)點(diǎn)數(shù)量時(shí)的起止點(diǎn),同步申請(qǐng)點(diǎn)的數(shù)量即是在這一起止點(diǎn)之間該測(cè)試線程調(diào)用Lock()函數(shù)的次數(shù);測(cè)試線程在退出前執(zhí)行Fini()函數(shù),在Fini()函數(shù)中,會(huì)判斷是否當(dāng)前運(yùn)行中的其他測(cè)試線程都處于等待狀態(tài),如果是,令其他測(cè)試線程繼續(xù)執(zhí)行,以便本測(cè)試線程的退出不會(huì)妨礙其他測(cè)試線程中測(cè)試邏輯的實(shí)現(xiàn)。同時(shí),調(diào)用Fini()函數(shù)將通知測(cè)試程序本測(cè)試線程退出,測(cè)試程序據(jù)此在運(yùn)行線程記錄中刪除本測(cè)試線程。
線程類Thread的用來(lái)控制測(cè)試邏輯的重復(fù)運(yùn)行,并根據(jù)退出指令終止運(yùn)行,其主要功能由以下4個(gè)函數(shù)實(shí)現(xiàn)Thread(TestInterface&,LockInterface&)函數(shù)是一個(gè)構(gòu)造函數(shù),其含義為需要利用測(cè)試邏輯接口TestInterface和同步實(shí)現(xiàn)接口LockImplInterface這兩個(gè)類型的參數(shù)來(lái)生成線程類Thread的一個(gè)對(duì)象;測(cè)試人員或測(cè)試程序通過(guò)調(diào)用Terminate()函數(shù)來(lái)指令該測(cè)試線程退出。當(dāng)Terminate()函數(shù)被調(diào)用后,IsTerminate()函數(shù)即會(huì)返回True(邏輯真值),表示本測(cè)試線程被請(qǐng)求終止運(yùn)行;Terminate()函數(shù)的調(diào)用即是向該測(cè)試線程發(fā)出圖3的步驟S350中所述的退出指令;測(cè)試線程在一輪測(cè)試邏輯執(zhí)行完畢后會(huì)調(diào)用IsTerminate()函數(shù),看是否本測(cè)試線程被請(qǐng)求終止運(yùn)行,如果是,則在調(diào)用同步實(shí)現(xiàn)接口LockImplInterface的Fini()函數(shù)后退出運(yùn)行;測(cè)試線程調(diào)用IsTerminate()函數(shù)完成圖3中的步驟S350;Svc()函數(shù)通過(guò)調(diào)用上述的接口和函數(shù)實(shí)現(xiàn)一個(gè)測(cè)試線程的運(yùn)行過(guò)程。假設(shè)My-Test為測(cè)試程序中定義的測(cè)試邏輯接口TestInterface,My_Lock為測(cè)試程序中定義的同步實(shí)現(xiàn)接口LockImplInterface,則Svc()函數(shù)的流程如圖7所示在步驟S710,調(diào)用My_Lock.Init();在步驟S720,調(diào)用My_Test.Setup();在步驟S730,調(diào)用My_Test.Test();在步驟S740,調(diào)用My_Test.TearDown();在步驟S750,調(diào)用IsTerminated()函數(shù),當(dāng)IsTerminated()函數(shù)返回True時(shí),轉(zhuǎn)步驟S760;當(dāng)其返回False(非真值)時(shí),轉(zhuǎn)步驟S710,開(kāi)始下一輪測(cè)試邏輯的執(zhí)行;在步驟S760,調(diào)用My_Lock.Fini()函數(shù),之后該測(cè)試線程退出。
請(qǐng)?jiān)賲㈤唸D6,在上述各個(gè)接口和類的基礎(chǔ)上,具體測(cè)試邏輯通過(guò)繼承測(cè)試邏輯接口TestInterface來(lái)實(shí)現(xiàn);同步策略主要包括接受同步申請(qǐng)的條件,即對(duì)哪些API接口進(jìn)行并發(fā)沖突測(cè)試,將本發(fā)明的上述兩個(gè)實(shí)施例看作同步策略一和同步策略二,這兩種同步策略通過(guò)繼承同步實(shí)現(xiàn)接口LockImplInterface實(shí)現(xiàn),以下分別予以說(shuō)明。
本發(fā)明的第一實(shí)施例中,所有測(cè)試線程執(zhí)行相同的測(cè)試邏輯。由于允許測(cè)試人員或測(cè)試程序在測(cè)試過(guò)程中隨時(shí)增加和刪除測(cè)試線程,因此在第一實(shí)施例中必須對(duì)每個(gè)測(cè)試邏輯中同步申請(qǐng)點(diǎn)的數(shù)量進(jìn)行自動(dòng)統(tǒng)計(jì),統(tǒng)計(jì)方法如前所述。
實(shí)現(xiàn)第一實(shí)施例中的同步策略還需要設(shè)置接受同步申請(qǐng)的條件定義一個(gè)一維數(shù)組,該數(shù)組的變量個(gè)數(shù)N_Cnt由下式確定N_Cnt=Lock_Cnt+Lock_Cnt*((Thr_Cnt-1)/Lock_Cnt)上式中,Thr_Cnt為當(dāng)前運(yùn)行中的測(cè)試線程總數(shù),Lock_Cnt為當(dāng)前統(tǒng)計(jì)所得的每個(gè)測(cè)試線程中同步申請(qǐng)點(diǎn)數(shù)量的最大值,(Thr_Cnt-1)/Lock_Cnt為(Thr_Cnt-1)除以Lock_Cnt后所得的整數(shù)部分。當(dāng)Thr_Cnt≤Lock_Cnt時(shí),N_Cnt=Thr_Cnt;當(dāng)k*Lock_Cnt<Thr_Cnt≤(k+1)*Lock_Cnt時(shí)(k為大于等于1的整數(shù))時(shí),N_Cnt=(k+1)*Lock_Cnt。
上述數(shù)組用來(lái)記錄已被接受的同步申請(qǐng)。對(duì)數(shù)組元素的使用以Lock_Cnt為單位進(jìn)行,即該數(shù)組的第(k*Lock_Cnt+1)至第(k+1)*Lock_Cnt個(gè)元素為第k組。在每次同步后,將數(shù)組中的每個(gè)元素清零。請(qǐng)參閱圖4,當(dāng)接收到測(cè)試線程在同步申請(qǐng)點(diǎn)3發(fā)出的同步申請(qǐng)3時(shí),查詢數(shù)組中第1組的第3個(gè)元素是否為零,如果是,則接受該同步申請(qǐng)3,并將第1組的第3個(gè)元素置為1,表示本次同步已經(jīng)有一個(gè)測(cè)試線程將調(diào)用API接口3了。如果第1組中的第3個(gè)元素已經(jīng)置1了,則查詢是否本組其他元素是否都已經(jīng)置1了,如果本組中還有元素為零,則拒絕該同步申請(qǐng)3;如果本組中所有元素都已置1,則再以同樣的步驟查詢下一組。這樣,就可以實(shí)現(xiàn)對(duì)不同API接口并發(fā)沖突的優(yōu)先測(cè)試。
本發(fā)明的第二實(shí)施例實(shí)現(xiàn)起來(lái)更為簡(jiǎn)單方便。第二實(shí)施例中可以不對(duì)測(cè)試邏輯中同步申請(qǐng)點(diǎn)的數(shù)量進(jìn)行自動(dòng)計(jì)數(shù),而接受同步申請(qǐng)的條件只要設(shè)置為接受所有的同步申請(qǐng)即可。
實(shí)施本發(fā)明所述方法后,測(cè)試程序不再等待API接口碰巧出現(xiàn)的同時(shí)調(diào)用,而是主動(dòng)控制對(duì)API接口的并發(fā)調(diào)用。理論上,本發(fā)明可以實(shí)現(xiàn)所有API接口的并發(fā)沖突測(cè)試,但是由于線程的調(diào)用是由操作系統(tǒng)直接管理的,實(shí)際真正能夠并發(fā)調(diào)用的API接口則受到了硬件條件的限制。如果測(cè)試程序中進(jìn)行同步的測(cè)試線程數(shù)量很大,即使在多CPU的計(jì)算機(jī)上也很難實(shí)現(xiàn)同時(shí)調(diào)用所有的測(cè)試線程。因而即使在事實(shí)上,本發(fā)明所述方法也為應(yīng)用程序測(cè)試提供了所有API接口都能夠并發(fā)調(diào)用的機(jī)會(huì)。
以上所述的本發(fā)明實(shí)施方式,并不構(gòu)成對(duì)本發(fā)明保護(hù)范圍的限定。任何在本發(fā)明的精神和原則之內(nèi)所作的任何修改、等同替換和改進(jìn)等,均應(yīng)包含在本發(fā)明的權(quán)利要求保護(hù)范圍之內(nèi)。
權(quán)利要求
1.一種測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,包括以下步驟a)在測(cè)試邏輯中調(diào)用待測(cè)試的應(yīng)用程序接口前插入同步申請(qǐng)點(diǎn);b)開(kāi)始運(yùn)行至少兩個(gè)測(cè)試線程,所述測(cè)試線程中執(zhí)行所述測(cè)試邏輯;c)所述測(cè)試線程運(yùn)行到同步申請(qǐng)點(diǎn)時(shí),發(fā)出同步申請(qǐng);d)判斷是否接受所述測(cè)試線程的同步申請(qǐng),如果否,繼續(xù)執(zhí)行所述發(fā)出同步申請(qǐng)的測(cè)試線程;如果是,執(zhí)行步驟e);e)判斷是否當(dāng)前運(yùn)行的除所述發(fā)出同步申請(qǐng)的測(cè)試線程外的其他測(cè)試線程都處于等待狀態(tài),如果否,將所述發(fā)出同步申請(qǐng)的測(cè)試線程置于等待狀態(tài);如果是,則所有的所述測(cè)試線程繼續(xù)執(zhí)行;f)進(jìn)行所述測(cè)試線程的并發(fā)沖突測(cè)試。
2.按照權(quán)利要求1所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,所述步驟e)與步驟f)之間包括所述發(fā)出同步申請(qǐng)的線程提示操作系統(tǒng)進(jìn)行線程切換。
3.按照權(quán)利要求2所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,所述步驟a)與步驟b)之間包括設(shè)置運(yùn)行線程記錄,在運(yùn)行線程記錄中存儲(chǔ)當(dāng)前正在運(yùn)行的測(cè)試線程的線程標(biāo)識(shí);所述步驟b)與步驟c)之間包括bc1)在運(yùn)行線程記錄中增加所述測(cè)試線程。
4.按照權(quán)利要求3所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,所述步驟bc1)之后包括bc2)所述測(cè)試線程準(zhǔn)備測(cè)試環(huán)境;bc3)所述測(cè)試線程開(kāi)始執(zhí)行其測(cè)試邏輯;所述步驟f)之后還包括g)當(dāng)所述測(cè)試線程執(zhí)行完其測(cè)試邏輯后,恢復(fù)測(cè)試環(huán)境。
5.按照權(quán)利要求4所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,所述步驟g)之后還包括h)判斷是否接到該測(cè)試線程的退出指令,如果是,執(zhí)行步驟i);如果否,轉(zhuǎn)步驟bc2);i)從運(yùn)行線程記錄中刪除該測(cè)試線程;判斷是否當(dāng)前運(yùn)行中的其他所述測(cè)試線程都處于等待狀態(tài),如果是,令其他所述測(cè)試線程繼續(xù)執(zhí)行,該測(cè)試線程退出;如果否,則該測(cè)試線程退出。
6.按照權(quán)利要求5所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于在所述測(cè)試線程第一次執(zhí)行所述測(cè)試邏輯時(shí)統(tǒng)計(jì)所述測(cè)試邏輯中同步申請(qǐng)點(diǎn)的數(shù)量。
7.按照權(quán)利要求6所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于所述步驟a)與步驟b)之間還包括建立所調(diào)用的應(yīng)用程序接口與所述同步申請(qǐng)之間的對(duì)應(yīng)關(guān)系。
8.按照權(quán)利要求7所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于所述測(cè)試線程執(zhí)行相同的測(cè)試邏輯,所述測(cè)試邏輯中調(diào)用所有待測(cè)試的應(yīng)用程序接口。
9.按照權(quán)利要求8所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于,步驟d)所述判斷是否接受同步申請(qǐng)的條件為相同同步申請(qǐng)的數(shù)量不超過(guò)(m-1)除以n所得的整數(shù)部分時(shí),接受所述同步申請(qǐng);其中m為正在運(yùn)行的所述測(cè)試線程的總數(shù),n為當(dāng)前統(tǒng)計(jì)所得的所有所述測(cè)試邏輯中同步申請(qǐng)點(diǎn)數(shù)量的最大值。
10.按照權(quán)利要求5至7任意一項(xiàng)所述測(cè)試多線程軟件并發(fā)沖突的方法,其特征在于不同的所述測(cè)試邏輯中調(diào)用不同的待測(cè)試應(yīng)用程序接口;步驟d)所述判斷是否接受同步申請(qǐng)的條件為接受所有的同步申請(qǐng)。
全文摘要
本發(fā)明公開(kāi)了一種測(cè)試多線程軟件并發(fā)沖突的方法,包括以下步驟在測(cè)試邏輯中調(diào)用待測(cè)試的應(yīng)用程序接口前插入同步申請(qǐng)點(diǎn);開(kāi)始運(yùn)行至少兩個(gè)測(cè)試線程;所述測(cè)試線程運(yùn)行到同步申請(qǐng)點(diǎn)時(shí),發(fā)出同步申請(qǐng);判斷是否接受所述測(cè)試線程的同步申請(qǐng),如果否,繼續(xù)執(zhí)行所述發(fā)出同步申請(qǐng)的測(cè)試線程;如果是,則若其他測(cè)試線程并未都處于等待狀態(tài),將所述發(fā)出同步申請(qǐng)的測(cè)試線程置于等待狀態(tài);若當(dāng)前運(yùn)行中的其他測(cè)試線程都處于等待狀態(tài),則所有的所述測(cè)試線程繼續(xù)執(zhí)行;進(jìn)行所述測(cè)試線程的并發(fā)沖突測(cè)試。本發(fā)明有針對(duì)性地對(duì)多線程并發(fā)沖突進(jìn)行測(cè)試,有效縮短了并發(fā)測(cè)試的周期,對(duì)提高并發(fā)測(cè)試效率和測(cè)試質(zhì)量有顯著的效果。
文檔編號(hào)G06F9/46GK1855068SQ200510069009
公開(kāi)日2006年11月1日 申請(qǐng)日期2005年4月29日 優(yōu)先權(quán)日2005年4月29日
發(fā)明者韓霆軍 申請(qǐng)人:華為技術(shù)有限公司