blob: d84b5fd62cdaefd79d733b589782f159422fd3ec [file] [log] [blame]
// Copyright 2019 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/bringup/bin/device-name-provider/args.h"
#include <fuchsia/boot/llcpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/dispatcher.h>
#include <lib/fdio/spawn.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/sync/completion.h>
#include <lib/zx/process.h>
#include <zircon/processargs.h>
#include <fs/pseudo_dir.h>
#include <fs/service.h>
#include <fs/synchronous_vfs.h>
#include <mock-boot-arguments/server.h>
#include <zxtest/zxtest.h>
namespace {
constexpr char kInterface[] = "/dev/whatever/whatever";
constexpr char kNodename[] = "some-four-word-name";
constexpr char kEthDir[] = "/dev";
class FakeSvc {
public:
explicit FakeSvc(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher), vfs_(dispatcher) {
auto root_dir = fbl::MakeRefCounted<fs::PseudoDir>();
root_dir->AddEntry(::llcpp::fuchsia::boot::Arguments::Name,
fbl::MakeRefCounted<fs::Service>([this](zx::channel request) {
auto result =
fidl::BindServer(dispatcher_, std::move(request), &mock_boot_);
if (!result.is_ok()) {
return result.error();
}
return ZX_OK;
}));
zx::channel svc_remote;
ASSERT_OK(zx::channel::create(0, &svc_local_, &svc_remote));
vfs_.ServeDirectory(root_dir, std::move(svc_remote));
}
mock_boot_arguments::Server& mock_boot() { return mock_boot_; }
zx::channel& svc_chan() { return svc_local_; }
private:
async_dispatcher_t* dispatcher_;
fs::SynchronousVfs vfs_;
mock_boot_arguments::Server mock_boot_;
zx::channel svc_local_;
};
class ArgsTest : public zxtest::Test {
public:
ArgsTest() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread), fake_svc_(loop_.dispatcher()) {
loop_.StartThread("paver-test-loop");
}
~ArgsTest() { loop_.Shutdown(); }
FakeSvc& fake_svc() { return fake_svc_; }
const zx::channel& svc_root() { return fake_svc_.svc_chan(); }
private:
async::Loop loop_;
FakeSvc fake_svc_;
};
TEST_F(ArgsTest, DeviceNameProviderNoneProvided) {
int argc = 1;
const char* argv[] = {"device-name-provider"};
const char* error = nullptr;
DeviceNameProviderArgs args;
ASSERT_EQ(ParseArgs(argc, const_cast<char**>(argv), svc_root(), &error, &args), 0, "%s", error);
ASSERT_TRUE(args.interface.empty());
ASSERT_TRUE(args.nodename.empty());
ASSERT_EQ(args.ethdir, std::string("/dev/class/ethernet"));
ASSERT_EQ(error, nullptr);
}
TEST_F(ArgsTest, DeviceNameProviderAllProvided) {
int argc = 7;
const char* argv[] = {"device-name-provider",
"--nodename",
kNodename,
"--interface",
kInterface,
"--ethdir",
kEthDir};
const char* error = nullptr;
DeviceNameProviderArgs args;
ASSERT_EQ(ParseArgs(argc, const_cast<char**>(argv), svc_root(), &error, &args), 0, "%s", error);
ASSERT_EQ(args.interface, std::string(kInterface));
ASSERT_EQ(args.nodename, std::string(kNodename));
ASSERT_EQ(args.ethdir, std::string(kEthDir));
ASSERT_EQ(error, nullptr);
}
TEST_F(ArgsTest, DeviceNameProviderValidation) {
int argc = 2;
const char* argv[] = {
"device-name-provider",
"--interface",
};
DeviceNameProviderArgs args;
const char* error = nullptr;
ASSERT_LT(ParseArgs(argc, const_cast<char**>(argv), svc_root(), &error, &args), 0);
ASSERT_TRUE(args.interface.empty());
ASSERT_TRUE(strstr(error, "interface"));
argc = 2;
argv[1] = "--nodename";
args.interface = "";
args.nodename = "";
error = nullptr;
ASSERT_LT(ParseArgs(argc, const_cast<char**>(argv), svc_root(), &error, &args), 0);
ASSERT_TRUE(args.nodename.empty());
ASSERT_TRUE(strstr(error, "nodename"));
}
} // namespace