blob: f86c77683bbd0932b96c8245f9c0770029f89ed8 [file] [log] [blame]
// Copyright 2020 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 "src/developer/debug/zxdb/console/commands/verb_attach_job.h"
#include <gtest/gtest.h>
#include "src/developer/debug/zxdb/console/commands/attach_command_test.h"
namespace zxdb {
namespace {
class VerbAttachJob : public AttachCommandTest {};
} // namespace
TEST_F(VerbAttachJob, Bad) {
// No arguments.
console().ProcessInputLine("attach-job");
auto event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Not enough arguments when reading the job koid.", event.output.AsString());
// Bad job koid.
constexpr uint64_t kBadJobKoid = 12345u;
console().ProcessInputLine("attach-job 12345");
ASSERT_TRUE(attach_remote_api()->last_attach);
ASSERT_EQ(kBadJobKoid, attach_remote_api()->last_attach->request.koid);
debug_ipc::AttachReply reply;
reply.status = debug::Status("Bad job");
attach_remote_api()->last_attach->cb(Err(), reply);
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Job 1 attach-job failed.\nError attaching: Bad job", event.output.AsString());
// Remove the job, this will delete the default job that exists.
console().ProcessInputLine("job 1 rm");
event = console().GetOutputEvent();
EXPECT_EQ(R"(Removed Job 1 state="Not attached" name="")", event.output.AsString());
// Now try to attach again (with no job objects alive), this should create a new job object but
// fail to attach it.
console().ProcessInputLine("attach-job 12345");
attach_remote_api()->last_attach->cb(Err(), reply);
event = console().GetOutputEvent();
EXPECT_EQ("Job 2 attach-job failed.\nError attaching: Bad job", event.output.AsString());
}
TEST_F(VerbAttachJob, Good) {
// Good job koid.
constexpr uint64_t kGoodJobKoid1 = 7890u;
console().ProcessInputLine("attach-job 7890");
ASSERT_TRUE(attach_remote_api()->last_attach);
ASSERT_EQ(kGoodJobKoid1, attach_remote_api()->last_attach->request.koid);
debug_ipc::AttachReply reply;
reply.status = debug::Status();
reply.koid = kGoodJobKoid1;
reply.name = "some job";
attach_remote_api()->last_attach->cb(Err(), reply);
EXPECT_TRUE(attach_remote_api()->filters.empty());
auto event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Job 1 state=Attached koid=7890 name=\"some job\"", event.output.AsString());
// Attaching a job with some filters. Since the current job is already attached, this should make
// a new job (#2).
constexpr uint64_t kGoodJobKoid2 = 5555u;
attach_remote_api()->last_attach = std::nullopt;
console().ProcessInputLine("attach-job 5555 foo bar");
// It will immediately make two filters to apply to the new job.
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Created Filter 1 pattern=foo job=2", event.output.AsString());
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Created Filter 2 pattern=bar job=2", event.output.AsString());
// Report job attachment a success.
ASSERT_TRUE(attach_remote_api()->last_attach);
ASSERT_EQ(kGoodJobKoid2, attach_remote_api()->last_attach->request.koid);
reply.status = debug::Status();
reply.koid = kGoodJobKoid2;
reply.name = "other job";
attach_remote_api()->last_attach->cb(Err(), reply);
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Job 2 state=Attached koid=5555 name=\"other job\"", event.output.AsString());
// The single update should contain both filters since it should be sent after the job attach
// callback is run (so both filters will be applied at once even though they were created in
// sequence).
ASSERT_EQ(1u, attach_remote_api()->filters.size());
auto& filters0 = attach_remote_api()->filters[0].request;
EXPECT_EQ(kGoodJobKoid2, filters0.job_koid);
ASSERT_EQ(2u, filters0.filters.size());
EXPECT_EQ("foo", filters0.filters[0]);
EXPECT_EQ("bar", filters0.filters[1]);
// Attach to the same koid. This should append the filter.
attach_remote_api()->last_attach = std::nullopt;
console().ProcessInputLine("attach-job 5555 baz");
ASSERT_FALSE(attach_remote_api()->last_attach); // No messages should have been sent.
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("Created Filter 3 pattern=baz job=2", event.output.AsString());
// Validate the jobs and filters.
console().ProcessInputLine("job");
event = console().GetOutputEvent();
EXPECT_EQ(
" # State Koid Name\n"
" 1 Attached 7890 some job\n"
"▶ 2 Attached 5555 other job\n",
event.output.AsString());
console().ProcessInputLine("filter");
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ(
" # pattern job\n"
" 1 foo 2\n"
" 2 bar 2\n"
"▶ 3 baz 2\n",
event.output.AsString());
// Remove the active job. This should delete the associated filters also.
console().ProcessInputLine("job 2 rm");
event = console().GetOutputEvent();
EXPECT_EQ(R"(Removed Job 2 state=Attached koid=5555 name="other job")", event.output.AsString());
console().ProcessInputLine("job");
event = console().GetOutputEvent();
EXPECT_EQ(
" # State Koid Name\n"
" 1 Attached 7890 some job\n",
event.output.AsString());
console().ProcessInputLine("filter");
event = console().GetOutputEvent();
EXPECT_EQ(MockConsole::OutputEvent::Type::kOutput, event.type);
EXPECT_EQ("No filters.\n", event.output.AsString());
// Attaching again should maje a new job object and set it as the default.
console().ProcessInputLine("attach-job 5555");
attach_remote_api()->last_attach->cb(Err(), reply);
event = console().GetOutputEvent();
EXPECT_EQ("Job 3 state=Attached koid=5555 name=\"other job\"", event.output.AsString());
console().ProcessInputLine("job");
event = console().GetOutputEvent();
EXPECT_EQ(
" # State Koid Name\n"
" 1 Attached 7890 some job\n"
"▶ 3 Attached 5555 other job\n",
event.output.AsString());
}
} // namespace zxdb