Skip to content

Commit

Permalink
tests: fix spurious failure of stats tests
Browse files Browse the repository at this point in the history
Some of the test_stats tests would fail occasionally with the wrong
queue length.  Traced it back to the redis 'Queue' object somehow
persisting across tests.  We now ensure that a fresh queue is used
for each test.

Signed-off-by: Eric Fahlgren <[email protected]>
  • Loading branch information
efahl committed Oct 23, 2024
1 parent 060ec53 commit 08d4698
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 144 deletions.
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pytest
from fakeredis import FakeStrictRedis
from rq import Queue
from fastapi.testclient import TestClient

from asu.config import settings
Expand Down Expand Up @@ -93,12 +94,17 @@ def app(redis_server, test_path, monkeypatch):
def mocked_redis_client(*args, **kwargs):
return redis_server

def mocked_redis_queue():
return Queue(connection=redis_server, is_async=settings.async_queue)

settings.public_path = Path(test_path) / "public"
settings.async_queue = False
for branch in "1.2", "19.07", "21.02":
if branch not in settings.branches:
settings.branches[branch] = {"path": "releases/{version}"}

monkeypatch.setattr("asu.util.get_queue", mocked_redis_queue)
monkeypatch.setattr("asu.routers.api.get_queue", mocked_redis_queue)
monkeypatch.setattr("asu.util.get_redis_client", mocked_redis_client)
monkeypatch.setattr("asu.routers.api.get_redis_client", mocked_redis_client)

Expand Down
222 changes: 78 additions & 144 deletions tests/test_stats.py
Original file line number Diff line number Diff line change
@@ -1,184 +1,118 @@
import time
from fakeredis import FakeStrictRedis

build_config_1 = dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1"],
)

def test_stats_image_builds(client, redis_server: FakeStrictRedis):
response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
)
assert response.status_code == 200
build_config_2 = dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
)

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=builds"])[0][
"stats:builds:1.2.3:testtarget/testsubtarget:testprofile"
][1]
)
== 1
)
class Stats:
def __init__(self, redis_server: FakeStrictRedis):
self.ts = redis_server.ts()

response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1"],
),
)
assert response.status_code == 200
def cache(self, type):
return self.ts.mrange("-", "+", filters=[f"stats=cache-{type}"])

assert (
len(
ts.mrange("-", "+", filters=["stats=builds"])[0][
"stats:builds:1.2.3:testtarget/testsubtarget:testprofile"
][1]
)
== 2
)
def client(self, tag):
clients = self.ts.mrange("-", "+", filters=["stats=clients"])
if not clients:
return []
return clients[0][f"stats:clients:{tag}"]

def build(self, tag):
builds = self.ts.mrange("-", "+", filters=["stats=builds"])
if not builds:
return []
return builds[0][f"stats:builds:{tag}"]

def test_stats_cache(client, redis_server: FakeStrictRedis):
response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
)

def test_stats_image_builds(client, redis_server: FakeStrictRedis):
stats = Stats(redis_server)
assert len(stats.build("1.2.3:testtarget/testsubtarget:testprofile")) == 0

response = client.post("/api/v1/build", json=build_config_1)
assert response.status_code == 200
assert len(stats.build("1.2.3:testtarget/testsubtarget:testprofile")[1]) == 1

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=cache-misses"])[0][
"stats:cache-misses"
][1]
)
== 1
)
def test_stats_cache(client, redis_server: FakeStrictRedis):
stats = Stats(redis_server)

response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
)
assert len(stats.cache("hits")) == 0
assert len(stats.cache("misses")) == 0

response = client.post("/api/v1/build", json=build_config_2)
assert response.status_code == 200
assert len(stats.cache("hits")) == 0
assert len(stats.cache("misses")[0]["stats:cache-misses"][1]) == 1

assert (
len(ts.mrange("-", "+", filters=["stats=cache-hits"])[0]["stats:cache-hits"][1])
== 1
)
response = client.post("/api/v1/build", json=build_config_2)
assert response.status_code == 200
assert len(stats.cache("hits")[0]["stats:cache-hits"][1]) == 1
assert len(stats.cache("misses")[0]["stats:cache-misses"][1]) == 1

time.sleep(1) # Ensure timestamp is on next second.
response = client.post("/api/v1/build", json=build_config_2)
assert response.status_code == 200
assert len(stats.cache("hits")[0]["stats:cache-hits"][1]) == 2
assert len(stats.cache("misses")[0]["stats:cache-misses"][1]) == 1


def test_stats_clients_luci(client, redis_server: FakeStrictRedis):
asu_client = "luci/git-22.073.39928-701ea94"

stats = Stats(redis_server)
assert len(stats.client(asu_client)) == 0

response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
client="luci/git-22.073.39928-701ea94",
),
"/api/v1/build", json=dict(client=asu_client, **build_config_1)
)
assert response.status_code == 200
assert len(stats.client(asu_client)[1]) == 1

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=clients"])[0][
"stats:clients:luci/git-22.073.39928-701ea94"
][1]
)
== 1
)
def test_stats_clients_unknown(client, redis_server: FakeStrictRedis):
asu_client = "unknown/0"

stats = Stats(redis_server)
assert len(stats.client(asu_client)) == 0

def test_stats_clients_unknown(client, redis_server: FakeStrictRedis):
response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
)
response = client.post("/api/v1/build", json=build_config_2)
assert response.status_code == 200
assert len(stats.client(asu_client)[1]) == 1

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=clients"])[0][
"stats:clients:unknown/0"
][1]
)
== 1
)
def test_stats_clients_auc(client, redis_server: FakeStrictRedis):
asu_client = "auc/0.3.2"

stats = Stats(redis_server)
assert len(stats.client(asu_client)) == 0

def test_stats_clients_auc(client, redis_server: FakeStrictRedis):
response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
headers={"User-Agent": "auc (0.3.2)"},
"/api/v1/build", json=build_config_2, headers={"User-Agent": "auc (0.3.2)"}
)
assert response.status_code == 200
assert len(stats.client(asu_client)[1]) == 1

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=clients"])[0][
"stats:clients:auc/0.3.2"
][1]
)
== 1
)
def test_stats_clients_auc_possible_new_format(client, redis_server: FakeStrictRedis):
asu_client = "auc/0.3.2"

stats = Stats(redis_server)
assert len(stats.client(asu_client)) == 0

def test_stats_clients_auc_possible_new_format(client, redis_server: FakeStrictRedis):
response = client.post(
"/api/v1/build",
json=dict(
version="1.2.3",
target="testtarget/testsubtarget",
profile="testprofile",
packages=["test1", "test2"],
),
headers={"User-Agent": "auc/0.3.2"},
"/api/v1/build", json=build_config_2, headers={"User-Agent": asu_client}
)
assert response.status_code == 200

ts = redis_server.ts()

assert (
len(
ts.mrange("-", "+", filters=["stats=clients"])[0][
"stats:clients:auc/0.3.2"
][1]
)
== 1
)
assert len(stats.client(asu_client)[1]) == 1

0 comments on commit 08d4698

Please sign in to comment.