| // 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 |