You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libcutefish/clients/networkmanager/tests/secretreader_test.cpp

110 lines
3.2 KiB
C++

// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
#include <gtest/gtest.h>
#include <chrono>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <vector>
#include "base/dbus.h"
#include "base/event_loop.h"
#include "base/timer.h"
#include "networkmanager/secretreader.h"
using namespace std::chrono_literals;
using namespace cutefish::base;
using cutefish::networkmanager::SecretReader;
using Paths = std::vector<dbus::ObjectPath>;
static EventLoop* loop = nullptr;
static bool waitFor(const std::function<bool()>& condition, std::chrono::milliseconds timeout = 3000ms)
{
if (condition())
return true;
bool met = false;
Timer poll;
poll.onTimeout = [&] {
if (condition()) {
met = true;
loop->quit();
}
};
poll.start(2ms);
Timer limit;
limit.setSingleShot(true);
limit.onTimeout = [&] { loop->quit(); };
limit.start(timeout);
loop->run();
return met || condition();
}
// A keyring whose only item is locked, and whose unlock prompt the user dismisses.
class FakeSecretService
{
public:
FakeSecretService()
: m_bus(dbus::Connection::open(dbus::Connection::Bus::Session))
, m_service(m_bus.get(), "/org/freedesktop/secrets", "org.freedesktop.Secret.Service")
, m_prompt(m_bus.get(), "/prompt/1", "org.freedesktop.Secret.Prompt")
{
m_service.addMethod("OpenSession", [](const std::string&, const dbus::Variant&) {
return std::tuple<dbus::Variant, dbus::ObjectPath>{dbus::Variant(std::string()),
dbus::ObjectPath{"/session/1"}};
});
m_service.addMethod("SearchItems", [](const std::map<std::string, std::string>&) {
return std::tuple<Paths, Paths>{Paths(), Paths{dbus::ObjectPath{"/item/1"}}};
});
m_service.addMethod("Unlock", [](const Paths&) {
return std::tuple<Paths, dbus::ObjectPath>{Paths(), dbus::ObjectPath{"/prompt/1"}};
});
m_service.publish();
m_prompt.addMethod("Prompt", [this](const std::string&) {
++prompts;
m_bus->emitSignal("/prompt/1", "org.freedesktop.Secret.Prompt", "Completed", true, dbus::Variant(Paths()));
});
m_prompt.addSignal("Completed", "bv");
m_prompt.publish();
}
bool serve() { return m_bus->requestName("org.freedesktop.secrets"); }
int prompts = 0;
private:
std::unique_ptr<dbus::Connection> m_bus;
dbus::Object m_service;
dbus::Object m_prompt;
};
TEST(SecretReaderTest, DismissedPromptAnswersWithNothing)
{
FakeSecretService service;
ASSERT_TRUE(service.serve());
std::optional<std::map<std::string, std::string>> loaded;
{
SecretReader reader;
reader.load("uuid", "vpn", [&](const std::map<std::string, std::string>& secrets) { loaded = secrets; });
ASSERT_TRUE(waitFor([&] { return loaded.has_value(); }));
}
EXPECT_EQ(service.prompts, 1);
EXPECT_TRUE(loaded->empty());
}
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
EventLoop eventLoop;
loop = &eventLoop;
return RUN_ALL_TESTS();
}