Fix an invalid comparison of `UserPresenceState` to `str` (#14393)
parent
d8cc86eff4
commit
618e4ab81b
|
@ -0,0 +1 @@
|
||||||
|
Fix a bug introduced in 1.58.0 where a user with presence state 'org.matrix.msc3026.busy' would mistakenly be set to 'online' when calling `/sync` or `/events` on a worker process.
|
|
@ -478,7 +478,7 @@ class WorkerPresenceHandler(BasePresenceHandler):
|
||||||
return _NullContextManager()
|
return _NullContextManager()
|
||||||
|
|
||||||
prev_state = await self.current_state_for_user(user_id)
|
prev_state = await self.current_state_for_user(user_id)
|
||||||
if prev_state != PresenceState.BUSY:
|
if prev_state.state != PresenceState.BUSY:
|
||||||
# We set state here but pass ignore_status_msg = True as we don't want to
|
# We set state here but pass ignore_status_msg = True as we don't want to
|
||||||
# cause the status message to be cleared.
|
# cause the status message to be cleared.
|
||||||
# Note that this causes last_active_ts to be incremented which is not
|
# Note that this causes last_active_ts to be incremented which is not
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from unittest.mock import Mock, call
|
from unittest.mock import Mock, call
|
||||||
|
|
||||||
|
from parameterized import parameterized
|
||||||
from signedjson.key import generate_signing_key
|
from signedjson.key import generate_signing_key
|
||||||
|
|
||||||
from synapse.api.constants import EventTypes, Membership, PresenceState
|
from synapse.api.constants import EventTypes, Membership, PresenceState
|
||||||
|
@ -37,6 +38,7 @@ from synapse.rest.client import room
|
||||||
from synapse.types import UserID, get_domain_from_id
|
from synapse.types import UserID, get_domain_from_id
|
||||||
|
|
||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
from tests.replication._base import BaseMultiWorkerStreamTestCase
|
||||||
|
|
||||||
|
|
||||||
class PresenceUpdateTestCase(unittest.HomeserverTestCase):
|
class PresenceUpdateTestCase(unittest.HomeserverTestCase):
|
||||||
|
@ -505,7 +507,7 @@ class PresenceTimeoutTestCase(unittest.TestCase):
|
||||||
self.assertEqual(state, new_state)
|
self.assertEqual(state, new_state)
|
||||||
|
|
||||||
|
|
||||||
class PresenceHandlerTestCase(unittest.HomeserverTestCase):
|
class PresenceHandlerTestCase(BaseMultiWorkerStreamTestCase):
|
||||||
def prepare(self, reactor, clock, hs):
|
def prepare(self, reactor, clock, hs):
|
||||||
self.presence_handler = hs.get_presence_handler()
|
self.presence_handler = hs.get_presence_handler()
|
||||||
self.clock = hs.get_clock()
|
self.clock = hs.get_clock()
|
||||||
|
@ -716,20 +718,47 @@ class PresenceHandlerTestCase(unittest.HomeserverTestCase):
|
||||||
# our status message should be the same as it was before
|
# our status message should be the same as it was before
|
||||||
self.assertEqual(state.status_msg, status_msg)
|
self.assertEqual(state.status_msg, status_msg)
|
||||||
|
|
||||||
def test_set_presence_from_syncing_keeps_busy(self):
|
@parameterized.expand([(False,), (True,)])
|
||||||
"""Test that presence set by syncing doesn't affect busy status"""
|
@unittest.override_config(
|
||||||
# while this isn't the default
|
{
|
||||||
self.presence_handler._busy_presence_enabled = True
|
"experimental_features": {
|
||||||
|
"msc3026_enabled": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_set_presence_from_syncing_keeps_busy(self, test_with_workers: bool):
|
||||||
|
"""Test that presence set by syncing doesn't affect busy status
|
||||||
|
|
||||||
|
Args:
|
||||||
|
test_with_workers: If True, check the presence state of the user by calling
|
||||||
|
/sync against a worker, rather than the main process.
|
||||||
|
"""
|
||||||
user_id = "@test:server"
|
user_id = "@test:server"
|
||||||
status_msg = "I'm busy!"
|
status_msg = "I'm busy!"
|
||||||
|
|
||||||
|
# By default, we call /sync against the main process.
|
||||||
|
worker_to_sync_against = self.hs
|
||||||
|
if test_with_workers:
|
||||||
|
# Create a worker and use it to handle /sync traffic instead.
|
||||||
|
# This is used to test that presence changes get replicated from workers
|
||||||
|
# to the main process correctly.
|
||||||
|
worker_to_sync_against = self.make_worker_hs(
|
||||||
|
"synapse.app.generic_worker", {"worker_name": "presence_writer"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set presence to BUSY
|
||||||
self._set_presencestate_with_status_msg(user_id, PresenceState.BUSY, status_msg)
|
self._set_presencestate_with_status_msg(user_id, PresenceState.BUSY, status_msg)
|
||||||
|
|
||||||
|
# Perform a sync with a presence state other than busy. This should NOT change
|
||||||
|
# our presence status; we only change from busy if we explicitly set it via
|
||||||
|
# /presence/*.
|
||||||
self.get_success(
|
self.get_success(
|
||||||
self.presence_handler.user_syncing(user_id, True, PresenceState.ONLINE)
|
worker_to_sync_against.get_presence_handler().user_syncing(
|
||||||
|
user_id, True, PresenceState.ONLINE
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check against the main process that the user's presence did not change.
|
||||||
state = self.get_success(
|
state = self.get_success(
|
||||||
self.presence_handler.get_state(UserID.from_string(user_id))
|
self.presence_handler.get_state(UserID.from_string(user_id))
|
||||||
)
|
)
|
||||||
|
|
|
@ -778,8 +778,11 @@ def _test_sending_local_online_presence_to_local_user(
|
||||||
worker process. The test users will still sync with the main process. The purpose of testing
|
worker process. The test users will still sync with the main process. The purpose of testing
|
||||||
with a worker is to check whether a Synapse module running on a worker can inform other workers/
|
with a worker is to check whether a Synapse module running on a worker can inform other workers/
|
||||||
the main process that they should include additional presence when a user next syncs.
|
the main process that they should include additional presence when a user next syncs.
|
||||||
|
If this argument is True, `test_case` MUST be an instance of BaseMultiWorkerStreamTestCase.
|
||||||
"""
|
"""
|
||||||
if test_with_workers:
|
if test_with_workers:
|
||||||
|
assert isinstance(test_case, BaseMultiWorkerStreamTestCase)
|
||||||
|
|
||||||
# Create a worker process to make module_api calls against
|
# Create a worker process to make module_api calls against
|
||||||
worker_hs = test_case.make_worker_hs(
|
worker_hs = test_case.make_worker_hs(
|
||||||
"synapse.app.generic_worker", {"worker_name": "presence_writer"}
|
"synapse.app.generic_worker", {"worker_name": "presence_writer"}
|
||||||
|
|
|
@ -542,8 +542,13 @@ class FakeRedisPubSubProtocol(Protocol):
|
||||||
self.send("OK")
|
self.send("OK")
|
||||||
elif command == b"GET":
|
elif command == b"GET":
|
||||||
self.send(None)
|
self.send(None)
|
||||||
|
|
||||||
|
# Connection keep-alives.
|
||||||
|
elif command == b"PING":
|
||||||
|
self.send("PONG")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown command")
|
raise Exception(f"Unknown command: {command}")
|
||||||
|
|
||||||
def send(self, msg):
|
def send(self, msg):
|
||||||
"""Send a message back to the client."""
|
"""Send a message back to the client."""
|
||||||
|
|
Loading…
Reference in New Issue