|
5 | 5 | from __future__ import annotations |
6 | 6 |
|
7 | 7 | from collections import defaultdict |
8 | | -from collections.abc import Iterable, Sequence |
| 8 | +from collections.abc import Sequence |
9 | 9 | from confluent_kafka.cimpl import KafkaError |
10 | 10 | from karapace.config import DEFAULTS |
11 | 11 | from karapace.constants import DEFAULT_SCHEMA_TOPIC |
12 | 12 | from karapace.in_memory_database import InMemoryDatabase, KarapaceDatabase, Subject, SubjectData |
13 | 13 | from karapace.kafka.types import Timestamp |
14 | 14 | from karapace.key_format import KeyFormatter |
15 | 15 | from karapace.offset_watcher import OffsetWatcher |
| 16 | +from karapace.protobuf.schema import ProtobufSchema |
16 | 17 | from karapace.schema_models import SchemaVersion, TypedSchema |
17 | 18 | from karapace.schema_reader import KafkaSchemaReader |
18 | 19 | from karapace.schema_references import Reference, Referents |
| 20 | +from karapace.schema_type import SchemaType |
19 | 21 | from karapace.typing import SchemaId, Version |
20 | 22 | from pathlib import Path |
21 | 23 | from typing import Final |
22 | 24 |
|
| 25 | +import pytest |
| 26 | + |
23 | 27 | TEST_DATA_FOLDER: Final = Path("tests/unit/test_data/") |
24 | 28 |
|
25 | 29 |
|
@@ -176,15 +180,9 @@ def num_subjects(self) -> int: |
176 | 180 | def num_schema_versions(self) -> tuple[int, int]: |
177 | 181 | return self.db.num_schema_versions() |
178 | 182 |
|
179 | | - def insert_referenced_by(self, *, subject: Subject, version: Version, schema_id: SchemaId) -> None: |
180 | | - return self.db.insert_referenced_by(subject=subject, version=version, schema_id=schema_id) |
181 | | - |
182 | 183 | def get_referenced_by(self, subject: Subject, version: Version) -> Referents | None: |
183 | 184 | return self.db.get_referenced_by(subject=subject, version=version) |
184 | 185 |
|
185 | | - def remove_referenced_by(self, schema_id: SchemaId, references: Iterable[Reference]) -> None: |
186 | | - return self.db.remove_referenced_by(schema_id=schema_id, references=references) |
187 | | - |
188 | 186 | def duplicates(self) -> dict[SchemaId, list[tuple[Subject, TypedSchema]]]: |
189 | 187 | duplicate_data = defaultdict(list) |
190 | 188 | for schema_id, schemas in self._duplicates.items(): |
@@ -259,3 +257,77 @@ def test_can_ingest_schemas_from_log() -> None: |
259 | 257 | schema_id_to_duplicated_subjects = compute_schema_id_to_subjects(duplicates, database.subject_to_subject_data()) |
260 | 258 | assert schema_id_to_duplicated_subjects == {}, "there shouldn't be any duplicated schemas" |
261 | 259 | assert duplicates == {}, "the schema database is broken. The id should be unique" |
| 260 | + |
| 261 | + |
| 262 | +@pytest.fixture(name="db_with_schemas") |
| 263 | +def fixture_in_memory_database_with_schemas() -> InMemoryDatabase: |
| 264 | + db = InMemoryDatabase() |
| 265 | + schema_str = "syntax = 'proto3'; message Test { string test = 1; }" |
| 266 | + |
| 267 | + subject_a = Subject("subject_a") |
| 268 | + schema_a = TypedSchema( |
| 269 | + schema_type=SchemaType.PROTOBUF, |
| 270 | + schema_str=schema_str, |
| 271 | + schema=ProtobufSchema(schema=schema_str), |
| 272 | + ) |
| 273 | + db.insert_subject(subject=subject_a) |
| 274 | + schema_id_a = db.get_schema_id(schema_a) |
| 275 | + db.insert_schema_version( |
| 276 | + subject=subject_a, schema_id=schema_id_a, version=Version(1), schema=schema_a, deleted=False, references=None |
| 277 | + ) |
| 278 | + db.insert_schema_version( |
| 279 | + subject=subject_a, schema_id=schema_id_a, version=Version(2), schema=schema_a, deleted=False, references=None |
| 280 | + ) |
| 281 | + |
| 282 | + subject_b = Subject("subject_b") |
| 283 | + references_b = [Reference(name="test", subject=subject_a, version=Version(1))] |
| 284 | + schema_b = TypedSchema( |
| 285 | + schema_type=SchemaType.PROTOBUF, |
| 286 | + schema_str=schema_str, |
| 287 | + schema=ProtobufSchema(schema=schema_str), |
| 288 | + references=references_b, |
| 289 | + ) |
| 290 | + db.insert_subject(subject=subject_b) |
| 291 | + schema_id_b = db.get_schema_id(schema_b) |
| 292 | + db.insert_schema_version( |
| 293 | + subject=subject_b, |
| 294 | + schema_id=schema_id_b, |
| 295 | + version=Version(1), |
| 296 | + schema=schema_b, |
| 297 | + deleted=False, |
| 298 | + references=references_b, |
| 299 | + ) |
| 300 | + |
| 301 | + return db |
| 302 | + |
| 303 | + |
| 304 | +def test_delete_schema_references(db_with_schemas: InMemoryDatabase) -> None: |
| 305 | + # Check that the schema is referenced by subject_b |
| 306 | + referents = db_with_schemas.get_referenced_by(subject=Subject("subject_a"), version=Version(1)) |
| 307 | + assert referents is not None |
| 308 | + version = db_with_schemas.find_schema_versions_by_schema_id(schema_id=referents.pop(), include_deleted=False)[0] |
| 309 | + assert version.subject == Subject("subject_b") |
| 310 | + assert version.version == Version(1) |
| 311 | + |
| 312 | + # Delete the schema from subject_b |
| 313 | + db_with_schemas.delete_subject_schema(subject=Subject("subject_b"), version=Version(1)) |
| 314 | + |
| 315 | + # Check that the schema is no longer referenced by subject_b |
| 316 | + referents = db_with_schemas.get_referenced_by(subject=Subject("subject_a"), version=Version(1)) |
| 317 | + assert len(referents) == 0, "referents should be gone after deleting the schema" |
| 318 | + |
| 319 | + |
| 320 | +def test_delete_subject(db_with_schemas: InMemoryDatabase) -> None: |
| 321 | + # Check that the schema is referenced by subject_b |
| 322 | + referents = db_with_schemas.get_referenced_by(subject=Subject("subject_a"), version=Version(1)) |
| 323 | + assert referents is not None |
| 324 | + version = db_with_schemas.find_schema_versions_by_schema_id(schema_id=referents.pop(), include_deleted=False)[0] |
| 325 | + assert version.subject == Subject("subject_b") |
| 326 | + assert version.version == Version(1) |
| 327 | + |
| 328 | + # Hard delete subject_b |
| 329 | + db_with_schemas.delete_subject_hard(subject=Subject("subject_b")) |
| 330 | + |
| 331 | + # Check that the schema is no longer referenced by subject_b |
| 332 | + referents = db_with_schemas.get_referenced_by(subject=Subject("subject_a"), version=Version(1)) |
| 333 | + assert len(referents) == 0, "referents should be gone after hard deleting the subject" |
0 commit comments