Skip to content

Commit a03923f

Browse files
authored
Merge pull request #708 from tisnik/lcore-741-unit-tests-for-quota-limiters
LCORE-741: Rest of unit tests
2 parents c7d0d30 + 3a3f665 commit a03923f

File tree

6 files changed

+416
-7
lines changed

6 files changed

+416
-7
lines changed

tests/unit/quota/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Unit tests for quota limiters."""
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
"""Unit tests for ClusterQuotaLimiter class."""
2+
3+
import pytest
4+
5+
from models.config import (
6+
QuotaLimiterConfiguration,
7+
SQLiteDatabaseConfiguration,
8+
QuotaHandlersConfiguration,
9+
)
10+
from quota.cluster_quota_limiter import ClusterQuotaLimiter
11+
from quota.quota_exceed_error import QuotaExceedError
12+
13+
# pylint: disable=protected-access
14+
15+
16+
def create_quota_limiter(
17+
name: str, initial_quota: int, quota_limit: int
18+
) -> ClusterQuotaLimiter:
19+
"""Create new quota limiter instance."""
20+
configuration = QuotaHandlersConfiguration()
21+
configuration.sqlite = SQLiteDatabaseConfiguration(
22+
db_path=":memory:",
23+
)
24+
configuration.limiters = [
25+
QuotaLimiterConfiguration(
26+
type="cluster_limiter",
27+
name=name,
28+
initial_quota=quota_limit,
29+
quota_increase=1,
30+
period="5 days",
31+
),
32+
]
33+
quota_limiter = ClusterQuotaLimiter(configuration, initial_quota, 1)
34+
assert quota_limiter is not None
35+
return quota_limiter
36+
37+
38+
def test_connected():
39+
"""Test the connected method."""
40+
initial_quota = 1000
41+
quota_limit = 100
42+
43+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
44+
assert quota_limiter.connected()
45+
46+
47+
def test_init_quota():
48+
"""Test the init quota operation."""
49+
initial_quota = 1000
50+
quota_limit = 100
51+
52+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
53+
54+
# init quota for given cluster
55+
quota_limiter._init_quota()
56+
57+
assert (
58+
str(quota_limiter) == "ClusterQuotaLimiter: initial quota: 1000 increase by: 1"
59+
)
60+
61+
62+
def test_available_quota():
63+
"""Test the available quota operation."""
64+
initial_quota = 1000
65+
quota_limit = 100
66+
67+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
68+
69+
# init quota for given cluster
70+
quota_limiter._init_quota()
71+
72+
available_quota = quota_limiter.available_quota("foo")
73+
assert available_quota == initial_quota
74+
75+
76+
def test_consume_tokens():
77+
"""Test the consume tokens operation."""
78+
initial_quota = 1000
79+
quota_limit = 100
80+
81+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
82+
83+
# init quota for given cluster
84+
quota_limiter._init_quota()
85+
86+
available_quota = quota_limiter.available_quota("foo")
87+
assert available_quota == initial_quota
88+
89+
quota_limiter.consume_tokens(0, 1, "foo")
90+
91+
available_quota = quota_limiter.available_quota("foo")
92+
assert available_quota == initial_quota - 1
93+
94+
quota_limiter.consume_tokens(1, 0, "foo")
95+
96+
available_quota = quota_limiter.available_quota("foo")
97+
assert available_quota == initial_quota - 2
98+
99+
quota_limiter.consume_tokens(1, 1, "foo")
100+
101+
available_quota = quota_limiter.available_quota("foo")
102+
assert available_quota == initial_quota - 4
103+
104+
105+
def test_increase_quota():
106+
"""Test the increase_quota operation."""
107+
initial_quota = 1000
108+
quota_limit = 100
109+
110+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
111+
112+
# init quota for given cluster
113+
quota_limiter._init_quota()
114+
115+
available_quota = quota_limiter.available_quota("foo")
116+
assert available_quota == initial_quota
117+
118+
quota_limiter.consume_tokens(1, 1, "foo")
119+
available_quota = quota_limiter.available_quota("foo")
120+
assert available_quota == initial_quota - 2
121+
122+
quota_limiter.increase_quota("foo")
123+
available_quota = quota_limiter.available_quota("foo")
124+
assert available_quota == initial_quota - 1
125+
126+
127+
def test_ensure_available_quota():
128+
"""Test the ensure_available_quota operation."""
129+
initial_quota = 1000
130+
quota_limit = 100
131+
132+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
133+
134+
# init quota for given cluster
135+
quota_limiter._init_quota()
136+
137+
quota_limiter.ensure_available_quota("foo")
138+
139+
140+
def test_ensure_available_quota_no_quota():
141+
"""Test the ensure_available_quota operation."""
142+
initial_quota = 0
143+
quota_limit = 100
144+
145+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
146+
147+
# init quota for given cluster
148+
quota_limiter._init_quota()
149+
150+
with pytest.raises(QuotaExceedError, match="Cluster has no available tokens"):
151+
quota_limiter.ensure_available_quota("foo")
152+
153+
154+
def test_revoke_quota():
155+
"""Test the revoke_quota operation."""
156+
initial_quota = 1000
157+
quota_limit = 100
158+
159+
quota_limiter = create_quota_limiter("foo", initial_quota, quota_limit)
160+
161+
# init quota for given cluster
162+
quota_limiter._init_quota()
163+
164+
available_quota = quota_limiter.available_quota("foo")
165+
assert available_quota == initial_quota
166+
167+
quota_limiter.consume_tokens(1, 1, "foo")
168+
available_quota = quota_limiter.available_quota("foo")
169+
assert available_quota == initial_quota - 2
170+
171+
quota_limiter.revoke_quota("foo")
172+
available_quota = quota_limiter.available_quota("foo")
173+
assert available_quota == initial_quota
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Unit tests for PostgreSQL connection handler."""
2+
3+
import pytest
4+
from pytest_mock import MockerFixture
5+
6+
from psycopg2 import OperationalError
7+
8+
from quota.connect_pg import connect_pg
9+
from models.config import PostgreSQLDatabaseConfiguration
10+
11+
12+
def test_connect_pg_when_connection_established(mocker: MockerFixture):
13+
"""Test the connection to PostgreSQL database."""
14+
# any correct PostgreSQL configuration can be used
15+
configuration = PostgreSQLDatabaseConfiguration(
16+
db="db", user="user", password="password"
17+
)
18+
19+
# do not use connection to real PostgreSQL instance
20+
mocker.patch("psycopg2.connect")
21+
22+
# connection should be established
23+
connection = connect_pg(configuration)
24+
assert connection is not None
25+
26+
27+
def test_connect_pg_when_connection_error(mocker: MockerFixture):
28+
"""Test the connection to PostgreSQL database."""
29+
# any correct PostgreSQL configuration can be used
30+
configuration = PostgreSQLDatabaseConfiguration(
31+
host="foo", db="db", user="user", password="password"
32+
)
33+
34+
# do not use connection to real PostgreSQL instance
35+
mocker.patch("psycopg2.connect", side_effect=OperationalError("ERROR"))
36+
with pytest.raises(OperationalError, match="ERROR"):
37+
# connection should not be established
38+
_ = connect_pg(configuration)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Unit tests for SQLite connection handler."""
2+
3+
from sqlite3 import OperationalError
4+
5+
import pytest
6+
7+
from quota.connect_sqlite import connect_sqlite
8+
from models.config import SQLiteDatabaseConfiguration
9+
10+
11+
def test_connect_sqlite_when_connection_established():
12+
"""Test the connection to SQLite database residing in memory."""
13+
configuration = SQLiteDatabaseConfiguration(db_path=":memory:")
14+
15+
# connection should be established
16+
connection = connect_sqlite(configuration)
17+
assert connection is not None
18+
19+
20+
def test_connect_sqlite_when_connection_error():
21+
"""Test the connection to SQLite database."""
22+
configuration = SQLiteDatabaseConfiguration(db_path="/")
23+
24+
# connection should not be established
25+
with pytest.raises(OperationalError, match="unable to open database file"):
26+
_ = connect_sqlite(configuration)

tests/unit/quota/test_quota_limiter_factory.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_quota_limiters_no_storage():
2121
configuration.postgres = None
2222
configuration.limiters = []
2323
limiters = QuotaLimiterFactory.quota_limiters(configuration)
24-
assert limiters == []
24+
assert not limiters
2525

2626

2727
def test_quota_limiters_no_limiters_pg_storage():
@@ -32,7 +32,7 @@ def test_quota_limiters_no_limiters_pg_storage():
3232
)
3333
configuration.limiters = None
3434
limiters = QuotaLimiterFactory.quota_limiters(configuration)
35-
assert limiters == []
35+
assert not limiters
3636

3737

3838
def test_quota_limiters_no_limiters_sqlite_storage():
@@ -43,7 +43,7 @@ def test_quota_limiters_no_limiters_sqlite_storage():
4343
)
4444
configuration.limiters = None
4545
limiters = QuotaLimiterFactory.quota_limiters(configuration)
46-
assert limiters == []
46+
assert not limiters
4747

4848

4949
def test_quota_limiters_empty_limiters_pg_storage():
@@ -54,7 +54,7 @@ def test_quota_limiters_empty_limiters_pg_storage():
5454
)
5555
configuration.limiters = []
5656
limiters = QuotaLimiterFactory.quota_limiters(configuration)
57-
assert limiters == []
57+
assert not limiters
5858

5959

6060
def test_quota_limiters_empty_limiters_sqlite_storage():
@@ -65,7 +65,7 @@ def test_quota_limiters_empty_limiters_sqlite_storage():
6565
)
6666
configuration.limiters = []
6767
limiters = QuotaLimiterFactory.quota_limiters(configuration)
68-
assert limiters == []
68+
assert not limiters
6969

7070

7171
def test_quota_limiters_user_quota_limiter_postgres_storage(mocker: MockerFixture):
@@ -90,7 +90,7 @@ def test_quota_limiters_user_quota_limiter_postgres_storage(mocker: MockerFixtur
9090
assert isinstance(limiters[0], UserQuotaLimiter)
9191

9292

93-
def test_quota_limiters_user_quota_limiter_sqlite_storage(mocker: MockerFixture):
93+
def test_quota_limiters_user_quota_limiter_sqlite_storage():
9494
"""Test the quota limiters creating when one limiter is specified."""
9595
configuration = QuotaHandlersConfiguration()
9696
configuration.sqlite = SQLiteDatabaseConfiguration(
@@ -132,7 +132,7 @@ def test_quota_limiters_cluster_quota_limiter_postgres_storage(mocker: MockerFix
132132
assert isinstance(limiters[0], ClusterQuotaLimiter)
133133

134134

135-
def test_quota_limiters_cluster_quota_limiter_sqlite_storage(mocker: MockerFixture):
135+
def test_quota_limiters_cluster_quota_limiter_sqlite_storage():
136136
"""Test the quota limiters creating when one limiter is specified."""
137137
configuration = QuotaHandlersConfiguration()
138138
configuration.sqlite = SQLiteDatabaseConfiguration(

0 commit comments

Comments
 (0)