""" Контракт DAG generator_control без запуска Airflow. """ import ast from pathlib import Path from clickstream_generator.launch import PROFILES DAG_PATH = Path(__file__).parents[2] / "airflow" / "dags" / "generator_control_dag.py" REPO_ROOT = Path(__file__).parents[2] def _tree(): return ast.parse(DAG_PATH.read_text(encoding="utf-8")) def test_dag_file_exists_and_uses_dynamic_profiles(): """DAG берёт варианты профилей из PROFILES, а не из ручного списка.""" text = DAG_PATH.read_text(encoding="utf-8") assert "dag_id=\"generator_control\"" in text assert "sorted(PROFILES)" in text for profile in PROFILES: assert profile not in {"hardcoded-profile"} def test_trigger_form_has_expected_param_enums(): """Форма запуска ограничивает операции и профили.""" text = DAG_PATH.read_text(encoding="utf-8") assert 'enum=["backfill", "import", "check"]' in text assert "enum=sorted(PROFILES)" in text assert '"duration": Param(' in text assert '"artifact_path": Param(' in text def test_dag_branches_and_waits_for_etl_completion(): """Backfill/import запускают ETL и ждут его завершения перед check.""" text = DAG_PATH.read_text(encoding="utf-8") assert "BranchPythonOperator" in text assert "TriggerDagRunOperator" in text assert 'trigger_dag_id="etl_pipeline"' in text assert "wait_for_completion=True" in text assert 'allowed_states=["success"]' in text assert 'failed_states=["failed"]' in text def test_no_docker_or_continue_operation_in_dag(): """Пульт не управляет Docker и не содержит операцию continue.""" text = DAG_PATH.read_text(encoding="utf-8") assert "docker" not in text.lower() assert '"continue"' not in text def test_compose_mounts_generator_code_without_socket_and_gates_live_service(): """Airflow видит код генератора, но не получает Docker socket.""" text = (REPO_ROOT / "docker-compose.yml").read_text(encoding="utf-8") assert "PYTHONPATH: /opt/airflow/generator_src" in text assert "./generator/src:/opt/airflow/generator_src:ro" in text assert "/var/run/docker.sock" not in text assert "profiles:\n - live-generator" in text def test_airflow_and_generator_kafka_dependency_versions_match(): """Airflow и генератор используют одну версию kafka-python.""" airflow_req = (REPO_ROOT / "airflow" / "requirements.txt").read_text(encoding="utf-8") generator_req = (REPO_ROOT / "generator" / "requirements.txt").read_text(encoding="utf-8") assert "kafka-python==2.0.6" in airflow_req assert "kafka-python==2.0.6" in generator_req assert "prometheus-client==0.21.1" in airflow_req