天天看點

從精準化測試看ASM在Android中的強勢插入-讀懂diff

我們計算增量代碼覆寫率的基礎,就是要找出兩個版本代碼的差異,在Git環境下,我們可以很友善的通過Git腳本來擷取這些資料。

Git擷取diff資訊

git diff指令可以使用如下格式,用來對比不同commit(或分支)間的增量代碼:

git diff [<options>] <commit> <commit>
           

複制

其中commit可以是分支名,也可以是commit的id,對比分支間的差異,可以簡寫為 git diff targetBranchName,表示對比目前分支與目标分支間的代碼差異。

下面這張圖,就是通過git diff指令擷取的一段更新diff資訊,如下所示。

git diff HEAD~1 HEAD
           

複制

輸出如下:

從精準化測試看ASM在Android中的強勢插入-讀懂diff

image-20210621155525706

diff指令,一定會有兩個輸入,即A和B,圖中第一行,就标記了A和B檔案。

對于版本A,它的符号是一個減号(「-」);而對于版本B ,它會使用一個加号(「+」)。

圖中的第三四行,就是被标記的兩個檔案,針對這個标記,存在下面幾種情況。

  • diff檔案是新增檔案,則---後面是/dev/null
  • diff檔案被删除,則+++後面是/dev/null
  • diff發生修改,則---和+++後面都有檔案名

通過這個,就可以區分檔案狀态。

Chunk Header

git diff的每個修改,都會生成一個Chunk Header,對應圖中的「@@」和「@@」符号之間。

@@ -31,21 +31,25 @@
           

複制

這裡表示,從A版本的第31行開始,變更了21行,B版本從31行開始,變更了25行。

但是,我隻是加了4行log啊,這是什麼鬼??

其實git diff指令不僅僅會給出變更行,而且還會帶上前後預設3行的修改資訊,作為上下文,是以才會有這麼多的修改。

是以,我們需要再利用git的一個指令:

--unified=<n>,簡寫為-U<n>
           

複制

來指定上下文關聯的代碼行數,這裡設定為-U0,表示隻關心實際的變更。

加上這個參數後,輸出如下:

從精準化測試看ASM在Android中的強勢插入-讀懂diff

image-20210625145214250

加了這個參數後,Chunk Header同樣會有三種情況:

  • -/+号後面隻有一個數字,設為N,那麼表示增加(+)、删除(-)了1行,行号為N,例如+34,就是第34行,增加了1行。
  • -/+号後面有兩個數字,第1個數字設為N,且第二個數字為0,那麼表示第N行沒有變化,增加(+)、删除(-)了0行,這有啥意義呢?其實這就表示該内容是新增的。
  • -/+号後面有兩個數字,第1個數字設為N,第二個數字為M,那麼表示從N行開始,增加(+)、删除(-)了M行,這用于标記多行的修改。

那麼有了這樣一個認知後,就可以通過正則來檢出這些資料。

git diff HEAD~1 HEAD -U0 | ggrep -Po '^\+\+\+ ./\K.*|^@@ -[0-9]+(,[0-9]+)? \+\K[0-9]+(,[0-9]+)?(?= @@)'
           

複制

借助這樣一個正規表達式和grep,就可以從diff資訊中找出修改的檔案和行号,執行如下:

app/src/main/java/com/yw/qdcoverage/MainActivity.kt
34
40
46
52
           

複制

這裡要注意,Mac下grep是用的2.5.1-FreeBSD版本,是以不支援 -P指令,需要安裝GNU Grep,通過brew install grep來安裝即可,安裝好之後,通過ggrep來調用GNU Grep(如果是Linux的話,那麼可以直接使用grep)。

如果在腳本中,可以借助正規表達式來擷取。

Pattern.compile("^@@ -(\\d+),?(\\d+)? \\+(\\d+),?(\\d+)? @@.*");
           

複制

這樣通過下面的代碼就可以擷取新檔案的修改行:

matcher.group(3)
matcher.group(4)
           

複制

以上就是我們擷取增量資訊的基礎,借助git的這些指令,我們就為後續JaCoco探針的插入,提供了Diff的資訊,進而可以實作增量探針機制。

向大家推薦下我的網站 https://xuyisheng.top/ 點選原文一鍵直達

專注 Android-Kotlin-Flutter 歡迎大家通路