blob: a854ff8e35918cf90ecd47c632a27a9d2fe0f13f [file] [log] [blame]
// Copyright 2022 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/e2e_tests/script_test.h"
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <string>
#include <string_view>
#include <gtest/gtest.h>
#include "src/developer/debug/shared/string_util.h"
#include "src/developer/debug/zxdb/common/host_util.h"
#include "src/lib/fxl/strings/trim.h"
namespace zxdb {
namespace {
constexpr uint64_t kDefaultTimeout = 3; // in seconds
constexpr std::string_view kBuildType = ZXDB_E2E_TESTS_BUILD_TYPE;
} // namespace
void ScriptTest::TestBody() {
std::ifstream script_file(script_path_);
ASSERT_TRUE(script_file) << "Fail to open " << script_path_;
// Process directives first.
uint64_t timeout = kDefaultTimeout;
std::string line;
while (std::getline(script_file, line)) {
if (line.empty())
continue;
if (debug::StringStartsWith(line, "##")) {
std::string directive = std::string(fxl::TrimString(line.substr(2), " "));
if (debug::StringStartsWith(directive, "require ")) {
std::string requirement = directive.substr(8);
if (!debug::StringContains(kBuildType, requirement)) {
GTEST_SKIP() << "Skipped because of unmet requirement " << requirement;
}
} else if (debug::StringStartsWith(directive, "set timeout ")) {
timeout = std::stoul(directive.substr(12));
} else {
GTEST_FAIL() << "Unknown directive: " << directive;
}
} else if (debug::StringStartsWith(line, "#")) {
continue;
} else {
break;
}
}
script_file.close();
// Adjust timeout when running on bots so we're less likely to flake.
if (std::getenv("BUILDBUCKET_ID")) {
timeout *= 5;
}
ScriptRunner runner(&session(), &console());
runner.set_timeout_s(timeout);
bool script_success = false;
runner.Run(script_path_, [&](bool success) {
script_success = success;
loop().QuitNow();
});
loop().Run();
if (!script_success) {
FAIL() << "Script execution failed: " << script_path_ << "\n"
<< runner.GetFailureContext().AsString();
}
}
void ScriptTest::OnTestExited(const std::string& url) {
// Insert a definitive marker for a test component being completed. Scripts that use `run-test`
// will want to depend on this output so we remain listening for test_runner messages until it has
// completely shutdown.
loop().PostTask(FROM_HERE, [this, url]() { console().Output("Test Done: " + url, false); });
}
void ScriptTest::RegisterScriptTests() {
std::filesystem::path test_scripts_dir =
(std::filesystem::path(GetSelfPath()).parent_path() / ZXDB_E2E_TESTS_SCRIPTS_DIR)
.lexically_normal();
for (const auto& entry : std::filesystem::directory_iterator(test_scripts_dir)) {
if (entry.path().extension() == ".script") {
::testing::RegisterTest("ScriptTest", entry.path().stem().c_str(), nullptr, nullptr,
entry.path().c_str(), 0,
[=]() { return new ScriptTest(entry.path()); });
}
}
}
} // namespace zxdb