本文件說明如何使用 Rust 壓力測試程式庫編寫壓力測試。程式庫位於 //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
特徵。操作者特徵是 ActorRunner
叫用的一個方法 perform()
。叫用時,執行者只能執行一項作業,並將結果傳回執行元件。執行者必須儲存執行作業所需的所有連線。
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>
對基礎架構執行壓力測試
壓力測試會透過附加至 fuchsia_test_package
或 fuchsia_unittest_package
GN 建構目標的 stress-tests
標記進行識別。
fuchsia_test_package("filesystem-stress-tests") {
test_components = [
":filesystem-stressor"
]
test_specs = {
environments = [
{
dimensions = {
device_type = "QEMU"
}
tags = [ "stress-tests" ]
},
]
}
}
專屬的 core.x64-stress
建構工具會識別這些測試,並執行套件中的每個測試元件,最長可執行 22 小時。
對壓力測試進行偵錯
這個架構使用 rust 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}