blob: ca15e5eb1841276ff0142306e6a29f166bb1b1d0 [file] [log] [blame] [edit]
// 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/syslog/cpp/macros.h>
#include "src/performance/trace_manager/tests/trace_manager_test.h"
namespace tracing {
namespace test {
using SessionState = TraceManagerTest::SessionState;
TEST_F(TraceManagerTest, RetryAfterFailedStop) {
ConnectToProvisionerService();
EXPECT_TRUE(AddFakeProvider(kProvider1Pid, kProvider1Name));
ASSERT_TRUE(InitializeSession());
ASSERT_TRUE(StartSession());
fuchsia_tracing_controller::StopOptions stop_options{GetDefaultStopOptions()};
session_client()->StopTracing({{std::move(stop_options)}}).ThenExactlyOnce([](auto& result) {
ASSERT_TRUE(result.is_error());
ASSERT_TRUE(result.error_value().is_domain_error());
ASSERT_EQ(result.error_value().domain_error(), fuchsia_tracing_controller::StopError::kAborted);
});
RunLoopUntilIdle();
ASSERT_EQ(GetSessionState(), SessionState::kStopping);
// Drop the socket before marking all providers stopped. This causes
// an error while writing the buffer to the socket. Trace session should
// abort and terminate.
DropSocket();
MarkAllProvidersStopped();
RunLoopUntilIdle();
ASSERT_EQ(GetSessionState(), SessionState::kTerminating);
MarkAllProvidersTerminated();
RunLoopUntilIdle();
ASSERT_EQ(GetSessionState(), SessionState::kNonexistent);
// Initialize a new session and verify that everything works fine
zx::socket our_socket, their_socket;
zx_status_t status = zx::socket::create(0u, &our_socket, &their_socket);
ASSERT_EQ(status, ZX_OK);
fuchsia_tracing_controller::TraceConfig config{GetDefaultTraceConfig()};
auto endpoints = fidl::Endpoints<fuchsia_tracing_controller::Session>::Create();
session_client() = fidl::Client(std::move(endpoints.client), dispatcher(), this);
auto initialize_result = provisioner_client()->InitializeTracing(
{{std::move(endpoints.server), std::move(config), std::move(their_socket)}});
ASSERT_TRUE(initialize_result.is_ok());
RunLoopUntilIdle();
ASSERT_EQ(GetSessionState(), SessionState::kInitialized);
RunLoopUntilIdle();
fuchsia_tracing_controller::StartOptions start_options{GetDefaultStartOptions()};
bool start_completed = false;
session_client()
->StartTracing({{std::move(start_options)}})
.ThenExactlyOnce([this, &start_completed](auto& result) {
start_completed = true;
QuitLoop();
});
RunLoopUntilIdle();
MarkAllProvidersStarted();
RunLoopUntilIdle();
ASSERT_EQ(GetSessionState(), SessionState::kStarted);
ASSERT_TRUE(StopSession());
ASSERT_TRUE(TerminateSession());
}
template <typename T>
void TryExtraStop(TraceManagerTest* fixture, const T& interface_ptr) {
fuchsia_tracing_controller::StopOptions stop_options{fixture->GetDefaultStopOptions()};
bool stop_completed = false;
interface_ptr->StopTracing({{std::move(stop_options)}})
.ThenExactlyOnce([fixture, &stop_completed](auto& result) {
ASSERT_TRUE(result.is_error());
ASSERT_TRUE(result.error_value().is_domain_error());
ASSERT_EQ(result.error_value().domain_error(),
fuchsia_tracing_controller::StopError::kNotStarted);
stop_completed = true;
fixture->QuitLoop();
});
fixture->RunLoopUntilIdle();
FX_LOGS(DEBUG) << "Loop done, expecting session still stopped";
EXPECT_TRUE(stop_completed);
EXPECT_EQ(fixture->GetSessionState(), SessionState::kStopped);
}
TEST_F(TraceManagerTest, ExtraStop) {
ConnectToProvisionerService();
EXPECT_TRUE(AddFakeProvider(kProvider1Pid, kProvider1Name));
ASSERT_TRUE(InitializeSession());
ASSERT_TRUE(StartSession());
ASSERT_TRUE(StopSession());
// Now try stopping again.
// This should complete with a NOT_STARTED error
TryExtraStop(this, session_client());
}
TEST_F(TraceManagerTest, StopWhileStopping) {
ConnectToProvisionerService();
FakeProvider* provider;
EXPECT_TRUE(AddFakeProvider(kProvider1Pid, kProvider1Name, &provider));
ASSERT_TRUE(InitializeSession());
ASSERT_TRUE(StartSession());
fuchsia_tracing_controller::StopOptions stop1_options{GetDefaultStopOptions()};
session_client()->StopTracing({{std::move(stop1_options)}}).ThenExactlyOnce([](auto& result) {
ASSERT_TRUE(result.is_ok());
});
RunLoopUntilIdle();
// The loop will exit for the transition to kStopping.
FX_LOGS(DEBUG) << "Loop done, expecting session stopping";
EXPECT_EQ(GetSessionState(), SessionState::kStopping);
// Now try another Stop while we're still in |kStopping|.
// The provider doesn't advance state until we tell it to, so we should
// still remain in |kStopping|.
fuchsia_tracing_controller::StopOptions stop2_options{GetDefaultStopOptions()};
bool stop_completed = false;
session_client()
->StopTracing({{std::move(stop2_options)}})
.ThenExactlyOnce([this, &stop_completed](auto& result) {
ASSERT_TRUE(result.is_error());
ASSERT_TRUE(result.error_value().is_domain_error());
ASSERT_EQ(result.error_value().domain_error(),
fuchsia_tracing_controller::StopError::kNotStarted);
stop_completed = true;
QuitLoop();
});
RunLoopUntilIdle();
FX_LOGS(DEBUG) << "Stop loop done";
EXPECT_TRUE(stop_completed);
EXPECT_TRUE(GetSessionState() == SessionState::kStopping);
MarkAllProvidersStopped();
RunLoopUntilIdle();
}
} // namespace test
} // namespace tracing