blob: 9de798bfdaa342ab9923a406ef16b3dd089bba2a [file] [log] [blame]
// Copyright 2018 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.
//
// This application is intenteded to be used for manual testing of
// the Cobalt logger client on Fuchsia by Cobalt engineers.
//
// It also serves as an example of how to use the Cobalt FIDL API.
//
// It is also invoked by the cobalt_client CQ and CI.
#include "garnet/bin/cobalt/testapp/cobalt_testapp.h"
#include <memory>
#include <sstream>
#include <string>
#include <fuchsia/cobalt/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include "garnet/bin/cobalt/testapp/cobalt_testapp_logger.h"
#include "garnet/bin/cobalt/testapp/tests.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/fidl/cpp/synchronous_interface_ptr.h"
#include "lib/fsl/vmo/file.h"
#include "lib/fxl/command_line.h"
#include "lib/fxl/log_settings_command_line.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/strings/string_view.h"
#include "lib/svc/cpp/services.h"
namespace cobalt {
namespace testapp {
// This app is not launched through appmgr as part of a package so we need the
// full path
constexpr char kLegacyConfigBinProtoPath[] =
"/pkgfs/packages/cobalt_tests/0/data/legacy_cobalt_metrics.pb";
constexpr char kConfigBinProtoPath[] =
"/pkgfs/packages/cobalt_tests/0/data/cobalt_metrics.pb";
fuchsia::cobalt::ProjectProfile CobaltTestApp::LoadCobaltConfig(
CobaltConfigType type) {
fsl::SizedVmo config_vmo;
auto path = "";
switch (type) {
case kLegacyCobaltConfig:
path = kLegacyConfigBinProtoPath;
break;
case kCobaltConfig:
path = kConfigBinProtoPath;
break;
}
bool success = fsl::VmoFromFilename(path, &config_vmo);
FXL_CHECK(success) << "Could not read Cobalt config file into VMO";
fuchsia::cobalt::ProjectProfile profile;
profile.config = std::move(config_vmo).ToTransport();
return profile;
}
bool CobaltTestApp::RunTests() {
if (!RunTestsWithRequestSendSoon()) {
return false;
}
if (!RunTestsWithBlockUntilEmpty()) {
return false;
}
if (do_environment_test_) {
return RunTestsUsingServiceFromEnvironment();
} else {
FXL_LOG(INFO) << "Skipping RunTestsUsingServiceFromEnvironment because "
"--skip_environment_test was passed.";
}
return true;
}
void CobaltTestApp::Connect(uint32_t schedule_interval_seconds,
uint32_t min_interval_seconds,
CobaltConfigType type,
uint32_t initial_interval_seconds) {
controller_.Unbind();
component::Services services;
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = "fuchsia-pkg://fuchsia.com/cobalt#meta/cobalt.cmx";
launch_info.directory_request = services.NewRequest();
{
std::ostringstream stream;
stream << "--schedule_interval_seconds=" << schedule_interval_seconds;
launch_info.arguments.push_back(stream.str());
}
if (initial_interval_seconds > 0) {
std::ostringstream stream;
stream << "--initial_interval_seconds=" << initial_interval_seconds;
launch_info.arguments.push_back(stream.str());
}
{
std::ostringstream stream;
stream << "--min_interval_seconds=" << min_interval_seconds;
launch_info.arguments.push_back(stream.str());
}
{
std::ostringstream stream;
stream << "--verbose=" << fxl::GetVlogVerbosity();
launch_info.arguments.push_back(stream.str());
}
context_->launcher()->CreateComponent(std::move(launch_info),
controller_.NewRequest());
controller_.set_error_handler([](zx_status_t status) {
FXL_LOG(ERROR) << "Connection error from CobaltTestApp to CobaltClient.";
});
fuchsia::cobalt::LoggerFactorySyncPtr logger_factory;
services.ConnectToService(logger_factory.NewRequest());
fuchsia::cobalt::Status status = fuchsia::cobalt::Status::INTERNAL_ERROR;
logger_factory->CreateLogger(LoadCobaltConfig(type),
logger_.logger_.NewRequest(), &status);
FXL_CHECK(status == fuchsia::cobalt::Status::OK)
<< "CreateLogger() => " << StatusToString(status);
logger_factory->CreateLoggerSimple(
LoadCobaltConfig(type), logger_.logger_simple_.NewRequest(), &status);
FXL_CHECK(status == fuchsia::cobalt::Status::OK)
<< "CreateLoggerSimple() => " << StatusToString(status);
services.ConnectToService(cobalt_controller_.NewRequest());
}
bool CobaltTestApp::RunTestsWithRequestSendSoon() {
// With the following values for the scheduling parameters we are
// essentially configuring the ShippingManager to be in manual mode. It will
// never send Observations because of the schedule and send them immediately
// in response to RequestSendSoon().
Connect(999999999, 0, kLegacyCobaltConfig);
// Invoke LegacyRequestSendSoonTests() three times and return true if it
// succeeds all three times.
for (int i = 0; i < 3; i++) {
FXL_LOG(INFO) << "\nRunTestsWithRequestSendSoon (legacy config) iteration "
<< i << ".";
if (!LegacyRequestSendSoonTests()) {
return false;
}
}
// Reconnect using the cobalt 1.0 config.
Connect(999999999, 0, kCobaltConfig);
for (int i = 0; i < 3; i++) {
FXL_LOG(INFO) << "\nRunTestsWithRequestSendSoon (v1.0 config) iteration "
<< i << ".";
if (!RequestSendSoonTests()) {
return false;
}
}
return true;
}
bool CobaltTestApp::RunTestsWithBlockUntilEmpty() {
Connect(1, 0, kLegacyCobaltConfig);
// Invoke TestLogStringUsingBlockUntilEmpty() three times and
// return true if it succeeds all three times.
for (int i = 0; i < 3; i++) {
FXL_LOG(INFO) << "\nRunTestsWithBlockUntilEmpty iteration " << i << ".";
if (!legacy::TestLogStringUsingBlockUntilEmpty(&logger_)) {
return false;
}
}
return true;
}
bool CobaltTestApp::RunTestsUsingServiceFromEnvironment() {
// Connect to the Cobalt FIDL service provided by the environment.
fuchsia::cobalt::LoggerFactorySyncPtr logger_factory;
context_->ConnectToEnvironmentService(logger_factory.NewRequest());
fuchsia::cobalt::Status status = fuchsia::cobalt::Status::INTERNAL_ERROR;
logger_factory->CreateLogger(LoadCobaltConfig(kLegacyCobaltConfig),
logger_.logger_.NewRequest(), &status);
FXL_CHECK(status == fuchsia::cobalt::Status::OK)
<< "CreateLogger() => " << StatusToString(status);
logger_factory->CreateLoggerSimple(LoadCobaltConfig(kLegacyCobaltConfig),
logger_.logger_simple_.NewRequest(),
&status);
FXL_CHECK(status == fuchsia::cobalt::Status::OK)
<< "CreateLoggerSimple() => " << StatusToString(status);
// Invoke TestLogEventUsingServiceFromEnvironment() three times
// and return true if it succeeds all three times.
for (int i = 0; i < 3; i++) {
FXL_LOG(INFO) << "\nRunTestsUsingServiceFromEnvironment iteration " << i
<< ".";
// TODO(zmbush): Add a test from environment for v1.0
if (!legacy::TestLogEventUsingServiceFromEnvironment(&logger_)) {
return false;
}
}
return true;
}
#define TRY_TEST(test) \
if (!(test)) { \
return false; \
}
bool CobaltTestApp::LegacyRequestSendSoonTests() {
TRY_TEST(legacy::TestLogEvent(&logger_));
TRY_TEST(legacy::TestLogEventCount(&logger_));
TRY_TEST(legacy::TestLogElapsedTime(&logger_));
TRY_TEST(legacy::TestLogFrameRate(&logger_));
TRY_TEST(legacy::TestLogMemoryUsage(&logger_));
TRY_TEST(legacy::TestLogString(&logger_));
TRY_TEST(legacy::TestLogTimer(&logger_));
TRY_TEST(legacy::TestLogIntHistogram(&logger_));
TRY_TEST(legacy::TestLogCustomEvent(&logger_));
return true;
}
bool CobaltTestApp::RequestSendSoonTests() {
// TODO(zmbush): Create tests for all logger methods (as we have for legacy).
TRY_TEST(TestLogEvent(&logger_));
TRY_TEST(TestLogCustomEvent(&logger_));
return true;
}
} // namespace testapp
} // namespace cobalt