一次性重排,无任何行为改动。四个目录各自的 .clang-format 放在仓库里已久,但全组织只有 MSIME-Linux 在 CI 里执行 clang-format 检查,这边 149 个文件里有 149 个不符合自己声明的风格。 已逐文件核对语义等价:去掉空白、注释与相邻字符串字面量拆分之后,全部 149 个文件与重排前逐字节 相同。差异只有三类——缩进与换行、clang-format 补的 } // namespace 结尾注释、以及长字符串被拆成 相邻字面量(C++ 保证自动拼接)。 这个提交会写进 .git-blame-ignore-revs。
124 lines
4.2 KiB
C++
124 lines
4.2 KiB
C++
#include "ipc/active_client_state.h"
|
|
#include "ipc/focus_session_policy.h"
|
|
#include "tests/includes/test_framework.h"
|
|
|
|
TEST_CASE(active_client_stale_deactivation_cannot_clear_new_active_client)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto first_a = state.activate(1001);
|
|
REQUIRE(first_a.changed);
|
|
const auto b = state.activate(2002);
|
|
REQUIRE(b.changed);
|
|
const auto second_a = state.activate(1001);
|
|
REQUIRE(second_a.changed);
|
|
|
|
REQUIRE_EQ(state.deactivate(2002), 0u);
|
|
REQUIRE(state.matches(1001, second_a.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_implicit_input_activation_is_idempotent)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto first = state.activate(1001);
|
|
REQUIRE(first.changed);
|
|
const auto repeated = state.activate(1001);
|
|
REQUIRE(!repeated.changed);
|
|
REQUIRE_EQ(repeated.epoch, first.epoch);
|
|
|
|
state.activate(2002);
|
|
const auto recovered = state.activate(1001);
|
|
REQUIRE(recovered.changed);
|
|
REQUIRE(state.matches(1001, recovered.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_old_epoch_tasks_are_rejected)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto old_a = state.activate(1001);
|
|
state.activate(2002);
|
|
const auto current_a = state.activate(1001);
|
|
|
|
REQUIRE(!state.matches(1001, old_a.epoch));
|
|
REQUIRE(state.matches(1001, current_a.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_same_client_reconnect_advances_epoch)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto old_session = state.activate(1001);
|
|
REQUIRE(state.deactivate(1001) != 0);
|
|
const auto new_session = state.activate(1001);
|
|
|
|
REQUIRE(new_session.changed);
|
|
REQUIRE(old_session.epoch != new_session.epoch);
|
|
REQUIRE(!state.matches(1001, old_session.epoch));
|
|
REQUIRE(state.matches(1001, new_session.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_transport_failure_invalidates_only_exact_epoch)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto old_session = state.activate(1001);
|
|
REQUIRE(state.invalidate(1001, old_session.epoch) != 0);
|
|
REQUIRE(!state.is_current(1001));
|
|
|
|
const auto new_session = state.activate(1001);
|
|
REQUIRE_EQ(state.invalidate(1001, old_session.epoch), 0u);
|
|
REQUIRE(state.matches(1001, new_session.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_new_focus_session_renews_same_client_epoch)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
const auto first_focus = state.activate(1001);
|
|
const auto second_focus = state.renew(1001);
|
|
|
|
REQUIRE(second_focus.changed);
|
|
REQUIRE(first_focus.epoch != second_focus.epoch);
|
|
REQUIRE(!state.matches(1001, first_focus.epoch));
|
|
REQUIRE(state.matches(1001, second_focus.epoch));
|
|
}
|
|
|
|
TEST_CASE(active_client_terminal_deactivation_reuses_only_current_inactive_epoch)
|
|
{
|
|
FanyImeIpc::ActiveClientState state;
|
|
|
|
state.activate(1001);
|
|
const uint64_t suspended_epoch = state.deactivate(1001);
|
|
REQUIRE(suspended_epoch != 0);
|
|
REQUIRE_EQ(state.terminal_deactivation_epoch(1001, suspended_epoch), suspended_epoch);
|
|
|
|
// A later real deactivation observes an already-suspended route. It must
|
|
// still carry the exact inactive epoch to the UI worker.
|
|
REQUIRE_EQ(state.deactivate(1001), 0u);
|
|
REQUIRE_EQ(state.terminal_deactivation_epoch(1001), suspended_epoch);
|
|
REQUIRE(state.matches(0, suspended_epoch));
|
|
|
|
// Once another activation wins, the old terminal event cannot hide it.
|
|
const auto active = state.activate(2002);
|
|
REQUIRE_EQ(state.terminal_deactivation_epoch(1001), 0u);
|
|
REQUIRE(!state.matches(0, suspended_epoch));
|
|
REQUIRE(state.matches(2002, active.epoch));
|
|
|
|
// Inactive state is not sufficient ownership: after B suspends, a delayed
|
|
// terminal event or disconnect from A must not reuse B's zero-state epoch.
|
|
const uint64_t second_suspended_epoch = state.deactivate(2002);
|
|
REQUIRE(second_suspended_epoch != 0);
|
|
REQUIRE_EQ(state.terminal_deactivation_epoch(1001), 0u);
|
|
REQUIRE_EQ(state.terminal_deactivation_epoch(2002), second_suspended_epoch);
|
|
}
|
|
|
|
TEST_CASE(focus_session_ready_requires_nonzero_client_epoch_and_token)
|
|
{
|
|
REQUIRE(FanyImeIpc::CanSendFocusSessionReady(1001, 22, 77));
|
|
REQUIRE(!FanyImeIpc::CanSendFocusSessionReady(0, 22, 77));
|
|
REQUIRE(!FanyImeIpc::CanSendFocusSessionReady(1001, 0, 77));
|
|
REQUIRE(!FanyImeIpc::CanSendFocusSessionReady(1001, 22, 0));
|
|
}
|