2017年1月18日 星期三

diff 工具中的 unified format

稍早在討論 cram 這個測試工具的文章中[1],有提到 unified format。這邊文章稍微補充一些更多的香關知識。動機很單純,因為 diff 這個實用的工具用很久了,順便整理一下對於新接觸這種格式的人可能會有的障礙。wikipedia 上面其實已經整理得很清楚了[2],這邊算是中文摘要。

[1] http://zh-tw-tai271828.blogspot.tw/2017/01/cram.html
[2] https://en.wikipedia.org/wiki/Diff_utility#Unified_format

unified format

最主要是要知道要怎麼解讀這個格式

@@ -l,s +l,s @@ optional section heading


  • 格式開頭由兩個 @包夾
  • - 原本的檔案
  • + 更動後的檔案
  • l 開始的行數
  • s 由開始起算的相關行數(刪減、更動或是增加)

簡史


Wayne Davison 在 1990 八月提出,隨後由 Richard Stallman 加入 GNU diff 中 (GNU diff 1.15)

字彙



  • hunk - 在這裡指「一整個更動過的文字區塊」。了解這個字義有助於使用 patch 時,可以更清楚地解讀上 patch 後 patch 工具所反饋的訊息。

初探命令列測試工具 cram

cram 簡介


cram 是一個設計來適用於測試命令列的工具。包括下面特性

  • 執行一個 .t extention file 來進行測試
  • 測試結果使用 unified format[1] 呈現

我的心得是似乎是一個可以用於 function test or API test 的工具:測試產品整體的執行結果。[2] 另外就是近年來似乎使用 command pattern + factory pattern 的命令列實作似乎越來越常見[3],或許是一個值得了解的測試方式。


[1] https://en.wikipedia.org/wiki/Diff_utility#Unified_format
[2] 請見下面的「mercurial 的測試設計思想」
[3] kubernetes, mercurial, MAAS, checkbox(這個不完全是,沒有前面三者這麼"API")

使用範例


安裝
pip install cram

取得 cram source code (我只是要拿裡面 cram 測試自己 source code 的 test file)
git clone git@github.com:brodie/cram.git

進到取得的 source code 中存放  test file 之處
cd <cram source root>/cram/tests

執行看看
cram usage.t

稍微改動一下 usage.t,比較一下前後輸入輸出結果,大概就會有些感覺了。包括:

  • .t file 基本上由兩者構成:「要執行的命令」、「執行後的輸出」
  • 由空白兩行的縮排來告知 cram 「這是要執行的命令與執行後的輸出」

已經有過的討論案例:mercurial 的測試設計思想


在研究 cram 的過程中,我發現了這個討論串[1][2],大致上是說
  • mercurial 的開發上,產品的測試佔極大部份(程式碼幾乎是產品本身行數的一半),unit test 只有一點點
  • 上面這種測試的中心思想是「我只保證 API 行為始終一致,中間怎麼實作基本上你不要管我」。優點是向下相容容易、測試程式碼不需要跟著一直改動。
  • 有人就建議那這樣可能適合使用 cram[3]
[1] https://www.selenic.com/blog/?p=663
[2] https://www.selenic.com/blog/?p=582
[3] 我不知道最後 mercurial 最後有沒有採取這個作法,有興趣可以追一下。cram 的開發好像也沈寂了一段時間了就是。(cram 在 github 上面的 README 中,有些 link 還是指到 bitbucket 上呢)

自己想用上的案例:SOLVCON 上面使用 cram


動機


在 2015 的計畫中(對滿一年了 XD),我們有考慮設計 mesh IO 的 API。目前 mesh 工具也是朝著 command + factory pattern 的方式實作。

可以預期的問題


  • 有些行為本質是亂數,例如切  partition 的方式
  • elapsed time 資訊不太可能每次一樣
所以至少第一步是要先挑出究竟哪些 mesh/block 行為並不會改變,再去實作。








2017年1月17日 星期二

書摘:Effective Debugging - Item 21 修正所有造成問題的類別實例

這也是很直觀,不過作者舉了一些找出類似實例的方式,例如


  • 用 grep 找出關鍵字、使用 -v [1] 做過濾、使用 --color=always 高亮自己要的訊息
  • sort -u 移除重複
在某些情況下,例如使用不推薦或是錯誤的 API,可以使用 global include file 來重新定義錯誤的 API 名稱,讓他改作其他事情(例如拋出警告取代實際執行),這樣就可以在程式早期(例如編譯或是連結的時候)就發現問題了。

[1] 我自己 -v 也是用很兇,在這裡看到有同好也是,覺得安心 XDDDD

書摘:Effective Debugging - Item 20 除錯前後理清資訊

debugging 是一個在複雜的環境中找線索的過程,起頭往往可以是(部份舉例)


  • 能夠協助你找到問題的工具是什麼?
  • warnings 訊息等等是什麼?
  • 好像跟你的問題有關的、但你又讀不懂的程式碼段
  • comment 有些關鍵字例如 "should" "think" "must" "FIXME" "TODO" 等等的程式碼附近。
關掉或是移除這些嫌疑犯(例如會產生 warning 的程式碼片段)來找出錯誤;注意因為可能性太多了,所以務必要在除錯之前,把要除錯系統先「穩定」下來;除非你真的很確定有幫助,不然不要貿然升級或是改動程式碼等等。

除錯完成後,記得
  • 在程式裡面尋找類似的錯誤
  • 加入可以在未來協助找出類似錯誤的例外處理 [1]
  • undo 任何暫時性的修改(可以考慮搭配 version control)


[1] 這點對我而言有被刺激到,例如我後來就在 SOLVCON 裡面加入了類似的檢查,來找出未來 boundary condition 是一個 generic layer 而不是具體的 boundary condition 時,拋出訊息。https://github.com/solvcon/solvcon/pull/180/commits/d946c3d1b6bb23d9011f0f774cf9c2c917848579

書摘:Effective Debugging - Item 19 自動化除錯任務

這其實滿直觀的一種想法:把針對某個任務常用到的指令整合、寫下等等方便重複利用,或是反覆替自己找出有用的資訊。這章節的價值在於作者很具體地提供某些工具的名稱和應用方式。例如:


  • which 很慢,如何分析自己的 PATH 變數(搭配 sed, pipe and while),找出 typo
作者另外指出各種怪現象都有對應的工具(並且列出書中對應章節供更進一步的參考),例如:
  • API violations
  • memory butter overflows
  • race conditions

我自己是有一個心得,使用編輯器的 exhaustive search 之前,可以先大概想一下,自己遇到的這個案例,適合這樣做,或是適合先寫個 script 來幫你過濾程式碼或是 log。

總之如作者所說:「computer time is cheap, yours is expensive.」(我個人是覺得把 time 換成專注力,應該更貼切)

書摘:Effective Debugging - Item 18 從你的桌面替其他不便的系統除錯

不是自己平常使用的系統當然很不習慣,例如缺少某些自己慣用的工具,這個章節提供幾個方法讓想要除錯的系統盡可能地接近自己習慣的環境。


  • 對於手機 app 或是有些 embedded devices,使用 device emulator;這樣就可以使用自己習慣的螢幕、鍵盤和編輯器。缺點是可能無法使用 symbolic debugger。
  • 搭配 device emulator,使用 shim 這種技巧的概念:使用一個中介(例如檔案 IO),來存放執行時相關的資料或是參數,實際的 code 則是跑在本機。本技巧通常只是用演算法測試,不包括 UI 測試。我自己是覺得 core.dump 就是類似的東西。書中是舉手機中某個會用到網路與 API 的應用程式先在本機上寫好並且測試好,然後包成一個 class 整合進去原本的程式碼。
  • Teamviewer 這東東應該不用再多說明了,名氣響亮。
  • Teamviewer + strace or truss command on a third-party computer.
  • KVM over IP device;使用情境:inaccessible data center. 我自己有用過這種東西(使用跟架設都有),有點厲害。例如,自己桌機的鍵盤訊號可以透過網路,在遠端的機器上就像真實的鍵盤輸入一樣(螢幕輸出則是由遠端電器訊號忠實送到你面前)。這種物理手段可以作到連 BIOS 階段都可以進去、調整。只是因為訊號傳送要一段時間,所以想要進 BIOS 有點要透過盲按 XDD 因為 BIOS 畫面往往幾秒而已,等送到你的螢幕上時早就跳掉了。


2017年1月9日 星期一

修 hot key 實例 (Ubuntu Yakkety on Dell Latitude 7370)

今天在 Launchpad 上看到有人回報筆電 Dell Latitude 7370 麥克風靜音 hotkey (Fn + F4)無效(LP:# 1654827)[1]。這個回報很有意思,顯然回報者是一位專業玩家,他的回報非常具體、提供的資訊在除錯上非常地有用,很適合做為一個小小的教學範例;因此動了念頭想介紹一下這個範例。

原因

hwdb 中原本預期的 event value 150,在 driver 中給出的值是 100150。[2]

會使用到的工具


  • acpi_listen
  • showkey
  • evtest
  • systemd-hwdb https://www.freedesktop.org/software/systemd/man/systemd-hwdb.html#

需要的背景知識



  • hwdb 經由 systemd-hwdb 這個指令會編譯成 binary (叫做 hwdb.bin),提供給  wmi 這個 module 使用。
  • hwdb https://www.freedesktop.org/software/systemd/man/hwdb.html
  • wmi https://wiki.ubuntu.com/Kernel/Reference/WMI

[1] https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1654827
[2] https://github.com/systemd/systemd/pull/5012


2017年1月3日 星期二

Mesa 和 Linux graphic stack 簡介

前陣子提到 PRIME 技術,今天把更多相關知識補齊。

以下大多是從[1]這篇文章所做的摘要。

graphic stack 的「演化」


  • 2D: 透過 X server 來控制硬體(螢幕上畫圖等,rendering)。參考下面的「X window 架構」
  • 3D: 使用 OpenGL 實作的應用程式透過 X server 來控制硬體、rendering。這叫 indirect rendering (相對於 direct rendering 的一個詞彙)。參考下面的 「GLX 架構」
  • 3D + DRI (Direct Rendering Infrastructure): 使用 OpenGL 實作的應用程式透過 X server 來控制硬體、rendering。

X window 架構


  • X client 控制資料運算、X server 控制硬體。(注意一台 ssh server 是透過 X client 和某處的 X server 溝通,不要混淆了一般的 server 詞彙涵義和 X server 的「server」)
  • X client 透過 X11 protocol 和 X server 溝通,實作是 Xlib。
  • X server 透過 DDX (device-dependent X) driver 和硬體溝通。


GLX 架構 / Indirecting Rendering


  • Hardware --> OpenGL --> OpenGL API --> libGL.so--> OpenGL application,但這條路在中間還有 X server 的時候會不通,因此用 GLX 來串連。
  • OpenGL application --> GLX --> X server --> GLX driver --> kernel
  • 效率會因為多一層要通過 X server 就會比較差,因此有 DRI 架構

DRI 架構

  • 上面的 in-directing rendering 效率較差,因此試試 directing rendering
  • Hardware --> kernel (DRM) --> OpenGL DRI driver --> OpenGL / libGL.so --> OpenGL application
  • DRM 可以說是 DRI 在 kernel 面向的實作,包括有給 userspace 呼叫的 API

MESA


有了上面的概念之後,就可以理解 Mesa 在 graphic stack 中扮演的角色了。Mesa 包括:
  • 包/利用 libGL
  • 基於 DRI/DRM 架構
  • Mesa 面向的 GLX;原則上還是讓 X 去控制原本 X server 已經在控制的東西,例如圖形內容;Mesa 本身只是想要同步好 X server 已經在控制的內容和透過 DRI 進出的資料與運算。





[1] https://blogs.igalia.com/itoral/2014/07/