blob: 97b5c3d0e2f4850b2f796302eb211e33809c958d [file] [log] [blame]
// Copyright 2017 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 "peridot/lib/testing/testing.h"
#include <set>
#include <fuchsia/cpp/test_runner.h>
#include "lib/fxl/logging.h"
namespace modular {
namespace testing {
namespace {
test_runner::TestRunnerPtr g_test_runner;
test_runner::TestRunnerStorePtr g_test_runner_store;
std::set<std::string> g_test_points;
bool g_connected;
} // namespace
void Init(component::ApplicationContext* app_context,
const std::string& identity) {
FXL_CHECK(app_context);
FXL_CHECK(!g_test_runner.is_bound());
FXL_CHECK(!g_test_runner_store.is_bound());
g_test_runner =
app_context->ConnectToEnvironmentService<test_runner::TestRunner>();
g_test_runner.set_error_handler([] {
if (g_connected) {
FXL_LOG(ERROR) << "Lost connection to TestRunner. Did the active test "
"call Logout() while modules were still running?";
} else {
FXL_LOG(ERROR) << "This application must be run under test_runner.";
}
exit(1);
});
g_test_runner->Identify(identity, [] { g_connected = true; });
g_test_runner->SetTestPointCount(g_test_points.size());
g_test_runner_store =
app_context->ConnectToEnvironmentService<test_runner::TestRunnerStore>();
}
void Fail(const std::string& log_msg) {
if (g_test_runner.is_bound()) {
g_test_runner->Fail(log_msg);
}
}
void Done(const std::function<void()>& ack) {
if (g_test_runner.is_bound()) {
g_test_runner->Done([ack] {
ack();
g_test_runner.Unbind();
});
} else {
ack();
}
if (g_test_runner_store.is_bound()) {
g_test_runner_store.Unbind();
}
}
void Teardown(const std::function<void()>& ack) {
if (g_test_runner.is_bound()) {
g_test_runner->Teardown([ack] {
ack();
g_test_runner.Unbind();
});
} else {
ack();
}
if (g_test_runner_store.is_bound()) {
g_test_runner_store.Unbind();
}
}
void WillTerminate(double withinSeconds) {
if (g_test_runner.is_bound()) {
g_test_runner->WillTerminate(withinSeconds);
}
}
test_runner::TestRunnerStore* GetStore() {
FXL_CHECK(g_test_runner_store.is_bound());
return g_test_runner_store.get();
}
namespace internal {
void RegisterTestPoint(const std::string& label) {
// Test points can only be registered before Init is called.
FXL_CHECK(!g_test_runner.is_bound())
<< "Test Runner connection not bound. You must call "
<< "ComponentBase::TestInit() before registering "
<< "\"" << label << "\".";
auto inserted = g_test_points.insert(label);
// Test points must have unique labels.
FXL_CHECK(inserted.second) << "Test points must have unique labels. "
<< "\"" << label << "\" is repeated.";
}
void PassTestPoint(const std::string& label) {
// Test points can only be passed after initialization.
FXL_CHECK(g_test_runner.is_bound())
<< "Test Runner connection not bound. You must call "
<< "ComponentBase::TestInit() before \"" << label << "\".Pass() can be "
<< "called.";
// Test points can only be passed once.
FXL_CHECK(g_test_points.erase(label))
<< "TEST FAILED: Test point can only be passed once. "
<< "\"" << label << "\".Pass() has been called twice.";
g_test_runner->PassTestPoint();
}
} // namespace internal
} // namespace testing
} // namespace modular