本文說明如何使用信任壓力測試編寫「壓力測試」
資源庫。你可以在 //src/sys/lib/stress-test 找到程式庫。它會實作測試迴圈
執行這些測試所需的並行和同步基元。
撰寫壓力檢測
定義 GN 建構目標
定義 rustc_binary、fuchsia_component 和 fuchsia_test_package GN 建構目標
測試:
rustc_binary("filesystem-stressor-bin") {
    deps = [
        ...
        "//src/sys/lib/stress-test",
        ...
    ]
    sources = [
        ...
    ]
}
fuchsia_component("filesystem-stressor") {
    deps = [ ":filesystem-stressor-bin" ]
    manifest = "meta/filesystem-stressor.cml"
    testonly = true
}
fuchsia_test_package("filesystem-stress-tests") {
  test_components = [
    ":filesystem-stressor"
  ]
}
編寫演員
每位演員都必須實作 Actor 特徵。演員特徵是 perform() 的其中一種方法,
呼叫 ActorRunner。叫用時,執行者只能執行一項作業並傳回
傳送到執行元件的結果執行者必須儲存執行作業所需的所有連線。
pub trait Actor: Sync + Send + 'static {
    // ActorRunner invokes this function, instructing the actor
    // to perform exactly one operation and return result.
    async fn perform(&mut self) -> Result<(), ActorError>;
}
執行者可以透過傳回結果來指出下列內容:
- Ok(()):作業成功,已新增至全域作業數量中。
- Err(ActorError::DoNotCount):這項作業不會計入全域作業中 數量。
- Err(ActorError::ResetEnvironment):必須重設環境,且不得執行作業 會計入全球作業數量。
執行者遇到未預期的錯誤時,應該會恐慌,進而停止測試。
由於發動者是在相同的環境下作業,因此他們的作業可能會 碰撞例如,進行檔案系統壓力測試時,發動者可能會對同一組檔案執行作業。 若可發現此類衝突,您必須設定發動者妥善處理這類衝突。 否則,行為人應恐慌,導致測試停止。
發動者可以刻意破壞系統底層測試,並要求重設環境。適用對象
例如,在檔案系統壓力測試中,執行者可以隨機
檔案系統和基礎區塊裝置在這個範例中,其他演員也應要求使用新的
使用 ActorError::ResetEnvironment 的環境,且環境會重新建立連線
讓所有演員都能獲益良多
pub struct FilesystemActor {
    /// Store a connection to the root of filesystem here
    pub root_directory: Directory
    ...
}
impl FilesystemActor {
    pub fn new(root_directory: Directory) -> Self {
        ...
    }
}
#[async_trait]
impl Actor for FilesystemActor {
    async pub fn perform(&mut self) -> Result<(), ActorError> {
        // Choose exactly one operation to do on the filesystem
        // using the root_directory
        self.root_directory.delete_all_files();
    }
}
寫入環境
環境提供壓力測試的基本設定,包括結束條件、 和重設方法
pub trait Environment: Send + Sync + Debug {
    /// Returns the target number of operations to complete before exiting
    fn target_operations(&self) -> Option<u64>;
    /// Returns the number of seconds to wait before exiting
    fn timeout_seconds(&self) -> Option<u64>;
    /// Return the runners for all the actors
    async fn actor_runners(&mut self) -> Vec<ActorRunner>;
    /// Reset the environment, when an actor requests one
    async fn reset(&mut self);
}
環境可以儲存測試的其他設定。我們可以提供這項設定
透過指令列加上 argh Crate。
執行者會由執行元件和環境共用,因此必須包裝為
Arc<Mutex<dyn Actor>>。跑者在執行作業時保持鎖頭。
這表示環境只能在作業之間取得執行者的鎖定。
行為人判定 系統下層測試已故障環境應會為 並鎖定發動者,以更新他們與新的執行個體之間的連線。
環境也必須實作 Debug 特徵。壓力測試會記錄環境
測試開始,以及測試是否恐慌時。一般做法是輸出
以便重現測試,例如使用的隨機種子。
#[derive(Debug)]
pub struct FilesystemEnvironment {
    fs_actor: Arc<Mutex<FilesystemActor>>,
    seed: u64,
    ...
}
impl Environment {
    pub fn new() -> Self {
        ...
    }
}
#[async_trait]
impl Environment for FilesystemEnvironment {
    fn target_operations(&self) -> Option<u64> {
        // By specifying None here, the test will run without an operation limit
        None
    }
    fn timeout_seconds(&self) -> Option<u64> {
        // By specifying None here, the test will run without a time limit
        None
    }
    async fn actor_runners(&mut self) -> Vec<ActorRunner> {
        vec![
            ActorRunner::new(
                "filesystem_actor",  // debug name
                60,  // delay (in seconds) between each operation (0 means no delay)
                self.fs_actor.clone()), // actor
            )
        ]
    }
    async fn reset(&mut self) {
        // If the actor is performing an operation, this will remain
        // locked until the operation is complete.
        let actor = self.fs_actor.lock().await;
        // Now the environment can update the actor before it is run again.
        actor.root_directory = ...;
        // Releasing the lock will resume the runner.
    }
}
編寫主函式
壓力測試的主要功能相當簡單,因為大部分的邏輯 環境和發動者。使用主要函式收集指令列 引數 (如有),初始化記錄並設定記錄嚴重性。
#[fuchsia::main]
async fn main() {
    // Create the environment
    let env = FilesystemEnvironment::new();
    // Run the test.
    // Depending on the exit criteria, this may never return.
    stress_test::run_test(env).await;
}
在本機執行壓力測試
由於壓力測試是 fuchsia_test_package 的一部分,因此執行壓力最簡單的方式之一
是執行 fx test 指令:
fx test filesystem-stress-tests
如要使用自訂指令列引數執行測試,請使用 fx shell run:
fx shell run fuchsia-pkg://fuchsia.com/filesystem-stress-tests#meta/filesystem-stressor.cm <args>
對基礎架構執行壓力測試
壓力測試是由基礎架構所連接的 stress-tests 標記來識別
fuchsia_test_package 或 fuchsia_unittest_package GN 建構目標。
fuchsia_test_package("filesystem-stress-tests") {
  test_components = [
    ":filesystem-stressor"
  ]
  test_specs = {
    environments = [
      {
        dimensions = {
          device_type = "QEMU"
        }
        tags = [ "stress-tests" ]
      },
    ]
  }
}
專屬的 core.x64-stress 建構工具可識別這些測試,並在
最長可達 22 小時的套件
對壓力測試進行偵錯
這個架構使用信任 log Crate 記錄訊息。測試會記錄位於
看看是否會造成問題
--------------------- stressor is starting -----------------------
Environment {
    seed: 268479717856254664270968796173957499835,
    filesystem_actor: { ... }
    ...
}
------------------------------------------------------------------
如果已啟用偵錯記錄功能,系統也會記錄個別發動者作業和作業計數。
DEBUG: [0][filesystem_actor][389] Sleeping for 2 seconds
DEBUG: [0][filesystem_actor][389] Performing...
DEBUG: [0][filesystem_actor][389] Done!
DEBUG: Counters -> [total:403] {"filesystem_actor": 403}