blob: 0f982570ba2a01adf466c9f03008e0600591bf96 [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 "garnet/bin/run_test_component/test_metadata.h"
#include <unordered_set>
#include "garnet/lib/cmx/cmx.h"
#include "lib/fxl/strings/substitute.h"
#include <fuchsia/net/cpp/fidl.h>
#include <fuchsia/net/stack/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
namespace run {
namespace {
using fxl::Substitute;
constexpr char kInjectedServices[] = "injected-services";
constexpr char kSystemServices[] = "system-services";
const std::unordered_set<std::string> kAllowedSystemServices = {
fuchsia::net::Connectivity::Name_,
fuchsia::net::SocketProvider::Name_,
fuchsia::net::stack::Stack::Name_,
fuchsia::netstack::Netstack::Name_,
};
} // namespace
TestMetadata::TestMetadata() {}
TestMetadata::~TestMetadata() {}
fuchsia::sys::LaunchInfo TestMetadata::GetLaunchInfo(
const rapidjson::Document::ValueType& value, const std::string& name) {
fuchsia::sys::LaunchInfo launch_info;
if (value.IsString()) {
launch_info.url = value.GetString();
return launch_info;
}
if (value.IsArray()) {
const auto& array = value.GetArray();
// If the element is an array, ensure it is non-empty and all values are
// strings.
if (!array.Empty() && std::all_of(array.begin(), array.end(),
[](const rapidjson::Value& val) {
return val.IsString();
})) {
launch_info.url = array[0].GetString();
for (size_t i = 1; i < array.Size(); ++i) {
launch_info.arguments.push_back(array[i].GetString());
}
return launch_info;
}
}
json_parser_.ReportError(Substitute(
"'$0' must be a string or a non-empty array of strings.", name));
return launch_info;
}
bool TestMetadata::ParseFromFile(const std::string& cmx_file_path) {
component::CmxMetadata cmx;
cmx.ParseFromFileAt(-1, cmx_file_path, &json_parser_);
if (json_parser_.HasError()) {
return false;
}
auto& fuchisa_test = cmx.GetFacet(kFuchsiaTest);
if (!fuchisa_test.IsNull()) {
null_ = false;
if (!fuchisa_test.IsObject()) {
json_parser_.ReportError(
Substitute("'$0' in 'facets' should be an object.", kFuchsiaTest));
return false;
}
auto allow_network_services = fuchisa_test.FindMember(kSystemServices);
if (allow_network_services != fuchisa_test.MemberEnd()) {
if (!allow_network_services->value.IsArray()) {
json_parser_.ReportError(
Substitute("'$0' in '$1' should be a string array.",
kSystemServices, kFuchsiaTest));
} else {
const auto& array = allow_network_services->value.GetArray();
std::all_of(
array.begin(), array.end(), [&](const rapidjson::Value& val) {
if (!val.IsString()) {
json_parser_.ReportError(
Substitute("'$0' in '$1' should be a string array.",
kSystemServices, kFuchsiaTest));
return false;
}
std::string service = val.GetString();
if (kAllowedSystemServices.count(service) == 0) {
json_parser_.ReportError(fxl::Substitute(
"'$0' cannot contain '$1'.", kSystemServices, service));
return false;
}
system_services_.push_back(service);
return true;
});
}
}
auto services = fuchisa_test.FindMember(kInjectedServices);
if (services != fuchisa_test.MemberEnd()) {
if (!services->value.IsObject()) {
json_parser_.ReportError(Substitute("'$0' in '$1' should be an object.",
kInjectedServices, kFuchsiaTest));
return false;
}
for (auto itr = services->value.MemberBegin();
itr != services->value.MemberEnd(); ++itr) {
if (!itr->name.IsString()) {
json_parser_.ReportError(
Substitute("'$0' in '$1' should define string service names.",
kInjectedServices, kFuchsiaTest));
return false;
}
auto name = itr->name.GetString();
auto launch_info = GetLaunchInfo(itr->value, name);
service_url_pair_.push_back(
std::make_pair(name, std::move(launch_info)));
}
}
}
return !HasError();
}
} // namespace run