blob: 91fb4a8d4189d59e2393ea41fb29004b92e6c0d6 [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.
#include "src/sys/run_test_component/run_test_component.h"
#include <glob.h>
#include <lib/fit/defer.h>
#include <lib/fitx/result.h>
#include <lib/sys/cpp/service_directory.h>
#include <limits.h>
#include <sstream>
#include <string>
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/strings/substitute.h"
#include "src/lib/pkg_url/fuchsia_pkg_url.h"
namespace run {
static constexpr char kLabelArgPrefix[] = "--realm-label=";
static constexpr char kTimeoutArgPrefix[] = "--timeout=";
static constexpr char kSeverityArgPrefix[] = "--min-severity-logs=";
static constexpr char kMaxSeverityArgPrefix[] = "--max-log-severity=";
bool to_bool(std::string str) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::istringstream is(str);
bool b;
is >> std::boolalpha >> b;
return b;
}
fitx::result<bool, uint32_t> ParseLogLevel(const std::string& level) {
if (level == "TRACE") {
return fitx::success(syslog::LOG_TRACE);
}
if (level == "DEBUG") {
return fitx::success(syslog::LOG_DEBUG);
}
if (level == "INFO") {
return fitx::success(syslog::LOG_INFO);
}
if (level == "WARN") {
return fitx::success(syslog::LOG_WARNING);
}
if (level == "ERROR") {
return fitx::success(syslog::LOG_ERROR);
}
if (level == "FATAL") {
return fitx::success(syslog::LOG_FATAL);
}
return fitx::error(false);
}
ParseArgsResult ParseArgs(const std::shared_ptr<sys::ServiceDirectory>& services, int argc,
const char** argv) {
ParseArgsResult result;
result.error = false;
result.timeout = -1;
int url_or_matcher_argi = 1;
std::string url;
while (true) {
if (argc < url_or_matcher_argi + 1) {
result.error = true;
result.error_msg = "Missing test URL, or matcher argument";
return result;
}
std::string argument = argv[url_or_matcher_argi];
const size_t kLabelArgPrefixLength = strlen(kLabelArgPrefix);
const size_t kTimeoutArgPrefixLength = strlen(kTimeoutArgPrefix);
const size_t kSeverityArgPrefixLength = strlen(kSeverityArgPrefix);
const size_t kMaxSeverityArgPrefixLength = strlen(kMaxSeverityArgPrefix);
if (argument.substr(0, kLabelArgPrefixLength) == kLabelArgPrefix) {
result.realm_label = argument.substr(kLabelArgPrefixLength);
url_or_matcher_argi++;
continue;
}
if (argument.substr(0, kSeverityArgPrefixLength) == kSeverityArgPrefix) {
std::string level = argument.substr(kSeverityArgPrefixLength);
auto level_result = ParseLogLevel(level);
if (level_result.is_error()) {
result.error = true;
result.error_msg = fxl::StringPrintf("Invalid --min-severity-logs %s", level.c_str());
return result;
}
result.min_log_severity = level_result.value();
url_or_matcher_argi++;
continue;
}
if (argument.substr(0, kMaxSeverityArgPrefixLength) == kMaxSeverityArgPrefix) {
std::string level = argument.substr(kMaxSeverityArgPrefixLength);
auto level_result = ParseLogLevel(level);
if (level_result.is_error()) {
result.error = true;
result.error_msg = fxl::StringPrintf("Invalid --max-log-severity %s", level.c_str());
return result;
}
result.max_log_severity = level_result.value();
url_or_matcher_argi++;
continue;
}
if (argument.substr(0, kTimeoutArgPrefixLength) == kTimeoutArgPrefix) {
std::string arg = argument.substr(kTimeoutArgPrefixLength);
std::istringstream stream(arg);
stream >> result.timeout;
if (stream.fail() || result.timeout <= 0) {
result.error = true;
result.error_msg = fxl::StringPrintf("\"%s\" is not a valid timeout.", arg.c_str());
return result;
}
url_or_matcher_argi++;
continue;
}
url = argument;
break;
}
result.launch_info.url = url;
result.launch_info.arguments.emplace();
int i = url_or_matcher_argi + 1;
if (i < argc && std::string(argv[i]) != "--") {
printf(
"WARNING: Please use Option delimiter(--) before specifying test args. Current commandline "
"will error out in future. Use\n 'run-test-component [run-test-component-args] <test_url> "
"-- [test_args]'\n");
} else {
i++;
}
for (; i < argc; i++) {
result.launch_info.arguments->push_back(argv[i]);
}
return result;
}
std::string GetSimplifiedUrl(const std::string& url) {
component::FuchsiaPkgUrl furl;
furl.Parse(url);
return fxl::Substitute("fuchsia-pkg://$0/$1#$2", furl.host_name(), furl.package_name(),
furl.resource_path());
}
} // namespace run