import os
import os.path as p
import pytest
import time
import logging

from helpers.cluster import ClickHouseCluster, run_and_check
from test_library_bridge.test import create_dict_simple

cluster = ClickHouseCluster(__file__)

instance = cluster.add_instance(
    "instance",
    dictionaries=["configs/dictionaries/dict1.xml"],
    main_configs=["configs/config.d/config.xml"],
    stay_alive=True,
)


@pytest.fixture(scope="module")
def ch_cluster():
    try:
        cluster.start()
        instance.query("CREATE DATABASE test")

        instance.copy_file_to_container(
            os.path.join(
                os.path.dirname(os.path.realpath(__file__)), "configs/dict_lib.cpp"
            ),
            "/etc/clickhouse-server/config.d/dictionaries_lib/dict_lib.cpp",
        )

        instance.query("SYSTEM RELOAD CONFIG")

        instance.exec_in_container(
            [
                "bash",
                "-c",
                "/usr/bin/g++ -shared -o /etc/clickhouse-server/config.d/dictionaries_lib/dict_lib.so -fPIC /etc/clickhouse-server/config.d/dictionaries_lib/dict_lib.cpp",
            ],
            user="root",
        )
        yield cluster

    finally:
        cluster.shutdown()


def test_bridge_dies_with_parent(ch_cluster):
    if instance.is_built_with_memory_sanitizer():
        pytest.skip("Memory Sanitizer cannot work with third-party shared libraries")
    if instance.is_built_with_address_sanitizer():
        pytest.skip(
            "Leak sanitizer falsely reports about a leak of 16 bytes in clickhouse-odbc-bridge"
        )

    create_dict_simple(instance)
    result = instance.query("""select dictGet(lib_dict_c, 'value1', toUInt64(1));""")
    assert result.strip() == "101"

    clickhouse_pid = instance.get_process_pid("clickhouse server")
    bridge_pid = instance.get_process_pid("library-bridge")
    assert clickhouse_pid is not None
    assert bridge_pid is not None

    try:
        instance.exec_in_container(
            ["kill", str(clickhouse_pid)], privileged=True, user="root"
        )
    except:
        pass

    for i in range(30):
        time.sleep(1)
        clickhouse_pid = instance.get_process_pid("clickhouse server")
        if clickhouse_pid is None:
            break

    for i in range(30):
        time.sleep(1)
        bridge_pid = instance.get_process_pid("library-bridge")
        if bridge_pid is None:
            break

    if bridge_pid:
        out = instance.exec_in_container(
            ["gdb", "-p", str(bridge_pid), "--ex", "thread apply all bt", "--ex", "q"],
            privileged=True,
            user="root",
        )
        logging.debug(f"Bridge is running, gdb output:\n{out}")

    try:
        assert clickhouse_pid is None
        assert bridge_pid is None
    finally:
        instance.start_clickhouse(20)
        instance.query("DROP DICTIONARY lib_dict_c")
