設備外殼命令

在 VTS 測試期間,shell 命令用於執行目標端測試二進製文件,獲取/設置屬性、環境變量和系統信息,以及啟動/停止 Android 框架。您可以使用adb shell命令或設備上運行的 VTS shell 驅動程序執行 VTS 設備 shell 命令(推薦)。

使用亞行外殼

在測試期間需要關閉 USB 端口或重新啟動設備的測試必須使用 ADB shell,因為 VTS shell 驅動程序在沒有持久 USB 連接的情況下不可用。您可以從 Python 測試腳本中的AndroidDevice對象調用 ADB shell。例子:

  • 獲取一個 Android 設備對象:
    self.device = self.android_devices[0]
    
  • 發出一個 shell 命令:
    result = self.device.adb.shell(‘ls')
    

使用 VTS 外殼驅動程序

VTS shell 驅動程序是在設備上運行並執行 shell 命令的代理二進製文件。默認情況下,如果驅動程序在設備上運行,VTS 會使用 shell 驅動程序,因為這種方法的延遲比使用adb shell命令的時間短。

圖 1. VTS 外殼驅動程序。

VTS 框架支持多設備測試,其中每個 Android 設備在基本運行程序中表示為 AndroidDevice 對象。默認情況下,VTS 框架將 VTS 代理和 VTS shell 驅動程序二進製文件推送到每個 Android 設備,並與這些設備上的 VTS 代理建立 TCP 連接。

為了執行 shell 命令,主機端 Python 腳本對 AndroidDevice 對象內的 ShellMirror 對象進行函數調用。 ShellMirror 對象將 shell 命令文本打包到protobuf消息中,並將其(通過 TCP 通道)發送到 Android 設備上的 VTS 代理。然後,在設備上運行的代理通過 Unix 套接字將 shell 命令轉發給 VTS shell 驅動程序。

當 VTS shell 驅動程序接收到一個 shell 命令時,它會通過設備 shell 上的nohup執行該命令,以防止掛起。然後從nohup檢索標準輸出、標準錯誤和返回碼,並將其發送回 VTS 代理。最後,代理通過將命令結果包裝到protobuf消息中來回复主機。

優點

使用 VTS shell 驅動程序而不是adb shell的優點包括:

  • 可靠性。 VTS shell 驅動程序使用nohup在默認設置下執行命令。由於 VTS 測試大多是較低級別的 HAL 和內核測試,因此nohup可確保 shell 命令在執行期間不會掛起。
  • 性能。雖然adb shell命令會緩存一些結果(例如列出目錄中的文件),但它在執行任務(例如執行測試二進製文件)時會產生連接開銷。 VTS shell 驅動程序在整個測試過程中保持活動連接,因此唯一的開銷是 USB 通信。在我們的測試中,使用 VTS shell 驅動程序執行一個對空 gtest 二進製文件調用 100 次的命令比使用adb shell快大約 20%;由於 VTS shell 通信具有廣泛的日誌記錄,因此實際差異更大。
  • 守國。 VTS shell 驅動程序為每個終端名稱維護一個終端會話(默認終端名稱為default )。在一個終端會話中設置的環境變量僅對同一會話中的後續命令可用。
  • 可擴展。 VTS 框架和設備驅動程序之間的 Shell 命令通信被包裝在 protobuf 中,以在將來啟用潛在的壓縮、遠程處理、加密等。其他提高性能的可能性也是可用的,包括當通信開銷變得大於結果字符串解析時的設備端結果解析。

缺點

使用 VTS shell 驅動程序而不是adb shell的缺點包括:

  • 額外的二進製文件。 VTS 代理文件必須在測試執行後推送到設備並清理。
  • 需要主動連接。如果在測試過程中主機和代理之間的 TCP 連接有意或無意丟失(由於 USB 斷開、端口關閉、設備崩潰等),則無法將 shell 命令傳輸到 VTS 代理。即使自動切換到adb shell ,斷開前命令的結果和狀態也是未知的。

例子

在 VTS 主機端 Python 測試腳本中使用 shell 命令的示例:

  • 獲取一個 Android 設備對象:
    self.device = self.android_devices[0]
    
  • 獲取所選設備的外殼對象:
    self.shell = self.device.shell
    
  • 發出單個 shell 命令:
    results = self.shell.Execute(‘ls')
    
  • 發出一個shell命令列表:
    results = self.shell.Execute([‘cd /data/local/tmp', ‘ls'])
    

命令結果對象

shell 命令執行的返回對像是一個包含鍵stdoutsstderrsreturn_codes的字典。無論 shell 命令是作為單個字符串還是命令字符串列表提供的,結果字典的每個值始終是一個列表。

要驗證命令列表的返回碼,測試腳本必須檢查索引。例子:

asserts.assertFalse(any(results[‘return_codes']), ‘some command failed.')

或者,腳本可以單獨檢查每個命令索引。例子:

asserts.assertEqual(results[‘return_codes'][0], 0, ‘first command failed')
asserts.assertEqual(results[‘return_codes'][1], 0, ‘second command failed')