本教學課程將逐步說明如何使用 fx test
指令和 Fuchsia 偵錯工具 (zxdb
) 進行偵錯工作流程。
如要進一步瞭解如何使用 zxdb 偵錯測試,請參閱「使用 zxdb 偵錯測試」一文。
瞭解測試案例
荒漠油廠
Rust 測試是由 Rust 測試執行器執行。與 C++ 測試的 gTest 或 gUnit 執行器不同,Rust 測試執行元件預設會並行執行測試案例。這在使用 --break-on-failure
功能時會產生不同體驗。如要進一步瞭解並行測試程序的預期結果,請參閱「並行執行測試案例」。支援並行測試程序。
以下是根據部分Rust 測試程式碼的範例:
...
let mut log_helper2 = LogSinkHelper::new(&directory);
log_helper2.write_log("my msg1");
log_helper.write_log("my msg2");
let mut expected = vec!["my msg1".to_owned(), "my msg3".to_owned()];
expected.sort();
let mut actual = vec![recv_logs.next().await.unwrap(), recv_logs.next().await.unwrap()];
actual.sort();
assert_eq!(expected, actual);
...
您可以使用 fx set
將這個測試目標加入建構圖:
fx set workbench_eng.x64 --with-tests //src/diagnostics/archivist:tests
C++
根據預設,gTest 測試執行元件會依序執行測試案例,因此一次只會偵錯一個測試失敗。只要在 fx test
指令中加入 --parallel-cases
標記,即可平行執行測試案例。
以下是根據部分C++ 測試程式碼的範例:
// Inject 1 process.
auto process1 = std::make_unique<MockProcess>(nullptr, kProcessKoid1, kProcessName1);
process1->AddThread(kProcess1ThreadKoid1);
harness.debug_agent()->InjectProcessForTest(std::move(process1));
// And another, with 2 threads.
auto process2 = std::make_unique<MockProcess>(nullptr, kProcessKoid2, kProcessName2);
process2->AddThread(kProcess2ThreadKoid1);
process2->AddThread(kProcess2ThreadKoid2);
harness.debug_agent()->InjectProcessForTest(std::move(process2));
reply = {};
remote_api->OnStatus(request, &reply);
ASSERT_EQ(reply.processes.size(), 3u); // <-- This will fail, since reply.processes.size() == 2
EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
...
您可以使用 fx set
將這個測試目標加入建構圖:
fx set workbench_eng.x64 --with-tests //src/developer/debug:tests
執行測試
荒漠油廠
使用 fx test --break-on-failure
指令執行測試,例如:
fx test -o --break-on-failure archivist-unittests
輸出內容如下:
<...fx test startup...>
Running 1 tests
Starting: fuchsia-pkg://fuchsia.com/archivist-tests#meta/archivist-unittests.cm
Command: fx ffx test run --max-severity-logs WARN --break-on-failure fuchsia-pkg://fuchsia.com/archivist-tests?hash=9a531e48fe82d86edef22f86f7e9b819d18a7d678f0823912d9224dd91f8926f#meta/archivist-unittests.cm
Running test 'fuchsia-pkg://fuchsia.com/archivist-tests?hash=9a531e48fe82d86edef22f86f7e9b819d18a7d678f0823912d9224dd91f8926f#meta/archivist-unittests.cm'
[RUNNING] archivist::tests::can_log_and_retrive_log
[101430.272555][5631048][5631050][<root>][can_log_and_retrive_log] WARN: Failed to create event source for log sink requests err=Error connecting to protocol path: /events/log_sink_requested_event_stream
Caused by:
NOT_FOUND
[101430.277339][5631048][5631050][<root>][can_log_and_retrive_log] WARN: Failed to create event source for InspectSink requests err=Error connecting to protocol path: /events/inspect_sink_requested_event_stream
[101430.336160][5631048][5631050][<root>][can_log_and_retrive_log] INFO: archivist: Entering core loop.
[101430.395986][5631048][5631050][<root>][can_log_and_retrive_log] ERROR: [src/lib/diagnostics/log/rust/src/lib.rs(62)] PANIC info=panicked at ../../src/diagnostics/archivist/src/archivist.rs:544:9:
assertion `left == right` failed
left: ["my msg1", "my msg2"]
right: ["my msg1", "my msg3"]
👋 zxdb is loading symbols to debug test failure in archivist-unittests.cm, please wait.
⚠️ test failure in archivist-unittests.cm, type `frame` or `help` to get started.
536 actual.sort();
537
▶ 538 assert_eq!(expected, actual);
539
540 // can log after killing log sink proxy
🛑 process 9 archivist_lib_lib_test::archivist::tests::can_log_and_retrive_log::test_entry_point::λ(core::task::wake::Context*) • archivist.rs:538
[zxdb]
請注意,測試的輸出內容會混合,這是因為信任測試執行元件預設同時執行測試案例。您可以使用 fx test
搭配 --parallel-cases
選項來避免這種情況,例如:fx test --parallel-cases 1 --break-on-failure archivist-unittests
C++
使用 fx test --break-on-failure
指令執行測試,例如:
fx test -o --break-on-failure debug_agent_unit_tests
輸出內容如下:
<...fx test startup...>
Starting: fuchsia-pkg://fuchsia.com/debug_agent_unit_tests#meta/debug_agent_unit_tests.cm (NOT HERMETIC)
Command: fx ffx test run --realm /core/testing:system-tests --max-severity-logs WARN --break-on-failure fuchsia-pkg://fuchsia.com/debug_agent_unit_tests?hash=3f6d97801bb147034a344e3fe1bb69291a7b690b9d3d075246ddcba59397ac12#meta/debug_agent_unit_tests.cm
Status: [duration: 30.9s] [tasks: 3 running, 15/19 complete]
Running 2 tests [ ] 0.0%
👋 zxdb is loading symbols to debug test failure in debug_agent_unit_tests.cm, please wait.
⚠️ test failure in debug_agent_unit_tests.cm, type `frame` or `help` to get started.
103 remote_api->OnStatus(request, &reply);
104
▶ 105 ASSERT_EQ(reply.processes.size(), 3u);
106 EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
107 EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
🛑 thread 1 debug_agent::DebugAgentTests_OnGlobalStatus_Test::TestBody(debug_agent::DebugAgentTests_OnGlobalStatus_Test*) • debug_agent_unittest.cc:105
[zxdb]
檢查失敗
荒漠油廠
這個範例包含測試失敗,因此 Rust 測試會在失敗時發出 abort
,而 zxdb
會通知並回報這項資訊。zxdb
也會分析中止作業的呼叫堆疊,並方便地將我們直接帶往失敗的原始碼。您可以使用 list
查看目前影格中的其他程式碼行,例如:
list
533 expected.sort();
534
535 let mut actual = vec![recv_logs.next().await.unwrap(), recv_logs.next().await.unwrap()];
536 actual.sort();
537
▶ 538 assert_eq!(expected, actual);
539
540 // can log after killing log sink proxy
541 log_helper.kill_log_sink();
542 log_helper.write_log("my msg1");
543 log_helper.write_log("my msg2");
544
545 assert_eq!(
546 expected,
547 vec! {recv_logs.next().await.unwrap(),recv_logs.next().await.unwrap()}
548 );
[zxdb]
您也可以使用 frame
檢查整個呼叫堆疊,例如:
frame
0…12 «Rust library» (-r expands)
13 std::panicking::begin_panic_handler(…) • library/std/src/panicking.rs:645
14 core::panicking::panic_fmt(…) • library/core/src/panicking.rs:72
15 core::panicking::assert_failed_inner(…) • library/core/src/panicking.rs:402
16 core::panicking::assert_failed<…>(…) • /b/s/w/ir/x/w/fuchsia-third_party-rust/library/core/src/panicking.rs:357
▶ 17 archivist_lib_lib_test::archivist::tests::can_log_and_retrive_log::test_entry_point::λ(…) • archivist.rs:544
18 core::future::future::«impl»::poll<…>(…) • future/future.rs:123
19 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:26
20 fuchsia_async::test_support::«impl»::run_singlethreaded::λ::λ(…) • test_support.rs:121
21 fuchsia_async::atomic_future::«impl»::poll<…>(…) • atomic_future.rs:78
22 fuchsia_async::atomic_future::AtomicFuture::try_poll(…) • atomic_future.rs:223
23 fuchsia_async::runtime::fuchsia::executor::common::Inner::try_poll(…) • executor/common.rs:588
24 fuchsia_async::runtime::fuchsia::executor::common::Inner::poll_ready_tasks(…) • executor/common.rs:148
25 fuchsia_async::runtime::fuchsia::executor::common::Inner::worker_lifecycle<…>(…) • executor/common.rs:448
26 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run<…>(…) • executor/local.rs:100
27 fuchsia_async::runtime::fuchsia::executor::local::LocalExecutor::run_singlethreaded<…>(…) • executor/local.rs:68
28 fuchsia_async::test_support::«impl»::run_singlethreaded::λ() • test_support.rs:119
29 fuchsia_async::test_support::Config::in_parallel(…) • test_support.rs:214
30 fuchsia_async::test_support::«impl»::run_singlethreaded(…) • test_support.rs:116
31 fuchsia_async::test_support::run_singlethreaded_test<…>(…) • test_support.rs:226
32 fuchsia::test_singlethreaded<…>(…) • fuchsia/src/lib.rs:188
33 archivist_lib_lib_test::archivist::tests::can_log_and_retrive_log() • archivist.rs:519
34 archivist_lib_lib_test::archivist::tests::can_log_and_retrive_log::λ(…) • archivist.rs:520
35 core::ops::function::FnOnce::call_once<…>(…) • /b/s/w/ir/x/w/fuchsia-third_party-rust/library/core/src/ops/function.rs:250
36 core::ops::function::FnOnce::call_once<…>(…) • library/core/src/ops/function.rs:250 (inline)
37 test::__rust_begin_short_backtrace<…>(…) • library/test/src/lib.rs:621
38 test::run_test_in_spawned_subprocess(…) • library/test/src/lib.rs:749
39 test::test_main_static_abort(…) • library/test/src/lib.rs:197
40 archivist_lib_lib_test::main() • archivist/src/lib.rs:1
41…58 «Rust startup» (-r expands)
[zxdb]
或者,在非同步內容中,您可以使用 async-backtrace
,例如:
[zxdb] async-backtrace
Task(id = 0)
└─ fuchsia_async::test_support::«impl»::run_singlethreaded::λ • test_support.rs:122
└─ fuchsia_async::test_support::«impl»::run_singlethreaded::λ • test_support.rs:27
└─ archivist_lib_lib_test::archivist::tests::can_log_and_retrive_log::test_entry_point • archivist.rs:546
└─ futures_util::stream::stream::next::Next
Task(id = 1)
└─ diagnostics_log::fuchsia::filter::«impl»::listen_to_interest_changes • fuchsia/filter.rs:77
└─ fidl::client::QueryResponseFut
Task(id = 2)
└─ archivist_lib_lib_test::logs::repository::«impl»::new • logs/repository.rs:433
└─ futures_util::stream::stream::next::Next
Task(id = 3)
└─ archivist_lib_lib_test::logs::repository::«impl»::process_removal_of_components • logs/repository.rs:232
└─ futures_util::stream::stream::next::Next
Task(id = 4)
└─ archivist_lib_lib_test::logs::servers::log_settings::«impl»::new • log_settings.rs:33
└─ futures_util::stream::stream::for_each_concurrent::ForEachConcurrent
Task(id = 5)
└─ archivist_lib_lib_test::inspect::servers::inspect_sink::«impl»::new • inspect_sink.rs:42
└─ futures_util::stream::stream::for_each_concurrent::ForEachConcurrent
Task(id = 6)
└─ archivist_lib_lib_test::logs::servers::log_settings::«impl»::new • log_settings.rs:33
└─ futures_util::stream::stream::for_each_concurrent::ForEachConcurrent
Task(id = 7)
└─ archivist_lib_lib_test::logs::servers::log_settings::«impl»::new • log_settings.rs:33
└─ futures_util::stream::stream::for_each_concurrent::ForEachConcurrent
Task(id = 8)
└─ archivist_lib_lib_test::logs::servers::log_settings::«impl»::new • log_settings.rs:33
└─ futures_util::stream::stream::for_each_concurrent::ForEachConcurrent
Task(id = 9)
└─ archivist_lib_lib_test::archivist::tests::run_archivist::λ • archivist.rs:518
└─ archivist_lib_lib_test::archivist::«impl»::run • archivist.rs:342
└─ futures_util::future::join::Join3
Task(id = 10)
└─ archivist_lib_lib_test::logs::testing::start_listener • logs/testing.rs:592
└─ fuchsia_syslog_listener::run_log_listener_with_proxy • syslog-listener/src/lib.rs:78
└─ fuchsia_syslog_listener::log_listener • syslog-listener/src/lib.rs:34
└─ futures_util::stream::try_stream::try_next::TryNext
Task(id = 11)
└─ inspect_runtime::service::spawn_tree_server_with_stream • runtime/rust/src/service.rs:80
└─ inspect_runtime::service::handle_request_stream • runtime/rust/src/service.rs:28
└─ futures_util::stream::try_stream::try_next::TryNext
Task(id = 12)
└─ archivist_lib_lib_test::archivist::«impl»::run::λ • archivist.rs:293
└─ archivist_lib_lib_test::events::router::«impl»::start • router.rs:96
└─ futures_util::stream::stream::next::Next
Task(id = 14)
└─ archivist_lib_lib_test::logs::servers::log::«impl»::spawn • log.rs:46
└─ archivist_lib_lib_test::logs::servers::log::«impl»::handle_requests • log.rs:78
└─ futures_util::stream::stream::next::Next
Task(id = 15)
└─ archivist_lib_lib_test::logs::listener::«impl»::spawn • logs/listener.rs:83
└─ archivist_lib_lib_test::logs::listener::«impl»::run • logs/listener.rs:106
└─ archivist_lib_lib_test::logs::listener::«impl»::send_new_logs • logs/listener.rs:123
└─ archivist_lib_lib_test::logs::listener::«impl»::send_log • logs/listener.rs:181
└─ fidl::client::QueryResponseFut
Task(id = 16)
└─ archivist_lib_lib_test::logs::container::«impl»::actually_handle_log_sink • logs/container.rs:256
└─ futures_util::stream::stream::next::Next
Task(id = 17)
└─ archivist_lib_lib_test::logs::container::«impl»::drain_messages • logs/container.rs:373
└─ futures_util::stream::stream::next::Next
Task(id = 18)
└─ archivist_lib_lib_test::logs::container::«impl»::actually_handle_log_sink • logs/container.rs:256
└─ futures_util::stream::stream::next::Next
Task(id = 19)
└─ archivist_lib_lib_test::logs::container::«impl»::drain_messages • logs/container.rs:373
└─ futures_util::stream::stream::next::Next
Scope(0x1771eceb2a0)
└─ Task(id = 13)
└─ vfs::execution_scope::«impl»::spawn • execution_scope.rs:120
└─ core::future::poll_fn::PollFn
您執行的所有指令都會在頁框 #17 的內容中,如 ▶
所示。您可以再次列出原始碼,並提供一些額外的背景資訊:
list -c 10
528 let mut log_helper2 = LogSinkHelper::new(&directory);
529 log_helper2.write_log("my msg1");
530 log_helper.write_log("my msg3");
531
532 let mut expected = vec!["my msg1".to_owned(), "my msg2".to_owned()];
533 expected.sort();
534
535 let mut actual = vec![recv_logs.next().await.unwrap(), recv_logs.next().await.unwrap()];
536 actual.sort();
537
▶ 538 assert_eq!(expected, actual);
539
540 // can log after killing log sink proxy
541 log_helper.kill_log_sink();
542 log_helper.write_log("my msg1");
543 log_helper.write_log("my msg2");
544
545 assert_eq!(
546 expected,
547 vec! {recv_logs.next().await.unwrap(),recv_logs.next().await.unwrap()}
548 );
[zxdb]
如要找出測試失敗的原因,請輸出一些變數來查看發生的情況。actual
影格包含本機變數,該變數應包含一些字串,這些字串是透過對 log_helper
和 log_helper2
例項呼叫 write_log
,以及透過 mpsc 管道 recv_logs
接收這些例項而新增:
print expected
vec!["my msg1", "my msg3"]
[zxdb] print actual
vec!["my msg1", "my msg2"]
測試的預期結果似乎有誤。"my msg3"
應為第二個字串,但實際上記錄的是 "my msg2"
。您可以修正測試,讓預期值為 "my msg2"
。您現在可以從測試中分離,繼續完成測試套件:
quit
<...fx test output continues...>
Failed tests: archivist::tests::can_log_and_retrive_log
122 out of 123 tests passed...
Test fuchsia-pkg://fuchsia.com/archivist-tests?hash=8bcb30a2bfb923a4b42d1f0ea590af613ab0b1aa1ac67ada56ae4d325f3330a0#meta/archivist-unittests.cm produced unexpected high-severity logs:
----------------xxxxx----------------
[105255.347070][5853309][5853311][<root>][can_log_and_retrive_log] ERROR: [src/lib/diagnostics/log/rust/src/lib.rs(62)] PANIC info=panicked at ../../src/diagnostics/archivist/src/archivist.rs:544:9:
assertion `left == right` failed
left: ["my msg1", "my msg2"]
right: ["my msg1", "my msg3"]
----------------xxxxx----------------
Failing this test. See: https://fuchsia.dev/fuchsia-src/development/diagnostics/test_and_logs#restricting_log_severity
fuchsia-pkg://fuchsia.com/archivist-tests?hash=8bcb30a2bfb923a4b42d1f0ea590af613ab0b1aa1ac67ada56ae4d325f3330a0#meta/archivist-unittests.cm completed with result: FAILED
The test was executed in the hermetic realm. If your test depends on system capabilities, pass in correct realm. See https://fuchsia.dev/go/components/non-hermetic-tests
Tests failed.
Deleting 1 files at /tmp/tmpgr0otc3w: ffx_logs/ffx.log
To keep these files, set --ffx-output-directory.
您現在可以對程式碼進行下列變更,以修正測試:
- let mut expected = vec!["my msg1".to_owned(), "my msg3".to_owned()];
+ let mut expected = vec!["my msg1".to_owned(), "my msg2".to_owned()];
您現在可以再次執行測試:
fx test --break-on-failure archivist-unittests
輸出內容應如下所示:
<...fx test startup...>
Running 1 tests
Starting: fuchsia-pkg://fuchsia.com/archivist-tests#meta/archivist-unittests.cm
Command: fx ffx test run --max-severity-logs WARN --break-on-failure fuchsia-pkg://fuchsia.com/archivist-tests?hash=36bf634de9f8850fad02fe43ec7fbe2b086000d0f55f7028d6d9fc8320738301#meta/archivist-unittests.cm
Running test 'fuchsia-pkg://fuchsia.com/archivist-tests?hash=36bf634de9f8850fad02fe43ec7fbe2b086000d0f55f7028d6d9fc8320738301#meta/archivist-unittests.cm'
[RUNNING] accessor::tests::accessor_skips_invalid_selectors
[RUNNING] accessor::tests::batch_iterator_on_ready_is_called
[RUNNING] accessor::tests::batch_iterator_terminates_on_client_disconnect
[RUNNING] accessor::tests::buffered_iterator_handles_peer_closed
[RUNNING] accessor::tests::buffered_iterator_handles_two_consecutive_buffer_waits
[RUNNING] accessor::tests::logs_only_accept_basic_component_selectors
[RUNNING] accessor::tests::socket_writer_does_not_handle_cbor
[RUNNING] accessor::tests::socket_writer_handles_closed_socket
[RUNNING] accessor::tests::socket_writer_handles_text
[RUNNING] archivist::tests::can_log_and_retrive_log
[PASSED] accessor::tests::socket_writer_handles_text
[RUNNING] archivist::tests::log_from_multiple_sock
[PASSED] accessor::tests::socket_writer_does_not_handle_cbor
[RUNNING] archivist::tests::remote_log_test
[PASSED] accessor::tests::socket_writer_handles_closed_socket
[RUNNING] archivist::tests::stop_works
[PASSED] accessor::tests::buffered_iterator_handles_peer_closed
[RUNNING] configs::tests::parse_allow_empty_pipeline
[PASSED] accessor::tests::buffered_iterator_handles_two_consecutive_buffer_waits
[RUNNING] configs::tests::parse_disabled_valid_pipeline
<...lots of tests...>
[PASSED] logs::repository::tests::multiplexer_broker_cleanup
[PASSED] logs::tests::attributed_inspect_two_v2_streams_different_identities
[RUNNING] logs::tests::unfiltered_stats
[PASSED] logs::tests::test_debuglog_drainer
[RUNNING] utils::tests::drop_test
[PASSED] logs::tests::test_filter_by_combination
[PASSED] logs::tests::test_filter_by_min_severity
[PASSED] logs::tests::test_filter_by_pid
[PASSED] logs::tests::test_filter_by_tags
[PASSED] logs::tests::test_filter_by_tid
[PASSED] logs::tests::test_log_manager_dump
[PASSED] logs::tests::test_structured_log
[PASSED] logs::tests::test_log_manager_simple
[PASSED] logs::tests::unfiltered_stats
[PASSED] utils::tests::drop_test
128 out of 128 tests passed...
fuchsia-pkg://fuchsia.com/archivist-tests?hash=36bf634de9f8850fad02fe43ec7fbe2b086000d0f55f7028d6d9fc8320738301#meta/archivist-unittests.cm completed with result: PASSED
Deleting 1 files at /tmp/tmpho9yjjz9: ffx_logs/ffx.log
To keep these files, set --ffx-output-directory.
Status: [duration: 36.4s] [tests: PASS: 1 FAIL: 0 SKIP: 0]
Running 1 tests [====================================================================================================================] 100.0%
C++
這個範例包含測試失敗,gTest 有一個選項可在測試失敗的路徑中插入軟體中斷點,而 zxdb
會擷取這個中斷點。zxdb
也會根據這個值判斷測試程式碼的位置,並直接跳到測試的框架。您可以使用 list
查看目前影格的其他幾行程式碼,例如:
list
100 harness.debug_agent()->InjectProcessForTest(std::move(process2));
101
102 reply = {};
103 remote_api->OnStatus(request, &reply);
104
▶ 105 ASSERT_EQ(reply.processes.size(), 3u);
106 EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
107 EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
108 ASSERT_EQ(reply.processes[0].threads.size(), 1u);
您可以使用 list
的 -c
標記,查看更多行程式碼:
list -c 10
95 constexpr uint64_t kProcess2ThreadKoid2 = 0x2;
96
97 auto process2 = std::make_unique<MockProcess>(nullptr, kProcessKoid2, kProcessName2);
98 process2->AddThread(kProcess2ThreadKoid1);
99 process2->AddThread(kProcess2ThreadKoid2);
100 harness.debug_agent()->InjectProcessForTest(std::move(process2));
101
102 reply = {};
103 remote_api->OnStatus(request, &reply);
104
▶ 105 ASSERT_EQ(reply.processes.size(), 3u);
106 EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
107 EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
108 ASSERT_EQ(reply.processes[0].threads.size(), 1u);
109 EXPECT_EQ(reply.processes[0].threads[0].id.process, kProcessKoid1);
110 EXPECT_EQ(reply.processes[0].threads[0].id.thread, kProcess1ThreadKoid1);
111
112 EXPECT_EQ(reply.processes[1].process_koid, kProcessKoid2);
113 EXPECT_EQ(reply.processes[1].process_name, kProcessName2);
114 ASSERT_EQ(reply.processes[1].threads.size(), 2u);
115 EXPECT_EQ(reply.processes[1].threads[0].id.process, kProcessKoid2);
[zxdb]
您也可以使用 frame
指令檢查完整的堆疊追蹤:
frame
0 testing::UnitTest::AddTestPartResult(…) • gtest.cc:5383
1 testing::internal::AssertHelper::operator=(…) • gtest.cc:476
▶ 2 debug_agent::DebugAgentTests_OnGlobalStatus_Test::TestBody(…) • debug_agent_unittest.cc:105
3 testing::internal::HandleSehExceptionsInMethodIfSupported<…>(…) • gtest.cc:2635
4 testing::internal::HandleExceptionsInMethodIfSupported<…>(…) • gtest.cc:2690
5 testing::Test::Run(…) • gtest.cc:2710
6 testing::TestInfo::Run(…) • gtest.cc:2859
7 testing::TestSuite::Run(…) • gtest.cc:3038
8 testing::internal::UnitTestImpl::RunAllTests(…) • gtest.cc:5942
9 testing::internal::HandleSehExceptionsInMethodIfSupported<…>(…) • gtest.cc:2635
10 testing::internal::HandleExceptionsInMethodIfSupported<…>(…) • gtest.cc:2690
11 testing::UnitTest::Run(…) • gtest.cc:5506
12 RUN_ALL_TESTS() • gtest.h:2318
13 main(…) • run_all_unittests.cc:20
14…17 «libc startup» (-r expands)
[zxdb]
請注意,▶
會指向測試的原始碼框架,表示所有指令都會在這個情境中執行。您可以使用 frame
指令搭配堆疊追蹤中的相關編號,選取其他影格。
如要找出測試失敗的原因,請輸出一些變數來查看發生的情況。reply
框架包含區域變數,該變數應已由函式呼叫 remote_api->OnStatus
填入:
print reply
{
processes = {
[0] = {
process_koid = 4660
process_name = "process-1"
components = {}
threads = {
[0] = {
id = {process = 4660, thread = 1}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
}
}
[1] = {
process_koid = 22136
process_name = "process-2"
components = {}
threads = {
[0] = {
id = {process = 22136, thread = 1}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
[1] = {
id = {process = 22136, thread = 2}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
}
}
}
limbo = {}
breakpoints = {}
filters = {}
}
從輸出結果中,您可以看到 reply
變數已填入一些資訊,預期 processes
向量的大小應等於 3。請列印 reply
的會員變數,以便查看更多資訊。您也可以列印該向量的大小方法 (尚未實作一般函式呼叫支援):
print reply.processes
{
[0] = {
process_koid = 4660
process_name = "process-1"
components = {}
threads = {
[0] = {
id = {process = 4660, thread = 1}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
}
}
[1] = {
process_koid = 22136
process_name = "process-2"
components = {}
threads = {
[0] = {
id = {process = 22136, thread = 1}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
[1] = {
id = {process = 22136, thread = 2}
name = "test thread"
state = kRunning
blocked_reason = kNotBlocked
stack_amount = kNone
frames = {}
}
}
}
}
[zxdb] print reply.processes.size()
2
測試的預期結果似乎有誤。您只插入 2 個模擬程序,但測試預期有 3 個。只要更新測試,即可預期 reply.processes
向量的大小為 2,而非 3。您現在可以使用 quit
關閉 zxdb,然後更新並修正測試:
quit
<...fx test output continues...>
Failed tests: DebugAgentTests.OnGlobalStatus <-- Failed test case that we debugged.
175 out of 176 attempted tests passed, 2 tests skipped...
fuchsia-pkg://fuchsia.com/debug_agent_unit_tests?hash=3f6d97801bb147034a344e3fe1bb69291a7b690b9d3d075246ddcba59397ac12#meta/debug_agent_unit_tests.cm completed with result: FAILED
Tests failed.
FAILED: fuchsia-pkg://fuchsia.com/debug_agent_unit_tests#meta/debug_agent_unit_tests.cm
找出測試失敗的來源後,您可以修正測試:
-ASSERT_EQ(reply.processes.size(), 3u)
+ASSERT_EQ(reply.processes.size(), 2u)
接著執行 fx test
:
fx test --break-on-failure debug_agent_unit_tests
輸出內容應如下所示:
You are using the new fx test, which is currently ready for general use ✅
See details here: https://fuchsia.googlesource.com/fuchsia/+/refs/heads/main/scripts/fxtest/rewrite
To go back to the old fx test, use `fx --enable=legacy_fxtest test`, and please file a bug under b/293917801.
Default flags loaded from /usr/local/google/home/jruthe/.fxtestrc:
[]
Logging all output to: /usr/local/google/home/jruthe/upstream/fuchsia/out/workbench_eng.x64/fxtest-2024-03-25T15:56:31.874893.log.json.gz
Use the `--logpath` argument to specify a log location or `--no-log` to disable
To show all output, specify the `-o/--output` flag.
Found 913 total tests in //out/workbench_eng.x64/tests.json
Plan to run 1 test
Refreshing 1 target
> fx build src/developer/debug/debug_agent:debug_agent_unit_tests host_x64/debug_agent_unit_tests
Use --no-build to skip building
Executing build. Status output suspended.
ninja: Entering directory `/usr/local/google/home/jruthe/upstream/fuchsia/out/workbench_eng.x64'
[22/22](0) STAMP obj/src/developer/debug/debug_agent/debug_agent_unit_tests.stamp
Running 1 test
Starting: fuchsia-pkg://fuchsia.com/debug_agent_unit_tests#meta/debug_agent_unit_tests.cm (NOT HERMETIC)
Command: fx ffx test run --realm /core/testing:system-tests --max-severity-logs WARN --break-on-failure fuchsia-pkg://fuchsia.com/debug_agent_unit_tests?hash=399ff8d9871a6f0d53557c3d7c233cad645061016d44a7855dcea2c7b8af8101#meta/debug_agent_unit_tests.cm
Deleting 1 files at /tmp/tmp8m56ht95: ffx_logs/ffx.log
To keep these files, set --ffx-output-directory.
PASSED: fuchsia-pkg://fuchsia.com/debug_agent_unit_tests#meta/debug_agent_unit_tests.cm
Status: [duration: 16.9s] [tests: PASS: 1 FAIL: 0 SKIP: 0]
Running 1 tests [=====================================================================================================] 100.0%
由於您已成功修正所有測試失敗問題,因此 zxdb 不會再顯示。