Skip to content

Commit

Permalink
Test daemon reading MAC addresses from JSON.
Browse files Browse the repository at this point in the history
  • Loading branch information
luis4a0 committed Nov 9, 2020
1 parent c634a19 commit 7627b35
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
2 changes: 1 addition & 1 deletion tests/stub_vm_image_vault.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace multipass
{
namespace test
{
struct StubVMImageVault final : public multipass::VMImageVault
struct StubVMImageVault : public multipass::VMImageVault
{
multipass::VMImage fetch_image(const multipass::FetchType&, const multipass::Query&, const PrepareAction& prepare,
const multipass::ProgressMonitor&) override
Expand Down
118 changes: 118 additions & 0 deletions tests/test_daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <multipass/vm_image_host.h>

#include "extra_assertions.h"
#include "file_operations.h"
#include "mock_environment_helpers.h"
#include "mock_process_factory.h"
#include "mock_standard_paths.h"
Expand All @@ -51,6 +52,8 @@
#include <gtest/gtest.h>

#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkProxyFactory>
#include <QSysInfo>

Expand Down Expand Up @@ -876,4 +879,119 @@ INSTANTIATE_TEST_SUITE_P(Daemon, LaunchImgSizeSuite,
Values(std::vector<std::string>{}, std::vector<std::string>{"--disk", "4G"}),
Values("1G", mp::default_disk_size, "10G")));

class NotEmptyStubVMImageVault final : public mpt::StubVMImageVault
{
bool has_record_for(const std::string& name) override
{
return name == "real-zebraphant";
}
};

std::string fake_json_contents(const std::string& default_mac, const std::vector<mp::NetworkInterface>& extra_ifaces)
{
QString contents("{\n"
" \"real-zebraphant\": {\n"
" \"deleted\": false,\n"
" \"disk_space\": \"5368709120\",\n"
" \"extra_interfaces\": [\n");

QStringList extra_json;
for (auto extra_interface : extra_ifaces)
{
extra_json += QString::fromStdString(fmt::format(" {{\n"
" \"auto_mode\": {},\n"
" \"id\": \"{}\",\n"
" \"mac_address\": \"{}\"\n"
" }}\n",
extra_interface.auto_mode, extra_interface.id,
extra_interface.mac_address));
}
contents += extra_json.join(',');

contents += QString::fromStdString(fmt::format(" ],\n"
" \"mac_addr\": \"{}\",\n"
" \"mem_size\": \"1073741824\",\n"
" \"metadata\": {{\n"
" \"arguments\": [\n"
" \"many\",\n"
" \"arguments\"\n"
" ],\n"
" \"machine_type\": \"dmc-de-lorean\"\n"
" }},\n"
" \"mounts\": [\n"
" ],\n"
" \"num_cores\": 1,\n"
" \"ssh_username\": \"ubuntu\",\n"
" \"state\": 2\n"
" }}\n"
"}}",
default_mac));

return contents.toStdString();
}

void check_interfaces_in_json(const QString& file, const std::string& mac,
const std::vector<mp::NetworkInterface>& extra_interfaces)
{
QByteArray json = mpt::load(file);

QJsonParseError parse_error;
const auto doc = QJsonDocument::fromJson(json, &parse_error);
EXPECT_FALSE(doc.isNull());
EXPECT_TRUE(doc.isObject());

const auto instance = doc[QString("real-zebraphant")];
const auto default_mac = instance["mac_addr"].toString().toStdString();
ASSERT_EQ(default_mac, mac);

const auto extra = instance["extra_interfaces"].toArray();

auto it = extra_interfaces.cbegin();
for (const auto& extra_i : extra)
{
const auto interface = extra_i.toObject();
ASSERT_EQ(interface["mac_address"].toString().toStdString(), it->mac_address);
ASSERT_EQ(interface["id"].toString().toStdString(), it->id);
ASSERT_EQ(interface["auto_mode"].toBool(), it->auto_mode);
++it;
}
}

TEST_F(Daemon, reads_mac_addresses_from_json)
{
config_builder.vault = std::make_unique<NotEmptyStubVMImageVault>();

std::string mac_addr("52:54:00:73:76:28");
std::vector<mp::NetworkInterface> extra_interfaces{
mp::NetworkInterface{"wlx60e3270f55fe", "52:54:00:bd:19:41", true},
mp::NetworkInterface{"enp3s0", "01:23:45:67:89:ab", false}};

std::string json_contents = fake_json_contents(mac_addr, extra_interfaces);

mpt::TempDir temp_dir;
QString filename(temp_dir.path() + "/multipassd-vm-instances.json");

mpt::make_file_with_content(filename, json_contents);

// Make the daemon look for the JSON on our temporary directory. It will read the contents of the file.
config_builder.data_directory = temp_dir.path();
mp::Daemon daemon{config_builder.build()};

// By issuing the `list` command, we check at least that the instance was indeed read and there were no errors.
std::stringstream stream;
send_command({"list"}, stream);
EXPECT_THAT(stream.str(), HasSubstr("real-zebraphant"));

// Removing the JSON is possible now because data was already read. This step is not necessary, but doing it we
// make sure that the file was indeed rewritten after the next step.
QFile::remove(filename);

// The purge command will be apparently no-op, because there are no deleted instances. However, it will trigger
// a rewriting of the JSON, which will be useful for us to check if the data was correctly read.
send_command({"purge"});

// Finally, check the contents of the file. If they match with what we read, we are done.
check_interfaces_in_json(filename, mac_addr, extra_interfaces);
}

} // namespace

0 comments on commit 7627b35

Please sign in to comment.