blob: ef7fcd941ec90332f41a70351205aab2a3aef8ac [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lib/fit/defer.h"
#include "src/developer/debug/e2e_tests/e2e_test.h"
#include "src/developer/debug/e2e_tests/fuzzy_matcher.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/thread.h"
namespace zxdb {
namespace {
// Zxdb should be able to display an async backtrace from a single threaded executor in Rust.
class AsyncBacktrace : public E2eTest {
public:
void Run() {
console().ProcessInputLine(
"run-component fuchsia-pkg://fuchsia.com/zxdb_e2e_inferiors#meta/async_rust.cm");
loop().Run();
}
void OnThreadStopped(Thread* thread, const StopInfo& info) override {
console().ProcessInputLine("abt -v", [this](OutputBuffer output, std::vector<Err> errors) {
// Ensure the process is killed even when the following assertions fail.
auto _ = fit::defer([this]() { console().ProcessInputLine("kill"); });
// The output should look like
//
// MainTask
// └─ async_rust::main::func • select_mod.rs:321
// └─ select!
// └─ async_rust::foo • join_mod.rs:95
// └─ join!
// └─ async_rust::baz • async_rust.rs:35
// i = 10
// └─ async_rust::baz • async_rust.rs:35
// i = 11
// └─ async_rust::bar • async_rust.rs:28
// └─ async_rust::baz • async_rust.rs:35
// i = 30
// └─ async_rust::main::func::λ • async_rust.rs:12
// Task(id = 2)
// └─ async_rust::baz (Unresumed) • async_rust.rs:31
// i = 21
// Task(id = 1)
// └─ async_rust::baz • async_rust.rs:35
// i = 20
FuzzyMatcher matcher(output.AsString());
ASSERT_TRUE(matcher.MatchesLine({"MainTask"}));
ASSERT_TRUE(matcher.MatchesLine({"└─ async_rust::main::func"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ select!"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::foo"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ join!"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::baz • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" i = 10"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::baz • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" i = 11"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::bar • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::baz • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" i = 30"}));
ASSERT_TRUE(matcher.MatchesLine({" └─ async_rust::main::func::λ • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({"Task(id = 1)"}));
ASSERT_TRUE(matcher.MatchesLine({"└─ async_rust::baz • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" i = 20"}));
// Reset matcher because the order between Task(1) and Task(2) is nondeterministic.
matcher = FuzzyMatcher(output.AsString());
ASSERT_TRUE(matcher.MatchesLine({"Task(id = 2)"}));
ASSERT_TRUE(matcher.MatchesLine({"└─ async_rust::baz (Unresumed) • async_rust.rs:"}));
ASSERT_TRUE(matcher.MatchesLine({" i = 21"}));
});
}
void WillDestroyProcess(Process* process, DestroyReason reason, int exit_code,
uint64_t timestamp) override {
EXPECT_EQ(reason, DestroyReason::kKill);
loop().QuitNow();
}
};
} // namespace
TEST_F(AsyncBacktrace, AsyncBacktrace) { Run(); }
} // namespace zxdb