Page MenuHomePhorge

device-ops-test.cpp
No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None

device-ops-test.cpp

/*
* This file is part of libkazv.
* SPDX-FileCopyrightText: 2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_predicate.hpp>
#include <catch2/matchers/catch_matchers_contains.hpp>
#include <boost/asio.hpp>
#include <asio-promise-handler.hpp>
#include <cursorutil.hpp>
#include <sdk-model.hpp>
#include <client/client.hpp>
#include "client-test-util.hpp"
static void addDeviceToModel(ClientModel &model, std::string userId, std::string deviceId,
std::string displayName, DeviceTrustLevel trustLevel = DeviceTrustLevel::Unseen)
{
DeviceKeyInfo info{
deviceId,
deviceId + "ed25519",
deviceId + "curve25519",
displayName,
trustLevel,
};
model.deviceLists.deviceLists = std::move(model.deviceLists.deviceLists)
.update(userId, [=](auto deviceMap) {
return std::move(deviceMap).set(deviceId, info);
});
}
static void addRoomToModel(ClientModel &model, std::string roomId)
{
RoomModel room;
room.encrypted = true;
room.roomId = roomId;
room.shouldRotateSessionKey = false;
model.roomList.rooms = model.roomList.rooms.set(roomId, room);
}
static void addRoomMemberToModel(ClientModel &model, std::string roomId, std::string userId)
{
model.roomList.rooms = model.roomList.rooms.update(roomId, [userId, roomId](auto room) {
auto memberEvent = Event{json{
{"type", "m.room.member"},
{"state_key", userId},
{"event_id", "$roommember" + userId},
{"room_id", roomId},
{"content", {{"displayname", userId + "name"}, {"membership", "join"}}},
{"sender", userId},
}};
room.stateEvents = room.stateEvents.set(KeyOfState{"m.room.member", userId}, memberEvent);
return room;
});
}
static auto getModel()
{
auto model = createTestClientModel();
addDeviceToModel(model, "@test1:test1.org", "device1", "test1-device1");
addDeviceToModel(model, "@test1:test1.org", "device2", "test1-device2");
return model;
}
static auto getModelWithEncryptedRooms()
{
auto model = createTestClientModel();
addDeviceToModel(model, "@test1:test1.org", "device1", "test1-device1", Unseen);
addDeviceToModel(model, "@test1:test1.org", "device2", "test1-device2", Verified);
addDeviceToModel(model, "@test1:test1.org", "device3", "test1-device3", Seen);
addDeviceToModel(model, "@test2:test2.org", "device1", "test2-device1", Unseen);
addDeviceToModel(model, "@test2:test2.org", "device2", "test2-device2", Blocked);
addDeviceToModel(model, "@test2:test2.org", "device3", "test2-device3", Seen);
addRoomToModel(model, "!room1:tusooa.xyz");
addRoomMemberToModel(model, "!room1:tusooa.xyz", "@test1:test1.org");
addRoomToModel(model, "!room2:tusooa.xyz");
addRoomMemberToModel(model, "!room2:tusooa.xyz", "@test2:test2.org");
addRoomToModel(model, "!room3:tusooa.xyz");
addRoomMemberToModel(model, "!room3:tusooa.xyz", "@test1:test1.org");
addRoomMemberToModel(model, "!room3:tusooa.xyz", "@test2:test2.org");
return model;
}
using namespace Kazv::CursorOp;
using namespace Catch::Matchers;
TEST_CASE("devicesOfUser()", "[client][device-list-tracker]")
{
boost::asio::io_context io;
AsioPromiseHandler ph{io.get_executor()};
auto model = getModel();
auto store = createTestClientStoreFrom(model, ph);
auto client = Client(store.reader().map([](auto c) { return SdkModel{c}; }), store,
std::nullopt);
auto devices = +client.devicesOfUser("@test1:test1.org");
REQUIRE(devices.size() == 2);
REQUIRE_THAT(devices, Contains(Predicate<DeviceKeyInfo>([](auto d) { return d.deviceId == "device1"; })));
REQUIRE_THAT(devices, Contains(Predicate<DeviceKeyInfo>([](auto d) { return d.deviceId == "device2"; })));
}
TEST_CASE("setTrustLevel()", "[client][device-list-tracker]")
{
boost::asio::io_context io;
AsioPromiseHandler ph{io.get_executor()};
auto model = getModel();
auto store = createTestClientStoreFrom(model, ph);
auto client = Client(store.reader().map([](auto c) { return SdkModel{c}; }), store,
std::nullopt);
client.setDeviceTrustLevel("@test1:test1.org", "device1", Seen)
.then([client](auto s) {
REQUIRE(s.success());
REQUIRE_THAT((+client.devicesOfUser("@test1:test1.org")),
Contains(Predicate<DeviceKeyInfo>([](auto d) { return d.deviceId == "device1" && d.trustLevel == Seen; })));
});
io.run();
}
TEST_CASE("setTrustLevelNeededToSendKeys()", "[client][device-list-tracker]")
{
boost::asio::io_context io;
AsioPromiseHandler ph{io.get_executor()};
auto model = getModel();
auto store = createTestClientStoreFrom(model, ph);
auto client = Client(store.reader().map([](auto c) { return SdkModel{c}; }), store,
std::nullopt);
REQUIRE((+client.trustLevelNeededToSendKeys()) == Unseen);
client.setTrustLevelNeededToSendKeys(Verified)
.then([client](auto s) {
REQUIRE(s.success());
REQUIRE((+client.trustLevelNeededToSendKeys()) == Verified);
});
io.run();
}
TEST_CASE("maybeRotateSessions()", "[client][device-list-tracker]")
{
auto oldModel = getModelWithEncryptedRooms();
oldModel.trustLevelNeededToSendKeys = Seen;
WHEN("change a device display name")
{
auto newModel = oldModel;
addDeviceToModel(newModel, "@test1:test1.org", "device1", "some other things", Unseen);
newModel.maybeRotateSessions(oldModel);
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("change from unseen to blocked")
{
auto [newModel, dontCareEffect] = ClientModel::update(oldModel, SetDeviceTrustLevelAction{"@test1:test1.org", "device1", Blocked});
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("change from verified to unseen")
{
auto [newModel, dontCareEffect] = ClientModel::update(oldModel, SetDeviceTrustLevelAction{"@test1:test1.org", "device2", Unseen});
REQUIRE(newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("change from verified to seen")
{
auto [newModel, dontCareEffect] = ClientModel::update(oldModel, SetDeviceTrustLevelAction{"@test1:test1.org", "device2", Seen});
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("change from verified to blocked")
{
auto [newModel, dontCareEffect] = ClientModel::update(oldModel, SetDeviceTrustLevelAction{"@test1:test1.org", "device2", Blocked});
REQUIRE(newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("change from unseen to verified")
{
auto [newModel, dontCareEffect] = ClientModel::update(oldModel, SetDeviceTrustLevelAction{"@test2:test2.org", "device1", Verified});
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
}
TEST_CASE("maybeRotateSessions() when trustLevelNeededToSendKeys changed", "[client][device-list-tracker]")
{
auto oldModel = getModelWithEncryptedRooms();
oldModel.trustLevelNeededToSendKeys = Unseen;
WHEN("threshold didn't change")
{
auto newModel = oldModel;
newModel.maybeRotateSessions(oldModel);
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(!newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("threshold changed from unseen to blocked")
{
auto newModel = oldModel;
newModel.trustLevelNeededToSendKeys = Blocked;
newModel.maybeRotateSessions(oldModel);
REQUIRE(!newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("threshold changed from unseen to seen")
{
auto newModel = oldModel;
newModel.trustLevelNeededToSendKeys = Seen;
newModel.maybeRotateSessions(oldModel);
REQUIRE(newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
WHEN("threshold changed from seen to verified")
{
oldModel.trustLevelNeededToSendKeys = Seen;
auto newModel = oldModel;
newModel.trustLevelNeededToSendKeys = Verified;
newModel.maybeRotateSessions(oldModel);
REQUIRE(newModel.roomList.rooms["!room1:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room2:tusooa.xyz"].shouldRotateSessionKey);
REQUIRE(newModel.roomList.rooms["!room3:tusooa.xyz"].shouldRotateSessionKey);
}
}

File Metadata

Mime Type
text/x-c
Expires
Fri, Jul 18, 12:17 PM (1 d, 9 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
261697
Default Alt Text
device-ops-test.cpp (10 KB)

Event Timeline