mirror of
https://github.com/ansible/awx.git
synced 2026-10-29 22:03:20 -02:30
Complete the FakeRedis test double for the subsystem metrics pipe (#16745)
TestCallbackBrokerWorker::test_duplicate_key_not_saved_twice can crash
with AttributeError: 'FakeRedis' object has no attribute 'hincrby'.
CallbackBrokerWorker.flush() ends with
if self.subsystem_metrics.should_pipe_execute() is True:
self.subsystem_metrics.pipe_execute()
and should_pipe_execute() is True once more than
SUBSYSTEM_METRICS_INTERVAL_SAVE_TO_REDIS seconds have passed since the
last pipe execute. On a fast machine that interval never elapses during
the test, so the pipe is never executed and nothing notices; on a slow
one it does, pipe_execute() calls store_value() on every metric, and
IntM/FloatM/SetIntM reach for hincrby/hincrbyfloat/hset, which the
FakeRedis double in awx/main/tests/functional/conftest.py does not have.
Rather than suppress the pipe execute in the one test, make the double
complete enough to execute it: add the hash commands the metric
store_value() implementations use, an execute() for the pipeline
(pipeline() returns self), and a lock() returning a lock that never
acquires, so send_metrics() takes its "another thread holds the lock"
early return instead of trying to emit a websocket notification through
a channel layer that is not available under test.
This commit is contained in:
@@ -76,6 +76,16 @@ def swagger_autogen(requests=__SWAGGER_REQUESTS__):
|
||||
return requests
|
||||
|
||||
|
||||
class FakeLock:
|
||||
# Never acquirable, so callers that guard work with a redis lock take the
|
||||
# "someone else holds it" branch instead of reaching for real services.
|
||||
def acquire(self, *args, **kwargs):
|
||||
return False
|
||||
|
||||
def release(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class FakeRedis:
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Accept and ignore all arguments to match redis.Redis signature
|
||||
@@ -90,6 +100,21 @@ class FakeRedis:
|
||||
def get(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
def hset(self, *args, **kwargs):
|
||||
return 1
|
||||
|
||||
def hget(self, *args, **kwargs):
|
||||
return None
|
||||
|
||||
def hincrby(self, *args, **kwargs):
|
||||
return 0
|
||||
|
||||
def hincrbyfloat(self, *args, **kwargs):
|
||||
return 0.0
|
||||
|
||||
def lock(self, *args, **kwargs):
|
||||
return FakeLock()
|
||||
|
||||
def rpush(self, *args, **kwargs):
|
||||
return 1
|
||||
|
||||
@@ -112,6 +137,9 @@ class FakeRedis:
|
||||
def pipeline(self):
|
||||
return self
|
||||
|
||||
def execute(self, *args, **kwargs):
|
||||
return []
|
||||
|
||||
def ping(self):
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user