blob: 7f8bf29cd05ef9f164c54b654f26c40f9df59051 [file] [log] [blame]
// Copyright 2019 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/async/cpp/task.h>
#include <lib/zx/channel.h>
#include "garnet/lib/inferior_control/process.h"
#include "garnet/lib/inferior_control/test_server.h"
#include "gtest/gtest.h"
namespace inferior_control {
namespace {
// TODO(dje): Obtain path more cleanly.
const char helper_program[] =
"/pkgfs/packages/inferior_control_tests/0/bin/"
"inferior_control_test_helper";
// Test resume from exception and try-next.
// Note: Exceptions are handled in the same thread as server.Run().
class ThreadTest : public TestServer {
public:
ThreadTest() = default;
bool got_sw_breakpoint() const { return got_sw_breakpoint_; }
bool got_unexpected_exception() const { return got_unexpected_exception_; }
void OnArchitecturalException(
Process* process, Thread* thread, const zx_excp_type_t type,
const zx_exception_context_t& context) {
FXL_LOG(INFO) << "Got exception 0x" << std::hex << type;
if (type == ZX_EXCP_SW_BREAKPOINT) {
got_sw_breakpoint_ = true;
thread->TryNext();
} else {
// We shouldn't get here, test has failed.
// Record the fact for the test, and terminate the inferior, we don't
// want the exception propagating to the system exception handler.
got_unexpected_exception_ = true;
zx_task_kill(process->handle());
}
}
private:
bool got_sw_breakpoint_ = false;
bool got_unexpected_exception_ = false;
};
TEST_F(ThreadTest, ResumeTryNextTest) {
std::vector<std::string> argv{
helper_program,
"test-try-next",
};
ASSERT_TRUE(SetupInferior(argv));
zx::channel our_channel, their_channel;
auto status = zx::channel::create(0, &our_channel, &their_channel);
ASSERT_EQ(status, ZX_OK);
EXPECT_TRUE(RunHelperProgram(std::move(their_channel)));
// The inferior is waiting for us to close our side of the channel.
our_channel.reset();
EXPECT_TRUE(Run());
EXPECT_TRUE(TestSuccessfulExit());
EXPECT_TRUE(got_sw_breakpoint());
EXPECT_FALSE(got_unexpected_exception());
}
} // namespace
} // namespace inferior_control